blob: 8704a6ef1a4d7667b7ab30b952039aae03448ba9 [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,
Jonas Orelande02f9ee2022-03-25 12:43:14 +010026 std::map<int, std::pair<SdpVideoFormat, int>> decoder_settings,
27 const WebRtcKeyValueConfig* field_trials)
28 : field_trials_(field_trials),
29 timing_(Clock::GetRealTimeClock(), *field_trials_),
philipel539f9b32020-01-09 16:12:25 +010030 decode_callbacks_(this),
philipel3dc47802020-09-10 15:30:02 +020031 next_frame_info_index_(0),
philipel539f9b32020-01-09 16:12:25 +010032 callbacks_(callbacks),
33 keyframe_required_(true),
philipel2fee4d62018-03-21 16:52:13 +010034 decoder_factory_(decoder_factory),
philipel97187112018-03-23 10:43:21 +010035 decoder_settings_(std::move(decoder_settings)),
philipel539f9b32020-01-09 16:12:25 +010036 shut_down_(false),
Jonas Orelande02f9ee2022-03-25 12:43:14 +010037 frame_buffer_(Clock::GetRealTimeClock(),
38 &timing_,
39 nullptr,
40 *field_trials_),
Danil Chapovalovb703db92019-04-08 16:59:28 +020041 bookkeeping_queue_(task_queue_factory->CreateTaskQueue(
42 "video_stream_decoder_bookkeeping_queue",
43 TaskQueueFactory::Priority::NORMAL)),
philipel539f9b32020-01-09 16:12:25 +010044 decode_queue_(task_queue_factory->CreateTaskQueue(
45 "video_stream_decoder_decode_queue",
46 TaskQueueFactory::Priority::NORMAL)) {
philipel539f9b32020-01-09 16:12:25 +010047 bookkeeping_queue_.PostTask([this]() {
48 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
49 StartNextDecode();
50 });
philipel844876d2018-04-05 11:02:54 +020051}
philipel2fee4d62018-03-21 16:52:13 +010052
philipel97187112018-03-23 10:43:21 +010053VideoStreamDecoderImpl::~VideoStreamDecoderImpl() {
Markus Handell265931e2020-07-10 12:23:48 +020054 MutexLock lock(&shut_down_mutex_);
philipel539f9b32020-01-09 16:12:25 +010055 shut_down_ = true;
philipel97187112018-03-23 10:43:21 +010056}
philipel2fee4d62018-03-21 16:52:13 +010057
philipelca188092021-03-23 12:00:49 +010058void VideoStreamDecoderImpl::OnFrame(std::unique_ptr<EncodedFrame> frame) {
philipel97187112018-03-23 10:43:21 +010059 if (!bookkeeping_queue_.IsCurrent()) {
philipel539f9b32020-01-09 16:12:25 +010060 bookkeeping_queue_.PostTask([this, frame = std::move(frame)]() mutable {
61 OnFrame(std::move(frame));
62 return true;
63 });
philipel97187112018-03-23 10:43:21 +010064
philipel97187112018-03-23 10:43:21 +010065 return;
66 }
67
68 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
69
philipel9aa9b8d2021-02-15 13:31:29 +010070 int64_t continuous_frame_id = frame_buffer_.InsertFrame(std::move(frame));
71 if (last_continuous_frame_id_ < continuous_frame_id) {
72 last_continuous_frame_id_ = continuous_frame_id;
73 callbacks_->OnContinuousUntil(last_continuous_frame_id_);
philipel97187112018-03-23 10:43:21 +010074 }
75}
76
philipel781653c2019-06-04 17:10:37 +020077void VideoStreamDecoderImpl::SetMinPlayoutDelay(TimeDelta min_delay) {
Evan Shrubsoled6cdf802022-03-02 15:13:55 +010078 timing_.set_min_playout_delay(min_delay);
philipel781653c2019-06-04 17:10:37 +020079}
80
81void VideoStreamDecoderImpl::SetMaxPlayoutDelay(TimeDelta max_delay) {
Evan Shrubsoled6cdf802022-03-02 15:13:55 +010082 timing_.set_max_playout_delay(max_delay);
philipel781653c2019-06-04 17:10:37 +020083}
84
philipel79aab3f2018-03-26 14:31:23 +020085VideoDecoder* VideoStreamDecoderImpl::GetDecoder(int payload_type) {
86 if (current_payload_type_ == payload_type) {
87 RTC_DCHECK(decoder_);
88 return decoder_.get();
89 }
90
91 current_payload_type_.reset();
92 decoder_.reset();
93
94 auto decoder_settings_it = decoder_settings_.find(payload_type);
95 if (decoder_settings_it == decoder_settings_.end()) {
96 RTC_LOG(LS_WARNING) << "Payload type " << payload_type
97 << " not registered.";
98 return nullptr;
99 }
100
101 const SdpVideoFormat& video_format = decoder_settings_it->second.first;
102 std::unique_ptr<VideoDecoder> decoder =
103 decoder_factory_->CreateVideoDecoder(video_format);
104 if (!decoder) {
105 RTC_LOG(LS_WARNING) << "Failed to create decoder for payload type "
106 << payload_type << ".";
107 return nullptr;
108 }
109
Danil Chapovalovb6f19d72021-08-18 13:34:36 +0000110 VideoDecoder::Settings settings;
111 settings.set_number_of_cores(decoder_settings_it->second.second);
112 if (!decoder->Configure(settings)) {
philipel79aab3f2018-03-26 14:31:23 +0200113 RTC_LOG(LS_WARNING) << "Failed to initialize decoder for payload type "
114 << payload_type << ".";
115 return nullptr;
116 }
117
philipel539f9b32020-01-09 16:12:25 +0100118 int32_t register_result =
119 decoder->RegisterDecodeCompleteCallback(&decode_callbacks_);
philipel79aab3f2018-03-26 14:31:23 +0200120 if (register_result != WEBRTC_VIDEO_CODEC_OK) {
121 RTC_LOG(LS_WARNING) << "Failed to register decode callback.";
122 return nullptr;
123 }
124
125 current_payload_type_.emplace(payload_type);
126 decoder_ = std::move(decoder);
127 return decoder_.get();
128}
129
philipelca188092021-03-23 12:00:49 +0100130void VideoStreamDecoderImpl::SaveFrameInfo(const EncodedFrame& frame) {
philipel3dc47802020-09-10 15:30:02 +0200131 FrameInfo* frame_info = &frame_info_[next_frame_info_index_];
132 frame_info->timestamp = frame.Timestamp();
133 frame_info->decode_start_time_ms = rtc::TimeMillis();
134 frame_info->render_time_us = frame.RenderTimeMs() * 1000;
135 frame_info->content_type = frame.EncodedImage().content_type_;
philipel844876d2018-04-05 11:02:54 +0200136
philipel3dc47802020-09-10 15:30:02 +0200137 next_frame_info_index_ = Add<kFrameInfoMemory>(next_frame_info_index_, 1);
philipel539f9b32020-01-09 16:12:25 +0100138}
philipel844876d2018-04-05 11:02:54 +0200139
philipel539f9b32020-01-09 16:12:25 +0100140void VideoStreamDecoderImpl::StartNextDecode() {
141 int64_t max_wait_time = keyframe_required_ ? 200 : 3000;
142
Evan Shrubsole3d29efd2021-12-07 14:11:45 +0100143 frame_buffer_.NextFrame(max_wait_time, keyframe_required_,
144 &bookkeeping_queue_,
145 [this](std::unique_ptr<EncodedFrame> frame) {
146 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
147 OnNextFrameCallback(std::move(frame));
148 });
philipel539f9b32020-01-09 16:12:25 +0100149}
150
151void VideoStreamDecoderImpl::OnNextFrameCallback(
Evan Shrubsole3d29efd2021-12-07 14:11:45 +0100152 std::unique_ptr<EncodedFrame> frame) {
153 if (frame) {
154 RTC_DCHECK(frame);
155 SaveFrameInfo(*frame);
philipel539f9b32020-01-09 16:12:25 +0100156
Evan Shrubsole3d29efd2021-12-07 14:11:45 +0100157 MutexLock lock(&shut_down_mutex_);
158 if (shut_down_) {
159 return;
philipel539f9b32020-01-09 16:12:25 +0100160 }
Evan Shrubsole3d29efd2021-12-07 14:11:45 +0100161
162 decode_queue_.PostTask([this, frame = std::move(frame)]() mutable {
163 RTC_DCHECK_RUN_ON(&decode_queue_);
164 DecodeResult decode_result = DecodeFrame(std::move(frame));
165 bookkeeping_queue_.PostTask([this, decode_result]() {
philipel539f9b32020-01-09 16:12:25 +0100166 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
Evan Shrubsole3d29efd2021-12-07 14:11:45 +0100167 switch (decode_result) {
168 case kOk: {
169 keyframe_required_ = false;
170 break;
171 }
172 case kOkRequestKeyframe: {
173 callbacks_->OnNonDecodableState();
174 keyframe_required_ = false;
175 break;
176 }
177 case kDecodeFailure: {
178 callbacks_->OnNonDecodableState();
179 keyframe_required_ = true;
180 break;
181 }
182 }
philipel539f9b32020-01-09 16:12:25 +0100183 StartNextDecode();
184 });
Evan Shrubsole3d29efd2021-12-07 14:11:45 +0100185 });
186 } else {
187 callbacks_->OnNonDecodableState();
188 // The `frame_buffer_` requires the frame callback function to complete
189 // before NextFrame is called again. For this reason we call
190 // StartNextDecode in a later task to allow this task to complete first.
191 bookkeeping_queue_.PostTask([this]() {
192 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
193 StartNextDecode();
194 });
philipel844876d2018-04-05 11:02:54 +0200195 }
196}
197
philipel539f9b32020-01-09 16:12:25 +0100198VideoStreamDecoderImpl::DecodeResult VideoStreamDecoderImpl::DecodeFrame(
philipelca188092021-03-23 12:00:49 +0100199 std::unique_ptr<EncodedFrame> frame) {
philipel539f9b32020-01-09 16:12:25 +0100200 RTC_DCHECK(frame);
philipel844876d2018-04-05 11:02:54 +0200201
philipel539f9b32020-01-09 16:12:25 +0100202 VideoDecoder* decoder = GetDecoder(frame->PayloadType());
203 if (!decoder) {
204 return kDecodeFailure;
philipel844876d2018-04-05 11:02:54 +0200205 }
206
philipel539f9b32020-01-09 16:12:25 +0100207 int32_t decode_result = decoder->Decode(frame->EncodedImage(), //
208 /*missing_frames=*/false, //
209 frame->RenderTimeMs());
210 switch (decode_result) {
211 case WEBRTC_VIDEO_CODEC_OK: {
212 return kOk;
213 }
214 case WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME: {
215 return kOkRequestKeyframe;
216 }
217 default:
218 return kDecodeFailure;
219 }
philipel844876d2018-04-05 11:02:54 +0200220}
221
philipel3dc47802020-09-10 15:30:02 +0200222VideoStreamDecoderImpl::FrameInfo* VideoStreamDecoderImpl::GetFrameInfo(
223 int64_t timestamp) {
224 int start_time_index = next_frame_info_index_;
225 for (int i = 0; i < kFrameInfoMemory; ++i) {
226 start_time_index = Subtract<kFrameInfoMemory>(start_time_index, 1);
philipel6847f9b2018-04-20 15:05:37 +0200227
philipel3dc47802020-09-10 15:30:02 +0200228 if (frame_info_[start_time_index].timestamp == timestamp)
229 return &frame_info_[start_time_index];
philipel6847f9b2018-04-20 15:05:37 +0200230 }
231
232 return nullptr;
233}
234
philipel539f9b32020-01-09 16:12:25 +0100235void VideoStreamDecoderImpl::OnDecodedFrameCallback(
236 VideoFrame& decoded_image,
237 absl::optional<int32_t> decode_time_ms,
238 absl::optional<uint8_t> qp) {
philipel6847f9b2018-04-20 15:05:37 +0200239 int64_t decode_stop_time_ms = rtc::TimeMillis();
240
241 bookkeeping_queue_.PostTask([this, decode_stop_time_ms, decoded_image,
philipel85ddb232020-10-02 14:46:14 +0200242 decode_time_ms, qp]() mutable {
philipel6847f9b2018-04-20 15:05:37 +0200243 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
244
philipel3dc47802020-09-10 15:30:02 +0200245 FrameInfo* frame_info = GetFrameInfo(decoded_image.timestamp());
246 if (!frame_info) {
philipel6847f9b2018-04-20 15:05:37 +0200247 RTC_LOG(LS_ERROR) << "No frame information found for frame with timestamp"
248 << decoded_image.timestamp();
249 return;
250 }
251
philipel3dc47802020-09-10 15:30:02 +0200252 Callbacks::FrameInfo callback_info;
253 callback_info.content_type = frame_info->content_type;
254
philipel6847f9b2018-04-20 15:05:37 +0200255 if (qp)
philipel3dc47802020-09-10 15:30:02 +0200256 callback_info.qp.emplace(*qp);
philipel6847f9b2018-04-20 15:05:37 +0200257
philipel85ddb232020-10-02 14:46:14 +0200258 if (!decode_time_ms) {
259 decode_time_ms = decode_stop_time_ms - frame_info->decode_start_time_ms;
260 }
261 decoded_image.set_processing_time(
262 {Timestamp::Millis(frame_info->decode_start_time_ms),
263 Timestamp::Millis(frame_info->decode_start_time_ms +
264 *decode_time_ms)});
265 decoded_image.set_timestamp_us(frame_info->render_time_us);
Evan Shrubsoled6cdf802022-03-02 15:13:55 +0100266 timing_.StopDecodeTimer(TimeDelta::Millis(*decode_time_ms),
267 Timestamp::Millis(decode_stop_time_ms));
philipel6847f9b2018-04-20 15:05:37 +0200268
philipel85ddb232020-10-02 14:46:14 +0200269 callbacks_->OnDecodedFrame(decoded_image, callback_info);
philipel6847f9b2018-04-20 15:05:37 +0200270 });
271}
272
philipel539f9b32020-01-09 16:12:25 +0100273VideoStreamDecoderImpl::DecodeCallbacks::DecodeCallbacks(
274 VideoStreamDecoderImpl* video_stream_decoder_impl)
275 : video_stream_decoder_impl_(video_stream_decoder_impl) {}
276
277int32_t VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
278 VideoFrame& decoded_image) {
279 Decoded(decoded_image, absl::nullopt, absl::nullopt);
280 return WEBRTC_VIDEO_CODEC_OK;
281}
282
283int32_t VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
284 VideoFrame& decoded_image,
285 int64_t decode_time_ms) {
286 Decoded(decoded_image, decode_time_ms, absl::nullopt);
287 return WEBRTC_VIDEO_CODEC_OK;
288}
289
290void VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
291 VideoFrame& decoded_image,
292 absl::optional<int32_t> decode_time_ms,
293 absl::optional<uint8_t> qp) {
294 video_stream_decoder_impl_->OnDecodedFrameCallback(decoded_image,
295 decode_time_ms, qp);
296}
philipel2fee4d62018-03-21 16:52:13 +0100297} // namespace webrtc