blob: fdc79eb229ebb2f0ac463f695c882887a4b6acdb [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
philipel97187112018-03-23 10:43:21 +010015#include "rtc_base/logging.h"
philipel844876d2018-04-05 11:02:54 +020016#include "rtc_base/numerics/mod_ops.h"
Steve Anton10542f22019-01-11 09:11:00 -080017#include "rtc_base/time_utils.h"
philipel2fee4d62018-03-21 16:52:13 +010018
19namespace webrtc {
philipel97187112018-03-23 10:43:21 +010020
philipel2fee4d62018-03-21 16:52:13 +010021VideoStreamDecoderImpl::VideoStreamDecoderImpl(
Danil Chapovalovb703db92019-04-08 16:59:28 +020022 VideoStreamDecoderInterface::Callbacks* callbacks,
philipel2fee4d62018-03-21 16:52:13 +010023 VideoDecoderFactory* decoder_factory,
Danil Chapovalovb703db92019-04-08 16:59:28 +020024 TaskQueueFactory* task_queue_factory,
Jonas Orelande02f9ee2022-03-25 12:43:14 +010025 std::map<int, std::pair<SdpVideoFormat, int>> decoder_settings,
Jonas Orelande62c2f22022-03-29 11:04:48 +020026 const FieldTrialsView* field_trials)
Jonas Orelande02f9ee2022-03-25 12:43:14 +010027 : field_trials_(field_trials),
28 timing_(Clock::GetRealTimeClock(), *field_trials_),
philipel539f9b32020-01-09 16:12:25 +010029 decode_callbacks_(this),
philipel3dc47802020-09-10 15:30:02 +020030 next_frame_info_index_(0),
philipel539f9b32020-01-09 16:12:25 +010031 callbacks_(callbacks),
32 keyframe_required_(true),
philipel2fee4d62018-03-21 16:52:13 +010033 decoder_factory_(decoder_factory),
philipel97187112018-03-23 10:43:21 +010034 decoder_settings_(std::move(decoder_settings)),
philipel539f9b32020-01-09 16:12:25 +010035 shut_down_(false),
Jonas Orelande02f9ee2022-03-25 12:43:14 +010036 frame_buffer_(Clock::GetRealTimeClock(),
37 &timing_,
38 nullptr,
39 *field_trials_),
Danil Chapovalovb703db92019-04-08 16:59:28 +020040 bookkeeping_queue_(task_queue_factory->CreateTaskQueue(
41 "video_stream_decoder_bookkeeping_queue",
42 TaskQueueFactory::Priority::NORMAL)),
philipel539f9b32020-01-09 16:12:25 +010043 decode_queue_(task_queue_factory->CreateTaskQueue(
44 "video_stream_decoder_decode_queue",
45 TaskQueueFactory::Priority::NORMAL)) {
philipel539f9b32020-01-09 16:12:25 +010046 bookkeeping_queue_.PostTask([this]() {
47 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
48 StartNextDecode();
49 });
philipel844876d2018-04-05 11:02:54 +020050}
philipel2fee4d62018-03-21 16:52:13 +010051
philipel97187112018-03-23 10:43:21 +010052VideoStreamDecoderImpl::~VideoStreamDecoderImpl() {
Markus Handell265931e2020-07-10 12:23:48 +020053 MutexLock lock(&shut_down_mutex_);
philipel539f9b32020-01-09 16:12:25 +010054 shut_down_ = true;
philipel97187112018-03-23 10:43:21 +010055}
philipel2fee4d62018-03-21 16:52:13 +010056
philipelca188092021-03-23 12:00:49 +010057void VideoStreamDecoderImpl::OnFrame(std::unique_ptr<EncodedFrame> frame) {
philipel97187112018-03-23 10:43:21 +010058 if (!bookkeeping_queue_.IsCurrent()) {
philipel539f9b32020-01-09 16:12:25 +010059 bookkeeping_queue_.PostTask([this, frame = std::move(frame)]() mutable {
60 OnFrame(std::move(frame));
61 return true;
62 });
philipel97187112018-03-23 10:43:21 +010063
philipel97187112018-03-23 10:43:21 +010064 return;
65 }
66
67 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
68
philipel9aa9b8d2021-02-15 13:31:29 +010069 int64_t continuous_frame_id = frame_buffer_.InsertFrame(std::move(frame));
70 if (last_continuous_frame_id_ < continuous_frame_id) {
71 last_continuous_frame_id_ = continuous_frame_id;
72 callbacks_->OnContinuousUntil(last_continuous_frame_id_);
philipel97187112018-03-23 10:43:21 +010073 }
74}
75
philipel781653c2019-06-04 17:10:37 +020076void VideoStreamDecoderImpl::SetMinPlayoutDelay(TimeDelta min_delay) {
Evan Shrubsoled6cdf802022-03-02 15:13:55 +010077 timing_.set_min_playout_delay(min_delay);
philipel781653c2019-06-04 17:10:37 +020078}
79
80void VideoStreamDecoderImpl::SetMaxPlayoutDelay(TimeDelta max_delay) {
Evan Shrubsoled6cdf802022-03-02 15:13:55 +010081 timing_.set_max_playout_delay(max_delay);
philipel781653c2019-06-04 17:10:37 +020082}
83
philipel79aab3f2018-03-26 14:31:23 +020084VideoDecoder* VideoStreamDecoderImpl::GetDecoder(int payload_type) {
85 if (current_payload_type_ == payload_type) {
86 RTC_DCHECK(decoder_);
87 return decoder_.get();
88 }
89
90 current_payload_type_.reset();
91 decoder_.reset();
92
93 auto decoder_settings_it = decoder_settings_.find(payload_type);
94 if (decoder_settings_it == decoder_settings_.end()) {
95 RTC_LOG(LS_WARNING) << "Payload type " << payload_type
96 << " not registered.";
97 return nullptr;
98 }
99
100 const SdpVideoFormat& video_format = decoder_settings_it->second.first;
101 std::unique_ptr<VideoDecoder> decoder =
102 decoder_factory_->CreateVideoDecoder(video_format);
103 if (!decoder) {
104 RTC_LOG(LS_WARNING) << "Failed to create decoder for payload type "
105 << payload_type << ".";
106 return nullptr;
107 }
108
Danil Chapovalovb6f19d72021-08-18 13:34:36 +0000109 VideoDecoder::Settings settings;
110 settings.set_number_of_cores(decoder_settings_it->second.second);
111 if (!decoder->Configure(settings)) {
philipel79aab3f2018-03-26 14:31:23 +0200112 RTC_LOG(LS_WARNING) << "Failed to initialize decoder for payload type "
113 << payload_type << ".";
114 return nullptr;
115 }
116
philipel539f9b32020-01-09 16:12:25 +0100117 int32_t register_result =
118 decoder->RegisterDecodeCompleteCallback(&decode_callbacks_);
philipel79aab3f2018-03-26 14:31:23 +0200119 if (register_result != WEBRTC_VIDEO_CODEC_OK) {
120 RTC_LOG(LS_WARNING) << "Failed to register decode callback.";
121 return nullptr;
122 }
123
124 current_payload_type_.emplace(payload_type);
125 decoder_ = std::move(decoder);
126 return decoder_.get();
127}
128
philipelca188092021-03-23 12:00:49 +0100129void VideoStreamDecoderImpl::SaveFrameInfo(const EncodedFrame& frame) {
philipel3dc47802020-09-10 15:30:02 +0200130 FrameInfo* frame_info = &frame_info_[next_frame_info_index_];
131 frame_info->timestamp = frame.Timestamp();
132 frame_info->decode_start_time_ms = rtc::TimeMillis();
133 frame_info->render_time_us = frame.RenderTimeMs() * 1000;
134 frame_info->content_type = frame.EncodedImage().content_type_;
philipel844876d2018-04-05 11:02:54 +0200135
philipel3dc47802020-09-10 15:30:02 +0200136 next_frame_info_index_ = Add<kFrameInfoMemory>(next_frame_info_index_, 1);
philipel539f9b32020-01-09 16:12:25 +0100137}
philipel844876d2018-04-05 11:02:54 +0200138
philipel539f9b32020-01-09 16:12:25 +0100139void VideoStreamDecoderImpl::StartNextDecode() {
140 int64_t max_wait_time = keyframe_required_ ? 200 : 3000;
141
Evan Shrubsole3d29efd2021-12-07 14:11:45 +0100142 frame_buffer_.NextFrame(max_wait_time, keyframe_required_,
Danil Chapovalov03f8b8a2022-07-18 13:11:42 +0200143 bookkeeping_queue_.Get(),
Evan Shrubsole3d29efd2021-12-07 14:11:45 +0100144 [this](std::unique_ptr<EncodedFrame> frame) {
145 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
146 OnNextFrameCallback(std::move(frame));
147 });
philipel539f9b32020-01-09 16:12:25 +0100148}
149
150void VideoStreamDecoderImpl::OnNextFrameCallback(
Evan Shrubsole3d29efd2021-12-07 14:11:45 +0100151 std::unique_ptr<EncodedFrame> frame) {
152 if (frame) {
153 RTC_DCHECK(frame);
154 SaveFrameInfo(*frame);
philipel539f9b32020-01-09 16:12:25 +0100155
Evan Shrubsole3d29efd2021-12-07 14:11:45 +0100156 MutexLock lock(&shut_down_mutex_);
157 if (shut_down_) {
158 return;
philipel539f9b32020-01-09 16:12:25 +0100159 }
Evan Shrubsole3d29efd2021-12-07 14:11:45 +0100160
161 decode_queue_.PostTask([this, frame = std::move(frame)]() mutable {
162 RTC_DCHECK_RUN_ON(&decode_queue_);
163 DecodeResult decode_result = DecodeFrame(std::move(frame));
164 bookkeeping_queue_.PostTask([this, decode_result]() {
philipel539f9b32020-01-09 16:12:25 +0100165 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
Evan Shrubsole3d29efd2021-12-07 14:11:45 +0100166 switch (decode_result) {
167 case kOk: {
168 keyframe_required_ = false;
169 break;
170 }
171 case kOkRequestKeyframe: {
172 callbacks_->OnNonDecodableState();
173 keyframe_required_ = false;
174 break;
175 }
176 case kDecodeFailure: {
177 callbacks_->OnNonDecodableState();
178 keyframe_required_ = true;
179 break;
180 }
181 }
philipel539f9b32020-01-09 16:12:25 +0100182 StartNextDecode();
183 });
Evan Shrubsole3d29efd2021-12-07 14:11:45 +0100184 });
185 } else {
186 callbacks_->OnNonDecodableState();
187 // The `frame_buffer_` requires the frame callback function to complete
188 // before NextFrame is called again. For this reason we call
189 // StartNextDecode in a later task to allow this task to complete first.
190 bookkeeping_queue_.PostTask([this]() {
191 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
192 StartNextDecode();
193 });
philipel844876d2018-04-05 11:02:54 +0200194 }
195}
196
philipel539f9b32020-01-09 16:12:25 +0100197VideoStreamDecoderImpl::DecodeResult VideoStreamDecoderImpl::DecodeFrame(
philipelca188092021-03-23 12:00:49 +0100198 std::unique_ptr<EncodedFrame> frame) {
philipel539f9b32020-01-09 16:12:25 +0100199 RTC_DCHECK(frame);
philipel844876d2018-04-05 11:02:54 +0200200
philipel539f9b32020-01-09 16:12:25 +0100201 VideoDecoder* decoder = GetDecoder(frame->PayloadType());
202 if (!decoder) {
203 return kDecodeFailure;
philipel844876d2018-04-05 11:02:54 +0200204 }
205
philipel539f9b32020-01-09 16:12:25 +0100206 int32_t decode_result = decoder->Decode(frame->EncodedImage(), //
207 /*missing_frames=*/false, //
208 frame->RenderTimeMs());
209 switch (decode_result) {
210 case WEBRTC_VIDEO_CODEC_OK: {
211 return kOk;
212 }
213 case WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME: {
214 return kOkRequestKeyframe;
215 }
216 default:
217 return kDecodeFailure;
218 }
philipel844876d2018-04-05 11:02:54 +0200219}
220
philipel3dc47802020-09-10 15:30:02 +0200221VideoStreamDecoderImpl::FrameInfo* VideoStreamDecoderImpl::GetFrameInfo(
222 int64_t timestamp) {
223 int start_time_index = next_frame_info_index_;
224 for (int i = 0; i < kFrameInfoMemory; ++i) {
225 start_time_index = Subtract<kFrameInfoMemory>(start_time_index, 1);
philipel6847f9b2018-04-20 15:05:37 +0200226
philipel3dc47802020-09-10 15:30:02 +0200227 if (frame_info_[start_time_index].timestamp == timestamp)
228 return &frame_info_[start_time_index];
philipel6847f9b2018-04-20 15:05:37 +0200229 }
230
231 return nullptr;
232}
233
philipel539f9b32020-01-09 16:12:25 +0100234void VideoStreamDecoderImpl::OnDecodedFrameCallback(
235 VideoFrame& decoded_image,
236 absl::optional<int32_t> decode_time_ms,
237 absl::optional<uint8_t> qp) {
philipel6847f9b2018-04-20 15:05:37 +0200238 int64_t decode_stop_time_ms = rtc::TimeMillis();
239
240 bookkeeping_queue_.PostTask([this, decode_stop_time_ms, decoded_image,
philipel85ddb232020-10-02 14:46:14 +0200241 decode_time_ms, qp]() mutable {
philipel6847f9b2018-04-20 15:05:37 +0200242 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
243
philipel3dc47802020-09-10 15:30:02 +0200244 FrameInfo* frame_info = GetFrameInfo(decoded_image.timestamp());
245 if (!frame_info) {
philipel6847f9b2018-04-20 15:05:37 +0200246 RTC_LOG(LS_ERROR) << "No frame information found for frame with timestamp"
247 << decoded_image.timestamp();
248 return;
249 }
250
philipel3dc47802020-09-10 15:30:02 +0200251 Callbacks::FrameInfo callback_info;
252 callback_info.content_type = frame_info->content_type;
253
philipel6847f9b2018-04-20 15:05:37 +0200254 if (qp)
philipel3dc47802020-09-10 15:30:02 +0200255 callback_info.qp.emplace(*qp);
philipel6847f9b2018-04-20 15:05:37 +0200256
philipel85ddb232020-10-02 14:46:14 +0200257 if (!decode_time_ms) {
258 decode_time_ms = decode_stop_time_ms - frame_info->decode_start_time_ms;
259 }
260 decoded_image.set_processing_time(
261 {Timestamp::Millis(frame_info->decode_start_time_ms),
262 Timestamp::Millis(frame_info->decode_start_time_ms +
263 *decode_time_ms)});
264 decoded_image.set_timestamp_us(frame_info->render_time_us);
Evan Shrubsoled6cdf802022-03-02 15:13:55 +0100265 timing_.StopDecodeTimer(TimeDelta::Millis(*decode_time_ms),
266 Timestamp::Millis(decode_stop_time_ms));
philipel6847f9b2018-04-20 15:05:37 +0200267
philipel85ddb232020-10-02 14:46:14 +0200268 callbacks_->OnDecodedFrame(decoded_image, callback_info);
philipel6847f9b2018-04-20 15:05:37 +0200269 });
270}
271
philipel539f9b32020-01-09 16:12:25 +0100272VideoStreamDecoderImpl::DecodeCallbacks::DecodeCallbacks(
273 VideoStreamDecoderImpl* video_stream_decoder_impl)
274 : video_stream_decoder_impl_(video_stream_decoder_impl) {}
275
276int32_t VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
277 VideoFrame& decoded_image) {
278 Decoded(decoded_image, absl::nullopt, absl::nullopt);
279 return WEBRTC_VIDEO_CODEC_OK;
280}
281
282int32_t VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
283 VideoFrame& decoded_image,
284 int64_t decode_time_ms) {
285 Decoded(decoded_image, decode_time_ms, absl::nullopt);
286 return WEBRTC_VIDEO_CODEC_OK;
287}
288
289void VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
290 VideoFrame& decoded_image,
291 absl::optional<int32_t> decode_time_ms,
292 absl::optional<uint8_t> qp) {
293 video_stream_decoder_impl_->OnDecodedFrameCallback(decoded_image,
294 decode_time_ms, qp);
295}
philipel2fee4d62018-03-21 16:52:13 +0100296} // namespace webrtc