Chromium Code Reviews| Index: chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc |
| diff --git a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..33afc74f57af1691c37b992695c89482919f2543 |
| --- /dev/null |
| +++ b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc |
| @@ -0,0 +1,276 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
|
damienv1
2014/10/03 22:19:41
I think the whole unit test has been updated in th
gunsch
2014/10/03 23:08:44
Huh, so it was. Updated.
|
| + |
| +#include <list> |
| +#include <vector> |
| + |
| +#include "base/basictypes.h" |
| +#include "base/bind.h" |
| +#include "base/files/file_path.h" |
| +#include "base/files/memory_mapped_file.h" |
| +#include "base/logging.h" |
| +#include "base/memory/ref_counted.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/message_loop/message_loop.h" |
| +#include "base/message_loop/message_loop_proxy.h" |
| +#include "base/path_service.h" |
| +#include "base/threading/thread.h" |
| +#include "base/time/time.h" |
| +#include "chromecast/media/cma/backend/audio_pipeline_device.h" |
| +#include "chromecast/media/cma/backend/media_clock_device.h" |
| +#include "chromecast/media/cma/backend/media_component_device_feeder_for_test.h" |
| +#include "chromecast/media/cma/backend/media_pipeline_device.h" |
| +#include "chromecast/media/cma/backend/video_pipeline_device.h" |
| +#include "chromecast/media/cma/base/decoder_buffer_adapter.h" |
| +#include "chromecast/media/cma/base/decoder_buffer_base.h" |
| +#include "chromecast/media/cma/test/frame_segmenter_for_test.h" |
| +#include "media/base/audio_decoder_config.h" |
| +#include "media/base/buffers.h" |
| +#include "media/base/decoder_buffer.h" |
| +#include "media/base/video_decoder_config.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +namespace chromecast { |
| +namespace media { |
| + |
| +namespace { |
| + |
| +base::FilePath GetTestDataFilePath(const std::string& name) { |
| + base::FilePath file_path; |
| + CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); |
| + |
| + file_path = file_path.Append(FILE_PATH_LITERAL("media")) |
| + .Append(FILE_PATH_LITERAL("test")) |
| + .Append(FILE_PATH_LITERAL("data")) |
| + .AppendASCII(name); |
| + return file_path; |
| +} |
| + |
| +} |
| + |
| +class AudioVideoPipelineDeviceTest : public testing::Test { |
| + public: |
| + AudioVideoPipelineDeviceTest(); |
| + virtual ~AudioVideoPipelineDeviceTest(); |
| + |
| + void ConfigureForFile(std::string filename); |
| + void ConfigureForAudioOnly(std::string filename); |
| + void ConfigureForVideoOnly(std::string filename, |
| + bool raw_h264); |
| + |
| + void Start(); |
| + |
| + private: |
| + void Initialize(); |
| + |
| + void LoadAudioStream(std::string filename); |
| + void LoadVideoStream(std::string filename, bool raw_h264); |
| + |
| + void OnPrimaryEos(); |
| + |
| + scoped_ptr<MediaPipelineDevice> media_pipeline_device_; |
| + MediaClockDevice* media_clock_device_; |
| + |
| + // Devices to feed |
| + std::vector<scoped_refptr<MediaComponentDeviceFeeder> > |
| + component_device_feeders_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(AudioVideoPipelineDeviceTest); |
| +}; |
| + |
| +AudioVideoPipelineDeviceTest::AudioVideoPipelineDeviceTest() { |
| +} |
| + |
| +AudioVideoPipelineDeviceTest::~AudioVideoPipelineDeviceTest() { |
| +} |
| + |
| +void AudioVideoPipelineDeviceTest::ConfigureForAudioOnly(std::string filename) { |
| + Initialize(); |
| + |
| + LoadAudioStream(filename); |
| + |
| + component_device_feeders_[0]->SetFrameCountBetweenPause(50); |
| + component_device_feeders_[0]->SetEosCB( |
| + base::Bind(&AudioVideoPipelineDeviceTest::OnPrimaryEos, |
| + base::Unretained(this))); |
| +} |
| + |
| +void AudioVideoPipelineDeviceTest::ConfigureForVideoOnly(std::string filename, |
| + bool raw_h264) { |
| + Initialize(); |
| + |
| + LoadVideoStream(filename, raw_h264); |
| + |
| + component_device_feeders_[0]->SetFrameCountBetweenPause(50); |
| + component_device_feeders_[0]->SetEosCB( |
| + base::Bind(&AudioVideoPipelineDeviceTest::OnPrimaryEos, |
| + base::Unretained(this))); |
| +} |
| + |
| +void AudioVideoPipelineDeviceTest::ConfigureForFile(std::string filename) { |
| + Initialize(); |
| + |
| + LoadVideoStream(filename, /* raw_h264 */ false); |
| + LoadAudioStream(filename); |
| + |
| + component_device_feeders_[0]->SetFrameCountBetweenPause(50); |
| + component_device_feeders_[0]->SetEosCB( |
| + base::Bind(&AudioVideoPipelineDeviceTest::OnPrimaryEos, |
| + base::Unretained(this))); |
| +} |
| + |
| +void AudioVideoPipelineDeviceTest::LoadAudioStream(std::string filename) { |
| + base::FilePath file_path = GetTestDataFilePath(filename); |
| + DemuxResult demux_result = FFmpegDemuxForTest(file_path, /*audio*/ true); |
| + std::list<scoped_refptr<DecoderBufferBase> > frames = demux_result.frames; |
| + |
| + AudioPipelineDevice *audio_pipeline_device = |
| + media_pipeline_device_->GetAudioPipelineDevice(); |
| + |
| + // Set configuration. |
| + bool success = audio_pipeline_device->SetConfig(demux_result.audio_config); |
| + ASSERT_TRUE(success); |
| + |
| + VLOG(2) << "Got " << frames.size() << " audio input frames"; |
| + |
| + frames.push_back( |
| + scoped_refptr<DecoderBufferBase>( |
| + new DecoderBufferAdapter(::media::DecoderBuffer::CreateEOSBuffer()))); |
| + |
| + scoped_refptr<MediaComponentDeviceFeeder> new_feeder = |
| + scoped_refptr<MediaComponentDeviceFeeder>( |
| + new MediaComponentDeviceFeeder(audio_pipeline_device, |
| + media_clock_device_, |
| + frames)); |
| + new_feeder->Initialize(); |
| + |
| + component_device_feeders_.push_back(new_feeder); |
| +} |
| + |
| +void AudioVideoPipelineDeviceTest::LoadVideoStream(std::string filename, |
| + bool raw_h264) { |
| + std::list<scoped_refptr<DecoderBufferBase> > frames; |
| + ::media::VideoDecoderConfig video_config; |
| + |
| + if (raw_h264) { |
| + base::FilePath file_path = GetTestDataFilePath(filename); |
| + base::MemoryMappedFile video_stream; |
| + ASSERT_TRUE(video_stream.Initialize(file_path)) |
| + << "Couldn't open stream file: " << file_path.MaybeAsASCII(); |
| + frames = H264SegmenterForTest(video_stream.data(), video_stream.length()); |
| + |
| + // Use arbitraty sizes. |
| + gfx::Size coded_size(320, 240); |
| + gfx::Rect visible_rect(0, 0, 320, 240); |
| + gfx::Size natural_size(320, 240); |
| + |
| + video_config = ::media::VideoDecoderConfig( |
| + ::media::kCodecH264, |
| + ::media::H264PROFILE_MAIN, |
| + ::media::VideoFrame::I420, |
| + coded_size, |
| + visible_rect, |
| + natural_size, |
| + NULL, 0, false); |
| + } else { |
| + base::FilePath file_path = GetTestDataFilePath(filename); |
| + DemuxResult demux_result = FFmpegDemuxForTest(file_path, |
| + /*audio*/ false); |
| + frames = demux_result.frames; |
| + video_config = demux_result.video_config; |
| + } |
| + |
| + VideoPipelineDevice *video_pipeline_device = |
| + media_pipeline_device_->GetVideoPipelineDevice(); |
| + |
| + // Set configuration. |
| + bool success = video_pipeline_device->SetConfig(video_config); |
| + ASSERT_TRUE(success); |
| + |
| + VLOG(2) << "Got " << frames.size() << " video input frames"; |
| + |
| + frames.push_back( |
| + scoped_refptr<DecoderBufferBase>(new DecoderBufferAdapter( |
| + ::media::DecoderBuffer::CreateEOSBuffer()))); |
| + |
| + scoped_refptr<MediaComponentDeviceFeeder> new_feeder = |
| + scoped_refptr<MediaComponentDeviceFeeder>( |
| + new MediaComponentDeviceFeeder(video_pipeline_device, |
| + media_clock_device_, |
| + frames)); |
| + new_feeder->Initialize(); |
| + |
| + component_device_feeders_.push_back(new_feeder); |
| +} |
| + |
| +void AudioVideoPipelineDeviceTest::Start() { |
| + for (int i=0; i < component_device_feeders_.size(); i++) { |
| + base::MessageLoopProxy::current()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&MediaComponentDeviceFeeder::Feed, |
| + base::Unretained(component_device_feeders_[i].get()))); |
| + } |
| +} |
| + |
| +void AudioVideoPipelineDeviceTest::OnPrimaryEos() { |
| + base::MessageLoop::current()->QuitWhenIdle(); |
| +} |
| + |
| +void AudioVideoPipelineDeviceTest::Initialize() { |
| + // Create the media device. |
| + MediaPipelineDevice::CreateParameters params; |
| + media_pipeline_device_.reset(CreateMediaPipelineDevice(params).release()); |
| + media_clock_device_ = media_pipeline_device_->GetMediaClockDevice(); |
| + |
| + // Clock initialization and configuration. |
| + bool success = |
| + media_clock_device_->SetState(MediaClockDevice::kStateIdle); |
| + ASSERT_TRUE(success); |
| + success = media_clock_device_->ResetTimeline(base::TimeDelta()); |
| + ASSERT_TRUE(success); |
| + media_clock_device_->SetRate(1.0); |
| +} |
| + |
| +TEST_F(AudioVideoPipelineDeviceTest, Mp3Playback) { |
| + scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); |
| + |
| + ConfigureForAudioOnly("sfx.mp3"); |
| + Start(); |
| + message_loop->Run(); |
| +} |
| + |
| +TEST_F(AudioVideoPipelineDeviceTest, VorbisPlayback) { |
| + scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); |
| + |
| + ConfigureForAudioOnly("sfx.ogg"); |
| + Start(); |
| + message_loop->Run(); |
| +} |
| + |
| +TEST_F(AudioVideoPipelineDeviceTest, H264Playback) { |
| + scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); |
| + |
| + ConfigureForVideoOnly("bear.h264", /* raw_h264 */ true); |
|
damienv1
2014/10/03 22:19:41
Note: we introduce a dependency on Chrome test med
gunsch
2014/10/03 23:08:44
Only w.r.t header includes. Even gyp DEPS are okay
|
| + Start(); |
| + message_loop->Run(); |
| +} |
| + |
| +TEST_F(AudioVideoPipelineDeviceTest, Vp8Playback) { |
| + scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); |
| + |
| + ConfigureForVideoOnly("bear-vp8a.webm", /* raw_h264 */ false); |
| + Start(); |
| + message_loop->Run(); |
| +} |
| + |
| +TEST_F(AudioVideoPipelineDeviceTest, VorbisAndVp8InWebmPlayback) { |
| + scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); |
| + |
| + ConfigureForFile("bear-640x360.webm"); |
| + Start(); |
| + message_loop->Run(); |
| +} |
| + |
| +} // namespace media |
| +} // namespace chromecast |