| 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 "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, | 82 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, |
| 83 weak_factory_.GetWeakPtr()), | 83 weak_factory_.GetWeakPtr()), |
| 84 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, | 84 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, |
| 85 weak_factory_.GetWeakPtr())); | 85 weak_factory_.GetWeakPtr())); |
| 86 } | 86 } |
| 87 | 87 |
| 88 template <DemuxerStream::Type StreamType> | 88 template <DemuxerStream::Type StreamType> |
| 89 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { | 89 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { |
| 90 FUNCTION_DVLOG(2); | 90 FUNCTION_DVLOG(2); |
| 91 DCHECK(task_runner_->BelongsToCurrentThread()); | 91 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 92 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 92 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_INITIALIZING && |
| 93 state_ == STATE_ERROR || state_ == STATE_REINITIALIZING_DECODER || | 93 state_ != STATE_STOPPED) << state_; |
| 94 state_ == STATE_PENDING_DEMUXER_READ) | |
| 95 << state_; | |
| 96 // No two reads in the flight at any time. | 94 // No two reads in the flight at any time. |
| 97 DCHECK(read_cb_.is_null()); | 95 DCHECK(read_cb_.is_null()); |
| 98 // No read during resetting or stopping process. | 96 // No read during resetting or stopping process. |
| 99 DCHECK(reset_cb_.is_null()); | 97 DCHECK(reset_cb_.is_null()); |
| 100 DCHECK(stop_cb_.is_null()); | 98 DCHECK(stop_cb_.is_null()); |
| 101 | 99 |
| 102 read_cb_ = read_cb; | 100 if (state_ == STATE_ERROR) { |
| 101 task_runner_->PostTask( |
| 102 FROM_HERE, base::Bind(read_cb, DECODE_ERROR, scoped_refptr<Output>())); |
| 103 return; |
| 104 } |
| 103 | 105 |
| 104 if (state_ == STATE_ERROR) { | 106 if (state_ == STATE_END_OF_STREAM && ready_outputs_.empty()) { |
| 105 task_runner_->PostTask(FROM_HERE, | 107 task_runner_->PostTask( |
| 106 base::Bind(base::ResetAndReturn(&read_cb_), | 108 FROM_HERE, base::Bind(read_cb, OK, StreamTraits::CreateEOSOutput())); |
| 107 DECODE_ERROR, | |
| 108 scoped_refptr<Output>())); | |
| 109 return; | 109 return; |
| 110 } | 110 } |
| 111 | 111 |
| 112 if (!ready_outputs_.empty()) { | 112 if (!ready_outputs_.empty()) { |
| 113 task_runner_->PostTask(FROM_HERE, base::Bind( | 113 task_runner_->PostTask(FROM_HERE, |
| 114 base::ResetAndReturn(&read_cb_), OK, ready_outputs_.front())); | 114 base::Bind(read_cb, OK, ready_outputs_.front())); |
| 115 ready_outputs_.pop_front(); | 115 ready_outputs_.pop_front(); |
| 116 } else { |
| 117 read_cb_ = read_cb; |
| 116 } | 118 } |
| 117 | 119 |
| 118 if (state_ == STATE_NORMAL && CanDecodeMore()) | 120 if (state_ == STATE_NORMAL && CanDecodeMore()) |
| 119 ReadFromDemuxerStream(); | 121 ReadFromDemuxerStream(); |
| 120 } | 122 } |
| 121 | 123 |
| 122 template <DemuxerStream::Type StreamType> | 124 template <DemuxerStream::Type StreamType> |
| 123 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { | 125 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { |
| 124 FUNCTION_DVLOG(2); | 126 FUNCTION_DVLOG(2); |
| 125 DCHECK(task_runner_->BelongsToCurrentThread()); | 127 DCHECK(task_runner_->BelongsToCurrentThread()); |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 if (!reset_cb_.is_null()) | 332 if (!reset_cb_.is_null()) |
| 331 return; | 333 return; |
| 332 | 334 |
| 333 switch (status) { | 335 switch (status) { |
| 334 case Decoder::kDecodeError: | 336 case Decoder::kDecodeError: |
| 335 case Decoder::kDecryptError: | 337 case Decoder::kDecryptError: |
| 336 state_ = STATE_ERROR; | 338 state_ = STATE_ERROR; |
| 337 ready_outputs_.clear(); | 339 ready_outputs_.clear(); |
| 338 if (!read_cb_.is_null()) | 340 if (!read_cb_.is_null()) |
| 339 SatisfyRead(DECODE_ERROR, NULL); | 341 SatisfyRead(DECODE_ERROR, NULL); |
| 340 break; | 342 return; |
| 341 | 343 |
| 342 case Decoder::kAborted: | 344 case Decoder::kAborted: |
| 343 // Decoder can return kAborted only when Reset is pending. | 345 // Decoder can return kAborted only when Reset is pending. |
| 344 NOTREACHED(); | 346 NOTREACHED(); |
| 345 break; | 347 return; |
| 346 | 348 |
| 347 case Decoder::kOk: | 349 case Decoder::kOk: |
| 348 // Any successful decode counts! | 350 // Any successful decode counts! |
| 349 if (buffer_size > 0) { | 351 if (buffer_size > 0) |
| 350 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); | 352 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); |
| 353 |
| 354 if (state_ == STATE_NORMAL) { |
| 355 if (end_of_stream) { |
| 356 state_ = STATE_END_OF_STREAM; |
| 357 if (ready_outputs_.empty() && !read_cb_.is_null()) |
| 358 SatisfyRead(OK, StreamTraits::CreateEOSOutput()); |
| 359 return; |
| 360 } |
| 361 |
| 362 if (CanDecodeMore()) |
| 363 ReadFromDemuxerStream(); |
| 364 return; |
| 351 } | 365 } |
| 352 | 366 |
| 353 if (state_ == STATE_NORMAL) { | 367 if (state_ == STATE_FLUSHING_DECODER && !pending_decode_requests_) |
| 354 if (CanDecodeMore() && !end_of_stream) | 368 ReinitializeDecoder(); |
| 355 ReadFromDemuxerStream(); | 369 return; |
| 356 } else if (state_ == STATE_FLUSHING_DECODER) { | |
| 357 if (!pending_decode_requests_) | |
| 358 ReinitializeDecoder(); | |
| 359 } | |
| 360 break; | |
| 361 } | 370 } |
| 362 } | 371 } |
| 363 | 372 |
| 364 template <DemuxerStream::Type StreamType> | 373 template <DemuxerStream::Type StreamType> |
| 365 void DecoderStream<StreamType>::OnDecodeOutputReady( | 374 void DecoderStream<StreamType>::OnDecodeOutputReady( |
| 366 const scoped_refptr<Output>& output) { | 375 const scoped_refptr<Output>& output) { |
| 367 FUNCTION_DVLOG(2) << output; | 376 FUNCTION_DVLOG(2) << ": " << output->timestamp().InMilliseconds() << " ms"; |
| 368 DCHECK(output); | 377 DCHECK(output); |
| 378 DCHECK(!output->end_of_stream()); |
| 369 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 379 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 370 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) | 380 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) |
| 371 << state_; | 381 << state_; |
| 372 | 382 |
| 373 if (state_ == STATE_ERROR) { | 383 if (state_ == STATE_ERROR) { |
| 374 DCHECK(read_cb_.is_null()); | 384 DCHECK(read_cb_.is_null()); |
| 375 return; | 385 return; |
| 376 } | 386 } |
| 377 | 387 |
| 378 // Drop decoding result if Reset() was called during decoding. | 388 // Drop decoding result if Reset() was called during decoding. |
| 379 // The resetting process will be handled when the decoder is reset. | 389 // The resetting process will be handled when the decoder is reset. |
| 380 if (!reset_cb_.is_null()) | 390 if (!reset_cb_.is_null()) |
| 381 return; | 391 return; |
| 382 | 392 |
| 383 if (state_ == STATE_FLUSHING_DECODER && output->end_of_stream()) { | |
| 384 // ReinitializeDecoder() will be called from OnDecodeDone(). | |
| 385 return; | |
| 386 } | |
| 387 | |
| 388 // Store decoded output. | 393 // Store decoded output. |
| 389 ready_outputs_.push_back(output); | 394 ready_outputs_.push_back(output); |
| 390 | 395 |
| 396 if (read_cb_.is_null()) |
| 397 return; |
| 398 |
| 391 // Satisfy outstanding read request, if any. | 399 // Satisfy outstanding read request, if any. |
| 392 if (!read_cb_.is_null()) { | 400 scoped_refptr<Output> read_result = ready_outputs_.front(); |
| 393 scoped_refptr<Output> read_result = ready_outputs_.front(); | 401 ready_outputs_.pop_front(); |
| 394 ready_outputs_.pop_front(); | 402 SatisfyRead(OK, output); |
| 395 SatisfyRead(OK, output); | |
| 396 } | |
| 397 } | 403 } |
| 398 | 404 |
| 399 template <DemuxerStream::Type StreamType> | 405 template <DemuxerStream::Type StreamType> |
| 400 void DecoderStream<StreamType>::ReadFromDemuxerStream() { | 406 void DecoderStream<StreamType>::ReadFromDemuxerStream() { |
| 401 FUNCTION_DVLOG(2); | 407 FUNCTION_DVLOG(2); |
| 402 DCHECK_EQ(state_, STATE_NORMAL) << state_; | 408 DCHECK_EQ(state_, STATE_NORMAL) << state_; |
| 403 DCHECK(CanDecodeMore()); | 409 DCHECK(CanDecodeMore()); |
| 404 DCHECK(reset_cb_.is_null()); | 410 DCHECK(reset_cb_.is_null()); |
| 405 DCHECK(stop_cb_.is_null()); | 411 DCHECK(stop_cb_.is_null()); |
| 406 | 412 |
| 407 state_ = STATE_PENDING_DEMUXER_READ; | 413 state_ = STATE_PENDING_DEMUXER_READ; |
| 408 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, | 414 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, |
| 409 weak_factory_.GetWeakPtr())); | 415 weak_factory_.GetWeakPtr())); |
| 410 } | 416 } |
| 411 | 417 |
| 412 template <DemuxerStream::Type StreamType> | 418 template <DemuxerStream::Type StreamType> |
| 413 void DecoderStream<StreamType>::OnBufferReady( | 419 void DecoderStream<StreamType>::OnBufferReady( |
| 414 DemuxerStream::Status status, | 420 DemuxerStream::Status status, |
| 415 const scoped_refptr<DecoderBuffer>& buffer) { | 421 const scoped_refptr<DecoderBuffer>& buffer) { |
| 416 FUNCTION_DVLOG(2) << ": " << status; | 422 FUNCTION_DVLOG(2) << ": " << status << ", " |
| 423 << buffer->AsHumanReadableString(); |
| 424 |
| 417 DCHECK(task_runner_->BelongsToCurrentThread()); | 425 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 418 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR || | 426 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR || |
| 419 state_ == STATE_STOPPED) | 427 state_ == STATE_STOPPED) |
| 420 << state_; | 428 << state_; |
| 421 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; | 429 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; |
| 422 DCHECK(stop_cb_.is_null()); | 430 DCHECK(stop_cb_.is_null()); |
| 423 | 431 |
| 424 // Decoding has been stopped (e.g due to an error). | 432 // Decoding has been stopped (e.g due to an error). |
| 425 if (state_ != STATE_PENDING_DEMUXER_READ) { | 433 if (state_ != STATE_PENDING_DEMUXER_READ) { |
| 426 DCHECK(state_ == STATE_ERROR || state_ == STATE_STOPPED); | 434 DCHECK(state_ == STATE_ERROR || state_ == STATE_STOPPED); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 } | 536 } |
| 529 | 537 |
| 530 ReadFromDemuxerStream(); | 538 ReadFromDemuxerStream(); |
| 531 } | 539 } |
| 532 | 540 |
| 533 template <DemuxerStream::Type StreamType> | 541 template <DemuxerStream::Type StreamType> |
| 534 void DecoderStream<StreamType>::ResetDecoder() { | 542 void DecoderStream<StreamType>::ResetDecoder() { |
| 535 FUNCTION_DVLOG(2); | 543 FUNCTION_DVLOG(2); |
| 536 DCHECK(task_runner_->BelongsToCurrentThread()); | 544 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 537 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 545 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 538 state_ == STATE_ERROR) << state_; | 546 state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_; |
| 539 DCHECK(!reset_cb_.is_null()); | 547 DCHECK(!reset_cb_.is_null()); |
| 540 | 548 |
| 541 decoder_->Reset(base::Bind(&DecoderStream<StreamType>::OnDecoderReset, | 549 decoder_->Reset(base::Bind(&DecoderStream<StreamType>::OnDecoderReset, |
| 542 weak_factory_.GetWeakPtr())); | 550 weak_factory_.GetWeakPtr())); |
| 543 } | 551 } |
| 544 | 552 |
| 545 template <DemuxerStream::Type StreamType> | 553 template <DemuxerStream::Type StreamType> |
| 546 void DecoderStream<StreamType>::OnDecoderReset() { | 554 void DecoderStream<StreamType>::OnDecoderReset() { |
| 547 FUNCTION_DVLOG(2); | 555 FUNCTION_DVLOG(2); |
| 548 DCHECK(task_runner_->BelongsToCurrentThread()); | 556 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 549 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 557 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 550 state_ == STATE_ERROR) << state_; | 558 state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_; |
| 551 // If Reset() was called during pending read, read callback should be fired | 559 // If Reset() was called during pending read, read callback should be fired |
| 552 // before the reset callback is fired. | 560 // before the reset callback is fired. |
| 553 DCHECK(read_cb_.is_null()); | 561 DCHECK(read_cb_.is_null()); |
| 554 DCHECK(!reset_cb_.is_null()); | 562 DCHECK(!reset_cb_.is_null()); |
| 555 DCHECK(stop_cb_.is_null()); | 563 DCHECK(stop_cb_.is_null()); |
| 556 | 564 |
| 557 if (state_ != STATE_FLUSHING_DECODER) { | 565 if (state_ != STATE_FLUSHING_DECODER) { |
| 558 base::ResetAndReturn(&reset_cb_).Run(); | 566 base::ResetAndReturn(&reset_cb_).Run(); |
| 559 return; | 567 return; |
| 560 } | 568 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 577 decrypting_demuxer_stream_.reset(); | 585 decrypting_demuxer_stream_.reset(); |
| 578 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also | 586 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also |
| 579 // posted in Stop(). | 587 // posted in Stop(). |
| 580 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | 588 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
| 581 } | 589 } |
| 582 | 590 |
| 583 template class DecoderStream<DemuxerStream::VIDEO>; | 591 template class DecoderStream<DemuxerStream::VIDEO>; |
| 584 template class DecoderStream<DemuxerStream::AUDIO>; | 592 template class DecoderStream<DemuxerStream::AUDIO>; |
| 585 | 593 |
| 586 } // namespace media | 594 } // namespace media |
| OLD | NEW |