Commit 267652ed authored by miu's avatar miu Committed by Commit bot

[cast/test] Use AudioConverter in FakeMediaSource to play back 6-channel WEBM's.

Replaces the use of MultiChannelResampler with AudioConverter in
FakeMediaSource to allow the cast_sender_app and cast_simulator to
re-mix any-number-of-channels audio into the 2-channel audio for Cast
sending.

Review URL: https://codereview.chromium.org/900913004

Cr-Commit-Position: refs/heads/master@{#314680}
parent 1ea8a245
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "media/base/audio_fifo.h" #include "media/base/audio_fifo.h"
#include "media/base/audio_timestamp_helper.h" #include "media/base/audio_timestamp_helper.h"
#include "media/base/media.h" #include "media/base/media.h"
#include "media/base/multi_channel_resampler.h"
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
#include "media/base/video_util.h" #include "media/base/video_util.h"
#include "media/cast/cast_sender.h" #include "media/cast/cast_sender.h"
...@@ -31,8 +30,6 @@ ...@@ -31,8 +30,6 @@
namespace { namespace {
static const int kAudioChannels = 2;
static const int kAudioSamplingFrequency = 48000;
static const int kSoundFrequency = 440; // Frequency of sinusoid wave. static const int kSoundFrequency = 440; // Frequency of sinusoid wave.
static const float kSoundVolume = 0.10f; static const float kSoundVolume = 0.10f;
static const int kAudioFrameMs = 10; // Each audio frame is exactly 10ms. static const int kAudioFrameMs = 10; // Each audio frame is exactly 10ms.
...@@ -69,9 +66,15 @@ namespace cast { ...@@ -69,9 +66,15 @@ namespace cast {
FakeMediaSource::FakeMediaSource( FakeMediaSource::FakeMediaSource(
scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_refptr<base::SingleThreadTaskRunner> task_runner,
base::TickClock* clock, base::TickClock* clock,
const AudioSenderConfig& audio_config,
const VideoSenderConfig& video_config, const VideoSenderConfig& video_config,
bool keep_frames) bool keep_frames)
: task_runner_(task_runner), : task_runner_(task_runner),
output_audio_params_(AudioParameters::AUDIO_PCM_LINEAR,
media::GuessChannelLayout(audio_config.channels),
audio_config.frequency,
32,
audio_config.frequency / kAudioPacketsPerSecond),
video_config_(video_config), video_config_(video_config),
keep_frames_(keep_frames), keep_frames_(keep_frames),
variable_frame_size_mode_(false), variable_frame_size_mode_(false),
...@@ -88,8 +91,9 @@ FakeMediaSource::FakeMediaSource( ...@@ -88,8 +91,9 @@ FakeMediaSource::FakeMediaSource(
video_first_pts_(0), video_first_pts_(0),
video_first_pts_set_(false), video_first_pts_set_(false),
weak_factory_(this) { weak_factory_(this) {
audio_bus_factory_.reset(new TestAudioBusFactory(kAudioChannels, CHECK(output_audio_params_.IsValid());
kAudioSamplingFrequency, audio_bus_factory_.reset(new TestAudioBusFactory(audio_config.channels,
audio_config.frequency,
kSoundFrequency, kSoundFrequency,
kSoundVolume)); kSoundVolume));
} }
...@@ -161,13 +165,14 @@ void FakeMediaSource::SetSourceFile(const base::FilePath& video_file, ...@@ -161,13 +165,14 @@ void FakeMediaSource::SetSourceFile(const base::FilePath& video_file,
LOG(WARNING) << "Found multiple audio streams."; LOG(WARNING) << "Found multiple audio streams.";
} }
audio_stream_index_ = static_cast<int>(i); audio_stream_index_ = static_cast<int>(i);
audio_params_.Reset( source_audio_params_.Reset(
AudioParameters::AUDIO_PCM_LINEAR, AudioParameters::AUDIO_PCM_LINEAR,
layout, layout,
av_codec_context->channels, av_codec_context->channels,
av_codec_context->sample_rate, av_codec_context->sample_rate,
8 * av_get_bytes_per_sample(av_codec_context->sample_fmt), 8 * av_get_bytes_per_sample(av_codec_context->sample_fmt),
av_codec_context->sample_rate / kAudioPacketsPerSecond); av_codec_context->sample_rate / kAudioPacketsPerSecond);
CHECK(source_audio_params_.IsValid());
LOG(INFO) << "Source file has audio."; LOG(INFO) << "Source file has audio.";
} else if (av_codec->type == AVMEDIA_TYPE_VIDEO) { } else if (av_codec->type == AVMEDIA_TYPE_VIDEO) {
VideoFrame::Format format = VideoFrame::Format format =
...@@ -228,21 +233,18 @@ void FakeMediaSource::Start(scoped_refptr<AudioFrameInput> audio_frame_input, ...@@ -228,21 +233,18 @@ void FakeMediaSource::Start(scoped_refptr<AudioFrameInput> audio_frame_input,
} }
// Send transcoding streams. // Send transcoding streams.
audio_algo_.Initialize(audio_params_); audio_algo_.Initialize(source_audio_params_);
audio_algo_.FlushBuffers(); audio_algo_.FlushBuffers();
audio_fifo_input_bus_ = audio_fifo_input_bus_ = AudioBus::Create(
AudioBus::Create( source_audio_params_.channels(),
audio_params_.channels(), audio_params_.frames_per_buffer()); source_audio_params_.frames_per_buffer());
// Audio FIFO can carry all data fron AudioRendererAlgorithm. // Audio FIFO can carry all data fron AudioRendererAlgorithm.
audio_fifo_.reset( audio_fifo_.reset(
new AudioFifo(audio_params_.channels(), new AudioFifo(source_audio_params_.channels(),
audio_algo_.QueueCapacity())); audio_algo_.QueueCapacity()));
audio_resampler_.reset(new media::MultiChannelResampler( audio_converter_.reset(new media::AudioConverter(
audio_params_.channels(), source_audio_params_, output_audio_params_, true));
static_cast<double>(audio_params_.sample_rate()) / audio_converter_->AddInput(this);
kAudioSamplingFrequency,
audio_params_.frames_per_buffer(),
base::Bind(&FakeMediaSource::ProvideData, weak_factory_.GetWeakPtr())));
task_runner_->PostTask( task_runner_->PostTask(
FROM_HERE, FROM_HERE,
base::Bind(&FakeMediaSource::SendNextFrame, weak_factory_.GetWeakPtr())); base::Bind(&FakeMediaSource::SendNextFrame, weak_factory_.GetWeakPtr()));
...@@ -462,7 +464,7 @@ void FakeMediaSource::DecodeAudio(ScopedAVPacket packet) { ...@@ -462,7 +464,7 @@ void FakeMediaSource::DecodeAudio(ScopedAVPacket packet) {
// Not the frequency of the source file. This is because we // Not the frequency of the source file. This is because we
// increment the frame count by samples we sent. // increment the frame count by samples we sent.
audio_sent_ts_.reset( audio_sent_ts_.reset(
new AudioTimestampHelper(kAudioSamplingFrequency)); new AudioTimestampHelper(output_audio_params_.sample_rate()));
// For some files this is an invalid value. // For some files this is an invalid value.
base::TimeDelta base_ts; base::TimeDelta base_ts;
audio_sent_ts_->SetBaseTimestamp(base_ts); audio_sent_ts_->SetBaseTimestamp(base_ts);
...@@ -506,16 +508,15 @@ void FakeMediaSource::DecodeAudio(ScopedAVPacket packet) { ...@@ -506,16 +508,15 @@ void FakeMediaSource::DecodeAudio(ScopedAVPacket packet) {
// Make sure there's enough data to resample audio. // Make sure there's enough data to resample audio.
if (audio_fifo_->frames() < if (audio_fifo_->frames() <
2 * audio_params_.sample_rate() / kAudioPacketsPerSecond) { 2 * source_audio_params_.sample_rate() / kAudioPacketsPerSecond) {
continue; continue;
} }
scoped_ptr<media::AudioBus> resampled_bus( scoped_ptr<media::AudioBus> resampled_bus(
media::AudioBus::Create( media::AudioBus::Create(
audio_params_.channels(), output_audio_params_.channels(),
kAudioSamplingFrequency / kAudioPacketsPerSecond)); output_audio_params_.sample_rate() / kAudioPacketsPerSecond));
audio_resampler_->Resample(resampled_bus->frames(), audio_converter_->Convert(resampled_bus.get());
resampled_bus.get());
audio_bus_queue_.push(resampled_bus.release()); audio_bus_queue_.push(resampled_bus.release());
} }
} }
...@@ -588,13 +589,15 @@ void FakeMediaSource::Decode(bool decode_audio) { ...@@ -588,13 +589,15 @@ void FakeMediaSource::Decode(bool decode_audio) {
} }
} }
void FakeMediaSource::ProvideData(int frame_delay, double FakeMediaSource::ProvideInput(media::AudioBus* output_bus,
media::AudioBus* output_bus) { base::TimeDelta buffer_delay) {
if (audio_fifo_->frames() >= output_bus->frames()) { if (audio_fifo_->frames() >= output_bus->frames()) {
audio_fifo_->Consume(output_bus, 0, output_bus->frames()); audio_fifo_->Consume(output_bus, 0, output_bus->frames());
return 1.0;
} else { } else {
LOG(WARNING) << "Not enough audio data for resampling."; LOG(WARNING) << "Not enough audio data for resampling.";
output_bus->Zero(); output_bus->Zero();
return 0.0;
} }
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/time/tick_clock.h" #include "base/time/tick_clock.h"
#include "media/audio/audio_parameters.h" #include "media/audio/audio_parameters.h"
#include "media/base/audio_converter.h"
#include "media/cast/cast_config.h" #include "media/cast/cast_config.h"
#include "media/filters/audio_renderer_algorithm.h" #include "media/filters/audio_renderer_algorithm.h"
#include "media/filters/ffmpeg_demuxer.h" #include "media/filters/ffmpeg_demuxer.h"
...@@ -29,11 +30,11 @@ struct AVFormatContext; ...@@ -29,11 +30,11 @@ struct AVFormatContext;
namespace media { namespace media {
class AudioBus; class AudioBus;
class AudioConverter;
class AudioFifo; class AudioFifo;
class AudioTimestampHelper; class AudioTimestampHelper;
class FFmpegGlue; class FFmpegGlue;
class InMemoryUrlProtocol; class InMemoryUrlProtocol;
class MultiChannelResampler;
namespace cast { namespace cast {
...@@ -41,17 +42,19 @@ class AudioFrameInput; ...@@ -41,17 +42,19 @@ class AudioFrameInput;
class VideoFrameInput; class VideoFrameInput;
class TestAudioBusFactory; class TestAudioBusFactory;
class FakeMediaSource { class FakeMediaSource : public media::AudioConverter::InputCallback {
public: public:
// |task_runner| is to schedule decoding tasks. // |task_runner| is to schedule decoding tasks.
// |clock| is used by this source but is not owned. // |clock| is used by this source but is not owned.
// |audio_config| is the desired audio config.
// |video_config| is the desired video config. // |video_config| is the desired video config.
// |keep_frames| is true if all VideoFrames are saved in a queue. // |keep_frames| is true if all VideoFrames are saved in a queue.
FakeMediaSource(scoped_refptr<base::SingleThreadTaskRunner> task_runner, FakeMediaSource(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
base::TickClock* clock, base::TickClock* clock,
const AudioSenderConfig& audio_config,
const VideoSenderConfig& video_config, const VideoSenderConfig& video_config,
bool keep_frames); bool keep_frames);
~FakeMediaSource(); ~FakeMediaSource() override;
// Transcode this file as the source of video and audio frames. // Transcode this file as the source of video and audio frames.
// If |override_fps| is non zero then the file is played at the desired rate. // If |override_fps| is non zero then the file is played at the desired rate.
...@@ -100,7 +103,9 @@ class FakeMediaSource { ...@@ -100,7 +103,9 @@ class FakeMediaSource {
void DecodeVideo(ScopedAVPacket packet); void DecodeVideo(ScopedAVPacket packet);
void Decode(bool decode_audio); void Decode(bool decode_audio);
void ProvideData(int frame_delay, media::AudioBus* output_bus); // media::AudioConverter::InputCallback implementation.
double ProvideInput(media::AudioBus* output_bus, base::TimeDelta buffer_delay)
override;
AVStream* av_audio_stream(); AVStream* av_audio_stream();
AVStream* av_video_stream(); AVStream* av_video_stream();
...@@ -108,6 +113,7 @@ class FakeMediaSource { ...@@ -108,6 +113,7 @@ class FakeMediaSource {
AVCodecContext* av_video_context(); AVCodecContext* av_video_context();
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
const media::AudioParameters output_audio_params_;
const VideoSenderConfig video_config_; const VideoSenderConfig video_config_;
const bool keep_frames_; const bool keep_frames_;
bool variable_frame_size_mode_; bool variable_frame_size_mode_;
...@@ -132,7 +138,7 @@ class FakeMediaSource { ...@@ -132,7 +138,7 @@ class FakeMediaSource {
AVFormatContext* av_format_context_; AVFormatContext* av_format_context_;
int audio_stream_index_; int audio_stream_index_;
AudioParameters audio_params_; AudioParameters source_audio_params_;
double playback_rate_; double playback_rate_;
int video_stream_index_; int video_stream_index_;
...@@ -140,7 +146,7 @@ class FakeMediaSource { ...@@ -140,7 +146,7 @@ class FakeMediaSource {
int video_frame_rate_denominator_; int video_frame_rate_denominator_;
// These are used for audio resampling. // These are used for audio resampling.
scoped_ptr<media::MultiChannelResampler> audio_resampler_; scoped_ptr<media::AudioConverter> audio_converter_;
scoped_ptr<media::AudioFifo> audio_fifo_; scoped_ptr<media::AudioFifo> audio_fifo_;
scoped_ptr<media::AudioBus> audio_fifo_input_bus_; scoped_ptr<media::AudioBus> audio_fifo_input_bus_;
media::AudioRendererAlgorithm audio_algo_; media::AudioRendererAlgorithm audio_algo_;
......
...@@ -259,7 +259,9 @@ int main(int argc, char** argv) { ...@@ -259,7 +259,9 @@ int main(int argc, char** argv) {
scoped_ptr<media::cast::FakeMediaSource> fake_media_source( scoped_ptr<media::cast::FakeMediaSource> fake_media_source(
new media::cast::FakeMediaSource(test_thread.message_loop_proxy(), new media::cast::FakeMediaSource(test_thread.message_loop_proxy(),
cast_environment->Clock(), cast_environment->Clock(),
video_config, false)); audio_config,
video_config,
false));
int override_fps = 0; int override_fps = 0;
if (!base::StringToInt(cmd->GetSwitchValueASCII(kSwitchFps), if (!base::StringToInt(cmd->GetSwitchValueASCII(kSwitchFps),
......
...@@ -480,6 +480,7 @@ void RunSimulation(const base::FilePath& source_path, ...@@ -480,6 +480,7 @@ void RunSimulation(const base::FilePath& source_path,
const bool quality_test = !metrics_output_path.empty(); const bool quality_test = !metrics_output_path.empty();
FakeMediaSource media_source(task_runner, FakeMediaSource media_source(task_runner,
&testing_clock, &testing_clock,
audio_sender_config,
video_sender_config, video_sender_config,
quality_test); quality_test);
scoped_ptr<EncodedVideoFrameTracker> video_frame_tracker; scoped_ptr<EncodedVideoFrameTracker> video_frame_tracker;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment