OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cast/test/fake_media_source.h" | 5 #include "media/cast/test/fake_media_source.h" |
6 | 6 |
7 #include "base/files/memory_mapped_file.h" | 7 #include "base/files/memory_mapped_file.h" |
8 #include "base/files/scoped_file.h" | 8 #include "base/files/scoped_file.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/rand_util.h" | 10 #include "base/rand_util.h" |
11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
12 #include "media/audio/audio_parameters.h" | 12 #include "media/audio/audio_parameters.h" |
13 #include "media/base/audio_buffer.h" | 13 #include "media/base/audio_buffer.h" |
14 #include "media/base/audio_bus.h" | 14 #include "media/base/audio_bus.h" |
15 #include "media/base/audio_fifo.h" | 15 #include "media/base/audio_fifo.h" |
16 #include "media/base/audio_timestamp_helper.h" | 16 #include "media/base/audio_timestamp_helper.h" |
17 #include "media/base/media.h" | 17 #include "media/base/media.h" |
18 #include "media/base/multi_channel_resampler.h" | |
19 #include "media/base/video_frame.h" | 18 #include "media/base/video_frame.h" |
20 #include "media/base/video_util.h" | 19 #include "media/base/video_util.h" |
21 #include "media/cast/cast_sender.h" | 20 #include "media/cast/cast_sender.h" |
22 #include "media/cast/test/utility/audio_utility.h" | 21 #include "media/cast/test/utility/audio_utility.h" |
23 #include "media/cast/test/utility/video_utility.h" | 22 #include "media/cast/test/utility/video_utility.h" |
24 #include "media/ffmpeg/ffmpeg_common.h" | 23 #include "media/ffmpeg/ffmpeg_common.h" |
25 #include "media/ffmpeg/ffmpeg_deleters.h" | 24 #include "media/ffmpeg/ffmpeg_deleters.h" |
26 #include "media/filters/audio_renderer_algorithm.h" | 25 #include "media/filters/audio_renderer_algorithm.h" |
27 #include "media/filters/ffmpeg_demuxer.h" | 26 #include "media/filters/ffmpeg_demuxer.h" |
28 #include "media/filters/ffmpeg_glue.h" | 27 #include "media/filters/ffmpeg_glue.h" |
29 #include "media/filters/in_memory_url_protocol.h" | 28 #include "media/filters/in_memory_url_protocol.h" |
30 #include "ui/gfx/geometry/size.h" | 29 #include "ui/gfx/geometry/size.h" |
31 | 30 |
32 namespace { | 31 namespace { |
33 | 32 |
34 static const int kAudioChannels = 2; | |
35 static const int kAudioSamplingFrequency = 48000; | |
36 static const int kSoundFrequency = 440; // Frequency of sinusoid wave. | 33 static const int kSoundFrequency = 440; // Frequency of sinusoid wave. |
37 static const float kSoundVolume = 0.10f; | 34 static const float kSoundVolume = 0.10f; |
38 static const int kAudioFrameMs = 10; // Each audio frame is exactly 10ms. | 35 static const int kAudioFrameMs = 10; // Each audio frame is exactly 10ms. |
39 static const int kAudioPacketsPerSecond = 1000 / kAudioFrameMs; | 36 static const int kAudioPacketsPerSecond = 1000 / kAudioFrameMs; |
40 | 37 |
41 // Bounds for variable frame size mode. | 38 // Bounds for variable frame size mode. |
42 static const int kMinFakeFrameWidth = 60; | 39 static const int kMinFakeFrameWidth = 60; |
43 static const int kMinFakeFrameHeight = 34; | 40 static const int kMinFakeFrameHeight = 34; |
44 static const int kStartingFakeFrameWidth = 854; | 41 static const int kStartingFakeFrameWidth = 854; |
45 static const int kStartingFakeFrameHeight = 480; | 42 static const int kStartingFakeFrameHeight = 480; |
(...skipping 16 matching lines...) Expand all Loading... |
62 } | 59 } |
63 | 60 |
64 } // namespace | 61 } // namespace |
65 | 62 |
66 namespace media { | 63 namespace media { |
67 namespace cast { | 64 namespace cast { |
68 | 65 |
69 FakeMediaSource::FakeMediaSource( | 66 FakeMediaSource::FakeMediaSource( |
70 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | 67 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
71 base::TickClock* clock, | 68 base::TickClock* clock, |
| 69 const AudioSenderConfig& audio_config, |
72 const VideoSenderConfig& video_config, | 70 const VideoSenderConfig& video_config, |
73 bool keep_frames) | 71 bool keep_frames) |
74 : task_runner_(task_runner), | 72 : task_runner_(task_runner), |
| 73 output_audio_params_(AudioParameters::AUDIO_PCM_LINEAR, |
| 74 media::GuessChannelLayout(audio_config.channels), |
| 75 audio_config.frequency, |
| 76 32, |
| 77 audio_config.frequency / kAudioPacketsPerSecond), |
75 video_config_(video_config), | 78 video_config_(video_config), |
76 keep_frames_(keep_frames), | 79 keep_frames_(keep_frames), |
77 variable_frame_size_mode_(false), | 80 variable_frame_size_mode_(false), |
78 synthetic_count_(0), | 81 synthetic_count_(0), |
79 clock_(clock), | 82 clock_(clock), |
80 audio_frame_count_(0), | 83 audio_frame_count_(0), |
81 video_frame_count_(0), | 84 video_frame_count_(0), |
82 av_format_context_(NULL), | 85 av_format_context_(NULL), |
83 audio_stream_index_(-1), | 86 audio_stream_index_(-1), |
84 playback_rate_(1.0), | 87 playback_rate_(1.0), |
85 video_stream_index_(-1), | 88 video_stream_index_(-1), |
86 video_frame_rate_numerator_(video_config.max_frame_rate), | 89 video_frame_rate_numerator_(video_config.max_frame_rate), |
87 video_frame_rate_denominator_(1), | 90 video_frame_rate_denominator_(1), |
88 video_first_pts_(0), | 91 video_first_pts_(0), |
89 video_first_pts_set_(false), | 92 video_first_pts_set_(false), |
90 weak_factory_(this) { | 93 weak_factory_(this) { |
91 audio_bus_factory_.reset(new TestAudioBusFactory(kAudioChannels, | 94 CHECK(output_audio_params_.IsValid()); |
92 kAudioSamplingFrequency, | 95 audio_bus_factory_.reset(new TestAudioBusFactory(audio_config.channels, |
| 96 audio_config.frequency, |
93 kSoundFrequency, | 97 kSoundFrequency, |
94 kSoundVolume)); | 98 kSoundVolume)); |
95 } | 99 } |
96 | 100 |
97 FakeMediaSource::~FakeMediaSource() { | 101 FakeMediaSource::~FakeMediaSource() { |
98 } | 102 } |
99 | 103 |
100 void FakeMediaSource::SetSourceFile(const base::FilePath& video_file, | 104 void FakeMediaSource::SetSourceFile(const base::FilePath& video_file, |
101 int override_fps) { | 105 int override_fps) { |
102 DCHECK(!video_file.empty()); | 106 DCHECK(!video_file.empty()); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 av_codec_context->channel_layout, | 158 av_codec_context->channel_layout, |
155 av_codec_context->channels); | 159 av_codec_context->channels); |
156 if (layout == CHANNEL_LAYOUT_UNSUPPORTED) { | 160 if (layout == CHANNEL_LAYOUT_UNSUPPORTED) { |
157 LOG(ERROR) << "Unsupported audio channels layout."; | 161 LOG(ERROR) << "Unsupported audio channels layout."; |
158 continue; | 162 continue; |
159 } | 163 } |
160 if (audio_stream_index_ != -1) { | 164 if (audio_stream_index_ != -1) { |
161 LOG(WARNING) << "Found multiple audio streams."; | 165 LOG(WARNING) << "Found multiple audio streams."; |
162 } | 166 } |
163 audio_stream_index_ = static_cast<int>(i); | 167 audio_stream_index_ = static_cast<int>(i); |
164 audio_params_.Reset( | 168 source_audio_params_.Reset( |
165 AudioParameters::AUDIO_PCM_LINEAR, | 169 AudioParameters::AUDIO_PCM_LINEAR, |
166 layout, | 170 layout, |
167 av_codec_context->channels, | 171 av_codec_context->channels, |
168 av_codec_context->sample_rate, | 172 av_codec_context->sample_rate, |
169 8 * av_get_bytes_per_sample(av_codec_context->sample_fmt), | 173 8 * av_get_bytes_per_sample(av_codec_context->sample_fmt), |
170 av_codec_context->sample_rate / kAudioPacketsPerSecond); | 174 av_codec_context->sample_rate / kAudioPacketsPerSecond); |
| 175 CHECK(source_audio_params_.IsValid()); |
171 LOG(INFO) << "Source file has audio."; | 176 LOG(INFO) << "Source file has audio."; |
172 } else if (av_codec->type == AVMEDIA_TYPE_VIDEO) { | 177 } else if (av_codec->type == AVMEDIA_TYPE_VIDEO) { |
173 VideoFrame::Format format = | 178 VideoFrame::Format format = |
174 PixelFormatToVideoFormat(av_codec_context->pix_fmt); | 179 PixelFormatToVideoFormat(av_codec_context->pix_fmt); |
175 if (format != VideoFrame::YV12) { | 180 if (format != VideoFrame::YV12) { |
176 LOG(ERROR) << "Cannot handle non YV12 video format: " << format; | 181 LOG(ERROR) << "Cannot handle non YV12 video format: " << format; |
177 continue; | 182 continue; |
178 } | 183 } |
179 if (video_stream_index_ != -1) { | 184 if (video_stream_index_ != -1) { |
180 LOG(WARNING) << "Found multiple video streams."; | 185 LOG(WARNING) << "Found multiple video streams."; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 if (!is_transcoding_audio() && !is_transcoding_video()) { | 226 if (!is_transcoding_audio() && !is_transcoding_video()) { |
222 // Send fake patterns. | 227 // Send fake patterns. |
223 task_runner_->PostTask( | 228 task_runner_->PostTask( |
224 FROM_HERE, | 229 FROM_HERE, |
225 base::Bind(&FakeMediaSource::SendNextFakeFrame, | 230 base::Bind(&FakeMediaSource::SendNextFakeFrame, |
226 weak_factory_.GetWeakPtr())); | 231 weak_factory_.GetWeakPtr())); |
227 return; | 232 return; |
228 } | 233 } |
229 | 234 |
230 // Send transcoding streams. | 235 // Send transcoding streams. |
231 audio_algo_.Initialize(audio_params_); | 236 audio_algo_.Initialize(source_audio_params_); |
232 audio_algo_.FlushBuffers(); | 237 audio_algo_.FlushBuffers(); |
233 audio_fifo_input_bus_ = | 238 audio_fifo_input_bus_ = AudioBus::Create( |
234 AudioBus::Create( | 239 source_audio_params_.channels(), |
235 audio_params_.channels(), audio_params_.frames_per_buffer()); | 240 source_audio_params_.frames_per_buffer()); |
236 // Audio FIFO can carry all data fron AudioRendererAlgorithm. | 241 // Audio FIFO can carry all data fron AudioRendererAlgorithm. |
237 audio_fifo_.reset( | 242 audio_fifo_.reset( |
238 new AudioFifo(audio_params_.channels(), | 243 new AudioFifo(source_audio_params_.channels(), |
239 audio_algo_.QueueCapacity())); | 244 audio_algo_.QueueCapacity())); |
240 audio_resampler_.reset(new media::MultiChannelResampler( | 245 audio_converter_.reset(new media::AudioConverter( |
241 audio_params_.channels(), | 246 source_audio_params_, output_audio_params_, true)); |
242 static_cast<double>(audio_params_.sample_rate()) / | 247 audio_converter_->AddInput(this); |
243 kAudioSamplingFrequency, | |
244 audio_params_.frames_per_buffer(), | |
245 base::Bind(&FakeMediaSource::ProvideData, weak_factory_.GetWeakPtr()))); | |
246 task_runner_->PostTask( | 248 task_runner_->PostTask( |
247 FROM_HERE, | 249 FROM_HERE, |
248 base::Bind(&FakeMediaSource::SendNextFrame, weak_factory_.GetWeakPtr())); | 250 base::Bind(&FakeMediaSource::SendNextFrame, weak_factory_.GetWeakPtr())); |
249 } | 251 } |
250 | 252 |
251 void FakeMediaSource::SendNextFakeFrame() { | 253 void FakeMediaSource::SendNextFakeFrame() { |
252 UpdateNextFrameSize(); | 254 UpdateNextFrameSize(); |
253 scoped_refptr<VideoFrame> video_frame = | 255 scoped_refptr<VideoFrame> video_frame = |
254 VideoFrame::CreateBlackFrame(current_frame_size_); | 256 VideoFrame::CreateBlackFrame(current_frame_size_); |
255 PopulateVideoFrame(video_frame.get(), synthetic_count_); | 257 PopulateVideoFrame(video_frame.get(), synthetic_count_); |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 int frames_read = avframe->nb_samples; | 457 int frames_read = avframe->nb_samples; |
456 if (frames_read < 0) | 458 if (frames_read < 0) |
457 break; | 459 break; |
458 | 460 |
459 if (!audio_sent_ts_) { | 461 if (!audio_sent_ts_) { |
460 // Initialize the base time to the first packet in the file. | 462 // Initialize the base time to the first packet in the file. |
461 // This is set to the frequency we send to the receiver. | 463 // This is set to the frequency we send to the receiver. |
462 // Not the frequency of the source file. This is because we | 464 // Not the frequency of the source file. This is because we |
463 // increment the frame count by samples we sent. | 465 // increment the frame count by samples we sent. |
464 audio_sent_ts_.reset( | 466 audio_sent_ts_.reset( |
465 new AudioTimestampHelper(kAudioSamplingFrequency)); | 467 new AudioTimestampHelper(output_audio_params_.sample_rate())); |
466 // For some files this is an invalid value. | 468 // For some files this is an invalid value. |
467 base::TimeDelta base_ts; | 469 base::TimeDelta base_ts; |
468 audio_sent_ts_->SetBaseTimestamp(base_ts); | 470 audio_sent_ts_->SetBaseTimestamp(base_ts); |
469 } | 471 } |
470 | 472 |
471 scoped_refptr<AudioBuffer> buffer = | 473 scoped_refptr<AudioBuffer> buffer = |
472 AudioBuffer::CopyFrom( | 474 AudioBuffer::CopyFrom( |
473 AVSampleFormatToSampleFormat( | 475 AVSampleFormatToSampleFormat( |
474 av_audio_context()->sample_fmt), | 476 av_audio_context()->sample_fmt), |
475 ChannelLayoutToChromeChannelLayout( | 477 ChannelLayoutToChromeChannelLayout( |
(...skipping 23 matching lines...) Expand all Loading... |
499 // Prevent overflow of audio data in the FIFO. | 501 // Prevent overflow of audio data in the FIFO. |
500 if (audio_fifo_input_bus_->frames() + audio_fifo_->frames() | 502 if (audio_fifo_input_bus_->frames() + audio_fifo_->frames() |
501 <= audio_fifo_->max_frames()) { | 503 <= audio_fifo_->max_frames()) { |
502 audio_fifo_->Push(audio_fifo_input_bus_.get()); | 504 audio_fifo_->Push(audio_fifo_input_bus_.get()); |
503 } else { | 505 } else { |
504 LOG(WARNING) << "Audio FIFO full; dropping samples."; | 506 LOG(WARNING) << "Audio FIFO full; dropping samples."; |
505 } | 507 } |
506 | 508 |
507 // Make sure there's enough data to resample audio. | 509 // Make sure there's enough data to resample audio. |
508 if (audio_fifo_->frames() < | 510 if (audio_fifo_->frames() < |
509 2 * audio_params_.sample_rate() / kAudioPacketsPerSecond) { | 511 2 * source_audio_params_.sample_rate() / kAudioPacketsPerSecond) { |
510 continue; | 512 continue; |
511 } | 513 } |
512 | 514 |
513 scoped_ptr<media::AudioBus> resampled_bus( | 515 scoped_ptr<media::AudioBus> resampled_bus( |
514 media::AudioBus::Create( | 516 media::AudioBus::Create( |
515 audio_params_.channels(), | 517 output_audio_params_.channels(), |
516 kAudioSamplingFrequency / kAudioPacketsPerSecond)); | 518 output_audio_params_.sample_rate() / kAudioPacketsPerSecond)); |
517 audio_resampler_->Resample(resampled_bus->frames(), | 519 audio_converter_->Convert(resampled_bus.get()); |
518 resampled_bus.get()); | |
519 audio_bus_queue_.push(resampled_bus.release()); | 520 audio_bus_queue_.push(resampled_bus.release()); |
520 } | 521 } |
521 } | 522 } |
522 | 523 |
523 void FakeMediaSource::DecodeVideo(ScopedAVPacket packet) { | 524 void FakeMediaSource::DecodeVideo(ScopedAVPacket packet) { |
524 // Video. | 525 // Video. |
525 int got_picture; | 526 int got_picture; |
526 AVFrame* avframe = av_frame_alloc(); | 527 AVFrame* avframe = av_frame_alloc(); |
527 CHECK(avcodec_decode_video2( | 528 CHECK(avcodec_decode_video2( |
528 av_video_context(), avframe, &got_picture, packet.get()) >= 0) | 529 av_video_context(), avframe, &got_picture, packet.get()) >= 0) |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 return; | 582 return; |
582 } | 583 } |
583 | 584 |
584 if (audio_packet) | 585 if (audio_packet) |
585 DecodeAudio(packet.Pass()); | 586 DecodeAudio(packet.Pass()); |
586 else | 587 else |
587 DecodeVideo(packet.Pass()); | 588 DecodeVideo(packet.Pass()); |
588 } | 589 } |
589 } | 590 } |
590 | 591 |
591 void FakeMediaSource::ProvideData(int frame_delay, | 592 double FakeMediaSource::ProvideInput(media::AudioBus* output_bus, |
592 media::AudioBus* output_bus) { | 593 base::TimeDelta buffer_delay) { |
593 if (audio_fifo_->frames() >= output_bus->frames()) { | 594 if (audio_fifo_->frames() >= output_bus->frames()) { |
594 audio_fifo_->Consume(output_bus, 0, output_bus->frames()); | 595 audio_fifo_->Consume(output_bus, 0, output_bus->frames()); |
| 596 return 1.0; |
595 } else { | 597 } else { |
596 LOG(WARNING) << "Not enough audio data for resampling."; | 598 LOG(WARNING) << "Not enough audio data for resampling."; |
597 output_bus->Zero(); | 599 output_bus->Zero(); |
| 600 return 0.0; |
598 } | 601 } |
599 } | 602 } |
600 | 603 |
601 scoped_refptr<media::VideoFrame> | 604 scoped_refptr<media::VideoFrame> |
602 FakeMediaSource::PopOldestInsertedVideoFrame() { | 605 FakeMediaSource::PopOldestInsertedVideoFrame() { |
603 CHECK(!inserted_video_frame_queue_.empty()); | 606 CHECK(!inserted_video_frame_queue_.empty()); |
604 scoped_refptr<media::VideoFrame> video_frame = | 607 scoped_refptr<media::VideoFrame> video_frame = |
605 inserted_video_frame_queue_.front(); | 608 inserted_video_frame_queue_.front(); |
606 inserted_video_frame_queue_.pop(); | 609 inserted_video_frame_queue_.pop(); |
607 return video_frame; | 610 return video_frame; |
(...skipping 10 matching lines...) Expand all Loading... |
618 AVCodecContext* FakeMediaSource::av_audio_context() { | 621 AVCodecContext* FakeMediaSource::av_audio_context() { |
619 return av_audio_stream()->codec; | 622 return av_audio_stream()->codec; |
620 } | 623 } |
621 | 624 |
622 AVCodecContext* FakeMediaSource::av_video_context() { | 625 AVCodecContext* FakeMediaSource::av_video_context() { |
623 return av_video_stream()->codec; | 626 return av_video_stream()->codec; |
624 } | 627 } |
625 | 628 |
626 } // namespace cast | 629 } // namespace cast |
627 } // namespace media | 630 } // namespace media |
OLD | NEW |