summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-10 20:47:51 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-10 20:47:51 +0000
commitba650a35365f11389eebe5b5325d1ad0e9a69b8e (patch)
tree80089187df282aec574b927ca720449b4bff15a0 /media
parentfe9d5d06dd4acbd1df3f828207d7ebfa1a245279 (diff)
downloadchromium_src-ba650a35365f11389eebe5b5325d1ad0e9a69b8e.zip
chromium_src-ba650a35365f11389eebe5b5325d1ad0e9a69b8e.tar.gz
chromium_src-ba650a35365f11389eebe5b5325d1ad0e9a69b8e.tar.bz2
Converted remaining tests to use gmock and deleted all old mocking code.
The most important part was refactoring PipelineImpl tests in preparation for message loop injection. The old mocks just did not work *at all* with my message loop injection patch. BUG=16008 TEST=media_unittests should pass and not flake out Review URL: http://codereview.chromium.org/149423 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20412 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/base/mock_ffmpeg.cc41
-rw-r--r--media/base/mock_ffmpeg.h8
-rw-r--r--media/base/mock_filters.h51
-rw-r--r--media/base/mock_media_filters.h656
-rw-r--r--media/base/pipeline_impl_unittest.cc248
-rw-r--r--media/base/video_frame_impl_unittest.cc50
-rw-r--r--media/filters/ffmpeg_glue_unittest.cc441
-rw-r--r--media/filters/test_video_decoder.h80
-rw-r--r--media/filters/test_video_renderer.h67
-rw-r--r--media/media.gyp3
10 files changed, 519 insertions, 1126 deletions
diff --git a/media/base/mock_ffmpeg.cc b/media/base/mock_ffmpeg.cc
index 054f996..562aff2 100644
--- a/media/base/mock_ffmpeg.cc
+++ b/media/base/mock_ffmpeg.cc
@@ -7,12 +7,36 @@
#include "base/logging.h"
#include "media/filters/ffmpeg_common.h"
+using ::testing::_;
+using ::testing::AtMost;
+using ::testing::DoAll;
+using ::testing::Return;
+using ::testing::SaveArg;
+
namespace media {
MockFFmpeg* MockFFmpeg::instance_ = NULL;
+URLProtocol* MockFFmpeg::protocol_ = NULL;
MockFFmpeg::MockFFmpeg()
: outstanding_packets_(0) {
+ // If we haven't assigned our static copy of URLProtocol, set up expectations
+ // to catch the URLProtocol registered when the singleton instance of
+ // FFmpegGlue is created.
+ //
+ // TODO(scherkus): this feels gross and I need to think of a way to better
+ // inject/mock singletons.
+ if (!protocol_) {
+ EXPECT_CALL(*this, AVCodecInit())
+ .Times(AtMost(1))
+ .WillOnce(Return());
+ EXPECT_CALL(*this, AVRegisterProtocol(_))
+ .Times(AtMost(1))
+ .WillOnce(DoAll(SaveArg<0>(&protocol_), Return(0)));
+ EXPECT_CALL(*this, AVRegisterAll())
+ .Times(AtMost(1))
+ .WillOnce(Return());
+ }
}
MockFFmpeg::~MockFFmpeg() {
@@ -40,6 +64,11 @@ MockFFmpeg* MockFFmpeg::get() {
}
// static
+URLProtocol* MockFFmpeg::protocol() {
+ return protocol_;
+}
+
+// static
void MockFFmpeg::DestructPacket(AVPacket* packet) {
delete [] packet->data;
packet->data = NULL;
@@ -49,6 +78,18 @@ void MockFFmpeg::DestructPacket(AVPacket* packet) {
// FFmpeg stubs that delegate to the FFmpegMock instance.
extern "C" {
+void avcodec_init() {
+ media::MockFFmpeg::get()->AVCodecInit();
+}
+
+int av_register_protocol(URLProtocol* protocol) {
+ return media::MockFFmpeg::get()->AVRegisterProtocol(protocol);
+}
+
+void av_register_all() {
+ media::MockFFmpeg::get()->AVRegisterAll();
+}
+
AVCodec* avcodec_find_decoder(enum CodecID id) {
return media::MockFFmpeg::get()->AVCodecFindDecoder(id);
}
diff --git a/media/base/mock_ffmpeg.h b/media/base/mock_ffmpeg.h
index 3afdef9..4ba38fc 100644
--- a/media/base/mock_ffmpeg.h
+++ b/media/base/mock_ffmpeg.h
@@ -16,6 +16,10 @@ class MockFFmpeg {
MockFFmpeg();
virtual ~MockFFmpeg();
+ MOCK_METHOD0(AVCodecInit, void());
+ MOCK_METHOD1(AVRegisterProtocol, int(URLProtocol* protocol));
+ MOCK_METHOD0(AVRegisterAll, void());
+
MOCK_METHOD1(AVCodecFindDecoder, AVCodec*(enum CodecID id));
MOCK_METHOD2(AVCodecOpen, int(AVCodecContext* avctx, AVCodec* codec));
MOCK_METHOD1(AVCodecClose, int(AVCodecContext* avctx));
@@ -51,6 +55,9 @@ class MockFFmpeg {
static void set(MockFFmpeg* instance);
static MockFFmpeg* get();
+ // Returns the URLProtocol registered by the FFmpegGlue singleton.
+ static URLProtocol* protocol();
+
// AVPacket destructor for packets allocated by av_new_packet().
static void DestructPacket(AVPacket* packet);
@@ -60,6 +67,7 @@ class MockFFmpeg {
private:
static MockFFmpeg* instance_;
+ static URLProtocol* protocol_;
// Tracks the number of packets allocated by calls to av_read_frame() and
// av_free_packet(). We crash the unit test if this is not zero at time of
diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h
index bef46a7..bffba6f 100644
--- a/media/base/mock_filters.h
+++ b/media/base/mock_filters.h
@@ -19,6 +19,27 @@
namespace media {
+// Use this template to test for object destruction by setting expectations on
+// the method OnDestroy().
+//
+// TODO(scherkus): not sure about the naming... perhaps contribute this back
+// to gmock itself!
+template<class MockClass>
+class Destroyable : public MockClass {
+ public:
+ Destroyable() {}
+
+ MOCK_METHOD0(OnDestroy, void());
+
+ protected:
+ virtual ~Destroyable() {
+ OnDestroy();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Destroyable);
+};
+
class MockDataSource : public DataSource {
public:
MockDataSource() {}
@@ -71,6 +92,12 @@ class MockDemuxerStream : public DemuxerStream {
public:
MockDemuxerStream() {}
+ // Sets the mime type of this object's media format, which is usually checked
+ // to determine the type of decoder to create.
+ explicit MockDemuxerStream(const std::string& mime_type) {
+ media_format_.SetAsString(MediaFormat::kMimeType, mime_type);
+ }
+
// DemuxerStream implementation.
const MediaFormat& media_format() { return media_format_; }
MOCK_METHOD1(Read, void(Callback1<Buffer*>::Type* read_callback));
@@ -175,7 +202,8 @@ class MockAudioRenderer : public AudioRenderer {
class MockFilterFactory : public FilterFactory {
public:
MockFilterFactory()
- : data_source_(new MockDataSource()),
+ : creation_successful_(true),
+ data_source_(new MockDataSource()),
demuxer_(new MockDemuxer()),
video_decoder_(new MockVideoDecoder()),
audio_decoder_(new MockAudioDecoder()),
@@ -185,6 +213,11 @@ class MockFilterFactory : public FilterFactory {
virtual ~MockFilterFactory() {}
+ // Controls whether the Create() method is successful or not.
+ void set_creation_successful(bool creation_successful) {
+ creation_successful_ = creation_successful;
+ }
+
// Mock accessors.
MockDataSource* data_source() const { return data_source_; }
MockDemuxer* demuxer() const { return demuxer_; }
@@ -195,6 +228,10 @@ class MockFilterFactory : public FilterFactory {
protected:
MediaFilter* Create(FilterType filter_type, const MediaFormat& media_format) {
+ if (!creation_successful_) {
+ return NULL;
+ }
+
switch (filter_type) {
case FILTER_DATA_SOURCE:
return data_source_;
@@ -215,6 +252,7 @@ class MockFilterFactory : public FilterFactory {
}
private:
+ bool creation_successful_;
scoped_refptr<MockDataSource> data_source_;
scoped_refptr<MockDemuxer> demuxer_;
scoped_refptr<MockVideoDecoder> video_decoder_;
@@ -225,6 +263,17 @@ class MockFilterFactory : public FilterFactory {
DISALLOW_COPY_AND_ASSIGN(MockFilterFactory);
};
+// Helper gmock action that calls InitializationComplete() on behalf of the
+// provided filter.
+ACTION_P(InitializationComplete, filter) {
+ filter->host()->InitializationComplete();
+}
+
+// Helper gmock action that calls Error() on behalf of the provided filter.
+ACTION_P2(Error, filter, error) {
+ filter->host()->Error(error);
+}
+
} // namespace media
#endif // MEDIA_BASE_MOCK_FILTERS_H_
diff --git a/media/base/mock_media_filters.h b/media/base/mock_media_filters.h
deleted file mode 100644
index 698815f..0000000
--- a/media/base/mock_media_filters.h
+++ /dev/null
@@ -1,656 +0,0 @@
-// Copyright (c) 2009 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.
-//
-// TODO(ajwong): This whole file is deprecated in favor or gmock style mocks.
-// The deprecated classes have been moved into the old_mocks to avoid colliding
-// with the newer mock classes. Once all the unittests have been migrated, this
-// should be deleted.
-
-#ifndef MEDIA_BASE_MOCK_MEDIA_FILTERS_H_
-#define MEDIA_BASE_MOCK_MEDIA_FILTERS_H_
-
-#include <string>
-
-#include "base/scoped_ptr.h"
-#include "base/waitable_event.h"
-#include "media/base/buffers.h"
-#include "media/base/factory.h"
-#include "media/base/filter_host.h"
-#include "media/base/filters.h"
-#include "media/base/media_format.h"
-#include "media/base/pipeline.h"
-#include "media/base/video_frame_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace media {
-
-namespace old_mocks {
-
-// Behaviors for MockDataSource filter.
-enum MockDataSourceBehavior {
- MOCK_DATA_SOURCE_NORMAL_INIT,
- MOCK_DATA_SOURCE_NEVER_INIT,
- MOCK_DATA_SOURCE_URL_ERROR_IN_INIT,
- MOCK_DATA_SOURCE_INIT_RETURN_FALSE,
-};
-
-
-// This class is used by all of the mock filters to change the configuration
-// of the desired pipeline. The test using this must ensure that the lifetime
-// of the object is at least as long as the lifetime of the filters, as this
-// is typically allocated on the stack.
-struct MockFilterConfig {
- MockFilterConfig()
- : create_filter(true),
- data_source_behavior(MOCK_DATA_SOURCE_NORMAL_INIT),
- data_source_value('!'),
- has_video(true),
- video_width(1280u),
- video_height(720u),
- video_surface_format(VideoSurface::YV12),
- has_audio(true),
- compressed_audio_mime_type(mime_type::kAACAudio),
- uncompressed_audio_mime_type(mime_type::kUncompressedAudio),
- compressed_video_mime_type(mime_type::kH264AnnexB),
- uncompressed_video_mime_type(mime_type::kUncompressedVideo),
- frame_duration(base::TimeDelta::FromMicroseconds(33333)),
- media_duration(base::TimeDelta::FromSeconds(5)),
- media_total_bytes(media_duration.InMilliseconds() * 250) {
- }
-
- bool create_filter;
- MockDataSourceBehavior data_source_behavior;
- char data_source_value;
- bool has_video;
- size_t video_width;
- size_t video_height;
- VideoSurface::Format video_surface_format;
- bool has_audio;
- std::string compressed_audio_mime_type;
- std::string uncompressed_audio_mime_type;
- std::string compressed_video_mime_type;
- std::string uncompressed_video_mime_type;
- base::TimeDelta frame_duration;
- base::TimeDelta media_duration;
- int64 media_total_bytes;
-};
-
-
-class MockDataSource : public DataSource {
- public:
- explicit MockDataSource(const MockFilterConfig* config)
- : config_(config),
- position_(0),
- deleted_(NULL) {
- }
-
- MockDataSource(const MockFilterConfig* config, bool* deleted)
- : config_(config),
- position_(0),
- deleted_(deleted) {
- EXPECT_TRUE(deleted);
- EXPECT_FALSE(*deleted);
- }
-
- // Implementation of MediaFilter.
- virtual void Stop() {}
-
- virtual void Seek(base::TimeDelta time) {
- seek_time_ = time;
- }
-
- // Implementation of DataSource.
- virtual bool Initialize(const std::string& url) {
- media_format_.SetAsString(MediaFormat::kMimeType,
- mime_type::kApplicationOctetStream);
- media_format_.SetAsString(MediaFormat::kURL, url);
- host()->SetTotalBytes(config_->media_total_bytes);
- switch (config_->data_source_behavior) {
- case MOCK_DATA_SOURCE_NORMAL_INIT:
- host()->InitializationComplete();
- return true;
- case MOCK_DATA_SOURCE_NEVER_INIT:
- return true;
- case MOCK_DATA_SOURCE_URL_ERROR_IN_INIT:
- host()->Error(PIPELINE_ERROR_URL_NOT_FOUND);
- return false;
- case MOCK_DATA_SOURCE_INIT_RETURN_FALSE:
- return false;
- default:
- NOTREACHED();
- return false;
- }
- }
-
- virtual const MediaFormat& media_format() {
- return media_format_;
- }
-
- virtual size_t Read(uint8* data, size_t size) {
- size_t read = static_cast<size_t>(config_->media_total_bytes - position_);
- if (size < read) {
- read = size;
- }
- memset(data, config_->data_source_value, read);
- return read;
- }
-
- virtual bool GetPosition(int64* position_out) {
- *position_out = position_;
- return true;
- }
-
- virtual bool SetPosition(int64 position) {
- if (position < 0u || position > config_->media_total_bytes) {
- return false;
- }
- position_ = position;
- return true;
- }
-
- virtual bool GetSize(int64* size_out) {
- if (config_->media_total_bytes >= 0) {
- *size_out = config_->media_total_bytes;
- return true;
- }
- return false;
- }
-
- virtual bool IsSeekable() {
- return true;
- }
-
- // Mock accessors.
- int64 position() const { return position_; }
- const base::TimeDelta& seek_time() const { return seek_time_; }
-
- private:
- virtual ~MockDataSource() {
- if (deleted_) {
- *deleted_ = true;
- }
- }
-
- const MockFilterConfig* config_;
- int64 position_;
- MediaFormat media_format_;
- base::TimeDelta seek_time_;
-
- // Set to true inside the destructor. Used in FFmpegGlue unit tests for
- // testing proper reference counting.
- bool* deleted_;
-
- DISALLOW_COPY_AND_ASSIGN(MockDataSource);
-};
-
-
-class MockDemuxerStream : public DemuxerStream {
- public:
- MockDemuxerStream(const MockFilterConfig* config, bool is_audio) {
- if (is_audio) {
- media_format_.SetAsString(MediaFormat::kMimeType,
- config->compressed_audio_mime_type);
- } else {
- media_format_.SetAsString(MediaFormat::kMimeType,
- config->compressed_video_mime_type);
- media_format_.SetAsInteger(MediaFormat::kWidth, config->video_width);
- media_format_.SetAsInteger(MediaFormat::kHeight, config->video_height);
- }
- }
-
- // Implementation of DemuxerStream.
- virtual const MediaFormat& media_format() {
- return media_format_;
- }
-
- virtual void Read(Callback1<Buffer*>::Type* read_callback) {
- NOTREACHED(); // TODO(ralphl): fix me!!
- }
-
- private:
- virtual ~MockDemuxerStream() {}
-
- MediaFormat media_format_;
-
- DISALLOW_COPY_AND_ASSIGN(MockDemuxerStream);
-};
-
-
-class MockDemuxer : public Demuxer {
- public:
- explicit MockDemuxer(const MockFilterConfig* config)
- : config_(config),
- mock_audio_stream_(new MockDemuxerStream(config, true)),
- mock_video_stream_(new MockDemuxerStream(config, false)) {
- }
-
- // Implementation of MediaFilter.
- virtual void Stop() {}
-
- virtual void Seek(base::TimeDelta time) {
- seek_time_ = time;
- }
-
- // Implementation of Demuxer.
- virtual bool Initialize(DataSource* data_source) {
- host()->InitializationComplete();
- return true;
- }
-
- virtual size_t GetNumberOfStreams() {
- size_t num_streams = 0;
- if (config_->has_audio) {
- ++num_streams;
- }
- if (config_->has_video) {
- ++num_streams;
- }
- return num_streams;
- }
-
- virtual scoped_refptr<DemuxerStream> GetStream(int stream_id) {
- switch (stream_id) {
- case 0:
- if (config_->has_audio) {
- return mock_audio_stream_;
- } else if (config_->has_video) {
- return mock_video_stream_;
- }
- break;
- case 1:
- if (config_->has_audio && config_->has_video) {
- return mock_video_stream_;
- }
- break;
- }
- ADD_FAILURE();
- return NULL;
- }
-
- // Mock accessors.
- const base::TimeDelta& seek_time() const { return seek_time_; }
-
- private:
- virtual ~MockDemuxer() {}
-
- const MockFilterConfig* config_;
- scoped_refptr<DemuxerStream> mock_audio_stream_;
- scoped_refptr<DemuxerStream> mock_video_stream_;
- base::TimeDelta seek_time_;
-
- DISALLOW_COPY_AND_ASSIGN(MockDemuxer);
-};
-
-
-class MockAudioDecoder : public AudioDecoder {
- public:
- explicit MockAudioDecoder(const MockFilterConfig* config) {
- media_format_.SetAsString(MediaFormat::kMimeType,
- config->uncompressed_audio_mime_type);
- }
-
- // Implementation of MediaFilter.
- virtual void Stop() {}
-
- virtual void Seek(base::TimeDelta time) {
- seek_time_ = time;
- }
-
- // Implementation of AudioDecoder.
- virtual bool Initialize(DemuxerStream* stream) {
- host()->InitializationComplete();
- return true;
- }
-
- virtual const MediaFormat& media_format() {
- return media_format_;
- }
-
- virtual void Read(Callback1<Buffer*>::Type* callback) {
- // TODO(ralphl): implement mock read.
- NOTREACHED();
- }
-
- // Mock accessors.
- const base::TimeDelta& seek_time() const { return seek_time_; }
-
- private:
- virtual ~MockAudioDecoder() {}
-
- MediaFormat media_format_;
- base::TimeDelta seek_time_;
-
- DISALLOW_COPY_AND_ASSIGN(MockAudioDecoder);
-};
-
-
-class MockAudioRenderer : public AudioRenderer {
- public:
- explicit MockAudioRenderer(const MockFilterConfig* config) {}
-
- // Implementation of MediaFilter.
- virtual void Stop() {}
-
- virtual void Seek(base::TimeDelta time) {
- seek_time_ = time;
- }
-
- // Implementation of AudioRenderer.
- virtual bool Initialize(AudioDecoder* decoder) {
- host()->InitializationComplete();
- return true;
- }
-
- virtual void SetVolume(float volume) {}
-
- // Mock accessors.
- const base::TimeDelta& seek_time() const { return seek_time_; }
-
- private:
- virtual ~MockAudioRenderer() {}
-
- base::TimeDelta seek_time_;
-
- DISALLOW_COPY_AND_ASSIGN(MockAudioRenderer);
-};
-
-
-class MockVideoDecoder : public VideoDecoder {
- public:
- // Helper function that initializes a YV12 frame with white and black scan
- // lines based on the |white_to_black| parameter. If 0, then the entire
- // frame will be black, if 1 then the entire frame will be white.
- static void InitializeYV12Frame(VideoFrame* frame, double white_to_black) {
- VideoSurface surface;
- if (!frame->Lock(&surface)) {
- ADD_FAILURE();
- } else {
- EXPECT_EQ(surface.format, VideoSurface::YV12);
- size_t first_black_row = static_cast<size_t>(surface.height *
- white_to_black);
- uint8* y_plane = surface.data[VideoSurface::kYPlane];
- for (size_t row = 0; row < surface.height; ++row) {
- int color = (row < first_black_row) ? 0xFF : 0x00;
- memset(y_plane, color, surface.width);
- y_plane += surface.strides[VideoSurface::kYPlane];
- }
- uint8* u_plane = surface.data[VideoSurface::kUPlane];
- uint8* v_plane = surface.data[VideoSurface::kVPlane];
- for (size_t row = 0; row < surface.height; row += 2) {
- memset(u_plane, 0x80, surface.width / 2);
- memset(v_plane, 0x80, surface.width / 2);
- u_plane += surface.strides[VideoSurface::kUPlane];
- v_plane += surface.strides[VideoSurface::kVPlane];
- }
- frame->Unlock();
- }
- }
-
- explicit MockVideoDecoder(const MockFilterConfig* config)
- : config_(config) {
- media_format_.SetAsString(MediaFormat::kMimeType,
- config->uncompressed_video_mime_type);
- media_format_.SetAsInteger(MediaFormat::kWidth, config->video_width);
- media_format_.SetAsInteger(MediaFormat::kHeight, config->video_height);
- }
-
- // Implementation of MediaFilter.
- virtual void Stop() {}
-
- virtual void Seek(base::TimeDelta time) {
- seek_time_ = time;
- }
-
- // Implementation of VideoDecoder.
- virtual bool Initialize(DemuxerStream* stream) {
- host()->InitializationComplete();
- return true;
- }
-
- virtual const MediaFormat& media_format() {
- return media_format_;
- }
-
- virtual void Read(Callback1<VideoFrame*>::Type* callback) {
- DoRead(callback);
- }
-
- // Mock accessors.
- const base::TimeDelta& seek_time() const { return seek_time_; }
-
- private:
- virtual ~MockVideoDecoder() {}
-
- void DoRead(Callback1<VideoFrame*>::Type* callback) {
- scoped_ptr<Callback1<VideoFrame*>::Type> scoped_callback(callback);
- if (mock_frame_time_ < config_->media_duration) {
- // TODO(ralphl): Mock video decoder only works with YV12. Implement other
- // formats as needed.
- EXPECT_EQ(config_->video_surface_format, VideoSurface::YV12);
- scoped_refptr<VideoFrame> frame;
- VideoFrameImpl::CreateFrame(config_->video_surface_format,
- config_->video_width,
- config_->video_height,
- mock_frame_time_,
- config_->frame_duration,
- &frame);
- if (!frame) {
- host()->Error(PIPELINE_ERROR_OUT_OF_MEMORY);
- ADD_FAILURE();
- } else {
- mock_frame_time_ += config_->frame_duration;
- if (mock_frame_time_ >= config_->media_duration) {
- VideoFrameImpl::CreateEmptyFrame(&frame);
- } else {
- InitializeYV12Frame(frame, (mock_frame_time_.InSecondsF() /
- config_->media_duration.InSecondsF()));
- }
- callback->Run(frame);
- }
- }
- }
-
- MediaFormat media_format_;
- base::TimeDelta mock_frame_time_;
- base::TimeDelta seek_time_;
- const MockFilterConfig* config_;
-
- DISALLOW_COPY_AND_ASSIGN(MockVideoDecoder);
-};
-
-
-class MockVideoRenderer : public VideoRenderer {
- public:
- explicit MockVideoRenderer(const MockFilterConfig* config)
- : config_(config) {
- }
-
- // Implementation of MediaFilter.
- virtual void Stop() {}
-
- virtual void Seek(base::TimeDelta time) {
- seek_time_ = time;
- }
-
- // Implementation of VideoRenderer.
- virtual bool Initialize(VideoDecoder* decoder) {
- host()->SetVideoSize(config_->video_width, config_->video_height);
- host()->InitializationComplete();
- return true;
- }
-
- // Mock accessors.
- const base::TimeDelta& seek_time() const { return seek_time_; }
-
- private:
- virtual ~MockVideoRenderer() {}
-
- base::TimeDelta seek_time_;
- const MockFilterConfig* config_;
-
- DISALLOW_COPY_AND_ASSIGN(MockVideoRenderer);
-};
-
-
-// FilterFactory capable of creating each mock filter type. Only one instance
-// of each filter type can exist at any time. Filters can be inspected for
-// expectations using the accessors, which may return NULL if the filter was
-// never created (i.e., streams containing no video).
-class MockFilterFactory : public FilterFactory {
- public:
- explicit MockFilterFactory(const MockFilterConfig* config)
- : config_(config) {
- }
-
- // Mock accessors.
- MockDataSource* data_source() const { return data_source_; }
- MockDemuxer* demuxer() const { return demuxer_; }
- MockAudioDecoder* audio_decoder() const { return audio_decoder_; }
- MockVideoDecoder* video_decoder() const { return video_decoder_; }
- MockAudioRenderer* audio_renderer() const { return audio_renderer_; }
- MockVideoRenderer* video_renderer() const { return video_renderer_; }
-
- protected:
- MediaFilter* Create(FilterType filter_type, const MediaFormat& media_format) {
- if (!config_->create_filter)
- return NULL;
-
- switch (filter_type) {
- case FILTER_DATA_SOURCE:
- DCHECK(!data_source_);
- data_source_ = new MockDataSource(config_);
- return data_source_;
-
- case FILTER_DEMUXER:
- DCHECK(!demuxer_);
- demuxer_ = new MockDemuxer(config_);
- return demuxer_;
-
- case FILTER_AUDIO_DECODER:
- DCHECK(!audio_decoder_);
- audio_decoder_ = new MockAudioDecoder(config_);
- return audio_decoder_;
-
- case FILTER_VIDEO_DECODER:
- DCHECK(!video_decoder_);
- video_decoder_ = new MockVideoDecoder(config_);
- return video_decoder_;
-
- case FILTER_AUDIO_RENDERER:
- DCHECK(!audio_renderer_);
- audio_renderer_ = new MockAudioRenderer(config_);
- return audio_renderer_;
-
- case FILTER_VIDEO_RENDERER:
- DCHECK(!video_renderer_);
- video_renderer_ = new MockVideoRenderer(config_);
- return video_renderer_;
-
- default:
- NOTREACHED();
- }
- return NULL;
- }
-
- private:
- const MockFilterConfig* config_;
- scoped_refptr<MockDataSource> data_source_;
- scoped_refptr<MockDemuxer> demuxer_;
- scoped_refptr<MockAudioDecoder> audio_decoder_;
- scoped_refptr<MockVideoDecoder> video_decoder_;
- scoped_refptr<MockAudioRenderer> audio_renderer_;
- scoped_refptr<MockVideoRenderer> video_renderer_;
-
- DISALLOW_COPY_AND_ASSIGN(MockFilterFactory);
-};
-
-// A simple class that waits for a pipeline to be started and checks some
-// basic initialization values. The Start() method will not return until
-// either a pre-determined amount of time has passed or the pipeline calls the
-// InitCallback() callback. A typical use would be:
-// Pipeline p;
-// FilterFactoryCollection f;
-// f->AddFactory(a);
-// f->AddFactory(b);
-// ...
-// InitializationHelper h;
-// h.Start(&p, f, uri);
-//
-// If the test is expecting to produce an error use would be:
-// h.Start(&p, f, uri, PIPELINE_ERROR_REQUIRED_FILTER_MISSING)
-//
-// If the test expects the pipeline to hang during initialization (a filter
-// never calls FilterHost::InitializationComplete()) then the use would be:
-// h.Start(&p, f, uri, PIPELINE_OK, true);
-//
-// TODO(scherkus): Keep refactoring tests until we can remove this entirely.
-class InitializationHelper {
- public:
- InitializationHelper()
- : event_(true, false),
- callback_success_status_(false),
- waiting_for_callback_(false) {}
-
- // If callback has been called, then returns the boolean passed by the
- // pipeline to the callback.
- bool callback_success_status() { return callback_success_status_; }
-
- // Returns true if Start has been called, but the pipeline has not yet
- // called the initialization complete callback.
- bool waiting_for_callback() { return waiting_for_callback_; }
-
- // Starts the pipeline, providing an initialization callback that points
- // to this object.
- void Start(Pipeline* pipeline,
- FilterFactory* filter_factory,
- const std::string& uri,
- PipelineError expect_error = PIPELINE_OK,
- bool expect_hang = false) {
- // For tests that we expect to hang in initialization, we want to
- // wait a short time. If a hang is not expected, then wait long enough
- // to make sure that the filters have time to initalize. 1/2 second if
- // we expect to hang, and 3 seconds if we expect success.
- base::TimeDelta max_wait = base::TimeDelta::FromMilliseconds(expect_hang ?
- 500 : 3000);
- EXPECT_FALSE(waiting_for_callback_);
- waiting_for_callback_ = true;
- callback_success_status_ = false;
- event_.Reset();
- pipeline->Start(filter_factory, uri,
- NewCallback(this, &InitializationHelper::InitCallback));
- bool signaled = event_.TimedWait(max_wait);
- if (expect_hang) {
- EXPECT_FALSE(signaled);
- EXPECT_FALSE(pipeline->IsInitialized());
- EXPECT_TRUE(waiting_for_callback_);
- } else {
- EXPECT_TRUE(signaled);
- EXPECT_FALSE(waiting_for_callback_);
- EXPECT_EQ(pipeline->GetError(), expect_error);
- EXPECT_EQ(callback_success_status_, (expect_error == PIPELINE_OK));
- EXPECT_EQ(pipeline->IsInitialized(), (expect_error == PIPELINE_OK));
- }
- }
-
- private:
- void InitCallback(bool success) {
- EXPECT_TRUE(waiting_for_callback_);
- EXPECT_FALSE(event_.IsSignaled());
- waiting_for_callback_ = false;
- callback_success_status_ = success;
- event_.Signal();
- }
-
- base::WaitableEvent event_;
- bool callback_success_status_;
- bool waiting_for_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(InitializationHelper);
-};
-
-} // namespace old_mocks
-
-} // namespace media
-
-#endif // MEDIA_BASE_MOCK_MEDIA_FILTERS_H_
diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc
index 56aa246..4183126 100644
--- a/media/base/pipeline_impl_unittest.cc
+++ b/media/base/pipeline_impl_unittest.cc
@@ -10,34 +10,38 @@
#include "media/base/filters.h"
#include "media/base/factory.h"
#include "media/base/filter_host.h"
-#include "media/base/mock_media_filters.h"
+#include "media/base/mock_filters.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace {
+using ::testing::DoAll;
+using ::testing::Return;
+using ::testing::StrictMock;
-class PipelineImplTest : public testing::Test {
- protected:
+namespace media {
+
+typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
+
+class PipelineImplTest : public ::testing::Test {
+ public:
PipelineImplTest()
- : initialize_result_(false),
+ : mocks_(new MockFilterFactory()),
+ initialize_result_(false),
seek_result_(false),
initialize_event_(false, false),
seek_event_(false, false) {
}
- virtual ~PipelineImplTest() {}
-
- virtual void TearDown() {
+ virtual ~PipelineImplTest() {
// Force the pipeline to shut down its thread.
pipeline_.Stop();
}
+ protected:
// Called by tests after they have finished setting up MockFilterConfig.
// Initializes the pipeline and returns true if the initialization callback
// was executed, false otherwise.
bool InitializeAndWait() {
- DCHECK(!filters_);
- filters_ = new media::old_mocks::MockFilterFactory(&config_);
- pipeline_.Start(filters_, "",
+ pipeline_.Start(mocks_, "",
NewCallback(this, &PipelineImplTest::OnInitialize));
return initialize_event_.TimedWait(base::TimeDelta::FromMilliseconds(500));
}
@@ -49,10 +53,66 @@ class PipelineImplTest : public testing::Test {
return seek_event_.TimedWait(base::TimeDelta::FromMilliseconds(500));
}
+ // Sets up expectations to allow the data source to initialize.
+ void InitializeDataSource() {
+ EXPECT_CALL(*mocks_->data_source(), Initialize(""))
+ .WillOnce(DoAll(InitializationComplete(mocks_->data_source()),
+ Return(true)));
+ EXPECT_CALL(*mocks_->data_source(), Stop());
+ }
+
+ // Sets up expectations to allow the demuxer to initialize.
+ void InitializeDemuxer(MockDemuxerStreamVector* streams) {
+ EXPECT_CALL(*mocks_->demuxer(), Initialize(mocks_->data_source()))
+ .WillOnce(DoAll(InitializationComplete(mocks_->demuxer()),
+ Return(true)));
+ EXPECT_CALL(*mocks_->demuxer(), GetNumberOfStreams())
+ .WillRepeatedly(Return(streams->size()));
+ EXPECT_CALL(*mocks_->demuxer(), Stop());
+
+ // Configure the demuxer to return the streams.
+ for (size_t i = 0; i < streams->size(); ++i) {
+ scoped_refptr<DemuxerStream> stream = (*streams)[i];
+ EXPECT_CALL(*mocks_->demuxer(), GetStream(i))
+ .WillRepeatedly(Return(stream));
+ }
+ }
+
+ // Sets up expectations to allow the video decoder to initialize.
+ void InitializeVideoDecoder(MockDemuxerStream* stream) {
+ EXPECT_CALL(*mocks_->video_decoder(), Initialize(stream))
+ .WillOnce(DoAll(InitializationComplete(mocks_->video_decoder()),
+ Return(true)));
+ EXPECT_CALL(*mocks_->video_decoder(), Stop());
+ }
+
+ // Sets up expectations to allow the audio decoder to initialize.
+ void InitializeAudioDecoder(MockDemuxerStream* stream) {
+ EXPECT_CALL(*mocks_->audio_decoder(), Initialize(stream))
+ .WillOnce(DoAll(InitializationComplete(mocks_->audio_decoder()),
+ Return(true)));
+ EXPECT_CALL(*mocks_->audio_decoder(), Stop());
+ }
+
+ // Sets up expectations to allow the video renderer to initialize.
+ void InitializeVideoRenderer() {
+ EXPECT_CALL(*mocks_->video_renderer(), Initialize(mocks_->video_decoder()))
+ .WillOnce(DoAll(InitializationComplete(mocks_->video_renderer()),
+ Return(true)));
+ EXPECT_CALL(*mocks_->video_renderer(), Stop());
+ }
+
+ // Sets up expectations to allow the audio renderer to initialize.
+ void InitializeAudioRenderer() {
+ EXPECT_CALL(*mocks_->audio_renderer(), Initialize(mocks_->audio_decoder()))
+ .WillOnce(DoAll(InitializationComplete(mocks_->audio_renderer()),
+ Return(true)));
+ EXPECT_CALL(*mocks_->audio_renderer(), Stop());
+ }
+
// Fixture members.
media::PipelineImpl pipeline_;
- scoped_refptr<media::old_mocks::MockFilterFactory> filters_;
- media::old_mocks::MockFilterConfig config_;
+ scoped_refptr<media::MockFilterFactory> mocks_;
bool initialize_result_;
bool seek_result_;
@@ -75,7 +135,9 @@ class PipelineImplTest : public testing::Test {
};
TEST_F(PipelineImplTest, NeverInitializes) {
- config_.data_source_behavior = media::old_mocks::MOCK_DATA_SOURCE_NEVER_INIT;
+ EXPECT_CALL(*mocks_->data_source(), Initialize(""))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*mocks_->data_source(), Stop());
// This test hangs during initialization by never calling
// InitializationComplete(). Make sure we tear down the pipeline properly.
@@ -86,7 +148,7 @@ TEST_F(PipelineImplTest, NeverInitializes) {
}
TEST_F(PipelineImplTest, RequiredFilterMissing) {
- config_.create_filter = false;
+ mocks_->set_creation_successful(false);
ASSERT_TRUE(InitializeAndWait());
EXPECT_FALSE(initialize_result_);
@@ -96,8 +158,11 @@ TEST_F(PipelineImplTest, RequiredFilterMissing) {
}
TEST_F(PipelineImplTest, URLNotFound) {
- config_.data_source_behavior =
- media::old_mocks::MOCK_DATA_SOURCE_URL_ERROR_IN_INIT;
+ EXPECT_CALL(*mocks_->data_source(), Initialize(""))
+ .WillOnce(DoAll(Error(mocks_->data_source(),
+ PIPELINE_ERROR_URL_NOT_FOUND),
+ Return(false)));
+ EXPECT_CALL(*mocks_->data_source(), Stop());
ASSERT_TRUE(InitializeAndWait());
EXPECT_FALSE(initialize_result_);
@@ -106,117 +171,128 @@ TEST_F(PipelineImplTest, URLNotFound) {
}
TEST_F(PipelineImplTest, NoStreams) {
- config_.has_audio = false;
- config_.has_video = false;
+ MockDemuxerStreamVector streams;
+ InitializeDataSource();
+ InitializeDemuxer(&streams);
ASSERT_TRUE(InitializeAndWait());
EXPECT_FALSE(initialize_result_);
EXPECT_FALSE(pipeline_.IsInitialized());
EXPECT_EQ(media::PIPELINE_ERROR_COULD_NOT_RENDER, pipeline_.GetError());
-
- EXPECT_FALSE(filters_->audio_decoder());
- EXPECT_FALSE(filters_->audio_renderer());
- EXPECT_FALSE(filters_->video_decoder());
- EXPECT_FALSE(filters_->video_renderer());
}
TEST_F(PipelineImplTest, AudioStream) {
- config_.has_video = false;
+ scoped_refptr<StrictMock<MockDemuxerStream> > stream =
+ new StrictMock<MockDemuxerStream>("audio/x-foo");
+ MockDemuxerStreamVector streams;
+ streams.push_back(stream);
+
+ InitializeDataSource();
+ InitializeDemuxer(&streams);
+ InitializeAudioDecoder(stream);
+ InitializeAudioRenderer();
ASSERT_TRUE(InitializeAndWait());
EXPECT_TRUE(initialize_result_);
EXPECT_TRUE(pipeline_.IsInitialized());
EXPECT_EQ(media::PIPELINE_OK, pipeline_.GetError());
-
- size_t width, height;
- pipeline_.GetVideoSize(&width, &height);
- EXPECT_EQ(0u, width);
- EXPECT_EQ(0u, height);
EXPECT_TRUE(pipeline_.IsRendered(media::mime_type::kMajorTypeAudio));
EXPECT_FALSE(pipeline_.IsRendered(media::mime_type::kMajorTypeVideo));
-
- EXPECT_TRUE(filters_->audio_decoder());
- EXPECT_TRUE(filters_->audio_renderer());
- EXPECT_FALSE(filters_->video_decoder());
- EXPECT_FALSE(filters_->video_renderer());
}
TEST_F(PipelineImplTest, VideoStream) {
- config_.has_audio = false;
+ scoped_refptr<StrictMock<MockDemuxerStream> > stream =
+ new StrictMock<MockDemuxerStream>("video/x-foo");
+ MockDemuxerStreamVector streams;
+ streams.push_back(stream);
+
+ InitializeDataSource();
+ InitializeDemuxer(&streams);
+ InitializeVideoDecoder(stream);
+ InitializeVideoRenderer();
ASSERT_TRUE(InitializeAndWait());
EXPECT_TRUE(initialize_result_);
EXPECT_TRUE(pipeline_.IsInitialized());
EXPECT_EQ(media::PIPELINE_OK, pipeline_.GetError());
-
- size_t width, height;
- pipeline_.GetVideoSize(&width, &height);
- EXPECT_EQ(config_.video_width, width);
- EXPECT_EQ(config_.video_height, height);
EXPECT_FALSE(pipeline_.IsRendered(media::mime_type::kMajorTypeAudio));
EXPECT_TRUE(pipeline_.IsRendered(media::mime_type::kMajorTypeVideo));
-
- EXPECT_FALSE(filters_->audio_decoder());
- EXPECT_FALSE(filters_->audio_renderer());
- EXPECT_TRUE(filters_->video_decoder());
- EXPECT_TRUE(filters_->video_renderer());
}
TEST_F(PipelineImplTest, AudioVideoStream) {
+ scoped_refptr<StrictMock<MockDemuxerStream> > audio_stream =
+ new StrictMock<MockDemuxerStream>("audio/x-foo");
+ scoped_refptr<StrictMock<MockDemuxerStream> > video_stream =
+ new StrictMock<MockDemuxerStream>("video/x-foo");
+ MockDemuxerStreamVector streams;
+ streams.push_back(audio_stream);
+ streams.push_back(video_stream);
+
+ InitializeDataSource();
+ InitializeDemuxer(&streams);
+ InitializeAudioDecoder(audio_stream);
+ InitializeAudioRenderer();
+ InitializeVideoDecoder(video_stream);
+ InitializeVideoRenderer();
+
ASSERT_TRUE(InitializeAndWait());
EXPECT_TRUE(initialize_result_);
EXPECT_TRUE(pipeline_.IsInitialized());
EXPECT_EQ(media::PIPELINE_OK, pipeline_.GetError());
-
- size_t width, height;
- pipeline_.GetVideoSize(&width, &height);
- EXPECT_EQ(config_.video_width, width);
- EXPECT_EQ(config_.video_height, height);
EXPECT_TRUE(pipeline_.IsRendered(media::mime_type::kMajorTypeAudio));
EXPECT_TRUE(pipeline_.IsRendered(media::mime_type::kMajorTypeVideo));
-
- EXPECT_TRUE(filters_->audio_decoder());
- EXPECT_TRUE(filters_->audio_renderer());
- EXPECT_TRUE(filters_->video_decoder());
- EXPECT_TRUE(filters_->video_renderer());
}
TEST_F(PipelineImplTest, Seek) {
- ASSERT_TRUE(InitializeAndWait());
-
- // Seek and verify callback returned true.
+ scoped_refptr<StrictMock<MockDemuxerStream> > audio_stream =
+ new StrictMock<MockDemuxerStream>("audio/x-foo");
+ scoped_refptr<StrictMock<MockDemuxerStream> > video_stream =
+ new StrictMock<MockDemuxerStream>("video/x-foo");
+ MockDemuxerStreamVector streams;
+ streams.push_back(audio_stream);
+ streams.push_back(video_stream);
+
+ InitializeDataSource();
+ InitializeDemuxer(&streams);
+ InitializeAudioDecoder(audio_stream);
+ InitializeAudioRenderer();
+ InitializeVideoDecoder(video_stream);
+ InitializeVideoRenderer();
+
+ // Every filter should receive a call to Seek().
base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
+ EXPECT_CALL(*mocks_->data_source(), Seek(expected));
+ EXPECT_CALL(*mocks_->demuxer(), Seek(expected));
+ EXPECT_CALL(*mocks_->audio_decoder(), Seek(expected));
+ EXPECT_CALL(*mocks_->audio_renderer(), Seek(expected));
+ EXPECT_CALL(*mocks_->video_decoder(), Seek(expected));
+ EXPECT_CALL(*mocks_->video_renderer(), Seek(expected));
+
+ // Initialize then seek!
+ ASSERT_TRUE(InitializeAndWait());
EXPECT_TRUE(SeekAndWait(expected));
EXPECT_TRUE(seek_result_);
-
- // Verify every filter received the seek.
- // TODO(scherkus): implement whatever it takes so I can use EXPECT_EQ with
- // base::TimeDelta.
- EXPECT_TRUE(expected == filters_->data_source()->seek_time());
- EXPECT_TRUE(expected == filters_->demuxer()->seek_time());
- EXPECT_TRUE(expected == filters_->audio_decoder()->seek_time());
- EXPECT_TRUE(expected == filters_->audio_renderer()->seek_time());
- EXPECT_TRUE(expected == filters_->video_decoder()->seek_time());
- EXPECT_TRUE(expected == filters_->video_renderer()->seek_time());
}
-// Try to execute Start()/Stop() on the Pipeline many times and very fast. This
-// test is trying to simulate the situation where the pipeline can get dead
-// locked very easily by quickly calling Start()/Stop().
-TEST_F(PipelineImplTest, StressTestPipelineStartStop) {
- media::old_mocks::MockFilterConfig config;
- const int kTimes = 1000;
- for (int i = 0; i < kTimes; ++i) {
- scoped_refptr<media::old_mocks::MockFilterFactory> factory =
- new media::old_mocks::MockFilterFactory(&config);
- media::PipelineImpl pipeline;
- pipeline.Start(factory.get(), "", NULL);
- pipeline.Stop();
- }
+TEST_F(PipelineImplTest, SetVolume) {
+ scoped_refptr<StrictMock<MockDemuxerStream> > audio_stream =
+ new StrictMock<MockDemuxerStream>("audio/x-foo");
+ MockDemuxerStreamVector streams;
+ streams.push_back(audio_stream);
+
+ InitializeDataSource();
+ InitializeDemuxer(&streams);
+ InitializeAudioDecoder(audio_stream);
+ InitializeAudioRenderer();
+
+ // The audio renderer should receive a call to SetVolume().
+ float expected = 0.5f;
+ EXPECT_CALL(*mocks_->audio_renderer(), SetVolume(expected));
+
+ // Initialize then set volume!
+ ASSERT_TRUE(InitializeAndWait());
+ pipeline_.SetVolume(expected);
}
-// TODO(ralphl): Add a unit test that makes sure that the mock audio filter
-// is actually called on a SetVolume() call to the pipeline. I almost checked
-// in code that broke this, but all unit tests were passing.
+} // namespace media
-} // namespace
diff --git a/media/base/video_frame_impl_unittest.cc b/media/base/video_frame_impl_unittest.cc
index a6a1a6a..eeec716 100644
--- a/media/base/video_frame_impl_unittest.cc
+++ b/media/base/video_frame_impl_unittest.cc
@@ -3,15 +3,40 @@
// found in the LICENSE file.
#include "media/base/buffers.h"
-#include "media/base/mock_media_filters.h"
+#include "media/base/mock_filters.h"
#include "media/base/video_frame_impl.h"
#include "media/base/yuv_convert.h"
#include "testing/gtest/include/gtest/gtest.h"
-using media::VideoFrameImpl;
-using media::VideoSurface;
+namespace media {
-namespace {
+// Helper function that initializes a YV12 frame with white and black scan
+// lines based on the |white_to_black| parameter. If 0, then the entire
+// frame will be black, if 1 then the entire frame will be white.
+void InitializeYV12Frame(VideoFrame* frame, double white_to_black) {
+ VideoSurface surface;
+ if (!frame->Lock(&surface)) {
+ ADD_FAILURE();
+ return;
+ }
+ EXPECT_EQ(surface.format, VideoSurface::YV12);
+ size_t first_black_row = static_cast<size_t>(surface.height * white_to_black);
+ uint8* y_plane = surface.data[VideoSurface::kYPlane];
+ for (size_t row = 0; row < surface.height; ++row) {
+ int color = (row < first_black_row) ? 0xFF : 0x00;
+ memset(y_plane, color, surface.width);
+ y_plane += surface.strides[VideoSurface::kYPlane];
+ }
+ uint8* u_plane = surface.data[VideoSurface::kUPlane];
+ uint8* v_plane = surface.data[VideoSurface::kVPlane];
+ for (size_t row = 0; row < surface.height; row += 2) {
+ memset(u_plane, 0x80, surface.width / 2);
+ memset(v_plane, 0x80, surface.width / 2);
+ u_plane += surface.strides[VideoSurface::kUPlane];
+ v_plane += surface.strides[VideoSurface::kVPlane];
+ }
+ frame->Unlock();
+}
// Given a |yv12_frame| this method converts the YV12 frame to RGBA and
// makes sure that all the pixels of the RBG frame equal |expect_rgb_color|.
@@ -65,10 +90,7 @@ void ExpectFrameColor(media::VideoFrame* yv12_frame, uint32 expect_rgb_color) {
yv12_frame->Unlock();
}
-} // namespace
-
-
-TEST(VideoFrameImpl, Basic) {
+TEST(VideoFrameImpl, CreateFrame) {
const size_t kWidth = 64;
const size_t kHeight = 48;
const base::TimeDelta kTimestampA = base::TimeDelta::FromMicroseconds(1337);
@@ -78,8 +100,8 @@ TEST(VideoFrameImpl, Basic) {
// Create a YV12 Video Frame.
scoped_refptr<media::VideoFrame> frame;
- media::VideoFrameImpl::CreateFrame(media::VideoSurface::YV12, kWidth, kHeight,
- kTimestampA, kDurationA, &frame);
+ VideoFrameImpl::CreateFrame(media::VideoSurface::YV12, kWidth, kHeight,
+ kTimestampA, kDurationA, &frame);
ASSERT_TRUE(frame);
// Test StreamSample implementation.
@@ -98,12 +120,14 @@ TEST(VideoFrameImpl, Basic) {
EXPECT_FALSE(frame->IsDiscontinuous());
// Test VideoFrame implementation.
- media::old_mocks::MockVideoDecoder::InitializeYV12Frame(frame, 0.0f);
+ InitializeYV12Frame(frame, 0.0f);
ExpectFrameColor(frame, 0xFF000000);
- media::old_mocks::MockVideoDecoder::InitializeYV12Frame(frame, 1.0f);
+ InitializeYV12Frame(frame, 1.0f);
ExpectFrameColor(frame, 0xFFFFFFFF);
// Test an empty frame.
- media::VideoFrameImpl::CreateEmptyFrame(&frame);
+ VideoFrameImpl::CreateEmptyFrame(&frame);
EXPECT_TRUE(frame->IsEndOfStream());
}
+
+} // namespace media
diff --git a/media/filters/ffmpeg_glue_unittest.cc b/media/filters/ffmpeg_glue_unittest.cc
index 993fb31..9f60868 100644
--- a/media/filters/ffmpeg_glue_unittest.cc
+++ b/media/filters/ffmpeg_glue_unittest.cc
@@ -2,65 +2,81 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "media/base/filters.h"
-#include "media/base/mock_media_filters.h"
+#include "media/base/mock_ffmpeg.h"
+#include "media/base/mock_filters.h"
#include "media/filters/ffmpeg_common.h"
#include "media/filters/ffmpeg_glue.h"
#include "testing/gtest/include/gtest/gtest.h"
-// FFmpeg mocks to remove dependency on having the DLLs present.
-extern "C" {
-static bool g_avcodec_init = false;
-static URLProtocol* g_protocol = NULL;
-static bool g_av_register_all = false;
-
-void avcodec_init() {
- EXPECT_FALSE(g_avcodec_init);
- g_avcodec_init = true;
-}
-
-int av_register_protocol(URLProtocol* protocol) {
- EXPECT_FALSE(g_protocol);
- g_protocol = protocol;
- return 0;
-}
-
-void av_register_all() {
- EXPECT_FALSE(g_av_register_all);
- g_av_register_all = true;
-}
-} // extern "C"
-
-TEST(FFmpegGlueTest, InitializeFFmpeg) {
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::InSequence;
+using ::testing::Return;
+using ::testing::SetArgumentPointee;
+using ::testing::StrictMock;
+
+namespace media {
+
+class FFmpegGlueTest : public ::testing::Test {
+ public:
+ FFmpegGlueTest() {
+ MockFFmpeg::set(&mock_ffmpeg_);
+ }
+
+ virtual ~FFmpegGlueTest() {
+ MockFFmpeg::set(NULL);
+ }
+
+ // Helper to open a URLContext pointing to the given mocked data source.
+ // Callers are expected to close the context at the end of their test.
+ virtual void OpenContext(MockDataSource* data_source, URLContext* context) {
+ // IsSeekable() is called when opening.
+ EXPECT_CALL(*data_source, IsSeekable()).WillOnce(Return(false));
+
+ // Add the data source to the glue layer and open a context.
+ std::string key = FFmpegGlue::get()->AddDataSource(data_source);
+ memset(context, 0, sizeof(*context));
+ EXPECT_EQ(0, protocol_->url_open(context, key.c_str(), 0));
+ FFmpegGlue::get()->RemoveDataSource(data_source);
+ }
+
+ protected:
+ // Fixture members.
+ MockFFmpeg mock_ffmpeg_;
+ static URLProtocol* protocol_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FFmpegGlueTest);
+};
+
+URLProtocol* FFmpegGlueTest::protocol_ = NULL;
+
+TEST_F(FFmpegGlueTest, InitializeFFmpeg) {
// Singleton should initialize FFmpeg.
- media::FFmpegGlue* glue = media::FFmpegGlue::get();
+ FFmpegGlue* glue = FFmpegGlue::get();
EXPECT_TRUE(glue);
- EXPECT_TRUE(g_avcodec_init);
- EXPECT_TRUE(g_protocol);
- EXPECT_TRUE(g_av_register_all);
+
+ // Assign our static copy of URLProtocol for the rest of the tests.
+ protocol_ = MockFFmpeg::protocol();
// Make sure URLProtocol was filled out correctly.
- EXPECT_STREQ("http", g_protocol->name);
- EXPECT_TRUE(g_protocol->url_close);
- EXPECT_TRUE(g_protocol->url_open);
- EXPECT_TRUE(g_protocol->url_read);
- EXPECT_TRUE(g_protocol->url_seek);
- EXPECT_TRUE(g_protocol->url_write);
+ EXPECT_STREQ("http", protocol_->name);
+ EXPECT_TRUE(protocol_->url_close);
+ EXPECT_TRUE(protocol_->url_open);
+ EXPECT_TRUE(protocol_->url_read);
+ EXPECT_TRUE(protocol_->url_seek);
+ EXPECT_TRUE(protocol_->url_write);
}
-TEST(FFmpegGlueTest, AddRemoveGetDataSource) {
+TEST_F(FFmpegGlueTest, AddRemoveGetDataSource) {
// Prepare testing data.
- media::FFmpegGlue* glue = media::FFmpegGlue::get();
+ FFmpegGlue* glue = FFmpegGlue::get();
// Create our data sources and add them to the glue layer.
- bool deleted_a = false;
- bool deleted_b = false;
- media::old_mocks::MockFilterConfig config_a;
- media::old_mocks::MockFilterConfig config_b;
- scoped_refptr<media::old_mocks::MockDataSource> data_source_a
- = new media::old_mocks::MockDataSource(&config_a, &deleted_a);
- scoped_refptr<media::old_mocks::MockDataSource> data_source_b
- = new media::old_mocks::MockDataSource(&config_b, &deleted_b);
+ scoped_refptr<StrictMock<Destroyable<MockDataSource> > > data_source_a
+ = new StrictMock<Destroyable<MockDataSource> >();
+ scoped_refptr<StrictMock<Destroyable<MockDataSource> > > data_source_b
+ = new StrictMock<Destroyable<MockDataSource> >();
// Make sure the keys are unique.
std::string key_a = glue->AddDataSource(data_source_a);
@@ -70,8 +86,8 @@ TEST(FFmpegGlueTest, AddRemoveGetDataSource) {
EXPECT_NE(key_a, key_b);
// Our keys should return our data sources.
- scoped_refptr<media::DataSource> data_source_c;
- scoped_refptr<media::DataSource> data_source_d;
+ scoped_refptr<DataSource> data_source_c;
+ scoped_refptr<DataSource> data_source_d;
glue->GetDataSource(key_a, &data_source_c);
glue->GetDataSource(key_b, &data_source_d);
EXPECT_EQ(data_source_a, data_source_c);
@@ -84,8 +100,13 @@ TEST(FFmpegGlueTest, AddRemoveGetDataSource) {
glue->GetDataSource(key_a2, &data_source_c);
EXPECT_EQ(data_source_a, data_source_c);
- // Removes the data sources and then releases our references. They should be
- // deleted.
+ // Removes the data sources then releases our references. They should be
+ // destroyed.
+ InSequence s;
+ EXPECT_CALL(*data_source_a, OnDestroy());
+ EXPECT_CALL(*data_source_b, OnDestroy());
+ EXPECT_CALL(mock_ffmpeg_, CheckPoint(0));
+
glue->RemoveDataSource(data_source_a);
glue->GetDataSource(key_a, &data_source_c);
EXPECT_FALSE(data_source_c);
@@ -94,23 +115,21 @@ TEST(FFmpegGlueTest, AddRemoveGetDataSource) {
glue->RemoveDataSource(data_source_b);
glue->GetDataSource(key_b, &data_source_d);
EXPECT_FALSE(data_source_d);
- EXPECT_FALSE(deleted_a);
- EXPECT_FALSE(deleted_b);
data_source_a = NULL;
data_source_b = NULL;
- EXPECT_TRUE(deleted_a);
- EXPECT_TRUE(deleted_b);
+
+ // Data sources should be deleted by this point.
+ mock_ffmpeg_.CheckPoint(0);
}
-TEST(FFmpegGlueTest, OpenClose) {
+TEST_F(FFmpegGlueTest, OpenClose) {
// Prepare testing data.
- media::FFmpegGlue* glue = media::FFmpegGlue::get();
+ FFmpegGlue* glue = FFmpegGlue::get();
// Create our data source and add them to the glue layer.
- bool deleted = false;
- media::old_mocks::MockFilterConfig config;
- scoped_refptr<media::old_mocks::MockDataSource> data_source
- = new media::old_mocks::MockDataSource(&config, &deleted);
+ scoped_refptr<StrictMock<Destroyable<MockDataSource> > > data_source
+ = new StrictMock<Destroyable<MockDataSource> >();
+ EXPECT_CALL(*data_source, IsSeekable()).WillOnce(Return(false));
std::string key = glue->AddDataSource(data_source);
// Prepare FFmpeg URLContext structure.
@@ -118,192 +137,174 @@ TEST(FFmpegGlueTest, OpenClose) {
memset(&context, 0, sizeof(context));
// Test opening a URLContext with a data source that doesn't exist.
- EXPECT_EQ(AVERROR_IO, g_protocol->url_open(&context, "foobar", 0));
+ EXPECT_EQ(AVERROR_IO, protocol_->url_open(&context, "foobar", 0));
// Test opening a URLContext with our data source.
- EXPECT_EQ(0, g_protocol->url_open(&context, key.c_str(), 0));
+ EXPECT_EQ(0, protocol_->url_open(&context, key.c_str(), 0));
EXPECT_EQ(URL_RDONLY, context.flags);
EXPECT_EQ(data_source, context.priv_data);
- EXPECT_FALSE(context.is_streamed);
+ EXPECT_TRUE(context.is_streamed);
+
+ // We're going to remove references one by one until the last reference is
+ // held by FFmpeg. Once we close the URLContext, the data source should be
+ // destroyed.
+ InSequence s;
+ EXPECT_CALL(mock_ffmpeg_, CheckPoint(0));
+ EXPECT_CALL(mock_ffmpeg_, CheckPoint(1));
+ EXPECT_CALL(*data_source, OnDestroy());
+ EXPECT_CALL(mock_ffmpeg_, CheckPoint(2));
// Remove the data source from the glue layer, releasing a reference.
glue->RemoveDataSource(data_source);
- EXPECT_FALSE(deleted);
+ mock_ffmpeg_.CheckPoint(0);
// Remove our own reference -- URLContext should maintain a reference.
data_source = NULL;
- EXPECT_FALSE(deleted);
+ mock_ffmpeg_.CheckPoint(1);
// Close the URLContext, which should release the final reference.
- EXPECT_EQ(0, g_protocol->url_close(&context));
- EXPECT_TRUE(deleted);
+ EXPECT_EQ(0, protocol_->url_close(&context));
+ mock_ffmpeg_.CheckPoint(2);
}
-TEST(FFmpegGlueTest, ReadingWriting) {
- // Prepare testing data.
- media::FFmpegGlue* glue = media::FFmpegGlue::get();
- const size_t kBufferSize = 16;
- unsigned char buffer[kBufferSize];
-
- // Configure MockDataSource to be 8 characters long and fill reads with
- // periods. Therefore our expected string should be a character of 8 periods.
- const int kExpectedSize = 8;
- media::old_mocks::MockFilterConfig config;
- config.media_total_bytes = kExpectedSize;
- config.data_source_value = '.';
- const char kExpected[] = "........";
- COMPILE_ASSERT(kExpectedSize == (arraysize(kExpected) - 1), string_length);
-
- // Create our data source and add them to the glue layer.
- bool deleted = false;
- scoped_refptr<media::old_mocks::MockDataSource> data_source
- = new media::old_mocks::MockDataSource(&config, &deleted);
- std::string key = glue->AddDataSource(data_source);
-
- // Open our data source and then remove it from the glue layer.
+TEST_F(FFmpegGlueTest, Write) {
+ scoped_refptr<StrictMock<MockDataSource> > data_source
+ = new StrictMock<MockDataSource>();
URLContext context;
- memset(&context, 0, sizeof(context));
- EXPECT_EQ(0, g_protocol->url_open(&context, key.c_str(), 0));
- glue->RemoveDataSource(data_source);
- EXPECT_FALSE(deleted);
-
- // Writing should always fail.
- EXPECT_EQ(AVERROR_IO, g_protocol->url_write(&context, NULL, 0));
- EXPECT_EQ(AVERROR_IO, g_protocol->url_write(&context, buffer, 0));
- EXPECT_EQ(AVERROR_IO, g_protocol->url_write(&context, buffer, -1));
- EXPECT_EQ(AVERROR_IO, g_protocol->url_write(&context, buffer, kBufferSize));
- EXPECT_EQ(0, data_source->position());
-
- // Reading should return same amount of bytes if <= kExpectedSize.
- EXPECT_EQ(0, g_protocol->url_read(&context, buffer, 0));
- EXPECT_EQ(kExpectedSize / 2,
- g_protocol->url_read(&context, buffer, kExpectedSize / 2));
- EXPECT_EQ(kExpectedSize,
- g_protocol->url_read(&context, buffer, kExpectedSize));
- buffer[kExpectedSize] = '\0';
- EXPECT_STREQ(kExpected, reinterpret_cast<char*>(buffer));
-
- // Test reading more than kExpectedSize for simulating EOF.
- EXPECT_EQ(kExpectedSize, g_protocol->url_read(&context, buffer, kBufferSize));
- buffer[kExpectedSize] = '\0';
- EXPECT_STREQ(kExpected, reinterpret_cast<char*>(buffer));
-
- // Close our data source.
- EXPECT_EQ(0, g_protocol->url_close(&context));
- EXPECT_FALSE(deleted);
-
- // Remove our own reference, which should release the final reference.
- data_source = NULL;
- EXPECT_TRUE(deleted);
-}
+ OpenContext(data_source, &context);
-TEST(FFmpegGlueTest, Seeking) {
- // Prepare testing data.
- media::FFmpegGlue* glue = media::FFmpegGlue::get();
- const int64 kSize = 32;
+ const int kBufferSize = 16;
+ uint8 buffer[kBufferSize];
- // Create our data source and add them to the glue layer.
- bool deleted = false;
- media::old_mocks::MockFilterConfig config;
- config.media_total_bytes = kSize;
- scoped_refptr<media::old_mocks::MockDataSource> data_source
- = new media::old_mocks::MockDataSource(&config, &deleted);
- std::string key = glue->AddDataSource(data_source);
+ // Writing should always fail and never call the data source.
+ EXPECT_EQ(AVERROR_IO, protocol_->url_write(&context, NULL, 0));
+ EXPECT_EQ(AVERROR_IO, protocol_->url_write(&context, buffer, 0));
+ EXPECT_EQ(AVERROR_IO, protocol_->url_write(&context, buffer, kBufferSize));
- // Open our data source and then remove it from the glue layer.
- URLContext context;
- memset(&context, 0, sizeof(context));
- EXPECT_EQ(0, g_protocol->url_open(&context, key.c_str(), 0));
- glue->RemoveDataSource(data_source);
- EXPECT_FALSE(deleted);
-
- // Test SEEK_SET operations.
- config.media_total_bytes = -1;
- EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, 0, SEEK_SET));
-
- config.media_total_bytes = kSize;
- EXPECT_TRUE(data_source->SetPosition(0));
- EXPECT_EQ(0, g_protocol->url_seek(&context, 0, SEEK_SET));
- EXPECT_TRUE(data_source->SetPosition(5));
- EXPECT_EQ(0, g_protocol->url_seek(&context, 0, SEEK_SET));
- EXPECT_EQ(0, data_source->position());
- EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, -5, SEEK_SET));
- EXPECT_EQ(0, data_source->position());
- EXPECT_EQ(kSize, g_protocol->url_seek(&context, kSize, SEEK_SET));
- EXPECT_EQ(kSize, data_source->position());
- EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, kSize+1, SEEK_SET));
- EXPECT_EQ(kSize, data_source->position());
-
- // Test SEEK_CUR operations.
- config.media_total_bytes = -1;
- EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, 0, SEEK_CUR));
-
- config.media_total_bytes = kSize;
- EXPECT_TRUE(data_source->SetPosition(0));
- EXPECT_EQ(0, g_protocol->url_seek(&context, 0, SEEK_CUR));
- EXPECT_TRUE(data_source->SetPosition(5));
- EXPECT_EQ(5, g_protocol->url_seek(&context, 0, SEEK_CUR));
- EXPECT_EQ(0, g_protocol->url_seek(&context, -5, SEEK_CUR));
- EXPECT_EQ(0, data_source->position());
- EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, -1, SEEK_CUR));
- EXPECT_EQ(kSize, g_protocol->url_seek(&context, kSize, SEEK_CUR));
- EXPECT_EQ(kSize, data_source->position());
- EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, 1, SEEK_CUR));
- EXPECT_EQ(kSize, data_source->position());
-
- // Test SEEK_END operations.
- config.media_total_bytes = -1;
- EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, 0, SEEK_END));
-
- config.media_total_bytes = kSize;
- EXPECT_TRUE(data_source->SetPosition(0));
- EXPECT_EQ(kSize, g_protocol->url_seek(&context, 0, SEEK_END));
- EXPECT_EQ(kSize, data_source->position());
- EXPECT_EQ(kSize-5, g_protocol->url_seek(&context, -5, SEEK_END));
- EXPECT_EQ(kSize-5, data_source->position());
- EXPECT_EQ(0, g_protocol->url_seek(&context, -kSize, SEEK_END));
- EXPECT_EQ(0, data_source->position());
- EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, 1, SEEK_END));
- EXPECT_EQ(0, data_source->position());
-
- // Test AVSEEK_SIZE operation.
- config.media_total_bytes = -1;
- EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, 0, AVSEEK_SIZE));
-
- config.media_total_bytes = kSize;
- EXPECT_TRUE(data_source->SetPosition(0));
- EXPECT_EQ(kSize, g_protocol->url_seek(&context, 0, AVSEEK_SIZE));
-
- // Close our data source.
- EXPECT_EQ(0, g_protocol->url_close(&context));
- EXPECT_FALSE(deleted);
-
- // Remove our own reference, which should release the final reference.
- data_source = NULL;
- EXPECT_TRUE(deleted);
+ // Destroy the data source.
+ protocol_->url_close(&context);
}
-TEST(FFmpegGlueTest, Destructor) {
- // Prepare testing data.
- media::FFmpegGlue* glue = media::FFmpegGlue::get();
+TEST_F(FFmpegGlueTest, Read) {
+ scoped_refptr<StrictMock<MockDataSource> > data_source
+ = new StrictMock<MockDataSource>();
+ URLContext context;
+ OpenContext(data_source, &context);
+
+ const int kBufferSize = 16;
+ uint8 buffer[kBufferSize];
+
+ // Reads are for the most part straight-through calls to Read().
+ InSequence s;
+ EXPECT_CALL(*data_source, Read(buffer, 0))
+ .WillOnce(Return(0));
+ EXPECT_CALL(*data_source, Read(buffer, kBufferSize))
+ .WillOnce(Return(kBufferSize));
+ EXPECT_CALL(*data_source, Read(buffer, kBufferSize))
+ .WillOnce(Return(DataSource::kReadError));
+
+ EXPECT_EQ(0, protocol_->url_read(&context, buffer, 0));
+ EXPECT_EQ(kBufferSize, protocol_->url_read(&context, buffer, kBufferSize));
+ EXPECT_EQ(AVERROR_IO, protocol_->url_read(&context, buffer, kBufferSize));
+
+ // Destroy the data source.
+ protocol_->url_close(&context);
+}
- // We use a static bool since ~FFmpegGlue() will set it to true sometime
- // after this function exits.
- static bool deleted = false;
+TEST_F(FFmpegGlueTest, Seek) {
+ scoped_refptr<StrictMock<MockDataSource> > data_source
+ = new StrictMock<MockDataSource>();
+ URLContext context;
+ OpenContext(data_source, &context);
+
+ // SEEK_SET should be a straight-through call to SetPosition(), which when
+ // successful will return the result from GetPosition().
+ InSequence s;
+ EXPECT_CALL(*data_source, SetPosition(-16))
+ .WillOnce(Return(false));
+
+ EXPECT_CALL(*data_source, SetPosition(16))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*data_source, GetPosition(_))
+ .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true)));
+
+ EXPECT_EQ(AVERROR_IO, protocol_->url_seek(&context, -16, SEEK_SET));
+ EXPECT_EQ(8, protocol_->url_seek(&context, 16, SEEK_SET));
+
+ // SEEK_CUR should call GetPosition() first, and if it succeeds add the offset
+ // to the result then call SetPosition()+GetPosition().
+ EXPECT_CALL(*data_source, GetPosition(_))
+ .WillOnce(Return(false));
+
+ EXPECT_CALL(*data_source, GetPosition(_))
+ .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true)));
+ EXPECT_CALL(*data_source, SetPosition(16))
+ .WillOnce(Return(false));
+
+ EXPECT_CALL(*data_source, GetPosition(_))
+ .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true)));
+ EXPECT_CALL(*data_source, SetPosition(16))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*data_source, GetPosition(_))
+ .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true)));
+
+ EXPECT_EQ(AVERROR_IO, protocol_->url_seek(&context, 8, SEEK_CUR));
+ EXPECT_EQ(AVERROR_IO, protocol_->url_seek(&context, 8, SEEK_CUR));
+ EXPECT_EQ(16, protocol_->url_seek(&context, 8, SEEK_CUR));
+
+ // SEEK_END should call GetSize() first, and if it succeeds add the offset
+ // to the result then call SetPosition()+GetPosition().
+ EXPECT_CALL(*data_source, GetSize(_))
+ .WillOnce(Return(false));
+
+ EXPECT_CALL(*data_source, GetSize(_))
+ .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true)));
+ EXPECT_CALL(*data_source, SetPosition(8))
+ .WillOnce(Return(false));
+
+ EXPECT_CALL(*data_source, GetSize(_))
+ .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true)));
+ EXPECT_CALL(*data_source, SetPosition(8))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*data_source, GetPosition(_))
+ .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true)));
+
+ EXPECT_EQ(AVERROR_IO, protocol_->url_seek(&context, -8, SEEK_END));
+ EXPECT_EQ(AVERROR_IO, protocol_->url_seek(&context, -8, SEEK_END));
+ EXPECT_EQ(8, protocol_->url_seek(&context, -8, SEEK_END));
+
+ // AVSEEK_SIZE should be a straight-through call to GetSize().
+ EXPECT_CALL(*data_source, GetSize(_))
+ .WillOnce(Return(false));
+
+ EXPECT_CALL(*data_source, GetSize(_))
+ .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true)));
+
+ EXPECT_EQ(AVERROR_IO, protocol_->url_seek(&context, 0, AVSEEK_SIZE));
+ EXPECT_EQ(16, protocol_->url_seek(&context, 0, AVSEEK_SIZE));
+
+ // Destroy the data source.
+ protocol_->url_close(&context);
+}
+TEST_F(FFmpegGlueTest, Destroy) {
// Create our data source and add them to the glue layer.
- media::old_mocks::MockFilterConfig config;
- scoped_refptr<media::old_mocks::MockDataSource> data_source
- = new media::old_mocks::MockDataSource(&config, &deleted);
- std::string key = glue->AddDataSource(data_source);
+ scoped_refptr<StrictMock<Destroyable<MockDataSource> > > data_source
+ = new StrictMock<Destroyable<MockDataSource> >();
+ std::string key = FFmpegGlue::get()->AddDataSource(data_source);
- // Remove our own reference.
+ // We should expect the data source to get destroyed when the unit test
+ // exits.
+ InSequence s;
+ EXPECT_CALL(mock_ffmpeg_, CheckPoint(0));
+ EXPECT_CALL(*data_source, OnDestroy());
+
+ // Remove our own reference, we shouldn't be destroyed yet.
data_source = NULL;
- EXPECT_FALSE(deleted);
+ mock_ffmpeg_.CheckPoint(0);
// ~FFmpegGlue() will be called when this unit test finishes execution. By
// leaving something inside FFmpegGlue's map we get to test our cleanup code.
- //
- // MockDataSource will be holding onto a bad MockFilterConfig pointer at this
- // point but since no one is calling it everything will be ok.
}
+
+} // namespace media
diff --git a/media/filters/test_video_decoder.h b/media/filters/test_video_decoder.h
deleted file mode 100644
index bb82c36..0000000
--- a/media/filters/test_video_decoder.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2009 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.
-//
-
-#ifndef MEDIA_FILTERS_TEST_VIDEO_DECODER_H_
-#define MEDIA_FILTERS_TEST_VIDEO_DECODER_H_
-
-#include <string>
-
-#include "media/base/buffers.h"
-#include "media/base/factory.h"
-#include "media/base/filters.h"
-#include "media/base/mock_media_filters.h"
-#include "media/base/video_frame_impl.h"
-#include "media/filters/decoder_base.h"
-
-namespace media {
-
-class TestVideoDecoder : public DecoderBase<VideoDecoder, VideoFrame> {
- public:
- TestVideoDecoder()
- : video_width_(0),
- video_height_(0) {
- }
-
- bool OnInitialize(DemuxerStream* demuxer_stream) {
- const MediaFormat& media_format = demuxer_stream->media_format();
- std::string mime_type;
- int width, height;
- if (media_format.GetAsString(MediaFormat::kMimeType, &mime_type) &&
- mime_type.compare(mime_type::kH264AnnexB) == 0 &&
- media_format.GetAsInteger(MediaFormat::kWidth, &width) &&
- media_format.GetAsInteger(MediaFormat::kHeight, &height)) {
- video_width_ = width;
- video_height_ = height;
- media_format_.SetAsString(MediaFormat::kMimeType,
- mime_type::kUncompressedVideo);
- media_format_.SetAsInteger(MediaFormat::kWidth, width);
- media_format_.SetAsInteger(MediaFormat::kHeight, height);
- return true;
- }
- return false;
- }
-
- void OnDecode(Buffer* buffer) {
- scoped_refptr<VideoFrame> frame;
- VideoFrameImpl::CreateFrame(VideoSurface::YV12,
- video_width_,
- video_height_,
- buffer->GetTimestamp(),
- buffer->GetDuration(),
- &frame);
- if (frame) {
- old_mocks::MockVideoDecoder::InitializeYV12Frame(frame, 0.5f);
- EnqueueResult(frame);
- } else {
- host_->Error(PIPELINE_ERROR_OUT_OF_MEMORY);
- }
- }
-
- static bool IsMediaFormatSupported(const MediaFormat& media_format) {
- std::string mime_type;
- return (media_format.GetAsString(MediaFormat::kMimeType, &mime_type) &&
- mime_type == mime_type::kH264AnnexB);
- }
-
- private:
- friend class scoped_refptr<TestVideoDecoder>;
- virtual ~TestVideoDecoder() {}
-
- size_t video_width_;
- size_t video_height_;
-
- DISALLOW_COPY_AND_ASSIGN(TestVideoDecoder);
-};
-
-} // namespace
-
-#endif // MEDIA_FILTERS_TEST_VIDEO_DECODER_H_
diff --git a/media/filters/test_video_renderer.h b/media/filters/test_video_renderer.h
deleted file mode 100644
index f9535f2..0000000
--- a/media/filters/test_video_renderer.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2009 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.
-//
-// Simple test class used by unit tests. Tests create the filter on the test's
-// thread and then use InstanceFilterFactory to force the test's instance to
-// be returned to the pipeline.
-
-#ifndef MEDIA_FILTERS_TEST_VIDEO_RENDERER_H_
-#define MEDIA_FILTERS_TEST_VIDEO_RENDERER_H_
-
-#include "media/base/buffers.h"
-#include "media/base/factory.h"
-#include "media/base/filters.h"
-#include "media/filters/video_renderer_base.h"
-
-namespace media {
-
-class TestVideoRenderer : public VideoRendererBase {
- public:
- TestVideoRenderer()
- : last_frame_(NULL),
- paint_called_(0),
- unique_frames_(0) {
- }
-
- virtual bool OnInitialize(size_t width, size_t height) { return true; }
-
- virtual void OnPaintNeeded() {
- ++paint_called_;
- scoped_refptr<VideoFrame> frame;
- GetCurrentFrame(&frame);
- if (frame.get()) {
- VideoSurface video_surface;
- EXPECT_TRUE(frame->Lock(&video_surface));
- frame->Unlock();
- if (frame != last_frame_) {
- ++unique_frames_;
- last_frame_ = frame;
- last_timestamp_ = frame->GetTimestamp();
- }
- }
- }
-
- size_t unique_frames() { return unique_frames_; }
- size_t paint_called() { return paint_called_; }
- base::TimeDelta last_timestamp() { return last_timestamp_; }
-
- static bool IsMediaFormatSupported(const MediaFormat& format) {
- return VideoRendererBase::IsMediaFormatSupported(format);
- }
-
- private:
- friend class scoped_refptr<TestVideoRenderer>;
- virtual ~TestVideoRenderer() {}
-
- VideoFrame* last_frame_;
- size_t paint_called_;
- size_t unique_frames_;
- base::TimeDelta last_timestamp_;
-
- DISALLOW_COPY_AND_ASSIGN(TestVideoRenderer);
-};
-
-} // namespace
-
-#endif // MEDIA_FILTERS_TEST_VIDEO_RENDERER_H_
diff --git a/media/media.gyp b/media/media.gyp
index aaa009f..3b15e80 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -101,8 +101,6 @@
'filters/file_data_source.h',
'filters/null_audio_renderer.cc',
'filters/null_audio_renderer.h',
- 'filters/test_video_decoder.h',
- 'filters/test_video_renderer.h',
'filters/video_renderer_base.cc',
'filters/video_renderer_base.h',
],
@@ -158,7 +156,6 @@
'base/mock_ffmpeg.h',
'base/mock_filter_host.h',
'base/mock_filters.h',
- 'base/mock_media_filters.h',
'base/mock_reader.h',
'base/pipeline_impl_unittest.cc',
'base/run_all_unittests.cc',