[MD settings] moving attached() code
[chromium-blink-merge.git] / media / filters / ffmpeg_demuxer_unittest.cc
blob21158c286231cc7e6642a43d278dc80d88f574cb
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/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;
36 using ::testing::_;
38 namespace media {
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;
59 return;
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 {
71 protected:
72 FFmpegDemuxerTest() {}
74 virtual ~FFmpegDemuxerTest() {
75 if (demuxer_)
76 demuxer_->Stop();
79 void CreateDemuxer(const std::string& name) {
80 CHECK(!demuxer_);
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,
117 int64 timestamp_us,
118 const base::TimeDelta& discard_front_padding,
119 bool is_key_frame)
120 : size(size),
121 timestamp_us(timestamp_us),
122 discard_front_padding(discard_front_padding),
123 is_key_frame(is_key_frame) {
126 int size;
127 int64 timestamp_us;
128 base::TimeDelta discard_front_padding;
129 bool is_key_frame;
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,
157 int size,
158 int64 timestamp_us,
159 bool is_key_frame) {
160 return NewReadCBWithCheckedDiscard(location,
161 size,
162 timestamp_us,
163 base::TimeDelta(),
164 is_key_frame);
167 DemuxerStream::ReadCB NewReadCBWithCheckedDiscard(
168 const tracked_objects::Location& location,
169 int size,
170 int64 timestamp_us,
171 base::TimeDelta discard_front_padding,
172 bool is_key_frame) {
173 EXPECT_CALL(*this, OnReadDoneCalled(size, timestamp_us));
175 struct ReadExpectation read_expectation(size,
176 timestamp_us,
177 discard_front_padding,
178 is_key_frame);
180 return base::Bind(&FFmpegDemuxerTest::OnReadDone,
181 base::Unretained(this),
182 location,
183 read_expectation);
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);
197 CHECK(stream);
198 return !static_cast<FFmpegDemuxerStream*>(stream)->demuxer_;
201 // Fixture members.
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));
220 message_loop_.Run();
223 EXPECT_TRUE(got_eos_buffer);
226 private:
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"))
236 .AppendASCII(name);
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");
281 InitializeDemuxer();
283 // Video stream should be present.
284 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
285 ASSERT_TRUE(stream);
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);
304 ASSERT_TRUE(stream);
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");
330 InitializeDemuxer();
332 // Video stream should be VP8.
333 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
334 ASSERT_TRUE(stream);
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);
340 ASSERT_TRUE(stream);
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);
364 ASSERT_TRUE(stream);
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);
370 ASSERT_TRUE(stream);
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) {
379 EXPECT_CALL(*this,
380 OnEncryptedMediaInitData(
381 EmeInitDataType::WEBM,
382 std::vector<uint8>(kEncryptedMediaInitData,
383 kEncryptedMediaInitData +
384 arraysize(kEncryptedMediaInitData))))
385 .Times(Exactly(2));
387 CreateDemuxer("bear-320x240-av_enc-av.webm");
388 InitializeDemuxer();
391 TEST_F(FFmpegDemuxerTest, Read_Audio) {
392 // We test that on a successful audio packet read.
393 CreateDemuxer("bear-320x240.webm");
394 InitializeDemuxer();
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));
400 message_loop_.Run();
402 audio->Read(NewReadCB(FROM_HERE, 27, 3000, true));
403 message_loop_.Run();
406 TEST_F(FFmpegDemuxerTest, Read_Video) {
407 // We test that on a successful video packet read.
408 CreateDemuxer("bear-320x240.webm");
409 InitializeDemuxer();
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));
415 message_loop_.Run();
417 video->Read(NewReadCB(FROM_HERE, 1057, 33000, false));
418 message_loop_.Run();
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));
432 message_loop_.Run();
434 text_stream->Read(NewReadCB(FROM_HERE, 19, 500000, true));
435 message_loop_.Run();
438 TEST_F(FFmpegDemuxerTest, SeekInitialized_NoVideoStartTime) {
439 CreateDemuxer("audio-start-time-only.webm");
440 InitializeDemuxer();
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(),
464 true));
465 message_loop_.Run();
466 audio->Read(NewReadCB(FROM_HERE, 165, audio_start_time.InMicroseconds(),
467 true));
468 message_loop_.Run();
470 // Verify that the start time is equal to the lowest timestamp (ie the
471 // audio).
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");
488 InitializeDemuxer();
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));
494 message_loop_.Run();
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");
513 InitializeDemuxer();
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) {
521 audio->Read(
522 NewReadCBWithCheckedDiscard(FROM_HERE, 40, 0, kInfiniteDuration(),
523 true));
524 message_loop_.Run();
525 audio->Read(
526 NewReadCBWithCheckedDiscard(FROM_HERE, 41, 2903, kInfiniteDuration(),
527 true));
528 message_loop_.Run();
529 audio->Read(NewReadCBWithCheckedDiscard(
530 FROM_HERE, 173, 5805, base::TimeDelta::FromMicroseconds(10159), true));
531 message_loop_.Run();
533 audio->Read(NewReadCB(FROM_HERE, 148, 18866, true));
534 message_loop_.Run();
535 EXPECT_EQ(base::TimeDelta::FromMicroseconds(-15964),
536 demuxer_->start_time());
538 video->Read(NewReadCB(FROM_HERE, 5751, 0, true));
539 message_loop_.Run();
541 video->Read(NewReadCB(FROM_HERE, 846, 33367, true));
542 message_loop_.Run();
544 video->Read(NewReadCB(FROM_HERE, 1255, 66733, true));
545 message_loop_.Run();
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");
561 InitializeDemuxer();
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));
571 message_loop_.Run();
573 audio->Read(NewReadCB(FROM_HERE, 1, 2902, true));
574 message_loop_.Run();
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));
583 message_loop_.Run();
585 video->Read(NewReadCB(FROM_HERE, 16, 33241, false));
586 message_loop_.Run();
588 video->Read(NewReadCB(FROM_HERE, 631, 66482, false));
589 message_loop_.Run();
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");
602 InitializeDemuxer();
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));
621 message_loop_.Run();
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));
629 message_loop_.Run();
631 video->Read(NewReadCB(FROM_HERE, 2715, 1000, false));
632 message_loop_.Run();
634 video->Read(NewReadCB(FROM_HERE, 427, 33000, false));
635 message_loop_.Run();
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");
648 InitializeDemuxer();
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));
657 message_loop_.Run();
659 audio->Read(NewReadCB(FROM_HERE, 244, 20000, true));
660 message_loop_.Run();
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");
676 InitializeDemuxer();
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));
694 message_loop_.Run();
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");
703 InitializeDemuxer();
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");
713 InitializeDemuxer();
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");
722 InitializeDemuxer();
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");
732 InitializeDemuxer();
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
740 // a Seek().
741 CreateDemuxer("bear-320x240.webm");
742 InitializeDemuxer();
744 // Get our streams.
745 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
746 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
747 ASSERT_TRUE(video);
748 ASSERT_TRUE(audio);
750 // Read a video packet and release it.
751 video->Read(NewReadCB(FROM_HERE, 22084, 0, true));
752 message_loop_.Run();
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);
760 // Audio read #1.
761 audio->Read(NewReadCB(FROM_HERE, 145, 803000, true));
762 message_loop_.Run();
764 // Audio read #2.
765 audio->Read(NewReadCB(FROM_HERE, 148, 826000, true));
766 message_loop_.Run();
768 // Video read #1.
769 video->Read(NewReadCB(FROM_HERE, 5425, 801000, true));
770 message_loop_.Run();
772 // Video read #2.
773 video->Read(NewReadCB(FROM_HERE, 1906, 834000, false));
774 message_loop_.Run();
777 TEST_F(FFmpegDemuxerTest, SeekText) {
778 // We're testing that the demuxer frees all queued packets when it receives
779 // a Seek().
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());
788 // Get our streams.
789 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
790 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
791 ASSERT_TRUE(video);
792 ASSERT_TRUE(audio);
794 // Read a text packet and release it.
795 text_stream->Read(NewReadCB(FROM_HERE, 31, 0, true));
796 message_loop_.Run();
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);
804 // Audio read #1.
805 audio->Read(NewReadCB(FROM_HERE, 145, 803000, true));
806 message_loop_.Run();
808 // Audio read #2.
809 audio->Read(NewReadCB(FROM_HERE, 148, 826000, true));
810 message_loop_.Run();
812 // Video read #1.
813 video->Read(NewReadCB(FROM_HERE, 5425, 801000, true));
814 message_loop_.Run();
816 // Video read #2.
817 video->Read(NewReadCB(FROM_HERE, 1906, 834000, false));
818 message_loop_.Run();
820 // Text read #1.
821 text_stream->Read(NewReadCB(FROM_HERE, 19, 500000, true));
822 message_loop_.Run();
824 // Text read #2.
825 text_stream->Read(NewReadCB(FROM_HERE, 19, 1000000, true));
826 message_loop_.Run();
829 class MockReadCB {
830 public:
831 MockReadCB() {}
832 ~MockReadCB() {}
834 MOCK_METHOD2(Run, void(DemuxerStream::Status status,
835 const scoped_refptr<DecoderBuffer>& buffer));
836 private:
837 DISALLOW_COPY_AND_ASSIGN(MockReadCB);
840 TEST_F(FFmpegDemuxerTest, Stop) {
841 // Tests that calling Read() on a stopped demuxer stream immediately deletes
842 // the callback.
843 CreateDemuxer("bear-320x240.webm");
844 InitializeDemuxer();
846 // Get our stream.
847 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
848 ASSERT_TRUE(audio);
850 demuxer_->Stop();
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.
861 demuxer_.reset();
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");
868 InitializeDemuxer();
870 // Get our streams.
871 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
872 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
873 ASSERT_TRUE(video);
874 ASSERT_TRUE(audio);
876 // Read a video packet and release it.
877 video->Read(NewReadCB(FROM_HERE, 22084, 0, true));
878 message_loop_.Run();
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);
886 // Audio read #1.
887 audio->Read(NewReadCB(FROM_HERE, 40, 2403000, true));
888 message_loop_.Run();
890 // Audio read #2.
891 audio->Read(NewReadCB(FROM_HERE, 42, 2406000, true));
892 message_loop_.Run();
894 // Video read #1.
895 video->Read(NewReadCB(FROM_HERE, 5276, 2402000, true));
896 message_loop_.Run();
898 // Video read #2.
899 video->Read(NewReadCB(FROM_HERE, 1740, 2436000, false));
900 message_loop_.Run();
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");
908 InitializeDemuxer();
909 EXPECT_FALSE(av_dict_get(format_context()->metadata, "title", NULL, 0));
911 #endif
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");
919 InitializeDemuxer();
921 // Ensure the expected streams are present.
922 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO));
923 EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO));
925 #endif
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");
931 InitializeDemuxer();
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");
942 InitializeDemuxer();
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");
954 InitializeDemuxer();
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());
967 return;
970 std::vector<SubsampleEntry> subsamples;
972 if (buffer->decrypt_config())
973 subsamples = buffer->decrypt_config()->subsamples();
975 bool is_valid =
976 mp4::AVC::IsValidAnnexB(buffer->data(), buffer->data_size(),
977 subsamples);
978 EXPECT_TRUE(is_valid);
980 if (!is_valid) {
981 LOG(ERROR) << "Buffer contains invalid Annex B data.";
982 base::MessageLoop::current()->PostTask(
983 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
984 return;
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]);
999 InitializeDemuxer();
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();
1009 demuxer_->Stop();
1010 demuxer_.reset();
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());
1073 #endif
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);
1081 ASSERT_TRUE(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();
1089 #endif
1091 } // namespace media