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