Upstream version 10.38.208.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 been adjusted by the start time.
454     EXPECT_EQ(kTimelineOffsetMs + audio_start_time.InMilliseconds(),
455               demuxer_->GetTimelineOffset().ToJavaTime());
456
457     // Seek back to the beginning and repeat the test.
458     WaitableMessageLoopEvent event;
459     demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
460     event.RunAndWaitForStatus(PIPELINE_OK);
461   }
462 }
463
464 TEST_F(FFmpegDemuxerTest, Read_AudioNoStartTime) {
465   // FFmpeg does not set timestamps when demuxing wave files.  Ensure that the
466   // demuxer sets a start time of zero in this case.
467   CreateDemuxer("sfx_s24le.wav");
468   InitializeDemuxer();
469
470   // Run the test twice with a seek in between.
471   for (int i = 0; i < 2; ++i) {
472     demuxer_->GetStream(DemuxerStream::AUDIO)
473         ->Read(NewReadCB(FROM_HERE, 4095, 0));
474     message_loop_.Run();
475     EXPECT_EQ(base::TimeDelta(), demuxer_->start_time());
476
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);
481   }
482 }
483
484 // TODO(dalecurtis): Test is disabled since FFmpeg does not currently guarantee
485 // the order of demuxed packets in OGG containers.  Re-enable once we decide to
486 // either workaround it or attempt a fix upstream.  See http://crbug.com/387996.
487 TEST_F(FFmpegDemuxerTest,
488        DISABLED_Read_AudioNegativeStartTimeAndOggDiscard_Bear) {
489   // Many ogg files have negative starting timestamps, so ensure demuxing and
490   // seeking work correctly with a negative start time.
491   CreateDemuxer("bear.ogv");
492   InitializeDemuxer();
493
494   // Attempt a read from the video stream and run the message loop until done.
495   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
496   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
497
498   // Run the test twice with a seek in between.
499   for (int i = 0; i < 2; ++i) {
500     audio->Read(
501         NewReadCBWithCheckedDiscard(FROM_HERE, 40, 0, kInfiniteDuration()));
502     message_loop_.Run();
503     audio->Read(
504         NewReadCBWithCheckedDiscard(FROM_HERE, 41, 2903, kInfiniteDuration()));
505     message_loop_.Run();
506     audio->Read(NewReadCBWithCheckedDiscard(
507         FROM_HERE, 173, 5805, base::TimeDelta::FromMicroseconds(10159)));
508     message_loop_.Run();
509
510     audio->Read(NewReadCB(FROM_HERE, 148, 18866));
511     message_loop_.Run();
512     EXPECT_EQ(base::TimeDelta::FromMicroseconds(-15964),
513               demuxer_->start_time());
514
515     video->Read(NewReadCB(FROM_HERE, 5751, 0));
516     message_loop_.Run();
517
518     video->Read(NewReadCB(FROM_HERE, 846, 33367));
519     message_loop_.Run();
520
521     video->Read(NewReadCB(FROM_HERE, 1255, 66733));
522     message_loop_.Run();
523
524     // Seek back to the beginning and repeat the test.
525     WaitableMessageLoopEvent event;
526     demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
527     event.RunAndWaitForStatus(PIPELINE_OK);
528   }
529 }
530
531 // Same test above, but using sync2.ogv which has video stream muxed before the
532 // audio stream, so seeking based only on start time will fail since ffmpeg is
533 // essentially just seeking based on file position.
534 TEST_F(FFmpegDemuxerTest, Read_AudioNegativeStartTimeAndOggDiscard_Sync) {
535   // Many ogg files have negative starting timestamps, so ensure demuxing and
536   // seeking work correctly with a negative start time.
537   CreateDemuxer("sync2.ogv");
538   InitializeDemuxer();
539
540   // Attempt a read from the video stream and run the message loop until done.
541   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
542   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
543
544   // Run the test twice with a seek in between.
545   for (int i = 0; i < 2; ++i) {
546     audio->Read(NewReadCBWithCheckedDiscard(
547         FROM_HERE, 1, 0, base::TimeDelta::FromMicroseconds(2902)));
548     message_loop_.Run();
549
550     audio->Read(NewReadCB(FROM_HERE, 1, 2902));
551     message_loop_.Run();
552     EXPECT_EQ(base::TimeDelta::FromMicroseconds(-2902),
553               demuxer_->start_time());
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   WaitableMessageLoopEvent event;
749   demuxer_->Stop(event.GetClosure());
750   event.RunAndWait();
751
752   // Reads after being stopped are all EOS buffers.
753   StrictMock<MockReadCB> callback;
754   EXPECT_CALL(callback, Run(DemuxerStream::kOk, IsEndOfStreamBuffer()));
755
756   // Attempt the read...
757   audio->Read(base::Bind(&MockReadCB::Run, base::Unretained(&callback)));
758   message_loop_.RunUntilIdle();
759
760   // Don't let the test call Stop() again.
761   demuxer_.reset();
762 }
763
764 // Verify that seek works properly when the WebM cues data is at the start of
765 // the file instead of at the end.
766 TEST_F(FFmpegDemuxerTest, SeekWithCuesBeforeFirstCluster) {
767   CreateDemuxer("bear-320x240-cues-in-front.webm");
768   InitializeDemuxer();
769
770   // Get our streams.
771   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
772   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
773   ASSERT_TRUE(video);
774   ASSERT_TRUE(audio);
775
776   // Read a video packet and release it.
777   video->Read(NewReadCB(FROM_HERE, 22084, 0));
778   message_loop_.Run();
779
780   // Issue a simple forward seek, which should discard queued packets.
781   WaitableMessageLoopEvent event;
782   demuxer_->Seek(base::TimeDelta::FromMicroseconds(2500000),
783                  event.GetPipelineStatusCB());
784   event.RunAndWaitForStatus(PIPELINE_OK);
785
786   // Audio read #1.
787   audio->Read(NewReadCB(FROM_HERE, 40, 2403000));
788   message_loop_.Run();
789
790   // Audio read #2.
791   audio->Read(NewReadCB(FROM_HERE, 42, 2406000));
792   message_loop_.Run();
793
794   // Video read #1.
795   video->Read(NewReadCB(FROM_HERE, 5276, 2402000));
796   message_loop_.Run();
797
798   // Video read #2.
799   video->Read(NewReadCB(FROM_HERE, 1740, 2436000));
800   message_loop_.Run();
801 }
802
803 #if defined(USE_PROPRIETARY_CODECS)
804 // Ensure ID3v1 tag reading is disabled.  id3_test.mp3 has an ID3v1 tag with the
805 // field "title" set to "sample for id3 test".
806 TEST_F(FFmpegDemuxerTest, NoID3TagData) {
807   CreateDemuxer("id3_test.mp3");
808   InitializeDemuxer();
809   EXPECT_FALSE(av_dict_get(format_context()->metadata, "title", NULL, 0));
810 }
811 #endif
812
813 #if defined(USE_PROPRIETARY_CODECS)
814 // Ensure MP3 files with large image/video based ID3 tags demux okay.  FFmpeg
815 // will hand us a video stream to the data which will likely be in a format we
816 // don't accept as video; e.g. PNG.
817 TEST_F(FFmpegDemuxerTest, Mp3WithVideoStreamID3TagData) {
818   CreateDemuxer("id3_png_test.mp3");
819   InitializeDemuxer();
820
821   // Ensure the expected streams are present.
822   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO));
823   EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO));
824 }
825 #endif
826
827 // Ensure a video with an unsupported audio track still results in the video
828 // stream being demuxed.
829 TEST_F(FFmpegDemuxerTest, UnsupportedAudioSupportedVideoDemux) {
830   CreateDemuxer("speex_audio_vorbis_video.ogv");
831   InitializeDemuxer();
832
833   // Ensure the expected streams are present.
834   EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::VIDEO));
835   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::AUDIO));
836 }
837
838 // Ensure a video with an unsupported video track still results in the audio
839 // stream being demuxed.
840 TEST_F(FFmpegDemuxerTest, UnsupportedVideoSupportedAudioDemux) {
841   CreateDemuxer("vorbis_audio_wmv_video.mkv");
842   InitializeDemuxer();
843
844   // Ensure the expected streams are present.
845   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO));
846   EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO));
847 }
848
849 #if defined(USE_PROPRIETARY_CODECS)
850 // FFmpeg returns null data pointers when samples have zero size, leading to
851 // mistakenly creating end of stream buffers http://crbug.com/169133
852 TEST_F(FFmpegDemuxerTest, MP4_ZeroStszEntry) {
853   CreateDemuxer("bear-1280x720-zero-stsz-entry.mp4");
854   InitializeDemuxer();
855   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
856 }
857
858
859 static void ValidateAnnexB(DemuxerStream* stream,
860                            DemuxerStream::Status status,
861                            const scoped_refptr<DecoderBuffer>& buffer) {
862   EXPECT_EQ(status, DemuxerStream::kOk);
863
864   if (buffer->end_of_stream()) {
865     base::MessageLoop::current()->PostTask(
866         FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
867     return;
868   }
869
870   std::vector<SubsampleEntry> subsamples;
871
872   if (buffer->decrypt_config())
873     subsamples = buffer->decrypt_config()->subsamples();
874
875   bool is_valid =
876       mp4::AVC::IsValidAnnexB(buffer->data(), buffer->data_size(),
877                               subsamples);
878   EXPECT_TRUE(is_valid);
879
880   if (!is_valid) {
881     LOG(ERROR) << "Buffer contains invalid Annex B data.";
882     base::MessageLoop::current()->PostTask(
883         FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
884     return;
885   }
886
887   stream->Read(base::Bind(&ValidateAnnexB, stream));
888 };
889
890 TEST_F(FFmpegDemuxerTest, IsValidAnnexB) {
891   const char* files[] = {
892     "bear-1280x720-av_frag.mp4",
893     "bear-1280x720-av_with-aud-nalus_frag.mp4"
894   };
895
896   for (size_t i = 0; i < arraysize(files); ++i) {
897     DVLOG(1) << "Testing " << files[i];
898     CreateDemuxer(files[i]);
899     InitializeDemuxer();
900
901     // Ensure the expected streams are present.
902     DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
903     ASSERT_TRUE(stream);
904     stream->EnableBitstreamConverter();
905
906     stream->Read(base::Bind(&ValidateAnnexB, stream));
907     message_loop_.Run();
908
909     WaitableMessageLoopEvent event;
910     demuxer_->Stop(event.GetClosure());
911     event.RunAndWait();
912     demuxer_.reset();
913     data_source_.reset();
914   }
915 }
916
917 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_0) {
918   CreateDemuxer("bear_rotate_0.mp4");
919   InitializeDemuxer();
920
921   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
922   ASSERT_TRUE(stream);
923   ASSERT_EQ(VIDEO_ROTATION_0, stream->video_rotation());
924 }
925
926 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_90) {
927   CreateDemuxer("bear_rotate_90.mp4");
928   InitializeDemuxer();
929
930   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
931   ASSERT_TRUE(stream);
932   ASSERT_EQ(VIDEO_ROTATION_90, stream->video_rotation());
933 }
934
935 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_180) {
936   CreateDemuxer("bear_rotate_180.mp4");
937   InitializeDemuxer();
938
939   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
940   ASSERT_TRUE(stream);
941   ASSERT_EQ(VIDEO_ROTATION_180, stream->video_rotation());
942 }
943
944 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_270) {
945   CreateDemuxer("bear_rotate_270.mp4");
946   InitializeDemuxer();
947
948   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
949   ASSERT_TRUE(stream);
950   ASSERT_EQ(VIDEO_ROTATION_270, stream->video_rotation());
951 }
952
953 #endif
954
955 }  // namespace media