OLD | NEW |
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/file_path.h" | 10 #include "base/file_path.h" |
11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
12 #include "base/path_service.h" | 12 #include "base/path_service.h" |
13 #include "base/threading/thread.h" | 13 #include "base/threading/thread.h" |
14 #include "media/base/mock_callback.h" | |
15 #include "media/base/mock_demuxer_host.h" | 14 #include "media/base/mock_demuxer_host.h" |
| 15 #include "media/base/test_helpers.h" |
16 #include "media/ffmpeg/ffmpeg_common.h" | 16 #include "media/ffmpeg/ffmpeg_common.h" |
17 #include "media/filters/ffmpeg_demuxer.h" | 17 #include "media/filters/ffmpeg_demuxer.h" |
18 #include "media/filters/file_data_source.h" | 18 #include "media/filters/file_data_source.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
20 | 20 |
21 using ::testing::AnyNumber; | 21 using ::testing::AnyNumber; |
22 using ::testing::DoAll; | 22 using ::testing::DoAll; |
23 using ::testing::InSequence; | 23 using ::testing::InSequence; |
24 using ::testing::Invoke; | 24 using ::testing::Invoke; |
25 using ::testing::Return; | 25 using ::testing::Return; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 | 80 |
81 CreateDataSource(name); | 81 CreateDataSource(name); |
82 demuxer_ = new FFmpegDemuxer(message_loop_.message_loop_proxy(), | 82 demuxer_ = new FFmpegDemuxer(message_loop_.message_loop_proxy(), |
83 data_source_); | 83 data_source_); |
84 } | 84 } |
85 | 85 |
86 MOCK_METHOD1(CheckPoint, void(int v)); | 86 MOCK_METHOD1(CheckPoint, void(int v)); |
87 | 87 |
88 void InitializeDemuxer() { | 88 void InitializeDemuxer() { |
89 EXPECT_CALL(host_, SetDuration(_)); | 89 EXPECT_CALL(host_, SetDuration(_)); |
90 demuxer_->Initialize(&host_, NewStatusCB(PIPELINE_OK)); | 90 WaitableMessageLoopEvent event; |
91 message_loop_.Run(); | 91 demuxer_->Initialize(&host_, event.GetPipelineStatusCB()); |
| 92 event.RunAndWaitForStatus(PIPELINE_OK); |
92 } | 93 } |
93 | 94 |
94 MOCK_METHOD2(OnReadDoneCalled, void(int, int64)); | 95 MOCK_METHOD2(OnReadDoneCalled, void(int, int64)); |
95 | 96 |
96 // Verifies that |buffer| has a specific |size| and |timestamp|. | 97 // Verifies that |buffer| has a specific |size| and |timestamp|. |
97 // |location| simply indicates where the call to this function was made. | 98 // |location| simply indicates where the call to this function was made. |
98 // This makes it easier to track down where test failures occur. | 99 // This makes it easier to track down where test failures occur. |
99 void OnReadDone(const tracked_objects::Location& location, | 100 void OnReadDone(const tracked_objects::Location& location, |
100 int size, int64 timestampInMicroseconds, | 101 int size, int64 timestampInMicroseconds, |
101 DemuxerStream::Status status, | 102 DemuxerStream::Status status, |
(...skipping 13 matching lines...) Expand all Loading... |
115 message_loop_.PostTask(FROM_HERE, MessageLoop::QuitWhenIdleClosure()); | 116 message_loop_.PostTask(FROM_HERE, MessageLoop::QuitWhenIdleClosure()); |
116 } | 117 } |
117 | 118 |
118 DemuxerStream::ReadCB NewReadCB(const tracked_objects::Location& location, | 119 DemuxerStream::ReadCB NewReadCB(const tracked_objects::Location& location, |
119 int size, int64 timestampInMicroseconds) { | 120 int size, int64 timestampInMicroseconds) { |
120 EXPECT_CALL(*this, OnReadDoneCalled(size, timestampInMicroseconds)); | 121 EXPECT_CALL(*this, OnReadDoneCalled(size, timestampInMicroseconds)); |
121 return base::Bind(&FFmpegDemuxerTest::OnReadDone, base::Unretained(this), | 122 return base::Bind(&FFmpegDemuxerTest::OnReadDone, base::Unretained(this), |
122 location, size, timestampInMicroseconds); | 123 location, size, timestampInMicroseconds); |
123 } | 124 } |
124 | 125 |
125 PipelineStatusCB NewStatusCB(PipelineStatus expected) { | |
126 return base::Bind(&FFmpegDemuxerTest::OnStatusDone, | |
127 base::Unretained(this), expected); | |
128 } | |
129 | |
130 void OnStatusDone(PipelineStatus expected, PipelineStatus status) { | |
131 EXPECT_EQ(expected, status); | |
132 | |
133 DCHECK_EQ(&message_loop_, MessageLoop::current()); | |
134 message_loop_.PostTask(FROM_HERE, MessageLoop::QuitWhenIdleClosure()); | |
135 } | |
136 | |
137 // Accessor to demuxer internals. | 126 // Accessor to demuxer internals. |
138 void set_duration_known(bool duration_known) { | 127 void set_duration_known(bool duration_known) { |
139 demuxer_->duration_known_ = duration_known; | 128 demuxer_->duration_known_ = duration_known; |
140 } | 129 } |
141 | 130 |
142 bool IsStreamStopped(DemuxerStream::Type type) { | 131 bool IsStreamStopped(DemuxerStream::Type type) { |
143 DemuxerStream* stream = demuxer_->GetStream(type); | 132 DemuxerStream* stream = demuxer_->GetStream(type); |
144 CHECK(stream); | 133 CHECK(stream); |
145 return static_cast<FFmpegDemuxerStream*>(stream)->stopped_; | 134 return static_cast<FFmpegDemuxerStream*>(stream)->stopped_; |
146 } | 135 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 data_source_ = new FileDataSource(); | 174 data_source_ = new FileDataSource(); |
186 EXPECT_TRUE(data_source_->Initialize(file_path)); | 175 EXPECT_TRUE(data_source_->Initialize(file_path)); |
187 } | 176 } |
188 | 177 |
189 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest); | 178 DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest); |
190 }; | 179 }; |
191 | 180 |
192 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { | 181 TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { |
193 // Simulate avformat_open_input() failing. | 182 // Simulate avformat_open_input() failing. |
194 CreateDemuxer("ten_byte_file"); | 183 CreateDemuxer("ten_byte_file"); |
195 demuxer_->Initialize(&host_, NewStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); | 184 WaitableMessageLoopEvent event; |
196 message_loop_.Run(); | 185 demuxer_->Initialize(&host_, event.GetPipelineStatusCB()); |
| 186 event.RunAndWaitForStatus(DEMUXER_ERROR_COULD_NOT_OPEN); |
197 } | 187 } |
198 | 188 |
199 // TODO(acolwell): Uncomment this test when we discover a file that passes | 189 // TODO(acolwell): Uncomment this test when we discover a file that passes |
200 // avformat_open_input(), but has avformat_find_stream_info() fail. | 190 // avformat_open_input(), but has avformat_find_stream_info() fail. |
201 // | 191 // |
202 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) { | 192 //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) { |
203 // ("find_stream_info_fail.webm"); | 193 // ("find_stream_info_fail.webm"); |
204 // demuxer_->Initialize( | 194 // demuxer_->Initialize( |
205 // &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE)); | 195 // &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE)); |
206 // message_loop_.RunUntilIdle(); | 196 // message_loop_.RunUntilIdle(); |
207 //} | 197 //} |
208 | 198 |
209 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) { | 199 TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) { |
210 // Open a file with no streams whatsoever. | 200 // Open a file with no streams whatsoever. |
211 CreateDemuxer("no_streams.webm"); | 201 CreateDemuxer("no_streams.webm"); |
212 demuxer_->Initialize(&host_, NewStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); | 202 WaitableMessageLoopEvent event; |
213 message_loop_.Run(); | 203 demuxer_->Initialize(&host_, event.GetPipelineStatusCB()); |
| 204 event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); |
214 } | 205 } |
215 | 206 |
216 TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) { | 207 TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) { |
217 // Open a file containing streams but none of which are audio/video streams. | 208 // Open a file containing streams but none of which are audio/video streams. |
218 CreateDemuxer("no_audio_video.webm"); | 209 CreateDemuxer("no_audio_video.webm"); |
219 demuxer_->Initialize(&host_, NewStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); | 210 WaitableMessageLoopEvent event; |
220 message_loop_.Run(); | 211 demuxer_->Initialize(&host_, event.GetPipelineStatusCB()); |
| 212 event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); |
221 } | 213 } |
222 | 214 |
223 TEST_F(FFmpegDemuxerTest, Initialize_Successful) { | 215 TEST_F(FFmpegDemuxerTest, Initialize_Successful) { |
224 CreateDemuxer("bear-320x240.webm"); | 216 CreateDemuxer("bear-320x240.webm"); |
225 InitializeDemuxer(); | 217 InitializeDemuxer(); |
226 | 218 |
227 // Video stream should be present. | 219 // Video stream should be present. |
228 scoped_refptr<DemuxerStream> stream = | 220 scoped_refptr<DemuxerStream> stream = |
229 demuxer_->GetStream(DemuxerStream::VIDEO); | 221 demuxer_->GetStream(DemuxerStream::VIDEO); |
230 ASSERT_TRUE(stream); | 222 ASSERT_TRUE(stream); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 scoped_refptr<DemuxerStream> audio = | 365 scoped_refptr<DemuxerStream> audio = |
374 demuxer_->GetStream(DemuxerStream::AUDIO); | 366 demuxer_->GetStream(DemuxerStream::AUDIO); |
375 ASSERT_TRUE(video); | 367 ASSERT_TRUE(video); |
376 ASSERT_TRUE(audio); | 368 ASSERT_TRUE(audio); |
377 | 369 |
378 // Read a video packet and release it. | 370 // Read a video packet and release it. |
379 video->Read(NewReadCB(FROM_HERE, 22084, 0)); | 371 video->Read(NewReadCB(FROM_HERE, 22084, 0)); |
380 message_loop_.Run(); | 372 message_loop_.Run(); |
381 | 373 |
382 // Issue a simple forward seek, which should discard queued packets. | 374 // Issue a simple forward seek, which should discard queued packets. |
| 375 WaitableMessageLoopEvent event; |
383 demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000), | 376 demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000), |
384 NewStatusCB(PIPELINE_OK)); | 377 event.GetPipelineStatusCB()); |
385 message_loop_.Run(); | 378 event.RunAndWaitForStatus(PIPELINE_OK); |
386 | 379 |
387 // Audio read #1. | 380 // Audio read #1. |
388 audio->Read(NewReadCB(FROM_HERE, 145, 803000)); | 381 audio->Read(NewReadCB(FROM_HERE, 145, 803000)); |
389 message_loop_.Run(); | 382 message_loop_.Run(); |
390 | 383 |
391 // Audio read #2. | 384 // Audio read #2. |
392 audio->Read(NewReadCB(FROM_HERE, 148, 826000)); | 385 audio->Read(NewReadCB(FROM_HERE, 148, 826000)); |
393 message_loop_.Run(); | 386 message_loop_.Run(); |
394 | 387 |
395 // Video read #1. | 388 // Video read #1. |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 scoped_refptr<DemuxerStream> audio = | 539 scoped_refptr<DemuxerStream> audio = |
547 demuxer_->GetStream(DemuxerStream::AUDIO); | 540 demuxer_->GetStream(DemuxerStream::AUDIO); |
548 ASSERT_TRUE(video); | 541 ASSERT_TRUE(video); |
549 ASSERT_TRUE(audio); | 542 ASSERT_TRUE(audio); |
550 | 543 |
551 // Read a video packet and release it. | 544 // Read a video packet and release it. |
552 video->Read(NewReadCB(FROM_HERE, 22084, 0)); | 545 video->Read(NewReadCB(FROM_HERE, 22084, 0)); |
553 message_loop_.Run(); | 546 message_loop_.Run(); |
554 | 547 |
555 // Issue a simple forward seek, which should discard queued packets. | 548 // Issue a simple forward seek, which should discard queued packets. |
| 549 WaitableMessageLoopEvent event; |
556 demuxer_->Seek(base::TimeDelta::FromMicroseconds(2500000), | 550 demuxer_->Seek(base::TimeDelta::FromMicroseconds(2500000), |
557 NewStatusCB(PIPELINE_OK)); | 551 event.GetPipelineStatusCB()); |
558 message_loop_.Run(); | 552 event.RunAndWaitForStatus(PIPELINE_OK); |
559 | 553 |
560 // Audio read #1. | 554 // Audio read #1. |
561 audio->Read(NewReadCB(FROM_HERE, 40, 2403000)); | 555 audio->Read(NewReadCB(FROM_HERE, 40, 2403000)); |
562 message_loop_.Run(); | 556 message_loop_.Run(); |
563 | 557 |
564 // Audio read #2. | 558 // Audio read #2. |
565 audio->Read(NewReadCB(FROM_HERE, 42, 2406000)); | 559 audio->Read(NewReadCB(FROM_HERE, 42, 2406000)); |
566 message_loop_.Run(); | 560 message_loop_.Run(); |
567 | 561 |
568 // Video read #1. | 562 // Video read #1. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 TEST_F(FFmpegDemuxerTest, UnsupportedVideoSupportedAudioDemux) { | 610 TEST_F(FFmpegDemuxerTest, UnsupportedVideoSupportedAudioDemux) { |
617 CreateDemuxer("vorbis_audio_wmv_video.mkv"); | 611 CreateDemuxer("vorbis_audio_wmv_video.mkv"); |
618 InitializeDemuxer(); | 612 InitializeDemuxer(); |
619 | 613 |
620 // Ensure the expected streams are present. | 614 // Ensure the expected streams are present. |
621 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO)); | 615 EXPECT_FALSE(demuxer_->GetStream(DemuxerStream::VIDEO)); |
622 EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO)); | 616 EXPECT_TRUE(demuxer_->GetStream(DemuxerStream::AUDIO)); |
623 } | 617 } |
624 | 618 |
625 } // namespace media | 619 } // namespace media |
OLD | NEW |