Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(214)

Side by Side Diff: media/filters/ffmpeg_demuxer_unittest.cc

Issue 23702007: Render inband text tracks in the media pipeline (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: incorporate aaron's comments (11/12) Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <algorithm> 5 #include <algorithm>
6 #include <deque> 6 #include <deque>
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 CHECK(!demuxer_); 76 CHECK(!demuxer_);
77 77
78 EXPECT_CALL(host_, SetTotalBytes(_)).Times(AnyNumber()); 78 EXPECT_CALL(host_, SetTotalBytes(_)).Times(AnyNumber());
79 EXPECT_CALL(host_, AddBufferedByteRange(_, _)).Times(AnyNumber()); 79 EXPECT_CALL(host_, AddBufferedByteRange(_, _)).Times(AnyNumber());
80 EXPECT_CALL(host_, AddBufferedTimeRange(_, _)).Times(AnyNumber()); 80 EXPECT_CALL(host_, AddBufferedTimeRange(_, _)).Times(AnyNumber());
81 81
82 CreateDataSource(name); 82 CreateDataSource(name);
83 83
84 Demuxer::NeedKeyCB need_key_cb = 84 Demuxer::NeedKeyCB need_key_cb =
85 base::Bind(&FFmpegDemuxerTest::NeedKeyCB, base::Unretained(this)); 85 base::Bind(&FFmpegDemuxerTest::NeedKeyCB, base::Unretained(this));
86
86 demuxer_.reset(new FFmpegDemuxer(message_loop_.message_loop_proxy(), 87 demuxer_.reset(new FFmpegDemuxer(message_loop_.message_loop_proxy(),
87 data_source_.get(), 88 data_source_.get(),
88 need_key_cb, 89 need_key_cb,
89 new MediaLog())); 90 new MediaLog()));
90 } 91 }
91 92
92 MOCK_METHOD1(CheckPoint, void(int v)); 93 MOCK_METHOD1(CheckPoint, void(int v));
93 94
94 void InitializeDemuxer() { 95 void InitializeDemuxerText(bool enable_text) {
95 EXPECT_CALL(host_, SetDuration(_)); 96 EXPECT_CALL(host_, SetDuration(_));
96 WaitableMessageLoopEvent event; 97 WaitableMessageLoopEvent event;
97 demuxer_->Initialize(&host_, event.GetPipelineStatusCB()); 98 demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), enable_text);
98 event.RunAndWaitForStatus(PIPELINE_OK); 99 event.RunAndWaitForStatus(PIPELINE_OK);
99 } 100 }
100 101
102 void InitializeDemuxer() {
103 InitializeDemuxerText(false);
104 }
105
101 MOCK_METHOD2(OnReadDoneCalled, void(int, int64)); 106 MOCK_METHOD2(OnReadDoneCalled, void(int, int64));
102 107
103 // Verifies that |buffer| has a specific |size| and |timestamp|. 108 // Verifies that |buffer| has a specific |size| and |timestamp|.
104 // |location| simply indicates where the call to this function was made. 109 // |location| simply indicates where the call to this function was made.
105 // This makes it easier to track down where test failures occur. 110 // This makes it easier to track down where test failures occur.
106 void OnReadDone(const tracked_objects::Location& location, 111 void OnReadDone(const tracked_objects::Location& location,
107 int size, int64 timestampInMicroseconds, 112 int size, int64 timestampInMicroseconds,
108 DemuxerStream::Status status, 113 DemuxerStream::Status status,
109 const scoped_refptr<DecoderBuffer>& buffer) { 114 const scoped_refptr<DecoderBuffer>& buffer) {
110 std::string location_str; 115 std::string location_str;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 EXPECT_TRUE(data_source_->Initialize(file_path)); 197 EXPECT_TRUE(data_source_->Initialize(file_path));
193 } 198 }
194 199
195 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest); 200 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest);
196 }; 201 };
197 202
198 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { 203 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) {
199 // Simulate avformat_open_input() failing. 204 // Simulate avformat_open_input() failing.
200 CreateDemuxer("ten_byte_file"); 205 CreateDemuxer("ten_byte_file");
201 WaitableMessageLoopEvent event; 206 WaitableMessageLoopEvent event;
202 demuxer_->Initialize(&host_, event.GetPipelineStatusCB()); 207 demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
203 event.RunAndWaitForStatus(DEMUXER_ERROR_COULD_NOT_OPEN); 208 event.RunAndWaitForStatus(DEMUXER_ERROR_COULD_NOT_OPEN);
204 } 209 }
205 210
206 // TODO(acolwell): Uncomment this test when we discover a file that passes 211 // TODO(acolwell): Uncomment this test when we discover a file that passes
207 // avformat_open_input(), but has avformat_find_stream_info() fail. 212 // avformat_open_input(), but has avformat_find_stream_info() fail.
208 // 213 //
209 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) { 214 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) {
210 // ("find_stream_info_fail.webm"); 215 // ("find_stream_info_fail.webm");
211 // demuxer_->Initialize( 216 // demuxer_->Initialize(
212 // &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE)); 217 // &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE));
213 // message_loop_.RunUntilIdle(); 218 // message_loop_.RunUntilIdle();
214 //} 219 //}
215 220
216 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) { 221 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) {
217 // Open a file with no streams whatsoever. 222 // Open a file with no streams whatsoever.
218 CreateDemuxer("no_streams.webm"); 223 CreateDemuxer("no_streams.webm");
219 WaitableMessageLoopEvent event; 224 WaitableMessageLoopEvent event;
220 demuxer_->Initialize(&host_, event.GetPipelineStatusCB()); 225 demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
221 event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); 226 event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
222 } 227 }
223 228
224 TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) { 229 TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) {
225 // Open a file containing streams but none of which are audio/video streams. 230 // Open a file containing streams but none of which are audio/video streams.
226 CreateDemuxer("no_audio_video.webm"); 231 CreateDemuxer("no_audio_video.webm");
227 WaitableMessageLoopEvent event; 232 WaitableMessageLoopEvent event;
228 demuxer_->Initialize(&host_, event.GetPipelineStatusCB()); 233 demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
229 event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); 234 event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
230 } 235 }
231 236
232 TEST_F(FFmpegDemuxerTest, Initialize_Successful) { 237 TEST_F(FFmpegDemuxerTest, Initialize_Successful) {
233 CreateDemuxer("bear-320x240.webm"); 238 CreateDemuxer("bear-320x240.webm");
234 InitializeDemuxer(); 239 InitializeDemuxer();
235 240
236 // Video stream should be present. 241 // Video stream should be present.
237 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); 242 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
238 ASSERT_TRUE(stream); 243 ASSERT_TRUE(stream);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 // Audio stream should be Vorbis. 296 // Audio stream should be Vorbis.
292 stream = demuxer_->GetStream(DemuxerStream::AUDIO); 297 stream = demuxer_->GetStream(DemuxerStream::AUDIO);
293 ASSERT_TRUE(stream); 298 ASSERT_TRUE(stream);
294 EXPECT_EQ(DemuxerStream::AUDIO, stream->type()); 299 EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
295 EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec()); 300 EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec());
296 301
297 // Unknown stream should never be present. 302 // Unknown stream should never be present.
298 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN)); 303 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
299 } 304 }
300 305
306 TEST_F(FFmpegDemuxerTest, Initialize_MultitrackText) {
307 // Open a file containing the following streams:
308 // Stream #0: Video (VP8)
309 // Stream #1: Audio (Vorbis)
310 // Stream #2: Text (WebVTT)
311
312 CreateDemuxer("bear-vp8-webvtt.webm");
313 DemuxerStream* text_stream = NULL;
314 EXPECT_CALL(host_, AddTextStream(_, _))
315 .WillOnce(SaveArg<0>(&text_stream));
316 InitializeDemuxerText(true);
317 ASSERT_TRUE(text_stream);
318 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
319
320 // Video stream should be VP8.
321 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
322 ASSERT_TRUE(stream);
323 EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
324 EXPECT_EQ(kCodecVP8, stream->video_decoder_config().codec());
325
326 // Audio stream should be Vorbis.
327 stream = demuxer_->GetStream(DemuxerStream::AUDIO);
328 ASSERT_TRUE(stream);
329 EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
330 EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec());
331
332 // Unknown stream should never be present.
333 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::UNKNOWN));
334 }
335
301 TEST_F(FFmpegDemuxerTest, Initialize_Encrypted) { 336 TEST_F(FFmpegDemuxerTest, Initialize_Encrypted) {
302 EXPECT_CALL(*this, NeedKeyCBMock(kWebMEncryptInitDataType, NotNull(), 337 EXPECT_CALL(*this, NeedKeyCBMock(kWebMEncryptInitDataType, NotNull(),
303 DecryptConfig::kDecryptionKeySize)) 338 DecryptConfig::kDecryptionKeySize))
304 .Times(Exactly(2)); 339 .Times(Exactly(2));
305 340
306 CreateDemuxer("bear-320x240-av_enc-av.webm"); 341 CreateDemuxer("bear-320x240-av_enc-av.webm");
307 InitializeDemuxer(); 342 InitializeDemuxer();
308 } 343 }
309 344
310 TEST_F(FFmpegDemuxerTest, Read_Audio) { 345 TEST_F(FFmpegDemuxerTest, Read_Audio) {
(...skipping 19 matching lines...) Expand all
330 // Attempt a read from the video stream and run the message loop until done. 365 // Attempt a read from the video stream and run the message loop until done.
331 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO); 366 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
332 367
333 video->Read(NewReadCB(FROM_HERE, 22084, 0)); 368 video->Read(NewReadCB(FROM_HERE, 22084, 0));
334 message_loop_.Run(); 369 message_loop_.Run();
335 370
336 video->Read(NewReadCB(FROM_HERE, 1057, 33000)); 371 video->Read(NewReadCB(FROM_HERE, 1057, 33000));
337 message_loop_.Run(); 372 message_loop_.Run();
338 } 373 }
339 374
375 TEST_F(FFmpegDemuxerTest, Read_Text) {
376 // We test that on a successful text packet read.
377 CreateDemuxer("bear-vp8-webvtt.webm");
378 DemuxerStream* text_stream = NULL;
379 EXPECT_CALL(host_, AddTextStream(_, _))
380 .WillOnce(SaveArg<0>(&text_stream));
381 InitializeDemuxerText(true);
382 ASSERT_TRUE(text_stream);
383 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
384
385 text_stream->Read(NewReadCB(FROM_HERE, 31, 0));
386 message_loop_.Run();
387
388 text_stream->Read(NewReadCB(FROM_HERE, 19, 500000));
389 message_loop_.Run();
390 }
391
340 TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) { 392 TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) {
341 // Test the start time is the first timestamp of the video and audio stream. 393 // Test the start time is the first timestamp of the video and audio stream.
342 CreateDemuxer("nonzero-start-time.webm"); 394 CreateDemuxer("nonzero-start-time.webm");
343 InitializeDemuxer(); 395 InitializeDemuxer();
344 396
345 // Attempt a read from the video stream and run the message loop until done. 397 // Attempt a read from the video stream and run the message loop until done.
346 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO); 398 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
347 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO); 399 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
348 400
349 // Check first buffer in video stream. 401 // Check first buffer in video stream.
350 video->Read(NewReadCB(FROM_HERE, 5636, 400000)); 402 video->Read(NewReadCB(FROM_HERE, 5636, 400000));
351 message_loop_.Run(); 403 message_loop_.Run();
352 404
353 // Check first buffer in audio stream. 405 // Check first buffer in audio stream.
354 audio->Read(NewReadCB(FROM_HERE, 165, 396000)); 406 audio->Read(NewReadCB(FROM_HERE, 165, 396000));
355 message_loop_.Run(); 407 message_loop_.Run();
356 408
357 // Verify that the start time is equal to the lowest timestamp (ie the audio). 409 // Verify that the start time is equal to the lowest timestamp (ie the audio).
358 EXPECT_EQ(demuxer_->GetStartTime().InMicroseconds(), 396000); 410 EXPECT_EQ(demuxer_->GetStartTime().InMicroseconds(), 396000);
359 } 411 }
360 412
361 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) { 413 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) {
362 // Verify that end of stream buffers are created. 414 // Verify that end of stream buffers are created.
363 CreateDemuxer("bear-320x240.webm"); 415 CreateDemuxer("bear-320x240.webm");
364 InitializeDemuxer(); 416 InitializeDemuxer();
365 ReadUntilEndOfStream(); 417 ReadUntilEndOfStream();
366 } 418 }
367 419
420 TEST_F(FFmpegDemuxerTest, Read_EndOfStreamText) {
421 // Verify that end of stream buffers are created.
422 CreateDemuxer("bear-vp8-webvtt.webm");
423 DemuxerStream* text_stream = NULL;
424 EXPECT_CALL(host_, AddTextStream(_, _))
425 .WillOnce(SaveArg<0>(&text_stream));
426 InitializeDemuxerText(true);
427 ASSERT_TRUE(text_stream);
428 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
429
430 bool got_eos_buffer = false;
431 const int kMaxBuffers = 10000;
acolwell GONE FROM CHROMIUM 2013/11/20 01:15:24 nit: Please trim this down to a smaller number. I'
Matthew Heaney (Chromium) 2013/11/20 19:23:16 Done.
432 for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) {
433 text_stream->Read(base::Bind(&EosOnReadDone, &got_eos_buffer));
434 message_loop_.Run();
435 }
436
437 EXPECT_TRUE(got_eos_buffer);
438 }
439
368 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration) { 440 TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration) {
369 // Verify that end of stream buffers are created. 441 // Verify that end of stream buffers are created.
370 CreateDemuxer("bear-320x240.webm"); 442 CreateDemuxer("bear-320x240.webm");
371 InitializeDemuxer(); 443 InitializeDemuxer();
372 set_duration_known(false); 444 set_duration_known(false);
373 EXPECT_CALL(host_, SetDuration(_)); 445 EXPECT_CALL(host_, SetDuration(_));
374 ReadUntilEndOfStream(); 446 ReadUntilEndOfStream();
375 } 447 }
376 448
377 TEST_F(FFmpegDemuxerTest, Seek) { 449 TEST_F(FFmpegDemuxerTest, Seek) {
(...skipping 28 matching lines...) Expand all
406 478
407 // Video read #1. 479 // Video read #1.
408 video->Read(NewReadCB(FROM_HERE, 5425, 801000)); 480 video->Read(NewReadCB(FROM_HERE, 5425, 801000));
409 message_loop_.Run(); 481 message_loop_.Run();
410 482
411 // Video read #2. 483 // Video read #2.
412 video->Read(NewReadCB(FROM_HERE, 1906, 834000)); 484 video->Read(NewReadCB(FROM_HERE, 1906, 834000));
413 message_loop_.Run(); 485 message_loop_.Run();
414 } 486 }
415 487
488 TEST_F(FFmpegDemuxerTest, SeekText) {
489 // We're testing that the demuxer frees all queued packets when it receives
490 // a Seek().
491 CreateDemuxer("bear-vp8-webvtt.webm");
492 DemuxerStream* text_stream = NULL;
493 EXPECT_CALL(host_, AddTextStream(_, _))
494 .WillOnce(SaveArg<0>(&text_stream));
495 InitializeDemuxerText(true);
496 ASSERT_TRUE(text_stream);
497 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
498
499 // Get our streams.
500 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
501 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
502 ASSERT_TRUE(video);
503 ASSERT_TRUE(audio);
504
505 // Read a text packet and release it.
506 text_stream->Read(NewReadCB(FROM_HERE, 31, 0));
507 message_loop_.Run();
508
509 // Issue a simple forward seek, which should discard queued packets.
510 WaitableMessageLoopEvent event;
511 demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
512 event.GetPipelineStatusCB());
513 event.RunAndWaitForStatus(PIPELINE_OK);
514
515 // Audio read #1.
516 audio->Read(NewReadCB(FROM_HERE, 145, 803000));
517 message_loop_.Run();
518
519 // Audio read #2.
520 audio->Read(NewReadCB(FROM_HERE, 148, 826000));
521 message_loop_.Run();
522
523 // Video read #1.
524 video->Read(NewReadCB(FROM_HERE, 5425, 801000));
525 message_loop_.Run();
526
527 // Video read #2.
528 video->Read(NewReadCB(FROM_HERE, 1906, 834000));
529 message_loop_.Run();
530
531 // Text read #1.
532 text_stream->Read(NewReadCB(FROM_HERE, 19, 500000));
533 message_loop_.Run();
534
535 // Text read #2.
536 text_stream->Read(NewReadCB(FROM_HERE, 19, 1000000));
537 message_loop_.Run();
538 }
539
416 class MockReadCB { 540 class MockReadCB {
417 public: 541 public:
418 MockReadCB() {} 542 MockReadCB() {}
419 ~MockReadCB() {} 543 ~MockReadCB() {}
420 544
421 MOCK_METHOD2(Run, void(DemuxerStream::Status status, 545 MOCK_METHOD2(Run, void(DemuxerStream::Status status,
422 const scoped_refptr<DecoderBuffer>& buffer)); 546 const scoped_refptr<DecoderBuffer>& buffer));
423 private: 547 private:
424 DISALLOW_COPY_AND_ASSIGN(MockReadCB); 548 DISALLOW_COPY_AND_ASSIGN(MockReadCB);
425 }; 549 };
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 TEST_F(FFmpegDemuxerTest, MP4_ZeroStszEntry) { 700 TEST_F(FFmpegDemuxerTest, MP4_ZeroStszEntry) {
577 #if !defined(USE_PROPRIETARY_CODECS) 701 #if !defined(USE_PROPRIETARY_CODECS)
578 return; 702 return;
579 #endif 703 #endif
580 CreateDemuxer("bear-1280x720-zero-stsz-entry.mp4"); 704 CreateDemuxer("bear-1280x720-zero-stsz-entry.mp4");
581 InitializeDemuxer(); 705 InitializeDemuxer();
582 ReadUntilEndOfStream(); 706 ReadUntilEndOfStream();
583 } 707 }
584 708
585 } // namespace media 709 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698