blob: 2e8fc1a135ca59bc0b602d0c610ec6bd7cecc907 [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"
philipel97187112018-03-23 10:43:21 +010014#include "rtc_base/logging.h"
philipel844876d2018-04-05 11:02:54 +020015#include "rtc_base/numerics/mod_ops.h"
Danil Chapovalovdb128562018-09-17 13:11:50 +020016#include "rtc_base/timeutils.h"
philipel2fee4d62018-03-21 16:52:13 +010017
18namespace webrtc {
philipel97187112018-03-23 10:43:21 +010019
philipel2fee4d62018-03-21 16:52:13 +010020VideoStreamDecoderImpl::VideoStreamDecoderImpl(
21 VideoStreamDecoder::Callbacks* callbacks,
22 VideoDecoderFactory* decoder_factory,
23 std::map<int, std::pair<SdpVideoFormat, int>> decoder_settings)
24 : callbacks_(callbacks),
25 decoder_factory_(decoder_factory),
philipel97187112018-03-23 10:43:21 +010026 decoder_settings_(std::move(decoder_settings)),
27 bookkeeping_queue_("video_stream_decoder_bookkeeping_queue"),
philipel844876d2018-04-05 11:02:54 +020028 decode_thread_(&DecodeLoop,
29 this,
30 "video_stream_decoder_decode_thread",
31 rtc::kHighestPriority),
philipel97187112018-03-23 10:43:21 +010032 jitter_estimator_(Clock::GetRealTimeClock()),
33 timing_(Clock::GetRealTimeClock()),
34 frame_buffer_(Clock::GetRealTimeClock(),
35 &jitter_estimator_,
36 &timing_,
philipel844876d2018-04-05 11:02:54 +020037 nullptr),
philipel6847f9b2018-04-20 15:05:37 +020038 next_frame_timestamps_index_(0) {
39 frame_timestamps_.fill({-1, -1, -1});
philipel844876d2018-04-05 11:02:54 +020040 decode_thread_.Start();
41}
philipel2fee4d62018-03-21 16:52:13 +010042
philipel97187112018-03-23 10:43:21 +010043VideoStreamDecoderImpl::~VideoStreamDecoderImpl() {
44 frame_buffer_.Stop();
philipel844876d2018-04-05 11:02:54 +020045 decode_thread_.Stop();
philipel97187112018-03-23 10:43:21 +010046}
philipel2fee4d62018-03-21 16:52:13 +010047
48void VideoStreamDecoderImpl::OnFrame(
philipel97187112018-03-23 10:43:21 +010049 std::unique_ptr<video_coding::EncodedFrame> frame) {
50 if (!bookkeeping_queue_.IsCurrent()) {
51 struct OnFrameTask : rtc::QueuedTask {
52 OnFrameTask(std::unique_ptr<video_coding::EncodedFrame> frame,
53 VideoStreamDecoderImpl* video_stream_decoder)
54 : frame_(std::move(frame)),
55 video_stream_decoder_(video_stream_decoder) {}
56
Niels Möllerbe682d42018-03-27 08:31:45 +020057 bool Run() override {
philipel97187112018-03-23 10:43:21 +010058 video_stream_decoder_->OnFrame(std::move(frame_));
59 return true;
60 }
61
62 std::unique_ptr<video_coding::EncodedFrame> frame_;
63 VideoStreamDecoderImpl* video_stream_decoder_;
64 };
65
66 bookkeeping_queue_.PostTask(
Karl Wiberg918f50c2018-07-05 11:40:33 +020067 absl::make_unique<OnFrameTask>(std::move(frame), this));
philipel97187112018-03-23 10:43:21 +010068 return;
69 }
70
71 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
72
73 uint64_t continuous_pid = frame_buffer_.InsertFrame(std::move(frame));
74 video_coding::VideoLayerFrameId continuous_id(continuous_pid, 0);
75 if (last_continuous_id_ < continuous_id) {
76 last_continuous_id_ = continuous_id;
77 callbacks_->OnContinuousUntil(last_continuous_id_);
78 }
79}
80
philipel79aab3f2018-03-26 14:31:23 +020081VideoDecoder* VideoStreamDecoderImpl::GetDecoder(int payload_type) {
82 if (current_payload_type_ == payload_type) {
83 RTC_DCHECK(decoder_);
84 return decoder_.get();
85 }
86
87 current_payload_type_.reset();
88 decoder_.reset();
89
90 auto decoder_settings_it = decoder_settings_.find(payload_type);
91 if (decoder_settings_it == decoder_settings_.end()) {
92 RTC_LOG(LS_WARNING) << "Payload type " << payload_type
93 << " not registered.";
94 return nullptr;
95 }
96
97 const SdpVideoFormat& video_format = decoder_settings_it->second.first;
98 std::unique_ptr<VideoDecoder> decoder =
99 decoder_factory_->CreateVideoDecoder(video_format);
100 if (!decoder) {
101 RTC_LOG(LS_WARNING) << "Failed to create decoder for payload type "
102 << payload_type << ".";
103 return nullptr;
104 }
105
106 int num_cores = decoder_settings_it->second.second;
107 int32_t init_result = decoder->InitDecode(nullptr, num_cores);
108 if (init_result != WEBRTC_VIDEO_CODEC_OK) {
109 RTC_LOG(LS_WARNING) << "Failed to initialize decoder for payload type "
110 << payload_type << ".";
111 return nullptr;
112 }
113
114 int32_t register_result = decoder->RegisterDecodeCompleteCallback(this);
115 if (register_result != WEBRTC_VIDEO_CODEC_OK) {
116 RTC_LOG(LS_WARNING) << "Failed to register decode callback.";
117 return nullptr;
118 }
119
120 current_payload_type_.emplace(payload_type);
121 decoder_ = std::move(decoder);
122 return decoder_.get();
123}
124
philipel844876d2018-04-05 11:02:54 +0200125// static
126void VideoStreamDecoderImpl::DecodeLoop(void* ptr) {
127 // TODO(philipel): Remove this and use rtc::Event::kForever when it's
128 // supported by the |frame_buffer_|.
129 static constexpr int kForever = 100000000;
130
131 int max_wait_time_ms = kForever;
132 bool keyframe_required = true;
133 auto* vs_decoder = static_cast<VideoStreamDecoderImpl*>(ptr);
134 while (true) {
135 DecodeResult decode_result =
136 vs_decoder->DecodeNextFrame(max_wait_time_ms, keyframe_required);
137
138 switch (decode_result) {
139 case kOk: {
140 max_wait_time_ms = kForever;
141 keyframe_required = false;
142 break;
143 }
144 case kDecodeFailure: {
145 max_wait_time_ms = 0;
146 keyframe_required = true;
147 break;
148 }
149 case kNoFrame: {
150 max_wait_time_ms = kForever;
151 // If we end up here it means that we got a decoding error and there is
152 // no keyframe available in the |frame_buffer_|.
153 vs_decoder->bookkeeping_queue_.PostTask([vs_decoder]() {
154 RTC_DCHECK_RUN_ON(&vs_decoder->bookkeeping_queue_);
155 vs_decoder->callbacks_->OnNonDecodableState();
156 });
157 break;
158 }
159 case kNoDecoder: {
160 max_wait_time_ms = kForever;
161 break;
162 }
163 case kShutdown: {
164 return;
165 }
166 }
167 }
168}
169
170VideoStreamDecoderImpl::DecodeResult VideoStreamDecoderImpl::DecodeNextFrame(
171 int max_wait_time_ms,
172 bool keyframe_required) {
173 std::unique_ptr<video_coding::EncodedFrame> frame;
174 video_coding::FrameBuffer::ReturnReason res =
175 frame_buffer_.NextFrame(max_wait_time_ms, &frame, keyframe_required);
176
177 if (res == video_coding::FrameBuffer::ReturnReason::kStopped)
178 return kShutdown;
179
180 if (frame) {
181 VideoDecoder* decoder = GetDecoder(frame->PayloadType());
182 if (!decoder) {
183 RTC_LOG(LS_WARNING) << "Failed to get decoder, dropping frame ("
184 << frame->id.picture_id << ":"
185 << frame->id.spatial_layer << ").";
186 return kNoDecoder;
187 }
188
189 int64_t decode_start_time_ms = rtc::TimeMillis();
Niels Möller23775882018-08-16 10:24:12 +0200190 int64_t timestamp = frame->Timestamp();
philipel6847f9b2018-04-20 15:05:37 +0200191 int64_t render_time_us = frame->RenderTimeMs() * 1000;
philipel844876d2018-04-05 11:02:54 +0200192 bookkeeping_queue_.PostTask(
philipel6847f9b2018-04-20 15:05:37 +0200193 [this, decode_start_time_ms, timestamp, render_time_us]() {
philipel844876d2018-04-05 11:02:54 +0200194 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
195 // Saving decode start time this way wont work if we decode spatial
196 // layers sequentially.
philipel6847f9b2018-04-20 15:05:37 +0200197 FrameTimestamps* frame_timestamps =
198 &frame_timestamps_[next_frame_timestamps_index_];
199 frame_timestamps->timestamp = timestamp;
200 frame_timestamps->decode_start_time_ms = decode_start_time_ms;
201 frame_timestamps->render_time_us = render_time_us;
202
203 next_frame_timestamps_index_ =
204 Add<kFrameTimestampsMemory>(next_frame_timestamps_index_, 1);
philipel844876d2018-04-05 11:02:54 +0200205 });
206
Yves Gerey665174f2018-06-19 15:03:05 +0200207 int32_t decode_result = decoder->Decode(frame->EncodedImage(),
208 false, // missing_frame
209 nullptr, // codec specific info
210 frame->RenderTimeMs());
philipel844876d2018-04-05 11:02:54 +0200211
212 return decode_result == WEBRTC_VIDEO_CODEC_OK ? kOk : kDecodeFailure;
213 }
214
215 return kNoFrame;
216}
217
philipel6847f9b2018-04-20 15:05:37 +0200218VideoStreamDecoderImpl::FrameTimestamps*
219VideoStreamDecoderImpl::GetFrameTimestamps(int64_t timestamp) {
220 RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
221
222 int start_time_index = next_frame_timestamps_index_;
223 for (int i = 0; i < kFrameTimestampsMemory; ++i) {
224 start_time_index = Subtract<kFrameTimestampsMemory>(start_time_index, 1);
225
226 if (frame_timestamps_[start_time_index].timestamp == timestamp)
227 return &frame_timestamps_[start_time_index];
228 }
229
230 return nullptr;
231}
232
233// VideoDecoder::DecodedImageCallback
234int32_t VideoStreamDecoderImpl::Decoded(VideoFrame& decoded_image) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200235 Decoded(decoded_image, absl::nullopt, absl::nullopt);
philipel6847f9b2018-04-20 15:05:37 +0200236 return WEBRTC_VIDEO_CODEC_OK;
237}
238
239// VideoDecoder::DecodedImageCallback
240int32_t VideoStreamDecoderImpl::Decoded(VideoFrame& decoded_image,
241 int64_t decode_time_ms) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200242 Decoded(decoded_image, decode_time_ms, absl::nullopt);
philipel6847f9b2018-04-20 15:05:37 +0200243 return WEBRTC_VIDEO_CODEC_OK;
244}
245
246// VideoDecoder::DecodedImageCallback
247void VideoStreamDecoderImpl::Decoded(VideoFrame& decoded_image,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200248 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
271 timing_.StopDecodeTimer(0, *casted_decode_time_ms, decode_stop_time_ms,
272 frame_timestamps->render_time_us / 1000);
273
274 callbacks_->OnDecodedFrame(
275 VideoFrame(decoded_image.video_frame_buffer(), decoded_image.rotation(),
276 frame_timestamps->render_time_us),
277 casted_decode_time_ms, casted_qp);
278 });
279}
280
philipel2fee4d62018-03-21 16:52:13 +0100281} // namespace webrtc