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

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

Issue 325503003: Fix seeking when the start time is non-zero. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: FFmpeg only start time. Created 6 years, 6 months 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 | Annotate | Revision Log
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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 EXPECT_CALL(host_, SetDuration(_)); 96 EXPECT_CALL(host_, SetDuration(_));
97 WaitableMessageLoopEvent event; 97 WaitableMessageLoopEvent event;
98 demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), enable_text); 98 demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), enable_text);
99 event.RunAndWaitForStatus(PIPELINE_OK); 99 event.RunAndWaitForStatus(PIPELINE_OK);
100 } 100 }
101 101
102 void InitializeDemuxer() { 102 void InitializeDemuxer() {
103 InitializeDemuxerText(false); 103 InitializeDemuxerText(false);
104 } 104 }
105 105
106 void InitializeDemuxerWithTimelineOffset(const char* utc_date) {
107 EXPECT_CALL(host_, SetDuration(_));
108 WaitableMessageLoopEvent event;
109 demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), false);
110 // Inject the timeline offset into the FFmpeg metadata dictionary.
111 av_dict_set(&demuxer_->glue_->format_context()->metadata,
112 "creation_time",
113 utc_date,
114 0);
115 event.RunAndWaitForStatus(PIPELINE_OK);
116 }
117
106 MOCK_METHOD2(OnReadDoneCalled, void(int, int64)); 118 MOCK_METHOD2(OnReadDoneCalled, void(int, int64));
107 119
108 // Verifies that |buffer| has a specific |size| and |timestamp|. 120 // Verifies that |buffer| has a specific |size| and |timestamp|.
109 // |location| simply indicates where the call to this function was made. 121 // |location| simply indicates where the call to this function was made.
110 // This makes it easier to track down where test failures occur. 122 // This makes it easier to track down where test failures occur.
111 void OnReadDone(const tracked_objects::Location& location, 123 void OnReadDone(const tracked_objects::Location& location,
112 int size, int64 timestampInMicroseconds, 124 int size,
125 int64 timestamp_us,
126 bool should_be_marked_for_discard,
113 DemuxerStream::Status status, 127 DemuxerStream::Status status,
114 const scoped_refptr<DecoderBuffer>& buffer) { 128 const scoped_refptr<DecoderBuffer>& buffer) {
115 std::string location_str; 129 std::string location_str;
116 location.Write(true, false, &location_str); 130 location.Write(true, false, &location_str);
117 location_str += "\n"; 131 location_str += "\n";
118 SCOPED_TRACE(location_str); 132 SCOPED_TRACE(location_str);
119 EXPECT_EQ(status, DemuxerStream::kOk); 133 EXPECT_EQ(status, DemuxerStream::kOk);
120 OnReadDoneCalled(size, timestampInMicroseconds); 134 OnReadDoneCalled(size, timestamp_us);
121 EXPECT_TRUE(buffer.get() != NULL); 135 EXPECT_TRUE(buffer.get() != NULL);
122 EXPECT_EQ(size, buffer->data_size()); 136 EXPECT_EQ(size, buffer->data_size());
123 EXPECT_EQ(base::TimeDelta::FromMicroseconds(timestampInMicroseconds), 137 EXPECT_EQ(timestamp_us, buffer->timestamp().InMicroseconds());
124 buffer->timestamp());
125 138
139 const base::TimeDelta expected_front_discard =
140 should_be_marked_for_discard ? kInfiniteDuration() : base::TimeDelta();
141 EXPECT_EQ(expected_front_discard, buffer->discard_padding().first);
126 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 142 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
127 message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); 143 message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
128 } 144 }
129 145
130 DemuxerStream::ReadCB NewReadCB(const tracked_objects::Location& location, 146 DemuxerStream::ReadCB NewReadCB(const tracked_objects::Location& location,
131 int size, int64 timestampInMicroseconds) { 147 int size,
132 EXPECT_CALL(*this, OnReadDoneCalled(size, timestampInMicroseconds)); 148 int64 timestamp_us) {
133 return base::Bind(&FFmpegDemuxerTest::OnReadDone, base::Unretained(this), 149 EXPECT_CALL(*this, OnReadDoneCalled(size, timestamp_us));
134 location, size, timestampInMicroseconds); 150 return base::Bind(&FFmpegDemuxerTest::OnReadDone,
151 base::Unretained(this),
152 location,
153 size,
154 timestamp_us,
155 false);
156 }
157
158 DemuxerStream::ReadCB NewReadCBWithCheckedDiscard(
159 const tracked_objects::Location& location,
160 int size,
161 int64 timestamp_us) {
162 EXPECT_CALL(*this, OnReadDoneCalled(size, timestamp_us));
163 return base::Bind(&FFmpegDemuxerTest::OnReadDone,
164 base::Unretained(this),
165 location,
166 size,
167 timestamp_us,
168 true);
135 } 169 }
136 170
137 // TODO(xhwang): This is a workaround of the issue that move-only parameters 171 // TODO(xhwang): This is a workaround of the issue that move-only parameters
138 // are not supported in mocked methods. Remove this when the issue is fixed 172 // are not supported in mocked methods. Remove this when the issue is fixed
139 // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use 173 // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use
140 // std::string instead of scoped_ptr<uint8[]> (http://crbug.com/130689). 174 // std::string instead of scoped_ptr<uint8[]> (http://crbug.com/130689).
141 MOCK_METHOD3(NeedKeyCBMock, void(const std::string& type, 175 MOCK_METHOD3(NeedKeyCBMock, void(const std::string& type,
142 const uint8* init_data, int init_data_size)); 176 const uint8* init_data, int init_data_size));
143 void NeedKeyCB(const std::string& type, 177 void NeedKeyCB(const std::string& type,
144 const std::vector<uint8>& init_data) { 178 const std::vector<uint8>& init_data) {
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 ASSERT_TRUE(text_stream); 413 ASSERT_TRUE(text_stream);
380 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type()); 414 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
381 415
382 text_stream->Read(NewReadCB(FROM_HERE, 31, 0)); 416 text_stream->Read(NewReadCB(FROM_HERE, 31, 0));
383 message_loop_.Run(); 417 message_loop_.Run();
384 418
385 text_stream->Read(NewReadCB(FROM_HERE, 19, 500000)); 419 text_stream->Read(NewReadCB(FROM_HERE, 19, 500000));
386 message_loop_.Run(); 420 message_loop_.Run();
387 } 421 }
388 422
389 TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) { 423 TEST_F(FFmpegDemuxerTest, Read_VideoPositiveStartTime) {
424 const char kTimelineOffset[] = "2012-11-10 12:34:56";
425 const int64 kTimelineOffsetMs = 1352550896000LL;
426
390 // Test the start time is the first timestamp of the video and audio stream. 427 // Test the start time is the first timestamp of the video and audio stream.
391 CreateDemuxer("nonzero-start-time.webm"); 428 CreateDemuxer("nonzero-start-time.webm");
392 InitializeDemuxer(); 429 InitializeDemuxerWithTimelineOffset(kTimelineOffset);
393 430
394 // Attempt a read from the video stream and run the message loop until done. 431 // Attempt a read from the video stream and run the message loop until done.
395 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO); 432 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
396 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO); 433 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
397 434
398 // Check first buffer in video stream. 435 const base::TimeDelta video_start_time =
399 video->Read(NewReadCB(FROM_HERE, 5636, 400000)); 436 base::TimeDelta::FromMicroseconds(400000);
437 const base::TimeDelta audio_start_time =
438 base::TimeDelta::FromMicroseconds(396000);
439
440 // Run the test twice with a seek in between.
441 for (int i = 0; i < 2; ++i) {
442 // Check first buffer in video stream. It should have been adjusted such
443 // that
444 // it starts 400ms after the first audio buffer.
445 video->Read(
446 NewReadCB(FROM_HERE,
447 5636,
448 (video_start_time - audio_start_time).InMicroseconds()));
449 message_loop_.Run();
450
451 // Since the audio buffer has a lower first timestamp, it should become
452 // zero.
453 audio->Read(NewReadCB(FROM_HERE, 165, 0));
454 message_loop_.Run();
455
456 // Verify that the start time is equal to the lowest timestamp (ie the
457 // audio).
458 EXPECT_EQ(audio_start_time, demuxer_->start_time());
459
460 // Verify that the timeline offset has been adjusted by the start time.
461 EXPECT_EQ(kTimelineOffsetMs + audio_start_time.InMilliseconds(),
462 demuxer_->GetTimelineOffset().ToJavaTime());
463
464 // Seek back to the beginning and repeat the test.
465 WaitableMessageLoopEvent event;
466 demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
467 event.RunAndWaitForStatus(PIPELINE_OK);
468 }
469 }
470
471 TEST_F(FFmpegDemuxerTest, Read_AudioNoStartTime) {
472 // FFmpeg does not set timestamps when demuxing wave files. Ensure that the
473 // demuxer sets a start time of zero in this case.
474 CreateDemuxer("sfx_s24le.wav");
475 InitializeDemuxer();
476
477 // Run the test twice with a seek in between.
478 for (int i = 0; i < 2; ++i) {
479 demuxer_->GetStream(DemuxerStream::AUDIO)
480 ->Read(NewReadCB(FROM_HERE, 4095, 0));
481 message_loop_.Run();
482 EXPECT_EQ(base::TimeDelta(), demuxer_->start_time());
483
484 // Seek back to the beginning and repeat the test.
485 WaitableMessageLoopEvent event;
486 demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB());
487 event.RunAndWaitForStatus(PIPELINE_OK);
488 }
489 }
490
491 TEST_F(FFmpegDemuxerTest, Read_AudioNegativeStartTimeAndOggDiscard) {
492 // FFmpeg does not set timestamps when demuxing wave files. Ensure that the
acolwell GONE FROM CHROMIUM 2014/06/10 23:20:38 nit: Fix the comment since it talks about wave, bu
DaleCurtis 2014/06/12 00:21:56 Done.
493 // demuxer sets a start time of zero in this case.
494 CreateDemuxer("bear.ogv");
495 InitializeDemuxer();
496 demuxer_->GetStream(DemuxerStream::AUDIO)
497 ->Read(NewReadCBWithCheckedDiscard(FROM_HERE, 40, 0));
498 message_loop_.Run();
499 demuxer_->GetStream(DemuxerStream::AUDIO)
500 ->Read(NewReadCBWithCheckedDiscard(FROM_HERE, 41, 0));
400 message_loop_.Run(); 501 message_loop_.Run();
401 502
402 // Check first buffer in audio stream. 503 // TODO(dalecurtis): This negative timestamp is incorrect and due to an
403 audio->Read(NewReadCB(FROM_HERE, 165, 396000)); 504 // upstream bug: https://trac.ffmpeg.org/ticket/3710. Once fixed this
505 // test should have only positive timestamps and should pass a seek test
506 // similar to the positive and zero start time tests.
acolwell GONE FROM CHROMIUM 2014/06/10 23:20:38 Shouldn't we resolve this before landing this chan
DaleCurtis 2014/06/11 16:59:07 http://git.videolan.org/?p=ffmpeg.git;a=blobdiff;f
507 demuxer_->GetStream(DemuxerStream::AUDIO)
508 ->Read(NewReadCBWithCheckedDiscard(FROM_HERE, 173, -7257));
404 message_loop_.Run(); 509 message_loop_.Run();
405 510
406 // Verify that the start time is equal to the lowest timestamp (ie the audio). 511 demuxer_->GetStream(DemuxerStream::AUDIO)
407 EXPECT_EQ(demuxer_->GetStartTime().InMicroseconds(), 396000); 512 ->Read(NewReadCB(FROM_HERE, 148, 5804));
513 message_loop_.Run();
514 EXPECT_EQ(base::TimeDelta::FromMicroseconds(-2902), demuxer_->start_time());
408 } 515 }
409 516
410 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) { 517 TEST_F(FFmpegDemuxerTest, Read_EndOfStream) {
411 // Verify that end of stream buffers are created. 518 // Verify that end of stream buffers are created.
412 CreateDemuxer("bear-320x240.webm"); 519 CreateDemuxer("bear-320x240.webm");
413 InitializeDemuxer(); 520 InitializeDemuxer();
414 ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO)); 521 ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO));
415 } 522 }
416 523
417 TEST_F(FFmpegDemuxerTest, Read_EndOfStreamText) { 524 TEST_F(FFmpegDemuxerTest, Read_EndOfStreamText) {
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 demuxer_->Stop(event.GetClosure()); 850 demuxer_->Stop(event.GetClosure());
744 event.RunAndWait(); 851 event.RunAndWait();
745 demuxer_.reset(); 852 demuxer_.reset();
746 data_source_.reset(); 853 data_source_.reset();
747 } 854 }
748 } 855 }
749 856
750 #endif 857 #endif
751 858
752 } // namespace media 859 } // namespace media
OLDNEW
« media/filters/ffmpeg_demuxer.cc ('K') | « media/filters/ffmpeg_demuxer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698