blob: b4ae8488d998451ea1089e081a7c4d08d49e3ee7 [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
Karl Wiberg918f50c2018-07-05 11:40:33 +020013#include "absl/memory/memory.h"
Danil Chapovalov471783f2019-03-11 14:26:02 +010014#include "api/task_queue/queued_task.h"
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,
philipel2fee4d62018-03-21 16:52:13 +010025 std::map<int, std::pair<SdpVideoFormat, int>> decoder_settings)
26 : callbacks_(callbacks),
27 decoder_factory_(decoder_factory),
philipel97187112018-03-23 10:43:21 +010028 decoder_settings_(std::move(decoder_settings)),
Danil Chapovalovb703db92019-04-08 16:59:28 +020029 bookkeeping_queue_(task_queue_factory->CreateTaskQueue(
30 "video_stream_decoder_bookkeeping_queue",
31 TaskQueueFactory::Priority::NORMAL)),
philipel844876d2018-04-05 11:02:54 +020032 decode_thread_(&DecodeLoop,
33 this,
34 "video_stream_decoder_decode_thread",
35 rtc::kHighestPriority),
philipel97187112018-03-23 10:43:21 +010036 timing_(Clock::GetRealTimeClock()),
37 frame_buffer_(Clock::GetRealTimeClock(),
philipel97187112018-03-23 10:43:21 +010038 &timing_,
philipel844876d2018-04-05 11:02:54 +020039 nullptr),
philipel6847f9b2018-04-20 15:05:37 +020040 next_frame_timestamps_index_(0) {
41 frame_timestamps_.fill({-1, -1, -1});
philipel844876d2018-04-05 11:02:54 +020042 decode_thread_.Start();
43}
philipel2fee4d62018-03-21 16:52:13 +010044
philipel97187112018-03-23 10:43:21 +010045VideoStreamDecoderImpl::~VideoStreamDecoderImpl() {
46 frame_buffer_.Stop();
philipel844876d2018-04-05 11:02:54 +020047 decode_thread_.Stop();
philipel97187112018-03-23 10:43:21 +010048}
philipel2fee4d62018-03-21 16:52:13 +010049
50void VideoStreamDecoderImpl::OnFrame(
philipel97187112018-03-23 10:43:21 +010051 std::unique_ptr<video_coding::EncodedFrame> frame) {
52 if (!bookkeeping_queue_.IsCurrent()) {
Danil Chapovalov471783f2019-03-11 14:26:02 +010053 struct OnFrameTask : QueuedTask {
philipel97187112018-03-23 10:43:21 +010054 OnFrameTask(std::unique_ptr<video_coding::EncodedFrame> frame,
55 VideoStreamDecoderImpl* video_stream_decoder)
56 : frame_(std::move(frame)),
57 video_stream_decoder_(video_stream_decoder) {}
58
Niels Möllerbe682d42018-03-27 08:31:45 +020059 bool Run() override {
philipel97187112018-03-23 10:43:21 +010060 video_stream_decoder_->OnFrame(std::move(frame_));
61 return true;
62 }
63
64 std::unique_ptr<video_coding::EncodedFrame> frame_;
65 VideoStreamDecoderImpl* video_stream_decoder_;
66 };
67
68 bookkeeping_queue_.PostTask(
Karl Wiberg918f50c2018-07-05 11:40:33 +020069 absl::make_unique<OnFrameTask>(std::move(frame), this));
philipel97187112018-03-23 10:43:21 +010070 return;
71 }
72
73 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
74
75 uint64_t continuous_pid = frame_buffer_.InsertFrame(std::move(frame));
76 video_coding::VideoLayerFrameId continuous_id(continuous_pid, 0);
77 if (last_continuous_id_ < continuous_id) {
78 last_continuous_id_ = continuous_id;
79 callbacks_->OnContinuousUntil(last_continuous_id_);
80 }
81}
82
philipel781653c2019-06-04 17:10:37 +020083void VideoStreamDecoderImpl::SetMinPlayoutDelay(TimeDelta min_delay) {
84 timing_.set_min_playout_delay(min_delay.ms());
85}
86
87void VideoStreamDecoderImpl::SetMaxPlayoutDelay(TimeDelta max_delay) {
88 timing_.set_max_playout_delay(max_delay.ms());
89}
90
philipel79aab3f2018-03-26 14:31:23 +020091VideoDecoder* VideoStreamDecoderImpl::GetDecoder(int payload_type) {
92 if (current_payload_type_ == payload_type) {
93 RTC_DCHECK(decoder_);
94 return decoder_.get();
95 }
96
97 current_payload_type_.reset();
98 decoder_.reset();
99
100 auto decoder_settings_it = decoder_settings_.find(payload_type);
101 if (decoder_settings_it == decoder_settings_.end()) {
102 RTC_LOG(LS_WARNING) << "Payload type " << payload_type
103 << " not registered.";
104 return nullptr;
105 }
106
107 const SdpVideoFormat& video_format = decoder_settings_it->second.first;
108 std::unique_ptr<VideoDecoder> decoder =
109 decoder_factory_->CreateVideoDecoder(video_format);
110 if (!decoder) {
111 RTC_LOG(LS_WARNING) << "Failed to create decoder for payload type "
112 << payload_type << ".";
113 return nullptr;
114 }
115
116 int num_cores = decoder_settings_it->second.second;
117 int32_t init_result = decoder->InitDecode(nullptr, num_cores);
118 if (init_result != WEBRTC_VIDEO_CODEC_OK) {
119 RTC_LOG(LS_WARNING) << "Failed to initialize decoder for payload type "
120 << payload_type << ".";
121 return nullptr;
122 }
123
124 int32_t register_result = decoder->RegisterDecodeCompleteCallback(this);
125 if (register_result != WEBRTC_VIDEO_CODEC_OK) {
126 RTC_LOG(LS_WARNING) << "Failed to register decode callback.";
127 return nullptr;
128 }
129
130 current_payload_type_.emplace(payload_type);
131 decoder_ = std::move(decoder);
132 return decoder_.get();
133}
134
philipel844876d2018-04-05 11:02:54 +0200135// static
136void VideoStreamDecoderImpl::DecodeLoop(void* ptr) {
137 // TODO(philipel): Remove this and use rtc::Event::kForever when it's
138 // supported by the |frame_buffer_|.
139 static constexpr int kForever = 100000000;
140
141 int max_wait_time_ms = kForever;
142 bool keyframe_required = true;
143 auto* vs_decoder = static_cast<VideoStreamDecoderImpl*>(ptr);
144 while (true) {
145 DecodeResult decode_result =
146 vs_decoder->DecodeNextFrame(max_wait_time_ms, keyframe_required);
147
148 switch (decode_result) {
149 case kOk: {
150 max_wait_time_ms = kForever;
151 keyframe_required = false;
152 break;
153 }
154 case kDecodeFailure: {
155 max_wait_time_ms = 0;
156 keyframe_required = true;
157 break;
158 }
159 case kNoFrame: {
160 max_wait_time_ms = kForever;
161 // If we end up here it means that we got a decoding error and there is
162 // no keyframe available in the |frame_buffer_|.
163 vs_decoder->bookkeeping_queue_.PostTask([vs_decoder]() {
164 RTC_DCHECK_RUN_ON(&vs_decoder->bookkeeping_queue_);
165 vs_decoder->callbacks_->OnNonDecodableState();
166 });
167 break;
168 }
169 case kNoDecoder: {
170 max_wait_time_ms = kForever;
171 break;
172 }
173 case kShutdown: {
174 return;
175 }
176 }
177 }
178}
179
180VideoStreamDecoderImpl::DecodeResult VideoStreamDecoderImpl::DecodeNextFrame(
181 int max_wait_time_ms,
182 bool keyframe_required) {
183 std::unique_ptr<video_coding::EncodedFrame> frame;
184 video_coding::FrameBuffer::ReturnReason res =
185 frame_buffer_.NextFrame(max_wait_time_ms, &frame, keyframe_required);
186
187 if (res == video_coding::FrameBuffer::ReturnReason::kStopped)
188 return kShutdown;
189
190 if (frame) {
191 VideoDecoder* decoder = GetDecoder(frame->PayloadType());
192 if (!decoder) {
193 RTC_LOG(LS_WARNING) << "Failed to get decoder, dropping frame ("
194 << frame->id.picture_id << ":"
195 << frame->id.spatial_layer << ").";
196 return kNoDecoder;
197 }
198
199 int64_t decode_start_time_ms = rtc::TimeMillis();
Niels Möller23775882018-08-16 10:24:12 +0200200 int64_t timestamp = frame->Timestamp();
philipel6847f9b2018-04-20 15:05:37 +0200201 int64_t render_time_us = frame->RenderTimeMs() * 1000;
philipel844876d2018-04-05 11:02:54 +0200202 bookkeeping_queue_.PostTask(
philipel6847f9b2018-04-20 15:05:37 +0200203 [this, decode_start_time_ms, timestamp, render_time_us]() {
philipel844876d2018-04-05 11:02:54 +0200204 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
205 // Saving decode start time this way wont work if we decode spatial
206 // layers sequentially.
philipel6847f9b2018-04-20 15:05:37 +0200207 FrameTimestamps* frame_timestamps =
208 &frame_timestamps_[next_frame_timestamps_index_];
209 frame_timestamps->timestamp = timestamp;
210 frame_timestamps->decode_start_time_ms = decode_start_time_ms;
211 frame_timestamps->render_time_us = render_time_us;
212
213 next_frame_timestamps_index_ =
214 Add<kFrameTimestampsMemory>(next_frame_timestamps_index_, 1);
philipel844876d2018-04-05 11:02:54 +0200215 });
216
Yves Gerey665174f2018-06-19 15:03:05 +0200217 int32_t decode_result = decoder->Decode(frame->EncodedImage(),
218 false, // missing_frame
Yves Gerey665174f2018-06-19 15:03:05 +0200219 frame->RenderTimeMs());
philipel844876d2018-04-05 11:02:54 +0200220
221 return decode_result == WEBRTC_VIDEO_CODEC_OK ? kOk : kDecodeFailure;
222 }
223
224 return kNoFrame;
225}
226
philipel6847f9b2018-04-20 15:05:37 +0200227VideoStreamDecoderImpl::FrameTimestamps*
228VideoStreamDecoderImpl::GetFrameTimestamps(int64_t timestamp) {
229 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
230
231 int start_time_index = next_frame_timestamps_index_;
232 for (int i = 0; i < kFrameTimestampsMemory; ++i) {
233 start_time_index = Subtract<kFrameTimestampsMemory>(start_time_index, 1);
234
235 if (frame_timestamps_[start_time_index].timestamp == timestamp)
236 return &frame_timestamps_[start_time_index];
237 }
238
239 return nullptr;
240}
241
242// VideoDecoder::DecodedImageCallback
243int32_t VideoStreamDecoderImpl::Decoded(VideoFrame& decoded_image) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200244 Decoded(decoded_image, absl::nullopt, absl::nullopt);
philipel6847f9b2018-04-20 15:05:37 +0200245 return WEBRTC_VIDEO_CODEC_OK;
246}
247
248// VideoDecoder::DecodedImageCallback
249int32_t VideoStreamDecoderImpl::Decoded(VideoFrame& decoded_image,
250 int64_t decode_time_ms) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200251 Decoded(decoded_image, decode_time_ms, absl::nullopt);
philipel6847f9b2018-04-20 15:05:37 +0200252 return WEBRTC_VIDEO_CODEC_OK;
253}
254
255// VideoDecoder::DecodedImageCallback
256void VideoStreamDecoderImpl::Decoded(VideoFrame& decoded_image,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200257 absl::optional<int32_t> decode_time_ms,
258 absl::optional<uint8_t> qp) {
philipel6847f9b2018-04-20 15:05:37 +0200259 int64_t decode_stop_time_ms = rtc::TimeMillis();
260
261 bookkeeping_queue_.PostTask([this, decode_stop_time_ms, decoded_image,
262 decode_time_ms, qp]() {
263 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
264
265 FrameTimestamps* frame_timestamps =
266 GetFrameTimestamps(decoded_image.timestamp());
267 if (!frame_timestamps) {
268 RTC_LOG(LS_ERROR) << "No frame information found for frame with timestamp"
269 << decoded_image.timestamp();
270 return;
271 }
272
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200273 absl::optional<int> casted_qp;
philipel6847f9b2018-04-20 15:05:37 +0200274 if (qp)
275 casted_qp.emplace(*qp);
276
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200277 absl::optional<int> casted_decode_time_ms(decode_time_ms.value_or(
philipel6847f9b2018-04-20 15:05:37 +0200278 decode_stop_time_ms - frame_timestamps->decode_start_time_ms));
279
280 timing_.StopDecodeTimer(0, *casted_decode_time_ms, decode_stop_time_ms,
281 frame_timestamps->render_time_us / 1000);
282
Ilya Nikolaevskiy4fc08552019-06-05 15:59:12 +0200283 VideoFrame copy = decoded_image;
284 copy.set_timestamp_us(frame_timestamps->render_time_us);
285 callbacks_->OnDecodedFrame(copy, casted_decode_time_ms, casted_qp);
philipel6847f9b2018-04-20 15:05:37 +0200286 });
287}
288
philipel2fee4d62018-03-21 16:52:13 +0100289} // namespace webrtc