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       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 InitializeDemuxerText(bool enable_text) {
     96     EXPECT_CALL(host_, SetDuration(_));
     97     WaitableMessageLoopEvent event;
     98     demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), enable_text);
     99     event.RunAndWaitForStatus(PIPELINE_OK);
    100   }
    101 
    102   void InitializeDemuxer() {
    103     InitializeDemuxerText(false);
    104   }
    105 
    106   MOCK_METHOD2(OnReadDoneCalled, void(int, int64));
    107 
    108   // Verifies that |buffer| has a specific |size| and |timestamp|.
    109   // |location| simply indicates where the call to this function was made.
    110   // This makes it easier to track down where test failures occur.
    111   void OnReadDone(const tracked_objects::Location& location,
    112                   int size, int64 timestampInMicroseconds,
    113                   DemuxerStream::Status status,
    114                   const scoped_refptr<DecoderBuffer>& buffer) {
    115     std::string location_str;
    116     location.Write(true, false, &location_str);
    117     location_str += "\n";
    118     SCOPED_TRACE(location_str);
    119     EXPECT_EQ(status, DemuxerStream::kOk);
    120     OnReadDoneCalled(size, timestampInMicroseconds);
    121     EXPECT_TRUE(buffer.get() != NULL);
    122     EXPECT_EQ(size, buffer->data_size());
    123     EXPECT_EQ(base::TimeDelta::FromMicroseconds(timestampInMicroseconds),
    124               buffer->timestamp());
    125 
    126     DCHECK_EQ(&message_loop_, base::MessageLoop::current());
    127     message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
    128   }
    129 
    130   DemuxerStream::ReadCB NewReadCB(const tracked_objects::Location& location,
    131                                   int size, int64 timestampInMicroseconds) {
    132     EXPECT_CALL(*this, OnReadDoneCalled(size, timestampInMicroseconds));
    133     return base::Bind(&FFmpegDemuxerTest::OnReadDone, base::Unretained(this),
    134                       location, size, timestampInMicroseconds);
    135   }
    136 
    137   // TODO(xhwang): This is a workaround of the issue that move-only parameters
    138   // are not supported in mocked methods. Remove this when the issue is fixed
    139   // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use
    140   // std::string instead of scoped_ptr<uint8[]> (http://crbug.com/130689).
    141   MOCK_METHOD3(NeedKeyCBMock, void(const std::string& type,
    142                                    const uint8* init_data, int init_data_size));
    143   void NeedKeyCB(const std::string& type,
    144                  const std::vector<uint8>& init_data) {
    145     const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0];
    146     NeedKeyCBMock(type, init_data_ptr, init_data.size());
    147   }
    148 
    149   // Accessor to demuxer internals.
    150   void set_duration_known(bool duration_known) {
    151     demuxer_->duration_known_ = duration_known;
    152   }
    153 
    154   bool IsStreamStopped(DemuxerStream::Type type) {
    155     DemuxerStream* stream = demuxer_->GetStream(type);
    156     CHECK(stream);
    157     return !static_cast<FFmpegDemuxerStream*>(stream)->demuxer_;
    158   }
    159 
    160   // Fixture members.
    161   scoped_ptr<FileDataSource> data_source_;
    162   scoped_ptr<FFmpegDemuxer> demuxer_;
    163   StrictMock<MockDemuxerHost> host_;
    164   base::MessageLoop message_loop_;
    165 
    166   AVFormatContext* format_context() {
    167     return demuxer_->glue_->format_context();
    168   }
    169 
    170   void ReadUntilEndOfStream(DemuxerStream* stream) {
    171     bool got_eos_buffer = false;
    172     const int kMaxBuffers = 170;
    173     for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) {
    174       stream->Read(base::Bind(&EosOnReadDone, &got_eos_buffer));
    175       message_loop_.Run();
    176     }
    177 
    178     EXPECT_TRUE(got_eos_buffer);
    179   }
    180 
    181  private:
    182   void CreateDataSource(const std::string& name) {
    183     CHECK(!data_source_);
    184 
    185     base::FilePath file_path;
    186     EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
    187 
    188     file_path = file_path.Append(FILE_PATH_LITERAL("media"))
    189         .Append(FILE_PATH_LITERAL("test"))
    190         .Append(FILE_PATH_LITERAL("data"))
    191         .AppendASCII(name);
    192 
    193     data_source_.reset(new FileDataSource());
    194     EXPECT_TRUE(data_source_->Initialize(file_path));
    195   }
    196 
    197   DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest);
    198 };
    199 
    200 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) {
    201   // Simulate avformat_open_input() failing.
    202   CreateDemuxer("ten_byte_file");
    203   WaitableMessageLoopEvent event;
    204   demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
    205   event.RunAndWaitForStatus(DEMUXER_ERROR_COULD_NOT_OPEN);
    206 }
    207 
    208 // TODO(acolwell): Uncomment this test when we discover a file that passes
    209 // avformat_open_input(), but has avformat_find_stream_info() fail.
    210 //
    211 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) {
    212 //  ("find_stream_info_fail.webm");
    213 //  demuxer_->Initialize(
    214 //      &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE));
    215 //  message_loop_.RunUntilIdle();
    216 //}
    217 
    218 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) {
    219   // Open a file with no streams whatsoever.
    220   CreateDemuxer("no_streams.webm");
    221   WaitableMessageLoopEvent event;
    222   demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
    223   event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
    224 }
    225 
    226 TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) {
    227   // Open a file containing streams but none of which are audio/video streams.
    228   CreateDemuxer("no_audio_video.webm");
    229   WaitableMessageLoopEvent event;
    230   demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
    231   event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
    232 }
    233 
    234 TEST_F(FFmpegDemuxerTest, Initialize_Successful) {
    235   CreateDemuxer("bear-320x240.webm");
    236   InitializeDemuxer();
    237 
    238   // Video stream should be present.
    239   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
    240   ASSERT_TRUE(stream);
    241   EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
    242 
    243   const VideoDecoderConfig& video_config = stream->video_decoder_config();
    244   EXPECT_EQ(kCodecVP8, video_config.codec());
    245   EXPECT_EQ(VideoFrame::YV12, video_config.format());
    246   EXPECT_EQ(320, video_config.coded_size().width());
    247   EXPECT_EQ(240, video_config.coded_size().height());
    248   EXPECT_EQ(0, video_config.visible_rect().x());
    249   EXPECT_EQ(0, video_config.visible_rect().y());
    250   EXPECT_EQ(320, video_config.visible_rect().width());
    251   EXPECT_EQ(240, video_config.visible_rect().height());
    252   EXPECT_EQ(320, video_config.natural_size().width());
    253   EXPECT_EQ(240, video_config.natural_size().height());
    254   EXPECT_FALSE(video_config.extra_data());
    255   EXPECT_EQ(0u, video_config.extra_data_size());
    256 
    257   // Audio stream should be present.
    258   stream = demuxer_->GetStream(DemuxerStream::AUDIO);
    259   ASSERT_TRUE(stream);
    260   EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
    261 
    262   const AudioDecoderConfig& audio_config = stream->audio_decoder_config();
    263   EXPECT_EQ(kCodecVorbis, audio_config.codec());
    264   EXPECT_EQ(32, audio_config.bits_per_channel());
    265   EXPECT_EQ(CHANNEL_LAYOUT_STEREO, audio_config.channel_layout());
    266   EXPECT_EQ(44100, audio_config.samples_per_second());
    267   EXPECT_EQ(kSampleFormatPlanarF32, audio_config.sample_format());
    268   EXPECT_TRUE(audio_config.extra_data());
    269   EXPECT_GT(audio_config.extra_data_size(), 0u);
    270 
    271   // Unknown stream should never be present.
    272   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
    273 }
    274 
    275 TEST_F(FFmpegDemuxerTest, Initialize_Multitrack) {
    276   // Open a file containing the following streams:
    277   //   Stream #0: Video (VP8)
    278   //   Stream #1: Audio (Vorbis)
    279   //   Stream #2: Subtitles (SRT)
    280   //   Stream #3: Video (Theora)
    281   //   Stream #4: Audio (16-bit signed little endian PCM)
    282   //
    283   // We should only pick the first audio/video streams we come across.
    284   CreateDemuxer("bear-320x240-multitrack.webm");
    285   InitializeDemuxer();
    286 
    287   // Video stream should be VP8.
    288   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
    289   ASSERT_TRUE(stream);
    290   EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
    291   EXPECT_EQ(kCodecVP8, stream->video_decoder_config().codec());
    292 
    293   // Audio stream should be Vorbis.
    294   stream = demuxer_->GetStream(DemuxerStream::AUDIO);
    295   ASSERT_TRUE(stream);
    296   EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
    297   EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec());
    298 
    299   // Unknown stream should never be present.
    300   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
    301 }
    302 
    303 TEST_F(FFmpegDemuxerTest, Initialize_MultitrackText) {
    304   // Open a file containing the following streams:
    305   //   Stream #0: Video (VP8)
    306   //   Stream #1: Audio (Vorbis)
    307   //   Stream #2: Text (WebVTT)
    308 
    309   CreateDemuxer("bear-vp8-webvtt.webm");
    310   DemuxerStream* text_stream = NULL;
    311   EXPECT_CALL(host_, AddTextStream(_, _))
    312       .WillOnce(SaveArg<0>(&text_stream));
    313   InitializeDemuxerText(true);
    314   ASSERT_TRUE(text_stream);
    315   EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
    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_Encrypted) {
    334   EXPECT_CALL(*this, NeedKeyCBMock(kWebMEncryptInitDataType, NotNull(),
    335                                    DecryptConfig::kDecryptionKeySize))
    336       .Times(Exactly(2));
    337 
    338   CreateDemuxer("bear-320x240-av_enc-av.webm");
    339   InitializeDemuxer();
    340 }
    341 
    342 TEST_F(FFmpegDemuxerTest, Read_Audio) {
    343   // We test that on a successful audio packet read.
    344   CreateDemuxer("bear-320x240.webm");
    345   InitializeDemuxer();
    346 
    347   // Attempt a read from the audio stream and run the message loop until done.
    348   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
    349 
    350   audio->Read(NewReadCB(FROM_HERE, 29, 0));
    351   message_loop_.Run();
    352 
    353   audio->Read(NewReadCB(FROM_HERE, 27, 3000));
    354   message_loop_.Run();
    355 }
    356 
    357 TEST_F(FFmpegDemuxerTest, Read_Video) {
    358   // We test that on a successful video packet read.
    359   CreateDemuxer("bear-320x240.webm");
    360   InitializeDemuxer();
    361 
    362   // Attempt a read from the video stream and run the message loop until done.
    363   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
    364 
    365   video->Read(NewReadCB(FROM_HERE, 22084, 0));
    366   message_loop_.Run();
    367 
    368   video->Read(NewReadCB(FROM_HERE, 1057, 33000));
    369   message_loop_.Run();
    370 }
    371 
    372 TEST_F(FFmpegDemuxerTest, Read_Text) {
    373   // We test that on a successful text packet read.
    374   CreateDemuxer("bear-vp8-webvtt.webm");
    375   DemuxerStream* text_stream = NULL;
    376   EXPECT_CALL(host_, AddTextStream(_, _))
    377       .WillOnce(SaveArg<0>(&text_stream));
    378   InitializeDemuxerText(true);
    379   ASSERT_TRUE(text_stream);
    380   EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
    381 
    382   text_stream->Read(NewReadCB(FROM_HERE, 31, 0));
    383   message_loop_.Run();
    384 
    385   text_stream->Read(NewReadCB(FROM_HERE, 19, 500000));
    386   message_loop_.Run();
    387 }
    388 
    389 TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) {
    390   // Test the start time is the first timestamp of the video and audio stream.
    391   CreateDemuxer("nonzero-start-time.webm");
    392   InitializeDemuxer();
    393 
    394   // Attempt a read from the video stream and run the message loop until done.
    395   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
    396   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
    397 
    398   // Check first buffer in video stream.
    399   video->Read(NewReadCB(FROM_HERE, 5636, 400000));
    400   message_loop_.Run();
    401 
    402   // Check first buffer in audio stream.
    403   audio->Read(NewReadCB(FROM_HERE, 165, 396000));
    404   message_loop_.Run();
    405 
    406   // Verify that the start time is equal to the lowest timestamp (ie the audio).
    407   EXPECT_EQ(demuxer_->GetStartTime().InMicroseconds(), 396000);
    408 }
    409 
    410 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) {
    411   // Verify that end of stream buffers are created.
    412   CreateDemuxer("bear-320x240.webm");
    413   InitializeDemuxer();
    414   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
    415 }
    416 
    417 TEST_F(FFmpegDemuxerTest, Read_EndOfStreamText) {
    418   // Verify that end of stream buffers are created.
    419   CreateDemuxer("bear-vp8-webvtt.webm");
    420   DemuxerStream* text_stream = NULL;
    421   EXPECT_CALL(host_, AddTextStream(_, _))
    422       .WillOnce(SaveArg<0>(&text_stream));
    423   InitializeDemuxerText(true);
    424   ASSERT_TRUE(text_stream);
    425   EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
    426 
    427   bool got_eos_buffer = false;
    428   const int kMaxBuffers = 10;
    429   for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) {
    430     text_stream->Read(base::Bind(&EosOnReadDone, &got_eos_buffer));
    431     message_loop_.Run();
    432   }
    433 
    434   EXPECT_TRUE(got_eos_buffer);
    435 }
    436 
    437 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration) {
    438   // Verify that end of stream buffers are created.
    439   CreateDemuxer("bear-320x240.webm");
    440   InitializeDemuxer();
    441   set_duration_known(false);
    442   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2767)));
    443   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
    444   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::VIDEO));
    445 }
    446 
    447 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration_VideoOnly) {
    448   // Verify that end of stream buffers are created.
    449   CreateDemuxer("bear-320x240-video-only.webm");
    450   InitializeDemuxer();
    451   set_duration_known(false);
    452   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2703)));
    453   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::VIDEO));
    454 }
    455 
    456 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration_AudioOnly) {
    457   // Verify that end of stream buffers are created.
    458   CreateDemuxer("bear-320x240-audio-only.webm");
    459   InitializeDemuxer();
    460   set_duration_known(false);
    461   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2767)));
    462   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
    463 }
    464 
    465 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration_UnsupportedStream) {
    466   // Verify that end of stream buffers are created and we don't crash
    467   // if there are streams in the file that we don't support.
    468   CreateDemuxer("vorbis_audio_wmv_video.mkv");
    469   InitializeDemuxer();
    470   set_duration_known(false);
    471   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(1014)));
    472   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
    473 }
    474 
    475 TEST_F(FFmpegDemuxerTest, Seek) {
    476   // We're testing that the demuxer frees all queued packets when it receives
    477   // a Seek().
    478   CreateDemuxer("bear-320x240.webm");
    479   InitializeDemuxer();
    480 
    481   // Get our streams.
    482   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
    483   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
    484   ASSERT_TRUE(video);
    485   ASSERT_TRUE(audio);
    486 
    487   // Read a video packet and release it.
    488   video->Read(NewReadCB(FROM_HERE, 22084, 0));
    489   message_loop_.Run();
    490 
    491   // Issue a simple forward seek, which should discard queued packets.
    492   WaitableMessageLoopEvent event;
    493   demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
    494                  event.GetPipelineStatusCB());
    495   event.RunAndWaitForStatus(PIPELINE_OK);
    496 
    497   // Audio read #1.
    498   audio->Read(NewReadCB(FROM_HERE, 145, 803000));
    499   message_loop_.Run();
    500 
    501   // Audio read #2.
    502   audio->Read(NewReadCB(FROM_HERE, 148, 826000));
    503   message_loop_.Run();
    504 
    505   // Video read #1.
    506   video->Read(NewReadCB(FROM_HERE, 5425, 801000));
    507   message_loop_.Run();
    508 
    509   // Video read #2.
    510   video->Read(NewReadCB(FROM_HERE, 1906, 834000));
    511   message_loop_.Run();
    512 }
    513 
    514 TEST_F(FFmpegDemuxerTest, SeekText) {
    515   // We're testing that the demuxer frees all queued packets when it receives
    516   // a Seek().
    517   CreateDemuxer("bear-vp8-webvtt.webm");
    518   DemuxerStream* text_stream = NULL;
    519   EXPECT_CALL(host_, AddTextStream(_, _))
    520       .WillOnce(SaveArg<0>(&text_stream));
    521   InitializeDemuxerText(true);
    522   ASSERT_TRUE(text_stream);
    523   EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
    524 
    525   // Get our streams.
    526   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
    527   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
    528   ASSERT_TRUE(video);
    529   ASSERT_TRUE(audio);
    530 
    531   // Read a text packet and release it.
    532   text_stream->Read(NewReadCB(FROM_HERE, 31, 0));
    533   message_loop_.Run();
    534 
    535   // Issue a simple forward seek, which should discard queued packets.
    536   WaitableMessageLoopEvent event;
    537   demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
    538                  event.GetPipelineStatusCB());
    539   event.RunAndWaitForStatus(PIPELINE_OK);
    540 
    541   // Audio read #1.
    542   audio->Read(NewReadCB(FROM_HERE, 145, 803000));
    543   message_loop_.Run();
    544 
    545   // Audio read #2.
    546   audio->Read(NewReadCB(FROM_HERE, 148, 826000));
    547   message_loop_.Run();
    548 
    549   // Video read #1.
    550   video->Read(NewReadCB(FROM_HERE, 5425, 801000));
    551   message_loop_.Run();
    552 
    553   // Video read #2.
    554   video->Read(NewReadCB(FROM_HERE, 1906, 834000));
    555   message_loop_.Run();
    556 
    557   // Text read #1.
    558   text_stream->Read(NewReadCB(FROM_HERE, 19, 500000));
    559   message_loop_.Run();
    560 
    561   // Text read #2.
    562   text_stream->Read(NewReadCB(FROM_HERE, 19, 1000000));
    563   message_loop_.Run();
    564 }
    565 
    566 class MockReadCB {
    567  public:
    568   MockReadCB() {}
    569   ~MockReadCB() {}
    570 
    571   MOCK_METHOD2(Run, void(DemuxerStream::Status status,
    572                          const scoped_refptr<DecoderBuffer>& buffer));
    573  private:
    574   DISALLOW_COPY_AND_ASSIGN(MockReadCB);
    575 };
    576 
    577 TEST_F(FFmpegDemuxerTest, Stop) {
    578   // Tests that calling Read() on a stopped demuxer stream immediately deletes
    579   // the callback.
    580   CreateDemuxer("bear-320x240.webm");
    581   InitializeDemuxer();
    582 
    583   // Get our stream.
    584   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
    585   ASSERT_TRUE(audio);
    586 
    587   WaitableMessageLoopEvent event;
    588   demuxer_->Stop(event.GetClosure());
    589   event.RunAndWait();
    590 
    591   // Reads after being stopped are all EOS buffers.
    592   StrictMock<MockReadCB> callback;
    593   EXPECT_CALL(callback, Run(DemuxerStream::kOk, IsEndOfStreamBuffer()));
    594 
    595   // Attempt the read...
    596   audio->Read(base::Bind(&MockReadCB::Run, base::Unretained(&callback)));
    597   message_loop_.RunUntilIdle();
    598 
    599   // Don't let the test call Stop() again.
    600   demuxer_.reset();
    601 }
    602 
    603 // Verify that seek works properly when the WebM cues data is at the start of
    604 // the file instead of at the end.
    605 TEST_F(FFmpegDemuxerTest, SeekWithCuesBeforeFirstCluster) {
    606   CreateDemuxer("bear-320x240-cues-in-front.webm");
    607   InitializeDemuxer();
    608 
    609   // Get our streams.
    610   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
    611   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
    612   ASSERT_TRUE(video);
    613   ASSERT_TRUE(audio);
    614 
    615   // Read a video packet and release it.
    616   video->Read(NewReadCB(FROM_HERE, 22084, 0));
    617   message_loop_.Run();
    618 
    619   // Issue a simple forward seek, which should discard queued packets.
    620   WaitableMessageLoopEvent event;
    621   demuxer_->Seek(base::TimeDelta::FromMicroseconds(2500000),
    622                  event.GetPipelineStatusCB());
    623   event.RunAndWaitForStatus(PIPELINE_OK);
    624 
    625   // Audio read #1.
    626   audio->Read(NewReadCB(FROM_HERE, 40, 2403000));
    627   message_loop_.Run();
    628 
    629   // Audio read #2.
    630   audio->Read(NewReadCB(FROM_HERE, 42, 2406000));
    631   message_loop_.Run();
    632 
    633   // Video read #1.
    634   video->Read(NewReadCB(FROM_HERE, 5276, 2402000));
    635   message_loop_.Run();
    636 
    637   // Video read #2.
    638   video->Read(NewReadCB(FROM_HERE, 1740, 2436000));
    639   message_loop_.Run();
    640 }
    641 
    642 #if defined(USE_PROPRIETARY_CODECS)
    643 // Ensure ID3v1 tag reading is disabled.  id3_test.mp3 has an ID3v1 tag with the
    644 // field "title" set to "sample for id3 test".
    645 TEST_F(FFmpegDemuxerTest, NoID3TagData) {
    646   CreateDemuxer("id3_test.mp3");
    647   InitializeDemuxer();
    648   EXPECT_FALSE(av_dict_get(format_context()->metadata, "title", NULL, 0));
    649 }
    650 #endif
    651 
    652 #if defined(USE_PROPRIETARY_CODECS)
    653 // Ensure MP3 files with large image/video based ID3 tags demux okay.  FFmpeg
    654 // will hand us a video stream to the data which will likely be in a format we
    655 // don't accept as video; e.g. PNG.
    656 TEST_F(FFmpegDemuxerTest, Mp3WithVideoStreamID3TagData) {
    657   CreateDemuxer("id3_png_test.mp3");
    658   InitializeDemuxer();
    659 
    660   // Ensure the expected streams are present.
    661   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO));
    662   EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO));
    663 }
    664 #endif
    665 
    666 // Ensure a video with an unsupported audio track still results in the video
    667 // stream being demuxed.
    668 TEST_F(FFmpegDemuxerTest, UnsupportedAudioSupportedVideoDemux) {
    669   CreateDemuxer("speex_audio_vorbis_video.ogv");
    670   InitializeDemuxer();
    671 
    672   // Ensure the expected streams are present.
    673   EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::VIDEO));
    674   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::AUDIO));
    675 }
    676 
    677 // Ensure a video with an unsupported video track still results in the audio
    678 // stream being demuxed.
    679 TEST_F(FFmpegDemuxerTest, UnsupportedVideoSupportedAudioDemux) {
    680   CreateDemuxer("vorbis_audio_wmv_video.mkv");
    681   InitializeDemuxer();
    682 
    683   // Ensure the expected streams are present.
    684   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO));
    685   EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO));
    686 }
    687 
    688 #if defined(USE_PROPRIETARY_CODECS)
    689 // FFmpeg returns null data pointers when samples have zero size, leading to
    690 // mistakenly creating end of stream buffers http://crbug.com/169133
    691 TEST_F(FFmpegDemuxerTest, MP4_ZeroStszEntry) {
    692   CreateDemuxer("bear-1280x720-zero-stsz-entry.mp4");
    693   InitializeDemuxer();
    694   ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
    695 }
    696 
    697 
    698 static void ValidateAnnexB(DemuxerStream* stream,
    699                            DemuxerStream::Status status,
    700                            const scoped_refptr<DecoderBuffer>& buffer) {
    701   EXPECT_EQ(status, DemuxerStream::kOk);
    702 
    703   if (buffer->end_of_stream()) {
    704     base::MessageLoop::current()->PostTask(
    705         FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
    706     return;
    707   }
    708 
    709   bool is_valid =
    710       mp4::AVC::IsValidAnnexB(buffer->data(), buffer->data_size());
    711   EXPECT_TRUE(is_valid);
    712 
    713   if (!is_valid) {
    714     LOG(ERROR) << "Buffer contains invalid Annex B data.";
    715     base::MessageLoop::current()->PostTask(
    716         FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
    717     return;
    718   }
    719 
    720   stream->Read(base::Bind(&ValidateAnnexB, stream));
    721 };
    722 
    723 TEST_F(FFmpegDemuxerTest, IsValidAnnexB) {
    724   const char* files[] = {
    725     "bear-1280x720-av_frag.mp4",
    726     "bear-1280x720-av_with-aud-nalus_frag.mp4"
    727   };
    728 
    729   for (size_t i = 0; i < arraysize(files); ++i) {
    730     DVLOG(1) << "Testing " << files[i];
    731     CreateDemuxer(files[i]);
    732     InitializeDemuxer();
    733 
    734     // Ensure the expected streams are present.
    735     DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
    736     ASSERT_TRUE(stream);
    737     stream->EnableBitstreamConverter();
    738 
    739     stream->Read(base::Bind(&ValidateAnnexB, stream));
    740     message_loop_.Run();
    741 
    742     WaitableMessageLoopEvent event;
    743     demuxer_->Stop(event.GetClosure());
    744     event.RunAndWait();
    745     demuxer_.reset();
    746     data_source_.reset();
    747   }
    748 }
    749 
    750 #endif
    751 
    752 }  // namespace media
    753