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