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/logging.h"
12 #include "base/path_service.h"
13 #include "base/threading/thread.h"
14 #include "media/base/decrypt_config.h"
15 #include "media/base/media_log.h"
16 #include "media/base/mock_demuxer_host.h"
17 #include "media/base/test_helpers.h"
18 #include "media/base/timestamp_constants.h"
19 #include "media/ffmpeg/ffmpeg_common.h"
20 #include "media/filters/ffmpeg_demuxer.h"
21 #include "media/filters/file_data_source.h"
22 #include "media/formats/mp4/avc.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 using ::testing::AnyNumber
;
26 using ::testing::DoAll
;
27 using ::testing::Exactly
;
28 using ::testing::InSequence
;
29 using ::testing::Invoke
;
30 using ::testing::NotNull
;
31 using ::testing::Return
;
32 using ::testing::SaveArg
;
33 using ::testing::SetArgPointee
;
34 using ::testing::StrictMock
;
35 using ::testing::WithArgs
;
40 MATCHER(IsEndOfStreamBuffer
,
41 std::string(negation
? "isn't" : "is") + " end of stream") {
42 return arg
->end_of_stream();
45 const uint8 kEncryptedMediaInitData
[] = {
46 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
47 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
50 static void EosOnReadDone(bool* got_eos_buffer
,
51 DemuxerStream::Status status
,
52 const scoped_refptr
<DecoderBuffer
>& buffer
) {
53 base::MessageLoop::current()->PostTask(
54 FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
56 EXPECT_EQ(status
, DemuxerStream::kOk
);
57 if (buffer
->end_of_stream()) {
58 *got_eos_buffer
= true;
62 EXPECT_TRUE(buffer
->data());
63 EXPECT_GT(buffer
->data_size(), 0);
64 *got_eos_buffer
= false;
68 // Fixture class to facilitate writing tests. Takes care of setting up the
69 // FFmpeg, pipeline and filter host mocks.
70 class FFmpegDemuxerTest
: public testing::Test
{
72 FFmpegDemuxerTest() {}
74 virtual ~FFmpegDemuxerTest() {
79 void CreateDemuxer(const std::string
& name
) {
82 EXPECT_CALL(host_
, AddBufferedTimeRange(_
, _
)).Times(AnyNumber());
84 CreateDataSource(name
);
86 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb
= base::Bind(
87 &FFmpegDemuxerTest::OnEncryptedMediaInitData
, base::Unretained(this));
89 demuxer_
.reset(new FFmpegDemuxer(
90 message_loop_
.task_runner(), data_source_
.get(),
91 encrypted_media_init_data_cb
, new MediaLog()));
94 MOCK_METHOD1(CheckPoint
, void(int v
));
96 void InitializeDemuxerWithTimelineOffset(bool enable_text
,
97 base::Time timeline_offset
) {
98 EXPECT_CALL(host_
, SetDuration(_
));
99 WaitableMessageLoopEvent event
;
100 demuxer_
->Initialize(&host_
, event
.GetPipelineStatusCB(), enable_text
);
101 demuxer_
->timeline_offset_
= timeline_offset
;
102 event
.RunAndWaitForStatus(PIPELINE_OK
);
105 void InitializeDemuxerText(bool enable_text
) {
106 InitializeDemuxerWithTimelineOffset(enable_text
, base::Time());
109 void InitializeDemuxer() {
110 InitializeDemuxerText(false);
113 MOCK_METHOD2(OnReadDoneCalled
, void(int, int64
));
115 struct ReadExpectation
{
116 ReadExpectation(int size
,
118 const base::TimeDelta
& discard_front_padding
,
121 timestamp_us(timestamp_us
),
122 discard_front_padding(discard_front_padding
),
123 is_key_frame(is_key_frame
) {
128 base::TimeDelta discard_front_padding
;
132 // Verifies that |buffer| has a specific |size| and |timestamp|.
133 // |location| simply indicates where the call to this function was made.
134 // This makes it easier to track down where test failures occur.
135 void OnReadDone(const tracked_objects::Location
& location
,
136 const ReadExpectation
& read_expectation
,
137 DemuxerStream::Status status
,
138 const scoped_refptr
<DecoderBuffer
>& buffer
) {
139 std::string location_str
;
140 location
.Write(true, false, &location_str
);
141 location_str
+= "\n";
142 SCOPED_TRACE(location_str
);
143 EXPECT_EQ(status
, DemuxerStream::kOk
);
144 EXPECT_TRUE(buffer
.get() != NULL
);
145 EXPECT_EQ(read_expectation
.size
, buffer
->data_size());
146 EXPECT_EQ(read_expectation
.timestamp_us
,
147 buffer
->timestamp().InMicroseconds());
148 EXPECT_EQ(read_expectation
.discard_front_padding
,
149 buffer
->discard_padding().first
);
150 EXPECT_EQ(read_expectation
.is_key_frame
, buffer
->is_key_frame());
151 DCHECK_EQ(&message_loop_
, base::MessageLoop::current());
152 OnReadDoneCalled(read_expectation
.size
, read_expectation
.timestamp_us
);
153 message_loop_
.PostTask(FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
156 DemuxerStream::ReadCB
NewReadCB(const tracked_objects::Location
& location
,
160 return NewReadCBWithCheckedDiscard(location
,
167 DemuxerStream::ReadCB
NewReadCBWithCheckedDiscard(
168 const tracked_objects::Location
& location
,
171 base::TimeDelta discard_front_padding
,
173 EXPECT_CALL(*this, OnReadDoneCalled(size
, timestamp_us
));
175 struct ReadExpectation
read_expectation(size
,
177 discard_front_padding
,
180 return base::Bind(&FFmpegDemuxerTest::OnReadDone
,
181 base::Unretained(this),
186 MOCK_METHOD2(OnEncryptedMediaInitData
,
187 void(EmeInitDataType init_data_type
,
188 const std::vector
<uint8
>& init_data
));
190 // Accessor to demuxer internals.
191 void set_duration_known(bool duration_known
) {
192 demuxer_
->duration_known_
= duration_known
;
195 bool IsStreamStopped(DemuxerStream::Type type
) {
196 DemuxerStream
* stream
= demuxer_
->GetStream(type
);
198 return !static_cast<FFmpegDemuxerStream
*>(stream
)->demuxer_
;
202 scoped_ptr
<FileDataSource
> data_source_
;
203 scoped_ptr
<FFmpegDemuxer
> demuxer_
;
204 StrictMock
<MockDemuxerHost
> host_
;
205 base::MessageLoop message_loop_
;
207 AVFormatContext
* format_context() {
208 return demuxer_
->glue_
->format_context();
211 int preferred_seeking_stream_index() const {
212 return demuxer_
->preferred_stream_for_seeking_
.first
;
215 void ReadUntilEndOfStream(DemuxerStream
* stream
) {
216 bool got_eos_buffer
= false;
217 const int kMaxBuffers
= 170;
218 for (int i
= 0; !got_eos_buffer
&& i
< kMaxBuffers
; i
++) {
219 stream
->Read(base::Bind(&EosOnReadDone
, &got_eos_buffer
));
223 EXPECT_TRUE(got_eos_buffer
);
227 void CreateDataSource(const std::string
& name
) {
228 CHECK(!data_source_
);
230 base::FilePath file_path
;
231 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT
, &file_path
));
233 file_path
= file_path
.Append(FILE_PATH_LITERAL("media"))
234 .Append(FILE_PATH_LITERAL("test"))
235 .Append(FILE_PATH_LITERAL("data"))
238 data_source_
.reset(new FileDataSource());
239 EXPECT_TRUE(data_source_
->Initialize(file_path
));
242 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest
);
245 TEST_F(FFmpegDemuxerTest
, Initialize_OpenFails
) {
246 // Simulate avformat_open_input() failing.
247 CreateDemuxer("ten_byte_file");
248 WaitableMessageLoopEvent event
;
249 demuxer_
->Initialize(&host_
, event
.GetPipelineStatusCB(), true);
250 event
.RunAndWaitForStatus(DEMUXER_ERROR_COULD_NOT_OPEN
);
253 // TODO(acolwell): Uncomment this test when we discover a file that passes
254 // avformat_open_input(), but has avformat_find_stream_info() fail.
256 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) {
257 // ("find_stream_info_fail.webm");
258 // demuxer_->Initialize(
259 // &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE));
260 // message_loop_.RunUntilIdle();
263 TEST_F(FFmpegDemuxerTest
, Initialize_NoStreams
) {
264 // Open a file with no streams whatsoever.
265 CreateDemuxer("no_streams.webm");
266 WaitableMessageLoopEvent event
;
267 demuxer_
->Initialize(&host_
, event
.GetPipelineStatusCB(), true);
268 event
.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS
);
271 TEST_F(FFmpegDemuxerTest
, Initialize_NoAudioVideo
) {
272 // Open a file containing streams but none of which are audio/video streams.
273 CreateDemuxer("no_audio_video.webm");
274 WaitableMessageLoopEvent event
;
275 demuxer_
->Initialize(&host_
, event
.GetPipelineStatusCB(), true);
276 event
.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS
);
279 TEST_F(FFmpegDemuxerTest
, Initialize_Successful
) {
280 CreateDemuxer("bear-320x240.webm");
283 // Video stream should be present.
284 DemuxerStream
* stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
286 EXPECT_EQ(DemuxerStream::VIDEO
, stream
->type());
288 const VideoDecoderConfig
& video_config
= stream
->video_decoder_config();
289 EXPECT_EQ(kCodecVP8
, video_config
.codec());
290 EXPECT_EQ(PIXEL_FORMAT_YV12
, video_config
.format());
291 EXPECT_EQ(320, video_config
.coded_size().width());
292 EXPECT_EQ(240, video_config
.coded_size().height());
293 EXPECT_EQ(0, video_config
.visible_rect().x());
294 EXPECT_EQ(0, video_config
.visible_rect().y());
295 EXPECT_EQ(320, video_config
.visible_rect().width());
296 EXPECT_EQ(240, video_config
.visible_rect().height());
297 EXPECT_EQ(320, video_config
.natural_size().width());
298 EXPECT_EQ(240, video_config
.natural_size().height());
299 EXPECT_FALSE(video_config
.extra_data());
300 EXPECT_EQ(0u, video_config
.extra_data_size());
302 // Audio stream should be present.
303 stream
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
305 EXPECT_EQ(DemuxerStream::AUDIO
, stream
->type());
307 const AudioDecoderConfig
& audio_config
= stream
->audio_decoder_config();
308 EXPECT_EQ(kCodecVorbis
, audio_config
.codec());
309 EXPECT_EQ(32, audio_config
.bits_per_channel());
310 EXPECT_EQ(CHANNEL_LAYOUT_STEREO
, audio_config
.channel_layout());
311 EXPECT_EQ(44100, audio_config
.samples_per_second());
312 EXPECT_EQ(kSampleFormatPlanarF32
, audio_config
.sample_format());
313 EXPECT_TRUE(audio_config
.extra_data());
314 EXPECT_GT(audio_config
.extra_data_size(), 0u);
316 // Unknown stream should never be present.
317 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::UNKNOWN
));
320 TEST_F(FFmpegDemuxerTest
, Initialize_Multitrack
) {
321 // Open a file containing the following streams:
322 // Stream #0: Video (VP8)
323 // Stream #1: Audio (Vorbis)
324 // Stream #2: Subtitles (SRT)
325 // Stream #3: Video (Theora)
326 // Stream #4: Audio (16-bit signed little endian PCM)
328 // We should only pick the first audio/video streams we come across.
329 CreateDemuxer("bear-320x240-multitrack.webm");
332 // Video stream should be VP8.
333 DemuxerStream
* stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
335 EXPECT_EQ(DemuxerStream::VIDEO
, stream
->type());
336 EXPECT_EQ(kCodecVP8
, stream
->video_decoder_config().codec());
338 // Audio stream should be Vorbis.
339 stream
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
341 EXPECT_EQ(DemuxerStream::AUDIO
, stream
->type());
342 EXPECT_EQ(kCodecVorbis
, stream
->audio_decoder_config().codec());
344 // Unknown stream should never be present.
345 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::UNKNOWN
));
348 TEST_F(FFmpegDemuxerTest
, Initialize_MultitrackText
) {
349 // Open a file containing the following streams:
350 // Stream #0: Video (VP8)
351 // Stream #1: Audio (Vorbis)
352 // Stream #2: Text (WebVTT)
354 CreateDemuxer("bear-vp8-webvtt.webm");
355 DemuxerStream
* text_stream
= NULL
;
356 EXPECT_CALL(host_
, AddTextStream(_
, _
))
357 .WillOnce(SaveArg
<0>(&text_stream
));
358 InitializeDemuxerText(true);
359 ASSERT_TRUE(text_stream
);
360 EXPECT_EQ(DemuxerStream::TEXT
, text_stream
->type());
362 // Video stream should be VP8.
363 DemuxerStream
* stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
365 EXPECT_EQ(DemuxerStream::VIDEO
, stream
->type());
366 EXPECT_EQ(kCodecVP8
, stream
->video_decoder_config().codec());
368 // Audio stream should be Vorbis.
369 stream
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
371 EXPECT_EQ(DemuxerStream::AUDIO
, stream
->type());
372 EXPECT_EQ(kCodecVorbis
, stream
->audio_decoder_config().codec());
374 // Unknown stream should never be present.
375 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::UNKNOWN
));
378 TEST_F(FFmpegDemuxerTest
, Initialize_Encrypted
) {
380 OnEncryptedMediaInitData(
381 EmeInitDataType::WEBM
,
382 std::vector
<uint8
>(kEncryptedMediaInitData
,
383 kEncryptedMediaInitData
+
384 arraysize(kEncryptedMediaInitData
))))
387 CreateDemuxer("bear-320x240-av_enc-av.webm");
391 TEST_F(FFmpegDemuxerTest
, Read_Audio
) {
392 // We test that on a successful audio packet read.
393 CreateDemuxer("bear-320x240.webm");
396 // Attempt a read from the audio stream and run the message loop until done.
397 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
399 audio
->Read(NewReadCB(FROM_HERE
, 29, 0, true));
402 audio
->Read(NewReadCB(FROM_HERE
, 27, 3000, true));
406 TEST_F(FFmpegDemuxerTest
, Read_Video
) {
407 // We test that on a successful video packet read.
408 CreateDemuxer("bear-320x240.webm");
411 // Attempt a read from the video stream and run the message loop until done.
412 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
414 video
->Read(NewReadCB(FROM_HERE
, 22084, 0, true));
417 video
->Read(NewReadCB(FROM_HERE
, 1057, 33000, false));
421 TEST_F(FFmpegDemuxerTest
, Read_Text
) {
422 // We test that on a successful text packet read.
423 CreateDemuxer("bear-vp8-webvtt.webm");
424 DemuxerStream
* text_stream
= NULL
;
425 EXPECT_CALL(host_
, AddTextStream(_
, _
))
426 .WillOnce(SaveArg
<0>(&text_stream
));
427 InitializeDemuxerText(true);
428 ASSERT_TRUE(text_stream
);
429 EXPECT_EQ(DemuxerStream::TEXT
, text_stream
->type());
431 text_stream
->Read(NewReadCB(FROM_HERE
, 31, 0, true));
434 text_stream
->Read(NewReadCB(FROM_HERE
, 19, 500000, true));
438 TEST_F(FFmpegDemuxerTest
, SeekInitialized_NoVideoStartTime
) {
439 CreateDemuxer("audio-start-time-only.webm");
441 EXPECT_EQ(0, preferred_seeking_stream_index());
444 TEST_F(FFmpegDemuxerTest
, Read_VideoPositiveStartTime
) {
445 const int64 kTimelineOffsetMs
= 1352550896000LL;
447 // Test the start time is the first timestamp of the video and audio stream.
448 CreateDemuxer("nonzero-start-time.webm");
449 InitializeDemuxerWithTimelineOffset(
450 false, base::Time::FromJsTime(kTimelineOffsetMs
));
452 // Attempt a read from the video stream and run the message loop until done.
453 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
454 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
456 const base::TimeDelta video_start_time
=
457 base::TimeDelta::FromMicroseconds(400000);
458 const base::TimeDelta audio_start_time
=
459 base::TimeDelta::FromMicroseconds(396000);
461 // Run the test twice with a seek in between.
462 for (int i
= 0; i
< 2; ++i
) {
463 video
->Read(NewReadCB(FROM_HERE
, 5636, video_start_time
.InMicroseconds(),
466 audio
->Read(NewReadCB(FROM_HERE
, 165, audio_start_time
.InMicroseconds(),
470 // Verify that the start time is equal to the lowest timestamp (ie the
472 EXPECT_EQ(audio_start_time
, demuxer_
->start_time());
474 // Verify that the timeline offset has not been adjusted by the start time.
475 EXPECT_EQ(kTimelineOffsetMs
, demuxer_
->GetTimelineOffset().ToJavaTime());
477 // Seek back to the beginning and repeat the test.
478 WaitableMessageLoopEvent event
;
479 demuxer_
->Seek(base::TimeDelta(), event
.GetPipelineStatusCB());
480 event
.RunAndWaitForStatus(PIPELINE_OK
);
484 TEST_F(FFmpegDemuxerTest
, Read_AudioNoStartTime
) {
485 // FFmpeg does not set timestamps when demuxing wave files. Ensure that the
486 // demuxer sets a start time of zero in this case.
487 CreateDemuxer("sfx_s24le.wav");
490 // Run the test twice with a seek in between.
491 for (int i
= 0; i
< 2; ++i
) {
492 demuxer_
->GetStream(DemuxerStream::AUDIO
)
493 ->Read(NewReadCB(FROM_HERE
, 4095, 0, true));
495 EXPECT_EQ(base::TimeDelta(), demuxer_
->start_time());
497 // Seek back to the beginning and repeat the test.
498 WaitableMessageLoopEvent event
;
499 demuxer_
->Seek(base::TimeDelta(), event
.GetPipelineStatusCB());
500 event
.RunAndWaitForStatus(PIPELINE_OK
);
504 // TODO(dalecurtis): Test is disabled since FFmpeg does not currently guarantee
505 // the order of demuxed packets in OGG containers. Re-enable and fix key frame
506 // expectations once we decide to either workaround it or attempt a fix
507 // upstream. See http://crbug.com/387996.
508 TEST_F(FFmpegDemuxerTest
,
509 DISABLED_Read_AudioNegativeStartTimeAndOggDiscard_Bear
) {
510 // Many ogg files have negative starting timestamps, so ensure demuxing and
511 // seeking work correctly with a negative start time.
512 CreateDemuxer("bear.ogv");
515 // Attempt a read from the video stream and run the message loop until done.
516 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
517 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
519 // Run the test twice with a seek in between.
520 for (int i
= 0; i
< 2; ++i
) {
522 NewReadCBWithCheckedDiscard(FROM_HERE
, 40, 0, kInfiniteDuration(),
526 NewReadCBWithCheckedDiscard(FROM_HERE
, 41, 2903, kInfiniteDuration(),
529 audio
->Read(NewReadCBWithCheckedDiscard(
530 FROM_HERE
, 173, 5805, base::TimeDelta::FromMicroseconds(10159), true));
533 audio
->Read(NewReadCB(FROM_HERE
, 148, 18866, true));
535 EXPECT_EQ(base::TimeDelta::FromMicroseconds(-15964),
536 demuxer_
->start_time());
538 video
->Read(NewReadCB(FROM_HERE
, 5751, 0, true));
541 video
->Read(NewReadCB(FROM_HERE
, 846, 33367, true));
544 video
->Read(NewReadCB(FROM_HERE
, 1255, 66733, true));
547 // Seek back to the beginning and repeat the test.
548 WaitableMessageLoopEvent event
;
549 demuxer_
->Seek(base::TimeDelta(), event
.GetPipelineStatusCB());
550 event
.RunAndWaitForStatus(PIPELINE_OK
);
554 // Same test above, but using sync2.ogv which has video stream muxed before the
555 // audio stream, so seeking based only on start time will fail since ffmpeg is
556 // essentially just seeking based on file position.
557 TEST_F(FFmpegDemuxerTest
, Read_AudioNegativeStartTimeAndOggDiscard_Sync
) {
558 // Many ogg files have negative starting timestamps, so ensure demuxing and
559 // seeking work correctly with a negative start time.
560 CreateDemuxer("sync2.ogv");
563 // Attempt a read from the video stream and run the message loop until done.
564 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
565 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
567 // Run the test twice with a seek in between.
568 for (int i
= 0; i
< 2; ++i
) {
569 audio
->Read(NewReadCBWithCheckedDiscard(
570 FROM_HERE
, 1, 0, base::TimeDelta::FromMicroseconds(2902), true));
573 audio
->Read(NewReadCB(FROM_HERE
, 1, 2902, true));
575 EXPECT_EQ(base::TimeDelta::FromMicroseconds(-2902),
576 demuxer_
->start_time());
578 // Though the internal start time may be below zero, the exposed media time
579 // must always be greater than zero.
580 EXPECT_EQ(base::TimeDelta(), demuxer_
->GetStartTime());
582 video
->Read(NewReadCB(FROM_HERE
, 9997, 0, true));
585 video
->Read(NewReadCB(FROM_HERE
, 16, 33241, false));
588 video
->Read(NewReadCB(FROM_HERE
, 631, 66482, false));
591 // Seek back to the beginning and repeat the test.
592 WaitableMessageLoopEvent event
;
593 demuxer_
->Seek(base::TimeDelta(), event
.GetPipelineStatusCB());
594 event
.RunAndWaitForStatus(PIPELINE_OK
);
598 // Similar to the test above, but using an opus clip with a large amount of
599 // pre-skip, which ffmpeg encodes as negative timestamps.
600 TEST_F(FFmpegDemuxerTest
, Read_AudioNegativeStartTimeAndOpusDiscard_Sync
) {
601 CreateDemuxer("opus-trimming-video-test.webm");
604 // Attempt a read from the video stream and run the message loop until done.
605 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
606 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
607 EXPECT_EQ(audio
->audio_decoder_config().codec_delay(), 65535);
609 // Packet size to timestamp (in microseconds) mapping for the first N packets
610 // which should be fully discarded.
611 static const int kTestExpectations
[][2] = {
612 {635, 0}, {594, 120000}, {597, 240000}, {591, 360000},
613 {582, 480000}, {583, 600000}, {592, 720000}, {567, 840000},
614 {579, 960000}, {572, 1080000}, {583, 1200000}};
616 // Run the test twice with a seek in between.
617 for (int i
= 0; i
< 2; ++i
) {
618 for (size_t j
= 0; j
< arraysize(kTestExpectations
); ++j
) {
619 audio
->Read(NewReadCB(FROM_HERE
, kTestExpectations
[j
][0],
620 kTestExpectations
[j
][1], true));
624 // Though the internal start time may be below zero, the exposed media time
625 // must always be greater than zero.
626 EXPECT_EQ(base::TimeDelta(), demuxer_
->GetStartTime());
628 video
->Read(NewReadCB(FROM_HERE
, 16009, 0, true));
631 video
->Read(NewReadCB(FROM_HERE
, 2715, 1000, false));
634 video
->Read(NewReadCB(FROM_HERE
, 427, 33000, false));
637 // Seek back to the beginning and repeat the test.
638 WaitableMessageLoopEvent event
;
639 demuxer_
->Seek(base::TimeDelta(), event
.GetPipelineStatusCB());
640 event
.RunAndWaitForStatus(PIPELINE_OK
);
644 // Similar to the test above, but using sfx-opus.ogg, which has a much smaller
645 // amount of discard padding and no |start_time| set on the AVStream.
646 TEST_F(FFmpegDemuxerTest
, Read_AudioNegativeStartTimeAndOpusSfxDiscard_Sync
) {
647 CreateDemuxer("sfx-opus.ogg");
650 // Attempt a read from the video stream and run the message loop until done.
651 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
652 EXPECT_EQ(audio
->audio_decoder_config().codec_delay(), 312);
654 // Run the test twice with a seek in between.
655 for (int i
= 0; i
< 2; ++i
) {
656 audio
->Read(NewReadCB(FROM_HERE
, 314, 0, true));
659 audio
->Read(NewReadCB(FROM_HERE
, 244, 20000, true));
662 // Though the internal start time may be below zero, the exposed media time
663 // must always be greater than zero.
664 EXPECT_EQ(base::TimeDelta(), demuxer_
->GetStartTime());
666 // Seek back to the beginning and repeat the test.
667 WaitableMessageLoopEvent event
;
668 demuxer_
->Seek(base::TimeDelta(), event
.GetPipelineStatusCB());
669 event
.RunAndWaitForStatus(PIPELINE_OK
);
673 TEST_F(FFmpegDemuxerTest
, Read_EndOfStream
) {
674 // Verify that end of stream buffers are created.
675 CreateDemuxer("bear-320x240.webm");
677 ReadUntilEndOfStream(demuxer_
->GetStream(DemuxerStream::AUDIO
));
680 TEST_F(FFmpegDemuxerTest
, Read_EndOfStreamText
) {
681 // Verify that end of stream buffers are created.
682 CreateDemuxer("bear-vp8-webvtt.webm");
683 DemuxerStream
* text_stream
= NULL
;
684 EXPECT_CALL(host_
, AddTextStream(_
, _
))
685 .WillOnce(SaveArg
<0>(&text_stream
));
686 InitializeDemuxerText(true);
687 ASSERT_TRUE(text_stream
);
688 EXPECT_EQ(DemuxerStream::TEXT
, text_stream
->type());
690 bool got_eos_buffer
= false;
691 const int kMaxBuffers
= 10;
692 for (int i
= 0; !got_eos_buffer
&& i
< kMaxBuffers
; i
++) {
693 text_stream
->Read(base::Bind(&EosOnReadDone
, &got_eos_buffer
));
697 EXPECT_TRUE(got_eos_buffer
);
700 TEST_F(FFmpegDemuxerTest
, Read_EndOfStream_NoDuration
) {
701 // Verify that end of stream buffers are created.
702 CreateDemuxer("bear-320x240.webm");
704 set_duration_known(false);
705 EXPECT_CALL(host_
, SetDuration(base::TimeDelta::FromMilliseconds(2767)));
706 ReadUntilEndOfStream(demuxer_
->GetStream(DemuxerStream::AUDIO
));
707 ReadUntilEndOfStream(demuxer_
->GetStream(DemuxerStream::VIDEO
));
710 TEST_F(FFmpegDemuxerTest
, Read_EndOfStream_NoDuration_VideoOnly
) {
711 // Verify that end of stream buffers are created.
712 CreateDemuxer("bear-320x240-video-only.webm");
714 set_duration_known(false);
715 EXPECT_CALL(host_
, SetDuration(base::TimeDelta::FromMilliseconds(2736)));
716 ReadUntilEndOfStream(demuxer_
->GetStream(DemuxerStream::VIDEO
));
719 TEST_F(FFmpegDemuxerTest
, Read_EndOfStream_NoDuration_AudioOnly
) {
720 // Verify that end of stream buffers are created.
721 CreateDemuxer("bear-320x240-audio-only.webm");
723 set_duration_known(false);
724 EXPECT_CALL(host_
, SetDuration(base::TimeDelta::FromMilliseconds(2767)));
725 ReadUntilEndOfStream(demuxer_
->GetStream(DemuxerStream::AUDIO
));
728 TEST_F(FFmpegDemuxerTest
, Read_EndOfStream_NoDuration_UnsupportedStream
) {
729 // Verify that end of stream buffers are created and we don't crash
730 // if there are streams in the file that we don't support.
731 CreateDemuxer("vorbis_audio_wmv_video.mkv");
733 set_duration_known(false);
734 EXPECT_CALL(host_
, SetDuration(base::TimeDelta::FromMilliseconds(1014)));
735 ReadUntilEndOfStream(demuxer_
->GetStream(DemuxerStream::AUDIO
));
738 TEST_F(FFmpegDemuxerTest
, Seek
) {
739 // We're testing that the demuxer frees all queued packets when it receives
741 CreateDemuxer("bear-320x240.webm");
745 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
746 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
750 // Read a video packet and release it.
751 video
->Read(NewReadCB(FROM_HERE
, 22084, 0, true));
754 // Issue a simple forward seek, which should discard queued packets.
755 WaitableMessageLoopEvent event
;
756 demuxer_
->Seek(base::TimeDelta::FromMicroseconds(1000000),
757 event
.GetPipelineStatusCB());
758 event
.RunAndWaitForStatus(PIPELINE_OK
);
761 audio
->Read(NewReadCB(FROM_HERE
, 145, 803000, true));
765 audio
->Read(NewReadCB(FROM_HERE
, 148, 826000, true));
769 video
->Read(NewReadCB(FROM_HERE
, 5425, 801000, true));
773 video
->Read(NewReadCB(FROM_HERE
, 1906, 834000, false));
777 TEST_F(FFmpegDemuxerTest
, SeekText
) {
778 // We're testing that the demuxer frees all queued packets when it receives
780 CreateDemuxer("bear-vp8-webvtt.webm");
781 DemuxerStream
* text_stream
= NULL
;
782 EXPECT_CALL(host_
, AddTextStream(_
, _
))
783 .WillOnce(SaveArg
<0>(&text_stream
));
784 InitializeDemuxerText(true);
785 ASSERT_TRUE(text_stream
);
786 EXPECT_EQ(DemuxerStream::TEXT
, text_stream
->type());
789 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
790 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
794 // Read a text packet and release it.
795 text_stream
->Read(NewReadCB(FROM_HERE
, 31, 0, true));
798 // Issue a simple forward seek, which should discard queued packets.
799 WaitableMessageLoopEvent event
;
800 demuxer_
->Seek(base::TimeDelta::FromMicroseconds(1000000),
801 event
.GetPipelineStatusCB());
802 event
.RunAndWaitForStatus(PIPELINE_OK
);
805 audio
->Read(NewReadCB(FROM_HERE
, 145, 803000, true));
809 audio
->Read(NewReadCB(FROM_HERE
, 148, 826000, true));
813 video
->Read(NewReadCB(FROM_HERE
, 5425, 801000, true));
817 video
->Read(NewReadCB(FROM_HERE
, 1906, 834000, false));
821 text_stream
->Read(NewReadCB(FROM_HERE
, 19, 500000, true));
825 text_stream
->Read(NewReadCB(FROM_HERE
, 19, 1000000, true));
834 MOCK_METHOD2(Run
, void(DemuxerStream::Status status
,
835 const scoped_refptr
<DecoderBuffer
>& buffer
));
837 DISALLOW_COPY_AND_ASSIGN(MockReadCB
);
840 TEST_F(FFmpegDemuxerTest
, Stop
) {
841 // Tests that calling Read() on a stopped demuxer stream immediately deletes
843 CreateDemuxer("bear-320x240.webm");
847 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
852 // Reads after being stopped are all EOS buffers.
853 StrictMock
<MockReadCB
> callback
;
854 EXPECT_CALL(callback
, Run(DemuxerStream::kOk
, IsEndOfStreamBuffer()));
856 // Attempt the read...
857 audio
->Read(base::Bind(&MockReadCB::Run
, base::Unretained(&callback
)));
858 message_loop_
.RunUntilIdle();
860 // Don't let the test call Stop() again.
864 // Verify that seek works properly when the WebM cues data is at the start of
865 // the file instead of at the end.
866 TEST_F(FFmpegDemuxerTest
, SeekWithCuesBeforeFirstCluster
) {
867 CreateDemuxer("bear-320x240-cues-in-front.webm");
871 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
872 DemuxerStream
* audio
= demuxer_
->GetStream(DemuxerStream::AUDIO
);
876 // Read a video packet and release it.
877 video
->Read(NewReadCB(FROM_HERE
, 22084, 0, true));
880 // Issue a simple forward seek, which should discard queued packets.
881 WaitableMessageLoopEvent event
;
882 demuxer_
->Seek(base::TimeDelta::FromMicroseconds(2500000),
883 event
.GetPipelineStatusCB());
884 event
.RunAndWaitForStatus(PIPELINE_OK
);
887 audio
->Read(NewReadCB(FROM_HERE
, 40, 2403000, true));
891 audio
->Read(NewReadCB(FROM_HERE
, 42, 2406000, true));
895 video
->Read(NewReadCB(FROM_HERE
, 5276, 2402000, true));
899 video
->Read(NewReadCB(FROM_HERE
, 1740, 2436000, false));
903 #if defined(USE_PROPRIETARY_CODECS)
904 // Ensure ID3v1 tag reading is disabled. id3_test.mp3 has an ID3v1 tag with the
905 // field "title" set to "sample for id3 test".
906 TEST_F(FFmpegDemuxerTest
, NoID3TagData
) {
907 CreateDemuxer("id3_test.mp3");
909 EXPECT_FALSE(av_dict_get(format_context()->metadata
, "title", NULL
, 0));
913 #if defined(USE_PROPRIETARY_CODECS)
914 // Ensure MP3 files with large image/video based ID3 tags demux okay. FFmpeg
915 // will hand us a video stream to the data which will likely be in a format we
916 // don't accept as video; e.g. PNG.
917 TEST_F(FFmpegDemuxerTest
, Mp3WithVideoStreamID3TagData
) {
918 CreateDemuxer("id3_png_test.mp3");
921 // Ensure the expected streams are present.
922 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::VIDEO
));
923 EXPECT_TRUE(demuxer_
->GetStream(DemuxerStream::AUDIO
));
927 // Ensure a video with an unsupported audio track still results in the video
928 // stream being demuxed.
929 TEST_F(FFmpegDemuxerTest
, UnsupportedAudioSupportedVideoDemux
) {
930 CreateDemuxer("speex_audio_vorbis_video.ogv");
933 // Ensure the expected streams are present.
934 EXPECT_TRUE(demuxer_
->GetStream(DemuxerStream::VIDEO
));
935 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::AUDIO
));
938 // Ensure a video with an unsupported video track still results in the audio
939 // stream being demuxed.
940 TEST_F(FFmpegDemuxerTest
, UnsupportedVideoSupportedAudioDemux
) {
941 CreateDemuxer("vorbis_audio_wmv_video.mkv");
944 // Ensure the expected streams are present.
945 EXPECT_FALSE(demuxer_
->GetStream(DemuxerStream::VIDEO
));
946 EXPECT_TRUE(demuxer_
->GetStream(DemuxerStream::AUDIO
));
949 #if defined(USE_PROPRIETARY_CODECS)
950 // FFmpeg returns null data pointers when samples have zero size, leading to
951 // mistakenly creating end of stream buffers http://crbug.com/169133
952 TEST_F(FFmpegDemuxerTest
, MP4_ZeroStszEntry
) {
953 CreateDemuxer("bear-1280x720-zero-stsz-entry.mp4");
955 ReadUntilEndOfStream(demuxer_
->GetStream(DemuxerStream::AUDIO
));
959 static void ValidateAnnexB(DemuxerStream
* stream
,
960 DemuxerStream::Status status
,
961 const scoped_refptr
<DecoderBuffer
>& buffer
) {
962 EXPECT_EQ(status
, DemuxerStream::kOk
);
964 if (buffer
->end_of_stream()) {
965 base::MessageLoop::current()->PostTask(
966 FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
970 std::vector
<SubsampleEntry
> subsamples
;
972 if (buffer
->decrypt_config())
973 subsamples
= buffer
->decrypt_config()->subsamples();
976 mp4::AVC::IsValidAnnexB(buffer
->data(), buffer
->data_size(),
978 EXPECT_TRUE(is_valid
);
981 LOG(ERROR
) << "Buffer contains invalid Annex B data.";
982 base::MessageLoop::current()->PostTask(
983 FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
987 stream
->Read(base::Bind(&ValidateAnnexB
, stream
));
990 TEST_F(FFmpegDemuxerTest
, IsValidAnnexB
) {
991 const char* files
[] = {
992 "bear-1280x720-av_frag.mp4",
993 "bear-1280x720-av_with-aud-nalus_frag.mp4"
996 for (size_t i
= 0; i
< arraysize(files
); ++i
) {
997 DVLOG(1) << "Testing " << files
[i
];
998 CreateDemuxer(files
[i
]);
1001 // Ensure the expected streams are present.
1002 DemuxerStream
* stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
1003 ASSERT_TRUE(stream
);
1004 stream
->EnableBitstreamConverter();
1006 stream
->Read(base::Bind(&ValidateAnnexB
, stream
));
1007 message_loop_
.Run();
1011 data_source_
.reset();
1015 TEST_F(FFmpegDemuxerTest
, Rotate_Metadata_0
) {
1016 CreateDemuxer("bear_rotate_0.mp4");
1017 InitializeDemuxer();
1019 DemuxerStream
* stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
1020 ASSERT_TRUE(stream
);
1021 ASSERT_EQ(VIDEO_ROTATION_0
, stream
->video_rotation());
1024 TEST_F(FFmpegDemuxerTest
, Rotate_Metadata_90
) {
1025 CreateDemuxer("bear_rotate_90.mp4");
1026 InitializeDemuxer();
1028 DemuxerStream
* stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
1029 ASSERT_TRUE(stream
);
1030 ASSERT_EQ(VIDEO_ROTATION_90
, stream
->video_rotation());
1033 TEST_F(FFmpegDemuxerTest
, Rotate_Metadata_180
) {
1034 CreateDemuxer("bear_rotate_180.mp4");
1035 InitializeDemuxer();
1037 DemuxerStream
* stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
1038 ASSERT_TRUE(stream
);
1039 ASSERT_EQ(VIDEO_ROTATION_180
, stream
->video_rotation());
1042 TEST_F(FFmpegDemuxerTest
, Rotate_Metadata_270
) {
1043 CreateDemuxer("bear_rotate_270.mp4");
1044 InitializeDemuxer();
1046 DemuxerStream
* stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
1047 ASSERT_TRUE(stream
);
1048 ASSERT_EQ(VIDEO_ROTATION_270
, stream
->video_rotation());
1051 TEST_F(FFmpegDemuxerTest
, NaturalSizeWithoutPASP
) {
1052 CreateDemuxer("bear-640x360-non_square_pixel-without_pasp.mp4");
1053 InitializeDemuxer();
1055 DemuxerStream
* stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
1056 ASSERT_TRUE(stream
);
1058 const VideoDecoderConfig
& video_config
= stream
->video_decoder_config();
1059 EXPECT_EQ(gfx::Size(639, 360), video_config
.natural_size());
1062 TEST_F(FFmpegDemuxerTest
, NaturalSizeWithPASP
) {
1063 CreateDemuxer("bear-640x360-non_square_pixel-with_pasp.mp4");
1064 InitializeDemuxer();
1066 DemuxerStream
* stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
1067 ASSERT_TRUE(stream
);
1069 const VideoDecoderConfig
& video_config
= stream
->video_decoder_config();
1070 EXPECT_EQ(gfx::Size(639, 360), video_config
.natural_size());
1075 #if defined(ENABLE_HEVC_DEMUXING)
1076 TEST_F(FFmpegDemuxerTest
, HEVC_in_MP4_container
) {
1077 CreateDemuxer("bear-hevc-frag.mp4");
1078 InitializeDemuxer();
1080 DemuxerStream
* video
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
1083 video
->Read(NewReadCB(FROM_HERE
, 3569, 66733, true));
1084 message_loop_
.Run();
1086 video
->Read(NewReadCB(FROM_HERE
, 1042, 200200, false));
1087 message_loop_
.Run();
1091 } // namespace media