Upstream version 10.38.220.0
[platform/framework/web/crosswalk.git] / src / media / filters / ffmpeg_demuxer_unittest.cc
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.
4
5 #include <algorithm>
6 #include <deque>
7 #include <string>
8
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 "media/formats/webm/webm_crypto_helpers.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
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::_;
37
38 namespace media {
39
40 MATCHER(IsEndOfStreamBuffer,
41         std::string(negation ? "isn't" : "is") + " end of stream") {
42   return arg->end_of_stream();
43 }
44
45 static void EosOnReadDone(bool* got_eos_buffer,
46                           DemuxerStream::Status status,
47                           const scoped_refptr<DecoderBuffer>& buffer) {
48   base::MessageLoop::current()->PostTask(
49       FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
50
51   EXPECT_EQ(status, DemuxerStream::kOk);
52   if (buffer->end_of_stream()) {
53     *got_eos_buffer = true;
54     return;
55   }
56
57   EXPECT_TRUE(buffer->data());
58   EXPECT_GT(buffer->data_size(), 0);
59   *got_eos_buffer = false;
60 };
61
62
63 // Fixture class to facilitate writing tests.  Takes care of setting up the
64 // FFmpeg, pipeline and filter host mocks.
65 class FFmpegDemuxerTest : public testing::Test {
66  protected:
67   FFmpegDemuxerTest() {}
68
69   virtual ~FFmpegDemuxerTest() {
70     if (demuxer_) {
71       WaitableMessageLoopEvent event;
72       demuxer_->Stop(event.GetClosure());
73       event.RunAndWait();
74     }
75   }
76
77   void CreateDemuxer(const std::string& name) {
78     CHECK(!demuxer_);
79
80     EXPECT_CALL(host_, AddBufferedTimeRange(_, _)).Times(AnyNumber());
81
82     CreateDataSource(name);
83
84     Demuxer::NeedKeyCB need_key_cb =
85         base::Bind(&FFmpegDemuxerTest::NeedKeyCB, base::Unretained(this));
86
87     demuxer_.reset(new FFmpegDemuxer(message_loop_.message_loop_proxy(),
88                                      data_source_.get(),
89                                      need_key_cb,
90                                      new MediaLog()));
91   }
92
93   MOCK_METHOD1(CheckPoint, void(int v));
94
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);
102   }
103
104   void InitializeDemuxerText(bool enable_text) {
105     InitializeDemuxerWithTimelineOffset(enable_text, base::Time());
106   }
107
108   void InitializeDemuxer() {
109     InitializeDemuxerText(false);
110   }
111
112   MOCK_METHOD2(OnReadDoneCalled, void(int, int64));
113
114   // Verifies that |buffer| has a specific |size| and |timestamp|.
115   // |location| simply indicates where the call to this function was made.
116   // This makes it easier to track down where test failures occur.
117   void OnReadDone(const tracked_objects::Location& location,
118                   int size,
119                   int64 timestamp_us,
120                   base::TimeDelta discard_front_padding,
121                   DemuxerStream::Status status,
122                   const scoped_refptr<DecoderBuffer>& buffer) {
123     std::string location_str;
124     location.Write(true, false, &location_str);
125     location_str += "\n";
126     SCOPED_TRACE(location_str);
127     EXPECT_EQ(status, DemuxerStream::kOk);
128     OnReadDoneCalled(size, timestamp_us);
129     EXPECT_TRUE(buffer.get() != NULL);
130     EXPECT_EQ(size, buffer->data_size());
131     EXPECT_EQ(timestamp_us, buffer->timestamp().InMicroseconds());
132     EXPECT_EQ(discard_front_padding, buffer->discard_padding().first);
133     DCHECK_EQ(&message_loop_, base::MessageLoop::current());
134     message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
135   }
136
137   DemuxerStream::ReadCB NewReadCB(const tracked_objects::Location& location,
138                                   int size,
139                                   int64 timestamp_us) {
140     EXPECT_CALL(*this, OnReadDoneCalled(size, timestamp_us));
141     return base::Bind(&FFmpegDemuxerTest::OnReadDone,
142                       base::Unretained(this),
143                       location,
144                       size,
145                       timestamp_us,
146                       base::TimeDelta());
147   }
148
149   DemuxerStream::ReadCB NewReadCBWithCheckedDiscard(
150       const tracked_objects::Location& location,
151       int size,
152       int64 timestamp_us,
153       base::TimeDelta discard_front_padding) {
154     EXPECT_CALL(*this, OnReadDoneCalled(size, timestamp_us));
155     return base::Bind(&FFmpegDemuxerTest::OnReadDone,
156                       base::Unretained(this),
157                       location,
158                       size,
159                       timestamp_us,
160                       discard_front_padding);
161   }
162
163   // TODO(xhwang): This is a workaround of the issue that move-only parameters
164   // are not supported in mocked methods. Remove this when the issue is fixed
165   // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use
166   // std::string instead of scoped_ptr<uint8[]> (http://crbug.com/130689).
167   MOCK_METHOD3(NeedKeyCBMock, void(const std::string& type,
168                                    const uint8* init_data, int init_data_size));
169   void NeedKeyCB(const std::string& type,
170                  const std::vector<uint8>& init_data) {
171     const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0];
172     NeedKeyCBMock(type, init_data_ptr, init_data.size());
173   }
174
175   // Accessor to demuxer internals.
176   void set_duration_known(bool duration_known) {
177     demuxer_->duration_known_ = duration_known;
178   }
179
180   bool IsStreamStopped(DemuxerStream::Type type) {
181     DemuxerStream* stream = demuxer_->GetStream(type);
182     CHECK(stream);
183     return !static_cast<FFmpegDemuxerStream*>(stream)->demuxer_;
184   }
185
186   // Fixture members.
187   scoped_ptr<FileDataSource> data_source_;
188   scoped_ptr<FFmpegDemuxer> demuxer_;
189   StrictMock<MockDemuxerHost> host_;
190   base::MessageLoop message_loop_;
191
192   AVFormatContext* format_context() {
193     return demuxer_->glue_->format_context();
194   }
195
196   int preferred_seeking_stream_index() const {
197     return demuxer_->preferred_stream_for_seeking_.first;
198   }
199
200   void ReadUntilEndOfStream(DemuxerStream* stream) {
201     bool got_eos_buffer = false;
202     const int kMaxBuffers = 170;
203     for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) {
204       stream->Read(base::Bind(&EosOnReadDone, &got_eos_buffer));
205       message_loop_.Run();
206     }
207
208     EXPECT_TRUE(got_eos_buffer);
209   }
210
211  private:
212   void CreateDataSource(const std::string& name) {
213     CHECK(!data_source_);
214
215     base::FilePath file_path;
216     EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
217
218     file_path = file_path.Append(FILE_PATH_LITERAL("media"))
219         .Append(FILE_PATH_LITERAL("test"))
220         .Append(FILE_PATH_LITERAL("data"))
221         .AppendASCII(name);
222
223     data_source_.reset(new FileDataSource());
224     EXPECT_TRUE(data_source_->Initialize(file_path));
225   }
226
227   DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest);
228 };
229
230 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) {
231   // Simulate avformat_open_input() failing.
232   CreateDemuxer("ten_byte_file");
233   WaitableMessageLoopEvent event;
234   demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
235   event.RunAndWaitForStatus(DEMUXER_ERROR_COULD_NOT_OPEN);
236 }
237
238 // TODO(acolwell): Uncomment this test when we discover a file that passes
239 // avformat_open_input(), but has avformat_find_stream_info() fail.
240 //
241 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) {
242 //  ("find_stream_info_fail.webm");
243 //  demuxer_->Initialize(
244 //      &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE));
245 //  message_loop_.RunUntilIdle();
246 //}
247
248 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) {
249   // Open a file with no streams whatsoever.
250   CreateDemuxer("no_streams.webm");
251   WaitableMessageLoopEvent event;
252   demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
253   event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
254 }
255
256 TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) {
257   // Open a file containing streams but none of which are audio/video streams.
258   CreateDemuxer("no_audio_video.webm");
259   WaitableMessageLoopEvent event;
260   demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
261   event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
262 }
263
264 TEST_F(FFmpegDemuxerTest, Initialize_Successful) {
265   CreateDemuxer("bear-320x240.webm");
266   InitializeDemuxer();
267
268   // Video stream should be present.
269   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
270   ASSERT_TRUE(stream);
271   EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
272
273   const VideoDecoderConfig& video_config = stream->video_decoder_config();
274   EXPECT_EQ(kCodecVP8, video_config.codec());
275   EXPECT_EQ(VideoFrame::YV12, video_config.format());
276   EXPECT_EQ(320, video_config.coded_size().width());
277   EXPECT_EQ(240, video_config.coded_size().height());
278   EXPECT_EQ(0, video_config.visible_rect().x());
279   EXPECT_EQ(0, video_config.visible_rect().y());
280   EXPECT_EQ(320, video_config.visible_rect().width());
281   EXPECT_EQ(240, video_config.visible_rect().height());
282   EXPECT_EQ(320, video_config.natural_size().width());
283   EXPECT_EQ(240, video_config.natural_size().height());
284   EXPECT_FALSE(video_config.extra_data());
285   EXPECT_EQ(0u, video_config.extra_data_size());
286
287   // Audio stream should be present.
288   stream = demuxer_->GetStream(DemuxerStream::AUDIO);
289   ASSERT_TRUE(stream);
290   EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
291
292   const AudioDecoderConfig& audio_config = stream->audio_decoder_config();
293   EXPECT_EQ(kCodecVorbis, audio_config.codec());
294   EXPECT_EQ(32, audio_config.bits_per_channel());
295   EXPECT_EQ(CHANNEL_LAYOUT_STEREO, audio_config.channel_layout());
296   EXPECT_EQ(44100, audio_config.samples_per_second());
297   EXPECT_EQ(kSampleFormatPlanarF32, audio_config.sample_format());
298   EXPECT_TRUE(audio_config.extra_data());
299   EXPECT_GT(audio_config.extra_data_size(), 0u);
300
301   // Unknown stream should never be present.
302   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
303 }
304
305 TEST_F(FFmpegDemuxerTest, Initialize_Multitrack) {
306   // Open a file containing the following streams:
307   //   Stream #0: Video (VP8)
308   //   Stream #1: Audio (Vorbis)
309   //   Stream #2: Subtitles (SRT)
310   //   Stream #3: Video (Theora)
311   //   Stream #4: Audio (16-bit signed little endian PCM)
312   //
313   // We should only pick the first audio/video streams we come across.
314   CreateDemuxer("bear-320x240-multitrack.webm");
315   InitializeDemuxer();
316
317   // Video stream should be VP8.
318   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
319   ASSERT_TRUE(stream);
320   EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
321   EXPECT_EQ(kCodecVP8, stream->video_decoder_config().codec());
322
323   // Audio stream should be Vorbis.
324   stream = demuxer_->GetStream(DemuxerStream::AUDIO);
325   ASSERT_TRUE(stream);
326   EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
327   EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec());
328
329   // Unknown stream should never be present.
330   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
331 }
332
333 TEST_F(FFmpegDemuxerTest, Initialize_MultitrackText) {
334   // Open a file containing the following streams:
335   //   Stream #0: Video (VP8)
336   //   Stream #1: Audio (Vorbis)
337   //   Stream #2: Text (WebVTT)
338
339   CreateDemuxer("bear-vp8-webvtt.webm");
340   DemuxerStream* text_stream = NULL;
341   EXPECT_CALL(host_, AddTextStream(_, _))
342       .WillOnce(SaveArg<0>(&text_stream));
343   InitializeDemuxerText(true);
344   ASSERT_TRUE(text_stream);
345   EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
346
347   // Video stream should be VP8.
348   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
349   ASSERT_TRUE(stream);
350   EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
351   EXPECT_EQ(kCodecVP8, stream->video_decoder_config().codec());
352
353   // Audio stream should be Vorbis.
354   stream = demuxer_->GetStream(DemuxerStream::AUDIO);
355   ASSERT_TRUE(stream);
356   EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
357   EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec());
358
359   // Unknown stream should never be present.
360   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
361 }
362
363 TEST_F(FFmpegDemuxerTest, Initialize_Encrypted) {
364   EXPECT_CALL(*this, NeedKeyCBMock(kWebMEncryptInitDataType, NotNull(),
365                                    DecryptConfig::kDecryptionKeySize))
366       .Times(Exactly(2));
367
368   CreateDemuxer("bear-320x240-av_enc-av.webm");
369   InitializeDemuxer();
370 }
371
372 TEST_F(FFmpegDemuxerTest, Read_Audio) {
373   // We test that on a successful audio packet read.
374   CreateDemuxer("bear-320x240.webm");
375   InitializeDemuxer();
376
377   // Attempt a read from the audio stream and run the message loop until done.
378   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
379
380   audio->Read(NewReadCB(FROM_HERE, 29, 0));
381   message_loop_.Run();
382
383   audio->Read(NewReadCB(FROM_HERE, 27, 3000));
384   message_loop_.Run();
385 }
386
387 TEST_F(FFmpegDemuxerTest, Read_Video) {
388   // We test that on a successful video packet read.
389   CreateDemuxer("bear-320x240.webm");
390   InitializeDemuxer();
391
392   // Attempt a read from the video stream and run the message loop until done.
393   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
394
395   video->Read(NewReadCB(FROM_HERE, 22084, 0));
396   message_loop_.Run();
397
398   video->Read(NewReadCB(FROM_HERE, 1057, 33000));
399   message_loop_.Run();
400 }
401
402 TEST_F(FFmpegDemuxerTest, Read_Text) {
403   // We test that on a successful text packet read.
404   CreateDemuxer("bear-vp8-webvtt.webm");
405   DemuxerStream* text_stream = NULL;
406   EXPECT_CALL(host_, AddTextStream(_, _))
407       .WillOnce(SaveArg<0>(&text_stream));
408   InitializeDemuxerText(true);
409   ASSERT_TRUE(text_stream);
410   EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
411
412   text_stream->Read(NewReadCB(FROM_HERE, 31, 0));
413   message_loop_.Run();
414
415   text_stream->Read(NewReadCB(FROM_HERE, 19, 500000));
416   message_loop_.Run();
417 }
418
419 TEST_F(FFmpegDemuxerTest, SeekInitialized_NoVideoStartTime) {
420   CreateDemuxer("audio-start-time-only.webm");
421   InitializeDemuxer();
422   EXPECT_EQ(0, preferred_seeking_stream_index());
423 }
424
425 TEST_F(FFmpegDemuxerTest, Read_VideoPositiveStartTime) {
426   const int64 kTimelineOffsetMs = 1352550896000LL;
427
428   // Test the start time is the first timestamp of the video and audio stream.
429   CreateDemuxer("nonzero-start-time.webm");
430   InitializeDemuxerWithTimelineOffset(
431       false, base::Time::FromJsTime(kTimelineOffsetMs));
432
433   // Attempt a read from the video stream and run the message loop until done.
434   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
435   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
436
437   const base::TimeDelta video_start_time =
438       base::TimeDelta::FromMicroseconds(400000);
439   const base::TimeDelta audio_start_time =
440       base::TimeDelta::FromMicroseconds(396000);
441
442   // Run the test twice with a seek in between.
443   for (int i = 0; i < 2; ++i) {
444     video->Read(NewReadCB(FROM_HERE, 5636, video_start_time.InMicroseconds()));
445     message_loop_.Run();
446     audio->Read(NewReadCB(FROM_HERE, 165, audio_start_time.InMicroseconds()));
447     message_loop_.Run();
448
449     // Verify that the start time is equal to the lowest timestamp (ie the
450     // audio).
451     EXPECT_EQ(audio_start_time, demuxer_->start_time());
452
453     // Verify that the timeline offset has not been adjusted by the start time.
454     EXPECT_EQ(kTimelineOffsetMs, demuxer_->GetTimelineOffset().ToJavaTime());
455
456     // Seek back to the beginning and repeat the test.
457     WaitableMessageLoopEvent event;
458     demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
459     event.RunAndWaitForStatus(PIPELINE_OK);
460   }
461 }
462
463 TEST_F(FFmpegDemuxerTest, Read_AudioNoStartTime) {
464   // FFmpeg does not set timestamps when demuxing wave files.  Ensure that the
465   // demuxer sets a start time of zero in this case.
466   CreateDemuxer("sfx_s24le.wav");
467   InitializeDemuxer();
468
469   // Run the test twice with a seek in between.
470   for (int i = 0; i < 2; ++i) {
471     demuxer_->GetStream(DemuxerStream::AUDIO)
472         ->Read(NewReadCB(FROM_HERE, 4095, 0));
473     message_loop_.Run();
474     EXPECT_EQ(base::TimeDelta(), demuxer_->start_time());
475
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);
480   }
481 }
482
483 // TODO(dalecurtis): Test is disabled since FFmpeg does not currently guarantee
484 // the order of demuxed packets in OGG containers.  Re-enable once we decide to
485 // either workaround it or attempt a fix upstream.  See http://crbug.com/387996.
486 TEST_F(FFmpegDemuxerTest,
487        DISABLED_Read_AudioNegativeStartTimeAndOggDiscard_Bear) {
488   // Many ogg files have negative starting timestamps, so ensure demuxing and
489   // seeking work correctly with a negative start time.
490   CreateDemuxer("bear.ogv");
491   InitializeDemuxer();
492
493   // Attempt a read from the video stream and run the message loop until done.
494   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
495   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
496
497   // Run the test twice with a seek in between.
498   for (int i = 0; i < 2; ++i) {
499     audio->Read(
500         NewReadCBWithCheckedDiscard(FROM_HERE, 40, 0, kInfiniteDuration()));
501     message_loop_.Run();
502     audio->Read(
503         NewReadCBWithCheckedDiscard(FROM_HERE, 41, 2903, kInfiniteDuration()));
504     message_loop_.Run();
505     audio->Read(NewReadCBWithCheckedDiscard(
506         FROM_HERE, 173, 5805, base::TimeDelta::FromMicroseconds(10159)));
507     message_loop_.Run();
508
509     audio->Read(NewReadCB(FROM_HERE, 148, 18866));
510     message_loop_.Run();
511     EXPECT_EQ(base::TimeDelta::FromMicroseconds(-15964),
512               demuxer_->start_time());
513
514     video->Read(NewReadCB(FROM_HERE, 5751, 0));
515     message_loop_.Run();
516
517     video->Read(NewReadCB(FROM_HERE, 846, 33367));
518     message_loop_.Run();
519
520     video->Read(NewReadCB(FROM_HERE, 1255, 66733));
521     message_loop_.Run();
522
523     // Seek back to the beginning and repeat the test.
524     WaitableMessageLoopEvent event;
525     demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
526     event.RunAndWaitForStatus(PIPELINE_OK);
527   }
528 }
529
530 // Same test above, but using sync2.ogv which has video stream muxed before the
531 // audio stream, so seeking based only on start time will fail since ffmpeg is
532 // essentially just seeking based on file position.
533 TEST_F(FFmpegDemuxerTest, Read_AudioNegativeStartTimeAndOggDiscard_Sync) {
534   // Many ogg files have negative starting timestamps, so ensure demuxing and
535   // seeking work correctly with a negative start time.
536   CreateDemuxer("sync2.ogv");
537   InitializeDemuxer();
538
539   // Attempt a read from the video stream and run the message loop until done.
540   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
541   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
542
543   // Run the test twice with a seek in between.
544   for (int i = 0; i < 2; ++i) {
545     audio->Read(NewReadCBWithCheckedDiscard(
546         FROM_HERE, 1, 0, base::TimeDelta::FromMicroseconds(2902)));
547     message_loop_.Run();
548
549     audio->Read(NewReadCB(FROM_HERE, 1, 2902));
550     message_loop_.Run();
551     EXPECT_EQ(base::TimeDelta::FromMicroseconds(-2902),
552               demuxer_->start_time());
553
554     // Though the internal start time may be below zero, the exposed media time
555     // must always be greater than zero.
556     EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
557
558     video->Read(NewReadCB(FROM_HERE, 9997, 0));
559     message_loop_.Run();
560
561     video->Read(NewReadCB(FROM_HERE, 16, 33241));
562     message_loop_.Run();
563
564     video->Read(NewReadCB(FROM_HERE, 631, 66482));
565     message_loop_.Run();
566
567     // Seek back to the beginning and repeat the test.
568     WaitableMessageLoopEvent event;
569     demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
570     event.RunAndWaitForStatus(PIPELINE_OK);
571   }
572 }
573
574 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) {
575   // Verify that end of stream buffers are created.
576   CreateDemuxer("bear-320x240.webm");
577   InitializeDemuxer();
578   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
579 }
580
581 TEST_F(FFmpegDemuxerTest, Read_EndOfStreamText) {
582   // Verify that end of stream buffers are created.
583   CreateDemuxer("bear-vp8-webvtt.webm");
584   DemuxerStream* text_stream = NULL;
585   EXPECT_CALL(host_, AddTextStream(_, _))
586       .WillOnce(SaveArg<0>(&text_stream));
587   InitializeDemuxerText(true);
588   ASSERT_TRUE(text_stream);
589   EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
590
591   bool got_eos_buffer = false;
592   const int kMaxBuffers = 10;
593   for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) {
594     text_stream->Read(base::Bind(&EosOnReadDone, &got_eos_buffer));
595     message_loop_.Run();
596   }
597
598   EXPECT_TRUE(got_eos_buffer);
599 }
600
601 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration) {
602   // Verify that end of stream buffers are created.
603   CreateDemuxer("bear-320x240.webm");
604   InitializeDemuxer();
605   set_duration_known(false);
606   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2767)));
607   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
608   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::VIDEO));
609 }
610
611 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration_VideoOnly) {
612   // Verify that end of stream buffers are created.
613   CreateDemuxer("bear-320x240-video-only.webm");
614   InitializeDemuxer();
615   set_duration_known(false);
616   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2703)));
617   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::VIDEO));
618 }
619
620 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration_AudioOnly) {
621   // Verify that end of stream buffers are created.
622   CreateDemuxer("bear-320x240-audio-only.webm");
623   InitializeDemuxer();
624   set_duration_known(false);
625   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2767)));
626   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
627 }
628
629 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration_UnsupportedStream) {
630   // Verify that end of stream buffers are created and we don't crash
631   // if there are streams in the file that we don't support.
632   CreateDemuxer("vorbis_audio_wmv_video.mkv");
633   InitializeDemuxer();
634   set_duration_known(false);
635   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(1014)));
636   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
637 }
638
639 TEST_F(FFmpegDemuxerTest, Seek) {
640   // We're testing that the demuxer frees all queued packets when it receives
641   // a Seek().
642   CreateDemuxer("bear-320x240.webm");
643   InitializeDemuxer();
644
645   // Get our streams.
646   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
647   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
648   ASSERT_TRUE(video);
649   ASSERT_TRUE(audio);
650
651   // Read a video packet and release it.
652   video->Read(NewReadCB(FROM_HERE, 22084, 0));
653   message_loop_.Run();
654
655   // Issue a simple forward seek, which should discard queued packets.
656   WaitableMessageLoopEvent event;
657   demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
658                  event.GetPipelineStatusCB());
659   event.RunAndWaitForStatus(PIPELINE_OK);
660
661   // Audio read #1.
662   audio->Read(NewReadCB(FROM_HERE, 145, 803000));
663   message_loop_.Run();
664
665   // Audio read #2.
666   audio->Read(NewReadCB(FROM_HERE, 148, 826000));
667   message_loop_.Run();
668
669   // Video read #1.
670   video->Read(NewReadCB(FROM_HERE, 5425, 801000));
671   message_loop_.Run();
672
673   // Video read #2.
674   video->Read(NewReadCB(FROM_HERE, 1906, 834000));
675   message_loop_.Run();
676 }
677
678 TEST_F(FFmpegDemuxerTest, SeekText) {
679   // We're testing that the demuxer frees all queued packets when it receives
680   // a Seek().
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());
688
689   // Get our streams.
690   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
691   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
692   ASSERT_TRUE(video);
693   ASSERT_TRUE(audio);
694
695   // Read a text packet and release it.
696   text_stream->Read(NewReadCB(FROM_HERE, 31, 0));
697   message_loop_.Run();
698
699   // Issue a simple forward seek, which should discard queued packets.
700   WaitableMessageLoopEvent event;
701   demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
702                  event.GetPipelineStatusCB());
703   event.RunAndWaitForStatus(PIPELINE_OK);
704
705   // Audio read #1.
706   audio->Read(NewReadCB(FROM_HERE, 145, 803000));
707   message_loop_.Run();
708
709   // Audio read #2.
710   audio->Read(NewReadCB(FROM_HERE, 148, 826000));
711   message_loop_.Run();
712
713   // Video read #1.
714   video->Read(NewReadCB(FROM_HERE, 5425, 801000));
715   message_loop_.Run();
716
717   // Video read #2.
718   video->Read(NewReadCB(FROM_HERE, 1906, 834000));
719   message_loop_.Run();
720
721   // Text read #1.
722   text_stream->Read(NewReadCB(FROM_HERE, 19, 500000));
723   message_loop_.Run();
724
725   // Text read #2.
726   text_stream->Read(NewReadCB(FROM_HERE, 19, 1000000));
727   message_loop_.Run();
728 }
729
730 class MockReadCB {
731  public:
732   MockReadCB() {}
733   ~MockReadCB() {}
734
735   MOCK_METHOD2(Run, void(DemuxerStream::Status status,
736                          const scoped_refptr<DecoderBuffer>& buffer));
737  private:
738   DISALLOW_COPY_AND_ASSIGN(MockReadCB);
739 };
740
741 TEST_F(FFmpegDemuxerTest, Stop) {
742   // Tests that calling Read() on a stopped demuxer stream immediately deletes
743   // the callback.
744   CreateDemuxer("bear-320x240.webm");
745   InitializeDemuxer();
746
747   // Get our stream.
748   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
749   ASSERT_TRUE(audio);
750
751   WaitableMessageLoopEvent event;
752   demuxer_->Stop(event.GetClosure());
753   event.RunAndWait();
754
755   // Reads after being stopped are all EOS buffers.
756   StrictMock<MockReadCB> callback;
757   EXPECT_CALL(callback, Run(DemuxerStream::kOk, IsEndOfStreamBuffer()));
758
759   // Attempt the read...
760   audio->Read(base::Bind(&MockReadCB::Run, base::Unretained(&callback)));
761   message_loop_.RunUntilIdle();
762
763   // Don't let the test call Stop() again.
764   demuxer_.reset();
765 }
766
767 // Verify that seek works properly when the WebM cues data is at the start of
768 // the file instead of at the end.
769 TEST_F(FFmpegDemuxerTest, SeekWithCuesBeforeFirstCluster) {
770   CreateDemuxer("bear-320x240-cues-in-front.webm");
771   InitializeDemuxer();
772
773   // Get our streams.
774   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
775   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
776   ASSERT_TRUE(video);
777   ASSERT_TRUE(audio);
778
779   // Read a video packet and release it.
780   video->Read(NewReadCB(FROM_HERE, 22084, 0));
781   message_loop_.Run();
782
783   // Issue a simple forward seek, which should discard queued packets.
784   WaitableMessageLoopEvent event;
785   demuxer_->Seek(base::TimeDelta::FromMicroseconds(2500000),
786                  event.GetPipelineStatusCB());
787   event.RunAndWaitForStatus(PIPELINE_OK);
788
789   // Audio read #1.
790   audio->Read(NewReadCB(FROM_HERE, 40, 2403000));
791   message_loop_.Run();
792
793   // Audio read #2.
794   audio->Read(NewReadCB(FROM_HERE, 42, 2406000));
795   message_loop_.Run();
796
797   // Video read #1.
798   video->Read(NewReadCB(FROM_HERE, 5276, 2402000));
799   message_loop_.Run();
800
801   // Video read #2.
802   video->Read(NewReadCB(FROM_HERE, 1740, 2436000));
803   message_loop_.Run();
804 }
805
806 #if defined(USE_PROPRIETARY_CODECS)
807 // Ensure ID3v1 tag reading is disabled.  id3_test.mp3 has an ID3v1 tag with the
808 // field "title" set to "sample for id3 test".
809 TEST_F(FFmpegDemuxerTest, NoID3TagData) {
810   CreateDemuxer("id3_test.mp3");
811   InitializeDemuxer();
812   EXPECT_FALSE(av_dict_get(format_context()->metadata, "title", NULL, 0));
813 }
814 #endif
815
816 #if defined(USE_PROPRIETARY_CODECS)
817 // Ensure MP3 files with large image/video based ID3 tags demux okay.  FFmpeg
818 // will hand us a video stream to the data which will likely be in a format we
819 // don't accept as video; e.g. PNG.
820 TEST_F(FFmpegDemuxerTest, Mp3WithVideoStreamID3TagData) {
821   CreateDemuxer("id3_png_test.mp3");
822   InitializeDemuxer();
823
824   // Ensure the expected streams are present.
825   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO));
826   EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO));
827 }
828 #endif
829
830 // Ensure a video with an unsupported audio track still results in the video
831 // stream being demuxed.
832 TEST_F(FFmpegDemuxerTest, UnsupportedAudioSupportedVideoDemux) {
833   CreateDemuxer("speex_audio_vorbis_video.ogv");
834   InitializeDemuxer();
835
836   // Ensure the expected streams are present.
837   EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::VIDEO));
838   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::AUDIO));
839 }
840
841 // Ensure a video with an unsupported video track still results in the audio
842 // stream being demuxed.
843 TEST_F(FFmpegDemuxerTest, UnsupportedVideoSupportedAudioDemux) {
844   CreateDemuxer("vorbis_audio_wmv_video.mkv");
845   InitializeDemuxer();
846
847   // Ensure the expected streams are present.
848   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO));
849   EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO));
850 }
851
852 #if defined(USE_PROPRIETARY_CODECS)
853 // FFmpeg returns null data pointers when samples have zero size, leading to
854 // mistakenly creating end of stream buffers http://crbug.com/169133
855 TEST_F(FFmpegDemuxerTest, MP4_ZeroStszEntry) {
856   CreateDemuxer("bear-1280x720-zero-stsz-entry.mp4");
857   InitializeDemuxer();
858   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
859 }
860
861
862 static void ValidateAnnexB(DemuxerStream* stream,
863                            DemuxerStream::Status status,
864                            const scoped_refptr<DecoderBuffer>& buffer) {
865   EXPECT_EQ(status, DemuxerStream::kOk);
866
867   if (buffer->end_of_stream()) {
868     base::MessageLoop::current()->PostTask(
869         FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
870     return;
871   }
872
873   std::vector<SubsampleEntry> subsamples;
874
875   if (buffer->decrypt_config())
876     subsamples = buffer->decrypt_config()->subsamples();
877
878   bool is_valid =
879       mp4::AVC::IsValidAnnexB(buffer->data(), buffer->data_size(),
880                               subsamples);
881   EXPECT_TRUE(is_valid);
882
883   if (!is_valid) {
884     LOG(ERROR) << "Buffer contains invalid Annex B data.";
885     base::MessageLoop::current()->PostTask(
886         FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
887     return;
888   }
889
890   stream->Read(base::Bind(&ValidateAnnexB, stream));
891 };
892
893 TEST_F(FFmpegDemuxerTest, IsValidAnnexB) {
894   const char* files[] = {
895     "bear-1280x720-av_frag.mp4",
896     "bear-1280x720-av_with-aud-nalus_frag.mp4"
897   };
898
899   for (size_t i = 0; i < arraysize(files); ++i) {
900     DVLOG(1) << "Testing " << files[i];
901     CreateDemuxer(files[i]);
902     InitializeDemuxer();
903
904     // Ensure the expected streams are present.
905     DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
906     ASSERT_TRUE(stream);
907     stream->EnableBitstreamConverter();
908
909     stream->Read(base::Bind(&ValidateAnnexB, stream));
910     message_loop_.Run();
911
912     WaitableMessageLoopEvent event;
913     demuxer_->Stop(event.GetClosure());
914     event.RunAndWait();
915     demuxer_.reset();
916     data_source_.reset();
917   }
918 }
919
920 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_0) {
921   CreateDemuxer("bear_rotate_0.mp4");
922   InitializeDemuxer();
923
924   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
925   ASSERT_TRUE(stream);
926   ASSERT_EQ(VIDEO_ROTATION_0, stream->video_rotation());
927 }
928
929 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_90) {
930   CreateDemuxer("bear_rotate_90.mp4");
931   InitializeDemuxer();
932
933   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
934   ASSERT_TRUE(stream);
935   ASSERT_EQ(VIDEO_ROTATION_90, stream->video_rotation());
936 }
937
938 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_180) {
939   CreateDemuxer("bear_rotate_180.mp4");
940   InitializeDemuxer();
941
942   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
943   ASSERT_TRUE(stream);
944   ASSERT_EQ(VIDEO_ROTATION_180, stream->video_rotation());
945 }
946
947 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_270) {
948   CreateDemuxer("bear_rotate_270.mp4");
949   InitializeDemuxer();
950
951   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
952   ASSERT_TRUE(stream);
953   ASSERT_EQ(VIDEO_ROTATION_270, stream->video_rotation());
954 }
955
956 #endif
957
958 }  // namespace media