blob: f5b0f5f78703dfc867db0ad5ba5b7f23d0cb89d0 [file] [log] [blame]
philipel2fee4d62018-03-21 16:52:13 +01001/*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
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
11#include "video/video_stream_decoder_impl.h"
12
Mirko Bonadei317a1f02019-09-17 17:06:18 +020013#include <memory>
14
Danil Chapovalov471783f2019-03-11 14:26:02 +010015#include "api/task_queue/queued_task.h"
philipel97187112018-03-23 10:43:21 +010016#include "rtc_base/logging.h"
philipel844876d2018-04-05 11:02:54 +020017#include "rtc_base/numerics/mod_ops.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "rtc_base/time_utils.h"
philipel2fee4d62018-03-21 16:52:13 +010019
20namespace webrtc {
philipel97187112018-03-23 10:43:21 +010021
philipel2fee4d62018-03-21 16:52:13 +010022VideoStreamDecoderImpl::VideoStreamDecoderImpl(
Danil Chapovalovb703db92019-04-08 16:59:28 +020023 VideoStreamDecoderInterface::Callbacks* callbacks,
philipel2fee4d62018-03-21 16:52:13 +010024 VideoDecoderFactory* decoder_factory,
Danil Chapovalovb703db92019-04-08 16:59:28 +020025 TaskQueueFactory* task_queue_factory,
philipel2fee4d62018-03-21 16:52:13 +010026 std::map<int, std::pair<SdpVideoFormat, int>> decoder_settings)
philipel539f9b32020-01-09 16:12:25 +010027 : timing_(Clock::GetRealTimeClock()),
28 decode_callbacks_(this),
philipel3dc47802020-09-10 15:30:02 +020029 next_frame_info_index_(0),
philipel539f9b32020-01-09 16:12:25 +010030 callbacks_(callbacks),
31 keyframe_required_(true),
philipel2fee4d62018-03-21 16:52:13 +010032 decoder_factory_(decoder_factory),
philipel97187112018-03-23 10:43:21 +010033 decoder_settings_(std::move(decoder_settings)),
philipel539f9b32020-01-09 16:12:25 +010034 shut_down_(false),
35 frame_buffer_(Clock::GetRealTimeClock(), &timing_, nullptr),
Danil Chapovalovb703db92019-04-08 16:59:28 +020036 bookkeeping_queue_(task_queue_factory->CreateTaskQueue(
37 "video_stream_decoder_bookkeeping_queue",
38 TaskQueueFactory::Priority::NORMAL)),
philipel539f9b32020-01-09 16:12:25 +010039 decode_queue_(task_queue_factory->CreateTaskQueue(
40 "video_stream_decoder_decode_queue",
41 TaskQueueFactory::Priority::NORMAL)) {
philipel539f9b32020-01-09 16:12:25 +010042 bookkeeping_queue_.PostTask([this]() {
43 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
44 StartNextDecode();
45 });
philipel844876d2018-04-05 11:02:54 +020046}
philipel2fee4d62018-03-21 16:52:13 +010047
philipel97187112018-03-23 10:43:21 +010048VideoStreamDecoderImpl::~VideoStreamDecoderImpl() {
Markus Handell265931e2020-07-10 12:23:48 +020049 MutexLock lock(&shut_down_mutex_);
philipel539f9b32020-01-09 16:12:25 +010050 shut_down_ = true;
philipel97187112018-03-23 10:43:21 +010051}
philipel2fee4d62018-03-21 16:52:13 +010052
53void VideoStreamDecoderImpl::OnFrame(
philipel97187112018-03-23 10:43:21 +010054 std::unique_ptr<video_coding::EncodedFrame> frame) {
55 if (!bookkeeping_queue_.IsCurrent()) {
philipel539f9b32020-01-09 16:12:25 +010056 bookkeeping_queue_.PostTask([this, frame = std::move(frame)]() mutable {
57 OnFrame(std::move(frame));
58 return true;
59 });
philipel97187112018-03-23 10:43:21 +010060
philipel97187112018-03-23 10:43:21 +010061 return;
62 }
63
64 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
65
66 uint64_t continuous_pid = frame_buffer_.InsertFrame(std::move(frame));
67 video_coding::VideoLayerFrameId continuous_id(continuous_pid, 0);
68 if (last_continuous_id_ < continuous_id) {
69 last_continuous_id_ = continuous_id;
70 callbacks_->OnContinuousUntil(last_continuous_id_);
71 }
72}
73
philipel781653c2019-06-04 17:10:37 +020074void VideoStreamDecoderImpl::SetMinPlayoutDelay(TimeDelta min_delay) {
75 timing_.set_min_playout_delay(min_delay.ms());
76}
77
78void VideoStreamDecoderImpl::SetMaxPlayoutDelay(TimeDelta max_delay) {
79 timing_.set_max_playout_delay(max_delay.ms());
80}
81
philipel79aab3f2018-03-26 14:31:23 +020082VideoDecoder* VideoStreamDecoderImpl::GetDecoder(int payload_type) {
83 if (current_payload_type_ == payload_type) {
84 RTC_DCHECK(decoder_);
85 return decoder_.get();
86 }
87
88 current_payload_type_.reset();
89 decoder_.reset();
90
91 auto decoder_settings_it = decoder_settings_.find(payload_type);
92 if (decoder_settings_it == decoder_settings_.end()) {
93 RTC_LOG(LS_WARNING) << "Payload type " << payload_type
94 << " not registered.";
95 return nullptr;
96 }
97
98 const SdpVideoFormat& video_format = decoder_settings_it->second.first;
99 std::unique_ptr<VideoDecoder> decoder =
100 decoder_factory_->CreateVideoDecoder(video_format);
101 if (!decoder) {
102 RTC_LOG(LS_WARNING) << "Failed to create decoder for payload type "
103 << payload_type << ".";
104 return nullptr;
105 }
106
107 int num_cores = decoder_settings_it->second.second;
108 int32_t init_result = decoder->InitDecode(nullptr, num_cores);
109 if (init_result != WEBRTC_VIDEO_CODEC_OK) {
110 RTC_LOG(LS_WARNING) << "Failed to initialize decoder for payload type "
111 << payload_type << ".";
112 return nullptr;
113 }
114
philipel539f9b32020-01-09 16:12:25 +0100115 int32_t register_result =
116 decoder->RegisterDecodeCompleteCallback(&decode_callbacks_);
philipel79aab3f2018-03-26 14:31:23 +0200117 if (register_result != WEBRTC_VIDEO_CODEC_OK) {
118 RTC_LOG(LS_WARNING) << "Failed to register decode callback.";
119 return nullptr;
120 }
121
122 current_payload_type_.emplace(payload_type);
123 decoder_ = std::move(decoder);
124 return decoder_.get();
125}
126
philipel3dc47802020-09-10 15:30:02 +0200127void VideoStreamDecoderImpl::SaveFrameInfo(
philipel539f9b32020-01-09 16:12:25 +0100128 const video_coding::EncodedFrame& frame) {
philipel3dc47802020-09-10 15:30:02 +0200129 FrameInfo* frame_info = &frame_info_[next_frame_info_index_];
130 frame_info->timestamp = frame.Timestamp();
131 frame_info->decode_start_time_ms = rtc::TimeMillis();
132 frame_info->render_time_us = frame.RenderTimeMs() * 1000;
133 frame_info->content_type = frame.EncodedImage().content_type_;
philipel844876d2018-04-05 11:02:54 +0200134
philipel3dc47802020-09-10 15:30:02 +0200135 next_frame_info_index_ = Add<kFrameInfoMemory>(next_frame_info_index_, 1);
philipel539f9b32020-01-09 16:12:25 +0100136}
philipel844876d2018-04-05 11:02:54 +0200137
philipel539f9b32020-01-09 16:12:25 +0100138void VideoStreamDecoderImpl::StartNextDecode() {
139 int64_t max_wait_time = keyframe_required_ ? 200 : 3000;
140
141 frame_buffer_.NextFrame(
142 max_wait_time, keyframe_required_, &bookkeeping_queue_,
143 [this](std::unique_ptr<video_coding::EncodedFrame> frame,
144 video_coding::FrameBuffer::ReturnReason res) mutable {
145 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
146 OnNextFrameCallback(std::move(frame), res);
147 });
148}
149
150void VideoStreamDecoderImpl::OnNextFrameCallback(
151 std::unique_ptr<video_coding::EncodedFrame> frame,
152 video_coding::FrameBuffer::ReturnReason result) {
153 switch (result) {
154 case video_coding::FrameBuffer::kFrameFound: {
155 RTC_DCHECK(frame);
philipel3dc47802020-09-10 15:30:02 +0200156 SaveFrameInfo(*frame);
philipel539f9b32020-01-09 16:12:25 +0100157
Markus Handell265931e2020-07-10 12:23:48 +0200158 MutexLock lock(&shut_down_mutex_);
philipel539f9b32020-01-09 16:12:25 +0100159 if (shut_down_) {
philipel844876d2018-04-05 11:02:54 +0200160 return;
161 }
philipel539f9b32020-01-09 16:12:25 +0100162
163 decode_queue_.PostTask([this, frame = std::move(frame)]() mutable {
164 RTC_DCHECK_RUN_ON(&decode_queue_);
165 DecodeResult decode_result = DecodeFrame(std::move(frame));
166 bookkeeping_queue_.PostTask([this, decode_result]() {
167 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
168 switch (decode_result) {
169 case kOk: {
170 keyframe_required_ = false;
171 break;
172 }
173 case kOkRequestKeyframe: {
174 callbacks_->OnNonDecodableState();
175 keyframe_required_ = false;
176 break;
177 }
178 case kDecodeFailure: {
179 callbacks_->OnNonDecodableState();
180 keyframe_required_ = true;
181 break;
182 }
183 }
184 StartNextDecode();
185 });
186 });
187 break;
188 }
189 case video_coding::FrameBuffer::kTimeout: {
190 callbacks_->OnNonDecodableState();
191 // The |frame_buffer_| requires the frame callback function to complete
192 // before NextFrame is called again. For this reason we call
193 // StartNextDecode in a later task to allow this task to complete first.
194 bookkeeping_queue_.PostTask([this]() {
195 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
196 StartNextDecode();
197 });
198 break;
199 }
200 case video_coding::FrameBuffer::kStopped: {
201 // We are shutting down, do nothing.
202 break;
philipel844876d2018-04-05 11:02:54 +0200203 }
204 }
205}
206
philipel539f9b32020-01-09 16:12:25 +0100207VideoStreamDecoderImpl::DecodeResult VideoStreamDecoderImpl::DecodeFrame(
208 std::unique_ptr<video_coding::EncodedFrame> frame) {
209 RTC_DCHECK(frame);
philipel844876d2018-04-05 11:02:54 +0200210
philipel539f9b32020-01-09 16:12:25 +0100211 VideoDecoder* decoder = GetDecoder(frame->PayloadType());
212 if (!decoder) {
213 return kDecodeFailure;
philipel844876d2018-04-05 11:02:54 +0200214 }
215
philipel539f9b32020-01-09 16:12:25 +0100216 int32_t decode_result = decoder->Decode(frame->EncodedImage(), //
217 /*missing_frames=*/false, //
218 frame->RenderTimeMs());
219 switch (decode_result) {
220 case WEBRTC_VIDEO_CODEC_OK: {
221 return kOk;
222 }
223 case WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME: {
224 return kOkRequestKeyframe;
225 }
226 default:
227 return kDecodeFailure;
228 }
philipel844876d2018-04-05 11:02:54 +0200229}
230
philipel3dc47802020-09-10 15:30:02 +0200231VideoStreamDecoderImpl::FrameInfo* VideoStreamDecoderImpl::GetFrameInfo(
232 int64_t timestamp) {
233 int start_time_index = next_frame_info_index_;
234 for (int i = 0; i < kFrameInfoMemory; ++i) {
235 start_time_index = Subtract<kFrameInfoMemory>(start_time_index, 1);
philipel6847f9b2018-04-20 15:05:37 +0200236
philipel3dc47802020-09-10 15:30:02 +0200237 if (frame_info_[start_time_index].timestamp == timestamp)
238 return &frame_info_[start_time_index];
philipel6847f9b2018-04-20 15:05:37 +0200239 }
240
241 return nullptr;
242}
243
philipel539f9b32020-01-09 16:12:25 +0100244void VideoStreamDecoderImpl::OnDecodedFrameCallback(
245 VideoFrame& decoded_image,
246 absl::optional<int32_t> decode_time_ms,
247 absl::optional<uint8_t> qp) {
philipel6847f9b2018-04-20 15:05:37 +0200248 int64_t decode_stop_time_ms = rtc::TimeMillis();
249
250 bookkeeping_queue_.PostTask([this, decode_stop_time_ms, decoded_image,
philipel85ddb232020-10-02 14:46:14 +0200251 decode_time_ms, qp]() mutable {
philipel6847f9b2018-04-20 15:05:37 +0200252 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
253
philipel3dc47802020-09-10 15:30:02 +0200254 FrameInfo* frame_info = GetFrameInfo(decoded_image.timestamp());
255 if (!frame_info) {
philipel6847f9b2018-04-20 15:05:37 +0200256 RTC_LOG(LS_ERROR) << "No frame information found for frame with timestamp"
257 << decoded_image.timestamp();
258 return;
259 }
260
philipel3dc47802020-09-10 15:30:02 +0200261 Callbacks::FrameInfo callback_info;
262 callback_info.content_type = frame_info->content_type;
263
philipel6847f9b2018-04-20 15:05:37 +0200264 if (qp)
philipel3dc47802020-09-10 15:30:02 +0200265 callback_info.qp.emplace(*qp);
philipel6847f9b2018-04-20 15:05:37 +0200266
philipel85ddb232020-10-02 14:46:14 +0200267 if (!decode_time_ms) {
268 decode_time_ms = decode_stop_time_ms - frame_info->decode_start_time_ms;
269 }
270 decoded_image.set_processing_time(
271 {Timestamp::Millis(frame_info->decode_start_time_ms),
272 Timestamp::Millis(frame_info->decode_start_time_ms +
273 *decode_time_ms)});
274 decoded_image.set_timestamp_us(frame_info->render_time_us);
275 timing_.StopDecodeTimer(*decode_time_ms, decode_stop_time_ms);
philipel6847f9b2018-04-20 15:05:37 +0200276
philipel85ddb232020-10-02 14:46:14 +0200277 callbacks_->OnDecodedFrame(decoded_image, callback_info);
philipel6847f9b2018-04-20 15:05:37 +0200278 });
279}
280
philipel539f9b32020-01-09 16:12:25 +0100281VideoStreamDecoderImpl::DecodeCallbacks::DecodeCallbacks(
282 VideoStreamDecoderImpl* video_stream_decoder_impl)
283 : video_stream_decoder_impl_(video_stream_decoder_impl) {}
284
285int32_t VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
286 VideoFrame& decoded_image) {
287 Decoded(decoded_image, absl::nullopt, absl::nullopt);
288 return WEBRTC_VIDEO_CODEC_OK;
289}
290
291int32_t VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
292 VideoFrame& decoded_image,
293 int64_t decode_time_ms) {
294 Decoded(decoded_image, decode_time_ms, absl::nullopt);
295 return WEBRTC_VIDEO_CODEC_OK;
296}
297
298void VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
299 VideoFrame& decoded_image,
300 absl::optional<int32_t> decode_time_ms,
301 absl::optional<uint8_t> qp) {
302 video_stream_decoder_impl_->OnDecodedFrameCallback(decoded_image,
303 decode_time_ms, qp);
304}
philipel2fee4d62018-03-21 16:52:13 +0100305} // namespace webrtc