| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/filters/decoder_stream.h" | 5 #include "media/filters/decoder_stream.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 state_(STATE_UNINITIALIZED), | 52 state_(STATE_UNINITIALIZED), |
| 53 stream_(NULL), | 53 stream_(NULL), |
| 54 decoder_selector_(new DecoderSelector<StreamType>(task_runner, | 54 decoder_selector_(new DecoderSelector<StreamType>(task_runner, |
| 55 std::move(decoders), | 55 std::move(decoders), |
| 56 media_log)), | 56 media_log)), |
| 57 decoded_frames_since_fallback_(0), | 57 decoded_frames_since_fallback_(0), |
| 58 active_splice_(false), | 58 active_splice_(false), |
| 59 decoding_eos_(false), | 59 decoding_eos_(false), |
| 60 pending_decode_requests_(0), | 60 pending_decode_requests_(0), |
| 61 duration_tracker_(8), | 61 duration_tracker_(8), |
| 62 weak_factory_(this) {} | 62 weak_factory_(this), |
| 63 fallback_weak_factory_(this) {} |
| 63 | 64 |
| 64 template <DemuxerStream::Type StreamType> | 65 template <DemuxerStream::Type StreamType> |
| 65 DecoderStream<StreamType>::~DecoderStream() { | 66 DecoderStream<StreamType>::~DecoderStream() { |
| 66 FUNCTION_DVLOG(2); | 67 FUNCTION_DVLOG(2); |
| 67 DCHECK(task_runner_->BelongsToCurrentThread()); | 68 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 68 | 69 |
| 69 decoder_selector_.reset(); | 70 decoder_selector_.reset(); |
| 70 | 71 |
| 71 if (!init_cb_.is_null()) { | 72 if (!init_cb_.is_null()) { |
| 72 task_runner_->PostTask(FROM_HERE, | 73 task_runner_->PostTask(FROM_HERE, |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 : base::TimeDelta(); | 225 : base::TimeDelta(); |
| 225 } | 226 } |
| 226 | 227 |
| 227 template <DemuxerStream::Type StreamType> | 228 template <DemuxerStream::Type StreamType> |
| 228 void DecoderStream<StreamType>::SelectDecoder(CdmContext* cdm_context) { | 229 void DecoderStream<StreamType>::SelectDecoder(CdmContext* cdm_context) { |
| 229 decoder_selector_->SelectDecoder( | 230 decoder_selector_->SelectDecoder( |
| 230 stream_, cdm_context, | 231 stream_, cdm_context, |
| 231 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, | 232 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, |
| 232 weak_factory_.GetWeakPtr()), | 233 weak_factory_.GetWeakPtr()), |
| 233 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, | 234 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, |
| 234 weak_factory_.GetWeakPtr()), | 235 fallback_weak_factory_.GetWeakPtr()), |
| 235 waiting_for_decryption_key_cb_); | 236 waiting_for_decryption_key_cb_); |
| 236 } | 237 } |
| 237 | 238 |
| 238 template <DemuxerStream::Type StreamType> | 239 template <DemuxerStream::Type StreamType> |
| 239 void DecoderStream<StreamType>::OnDecoderSelected( | 240 void DecoderStream<StreamType>::OnDecoderSelected( |
| 240 scoped_ptr<Decoder> selected_decoder, | 241 scoped_ptr<Decoder> selected_decoder, |
| 241 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { | 242 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { |
| 242 FUNCTION_DVLOG(2) << ": " | 243 FUNCTION_DVLOG(2) << ": " |
| 243 << (selected_decoder ? selected_decoder->GetDisplayName() | 244 << (selected_decoder ? selected_decoder->GetDisplayName() |
| 244 : "No decoder selected."); | 245 : "No decoder selected."); |
| 245 DCHECK(task_runner_->BelongsToCurrentThread()); | 246 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 246 DCHECK(state_ == STATE_INITIALIZING || state_ == STATE_REINITIALIZING_DECODER) | 247 DCHECK(state_ == STATE_INITIALIZING || |
| 248 state_ == STATE_REINITIALIZING_DECODER || |
| 249 state_ == STATE_CONFIG_CHANGE_RECEIVED_WHILE_REINITIALIZING_DECODER) |
| 247 << state_; | 250 << state_; |
| 248 if (state_ == STATE_INITIALIZING) { | 251 if (state_ == STATE_INITIALIZING) { |
| 249 DCHECK(!init_cb_.is_null()); | 252 DCHECK(!init_cb_.is_null()); |
| 250 DCHECK(read_cb_.is_null()); | 253 DCHECK(read_cb_.is_null()); |
| 251 DCHECK(reset_cb_.is_null()); | 254 DCHECK(reset_cb_.is_null()); |
| 252 } else { | 255 } else if (state_ == STATE_REINITIALIZING_DECODER) { |
| 253 DCHECK(decoder_); | 256 DCHECK(decoder_); |
| 254 } | 257 } |
| 255 | 258 |
| 256 previous_decoder_ = std::move(decoder_); | 259 previous_decoder_ = std::move(decoder_); |
| 257 decoded_frames_since_fallback_ = 0; | 260 decoded_frames_since_fallback_ = 0; |
| 258 decoder_ = std::move(selected_decoder); | 261 decoder_ = std::move(selected_decoder); |
| 259 if (decrypting_demuxer_stream) { | 262 if (decrypting_demuxer_stream) { |
| 260 decrypting_demuxer_stream_ = std::move(decrypting_demuxer_stream); | 263 decrypting_demuxer_stream_ = std::move(decrypting_demuxer_stream); |
| 261 stream_ = decrypting_demuxer_stream_.get(); | 264 stream_ = decrypting_demuxer_stream_.get(); |
| 262 } | 265 } |
| 263 | 266 |
| 267 // TODO(tguilbert): crbug.com/603713 support config changes on decoder reinit. |
| 268 if (state_ == STATE_CONFIG_CHANGE_RECEIVED_WHILE_REINITIALIZING_DECODER) { |
| 269 CompleteDecoderReinitialization(false); |
| 270 return; |
| 271 } |
| 272 |
| 273 // Attempt to decode buffers from previous decoders (when those decoders have |
| 274 // never successfully outputed a frame). |
| 275 fallback_buffers_ = pending_buffers_; |
| 276 |
| 264 if (!decoder_) { | 277 if (!decoder_) { |
| 265 if (state_ == STATE_INITIALIZING) { | 278 if (state_ == STATE_INITIALIZING) { |
| 266 state_ = STATE_UNINITIALIZED; | 279 state_ = STATE_UNINITIALIZED; |
| 267 MEDIA_LOG(ERROR, media_log_) << GetStreamTypeString() | 280 MEDIA_LOG(ERROR, media_log_) << GetStreamTypeString() |
| 268 << " decoder initialization failed"; | 281 << " decoder initialization failed"; |
| 269 base::ResetAndReturn(&init_cb_).Run(false); | 282 base::ResetAndReturn(&init_cb_).Run(false); |
| 270 } else { | 283 } else { |
| 271 CompleteDecoderReinitialization(false); | 284 CompleteDecoderReinitialization(false); |
| 272 } | 285 } |
| 273 return; | 286 return; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 295 Status status, | 308 Status status, |
| 296 const scoped_refptr<Output>& output) { | 309 const scoped_refptr<Output>& output) { |
| 297 DCHECK(!read_cb_.is_null()); | 310 DCHECK(!read_cb_.is_null()); |
| 298 base::ResetAndReturn(&read_cb_).Run(status, output); | 311 base::ResetAndReturn(&read_cb_).Run(status, output); |
| 299 } | 312 } |
| 300 | 313 |
| 301 template <DemuxerStream::Type StreamType> | 314 template <DemuxerStream::Type StreamType> |
| 302 void DecoderStream<StreamType>::Decode( | 315 void DecoderStream<StreamType>::Decode( |
| 303 const scoped_refptr<DecoderBuffer>& buffer) { | 316 const scoped_refptr<DecoderBuffer>& buffer) { |
| 304 FUNCTION_DVLOG(2); | 317 FUNCTION_DVLOG(2); |
| 318 |
| 319 // We don't know if the decoder will error out on first decode yet. Save the |
| 320 // buffer to feed it to the fallback decoder later if needed. |
| 321 if (!decoded_frames_since_fallback_) |
| 322 pending_buffers_.push_back(buffer); |
| 323 |
| 324 DecodeInternal(buffer); |
| 325 } |
| 326 |
| 327 template <DemuxerStream::Type StreamType> |
| 328 void DecoderStream<StreamType>::DecodeInternal( |
| 329 const scoped_refptr<DecoderBuffer>& buffer) { |
| 330 FUNCTION_DVLOG(2); |
| 305 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 331 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; |
| 306 DCHECK_LT(pending_decode_requests_, GetMaxDecodeRequests()); | 332 DCHECK_LT(pending_decode_requests_, GetMaxDecodeRequests()); |
| 307 DCHECK(reset_cb_.is_null()); | 333 DCHECK(reset_cb_.is_null()); |
| 308 DCHECK(buffer.get()); | 334 DCHECK(buffer.get()); |
| 309 | 335 |
| 310 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); | 336 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); |
| 311 | 337 |
| 312 TRACE_EVENT_ASYNC_BEGIN2( | 338 TRACE_EVENT_ASYNC_BEGIN2( |
| 313 "media", GetTraceString<StreamType>(), this, "key frame", | 339 "media", GetTraceString<StreamType>(), this, "key frame", |
| 314 !buffer->end_of_stream() && buffer->is_key_frame(), "timestamp (ms)", | 340 !buffer->end_of_stream() && buffer->is_key_frame(), "timestamp (ms)", |
| 315 !buffer->end_of_stream() ? buffer->timestamp().InMilliseconds() : 0); | 341 !buffer->end_of_stream() ? buffer->timestamp().InMilliseconds() : 0); |
| 316 | 342 |
| 317 if (buffer->end_of_stream()) | 343 if (buffer->end_of_stream()) |
| 318 decoding_eos_ = true; | 344 decoding_eos_ = true; |
| 319 else if (buffer->duration() != kNoTimestamp()) | 345 else if (buffer->duration() != kNoTimestamp()) |
| 320 duration_tracker_.AddSample(buffer->duration()); | 346 duration_tracker_.AddSample(buffer->duration()); |
| 321 | 347 |
| 322 ++pending_decode_requests_; | 348 ++pending_decode_requests_; |
| 323 decoder_->Decode(buffer, | 349 decoder_->Decode(buffer, base::Bind(&DecoderStream<StreamType>::OnDecodeDone, |
| 324 base::Bind(&DecoderStream<StreamType>::OnDecodeDone, | 350 fallback_weak_factory_.GetWeakPtr(), |
| 325 weak_factory_.GetWeakPtr(), | 351 buffer_size, buffer->end_of_stream())); |
| 326 buffer_size, | |
| 327 buffer->end_of_stream())); | |
| 328 } | 352 } |
| 329 | 353 |
| 330 template <DemuxerStream::Type StreamType> | 354 template <DemuxerStream::Type StreamType> |
| 331 void DecoderStream<StreamType>::FlushDecoder() { | 355 void DecoderStream<StreamType>::FlushDecoder() { |
| 332 Decode(DecoderBuffer::CreateEOSBuffer()); | 356 // Send the EOS directly to the decoder, bypassing a potential add to |
| 357 // |pending_buffers_|. |
| 358 DecodeInternal(DecoderBuffer::CreateEOSBuffer()); |
| 333 } | 359 } |
| 334 | 360 |
| 335 template <DemuxerStream::Type StreamType> | 361 template <DemuxerStream::Type StreamType> |
| 336 void DecoderStream<StreamType>::OnDecodeDone(int buffer_size, | 362 void DecoderStream<StreamType>::OnDecodeDone(int buffer_size, |
| 337 bool end_of_stream, | 363 bool end_of_stream, |
| 338 DecodeStatus status) { | 364 DecodeStatus status) { |
| 339 FUNCTION_DVLOG(2) << ": " << status; | 365 FUNCTION_DVLOG(2) << ": " << status; |
| 340 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 366 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 341 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) | 367 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) |
| 342 << state_; | 368 << state_; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 356 return; | 382 return; |
| 357 } | 383 } |
| 358 | 384 |
| 359 // Drop decoding result if Reset() was called during decoding. | 385 // Drop decoding result if Reset() was called during decoding. |
| 360 // The resetting process will be handled when the decoder is reset. | 386 // The resetting process will be handled when the decoder is reset. |
| 361 if (!reset_cb_.is_null()) | 387 if (!reset_cb_.is_null()) |
| 362 return; | 388 return; |
| 363 | 389 |
| 364 switch (status) { | 390 switch (status) { |
| 365 case DecodeStatus::DECODE_ERROR: | 391 case DecodeStatus::DECODE_ERROR: |
| 392 if (!decoded_frames_since_fallback_) { |
| 393 pending_decode_requests_ = 0; |
| 394 |
| 395 // Prevent all pending decode requests and outputs form those requests |
| 396 // from being called back. |
| 397 fallback_weak_factory_.InvalidateWeakPtrs(); |
| 398 |
| 399 state_ = STATE_REINITIALIZING_DECODER; |
| 400 decoder_selector_->SelectDecoder( |
| 401 stream_, nullptr, |
| 402 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, |
| 403 weak_factory_.GetWeakPtr()), |
| 404 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, |
| 405 fallback_weak_factory_.GetWeakPtr()), |
| 406 waiting_for_decryption_key_cb_); |
| 407 return; |
| 408 } |
| 366 state_ = STATE_ERROR; | 409 state_ = STATE_ERROR; |
| 367 MEDIA_LOG(ERROR, media_log_) << GetStreamTypeString() << " decode error"; | 410 MEDIA_LOG(ERROR, media_log_) << GetStreamTypeString() << " decode error"; |
| 368 ready_outputs_.clear(); | 411 ready_outputs_.clear(); |
| 369 if (!read_cb_.is_null()) | 412 if (!read_cb_.is_null()) |
| 370 SatisfyRead(DECODE_ERROR, NULL); | 413 SatisfyRead(DECODE_ERROR, NULL); |
| 371 return; | 414 return; |
| 372 | 415 |
| 373 case DecodeStatus::ABORTED: | 416 case DecodeStatus::ABORTED: |
| 374 // Decoder can return DecodeStatus::ABORTED during Reset() or during | 417 // Decoder can return DecodeStatus::ABORTED during Reset() or during |
| 375 // destruction. | 418 // destruction. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 if (state_ == STATE_ERROR) { | 454 if (state_ == STATE_ERROR) { |
| 412 DCHECK(read_cb_.is_null()); | 455 DCHECK(read_cb_.is_null()); |
| 413 return; | 456 return; |
| 414 } | 457 } |
| 415 | 458 |
| 416 // Drop decoding result if Reset() was called during decoding. | 459 // Drop decoding result if Reset() was called during decoding. |
| 417 // The resetting process will be handled when the decoder is reset. | 460 // The resetting process will be handled when the decoder is reset. |
| 418 if (!reset_cb_.is_null()) | 461 if (!reset_cb_.is_null()) |
| 419 return; | 462 return; |
| 420 | 463 |
| 464 ++decoded_frames_since_fallback_; |
| 465 |
| 466 // |decoder_| sucessfully decoded a frame. No need to keep buffers for a |
| 467 // fallback decoder. |
| 468 // Note: |fallback_buffers_| might still have buffers, and we will keep |
| 469 // reading from there before requesting new buffers from |stream_|. |
| 470 pending_buffers_.clear(); |
| 471 |
| 421 if (!read_cb_.is_null()) { | 472 if (!read_cb_.is_null()) { |
| 422 // If |ready_outputs_| was non-empty, the read would have already been | 473 // If |ready_outputs_| was non-empty, the read would have already been |
| 423 // satisifed by Read(). | 474 // satisifed by Read(). |
| 424 DCHECK(ready_outputs_.empty()); | 475 DCHECK(ready_outputs_.empty()); |
| 425 SatisfyRead(OK, output); | 476 SatisfyRead(OK, output); |
| 426 return; | 477 return; |
| 427 } | 478 } |
| 428 | 479 |
| 429 // Store decoded output. | 480 // Store decoded output. |
| 430 ready_outputs_.push_back(output); | 481 ready_outputs_.push_back(output); |
| 431 | 482 |
| 432 // Destruct any previous decoder once we've decoded enough frames to ensure | 483 // Destruct any previous decoder once we've decoded enough frames to ensure |
| 433 // that it's no longer in use. | 484 // that it's no longer in use. |
| 434 if (previous_decoder_ && | 485 if (previous_decoder_ && |
| 435 ++decoded_frames_since_fallback_ > limits::kMaxVideoFrames) { | 486 decoded_frames_since_fallback_ > limits::kMaxVideoFrames) { |
| 436 previous_decoder_.reset(); | 487 previous_decoder_.reset(); |
| 437 } | 488 } |
| 438 } | 489 } |
| 439 | 490 |
| 440 template <DemuxerStream::Type StreamType> | 491 template <DemuxerStream::Type StreamType> |
| 441 void DecoderStream<StreamType>::ReadFromDemuxerStream() { | 492 void DecoderStream<StreamType>::ReadFromDemuxerStream() { |
| 442 FUNCTION_DVLOG(2); | 493 FUNCTION_DVLOG(2); |
| 443 DCHECK_EQ(state_, STATE_NORMAL); | 494 DCHECK_EQ(state_, STATE_NORMAL); |
| 444 DCHECK(CanDecodeMore()); | 495 DCHECK(CanDecodeMore()); |
| 445 DCHECK(reset_cb_.is_null()); | 496 DCHECK(reset_cb_.is_null()); |
| 446 | 497 |
| 498 if (!fallback_buffers_.empty()) { |
| 499 scoped_refptr<DecoderBuffer> buffer = fallback_buffers_.front(); |
| 500 fallback_buffers_.pop_front(); |
| 501 |
| 502 // Decode the buffer without re-appending it to |pending_buffers_|. |
| 503 DecodeInternal(buffer); |
| 504 return; |
| 505 } |
| 506 |
| 447 state_ = STATE_PENDING_DEMUXER_READ; | 507 state_ = STATE_PENDING_DEMUXER_READ; |
| 448 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, | 508 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, |
| 449 weak_factory_.GetWeakPtr())); | 509 weak_factory_.GetWeakPtr())); |
| 450 } | 510 } |
| 451 | 511 |
| 452 template <DemuxerStream::Type StreamType> | 512 template <DemuxerStream::Type StreamType> |
| 453 void DecoderStream<StreamType>::OnBufferReady( | 513 void DecoderStream<StreamType>::OnBufferReady( |
| 454 DemuxerStream::Status status, | 514 DemuxerStream::Status status, |
| 455 const scoped_refptr<DecoderBuffer>& buffer) { | 515 const scoped_refptr<DecoderBuffer>& buffer) { |
| 456 FUNCTION_DVLOG(2) << ": " << status << ", " | 516 FUNCTION_DVLOG(2) << ": " << status << ", " |
| 457 << (buffer.get() ? buffer->AsHumanReadableString() | 517 << (buffer.get() ? buffer->AsHumanReadableString() |
| 458 : "NULL"); | 518 : "NULL"); |
| 459 | 519 |
| 460 DCHECK(task_runner_->BelongsToCurrentThread()); | 520 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 461 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) | 521 if (decoded_frames_since_fallback_) { |
| 462 << state_; | 522 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) |
| 523 << state_; |
| 524 } else { |
| 525 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR || |
| 526 STATE_REINITIALIZING_DECODER) |
| 527 << state_; |
| 528 } |
| 463 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; | 529 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; |
| 464 | 530 |
| 531 // If parallel decode requests are supported, multiple read requests might |
| 532 // have been sent to the demuxer. The buffers might arrive while the decoder |
| 533 // is reinitializing after falling back on first decode error. |
| 534 if (state_ == STATE_REINITIALIZING_DECODER && |
| 535 !decoded_frames_since_fallback_) { |
| 536 switch (status) { |
| 537 case DemuxerStream::kOk: |
| 538 // Save valid buffers to be consumed by the new decoder. |
| 539 // |pending_buffers_| is copied to |fallback_buffers| in |
| 540 // OnDecoderSelected(). |
| 541 pending_buffers_.push_back(buffer); |
| 542 break; |
| 543 case DemuxerStream::kConfigChanged: |
| 544 // TODO(tguilbert): crbug.com/603713 |
| 545 // |decoder_| might have a stale config by the time it is reinitialized. |
| 546 // Ideally, we would save the config from |stream_| and reinitialize the |
| 547 // decoder by playing back the sequence of buffers and config changes. |
| 548 state_ = STATE_CONFIG_CHANGE_RECEIVED_WHILE_REINITIALIZING_DECODER; |
| 549 pending_buffers_.clear(); |
| 550 break; |
| 551 case DemuxerStream::kAborted: |
| 552 // |this| will read from the demuxer stream again in OnDecoderSelected() |
| 553 // and receive a kAborted then. |
| 554 pending_buffers_.clear(); |
| 555 break; |
| 556 } |
| 557 return; |
| 558 } |
| 559 |
| 465 // Decoding has been stopped (e.g due to an error). | 560 // Decoding has been stopped (e.g due to an error). |
| 466 if (state_ != STATE_PENDING_DEMUXER_READ) { | 561 if (state_ != STATE_PENDING_DEMUXER_READ) { |
| 467 DCHECK(state_ == STATE_ERROR); | 562 DCHECK(state_ == STATE_ERROR); |
| 468 DCHECK(read_cb_.is_null()); | 563 DCHECK(read_cb_.is_null()); |
| 469 return; | 564 return; |
| 470 } | 565 } |
| 471 | 566 |
| 472 state_ = STATE_NORMAL; | 567 state_ = STATE_NORMAL; |
| 473 | 568 |
| 474 if (status == DemuxerStream::kConfigChanged) { | 569 if (status == DemuxerStream::kConfigChanged) { |
| 475 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; | 570 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; |
| 476 DCHECK(stream_->SupportsConfigChanges()); | 571 DCHECK(stream_->SupportsConfigChanges()); |
| 477 | 572 |
| 573 // Pending buffers might not match the reinitialized decoder's new config. |
| 574 // |
| 575 // Note: as part of crbug.com/603713, we should record the config in order |
| 576 // to play it back to the fallback decoder. |
| 577 // |
| 578 // Clearing the buffers is an acceptable workaround for the time being. It |
| 579 // assures us that we maintain a consistent state, at the cost of |
| 580 // potentially dropping some frames. Flushing the decoder will cause one of |
| 581 // the following outcomes: |
| 582 // - The decoder outputs a valid frame during flushing (we no longer |
| 583 // care about |pending_buffers_| and fallback scenarios). |
| 584 // - The decoder returns a DECODE_ERROR via OnDecodeDone() without having |
| 585 // outputted a frame (we fallback to a new decoder which will read |
| 586 // straight from the demuxer, dropping some frames). |
| 587 // - The decoder is flushed without returning a frame or without a |
| 588 // DECODE_ERROR (we reinitialize the decoder as if a normal flush |
| 589 // happened, and read straight from the demuxer, which could lead to some |
| 590 // lost frames if we were to fallback then). |
| 591 pending_buffers_.clear(); |
| 592 |
| 478 if (!config_change_observer_cb_.is_null()) | 593 if (!config_change_observer_cb_.is_null()) |
| 479 config_change_observer_cb_.Run(); | 594 config_change_observer_cb_.Run(); |
| 480 | 595 |
| 481 state_ = STATE_FLUSHING_DECODER; | 596 state_ = STATE_FLUSHING_DECODER; |
| 482 if (!reset_cb_.is_null()) { | 597 if (!reset_cb_.is_null()) { |
| 483 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() | 598 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() |
| 484 // which will continue the resetting process in it's callback. | 599 // which will continue the resetting process in it's callback. |
| 485 if (!decrypting_demuxer_stream_) | 600 if (!decrypting_demuxer_stream_) |
| 486 Reset(base::ResetAndReturn(&reset_cb_)); | 601 Reset(base::ResetAndReturn(&reset_cb_)); |
| 487 // Reinitialization will continue after Reset() is done. | 602 // Reinitialization will continue after Reset() is done. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 DCHECK_EQ(state_, STATE_FLUSHING_DECODER); | 643 DCHECK_EQ(state_, STATE_FLUSHING_DECODER); |
| 529 DCHECK_EQ(pending_decode_requests_, 0); | 644 DCHECK_EQ(pending_decode_requests_, 0); |
| 530 | 645 |
| 531 state_ = STATE_REINITIALIZING_DECODER; | 646 state_ = STATE_REINITIALIZING_DECODER; |
| 532 // Decoders should not need a new CDM during reinitialization. | 647 // Decoders should not need a new CDM during reinitialization. |
| 533 DecoderStreamTraits<StreamType>::InitializeDecoder( | 648 DecoderStreamTraits<StreamType>::InitializeDecoder( |
| 534 decoder_.get(), stream_, nullptr, | 649 decoder_.get(), stream_, nullptr, |
| 535 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, | 650 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, |
| 536 weak_factory_.GetWeakPtr()), | 651 weak_factory_.GetWeakPtr()), |
| 537 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, | 652 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, |
| 538 weak_factory_.GetWeakPtr())); | 653 fallback_weak_factory_.GetWeakPtr())); |
| 539 } | 654 } |
| 540 | 655 |
| 541 template <DemuxerStream::Type StreamType> | 656 template <DemuxerStream::Type StreamType> |
| 542 void DecoderStream<StreamType>::OnDecoderReinitialized(bool success) { | 657 void DecoderStream<StreamType>::OnDecoderReinitialized(bool success) { |
| 543 FUNCTION_DVLOG(2); | 658 FUNCTION_DVLOG(2); |
| 544 DCHECK(task_runner_->BelongsToCurrentThread()); | 659 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 545 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER); | 660 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER); |
| 546 | 661 |
| 547 // ReinitializeDecoder() can be called in two cases: | 662 // ReinitializeDecoder() can be called in two cases: |
| 548 // 1, Flushing decoder finished (see OnDecodeOutputReady()). | 663 // 1, Flushing decoder finished (see OnDecodeOutputReady()). |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 void DecoderStream<StreamType>::OnDecoderReset() { | 719 void DecoderStream<StreamType>::OnDecoderReset() { |
| 605 FUNCTION_DVLOG(2); | 720 FUNCTION_DVLOG(2); |
| 606 DCHECK(task_runner_->BelongsToCurrentThread()); | 721 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 607 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 722 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 608 state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_; | 723 state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_; |
| 609 // If Reset() was called during pending read, read callback should be fired | 724 // If Reset() was called during pending read, read callback should be fired |
| 610 // before the reset callback is fired. | 725 // before the reset callback is fired. |
| 611 DCHECK(read_cb_.is_null()); | 726 DCHECK(read_cb_.is_null()); |
| 612 DCHECK(!reset_cb_.is_null()); | 727 DCHECK(!reset_cb_.is_null()); |
| 613 | 728 |
| 729 // Make sure we read directly from the demuxer after a reset. |
| 730 fallback_buffers_.clear(); |
| 731 pending_buffers_.clear(); |
| 732 |
| 614 if (state_ != STATE_FLUSHING_DECODER) { | 733 if (state_ != STATE_FLUSHING_DECODER) { |
| 615 state_ = STATE_NORMAL; | 734 state_ = STATE_NORMAL; |
| 616 active_splice_ = false; | 735 active_splice_ = false; |
| 617 base::ResetAndReturn(&reset_cb_).Run(); | 736 base::ResetAndReturn(&reset_cb_).Run(); |
| 618 return; | 737 return; |
| 619 } | 738 } |
| 620 | 739 |
| 621 // The resetting process will be continued in OnDecoderReinitialized(). | 740 // The resetting process will be continued in OnDecoderReinitialized(). |
| 622 ReinitializeDecoder(); | 741 ReinitializeDecoder(); |
| 623 } | 742 } |
| 624 | 743 |
| 625 template class DecoderStream<DemuxerStream::VIDEO>; | 744 template class DecoderStream<DemuxerStream::VIDEO>; |
| 626 template class DecoderStream<DemuxerStream::AUDIO>; | 745 template class DecoderStream<DemuxerStream::AUDIO>; |
| 627 | 746 |
| 628 } // namespace media | 747 } // namespace media |
| OLD | NEW |