blob: 1e11d3805087740b9a99e0299768f6f57f83faa8 [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),
29 next_frame_timestamps_index_(0),
30 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)) {
philipel6847f9b2018-04-20 15:05:37 +020042 frame_timestamps_.fill({-1, -1, -1});
philipel539f9b32020-01-09 16:12:25 +010043 bookkeeping_queue_.PostTask([this]() {
44 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
45 StartNextDecode();
46 });
philipel844876d2018-04-05 11:02:54 +020047}
philipel2fee4d62018-03-21 16:52:13 +010048
philipel97187112018-03-23 10:43:21 +010049VideoStreamDecoderImpl::~VideoStreamDecoderImpl() {
philipel539f9b32020-01-09 16:12:25 +010050 rtc::CritScope lock(&shut_down_crit_);
51 shut_down_ = true;
philipel97187112018-03-23 10:43:21 +010052}
philipel2fee4d62018-03-21 16:52:13 +010053
54void VideoStreamDecoderImpl::OnFrame(
philipel97187112018-03-23 10:43:21 +010055 std::unique_ptr<video_coding::EncodedFrame> frame) {
56 if (!bookkeeping_queue_.IsCurrent()) {
philipel539f9b32020-01-09 16:12:25 +010057 bookkeeping_queue_.PostTask([this, frame = std::move(frame)]() mutable {
58 OnFrame(std::move(frame));
59 return true;
60 });
philipel97187112018-03-23 10:43:21 +010061
philipel97187112018-03-23 10:43:21 +010062 return;
63 }
64
65 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
66
67 uint64_t continuous_pid = frame_buffer_.InsertFrame(std::move(frame));
68 video_coding::VideoLayerFrameId continuous_id(continuous_pid, 0);
69 if (last_continuous_id_ < continuous_id) {
70 last_continuous_id_ = continuous_id;
71 callbacks_->OnContinuousUntil(last_continuous_id_);
72 }
73}
74
philipel781653c2019-06-04 17:10:37 +020075void VideoStreamDecoderImpl::SetMinPlayoutDelay(TimeDelta min_delay) {
76 timing_.set_min_playout_delay(min_delay.ms());
77}
78
79void VideoStreamDecoderImpl::SetMaxPlayoutDelay(TimeDelta max_delay) {
80 timing_.set_max_playout_delay(max_delay.ms());
81}
82
philipel79aab3f2018-03-26 14:31:23 +020083VideoDecoder* VideoStreamDecoderImpl::GetDecoder(int payload_type) {
84 if (current_payload_type_ == payload_type) {
85 RTC_DCHECK(decoder_);
86 return decoder_.get();
87 }
88
89 current_payload_type_.reset();
90 decoder_.reset();
91
92 auto decoder_settings_it = decoder_settings_.find(payload_type);
93 if (decoder_settings_it == decoder_settings_.end()) {
94 RTC_LOG(LS_WARNING) << "Payload type " << payload_type
95 << " not registered.";
96 return nullptr;
97 }
98
99 const SdpVideoFormat& video_format = decoder_settings_it->second.first;
100 std::unique_ptr<VideoDecoder> decoder =
101 decoder_factory_->CreateVideoDecoder(video_format);
102 if (!decoder) {
103 RTC_LOG(LS_WARNING) << "Failed to create decoder for payload type "
104 << payload_type << ".";
105 return nullptr;
106 }
107
108 int num_cores = decoder_settings_it->second.second;
109 int32_t init_result = decoder->InitDecode(nullptr, num_cores);
110 if (init_result != WEBRTC_VIDEO_CODEC_OK) {
111 RTC_LOG(LS_WARNING) << "Failed to initialize decoder for payload type "
112 << payload_type << ".";
113 return nullptr;
114 }
115
philipel539f9b32020-01-09 16:12:25 +0100116 int32_t register_result =
117 decoder->RegisterDecodeCompleteCallback(&decode_callbacks_);
philipel79aab3f2018-03-26 14:31:23 +0200118 if (register_result != WEBRTC_VIDEO_CODEC_OK) {
119 RTC_LOG(LS_WARNING) << "Failed to register decode callback.";
120 return nullptr;
121 }
122
123 current_payload_type_.emplace(payload_type);
124 decoder_ = std::move(decoder);
125 return decoder_.get();
126}
127
philipel539f9b32020-01-09 16:12:25 +0100128void VideoStreamDecoderImpl::SaveFrameTimestamps(
129 const video_coding::EncodedFrame& frame) {
130 FrameTimestamps* frame_timestamps =
131 &frame_timestamps_[next_frame_timestamps_index_];
132 frame_timestamps->timestamp = frame.Timestamp();
133 frame_timestamps->decode_start_time_ms = rtc::TimeMillis();
134 frame_timestamps->render_time_us = frame.RenderTimeMs() * 1000;
philipel844876d2018-04-05 11:02:54 +0200135
philipel539f9b32020-01-09 16:12:25 +0100136 next_frame_timestamps_index_ =
137 Add<kFrameTimestampsMemory>(next_frame_timestamps_index_, 1);
138}
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
143 frame_buffer_.NextFrame(
144 max_wait_time, keyframe_required_, &bookkeeping_queue_,
145 [this](std::unique_ptr<video_coding::EncodedFrame> frame,
146 video_coding::FrameBuffer::ReturnReason res) mutable {
147 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
148 OnNextFrameCallback(std::move(frame), res);
149 });
150}
151
152void VideoStreamDecoderImpl::OnNextFrameCallback(
153 std::unique_ptr<video_coding::EncodedFrame> frame,
154 video_coding::FrameBuffer::ReturnReason result) {
155 switch (result) {
156 case video_coding::FrameBuffer::kFrameFound: {
157 RTC_DCHECK(frame);
158 SaveFrameTimestamps(*frame);
159
160 rtc::CritScope lock(&shut_down_crit_);
161 if (shut_down_) {
philipel844876d2018-04-05 11:02:54 +0200162 return;
163 }
philipel539f9b32020-01-09 16:12:25 +0100164
165 decode_queue_.PostTask([this, frame = std::move(frame)]() mutable {
166 RTC_DCHECK_RUN_ON(&decode_queue_);
167 DecodeResult decode_result = DecodeFrame(std::move(frame));
168 bookkeeping_queue_.PostTask([this, decode_result]() {
169 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
170 switch (decode_result) {
171 case kOk: {
172 keyframe_required_ = false;
173 break;
174 }
175 case kOkRequestKeyframe: {
176 callbacks_->OnNonDecodableState();
177 keyframe_required_ = false;
178 break;
179 }
180 case kDecodeFailure: {
181 callbacks_->OnNonDecodableState();
182 keyframe_required_ = true;
183 break;
184 }
185 }
186 StartNextDecode();
187 });
188 });
189 break;
190 }
191 case video_coding::FrameBuffer::kTimeout: {
192 callbacks_->OnNonDecodableState();
193 // The |frame_buffer_| requires the frame callback function to complete
194 // before NextFrame is called again. For this reason we call
195 // StartNextDecode in a later task to allow this task to complete first.
196 bookkeeping_queue_.PostTask([this]() {
197 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
198 StartNextDecode();
199 });
200 break;
201 }
202 case video_coding::FrameBuffer::kStopped: {
203 // We are shutting down, do nothing.
204 break;
philipel844876d2018-04-05 11:02:54 +0200205 }
206 }
207}
208
philipel539f9b32020-01-09 16:12:25 +0100209VideoStreamDecoderImpl::DecodeResult VideoStreamDecoderImpl::DecodeFrame(
210 std::unique_ptr<video_coding::EncodedFrame> frame) {
211 RTC_DCHECK(frame);
philipel844876d2018-04-05 11:02:54 +0200212
philipel539f9b32020-01-09 16:12:25 +0100213 VideoDecoder* decoder = GetDecoder(frame->PayloadType());
214 if (!decoder) {
215 return kDecodeFailure;
philipel844876d2018-04-05 11:02:54 +0200216 }
217
philipel539f9b32020-01-09 16:12:25 +0100218 int32_t decode_result = decoder->Decode(frame->EncodedImage(), //
219 /*missing_frames=*/false, //
220 frame->RenderTimeMs());
221 switch (decode_result) {
222 case WEBRTC_VIDEO_CODEC_OK: {
223 return kOk;
224 }
225 case WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME: {
226 return kOkRequestKeyframe;
227 }
228 default:
229 return kDecodeFailure;
230 }
philipel844876d2018-04-05 11:02:54 +0200231}
232
philipel6847f9b2018-04-20 15:05:37 +0200233VideoStreamDecoderImpl::FrameTimestamps*
234VideoStreamDecoderImpl::GetFrameTimestamps(int64_t timestamp) {
philipel6847f9b2018-04-20 15:05:37 +0200235 int start_time_index = next_frame_timestamps_index_;
236 for (int i = 0; i < kFrameTimestampsMemory; ++i) {
237 start_time_index = Subtract<kFrameTimestampsMemory>(start_time_index, 1);
238
239 if (frame_timestamps_[start_time_index].timestamp == timestamp)
240 return &frame_timestamps_[start_time_index];
241 }
242
243 return nullptr;
244}
245
philipel539f9b32020-01-09 16:12:25 +0100246void VideoStreamDecoderImpl::OnDecodedFrameCallback(
247 VideoFrame& decoded_image,
248 absl::optional<int32_t> decode_time_ms,
249 absl::optional<uint8_t> qp) {
philipel6847f9b2018-04-20 15:05:37 +0200250 int64_t decode_stop_time_ms = rtc::TimeMillis();
251
252 bookkeeping_queue_.PostTask([this, decode_stop_time_ms, decoded_image,
253 decode_time_ms, qp]() {
254 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
255
256 FrameTimestamps* frame_timestamps =
257 GetFrameTimestamps(decoded_image.timestamp());
258 if (!frame_timestamps) {
259 RTC_LOG(LS_ERROR) << "No frame information found for frame with timestamp"
260 << decoded_image.timestamp();
261 return;
262 }
263
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200264 absl::optional<int> casted_qp;
philipel6847f9b2018-04-20 15:05:37 +0200265 if (qp)
266 casted_qp.emplace(*qp);
267
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200268 absl::optional<int> casted_decode_time_ms(decode_time_ms.value_or(
philipel6847f9b2018-04-20 15:05:37 +0200269 decode_stop_time_ms - frame_timestamps->decode_start_time_ms));
270
Johannes Kronbfd343b2019-07-01 10:07:50 +0200271 timing_.StopDecodeTimer(*casted_decode_time_ms, decode_stop_time_ms);
philipel6847f9b2018-04-20 15:05:37 +0200272
Ilya Nikolaevskiy4fc08552019-06-05 15:59:12 +0200273 VideoFrame copy = decoded_image;
274 copy.set_timestamp_us(frame_timestamps->render_time_us);
275 callbacks_->OnDecodedFrame(copy, casted_decode_time_ms, casted_qp);
philipel6847f9b2018-04-20 15:05:37 +0200276 });
277}
278
philipel539f9b32020-01-09 16:12:25 +0100279VideoStreamDecoderImpl::DecodeCallbacks::DecodeCallbacks(
280 VideoStreamDecoderImpl* video_stream_decoder_impl)
281 : video_stream_decoder_impl_(video_stream_decoder_impl) {}
282
283int32_t VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
284 VideoFrame& decoded_image) {
285 Decoded(decoded_image, absl::nullopt, absl::nullopt);
286 return WEBRTC_VIDEO_CODEC_OK;
287}
288
289int32_t VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
290 VideoFrame& decoded_image,
291 int64_t decode_time_ms) {
292 Decoded(decoded_image, decode_time_ms, absl::nullopt);
293 return WEBRTC_VIDEO_CODEC_OK;
294}
295
296void VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
297 VideoFrame& decoded_image,
298 absl::optional<int32_t> decode_time_ms,
299 absl::optional<uint8_t> qp) {
300 video_stream_decoder_impl_->OnDecodedFrameCallback(decoded_image,
301 decode_time_ms, qp);
302}
philipel2fee4d62018-03-21 16:52:13 +0100303} // namespace webrtc