Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / filters / ffmpeg_demuxer_unittest.cc
blob9b2e93a36fd1aba76a2354b6a6590c3acdc81989
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.
5 #include <algorithm>
6 #include <deque>
7 #include <string>
9 #include "base/bind.h"
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/ffmpeg/ffmpeg_common.h"
19 #include "media/filters/ffmpeg_demuxer.h"
20 #include "media/filters/file_data_source.h"
21 #include "media/formats/mp4/avc.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using ::testing::AnyNumber;
25 using ::testing::DoAll;
26 using ::testing::Exactly;
27 using ::testing::InSequence;
28 using ::testing::Invoke;
29 using ::testing::NotNull;
30 using ::testing::Return;
31 using ::testing::SaveArg;
32 using ::testing::SetArgPointee;
33 using ::testing::StrictMock;
34 using ::testing::WithArgs;
35 using ::testing::_;
37 namespace media {
39 MATCHER(IsEndOfStreamBuffer,
40 std::string(negation ? "isn't" : "is") + " end of stream") {
41 return arg->end_of_stream();
44 const uint8 kEncryptedMediaInitData[] = {
45 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
46 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
49 static void EosOnReadDone(bool* got_eos_buffer,
50 DemuxerStream::Status status,
51 const scoped_refptr<DecoderBuffer>& buffer) {
52 base::MessageLoop::current()->PostTask(
53 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
55 EXPECT_EQ(status, DemuxerStream::kOk);
56 if (buffer->end_of_stream()) {
57 *got_eos_buffer = true;
58 return;
61 EXPECT_TRUE(buffer->data());
62 EXPECT_GT(buffer->data_size(), 0);
63 *got_eos_buffer = false;
67 // Fixture class to facilitate writing tests. Takes care of setting up the
68 // FFmpeg, pipeline and filter host mocks.
69 class FFmpegDemuxerTest : public testing::Test {
70 protected:
71 FFmpegDemuxerTest() {}
73 virtual ~FFmpegDemuxerTest() {
74 if (demuxer_)
75 demuxer_->Stop();
78 void CreateDemuxer(const std::string& name) {
79 CHECK(!demuxer_);
81 EXPECT_CALL(host_, AddBufferedTimeRange(_, _)).Times(AnyNumber());
83 CreateDataSource(name);
85 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb = base::Bind(
86 &FFmpegDemuxerTest::OnEncryptedMediaInitData, base::Unretained(this));
88 demuxer_.reset(new FFmpegDemuxer(
89 message_loop_.task_runner(), data_source_.get(),
90 encrypted_media_init_data_cb, new MediaLog()));
93 MOCK_METHOD1(CheckPoint, void(int v));
95 void InitializeDemuxerWithTimelineOffset(bool enable_text,
96 base::Time timeline_offset) {
97 EXPECT_CALL(host_, SetDuration(_));
98 WaitableMessageLoopEvent event;
99 demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), enable_text);
100 demuxer_->timeline_offset_ = timeline_offset;
101 event.RunAndWaitForStatus(PIPELINE_OK);
104 void InitializeDemuxerText(bool enable_text) {
105 InitializeDemuxerWithTimelineOffset(enable_text, base::Time());
108 void InitializeDemuxer() {
109 InitializeDemuxerText(false);
112 MOCK_METHOD2(OnReadDoneCalled, void(int, int64));
114 struct ReadExpectation {
115 ReadExpectation(int size,
116 int64 timestamp_us,
117 const base::TimeDelta& discard_front_padding,
118 bool is_key_frame)
119 : size(size),
120 timestamp_us(timestamp_us),
121 discard_front_padding(discard_front_padding),
122 is_key_frame(is_key_frame) {
125 int size;
126 int64 timestamp_us;
127 base::TimeDelta discard_front_padding;
128 bool is_key_frame;
131 // Verifies that |buffer| has a specific |size| and |timestamp|.
132 // |location| simply indicates where the call to this function was made.
133 // This makes it easier to track down where test failures occur.
134 void OnReadDone(const tracked_objects::Location& location,
135 const ReadExpectation& read_expectation,
136 DemuxerStream::Status status,
137 const scoped_refptr<DecoderBuffer>& buffer) {
138 std::string location_str;
139 location.Write(true, false, &location_str);
140 location_str += "\n";
141 SCOPED_TRACE(location_str);
142 EXPECT_EQ(status, DemuxerStream::kOk);
143 EXPECT_TRUE(buffer.get() != NULL);
144 EXPECT_EQ(read_expectation.size, buffer->data_size());
145 EXPECT_EQ(read_expectation.timestamp_us,
146 buffer->timestamp().InMicroseconds());
147 EXPECT_EQ(read_expectation.discard_front_padding,
148 buffer->discard_padding().first);
149 EXPECT_EQ(read_expectation.is_key_frame, buffer->is_key_frame());
150 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
151 OnReadDoneCalled(read_expectation.size, read_expectation.timestamp_us);
152 message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
155 DemuxerStream::ReadCB NewReadCB(const tracked_objects::Location& location,
156 int size,
157 int64 timestamp_us,
158 bool is_key_frame) {
159 return NewReadCBWithCheckedDiscard(location,
160 size,
161 timestamp_us,
162 base::TimeDelta(),
163 is_key_frame);
166 DemuxerStream::ReadCB NewReadCBWithCheckedDiscard(
167 const tracked_objects::Location& location,
168 int size,
169 int64 timestamp_us,
170 base::TimeDelta discard_front_padding,
171 bool is_key_frame) {
172 EXPECT_CALL(*this, OnReadDoneCalled(size, timestamp_us));
174 struct ReadExpectation read_expectation(size,
175 timestamp_us,
176 discard_front_padding,
177 is_key_frame);
179 return base::Bind(&FFmpegDemuxerTest::OnReadDone,
180 base::Unretained(this),
181 location,
182 read_expectation);
185 MOCK_METHOD2(OnEncryptedMediaInitData,
186 void(EmeInitDataType init_data_type,
187 const std::vector<uint8>& init_data));
189 // Accessor to demuxer internals.
190 void set_duration_known(bool duration_known) {
191 demuxer_->duration_known_ = duration_known;
194 bool IsStreamStopped(DemuxerStream::Type type) {
195 DemuxerStream* stream = demuxer_->GetStream(type);
196 CHECK(stream);
197 return !static_cast<FFmpegDemuxerStream*>(stream)->demuxer_;
200 // Fixture members.
201 scoped_ptr<FileDataSource> data_source_;
202 scoped_ptr<FFmpegDemuxer> demuxer_;
203 StrictMock<MockDemuxerHost> host_;
204 base::MessageLoop message_loop_;
206 AVFormatContext* format_context() {
207 return demuxer_->glue_->format_context();
210 int preferred_seeking_stream_index() const {
211 return demuxer_->preferred_stream_for_seeking_.first;
214 void ReadUntilEndOfStream(DemuxerStream* stream) {
215 bool got_eos_buffer = false;
216 const int kMaxBuffers = 170;
217 for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) {
218 stream->Read(base::Bind(&EosOnReadDone, &got_eos_buffer));
219 message_loop_.Run();
222 EXPECT_TRUE(got_eos_buffer);
225 private:
226 void CreateDataSource(const std::string& name) {
227 CHECK(!data_source_);
229 base::FilePath file_path;
230 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
232 file_path = file_path.Append(FILE_PATH_LITERAL("media"))
233 .Append(FILE_PATH_LITERAL("test"))
234 .Append(FILE_PATH_LITERAL("data"))
235 .AppendASCII(name);
237 data_source_.reset(new FileDataSource());
238 EXPECT_TRUE(data_source_->Initialize(file_path));
241 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest);
244 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) {
245 // Simulate avformat_open_input() failing.
246 CreateDemuxer("ten_byte_file");
247 WaitableMessageLoopEvent event;
248 demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
249 event.RunAndWaitForStatus(DEMUXER_ERROR_COULD_NOT_OPEN);
252 // TODO(acolwell): Uncomment this test when we discover a file that passes
253 // avformat_open_input(), but has avformat_find_stream_info() fail.
255 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) {
256 // ("find_stream_info_fail.webm");
257 // demuxer_->Initialize(
258 // &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE));
259 // message_loop_.RunUntilIdle();
262 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) {
263 // Open a file with no streams whatsoever.
264 CreateDemuxer("no_streams.webm");
265 WaitableMessageLoopEvent event;
266 demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
267 event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
270 TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) {
271 // Open a file containing streams but none of which are audio/video streams.
272 CreateDemuxer("no_audio_video.webm");
273 WaitableMessageLoopEvent event;
274 demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
275 event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
278 TEST_F(FFmpegDemuxerTest, Initialize_Successful) {
279 CreateDemuxer("bear-320x240.webm");
280 InitializeDemuxer();
282 // Video stream should be present.
283 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
284 ASSERT_TRUE(stream);
285 EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
287 const VideoDecoderConfig& video_config = stream->video_decoder_config();
288 EXPECT_EQ(kCodecVP8, video_config.codec());
289 EXPECT_EQ(PIXEL_FORMAT_YV12, video_config.format());
290 EXPECT_EQ(320, video_config.coded_size().width());
291 EXPECT_EQ(240, video_config.coded_size().height());
292 EXPECT_EQ(0, video_config.visible_rect().x());
293 EXPECT_EQ(0, video_config.visible_rect().y());
294 EXPECT_EQ(320, video_config.visible_rect().width());
295 EXPECT_EQ(240, video_config.visible_rect().height());
296 EXPECT_EQ(320, video_config.natural_size().width());
297 EXPECT_EQ(240, video_config.natural_size().height());
298 EXPECT_FALSE(video_config.extra_data());
299 EXPECT_EQ(0u, video_config.extra_data_size());
301 // Audio stream should be present.
302 stream = demuxer_->GetStream(DemuxerStream::AUDIO);
303 ASSERT_TRUE(stream);
304 EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
306 const AudioDecoderConfig& audio_config = stream->audio_decoder_config();
307 EXPECT_EQ(kCodecVorbis, audio_config.codec());
308 EXPECT_EQ(32, audio_config.bits_per_channel());
309 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, audio_config.channel_layout());
310 EXPECT_EQ(44100, audio_config.samples_per_second());
311 EXPECT_EQ(kSampleFormatPlanarF32, audio_config.sample_format());
312 EXPECT_TRUE(audio_config.extra_data());
313 EXPECT_GT(audio_config.extra_data_size(), 0u);
315 // Unknown stream should never be present.
316 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
319 TEST_F(FFmpegDemuxerTest, Initialize_Multitrack) {
320 // Open a file containing the following streams:
321 // Stream #0: Video (VP8)
322 // Stream #1: Audio (Vorbis)
323 // Stream #2: Subtitles (SRT)
324 // Stream #3: Video (Theora)
325 // Stream #4: Audio (16-bit signed little endian PCM)
327 // We should only pick the first audio/video streams we come across.
328 CreateDemuxer("bear-320x240-multitrack.webm");
329 InitializeDemuxer();
331 // Video stream should be VP8.
332 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
333 ASSERT_TRUE(stream);
334 EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
335 EXPECT_EQ(kCodecVP8, stream->video_decoder_config().codec());
337 // Audio stream should be Vorbis.
338 stream = demuxer_->GetStream(DemuxerStream::AUDIO);
339 ASSERT_TRUE(stream);
340 EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
341 EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec());
343 // Unknown stream should never be present.
344 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
347 TEST_F(FFmpegDemuxerTest, Initialize_MultitrackText) {
348 // Open a file containing the following streams:
349 // Stream #0: Video (VP8)
350 // Stream #1: Audio (Vorbis)
351 // Stream #2: Text (WebVTT)
353 CreateDemuxer("bear-vp8-webvtt.webm");
354 DemuxerStream* text_stream = NULL;
355 EXPECT_CALL(host_, AddTextStream(_, _))
356 .WillOnce(SaveArg<0>(&text_stream));
357 InitializeDemuxerText(true);
358 ASSERT_TRUE(text_stream);
359 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
361 // Video stream should be VP8.
362 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
363 ASSERT_TRUE(stream);
364 EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
365 EXPECT_EQ(kCodecVP8, stream->video_decoder_config().codec());
367 // Audio stream should be Vorbis.
368 stream = demuxer_->GetStream(DemuxerStream::AUDIO);
369 ASSERT_TRUE(stream);
370 EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
371 EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec());
373 // Unknown stream should never be present.
374 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
377 TEST_F(FFmpegDemuxerTest, Initialize_Encrypted) {
378 EXPECT_CALL(*this,
379 OnEncryptedMediaInitData(
380 EmeInitDataType::WEBM,
381 std::vector<uint8>(kEncryptedMediaInitData,
382 kEncryptedMediaInitData +
383 arraysize(kEncryptedMediaInitData))))
384 .Times(Exactly(2));
386 CreateDemuxer("bear-320x240-av_enc-av.webm");
387 InitializeDemuxer();
390 TEST_F(FFmpegDemuxerTest, Read_Audio) {
391 // We test that on a successful audio packet read.
392 CreateDemuxer("bear-320x240.webm");
393 InitializeDemuxer();
395 // Attempt a read from the audio stream and run the message loop until done.
396 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
398 audio->Read(NewReadCB(FROM_HERE, 29, 0, true));
399 message_loop_.Run();
401 audio->Read(NewReadCB(FROM_HERE, 27, 3000, true));
402 message_loop_.Run();
405 TEST_F(FFmpegDemuxerTest, Read_Video) {
406 // We test that on a successful video packet read.
407 CreateDemuxer("bear-320x240.webm");
408 InitializeDemuxer();
410 // Attempt a read from the video stream and run the message loop until done.
411 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
413 video->Read(NewReadCB(FROM_HERE, 22084, 0, true));
414 message_loop_.Run();
416 video->Read(NewReadCB(FROM_HERE, 1057, 33000, false));
417 message_loop_.Run();
420 TEST_F(FFmpegDemuxerTest, Read_Text) {
421 // We test that on a successful text packet read.
422 CreateDemuxer("bear-vp8-webvtt.webm");
423 DemuxerStream* text_stream = NULL;
424 EXPECT_CALL(host_, AddTextStream(_, _))
425 .WillOnce(SaveArg<0>(&text_stream));
426 InitializeDemuxerText(true);
427 ASSERT_TRUE(text_stream);
428 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
430 text_stream->Read(NewReadCB(FROM_HERE, 31, 0, true));
431 message_loop_.Run();
433 text_stream->Read(NewReadCB(FROM_HERE, 19, 500000, true));
434 message_loop_.Run();
437 TEST_F(FFmpegDemuxerTest, SeekInitialized_NoVideoStartTime) {
438 CreateDemuxer("audio-start-time-only.webm");
439 InitializeDemuxer();
440 EXPECT_EQ(0, preferred_seeking_stream_index());
443 TEST_F(FFmpegDemuxerTest, Read_VideoPositiveStartTime) {
444 const int64 kTimelineOffsetMs = 1352550896000LL;
446 // Test the start time is the first timestamp of the video and audio stream.
447 CreateDemuxer("nonzero-start-time.webm");
448 InitializeDemuxerWithTimelineOffset(
449 false, base::Time::FromJsTime(kTimelineOffsetMs));
451 // Attempt a read from the video stream and run the message loop until done.
452 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
453 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
455 const base::TimeDelta video_start_time =
456 base::TimeDelta::FromMicroseconds(400000);
457 const base::TimeDelta audio_start_time =
458 base::TimeDelta::FromMicroseconds(396000);
460 // Run the test twice with a seek in between.
461 for (int i = 0; i < 2; ++i) {
462 video->Read(NewReadCB(FROM_HERE, 5636, video_start_time.InMicroseconds(),
463 true));
464 message_loop_.Run();
465 audio->Read(NewReadCB(FROM_HERE, 165, audio_start_time.InMicroseconds(),
466 true));
467 message_loop_.Run();
469 // Verify that the start time is equal to the lowest timestamp (ie the
470 // audio).
471 EXPECT_EQ(audio_start_time, demuxer_->start_time());
473 // Verify that the timeline offset has not been adjusted by the start time.
474 EXPECT_EQ(kTimelineOffsetMs, demuxer_->GetTimelineOffset().ToJavaTime());
476 // Seek back to the beginning and repeat the test.
477 WaitableMessageLoopEvent event;
478 demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
479 event.RunAndWaitForStatus(PIPELINE_OK);
483 TEST_F(FFmpegDemuxerTest, Read_AudioNoStartTime) {
484 // FFmpeg does not set timestamps when demuxing wave files. Ensure that the
485 // demuxer sets a start time of zero in this case.
486 CreateDemuxer("sfx_s24le.wav");
487 InitializeDemuxer();
489 // Run the test twice with a seek in between.
490 for (int i = 0; i < 2; ++i) {
491 demuxer_->GetStream(DemuxerStream::AUDIO)
492 ->Read(NewReadCB(FROM_HERE, 4095, 0, true));
493 message_loop_.Run();
494 EXPECT_EQ(base::TimeDelta(), demuxer_->start_time());
496 // Seek back to the beginning and repeat the test.
497 WaitableMessageLoopEvent event;
498 demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
499 event.RunAndWaitForStatus(PIPELINE_OK);
503 // TODO(dalecurtis): Test is disabled since FFmpeg does not currently guarantee
504 // the order of demuxed packets in OGG containers. Re-enable and fix key frame
505 // expectations once we decide to either workaround it or attempt a fix
506 // upstream. See http://crbug.com/387996.
507 TEST_F(FFmpegDemuxerTest,
508 DISABLED_Read_AudioNegativeStartTimeAndOggDiscard_Bear) {
509 // Many ogg files have negative starting timestamps, so ensure demuxing and
510 // seeking work correctly with a negative start time.
511 CreateDemuxer("bear.ogv");
512 InitializeDemuxer();
514 // Attempt a read from the video stream and run the message loop until done.
515 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
516 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
518 // Run the test twice with a seek in between.
519 for (int i = 0; i < 2; ++i) {
520 audio->Read(
521 NewReadCBWithCheckedDiscard(FROM_HERE, 40, 0, kInfiniteDuration(),
522 true));
523 message_loop_.Run();
524 audio->Read(
525 NewReadCBWithCheckedDiscard(FROM_HERE, 41, 2903, kInfiniteDuration(),
526 true));
527 message_loop_.Run();
528 audio->Read(NewReadCBWithCheckedDiscard(
529 FROM_HERE, 173, 5805, base::TimeDelta::FromMicroseconds(10159), true));
530 message_loop_.Run();
532 audio->Read(NewReadCB(FROM_HERE, 148, 18866, true));
533 message_loop_.Run();
534 EXPECT_EQ(base::TimeDelta::FromMicroseconds(-15964),
535 demuxer_->start_time());
537 video->Read(NewReadCB(FROM_HERE, 5751, 0, true));
538 message_loop_.Run();
540 video->Read(NewReadCB(FROM_HERE, 846, 33367, true));
541 message_loop_.Run();
543 video->Read(NewReadCB(FROM_HERE, 1255, 66733, true));
544 message_loop_.Run();
546 // Seek back to the beginning and repeat the test.
547 WaitableMessageLoopEvent event;
548 demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
549 event.RunAndWaitForStatus(PIPELINE_OK);
553 // Same test above, but using sync2.ogv which has video stream muxed before the
554 // audio stream, so seeking based only on start time will fail since ffmpeg is
555 // essentially just seeking based on file position.
556 TEST_F(FFmpegDemuxerTest, Read_AudioNegativeStartTimeAndOggDiscard_Sync) {
557 // Many ogg files have negative starting timestamps, so ensure demuxing and
558 // seeking work correctly with a negative start time.
559 CreateDemuxer("sync2.ogv");
560 InitializeDemuxer();
562 // Attempt a read from the video stream and run the message loop until done.
563 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
564 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
566 // Run the test twice with a seek in between.
567 for (int i = 0; i < 2; ++i) {
568 audio->Read(NewReadCBWithCheckedDiscard(
569 FROM_HERE, 1, 0, base::TimeDelta::FromMicroseconds(2902), true));
570 message_loop_.Run();
572 audio->Read(NewReadCB(FROM_HERE, 1, 2902, true));
573 message_loop_.Run();
574 EXPECT_EQ(base::TimeDelta::FromMicroseconds(-2902),
575 demuxer_->start_time());
577 // Though the internal start time may be below zero, the exposed media time
578 // must always be greater than zero.
579 EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
581 video->Read(NewReadCB(FROM_HERE, 9997, 0, true));
582 message_loop_.Run();
584 video->Read(NewReadCB(FROM_HERE, 16, 33241, false));
585 message_loop_.Run();
587 video->Read(NewReadCB(FROM_HERE, 631, 66482, false));
588 message_loop_.Run();
590 // Seek back to the beginning and repeat the test.
591 WaitableMessageLoopEvent event;
592 demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
593 event.RunAndWaitForStatus(PIPELINE_OK);
597 // Similar to the test above, but using an opus clip with a large amount of
598 // pre-skip, which ffmpeg encodes as negative timestamps.
599 TEST_F(FFmpegDemuxerTest, Read_AudioNegativeStartTimeAndOpusDiscard_Sync) {
600 CreateDemuxer("opus-trimming-video-test.webm");
601 InitializeDemuxer();
603 // Attempt a read from the video stream and run the message loop until done.
604 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
605 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
606 EXPECT_EQ(audio->audio_decoder_config().codec_delay(), 65535);
608 // Packet size to timestamp (in microseconds) mapping for the first N packets
609 // which should be fully discarded.
610 static const int kTestExpectations[][2] = {
611 {635, 0}, {594, 120000}, {597, 240000}, {591, 360000},
612 {582, 480000}, {583, 600000}, {592, 720000}, {567, 840000},
613 {579, 960000}, {572, 1080000}, {583, 1200000}};
615 // Run the test twice with a seek in between.
616 for (int i = 0; i < 2; ++i) {
617 for (size_t j = 0; j < arraysize(kTestExpectations); ++j) {
618 audio->Read(NewReadCB(FROM_HERE, kTestExpectations[j][0],
619 kTestExpectations[j][1], true));
620 message_loop_.Run();
623 // Though the internal start time may be below zero, the exposed media time
624 // must always be greater than zero.
625 EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
627 video->Read(NewReadCB(FROM_HERE, 16009, 0, true));
628 message_loop_.Run();
630 video->Read(NewReadCB(FROM_HERE, 2715, 1000, false));
631 message_loop_.Run();
633 video->Read(NewReadCB(FROM_HERE, 427, 33000, false));
634 message_loop_.Run();
636 // Seek back to the beginning and repeat the test.
637 WaitableMessageLoopEvent event;
638 demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
639 event.RunAndWaitForStatus(PIPELINE_OK);
643 // Similar to the test above, but using sfx-opus.ogg, which has a much smaller
644 // amount of discard padding and no |start_time| set on the AVStream.
645 TEST_F(FFmpegDemuxerTest, Read_AudioNegativeStartTimeAndOpusSfxDiscard_Sync) {
646 CreateDemuxer("sfx-opus.ogg");
647 InitializeDemuxer();
649 // Attempt a read from the video stream and run the message loop until done.
650 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
651 EXPECT_EQ(audio->audio_decoder_config().codec_delay(), 312);
653 // Run the test twice with a seek in between.
654 for (int i = 0; i < 2; ++i) {
655 audio->Read(NewReadCB(FROM_HERE, 314, 0, true));
656 message_loop_.Run();
658 audio->Read(NewReadCB(FROM_HERE, 244, 20000, true));
659 message_loop_.Run();
661 // Though the internal start time may be below zero, the exposed media time
662 // must always be greater than zero.
663 EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
665 // Seek back to the beginning and repeat the test.
666 WaitableMessageLoopEvent event;
667 demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
668 event.RunAndWaitForStatus(PIPELINE_OK);
672 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) {
673 // Verify that end of stream buffers are created.
674 CreateDemuxer("bear-320x240.webm");
675 InitializeDemuxer();
676 ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
679 TEST_F(FFmpegDemuxerTest, Read_EndOfStreamText) {
680 // Verify that end of stream buffers are created.
681 CreateDemuxer("bear-vp8-webvtt.webm");
682 DemuxerStream* text_stream = NULL;
683 EXPECT_CALL(host_, AddTextStream(_, _))
684 .WillOnce(SaveArg<0>(&text_stream));
685 InitializeDemuxerText(true);
686 ASSERT_TRUE(text_stream);
687 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
689 bool got_eos_buffer = false;
690 const int kMaxBuffers = 10;
691 for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) {
692 text_stream->Read(base::Bind(&EosOnReadDone, &got_eos_buffer));
693 message_loop_.Run();
696 EXPECT_TRUE(got_eos_buffer);
699 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration) {
700 // Verify that end of stream buffers are created.
701 CreateDemuxer("bear-320x240.webm");
702 InitializeDemuxer();
703 set_duration_known(false);
704 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2767)));
705 ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
706 ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::VIDEO));
709 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration_VideoOnly) {
710 // Verify that end of stream buffers are created.
711 CreateDemuxer("bear-320x240-video-only.webm");
712 InitializeDemuxer();
713 set_duration_known(false);
714 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2736)));
715 ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::VIDEO));
718 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration_AudioOnly) {
719 // Verify that end of stream buffers are created.
720 CreateDemuxer("bear-320x240-audio-only.webm");
721 InitializeDemuxer();
722 set_duration_known(false);
723 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2767)));
724 ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
727 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration_UnsupportedStream) {
728 // Verify that end of stream buffers are created and we don't crash
729 // if there are streams in the file that we don't support.
730 CreateDemuxer("vorbis_audio_wmv_video.mkv");
731 InitializeDemuxer();
732 set_duration_known(false);
733 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(1014)));
734 ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
737 TEST_F(FFmpegDemuxerTest, Seek) {
738 // We're testing that the demuxer frees all queued packets when it receives
739 // a Seek().
740 CreateDemuxer("bear-320x240.webm");
741 InitializeDemuxer();
743 // Get our streams.
744 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
745 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
746 ASSERT_TRUE(video);
747 ASSERT_TRUE(audio);
749 // Read a video packet and release it.
750 video->Read(NewReadCB(FROM_HERE, 22084, 0, true));
751 message_loop_.Run();
753 // Issue a simple forward seek, which should discard queued packets.
754 WaitableMessageLoopEvent event;
755 demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
756 event.GetPipelineStatusCB());
757 event.RunAndWaitForStatus(PIPELINE_OK);
759 // Audio read #1.
760 audio->Read(NewReadCB(FROM_HERE, 145, 803000, true));
761 message_loop_.Run();
763 // Audio read #2.
764 audio->Read(NewReadCB(FROM_HERE, 148, 826000, true));
765 message_loop_.Run();
767 // Video read #1.
768 video->Read(NewReadCB(FROM_HERE, 5425, 801000, true));
769 message_loop_.Run();
771 // Video read #2.
772 video->Read(NewReadCB(FROM_HERE, 1906, 834000, false));
773 message_loop_.Run();
776 TEST_F(FFmpegDemuxerTest, SeekText) {
777 // We're testing that the demuxer frees all queued packets when it receives
778 // a Seek().
779 CreateDemuxer("bear-vp8-webvtt.webm");
780 DemuxerStream* text_stream = NULL;
781 EXPECT_CALL(host_, AddTextStream(_, _))
782 .WillOnce(SaveArg<0>(&text_stream));
783 InitializeDemuxerText(true);
784 ASSERT_TRUE(text_stream);
785 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
787 // Get our streams.
788 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
789 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
790 ASSERT_TRUE(video);
791 ASSERT_TRUE(audio);
793 // Read a text packet and release it.
794 text_stream->Read(NewReadCB(FROM_HERE, 31, 0, true));
795 message_loop_.Run();
797 // Issue a simple forward seek, which should discard queued packets.
798 WaitableMessageLoopEvent event;
799 demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
800 event.GetPipelineStatusCB());
801 event.RunAndWaitForStatus(PIPELINE_OK);
803 // Audio read #1.
804 audio->Read(NewReadCB(FROM_HERE, 145, 803000, true));
805 message_loop_.Run();
807 // Audio read #2.
808 audio->Read(NewReadCB(FROM_HERE, 148, 826000, true));
809 message_loop_.Run();
811 // Video read #1.
812 video->Read(NewReadCB(FROM_HERE, 5425, 801000, true));
813 message_loop_.Run();
815 // Video read #2.
816 video->Read(NewReadCB(FROM_HERE, 1906, 834000, false));
817 message_loop_.Run();
819 // Text read #1.
820 text_stream->Read(NewReadCB(FROM_HERE, 19, 500000, true));
821 message_loop_.Run();
823 // Text read #2.
824 text_stream->Read(NewReadCB(FROM_HERE, 19, 1000000, true));
825 message_loop_.Run();
828 class MockReadCB {
829 public:
830 MockReadCB() {}
831 ~MockReadCB() {}
833 MOCK_METHOD2(Run, void(DemuxerStream::Status status,
834 const scoped_refptr<DecoderBuffer>& buffer));
835 private:
836 DISALLOW_COPY_AND_ASSIGN(MockReadCB);
839 TEST_F(FFmpegDemuxerTest, Stop) {
840 // Tests that calling Read() on a stopped demuxer stream immediately deletes
841 // the callback.
842 CreateDemuxer("bear-320x240.webm");
843 InitializeDemuxer();
845 // Get our stream.
846 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
847 ASSERT_TRUE(audio);
849 demuxer_->Stop();
851 // Reads after being stopped are all EOS buffers.
852 StrictMock<MockReadCB> callback;
853 EXPECT_CALL(callback, Run(DemuxerStream::kOk, IsEndOfStreamBuffer()));
855 // Attempt the read...
856 audio->Read(base::Bind(&MockReadCB::Run, base::Unretained(&callback)));
857 message_loop_.RunUntilIdle();
859 // Don't let the test call Stop() again.
860 demuxer_.reset();
863 // Verify that seek works properly when the WebM cues data is at the start of
864 // the file instead of at the end.
865 TEST_F(FFmpegDemuxerTest, SeekWithCuesBeforeFirstCluster) {
866 CreateDemuxer("bear-320x240-cues-in-front.webm");
867 InitializeDemuxer();
869 // Get our streams.
870 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
871 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
872 ASSERT_TRUE(video);
873 ASSERT_TRUE(audio);
875 // Read a video packet and release it.
876 video->Read(NewReadCB(FROM_HERE, 22084, 0, true));
877 message_loop_.Run();
879 // Issue a simple forward seek, which should discard queued packets.
880 WaitableMessageLoopEvent event;
881 demuxer_->Seek(base::TimeDelta::FromMicroseconds(2500000),
882 event.GetPipelineStatusCB());
883 event.RunAndWaitForStatus(PIPELINE_OK);
885 // Audio read #1.
886 audio->Read(NewReadCB(FROM_HERE, 40, 2403000, true));
887 message_loop_.Run();
889 // Audio read #2.
890 audio->Read(NewReadCB(FROM_HERE, 42, 2406000, true));
891 message_loop_.Run();
893 // Video read #1.
894 video->Read(NewReadCB(FROM_HERE, 5276, 2402000, true));
895 message_loop_.Run();
897 // Video read #2.
898 video->Read(NewReadCB(FROM_HERE, 1740, 2436000, false));
899 message_loop_.Run();
902 #if defined(USE_PROPRIETARY_CODECS)
903 // Ensure ID3v1 tag reading is disabled. id3_test.mp3 has an ID3v1 tag with the
904 // field "title" set to "sample for id3 test".
905 TEST_F(FFmpegDemuxerTest, NoID3TagData) {
906 CreateDemuxer("id3_test.mp3");
907 InitializeDemuxer();
908 EXPECT_FALSE(av_dict_get(format_context()->metadata, "title", NULL, 0));
910 #endif
912 #if defined(USE_PROPRIETARY_CODECS)
913 // Ensure MP3 files with large image/video based ID3 tags demux okay. FFmpeg
914 // will hand us a video stream to the data which will likely be in a format we
915 // don't accept as video; e.g. PNG.
916 TEST_F(FFmpegDemuxerTest, Mp3WithVideoStreamID3TagData) {
917 CreateDemuxer("id3_png_test.mp3");
918 InitializeDemuxer();
920 // Ensure the expected streams are present.
921 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO));
922 EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO));
924 #endif
926 // Ensure a video with an unsupported audio track still results in the video
927 // stream being demuxed.
928 TEST_F(FFmpegDemuxerTest, UnsupportedAudioSupportedVideoDemux) {
929 CreateDemuxer("speex_audio_vorbis_video.ogv");
930 InitializeDemuxer();
932 // Ensure the expected streams are present.
933 EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::VIDEO));
934 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::AUDIO));
937 // Ensure a video with an unsupported video track still results in the audio
938 // stream being demuxed.
939 TEST_F(FFmpegDemuxerTest, UnsupportedVideoSupportedAudioDemux) {
940 CreateDemuxer("vorbis_audio_wmv_video.mkv");
941 InitializeDemuxer();
943 // Ensure the expected streams are present.
944 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO));
945 EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO));
948 #if defined(USE_PROPRIETARY_CODECS)
949 // FFmpeg returns null data pointers when samples have zero size, leading to
950 // mistakenly creating end of stream buffers http://crbug.com/169133
951 TEST_F(FFmpegDemuxerTest, MP4_ZeroStszEntry) {
952 CreateDemuxer("bear-1280x720-zero-stsz-entry.mp4");
953 InitializeDemuxer();
954 ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
958 static void ValidateAnnexB(DemuxerStream* stream,
959 DemuxerStream::Status status,
960 const scoped_refptr<DecoderBuffer>& buffer) {
961 EXPECT_EQ(status, DemuxerStream::kOk);
963 if (buffer->end_of_stream()) {
964 base::MessageLoop::current()->PostTask(
965 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
966 return;
969 std::vector<SubsampleEntry> subsamples;
971 if (buffer->decrypt_config())
972 subsamples = buffer->decrypt_config()->subsamples();
974 bool is_valid =
975 mp4::AVC::IsValidAnnexB(buffer->data(), buffer->data_size(),
976 subsamples);
977 EXPECT_TRUE(is_valid);
979 if (!is_valid) {
980 LOG(ERROR) << "Buffer contains invalid Annex B data.";
981 base::MessageLoop::current()->PostTask(
982 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
983 return;
986 stream->Read(base::Bind(&ValidateAnnexB, stream));
989 TEST_F(FFmpegDemuxerTest, IsValidAnnexB) {
990 const char* files[] = {
991 "bear-1280x720-av_frag.mp4",
992 "bear-1280x720-av_with-aud-nalus_frag.mp4"
995 for (size_t i = 0; i < arraysize(files); ++i) {
996 DVLOG(1) << "Testing " << files[i];
997 CreateDemuxer(files[i]);
998 InitializeDemuxer();
1000 // Ensure the expected streams are present.
1001 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
1002 ASSERT_TRUE(stream);
1003 stream->EnableBitstreamConverter();
1005 stream->Read(base::Bind(&ValidateAnnexB, stream));
1006 message_loop_.Run();
1008 demuxer_->Stop();
1009 demuxer_.reset();
1010 data_source_.reset();
1014 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_0) {
1015 CreateDemuxer("bear_rotate_0.mp4");
1016 InitializeDemuxer();
1018 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
1019 ASSERT_TRUE(stream);
1020 ASSERT_EQ(VIDEO_ROTATION_0, stream->video_rotation());
1023 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_90) {
1024 CreateDemuxer("bear_rotate_90.mp4");
1025 InitializeDemuxer();
1027 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
1028 ASSERT_TRUE(stream);
1029 ASSERT_EQ(VIDEO_ROTATION_90, stream->video_rotation());
1032 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_180) {
1033 CreateDemuxer("bear_rotate_180.mp4");
1034 InitializeDemuxer();
1036 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
1037 ASSERT_TRUE(stream);
1038 ASSERT_EQ(VIDEO_ROTATION_180, stream->video_rotation());
1041 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_270) {
1042 CreateDemuxer("bear_rotate_270.mp4");
1043 InitializeDemuxer();
1045 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
1046 ASSERT_TRUE(stream);
1047 ASSERT_EQ(VIDEO_ROTATION_270, stream->video_rotation());
1050 TEST_F(FFmpegDemuxerTest, NaturalSizeWithoutPASP) {
1051 CreateDemuxer("bear-640x360-non_square_pixel-without_pasp.mp4");
1052 InitializeDemuxer();
1054 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
1055 ASSERT_TRUE(stream);
1057 const VideoDecoderConfig& video_config = stream->video_decoder_config();
1058 EXPECT_EQ(gfx::Size(638, 360), video_config.natural_size());
1061 TEST_F(FFmpegDemuxerTest, NaturalSizeWithPASP) {
1062 CreateDemuxer("bear-640x360-non_square_pixel-with_pasp.mp4");
1063 InitializeDemuxer();
1065 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
1066 ASSERT_TRUE(stream);
1068 const VideoDecoderConfig& video_config = stream->video_decoder_config();
1069 EXPECT_EQ(gfx::Size(638, 360), video_config.natural_size());
1072 #endif
1074 } // namespace media