• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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