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/path_service.h"
     12 #include "base/threading/thread.h"
     13 #include "media/base/decrypt_config.h"
     14 #include "media/base/media_log.h"
     15 #include "media/base/mock_demuxer_host.h"
     16 #include "media/base/test_helpers.h"
     17 #include "media/ffmpeg/ffmpeg_common.h"
     18 #include "media/filters/ffmpeg_demuxer.h"
     19 #include "media/filters/file_data_source.h"
     20 #include "media/webm/webm_crypto_helpers.h"
     21 #include "testing/gtest/include/gtest/gtest.h"
     22 
     23 using ::testing::AnyNumber;
     24 using ::testing::DoAll;
     25 using ::testing::Exactly;
     26 using ::testing::InSequence;
     27 using ::testing::Invoke;
     28 using ::testing::NotNull;
     29 using ::testing::Return;
     30 using ::testing::SaveArg;
     31 using ::testing::SetArgPointee;
     32 using ::testing::StrictMock;
     33 using ::testing::WithArgs;
     34 using ::testing::_;
     35 
     36 namespace media {
     37 
     38 MATCHER(IsEndOfStreamBuffer,
     39         std::string(negation ? "isn't" : "is") + " end of stream") {
     40   return arg->end_of_stream();
     41 }
     42 
     43 static void EosOnReadDone(bool* got_eos_buffer,
     44                           DemuxerStream::Status status,
     45                           const scoped_refptr<DecoderBuffer>& buffer) {
     46   base::MessageLoop::current()->PostTask(
     47       FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
     48 
     49   EXPECT_EQ(status, DemuxerStream::kOk);
     50   if (buffer->end_of_stream()) {
     51     *got_eos_buffer = true;
     52     return;
     53   }
     54 
     55   EXPECT_TRUE(buffer->data());
     56   EXPECT_GT(buffer->data_size(), 0);
     57   *got_eos_buffer = false;
     58 };
     59 
     60 
     61 // Fixture class to facilitate writing tests.  Takes care of setting up the
     62 // FFmpeg, pipeline and filter host mocks.
     63 class FFmpegDemuxerTest : public testing::Test {
     64  protected:
     65   FFmpegDemuxerTest() {}
     66 
     67   virtual ~FFmpegDemuxerTest() {
     68     if (demuxer_) {
     69       WaitableMessageLoopEvent event;
     70       demuxer_->Stop(event.GetClosure());
     71       event.RunAndWait();
     72     }
     73   }
     74 
     75   void CreateDemuxer(const std::string& name) {
     76     CHECK(!demuxer_);
     77 
     78     EXPECT_CALL(host_, SetTotalBytes(_)).Times(AnyNumber());
     79     EXPECT_CALL(host_, AddBufferedByteRange(_, _)).Times(AnyNumber());
     80     EXPECT_CALL(host_, AddBufferedTimeRange(_, _)).Times(AnyNumber());
     81 
     82     CreateDataSource(name);
     83 
     84     media::FFmpegNeedKeyCB need_key_cb =
     85         base::Bind(&FFmpegDemuxerTest::NeedKeyCB, base::Unretained(this));
     86     demuxer_.reset(new FFmpegDemuxer(message_loop_.message_loop_proxy(),
     87                                      data_source_.get(),
     88                                      need_key_cb,
     89                                      new MediaLog()));
     90   }
     91 
     92   MOCK_METHOD1(CheckPoint, void(int v));
     93 
     94   void InitializeDemuxer() {
     95     EXPECT_CALL(host_, SetDuration(_));
     96     WaitableMessageLoopEvent event;
     97     demuxer_->Initialize(&host_, event.GetPipelineStatusCB());
     98     event.RunAndWaitForStatus(PIPELINE_OK);
     99   }
    100 
    101   MOCK_METHOD2(OnReadDoneCalled, void(int, int64));
    102 
    103   // Verifies that |buffer| has a specific |size| and |timestamp|.
    104   // |location| simply indicates where the call to this function was made.
    105   // This makes it easier to track down where test failures occur.
    106   void OnReadDone(const tracked_objects::Location& location,
    107                   int size, int64 timestampInMicroseconds,
    108                   DemuxerStream::Status status,
    109                   const scoped_refptr<DecoderBuffer>& buffer) {
    110     std::string location_str;
    111     location.Write(true, false, &location_str);
    112     location_str += "\n";
    113     SCOPED_TRACE(location_str);
    114     EXPECT_EQ(status, DemuxerStream::kOk);
    115     OnReadDoneCalled(size, timestampInMicroseconds);
    116     EXPECT_TRUE(buffer.get() != NULL);
    117     EXPECT_EQ(size, buffer->data_size());
    118     EXPECT_EQ(base::TimeDelta::FromMicroseconds(timestampInMicroseconds),
    119               buffer->timestamp());
    120 
    121     DCHECK_EQ(&message_loop_, base::MessageLoop::current());
    122     message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
    123   }
    124 
    125   DemuxerStream::ReadCB NewReadCB(const tracked_objects::Location& location,
    126                                   int size, int64 timestampInMicroseconds) {
    127     EXPECT_CALL(*this, OnReadDoneCalled(size, timestampInMicroseconds));
    128     return base::Bind(&FFmpegDemuxerTest::OnReadDone, base::Unretained(this),
    129                       location, size, timestampInMicroseconds);
    130   }
    131 
    132   // TODO(xhwang): This is a workaround of the issue that move-only parameters
    133   // are not supported in mocked methods. Remove this when the issue is fixed
    134   // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use
    135   // std::string instead of scoped_ptr<uint8[]> (http://crbug.com/130689).
    136   MOCK_METHOD3(NeedKeyCBMock, void(const std::string& type,
    137                                    const uint8* init_data, int init_data_size));
    138   void NeedKeyCB(const std::string& type,
    139                  scoped_ptr<uint8[]> init_data, int init_data_size) {
    140     NeedKeyCBMock(type, init_data.get(), init_data_size);
    141   }
    142 
    143   // Accessor to demuxer internals.
    144   void set_duration_known(bool duration_known) {
    145     demuxer_->duration_known_ = duration_known;
    146   }
    147 
    148   bool IsStreamStopped(DemuxerStream::Type type) {
    149     DemuxerStream* stream = demuxer_->GetStream(type);
    150     CHECK(stream);
    151     return !static_cast<FFmpegDemuxerStream*>(stream)->demuxer_;
    152   }
    153 
    154   // Fixture members.
    155   scoped_ptr<FileDataSource> data_source_;
    156   scoped_ptr<FFmpegDemuxer> demuxer_;
    157   StrictMock<MockDemuxerHost> host_;
    158   base::MessageLoop message_loop_;
    159 
    160   AVFormatContext* format_context() {
    161     return demuxer_->glue_->format_context();
    162   }
    163 
    164   void ReadUntilEndOfStream() {
    165     // We should expect an end of stream buffer.
    166     DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
    167 
    168     bool got_eos_buffer = false;
    169     const int kMaxBuffers = 170;
    170     for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) {
    171       audio->Read(base::Bind(&EosOnReadDone, &got_eos_buffer));
    172       message_loop_.Run();
    173     }
    174 
    175     EXPECT_TRUE(got_eos_buffer);
    176   }
    177 
    178  private:
    179   void CreateDataSource(const std::string& name) {
    180     CHECK(!data_source_);
    181 
    182     base::FilePath file_path;
    183     EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
    184 
    185     file_path = file_path.Append(FILE_PATH_LITERAL("media"))
    186         .Append(FILE_PATH_LITERAL("test"))
    187         .Append(FILE_PATH_LITERAL("data"))
    188         .AppendASCII(name);
    189 
    190     data_source_.reset(new FileDataSource());
    191     EXPECT_TRUE(data_source_->Initialize(file_path));
    192   }
    193 
    194   DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest);
    195 };
    196 
    197 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) {
    198   // Simulate avformat_open_input() failing.
    199   CreateDemuxer("ten_byte_file");
    200   WaitableMessageLoopEvent event;
    201   demuxer_->Initialize(&host_, event.GetPipelineStatusCB());
    202   event.RunAndWaitForStatus(DEMUXER_ERROR_COULD_NOT_OPEN);
    203 }
    204 
    205 // TODO(acolwell): Uncomment this test when we discover a file that passes
    206 // avformat_open_input(), but has avformat_find_stream_info() fail.
    207 //
    208 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) {
    209 //  ("find_stream_info_fail.webm");
    210 //  demuxer_->Initialize(
    211 //      &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE));
    212 //  message_loop_.RunUntilIdle();
    213 //}
    214 
    215 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) {
    216   // Open a file with no streams whatsoever.
    217   CreateDemuxer("no_streams.webm");
    218   WaitableMessageLoopEvent event;
    219   demuxer_->Initialize(&host_, event.GetPipelineStatusCB());
    220   event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
    221 }
    222 
    223 TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) {
    224   // Open a file containing streams but none of which are audio/video streams.
    225   CreateDemuxer("no_audio_video.webm");
    226   WaitableMessageLoopEvent event;
    227   demuxer_->Initialize(&host_, event.GetPipelineStatusCB());
    228   event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
    229 }
    230 
    231 TEST_F(FFmpegDemuxerTest, Initialize_Successful) {
    232   CreateDemuxer("bear-320x240.webm");
    233   InitializeDemuxer();
    234 
    235   // Video stream should be present.
    236   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
    237   ASSERT_TRUE(stream);
    238   EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
    239 
    240   const VideoDecoderConfig& video_config = stream->video_decoder_config();
    241   EXPECT_EQ(kCodecVP8, video_config.codec());
    242   EXPECT_EQ(VideoFrame::YV12, video_config.format());
    243   EXPECT_EQ(320, video_config.coded_size().width());
    244   EXPECT_EQ(240, video_config.coded_size().height());
    245   EXPECT_EQ(0, video_config.visible_rect().x());
    246   EXPECT_EQ(0, video_config.visible_rect().y());
    247   EXPECT_EQ(320, video_config.visible_rect().width());
    248   EXPECT_EQ(240, video_config.visible_rect().height());
    249   EXPECT_EQ(320, video_config.natural_size().width());
    250   EXPECT_EQ(240, video_config.natural_size().height());
    251   EXPECT_FALSE(video_config.extra_data());
    252   EXPECT_EQ(0u, video_config.extra_data_size());
    253 
    254   // Audio stream should be present.
    255   stream = demuxer_->GetStream(DemuxerStream::AUDIO);
    256   ASSERT_TRUE(stream);
    257   EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
    258 
    259   const AudioDecoderConfig& audio_config = stream->audio_decoder_config();
    260   EXPECT_EQ(kCodecVorbis, audio_config.codec());
    261   EXPECT_EQ(32, audio_config.bits_per_channel());
    262   EXPECT_EQ(CHANNEL_LAYOUT_STEREO, audio_config.channel_layout());
    263   EXPECT_EQ(44100, audio_config.samples_per_second());
    264   EXPECT_EQ(kSampleFormatPlanarF32, audio_config.sample_format());
    265   EXPECT_TRUE(audio_config.extra_data());
    266   EXPECT_GT(audio_config.extra_data_size(), 0u);
    267 
    268   // Unknown stream should never be present.
    269   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
    270 }
    271 
    272 TEST_F(FFmpegDemuxerTest, Initialize_Multitrack) {
    273   // Open a file containing the following streams:
    274   //   Stream #0: Video (VP8)
    275   //   Stream #1: Audio (Vorbis)
    276   //   Stream #2: Subtitles (SRT)
    277   //   Stream #3: Video (Theora)
    278   //   Stream #4: Audio (16-bit signed little endian PCM)
    279   //
    280   // We should only pick the first audio/video streams we come across.
    281   CreateDemuxer("bear-320x240-multitrack.webm");
    282   InitializeDemuxer();
    283 
    284   // Video stream should be VP8.
    285   DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
    286   ASSERT_TRUE(stream);
    287   EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
    288   EXPECT_EQ(kCodecVP8, stream->video_decoder_config().codec());
    289 
    290   // Audio stream should be Vorbis.
    291   stream = demuxer_->GetStream(DemuxerStream::AUDIO);
    292   ASSERT_TRUE(stream);
    293   EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
    294   EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec());
    295 
    296   // Unknown stream should never be present.
    297   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
    298 }
    299 
    300 TEST_F(FFmpegDemuxerTest, Initialize_Encrypted) {
    301   EXPECT_CALL(*this, NeedKeyCBMock(kWebMEncryptInitDataType, NotNull(),
    302                                    DecryptConfig::kDecryptionKeySize))
    303       .Times(Exactly(2));
    304 
    305   CreateDemuxer("bear-320x240-av_enc-av.webm");
    306   InitializeDemuxer();
    307 }
    308 
    309 TEST_F(FFmpegDemuxerTest, Read_Audio) {
    310   // We test that on a successful audio packet read.
    311   CreateDemuxer("bear-320x240.webm");
    312   InitializeDemuxer();
    313 
    314   // Attempt a read from the audio stream and run the message loop until done.
    315   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
    316 
    317   audio->Read(NewReadCB(FROM_HERE, 29, 0));
    318   message_loop_.Run();
    319 
    320   audio->Read(NewReadCB(FROM_HERE, 27, 3000));
    321   message_loop_.Run();
    322 }
    323 
    324 TEST_F(FFmpegDemuxerTest, Read_Video) {
    325   // We test that on a successful video packet read.
    326   CreateDemuxer("bear-320x240.webm");
    327   InitializeDemuxer();
    328 
    329   // Attempt a read from the video stream and run the message loop until done.
    330   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
    331 
    332   video->Read(NewReadCB(FROM_HERE, 22084, 0));
    333   message_loop_.Run();
    334 
    335   video->Read(NewReadCB(FROM_HERE, 1057, 33000));
    336   message_loop_.Run();
    337 }
    338 
    339 TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) {
    340   // Test the start time is the first timestamp of the video and audio stream.
    341   CreateDemuxer("nonzero-start-time.webm");
    342   InitializeDemuxer();
    343 
    344   // Attempt a read from the video stream and run the message loop until done.
    345   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
    346   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
    347 
    348   // Check first buffer in video stream.
    349   video->Read(NewReadCB(FROM_HERE, 5636, 400000));
    350   message_loop_.Run();
    351 
    352   // Check first buffer in audio stream.
    353   audio->Read(NewReadCB(FROM_HERE, 165, 396000));
    354   message_loop_.Run();
    355 
    356   // Verify that the start time is equal to the lowest timestamp (ie the audio).
    357   EXPECT_EQ(demuxer_->GetStartTime().InMicroseconds(), 396000);
    358 }
    359 
    360 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) {
    361   // Verify that end of stream buffers are created.
    362   CreateDemuxer("bear-320x240.webm");
    363   InitializeDemuxer();
    364   ReadUntilEndOfStream();
    365 }
    366 
    367 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration) {
    368   // Verify that end of stream buffers are created.
    369   CreateDemuxer("bear-320x240.webm");
    370   InitializeDemuxer();
    371   set_duration_known(false);
    372   EXPECT_CALL(host_, SetDuration(_));
    373   ReadUntilEndOfStream();
    374 }
    375 
    376 TEST_F(FFmpegDemuxerTest, Seek) {
    377   // We're testing that the demuxer frees all queued packets when it receives
    378   // a Seek().
    379   CreateDemuxer("bear-320x240.webm");
    380   InitializeDemuxer();
    381 
    382   // Get our streams.
    383   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
    384   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
    385   ASSERT_TRUE(video);
    386   ASSERT_TRUE(audio);
    387 
    388   // Read a video packet and release it.
    389   video->Read(NewReadCB(FROM_HERE, 22084, 0));
    390   message_loop_.Run();
    391 
    392   // Issue a simple forward seek, which should discard queued packets.
    393   WaitableMessageLoopEvent event;
    394   demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
    395                  event.GetPipelineStatusCB());
    396   event.RunAndWaitForStatus(PIPELINE_OK);
    397 
    398   // Audio read #1.
    399   audio->Read(NewReadCB(FROM_HERE, 145, 803000));
    400   message_loop_.Run();
    401 
    402   // Audio read #2.
    403   audio->Read(NewReadCB(FROM_HERE, 148, 826000));
    404   message_loop_.Run();
    405 
    406   // Video read #1.
    407   video->Read(NewReadCB(FROM_HERE, 5425, 801000));
    408   message_loop_.Run();
    409 
    410   // Video read #2.
    411   video->Read(NewReadCB(FROM_HERE, 1906, 834000));
    412   message_loop_.Run();
    413 }
    414 
    415 class MockReadCB {
    416  public:
    417   MockReadCB() {}
    418   ~MockReadCB() {}
    419 
    420   MOCK_METHOD2(Run, void(DemuxerStream::Status status,
    421                          const scoped_refptr<DecoderBuffer>& buffer));
    422  private:
    423   DISALLOW_COPY_AND_ASSIGN(MockReadCB);
    424 };
    425 
    426 TEST_F(FFmpegDemuxerTest, Stop) {
    427   // Tests that calling Read() on a stopped demuxer stream immediately deletes
    428   // the callback.
    429   CreateDemuxer("bear-320x240.webm");
    430   InitializeDemuxer();
    431 
    432   // Get our stream.
    433   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
    434   ASSERT_TRUE(audio);
    435 
    436   demuxer_->Stop(NewExpectedClosure());
    437 
    438   // Reads after being stopped are all EOS buffers.
    439   StrictMock<MockReadCB> callback;
    440   EXPECT_CALL(callback, Run(DemuxerStream::kOk, IsEndOfStreamBuffer()));
    441 
    442   // Attempt the read...
    443   audio->Read(base::Bind(&MockReadCB::Run, base::Unretained(&callback)));
    444   message_loop_.RunUntilIdle();
    445 }
    446 
    447 TEST_F(FFmpegDemuxerTest, DisableAudioStream) {
    448   // We are doing the following things here:
    449   // 1. Initialize the demuxer with audio and video stream.
    450   // 2. Send a "disable audio stream" message to the demuxer.
    451   // 3. Demuxer will free audio packets even if audio stream was initialized.
    452   CreateDemuxer("bear-320x240.webm");
    453   InitializeDemuxer();
    454 
    455   // Submit a "disable audio stream" message to the demuxer.
    456   demuxer_->OnAudioRendererDisabled();
    457   message_loop_.RunUntilIdle();
    458 
    459   // Get our streams.
    460   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
    461   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
    462   ASSERT_TRUE(video);
    463   ASSERT_TRUE(audio);
    464 
    465   // The audio stream should have been prematurely stopped.
    466   EXPECT_FALSE(IsStreamStopped(DemuxerStream::VIDEO));
    467   EXPECT_TRUE(IsStreamStopped(DemuxerStream::AUDIO));
    468 
    469   // Attempt a read from the video stream: it should return valid data.
    470   video->Read(NewReadCB(FROM_HERE, 22084, 0));
    471   message_loop_.Run();
    472 
    473   // Attempt a read from the audio stream: it should immediately return end of
    474   // stream without requiring the message loop to read data.
    475   bool got_eos_buffer = false;
    476   audio->Read(base::Bind(&EosOnReadDone, &got_eos_buffer));
    477   message_loop_.RunUntilIdle();
    478   EXPECT_TRUE(got_eos_buffer);
    479 }
    480 
    481 // Verify that seek works properly when the WebM cues data is at the start of
    482 // the file instead of at the end.
    483 TEST_F(FFmpegDemuxerTest, SeekWithCuesBeforeFirstCluster) {
    484   CreateDemuxer("bear-320x240-cues-in-front.webm");
    485   InitializeDemuxer();
    486 
    487   // Get our streams.
    488   DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
    489   DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
    490   ASSERT_TRUE(video);
    491   ASSERT_TRUE(audio);
    492 
    493   // Read a video packet and release it.
    494   video->Read(NewReadCB(FROM_HERE, 22084, 0));
    495   message_loop_.Run();
    496 
    497   // Issue a simple forward seek, which should discard queued packets.
    498   WaitableMessageLoopEvent event;
    499   demuxer_->Seek(base::TimeDelta::FromMicroseconds(2500000),
    500                  event.GetPipelineStatusCB());
    501   event.RunAndWaitForStatus(PIPELINE_OK);
    502 
    503   // Audio read #1.
    504   audio->Read(NewReadCB(FROM_HERE, 40, 2403000));
    505   message_loop_.Run();
    506 
    507   // Audio read #2.
    508   audio->Read(NewReadCB(FROM_HERE, 42, 2406000));
    509   message_loop_.Run();
    510 
    511   // Video read #1.
    512   video->Read(NewReadCB(FROM_HERE, 5276, 2402000));
    513   message_loop_.Run();
    514 
    515   // Video read #2.
    516   video->Read(NewReadCB(FROM_HERE, 1740, 2436000));
    517   message_loop_.Run();
    518 }
    519 
    520 // Ensure ID3v1 tag reading is disabled.  id3_test.mp3 has an ID3v1 tag with the
    521 // field "title" set to "sample for id3 test".
    522 TEST_F(FFmpegDemuxerTest, NoID3TagData) {
    523 #if !defined(USE_PROPRIETARY_CODECS)
    524   return;
    525 #endif
    526   CreateDemuxer("id3_test.mp3");
    527   InitializeDemuxer();
    528   EXPECT_FALSE(av_dict_get(format_context()->metadata, "title", NULL, 0));
    529 }
    530 
    531 // Ensure MP3 files with large image/video based ID3 tags demux okay.  FFmpeg
    532 // will hand us a video stream to the data which will likely be in a format we
    533 // don't accept as video; e.g. PNG.
    534 TEST_F(FFmpegDemuxerTest, Mp3WithVideoStreamID3TagData) {
    535 #if !defined(USE_PROPRIETARY_CODECS)
    536   return;
    537 #endif
    538   CreateDemuxer("id3_png_test.mp3");
    539   InitializeDemuxer();
    540 
    541   // Ensure the expected streams are present.
    542   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO));
    543   EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO));
    544 }
    545 
    546 // Ensure a video with an unsupported audio track still results in the video
    547 // stream being demuxed.
    548 TEST_F(FFmpegDemuxerTest, UnsupportedAudioSupportedVideoDemux) {
    549   CreateDemuxer("speex_audio_vorbis_video.ogv");
    550   InitializeDemuxer();
    551 
    552   // Ensure the expected streams are present.
    553   EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::VIDEO));
    554   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::AUDIO));
    555 }
    556 
    557 // Ensure a video with an unsupported video track still results in the audio
    558 // stream being demuxed.
    559 TEST_F(FFmpegDemuxerTest, UnsupportedVideoSupportedAudioDemux) {
    560   CreateDemuxer("vorbis_audio_wmv_video.mkv");
    561   InitializeDemuxer();
    562 
    563   // Ensure the expected streams are present.
    564   EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO));
    565   EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO));
    566 }
    567 
    568 // FFmpeg returns null data pointers when samples have zero size, leading to
    569 // mistakenly creating end of stream buffers http://crbug.com/169133
    570 TEST_F(FFmpegDemuxerTest, MP4_ZeroStszEntry) {
    571 #if !defined(USE_PROPRIETARY_CODECS)
    572   return;
    573 #endif
    574   CreateDemuxer("bear-1280x720-zero-stsz-entry.mp4");
    575   InitializeDemuxer();
    576   ReadUntilEndOfStream();
    577 }
    578 
    579 }  // namespace media
    580