blob: 3c72509c052d978276fe5c964b327ce993453d7e [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
mikhal@webrtc.orga2031d52012-07-31 15:53:44 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
pbos854e84c2015-11-16 16:39:06 -080011#include "webrtc/base/logging.h"
pbosd9eec762015-11-17 06:03:43 -080012#include "webrtc/base/trace_event.h"
Peter Boströma443ec12015-11-30 19:14:50 +010013#include "webrtc/modules/video_coding/include/video_coding.h"
kjellanderec192bd2015-11-30 23:14:33 -080014#include "webrtc/modules/video_coding/generic_decoder.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010015#include "webrtc/modules/video_coding/internal_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010016#include "webrtc/system_wrappers/include/clock.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000017
18namespace webrtc {
19
henrik.lundin@webrtc.org7d8c72e2011-12-21 15:24:01 +000020VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming& timing,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000021 Clock* clock)
Peter Boströmb7d9a972015-12-18 16:01:11 +010022 : _critSect(CriticalSectionWrapper::CreateCriticalSection()),
23 _clock(clock),
24 _receiveCallback(NULL),
25 _timing(timing),
26 _timestampMap(kDecoderFrameMemoryLength),
27 _lastReceivedPictureID(0) {}
niklase@google.com470e71d2011-07-07 08:21:25 +000028
29VCMDecodedFrameCallback::~VCMDecodedFrameCallback()
30{
stefan@webrtc.org7889a9b2011-12-12 08:18:24 +000031 delete _critSect;
niklase@google.com470e71d2011-07-07 08:21:25 +000032}
33
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000034void VCMDecodedFrameCallback::SetUserReceiveCallback(
35 VCMReceiveCallback* receiveCallback)
niklase@google.com470e71d2011-07-07 08:21:25 +000036{
37 CriticalSectionScoped cs(_critSect);
38 _receiveCallback = receiveCallback;
39}
40
wuchengli@chromium.org0d94c2f2013-08-12 14:20:49 +000041VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback()
42{
43 CriticalSectionScoped cs(_critSect);
44 return _receiveCallback;
45}
46
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070047int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage) {
Per327d8ba2015-11-10 14:00:27 +010048 return Decoded(decodedImage, -1);
49}
50
51int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
52 int64_t decode_time_ms) {
pbosd9eec762015-11-17 06:03:43 -080053 TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded",
54 "timestamp", decodedImage.timestamp());
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000055 // TODO(holmer): We should improve this so that we can handle multiple
56 // callbacks from one call to Decode().
fischman@webrtc.orge001b572013-06-04 03:29:37 +000057 VCMFrameInformation* frameInfo;
58 VCMReceiveCallback* callback;
59 {
60 CriticalSectionScoped cs(_critSect);
pbos1968d3f2015-09-28 08:52:18 -070061 frameInfo = _timestampMap.Pop(decodedImage.timestamp());
fischman@webrtc.orge001b572013-06-04 03:29:37 +000062 callback = _receiveCallback;
63 }
stefan@webrtc.org64339a72014-05-19 13:31:35 +000064
65 if (frameInfo == NULL) {
66 LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping "
67 "this one.";
68 return WEBRTC_VIDEO_CODEC_OK;
69 }
niklase@google.com470e71d2011-07-07 08:21:25 +000070
Per327d8ba2015-11-10 14:00:27 +010071 const int64_t now_ms = _clock->TimeInMilliseconds();
72 if (decode_time_ms < 0) {
73 decode_time_ms =
74 static_cast<int32_t>(now_ms - frameInfo->decodeStartTimeMs);
75 }
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000076 _timing.StopDecodeTimer(
magjed@webrtc.org2056ee32015-03-16 13:46:52 +000077 decodedImage.timestamp(),
Per327d8ba2015-11-10 14:00:27 +010078 decode_time_ms,
79 now_ms,
asapersson@webrtc.orgf2447602014-12-09 14:13:26 +000080 frameInfo->renderTimeMs);
niklase@google.com470e71d2011-07-07 08:21:25 +000081
fischman@webrtc.orge001b572013-06-04 03:29:37 +000082 if (callback != NULL)
niklase@google.com470e71d2011-07-07 08:21:25 +000083 {
magjed@webrtc.org2056ee32015-03-16 13:46:52 +000084 decodedImage.set_render_time_ms(frameInfo->renderTimeMs);
guoweis@webrtc.org54d072e2015-03-17 21:54:50 +000085 decodedImage.set_rotation(frameInfo->rotation);
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000086 callback->FrameToRender(decodedImage);
niklase@google.com470e71d2011-07-07 08:21:25 +000087 }
niklase@google.com470e71d2011-07-07 08:21:25 +000088 return WEBRTC_VIDEO_CODEC_OK;
89}
90
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +000091int32_t
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000092VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +000093 const uint64_t pictureId)
niklase@google.com470e71d2011-07-07 08:21:25 +000094{
95 CriticalSectionScoped cs(_critSect);
96 if (_receiveCallback != NULL)
97 {
98 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId);
99 }
100 return -1;
101}
102
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000103int32_t
104VCMDecodedFrameCallback::ReceivedDecodedFrame(const uint64_t pictureId)
niklase@google.com470e71d2011-07-07 08:21:25 +0000105{
106 _lastReceivedPictureID = pictureId;
107 return 0;
108}
109
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000110uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000111{
112 return _lastReceivedPictureID;
113}
114
Peter Boströmb7d9a972015-12-18 16:01:11 +0100115void VCMDecodedFrameCallback::OnDecoderImplementationName(
116 const char* implementation_name) {
117 CriticalSectionScoped cs(_critSect);
118 if (_receiveCallback)
119 _receiveCallback->OnDecoderImplementationName(implementation_name);
120}
121
pbos1968d3f2015-09-28 08:52:18 -0700122void VCMDecodedFrameCallback::Map(uint32_t timestamp,
123 VCMFrameInformation* frameInfo) {
124 CriticalSectionScoped cs(_critSect);
125 _timestampMap.Add(timestamp, frameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000126}
127
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000128int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp)
niklase@google.com470e71d2011-07-07 08:21:25 +0000129{
130 CriticalSectionScoped cs(_critSect);
131 if (_timestampMap.Pop(timestamp) == NULL)
132 {
133 return VCM_GENERAL_ERROR;
134 }
135 return VCM_OK;
136}
137
Peter Boström187db632015-12-01 17:20:01 +0100138VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal)
139 : _callback(NULL),
140 _frameInfos(),
141 _nextFrameInfoIdx(0),
142 _decoder(decoder),
143 _codecType(kVideoCodecUnknown),
144 _isExternal(isExternal),
145 _keyFrameDecoded(false) {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000146
Peter Boström187db632015-12-01 17:20:01 +0100147VCMGenericDecoder::~VCMGenericDecoder() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000148
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000149int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings,
mikhal@webrtc.orgb2c28c32013-08-23 21:54:50 +0000150 int32_t numberOfCores)
niklase@google.com470e71d2011-07-07 08:21:25 +0000151{
pbosd9eec762015-11-17 06:03:43 -0800152 TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode");
niklase@google.com470e71d2011-07-07 08:21:25 +0000153 _codecType = settings->codecType;
154
Peter Boström187db632015-12-01 17:20:01 +0100155 return _decoder->InitDecode(settings, numberOfCores);
niklase@google.com470e71d2011-07-07 08:21:25 +0000156}
157
pbosd9eec762015-11-17 06:03:43 -0800158int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) {
159 TRACE_EVENT1("webrtc", "VCMGenericDecoder::Decode", "timestamp",
160 frame.EncodedImage()._timeStamp);
henrik.lundin@webrtc.org7d8c72e2011-12-21 15:24:01 +0000161 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000162 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs();
guoweis@webrtc.org54d072e2015-03-17 21:54:50 +0000163 _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation();
niklase@google.com470e71d2011-07-07 08:21:25 +0000164 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]);
165
niklase@google.com470e71d2011-07-07 08:21:25 +0000166 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength;
Peter Boström187db632015-12-01 17:20:01 +0100167 int32_t ret = _decoder->Decode(frame.EncodedImage(), frame.MissingFrame(),
168 frame.FragmentationHeader(),
169 frame.CodecSpecific(), frame.RenderTimeMs());
niklase@google.com470e71d2011-07-07 08:21:25 +0000170
Peter Boströmb7d9a972015-12-18 16:01:11 +0100171 _callback->OnDecoderImplementationName(_decoder->ImplementationName());
niklase@google.com470e71d2011-07-07 08:21:25 +0000172 if (ret < WEBRTC_VIDEO_CODEC_OK)
173 {
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000174 LOG(LS_WARNING) << "Failed to decode frame with timestamp "
175 << frame.TimeStamp() << ", error code: " << ret;
niklase@google.com470e71d2011-07-07 08:21:25 +0000176 _callback->Pop(frame.TimeStamp());
177 return ret;
178 }
stefan@webrtc.org06887ae2011-10-10 14:17:46 +0000179 else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT ||
180 ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI)
181 {
182 // No output
183 _callback->Pop(frame.TimeStamp());
184 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000185 return ret;
186}
187
Peter Boström187db632015-12-01 17:20:01 +0100188int32_t VCMGenericDecoder::Release() {
189 return _decoder->Release();
niklase@google.com470e71d2011-07-07 08:21:25 +0000190}
191
Peter Boström187db632015-12-01 17:20:01 +0100192int32_t VCMGenericDecoder::Reset() {
193 return _decoder->Reset();
niklase@google.com470e71d2011-07-07 08:21:25 +0000194}
195
Peter Boström187db632015-12-01 17:20:01 +0100196int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(
197 VCMDecodedFrameCallback* callback) {
198 _callback = callback;
199 return _decoder->RegisterDecodeCompleteCallback(callback);
niklase@google.com470e71d2011-07-07 08:21:25 +0000200}
201
Peter Boström187db632015-12-01 17:20:01 +0100202bool VCMGenericDecoder::External() const {
203 return _isExternal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000204}
205
perkj796cfaf2015-12-10 09:27:38 -0800206bool VCMGenericDecoder::PrefersLateDecoding() const {
207 return _decoder->PrefersLateDecoding();
208}
209
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000210} // namespace