Chromium Code Reviews| 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 |