Home | History | Annotate | Download | only in filters
      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
    952