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 <stddef.h>
6 #include <stdint.h>
7 
8 #include <algorithm>
9 #include <string>
10 #include <utility>
11 
12 #include "base/bind.h"
13 #include "base/callback_forward.h"
14 #include "base/files/file_path.h"
15 #include "base/location.h"
16 #include "base/logging.h"
17 #include "base/path_service.h"
18 #include "base/run_loop.h"
19 #include "base/single_thread_task_runner.h"
20 #include "base/stl_util.h"
21 #include "base/test/mock_callback.h"
22 #include "base/test/task_environment.h"
23 #include "base/threading/thread.h"
24 #include "base/threading/thread_task_runner_handle.h"
25 #include "build/build_config.h"
26 #include "build/chromeos_buildflags.h"
27 #include "media/base/decrypt_config.h"
28 #include "media/base/demuxer_stream.h"
29 #include "media/base/media_client.h"
30 #include "media/base/media_tracks.h"
31 #include "media/base/media_util.h"
32 #include "media/base/mock_demuxer_host.h"
33 #include "media/base/mock_filters.h"
34 #include "media/base/mock_media_log.h"
35 #include "media/base/test_helpers.h"
36 #include "media/base/timestamp_constants.h"
37 #include "media/ffmpeg/ffmpeg_common.h"
38 #include "media/filters/ffmpeg_demuxer.h"
39 #include "media/filters/file_data_source.h"
40 #include "media/formats/mp4/avc.h"
41 #include "media/formats/mp4/bitstream_converter.h"
42 #include "media/media_buildflags.h"
43 #include "testing/gtest/include/gtest/gtest.h"
44 #include "ui/gfx/color_space.h"
45 
46 using ::testing::_;
47 using ::testing::AnyNumber;
48 using ::testing::DoAll;
49 using ::testing::Eq;
50 using ::testing::Exactly;
51 using ::testing::InSequence;
52 using ::testing::Invoke;
53 using ::testing::NotNull;
54 using ::testing::Return;
55 using ::testing::SaveArg;
56 using ::testing::SetArgPointee;
57 using ::testing::StrictMock;
58 using ::testing::WithArgs;
59 
60 namespace media {
61 
62 MATCHER(IsEndOfStreamBuffer,
63         std::string(negation ? "isn't" : "is") + " end of stream") {
64   return arg->end_of_stream();
65 }
66 
67 // This does not verify any of the codec parameters that may be included in the
68 // log entry.
69 MATCHER_P(SimpleCreatedFFmpegDemuxerStream, stream_type, "") {
70   return CONTAINS_STRING(arg, "\"info\":\"FFmpegDemuxer: created " +
71                                   std::string(stream_type) +
72                                   " stream, config codec:");
73 }
74 
75 MATCHER_P(FailedToCreateValidDecoderConfigFromStream, stream_type, "") {
76   return CONTAINS_STRING(
77       arg,
78       "\"debug\":\"Warning, FFmpegDemuxer failed to create a "
79       "valid/supported " +
80           std::string(stream_type) +
81           " decoder configuration from muxed stream");
82 }
83 
84 MATCHER_P(SkippingUnsupportedStream, stream_type, "") {
85   return CONTAINS_STRING(
86       arg, "\"info\":\"FFmpegDemuxer: skipping invalid or unsupported " +
87                std::string(stream_type) + " track");
88 }
89 
90 const uint8_t kEncryptedMediaInitData[] = {
91     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
92     0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
93 };
94 
EosOnReadDone(bool * got_eos_buffer,DemuxerStream::Status status,scoped_refptr<DecoderBuffer> buffer)95 static void EosOnReadDone(bool* got_eos_buffer,
96                           DemuxerStream::Status status,
97                           scoped_refptr<DecoderBuffer> buffer) {
98   base::ThreadTaskRunnerHandle::Get()->PostTask(
99       FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
100 
101   EXPECT_EQ(status, DemuxerStream::kOk);
102   if (buffer->end_of_stream()) {
103     *got_eos_buffer = true;
104     return;
105   }
106 
107   EXPECT_TRUE(buffer->data());
108   EXPECT_GT(buffer->data_size(), 0u);
109   *got_eos_buffer = false;
110 }
111 
112 // Fixture class to facilitate writing tests.  Takes care of setting up the
113 // FFmpeg, pipeline and filter host mocks.
114 class FFmpegDemuxerTest : public testing::Test {
115  protected:
116   FFmpegDemuxerTest() = default;
117 
~FFmpegDemuxerTest()118   ~FFmpegDemuxerTest() override { Shutdown(); }
119 
Shutdown()120   void Shutdown() {
121     if (demuxer_)
122       demuxer_->Stop();
123     demuxer_.reset();
124     task_environment_.RunUntilIdle();
125     data_source_.reset();
126   }
127 
128   // TODO(wolenetz): Combine with CreateDemuxer() and expand coverage of all of
129   // these tests to use strict media log. See https://crbug.com/749178.
CreateDemuxerWithStrictMediaLog(const std::string & name)130   void CreateDemuxerWithStrictMediaLog(const std::string& name) {
131     CreateDemuxerInternal(name, &media_log_);
132   }
133 
CreateDemuxer(const std::string & name)134   void CreateDemuxer(const std::string& name) {
135     CreateDemuxerInternal(name, &dummy_media_log_);
136   }
137 
GetStream(DemuxerStream::Type type)138   DemuxerStream* GetStream(DemuxerStream::Type type) {
139     std::vector<DemuxerStream*> streams = demuxer_->GetAllStreams();
140     for (auto* stream : streams) {
141       if (stream->type() == type)
142         return stream;
143     }
144     return nullptr;
145   }
146 
147   MOCK_METHOD1(CheckPoint, void(int v));
148 
InitializeDemuxerInternal(media::PipelineStatus expected_pipeline_status,base::Time timeline_offset)149   void InitializeDemuxerInternal(media::PipelineStatus expected_pipeline_status,
150                                  base::Time timeline_offset) {
151     if (expected_pipeline_status == PIPELINE_OK)
152       EXPECT_CALL(host_, SetDuration(_)).Times(AnyNumber());
153     WaitableMessageLoopEvent event;
154     demuxer_->Initialize(&host_, event.GetPipelineStatusCB());
155     demuxer_->timeline_offset_ = timeline_offset;
156     event.RunAndWaitForStatus(expected_pipeline_status);
157   }
158 
InitializeDemuxer()159   void InitializeDemuxer() {
160     InitializeDemuxerInternal(PIPELINE_OK, base::Time());
161   }
162 
InitializeDemuxerWithTimelineOffset(base::Time timeline_offset)163   void InitializeDemuxerWithTimelineOffset(base::Time timeline_offset) {
164     InitializeDemuxerInternal(PIPELINE_OK, timeline_offset);
165   }
166 
InitializeDemuxerAndExpectPipelineStatus(media::PipelineStatus expected_pipeline_status)167   void InitializeDemuxerAndExpectPipelineStatus(
168       media::PipelineStatus expected_pipeline_status) {
169     InitializeDemuxerInternal(expected_pipeline_status, base::Time());
170   }
171 
SeekOnVideoTrackChangePassthrough(base::TimeDelta time,base::OnceCallback<void (DemuxerStream::Type,const std::vector<DemuxerStream * > &)> cb,DemuxerStream::Type type,const std::vector<DemuxerStream * > & streams)172   void SeekOnVideoTrackChangePassthrough(
173       base::TimeDelta time,
174       base::OnceCallback<void(DemuxerStream::Type,
175                               const std::vector<DemuxerStream*>&)> cb,
176       DemuxerStream::Type type,
177       const std::vector<DemuxerStream*>& streams) {
178     // The tests can't access private methods directly because gtest uses
179     // some magic macros that break the 'friend' declaration.
180     demuxer_->SeekOnVideoTrackChange(time, std::move(cb), type, streams);
181   }
182 
183   MOCK_METHOD2(OnReadDoneCalled, void(int, int64_t));
184 
185   struct ReadExpectation {
ReadExpectationmedia::FFmpegDemuxerTest::ReadExpectation186     ReadExpectation(size_t size,
187                     int64_t timestamp_us,
188                     base::TimeDelta discard_front_padding,
189                     bool is_key_frame,
190                     DemuxerStream::Status status)
191         : size(size),
192           timestamp_us(timestamp_us),
193           discard_front_padding(discard_front_padding),
194           is_key_frame(is_key_frame),
195           status(status) {}
196 
197     size_t size;
198     int64_t timestamp_us;
199     base::TimeDelta discard_front_padding;
200     bool is_key_frame;
201     DemuxerStream::Status status;
202   };
203 
204   // Verifies that |buffer| has a specific |size| and |timestamp|.
205   // |location| simply indicates where the call to this function was made.
206   // This makes it easier to track down where test failures occur.
OnReadDone(const base::Location & location,const ReadExpectation & read_expectation,base::OnceClosure quit_closure,DemuxerStream::Status status,scoped_refptr<DecoderBuffer> buffer)207   void OnReadDone(const base::Location& location,
208                   const ReadExpectation& read_expectation,
209                   base::OnceClosure quit_closure,
210                   DemuxerStream::Status status,
211                   scoped_refptr<DecoderBuffer> buffer) {
212     std::string location_str = location.ToString();
213     location_str += "\n";
214     SCOPED_TRACE(location_str);
215     EXPECT_EQ(read_expectation.status, status);
216     if (status == DemuxerStream::kOk) {
217       EXPECT_TRUE(buffer);
218       EXPECT_EQ(read_expectation.size, buffer->data_size());
219       EXPECT_EQ(read_expectation.timestamp_us,
220                 buffer->timestamp().InMicroseconds());
221       EXPECT_EQ(read_expectation.discard_front_padding,
222                 buffer->discard_padding().first);
223       EXPECT_EQ(read_expectation.is_key_frame, buffer->is_key_frame());
224     }
225     OnReadDoneCalled(read_expectation.size, read_expectation.timestamp_us);
226     std::move(quit_closure).Run();
227   }
228 
NewReadCBWithCheckedDiscard(const base::Location & location,int size,int64_t timestamp_us,base::TimeDelta discard_front_padding,bool is_key_frame,DemuxerStream::Status status,base::OnceClosure quit_closure)229   DemuxerStream::ReadCB NewReadCBWithCheckedDiscard(
230       const base::Location& location,
231       int size,
232       int64_t timestamp_us,
233       base::TimeDelta discard_front_padding,
234       bool is_key_frame,
235       DemuxerStream::Status status,
236       base::OnceClosure quit_closure) {
237     EXPECT_CALL(*this, OnReadDoneCalled(size, timestamp_us));
238 
239     struct ReadExpectation read_expectation(
240         size, timestamp_us, discard_front_padding, is_key_frame, status);
241 
242     return base::BindOnce(&FFmpegDemuxerTest::OnReadDone,
243                           base::Unretained(this), location, read_expectation,
244                           std::move(quit_closure));
245   }
246 
Read(DemuxerStream * stream,const base::Location & location,int size,int64_t timestamp_us,bool is_key_frame,DemuxerStream::Status status=DemuxerStream::Status::kOk,base::TimeDelta discard_front_padding=base::TimeDelta ())247   void Read(DemuxerStream* stream,
248             const base::Location& location,
249             int size,
250             int64_t timestamp_us,
251             bool is_key_frame,
252             DemuxerStream::Status status = DemuxerStream::Status::kOk,
253             base::TimeDelta discard_front_padding = base::TimeDelta()) {
254     base::RunLoop run_loop;
255     stream->Read(NewReadCBWithCheckedDiscard(
256         location, size, timestamp_us, discard_front_padding, is_key_frame,
257         status, run_loop.QuitClosure()));
258     run_loop.Run();
259 
260     // Ensure tasks posted after the ReadCB is satisfied run. These are always
261     // tasks posted to FFmpegDemuxer's internal |blocking_task_runner_|, which
262     // the RunLoop above won't pump.
263     task_environment_.RunUntilIdle();
264   }
265 
266   MOCK_METHOD2(OnEncryptedMediaInitData,
267                void(EmeInitDataType init_data_type,
268                     const std::vector<uint8_t>& init_data));
269 
OnMediaTracksUpdated(std::unique_ptr<MediaTracks> tracks)270   void OnMediaTracksUpdated(std::unique_ptr<MediaTracks> tracks) {
271     CHECK(tracks.get());
272     media_tracks_ = std::move(tracks);
273   }
274 
275   // Accessor to demuxer internals.
SetDurationKnown(bool duration_known)276   void SetDurationKnown(bool duration_known) {
277     demuxer_->duration_known_ = duration_known;
278     if (!duration_known)
279       demuxer_->duration_ = kInfiniteDuration;
280   }
281 
282 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
HasBitstreamConverter(DemuxerStream * stream) const283   bool HasBitstreamConverter(DemuxerStream* stream) const {
284     return !!reinterpret_cast<FFmpegDemuxerStream*>(stream)
285                  ->bitstream_converter_;
286   }
287 #endif
288 
289   // Fixture members.
290 
291   base::test::TaskEnvironment task_environment_;
292 
293   // TODO(wolenetz): Consider expanding MediaLog verification coverage here
294   // using StrictMock<MockMediaLog> for all FFmpegDemuxerTests. See
295   // https://crbug.com/749178.
296   StrictMock<MockMediaLog> media_log_;
297   NullMediaLog dummy_media_log_;
298 
299   std::unique_ptr<FileDataSource> data_source_;
300   std::unique_ptr<FFmpegDemuxer> demuxer_;
301   StrictMock<MockDemuxerHost> host_;
302   std::unique_ptr<MediaTracks> media_tracks_;
303 
format_context()304   AVFormatContext* format_context() {
305     return demuxer_->glue_->format_context();
306   }
307 
preferred_seeking_stream(base::TimeDelta seek_time) const308   DemuxerStream* preferred_seeking_stream(base::TimeDelta seek_time) const {
309     return demuxer_->FindPreferredStreamForSeeking(seek_time);
310   }
311 
ReadUntilEndOfStream(DemuxerStream * stream)312   void ReadUntilEndOfStream(DemuxerStream* stream) {
313     bool got_eos_buffer = false;
314     const int kMaxBuffers = 170;
315     for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) {
316       stream->Read(base::BindOnce(&EosOnReadDone, &got_eos_buffer));
317       base::RunLoop().Run();
318     }
319 
320     EXPECT_TRUE(got_eos_buffer);
321   }
322 
Seek(base::TimeDelta seek_target)323   void Seek(base::TimeDelta seek_target) {
324     WaitableMessageLoopEvent event;
325     demuxer_->Seek(seek_target, event.GetPipelineStatusCB());
326     event.RunAndWaitForStatus(PIPELINE_OK);
327   }
328 
329  private:
CreateDemuxerInternal(const std::string & name,MediaLog * media_log)330   void CreateDemuxerInternal(const std::string& name, MediaLog* media_log) {
331     CHECK(!demuxer_);
332 
333     EXPECT_CALL(host_, OnBufferedTimeRangesChanged(_)).Times(AnyNumber());
334 
335     CreateDataSource(name);
336 
337     Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
338         base::BindRepeating(&FFmpegDemuxerTest::OnEncryptedMediaInitData,
339                             base::Unretained(this));
340 
341     Demuxer::MediaTracksUpdatedCB tracks_updated_cb = base::BindRepeating(
342         &FFmpegDemuxerTest::OnMediaTracksUpdated, base::Unretained(this));
343 
344     demuxer_.reset(new FFmpegDemuxer(
345         base::ThreadTaskRunnerHandle::Get(), data_source_.get(),
346         encrypted_media_init_data_cb, tracks_updated_cb, media_log, false));
347   }
348 
CreateDataSource(const std::string & name)349   void CreateDataSource(const std::string& name) {
350     CHECK(!data_source_);
351 
352     base::FilePath file_path;
353     EXPECT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
354 
355     file_path = file_path.Append(FILE_PATH_LITERAL("media"))
356                     .Append(FILE_PATH_LITERAL("test"))
357                     .Append(FILE_PATH_LITERAL("data"))
358                     .AppendASCII(name);
359 
360     data_source_.reset(new FileDataSource());
361     EXPECT_TRUE(data_source_->Initialize(file_path));
362   }
363 
364   DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest);
365 };
366 
TEST_F(FFmpegDemuxerTest,Initialize_OpenFails)367 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) {
368   // Simulate avformat_open_input() failing.
369   CreateDemuxer("ten_byte_file");
370   WaitableMessageLoopEvent event;
371   demuxer_->Initialize(&host_, event.GetPipelineStatusCB());
372   event.RunAndWaitForStatus(DEMUXER_ERROR_COULD_NOT_OPEN);
373 }
374 
TEST_F(FFmpegDemuxerTest,Initialize_NoStreams)375 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) {
376   // Open a file with no streams whatsoever.
377   CreateDemuxer("no_streams.webm");
378   WaitableMessageLoopEvent event;
379   demuxer_->Initialize(&host_, event.GetPipelineStatusCB());
380   event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
381 }
382 
TEST_F(FFmpegDemuxerTest,Initialize_NoAudioVideo)383 TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) {
384   // Open a file containing streams but none of which are audio/video streams.
385   CreateDemuxer("no_audio_video.webm");
386   WaitableMessageLoopEvent event;
387   demuxer_->Initialize(&host_, event.GetPipelineStatusCB());
388   event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
389 }
390 
TEST_F(FFmpegDemuxerTest,Initialize_Successful)391 TEST_F(FFmpegDemuxerTest, Initialize_Successful) {
392   CreateDemuxer("bear-320x240.webm");
393   InitializeDemuxer();
394 
395   // Video stream should be present.
396   DemuxerStream* stream = GetStream(DemuxerStream::VIDEO);
397   ASSERT_TRUE(stream);
398   EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
399 
400   const VideoDecoderConfig& video_config = stream->video_decoder_config();
401   EXPECT_EQ(kCodecVP8, video_config.codec());
402   EXPECT_EQ(VideoDecoderConfig::AlphaMode::kIsOpaque,
403             video_config.alpha_mode());
404   EXPECT_EQ(320, video_config.coded_size().width());
405   EXPECT_EQ(240, video_config.coded_size().height());
406   EXPECT_EQ(0, video_config.visible_rect().x());
407   EXPECT_EQ(0, video_config.visible_rect().y());
408   EXPECT_EQ(320, video_config.visible_rect().width());
409   EXPECT_EQ(240, video_config.visible_rect().height());
410   EXPECT_EQ(320, video_config.natural_size().width());
411   EXPECT_EQ(240, video_config.natural_size().height());
412   EXPECT_TRUE(video_config.extra_data().empty());
413 
414   // Audio stream should be present.
415   stream = GetStream(DemuxerStream::AUDIO);
416   ASSERT_TRUE(stream);
417   EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
418 
419   const AudioDecoderConfig& audio_config = stream->audio_decoder_config();
420   EXPECT_EQ(kCodecVorbis, audio_config.codec());
421   EXPECT_EQ(32, audio_config.bits_per_channel());
422   EXPECT_EQ(CHANNEL_LAYOUT_STEREO, audio_config.channel_layout());
423   EXPECT_EQ(44100, audio_config.samples_per_second());
424   EXPECT_EQ(kSampleFormatPlanarF32, audio_config.sample_format());
425   EXPECT_FALSE(audio_config.extra_data().empty());
426 
427   // Unknown stream should never be present.
428   EXPECT_EQ(2u, demuxer_->GetAllStreams().size());
429 }
430 
431 // Android has no Theora support, so this test doesn't work.
432 #if !defined(OS_ANDROID)
TEST_F(FFmpegDemuxerTest,Initialize_Multitrack)433 TEST_F(FFmpegDemuxerTest, Initialize_Multitrack) {
434   // Open a file containing the following streams:
435   //   Stream #0: Video (VP8)
436   //   Stream #1: Audio (Vorbis)
437   //   Stream #2: Subtitles (SRT)
438   //   Stream #3: Video (Theora)
439   //   Stream #4: Audio (16-bit signed little endian PCM)
440   CreateDemuxer("bear-320x240-multitrack.webm");
441   InitializeDemuxer();
442 
443   std::vector<DemuxerStream*> streams = demuxer_->GetAllStreams();
444   EXPECT_EQ(4u, streams.size());
445 
446   // Stream #0 should be VP8 video.
447   DemuxerStream* stream = streams[0];
448   ASSERT_TRUE(stream);
449   EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
450   EXPECT_EQ(kCodecVP8, stream->video_decoder_config().codec());
451 
452   // Stream #1 should be Vorbis audio.
453   stream = streams[1];
454   ASSERT_TRUE(stream);
455   EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
456   EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec());
457 
458   // The subtitles stream is skipped.
459   // Stream #2 should be Theora video.
460   stream = streams[2];
461   ASSERT_TRUE(stream);
462   EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
463   EXPECT_EQ(kCodecTheora, stream->video_decoder_config().codec());
464 
465   // Stream #3 should be PCM audio.
466   stream = streams[3];
467   ASSERT_TRUE(stream);
468   EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
469   EXPECT_EQ(kCodecPCM, stream->audio_decoder_config().codec());
470 }
471 #endif
472 
TEST_F(FFmpegDemuxerTest,Initialize_Encrypted)473 TEST_F(FFmpegDemuxerTest, Initialize_Encrypted) {
474   EXPECT_CALL(
475       *this, OnEncryptedMediaInitData(
476                  EmeInitDataType::WEBM,
477                  std::vector<uint8_t>(kEncryptedMediaInitData,
478                                       kEncryptedMediaInitData +
479                                           base::size(kEncryptedMediaInitData))))
480       .Times(Exactly(2));
481 
482   CreateDemuxer("bear-320x240-av_enc-av.webm");
483   InitializeDemuxer();
484 }
485 
TEST_F(FFmpegDemuxerTest,Initialize_NoConfigChangeSupport)486 TEST_F(FFmpegDemuxerTest, Initialize_NoConfigChangeSupport) {
487   // Will create one audio, one video, and one text stream.
488   CreateDemuxer("bear-vp8-webvtt.webm");
489   InitializeDemuxer();
490 
491   for (auto* stream : demuxer_->GetAllStreams())
492     EXPECT_FALSE(stream->SupportsConfigChanges());
493 }
494 
TEST_F(FFmpegDemuxerTest,AbortPendingReads)495 TEST_F(FFmpegDemuxerTest, AbortPendingReads) {
496   // We test that on a successful audio packet read.
497   CreateDemuxer("bear-320x240.webm");
498   InitializeDemuxer();
499 
500   // Attempt a read from the audio stream and run the message loop until done.
501   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
502 
503   // Depending on where in the reading process ffmpeg is, an error may cause the
504   // stream to be marked as EOF.  Simulate this here to ensure it is properly
505   // cleared by the AbortPendingReads() call.
506   format_context()->pb->eof_reached = 1;
507   {
508     base::RunLoop run_loop;
509     audio->Read(NewReadCBWithCheckedDiscard(FROM_HERE, 29, 0, base::TimeDelta(),
510                                             true, DemuxerStream::kAborted,
511                                             run_loop.QuitClosure()));
512     demuxer_->AbortPendingReads();
513     run_loop.Run();
514     task_environment_.RunUntilIdle();
515   }
516 
517   // Additional reads should also be aborted (until a Seek()).
518   Read(audio, FROM_HERE, 29, 0, true, DemuxerStream::kAborted);
519 
520   // Ensure blocking thread has completed outstanding work.
521   demuxer_->Stop();
522   EXPECT_EQ(format_context()->pb->eof_reached, 0);
523 
524   // Calling abort after stop should not crash.
525   demuxer_->AbortPendingReads();
526   demuxer_.reset();
527 }
528 
TEST_F(FFmpegDemuxerTest,Read_Audio)529 TEST_F(FFmpegDemuxerTest, Read_Audio) {
530   // We test that on a successful audio packet read.
531   CreateDemuxer("bear-320x240.webm");
532   InitializeDemuxer();
533 
534   // Attempt a read from the audio stream and run the message loop until done.
535   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
536   Read(audio, FROM_HERE, 29, 0, true);
537   Read(audio, FROM_HERE, 27, 3000, true);
538   EXPECT_EQ(166866, demuxer_->GetMemoryUsage());
539 }
540 
TEST_F(FFmpegDemuxerTest,Read_Video)541 TEST_F(FFmpegDemuxerTest, Read_Video) {
542   // We test that on a successful video packet read.
543   CreateDemuxer("bear-320x240.webm");
544   InitializeDemuxer();
545 
546   // Attempt a read from the video stream and run the message loop until done.
547   DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
548   Read(video, FROM_HERE, 22084, 0, true);
549   Read(video, FROM_HERE, 1057, 33000, false);
550   EXPECT_EQ(148778, demuxer_->GetMemoryUsage());
551 }
552 
TEST_F(FFmpegDemuxerTest,SeekInitialized_NoVideoStartTime)553 TEST_F(FFmpegDemuxerTest, SeekInitialized_NoVideoStartTime) {
554   CreateDemuxer("audio-start-time-only.webm");
555   InitializeDemuxer();
556   // Video stream should be preferred for seeking even if video start time is
557   // unknown.
558   DemuxerStream* vstream = GetStream(DemuxerStream::VIDEO);
559   EXPECT_EQ(vstream, preferred_seeking_stream(base::TimeDelta()));
560 }
561 
TEST_F(FFmpegDemuxerTest,Seeking_PreferredStreamSelection)562 TEST_F(FFmpegDemuxerTest, Seeking_PreferredStreamSelection) {
563   const int64_t kTimelineOffsetMs = 1352550896000LL;
564 
565   // Test the start time is the first timestamp of the video and audio stream.
566   CreateDemuxer("nonzero-start-time.webm");
567   InitializeDemuxerWithTimelineOffset(
568       base::Time::FromJsTime(kTimelineOffsetMs));
569 
570   FFmpegDemuxerStream* video =
571       static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::VIDEO));
572   FFmpegDemuxerStream* audio =
573       static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::AUDIO));
574 
575   const base::TimeDelta video_start_time =
576       base::TimeDelta::FromMicroseconds(400000);
577   const base::TimeDelta audio_start_time =
578       base::TimeDelta::FromMicroseconds(396000);
579 
580   // Seeking to a position lower than the start time of either stream should
581   // prefer video stream for seeking.
582   EXPECT_EQ(video, preferred_seeking_stream(base::TimeDelta()));
583   // Seeking to a position that has audio data, but not video, should prefer
584   // the audio stream for seeking.
585   EXPECT_EQ(audio, preferred_seeking_stream(audio_start_time));
586   // Seeking to a position where both audio and video streams have data should
587   // prefer the video stream for seeking.
588   EXPECT_EQ(video, preferred_seeking_stream(video_start_time));
589 
590   // A disabled stream should be preferred only when there's no other viable
591   // option among enabled streams.
592   audio->SetEnabled(false, base::TimeDelta());
593   EXPECT_EQ(video, preferred_seeking_stream(video_start_time));
594   // Audio stream is preferred, even though it is disabled, since video stream
595   // start time is higher than the seek target == audio_start_time in this case.
596   EXPECT_EQ(audio, preferred_seeking_stream(audio_start_time));
597 
598   audio->SetEnabled(true, base::TimeDelta());
599   video->SetEnabled(false, base::TimeDelta());
600   EXPECT_EQ(audio, preferred_seeking_stream(audio_start_time));
601   EXPECT_EQ(audio, preferred_seeking_stream(video_start_time));
602 
603   // When both audio and video streams are disabled and there's no enabled
604   // streams, then audio is preferred since it has lower start time.
605   audio->SetEnabled(false, base::TimeDelta());
606   EXPECT_EQ(audio, preferred_seeking_stream(audio_start_time));
607   EXPECT_EQ(audio, preferred_seeking_stream(video_start_time));
608 }
609 
TEST_F(FFmpegDemuxerTest,Read_VideoPositiveStartTime)610 TEST_F(FFmpegDemuxerTest, Read_VideoPositiveStartTime) {
611   const int64_t kTimelineOffsetMs = 1352550896000LL;
612 
613   // Test the start time is the first timestamp of the video and audio stream.
614   CreateDemuxer("nonzero-start-time.webm");
615   InitializeDemuxerWithTimelineOffset(
616       base::Time::FromJsTime(kTimelineOffsetMs));
617 
618   // Attempt a read from the video stream and run the message loop until done.
619   DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
620   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
621 
622   const base::TimeDelta video_start_time =
623       base::TimeDelta::FromMicroseconds(400000);
624   const base::TimeDelta audio_start_time =
625       base::TimeDelta::FromMicroseconds(396000);
626 
627   // Run the test twice with a seek in between.
628   for (int i = 0; i < 2; ++i) {
629     Read(video, FROM_HERE, 5636, video_start_time.InMicroseconds(), true);
630     Read(audio, FROM_HERE, 165, audio_start_time.InMicroseconds(), true);
631 
632     // Verify that the start time is equal to the lowest timestamp (ie the
633     // audio).
634     EXPECT_EQ(audio_start_time, demuxer_->start_time());
635 
636     // Verify that the timeline offset has not been adjusted by the start time.
637     EXPECT_EQ(kTimelineOffsetMs, demuxer_->GetTimelineOffset().ToJavaTime());
638 
639     // Seek back to the beginning and repeat the test.
640     WaitableMessageLoopEvent event;
641     demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
642     event.RunAndWaitForStatus(PIPELINE_OK);
643   }
644 }
645 
TEST_F(FFmpegDemuxerTest,Read_AudioNoStartTime)646 TEST_F(FFmpegDemuxerTest, Read_AudioNoStartTime) {
647   // FFmpeg does not set timestamps when demuxing wave files.  Ensure that the
648   // demuxer sets a start time of zero in this case.
649   CreateDemuxer("sfx_s24le.wav");
650   InitializeDemuxer();
651 
652   // Run the test twice with a seek in between.
653   for (int i = 0; i < 2; ++i) {
654     Read(GetStream(DemuxerStream::AUDIO), FROM_HERE, 4095, 0, true);
655     EXPECT_EQ(base::TimeDelta(), demuxer_->start_time());
656 
657     // Seek back to the beginning and repeat the test.
658     WaitableMessageLoopEvent event;
659     demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
660     event.RunAndWaitForStatus(PIPELINE_OK);
661   }
662 }
663 
664 // Android has no Theora support, so these tests doesn't work.
665 #if !defined(OS_ANDROID)
TEST_F(FFmpegDemuxerTest,Read_AudioNegativeStartTimeAndOggDiscard_Bear)666 TEST_F(FFmpegDemuxerTest, Read_AudioNegativeStartTimeAndOggDiscard_Bear) {
667   // Many ogg files have negative starting timestamps, so ensure demuxing and
668   // seeking work correctly with a negative start time.
669   CreateDemuxer("bear.ogv");
670   InitializeDemuxer();
671 
672   // Attempt a read from the video stream and run the message loop until done.
673   DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
674   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
675 
676   // Run the test once (should be twice..., see note) with a seek in between.
677   //
678   // TODO(dalecurtis): We only run the test once since FFmpeg does not currently
679   // guarantee the order of demuxed packets in OGG containers. See
680   // http://crbug.com/387996.
681   for (int i = 0; i < 1; ++i) {
682     Read(audio, FROM_HERE, 40, 0, true, DemuxerStream::Status::kOk,
683          kInfiniteDuration);
684     Read(audio, FROM_HERE, 41, 2903, true, DemuxerStream::Status::kOk,
685          kInfiniteDuration);
686     Read(audio, FROM_HERE, 173, 5805, true, DemuxerStream::Status::kOk,
687          base::TimeDelta::FromMicroseconds(10159));
688 
689     Read(audio, FROM_HERE, 148, 18866, true);
690     EXPECT_EQ(base::TimeDelta::FromMicroseconds(-15964),
691               demuxer_->start_time());
692 
693     Read(video, FROM_HERE, 5751, 0, true);
694     Read(video, FROM_HERE, 846, 33367, false);
695     Read(video, FROM_HERE, 1255, 66733, false);
696 
697     // Seek back to the beginning and repeat the test.
698     WaitableMessageLoopEvent event;
699     demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
700     event.RunAndWaitForStatus(PIPELINE_OK);
701   }
702 }
703 
704 // Same test above, but using sync2.ogv which has video stream muxed before the
705 // audio stream, so seeking based only on start time will fail since ffmpeg is
706 // essentially just seeking based on file position.
TEST_F(FFmpegDemuxerTest,Read_AudioNegativeStartTimeAndOggDiscard_Sync)707 TEST_F(FFmpegDemuxerTest, Read_AudioNegativeStartTimeAndOggDiscard_Sync) {
708   // Many ogg files have negative starting timestamps, so ensure demuxing and
709   // seeking work correctly with a negative start time.
710   CreateDemuxer("sync2.ogv");
711   InitializeDemuxer();
712 
713   // Attempt a read from the video stream and run the message loop until done.
714   DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
715   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
716 
717   // Run the test twice with a seek in between.
718   for (int i = 0; i < 2; ++i) {
719     Read(audio, FROM_HERE, 1, 0, true, DemuxerStream::Status::kOk,
720          base::TimeDelta::FromMicroseconds(2902));
721     Read(audio, FROM_HERE, 1, 2902, true);
722     EXPECT_EQ(base::TimeDelta::FromMicroseconds(-2902), demuxer_->start_time());
723 
724     // Though the internal start time may be below zero, the exposed media time
725     // must always be >= zero.
726     EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
727 
728     Read(video, FROM_HERE, 9997, 0, true);
729     Read(video, FROM_HERE, 16, 33241, false);
730     Read(video, FROM_HERE, 631, 66482, false);
731 
732     // Seek back to the beginning and repeat the test.
733     WaitableMessageLoopEvent event;
734     demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
735     event.RunAndWaitForStatus(PIPELINE_OK);
736   }
737 }
738 #endif  // !defined(OS_ANDROID)
739 
740 // Similar to the test above, but using an opus clip with a large amount of
741 // pre-skip, which ffmpeg encodes as negative timestamps.
TEST_F(FFmpegDemuxerTest,Read_AudioNegativeStartTimeAndOpusDiscard_Sync)742 TEST_F(FFmpegDemuxerTest, Read_AudioNegativeStartTimeAndOpusDiscard_Sync) {
743   CreateDemuxer("opus-trimming-video-test.webm");
744   InitializeDemuxer();
745 
746   // Attempt a read from the video stream and run the message loop until done.
747   DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
748   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
749   EXPECT_EQ(audio->audio_decoder_config().codec_delay(), 65535);
750 
751   // Packet size to timestamp (in microseconds) mapping for the first N packets
752   // which should be fully discarded.
753   static const int kTestExpectations[][2] = {
754       {635, 0},      {594, 120000},  {597, 240000}, {591, 360000},
755       {582, 480000}, {583, 600000},  {592, 720000}, {567, 840000},
756       {579, 960000}, {572, 1080000}, {583, 1200000}};
757 
758   // Run the test twice with a seek in between.
759   for (int i = 0; i < 2; ++i) {
760     for (size_t j = 0; j < base::size(kTestExpectations); ++j) {
761       Read(audio, FROM_HERE, kTestExpectations[j][0], kTestExpectations[j][1],
762            true);
763     }
764 
765     // Though the internal start time may be below zero, the exposed media time
766     // must always be >= zero.
767     EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
768 
769     Read(video, FROM_HERE, 16009, 0, true);
770     Read(video, FROM_HERE, 2715, 1000, false);
771     Read(video, FROM_HERE, 427, 33000, false);
772 
773     // Seek back to the beginning and repeat the test.
774     WaitableMessageLoopEvent event;
775     demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
776     event.RunAndWaitForStatus(PIPELINE_OK);
777   }
778 }
779 
780 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
781 
782 #if BUILDFLAG(IS_ASH)
TEST_F(FFmpegDemuxerTest,TestAudioNegativeTimestamps)783 TEST_F(FFmpegDemuxerTest, TestAudioNegativeTimestamps) {
784   // Note: This test will _crash_ the browser if negative timestamp
785   // values are skipped, since this file is heavily truncated to avoid
786   // copyright issue. If the negative timestamp packets are dropped, the
787   // demuxer will continue to read off the end of the stream.
788   CreateDemuxer("negative-audio-timestamps.avi");
789   InitializeDemuxer();
790 
791   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
792   Read(audio, FROM_HERE, 104, 0, true);
793   Read(audio, FROM_HERE, 104, 25873, true);
794   Read(audio, FROM_HERE, 104, 51746, true);
795   Read(audio, FROM_HERE, 104, 77619, true);
796   Read(audio, FROM_HERE, 104, 103492, true);
797 }
798 #endif  // BUILDFLAG(IS_ASH)
799 
800 // Similar to the test above, but using an opus clip plus h264 b-frames to
801 // ensure we don't apply chained ogg workarounds to other content.
TEST_F(FFmpegDemuxerTest,Read_AudioNegativeStartTimeAndOpusDiscardH264Mp4_Sync)802 TEST_F(FFmpegDemuxerTest,
803        Read_AudioNegativeStartTimeAndOpusDiscardH264Mp4_Sync) {
804   CreateDemuxer("tos-h264-opus.mp4");
805   InitializeDemuxer();
806 
807   // Attempt a read from the video stream and run the message loop until done.
808   DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
809   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
810   EXPECT_EQ(audio->audio_decoder_config().codec_delay(), 312);
811 
812   // Packet size to timestamp (in microseconds) mapping for the first N packets
813   // which should be fully discarded.
814   static const int kTestExpectations[][2] = {
815       {234, 20000}, {228, 40000}, {340, 60000}};
816 
817   // Run the test twice with a seek in between.
818   for (int i = 0; i < 2; ++i) {
819     Read(audio, FROM_HERE, 408, 0, true, DemuxerStream::Status::kOk,
820          base::TimeDelta::FromMicroseconds(6500));
821 
822     for (size_t j = 0; j < base::size(kTestExpectations); ++j) {
823       Read(audio, FROM_HERE, kTestExpectations[j][0], kTestExpectations[j][1],
824            true);
825     }
826 
827     // Though the internal start time may be below zero, the exposed media time
828     // must always be >= zero.
829     EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
830 
831     Read(video, FROM_HERE, 185105, 0, true);
832     Read(video, FROM_HERE, 35941, 125000, false);
833 
834     // If things aren't working correctly, this expectation will fail because
835     // the chained ogg workaround breaks out of order timestamps.
836     Read(video, FROM_HERE, 8129, 84000, false);
837 
838     // Seek back to the beginning and repeat the test.
839     WaitableMessageLoopEvent event;
840     demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
841     event.RunAndWaitForStatus(PIPELINE_OK);
842   }
843 }
844 #endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
845 
846 // Similar to the test above, but using sfx-opus.ogg, which has a much smaller
847 // amount of discard padding and no |start_time| set on the AVStream.
TEST_F(FFmpegDemuxerTest,Read_AudioNegativeStartTimeAndOpusSfxDiscard_Sync)848 TEST_F(FFmpegDemuxerTest, Read_AudioNegativeStartTimeAndOpusSfxDiscard_Sync) {
849   CreateDemuxer("sfx-opus.ogg");
850   InitializeDemuxer();
851 
852   // Attempt a read from the video stream and run the message loop until done.
853   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
854   EXPECT_EQ(audio->audio_decoder_config().codec_delay(), 312);
855 
856   // Run the test twice with a seek in between.
857   for (int i = 0; i < 2; ++i) {
858     // TODO(sandersd): Read_AudioNegativeStartTimeAndOpusDiscardH264Mp4_Sync
859     // has the same sequence, but doesn't have a different discard padding
860     // after seeking to the start. Why is this test different?
861     Read(audio, FROM_HERE, 314, 0, true, DemuxerStream::Status::kOk,
862          i == 0 ? base::TimeDelta::FromMicroseconds(6500) : base::TimeDelta());
863     Read(audio, FROM_HERE, 244, 20000, true);
864 
865     // Though the internal start time may be below zero, the exposed media time
866     // must always be >= zero.
867     EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
868 
869     // Seek back to the beginning and repeat the test.
870     WaitableMessageLoopEvent event;
871     demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
872     event.RunAndWaitForStatus(PIPELINE_OK);
873   }
874 }
875 
TEST_F(FFmpegDemuxerTest,Read_DiscardDisabledVideoStream)876 TEST_F(FFmpegDemuxerTest, Read_DiscardDisabledVideoStream) {
877   // Verify that disabling the video stream properly marks it as AVDISCARD_ALL
878   // in FFmpegDemuxer. The AVDISCARD_ALL flag allows FFmpeg to ignore key frame
879   // requirements for the disabled stream and thus allows to select the seek
880   // position closer to the |seek_target|, resulting in less data being read
881   // from the data source.
882   // The input file bear-vp8-webvtt.webm has key video frames at 1.602s and at
883   // 2.002s. If we want to seek to 2.0s position while the video stream is
884   // enabled, then FFmpeg is forced to start reading from 1.602s, which is the
885   // earliest position guaranteed to give us key frames for all enabled streams.
886   // But when the video stream is disabled, FFmpeg can start reading from 1.987s
887   // which is earliest audio key frame before the 2.0s |seek_target|.
888   const base::TimeDelta seek_target = base::TimeDelta::FromMilliseconds(2000);
889 
890   CreateDemuxer("bear-vp8-webvtt.webm");
891   InitializeDemuxer();
892   Seek(seek_target);
893   Read(GetStream(DemuxerStream::AUDIO), FROM_HERE, 163, 1612000, true);
894   auto bytes_read_with_video_enabled = data_source_->bytes_read_for_testing();
895 
896   static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::VIDEO))
897       ->SetEnabled(false, base::TimeDelta());
898   data_source_->reset_bytes_read_for_testing();
899   Seek(seek_target);
900   Read(GetStream(DemuxerStream::AUDIO), FROM_HERE, 156, 1987000, true);
901   auto bytes_read_with_video_disabled = data_source_->bytes_read_for_testing();
902   EXPECT_LT(bytes_read_with_video_disabled, bytes_read_with_video_enabled);
903 }
904 
TEST_F(FFmpegDemuxerTest,Read_EndOfStream)905 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) {
906   // Verify that end of stream buffers are created.
907   CreateDemuxer("bear-320x240.webm");
908   InitializeDemuxer();
909   ReadUntilEndOfStream(GetStream(DemuxerStream::AUDIO));
910 }
911 
TEST_F(FFmpegDemuxerTest,Read_EndOfStream_NoDuration)912 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration) {
913   // Verify that end of stream buffers are created.
914   CreateDemuxer("bear-320x240.webm");
915   InitializeDemuxer();
916   SetDurationKnown(false);
917   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2744)));
918   ReadUntilEndOfStream(GetStream(DemuxerStream::AUDIO));
919   ReadUntilEndOfStream(GetStream(DemuxerStream::VIDEO));
920 }
921 
TEST_F(FFmpegDemuxerTest,Read_EndOfStream_NoDuration_VideoOnly)922 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration_VideoOnly) {
923   // Verify that end of stream buffers are created.
924   CreateDemuxer("bear-320x240-video-only.webm");
925   InitializeDemuxer();
926   SetDurationKnown(false);
927   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2703)));
928   ReadUntilEndOfStream(GetStream(DemuxerStream::VIDEO));
929 }
930 
TEST_F(FFmpegDemuxerTest,Read_EndOfStream_NoDuration_AudioOnly)931 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration_AudioOnly) {
932   // Verify that end of stream buffers are created.
933   CreateDemuxer("bear-320x240-audio-only.webm");
934   InitializeDemuxer();
935   SetDurationKnown(false);
936   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2744)));
937   ReadUntilEndOfStream(GetStream(DemuxerStream::AUDIO));
938 }
939 
TEST_F(FFmpegDemuxerTest,Read_EndOfStream_NoDuration_UnsupportedStream)940 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration_UnsupportedStream) {
941   // Verify that end of stream buffers are created and we don't crash
942   // if there are streams in the file that we don't support.
943   CreateDemuxer("vorbis_audio_wmv_video.mkv");
944   InitializeDemuxer();
945   SetDurationKnown(false);
946   EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(991)));
947   ReadUntilEndOfStream(GetStream(DemuxerStream::AUDIO));
948 }
949 
TEST_F(FFmpegDemuxerTest,Seek)950 TEST_F(FFmpegDemuxerTest, Seek) {
951   // We're testing that the demuxer frees all queued packets when it receives
952   // a Seek().
953   CreateDemuxer("bear-320x240.webm");
954   InitializeDemuxer();
955 
956   // Get our streams.
957   DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
958   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
959   ASSERT_TRUE(video);
960   ASSERT_TRUE(audio);
961 
962   // Read a video packet and release it.
963   Read(video, FROM_HERE, 22084, 0, true);
964 
965   // Issue a simple forward seek, which should discard queued packets.
966   WaitableMessageLoopEvent event;
967   demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
968                  event.GetPipelineStatusCB());
969   event.RunAndWaitForStatus(PIPELINE_OK);
970 
971   // Audio read #1.
972   Read(audio, FROM_HERE, 145, 803000, true);
973 
974   // Audio read #2.
975   Read(audio, FROM_HERE, 148, 826000, true);
976 
977   // Video read #1.
978   Read(video, FROM_HERE, 5425, 801000, true);
979 
980   // Video read #2.
981   Read(video, FROM_HERE, 1906, 834000, false);
982 }
983 
TEST_F(FFmpegDemuxerTest,CancelledSeek)984 TEST_F(FFmpegDemuxerTest, CancelledSeek) {
985   CreateDemuxer("bear-320x240.webm");
986   InitializeDemuxer();
987 
988   // Get our streams.
989   DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
990   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
991   ASSERT_TRUE(video);
992   ASSERT_TRUE(audio);
993 
994   // Read a video packet and release it.
995   Read(video, FROM_HERE, 22084, 0, true);
996 
997   // Issue a simple forward seek, which should discard queued packets.
998   WaitableMessageLoopEvent event;
999   demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
1000                  event.GetPipelineStatusCB());
1001   // FFmpegDemuxer does not care what the previous seek time was when canceling.
1002   demuxer_->CancelPendingSeek(base::TimeDelta::FromSeconds(12345));
1003   event.RunAndWaitForStatus(PIPELINE_OK);
1004 }
1005 
TEST_F(FFmpegDemuxerTest,Stop)1006 TEST_F(FFmpegDemuxerTest, Stop) {
1007   // Tests that calling Read() on a stopped demuxer stream immediately deletes
1008   // the callback.
1009   CreateDemuxer("bear-320x240.webm");
1010   InitializeDemuxer();
1011 
1012   // Get our stream.
1013   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
1014   ASSERT_TRUE(audio);
1015 
1016   demuxer_->Stop();
1017 
1018   // Reads after being stopped are all EOS buffers.
1019   StrictMock<base::MockCallback<DemuxerStream::ReadCB>> callback;
1020   EXPECT_CALL(callback, Run(DemuxerStream::kOk, IsEndOfStreamBuffer()));
1021 
1022   // Attempt the read...
1023   audio->Read(callback.Get());
1024   task_environment_.RunUntilIdle();
1025 
1026   // Don't let the test call Stop() again.
1027   demuxer_.reset();
1028 }
1029 
1030 // Verify that seek works properly when the WebM cues data is at the start of
1031 // the file instead of at the end.
TEST_F(FFmpegDemuxerTest,SeekWithCuesBeforeFirstCluster)1032 TEST_F(FFmpegDemuxerTest, SeekWithCuesBeforeFirstCluster) {
1033   CreateDemuxer("bear-320x240-cues-in-front.webm");
1034   InitializeDemuxer();
1035 
1036   // Get our streams.
1037   DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
1038   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
1039   ASSERT_TRUE(video);
1040   ASSERT_TRUE(audio);
1041 
1042   // Read a video packet and release it.
1043   Read(video, FROM_HERE, 22084, 0, true);
1044 
1045   // Issue a simple forward seek, which should discard queued packets.
1046   WaitableMessageLoopEvent event;
1047   demuxer_->Seek(base::TimeDelta::FromMicroseconds(2500000),
1048                  event.GetPipelineStatusCB());
1049   event.RunAndWaitForStatus(PIPELINE_OK);
1050 
1051   // Audio read #1.
1052   Read(audio, FROM_HERE, 40, 2403000, true);
1053 
1054   // Audio read #2.
1055   Read(audio, FROM_HERE, 42, 2406000, true);
1056 
1057   // Video read #1.
1058   Read(video, FROM_HERE, 5276, 2402000, true);
1059 
1060   // Video read #2.
1061   Read(video, FROM_HERE, 1740, 2436000, false);
1062 }
1063 
1064 // Ensure ID3v1 tag reading is disabled.  id3_test.mp3 has an ID3v1 tag with the
1065 // field "title" set to "sample for id3 test".
TEST_F(FFmpegDemuxerTest,NoID3TagData)1066 TEST_F(FFmpegDemuxerTest, NoID3TagData) {
1067   CreateDemuxer("id3_test.mp3");
1068   InitializeDemuxer();
1069   EXPECT_FALSE(av_dict_get(format_context()->metadata, "title", nullptr, 0));
1070 }
1071 
1072 // Ensure MP3 files with large image/video based ID3 tags demux okay.  FFmpeg
1073 // will hand us a video stream to the data which will likely be in a format we
1074 // don't accept as video; e.g. PNG.
TEST_F(FFmpegDemuxerTest,Mp3WithVideoStreamID3TagData)1075 TEST_F(FFmpegDemuxerTest, Mp3WithVideoStreamID3TagData) {
1076   CreateDemuxerWithStrictMediaLog("id3_png_test.mp3");
1077 
1078   EXPECT_MEDIA_LOG_PROPERTY(kBitrate, 1421305);
1079   EXPECT_MEDIA_LOG_PROPERTY(kStartTime, 0.0f);
1080   EXPECT_MEDIA_LOG_PROPERTY(kVideoTracks, std::vector<VideoDecoderConfig>{});
1081   EXPECT_MEDIA_LOG_PROPERTY_ANY_VALUE(kMaxDuration);
1082   EXPECT_MEDIA_LOG_PROPERTY_ANY_VALUE(kAudioTracks);
1083   EXPECT_MEDIA_LOG(SimpleCreatedFFmpegDemuxerStream("audio"));
1084   EXPECT_MEDIA_LOG(FailedToCreateValidDecoderConfigFromStream("video"));
1085 
1086   // TODO(wolenetz): Use a matcher that verifies more of the event parameters
1087   // than FoundStream. See https://crbug.com/749178.
1088   EXPECT_MEDIA_LOG(SkippingUnsupportedStream("video"));
1089   InitializeDemuxer();
1090 
1091   // Ensure the expected streams are present.
1092   EXPECT_FALSE(GetStream(DemuxerStream::VIDEO));
1093   EXPECT_TRUE(GetStream(DemuxerStream::AUDIO));
1094 }
1095 
1096 // Ensure a video with an unsupported audio track still results in the video
1097 // stream being demuxed. Because we disable the speex parser for ogg, the audio
1098 // track won't even show up to the demuxer.
1099 //
1100 // Android has no Theora support, so this test doesn't work.
1101 #if !defined(OS_ANDROID)
TEST_F(FFmpegDemuxerTest,UnsupportedAudioSupportedVideoDemux)1102 TEST_F(FFmpegDemuxerTest, UnsupportedAudioSupportedVideoDemux) {
1103   CreateDemuxerWithStrictMediaLog("speex_audio_vorbis_video.ogv");
1104 
1105   EXPECT_MEDIA_LOG_PROPERTY(kBitrate, 398289);
1106   EXPECT_MEDIA_LOG_PROPERTY(kStartTime, 0.0f);
1107   EXPECT_MEDIA_LOG_PROPERTY(kAudioTracks, std::vector<AudioDecoderConfig>{});
1108   EXPECT_MEDIA_LOG_PROPERTY_ANY_VALUE(kVideoTracks);
1109   EXPECT_MEDIA_LOG_PROPERTY_ANY_VALUE(kMaxDuration);
1110   EXPECT_MEDIA_LOG(SimpleCreatedFFmpegDemuxerStream("video"));
1111 
1112   // TODO(wolenetz): Use a matcher that verifies more of the event parameters
1113   // than FoundStream. See https://crbug.com/749178.
1114   InitializeDemuxer();
1115 
1116   // Ensure the expected streams are present.
1117   EXPECT_TRUE(GetStream(DemuxerStream::VIDEO));
1118   EXPECT_FALSE(GetStream(DemuxerStream::AUDIO));
1119 }
1120 #endif
1121 
1122 // Ensure a video with an unsupported video track still results in the audio
1123 // stream being demuxed.
TEST_F(FFmpegDemuxerTest,UnsupportedVideoSupportedAudioDemux)1124 TEST_F(FFmpegDemuxerTest, UnsupportedVideoSupportedAudioDemux) {
1125   CreateDemuxer("vorbis_audio_wmv_video.mkv");
1126   InitializeDemuxer();
1127 
1128   // Ensure the expected streams are present.
1129   EXPECT_FALSE(GetStream(DemuxerStream::VIDEO));
1130   EXPECT_TRUE(GetStream(DemuxerStream::AUDIO));
1131 }
1132 
1133 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
1134 // FFmpeg returns null data pointers when samples have zero size, leading to
1135 // mistakenly creating end of stream buffers http://crbug.com/169133
TEST_F(FFmpegDemuxerTest,MP4_ZeroStszEntry)1136 TEST_F(FFmpegDemuxerTest, MP4_ZeroStszEntry) {
1137   CreateDemuxer("bear-1280x720-zero-stsz-entry.mp4");
1138   InitializeDemuxer();
1139   ReadUntilEndOfStream(GetStream(DemuxerStream::AUDIO));
1140 }
1141 #endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
1142 
1143 class Mp3SeekFFmpegDemuxerTest
1144     : public FFmpegDemuxerTest,
1145       public testing::WithParamInterface<const char*> {};
TEST_P(Mp3SeekFFmpegDemuxerTest,TestFastSeek)1146 TEST_P(Mp3SeekFFmpegDemuxerTest, TestFastSeek) {
1147   // Init demxuer with given MP3 file parameter.
1148   CreateDemuxer(GetParam());
1149   InitializeDemuxer();
1150 
1151   // We read a bunch of bytes when we first open the file. Reset the count
1152   // here to just track the bytes read for the upcoming seek. This allows us
1153   // to use a more narrow threshold for passing the test.
1154   data_source_->reset_bytes_read_for_testing();
1155 
1156   FFmpegDemuxerStream* audio =
1157       static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::AUDIO));
1158   ASSERT_TRUE(audio);
1159 
1160   // Seek to near the end of the file
1161   WaitableMessageLoopEvent event;
1162   demuxer_->Seek(.9 * audio->duration(), event.GetPipelineStatusCB());
1163   event.RunAndWaitForStatus(PIPELINE_OK);
1164 
1165   // Verify that seeking to the end read only a small portion of the file.
1166   // Slow seeks that read sequentially up to the seek point will read too many
1167   // bytes and fail this check.
1168   int64_t file_size = 0;
1169   ASSERT_TRUE(data_source_->GetSize(&file_size));
1170   EXPECT_LT(data_source_->bytes_read_for_testing(), (file_size * .25));
1171 }
1172 
1173 // MP3s should seek quickly without sequentially reading up to the seek point.
1174 // VBR vs CBR and the presence/absence of TOC influence the seeking algorithm.
1175 // See http://crbug.com/530043 and FFmpeg flag AVFMT_FLAG_FAST_SEEK.
1176 INSTANTIATE_TEST_SUITE_P(All,
1177                          Mp3SeekFFmpegDemuxerTest,
1178                          ::testing::Values("bear-audio-10s-CBR-has-TOC.mp3",
1179                                            "bear-audio-10s-CBR-no-TOC.mp3",
1180                                            "bear-audio-10s-VBR-has-TOC.mp3",
1181                                            "bear-audio-10s-VBR-no-TOC.mp3"));
1182 
1183 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
ValidateAnnexB(DemuxerStream * stream,DemuxerStream::Status status,scoped_refptr<DecoderBuffer> buffer)1184 static void ValidateAnnexB(DemuxerStream* stream,
1185                            DemuxerStream::Status status,
1186                            scoped_refptr<DecoderBuffer> buffer) {
1187   EXPECT_EQ(status, DemuxerStream::kOk);
1188 
1189   if (buffer->end_of_stream()) {
1190     base::ThreadTaskRunnerHandle::Get()->PostTask(
1191         FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
1192     return;
1193   }
1194 
1195   std::vector<SubsampleEntry> subsamples;
1196 
1197   if (buffer->decrypt_config())
1198     subsamples = buffer->decrypt_config()->subsamples();
1199 
1200   bool is_valid =
1201       mp4::AVC::AnalyzeAnnexB(buffer->data(), buffer->data_size(), subsamples)
1202           .is_conformant.value_or(false);
1203   EXPECT_TRUE(is_valid);
1204 
1205   if (!is_valid) {
1206     LOG(ERROR) << "Buffer contains invalid Annex B data.";
1207     base::ThreadTaskRunnerHandle::Get()->PostTask(
1208         FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
1209     return;
1210   }
1211 
1212   stream->Read(base::BindOnce(&ValidateAnnexB, stream));
1213 }
1214 
TEST_F(FFmpegDemuxerTest,IsValidAnnexB)1215 TEST_F(FFmpegDemuxerTest, IsValidAnnexB) {
1216   const char* files[] = {"bear-1280x720-av_frag.mp4",
1217                          "bear-1280x720-av_with-aud-nalus_frag.mp4"};
1218 
1219   for (size_t i = 0; i < base::size(files); ++i) {
1220     DVLOG(1) << "Testing " << files[i];
1221     CreateDemuxer(files[i]);
1222     InitializeDemuxer();
1223 
1224     // Ensure the expected streams are present.
1225     DemuxerStream* stream = GetStream(DemuxerStream::VIDEO);
1226     ASSERT_TRUE(stream);
1227     stream->EnableBitstreamConverter();
1228 
1229     stream->Read(base::BindOnce(&ValidateAnnexB, stream));
1230     base::RunLoop().Run();
1231 
1232     demuxer_->Stop();
1233     demuxer_.reset();
1234     data_source_.reset();
1235   }
1236 }
1237 
TEST_F(FFmpegDemuxerTest,Rotate_Metadata_0)1238 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_0) {
1239   CreateDemuxer("bear_rotate_0.mp4");
1240   InitializeDemuxer();
1241 
1242   DemuxerStream* stream = GetStream(DemuxerStream::VIDEO);
1243   ASSERT_TRUE(stream);
1244 
1245   const VideoDecoderConfig& video_config = stream->video_decoder_config();
1246   ASSERT_EQ(VIDEO_ROTATION_0, video_config.video_transformation().rotation);
1247 }
1248 
TEST_F(FFmpegDemuxerTest,Rotate_Metadata_90)1249 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_90) {
1250   CreateDemuxer("bear_rotate_90.mp4");
1251   InitializeDemuxer();
1252 
1253   DemuxerStream* stream = GetStream(DemuxerStream::VIDEO);
1254   ASSERT_TRUE(stream);
1255 
1256   const VideoDecoderConfig& video_config = stream->video_decoder_config();
1257   ASSERT_EQ(VIDEO_ROTATION_90, video_config.video_transformation().rotation);
1258 }
1259 
TEST_F(FFmpegDemuxerTest,Rotate_Metadata_180)1260 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_180) {
1261   CreateDemuxer("bear_rotate_180.mp4");
1262   InitializeDemuxer();
1263 
1264   DemuxerStream* stream = GetStream(DemuxerStream::VIDEO);
1265   ASSERT_TRUE(stream);
1266 
1267   const VideoDecoderConfig& video_config = stream->video_decoder_config();
1268   ASSERT_EQ(VIDEO_ROTATION_180, video_config.video_transformation().rotation);
1269 }
1270 
TEST_F(FFmpegDemuxerTest,Rotate_Metadata_270)1271 TEST_F(FFmpegDemuxerTest, Rotate_Metadata_270) {
1272   CreateDemuxer("bear_rotate_270.mp4");
1273   InitializeDemuxer();
1274 
1275   DemuxerStream* stream = GetStream(DemuxerStream::VIDEO);
1276   ASSERT_TRUE(stream);
1277 
1278   const VideoDecoderConfig& video_config = stream->video_decoder_config();
1279   ASSERT_EQ(VIDEO_ROTATION_270, video_config.video_transformation().rotation);
1280 }
1281 
TEST_F(FFmpegDemuxerTest,NaturalSizeWithoutPASP)1282 TEST_F(FFmpegDemuxerTest, NaturalSizeWithoutPASP) {
1283   CreateDemuxer("bear-640x360-non_square_pixel-without_pasp.mp4");
1284   InitializeDemuxer();
1285 
1286   DemuxerStream* stream = GetStream(DemuxerStream::VIDEO);
1287   ASSERT_TRUE(stream);
1288 
1289   const VideoDecoderConfig& video_config = stream->video_decoder_config();
1290   EXPECT_EQ(gfx::Size(639, 360), video_config.natural_size());
1291 }
1292 
TEST_F(FFmpegDemuxerTest,NaturalSizeWithPASP)1293 TEST_F(FFmpegDemuxerTest, NaturalSizeWithPASP) {
1294   CreateDemuxer("bear-640x360-non_square_pixel-with_pasp.mp4");
1295   InitializeDemuxer();
1296 
1297   DemuxerStream* stream = GetStream(DemuxerStream::VIDEO);
1298   ASSERT_TRUE(stream);
1299 
1300   const VideoDecoderConfig& video_config = stream->video_decoder_config();
1301   EXPECT_EQ(gfx::Size(639, 360), video_config.natural_size());
1302 }
1303 
TEST_F(FFmpegDemuxerTest,HEVC_in_MP4_container)1304 TEST_F(FFmpegDemuxerTest, HEVC_in_MP4_container) {
1305   CreateDemuxer("bear-hevc-frag.mp4");
1306 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
1307   // HEVC is not supported by default media platform. Embedders who add support
1308   // must declare it via MediaClient.
1309   MockMediaClient media_client;
1310   SetMediaClient(&media_client);
1311 
1312   VideoColorSpace color_space(VideoColorSpace::PrimaryID::SMPTE170M,
1313                               VideoColorSpace::TransferID::SMPTE170M,
1314                               VideoColorSpace::MatrixID::SMPTE170M,
1315                               gfx::ColorSpace::RangeID::LIMITED);
1316   VideoType hevc_type = {VideoCodec::kCodecHEVC,
1317                          VideoCodecProfile::HEVCPROFILE_MAIN, 10, color_space};
1318   EXPECT_CALL(media_client, IsSupportedVideoType(Eq(hevc_type)))
1319       .WillRepeatedly(Return(true));
1320 
1321   InitializeDemuxer();
1322 
1323   DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
1324   ASSERT_TRUE(video);
1325 
1326   Read(video, FROM_HERE, 3569, 66733, true);
1327   Read(video, FROM_HERE, 1042, 200200, false);
1328 
1329   SetMediaClient(nullptr);
1330 #else
1331   InitializeDemuxerAndExpectPipelineStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
1332 #endif
1333 }
1334 
TEST_F(FFmpegDemuxerTest,Read_AC3_Audio)1335 TEST_F(FFmpegDemuxerTest, Read_AC3_Audio) {
1336   CreateDemuxer("bear-ac3-only-frag.mp4");
1337 #if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
1338   // AC3 is not supported by default media platform. Embedders who add support
1339   // must declare it via MediaClient.
1340   MockMediaClient media_client;
1341   SetMediaClient(&media_client);
1342 
1343   AudioType ac3_type = {AudioCodec::kCodecAC3};
1344   EXPECT_CALL(media_client, IsSupportedAudioType(Eq(ac3_type)))
1345       .WillRepeatedly(Return(true));
1346 
1347   InitializeDemuxer();
1348 
1349   // Attempt a read from the audio stream and run the message loop until done.
1350   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
1351 
1352   // Read the first two frames and check that we are getting expected data
1353   Read(audio, FROM_HERE, 834, 0, true);
1354   Read(audio, FROM_HERE, 836, 34830, true);
1355 
1356   SetMediaClient(nullptr);
1357 #else
1358   InitializeDemuxerAndExpectPipelineStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
1359 #endif
1360 }
1361 
TEST_F(FFmpegDemuxerTest,Read_EAC3_Audio)1362 TEST_F(FFmpegDemuxerTest, Read_EAC3_Audio) {
1363   CreateDemuxer("bear-eac3-only-frag.mp4");
1364 #if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
1365   // EAC3 is not supported by default media platform. Embedders who add support
1366   // must declare it via MediaClient.
1367   MockMediaClient media_client;
1368   SetMediaClient(&media_client);
1369 
1370   AudioType eac3_type = {AudioCodec::kCodecEAC3};
1371   EXPECT_CALL(media_client, IsSupportedAudioType(Eq(eac3_type)))
1372       .WillRepeatedly(Return(true));
1373 
1374   InitializeDemuxer();
1375 
1376   // Attempt a read from the audio stream and run the message loop until done.
1377   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
1378 
1379   // Read the first two frames and check that we are getting expected data
1380   Read(audio, FROM_HERE, 870, 0, true);
1381   Read(audio, FROM_HERE, 872, 34830, true);
1382 
1383   SetMediaClient(nullptr);
1384 #else
1385   InitializeDemuxerAndExpectPipelineStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
1386 #endif
1387 }
1388 
TEST_F(FFmpegDemuxerTest,Read_Mp4_Media_Track_Info)1389 TEST_F(FFmpegDemuxerTest, Read_Mp4_Media_Track_Info) {
1390   CreateDemuxer("bear.mp4");
1391   InitializeDemuxer();
1392 
1393   EXPECT_EQ(media_tracks_->tracks().size(), 2u);
1394 
1395   const MediaTrack& audio_track = *(media_tracks_->tracks()[1]);
1396   EXPECT_EQ(audio_track.type(), MediaTrack::Audio);
1397   EXPECT_EQ(audio_track.bytestream_track_id(), 2);
1398   EXPECT_EQ(audio_track.kind().value(), "main");
1399   EXPECT_EQ(audio_track.label().value(), "SoundHandler");
1400   EXPECT_EQ(audio_track.language().value(), "und");
1401 
1402   const MediaTrack& video_track = *(media_tracks_->tracks()[0]);
1403   EXPECT_EQ(video_track.type(), MediaTrack::Video);
1404   EXPECT_EQ(video_track.bytestream_track_id(), 1);
1405   EXPECT_EQ(video_track.kind().value(), "main");
1406   EXPECT_EQ(video_track.label().value(), "VideoHandler");
1407   EXPECT_EQ(video_track.language().value(), "und");
1408 }
1409 
TEST_F(FFmpegDemuxerTest,Read_Mp4_Multiple_Tracks)1410 TEST_F(FFmpegDemuxerTest, Read_Mp4_Multiple_Tracks) {
1411   CreateDemuxer("bbb-320x240-2video-2audio.mp4");
1412   InitializeDemuxer();
1413 
1414   EXPECT_EQ(media_tracks_->tracks().size(), 4u);
1415 
1416   const MediaTrack& video_track = *(media_tracks_->tracks()[0]);
1417   EXPECT_EQ(video_track.type(), MediaTrack::Video);
1418   EXPECT_EQ(video_track.bytestream_track_id(), 1);
1419   EXPECT_EQ(video_track.kind().value(), "main");
1420   EXPECT_EQ(video_track.label().value(), "VideoHandler");
1421   EXPECT_EQ(video_track.language().value(), "und");
1422 
1423   const MediaTrack& audio_track = *(media_tracks_->tracks()[1]);
1424   EXPECT_EQ(audio_track.type(), MediaTrack::Audio);
1425   EXPECT_EQ(audio_track.bytestream_track_id(), 2);
1426   EXPECT_EQ(audio_track.kind().value(), "main");
1427   EXPECT_EQ(audio_track.label().value(), "SoundHandler");
1428   EXPECT_EQ(audio_track.language().value(), "und");
1429 
1430   const MediaTrack& video_track2 = *(media_tracks_->tracks()[2]);
1431   EXPECT_EQ(video_track2.type(), MediaTrack::Video);
1432   EXPECT_EQ(video_track2.bytestream_track_id(), 3);
1433   EXPECT_EQ(video_track2.kind().value(), "main");
1434   EXPECT_EQ(video_track2.label().value(), "VideoHandler");
1435   EXPECT_EQ(video_track2.language().value(), "und");
1436 
1437   const MediaTrack& audio_track2 = *(media_tracks_->tracks()[3]);
1438   EXPECT_EQ(audio_track2.type(), MediaTrack::Audio);
1439   EXPECT_EQ(audio_track2.bytestream_track_id(), 4);
1440   EXPECT_EQ(audio_track2.kind().value(), "main");
1441   EXPECT_EQ(audio_track2.label().value(), "SoundHandler");
1442   EXPECT_EQ(audio_track2.language().value(), "und");
1443 }
1444 
TEST_F(FFmpegDemuxerTest,Read_Mp4_Crbug657437)1445 TEST_F(FFmpegDemuxerTest, Read_Mp4_Crbug657437) {
1446   CreateDemuxer("crbug657437.mp4");
1447   InitializeDemuxer();
1448 }
1449 
TEST_F(FFmpegDemuxerTest,XHE_AAC)1450 TEST_F(FFmpegDemuxerTest, XHE_AAC) {
1451   CreateDemuxer("noise-xhe-aac.mp4");
1452   InitializeDemuxer();
1453 
1454   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
1455   ASSERT_TRUE(audio);
1456 
1457   EXPECT_EQ(audio->audio_decoder_config().profile(),
1458             AudioCodecProfile::kXHE_AAC);
1459 
1460   // ADTS bitstream conversion shouldn't be enabled for xHE-AAC since it can't
1461   // be represented with only two bits for the profile.
1462   audio->EnableBitstreamConverter();
1463   EXPECT_FALSE(HasBitstreamConverter(audio));
1464 
1465   // Even though FFmpeg can't decode xHE-AAC content, it should be demuxing it
1466   // just fine.
1467   Read(audio, FROM_HERE, 1796, 0, true);
1468 }
1469 
1470 #endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
1471 
TEST_F(FFmpegDemuxerTest,Read_Webm_Multiple_Tracks)1472 TEST_F(FFmpegDemuxerTest, Read_Webm_Multiple_Tracks) {
1473   CreateDemuxer("multitrack-3video-2audio.webm");
1474   InitializeDemuxer();
1475 
1476   EXPECT_EQ(media_tracks_->tracks().size(), 5u);
1477 
1478   const MediaTrack& video_track1 = *(media_tracks_->tracks()[0]);
1479   EXPECT_EQ(video_track1.type(), MediaTrack::Video);
1480   EXPECT_EQ(video_track1.bytestream_track_id(), 1);
1481 
1482   const MediaTrack& video_track2 = *(media_tracks_->tracks()[1]);
1483   EXPECT_EQ(video_track2.type(), MediaTrack::Video);
1484   EXPECT_EQ(video_track2.bytestream_track_id(), 2);
1485 
1486   const MediaTrack& video_track3 = *(media_tracks_->tracks()[2]);
1487   EXPECT_EQ(video_track3.type(), MediaTrack::Video);
1488   EXPECT_EQ(video_track3.bytestream_track_id(), 3);
1489 
1490   const MediaTrack& audio_track1 = *(media_tracks_->tracks()[3]);
1491   EXPECT_EQ(audio_track1.type(), MediaTrack::Audio);
1492   EXPECT_EQ(audio_track1.bytestream_track_id(), 4);
1493 
1494   const MediaTrack& audio_track2 = *(media_tracks_->tracks()[4]);
1495   EXPECT_EQ(audio_track2.type(), MediaTrack::Audio);
1496   EXPECT_EQ(audio_track2.bytestream_track_id(), 5);
1497 }
1498 
TEST_F(FFmpegDemuxerTest,Read_Webm_Media_Track_Info)1499 TEST_F(FFmpegDemuxerTest, Read_Webm_Media_Track_Info) {
1500   CreateDemuxer("bear.webm");
1501   InitializeDemuxer();
1502 
1503   EXPECT_EQ(media_tracks_->tracks().size(), 2u);
1504 
1505   const MediaTrack& video_track = *(media_tracks_->tracks()[0]);
1506   EXPECT_EQ(video_track.type(), MediaTrack::Video);
1507   EXPECT_EQ(video_track.bytestream_track_id(), 1);
1508   EXPECT_EQ(video_track.kind().value(), "main");
1509   EXPECT_EQ(video_track.label().value(), "");
1510   EXPECT_EQ(video_track.language().value(), "");
1511 
1512   const MediaTrack& audio_track = *(media_tracks_->tracks()[1]);
1513   EXPECT_EQ(audio_track.type(), MediaTrack::Audio);
1514   EXPECT_EQ(audio_track.bytestream_track_id(), 2);
1515   EXPECT_EQ(audio_track.kind().value(), "main");
1516   EXPECT_EQ(audio_track.label().value(), "");
1517   EXPECT_EQ(audio_track.language().value(), "");
1518 }
1519 
1520 // UTCDateToTime_* tests here assume FFmpegDemuxer's ExtractTimelineOffset
1521 // helper uses base::Time::FromUTCString() for conversion.
TEST_F(FFmpegDemuxerTest,UTCDateToTime_Valid)1522 TEST_F(FFmpegDemuxerTest, UTCDateToTime_Valid) {
1523   base::Time result;
1524   EXPECT_TRUE(
1525       base::Time::FromUTCString("2012-11-10T12:34:56.987654Z", &result));
1526 
1527   base::Time::Exploded exploded;
1528   result.UTCExplode(&exploded);
1529   EXPECT_TRUE(exploded.HasValidValues());
1530   EXPECT_EQ(2012, exploded.year);
1531   EXPECT_EQ(11, exploded.month);
1532   EXPECT_EQ(6, exploded.day_of_week);
1533   EXPECT_EQ(10, exploded.day_of_month);
1534   EXPECT_EQ(12, exploded.hour);
1535   EXPECT_EQ(34, exploded.minute);
1536   EXPECT_EQ(56, exploded.second);
1537   EXPECT_EQ(987, exploded.millisecond);
1538 
1539   // base::Time exploding operations round fractional milliseconds down, so
1540   // verify fractional milliseconds using a base::TimeDelta.
1541   base::Time without_fractional_ms;
1542   EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &without_fractional_ms));
1543   base::TimeDelta delta = result - without_fractional_ms;
1544   EXPECT_EQ(654, delta.InMicroseconds());
1545 }
1546 
TEST_F(FFmpegDemuxerTest,UTCDateToTime_Invalid)1547 TEST_F(FFmpegDemuxerTest, UTCDateToTime_Invalid) {
1548   const char* invalid_date_strings[] = {
1549       "",
1550       "12:34:56",
1551       "-- ::",
1552       "2012-11- 12:34:56",
1553       "2012--10 12:34:56",
1554       "-11-10 12:34:56",
1555       "2012-11 12:34:56",
1556       "ABCD-11-10 12:34:56",
1557       "2012-EF-10 12:34:56",
1558       "2012-11-GH 12:34:56",
1559       "2012-11-1012:34:56",
1560   };
1561 
1562   for (size_t i = 0; i < base::size(invalid_date_strings); ++i) {
1563     const char* date_string = invalid_date_strings[i];
1564     base::Time result;
1565     EXPECT_FALSE(base::Time::FromUTCString(date_string, &result))
1566         << "date_string '" << date_string << "'";
1567   }
1568 }
1569 
VerifyFlacStream(DemuxerStream * stream,int expected_bits_per_channel,ChannelLayout expected_channel_layout,int expected_samples_per_second,SampleFormat expected_sample_format)1570 static void VerifyFlacStream(DemuxerStream* stream,
1571                              int expected_bits_per_channel,
1572                              ChannelLayout expected_channel_layout,
1573                              int expected_samples_per_second,
1574                              SampleFormat expected_sample_format) {
1575   ASSERT_TRUE(stream);
1576   EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
1577 
1578   const AudioDecoderConfig& audio_config = stream->audio_decoder_config();
1579   EXPECT_EQ(kCodecFLAC, audio_config.codec());
1580   EXPECT_EQ(expected_bits_per_channel, audio_config.bits_per_channel());
1581   EXPECT_EQ(expected_channel_layout, audio_config.channel_layout());
1582   EXPECT_EQ(expected_samples_per_second, audio_config.samples_per_second());
1583   EXPECT_EQ(expected_sample_format, audio_config.sample_format());
1584 }
1585 
TEST_F(FFmpegDemuxerTest,Read_Flac)1586 TEST_F(FFmpegDemuxerTest, Read_Flac) {
1587   CreateDemuxer("sfx.flac");
1588   InitializeDemuxer();
1589 
1590   // Video stream should not be present.
1591   EXPECT_EQ(nullptr, GetStream(DemuxerStream::VIDEO));
1592 
1593   VerifyFlacStream(GetStream(DemuxerStream::AUDIO), 32, CHANNEL_LAYOUT_MONO,
1594                    44100, kSampleFormatS32);
1595 }
1596 
TEST_F(FFmpegDemuxerTest,Read_Flac_Mp4)1597 TEST_F(FFmpegDemuxerTest, Read_Flac_Mp4) {
1598   CreateDemuxer("bear-flac.mp4");
1599   InitializeDemuxer();
1600 
1601   // Video stream should not be present.
1602   EXPECT_EQ(nullptr, GetStream(DemuxerStream::VIDEO));
1603 
1604   VerifyFlacStream(GetStream(DemuxerStream::AUDIO), 32, CHANNEL_LAYOUT_STEREO,
1605                    44100, kSampleFormatS32);
1606 }
1607 
TEST_F(FFmpegDemuxerTest,Read_Flac_192kHz_Mp4)1608 TEST_F(FFmpegDemuxerTest, Read_Flac_192kHz_Mp4) {
1609   CreateDemuxer("bear-flac-192kHz.mp4");
1610   InitializeDemuxer();
1611 
1612   // Video stream should not be present.
1613   EXPECT_EQ(nullptr, GetStream(DemuxerStream::VIDEO));
1614 
1615   VerifyFlacStream(GetStream(DemuxerStream::AUDIO), 32, CHANNEL_LAYOUT_STEREO,
1616                    192000, kSampleFormatS32);
1617 }
1618 
1619 // Verify that FFmpeg demuxer falls back to choosing disabled streams for
1620 // seeking if there's no suitable enabled stream found.
TEST_F(FFmpegDemuxerTest,Seek_FallbackToDisabledVideoStream)1621 TEST_F(FFmpegDemuxerTest, Seek_FallbackToDisabledVideoStream) {
1622   // Input has only video stream, no audio.
1623   CreateDemuxer("bear-320x240-video-only.webm");
1624   InitializeDemuxer();
1625   EXPECT_EQ(nullptr, GetStream(DemuxerStream::AUDIO));
1626   FFmpegDemuxerStream* vstream =
1627       static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::VIDEO));
1628   EXPECT_NE(nullptr, vstream);
1629   EXPECT_EQ(vstream, preferred_seeking_stream(base::TimeDelta()));
1630 
1631   // Now pretend that video stream got disabled, e.g. due to current tab going
1632   // into background.
1633   vstream->SetEnabled(false, base::TimeDelta());
1634   // Since there's no other enabled streams, the preferred seeking stream should
1635   // still be the video stream.
1636   EXPECT_EQ(vstream, preferred_seeking_stream(base::TimeDelta()));
1637 }
1638 
TEST_F(FFmpegDemuxerTest,Seek_FallbackToDisabledAudioStream)1639 TEST_F(FFmpegDemuxerTest, Seek_FallbackToDisabledAudioStream) {
1640   CreateDemuxer("bear-320x240-audio-only.webm");
1641   InitializeDemuxer();
1642   FFmpegDemuxerStream* astream =
1643       static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::AUDIO));
1644   EXPECT_NE(nullptr, astream);
1645   EXPECT_EQ(nullptr, GetStream(DemuxerStream::VIDEO));
1646   EXPECT_EQ(astream, preferred_seeking_stream(base::TimeDelta()));
1647 
1648   // Now pretend that audio stream got disabled.
1649   astream->SetEnabled(false, base::TimeDelta());
1650   // Since there's no other enabled streams, the preferred seeking stream should
1651   // still be the audio stream.
1652   EXPECT_EQ(astream, preferred_seeking_stream(base::TimeDelta()));
1653 }
1654 
1655 namespace {
QuitLoop(base::Closure quit_closure,DemuxerStream::Type type,const std::vector<DemuxerStream * > & streams)1656 void QuitLoop(base::Closure quit_closure,
1657               DemuxerStream::Type type,
1658               const std::vector<DemuxerStream*>& streams) {
1659   quit_closure.Run();
1660 }
1661 
DisableAndEnableDemuxerTracks(FFmpegDemuxer * demuxer,base::test::TaskEnvironment * task_environment)1662 void DisableAndEnableDemuxerTracks(
1663     FFmpegDemuxer* demuxer,
1664     base::test::TaskEnvironment* task_environment) {
1665   base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1666                             base::WaitableEvent::InitialState::NOT_SIGNALED);
1667   std::vector<MediaTrack::Id> audio_tracks;
1668   std::vector<MediaTrack::Id> video_tracks;
1669 
1670   base::RunLoop disable_video;
1671   demuxer->OnSelectedVideoTrackChanged(
1672       video_tracks, base::TimeDelta(),
1673       base::BindOnce(QuitLoop, disable_video.QuitClosure()));
1674   disable_video.Run();
1675 
1676   base::RunLoop disable_audio;
1677   demuxer->OnEnabledAudioTracksChanged(
1678       audio_tracks, base::TimeDelta(),
1679       base::BindOnce(QuitLoop, disable_audio.QuitClosure()));
1680   disable_audio.Run();
1681 
1682   base::RunLoop enable_video;
1683   video_tracks.push_back(MediaTrack::Id("1"));
1684   demuxer->OnSelectedVideoTrackChanged(
1685       video_tracks, base::TimeDelta(),
1686       base::BindOnce(QuitLoop, enable_video.QuitClosure()));
1687   enable_video.Run();
1688 
1689   base::RunLoop enable_audio;
1690   audio_tracks.push_back(MediaTrack::Id("2"));
1691   demuxer->OnEnabledAudioTracksChanged(
1692       audio_tracks, base::TimeDelta(),
1693       base::BindOnce(QuitLoop, enable_audio.QuitClosure()));
1694   enable_audio.Run();
1695 
1696   task_environment->RunUntilIdle();
1697 }
1698 
OnReadDoneExpectEos(DemuxerStream::Status status,const scoped_refptr<DecoderBuffer> buffer)1699 void OnReadDoneExpectEos(DemuxerStream::Status status,
1700                          const scoped_refptr<DecoderBuffer> buffer) {
1701   EXPECT_EQ(status, DemuxerStream::kOk);
1702   EXPECT_TRUE(buffer->end_of_stream());
1703 }
1704 }  // namespace
1705 
TEST_F(FFmpegDemuxerTest,StreamStatusNotifications)1706 TEST_F(FFmpegDemuxerTest, StreamStatusNotifications) {
1707   CreateDemuxer("bear-320x240.webm");
1708   InitializeDemuxer();
1709   FFmpegDemuxerStream* audio_stream =
1710       static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::AUDIO));
1711   EXPECT_NE(nullptr, audio_stream);
1712   FFmpegDemuxerStream* video_stream =
1713       static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::VIDEO));
1714   EXPECT_NE(nullptr, video_stream);
1715 
1716   // Verify stream status notifications delivery without pending read first.
1717   DisableAndEnableDemuxerTracks(demuxer_.get(), &task_environment_);
1718 
1719   // Verify that stream notifications are delivered properly when stream status
1720   // changes with a pending read. Call FlushBuffers before reading, to ensure
1721   // there is no buffers ready to be returned by the Read right away, thus
1722   // ensuring that status changes occur while an async read is pending.
1723 
1724   audio_stream->FlushBuffers(true);
1725   video_stream->FlushBuffers(true);
1726   audio_stream->Read(base::BindOnce(&OnReadDoneExpectEos));
1727   video_stream->Read(base::BindOnce(&OnReadDoneExpectEos));
1728 
1729   DisableAndEnableDemuxerTracks(demuxer_.get(), &task_environment_);
1730 }
1731 
TEST_F(FFmpegDemuxerTest,MultitrackMemoryUsage)1732 TEST_F(FFmpegDemuxerTest, MultitrackMemoryUsage) {
1733   CreateDemuxer("multitrack-3video-2audio.webm");
1734   InitializeDemuxer();
1735 
1736   DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
1737 
1738   // Read from the audio stream to make sure FFmpegDemuxer buffers data for all
1739   // streams with available capacity, i.e all enabled streams. By default only
1740   // the first audio and the first video stream are enabled, so the memory usage
1741   // shouldn't be too high.
1742   Read(audio, FROM_HERE, 304, 0, true);
1743   EXPECT_EQ(22134, demuxer_->GetMemoryUsage());
1744 
1745   // Now enable all demuxer streams in the file and perform another read, this
1746   // will buffer the data for additional streams and memory usage will increase.
1747   std::vector<DemuxerStream*> streams = demuxer_->GetAllStreams();
1748   for (auto* stream : streams) {
1749     static_cast<FFmpegDemuxerStream*>(stream)->SetEnabled(true,
1750                                                           base::TimeDelta());
1751   }
1752   Read(audio, FROM_HERE, 166, 21000, true);
1753 
1754   // With newly enabled demuxer streams the amount of memory used by the demuxer
1755   // is much higher.
1756   EXPECT_EQ(156011, demuxer_->GetMemoryUsage());
1757 }
1758 
TEST_F(FFmpegDemuxerTest,SeekOnVideoTrackChangeWontSeekIfEmpty)1759 TEST_F(FFmpegDemuxerTest, SeekOnVideoTrackChangeWontSeekIfEmpty) {
1760   // We only care about video tracks.
1761   CreateDemuxer("bear-320x240-video-only.webm");
1762   InitializeDemuxer();
1763   std::vector<DemuxerStream*> streams;
1764   base::RunLoop loop;
1765 
1766   SeekOnVideoTrackChangePassthrough(
1767       base::TimeDelta(), base::BindOnce(QuitLoop, loop.QuitClosure()),
1768       DemuxerStream::VIDEO, streams);
1769 
1770   loop.Run();
1771 }
1772 
1773 }  // namespace media
1774