blob: 0477be0c54540b797a1cb946953909e445f59c3b [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)
27 : callbacks_(callbacks),
28 decoder_factory_(decoder_factory),
philipel97187112018-03-23 10:43:21 +010029 decoder_settings_(std::move(decoder_settings)),
Danil Chapovalovb703db92019-04-08 16:59:28 +020030 bookkeeping_queue_(task_queue_factory->CreateTaskQueue(
31 "video_stream_decoder_bookkeeping_queue",
32 TaskQueueFactory::Priority::NORMAL)),
philipel844876d2018-04-05 11:02:54 +020033 decode_thread_(&DecodeLoop,
34 this,
35 "video_stream_decoder_decode_thread",
36 rtc::kHighestPriority),
philipel97187112018-03-23 10:43:21 +010037 timing_(Clock::GetRealTimeClock()),
Jonas Olssona4d87372019-07-05 19:08:33 +020038 frame_buffer_(Clock::GetRealTimeClock(), &timing_, nullptr),
philipel6847f9b2018-04-20 15:05:37 +020039 next_frame_timestamps_index_(0) {
40 frame_timestamps_.fill({-1, -1, -1});
philipel844876d2018-04-05 11:02:54 +020041 decode_thread_.Start();
42}
philipel2fee4d62018-03-21 16:52:13 +010043
philipel97187112018-03-23 10:43:21 +010044VideoStreamDecoderImpl::~VideoStreamDecoderImpl() {
45 frame_buffer_.Stop();
philipel844876d2018-04-05 11:02:54 +020046 decode_thread_.Stop();
philipel97187112018-03-23 10:43:21 +010047}
philipel2fee4d62018-03-21 16:52:13 +010048
49void VideoStreamDecoderImpl::OnFrame(
philipel97187112018-03-23 10:43:21 +010050 std::unique_ptr<video_coding::EncodedFrame> frame) {
51 if (!bookkeeping_queue_.IsCurrent()) {
Danil Chapovalov471783f2019-03-11 14:26:02 +010052 struct OnFrameTask : QueuedTask {
philipel97187112018-03-23 10:43:21 +010053 OnFrameTask(std::unique_ptr<video_coding::EncodedFrame> frame,
54 VideoStreamDecoderImpl* video_stream_decoder)
55 : frame_(std::move(frame)),
56 video_stream_decoder_(video_stream_decoder) {}
57
Niels Möllerbe682d42018-03-27 08:31:45 +020058 bool Run() override {
philipel97187112018-03-23 10:43:21 +010059 video_stream_decoder_->OnFrame(std::move(frame_));
60 return true;
61 }
62
63 std::unique_ptr<video_coding::EncodedFrame> frame_;
64 VideoStreamDecoderImpl* video_stream_decoder_;
65 };
66
67 bookkeeping_queue_.PostTask(
Mirko Bonadei317a1f02019-09-17 17:06:18 +020068 std::make_unique<OnFrameTask>(std::move(frame), this));
philipel97187112018-03-23 10:43:21 +010069 return;
70 }
71
72 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
73
74 uint64_t continuous_pid = frame_buffer_.InsertFrame(std::move(frame));
75 video_coding::VideoLayerFrameId continuous_id(continuous_pid, 0);
76 if (last_continuous_id_ < continuous_id) {
77 last_continuous_id_ = continuous_id;
78 callbacks_->OnContinuousUntil(last_continuous_id_);
79 }
80}
81
philipel781653c2019-06-04 17:10:37 +020082void VideoStreamDecoderImpl::SetMinPlayoutDelay(TimeDelta min_delay) {
83 timing_.set_min_playout_delay(min_delay.ms());
84}
85
86void VideoStreamDecoderImpl::SetMaxPlayoutDelay(TimeDelta max_delay) {
87 timing_.set_max_playout_delay(max_delay.ms());
88}
89
philipel79aab3f2018-03-26 14:31:23 +020090VideoDecoder* VideoStreamDecoderImpl::GetDecoder(int payload_type) {
91 if (current_payload_type_ == payload_type) {
92 RTC_DCHECK(decoder_);
93 return decoder_.get();
94 }
95
96 current_payload_type_.reset();
97 decoder_.reset();
98
99 auto decoder_settings_it = decoder_settings_.find(payload_type);
100 if (decoder_settings_it == decoder_settings_.end()) {
101 RTC_LOG(LS_WARNING) << "Payload type " << payload_type
102 << " not registered.";
103 return nullptr;
104 }
105
106 const SdpVideoFormat& video_format = decoder_settings_it->second.first;
107 std::unique_ptr<VideoDecoder> decoder =
108 decoder_factory_->CreateVideoDecoder(video_format);
109 if (!decoder) {
110 RTC_LOG(LS_WARNING) << "Failed to create decoder for payload type "
111 << payload_type << ".";
112 return nullptr;
113 }
114
115 int num_cores = decoder_settings_it->second.second;
116 int32_t init_result = decoder->InitDecode(nullptr, num_cores);
117 if (init_result != WEBRTC_VIDEO_CODEC_OK) {
118 RTC_LOG(LS_WARNING) << "Failed to initialize decoder for payload type "
119 << payload_type << ".";
120 return nullptr;
121 }
122
123 int32_t register_result = decoder->RegisterDecodeCompleteCallback(this);
124 if (register_result != WEBRTC_VIDEO_CODEC_OK) {
125 RTC_LOG(LS_WARNING) << "Failed to register decode callback.";
126 return nullptr;
127 }
128
129 current_payload_type_.emplace(payload_type);
130 decoder_ = std::move(decoder);
131 return decoder_.get();
132}
133
philipel844876d2018-04-05 11:02:54 +0200134// static
135void VideoStreamDecoderImpl::DecodeLoop(void* ptr) {
136 // TODO(philipel): Remove this and use rtc::Event::kForever when it's
137 // supported by the |frame_buffer_|.
138 static constexpr int kForever = 100000000;
139
140 int max_wait_time_ms = kForever;
141 bool keyframe_required = true;
142 auto* vs_decoder = static_cast<VideoStreamDecoderImpl*>(ptr);
143 while (true) {
144 DecodeResult decode_result =
145 vs_decoder->DecodeNextFrame(max_wait_time_ms, keyframe_required);
146
147 switch (decode_result) {
148 case kOk: {
149 max_wait_time_ms = kForever;
150 keyframe_required = false;
151 break;
152 }
153 case kDecodeFailure: {
154 max_wait_time_ms = 0;
155 keyframe_required = true;
156 break;
157 }
158 case kNoFrame: {
159 max_wait_time_ms = kForever;
160 // If we end up here it means that we got a decoding error and there is
161 // no keyframe available in the |frame_buffer_|.
162 vs_decoder->bookkeeping_queue_.PostTask([vs_decoder]() {
163 RTC_DCHECK_RUN_ON(&vs_decoder->bookkeeping_queue_);
164 vs_decoder->callbacks_->OnNonDecodableState();
165 });
166 break;
167 }
168 case kNoDecoder: {
169 max_wait_time_ms = kForever;
170 break;
171 }
172 case kShutdown: {
173 return;
174 }
175 }
176 }
177}
178
179VideoStreamDecoderImpl::DecodeResult VideoStreamDecoderImpl::DecodeNextFrame(
180 int max_wait_time_ms,
181 bool keyframe_required) {
182 std::unique_ptr<video_coding::EncodedFrame> frame;
183 video_coding::FrameBuffer::ReturnReason res =
184 frame_buffer_.NextFrame(max_wait_time_ms, &frame, keyframe_required);
185
186 if (res == video_coding::FrameBuffer::ReturnReason::kStopped)
187 return kShutdown;
188
189 if (frame) {
190 VideoDecoder* decoder = GetDecoder(frame->PayloadType());
191 if (!decoder) {
192 RTC_LOG(LS_WARNING) << "Failed to get decoder, dropping frame ("
193 << frame->id.picture_id << ":"
194 << frame->id.spatial_layer << ").";
195 return kNoDecoder;
196 }
197
198 int64_t decode_start_time_ms = rtc::TimeMillis();
Niels Möller23775882018-08-16 10:24:12 +0200199 int64_t timestamp = frame->Timestamp();
philipel6847f9b2018-04-20 15:05:37 +0200200 int64_t render_time_us = frame->RenderTimeMs() * 1000;
philipel844876d2018-04-05 11:02:54 +0200201 bookkeeping_queue_.PostTask(
philipel6847f9b2018-04-20 15:05:37 +0200202 [this, decode_start_time_ms, timestamp, render_time_us]() {
philipel844876d2018-04-05 11:02:54 +0200203 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
204 // Saving decode start time this way wont work if we decode spatial
205 // layers sequentially.
philipel6847f9b2018-04-20 15:05:37 +0200206 FrameTimestamps* frame_timestamps =
207 &frame_timestamps_[next_frame_timestamps_index_];
208 frame_timestamps->timestamp = timestamp;
209 frame_timestamps->decode_start_time_ms = decode_start_time_ms;
210 frame_timestamps->render_time_us = render_time_us;
211
212 next_frame_timestamps_index_ =
213 Add<kFrameTimestampsMemory>(next_frame_timestamps_index_, 1);
philipel844876d2018-04-05 11:02:54 +0200214 });
215
Yves Gerey665174f2018-06-19 15:03:05 +0200216 int32_t decode_result = decoder->Decode(frame->EncodedImage(),
Jonas Olssona4d87372019-07-05 19:08:33 +0200217 false, // missing_frame
Yves Gerey665174f2018-06-19 15:03:05 +0200218 frame->RenderTimeMs());
philipel844876d2018-04-05 11:02:54 +0200219
220 return decode_result == WEBRTC_VIDEO_CODEC_OK ? kOk : kDecodeFailure;
221 }
222
223 return kNoFrame;
224}
225
philipel6847f9b2018-04-20 15:05:37 +0200226VideoStreamDecoderImpl::FrameTimestamps*
227VideoStreamDecoderImpl::GetFrameTimestamps(int64_t timestamp) {
228 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
229
230 int start_time_index = next_frame_timestamps_index_;
231 for (int i = 0; i < kFrameTimestampsMemory; ++i) {
232 start_time_index = Subtract<kFrameTimestampsMemory>(start_time_index, 1);
233
234 if (frame_timestamps_[start_time_index].timestamp == timestamp)
235 return &frame_timestamps_[start_time_index];
236 }
237
238 return nullptr;
239}
240
241// VideoDecoder::DecodedImageCallback
242int32_t VideoStreamDecoderImpl::Decoded(VideoFrame& decoded_image) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200243 Decoded(decoded_image, absl::nullopt, absl::nullopt);
philipel6847f9b2018-04-20 15:05:37 +0200244 return WEBRTC_VIDEO_CODEC_OK;
245}
246
247// VideoDecoder::DecodedImageCallback
248int32_t VideoStreamDecoderImpl::Decoded(VideoFrame& decoded_image,
249 int64_t decode_time_ms) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200250 Decoded(decoded_image, decode_time_ms, absl::nullopt);
philipel6847f9b2018-04-20 15:05:37 +0200251 return WEBRTC_VIDEO_CODEC_OK;
252}
253
254// VideoDecoder::DecodedImageCallback
255void VideoStreamDecoderImpl::Decoded(VideoFrame& decoded_image,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200256 absl::optional<int32_t> decode_time_ms,
257 absl::optional<uint8_t> qp) {
philipel6847f9b2018-04-20 15:05:37 +0200258 int64_t decode_stop_time_ms = rtc::TimeMillis();
259
260 bookkeeping_queue_.PostTask([this, decode_stop_time_ms, decoded_image,
261 decode_time_ms, qp]() {
262 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
263
264 FrameTimestamps* frame_timestamps =
265 GetFrameTimestamps(decoded_image.timestamp());
266 if (!frame_timestamps) {
267 RTC_LOG(LS_ERROR) << "No frame information found for frame with timestamp"
268 << decoded_image.timestamp();
269 return;
270 }
271
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200272 absl::optional<int> casted_qp;
philipel6847f9b2018-04-20 15:05:37 +0200273 if (qp)
274 casted_qp.emplace(*qp);
275
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200276 absl::optional<int> casted_decode_time_ms(decode_time_ms.value_or(
philipel6847f9b2018-04-20 15:05:37 +0200277 decode_stop_time_ms - frame_timestamps->decode_start_time_ms));
278
Johannes Kronbfd343b2019-07-01 10:07:50 +0200279 timing_.StopDecodeTimer(*casted_decode_time_ms, decode_stop_time_ms);
philipel6847f9b2018-04-20 15:05:37 +0200280
Ilya Nikolaevskiy4fc08552019-06-05 15:59:12 +0200281 VideoFrame copy = decoded_image;
282 copy.set_timestamp_us(frame_timestamps->render_time_us);
283 callbacks_->OnDecodedFrame(copy, casted_decode_time_ms, casted_qp);
philipel6847f9b2018-04-20 15:05:37 +0200284 });
285}
286
philipel2fee4d62018-03-21 16:52:13 +0100287} // namespace webrtc