blob: ace826602fcd8e721c48c57c2b4bcb96fc5ae4ac [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
philipel9d3ab612015-12-21 04:12:39 -080020VCMDecodedFrameCallback::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
philipel9d3ab612015-12-21 04:12:39 -080029VCMDecodedFrameCallback::~VCMDecodedFrameCallback() {
30 delete _critSect;
niklase@google.com470e71d2011-07-07 08:21:25 +000031}
32
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000033void VCMDecodedFrameCallback::SetUserReceiveCallback(
philipel9d3ab612015-12-21 04:12:39 -080034 VCMReceiveCallback* receiveCallback) {
35 CriticalSectionScoped cs(_critSect);
36 _receiveCallback = receiveCallback;
niklase@google.com470e71d2011-07-07 08:21:25 +000037}
38
philipel9d3ab612015-12-21 04:12:39 -080039VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() {
40 CriticalSectionScoped cs(_critSect);
41 return _receiveCallback;
wuchengli@chromium.org0d94c2f2013-08-12 14:20:49 +000042}
43
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070044int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage) {
Per327d8ba2015-11-10 14:00:27 +010045 return Decoded(decodedImage, -1);
46}
47
48int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
49 int64_t decode_time_ms) {
philipel9d3ab612015-12-21 04:12:39 -080050 TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded",
51 "timestamp", decodedImage.timestamp());
52 // TODO(holmer): We should improve this so that we can handle multiple
53 // callbacks from one call to Decode().
54 VCMFrameInformation* frameInfo;
55 VCMReceiveCallback* callback;
56 {
niklase@google.com470e71d2011-07-07 08:21:25 +000057 CriticalSectionScoped cs(_critSect);
philipel9d3ab612015-12-21 04:12:39 -080058 frameInfo = _timestampMap.Pop(decodedImage.timestamp());
59 callback = _receiveCallback;
60 }
61
62 if (frameInfo == NULL) {
63 LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping "
64 "this one.";
65 return WEBRTC_VIDEO_CODEC_OK;
66 }
67
68 const int64_t now_ms = _clock->TimeInMilliseconds();
69 if (decode_time_ms < 0) {
70 decode_time_ms =
71 static_cast<int32_t>(now_ms - frameInfo->decodeStartTimeMs);
72 }
73 _timing->StopDecodeTimer(decodedImage.timestamp(), decode_time_ms, now_ms,
74 frameInfo->renderTimeMs);
75
76 if (callback != NULL) {
77 decodedImage.set_render_time_ms(frameInfo->renderTimeMs);
78 decodedImage.set_rotation(frameInfo->rotation);
79 callback->FrameToRender(decodedImage);
80 }
81 return WEBRTC_VIDEO_CODEC_OK;
niklase@google.com470e71d2011-07-07 08:21:25 +000082}
83
philipel9d3ab612015-12-21 04:12:39 -080084int32_t VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(
85 const uint64_t pictureId) {
86 CriticalSectionScoped cs(_critSect);
87 if (_receiveCallback != NULL) {
88 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId);
89 }
90 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +000091}
92
philipel9d3ab612015-12-21 04:12:39 -080093int32_t VCMDecodedFrameCallback::ReceivedDecodedFrame(
94 const uint64_t pictureId) {
95 _lastReceivedPictureID = pictureId;
96 return 0;
97}
98
99uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const {
100 return _lastReceivedPictureID;
niklase@google.com470e71d2011-07-07 08:21:25 +0000101}
102
Peter Boströmb7d9a972015-12-18 16:01:11 +0100103void VCMDecodedFrameCallback::OnDecoderImplementationName(
104 const char* implementation_name) {
105 CriticalSectionScoped cs(_critSect);
106 if (_receiveCallback)
107 _receiveCallback->OnDecoderImplementationName(implementation_name);
108}
109
pbos1968d3f2015-09-28 08:52:18 -0700110void VCMDecodedFrameCallback::Map(uint32_t timestamp,
111 VCMFrameInformation* frameInfo) {
112 CriticalSectionScoped cs(_critSect);
113 _timestampMap.Add(timestamp, frameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000114}
115
philipel9d3ab612015-12-21 04:12:39 -0800116int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) {
117 CriticalSectionScoped cs(_critSect);
118 if (_timestampMap.Pop(timestamp) == NULL) {
119 return VCM_GENERAL_ERROR;
120 }
121 return VCM_OK;
niklase@google.com470e71d2011-07-07 08:21:25 +0000122}
123
Peter Boström187db632015-12-01 17:20:01 +0100124VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal)
125 : _callback(NULL),
126 _frameInfos(),
127 _nextFrameInfoIdx(0),
128 _decoder(decoder),
129 _codecType(kVideoCodecUnknown),
130 _isExternal(isExternal),
131 _keyFrameDecoded(false) {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000132
Peter Boström187db632015-12-01 17:20:01 +0100133VCMGenericDecoder::~VCMGenericDecoder() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000134
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000135int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings,
philipel9d3ab612015-12-21 04:12:39 -0800136 int32_t numberOfCores) {
137 TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode");
138 _codecType = settings->codecType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000139
philipel9d3ab612015-12-21 04:12:39 -0800140 return _decoder->InitDecode(settings, numberOfCores);
niklase@google.com470e71d2011-07-07 08:21:25 +0000141}
142
pbosd9eec762015-11-17 06:03:43 -0800143int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) {
144 TRACE_EVENT1("webrtc", "VCMGenericDecoder::Decode", "timestamp",
145 frame.EncodedImage()._timeStamp);
henrik.lundin@webrtc.org7d8c72e2011-12-21 15:24:01 +0000146 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000147 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs();
guoweis@webrtc.org54d072e2015-03-17 21:54:50 +0000148 _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation();
niklase@google.com470e71d2011-07-07 08:21:25 +0000149 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]);
150
niklase@google.com470e71d2011-07-07 08:21:25 +0000151 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength;
nisse6f112cc2016-09-30 03:43:00 -0700152 const RTPFragmentationHeader dummy_header;
Peter Boström187db632015-12-01 17:20:01 +0100153 int32_t ret = _decoder->Decode(frame.EncodedImage(), frame.MissingFrame(),
nisse6f112cc2016-09-30 03:43:00 -0700154 &dummy_header,
Peter Boström187db632015-12-01 17:20:01 +0100155 frame.CodecSpecific(), frame.RenderTimeMs());
niklase@google.com470e71d2011-07-07 08:21:25 +0000156
Peter Boströmb7d9a972015-12-18 16:01:11 +0100157 _callback->OnDecoderImplementationName(_decoder->ImplementationName());
philipel9d3ab612015-12-21 04:12:39 -0800158 if (ret < WEBRTC_VIDEO_CODEC_OK) {
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000159 LOG(LS_WARNING) << "Failed to decode frame with timestamp "
160 << frame.TimeStamp() << ", error code: " << ret;
niklase@google.com470e71d2011-07-07 08:21:25 +0000161 _callback->Pop(frame.TimeStamp());
162 return ret;
philipel9d3ab612015-12-21 04:12:39 -0800163 } else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT ||
164 ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI) {
stefan@webrtc.org06887ae2011-10-10 14:17:46 +0000165 // No output
166 _callback->Pop(frame.TimeStamp());
167 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000168 return ret;
169}
170
Peter Boström187db632015-12-01 17:20:01 +0100171int32_t VCMGenericDecoder::Release() {
172 return _decoder->Release();
niklase@google.com470e71d2011-07-07 08:21:25 +0000173}
174
Peter Boström187db632015-12-01 17:20:01 +0100175int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(
176 VCMDecodedFrameCallback* callback) {
177 _callback = callback;
178 return _decoder->RegisterDecodeCompleteCallback(callback);
niklase@google.com470e71d2011-07-07 08:21:25 +0000179}
180
Peter Boström187db632015-12-01 17:20:01 +0100181bool VCMGenericDecoder::External() const {
182 return _isExternal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000183}
184
perkj796cfaf2015-12-10 09:27:38 -0800185bool VCMGenericDecoder::PrefersLateDecoding() const {
186 return _decoder->PrefersLateDecoding();
187}
188
philipel9d3ab612015-12-21 04:12:39 -0800189} // namespace webrtc