roll skia to 4057
[chromium-blink-merge.git] / media / filters / ffmpeg_demuxer_unittest.cc
blob2c223cf538323cbf0b398ab357ff028beff8b385
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.
5 #include <algorithm>
6 #include <deque>
7 #include <string>
9 #include "base/file_path.h"
10 #include "base/file_util.h"
11 #include "base/path_service.h"
12 #include "base/threading/thread.h"
13 #include "media/base/filters.h"
14 #include "media/base/mock_callback.h"
15 #include "media/base/mock_demuxer_host.h"
16 #include "media/base/mock_filters.h"
17 #include "media/base/mock_reader.h"
18 #include "media/ffmpeg/ffmpeg_common.h"
19 #include "media/filters/ffmpeg_demuxer.h"
20 #include "media/filters/file_data_source.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using ::testing::AnyNumber;
24 using ::testing::DoAll;
25 using ::testing::InSequence;
26 using ::testing::Invoke;
27 using ::testing::NotNull;
28 using ::testing::Return;
29 using ::testing::SaveArg;
30 using ::testing::SetArgPointee;
31 using ::testing::StrictMock;
32 using ::testing::WithArgs;
33 using ::testing::_;
35 namespace media {
37 MATCHER(IsEndOfStreamBuffer,
38 std::string(negation ? "isn't" : "is") + " end of stream") {
39 return arg->IsEndOfStream();
42 // Fixture class to facilitate writing tests. Takes care of setting up the
43 // FFmpeg, pipeline and filter host mocks.
44 class FFmpegDemuxerTest : public testing::Test {
45 protected:
46 FFmpegDemuxerTest() {}
48 virtual ~FFmpegDemuxerTest() {
49 if (demuxer_) {
50 // Call Stop() to shut down internal threads.
51 demuxer_->Stop(NewExpectedClosure());
54 // Finish up any remaining tasks.
55 message_loop_.RunAllPending();
56 // Release the reference to the demuxer.
57 demuxer_ = NULL;
60 void CreateDemuxer(const std::string& name) {
61 CreateDemuxer(name, false);
64 void CreateDemuxer(const std::string& name, bool disable_file_size) {
65 CHECK(!demuxer_);
67 EXPECT_CALL(host_, SetTotalBytes(_)).Times(AnyNumber());
68 EXPECT_CALL(host_, SetBufferedBytes(_)).Times(AnyNumber());
69 EXPECT_CALL(host_, SetCurrentReadPosition(_))
70 .WillRepeatedly(SaveArg<0>(&current_read_position_));
72 CreateDataSource(name, disable_file_size);
73 demuxer_ = new FFmpegDemuxer(&message_loop_, data_source_);
76 MOCK_METHOD1(CheckPoint, void(int v));
78 void InitializeDemuxer() {
79 EXPECT_CALL(host_, SetDuration(_));
80 demuxer_->Initialize(&host_, NewExpectedStatusCB(PIPELINE_OK));
81 message_loop_.RunAllPending();
84 // Verifies that |buffer| has a specific |size| and |timestamp|.
85 // |location| simply indicates where the call to this function was made.
86 // This makes it easier to track down where test failures occur.
87 void ValidateBuffer(const tracked_objects::Location& location,
88 const scoped_refptr<Buffer>& buffer,
89 int size, int64 timestampInMicroseconds) {
90 std::string location_str;
91 location.Write(true, false, &location_str);
92 location_str += "\n";
93 SCOPED_TRACE(location_str);
94 EXPECT_TRUE(buffer.get() != NULL);
95 EXPECT_EQ(size, buffer->GetDataSize());
96 EXPECT_EQ(base::TimeDelta::FromMicroseconds(timestampInMicroseconds),
97 buffer->GetTimestamp());
100 // Accessor to demuxer internals.
101 void set_duration_known(bool duration_known) {
102 demuxer_->duration_known_ = duration_known;
105 // Creates a data source with the given |file_name|. If |disable_file_size|
106 // then the data source pretends it does not know the file size (e.g. often
107 // when streaming video). Uses this data source to initialize a demuxer, then
108 // returns true if the bitrate is valid, false otherwise.
109 bool VideoHasValidBitrate(
110 const std::string& file_name, bool disable_file_size) {
111 CreateDemuxer(file_name, disable_file_size);
112 InitializeDemuxer();
113 return demuxer_->GetBitrate() > 0;
116 bool IsStreamStopped(DemuxerStream::Type type) {
117 DemuxerStream* stream = demuxer_->GetStream(type);
118 CHECK(stream);
119 return static_cast<FFmpegDemuxerStream*>(stream)->stopped_;
122 // Fixture members.
123 scoped_refptr<FileDataSource> data_source_;
124 scoped_refptr<FFmpegDemuxer> demuxer_;
125 StrictMock<MockDemuxerHost> host_;
126 MessageLoop message_loop_;
128 int64 current_read_position_;
130 AVFormatContext* format_context() {
131 return demuxer_->format_context_;
134 void ReadUntilEndOfStream() {
135 // We should expect an end of stream buffer.
136 scoped_refptr<DemuxerStream> audio =
137 demuxer_->GetStream(DemuxerStream::AUDIO);
138 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
140 bool got_eos_buffer = false;
141 const int kMaxBuffers = 170;
142 for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) {
143 reader->Read(audio);
144 message_loop_.RunAllPending();
145 EXPECT_TRUE(reader->called());
146 ASSERT_TRUE(reader->buffer());
148 if (reader->buffer()->IsEndOfStream()) {
149 got_eos_buffer = true;
150 EXPECT_TRUE(reader->buffer()->GetData() == NULL);
151 EXPECT_EQ(0, reader->buffer()->GetDataSize());
152 break;
155 EXPECT_TRUE(reader->buffer()->GetData() != NULL);
156 EXPECT_GT(reader->buffer()->GetDataSize(), 0);
157 reader->Reset();
160 EXPECT_TRUE(got_eos_buffer);
163 private:
164 void CreateDataSource(const std::string& name, bool disable_file_size) {
165 CHECK(!data_source_);
167 FilePath file_path;
168 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
170 file_path = file_path.Append(FILE_PATH_LITERAL("media"))
171 .Append(FILE_PATH_LITERAL("test"))
172 .Append(FILE_PATH_LITERAL("data"))
173 .AppendASCII(name);
175 data_source_ = new FileDataSource(disable_file_size);
176 EXPECT_EQ(PIPELINE_OK, data_source_->Initialize(file_path.MaybeAsASCII()));
179 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest);
182 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) {
183 // Simulate avformat_open_input() failing.
184 CreateDemuxer("ten_byte_file"),
185 EXPECT_CALL(host_, SetCurrentReadPosition(_));
186 demuxer_->Initialize(
187 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
189 message_loop_.RunAllPending();
192 // TODO(acolwell): Uncomment this test when we discover a file that passes
193 // avformat_open_input(), but has avformat_find_stream_info() fail.
195 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) {
196 // CreateDemuxer("find_stream_info_fail.webm");
197 // demuxer_->Initialize(
198 // &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE));
199 // message_loop_.RunAllPending();
202 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) {
203 // Open a file with no streams whatsoever.
204 CreateDemuxer("no_streams.webm");
205 EXPECT_CALL(host_, SetCurrentReadPosition(_));
206 demuxer_->Initialize(
207 &host_, NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS));
208 message_loop_.RunAllPending();
211 TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) {
212 // Open a file containing streams but none of which are audio/video streams.
213 CreateDemuxer("no_audio_video.webm");
214 demuxer_->Initialize(
215 &host_, NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS));
216 message_loop_.RunAllPending();
219 TEST_F(FFmpegDemuxerTest, Initialize_Successful) {
220 CreateDemuxer("bear-320x240.webm");
221 InitializeDemuxer();
223 // Video stream should be present.
224 scoped_refptr<DemuxerStream> stream =
225 demuxer_->GetStream(DemuxerStream::VIDEO);
226 ASSERT_TRUE(stream);
227 EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
229 const VideoDecoderConfig& video_config = stream->video_decoder_config();
230 EXPECT_EQ(kCodecVP8, video_config.codec());
231 EXPECT_EQ(VideoFrame::YV12, video_config.format());
232 EXPECT_EQ(320, video_config.coded_size().width());
233 EXPECT_EQ(240, video_config.coded_size().height());
234 EXPECT_EQ(0, video_config.visible_rect().x());
235 EXPECT_EQ(0, video_config.visible_rect().y());
236 EXPECT_EQ(320, video_config.visible_rect().width());
237 EXPECT_EQ(240, video_config.visible_rect().height());
238 EXPECT_EQ(30000, video_config.frame_rate_numerator());
239 EXPECT_EQ(1001, video_config.frame_rate_denominator());
240 EXPECT_EQ(1, video_config.aspect_ratio_numerator());
241 EXPECT_EQ(1, video_config.aspect_ratio_denominator());
242 EXPECT_FALSE(video_config.extra_data());
243 EXPECT_EQ(0u, video_config.extra_data_size());
245 // Audio stream should be present.
246 stream = demuxer_->GetStream(DemuxerStream::AUDIO);
247 ASSERT_TRUE(stream);
248 EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
250 const AudioDecoderConfig& audio_config = stream->audio_decoder_config();
251 EXPECT_EQ(kCodecVorbis, audio_config.codec());
252 EXPECT_EQ(16, audio_config.bits_per_channel());
253 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, audio_config.channel_layout());
254 EXPECT_EQ(44100, audio_config.samples_per_second());
255 EXPECT_TRUE(audio_config.extra_data());
256 EXPECT_GT(audio_config.extra_data_size(), 0u);
258 // Unknown stream should never be present.
259 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
262 TEST_F(FFmpegDemuxerTest, Initialize_Multitrack) {
263 // Open a file containing the following streams:
264 // Stream #0: Video (VP8)
265 // Stream #1: Audio (Vorbis)
266 // Stream #2: Subtitles (SRT)
267 // Stream #3: Video (Theora)
268 // Stream #4: Audio (16-bit signed little endian PCM)
270 // We should only pick the first audio/video streams we come across.
271 CreateDemuxer("bear-320x240-multitrack.webm");
272 InitializeDemuxer();
274 // Video stream should be VP8.
275 scoped_refptr<DemuxerStream> stream =
276 demuxer_->GetStream(DemuxerStream::VIDEO);
277 ASSERT_TRUE(stream);
278 EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
279 EXPECT_EQ(kCodecVP8, stream->video_decoder_config().codec());
281 // Audio stream should be Vorbis.
282 stream = demuxer_->GetStream(DemuxerStream::AUDIO);
283 ASSERT_TRUE(stream);
284 EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
285 EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec());
287 // Unknown stream should never be present.
288 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
291 TEST_F(FFmpegDemuxerTest, Read_Audio) {
292 // We test that on a successful audio packet read.
293 CreateDemuxer("bear-320x240.webm");
294 InitializeDemuxer();
296 // Attempt a read from the audio stream and run the message loop until done.
297 scoped_refptr<DemuxerStream> audio =
298 demuxer_->GetStream(DemuxerStream::AUDIO);
299 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
300 reader->Read(audio);
301 message_loop_.RunAllPending();
302 EXPECT_TRUE(reader->called());
303 ValidateBuffer(FROM_HERE, reader->buffer(), 29, 0);
305 reader->Reset();
306 reader->Read(audio);
307 message_loop_.RunAllPending();
308 EXPECT_TRUE(reader->called());
309 ValidateBuffer(FROM_HERE, reader->buffer(), 27, 3000);
312 TEST_F(FFmpegDemuxerTest, Read_Video) {
313 // We test that on a successful video packet read.
314 CreateDemuxer("bear-320x240.webm");
315 InitializeDemuxer();
317 // Attempt a read from the video stream and run the message loop until done.
318 scoped_refptr<DemuxerStream> video =
319 demuxer_->GetStream(DemuxerStream::VIDEO);
320 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
322 reader->Read(video);
323 message_loop_.RunAllPending();
324 EXPECT_TRUE(reader->called());
325 ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0);
327 reader->Reset();
328 reader->Read(video);
329 message_loop_.RunAllPending();
330 EXPECT_TRUE(reader->called());
331 ValidateBuffer(FROM_HERE, reader->buffer(), 1057, 33000);
334 TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) {
335 // Test the start time is the first timestamp of the video and audio stream.
336 CreateDemuxer("nonzero-start-time.webm");
337 InitializeDemuxer();
339 // Attempt a read from the video stream and run the message loop until done.
340 scoped_refptr<DemuxerStream> video =
341 demuxer_->GetStream(DemuxerStream::VIDEO);
342 scoped_refptr<DemuxerStream> audio =
343 demuxer_->GetStream(DemuxerStream::AUDIO);
344 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
346 // Check first buffer in video stream.
347 reader->Read(video);
348 message_loop_.RunAllPending();
349 EXPECT_TRUE(reader->called());
350 ValidateBuffer(FROM_HERE, reader->buffer(), 5636, 400000);
351 const base::TimeDelta video_timestamp = reader->buffer()->GetTimestamp();
353 // Check first buffer in audio stream.
354 reader->Reset();
355 reader->Read(audio);
356 message_loop_.RunAllPending();
357 EXPECT_TRUE(reader->called());
358 ValidateBuffer(FROM_HERE, reader->buffer(), 165, 396000);
359 const base::TimeDelta audio_timestamp = reader->buffer()->GetTimestamp();
361 // Verify that the start time is equal to the lowest timestamp.
362 EXPECT_EQ(std::min(audio_timestamp, video_timestamp),
363 demuxer_->GetStartTime());
366 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) {
367 // Verify that end of stream buffers are created.
368 CreateDemuxer("bear-320x240.webm");
369 InitializeDemuxer();
370 ReadUntilEndOfStream();
373 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration) {
374 // Verify that end of stream buffers are created.
375 CreateDemuxer("bear-320x240.webm", false);
376 InitializeDemuxer();
377 set_duration_known(false);
378 EXPECT_CALL(host_, SetDuration(_));
379 ReadUntilEndOfStream();
382 TEST_F(FFmpegDemuxerTest, Seek) {
383 // We're testing that the demuxer frees all queued packets when it receives
384 // a Seek().
385 CreateDemuxer("bear-320x240.webm");
386 InitializeDemuxer();
388 // Get our streams.
389 scoped_refptr<DemuxerStream> video =
390 demuxer_->GetStream(DemuxerStream::VIDEO);
391 scoped_refptr<DemuxerStream> audio =
392 demuxer_->GetStream(DemuxerStream::AUDIO);
393 ASSERT_TRUE(video);
394 ASSERT_TRUE(audio);
396 // Read a video packet and release it.
397 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
398 reader->Read(video);
399 message_loop_.RunAllPending();
400 EXPECT_TRUE(reader->called());
401 ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0);
403 // Release the video packet and verify the other packets are still queued.
404 reader->Reset();
405 message_loop_.RunAllPending();
407 // Issue a simple forward seek, which should discard queued packets.
408 demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
409 NewExpectedStatusCB(PIPELINE_OK));
410 message_loop_.RunAllPending();
412 // Audio read #1.
413 reader->Read(audio);
414 message_loop_.RunAllPending();
415 EXPECT_TRUE(reader->called());
416 ValidateBuffer(FROM_HERE, reader->buffer(), 145, 803000);
418 // Audio read #2.
419 reader->Reset();
420 reader->Read(audio);
421 message_loop_.RunAllPending();
422 EXPECT_TRUE(reader->called());
423 ValidateBuffer(FROM_HERE, reader->buffer(), 148, 826000);
425 // Video read #1.
426 reader->Reset();
427 reader->Read(video);
428 message_loop_.RunAllPending();
429 EXPECT_TRUE(reader->called());
430 ValidateBuffer(FROM_HERE, reader->buffer(), 5425, 801000);
432 // Video read #2.
433 reader->Reset();
434 reader->Read(video);
435 message_loop_.RunAllPending();
436 EXPECT_TRUE(reader->called());
437 ValidateBuffer(FROM_HERE, reader->buffer(), 1906, 834000);
439 // Manually release the last reference to the buffer and verify it was freed.
440 reader->Reset();
441 message_loop_.RunAllPending();
444 // A mocked callback specialization for calling Read(). Since RunWithParams()
445 // is mocked we don't need to pass in object or method pointers.
446 class MockReadCB : public base::RefCountedThreadSafe<MockReadCB> {
447 public:
448 MockReadCB() {}
450 MOCK_METHOD0(OnDelete, void());
451 MOCK_METHOD1(Run, void(const scoped_refptr<Buffer>& buffer));
453 protected:
454 virtual ~MockReadCB() {
455 OnDelete();
458 private:
459 friend class base::RefCountedThreadSafe<MockReadCB>;
461 DISALLOW_COPY_AND_ASSIGN(MockReadCB);
464 TEST_F(FFmpegDemuxerTest, Stop) {
465 // Tests that calling Read() on a stopped demuxer stream immediately deletes
466 // the callback.
467 CreateDemuxer("bear-320x240.webm");
468 InitializeDemuxer();
470 // Get our stream.
471 scoped_refptr<DemuxerStream> audio =
472 demuxer_->GetStream(DemuxerStream::AUDIO);
473 ASSERT_TRUE(audio);
475 demuxer_->Stop(NewExpectedClosure());
477 // Expect all calls in sequence.
478 InSequence s;
480 // Create our mocked callback. The Callback created by base::Bind() will take
481 // ownership of this pointer.
482 StrictMock<MockReadCB>* callback = new StrictMock<MockReadCB>();
484 // The callback should be immediately deleted. We'll use a checkpoint to
485 // verify that it has indeed been deleted.
486 EXPECT_CALL(*callback, Run(IsEndOfStreamBuffer()));
487 EXPECT_CALL(*callback, OnDelete());
488 EXPECT_CALL(*this, CheckPoint(1));
490 // Attempt the read...
491 audio->Read(base::Bind(&MockReadCB::Run, callback));
493 message_loop_.RunAllPending();
495 // ...and verify that |callback| was deleted.
496 CheckPoint(1);
499 // The streams can outlive the demuxer because the streams may still be in use
500 // by the decoder when the demuxer is destroyed.
501 // This test verifies that DemuxerStream::Read() does not use an invalid demuxer
502 // pointer (no crash occurs) and calls the callback with an EndOfStream buffer.
503 TEST_F(FFmpegDemuxerTest, StreamReadAfterStopAndDemuxerDestruction) {
504 CreateDemuxer("bear-320x240.webm");
505 InitializeDemuxer();
507 // Get our stream.
508 scoped_refptr<DemuxerStream> audio =
509 demuxer_->GetStream(DemuxerStream::AUDIO);
510 ASSERT_TRUE(audio);
512 demuxer_->Stop(NewExpectedClosure());
514 // Finish up any remaining tasks.
515 message_loop_.RunAllPending();
517 // Expect all calls in sequence.
518 InSequence s;
520 // Create our mocked callback. The Callback created by base::Bind() will take
521 // ownership of this pointer.
522 StrictMock<MockReadCB>* callback = new StrictMock<MockReadCB>();
524 // The callback should be immediately deleted. We'll use a checkpoint to
525 // verify that it has indeed been deleted.
526 EXPECT_CALL(*callback, Run(IsEndOfStreamBuffer()));
527 EXPECT_CALL(*callback, OnDelete());
528 EXPECT_CALL(*this, CheckPoint(1));
530 // Release the reference to the demuxer. This should also destroy it.
531 demuxer_ = NULL;
532 // |audio| now has a demuxer_ pointer to invalid memory.
534 // Attempt the read...
535 audio->Read(base::Bind(&MockReadCB::Run, callback));
537 message_loop_.RunAllPending();
539 // ...and verify that |callback| was deleted.
540 CheckPoint(1);
543 TEST_F(FFmpegDemuxerTest, DisableAudioStream) {
544 // We are doing the following things here:
545 // 1. Initialize the demuxer with audio and video stream.
546 // 2. Send a "disable audio stream" message to the demuxer.
547 // 3. Demuxer will free audio packets even if audio stream was initialized.
548 CreateDemuxer("bear-320x240.webm");
549 InitializeDemuxer();
551 // Submit a "disable audio stream" message to the demuxer.
552 demuxer_->OnAudioRendererDisabled();
553 message_loop_.RunAllPending();
555 // Get our streams.
556 scoped_refptr<DemuxerStream> video =
557 demuxer_->GetStream(DemuxerStream::VIDEO);
558 scoped_refptr<DemuxerStream> audio =
559 demuxer_->GetStream(DemuxerStream::AUDIO);
560 ASSERT_TRUE(video);
561 ASSERT_TRUE(audio);
563 // The audio stream should have been prematurely stopped.
564 EXPECT_FALSE(IsStreamStopped(DemuxerStream::VIDEO));
565 EXPECT_TRUE(IsStreamStopped(DemuxerStream::AUDIO));
567 // Attempt a read from the video stream: it should return valid data.
568 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
569 reader->Read(video);
570 message_loop_.RunAllPending();
571 ASSERT_TRUE(reader->called());
572 ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0);
574 // Attempt a read from the audio stream: it should immediately return end of
575 // stream without requiring the message loop to read data.
576 reader->Reset();
577 reader->Read(audio);
578 ASSERT_TRUE(reader->called());
579 EXPECT_TRUE(reader->buffer()->IsEndOfStream());
582 TEST_F(FFmpegDemuxerTest, ProtocolRead) {
583 CreateDemuxer("bear-320x240.webm");
584 InitializeDemuxer();
586 // Set read head to zero as Initialize() will have parsed a bit of the file.
587 int64 position = 0;
588 EXPECT_TRUE(demuxer_->SetPosition(0));
589 EXPECT_TRUE(demuxer_->GetPosition(&position));
590 EXPECT_EQ(0, position);
592 // Read 32 bytes from offset zero and verify position.
593 uint8 buffer[32];
594 EXPECT_EQ(32u, demuxer_->Read(32, buffer));
595 EXPECT_EQ(32, current_read_position_);
596 EXPECT_TRUE(demuxer_->GetPosition(&position));
597 EXPECT_EQ(32, position);
599 // Read an additional 32 bytes and verify position.
600 EXPECT_EQ(32u, demuxer_->Read(32, buffer));
601 EXPECT_EQ(64, current_read_position_);
602 EXPECT_TRUE(demuxer_->GetPosition(&position));
603 EXPECT_EQ(64, position);
605 // Seek to end and read until EOF.
606 int64 size = 0;
607 EXPECT_TRUE(demuxer_->GetSize(&size));
608 EXPECT_TRUE(demuxer_->SetPosition(size - 48));
609 EXPECT_EQ(32u, demuxer_->Read(32, buffer));
610 EXPECT_EQ(size - 16, current_read_position_);
611 EXPECT_TRUE(demuxer_->GetPosition(&position));
612 EXPECT_EQ(size - 16, position);
614 EXPECT_EQ(16u, demuxer_->Read(32, buffer));
615 EXPECT_EQ(size, current_read_position_);
616 EXPECT_TRUE(demuxer_->GetPosition(&position));
617 EXPECT_EQ(size, position);
619 EXPECT_EQ(0u, demuxer_->Read(32, buffer));
620 EXPECT_EQ(size, current_read_position_);
621 EXPECT_TRUE(demuxer_->GetPosition(&position));
622 EXPECT_EQ(size, position);
624 demuxer_->Stop(NewExpectedClosure());
625 message_loop_.RunAllPending();
628 TEST_F(FFmpegDemuxerTest, GetBitrate_SetInContainer) {
629 EXPECT_TRUE(VideoHasValidBitrate("bear.ogv", false));
632 TEST_F(FFmpegDemuxerTest, GetBitrate_UnsetInContainer_KnownSize) {
633 EXPECT_TRUE(VideoHasValidBitrate("bear-320x240.webm", false));
636 TEST_F(FFmpegDemuxerTest, GetBitrate_SetInContainer_NoFileSize) {
637 EXPECT_TRUE(VideoHasValidBitrate("bear.ogv", true));
640 TEST_F(FFmpegDemuxerTest, GetBitrate_UnsetInContainer_NoFileSize) {
641 EXPECT_TRUE(VideoHasValidBitrate("bear-320x240.webm", true));
644 TEST_F(FFmpegDemuxerTest, ProtocolGetSetPosition) {
645 CreateDemuxer("bear-320x240.webm");
646 InitializeDemuxer();
648 InSequence s;
650 int64 size;
651 int64 position;
652 EXPECT_TRUE(demuxer_->GetSize(&size));
653 EXPECT_TRUE(demuxer_->GetPosition(&position));
654 EXPECT_EQ(current_read_position_, position);
656 EXPECT_TRUE(demuxer_->SetPosition(512));
657 EXPECT_FALSE(demuxer_->SetPosition(size));
658 EXPECT_FALSE(demuxer_->SetPosition(size + 1));
659 EXPECT_FALSE(demuxer_->SetPosition(-1));
660 EXPECT_TRUE(demuxer_->GetPosition(&position));
661 EXPECT_EQ(512, position);
664 TEST_F(FFmpegDemuxerTest, ProtocolGetSize) {
665 CreateDemuxer("bear-320x240.webm");
666 InitializeDemuxer();
668 int64 data_source_size = 0;
669 int64 demuxer_size = 0;
670 EXPECT_TRUE(data_source_->GetSize(&data_source_size));
671 EXPECT_TRUE(demuxer_->GetSize(&demuxer_size));
672 EXPECT_NE(0, data_source_size);
673 EXPECT_EQ(data_source_size, demuxer_size);
676 TEST_F(FFmpegDemuxerTest, ProtocolIsStreaming) {
677 CreateDemuxer("bear-320x240.webm");
678 InitializeDemuxer();
680 EXPECT_FALSE(data_source_->IsStreaming());
681 EXPECT_FALSE(demuxer_->IsStreaming());
684 // Verify that seek works properly when the WebM cues data is at the start of
685 // the file instead of at the end.
686 TEST_F(FFmpegDemuxerTest, SeekWithCuesBeforeFirstCluster) {
687 CreateDemuxer("bear-320x240-cues-in-front.webm");
688 InitializeDemuxer();
690 // Get our streams.
691 scoped_refptr<DemuxerStream> video =
692 demuxer_->GetStream(DemuxerStream::VIDEO);
693 scoped_refptr<DemuxerStream> audio =
694 demuxer_->GetStream(DemuxerStream::AUDIO);
695 ASSERT_TRUE(video);
696 ASSERT_TRUE(audio);
698 // Read a video packet and release it.
699 scoped_refptr<DemuxerStreamReader> reader(new DemuxerStreamReader());
700 reader->Read(video);
701 message_loop_.RunAllPending();
702 EXPECT_TRUE(reader->called());
703 ValidateBuffer(FROM_HERE, reader->buffer(), 22084, 0);
705 // Release the video packet and verify the other packets are still queued.
706 reader->Reset();
707 message_loop_.RunAllPending();
709 // Issue a simple forward seek, which should discard queued packets.
710 demuxer_->Seek(base::TimeDelta::FromMicroseconds(2500000),
711 NewExpectedStatusCB(PIPELINE_OK));
712 message_loop_.RunAllPending();
714 // Audio read #1.
715 reader->Read(audio);
716 message_loop_.RunAllPending();
717 EXPECT_TRUE(reader->called());
718 ValidateBuffer(FROM_HERE, reader->buffer(), 40, 2403000);
720 // Audio read #2.
721 reader->Reset();
722 reader->Read(audio);
723 message_loop_.RunAllPending();
724 EXPECT_TRUE(reader->called());
725 ValidateBuffer(FROM_HERE, reader->buffer(), 42, 2406000);
727 // Video read #1.
728 reader->Reset();
729 reader->Read(video);
730 message_loop_.RunAllPending();
731 EXPECT_TRUE(reader->called());
732 ValidateBuffer(FROM_HERE, reader->buffer(), 5276, 2402000);
734 // Video read #2.
735 reader->Reset();
736 reader->Read(video);
737 message_loop_.RunAllPending();
738 EXPECT_TRUE(reader->called());
739 ValidateBuffer(FROM_HERE, reader->buffer(), 1740, 2436000);
741 // Manually release the last reference to the buffer and verify it was freed.
742 reader->Reset();
743 message_loop_.RunAllPending();
746 // Ensure ID3v1 tag reading is disabled. id3_test.mp3 has an ID3v1 tag with the
747 // field "title" set to "sample for id3 test".
748 TEST_F(FFmpegDemuxerTest, NoID3TagData) {
749 #if !defined(USE_PROPRIETARY_CODECS)
750 return;
751 #endif
752 CreateDemuxer("id3_test.mp3");
753 InitializeDemuxer();
754 EXPECT_FALSE(av_dict_get(format_context()->metadata, "title", NULL, 0));
757 // Ensure MP3 files with large image/video based ID3 tags demux okay. FFmpeg
758 // will hand us a video stream to the data which will likely be in a format we
759 // don't accept as video; e.g. PNG.
760 TEST_F(FFmpegDemuxerTest, Mp3WithVideoStreamID3TagData) {
761 #if !defined(USE_PROPRIETARY_CODECS)
762 return;
763 #endif
764 CreateDemuxer("id3_png_test.mp3");
765 InitializeDemuxer();
767 // Ensure the expected streams are present.
768 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO));
769 EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO));
772 // Ensure a video with an unsupported audio track still results in the video
773 // stream being demuxed.
774 TEST_F(FFmpegDemuxerTest, UnsupportedAudioSupportedVideoDemux) {
775 CreateDemuxer("speex_audio_vorbis_video.ogv");
776 InitializeDemuxer();
778 // Ensure the expected streams are present.
779 EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::VIDEO));
780 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::AUDIO));
783 // Ensure a video with an unsupported video track still results in the audio
784 // stream being demuxed.
785 TEST_F(FFmpegDemuxerTest, UnsupportedVideoSupportedAudioDemux) {
786 CreateDemuxer("vorbis_audio_wmv_video.mkv");
787 InitializeDemuxer();
789 // Ensure the expected streams are present.
790 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO));
791 EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO));
794 } // namespace media