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/modules/video_coding/main/interface/video_coding.h"
12 #include "webrtc/modules/video_coding/main/source/generic_decoder.h"
13 #include "webrtc/modules/video_coding/main/source/internal_defines.h"
14 #include "webrtc/system_wrappers/interface/clock.h"
15 #include "webrtc/system_wrappers/interface/logging.h"
16
17 namespace webrtc {
18
VCMDecodedFrameCallback(VCMTiming & timing,Clock * clock)19 VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming& timing,
20 Clock* clock)
21 :
22 _critSect(CriticalSectionWrapper::CreateCriticalSection()),
23 _clock(clock),
24 _receiveCallback(NULL),
25 _timing(timing),
26 _timestampMap(kDecoderFrameMemoryLength),
27 _lastReceivedPictureID(0)
28 {
29 }
30
~VCMDecodedFrameCallback()31 VCMDecodedFrameCallback::~VCMDecodedFrameCallback()
32 {
33 delete _critSect;
34 }
35
SetUserReceiveCallback(VCMReceiveCallback * receiveCallback)36 void VCMDecodedFrameCallback::SetUserReceiveCallback(
37 VCMReceiveCallback* receiveCallback)
38 {
39 CriticalSectionScoped cs(_critSect);
40 _receiveCallback = receiveCallback;
41 }
42
UserReceiveCallback()43 VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback()
44 {
45 CriticalSectionScoped cs(_critSect);
46 return _receiveCallback;
47 }
48
Decoded(I420VideoFrame & decodedImage)49 int32_t VCMDecodedFrameCallback::Decoded(I420VideoFrame& decodedImage)
50 {
51 // TODO(holmer): We should improve this so that we can handle multiple
52 // callbacks from one call to Decode().
53 VCMFrameInformation* frameInfo;
54 VCMReceiveCallback* callback;
55 {
56 CriticalSectionScoped cs(_critSect);
57 frameInfo = static_cast<VCMFrameInformation*>(
58 _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 _timing.StopDecodeTimer(
69 decodedImage.timestamp(),
70 frameInfo->decodeStartTimeMs,
71 _clock->TimeInMilliseconds());
72
73 if (callback != NULL)
74 {
75 decodedImage.set_render_time_ms(frameInfo->renderTimeMs);
76 callback->FrameToRender(decodedImage);
77 }
78 return WEBRTC_VIDEO_CODEC_OK;
79 }
80
81 int32_t
ReceivedDecodedReferenceFrame(const uint64_t pictureId)82 VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(
83 const uint64_t pictureId)
84 {
85 CriticalSectionScoped cs(_critSect);
86 if (_receiveCallback != NULL)
87 {
88 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId);
89 }
90 return -1;
91 }
92
93 int32_t
ReceivedDecodedFrame(const uint64_t pictureId)94 VCMDecodedFrameCallback::ReceivedDecodedFrame(const uint64_t pictureId)
95 {
96 _lastReceivedPictureID = pictureId;
97 return 0;
98 }
99
LastReceivedPictureID() const100 uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const
101 {
102 return _lastReceivedPictureID;
103 }
104
Map(uint32_t timestamp,VCMFrameInformation * frameInfo)105 int32_t VCMDecodedFrameCallback::Map(uint32_t timestamp, VCMFrameInformation* frameInfo)
106 {
107 CriticalSectionScoped cs(_critSect);
108 return _timestampMap.Add(timestamp, frameInfo);
109 }
110
Pop(uint32_t timestamp)111 int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp)
112 {
113 CriticalSectionScoped cs(_critSect);
114 if (_timestampMap.Pop(timestamp) == NULL)
115 {
116 return VCM_GENERAL_ERROR;
117 }
118 return VCM_OK;
119 }
120
VCMGenericDecoder(VideoDecoder & decoder,bool isExternal)121 VCMGenericDecoder::VCMGenericDecoder(VideoDecoder& decoder, bool isExternal)
122 :
123 _callback(NULL),
124 _frameInfos(),
125 _nextFrameInfoIdx(0),
126 _decoder(decoder),
127 _codecType(kVideoCodecUnknown),
128 _isExternal(isExternal),
129 _keyFrameDecoded(false)
130 {
131 }
132
~VCMGenericDecoder()133 VCMGenericDecoder::~VCMGenericDecoder()
134 {
135 }
136
InitDecode(const VideoCodec * settings,int32_t numberOfCores)137 int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings,
138 int32_t numberOfCores)
139 {
140 _codecType = settings->codecType;
141
142 return _decoder.InitDecode(settings, numberOfCores);
143 }
144
Decode(const VCMEncodedFrame & frame,int64_t nowMs)145 int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame,
146 int64_t nowMs)
147 {
148 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs;
149 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs();
150 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]);
151
152 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength;
153 int32_t ret = _decoder.Decode(frame.EncodedImage(),
154 frame.MissingFrame(),
155 frame.FragmentationHeader(),
156 frame.CodecSpecific(),
157 frame.RenderTimeMs());
158
159 if (ret < WEBRTC_VIDEO_CODEC_OK)
160 {
161 LOG(LS_WARNING) << "Failed to decode frame with timestamp "
162 << frame.TimeStamp() << ", error code: " << ret;
163 _callback->Pop(frame.TimeStamp());
164 return ret;
165 }
166 else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT ||
167 ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI)
168 {
169 // No output
170 _callback->Pop(frame.TimeStamp());
171 }
172 return ret;
173 }
174
175 int32_t
Release()176 VCMGenericDecoder::Release()
177 {
178 return _decoder.Release();
179 }
180
Reset()181 int32_t VCMGenericDecoder::Reset()
182 {
183 return _decoder.Reset();
184 }
185
SetCodecConfigParameters(const uint8_t * buffer,int32_t size)186 int32_t VCMGenericDecoder::SetCodecConfigParameters(const uint8_t* buffer, int32_t size)
187 {
188 return _decoder.SetCodecConfigParameters(buffer, size);
189 }
190
RegisterDecodeCompleteCallback(VCMDecodedFrameCallback * callback)191 int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(VCMDecodedFrameCallback* callback)
192 {
193 _callback = callback;
194 return _decoder.RegisterDecodeCompleteCallback(callback);
195 }
196
External() const197 bool VCMGenericDecoder::External() const
198 {
199 return _isExternal;
200 }
201
202 } // namespace
203