blob: 6530a07d4de8120c18441b31e467841fbc9804f1 [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
tommie3aa88b2017-04-04 03:53:02 -070011#include "webrtc/modules/video_coding/generic_decoder.h"
12
sakal55d932b2016-09-30 06:19:08 -070013#include "webrtc/base/checks.h"
pbos854e84c2015-11-16 16:39:06 -080014#include "webrtc/base/logging.h"
pbosd9eec762015-11-17 06:03:43 -080015#include "webrtc/base/trace_event.h"
Peter Boströma443ec12015-11-30 19:14:50 +010016#include "webrtc/modules/video_coding/include/video_coding.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010017#include "webrtc/modules/video_coding/internal_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010018#include "webrtc/system_wrappers/include/clock.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000019
20namespace webrtc {
21
philipel9d3ab612015-12-21 04:12:39 -080022VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming* timing,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000023 Clock* clock)
tommid0a71ba2017-03-14 04:16:20 -070024 : _clock(clock),
Peter Boströmb7d9a972015-12-18 16:01:11 +010025 _timing(timing),
26 _timestampMap(kDecoderFrameMemoryLength),
tommie3aa88b2017-04-04 03:53:02 -070027 _lastReceivedPictureID(0) {
28 decoder_thread_.DetachFromThread();
29}
niklase@google.com470e71d2011-07-07 08:21:25 +000030
philipel9d3ab612015-12-21 04:12:39 -080031VCMDecodedFrameCallback::~VCMDecodedFrameCallback() {
tommie3aa88b2017-04-04 03:53:02 -070032 RTC_DCHECK(construction_thread_.CalledOnValidThread());
niklase@google.com470e71d2011-07-07 08:21:25 +000033}
34
stefan@webrtc.org06887ae2011-10-10 14:17:46 +000035void VCMDecodedFrameCallback::SetUserReceiveCallback(
philipel9d3ab612015-12-21 04:12:39 -080036 VCMReceiveCallback* receiveCallback) {
tommid0a71ba2017-03-14 04:16:20 -070037 RTC_DCHECK(construction_thread_.CalledOnValidThread());
38 RTC_DCHECK((!_receiveCallback && receiveCallback) ||
39 (_receiveCallback && !receiveCallback));
philipel9d3ab612015-12-21 04:12:39 -080040 _receiveCallback = receiveCallback;
niklase@google.com470e71d2011-07-07 08:21:25 +000041}
42
philipel9d3ab612015-12-21 04:12:39 -080043VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() {
tommie3aa88b2017-04-04 03:53:02 -070044 RTC_DCHECK_RUN_ON(&decoder_thread_);
tommid0a71ba2017-03-14 04:16:20 -070045 // Called on the decode thread via VCMCodecDataBase::GetDecoder.
46 // The callback must always have been set before this happens.
47 RTC_DCHECK(_receiveCallback);
philipel9d3ab612015-12-21 04:12:39 -080048 return _receiveCallback;
wuchengli@chromium.org0d94c2f2013-08-12 14:20:49 +000049}
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) {
sakalcc452e12017-02-09 04:53:45 -080057 Decoded(decodedImage,
58 decode_time_ms >= 0 ? rtc::Optional<int32_t>(decode_time_ms)
59 : rtc::Optional<int32_t>(),
60 rtc::Optional<uint8_t>());
61 return WEBRTC_VIDEO_CODEC_OK;
62}
63
64void VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
65 rtc::Optional<int32_t> decode_time_ms,
66 rtc::Optional<uint8_t> qp) {
tommie3aa88b2017-04-04 03:53:02 -070067 RTC_DCHECK_RUN_ON(&decoder_thread_);
tommid0a71ba2017-03-14 04:16:20 -070068 RTC_DCHECK(_receiveCallback) << "Callback must not be null at this point";
tommie3aa88b2017-04-04 03:53:02 -070069
philipel9d3ab612015-12-21 04:12:39 -080070 TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded",
71 "timestamp", decodedImage.timestamp());
72 // TODO(holmer): We should improve this so that we can handle multiple
73 // callbacks from one call to Decode().
tommie3aa88b2017-04-04 03:53:02 -070074 VCMFrameInformation* frameInfo = _timestampMap.Pop(decodedImage.timestamp());
philipel9d3ab612015-12-21 04:12:39 -080075
76 if (frameInfo == NULL) {
77 LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping "
78 "this one.";
sakalcc452e12017-02-09 04:53:45 -080079 return;
philipel9d3ab612015-12-21 04:12:39 -080080 }
81
82 const int64_t now_ms = _clock->TimeInMilliseconds();
sakalcc452e12017-02-09 04:53:45 -080083 if (!decode_time_ms) {
philipel9d3ab612015-12-21 04:12:39 -080084 decode_time_ms =
sakalcc452e12017-02-09 04:53:45 -080085 rtc::Optional<int32_t>(now_ms - frameInfo->decodeStartTimeMs);
philipel9d3ab612015-12-21 04:12:39 -080086 }
sakalcc452e12017-02-09 04:53:45 -080087 _timing->StopDecodeTimer(decodedImage.timestamp(), *decode_time_ms, now_ms,
philipel9d3ab612015-12-21 04:12:39 -080088 frameInfo->renderTimeMs);
89
nisse1c0dea82017-01-30 02:43:18 -080090 decodedImage.set_timestamp_us(
91 frameInfo->renderTimeMs * rtc::kNumMicrosecsPerMillisec);
sakal55d932b2016-09-30 06:19:08 -070092 decodedImage.set_rotation(frameInfo->rotation);
tommid0a71ba2017-03-14 04:16:20 -070093 _receiveCallback->FrameToRender(decodedImage, qp);
niklase@google.com470e71d2011-07-07 08:21:25 +000094}
95
philipel9d3ab612015-12-21 04:12:39 -080096int32_t VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(
97 const uint64_t pictureId) {
tommie3aa88b2017-04-04 03:53:02 -070098 RTC_DCHECK_RUN_ON(&decoder_thread_);
tommid0a71ba2017-03-14 04:16:20 -070099 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId);
niklase@google.com470e71d2011-07-07 08:21:25 +0000100}
101
philipel9d3ab612015-12-21 04:12:39 -0800102int32_t VCMDecodedFrameCallback::ReceivedDecodedFrame(
103 const uint64_t pictureId) {
tommie3aa88b2017-04-04 03:53:02 -0700104 RTC_DCHECK_RUN_ON(&decoder_thread_);
philipel9d3ab612015-12-21 04:12:39 -0800105 _lastReceivedPictureID = pictureId;
106 return 0;
107}
108
109uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const {
tommie3aa88b2017-04-04 03:53:02 -0700110 RTC_DCHECK_RUN_ON(&decoder_thread_);
philipel9d3ab612015-12-21 04:12:39 -0800111 return _lastReceivedPictureID;
niklase@google.com470e71d2011-07-07 08:21:25 +0000112}
113
Peter Boströmb7d9a972015-12-18 16:01:11 +0100114void VCMDecodedFrameCallback::OnDecoderImplementationName(
115 const char* implementation_name) {
tommie3aa88b2017-04-04 03:53:02 -0700116 RTC_DCHECK_RUN_ON(&decoder_thread_);
tommid0a71ba2017-03-14 04:16:20 -0700117 _receiveCallback->OnDecoderImplementationName(implementation_name);
Peter Boströmb7d9a972015-12-18 16:01:11 +0100118}
119
pbos1968d3f2015-09-28 08:52:18 -0700120void VCMDecodedFrameCallback::Map(uint32_t timestamp,
121 VCMFrameInformation* frameInfo) {
tommie3aa88b2017-04-04 03:53:02 -0700122 RTC_DCHECK_RUN_ON(&decoder_thread_);
pbos1968d3f2015-09-28 08:52:18 -0700123 _timestampMap.Add(timestamp, frameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000124}
125
philipel9d3ab612015-12-21 04:12:39 -0800126int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) {
tommie3aa88b2017-04-04 03:53:02 -0700127 RTC_DCHECK_RUN_ON(&decoder_thread_);
128 return _timestampMap.Pop(timestamp) == nullptr ? VCM_GENERAL_ERROR : VCM_OK;
niklase@google.com470e71d2011-07-07 08:21:25 +0000129}
130
Peter Boström187db632015-12-01 17:20:01 +0100131VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal)
132 : _callback(NULL),
133 _frameInfos(),
134 _nextFrameInfoIdx(0),
tommie3aa88b2017-04-04 03:53:02 -0700135 decoder_(decoder),
Peter Boström187db632015-12-01 17:20:01 +0100136 _codecType(kVideoCodecUnknown),
tommie3aa88b2017-04-04 03:53:02 -0700137 _isExternal(isExternal) {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000138
tommie3aa88b2017-04-04 03:53:02 -0700139VCMGenericDecoder::~VCMGenericDecoder() {
140 decoder_->Release();
141 if (_isExternal)
142 decoder_.release();
143
144 RTC_DCHECK(_isExternal || !decoder_);
145}
niklase@google.com470e71d2011-07-07 08:21:25 +0000146
pbos@webrtc.org7b859cc2013-04-02 15:54:38 +0000147int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings,
philipel9d3ab612015-12-21 04:12:39 -0800148 int32_t numberOfCores) {
tommie3aa88b2017-04-04 03:53:02 -0700149 RTC_DCHECK_RUN_ON(&decoder_thread_);
philipel9d3ab612015-12-21 04:12:39 -0800150 TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode");
151 _codecType = settings->codecType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000152
tommie3aa88b2017-04-04 03:53:02 -0700153 return decoder_->InitDecode(settings, numberOfCores);
niklase@google.com470e71d2011-07-07 08:21:25 +0000154}
155
pbosd9eec762015-11-17 06:03:43 -0800156int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) {
tommie3aa88b2017-04-04 03:53:02 -0700157 RTC_DCHECK_RUN_ON(&decoder_thread_);
158 TRACE_EVENT2("webrtc", "VCMGenericDecoder::Decode", "timestamp",
159 frame.EncodedImage()._timeStamp, "decoder",
160 decoder_->ImplementationName());
161 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs;
162 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs();
163 _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation();
164 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]);
niklase@google.com470e71d2011-07-07 08:21:25 +0000165
tommie3aa88b2017-04-04 03:53:02 -0700166 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength;
167 const RTPFragmentationHeader dummy_header;
168 int32_t ret = decoder_->Decode(frame.EncodedImage(), frame.MissingFrame(),
169 &dummy_header, frame.CodecSpecific(),
170 frame.RenderTimeMs());
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
tommie3aa88b2017-04-04 03:53:02 -0700172 // TODO(tommi): Necessary every time?
173 // Maybe this should be the first thing the function does, and only the first
174 // time around?
175 _callback->OnDecoderImplementationName(decoder_->ImplementationName());
176
177 if (ret != WEBRTC_VIDEO_CODEC_OK) {
philipel9d3ab612015-12-21 04:12:39 -0800178 if (ret < WEBRTC_VIDEO_CODEC_OK) {
tommie3aa88b2017-04-04 03:53:02 -0700179 LOG(LS_WARNING) << "Failed to decode frame with timestamp "
180 << frame.TimeStamp() << ", error code: " << ret;
stefan@webrtc.org06887ae2011-10-10 14:17:46 +0000181 }
tommie3aa88b2017-04-04 03:53:02 -0700182 // We pop the frame for all non-'OK', failure or success codes such as
183 // WEBRTC_VIDEO_CODEC_NO_OUTPUT and WEBRTC_VIDEO_CODEC_REQUEST_SLI.
184 _callback->Pop(frame.TimeStamp());
185 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000186
tommie3aa88b2017-04-04 03:53:02 -0700187 return ret;
niklase@google.com470e71d2011-07-07 08:21:25 +0000188}
189
Peter Boström187db632015-12-01 17:20:01 +0100190int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(
191 VCMDecodedFrameCallback* callback) {
tommie3aa88b2017-04-04 03:53:02 -0700192 RTC_DCHECK_RUN_ON(&decoder_thread_);
Peter Boström187db632015-12-01 17:20:01 +0100193 _callback = callback;
tommie3aa88b2017-04-04 03:53:02 -0700194 return decoder_->RegisterDecodeCompleteCallback(callback);
niklase@google.com470e71d2011-07-07 08:21:25 +0000195}
196
perkj796cfaf2015-12-10 09:27:38 -0800197bool VCMGenericDecoder::PrefersLateDecoding() const {
tommie3aa88b2017-04-04 03:53:02 -0700198 RTC_DCHECK_RUN_ON(&decoder_thread_);
199 return decoder_->PrefersLateDecoding();
perkj796cfaf2015-12-10 09:27:38 -0800200}
201
tommie3aa88b2017-04-04 03:53:02 -0700202#if defined(WEBRTC_ANDROID)
203void VCMGenericDecoder::PollDecodedFrames() {
204 RTC_DCHECK_RUN_ON(&decoder_thread_);
205 decoder_->PollDecodedFrames();
206}
207#endif
208
philipel9d3ab612015-12-21 04:12:39 -0800209} // namespace webrtc