1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/file_path.h"
10 #include "base/file_util.h"
11 #include "base/path_service.h"
12 #include "base/threading/thread.h"
13 #include "media/base/filters.h"
14 #include "media/base/mock_callback.h"
15 #include "media/base/mock_demuxer_host.h"
16 #include "media/base/mock_filters.h"
17 #include "media/base/mock_reader.h"
18 #include "media/ffmpeg/ffmpeg_common.h"
19 #include "media/filters/ffmpeg_demuxer.h"
20 #include "media/filters/file_data_source.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using ::testing::AnyNumber
;
24 using ::testing::DoAll
;
25 using ::testing::InSequence
;
26 using ::testing::Invoke
;
27 using ::testing::NotNull
;
28 using ::testing::Return
;
29 using ::testing::SaveArg
;
30 using ::testing::SetArgPointee
;
31 using ::testing::StrictMock
;
32 using ::testing::WithArgs
;
37 MATCHER(IsEndOfStreamBuffer
,
38 std::string(negation
? "isn't" : "is") + " end of stream") {
39 return arg
->IsEndOfStream();
42 // Fixture class to facilitate writing tests. Takes care of setting up the
43 // FFmpeg, pipeline and filter host mocks.
44 class FFmpegDemuxerTest
: public testing::Test
{
46 FFmpegDemuxerTest() {}
48 virtual ~FFmpegDemuxerTest() {
50 // Call Stop() to shut down internal threads.
51 demuxer_
->Stop(NewExpectedClosure());
54 // Finish up any remaining tasks.
55 message_loop_
.RunAllPending();
56 // Release the reference to the demuxer.
60 void CreateDemuxer(const std::string
& name
) {
61 CreateDemuxer(name
, false);
64 void CreateDemuxer(const std::string
& name
, bool disable_file_size
) {
67 EXPECT_CALL(host_
, SetTotalBytes(_
)).Times(AnyNumber());
68 EXPECT_CALL(host_
, SetBufferedBytes(_
)).Times(AnyNumber());
69 EXPECT_CALL(host_
, SetCurrentReadPosition(_
))
70 .WillRepeatedly(SaveArg
<0>(¤t_read_position_
));
72 CreateDataSource(name
, disable_file_size
);
73 demuxer_
= new FFmpegDemuxer(&message_loop_
, data_source_
);
76 MOCK_METHOD1(CheckPoint
, void(int v
));
78 void InitializeDemuxer() {
79 EXPECT_CALL(host_
, SetDuration(_
));
80 demuxer_
->Initialize(&host_
, NewExpectedStatusCB(PIPELINE_OK
));
81 message_loop_
.RunAllPending();
84 // Verifies that |buffer| has a specific |size| and |timestamp|.
85 // |location| simply indicates where the call to this function was made.
86 // This makes it easier to track down where test failures occur.
87 void ValidateBuffer(const tracked_objects::Location
& location
,
88 const scoped_refptr
<Buffer
>& buffer
,
89 int size
, int64 timestampInMicroseconds
) {
90 std::string location_str
;
91 location
.Write(true, false, &location_str
);
93 SCOPED_TRACE(location_str
);
94 EXPECT_TRUE(buffer
.get() != NULL
);
95 EXPECT_EQ(size
, buffer
->GetDataSize());
96 EXPECT_EQ(base::TimeDelta::FromMicroseconds(timestampInMicroseconds
),
97 buffer
->GetTimestamp());
100 // Accessor to demuxer internals.
101 void set_duration_known(bool duration_known
) {
102 demuxer_
->duration_known_
= duration_known
;
105 // Creates a data source with the given |file_name|. If |disable_file_size|
106 // then the data source pretends it does not know the file size (e.g. often
107 // when streaming video). Uses this data source to initialize a demuxer, then
108 // returns true if the bitrate is valid, false otherwise.
109 bool VideoHasValidBitrate(
110 const std::string
& file_name
, bool disable_file_size
) {
111 CreateDemuxer(file_name
, disable_file_size
);
113 return demuxer_
->GetBitrate() > 0;
116 bool IsStreamStopped(DemuxerStream::Type type
) {
117 DemuxerStream
* stream
= demuxer_
->GetStream(type
);
119 return static_cast<FFmpegDemuxerStream
*>(stream
)->stopped_
;
123 scoped_refptr
<FileDataSource
> data_source_
;
124 scoped_refptr
<FFmpegDemuxer
> demuxer_
;
125 StrictMock
<MockDemuxerHost
> host_
;
126 MessageLoop message_loop_
;
128 int64 current_read_position_
;
130 AVFormatContext
* format_context() {
131 return demuxer_
->format_context_
;
134 void ReadUntilEndOfStream() {
135 // We should expect an end of stream buffer.
136 scoped_refptr
<DemuxerStream
> audio
=
137 demuxer_
->GetStream(DemuxerStream::AUDIO
);
138 scoped_refptr
<DemuxerStreamReader
> reader(new DemuxerStreamReader());
140 bool got_eos_buffer
= false;
141 const int kMaxBuffers
= 170;
142 for (int i
= 0; !got_eos_buffer
&& i
< kMaxBuffers
; i
++) {
144 message_loop_
.RunAllPending();
145 EXPECT_TRUE(reader
->called());
146 ASSERT_TRUE(reader
->buffer());
148 if (reader
->buffer()->IsEndOfStream()) {
149 got_eos_buffer
= true;
150 EXPECT_TRUE(reader
->buffer()->GetData() == NULL
);
151 EXPECT_EQ(0, reader
->buffer()->GetDataSize());
155 EXPECT_TRUE(reader
->buffer()->GetData() != NULL
);
156 EXPECT_GT(reader
->buffer()->GetDataSize(), 0);
160 EXPECT_TRUE(got_eos_buffer
);
164 void CreateDataSource(const std::string
& name
, bool disable_file_size
) {
165 CHECK(!data_source_
);
168 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT
, &file_path
));
170 file_path
= file_path
.Append(FILE_PATH_LITERAL("media"))
171 .Append(FILE_PATH_LITERAL("test"))
172 .Append(FILE_PATH_LITERAL("data"))
175 data_source_
= new FileDataSource(disable_file_size
);
176 EXPECT_EQ(PIPELINE_OK
, data_source_
->Initialize(file_path
.MaybeAsASCII()));
179 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest
);
182 TEST_F(FFmpegDemuxerTest
, Initialize_OpenFails
) {
183 // Simulate avformat_open_input() failing.
184 CreateDemuxer("ten_byte_file"),
185 EXPECT_CALL(host_
, SetCurrentReadPosition(_
));
186 demuxer_
->Initialize(
187 &host_
, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN
));
189 message_loop_
.RunAllPending();
192 // TODO(acolwell): Uncomment this test when we discover a file that passes
193 // avformat_open_input(), but has avformat_find_stream_info() fail.
195 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) {
196 // CreateDemuxer("find_stream_info_fail.webm");
197 // demuxer_->Initialize(
198 // &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE));
199 // message_loop_.RunAllPending();
202 TEST_F(FFmpegDemuxerTest
, Initialize_NoStreams
) {
203 // Open a file with no streams whatsoever.
204 CreateDemuxer("no_streams.webm");
205 EXPECT_CALL(host_
, SetCurrentReadPosition(_
));
206 demuxer_
->Initialize(
207 &host_
, NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS
));
208 message_loop_
.RunAllPending();
211 TEST_F(FFmpegDemuxerTest
, Initialize_NoAudioVideo
) {
212 // Open a file containing streams but none of which are audio/video streams.
213 CreateDemuxer("no_audio_video.webm");
214 demuxer_
->Initialize(
215 &host_
, NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS
));
216 message_loop_
.RunAllPending();
219 TEST_F(FFmpegDemuxerTest
, Initialize_Successful
) {
220 CreateDemuxer("bear-320x240.webm");
223 // Video stream should be present.
224 scoped_refptr
<DemuxerStream
> stream
=
225 demuxer_
->GetStream(DemuxerStream::VIDEO
);
227 EXPECT_EQ(DemuxerStream::VIDEO
, stream
->type());
229 const VideoDecoderConfig
& video_config
= stream
->video_decoder_config();
230 EXPECT_EQ(kCodecVP8
, video_config
.codec());
231 EXPECT_EQ(VideoFrame::YV12
, video_config
.format());
232 EXPECT_EQ(320, video_config
.coded_size().width());
233 EXPECT_EQ(240, video_config
.coded_size().height());
234 EXPECT_EQ(0, video_config
.visible_rect().x());
235 EXPECT_EQ(0, video_config
.visible_rect().y());
236 EXPECT_EQ(320, video_config
.visible_rect().width());
237 EXPECT_EQ(240, video_config
.visible_rect().height());
238 EXPECT_EQ(30000, video_config
.frame_rate_numerator());
239 EXPECT_EQ(1001, video_config
.frame_rate_denominator());
240 EXPECT_EQ(1, video_config
.aspect_ratio_numerator());
241 EXPECT_EQ(1, video_config
.aspect_ratio_denominator());
242 EXPECT_FALSE(video_config
.extra_data());
243 EXPECT_EQ(0u, video_config
.extra_data_size());
245 // Audio stream should be present.
246 stream
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
248 EXPECT_EQ(DemuxerStream::AUDIO
, stream
->type());
250 const AudioDecoderConfig
& audio_config
= stream
->audio_decoder_config();
251 EXPECT_EQ(kCodecVorbis
, audio_config
.codec());
252 EXPECT_EQ(16, audio_config
.bits_per_channel());
253 EXPECT_EQ(CHANNEL_LAYOUT_STEREO
, audio_config
.channel_layout());
254 EXPECT_EQ(44100, audio_config
.samples_per_second());
255 EXPECT_TRUE(audio_config
.extra_data());
256 EXPECT_GT(audio_config
.extra_data_size(), 0u);
258 // Unknown stream should never be present.
259 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::UNKNOWN
));
262 TEST_F(FFmpegDemuxerTest
, Initialize_Multitrack
) {
263 // Open a file containing the following streams:
264 // Stream #0: Video (VP8)
265 // Stream #1: Audio (Vorbis)
266 // Stream #2: Subtitles (SRT)
267 // Stream #3: Video (Theora)
268 // Stream #4: Audio (16-bit signed little endian PCM)
270 // We should only pick the first audio/video streams we come across.
271 CreateDemuxer("bear-320x240-multitrack.webm");
274 // Video stream should be VP8.
275 scoped_refptr
<DemuxerStream
> stream
=
276 demuxer_
->GetStream(DemuxerStream::VIDEO
);
278 EXPECT_EQ(DemuxerStream::VIDEO
, stream
->type());
279 EXPECT_EQ(kCodecVP8
, stream
->video_decoder_config().codec());
281 // Audio stream should be Vorbis.
282 stream
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
284 EXPECT_EQ(DemuxerStream::AUDIO
, stream
->type());
285 EXPECT_EQ(kCodecVorbis
, stream
->audio_decoder_config().codec());
287 // Unknown stream should never be present.
288 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::UNKNOWN
));
291 TEST_F(FFmpegDemuxerTest
, Read_Audio
) {
292 // We test that on a successful audio packet read.
293 CreateDemuxer("bear-320x240.webm");
296 // Attempt a read from the audio stream and run the message loop until done.
297 scoped_refptr
<DemuxerStream
> audio
=
298 demuxer_
->GetStream(DemuxerStream::AUDIO
);
299 scoped_refptr
<DemuxerStreamReader
> reader(new DemuxerStreamReader());
301 message_loop_
.RunAllPending();
302 EXPECT_TRUE(reader
->called());
303 ValidateBuffer(FROM_HERE
, reader
->buffer(), 29, 0);
307 message_loop_
.RunAllPending();
308 EXPECT_TRUE(reader
->called());
309 ValidateBuffer(FROM_HERE
, reader
->buffer(), 27, 3000);
312 TEST_F(FFmpegDemuxerTest
, Read_Video
) {
313 // We test that on a successful video packet read.
314 CreateDemuxer("bear-320x240.webm");
317 // Attempt a read from the video stream and run the message loop until done.
318 scoped_refptr
<DemuxerStream
> video
=
319 demuxer_
->GetStream(DemuxerStream::VIDEO
);
320 scoped_refptr
<DemuxerStreamReader
> reader(new DemuxerStreamReader());
323 message_loop_
.RunAllPending();
324 EXPECT_TRUE(reader
->called());
325 ValidateBuffer(FROM_HERE
, reader
->buffer(), 22084, 0);
329 message_loop_
.RunAllPending();
330 EXPECT_TRUE(reader
->called());
331 ValidateBuffer(FROM_HERE
, reader
->buffer(), 1057, 33000);
334 TEST_F(FFmpegDemuxerTest
, Read_VideoNonZeroStart
) {
335 // Test the start time is the first timestamp of the video and audio stream.
336 CreateDemuxer("nonzero-start-time.webm");
339 // Attempt a read from the video stream and run the message loop until done.
340 scoped_refptr
<DemuxerStream
> video
=
341 demuxer_
->GetStream(DemuxerStream::VIDEO
);
342 scoped_refptr
<DemuxerStream
> audio
=
343 demuxer_
->GetStream(DemuxerStream::AUDIO
);
344 scoped_refptr
<DemuxerStreamReader
> reader(new DemuxerStreamReader());
346 // Check first buffer in video stream.
348 message_loop_
.RunAllPending();
349 EXPECT_TRUE(reader
->called());
350 ValidateBuffer(FROM_HERE
, reader
->buffer(), 5636, 400000);
351 const base::TimeDelta video_timestamp
= reader
->buffer()->GetTimestamp();
353 // Check first buffer in audio stream.
356 message_loop_
.RunAllPending();
357 EXPECT_TRUE(reader
->called());
358 ValidateBuffer(FROM_HERE
, reader
->buffer(), 165, 396000);
359 const base::TimeDelta audio_timestamp
= reader
->buffer()->GetTimestamp();
361 // Verify that the start time is equal to the lowest timestamp.
362 EXPECT_EQ(std::min(audio_timestamp
, video_timestamp
),
363 demuxer_
->GetStartTime());
366 TEST_F(FFmpegDemuxerTest
, Read_EndOfStream
) {
367 // Verify that end of stream buffers are created.
368 CreateDemuxer("bear-320x240.webm");
370 ReadUntilEndOfStream();
373 TEST_F(FFmpegDemuxerTest
, Read_EndOfStream_NoDuration
) {
374 // Verify that end of stream buffers are created.
375 CreateDemuxer("bear-320x240.webm", false);
377 set_duration_known(false);
378 EXPECT_CALL(host_
, SetDuration(_
));
379 ReadUntilEndOfStream();
382 TEST_F(FFmpegDemuxerTest
, Seek
) {
383 // We're testing that the demuxer frees all queued packets when it receives
385 CreateDemuxer("bear-320x240.webm");
389 scoped_refptr
<DemuxerStream
> video
=
390 demuxer_
->GetStream(DemuxerStream::VIDEO
);
391 scoped_refptr
<DemuxerStream
> audio
=
392 demuxer_
->GetStream(DemuxerStream::AUDIO
);
396 // Read a video packet and release it.
397 scoped_refptr
<DemuxerStreamReader
> reader(new DemuxerStreamReader());
399 message_loop_
.RunAllPending();
400 EXPECT_TRUE(reader
->called());
401 ValidateBuffer(FROM_HERE
, reader
->buffer(), 22084, 0);
403 // Release the video packet and verify the other packets are still queued.
405 message_loop_
.RunAllPending();
407 // Issue a simple forward seek, which should discard queued packets.
408 demuxer_
->Seek(base::TimeDelta::FromMicroseconds(1000000),
409 NewExpectedStatusCB(PIPELINE_OK
));
410 message_loop_
.RunAllPending();
414 message_loop_
.RunAllPending();
415 EXPECT_TRUE(reader
->called());
416 ValidateBuffer(FROM_HERE
, reader
->buffer(), 145, 803000);
421 message_loop_
.RunAllPending();
422 EXPECT_TRUE(reader
->called());
423 ValidateBuffer(FROM_HERE
, reader
->buffer(), 148, 826000);
428 message_loop_
.RunAllPending();
429 EXPECT_TRUE(reader
->called());
430 ValidateBuffer(FROM_HERE
, reader
->buffer(), 5425, 801000);
435 message_loop_
.RunAllPending();
436 EXPECT_TRUE(reader
->called());
437 ValidateBuffer(FROM_HERE
, reader
->buffer(), 1906, 834000);
439 // Manually release the last reference to the buffer and verify it was freed.
441 message_loop_
.RunAllPending();
444 // A mocked callback specialization for calling Read(). Since RunWithParams()
445 // is mocked we don't need to pass in object or method pointers.
446 class MockReadCB
: public base::RefCountedThreadSafe
<MockReadCB
> {
450 MOCK_METHOD0(OnDelete
, void());
451 MOCK_METHOD1(Run
, void(const scoped_refptr
<Buffer
>& buffer
));
454 virtual ~MockReadCB() {
459 friend class base::RefCountedThreadSafe
<MockReadCB
>;
461 DISALLOW_COPY_AND_ASSIGN(MockReadCB
);
464 TEST_F(FFmpegDemuxerTest
, Stop
) {
465 // Tests that calling Read() on a stopped demuxer stream immediately deletes
467 CreateDemuxer("bear-320x240.webm");
471 scoped_refptr
<DemuxerStream
> audio
=
472 demuxer_
->GetStream(DemuxerStream::AUDIO
);
475 demuxer_
->Stop(NewExpectedClosure());
477 // Expect all calls in sequence.
480 // Create our mocked callback. The Callback created by base::Bind() will take
481 // ownership of this pointer.
482 StrictMock
<MockReadCB
>* callback
= new StrictMock
<MockReadCB
>();
484 // The callback should be immediately deleted. We'll use a checkpoint to
485 // verify that it has indeed been deleted.
486 EXPECT_CALL(*callback
, Run(IsEndOfStreamBuffer()));
487 EXPECT_CALL(*callback
, OnDelete());
488 EXPECT_CALL(*this, CheckPoint(1));
490 // Attempt the read...
491 audio
->Read(base::Bind(&MockReadCB::Run
, callback
));
493 message_loop_
.RunAllPending();
495 // ...and verify that |callback| was deleted.
499 // The streams can outlive the demuxer because the streams may still be in use
500 // by the decoder when the demuxer is destroyed.
501 // This test verifies that DemuxerStream::Read() does not use an invalid demuxer
502 // pointer (no crash occurs) and calls the callback with an EndOfStream buffer.
503 TEST_F(FFmpegDemuxerTest
, StreamReadAfterStopAndDemuxerDestruction
) {
504 CreateDemuxer("bear-320x240.webm");
508 scoped_refptr
<DemuxerStream
> audio
=
509 demuxer_
->GetStream(DemuxerStream::AUDIO
);
512 demuxer_
->Stop(NewExpectedClosure());
514 // Finish up any remaining tasks.
515 message_loop_
.RunAllPending();
517 // Expect all calls in sequence.
520 // Create our mocked callback. The Callback created by base::Bind() will take
521 // ownership of this pointer.
522 StrictMock
<MockReadCB
>* callback
= new StrictMock
<MockReadCB
>();
524 // The callback should be immediately deleted. We'll use a checkpoint to
525 // verify that it has indeed been deleted.
526 EXPECT_CALL(*callback
, Run(IsEndOfStreamBuffer()));
527 EXPECT_CALL(*callback
, OnDelete());
528 EXPECT_CALL(*this, CheckPoint(1));
530 // Release the reference to the demuxer. This should also destroy it.
532 // |audio| now has a demuxer_ pointer to invalid memory.
534 // Attempt the read...
535 audio
->Read(base::Bind(&MockReadCB::Run
, callback
));
537 message_loop_
.RunAllPending();
539 // ...and verify that |callback| was deleted.
543 TEST_F(FFmpegDemuxerTest
, DisableAudioStream
) {
544 // We are doing the following things here:
545 // 1. Initialize the demuxer with audio and video stream.
546 // 2. Send a "disable audio stream" message to the demuxer.
547 // 3. Demuxer will free audio packets even if audio stream was initialized.
548 CreateDemuxer("bear-320x240.webm");
551 // Submit a "disable audio stream" message to the demuxer.
552 demuxer_
->OnAudioRendererDisabled();
553 message_loop_
.RunAllPending();
556 scoped_refptr
<DemuxerStream
> video
=
557 demuxer_
->GetStream(DemuxerStream::VIDEO
);
558 scoped_refptr
<DemuxerStream
> audio
=
559 demuxer_
->GetStream(DemuxerStream::AUDIO
);
563 // The audio stream should have been prematurely stopped.
564 EXPECT_FALSE(IsStreamStopped(DemuxerStream::VIDEO
));
565 EXPECT_TRUE(IsStreamStopped(DemuxerStream::AUDIO
));
567 // Attempt a read from the video stream: it should return valid data.
568 scoped_refptr
<DemuxerStreamReader
> reader(new DemuxerStreamReader());
570 message_loop_
.RunAllPending();
571 ASSERT_TRUE(reader
->called());
572 ValidateBuffer(FROM_HERE
, reader
->buffer(), 22084, 0);
574 // Attempt a read from the audio stream: it should immediately return end of
575 // stream without requiring the message loop to read data.
578 ASSERT_TRUE(reader
->called());
579 EXPECT_TRUE(reader
->buffer()->IsEndOfStream());
582 TEST_F(FFmpegDemuxerTest
, ProtocolRead
) {
583 CreateDemuxer("bear-320x240.webm");
586 // Set read head to zero as Initialize() will have parsed a bit of the file.
588 EXPECT_TRUE(demuxer_
->SetPosition(0));
589 EXPECT_TRUE(demuxer_
->GetPosition(&position
));
590 EXPECT_EQ(0, position
);
592 // Read 32 bytes from offset zero and verify position.
594 EXPECT_EQ(32u, demuxer_
->Read(32, buffer
));
595 EXPECT_EQ(32, current_read_position_
);
596 EXPECT_TRUE(demuxer_
->GetPosition(&position
));
597 EXPECT_EQ(32, position
);
599 // Read an additional 32 bytes and verify position.
600 EXPECT_EQ(32u, demuxer_
->Read(32, buffer
));
601 EXPECT_EQ(64, current_read_position_
);
602 EXPECT_TRUE(demuxer_
->GetPosition(&position
));
603 EXPECT_EQ(64, position
);
605 // Seek to end and read until EOF.
607 EXPECT_TRUE(demuxer_
->GetSize(&size
));
608 EXPECT_TRUE(demuxer_
->SetPosition(size
- 48));
609 EXPECT_EQ(32u, demuxer_
->Read(32, buffer
));
610 EXPECT_EQ(size
- 16, current_read_position_
);
611 EXPECT_TRUE(demuxer_
->GetPosition(&position
));
612 EXPECT_EQ(size
- 16, position
);
614 EXPECT_EQ(16u, demuxer_
->Read(32, buffer
));
615 EXPECT_EQ(size
, current_read_position_
);
616 EXPECT_TRUE(demuxer_
->GetPosition(&position
));
617 EXPECT_EQ(size
, position
);
619 EXPECT_EQ(0u, demuxer_
->Read(32, buffer
));
620 EXPECT_EQ(size
, current_read_position_
);
621 EXPECT_TRUE(demuxer_
->GetPosition(&position
));
622 EXPECT_EQ(size
, position
);
624 demuxer_
->Stop(NewExpectedClosure());
625 message_loop_
.RunAllPending();
628 TEST_F(FFmpegDemuxerTest
, GetBitrate_SetInContainer
) {
629 EXPECT_TRUE(VideoHasValidBitrate("bear.ogv", false));
632 TEST_F(FFmpegDemuxerTest
, GetBitrate_UnsetInContainer_KnownSize
) {
633 EXPECT_TRUE(VideoHasValidBitrate("bear-320x240.webm", false));
636 TEST_F(FFmpegDemuxerTest
, GetBitrate_SetInContainer_NoFileSize
) {
637 EXPECT_TRUE(VideoHasValidBitrate("bear.ogv", true));
640 TEST_F(FFmpegDemuxerTest
, GetBitrate_UnsetInContainer_NoFileSize
) {
641 EXPECT_TRUE(VideoHasValidBitrate("bear-320x240.webm", true));
644 TEST_F(FFmpegDemuxerTest
, ProtocolGetSetPosition
) {
645 CreateDemuxer("bear-320x240.webm");
652 EXPECT_TRUE(demuxer_
->GetSize(&size
));
653 EXPECT_TRUE(demuxer_
->GetPosition(&position
));
654 EXPECT_EQ(current_read_position_
, position
);
656 EXPECT_TRUE(demuxer_
->SetPosition(512));
657 EXPECT_FALSE(demuxer_
->SetPosition(size
));
658 EXPECT_FALSE(demuxer_
->SetPosition(size
+ 1));
659 EXPECT_FALSE(demuxer_
->SetPosition(-1));
660 EXPECT_TRUE(demuxer_
->GetPosition(&position
));
661 EXPECT_EQ(512, position
);
664 TEST_F(FFmpegDemuxerTest
, ProtocolGetSize
) {
665 CreateDemuxer("bear-320x240.webm");
668 int64 data_source_size
= 0;
669 int64 demuxer_size
= 0;
670 EXPECT_TRUE(data_source_
->GetSize(&data_source_size
));
671 EXPECT_TRUE(demuxer_
->GetSize(&demuxer_size
));
672 EXPECT_NE(0, data_source_size
);
673 EXPECT_EQ(data_source_size
, demuxer_size
);
676 TEST_F(FFmpegDemuxerTest
, ProtocolIsStreaming
) {
677 CreateDemuxer("bear-320x240.webm");
680 EXPECT_FALSE(data_source_
->IsStreaming());
681 EXPECT_FALSE(demuxer_
->IsStreaming());
684 // Verify that seek works properly when the WebM cues data is at the start of
685 // the file instead of at the end.
686 TEST_F(FFmpegDemuxerTest
, SeekWithCuesBeforeFirstCluster
) {
687 CreateDemuxer("bear-320x240-cues-in-front.webm");
691 scoped_refptr
<DemuxerStream
> video
=
692 demuxer_
->GetStream(DemuxerStream::VIDEO
);
693 scoped_refptr
<DemuxerStream
> audio
=
694 demuxer_
->GetStream(DemuxerStream::AUDIO
);
698 // Read a video packet and release it.
699 scoped_refptr
<DemuxerStreamReader
> reader(new DemuxerStreamReader());
701 message_loop_
.RunAllPending();
702 EXPECT_TRUE(reader
->called());
703 ValidateBuffer(FROM_HERE
, reader
->buffer(), 22084, 0);
705 // Release the video packet and verify the other packets are still queued.
707 message_loop_
.RunAllPending();
709 // Issue a simple forward seek, which should discard queued packets.
710 demuxer_
->Seek(base::TimeDelta::FromMicroseconds(2500000),
711 NewExpectedStatusCB(PIPELINE_OK
));
712 message_loop_
.RunAllPending();
716 message_loop_
.RunAllPending();
717 EXPECT_TRUE(reader
->called());
718 ValidateBuffer(FROM_HERE
, reader
->buffer(), 40, 2403000);
723 message_loop_
.RunAllPending();
724 EXPECT_TRUE(reader
->called());
725 ValidateBuffer(FROM_HERE
, reader
->buffer(), 42, 2406000);
730 message_loop_
.RunAllPending();
731 EXPECT_TRUE(reader
->called());
732 ValidateBuffer(FROM_HERE
, reader
->buffer(), 5276, 2402000);
737 message_loop_
.RunAllPending();
738 EXPECT_TRUE(reader
->called());
739 ValidateBuffer(FROM_HERE
, reader
->buffer(), 1740, 2436000);
741 // Manually release the last reference to the buffer and verify it was freed.
743 message_loop_
.RunAllPending();
746 // Ensure ID3v1 tag reading is disabled. id3_test.mp3 has an ID3v1 tag with the
747 // field "title" set to "sample for id3 test".
748 TEST_F(FFmpegDemuxerTest
, NoID3TagData
) {
749 #if !defined(USE_PROPRIETARY_CODECS)
752 CreateDemuxer("id3_test.mp3");
754 EXPECT_FALSE(av_dict_get(format_context()->metadata
, "title", NULL
, 0));
757 // Ensure MP3 files with large image/video based ID3 tags demux okay. FFmpeg
758 // will hand us a video stream to the data which will likely be in a format we
759 // don't accept as video; e.g. PNG.
760 TEST_F(FFmpegDemuxerTest
, Mp3WithVideoStreamID3TagData
) {
761 #if !defined(USE_PROPRIETARY_CODECS)
764 CreateDemuxer("id3_png_test.mp3");
767 // Ensure the expected streams are present.
768 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::VIDEO
));
769 EXPECT_TRUE(demuxer_
->GetStream(DemuxerStream::AUDIO
));
772 // Ensure a video with an unsupported audio track still results in the video
773 // stream being demuxed.
774 TEST_F(FFmpegDemuxerTest
, UnsupportedAudioSupportedVideoDemux
) {
775 CreateDemuxer("speex_audio_vorbis_video.ogv");
778 // Ensure the expected streams are present.
779 EXPECT_TRUE(demuxer_
->GetStream(DemuxerStream::VIDEO
));
780 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::AUDIO
));
783 // Ensure a video with an unsupported video track still results in the audio
784 // stream being demuxed.
785 TEST_F(FFmpegDemuxerTest
, UnsupportedVideoSupportedAudioDemux
) {
786 CreateDemuxer("vorbis_audio_wmv_video.mkv");
789 // Ensure the expected streams are present.
790 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::VIDEO
));
791 EXPECT_TRUE(demuxer_
->GetStream(DemuxerStream::AUDIO
));