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