blob: 294a9030c5c06106c090d17e208dfd2d4b31e405 [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
Peter Boströma443ec12015-11-30 19:14:50 +010011#include "webrtc/base/checks.h"
pbos854e84c2015-11-16 16:39:06 -080012#include "webrtc/base/logging.h"
pbosd9eec762015-11-17 06:03:43 -080013#include "webrtc/base/trace_event.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010014#include "webrtc/modules/video_coding/generic_decoder.h"
Peter Boströma443ec12015-11-30 19:14:50 +010015#include "webrtc/modules/video_coding/include/video_coding.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010016#include "webrtc/modules/video_coding/internal_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010017#include "webrtc/system_wrappers/include/clock.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000018
19namespace webrtc {
20
henrik.lundin@webrtc.org7d8c72e2011-12-21 15:24:01 +000021VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming& timing,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000022 Clock* clock)
niklase@google.com470e71d2011-07-07 08:21:25 +000023:
stefan@webrtc.org7889a9b2011-12-12 08:18:24 +000024_critSect(CriticalSectionWrapper::CreateCriticalSection()),
henrik.lundin@webrtc.org7d8c72e2011-12-21 15:24:01 +000025_clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000026_receiveCallback(NULL),
27_timing(timing),
stefan@webrtc.org8e506932012-01-19 12:30:21 +000028_timestampMap(kDecoderFrameMemoryLength),
29_lastReceivedPictureID(0)
niklase@google.com470e71d2011-07-07 08:21:25 +000030{
31}
32
33VCMDecodedFrameCallback::~VCMDecodedFrameCallback()
34{
stefan@webrtc.org7889a9b2011-12-12 08:18:24 +000035 delete _critSect;
niklase@google.com470e71d2011-07-07 08:21:25 +000036}
37
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000038void VCMDecodedFrameCallback::SetUserReceiveCallback(
39 VCMReceiveCallback* receiveCallback)
niklase@google.com470e71d2011-07-07 08:21:25 +000040{
41 CriticalSectionScoped cs(_critSect);
42 _receiveCallback = receiveCallback;
43}
44
wuchengli@chromium.org0d94c2f2013-08-12 14:20:49 +000045VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback()
46{
47 CriticalSectionScoped cs(_critSect);
48 return _receiveCallback;
49}
50
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070051int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage) {
Per327d8ba2015-11-10 14:00:27 +010052 return Decoded(decodedImage, -1);
53}
54
55int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
56 int64_t decode_time_ms) {
pbosd9eec762015-11-17 06:03:43 -080057 TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded",
58 "timestamp", decodedImage.timestamp());
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000059 // TODO(holmer): We should improve this so that we can handle multiple
60 // callbacks from one call to Decode().
fischman@webrtc.orge001b572013-06-04 03:29:37 +000061 VCMFrameInformation* frameInfo;
62 VCMReceiveCallback* callback;
63 {
64 CriticalSectionScoped cs(_critSect);
pbos1968d3f2015-09-28 08:52:18 -070065 frameInfo = _timestampMap.Pop(decodedImage.timestamp());
fischman@webrtc.orge001b572013-06-04 03:29:37 +000066 callback = _receiveCallback;
67 }
stefan@webrtc.org64339a72014-05-19 13:31:35 +000068
69 if (frameInfo == NULL) {
70 LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping "
71 "this one.";
72 return WEBRTC_VIDEO_CODEC_OK;
73 }
niklase@google.com470e71d2011-07-07 08:21:25 +000074
Per327d8ba2015-11-10 14:00:27 +010075 const int64_t now_ms = _clock->TimeInMilliseconds();
76 if (decode_time_ms < 0) {
77 decode_time_ms =
78 static_cast<int32_t>(now_ms - frameInfo->decodeStartTimeMs);
79 }
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000080 _timing.StopDecodeTimer(
magjed@webrtc.org2056ee32015-03-16 13:46:52 +000081 decodedImage.timestamp(),
Per327d8ba2015-11-10 14:00:27 +010082 decode_time_ms,
83 now_ms,
asapersson@webrtc.orgf2447602014-12-09 14:13:26 +000084 frameInfo->renderTimeMs);
niklase@google.com470e71d2011-07-07 08:21:25 +000085
fischman@webrtc.orge001b572013-06-04 03:29:37 +000086 if (callback != NULL)
niklase@google.com470e71d2011-07-07 08:21:25 +000087 {
magjed@webrtc.org2056ee32015-03-16 13:46:52 +000088 decodedImage.set_render_time_ms(frameInfo->renderTimeMs);
guoweis@webrtc.org54d072e2015-03-17 21:54:50 +000089 decodedImage.set_rotation(frameInfo->rotation);
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000090 callback->FrameToRender(decodedImage);
niklase@google.com470e71d2011-07-07 08:21:25 +000091 }
niklase@google.com470e71d2011-07-07 08:21:25 +000092 return WEBRTC_VIDEO_CODEC_OK;
93}
94
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +000095int32_t
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000096VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +000097 const uint64_t pictureId)
niklase@google.com470e71d2011-07-07 08:21:25 +000098{
99 CriticalSectionScoped cs(_critSect);
100 if (_receiveCallback != NULL)
101 {
102 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId);
103 }
104 return -1;
105}
106
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000107int32_t
108VCMDecodedFrameCallback::ReceivedDecodedFrame(const uint64_t pictureId)
niklase@google.com470e71d2011-07-07 08:21:25 +0000109{
110 _lastReceivedPictureID = pictureId;
111 return 0;
112}
113
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000114uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000115{
116 return _lastReceivedPictureID;
117}
118
pbos1968d3f2015-09-28 08:52:18 -0700119void VCMDecodedFrameCallback::Map(uint32_t timestamp,
120 VCMFrameInformation* frameInfo) {
121 CriticalSectionScoped cs(_critSect);
122 _timestampMap.Add(timestamp, frameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000123}
124
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000125int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp)
niklase@google.com470e71d2011-07-07 08:21:25 +0000126{
127 CriticalSectionScoped cs(_critSect);
128 if (_timestampMap.Pop(timestamp) == NULL)
129 {
130 return VCM_GENERAL_ERROR;
131 }
132 return VCM_OK;
133}
134
Peter Boströma443ec12015-11-30 19:14:50 +0100135VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal)
136 : _callback(NULL),
137 _frameInfos(),
138 _nextFrameInfoIdx(0),
139 _decoder(decoder),
140 _codecType(kVideoCodecUnknown),
141 _isExternal(isExternal),
142 _keyFrameDecoded(false) {
143 RTC_CHECK(_decoder);
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
Peter Boströma443ec12015-11-30 19:14:50 +0100156 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;
Peter Boströma443ec12015-11-30 19:14:50 +0100168 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{
Peter Boströma443ec12015-11-30 19:14:50 +0100193 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{
Peter Boströma443ec12015-11-30 19:14:50 +0100198 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;
Peter Boströma443ec12015-11-30 19:14:50 +0100204 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