blob: 08282f9e6c2c2de97221ab7f8c0197adca03e28d [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)
niklase@google.com470e71d2011-07-07 08:21:25 +000022:
stefan@webrtc.org7889a9b2011-12-12 08:18:24 +000023_critSect(CriticalSectionWrapper::CreateCriticalSection()),
henrik.lundin@webrtc.org7d8c72e2011-12-21 15:24:01 +000024_clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000025_receiveCallback(NULL),
26_timing(timing),
stefan@webrtc.org8e506932012-01-19 12:30:21 +000027_timestampMap(kDecoderFrameMemoryLength),
28_lastReceivedPictureID(0)
niklase@google.com470e71d2011-07-07 08:21:25 +000029{
30}
31
32VCMDecodedFrameCallback::~VCMDecodedFrameCallback()
33{
stefan@webrtc.org7889a9b2011-12-12 08:18:24 +000034 delete _critSect;
niklase@google.com470e71d2011-07-07 08:21:25 +000035}
36
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000037void VCMDecodedFrameCallback::SetUserReceiveCallback(
38 VCMReceiveCallback* receiveCallback)
niklase@google.com470e71d2011-07-07 08:21:25 +000039{
40 CriticalSectionScoped cs(_critSect);
41 _receiveCallback = receiveCallback;
42}
43
wuchengli@chromium.org0d94c2f2013-08-12 14:20:49 +000044VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback()
45{
46 CriticalSectionScoped cs(_critSect);
47 return _receiveCallback;
48}
49
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070050int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage) {
Per327d8ba2015-11-10 14:00:27 +010051 return Decoded(decodedImage, -1);
52}
53
54int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
55 int64_t decode_time_ms) {
pbosd9eec762015-11-17 06:03:43 -080056 TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded",
57 "timestamp", decodedImage.timestamp());
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000058 // TODO(holmer): We should improve this so that we can handle multiple
59 // callbacks from one call to Decode().
fischman@webrtc.orge001b572013-06-04 03:29:37 +000060 VCMFrameInformation* frameInfo;
61 VCMReceiveCallback* callback;
62 {
63 CriticalSectionScoped cs(_critSect);
pbos1968d3f2015-09-28 08:52:18 -070064 frameInfo = _timestampMap.Pop(decodedImage.timestamp());
fischman@webrtc.orge001b572013-06-04 03:29:37 +000065 callback = _receiveCallback;
66 }
stefan@webrtc.org64339a72014-05-19 13:31:35 +000067
68 if (frameInfo == NULL) {
69 LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping "
70 "this one.";
71 return WEBRTC_VIDEO_CODEC_OK;
72 }
niklase@google.com470e71d2011-07-07 08:21:25 +000073
Per327d8ba2015-11-10 14:00:27 +010074 const int64_t now_ms = _clock->TimeInMilliseconds();
75 if (decode_time_ms < 0) {
76 decode_time_ms =
77 static_cast<int32_t>(now_ms - frameInfo->decodeStartTimeMs);
78 }
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000079 _timing.StopDecodeTimer(
magjed@webrtc.org2056ee32015-03-16 13:46:52 +000080 decodedImage.timestamp(),
Per327d8ba2015-11-10 14:00:27 +010081 decode_time_ms,
82 now_ms,
asapersson@webrtc.orgf2447602014-12-09 14:13:26 +000083 frameInfo->renderTimeMs);
niklase@google.com470e71d2011-07-07 08:21:25 +000084
fischman@webrtc.orge001b572013-06-04 03:29:37 +000085 if (callback != NULL)
niklase@google.com470e71d2011-07-07 08:21:25 +000086 {
magjed@webrtc.org2056ee32015-03-16 13:46:52 +000087 decodedImage.set_render_time_ms(frameInfo->renderTimeMs);
guoweis@webrtc.org54d072e2015-03-17 21:54:50 +000088 decodedImage.set_rotation(frameInfo->rotation);
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000089 callback->FrameToRender(decodedImage);
niklase@google.com470e71d2011-07-07 08:21:25 +000090 }
niklase@google.com470e71d2011-07-07 08:21:25 +000091 return WEBRTC_VIDEO_CODEC_OK;
92}
93
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +000094int32_t
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000095VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +000096 const uint64_t pictureId)
niklase@google.com470e71d2011-07-07 08:21:25 +000097{
98 CriticalSectionScoped cs(_critSect);
99 if (_receiveCallback != NULL)
100 {
101 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId);
102 }
103 return -1;
104}
105
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000106int32_t
107VCMDecodedFrameCallback::ReceivedDecodedFrame(const uint64_t pictureId)
niklase@google.com470e71d2011-07-07 08:21:25 +0000108{
109 _lastReceivedPictureID = pictureId;
110 return 0;
111}
112
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000113uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000114{
115 return _lastReceivedPictureID;
116}
117
pbos1968d3f2015-09-28 08:52:18 -0700118void VCMDecodedFrameCallback::Map(uint32_t timestamp,
119 VCMFrameInformation* frameInfo) {
120 CriticalSectionScoped cs(_critSect);
121 _timestampMap.Add(timestamp, frameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000122}
123
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000124int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp)
niklase@google.com470e71d2011-07-07 08:21:25 +0000125{
126 CriticalSectionScoped cs(_critSect);
127 if (_timestampMap.Pop(timestamp) == NULL)
128 {
129 return VCM_GENERAL_ERROR;
130 }
131 return VCM_OK;
132}
133
Peter Boström187db632015-12-01 17:20:01 +0100134VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal)
135 : _callback(NULL),
136 _frameInfos(),
137 _nextFrameInfoIdx(0),
138 _decoder(decoder),
139 _codecType(kVideoCodecUnknown),
140 _isExternal(isExternal),
141 _keyFrameDecoded(false) {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000142
Peter Boström187db632015-12-01 17:20:01 +0100143VCMGenericDecoder::~VCMGenericDecoder() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000144
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000145int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings,
mikhal@webrtc.orgb2c28c32013-08-23 21:54:50 +0000146 int32_t numberOfCores)
niklase@google.com470e71d2011-07-07 08:21:25 +0000147{
pbosd9eec762015-11-17 06:03:43 -0800148 TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode");
niklase@google.com470e71d2011-07-07 08:21:25 +0000149 _codecType = settings->codecType;
150
Peter Boström187db632015-12-01 17:20:01 +0100151 return _decoder->InitDecode(settings, numberOfCores);
niklase@google.com470e71d2011-07-07 08:21:25 +0000152}
153
pbosd9eec762015-11-17 06:03:43 -0800154int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) {
155 TRACE_EVENT1("webrtc", "VCMGenericDecoder::Decode", "timestamp",
156 frame.EncodedImage()._timeStamp);
henrik.lundin@webrtc.org7d8c72e2011-12-21 15:24:01 +0000157 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000158 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs();
guoweis@webrtc.org54d072e2015-03-17 21:54:50 +0000159 _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation();
niklase@google.com470e71d2011-07-07 08:21:25 +0000160 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]);
161
niklase@google.com470e71d2011-07-07 08:21:25 +0000162 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength;
Peter Boström187db632015-12-01 17:20:01 +0100163 int32_t ret = _decoder->Decode(frame.EncodedImage(), frame.MissingFrame(),
164 frame.FragmentationHeader(),
165 frame.CodecSpecific(), frame.RenderTimeMs());
niklase@google.com470e71d2011-07-07 08:21:25 +0000166
167 if (ret < WEBRTC_VIDEO_CODEC_OK)
168 {
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000169 LOG(LS_WARNING) << "Failed to decode frame with timestamp "
170 << frame.TimeStamp() << ", error code: " << ret;
niklase@google.com470e71d2011-07-07 08:21:25 +0000171 _callback->Pop(frame.TimeStamp());
172 return ret;
173 }
stefan@webrtc.org06887ae2011-10-10 14:17:46 +0000174 else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT ||
175 ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI)
176 {
177 // No output
178 _callback->Pop(frame.TimeStamp());
179 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000180 return ret;
181}
182
Peter Boström187db632015-12-01 17:20:01 +0100183int32_t VCMGenericDecoder::Release() {
184 return _decoder->Release();
niklase@google.com470e71d2011-07-07 08:21:25 +0000185}
186
Peter Boström187db632015-12-01 17:20:01 +0100187int32_t VCMGenericDecoder::Reset() {
188 return _decoder->Reset();
niklase@google.com470e71d2011-07-07 08:21:25 +0000189}
190
Peter Boström187db632015-12-01 17:20:01 +0100191int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(
192 VCMDecodedFrameCallback* callback) {
193 _callback = callback;
194 return _decoder->RegisterDecodeCompleteCallback(callback);
niklase@google.com470e71d2011-07-07 08:21:25 +0000195}
196
Peter Boström187db632015-12-01 17:20:01 +0100197bool VCMGenericDecoder::External() const {
198 return _isExternal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000199}
200
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000201} // namespace