Chromium Code Reviews| Index: media/filters/ffmpeg_demuxer_unittest.cc |
| diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc |
| index a1614a421297fb83681baa506cbe683d8dd4de22..588ff4a179e41d7d840bfb4a4933598478ab39c7 100644 |
| --- a/media/filters/ffmpeg_demuxer_unittest.cc |
| +++ b/media/filters/ffmpeg_demuxer_unittest.cc |
| @@ -103,13 +103,27 @@ class FFmpegDemuxerTest : public testing::Test { |
| InitializeDemuxerText(false); |
| } |
| + void InitializeDemuxerWithTimelineOffset(const char* utc_date) { |
| + EXPECT_CALL(host_, SetDuration(_)); |
| + WaitableMessageLoopEvent event; |
| + demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), false); |
| + // Inject the timeline offset into the FFmpeg metadata dictionary. |
| + av_dict_set(&demuxer_->glue_->format_context()->metadata, |
| + "creation_time", |
| + utc_date, |
| + 0); |
| + event.RunAndWaitForStatus(PIPELINE_OK); |
| + } |
| + |
| MOCK_METHOD2(OnReadDoneCalled, void(int, int64)); |
| // Verifies that |buffer| has a specific |size| and |timestamp|. |
| // |location| simply indicates where the call to this function was made. |
| // This makes it easier to track down where test failures occur. |
| void OnReadDone(const tracked_objects::Location& location, |
| - int size, int64 timestampInMicroseconds, |
| + int size, |
| + int64 timestamp_us, |
| + bool should_be_marked_for_discard, |
| DemuxerStream::Status status, |
| const scoped_refptr<DecoderBuffer>& buffer) { |
| std::string location_str; |
| @@ -117,21 +131,41 @@ class FFmpegDemuxerTest : public testing::Test { |
| location_str += "\n"; |
| SCOPED_TRACE(location_str); |
| EXPECT_EQ(status, DemuxerStream::kOk); |
| - OnReadDoneCalled(size, timestampInMicroseconds); |
| + OnReadDoneCalled(size, timestamp_us); |
| EXPECT_TRUE(buffer.get() != NULL); |
| EXPECT_EQ(size, buffer->data_size()); |
| - EXPECT_EQ(base::TimeDelta::FromMicroseconds(timestampInMicroseconds), |
| - buffer->timestamp()); |
| + EXPECT_EQ(timestamp_us, buffer->timestamp().InMicroseconds()); |
| + const base::TimeDelta expected_front_discard = |
| + should_be_marked_for_discard ? kInfiniteDuration() : base::TimeDelta(); |
| + EXPECT_EQ(expected_front_discard, buffer->discard_padding().first); |
| DCHECK_EQ(&message_loop_, base::MessageLoop::current()); |
| message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); |
| } |
| DemuxerStream::ReadCB NewReadCB(const tracked_objects::Location& location, |
| - int size, int64 timestampInMicroseconds) { |
| - EXPECT_CALL(*this, OnReadDoneCalled(size, timestampInMicroseconds)); |
| - return base::Bind(&FFmpegDemuxerTest::OnReadDone, base::Unretained(this), |
| - location, size, timestampInMicroseconds); |
| + int size, |
| + int64 timestamp_us) { |
| + EXPECT_CALL(*this, OnReadDoneCalled(size, timestamp_us)); |
| + return base::Bind(&FFmpegDemuxerTest::OnReadDone, |
| + base::Unretained(this), |
| + location, |
| + size, |
| + timestamp_us, |
| + false); |
| + } |
| + |
| + DemuxerStream::ReadCB NewReadCBWithCheckedDiscard( |
| + const tracked_objects::Location& location, |
| + int size, |
| + int64 timestamp_us) { |
| + EXPECT_CALL(*this, OnReadDoneCalled(size, timestamp_us)); |
| + return base::Bind(&FFmpegDemuxerTest::OnReadDone, |
| + base::Unretained(this), |
| + location, |
| + size, |
| + timestamp_us, |
| + true); |
| } |
| // TODO(xhwang): This is a workaround of the issue that move-only parameters |
| @@ -386,25 +420,98 @@ TEST_F(FFmpegDemuxerTest, Read_Text) { |
| message_loop_.Run(); |
| } |
| -TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) { |
| +TEST_F(FFmpegDemuxerTest, Read_VideoPositiveStartTime) { |
| + const char kTimelineOffset[] = "2012-11-10 12:34:56"; |
| + const int64 kTimelineOffsetMs = 1352550896000LL; |
| + |
| // Test the start time is the first timestamp of the video and audio stream. |
| CreateDemuxer("nonzero-start-time.webm"); |
| - InitializeDemuxer(); |
| + InitializeDemuxerWithTimelineOffset(kTimelineOffset); |
| // Attempt a read from the video stream and run the message loop until done. |
| DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO); |
| DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO); |
| - // Check first buffer in video stream. |
| - video->Read(NewReadCB(FROM_HERE, 5636, 400000)); |
| + const base::TimeDelta video_start_time = |
| + base::TimeDelta::FromMicroseconds(400000); |
| + const base::TimeDelta audio_start_time = |
| + base::TimeDelta::FromMicroseconds(396000); |
| + |
| + // Run the test twice with a seek in between. |
| + for (int i = 0; i < 2; ++i) { |
| + // Check first buffer in video stream. It should have been adjusted such |
| + // that |
| + // it starts 400ms after the first audio buffer. |
| + video->Read( |
| + NewReadCB(FROM_HERE, |
| + 5636, |
| + (video_start_time - audio_start_time).InMicroseconds())); |
| + message_loop_.Run(); |
| + |
| + // Since the audio buffer has a lower first timestamp, it should become |
| + // zero. |
| + audio->Read(NewReadCB(FROM_HERE, 165, 0)); |
| + message_loop_.Run(); |
| + |
| + // Verify that the start time is equal to the lowest timestamp (ie the |
| + // audio). |
| + EXPECT_EQ(audio_start_time, demuxer_->start_time()); |
| + |
| + // Verify that the timeline offset has been adjusted by the start time. |
| + EXPECT_EQ(kTimelineOffsetMs + audio_start_time.InMilliseconds(), |
| + demuxer_->GetTimelineOffset().ToJavaTime()); |
| + |
| + // Seek back to the beginning and repeat the test. |
| + WaitableMessageLoopEvent event; |
| + demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB()); |
| + event.RunAndWaitForStatus(PIPELINE_OK); |
| + } |
| +} |
| + |
| +TEST_F(FFmpegDemuxerTest, Read_AudioNoStartTime) { |
| + // FFmpeg does not set timestamps when demuxing wave files. Ensure that the |
| + // demuxer sets a start time of zero in this case. |
| + CreateDemuxer("sfx_s24le.wav"); |
| + InitializeDemuxer(); |
| + |
| + // Run the test twice with a seek in between. |
| + for (int i = 0; i < 2; ++i) { |
| + demuxer_->GetStream(DemuxerStream::AUDIO) |
| + ->Read(NewReadCB(FROM_HERE, 4095, 0)); |
| + message_loop_.Run(); |
| + EXPECT_EQ(base::TimeDelta(), demuxer_->start_time()); |
| + |
| + // Seek back to the beginning and repeat the test. |
| + WaitableMessageLoopEvent event; |
| + demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB()); |
| + event.RunAndWaitForStatus(PIPELINE_OK); |
| + } |
| +} |
| + |
| +TEST_F(FFmpegDemuxerTest, Read_AudioNegativeStartTimeAndOggDiscard) { |
| + // 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.
|
| + // demuxer sets a start time of zero in this case. |
| + CreateDemuxer("bear.ogv"); |
| + InitializeDemuxer(); |
| + demuxer_->GetStream(DemuxerStream::AUDIO) |
| + ->Read(NewReadCBWithCheckedDiscard(FROM_HERE, 40, 0)); |
| + message_loop_.Run(); |
| + demuxer_->GetStream(DemuxerStream::AUDIO) |
| + ->Read(NewReadCBWithCheckedDiscard(FROM_HERE, 41, 0)); |
| message_loop_.Run(); |
| - // Check first buffer in audio stream. |
| - audio->Read(NewReadCB(FROM_HERE, 165, 396000)); |
| + // TODO(dalecurtis): This negative timestamp is incorrect and due to an |
| + // upstream bug: https://trac.ffmpeg.org/ticket/3710. Once fixed this |
| + // test should have only positive timestamps and should pass a seek test |
| + // 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
|
| + demuxer_->GetStream(DemuxerStream::AUDIO) |
| + ->Read(NewReadCBWithCheckedDiscard(FROM_HERE, 173, -7257)); |
| message_loop_.Run(); |
| - // Verify that the start time is equal to the lowest timestamp (ie the audio). |
| - EXPECT_EQ(demuxer_->GetStartTime().InMicroseconds(), 396000); |
| + demuxer_->GetStream(DemuxerStream::AUDIO) |
| + ->Read(NewReadCB(FROM_HERE, 148, 5804)); |
| + message_loop_.Run(); |
| + EXPECT_EQ(base::TimeDelta::FromMicroseconds(-2902), demuxer_->start_time()); |
| } |
| TEST_F(FFmpegDemuxerTest, Read_EndOfStream) { |