1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "video/video_stream_decoder_impl.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <memory>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
16*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/mod_ops.h"
17*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
18*d9f75844SAndroid Build Coastguard Worker
19*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
20*d9f75844SAndroid Build Coastguard Worker
VideoStreamDecoderImpl(VideoStreamDecoderInterface::Callbacks * callbacks,VideoDecoderFactory * decoder_factory,TaskQueueFactory * task_queue_factory,std::map<int,std::pair<SdpVideoFormat,int>> decoder_settings,const FieldTrialsView * field_trials)21*d9f75844SAndroid Build Coastguard Worker VideoStreamDecoderImpl::VideoStreamDecoderImpl(
22*d9f75844SAndroid Build Coastguard Worker VideoStreamDecoderInterface::Callbacks* callbacks,
23*d9f75844SAndroid Build Coastguard Worker VideoDecoderFactory* decoder_factory,
24*d9f75844SAndroid Build Coastguard Worker TaskQueueFactory* task_queue_factory,
25*d9f75844SAndroid Build Coastguard Worker std::map<int, std::pair<SdpVideoFormat, int>> decoder_settings,
26*d9f75844SAndroid Build Coastguard Worker const FieldTrialsView* field_trials)
27*d9f75844SAndroid Build Coastguard Worker : field_trials_(field_trials),
28*d9f75844SAndroid Build Coastguard Worker timing_(Clock::GetRealTimeClock(), *field_trials_),
29*d9f75844SAndroid Build Coastguard Worker decode_callbacks_(this),
30*d9f75844SAndroid Build Coastguard Worker next_frame_info_index_(0),
31*d9f75844SAndroid Build Coastguard Worker callbacks_(callbacks),
32*d9f75844SAndroid Build Coastguard Worker keyframe_required_(true),
33*d9f75844SAndroid Build Coastguard Worker decoder_factory_(decoder_factory),
34*d9f75844SAndroid Build Coastguard Worker decoder_settings_(std::move(decoder_settings)),
35*d9f75844SAndroid Build Coastguard Worker shut_down_(false),
36*d9f75844SAndroid Build Coastguard Worker frame_buffer_(Clock::GetRealTimeClock(), &timing_, *field_trials_),
37*d9f75844SAndroid Build Coastguard Worker bookkeeping_queue_(task_queue_factory->CreateTaskQueue(
38*d9f75844SAndroid Build Coastguard Worker "video_stream_decoder_bookkeeping_queue",
39*d9f75844SAndroid Build Coastguard Worker TaskQueueFactory::Priority::NORMAL)),
40*d9f75844SAndroid Build Coastguard Worker decode_queue_(task_queue_factory->CreateTaskQueue(
41*d9f75844SAndroid Build Coastguard Worker "video_stream_decoder_decode_queue",
42*d9f75844SAndroid Build Coastguard Worker TaskQueueFactory::Priority::NORMAL)) {
43*d9f75844SAndroid Build Coastguard Worker bookkeeping_queue_.PostTask([this]() {
44*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
45*d9f75844SAndroid Build Coastguard Worker StartNextDecode();
46*d9f75844SAndroid Build Coastguard Worker });
47*d9f75844SAndroid Build Coastguard Worker }
48*d9f75844SAndroid Build Coastguard Worker
~VideoStreamDecoderImpl()49*d9f75844SAndroid Build Coastguard Worker VideoStreamDecoderImpl::~VideoStreamDecoderImpl() {
50*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&shut_down_mutex_);
51*d9f75844SAndroid Build Coastguard Worker shut_down_ = true;
52*d9f75844SAndroid Build Coastguard Worker }
53*d9f75844SAndroid Build Coastguard Worker
OnFrame(std::unique_ptr<EncodedFrame> frame)54*d9f75844SAndroid Build Coastguard Worker void VideoStreamDecoderImpl::OnFrame(std::unique_ptr<EncodedFrame> frame) {
55*d9f75844SAndroid Build Coastguard Worker if (!bookkeeping_queue_.IsCurrent()) {
56*d9f75844SAndroid Build Coastguard Worker bookkeeping_queue_.PostTask([this, frame = std::move(frame)]() mutable {
57*d9f75844SAndroid Build Coastguard Worker OnFrame(std::move(frame));
58*d9f75844SAndroid Build Coastguard Worker return true;
59*d9f75844SAndroid Build Coastguard Worker });
60*d9f75844SAndroid Build Coastguard Worker
61*d9f75844SAndroid Build Coastguard Worker return;
62*d9f75844SAndroid Build Coastguard Worker }
63*d9f75844SAndroid Build Coastguard Worker
64*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
65*d9f75844SAndroid Build Coastguard Worker
66*d9f75844SAndroid Build Coastguard Worker int64_t continuous_frame_id = frame_buffer_.InsertFrame(std::move(frame));
67*d9f75844SAndroid Build Coastguard Worker if (last_continuous_frame_id_ < continuous_frame_id) {
68*d9f75844SAndroid Build Coastguard Worker last_continuous_frame_id_ = continuous_frame_id;
69*d9f75844SAndroid Build Coastguard Worker callbacks_->OnContinuousUntil(last_continuous_frame_id_);
70*d9f75844SAndroid Build Coastguard Worker }
71*d9f75844SAndroid Build Coastguard Worker }
72*d9f75844SAndroid Build Coastguard Worker
SetMinPlayoutDelay(TimeDelta min_delay)73*d9f75844SAndroid Build Coastguard Worker void VideoStreamDecoderImpl::SetMinPlayoutDelay(TimeDelta min_delay) {
74*d9f75844SAndroid Build Coastguard Worker timing_.set_min_playout_delay(min_delay);
75*d9f75844SAndroid Build Coastguard Worker }
76*d9f75844SAndroid Build Coastguard Worker
SetMaxPlayoutDelay(TimeDelta max_delay)77*d9f75844SAndroid Build Coastguard Worker void VideoStreamDecoderImpl::SetMaxPlayoutDelay(TimeDelta max_delay) {
78*d9f75844SAndroid Build Coastguard Worker timing_.set_max_playout_delay(max_delay);
79*d9f75844SAndroid Build Coastguard Worker }
80*d9f75844SAndroid Build Coastguard Worker
GetDecoder(int payload_type)81*d9f75844SAndroid Build Coastguard Worker VideoDecoder* VideoStreamDecoderImpl::GetDecoder(int payload_type) {
82*d9f75844SAndroid Build Coastguard Worker if (current_payload_type_ == payload_type) {
83*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(decoder_);
84*d9f75844SAndroid Build Coastguard Worker return decoder_.get();
85*d9f75844SAndroid Build Coastguard Worker }
86*d9f75844SAndroid Build Coastguard Worker
87*d9f75844SAndroid Build Coastguard Worker current_payload_type_.reset();
88*d9f75844SAndroid Build Coastguard Worker decoder_.reset();
89*d9f75844SAndroid Build Coastguard Worker
90*d9f75844SAndroid Build Coastguard Worker auto decoder_settings_it = decoder_settings_.find(payload_type);
91*d9f75844SAndroid Build Coastguard Worker if (decoder_settings_it == decoder_settings_.end()) {
92*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "Payload type " << payload_type
93*d9f75844SAndroid Build Coastguard Worker << " not registered.";
94*d9f75844SAndroid Build Coastguard Worker return nullptr;
95*d9f75844SAndroid Build Coastguard Worker }
96*d9f75844SAndroid Build Coastguard Worker
97*d9f75844SAndroid Build Coastguard Worker const SdpVideoFormat& video_format = decoder_settings_it->second.first;
98*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<VideoDecoder> decoder =
99*d9f75844SAndroid Build Coastguard Worker decoder_factory_->CreateVideoDecoder(video_format);
100*d9f75844SAndroid Build Coastguard Worker if (!decoder) {
101*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "Failed to create decoder for payload type "
102*d9f75844SAndroid Build Coastguard Worker << payload_type << ".";
103*d9f75844SAndroid Build Coastguard Worker return nullptr;
104*d9f75844SAndroid Build Coastguard Worker }
105*d9f75844SAndroid Build Coastguard Worker
106*d9f75844SAndroid Build Coastguard Worker VideoDecoder::Settings settings;
107*d9f75844SAndroid Build Coastguard Worker settings.set_number_of_cores(decoder_settings_it->second.second);
108*d9f75844SAndroid Build Coastguard Worker if (!decoder->Configure(settings)) {
109*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "Failed to initialize decoder for payload type "
110*d9f75844SAndroid Build Coastguard Worker << payload_type << ".";
111*d9f75844SAndroid Build Coastguard Worker return nullptr;
112*d9f75844SAndroid Build Coastguard Worker }
113*d9f75844SAndroid Build Coastguard Worker
114*d9f75844SAndroid Build Coastguard Worker int32_t register_result =
115*d9f75844SAndroid Build Coastguard Worker decoder->RegisterDecodeCompleteCallback(&decode_callbacks_);
116*d9f75844SAndroid Build Coastguard Worker if (register_result != WEBRTC_VIDEO_CODEC_OK) {
117*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "Failed to register decode callback.";
118*d9f75844SAndroid Build Coastguard Worker return nullptr;
119*d9f75844SAndroid Build Coastguard Worker }
120*d9f75844SAndroid Build Coastguard Worker
121*d9f75844SAndroid Build Coastguard Worker current_payload_type_.emplace(payload_type);
122*d9f75844SAndroid Build Coastguard Worker decoder_ = std::move(decoder);
123*d9f75844SAndroid Build Coastguard Worker return decoder_.get();
124*d9f75844SAndroid Build Coastguard Worker }
125*d9f75844SAndroid Build Coastguard Worker
SaveFrameInfo(const EncodedFrame & frame)126*d9f75844SAndroid Build Coastguard Worker void VideoStreamDecoderImpl::SaveFrameInfo(const EncodedFrame& frame) {
127*d9f75844SAndroid Build Coastguard Worker FrameInfo* frame_info = &frame_info_[next_frame_info_index_];
128*d9f75844SAndroid Build Coastguard Worker frame_info->timestamp = frame.Timestamp();
129*d9f75844SAndroid Build Coastguard Worker frame_info->decode_start_time_ms = rtc::TimeMillis();
130*d9f75844SAndroid Build Coastguard Worker frame_info->render_time_us = frame.RenderTimeMs() * 1000;
131*d9f75844SAndroid Build Coastguard Worker frame_info->content_type = frame.EncodedImage().content_type_;
132*d9f75844SAndroid Build Coastguard Worker
133*d9f75844SAndroid Build Coastguard Worker next_frame_info_index_ = Add<kFrameInfoMemory>(next_frame_info_index_, 1);
134*d9f75844SAndroid Build Coastguard Worker }
135*d9f75844SAndroid Build Coastguard Worker
StartNextDecode()136*d9f75844SAndroid Build Coastguard Worker void VideoStreamDecoderImpl::StartNextDecode() {
137*d9f75844SAndroid Build Coastguard Worker int64_t max_wait_time = keyframe_required_ ? 200 : 3000;
138*d9f75844SAndroid Build Coastguard Worker
139*d9f75844SAndroid Build Coastguard Worker frame_buffer_.NextFrame(max_wait_time, keyframe_required_,
140*d9f75844SAndroid Build Coastguard Worker bookkeeping_queue_.Get(),
141*d9f75844SAndroid Build Coastguard Worker [this](std::unique_ptr<EncodedFrame> frame) {
142*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
143*d9f75844SAndroid Build Coastguard Worker OnNextFrameCallback(std::move(frame));
144*d9f75844SAndroid Build Coastguard Worker });
145*d9f75844SAndroid Build Coastguard Worker }
146*d9f75844SAndroid Build Coastguard Worker
OnNextFrameCallback(std::unique_ptr<EncodedFrame> frame)147*d9f75844SAndroid Build Coastguard Worker void VideoStreamDecoderImpl::OnNextFrameCallback(
148*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<EncodedFrame> frame) {
149*d9f75844SAndroid Build Coastguard Worker if (frame) {
150*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(frame);
151*d9f75844SAndroid Build Coastguard Worker SaveFrameInfo(*frame);
152*d9f75844SAndroid Build Coastguard Worker
153*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&shut_down_mutex_);
154*d9f75844SAndroid Build Coastguard Worker if (shut_down_) {
155*d9f75844SAndroid Build Coastguard Worker return;
156*d9f75844SAndroid Build Coastguard Worker }
157*d9f75844SAndroid Build Coastguard Worker
158*d9f75844SAndroid Build Coastguard Worker decode_queue_.PostTask([this, frame = std::move(frame)]() mutable {
159*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&decode_queue_);
160*d9f75844SAndroid Build Coastguard Worker DecodeResult decode_result = DecodeFrame(std::move(frame));
161*d9f75844SAndroid Build Coastguard Worker bookkeeping_queue_.PostTask([this, decode_result]() {
162*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
163*d9f75844SAndroid Build Coastguard Worker switch (decode_result) {
164*d9f75844SAndroid Build Coastguard Worker case kOk: {
165*d9f75844SAndroid Build Coastguard Worker keyframe_required_ = false;
166*d9f75844SAndroid Build Coastguard Worker break;
167*d9f75844SAndroid Build Coastguard Worker }
168*d9f75844SAndroid Build Coastguard Worker case kOkRequestKeyframe: {
169*d9f75844SAndroid Build Coastguard Worker callbacks_->OnNonDecodableState();
170*d9f75844SAndroid Build Coastguard Worker keyframe_required_ = false;
171*d9f75844SAndroid Build Coastguard Worker break;
172*d9f75844SAndroid Build Coastguard Worker }
173*d9f75844SAndroid Build Coastguard Worker case kDecodeFailure: {
174*d9f75844SAndroid Build Coastguard Worker callbacks_->OnNonDecodableState();
175*d9f75844SAndroid Build Coastguard Worker keyframe_required_ = true;
176*d9f75844SAndroid Build Coastguard Worker break;
177*d9f75844SAndroid Build Coastguard Worker }
178*d9f75844SAndroid Build Coastguard Worker }
179*d9f75844SAndroid Build Coastguard Worker StartNextDecode();
180*d9f75844SAndroid Build Coastguard Worker });
181*d9f75844SAndroid Build Coastguard Worker });
182*d9f75844SAndroid Build Coastguard Worker } else {
183*d9f75844SAndroid Build Coastguard Worker callbacks_->OnNonDecodableState();
184*d9f75844SAndroid Build Coastguard Worker // The `frame_buffer_` requires the frame callback function to complete
185*d9f75844SAndroid Build Coastguard Worker // before NextFrame is called again. For this reason we call
186*d9f75844SAndroid Build Coastguard Worker // StartNextDecode in a later task to allow this task to complete first.
187*d9f75844SAndroid Build Coastguard Worker bookkeeping_queue_.PostTask([this]() {
188*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
189*d9f75844SAndroid Build Coastguard Worker StartNextDecode();
190*d9f75844SAndroid Build Coastguard Worker });
191*d9f75844SAndroid Build Coastguard Worker }
192*d9f75844SAndroid Build Coastguard Worker }
193*d9f75844SAndroid Build Coastguard Worker
DecodeFrame(std::unique_ptr<EncodedFrame> frame)194*d9f75844SAndroid Build Coastguard Worker VideoStreamDecoderImpl::DecodeResult VideoStreamDecoderImpl::DecodeFrame(
195*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<EncodedFrame> frame) {
196*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(frame);
197*d9f75844SAndroid Build Coastguard Worker
198*d9f75844SAndroid Build Coastguard Worker VideoDecoder* decoder = GetDecoder(frame->PayloadType());
199*d9f75844SAndroid Build Coastguard Worker if (!decoder) {
200*d9f75844SAndroid Build Coastguard Worker return kDecodeFailure;
201*d9f75844SAndroid Build Coastguard Worker }
202*d9f75844SAndroid Build Coastguard Worker
203*d9f75844SAndroid Build Coastguard Worker int32_t decode_result = decoder->Decode(frame->EncodedImage(), //
204*d9f75844SAndroid Build Coastguard Worker /*missing_frames=*/false, //
205*d9f75844SAndroid Build Coastguard Worker frame->RenderTimeMs());
206*d9f75844SAndroid Build Coastguard Worker switch (decode_result) {
207*d9f75844SAndroid Build Coastguard Worker case WEBRTC_VIDEO_CODEC_OK: {
208*d9f75844SAndroid Build Coastguard Worker return kOk;
209*d9f75844SAndroid Build Coastguard Worker }
210*d9f75844SAndroid Build Coastguard Worker case WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME: {
211*d9f75844SAndroid Build Coastguard Worker return kOkRequestKeyframe;
212*d9f75844SAndroid Build Coastguard Worker }
213*d9f75844SAndroid Build Coastguard Worker default:
214*d9f75844SAndroid Build Coastguard Worker return kDecodeFailure;
215*d9f75844SAndroid Build Coastguard Worker }
216*d9f75844SAndroid Build Coastguard Worker }
217*d9f75844SAndroid Build Coastguard Worker
GetFrameInfo(int64_t timestamp)218*d9f75844SAndroid Build Coastguard Worker VideoStreamDecoderImpl::FrameInfo* VideoStreamDecoderImpl::GetFrameInfo(
219*d9f75844SAndroid Build Coastguard Worker int64_t timestamp) {
220*d9f75844SAndroid Build Coastguard Worker int start_time_index = next_frame_info_index_;
221*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < kFrameInfoMemory; ++i) {
222*d9f75844SAndroid Build Coastguard Worker start_time_index = Subtract<kFrameInfoMemory>(start_time_index, 1);
223*d9f75844SAndroid Build Coastguard Worker
224*d9f75844SAndroid Build Coastguard Worker if (frame_info_[start_time_index].timestamp == timestamp)
225*d9f75844SAndroid Build Coastguard Worker return &frame_info_[start_time_index];
226*d9f75844SAndroid Build Coastguard Worker }
227*d9f75844SAndroid Build Coastguard Worker
228*d9f75844SAndroid Build Coastguard Worker return nullptr;
229*d9f75844SAndroid Build Coastguard Worker }
230*d9f75844SAndroid Build Coastguard Worker
OnDecodedFrameCallback(VideoFrame & decoded_image,absl::optional<int32_t> decode_time_ms,absl::optional<uint8_t> qp)231*d9f75844SAndroid Build Coastguard Worker void VideoStreamDecoderImpl::OnDecodedFrameCallback(
232*d9f75844SAndroid Build Coastguard Worker VideoFrame& decoded_image,
233*d9f75844SAndroid Build Coastguard Worker absl::optional<int32_t> decode_time_ms,
234*d9f75844SAndroid Build Coastguard Worker absl::optional<uint8_t> qp) {
235*d9f75844SAndroid Build Coastguard Worker int64_t decode_stop_time_ms = rtc::TimeMillis();
236*d9f75844SAndroid Build Coastguard Worker
237*d9f75844SAndroid Build Coastguard Worker bookkeeping_queue_.PostTask([this, decode_stop_time_ms, decoded_image,
238*d9f75844SAndroid Build Coastguard Worker decode_time_ms, qp]() mutable {
239*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&bookkeeping_queue_);
240*d9f75844SAndroid Build Coastguard Worker
241*d9f75844SAndroid Build Coastguard Worker FrameInfo* frame_info = GetFrameInfo(decoded_image.timestamp());
242*d9f75844SAndroid Build Coastguard Worker if (!frame_info) {
243*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "No frame information found for frame with timestamp"
244*d9f75844SAndroid Build Coastguard Worker << decoded_image.timestamp();
245*d9f75844SAndroid Build Coastguard Worker return;
246*d9f75844SAndroid Build Coastguard Worker }
247*d9f75844SAndroid Build Coastguard Worker
248*d9f75844SAndroid Build Coastguard Worker Callbacks::FrameInfo callback_info;
249*d9f75844SAndroid Build Coastguard Worker callback_info.content_type = frame_info->content_type;
250*d9f75844SAndroid Build Coastguard Worker
251*d9f75844SAndroid Build Coastguard Worker if (qp)
252*d9f75844SAndroid Build Coastguard Worker callback_info.qp.emplace(*qp);
253*d9f75844SAndroid Build Coastguard Worker
254*d9f75844SAndroid Build Coastguard Worker if (!decode_time_ms) {
255*d9f75844SAndroid Build Coastguard Worker decode_time_ms = decode_stop_time_ms - frame_info->decode_start_time_ms;
256*d9f75844SAndroid Build Coastguard Worker }
257*d9f75844SAndroid Build Coastguard Worker decoded_image.set_processing_time(
258*d9f75844SAndroid Build Coastguard Worker {Timestamp::Millis(frame_info->decode_start_time_ms),
259*d9f75844SAndroid Build Coastguard Worker Timestamp::Millis(frame_info->decode_start_time_ms +
260*d9f75844SAndroid Build Coastguard Worker *decode_time_ms)});
261*d9f75844SAndroid Build Coastguard Worker decoded_image.set_timestamp_us(frame_info->render_time_us);
262*d9f75844SAndroid Build Coastguard Worker timing_.StopDecodeTimer(TimeDelta::Millis(*decode_time_ms),
263*d9f75844SAndroid Build Coastguard Worker Timestamp::Millis(decode_stop_time_ms));
264*d9f75844SAndroid Build Coastguard Worker
265*d9f75844SAndroid Build Coastguard Worker callbacks_->OnDecodedFrame(decoded_image, callback_info);
266*d9f75844SAndroid Build Coastguard Worker });
267*d9f75844SAndroid Build Coastguard Worker }
268*d9f75844SAndroid Build Coastguard Worker
DecodeCallbacks(VideoStreamDecoderImpl * video_stream_decoder_impl)269*d9f75844SAndroid Build Coastguard Worker VideoStreamDecoderImpl::DecodeCallbacks::DecodeCallbacks(
270*d9f75844SAndroid Build Coastguard Worker VideoStreamDecoderImpl* video_stream_decoder_impl)
271*d9f75844SAndroid Build Coastguard Worker : video_stream_decoder_impl_(video_stream_decoder_impl) {}
272*d9f75844SAndroid Build Coastguard Worker
Decoded(VideoFrame & decoded_image)273*d9f75844SAndroid Build Coastguard Worker int32_t VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
274*d9f75844SAndroid Build Coastguard Worker VideoFrame& decoded_image) {
275*d9f75844SAndroid Build Coastguard Worker Decoded(decoded_image, absl::nullopt, absl::nullopt);
276*d9f75844SAndroid Build Coastguard Worker return WEBRTC_VIDEO_CODEC_OK;
277*d9f75844SAndroid Build Coastguard Worker }
278*d9f75844SAndroid Build Coastguard Worker
Decoded(VideoFrame & decoded_image,int64_t decode_time_ms)279*d9f75844SAndroid Build Coastguard Worker int32_t VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
280*d9f75844SAndroid Build Coastguard Worker VideoFrame& decoded_image,
281*d9f75844SAndroid Build Coastguard Worker int64_t decode_time_ms) {
282*d9f75844SAndroid Build Coastguard Worker Decoded(decoded_image, decode_time_ms, absl::nullopt);
283*d9f75844SAndroid Build Coastguard Worker return WEBRTC_VIDEO_CODEC_OK;
284*d9f75844SAndroid Build Coastguard Worker }
285*d9f75844SAndroid Build Coastguard Worker
Decoded(VideoFrame & decoded_image,absl::optional<int32_t> decode_time_ms,absl::optional<uint8_t> qp)286*d9f75844SAndroid Build Coastguard Worker void VideoStreamDecoderImpl::DecodeCallbacks::Decoded(
287*d9f75844SAndroid Build Coastguard Worker VideoFrame& decoded_image,
288*d9f75844SAndroid Build Coastguard Worker absl::optional<int32_t> decode_time_ms,
289*d9f75844SAndroid Build Coastguard Worker absl::optional<uint8_t> qp) {
290*d9f75844SAndroid Build Coastguard Worker video_stream_decoder_impl_->OnDecodedFrameCallback(decoded_image,
291*d9f75844SAndroid Build Coastguard Worker decode_time_ms, qp);
292*d9f75844SAndroid Build Coastguard Worker }
293*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
294