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.
10 #include "base/files/file_path.h"
11 #include "base/path_service.h"
12 #include "base/threading/thread.h"
13 #include "media/base/decrypt_config.h"
14 #include "media/base/media_log.h"
15 #include "media/base/mock_demuxer_host.h"
16 #include "media/base/test_helpers.h"
17 #include "media/ffmpeg/ffmpeg_common.h"
18 #include "media/filters/ffmpeg_demuxer.h"
19 #include "media/filters/file_data_source.h"
20 #include "media/webm/webm_crypto_helpers.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using ::testing::AnyNumber
;
24 using ::testing::DoAll
;
25 using ::testing::Exactly
;
26 using ::testing::InSequence
;
27 using ::testing::Invoke
;
28 using ::testing::NotNull
;
29 using ::testing::Return
;
30 using ::testing::SaveArg
;
31 using ::testing::SetArgPointee
;
32 using ::testing::StrictMock
;
33 using ::testing::WithArgs
;
38 MATCHER(IsEndOfStreamBuffer
,
39 std::string(negation
? "isn't" : "is") + " end of stream") {
40 return arg
->end_of_stream();
43 static void EosOnReadDone(bool* got_eos_buffer
,
44 DemuxerStream::Status status
,
45 const scoped_refptr
<DecoderBuffer
>& buffer
) {
46 base::MessageLoop::current()->PostTask(
47 FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
49 EXPECT_EQ(status
, DemuxerStream::kOk
);
50 if (buffer
->end_of_stream()) {
51 *got_eos_buffer
= true;
55 EXPECT_TRUE(buffer
->data());
56 EXPECT_GT(buffer
->data_size(), 0);
57 *got_eos_buffer
= false;
61 // Fixture class to facilitate writing tests. Takes care of setting up the
62 // FFmpeg, pipeline and filter host mocks.
63 class FFmpegDemuxerTest
: public testing::Test
{
65 FFmpegDemuxerTest() {}
67 virtual ~FFmpegDemuxerTest() {
69 WaitableMessageLoopEvent event
;
70 demuxer_
->Stop(event
.GetClosure());
75 void CreateDemuxer(const std::string
& name
) {
78 EXPECT_CALL(host_
, SetTotalBytes(_
)).Times(AnyNumber());
79 EXPECT_CALL(host_
, AddBufferedByteRange(_
, _
)).Times(AnyNumber());
80 EXPECT_CALL(host_
, AddBufferedTimeRange(_
, _
)).Times(AnyNumber());
82 CreateDataSource(name
);
84 Demuxer::NeedKeyCB need_key_cb
=
85 base::Bind(&FFmpegDemuxerTest::NeedKeyCB
, base::Unretained(this));
87 demuxer_
.reset(new FFmpegDemuxer(message_loop_
.message_loop_proxy(),
93 MOCK_METHOD1(CheckPoint
, void(int v
));
95 void InitializeDemuxerText(bool enable_text
) {
96 EXPECT_CALL(host_
, SetDuration(_
));
97 WaitableMessageLoopEvent event
;
98 demuxer_
->Initialize(&host_
, event
.GetPipelineStatusCB(), enable_text
);
99 event
.RunAndWaitForStatus(PIPELINE_OK
);
102 void InitializeDemuxer() {
103 InitializeDemuxerText(false);
106 MOCK_METHOD2(OnReadDoneCalled
, void(int, int64
));
108 // Verifies that |buffer| has a specific |size| and |timestamp|.
109 // |location| simply indicates where the call to this function was made.
110 // This makes it easier to track down where test failures occur.
111 void OnReadDone(const tracked_objects::Location
& location
,
112 int size
, int64 timestampInMicroseconds
,
113 DemuxerStream::Status status
,
114 const scoped_refptr
<DecoderBuffer
>& buffer
) {
115 std::string location_str
;
116 location
.Write(true, false, &location_str
);
117 location_str
+= "\n";
118 SCOPED_TRACE(location_str
);
119 EXPECT_EQ(status
, DemuxerStream::kOk
);
120 OnReadDoneCalled(size
, timestampInMicroseconds
);
121 EXPECT_TRUE(buffer
.get() != NULL
);
122 EXPECT_EQ(size
, buffer
->data_size());
123 EXPECT_EQ(base::TimeDelta::FromMicroseconds(timestampInMicroseconds
),
124 buffer
->timestamp());
126 DCHECK_EQ(&message_loop_
, base::MessageLoop::current());
127 message_loop_
.PostTask(FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
130 DemuxerStream::ReadCB
NewReadCB(const tracked_objects::Location
& location
,
131 int size
, int64 timestampInMicroseconds
) {
132 EXPECT_CALL(*this, OnReadDoneCalled(size
, timestampInMicroseconds
));
133 return base::Bind(&FFmpegDemuxerTest::OnReadDone
, base::Unretained(this),
134 location
, size
, timestampInMicroseconds
);
137 // TODO(xhwang): This is a workaround of the issue that move-only parameters
138 // are not supported in mocked methods. Remove this when the issue is fixed
139 // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use
140 // std::string instead of scoped_ptr<uint8[]> (http://crbug.com/130689).
141 MOCK_METHOD3(NeedKeyCBMock
, void(const std::string
& type
,
142 const uint8
* init_data
, int init_data_size
));
143 void NeedKeyCB(const std::string
& type
,
144 const std::vector
<uint8
>& init_data
) {
145 const uint8
* init_data_ptr
= init_data
.empty() ? NULL
: &init_data
[0];
146 NeedKeyCBMock(type
, init_data_ptr
, init_data
.size());
149 // Accessor to demuxer internals.
150 void set_duration_known(bool duration_known
) {
151 demuxer_
->duration_known_
= duration_known
;
154 bool IsStreamStopped(DemuxerStream::Type type
) {
155 DemuxerStream
* stream
= demuxer_
->GetStream(type
);
157 return !static_cast<FFmpegDemuxerStream
*>(stream
)->demuxer_
;
161 scoped_ptr
<FileDataSource
> data_source_
;
162 scoped_ptr
<FFmpegDemuxer
> demuxer_
;
163 StrictMock
<MockDemuxerHost
> host_
;
164 base::MessageLoop message_loop_
;
166 AVFormatContext
* format_context() {
167 return demuxer_
->glue_
->format_context();
170 void ReadUntilEndOfStream(DemuxerStream
* stream
) {
171 bool got_eos_buffer
= false;
172 const int kMaxBuffers
= 170;
173 for (int i
= 0; !got_eos_buffer
&& i
< kMaxBuffers
; i
++) {
174 stream
->Read(base::Bind(&EosOnReadDone
, &got_eos_buffer
));
178 EXPECT_TRUE(got_eos_buffer
);
182 void CreateDataSource(const std::string
& name
) {
183 CHECK(!data_source_
);
185 base::FilePath file_path
;
186 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT
, &file_path
));
188 file_path
= file_path
.Append(FILE_PATH_LITERAL("media"))
189 .Append(FILE_PATH_LITERAL("test"))
190 .Append(FILE_PATH_LITERAL("data"))
193 data_source_
.reset(new FileDataSource());
194 EXPECT_TRUE(data_source_
->Initialize(file_path
));
197 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest
);
200 TEST_F(FFmpegDemuxerTest
, Initialize_OpenFails
) {
201 // Simulate avformat_open_input() failing.
202 CreateDemuxer("ten_byte_file");
203 WaitableMessageLoopEvent event
;
204 demuxer_
->Initialize(&host_
, event
.GetPipelineStatusCB(), true);
205 event
.RunAndWaitForStatus(DEMUXER_ERROR_COULD_NOT_OPEN
);
208 // TODO(acolwell): Uncomment this test when we discover a file that passes
209 // avformat_open_input(), but has avformat_find_stream_info() fail.
211 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) {
212 // ("find_stream_info_fail.webm");
213 // demuxer_->Initialize(
214 // &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE));
215 // message_loop_.RunUntilIdle();
218 TEST_F(FFmpegDemuxerTest
, Initialize_NoStreams
) {
219 // Open a file with no streams whatsoever.
220 CreateDemuxer("no_streams.webm");
221 WaitableMessageLoopEvent event
;
222 demuxer_
->Initialize(&host_
, event
.GetPipelineStatusCB(), true);
223 event
.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS
);
226 TEST_F(FFmpegDemuxerTest
, Initialize_NoAudioVideo
) {
227 // Open a file containing streams but none of which are audio/video streams.
228 CreateDemuxer("no_audio_video.webm");
229 WaitableMessageLoopEvent event
;
230 demuxer_
->Initialize(&host_
, event
.GetPipelineStatusCB(), true);
231 event
.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS
);
234 TEST_F(FFmpegDemuxerTest
, Initialize_Successful
) {
235 CreateDemuxer("bear-320x240.webm");
238 // Video stream should be present.
239 DemuxerStream
* stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
241 EXPECT_EQ(DemuxerStream::VIDEO
, stream
->type());
243 const VideoDecoderConfig
& video_config
= stream
->video_decoder_config();
244 EXPECT_EQ(kCodecVP8
, video_config
.codec());
245 EXPECT_EQ(VideoFrame::YV12
, video_config
.format());
246 EXPECT_EQ(320, video_config
.coded_size().width());
247 EXPECT_EQ(240, video_config
.coded_size().height());
248 EXPECT_EQ(0, video_config
.visible_rect().x());
249 EXPECT_EQ(0, video_config
.visible_rect().y());
250 EXPECT_EQ(320, video_config
.visible_rect().width());
251 EXPECT_EQ(240, video_config
.visible_rect().height());
252 EXPECT_EQ(320, video_config
.natural_size().width());
253 EXPECT_EQ(240, video_config
.natural_size().height());
254 EXPECT_FALSE(video_config
.extra_data());
255 EXPECT_EQ(0u, video_config
.extra_data_size());
257 // Audio stream should be present.
258 stream
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
260 EXPECT_EQ(DemuxerStream::AUDIO
, stream
->type());
262 const AudioDecoderConfig
& audio_config
= stream
->audio_decoder_config();
263 EXPECT_EQ(kCodecVorbis
, audio_config
.codec());
264 EXPECT_EQ(32, audio_config
.bits_per_channel());
265 EXPECT_EQ(CHANNEL_LAYOUT_STEREO
, audio_config
.channel_layout());
266 EXPECT_EQ(44100, audio_config
.samples_per_second());
267 EXPECT_EQ(kSampleFormatPlanarF32
, audio_config
.sample_format());
268 EXPECT_TRUE(audio_config
.extra_data());
269 EXPECT_GT(audio_config
.extra_data_size(), 0u);
271 // Unknown stream should never be present.
272 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::UNKNOWN
));
275 TEST_F(FFmpegDemuxerTest
, Initialize_Multitrack
) {
276 // Open a file containing the following streams:
277 // Stream #0: Video (VP8)
278 // Stream #1: Audio (Vorbis)
279 // Stream #2: Subtitles (SRT)
280 // Stream #3: Video (Theora)
281 // Stream #4: Audio (16-bit signed little endian PCM)
283 // We should only pick the first audio/video streams we come across.
284 CreateDemuxer("bear-320x240-multitrack.webm");
287 // Video stream should be VP8.
288 DemuxerStream
* stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
290 EXPECT_EQ(DemuxerStream::VIDEO
, stream
->type());
291 EXPECT_EQ(kCodecVP8
, stream
->video_decoder_config().codec());
293 // Audio stream should be Vorbis.
294 stream
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
296 EXPECT_EQ(DemuxerStream::AUDIO
, stream
->type());
297 EXPECT_EQ(kCodecVorbis
, stream
->audio_decoder_config().codec());
299 // Unknown stream should never be present.
300 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::UNKNOWN
));
303 TEST_F(FFmpegDemuxerTest
, Initialize_MultitrackText
) {
304 // Open a file containing the following streams:
305 // Stream #0: Video (VP8)
306 // Stream #1: Audio (Vorbis)
307 // Stream #2: Text (WebVTT)
309 CreateDemuxer("bear-vp8-webvtt.webm");
310 DemuxerStream
* text_stream
= NULL
;
311 EXPECT_CALL(host_
, AddTextStream(_
, _
))
312 .WillOnce(SaveArg
<0>(&text_stream
));
313 InitializeDemuxerText(true);
314 ASSERT_TRUE(text_stream
);
315 EXPECT_EQ(DemuxerStream::TEXT
, text_stream
->type());
317 // Video stream should be VP8.
318 DemuxerStream
* stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
320 EXPECT_EQ(DemuxerStream::VIDEO
, stream
->type());
321 EXPECT_EQ(kCodecVP8
, stream
->video_decoder_config().codec());
323 // Audio stream should be Vorbis.
324 stream
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
326 EXPECT_EQ(DemuxerStream::AUDIO
, stream
->type());
327 EXPECT_EQ(kCodecVorbis
, stream
->audio_decoder_config().codec());
329 // Unknown stream should never be present.
330 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::UNKNOWN
));
333 TEST_F(FFmpegDemuxerTest
, Initialize_Encrypted
) {
334 EXPECT_CALL(*this, NeedKeyCBMock(kWebMEncryptInitDataType
, NotNull(),
335 DecryptConfig::kDecryptionKeySize
))
338 CreateDemuxer("bear-320x240-av_enc-av.webm");
342 TEST_F(FFmpegDemuxerTest
, Read_Audio
) {
343 // We test that on a successful audio packet read.
344 CreateDemuxer("bear-320x240.webm");
347 // Attempt a read from the audio stream and run the message loop until done.
348 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
350 audio
->Read(NewReadCB(FROM_HERE
, 29, 0));
353 audio
->Read(NewReadCB(FROM_HERE
, 27, 3000));
357 TEST_F(FFmpegDemuxerTest
, Read_Video
) {
358 // We test that on a successful video packet read.
359 CreateDemuxer("bear-320x240.webm");
362 // Attempt a read from the video stream and run the message loop until done.
363 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
365 video
->Read(NewReadCB(FROM_HERE
, 22084, 0));
368 video
->Read(NewReadCB(FROM_HERE
, 1057, 33000));
372 TEST_F(FFmpegDemuxerTest
, Read_Text
) {
373 // We test that on a successful text packet read.
374 CreateDemuxer("bear-vp8-webvtt.webm");
375 DemuxerStream
* text_stream
= NULL
;
376 EXPECT_CALL(host_
, AddTextStream(_
, _
))
377 .WillOnce(SaveArg
<0>(&text_stream
));
378 InitializeDemuxerText(true);
379 ASSERT_TRUE(text_stream
);
380 EXPECT_EQ(DemuxerStream::TEXT
, text_stream
->type());
382 text_stream
->Read(NewReadCB(FROM_HERE
, 31, 0));
385 text_stream
->Read(NewReadCB(FROM_HERE
, 19, 500000));
389 TEST_F(FFmpegDemuxerTest
, Read_VideoNonZeroStart
) {
390 // Test the start time is the first timestamp of the video and audio stream.
391 CreateDemuxer("nonzero-start-time.webm");
394 // Attempt a read from the video stream and run the message loop until done.
395 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
396 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
398 // Check first buffer in video stream.
399 video
->Read(NewReadCB(FROM_HERE
, 5636, 400000));
402 // Check first buffer in audio stream.
403 audio
->Read(NewReadCB(FROM_HERE
, 165, 396000));
406 // Verify that the start time is equal to the lowest timestamp (ie the audio).
407 EXPECT_EQ(demuxer_
->GetStartTime().InMicroseconds(), 396000);
410 TEST_F(FFmpegDemuxerTest
, Read_EndOfStream
) {
411 // Verify that end of stream buffers are created.
412 CreateDemuxer("bear-320x240.webm");
414 ReadUntilEndOfStream(demuxer_
->GetStream(DemuxerStream::AUDIO
));
417 TEST_F(FFmpegDemuxerTest
, Read_EndOfStreamText
) {
418 // Verify that end of stream buffers are created.
419 CreateDemuxer("bear-vp8-webvtt.webm");
420 DemuxerStream
* text_stream
= NULL
;
421 EXPECT_CALL(host_
, AddTextStream(_
, _
))
422 .WillOnce(SaveArg
<0>(&text_stream
));
423 InitializeDemuxerText(true);
424 ASSERT_TRUE(text_stream
);
425 EXPECT_EQ(DemuxerStream::TEXT
, text_stream
->type());
427 bool got_eos_buffer
= false;
428 const int kMaxBuffers
= 10;
429 for (int i
= 0; !got_eos_buffer
&& i
< kMaxBuffers
; i
++) {
430 text_stream
->Read(base::Bind(&EosOnReadDone
, &got_eos_buffer
));
434 EXPECT_TRUE(got_eos_buffer
);
437 TEST_F(FFmpegDemuxerTest
, Read_EndOfStream_NoDuration
) {
438 // Verify that end of stream buffers are created.
439 CreateDemuxer("bear-320x240.webm");
441 set_duration_known(false);
442 EXPECT_CALL(host_
, SetDuration(base::TimeDelta::FromMilliseconds(2767)));
443 ReadUntilEndOfStream(demuxer_
->GetStream(DemuxerStream::AUDIO
));
444 ReadUntilEndOfStream(demuxer_
->GetStream(DemuxerStream::VIDEO
));
447 TEST_F(FFmpegDemuxerTest
, Read_EndOfStream_NoDuration_VideoOnly
) {
448 // Verify that end of stream buffers are created.
449 CreateDemuxer("bear-320x240-video-only.webm");
451 set_duration_known(false);
452 EXPECT_CALL(host_
, SetDuration(base::TimeDelta::FromMilliseconds(2703)));
453 ReadUntilEndOfStream(demuxer_
->GetStream(DemuxerStream::VIDEO
));
456 TEST_F(FFmpegDemuxerTest
, Read_EndOfStream_NoDuration_AudioOnly
) {
457 // Verify that end of stream buffers are created.
458 CreateDemuxer("bear-320x240-audio-only.webm");
460 set_duration_known(false);
461 EXPECT_CALL(host_
, SetDuration(base::TimeDelta::FromMilliseconds(2767)));
462 ReadUntilEndOfStream(demuxer_
->GetStream(DemuxerStream::AUDIO
));
465 TEST_F(FFmpegDemuxerTest
, Seek
) {
466 // We're testing that the demuxer frees all queued packets when it receives
468 CreateDemuxer("bear-320x240.webm");
472 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
473 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
477 // Read a video packet and release it.
478 video
->Read(NewReadCB(FROM_HERE
, 22084, 0));
481 // Issue a simple forward seek, which should discard queued packets.
482 WaitableMessageLoopEvent event
;
483 demuxer_
->Seek(base::TimeDelta::FromMicroseconds(1000000),
484 event
.GetPipelineStatusCB());
485 event
.RunAndWaitForStatus(PIPELINE_OK
);
488 audio
->Read(NewReadCB(FROM_HERE
, 145, 803000));
492 audio
->Read(NewReadCB(FROM_HERE
, 148, 826000));
496 video
->Read(NewReadCB(FROM_HERE
, 5425, 801000));
500 video
->Read(NewReadCB(FROM_HERE
, 1906, 834000));
504 TEST_F(FFmpegDemuxerTest
, SeekText
) {
505 // We're testing that the demuxer frees all queued packets when it receives
507 CreateDemuxer("bear-vp8-webvtt.webm");
508 DemuxerStream
* text_stream
= NULL
;
509 EXPECT_CALL(host_
, AddTextStream(_
, _
))
510 .WillOnce(SaveArg
<0>(&text_stream
));
511 InitializeDemuxerText(true);
512 ASSERT_TRUE(text_stream
);
513 EXPECT_EQ(DemuxerStream::TEXT
, text_stream
->type());
516 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
517 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
521 // Read a text packet and release it.
522 text_stream
->Read(NewReadCB(FROM_HERE
, 31, 0));
525 // Issue a simple forward seek, which should discard queued packets.
526 WaitableMessageLoopEvent event
;
527 demuxer_
->Seek(base::TimeDelta::FromMicroseconds(1000000),
528 event
.GetPipelineStatusCB());
529 event
.RunAndWaitForStatus(PIPELINE_OK
);
532 audio
->Read(NewReadCB(FROM_HERE
, 145, 803000));
536 audio
->Read(NewReadCB(FROM_HERE
, 148, 826000));
540 video
->Read(NewReadCB(FROM_HERE
, 5425, 801000));
544 video
->Read(NewReadCB(FROM_HERE
, 1906, 834000));
548 text_stream
->Read(NewReadCB(FROM_HERE
, 19, 500000));
552 text_stream
->Read(NewReadCB(FROM_HERE
, 19, 1000000));
561 MOCK_METHOD2(Run
, void(DemuxerStream::Status status
,
562 const scoped_refptr
<DecoderBuffer
>& buffer
));
564 DISALLOW_COPY_AND_ASSIGN(MockReadCB
);
567 TEST_F(FFmpegDemuxerTest
, Stop
) {
568 // Tests that calling Read() on a stopped demuxer stream immediately deletes
570 CreateDemuxer("bear-320x240.webm");
574 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
577 WaitableMessageLoopEvent event
;
578 demuxer_
->Stop(event
.GetClosure());
581 // Reads after being stopped are all EOS buffers.
582 StrictMock
<MockReadCB
> callback
;
583 EXPECT_CALL(callback
, Run(DemuxerStream::kOk
, IsEndOfStreamBuffer()));
585 // Attempt the read...
586 audio
->Read(base::Bind(&MockReadCB::Run
, base::Unretained(&callback
)));
587 message_loop_
.RunUntilIdle();
589 // Don't let the test call Stop() again.
593 TEST_F(FFmpegDemuxerTest
, DisableAudioStream
) {
594 // We are doing the following things here:
595 // 1. Initialize the demuxer with audio and video stream.
596 // 2. Send a "disable audio stream" message to the demuxer.
597 // 3. Demuxer will free audio packets even if audio stream was initialized.
598 CreateDemuxer("bear-320x240.webm");
601 // Submit a "disable audio stream" message to the demuxer.
602 demuxer_
->OnAudioRendererDisabled();
603 message_loop_
.RunUntilIdle();
606 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
607 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
611 // The audio stream should have been prematurely stopped.
612 EXPECT_FALSE(IsStreamStopped(DemuxerStream::VIDEO
));
613 EXPECT_TRUE(IsStreamStopped(DemuxerStream::AUDIO
));
615 // Attempt a read from the video stream: it should return valid data.
616 video
->Read(NewReadCB(FROM_HERE
, 22084, 0));
619 // Attempt a read from the audio stream: it should immediately return end of
620 // stream without requiring the message loop to read data.
621 bool got_eos_buffer
= false;
622 audio
->Read(base::Bind(&EosOnReadDone
, &got_eos_buffer
));
623 message_loop_
.RunUntilIdle();
624 EXPECT_TRUE(got_eos_buffer
);
627 // Verify that seek works properly when the WebM cues data is at the start of
628 // the file instead of at the end.
629 TEST_F(FFmpegDemuxerTest
, SeekWithCuesBeforeFirstCluster
) {
630 CreateDemuxer("bear-320x240-cues-in-front.webm");
634 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
635 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
639 // Read a video packet and release it.
640 video
->Read(NewReadCB(FROM_HERE
, 22084, 0));
643 // Issue a simple forward seek, which should discard queued packets.
644 WaitableMessageLoopEvent event
;
645 demuxer_
->Seek(base::TimeDelta::FromMicroseconds(2500000),
646 event
.GetPipelineStatusCB());
647 event
.RunAndWaitForStatus(PIPELINE_OK
);
650 audio
->Read(NewReadCB(FROM_HERE
, 40, 2403000));
654 audio
->Read(NewReadCB(FROM_HERE
, 42, 2406000));
658 video
->Read(NewReadCB(FROM_HERE
, 5276, 2402000));
662 video
->Read(NewReadCB(FROM_HERE
, 1740, 2436000));
666 // Ensure ID3v1 tag reading is disabled. id3_test.mp3 has an ID3v1 tag with the
667 // field "title" set to "sample for id3 test".
668 TEST_F(FFmpegDemuxerTest
, NoID3TagData
) {
669 #if !defined(USE_PROPRIETARY_CODECS)
672 CreateDemuxer("id3_test.mp3");
674 EXPECT_FALSE(av_dict_get(format_context()->metadata
, "title", NULL
, 0));
677 // Ensure MP3 files with large image/video based ID3 tags demux okay. FFmpeg
678 // will hand us a video stream to the data which will likely be in a format we
679 // don't accept as video; e.g. PNG.
680 TEST_F(FFmpegDemuxerTest
, Mp3WithVideoStreamID3TagData
) {
681 #if !defined(USE_PROPRIETARY_CODECS)
684 CreateDemuxer("id3_png_test.mp3");
687 // Ensure the expected streams are present.
688 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::VIDEO
));
689 EXPECT_TRUE(demuxer_
->GetStream(DemuxerStream::AUDIO
));
692 // Ensure a video with an unsupported audio track still results in the video
693 // stream being demuxed.
694 TEST_F(FFmpegDemuxerTest
, UnsupportedAudioSupportedVideoDemux
) {
695 CreateDemuxer("speex_audio_vorbis_video.ogv");
698 // Ensure the expected streams are present.
699 EXPECT_TRUE(demuxer_
->GetStream(DemuxerStream::VIDEO
));
700 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::AUDIO
));
703 // Ensure a video with an unsupported video track still results in the audio
704 // stream being demuxed.
705 TEST_F(FFmpegDemuxerTest
, UnsupportedVideoSupportedAudioDemux
) {
706 CreateDemuxer("vorbis_audio_wmv_video.mkv");
709 // Ensure the expected streams are present.
710 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::VIDEO
));
711 EXPECT_TRUE(demuxer_
->GetStream(DemuxerStream::AUDIO
));
714 // FFmpeg returns null data pointers when samples have zero size, leading to
715 // mistakenly creating end of stream buffers http://crbug.com/169133
716 TEST_F(FFmpegDemuxerTest
, MP4_ZeroStszEntry
) {
717 #if !defined(USE_PROPRIETARY_CODECS)
720 CreateDemuxer("bear-1280x720-zero-stsz-entry.mp4");
722 ReadUntilEndOfStream(demuxer_
->GetStream(DemuxerStream::AUDIO
));