blob: 092d0546ca48615bde27eb5eb184772068081d5a [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
kjellanderec192bd2015-11-30 23:14:33 -0800134VCMGenericDecoder::VCMGenericDecoder(VideoDecoder& decoder, bool isExternal)
135:
136_callback(NULL),
137_frameInfos(),
138_nextFrameInfoIdx(0),
139_decoder(decoder),
140_codecType(kVideoCodecUnknown),
141_isExternal(isExternal),
142_keyFrameDecoded(false)
143{
niklase@google.com470e71d2011-07-07 08:21:25 +0000144}
145
146VCMGenericDecoder::~VCMGenericDecoder()
147{
148}
149
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000150int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings,
mikhal@webrtc.orgb2c28c32013-08-23 21:54:50 +0000151 int32_t numberOfCores)
niklase@google.com470e71d2011-07-07 08:21:25 +0000152{
pbosd9eec762015-11-17 06:03:43 -0800153 TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode");
niklase@google.com470e71d2011-07-07 08:21:25 +0000154 _codecType = settings->codecType;
155
kjellanderec192bd2015-11-30 23:14:33 -0800156 return _decoder.InitDecode(settings, numberOfCores);
niklase@google.com470e71d2011-07-07 08:21:25 +0000157}
158
pbosd9eec762015-11-17 06:03:43 -0800159int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) {
160 TRACE_EVENT1("webrtc", "VCMGenericDecoder::Decode", "timestamp",
161 frame.EncodedImage()._timeStamp);
henrik.lundin@webrtc.org7d8c72e2011-12-21 15:24:01 +0000162 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000163 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs();
guoweis@webrtc.org54d072e2015-03-17 21:54:50 +0000164 _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation();
niklase@google.com470e71d2011-07-07 08:21:25 +0000165 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]);
166
niklase@google.com470e71d2011-07-07 08:21:25 +0000167 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength;
kjellanderec192bd2015-11-30 23:14:33 -0800168 int32_t ret = _decoder.Decode(frame.EncodedImage(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000169 frame.MissingFrame(),
stefan@webrtc.orgc3d89102011-09-08 06:50:28 +0000170 frame.FragmentationHeader(),
henrik.lundin@webrtc.org473bac82011-08-17 09:47:33 +0000171 frame.CodecSpecific(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000172 frame.RenderTimeMs());
173
174 if (ret < WEBRTC_VIDEO_CODEC_OK)
175 {
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000176 LOG(LS_WARNING) << "Failed to decode frame with timestamp "
177 << frame.TimeStamp() << ", error code: " << ret;
niklase@google.com470e71d2011-07-07 08:21:25 +0000178 _callback->Pop(frame.TimeStamp());
179 return ret;
180 }
stefan@webrtc.org06887ae2011-10-10 14:17:46 +0000181 else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT ||
182 ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI)
183 {
184 // No output
185 _callback->Pop(frame.TimeStamp());
186 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000187 return ret;
188}
189
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000190int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000191VCMGenericDecoder::Release()
192{
kjellanderec192bd2015-11-30 23:14:33 -0800193 return _decoder.Release();
niklase@google.com470e71d2011-07-07 08:21:25 +0000194}
195
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000196int32_t VCMGenericDecoder::Reset()
niklase@google.com470e71d2011-07-07 08:21:25 +0000197{
kjellanderec192bd2015-11-30 23:14:33 -0800198 return _decoder.Reset();
niklase@google.com470e71d2011-07-07 08:21:25 +0000199}
200
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000201int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(VCMDecodedFrameCallback* callback)
niklase@google.com470e71d2011-07-07 08:21:25 +0000202{
203 _callback = callback;
kjellanderec192bd2015-11-30 23:14:33 -0800204 return _decoder.RegisterDecodeCompleteCallback(callback);
niklase@google.com470e71d2011-07-07 08:21:25 +0000205}
206
207bool VCMGenericDecoder::External() const
208{
209 return _isExternal;
210}
211
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000212} // namespace