Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(860)

Unified Diff: media/filters/ffmpeg_demuxer_unittest.cc

Issue 7587012: Remove mock_ffmpeg and update media unittests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/filters/ffmpeg_demuxer_unittest.cc
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc
index 1113e9b3a920f495fcf6cc7142127163aafc68d2..36263a45fd23243cbbc963fa7a0c837fe514558e 100644
--- a/media/filters/ffmpeg_demuxer_unittest.cc
+++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -4,15 +4,18 @@
#include <deque>
+#include "base/file_path.h"
+#include "base/path_service.h"
#include "base/threading/thread.h"
#include "media/base/filters.h"
+#include "media/base/media.h"
#include "media/base/mock_callback.h"
-#include "media/base/mock_ffmpeg.h"
#include "media/base/mock_filter_host.h"
#include "media/base/mock_filters.h"
#include "media/base/mock_reader.h"
#include "media/ffmpeg/ffmpeg_common.h"
#include "media/filters/ffmpeg_demuxer.h"
+#include "media/filters/file_data_source.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::AnyNumber;
@@ -21,7 +24,8 @@ using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::NotNull;
using ::testing::Return;
-using ::testing::SetArgumentPointee;
+using ::testing::SaveArg;
+using ::testing::SetArgPointee;
using ::testing::StrictMock;
using ::testing::WithArgs;
using ::testing::_;
@@ -32,83 +36,21 @@ namespace media {
// FFmpeg, pipeline and filter host mocks.
class FFmpegDemuxerTest : public testing::Test {
protected:
- // These constants refer to the stream ordering inside AVFormatContext. We
- // simulate media with a data stream, audio stream and video stream. Having
- // the data stream first forces the audio and video streams to get remapped
- // from indices {1,2} to {0,1} respectively, which covers an important test
- // case.
- enum AVStreamIndex {
- AV_STREAM_DATA,
- AV_STREAM_VIDEO,
- AV_STREAM_AUDIO,
- AV_STREAM_MAX,
- };
-
- // These constants refer to the stream ordering inside an initialized
- // FFmpegDemuxer based on the ordering of the AVStreamIndex constants.
- enum DemuxerStreamIndex {
- DS_STREAM_VIDEO,
- DS_STREAM_AUDIO,
- DS_STREAM_MAX,
- };
-
- static const int kDurations[];
- static const int kChannels;
- static const int kSampleRate;
- static const int kWidth;
- static const int kHeight;
-
- static const size_t kDataSize;
- static const uint8 kAudioData[];
- static const uint8 kVideoData[];
- static const uint8* kNullData;
FFmpegDemuxerTest() {
+ EXPECT_TRUE(InitializeMediaLibraryForTesting());
+
// Create an FFmpegDemuxer.
demuxer_ = new FFmpegDemuxer(&message_loop_);
demuxer_->disable_first_seek_hack_for_testing();
// Inject a filter host and message loop and prepare a data source.
demuxer_->set_host(&host_);
- data_source_ = new StrictMock<MockDataSource>();
-
- EXPECT_CALL(*data_source_, Stop(NotNull()))
- .WillRepeatedly(Invoke(&RunStopFilterCallback));
-
- // Initialize FFmpeg fixtures.
- memset(&format_context_, 0, sizeof(format_context_));
- memset(&input_format_, 0, sizeof(input_format_));
- memset(&streams_, 0, sizeof(streams_));
- memset(&codecs_, 0, sizeof(codecs_));
-
- // Initialize AVCodecContext structures.
- codecs_[AV_STREAM_DATA].codec_type = AVMEDIA_TYPE_DATA;
- codecs_[AV_STREAM_DATA].codec_id = CODEC_ID_NONE;
-
- codecs_[AV_STREAM_VIDEO].codec_type = AVMEDIA_TYPE_VIDEO;
- codecs_[AV_STREAM_VIDEO].codec_id = CODEC_ID_THEORA;
- codecs_[AV_STREAM_VIDEO].width = kWidth;
- codecs_[AV_STREAM_VIDEO].height = kHeight;
-
- codecs_[AV_STREAM_AUDIO].codec_type = AVMEDIA_TYPE_AUDIO;
- codecs_[AV_STREAM_AUDIO].codec_id = CODEC_ID_VORBIS;
- codecs_[AV_STREAM_AUDIO].channels = kChannels;
- codecs_[AV_STREAM_AUDIO].sample_rate = kSampleRate;
-
- input_format_.name = "foo";
- format_context_.iformat = &input_format_;
-
- // Initialize AVStream and AVFormatContext structures. We set the time base
- // of the streams such that duration is reported in microseconds.
- format_context_.nb_streams = AV_STREAM_MAX;
- format_context_.streams = new AVStream*[AV_STREAM_MAX];
- for (size_t i = 0; i < AV_STREAM_MAX; ++i) {
- format_context_.streams[i] = &streams_[i];
- streams_[i].codec = &codecs_[i];
- streams_[i].duration = kDurations[i];
- streams_[i].time_base.den = 1 * base::Time::kMicrosecondsPerSecond;
- streams_[i].time_base.num = 1;
- }
+
+ EXPECT_CALL(host_, SetTotalBytes(_)).Times(AnyNumber());
+ EXPECT_CALL(host_, SetBufferedBytes(_)).Times(AnyNumber());
+ EXPECT_CALL(host_, SetCurrentReadPosition(_))
+ .WillRepeatedly(SaveArg<0>(&current_read_position_));
}
virtual ~FFmpegDemuxerTest() {
@@ -119,160 +61,114 @@ class FFmpegDemuxerTest : public testing::Test {
message_loop_.RunAllPending();
// Release the reference to the demuxer.
demuxer_ = NULL;
-
- if (format_context_.streams) {
- delete[] format_context_.streams;
- format_context_.streams = NULL;
- format_context_.nb_streams = 0;
- }
}
- // Sets up MockFFmpeg to allow FFmpegDemuxer to successfully initialize.
- void InitializeDemuxerMocks() {
- EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL))
- .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), Return(0)));
- EXPECT_CALL(mock_ffmpeg_, AVFindStreamInfo(&format_context_))
- .WillOnce(Return(0));
- EXPECT_CALL(mock_ffmpeg_, AVCloseInputFile(&format_context_));
- }
+ scoped_refptr<DataSource> CreateDataSource(const std::string& name) {
+ FilePath file_path;
+ EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
scherkus (not reviewing) 2011/08/11 01:26:29 can we use the ReadTestData functions here?
acolwell GONE FROM CHROMIUM 2011/08/11 23:54:40 No because we don't have an in-memory DataSource i
+
+ file_path = file_path.Append(FILE_PATH_LITERAL("media"))
+ .Append(FILE_PATH_LITERAL("test"))
+ .Append(FILE_PATH_LITERAL("data"))
+ .AppendASCII(name);
- // Initializes both MockFFmpeg and FFmpegDemuxer.
- void InitializeDemuxer() {
- InitializeDemuxerMocks();
+ scoped_refptr<FileDataSource> data_source = new FileDataSource();
- // Since we ignore data streams, the duration should be equal to the longest
- // supported stream's duration (audio, in this case).
- base::TimeDelta expected_duration =
- base::TimeDelta::FromMicroseconds(kDurations[AV_STREAM_AUDIO]);
- EXPECT_CALL(host_, SetDuration(expected_duration));
+ EXPECT_EQ(PIPELINE_OK, data_source->Initialize(file_path.MaybeAsASCII()));
+
+ return data_source.get();
+ }
- demuxer_->Initialize(data_source_.get(),
- NewExpectedStatusCB(PIPELINE_OK));
+ MOCK_METHOD1(CheckPoint, void(int v));
+
+ // Initializes FFmpegDemuxer.
+ void InitializeDemuxer(const scoped_refptr<DataSource>& data_source) {
+ EXPECT_CALL(host_, SetDuration(_));
+ demuxer_->Initialize(data_source, NewExpectedStatusCB(PIPELINE_OK));
message_loop_.RunAllPending();
}
+ void ValidateBuffer(const tracked_objects::Location& location,
scherkus (not reviewing) 2011/08/11 01:26:29 docs? what does this do exactly?
acolwell GONE FROM CHROMIUM 2011/08/11 23:54:40 Done. It just makes sure the buffer has the expect
+ const scoped_refptr<Buffer>& buffer,
+ size_t size, int64 timestampInMicroseconds) {
+ std::string location_str;
+ location.Write(true, false, &location_str);
+ location_str += "\n";
+ SCOPED_TRACE(location_str);
+ EXPECT_TRUE(buffer.get() != NULL);
+ EXPECT_EQ(size, buffer->GetDataSize());
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(timestampInMicroseconds),
+ buffer->GetTimestamp());
+ }
+
// Fixture members.
scoped_refptr<FFmpegDemuxer> demuxer_;
- scoped_refptr<StrictMock<MockDataSource> > data_source_;
StrictMock<MockFilterHost> host_;
MessageLoop message_loop_;
- // FFmpeg fixtures.
- AVFormatContext format_context_;
- AVInputFormat input_format_;
- AVCodecContext codecs_[AV_STREAM_MAX];
- AVStream streams_[AV_STREAM_MAX];
- MockFFmpeg mock_ffmpeg_;
+ int64 current_read_position_;
private:
DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest);
};
-// These durations are picked so that the demuxer chooses the longest supported
-// stream, which would be 30 in this case for the audio stream.
-const int FFmpegDemuxerTest::kDurations[AV_STREAM_MAX] = {100, 20, 30};
-const int FFmpegDemuxerTest::kChannels = 2;
-const int FFmpegDemuxerTest::kSampleRate = 44100;
-const int FFmpegDemuxerTest::kWidth = 1280;
-const int FFmpegDemuxerTest::kHeight = 720;
-
-const size_t FFmpegDemuxerTest::kDataSize = 4;
-const uint8 FFmpegDemuxerTest::kAudioData[kDataSize] = {0, 1, 2, 3};
-const uint8 FFmpegDemuxerTest::kVideoData[kDataSize] = {4, 5, 6, 7};
-const uint8* FFmpegDemuxerTest::kNullData = NULL;
-
TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) {
// Simulate av_open_input_file() failing.
- EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL))
- .WillOnce(Return(-1));
-
- demuxer_->Initialize(data_source_.get(),
+ EXPECT_CALL(host_, SetCurrentReadPosition(_));
+ demuxer_->Initialize(CreateDataSource("ten_byte_file"),
NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
- message_loop_.RunAllPending();
-}
-TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) {
- // Simulate av_find_stream_info() failing.
- EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL))
- .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), Return(0)));
- EXPECT_CALL(mock_ffmpeg_, AVFindStreamInfo(&format_context_))
- .WillOnce(Return(AVERROR(EIO)));
- EXPECT_CALL(mock_ffmpeg_, AVCloseInputFile(&format_context_));
-
- demuxer_->Initialize(
- data_source_.get(),
- NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE));
message_loop_.RunAllPending();
}
-TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) {
- // Simulate media with no parseable streams.
- {
- SCOPED_TRACE("");
- InitializeDemuxerMocks();
- }
- format_context_.nb_streams = 0;
+// TODO(acolwell): Uncomment this test when we discover a file that passes
+// av_open_input_file(), but has av_find_stream_info() fail.
+//
+//TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) {
+// demuxer_->Initialize(
+// CreateDataSource("find_stream_info_fail.webm"),
+// NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE));
+// message_loop_.RunAllPending();
+//}
+TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) {
+ // Open a file with no parseable streams.
+ EXPECT_CALL(host_, SetCurrentReadPosition(_));
demuxer_->Initialize(
- data_source_.get(),
+ CreateDataSource("no_streams.webm"),
NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS));
message_loop_.RunAllPending();
}
-TEST_F(FFmpegDemuxerTest, Initialize_DataStreamOnly) {
- // Simulate media with a data stream but no audio or video streams.
- {
- SCOPED_TRACE("");
- InitializeDemuxerMocks();
- }
- EXPECT_EQ(format_context_.streams[0], &streams_[AV_STREAM_DATA]);
- format_context_.nb_streams = 1;
-
- demuxer_->Initialize(
- data_source_.get(),
- NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS));
- message_loop_.RunAllPending();
-}
+// TODO(acolwell): Find a subtitle only file so we can uncomment this test.
+//
+//TEST_F(FFmpegDemuxerTest, Initialize_DataStreamOnly) {
+// demuxer_->Initialize(
+// CreateDataSource("subtitles_only.mp4"),,
+// NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS));
+// message_loop_.RunAllPending();
+//}
TEST_F(FFmpegDemuxerTest, Initialize_Successful) {
- {
- SCOPED_TRACE("");
- InitializeDemuxer();
- }
+ InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
// First stream should be video and support the FFmpegDemuxerStream interface.
scoped_refptr<DemuxerStream> stream =
demuxer_->GetStream(DemuxerStream::VIDEO);
ASSERT_TRUE(stream);
EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
- EXPECT_EQ(&streams_[AV_STREAM_VIDEO], stream->GetAVStream());
+ ASSERT_TRUE(stream->GetAVStream());
// Other stream should be audio and support the FFmpegDemuxerStream interface.
stream = demuxer_->GetStream(DemuxerStream::AUDIO);
ASSERT_TRUE(stream);
EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
- EXPECT_EQ(&streams_[AV_STREAM_AUDIO], stream->GetAVStream());
+ ASSERT_TRUE(stream->GetAVStream());
}
-TEST_F(FFmpegDemuxerTest, Read_DiscardUninteresting) {
- // We test that on a successful audio packet read, that the packet is
- // duplicated (FFmpeg memory management safety), and a copy of it ends up in
- // the DemuxerStream.
- {
- SCOPED_TRACE("");
- InitializeDemuxer();
- }
-
- // Ignore all AVFreePacket() calls. We check this elsewhere.
- EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
-
- // The demuxer will read a data packet which will get immediately freed,
- // followed by a read error to end the reading.
- InSequence s;
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketNoCount(AV_STREAM_DATA, kNullData, 0));
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(Return(AVERROR(EIO)));
+TEST_F(FFmpegDemuxerTest, Read_Audio) {
+ // We test that on a successful audio packet read.
+ InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
// Attempt a read from the audio stream and run the message loop until done.
scoped_refptr<DemuxerStream> audio =
@@ -280,231 +176,107 @@ TEST_F(FFmpegDemuxerTest, Read_DiscardUninteresting) {
scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
reader->Read(audio);
message_loop_.RunAllPending();
-
EXPECT_TRUE(reader->called());
- ASSERT_TRUE(reader->buffer());
- EXPECT_TRUE(reader->buffer()->IsEndOfStream());
-}
+ ValidateBuffer(FROM_HERE, reader->buffer(), 29, 0);
-TEST_F(FFmpegDemuxerTest, Read_Audio) {
- // We test that on a successful audio packet read, that the packet is
- // duplicated (FFmpeg memory management safety), and a copy of it ends up in
- // the DemuxerStream.
- {
- SCOPED_TRACE("");
- InitializeDemuxer();
- }
-
- // Ignore all AVFreePacket() calls. We check this via valgrind.
- EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
-
- // The demuxer will read a data packet which will get immediately freed,
- // followed by reading an audio packet...
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketNoCount(AV_STREAM_AUDIO, kAudioData, kDataSize));
- EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
- .WillOnce(Return(0));
-
- // Attempt a read from the audio stream and run the message loop until done.
- scoped_refptr<DemuxerStream> audio =
- demuxer_->GetStream(DemuxerStream::AUDIO);
- scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
+ reader->Reset();
reader->Read(audio);
message_loop_.RunAllPending();
-
EXPECT_TRUE(reader->called());
- ASSERT_TRUE(reader->buffer());
- ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
- EXPECT_EQ(0, memcmp(kAudioData, reader->buffer()->GetData(),
- reader->buffer()->GetDataSize()));
+ ValidateBuffer(FROM_HERE, reader->buffer(), 27, 3000);
}
TEST_F(FFmpegDemuxerTest, Read_Video) {
- // We test that on a successful video packet read, that the packet is
- // duplicated (FFmpeg memory management safety), and a copy of it ends up in
- // the DemuxerStream.
- {
- SCOPED_TRACE("");
- InitializeDemuxer();
- }
-
- // Ignore all AVFreePacket() calls. We check this via valgrind.
- EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
-
- // Simulate a successful frame read.
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketNoCount(AV_STREAM_VIDEO, kVideoData, kDataSize));
- EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
- .WillOnce(Return(0));
+ // We test that on a successful video packet read.
+ InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
// Attempt a read from the video stream and run the message loop until done.
scoped_refptr<DemuxerStream> video =
demuxer_->GetStream(DemuxerStream::VIDEO);
scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
+
reader->Read(video);
message_loop_.RunAllPending();
-
EXPECT_TRUE(reader->called());
- ASSERT_TRUE(reader->buffer());
- ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
- EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
- reader->buffer()->GetDataSize()));
-}
-
-TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) {
- // Test the start time is the first timestamp of the video and audio stream.
- const int64 kStartTime = 60000;
- // Set the audio and video stream's first timestamp.
- streams_[AV_STREAM_AUDIO].first_dts = kStartTime;
- streams_[AV_STREAM_VIDEO].first_dts = kStartTime;
- {
- SCOPED_TRACE("");
- InitializeDemuxer();
- }
-
- // Ignore all AVFreePacket() calls. We check this via valgrind.
- EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
+ ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0);
- const base::TimeDelta kExpectedTimestamp =
- base::TimeDelta::FromMicroseconds(kStartTime);
-
- // Simulate a successful frame read.
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketTimeNoCount(AV_STREAM_VIDEO,
- kVideoData,
- kDataSize,
- kStartTime));
- EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
- .WillOnce(Return(0));
-
- // Attempt a read from the video stream and run the message loop until done.
- scoped_refptr<DemuxerStream> video =
- demuxer_->GetStream(DemuxerStream::VIDEO);
- scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
+ reader->Reset();
reader->Read(video);
message_loop_.RunAllPending();
-
EXPECT_TRUE(reader->called());
- ASSERT_TRUE(reader->buffer());
- ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
- EXPECT_EQ(kExpectedTimestamp, reader->buffer()->GetTimestamp());
- EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
- reader->buffer()->GetDataSize()));
-
- EXPECT_EQ(kExpectedTimestamp, demuxer_->GetStartTime());
+ ValidateBuffer(FROM_HERE, reader->buffer(), 1057, 33000);
}
-TEST_F(FFmpegDemuxerTest, CheckMinStartTime) {
- // Test the start time is minimum timestamp of all streams.
- const int64 kAudioStartTime = 5000000;
- const int64 kVideoStartTime = 5033000;
- // Set the audio and video stream's first timestamp.
- streams_[AV_STREAM_AUDIO].first_dts = kAudioStartTime;
- streams_[AV_STREAM_VIDEO].first_dts = kVideoStartTime;
- {
- SCOPED_TRACE("");
- InitializeDemuxer();
- }
-
- // Ignore all AVFreePacket() calls. We check this via valgrind.
- EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
-
- // Expect all calls in sequence.
- InSequence s;
+TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) {
+ // Test the start time is the first timestamp of the video and audio stream.
+ InitializeDemuxer(CreateDataSource("nonzero-start-time.webm"));
- const base::TimeDelta kExpectedAudioTimestamp =
- base::TimeDelta::FromMicroseconds(kAudioStartTime);
- const base::TimeDelta kExpectedVideoTimestamp =
- base::TimeDelta::FromMicroseconds(kVideoStartTime);
-
- // First read a video packet, then an audio packet.
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketTimeNoCount(AV_STREAM_AUDIO,
- kAudioData,
- kDataSize,
- kAudioStartTime));
- EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
- .WillOnce(Return(0));
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketTimeNoCount(AV_STREAM_VIDEO,
- kVideoData,
- kDataSize,
- kVideoStartTime));
- EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
- .WillOnce(Return(0));
+ const base::TimeDelta kExpectedTimestamp =
+ base::TimeDelta::FromMicroseconds(396000);
// Attempt a read from the video stream and run the message loop until done.
scoped_refptr<DemuxerStream> video =
demuxer_->GetStream(DemuxerStream::VIDEO);
scoped_refptr<DemuxerStream> audio =
demuxer_->GetStream(DemuxerStream::AUDIO);
- ASSERT_TRUE(video);
- ASSERT_TRUE(audio);
-
scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
+
+ // Check first buffer in video stream.
reader->Read(video);
message_loop_.RunAllPending();
-
EXPECT_TRUE(reader->called());
- ASSERT_TRUE(reader->buffer());
- ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
- EXPECT_EQ(kExpectedVideoTimestamp, reader->buffer()->GetTimestamp());
- EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
- reader->buffer()->GetDataSize()));
-
- EXPECT_EQ(kExpectedAudioTimestamp, demuxer_->GetStartTime());
+ ValidateBuffer(FROM_HERE, reader->buffer(), 5636, 400000);
+ const base::TimeDelta video_timestamp = reader->buffer()->GetTimestamp();
+ // Check first buffer in audio stream.
reader->Reset();
reader->Read(audio);
message_loop_.RunAllPending();
EXPECT_TRUE(reader->called());
- ASSERT_TRUE(reader->buffer());
- ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
- EXPECT_EQ(kExpectedAudioTimestamp, reader->buffer()->GetTimestamp());
- EXPECT_EQ(0, memcmp(kAudioData, reader->buffer()->GetData(),
- reader->buffer()->GetDataSize()));
+ ValidateBuffer(FROM_HERE, reader->buffer(), 165, 396000);
+ const base::TimeDelta audio_timestamp = reader->buffer()->GetTimestamp();
- EXPECT_EQ(kExpectedAudioTimestamp, demuxer_->GetStartTime());
+ // Verify that the start time is equal to the lowest timestamp.
+ EXPECT_EQ(std::min(audio_timestamp, video_timestamp),
+ demuxer_->GetStartTime());
}
TEST_F(FFmpegDemuxerTest, Read_EndOfStream) {
- // On end of stream, a new, empty, AVPackets are created without any data for
- // each stream and enqueued into the Buffer stream. Verify that these are
- // indeed inserted.
- {
- SCOPED_TRACE("");
- InitializeDemuxer();
- }
-
- // Ignore all AVFreePacket() calls. We check this via valgrind.
- EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
-
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(Return(AVERROR(EIO)));
+ // Verify that end of stream buffers are created.
+ InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
// We should now expect an end of stream buffer.
scoped_refptr<DemuxerStream> audio =
demuxer_->GetStream(DemuxerStream::AUDIO);
scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
- reader->Read(audio);
- message_loop_.RunAllPending();
- EXPECT_TRUE(reader->called());
- ASSERT_TRUE(reader->buffer());
- EXPECT_TRUE(reader->buffer()->IsEndOfStream());
- EXPECT_TRUE(reader->buffer()->GetData() == NULL);
- EXPECT_EQ(0u, reader->buffer()->GetDataSize());
+
+ bool got_eos_buffer = false;
+ const int kMaxBuffers = 170;
+ for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) {
+ reader->Read(audio);
+ message_loop_.RunAllPending();
+ EXPECT_TRUE(reader->called());
+ ASSERT_TRUE(reader->buffer());
+
+ if (reader->buffer()->IsEndOfStream()) {
+ got_eos_buffer = true;
+ EXPECT_TRUE(reader->buffer()->GetData() == NULL);
+ EXPECT_EQ(0u, reader->buffer()->GetDataSize());
+ break;
+ }
+
+ EXPECT_TRUE(reader->buffer()->GetData() != NULL);
+ EXPECT_GT(reader->buffer()->GetDataSize(), 0u);
+ reader->Reset();
+ }
+
+ EXPECT_TRUE(got_eos_buffer);
}
TEST_F(FFmpegDemuxerTest, Seek) {
// We're testing that the demuxer frees all queued packets when it receives
// a Seek().
- //
- // Since we can't test which packets are being freed, we use check points to
- // infer that the correct packets have been freed.
- {
- SCOPED_TRACE("");
- InitializeDemuxer();
- }
+ InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
// Get our streams.
scoped_refptr<DemuxerStream> video =
@@ -514,129 +286,52 @@ TEST_F(FFmpegDemuxerTest, Seek) {
ASSERT_TRUE(video);
ASSERT_TRUE(audio);
- // Expected values.
- const int64 kExpectedTimestamp = 1234;
- const int64 kExpectedFlags = AVSEEK_FLAG_BACKWARD;
-
- // Ignore all AVFreePacket() calls. We check this via valgrind.
- EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
-
- // Expect all calls in sequence.
- InSequence s;
-
- // First we'll read a video packet that causes two audio packets to be queued
- // inside FFmpegDemuxer...
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketNoCount(AV_STREAM_AUDIO, kAudioData, kDataSize));
- EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
- .WillOnce(Return(0));
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketNoCount(AV_STREAM_AUDIO, kAudioData, kDataSize));
- EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
- .WillOnce(Return(0));
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketNoCount(AV_STREAM_VIDEO, kVideoData, kDataSize));
- EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
- .WillOnce(Return(0));
-
- EXPECT_CALL(mock_ffmpeg_, CheckPoint(1));
-
- // ...then we'll expect a seek call...
- EXPECT_CALL(mock_ffmpeg_,
- AVSeekFrame(&format_context_, -1, kExpectedTimestamp, kExpectedFlags))
- .WillOnce(Return(0));
-
- // ...then our callback will be executed...
- FilterStatusCB seek_cb = NewExpectedStatusCB(PIPELINE_OK);
- EXPECT_CALL(mock_ffmpeg_, CheckPoint(2));
-
- // ...followed by two audio packet reads we'll trigger...
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketNoCount(AV_STREAM_AUDIO, kAudioData, kDataSize));
- EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
- .WillOnce(Return(0));
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketNoCount(AV_STREAM_AUDIO, kAudioData, kDataSize));
- EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
- .WillOnce(Return(0));
-
- // ...followed by two video packet reads...
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketNoCount(AV_STREAM_VIDEO, kVideoData, kDataSize));
- EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
- .WillOnce(Return(0));
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketNoCount(AV_STREAM_VIDEO, kVideoData, kDataSize));
- EXPECT_CALL(mock_ffmpeg_, AVDupPacket(_))
- .WillOnce(Return(0));
-
- // ...and finally a sanity checkpoint to make sure everything was released.
- EXPECT_CALL(mock_ffmpeg_, CheckPoint(3));
-
// Read a video packet and release it.
scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
reader->Read(video);
message_loop_.RunAllPending();
EXPECT_TRUE(reader->called());
- ASSERT_TRUE(reader->buffer());
- ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
- EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
- reader->buffer()->GetDataSize()));
+ ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0);
// Release the video packet and verify the other packets are still queued.
reader->Reset();
message_loop_.RunAllPending();
- mock_ffmpeg_.CheckPoint(1);
// Issue a simple forward seek, which should discard queued packets.
- demuxer_->Seek(base::TimeDelta::FromMicroseconds(kExpectedTimestamp),
- seek_cb);
+ demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
+ NewExpectedStatusCB(PIPELINE_OK));
message_loop_.RunAllPending();
- mock_ffmpeg_.CheckPoint(2);
// Audio read #1.
reader->Read(audio);
message_loop_.RunAllPending();
EXPECT_TRUE(reader->called());
- ASSERT_TRUE(reader->buffer());
- ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
- EXPECT_EQ(0, memcmp(kAudioData, reader->buffer()->GetData(),
- reader->buffer()->GetDataSize()));
+ ValidateBuffer(FROM_HERE, reader->buffer(), 145, 803000);
// Audio read #2.
reader->Reset();
reader->Read(audio);
message_loop_.RunAllPending();
EXPECT_TRUE(reader->called());
- ASSERT_TRUE(reader->buffer());
- ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
- EXPECT_EQ(0, memcmp(kAudioData, reader->buffer()->GetData(),
- reader->buffer()->GetDataSize()));
+ ValidateBuffer(FROM_HERE, reader->buffer(), 148, 826000);
// Video read #1.
reader->Reset();
reader->Read(video);
message_loop_.RunAllPending();
EXPECT_TRUE(reader->called());
- ASSERT_TRUE(reader->buffer());
- ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
- EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
- reader->buffer()->GetDataSize()));
+ ValidateBuffer(FROM_HERE, reader->buffer(), 5425, 801000);
// Video read #2.
reader->Reset();
reader->Read(video);
message_loop_.RunAllPending();
EXPECT_TRUE(reader->called());
- ASSERT_TRUE(reader->buffer());
- ASSERT_EQ(kDataSize, reader->buffer()->GetDataSize());
- EXPECT_EQ(0, memcmp(kVideoData, reader->buffer()->GetData(),
- reader->buffer()->GetDataSize()));
+ ValidateBuffer(FROM_HERE, reader->buffer(), 1906, 834000);
// Manually release the last reference to the buffer and verify it was freed.
reader->Reset();
message_loop_.RunAllPending();
- mock_ffmpeg_.CheckPoint(3);
}
// A mocked callback specialization for calling Read(). Since RunWithParams()
@@ -659,21 +354,13 @@ class MockReadCallback : public base::RefCountedThreadSafe<MockReadCallback> {
TEST_F(FFmpegDemuxerTest, Stop) {
// Tests that calling Read() on a stopped demuxer immediately deletes the
// callback.
- {
- SCOPED_TRACE("");
- InitializeDemuxer();
- }
+ InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
// Get our stream.
scoped_refptr<DemuxerStream> audio =
demuxer_->GetStream(DemuxerStream::AUDIO);
ASSERT_TRUE(audio);
- // Stop the demuxer, overriding the default expectation to assert that
- // data_source_ really is Stop()'d.
- EXPECT_CALL(*data_source_, Stop(_))
- .WillOnce(Invoke(&RunStopFilterCallback))
- .RetiresOnSaturation();
demuxer_->Stop(NewExpectedCallback());
// Expect all calls in sequence.
@@ -686,7 +373,7 @@ TEST_F(FFmpegDemuxerTest, Stop) {
// The callback should be immediately deleted. We'll use a checkpoint to
// verify that it has indeed been deleted.
EXPECT_CALL(*callback, OnDelete());
- EXPECT_CALL(mock_ffmpeg_, CheckPoint(1));
+ EXPECT_CALL(*this, CheckPoint(1));
// Attempt the read...
audio->Read(base::Bind(&MockReadCallback::Run, callback));
@@ -694,7 +381,7 @@ TEST_F(FFmpegDemuxerTest, Stop) {
message_loop_.RunAllPending();
// ...and verify that |callback| was deleted.
- mock_ffmpeg_.CheckPoint(1);
+ CheckPoint(1);
}
TEST_F(FFmpegDemuxerTest, DisableAudioStream) {
@@ -702,38 +389,32 @@ TEST_F(FFmpegDemuxerTest, DisableAudioStream) {
// 1. Initialize the demuxer with audio and video stream.
// 2. Send a "disable audio stream" message to the demuxer.
// 3. Demuxer will free audio packets even if audio stream was initialized.
- {
- SCOPED_TRACE("");
- InitializeDemuxer();
- }
+ InitializeDemuxer(CreateDataSource("bear-320x240.webm"));
// Submit a "disable audio stream" message to the demuxer.
demuxer_->OnAudioRendererDisabled();
message_loop_.RunAllPending();
- // Ignore all AVFreePacket() calls. We check this via valgrind.
- EXPECT_CALL(mock_ffmpeg_, AVFreePacket(_)).Times(AnyNumber());
-
- // Expect all calls in sequence.
- InSequence s;
-
- // The demuxer will read an audio packet which will get immediately freed.
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(CreatePacketNoCount(AV_STREAM_AUDIO, kNullData, 0));
-
- // Then an end-of-stream packet is read.
- EXPECT_CALL(mock_ffmpeg_, AVReadFrame(&format_context_, _))
- .WillOnce(Return(AVERROR(EIO)));
-
// Get our streams.
scoped_refptr<DemuxerStream> video =
demuxer_->GetStream(DemuxerStream::VIDEO);
+ scoped_refptr<DemuxerStream> audio =
+ demuxer_->GetStream(DemuxerStream::AUDIO);
ASSERT_TRUE(video);
+ ASSERT_TRUE(audio);
// Attempt a read from the video stream and run the message loop until done.
scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
reader->Read(video);
message_loop_.RunAllPending();
+ EXPECT_TRUE(reader->called());
+ ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0);
+
+ reader->Reset();
+ reader->Read(audio);
+ message_loop_.RunAllPending();
+ EXPECT_TRUE(reader->called());
+ EXPECT_TRUE(reader->buffer()->IsEndOfStream());
}
class MockFFmpegDemuxer : public FFmpegDemuxer {
@@ -758,19 +439,25 @@ void RunCallback(size_t size, DataSource::ReadCallback* callback) {
}
TEST_F(FFmpegDemuxerTest, ProtocolRead) {
+ scoped_refptr<StrictMock<MockDataSource> > data_source =
+ new StrictMock<MockDataSource>();
+
+ EXPECT_CALL(*data_source, Stop(NotNull()))
+ .WillRepeatedly(Invoke(&RunStopFilterCallback));
+
// Creates a demuxer.
scoped_refptr<MockFFmpegDemuxer> demuxer(
new MockFFmpegDemuxer(&message_loop_));
ASSERT_TRUE(demuxer);
demuxer->set_host(&host_);
- demuxer->data_source_ = data_source_;
+ demuxer->data_source_ = data_source;
uint8 kBuffer[1];
InSequence s;
// Actions taken in the first read.
- EXPECT_CALL(*data_source_, GetSize(_))
- .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
- EXPECT_CALL(*data_source_, Read(0, 512, kBuffer, NotNull()))
+ EXPECT_CALL(*data_source, GetSize(_))
+ .WillOnce(DoAll(SetArgPointee<0>(1024), Return(true)));
+ EXPECT_CALL(*data_source, Read(0, 512, kBuffer, NotNull()))
.WillOnce(WithArgs<1, 3>(Invoke(&RunCallback)));
EXPECT_CALL(*demuxer, SignalReadCompleted(512));
EXPECT_CALL(*demuxer, WaitForRead())
@@ -778,9 +465,9 @@ TEST_F(FFmpegDemuxerTest, ProtocolRead) {
EXPECT_CALL(host_, SetCurrentReadPosition(512));
// Second read.
- EXPECT_CALL(*data_source_, GetSize(_))
- .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
- EXPECT_CALL(*data_source_, Read(512, 512, kBuffer, NotNull()))
+ EXPECT_CALL(*data_source, GetSize(_))
+ .WillOnce(DoAll(SetArgPointee<0>(1024), Return(true)));
+ EXPECT_CALL(*data_source, Read(512, 512, kBuffer, NotNull()))
.WillOnce(WithArgs<1, 3>(Invoke(&RunCallback)));
EXPECT_CALL(*demuxer, SignalReadCompleted(512));
EXPECT_CALL(*demuxer, WaitForRead())
@@ -788,8 +475,8 @@ TEST_F(FFmpegDemuxerTest, ProtocolRead) {
EXPECT_CALL(host_, SetCurrentReadPosition(1024));
// Third read will fail because it exceeds the file size.
- EXPECT_CALL(*data_source_, GetSize(_))
- .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
+ EXPECT_CALL(*data_source, GetSize(_))
+ .WillOnce(DoAll(SetArgPointee<0>(1024), Return(true)));
// First read.
EXPECT_EQ(512, demuxer->Read(512, kBuffer));
@@ -812,52 +499,42 @@ TEST_F(FFmpegDemuxerTest, ProtocolRead) {
}
TEST_F(FFmpegDemuxerTest, ProtocolGetSetPosition) {
- {
- SCOPED_TRACE("");
- InitializeDemuxer();
- }
+ scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm");
+ InitializeDemuxer(data_source);
InSequence s;
- EXPECT_CALL(*data_source_, GetSize(_))
- .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
- EXPECT_CALL(*data_source_, GetSize(_))
- .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
- EXPECT_CALL(*data_source_, GetSize(_))
- .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
-
+ int64 size;
int64 position;
+ EXPECT_TRUE(demuxer_->GetSize(&size));
EXPECT_TRUE(demuxer_->GetPosition(&position));
- EXPECT_EQ(0, position);
+ EXPECT_EQ(current_read_position_, position);
EXPECT_TRUE(demuxer_->SetPosition(512));
- EXPECT_FALSE(demuxer_->SetPosition(2048));
+ EXPECT_FALSE(demuxer_->SetPosition(size));
+ EXPECT_FALSE(demuxer_->SetPosition(size + 1));
EXPECT_FALSE(demuxer_->SetPosition(-1));
EXPECT_TRUE(demuxer_->GetPosition(&position));
EXPECT_EQ(512, position);
}
TEST_F(FFmpegDemuxerTest, ProtocolGetSize) {
- {
- SCOPED_TRACE("");
- InitializeDemuxer();
- }
-
- EXPECT_CALL(*data_source_, GetSize(_))
- .WillOnce(DoAll(SetArgumentPointee<0>(1024), Return(true)));
-
- int64 size;
- EXPECT_TRUE(demuxer_->GetSize(&size));
- EXPECT_EQ(1024, size);
+ scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm");
+ InitializeDemuxer(data_source);
+
+ int64 data_source_size = 0;
+ int64 demuxer_size = 0;
+ EXPECT_TRUE(data_source->GetSize(&data_source_size));
+ EXPECT_TRUE(demuxer_->GetSize(&demuxer_size));
+ EXPECT_NE(0, data_source_size);
+ EXPECT_EQ(data_source_size, demuxer_size);
}
TEST_F(FFmpegDemuxerTest, ProtocolIsStreaming) {
- {
- SCOPED_TRACE("");
- InitializeDemuxer();
- }
- EXPECT_CALL(*data_source_, IsStreaming())
- .WillOnce(Return(false));
+ scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm");
+ InitializeDemuxer(data_source);
+
+ EXPECT_FALSE(data_source->IsStreaming());
EXPECT_FALSE(demuxer_->IsStreaming());
}

Powered by Google App Engine
This is Rietveld 408576698