1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/cast/test/fake_media_source.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/files/scoped_file.h"
11 #include "base/logging.h"
12 #include "base/rand_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "media/base/audio_buffer.h"
15 #include "media/base/audio_bus.h"
16 #include "media/base/audio_fifo.h"
17 #include "media/base/audio_timestamp_helper.h"
18 #include "media/base/media.h"
19 #include "media/base/video_frame.h"
20 #include "media/base/video_util.h"
21 #include "media/cast/cast_sender.h"
22 #include "media/cast/test/utility/audio_utility.h"
23 #include "media/cast/test/utility/video_utility.h"
24 #include "ui/gfx/geometry/size.h"
25
26 // TODO(miu): Figure out why _mkdir() and _rmdir() are missing when compiling
27 // third_party/ffmpeg/libavformat/os_support.h (lines 182, 183).
28 // http://crbug.com/572986
29 #if defined(OS_WIN)
30 #include <direct.h>
31 #endif // defined(OS_WIN)
32 #include "media/ffmpeg/ffmpeg_common.h"
33 #include "media/ffmpeg/ffmpeg_decoding_loop.h"
34 #include "media/ffmpeg/ffmpeg_deleters.h"
35 #include "media/filters/ffmpeg_glue.h"
36 #include "media/filters/in_memory_url_protocol.h"
37
38 namespace {
39
40 static const int kSoundFrequency = 440; // Frequency of sinusoid wave.
41 static const float kSoundVolume = 0.10f;
42 static const int kAudioFrameMs = 10; // Each audio frame is exactly 10ms.
43 static const int kAudioPacketsPerSecond = 1000 / kAudioFrameMs;
44
45 // Bounds for variable frame size mode.
46 static const int kMinFakeFrameWidth = 60;
47 static const int kMinFakeFrameHeight = 34;
48 static const int kStartingFakeFrameWidth = 854;
49 static const int kStartingFakeFrameHeight = 480;
50 static const int kMaxFakeFrameWidth = 1280;
51 static const int kMaxFakeFrameHeight = 720;
52 static const int kMaxFrameSizeChangeMillis = 5000;
53
AVFreeFrame(AVFrame * frame)54 void AVFreeFrame(AVFrame* frame) {
55 av_frame_free(&frame);
56 }
57
PtsToTimeDelta(int64_t pts,const AVRational & time_base)58 base::TimeDelta PtsToTimeDelta(int64_t pts, const AVRational& time_base) {
59 return pts * base::TimeDelta::FromSeconds(1) * time_base.num / time_base.den;
60 }
61
TimeDeltaToPts(base::TimeDelta delta,const AVRational & time_base)62 int64_t TimeDeltaToPts(base::TimeDelta delta, const AVRational& time_base) {
63 return static_cast<int64_t>(
64 delta.InSecondsF() * time_base.den / time_base.num + 0.5 /* rounding */);
65 }
66
67 } // namespace
68
69 namespace media {
70 namespace cast {
71
FakeMediaSource(scoped_refptr<base::SingleThreadTaskRunner> task_runner,const base::TickClock * clock,const FrameSenderConfig & audio_config,const FrameSenderConfig & video_config,bool keep_frames)72 FakeMediaSource::FakeMediaSource(
73 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
74 const base::TickClock* clock,
75 const FrameSenderConfig& audio_config,
76 const FrameSenderConfig& video_config,
77 bool keep_frames)
78 : task_runner_(task_runner),
79 output_audio_params_(AudioParameters::AUDIO_PCM_LINEAR,
80 media::GuessChannelLayout(audio_config.channels),
81 audio_config.rtp_timebase,
82 audio_config.rtp_timebase / kAudioPacketsPerSecond),
83 video_config_(video_config),
84 keep_frames_(keep_frames),
85 variable_frame_size_mode_(false),
86 synthetic_count_(0),
87 clock_(clock),
88 audio_frame_count_(0),
89 video_frame_count_(0),
90 av_format_context_(nullptr),
91 audio_stream_index_(-1),
92 playback_rate_(1.0),
93 video_stream_index_(-1),
94 video_frame_rate_numerator_(video_config.max_frame_rate),
95 video_frame_rate_denominator_(1),
96 audio_algo_(&media_log_),
97 video_first_pts_(0),
98 video_first_pts_set_(false) {
99 CHECK(output_audio_params_.IsValid());
100 audio_bus_factory_.reset(
101 new TestAudioBusFactory(audio_config.channels, audio_config.rtp_timebase,
102 kSoundFrequency, kSoundVolume));
103 }
104
105 FakeMediaSource::~FakeMediaSource() = default;
106
SetSourceFile(const base::FilePath & video_file,int final_fps)107 void FakeMediaSource::SetSourceFile(const base::FilePath& video_file,
108 int final_fps) {
109 DCHECK(!video_file.empty());
110
111 LOG(INFO) << "Source: " << video_file.value();
112 if (!file_data_.Initialize(video_file)) {
113 LOG(ERROR) << "Cannot load file.";
114 return;
115 }
116 protocol_.reset(
117 new InMemoryUrlProtocol(file_data_.data(), file_data_.length(), false));
118 glue_.reset(new FFmpegGlue(protocol_.get()));
119
120 if (!glue_->OpenContext()) {
121 LOG(ERROR) << "Cannot open file.";
122 return;
123 }
124
125 // AVFormatContext is owned by the glue.
126 av_format_context_ = glue_->format_context();
127 if (avformat_find_stream_info(av_format_context_, NULL) < 0) {
128 LOG(ERROR) << "Cannot find stream information.";
129 return;
130 }
131
132 // Prepare FFmpeg decoders.
133 for (unsigned int i = 0; i < av_format_context_->nb_streams; ++i) {
134 AVStream* av_stream = av_format_context_->streams[i];
135 std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> av_codec_context(
136 AVStreamToAVCodecContext(av_stream));
137 if (!av_codec_context) {
138 LOG(ERROR) << "Cannot get a codec context for the codec: "
139 << av_stream->codecpar->codec_id;
140 continue;
141 }
142
143 AVCodec* av_codec = avcodec_find_decoder(av_codec_context->codec_id);
144
145 if (!av_codec) {
146 LOG(ERROR) << "Cannot find decoder for the codec: "
147 << av_codec_context->codec_id;
148 continue;
149 }
150
151 // Number of threads for decoding.
152 av_codec_context->thread_count = 2;
153 av_codec_context->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
154 av_codec_context->request_sample_fmt = AV_SAMPLE_FMT_S16;
155
156 if (avcodec_open2(av_codec_context.get(), av_codec, nullptr) < 0) {
157 LOG(ERROR) << "Cannot open AVCodecContext for the codec: "
158 << av_codec_context->codec_id;
159 return;
160 }
161
162 if (av_codec->type == AVMEDIA_TYPE_AUDIO) {
163 if (av_codec_context->sample_fmt == AV_SAMPLE_FMT_S16P) {
164 LOG(ERROR) << "Audio format not supported.";
165 continue;
166 }
167 ChannelLayout layout = ChannelLayoutToChromeChannelLayout(
168 av_codec_context->channel_layout,
169 av_codec_context->channels);
170 if (layout == CHANNEL_LAYOUT_UNSUPPORTED) {
171 LOG(ERROR) << "Unsupported audio channels layout.";
172 continue;
173 }
174 if (audio_stream_index_ != -1) {
175 LOG(WARNING) << "Found multiple audio streams.";
176 }
177 audio_stream_index_ = static_cast<int>(i);
178 av_audio_context_ = std::move(av_codec_context);
179 source_audio_params_.Reset(
180 AudioParameters::AUDIO_PCM_LINEAR, layout,
181 av_audio_context_->sample_rate,
182 av_audio_context_->sample_rate / kAudioPacketsPerSecond);
183 source_audio_params_.set_channels_for_discrete(
184 av_audio_context_->channels);
185 CHECK(source_audio_params_.IsValid());
186 LOG(INFO) << "Source file has audio.";
187 audio_decoding_loop_.reset(
188 new FFmpegDecodingLoop(av_audio_context_.get()));
189 } else if (av_codec->type == AVMEDIA_TYPE_VIDEO) {
190 VideoPixelFormat format =
191 AVPixelFormatToVideoPixelFormat(av_codec_context->pix_fmt);
192 if (format != PIXEL_FORMAT_I420) {
193 LOG(ERROR) << "Cannot handle non YV12 video format: " << format;
194 continue;
195 }
196 if (video_stream_index_ != -1) {
197 LOG(WARNING) << "Found multiple video streams.";
198 }
199 video_stream_index_ = static_cast<int>(i);
200 av_video_context_ = std::move(av_codec_context);
201 video_decoding_loop_.reset(
202 new FFmpegDecodingLoop(av_video_context_.get()));
203 if (final_fps > 0) {
204 // If video is played at a manual speed audio needs to match.
205 playback_rate_ = 1.0 * final_fps *
206 av_stream->r_frame_rate.den / av_stream->r_frame_rate.num;
207 video_frame_rate_numerator_ = final_fps;
208 video_frame_rate_denominator_ = 1;
209 } else {
210 playback_rate_ = 1.0;
211 video_frame_rate_numerator_ = av_stream->r_frame_rate.num;
212 video_frame_rate_denominator_ = av_stream->r_frame_rate.den;
213 }
214 LOG(INFO) << "Source file has video.";
215 } else {
216 LOG(ERROR) << "Unknown stream type; ignore.";
217 }
218 }
219
220 Rewind();
221 }
222
SetVariableFrameSizeMode(bool enabled)223 void FakeMediaSource::SetVariableFrameSizeMode(bool enabled) {
224 variable_frame_size_mode_ = enabled;
225 }
226
Start(scoped_refptr<AudioFrameInput> audio_frame_input,scoped_refptr<VideoFrameInput> video_frame_input)227 void FakeMediaSource::Start(scoped_refptr<AudioFrameInput> audio_frame_input,
228 scoped_refptr<VideoFrameInput> video_frame_input) {
229 audio_frame_input_ = audio_frame_input;
230 video_frame_input_ = video_frame_input;
231
232 LOG(INFO) << "Max Frame rate: " << video_config_.max_frame_rate;
233 LOG(INFO) << "Source Frame rate: "
234 << video_frame_rate_numerator_ << "/"
235 << video_frame_rate_denominator_ << " fps.";
236 LOG(INFO) << "Audio playback rate: " << playback_rate_;
237
238 if (start_time_.is_null())
239 start_time_ = clock_->NowTicks();
240
241 if (!is_transcoding_audio() && !is_transcoding_video()) {
242 // Send fake patterns.
243 task_runner_->PostTask(FROM_HERE,
244 base::BindOnce(&FakeMediaSource::SendNextFakeFrame,
245 weak_factory_.GetWeakPtr()));
246 return;
247 }
248
249 // Send transcoding streams.
250 bool is_encrypted = false;
251 audio_algo_.Initialize(source_audio_params_, is_encrypted);
252 audio_algo_.FlushBuffers();
253 audio_fifo_input_bus_ = AudioBus::Create(
254 source_audio_params_.channels(),
255 source_audio_params_.frames_per_buffer());
256 // Audio FIFO can carry all data fron AudioRendererAlgorithm.
257 audio_fifo_.reset(
258 new AudioFifo(source_audio_params_.channels(),
259 audio_algo_.QueueCapacity()));
260 audio_converter_.reset(new media::AudioConverter(
261 source_audio_params_, output_audio_params_, true));
262 audio_converter_->AddInput(this);
263 task_runner_->PostTask(FROM_HERE,
264 base::BindOnce(&FakeMediaSource::SendNextFrame,
265 weak_factory_.GetWeakPtr()));
266 }
267
SendNextFakeFrame()268 void FakeMediaSource::SendNextFakeFrame() {
269 UpdateNextFrameSize();
270 scoped_refptr<VideoFrame> video_frame =
271 VideoFrame::CreateBlackFrame(current_frame_size_);
272 PopulateVideoFrame(video_frame.get(), synthetic_count_);
273 ++synthetic_count_;
274
275 const base::TimeTicks now = clock_->NowTicks();
276
277 base::TimeDelta video_time = VideoFrameTime(++video_frame_count_);
278 video_frame->set_timestamp(video_time);
279 if (keep_frames_)
280 inserted_video_frame_queue_.push(video_frame);
281 video_frame_input_->InsertRawVideoFrame(video_frame,
282 start_time_ + video_time);
283
284 // Send just enough audio data to match next video frame's time.
285 base::TimeDelta audio_time = AudioFrameTime(audio_frame_count_);
286 while (audio_time < video_time) {
287 if (is_transcoding_audio()) {
288 Decode(true);
289 CHECK(!audio_bus_queue_.empty()) << "No audio decoded.";
290 std::unique_ptr<AudioBus> bus(audio_bus_queue_.front());
291 audio_bus_queue_.pop();
292 audio_frame_input_->InsertAudio(std::move(bus), start_time_ + audio_time);
293 } else {
294 audio_frame_input_->InsertAudio(
295 audio_bus_factory_->NextAudioBus(
296 base::TimeDelta::FromMilliseconds(kAudioFrameMs)),
297 start_time_ + audio_time);
298 }
299 audio_time = AudioFrameTime(++audio_frame_count_);
300 }
301
302 // This is the time since FakeMediaSource was started.
303 const base::TimeDelta elapsed_time = now - start_time_;
304
305 // Handle the case when frame generation cannot keep up.
306 // Move the time ahead to match the next frame.
307 while (video_time < elapsed_time) {
308 LOG(WARNING) << "Skipping one frame.";
309 video_time = VideoFrameTime(++video_frame_count_);
310 }
311
312 task_runner_->PostDelayedTask(
313 FROM_HERE,
314 base::BindOnce(&FakeMediaSource::SendNextFakeFrame,
315 weak_factory_.GetWeakPtr()),
316 video_time - elapsed_time);
317 }
318
UpdateNextFrameSize()319 void FakeMediaSource::UpdateNextFrameSize() {
320 if (variable_frame_size_mode_) {
321 bool update_size_change_time = false;
322 if (current_frame_size_.IsEmpty()) {
323 current_frame_size_ = gfx::Size(kStartingFakeFrameWidth,
324 kStartingFakeFrameHeight);
325 update_size_change_time = true;
326 } else if (clock_->NowTicks() >= next_frame_size_change_time_) {
327 current_frame_size_ = gfx::Size(
328 base::RandInt(kMinFakeFrameWidth, kMaxFakeFrameWidth),
329 base::RandInt(kMinFakeFrameHeight, kMaxFakeFrameHeight));
330 update_size_change_time = true;
331 }
332
333 if (update_size_change_time) {
334 next_frame_size_change_time_ = clock_->NowTicks() +
335 base::TimeDelta::FromMillisecondsD(
336 base::RandDouble() * kMaxFrameSizeChangeMillis);
337 }
338 } else {
339 current_frame_size_ = gfx::Size(kStartingFakeFrameWidth,
340 kStartingFakeFrameHeight);
341 next_frame_size_change_time_ = base::TimeTicks();
342 }
343 }
344
SendNextTranscodedVideo(base::TimeDelta elapsed_time)345 bool FakeMediaSource::SendNextTranscodedVideo(base::TimeDelta elapsed_time) {
346 if (!is_transcoding_video())
347 return false;
348
349 Decode(false);
350 if (video_frame_queue_.empty())
351 return false;
352
353 const scoped_refptr<VideoFrame> video_frame = video_frame_queue_.front();
354 if (elapsed_time < video_frame->timestamp())
355 return false;
356 video_frame_queue_.pop();
357
358 // Use the timestamp from the file if we're transcoding.
359 video_frame->set_timestamp(ScaleTimestamp(video_frame->timestamp()));
360 if (keep_frames_)
361 inserted_video_frame_queue_.push(video_frame);
362 video_frame_input_->InsertRawVideoFrame(
363 video_frame, start_time_ + video_frame->timestamp());
364
365 // Make sure queue is not empty.
366 Decode(false);
367 return true;
368 }
369
SendNextTranscodedAudio(base::TimeDelta elapsed_time)370 bool FakeMediaSource::SendNextTranscodedAudio(base::TimeDelta elapsed_time) {
371 if (!is_transcoding_audio())
372 return false;
373
374 Decode(true);
375 if (audio_bus_queue_.empty())
376 return false;
377
378 base::TimeDelta audio_time = audio_sent_ts_->GetTimestamp();
379 if (elapsed_time < audio_time)
380 return false;
381 std::unique_ptr<AudioBus> bus(audio_bus_queue_.front());
382 audio_bus_queue_.pop();
383 audio_sent_ts_->AddFrames(bus->frames());
384 audio_frame_input_->InsertAudio(std::move(bus), start_time_ + audio_time);
385
386 // Make sure queue is not empty.
387 Decode(true);
388 return true;
389 }
390
SendNextFrame()391 void FakeMediaSource::SendNextFrame() {
392 // Send as much as possible. Audio is sent according to
393 // system time.
394 while (SendNextTranscodedAudio(clock_->NowTicks() - start_time_)) {
395 }
396
397 // Video is sync'ed to audio.
398 while (SendNextTranscodedVideo(audio_sent_ts_->GetTimestamp())) {
399 }
400
401 if (audio_bus_queue_.empty() && video_frame_queue_.empty()) {
402 // Both queues are empty can only mean that we have reached
403 // the end of the stream.
404 LOG(INFO) << "Rewind.";
405 Rewind();
406 }
407
408 // Send next send.
409 task_runner_->PostDelayedTask(
410 FROM_HERE,
411 base::BindOnce(&FakeMediaSource::SendNextFrame,
412 weak_factory_.GetWeakPtr()),
413 base::TimeDelta::FromMilliseconds(kAudioFrameMs));
414 }
415
VideoFrameTime(int frame_number)416 base::TimeDelta FakeMediaSource::VideoFrameTime(int frame_number) {
417 return frame_number * base::TimeDelta::FromSeconds(1) *
418 video_frame_rate_denominator_ / video_frame_rate_numerator_;
419 }
420
ScaleTimestamp(base::TimeDelta timestamp)421 base::TimeDelta FakeMediaSource::ScaleTimestamp(base::TimeDelta timestamp) {
422 return timestamp / playback_rate_;
423 }
424
AudioFrameTime(int frame_number)425 base::TimeDelta FakeMediaSource::AudioFrameTime(int frame_number) {
426 return frame_number * base::TimeDelta::FromMilliseconds(kAudioFrameMs);
427 }
428
Rewind()429 void FakeMediaSource::Rewind() {
430 CHECK(av_seek_frame(av_format_context_, -1, 0, AVSEEK_FLAG_BACKWARD) >= 0)
431 << "Failed to rewind to the beginning.";
432 }
433
DemuxOnePacket(bool * audio)434 ScopedAVPacket FakeMediaSource::DemuxOnePacket(bool* audio) {
435 ScopedAVPacket packet(new AVPacket());
436 if (av_read_frame(av_format_context_, packet.get()) < 0) {
437 VLOG(1) << "Failed to read one AVPacket.";
438 packet.reset();
439 return packet;
440 }
441
442 int stream_index = static_cast<int>(packet->stream_index);
443 if (stream_index == audio_stream_index_) {
444 *audio = true;
445 } else if (stream_index == video_stream_index_) {
446 *audio = false;
447 } else {
448 // Ignore unknown packet.
449 LOG(INFO) << "Unknown packet.";
450 packet.reset();
451 }
452 return packet;
453 }
454
DecodeAudio(ScopedAVPacket packet)455 void FakeMediaSource::DecodeAudio(ScopedAVPacket packet) {
456 auto result = audio_decoding_loop_->DecodePacket(
457 packet.get(), base::BindRepeating(&FakeMediaSource::OnNewAudioFrame,
458 base::Unretained(this)));
459 CHECK_EQ(result, FFmpegDecodingLoop::DecodeStatus::kOkay)
460 << "Failed to decode audio.";
461
462 const int frames_needed_to_scale =
463 playback_rate_ * av_audio_context_->sample_rate / kAudioPacketsPerSecond;
464 while (frames_needed_to_scale <= audio_algo_.BufferedFrames()) {
465 if (!audio_algo_.FillBuffer(audio_fifo_input_bus_.get(), 0,
466 audio_fifo_input_bus_->frames(),
467 playback_rate_)) {
468 // Nothing can be scaled. Decode some more.
469 return;
470 }
471
472 // Prevent overflow of audio data in the FIFO.
473 if (audio_fifo_input_bus_->frames() + audio_fifo_->frames() <=
474 audio_fifo_->max_frames()) {
475 audio_fifo_->Push(audio_fifo_input_bus_.get());
476 } else {
477 LOG(WARNING) << "Audio FIFO full; dropping samples.";
478 }
479
480 // Make sure there's enough data to resample audio.
481 if (audio_fifo_->frames() <
482 2 * source_audio_params_.sample_rate() / kAudioPacketsPerSecond) {
483 continue;
484 }
485
486 std::unique_ptr<media::AudioBus> resampled_bus(media::AudioBus::Create(
487 output_audio_params_.channels(),
488 output_audio_params_.sample_rate() / kAudioPacketsPerSecond));
489 audio_converter_->Convert(resampled_bus.get());
490 audio_bus_queue_.push(resampled_bus.release());
491 }
492 }
493
OnNewAudioFrame(AVFrame * frame)494 bool FakeMediaSource::OnNewAudioFrame(AVFrame* frame) {
495 int frames_read = frame->nb_samples;
496 if (frames_read < 0)
497 return false;
498
499 if (!audio_sent_ts_) {
500 // Initialize the base time to the first packet in the file. This is set to
501 // the frequency we send to the receiver. Not the frequency of the source
502 // file. This is because we increment the frame count by samples we sent.
503 audio_sent_ts_.reset(
504 new AudioTimestampHelper(output_audio_params_.sample_rate()));
505 // For some files this is an invalid value.
506 base::TimeDelta base_ts;
507 audio_sent_ts_->SetBaseTimestamp(base_ts);
508 }
509
510 scoped_refptr<AudioBuffer> buffer = AudioBuffer::CopyFrom(
511 AVSampleFormatToSampleFormat(av_audio_context_->sample_fmt,
512 av_audio_context_->codec_id),
513 ChannelLayoutToChromeChannelLayout(av_audio_context_->channel_layout,
514 av_audio_context_->channels),
515 av_audio_context_->channels, av_audio_context_->sample_rate, frames_read,
516 &frame->data[0],
517 PtsToTimeDelta(frame->pts, av_audio_stream()->time_base));
518 audio_algo_.EnqueueBuffer(buffer);
519 return true;
520 }
521
DecodeVideo(ScopedAVPacket packet)522 void FakeMediaSource::DecodeVideo(ScopedAVPacket packet) {
523 auto result = video_decoding_loop_->DecodePacket(
524 packet.get(), base::BindRepeating(&FakeMediaSource::OnNewVideoFrame,
525 base::Unretained(this)));
526 CHECK_EQ(result, FFmpegDecodingLoop::DecodeStatus::kOkay)
527 << "Failed to decode video.";
528 }
529
OnNewVideoFrame(AVFrame * frame)530 bool FakeMediaSource::OnNewVideoFrame(AVFrame* frame) {
531 gfx::Size size(av_video_context_->width, av_video_context_->height);
532
533 if (!video_first_pts_set_) {
534 video_first_pts_ = frame->pts;
535 video_first_pts_set_ = true;
536 }
537 const AVRational& time_base = av_video_stream()->time_base;
538 base::TimeDelta timestamp =
539 PtsToTimeDelta(frame->pts - video_first_pts_, time_base);
540 if (timestamp < last_video_frame_timestamp_) {
541 // Stream has rewound. Rebase |video_first_pts_|.
542 const AVRational& frame_rate = av_video_stream()->r_frame_rate;
543 timestamp = last_video_frame_timestamp_ + (base::TimeDelta::FromSeconds(1) *
544 frame_rate.den / frame_rate.num);
545 const int64_t adjustment_pts = TimeDeltaToPts(timestamp, time_base);
546 video_first_pts_ = frame->pts - adjustment_pts;
547 }
548
549 AVFrame* shallow_copy = av_frame_clone(frame);
550 scoped_refptr<media::VideoFrame> video_frame =
551 VideoFrame::WrapExternalYuvData(
552 media::PIXEL_FORMAT_I420, size, gfx::Rect(size), size,
553 shallow_copy->linesize[0], shallow_copy->linesize[1],
554 shallow_copy->linesize[2], shallow_copy->data[0],
555 shallow_copy->data[1], shallow_copy->data[2], timestamp);
556 if (!video_frame)
557 return false;
558 video_frame_queue_.push(video_frame);
559 video_frame_queue_.back()->AddDestructionObserver(
560 base::BindOnce(&AVFreeFrame, shallow_copy));
561 last_video_frame_timestamp_ = timestamp;
562 return true;
563 }
564
Decode(bool decode_audio)565 void FakeMediaSource::Decode(bool decode_audio) {
566 // Read the stream until one video frame can be decoded.
567 while (true) {
568 if (decode_audio && !audio_bus_queue_.empty())
569 return;
570 if (!decode_audio && !video_frame_queue_.empty())
571 return;
572
573 bool audio_packet = false;
574 ScopedAVPacket packet = DemuxOnePacket(&audio_packet);
575 if (!packet) {
576 VLOG(1) << "End of stream.";
577 return;
578 }
579
580 if (audio_packet)
581 DecodeAudio(std::move(packet));
582 else
583 DecodeVideo(std::move(packet));
584 }
585 }
586
ProvideInput(media::AudioBus * output_bus,uint32_t frames_delayed)587 double FakeMediaSource::ProvideInput(media::AudioBus* output_bus,
588 uint32_t frames_delayed) {
589 if (audio_fifo_->frames() >= output_bus->frames()) {
590 audio_fifo_->Consume(output_bus, 0, output_bus->frames());
591 return 1.0;
592 } else {
593 LOG(WARNING) << "Not enough audio data for resampling.";
594 output_bus->Zero();
595 return 0.0;
596 }
597 }
598
599 scoped_refptr<media::VideoFrame>
PopOldestInsertedVideoFrame()600 FakeMediaSource::PopOldestInsertedVideoFrame() {
601 CHECK(!inserted_video_frame_queue_.empty());
602 scoped_refptr<media::VideoFrame> video_frame =
603 inserted_video_frame_queue_.front();
604 inserted_video_frame_queue_.pop();
605 return video_frame;
606 }
607
av_audio_stream()608 AVStream* FakeMediaSource::av_audio_stream() {
609 return av_format_context_->streams[audio_stream_index_];
610 }
611
av_video_stream()612 AVStream* FakeMediaSource::av_video_stream() {
613 return av_format_context_->streams[video_stream_index_];
614 }
615
616 } // namespace cast
617 } // namespace media
618