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 "media/test/pipeline_integration_test_base.h" | 5 #include "media/test/pipeline_integration_test_base.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
11 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
12 #include "base/memory/scoped_vector.h" | 12 #include "base/memory/scoped_vector.h" |
13 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
14 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
15 #include "media/base/cdm_context.h" | 15 #include "base/threading/thread_task_runner_handle.h" |
16 #include "media/base/cdm_key_information.h" | |
16 #include "media/base/media_log.h" | 17 #include "media/base/media_log.h" |
17 #include "media/base/media_tracks.h" | 18 #include "media/base/media_tracks.h" |
18 #include "media/base/test_data_util.h" | 19 #include "media/base/test_data_util.h" |
19 #include "media/filters/chunk_demuxer.h" | 20 #include "media/base/timestamp_constants.h" |
21 #include "media/cdm/aes_decryptor.h" | |
20 #if !defined(MEDIA_DISABLE_FFMPEG) | 22 #if !defined(MEDIA_DISABLE_FFMPEG) |
21 #include "media/filters/ffmpeg_audio_decoder.h" | 23 #include "media/filters/ffmpeg_audio_decoder.h" |
22 #include "media/filters/ffmpeg_demuxer.h" | 24 #include "media/filters/ffmpeg_demuxer.h" |
23 #include "media/filters/ffmpeg_video_decoder.h" | 25 #include "media/filters/ffmpeg_video_decoder.h" |
24 #endif | 26 #endif |
25 #include "media/filters/file_data_source.h" | 27 #include "media/filters/file_data_source.h" |
26 #include "media/filters/memory_data_source.h" | 28 #include "media/filters/memory_data_source.h" |
27 #include "media/renderers/audio_renderer_impl.h" | 29 #include "media/renderers/audio_renderer_impl.h" |
28 #include "media/renderers/renderer_impl.h" | 30 #include "media/renderers/renderer_impl.h" |
29 #if !defined(MEDIA_DISABLE_LIBVPX) | 31 #if !defined(MEDIA_DISABLE_LIBVPX) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 | 77 |
76 #if !defined(MEDIA_DISABLE_FFMPEG) | 78 #if !defined(MEDIA_DISABLE_FFMPEG) |
77 audio_decoders.push_back( | 79 audio_decoders.push_back( |
78 new FFmpegAudioDecoder(media_task_runner, media_log)); | 80 new FFmpegAudioDecoder(media_task_runner, media_log)); |
79 #endif | 81 #endif |
80 return audio_decoders; | 82 return audio_decoders; |
81 } | 83 } |
82 | 84 |
83 const char kNullVideoHash[] = "d41d8cd98f00b204e9800998ecf8427e"; | 85 const char kNullVideoHash[] = "d41d8cd98f00b204e9800998ecf8427e"; |
84 const char kNullAudioHash[] = "0.00,0.00,0.00,0.00,0.00,0.00,"; | 86 const char kNullAudioHash[] = "0.00,0.00,0.00,0.00,0.00,0.00,"; |
87 const size_t kAppendWholeFile = std::numeric_limits<size_t>::max(); | |
88 | |
89 namespace { | |
DaleCurtis
2017/04/20 18:24:51
Again drop.
xjz
2017/04/20 21:26:10
Done.
| |
90 | |
91 constexpr char kSourceId[] = "SourceId"; | |
92 | |
93 class RendererFactoryImpl final : public PipelineTestRendererFactory { | |
94 public: | |
95 explicit RendererFactoryImpl(PipelineIntegrationTestBase* integration_test) | |
96 : integration_test_(integration_test) {} | |
97 ~RendererFactoryImpl() override {} | |
98 | |
99 // PipelineTestRendererFactory implementation. | |
100 std::unique_ptr<Renderer> CreateRenderer( | |
101 CreateVideoDecodersCB prepend_video_decoders_cb = CreateVideoDecodersCB(), | |
102 CreateAudioDecodersCB prepend_audio_decoders_cb = | |
103 CreateAudioDecodersCB()) override { | |
104 return integration_test_->CreateRenderer(prepend_video_decoders_cb, | |
105 prepend_audio_decoders_cb); | |
106 } | |
107 | |
108 private: | |
109 PipelineIntegrationTestBase* integration_test_; | |
110 | |
111 DISALLOW_COPY_AND_ASSIGN(RendererFactoryImpl); | |
112 }; | |
113 | |
114 } // namespace | |
115 | |
116 MockMediaSource::MockMediaSource(const std::string& filename, | |
117 const std::string& mimetype, | |
118 size_t initial_append_size) | |
119 : current_position_(0), | |
120 initial_append_size_(initial_append_size), | |
121 mimetype_(mimetype), | |
122 chunk_demuxer_(new ChunkDemuxer( | |
123 base::Bind(&MockMediaSource::DemuxerOpened, base::Unretained(this)), | |
124 base::Bind(&MockMediaSource::OnEncryptedMediaInitData, | |
125 base::Unretained(this)), | |
126 &media_log_)), | |
127 owned_chunk_demuxer_(chunk_demuxer_) { | |
128 file_data_ = ReadTestDataFile(filename); | |
129 | |
130 if (initial_append_size_ == kAppendWholeFile) | |
131 initial_append_size_ = file_data_->data_size(); | |
132 | |
133 DCHECK_GT(initial_append_size_, 0u); | |
134 DCHECK_LE(initial_append_size_, file_data_->data_size()); | |
135 } | |
136 | |
137 MockMediaSource::~MockMediaSource() {} | |
138 | |
139 std::unique_ptr<Demuxer> MockMediaSource::GetDemuxer() { | |
140 return std::move(owned_chunk_demuxer_); | |
141 } | |
142 | |
143 void MockMediaSource::set_encrypted_media_init_data_cb( | |
144 const Demuxer::EncryptedMediaInitDataCB& encrypted_media_init_data_cb) { | |
145 encrypted_media_init_data_cb_ = encrypted_media_init_data_cb; | |
146 } | |
147 | |
148 void MockMediaSource::set_demuxer_failure_cb( | |
149 const PipelineStatusCB& demuxer_failure_cb) { | |
150 demuxer_failure_cb_ = demuxer_failure_cb; | |
151 } | |
152 | |
153 void MockMediaSource::Seek(base::TimeDelta seek_time, | |
154 size_t new_position, | |
155 size_t seek_append_size) { | |
156 chunk_demuxer_->StartWaitingForSeek(seek_time); | |
157 | |
158 chunk_demuxer_->ResetParserState(kSourceId, base::TimeDelta(), | |
159 kInfiniteDuration, &last_timestamp_offset_); | |
160 | |
161 DCHECK_LT(new_position, file_data_->data_size()); | |
162 current_position_ = new_position; | |
163 | |
164 AppendData(seek_append_size); | |
165 } | |
166 | |
167 void MockMediaSource::Seek(base::TimeDelta seek_time) { | |
168 chunk_demuxer_->StartWaitingForSeek(seek_time); | |
169 } | |
170 | |
171 void MockMediaSource::AppendData(size_t size) { | |
172 DCHECK(chunk_demuxer_); | |
173 DCHECK_LT(current_position_, file_data_->data_size()); | |
174 DCHECK_LE(current_position_ + size, file_data_->data_size()); | |
175 | |
176 ASSERT_TRUE(chunk_demuxer_->AppendData( | |
177 kSourceId, file_data_->data() + current_position_, size, | |
178 base::TimeDelta(), kInfiniteDuration, &last_timestamp_offset_)); | |
179 current_position_ += size; | |
180 } | |
181 | |
182 bool MockMediaSource::AppendAtTime(base::TimeDelta timestamp_offset, | |
183 const uint8_t* pData, | |
184 int size) { | |
185 CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId)); | |
186 bool success = | |
187 chunk_demuxer_->AppendData(kSourceId, pData, size, base::TimeDelta(), | |
188 kInfiniteDuration, ×tamp_offset); | |
189 last_timestamp_offset_ = timestamp_offset; | |
190 return success; | |
191 } | |
192 | |
193 void MockMediaSource::AppendAtTimeWithWindow( | |
194 base::TimeDelta timestamp_offset, | |
195 base::TimeDelta append_window_start, | |
196 base::TimeDelta append_window_end, | |
197 const uint8_t* pData, | |
198 int size) { | |
199 CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId)); | |
200 ASSERT_TRUE(chunk_demuxer_->AppendData(kSourceId, pData, size, | |
201 append_window_start, append_window_end, | |
202 ×tamp_offset)); | |
203 last_timestamp_offset_ = timestamp_offset; | |
204 } | |
205 | |
206 void MockMediaSource::SetMemoryLimits(size_t limit_bytes) { | |
207 chunk_demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, limit_bytes); | |
208 chunk_demuxer_->SetMemoryLimitsForTest(DemuxerStream::VIDEO, limit_bytes); | |
209 } | |
210 | |
211 void MockMediaSource::EvictCodedFrames(base::TimeDelta currentMediaTime, | |
212 size_t newDataSize) { | |
213 chunk_demuxer_->EvictCodedFrames(kSourceId, currentMediaTime, newDataSize); | |
214 } | |
215 | |
216 void MockMediaSource::RemoveRange(base::TimeDelta start, base::TimeDelta end) { | |
217 chunk_demuxer_->Remove(kSourceId, start, end); | |
218 } | |
219 | |
220 void MockMediaSource::EndOfStream() { | |
221 chunk_demuxer_->MarkEndOfStream(PIPELINE_OK); | |
222 } | |
223 | |
224 void MockMediaSource::Shutdown() { | |
225 if (!chunk_demuxer_) | |
226 return; | |
227 chunk_demuxer_->ResetParserState(kSourceId, base::TimeDelta(), | |
228 kInfiniteDuration, &last_timestamp_offset_); | |
229 chunk_demuxer_->Shutdown(); | |
230 chunk_demuxer_ = NULL; | |
231 } | |
232 | |
233 void MockMediaSource::DemuxerOpened() { | |
234 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
235 FROM_HERE, | |
236 base::Bind(&MockMediaSource::DemuxerOpenedTask, base::Unretained(this))); | |
237 } | |
238 | |
239 void MockMediaSource::DemuxerOpenedTask() { | |
240 ChunkDemuxer::Status status = AddId(); | |
241 if (status != ChunkDemuxer::kOk) { | |
242 CHECK(!demuxer_failure_cb_.is_null()); | |
243 demuxer_failure_cb_.Run(DEMUXER_ERROR_COULD_NOT_OPEN); | |
244 return; | |
245 } | |
246 chunk_demuxer_->SetTracksWatcher( | |
247 kSourceId, base::Bind(&MockMediaSource::InitSegmentReceived, | |
248 base::Unretained(this))); | |
249 | |
250 AppendData(initial_append_size_); | |
251 } | |
252 | |
253 ChunkDemuxer::Status MockMediaSource::AddId() { | |
254 // This code assumes that |mimetype_| is one of the following forms. | |
255 // 1. audio/mpeg | |
256 // 2. video/webm;codec="vorbis,vp8". | |
257 size_t semicolon = mimetype_.find(";"); | |
258 std::string type = mimetype_; | |
259 std::string codecs_param = ""; | |
260 if (semicolon != std::string::npos) { | |
261 type = mimetype_.substr(0, semicolon); | |
262 size_t codecs_param_start = mimetype_.find("codecs=\"", semicolon); | |
263 | |
264 CHECK_NE(codecs_param_start, std::string::npos); | |
265 | |
266 codecs_param_start += 8; // Skip over the codecs=". | |
267 | |
268 size_t codecs_param_end = mimetype_.find("\"", codecs_param_start); | |
269 | |
270 CHECK_NE(codecs_param_end, std::string::npos); | |
271 | |
272 codecs_param = mimetype_.substr(codecs_param_start, | |
273 codecs_param_end - codecs_param_start); | |
274 } | |
275 | |
276 return chunk_demuxer_->AddId(kSourceId, type, codecs_param); | |
277 } | |
278 | |
279 void MockMediaSource::OnEncryptedMediaInitData( | |
280 EmeInitDataType init_data_type, | |
281 const std::vector<uint8_t>& init_data) { | |
282 DCHECK(!init_data.empty()); | |
283 CHECK(!encrypted_media_init_data_cb_.is_null()); | |
284 encrypted_media_init_data_cb_.Run(init_data_type, init_data); | |
285 } | |
286 | |
287 base::TimeDelta MockMediaSource::last_timestamp_offset() const { | |
288 return last_timestamp_offset_; | |
289 } | |
290 | |
291 void MockMediaSource::InitSegmentReceived(std::unique_ptr<MediaTracks> tracks) { | |
292 CHECK(tracks.get()); | |
293 EXPECT_GT(tracks->tracks().size(), 0u); | |
294 CHECK(chunk_demuxer_); | |
295 // Verify that track ids are unique. | |
296 std::set<MediaTrack::Id> track_ids; | |
297 for (const auto& track : tracks->tracks()) { | |
298 EXPECT_EQ(track_ids.end(), track_ids.find(track->id())); | |
299 track_ids.insert(track->id()); | |
300 } | |
301 InitSegmentReceivedMock(tracks); | |
302 } | |
303 | |
304 FakeEncryptedMedia::TestCdmContext::TestCdmContext(Decryptor* decryptor) | |
305 : decryptor_(decryptor) {} | |
306 | |
307 Decryptor* FakeEncryptedMedia::TestCdmContext::GetDecryptor() { | |
308 return decryptor_; | |
309 } | |
310 int FakeEncryptedMedia::TestCdmContext::GetCdmId() const { | |
311 return kInvalidCdmId; | |
312 } | |
313 | |
314 FakeEncryptedMedia::FakeEncryptedMedia(AppBase* app) | |
315 : decryptor_( | |
316 new AesDecryptor(GURL::EmptyGURL(), | |
317 base::Bind(&FakeEncryptedMedia::OnSessionMessage, | |
318 base::Unretained(this)), | |
319 base::Bind(&FakeEncryptedMedia::OnSessionClosed, | |
320 base::Unretained(this)), | |
321 base::Bind(&FakeEncryptedMedia::OnSessionKeysChange, | |
322 base::Unretained(this)))), | |
323 cdm_context_(decryptor_.get()), | |
324 app_(app) {} | |
325 | |
326 FakeEncryptedMedia::~FakeEncryptedMedia() {} | |
327 | |
328 CdmContext* FakeEncryptedMedia::GetCdmContext() { | |
329 return &cdm_context_; | |
330 } | |
331 | |
332 // Callbacks for firing session events. Delegate to |app_|. | |
333 void FakeEncryptedMedia::OnSessionMessage( | |
334 const std::string& session_id, | |
335 ContentDecryptionModule::MessageType message_type, | |
336 const std::vector<uint8_t>& message) { | |
337 app_->OnSessionMessage(session_id, message_type, message, decryptor_.get()); | |
338 } | |
339 | |
340 void FakeEncryptedMedia::OnSessionClosed(const std::string& session_id) { | |
341 app_->OnSessionClosed(session_id); | |
342 } | |
343 | |
344 void FakeEncryptedMedia::OnSessionKeysChange(const std::string& session_id, | |
345 bool has_additional_usable_key, | |
346 CdmKeysInfo keys_info) { | |
347 app_->OnSessionKeysChange(session_id, has_additional_usable_key, | |
348 std::move(keys_info)); | |
349 } | |
350 | |
351 void FakeEncryptedMedia::OnEncryptedMediaInitData( | |
352 EmeInitDataType init_data_type, | |
353 const std::vector<uint8_t>& init_data) { | |
354 app_->OnEncryptedMediaInitData(init_data_type, init_data, decryptor_.get()); | |
355 } | |
85 | 356 |
86 PipelineIntegrationTestBase::PipelineIntegrationTestBase() | 357 PipelineIntegrationTestBase::PipelineIntegrationTestBase() |
87 : hashing_enabled_(false), | 358 : hashing_enabled_(false), |
88 clockless_playback_(false), | 359 clockless_playback_(false), |
89 pipeline_(new PipelineImpl(message_loop_.task_runner(), &media_log_)), | 360 pipeline_(new PipelineImpl(message_loop_.task_runner(), &media_log_)), |
90 ended_(false), | 361 ended_(false), |
91 pipeline_status_(PIPELINE_OK), | 362 pipeline_status_(PIPELINE_OK), |
92 last_video_frame_format_(PIXEL_FORMAT_UNKNOWN), | 363 last_video_frame_format_(PIXEL_FORMAT_UNKNOWN), |
93 last_video_frame_color_space_(COLOR_SPACE_UNSPECIFIED), | 364 last_video_frame_color_space_(COLOR_SPACE_UNSPECIFIED), |
94 current_duration_(kInfiniteDuration) { | 365 current_duration_(kInfiniteDuration), |
366 renderer_factory_(new RendererFactoryImpl(this)) { | |
95 ResetVideoHash(); | 367 ResetVideoHash(); |
96 EXPECT_CALL(*this, OnVideoAverageKeyframeDistanceUpdate()).Times(AnyNumber()); | 368 EXPECT_CALL(*this, OnVideoAverageKeyframeDistanceUpdate()).Times(AnyNumber()); |
97 } | 369 } |
98 | 370 |
99 PipelineIntegrationTestBase::~PipelineIntegrationTestBase() { | 371 PipelineIntegrationTestBase::~PipelineIntegrationTestBase() { |
100 if (pipeline_->IsRunning()) | 372 if (pipeline_->IsRunning()) |
101 Stop(); | 373 Stop(); |
102 | 374 |
103 demuxer_.reset(); | 375 demuxer_.reset(); |
104 pipeline_.reset(); | 376 pipeline_.reset(); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
210 EXPECT_CALL(*this, DecryptorAttached(true)); | 482 EXPECT_CALL(*this, DecryptorAttached(true)); |
211 pipeline_->SetCdm( | 483 pipeline_->SetCdm( |
212 cdm_context, base::Bind(&PipelineIntegrationTestBase::DecryptorAttached, | 484 cdm_context, base::Bind(&PipelineIntegrationTestBase::DecryptorAttached, |
213 base::Unretained(this))); | 485 base::Unretained(this))); |
214 } | 486 } |
215 | 487 |
216 // Should never be called as the required decryption keys for the encrypted | 488 // Should never be called as the required decryption keys for the encrypted |
217 // media files are provided in advance. | 489 // media files are provided in advance. |
218 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0); | 490 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0); |
219 | 491 |
220 pipeline_->Start( | 492 pipeline_->Start(demuxer_.get(), |
221 demuxer_.get(), | 493 renderer_factory_->CreateRenderer(prepend_video_decoders_cb, |
222 CreateRenderer(prepend_video_decoders_cb, prepend_audio_decoders_cb), | 494 prepend_audio_decoders_cb), |
223 this, | 495 this, |
224 base::Bind(&PipelineIntegrationTestBase::OnStatusCallback, | 496 base::Bind(&PipelineIntegrationTestBase::OnStatusCallback, |
225 base::Unretained(this))); | 497 base::Unretained(this))); |
226 base::RunLoop().Run(); | 498 base::RunLoop().Run(); |
227 return pipeline_status_; | 499 return pipeline_status_; |
228 } | 500 } |
229 | 501 |
230 PipelineStatus PipelineIntegrationTestBase::StartWithFile( | 502 PipelineStatus PipelineIntegrationTestBase::StartWithFile( |
231 const std::string& filename, | 503 const std::string& filename, |
232 CdmContext* cdm_context, | 504 CdmContext* cdm_context, |
233 uint8_t test_type, | 505 uint8_t test_type, |
234 CreateVideoDecodersCB prepend_video_decoders_cb, | 506 CreateVideoDecodersCB prepend_video_decoders_cb, |
235 CreateAudioDecodersCB prepend_audio_decoders_cb) { | 507 CreateAudioDecodersCB prepend_audio_decoders_cb) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
291 base::Unretained(this))); | 563 base::Unretained(this))); |
292 base::RunLoop().Run(); | 564 base::RunLoop().Run(); |
293 return (pipeline_status_ == PIPELINE_OK); | 565 return (pipeline_status_ == PIPELINE_OK); |
294 } | 566 } |
295 | 567 |
296 bool PipelineIntegrationTestBase::Resume(base::TimeDelta seek_time) { | 568 bool PipelineIntegrationTestBase::Resume(base::TimeDelta seek_time) { |
297 ended_ = false; | 569 ended_ = false; |
298 | 570 |
299 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 571 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
300 .WillOnce(InvokeWithoutArgs(&message_loop_, &base::MessageLoop::QuitNow)); | 572 .WillOnce(InvokeWithoutArgs(&message_loop_, &base::MessageLoop::QuitNow)); |
301 pipeline_->Resume(CreateRenderer(), seek_time, | 573 pipeline_->Resume(renderer_factory_->CreateRenderer(), seek_time, |
302 base::Bind(&PipelineIntegrationTestBase::OnSeeked, | 574 base::Bind(&PipelineIntegrationTestBase::OnSeeked, |
303 base::Unretained(this), seek_time)); | 575 base::Unretained(this), seek_time)); |
304 base::RunLoop().Run(); | 576 base::RunLoop().Run(); |
305 return (pipeline_status_ == PIPELINE_OK); | 577 return (pipeline_status_ == PIPELINE_OK); |
306 } | 578 } |
307 | 579 |
308 void PipelineIntegrationTestBase::Stop() { | 580 void PipelineIntegrationTestBase::Stop() { |
309 DCHECK(pipeline_->IsRunning()); | 581 DCHECK(pipeline_->IsRunning()); |
310 pipeline_->Stop(); | 582 pipeline_->Stop(); |
311 base::RunLoop().RunUntilIdle(); | 583 base::RunLoop().RunUntilIdle(); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
465 if (clockless_playback_) | 737 if (clockless_playback_) |
466 return clockless_audio_sink_->GetAudioHashForTesting(); | 738 return clockless_audio_sink_->GetAudioHashForTesting(); |
467 return audio_sink_->GetAudioHashForTesting(); | 739 return audio_sink_->GetAudioHashForTesting(); |
468 } | 740 } |
469 | 741 |
470 base::TimeDelta PipelineIntegrationTestBase::GetAudioTime() { | 742 base::TimeDelta PipelineIntegrationTestBase::GetAudioTime() { |
471 DCHECK(clockless_playback_); | 743 DCHECK(clockless_playback_); |
472 return clockless_audio_sink_->render_time(); | 744 return clockless_audio_sink_->render_time(); |
473 } | 745 } |
474 | 746 |
747 PipelineStatus PipelineIntegrationTestBase::StartPipelineWithMediaSource( | |
748 MockMediaSource* source) { | |
749 return StartPipelineWithMediaSource(source, kNormal, nullptr); | |
750 } | |
751 | |
752 PipelineStatus PipelineIntegrationTestBase::StartPipelineWithEncryptedMedia( | |
753 MockMediaSource* source, | |
754 FakeEncryptedMedia* encrypted_media) { | |
755 return StartPipelineWithMediaSource(source, kNormal, encrypted_media); | |
756 } | |
757 | |
758 PipelineStatus PipelineIntegrationTestBase::StartPipelineWithMediaSource( | |
759 MockMediaSource* source, | |
760 uint8_t test_type, | |
761 FakeEncryptedMedia* encrypted_media) { | |
762 hashing_enabled_ = test_type & kHashed; | |
763 clockless_playback_ = test_type & kClockless; | |
764 | |
765 if (!(test_type & kExpectDemuxerFailure)) | |
766 EXPECT_CALL(*source, InitSegmentReceivedMock(_)).Times(AtLeast(1)); | |
767 | |
768 EXPECT_CALL(*this, OnMetadata(_)) | |
769 .Times(AtMost(1)) | |
770 .WillRepeatedly(SaveArg<0>(&metadata_)); | |
771 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) | |
772 .Times(AnyNumber()); | |
773 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)) | |
774 .Times(AnyNumber()); | |
775 EXPECT_CALL(*this, OnDurationChange()).Times(AnyNumber()); | |
776 EXPECT_CALL(*this, OnVideoNaturalSizeChange(_)).Times(AtMost(1)); | |
777 EXPECT_CALL(*this, OnVideoOpacityChange(_)).Times(AtMost(1)); | |
778 | |
779 source->set_demuxer_failure_cb(base::Bind( | |
780 &PipelineIntegrationTestBase::OnStatusCallback, base::Unretained(this))); | |
781 demuxer_ = source->GetDemuxer(); | |
782 | |
783 if (encrypted_media) { | |
784 EXPECT_CALL(*this, DecryptorAttached(true)); | |
785 | |
786 // Encrypted content used but keys provided in advance, so this is | |
787 // never called. | |
788 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0); | |
789 pipeline_->SetCdm( | |
790 encrypted_media->GetCdmContext(), | |
791 base::Bind(&PipelineIntegrationTestBase::DecryptorAttached, | |
792 base::Unretained(this))); | |
793 } else { | |
794 // Encrypted content not used, so this is never called. | |
795 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0); | |
796 } | |
797 | |
798 pipeline_->Start(demuxer_.get(), renderer_factory_->CreateRenderer(), this, | |
799 base::Bind(&PipelineIntegrationTestBase::OnStatusCallback, | |
800 base::Unretained(this))); | |
801 | |
802 if (encrypted_media) { | |
803 source->set_encrypted_media_init_data_cb( | |
804 base::Bind(&FakeEncryptedMedia::OnEncryptedMediaInitData, | |
805 base::Unretained(encrypted_media))); | |
806 } | |
807 base::RunLoop().Run(); | |
808 return pipeline_status_; | |
809 } | |
810 | |
811 // Verifies that seeking works properly for ChunkDemuxer when the | |
812 // seek happens while there is a pending read on the ChunkDemuxer | |
813 // and no data is available. | |
814 bool PipelineIntegrationTestBase::TestSeekDuringRead( | |
815 const std::string& filename, | |
816 const std::string& mimetype, | |
817 int initial_append_size, | |
818 base::TimeDelta start_seek_time, | |
819 base::TimeDelta seek_time, | |
820 int seek_file_position, | |
821 int seek_append_size) { | |
822 MockMediaSource source(filename, mimetype, initial_append_size); | |
823 | |
824 if (StartPipelineWithMediaSource(&source) != PIPELINE_OK) | |
825 return false; | |
826 | |
827 Play(); | |
828 if (!WaitUntilCurrentTimeIsAfter(start_seek_time)) | |
829 return false; | |
830 | |
831 source.Seek(seek_time, seek_file_position, seek_append_size); | |
832 if (!Seek(seek_time)) | |
833 return false; | |
834 | |
835 source.EndOfStream(); | |
836 | |
837 source.Shutdown(); | |
838 Stop(); | |
839 return true; | |
840 } | |
841 | |
475 base::TimeTicks DummyTickClock::NowTicks() { | 842 base::TimeTicks DummyTickClock::NowTicks() { |
476 now_ += base::TimeDelta::FromSeconds(60); | 843 now_ += base::TimeDelta::FromSeconds(60); |
477 return now_; | 844 return now_; |
478 } | 845 } |
479 | 846 |
480 } // namespace media | 847 } // namespace media |
OLD | NEW |