1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/base/logging.h"
12 #include "webrtc/base/trace_event.h"
13 #include "webrtc/modules/video_coding/include/video_coding.h"
14 #include "webrtc/modules/video_coding/generic_decoder.h"
15 #include "webrtc/modules/video_coding/internal_defines.h"
16 #include "webrtc/system_wrappers/include/clock.h"
17 
18 namespace webrtc {
19 
VCMDecodedFrameCallback(VCMTiming * timing,Clock * clock)20 VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming* timing,
21                                                  Clock* clock)
22     : _critSect(CriticalSectionWrapper::CreateCriticalSection()),
23       _clock(clock),
24       _receiveCallback(NULL),
25       _timing(timing),
26       _timestampMap(kDecoderFrameMemoryLength),
27       _lastReceivedPictureID(0) {}
28 
~VCMDecodedFrameCallback()29 VCMDecodedFrameCallback::~VCMDecodedFrameCallback() {
30   delete _critSect;
31 }
32 
SetUserReceiveCallback(VCMReceiveCallback * receiveCallback)33 void VCMDecodedFrameCallback::SetUserReceiveCallback(
34     VCMReceiveCallback* receiveCallback) {
35   CriticalSectionScoped cs(_critSect);
36   _receiveCallback = receiveCallback;
37 }
38 
UserReceiveCallback()39 VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() {
40   CriticalSectionScoped cs(_critSect);
41   return _receiveCallback;
42 }
43 
Decoded(VideoFrame & decodedImage)44 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage) {
45   return Decoded(decodedImage, -1);
46 }
47 
Decoded(VideoFrame & decodedImage,int64_t decode_time_ms)48 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
49                                          int64_t decode_time_ms) {
50   TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded",
51                        "timestamp", decodedImage.timestamp());
52   // TODO(holmer): We should improve this so that we can handle multiple
53   // callbacks from one call to Decode().
54   VCMFrameInformation* frameInfo;
55   VCMReceiveCallback* callback;
56   {
57     CriticalSectionScoped cs(_critSect);
58     frameInfo = _timestampMap.Pop(decodedImage.timestamp());
59     callback = _receiveCallback;
60   }
61 
62   if (frameInfo == NULL) {
63     LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping "
64                        "this one.";
65     return WEBRTC_VIDEO_CODEC_OK;
66   }
67 
68   const int64_t now_ms = _clock->TimeInMilliseconds();
69   if (decode_time_ms < 0) {
70     decode_time_ms =
71         static_cast<int32_t>(now_ms - frameInfo->decodeStartTimeMs);
72   }
73   _timing->StopDecodeTimer(decodedImage.timestamp(), decode_time_ms, now_ms,
74                            frameInfo->renderTimeMs);
75 
76   if (callback != NULL) {
77     decodedImage.set_render_time_ms(frameInfo->renderTimeMs);
78     decodedImage.set_rotation(frameInfo->rotation);
79     callback->FrameToRender(decodedImage);
80   }
81   return WEBRTC_VIDEO_CODEC_OK;
82 }
83 
ReceivedDecodedReferenceFrame(const uint64_t pictureId)84 int32_t VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(
85     const uint64_t pictureId) {
86   CriticalSectionScoped cs(_critSect);
87   if (_receiveCallback != NULL) {
88     return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId);
89   }
90   return -1;
91 }
92 
ReceivedDecodedFrame(const uint64_t pictureId)93 int32_t VCMDecodedFrameCallback::ReceivedDecodedFrame(
94     const uint64_t pictureId) {
95   _lastReceivedPictureID = pictureId;
96   return 0;
97 }
98 
LastReceivedPictureID() const99 uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const {
100   return _lastReceivedPictureID;
101 }
102 
OnDecoderImplementationName(const char * implementation_name)103 void VCMDecodedFrameCallback::OnDecoderImplementationName(
104     const char* implementation_name) {
105   CriticalSectionScoped cs(_critSect);
106   if (_receiveCallback)
107     _receiveCallback->OnDecoderImplementationName(implementation_name);
108 }
109 
Map(uint32_t timestamp,VCMFrameInformation * frameInfo)110 void VCMDecodedFrameCallback::Map(uint32_t timestamp,
111                                   VCMFrameInformation* frameInfo) {
112   CriticalSectionScoped cs(_critSect);
113   _timestampMap.Add(timestamp, frameInfo);
114 }
115 
Pop(uint32_t timestamp)116 int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) {
117   CriticalSectionScoped cs(_critSect);
118   if (_timestampMap.Pop(timestamp) == NULL) {
119     return VCM_GENERAL_ERROR;
120   }
121   return VCM_OK;
122 }
123 
VCMGenericDecoder(VideoDecoder * decoder,bool isExternal)124 VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal)
125     : _callback(NULL),
126       _frameInfos(),
127       _nextFrameInfoIdx(0),
128       _decoder(decoder),
129       _codecType(kVideoCodecUnknown),
130       _isExternal(isExternal),
131       _keyFrameDecoded(false) {}
132 
~VCMGenericDecoder()133 VCMGenericDecoder::~VCMGenericDecoder() {}
134 
InitDecode(const VideoCodec * settings,int32_t numberOfCores)135 int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings,
136                                       int32_t numberOfCores) {
137   TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode");
138   _codecType = settings->codecType;
139 
140   return _decoder->InitDecode(settings, numberOfCores);
141 }
142 
Decode(const VCMEncodedFrame & frame,int64_t nowMs)143 int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) {
144     TRACE_EVENT1("webrtc", "VCMGenericDecoder::Decode", "timestamp",
145                  frame.EncodedImage()._timeStamp);
146     _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs;
147     _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs();
148     _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation();
149     _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]);
150 
151     _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength;
152     int32_t ret = _decoder->Decode(frame.EncodedImage(), frame.MissingFrame(),
153                                    frame.FragmentationHeader(),
154                                    frame.CodecSpecific(), frame.RenderTimeMs());
155 
156     _callback->OnDecoderImplementationName(_decoder->ImplementationName());
157     if (ret < WEBRTC_VIDEO_CODEC_OK) {
158         LOG(LS_WARNING) << "Failed to decode frame with timestamp "
159                         << frame.TimeStamp() << ", error code: " << ret;
160         _callback->Pop(frame.TimeStamp());
161         return ret;
162     } else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT ||
163                ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI) {
164         // No output
165         _callback->Pop(frame.TimeStamp());
166     }
167     return ret;
168 }
169 
Release()170 int32_t VCMGenericDecoder::Release() {
171   return _decoder->Release();
172 }
173 
Reset()174 int32_t VCMGenericDecoder::Reset() {
175   return _decoder->Reset();
176 }
177 
RegisterDecodeCompleteCallback(VCMDecodedFrameCallback * callback)178 int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(
179     VCMDecodedFrameCallback* callback) {
180   _callback = callback;
181   return _decoder->RegisterDecodeCompleteCallback(callback);
182 }
183 
External() const184 bool VCMGenericDecoder::External() const {
185   return _isExternal;
186 }
187 
PrefersLateDecoding() const188 bool VCMGenericDecoder::PrefersLateDecoding() const {
189   return _decoder->PrefersLateDecoding();
190 }
191 
192 }  // namespace webrtc
193