Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / cast / test / fake_media_source.cc
blobea42a3a84762dc64aafa7fc87b018a5c88706fa9
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.
5 #include "media/cast/test/fake_media_source.h"
7 #include "base/bind.h"
8 #include "base/files/scoped_file.h"
9 #include "base/logging.h"
10 #include "base/rand_util.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "media/base/audio_buffer.h"
13 #include "media/base/audio_bus.h"
14 #include "media/base/audio_fifo.h"
15 #include "media/base/audio_timestamp_helper.h"
16 #include "media/base/media.h"
17 #include "media/base/video_frame.h"
18 #include "media/base/video_util.h"
19 #include "media/cast/cast_sender.h"
20 #include "media/cast/test/utility/audio_utility.h"
21 #include "media/cast/test/utility/video_utility.h"
22 #include "media/ffmpeg/ffmpeg_common.h"
23 #include "media/ffmpeg/ffmpeg_deleters.h"
24 #include "media/filters/ffmpeg_glue.h"
25 #include "media/filters/in_memory_url_protocol.h"
26 #include "ui/gfx/geometry/size.h"
28 namespace {
30 static const int kSoundFrequency = 440; // Frequency of sinusoid wave.
31 static const float kSoundVolume = 0.10f;
32 static const int kAudioFrameMs = 10; // Each audio frame is exactly 10ms.
33 static const int kAudioPacketsPerSecond = 1000 / kAudioFrameMs;
35 // Bounds for variable frame size mode.
36 static const int kMinFakeFrameWidth = 60;
37 static const int kMinFakeFrameHeight = 34;
38 static const int kStartingFakeFrameWidth = 854;
39 static const int kStartingFakeFrameHeight = 480;
40 static const int kMaxFakeFrameWidth = 1280;
41 static const int kMaxFakeFrameHeight = 720;
42 static const int kMaxFrameSizeChangeMillis = 5000;
44 void AVFreeFrame(AVFrame* frame) {
45 av_frame_free(&frame);
48 base::TimeDelta PtsToTimeDelta(int64 pts, const AVRational& time_base) {
49 return pts * base::TimeDelta::FromSeconds(1) * time_base.num / time_base.den;
52 int64 TimeDeltaToPts(base::TimeDelta delta, const AVRational& time_base) {
53 return static_cast<int64>(
54 delta.InSecondsF() * time_base.den / time_base.num +
55 0.5 /* rounding */);
58 } // namespace
60 namespace media {
61 namespace cast {
63 FakeMediaSource::FakeMediaSource(
64 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
65 base::TickClock* clock,
66 const AudioSenderConfig& audio_config,
67 const VideoSenderConfig& video_config,
68 bool keep_frames)
69 : task_runner_(task_runner),
70 output_audio_params_(AudioParameters::AUDIO_PCM_LINEAR,
71 media::GuessChannelLayout(audio_config.channels),
72 audio_config.frequency,
73 32,
74 audio_config.frequency / kAudioPacketsPerSecond),
75 video_config_(video_config),
76 keep_frames_(keep_frames),
77 variable_frame_size_mode_(false),
78 synthetic_count_(0),
79 clock_(clock),
80 audio_frame_count_(0),
81 video_frame_count_(0),
82 av_format_context_(NULL),
83 audio_stream_index_(-1),
84 playback_rate_(1.0),
85 video_stream_index_(-1),
86 video_frame_rate_numerator_(video_config.max_frame_rate),
87 video_frame_rate_denominator_(1),
88 video_first_pts_(0),
89 video_first_pts_set_(false),
90 weak_factory_(this) {
91 CHECK(output_audio_params_.IsValid());
92 audio_bus_factory_.reset(new TestAudioBusFactory(audio_config.channels,
93 audio_config.frequency,
94 kSoundFrequency,
95 kSoundVolume));
98 FakeMediaSource::~FakeMediaSource() {
101 void FakeMediaSource::SetSourceFile(const base::FilePath& video_file,
102 int final_fps) {
103 DCHECK(!video_file.empty());
105 LOG(INFO) << "Source: " << video_file.value();
106 if (!file_data_.Initialize(video_file)) {
107 LOG(ERROR) << "Cannot load file.";
108 return;
110 protocol_.reset(
111 new InMemoryUrlProtocol(file_data_.data(), file_data_.length(), false));
112 glue_.reset(new FFmpegGlue(protocol_.get()));
114 if (!glue_->OpenContext()) {
115 LOG(ERROR) << "Cannot open file.";
116 return;
119 // AVFormatContext is owned by the glue.
120 av_format_context_ = glue_->format_context();
121 if (avformat_find_stream_info(av_format_context_, NULL) < 0) {
122 LOG(ERROR) << "Cannot find stream information.";
123 return;
126 // Prepare FFmpeg decoders.
127 for (unsigned int i = 0; i < av_format_context_->nb_streams; ++i) {
128 AVStream* av_stream = av_format_context_->streams[i];
129 AVCodecContext* av_codec_context = av_stream->codec;
130 AVCodec* av_codec = avcodec_find_decoder(av_codec_context->codec_id);
132 if (!av_codec) {
133 LOG(ERROR) << "Cannot find decoder for the codec: "
134 << av_codec_context->codec_id;
135 continue;
138 // Number of threads for decoding.
139 av_codec_context->thread_count = 2;
140 av_codec_context->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
141 av_codec_context->request_sample_fmt = AV_SAMPLE_FMT_S16;
143 if (avcodec_open2(av_codec_context, av_codec, NULL) < 0) {
144 LOG(ERROR) << "Cannot open AVCodecContext for the codec: "
145 << av_codec_context->codec_id;
146 return;
149 if (av_codec->type == AVMEDIA_TYPE_AUDIO) {
150 if (av_codec_context->sample_fmt == AV_SAMPLE_FMT_S16P) {
151 LOG(ERROR) << "Audio format not supported.";
152 continue;
154 ChannelLayout layout = ChannelLayoutToChromeChannelLayout(
155 av_codec_context->channel_layout,
156 av_codec_context->channels);
157 if (layout == CHANNEL_LAYOUT_UNSUPPORTED) {
158 LOG(ERROR) << "Unsupported audio channels layout.";
159 continue;
161 if (audio_stream_index_ != -1) {
162 LOG(WARNING) << "Found multiple audio streams.";
164 audio_stream_index_ = static_cast<int>(i);
165 source_audio_params_.Reset(
166 AudioParameters::AUDIO_PCM_LINEAR,
167 layout,
168 av_codec_context->channels,
169 av_codec_context->sample_rate,
170 8 * av_get_bytes_per_sample(av_codec_context->sample_fmt),
171 av_codec_context->sample_rate / kAudioPacketsPerSecond);
172 CHECK(source_audio_params_.IsValid());
173 LOG(INFO) << "Source file has audio.";
174 } else if (av_codec->type == AVMEDIA_TYPE_VIDEO) {
175 VideoPixelFormat format =
176 PixelFormatToVideoPixelFormat(av_codec_context->pix_fmt);
177 if (format != PIXEL_FORMAT_YV12) {
178 LOG(ERROR) << "Cannot handle non YV12 video format: " << format;
179 continue;
181 if (video_stream_index_ != -1) {
182 LOG(WARNING) << "Found multiple video streams.";
184 video_stream_index_ = static_cast<int>(i);
185 if (final_fps > 0) {
186 // If video is played at a manual speed audio needs to match.
187 playback_rate_ = 1.0 * final_fps *
188 av_stream->r_frame_rate.den / av_stream->r_frame_rate.num;
189 video_frame_rate_numerator_ = final_fps;
190 video_frame_rate_denominator_ = 1;
191 } else {
192 playback_rate_ = 1.0;
193 video_frame_rate_numerator_ = av_stream->r_frame_rate.num;
194 video_frame_rate_denominator_ = av_stream->r_frame_rate.den;
196 LOG(INFO) << "Source file has video.";
197 } else {
198 LOG(ERROR) << "Unknown stream type; ignore.";
202 Rewind();
205 void FakeMediaSource::SetVariableFrameSizeMode(bool enabled) {
206 variable_frame_size_mode_ = enabled;
209 void FakeMediaSource::Start(scoped_refptr<AudioFrameInput> audio_frame_input,
210 scoped_refptr<VideoFrameInput> video_frame_input) {
211 audio_frame_input_ = audio_frame_input;
212 video_frame_input_ = video_frame_input;
214 LOG(INFO) << "Max Frame rate: " << video_config_.max_frame_rate;
215 LOG(INFO) << "Source Frame rate: "
216 << video_frame_rate_numerator_ << "/"
217 << video_frame_rate_denominator_ << " fps.";
218 LOG(INFO) << "Audio playback rate: " << playback_rate_;
220 if (start_time_.is_null())
221 start_time_ = clock_->NowTicks();
223 if (!is_transcoding_audio() && !is_transcoding_video()) {
224 // Send fake patterns.
225 task_runner_->PostTask(
226 FROM_HERE,
227 base::Bind(&FakeMediaSource::SendNextFakeFrame,
228 weak_factory_.GetWeakPtr()));
229 return;
232 // Send transcoding streams.
233 audio_algo_.Initialize(source_audio_params_);
234 audio_algo_.FlushBuffers();
235 audio_fifo_input_bus_ = AudioBus::Create(
236 source_audio_params_.channels(),
237 source_audio_params_.frames_per_buffer());
238 // Audio FIFO can carry all data fron AudioRendererAlgorithm.
239 audio_fifo_.reset(
240 new AudioFifo(source_audio_params_.channels(),
241 audio_algo_.QueueCapacity()));
242 audio_converter_.reset(new media::AudioConverter(
243 source_audio_params_, output_audio_params_, true));
244 audio_converter_->AddInput(this);
245 task_runner_->PostTask(
246 FROM_HERE,
247 base::Bind(&FakeMediaSource::SendNextFrame, weak_factory_.GetWeakPtr()));
250 void FakeMediaSource::SendNextFakeFrame() {
251 UpdateNextFrameSize();
252 scoped_refptr<VideoFrame> video_frame =
253 VideoFrame::CreateBlackFrame(current_frame_size_);
254 PopulateVideoFrame(video_frame.get(), synthetic_count_);
255 ++synthetic_count_;
257 const base::TimeTicks now = clock_->NowTicks();
259 base::TimeDelta video_time = VideoFrameTime(++video_frame_count_);
260 video_frame->set_timestamp(video_time);
261 if (keep_frames_)
262 inserted_video_frame_queue_.push(video_frame);
263 video_frame_input_->InsertRawVideoFrame(video_frame,
264 start_time_ + video_time);
266 // Send just enough audio data to match next video frame's time.
267 base::TimeDelta audio_time = AudioFrameTime(audio_frame_count_);
268 while (audio_time < video_time) {
269 if (is_transcoding_audio()) {
270 Decode(true);
271 CHECK(!audio_bus_queue_.empty()) << "No audio decoded.";
272 scoped_ptr<AudioBus> bus(audio_bus_queue_.front());
273 audio_bus_queue_.pop();
274 audio_frame_input_->InsertAudio(
275 bus.Pass(), start_time_ + audio_time);
276 } else {
277 audio_frame_input_->InsertAudio(
278 audio_bus_factory_->NextAudioBus(
279 base::TimeDelta::FromMilliseconds(kAudioFrameMs)),
280 start_time_ + audio_time);
282 audio_time = AudioFrameTime(++audio_frame_count_);
285 // This is the time since FakeMediaSource was started.
286 const base::TimeDelta elapsed_time = now - start_time_;
288 // Handle the case when frame generation cannot keep up.
289 // Move the time ahead to match the next frame.
290 while (video_time < elapsed_time) {
291 LOG(WARNING) << "Skipping one frame.";
292 video_time = VideoFrameTime(++video_frame_count_);
295 task_runner_->PostDelayedTask(
296 FROM_HERE,
297 base::Bind(&FakeMediaSource::SendNextFakeFrame,
298 weak_factory_.GetWeakPtr()),
299 video_time - elapsed_time);
302 void FakeMediaSource::UpdateNextFrameSize() {
303 if (variable_frame_size_mode_) {
304 bool update_size_change_time = false;
305 if (current_frame_size_.IsEmpty()) {
306 current_frame_size_ = gfx::Size(kStartingFakeFrameWidth,
307 kStartingFakeFrameHeight);
308 update_size_change_time = true;
309 } else if (clock_->NowTicks() >= next_frame_size_change_time_) {
310 current_frame_size_ = gfx::Size(
311 base::RandInt(kMinFakeFrameWidth, kMaxFakeFrameWidth),
312 base::RandInt(kMinFakeFrameHeight, kMaxFakeFrameHeight));
313 update_size_change_time = true;
316 if (update_size_change_time) {
317 next_frame_size_change_time_ = clock_->NowTicks() +
318 base::TimeDelta::FromMillisecondsD(
319 base::RandDouble() * kMaxFrameSizeChangeMillis);
321 } else {
322 current_frame_size_ = gfx::Size(kStartingFakeFrameWidth,
323 kStartingFakeFrameHeight);
324 next_frame_size_change_time_ = base::TimeTicks();
328 bool FakeMediaSource::SendNextTranscodedVideo(base::TimeDelta elapsed_time) {
329 if (!is_transcoding_video())
330 return false;
332 Decode(false);
333 if (video_frame_queue_.empty())
334 return false;
336 const scoped_refptr<VideoFrame> video_frame = video_frame_queue_.front();
337 if (elapsed_time < video_frame->timestamp())
338 return false;
339 video_frame_queue_.pop();
341 // Use the timestamp from the file if we're transcoding.
342 video_frame->set_timestamp(ScaleTimestamp(video_frame->timestamp()));
343 if (keep_frames_)
344 inserted_video_frame_queue_.push(video_frame);
345 video_frame_input_->InsertRawVideoFrame(
346 video_frame, start_time_ + video_frame->timestamp());
348 // Make sure queue is not empty.
349 Decode(false);
350 return true;
353 bool FakeMediaSource::SendNextTranscodedAudio(base::TimeDelta elapsed_time) {
354 if (!is_transcoding_audio())
355 return false;
357 Decode(true);
358 if (audio_bus_queue_.empty())
359 return false;
361 base::TimeDelta audio_time = audio_sent_ts_->GetTimestamp();
362 if (elapsed_time < audio_time)
363 return false;
364 scoped_ptr<AudioBus> bus(audio_bus_queue_.front());
365 audio_bus_queue_.pop();
366 audio_sent_ts_->AddFrames(bus->frames());
367 audio_frame_input_->InsertAudio(
368 bus.Pass(), start_time_ + audio_time);
370 // Make sure queue is not empty.
371 Decode(true);
372 return true;
375 void FakeMediaSource::SendNextFrame() {
376 // Send as much as possible. Audio is sent according to
377 // system time.
378 while (SendNextTranscodedAudio(clock_->NowTicks() - start_time_));
380 // Video is sync'ed to audio.
381 while (SendNextTranscodedVideo(audio_sent_ts_->GetTimestamp()));
383 if (audio_bus_queue_.empty() && video_frame_queue_.empty()) {
384 // Both queues are empty can only mean that we have reached
385 // the end of the stream.
386 LOG(INFO) << "Rewind.";
387 Rewind();
390 // Send next send.
391 task_runner_->PostDelayedTask(
392 FROM_HERE,
393 base::Bind(&FakeMediaSource::SendNextFrame, weak_factory_.GetWeakPtr()),
394 base::TimeDelta::FromMilliseconds(kAudioFrameMs));
397 base::TimeDelta FakeMediaSource::VideoFrameTime(int frame_number) {
398 return frame_number * base::TimeDelta::FromSeconds(1) *
399 video_frame_rate_denominator_ / video_frame_rate_numerator_;
402 base::TimeDelta FakeMediaSource::ScaleTimestamp(base::TimeDelta timestamp) {
403 return base::TimeDelta::FromSecondsD(timestamp.InSecondsF() / playback_rate_);
406 base::TimeDelta FakeMediaSource::AudioFrameTime(int frame_number) {
407 return frame_number * base::TimeDelta::FromMilliseconds(kAudioFrameMs);
410 void FakeMediaSource::Rewind() {
411 CHECK(av_seek_frame(av_format_context_, -1, 0, AVSEEK_FLAG_BACKWARD) >= 0)
412 << "Failed to rewind to the beginning.";
415 ScopedAVPacket FakeMediaSource::DemuxOnePacket(bool* audio) {
416 ScopedAVPacket packet(new AVPacket());
417 if (av_read_frame(av_format_context_, packet.get()) < 0) {
418 VLOG(1) << "Failed to read one AVPacket.";
419 packet.reset();
420 return packet.Pass();
423 int stream_index = static_cast<int>(packet->stream_index);
424 if (stream_index == audio_stream_index_) {
425 *audio = true;
426 } else if (stream_index == video_stream_index_) {
427 *audio = false;
428 } else {
429 // Ignore unknown packet.
430 LOG(INFO) << "Unknown packet.";
431 packet.reset();
433 return packet.Pass();
436 void FakeMediaSource::DecodeAudio(ScopedAVPacket packet) {
437 // Audio.
438 AVFrame* avframe = av_frame_alloc();
440 // Make a shallow copy of packet so we can slide packet.data as frames are
441 // decoded from the packet; otherwise av_free_packet() will corrupt memory.
442 AVPacket packet_temp = *packet.get();
444 do {
445 int frame_decoded = 0;
446 int result = avcodec_decode_audio4(
447 av_audio_context(), avframe, &frame_decoded, &packet_temp);
448 CHECK(result >= 0) << "Failed to decode audio.";
449 packet_temp.size -= result;
450 packet_temp.data += result;
451 if (!frame_decoded)
452 continue;
454 int frames_read = avframe->nb_samples;
455 if (frames_read < 0)
456 break;
458 if (!audio_sent_ts_) {
459 // Initialize the base time to the first packet in the file.
460 // This is set to the frequency we send to the receiver.
461 // Not the frequency of the source file. This is because we
462 // increment the frame count by samples we sent.
463 audio_sent_ts_.reset(
464 new AudioTimestampHelper(output_audio_params_.sample_rate()));
465 // For some files this is an invalid value.
466 base::TimeDelta base_ts;
467 audio_sent_ts_->SetBaseTimestamp(base_ts);
470 scoped_refptr<AudioBuffer> buffer =
471 AudioBuffer::CopyFrom(
472 AVSampleFormatToSampleFormat(
473 av_audio_context()->sample_fmt),
474 ChannelLayoutToChromeChannelLayout(
475 av_audio_context()->channel_layout,
476 av_audio_context()->channels),
477 av_audio_context()->channels,
478 av_audio_context()->sample_rate,
479 frames_read,
480 &avframe->data[0],
481 PtsToTimeDelta(avframe->pkt_pts, av_audio_stream()->time_base));
482 audio_algo_.EnqueueBuffer(buffer);
483 av_frame_unref(avframe);
484 } while (packet_temp.size > 0);
485 av_frame_free(&avframe);
487 const int frames_needed_to_scale =
488 playback_rate_ * av_audio_context()->sample_rate /
489 kAudioPacketsPerSecond;
490 while (frames_needed_to_scale <= audio_algo_.frames_buffered()) {
491 if (!audio_algo_.FillBuffer(audio_fifo_input_bus_.get(), 0,
492 audio_fifo_input_bus_->frames(),
493 playback_rate_)) {
494 // Nothing can be scaled. Decode some more.
495 return;
498 // Prevent overflow of audio data in the FIFO.
499 if (audio_fifo_input_bus_->frames() + audio_fifo_->frames()
500 <= audio_fifo_->max_frames()) {
501 audio_fifo_->Push(audio_fifo_input_bus_.get());
502 } else {
503 LOG(WARNING) << "Audio FIFO full; dropping samples.";
506 // Make sure there's enough data to resample audio.
507 if (audio_fifo_->frames() <
508 2 * source_audio_params_.sample_rate() / kAudioPacketsPerSecond) {
509 continue;
512 scoped_ptr<media::AudioBus> resampled_bus(
513 media::AudioBus::Create(
514 output_audio_params_.channels(),
515 output_audio_params_.sample_rate() / kAudioPacketsPerSecond));
516 audio_converter_->Convert(resampled_bus.get());
517 audio_bus_queue_.push(resampled_bus.release());
521 void FakeMediaSource::DecodeVideo(ScopedAVPacket packet) {
522 // Video.
523 int got_picture;
524 AVFrame* avframe = av_frame_alloc();
525 CHECK(avcodec_decode_video2(
526 av_video_context(), avframe, &got_picture, packet.get()) >= 0)
527 << "Video decode error.";
528 if (!got_picture) {
529 av_frame_free(&avframe);
530 return;
532 gfx::Size size(av_video_context()->width, av_video_context()->height);
534 if (!video_first_pts_set_) {
535 video_first_pts_ = avframe->pkt_pts;
536 video_first_pts_set_ = true;
538 const AVRational& time_base = av_video_stream()->time_base;
539 base::TimeDelta timestamp =
540 PtsToTimeDelta(avframe->pkt_pts - video_first_pts_, time_base);
541 if (timestamp < last_video_frame_timestamp_) {
542 // Stream has rewound. Rebase |video_first_pts_|.
543 const AVRational& frame_rate = av_video_stream()->r_frame_rate;
544 timestamp = last_video_frame_timestamp_ +
545 (base::TimeDelta::FromSeconds(1) * frame_rate.den / frame_rate.num);
546 const int64 adjustment_pts = TimeDeltaToPts(timestamp, time_base);
547 video_first_pts_ = avframe->pkt_pts - adjustment_pts;
550 video_frame_queue_.push(VideoFrame::WrapExternalYuvData(
551 media::PIXEL_FORMAT_YV12, size, gfx::Rect(size), size,
552 avframe->linesize[0], avframe->linesize[1], avframe->linesize[2],
553 avframe->data[0], avframe->data[1], avframe->data[2], timestamp));
554 video_frame_queue_.back()->AddDestructionObserver(
555 base::Bind(&AVFreeFrame, avframe));
556 last_video_frame_timestamp_ = timestamp;
559 void FakeMediaSource::Decode(bool decode_audio) {
560 // Read the stream until one video frame can be decoded.
561 while (true) {
562 if (decode_audio && !audio_bus_queue_.empty())
563 return;
564 if (!decode_audio && !video_frame_queue_.empty())
565 return;
567 bool audio_packet = false;
568 ScopedAVPacket packet = DemuxOnePacket(&audio_packet);
569 if (!packet) {
570 VLOG(1) << "End of stream.";
571 return;
574 if (audio_packet)
575 DecodeAudio(packet.Pass());
576 else
577 DecodeVideo(packet.Pass());
581 double FakeMediaSource::ProvideInput(media::AudioBus* output_bus,
582 base::TimeDelta buffer_delay) {
583 if (audio_fifo_->frames() >= output_bus->frames()) {
584 audio_fifo_->Consume(output_bus, 0, output_bus->frames());
585 return 1.0;
586 } else {
587 LOG(WARNING) << "Not enough audio data for resampling.";
588 output_bus->Zero();
589 return 0.0;
593 scoped_refptr<media::VideoFrame>
594 FakeMediaSource::PopOldestInsertedVideoFrame() {
595 CHECK(!inserted_video_frame_queue_.empty());
596 scoped_refptr<media::VideoFrame> video_frame =
597 inserted_video_frame_queue_.front();
598 inserted_video_frame_queue_.pop();
599 return video_frame;
602 AVStream* FakeMediaSource::av_audio_stream() {
603 return av_format_context_->streams[audio_stream_index_];
606 AVStream* FakeMediaSource::av_video_stream() {
607 return av_format_context_->streams[video_stream_index_];
610 AVCodecContext* FakeMediaSource::av_audio_context() {
611 return av_audio_stream()->codec;
614 AVCodecContext* FakeMediaSource::av_video_context() {
615 return av_video_stream()->codec;
618 } // namespace cast
619 } // namespace media