| 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 // TODO(xhwang): VideoDecoder doesn't need to return EOS after it's flushed. | 393 // TODO(xhwang): VideoDecoder doesn't need to return EOS after it's flushed. |
| 384 // Fix all decoders and remove this block. | 394 // Fix all decoders and remove this block. |
| 385 if (state_ == STATE_FLUSHING_DECODER && output->end_of_stream()) { | |
| 386 // ReinitializeDecoder() will be called from OnDecodeDone(). | |
| 387 return; | |
| 388 } | |
| 389 | |
| 390 // Store decoded output. | 395 // Store decoded output. |
| 391 ready_outputs_.push_back(output); | 396 ready_outputs_.push_back(output); |
| 392 | 397 |
| 398 if (read_cb_.is_null()) |
| 399 return; |
| 400 |
| 393 // Satisfy outstanding read request, if any. | 401 // Satisfy outstanding read request, if any. |
| 394 if (!read_cb_.is_null()) { | 402 scoped_refptr<Output> read_result = ready_outputs_.front(); |
| 395 scoped_refptr<Output> read_result = ready_outputs_.front(); | 403 ready_outputs_.pop_front(); |
| 396 ready_outputs_.pop_front(); | 404 SatisfyRead(OK, output); |
| 397 SatisfyRead(OK, output); | |
| 398 } | |
| 399 } | 405 } |
| 400 | 406 |
| 401 template <DemuxerStream::Type StreamType> | 407 template <DemuxerStream::Type StreamType> |
| 402 void DecoderStream<StreamType>::ReadFromDemuxerStream() { | 408 void DecoderStream<StreamType>::ReadFromDemuxerStream() { |
| 403 FUNCTION_DVLOG(2); | 409 FUNCTION_DVLOG(2); |
| 404 DCHECK_EQ(state_, STATE_NORMAL) << state_; | 410 DCHECK_EQ(state_, STATE_NORMAL) << state_; |
| 405 DCHECK(CanDecodeMore()); | 411 DCHECK(CanDecodeMore()); |
| 406 DCHECK(reset_cb_.is_null()); | 412 DCHECK(reset_cb_.is_null()); |
| 407 DCHECK(stop_cb_.is_null()); | 413 DCHECK(stop_cb_.is_null()); |
| 408 | 414 |
| 409 state_ = STATE_PENDING_DEMUXER_READ; | 415 state_ = STATE_PENDING_DEMUXER_READ; |
| 410 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, | 416 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, |
| 411 weak_factory_.GetWeakPtr())); | 417 weak_factory_.GetWeakPtr())); |
| 412 } | 418 } |
| 413 | 419 |
| 414 template <DemuxerStream::Type StreamType> | 420 template <DemuxerStream::Type StreamType> |
| 415 void DecoderStream<StreamType>::OnBufferReady( | 421 void DecoderStream<StreamType>::OnBufferReady( |
| 416 DemuxerStream::Status status, | 422 DemuxerStream::Status status, |
| 417 const scoped_refptr<DecoderBuffer>& buffer) { | 423 const scoped_refptr<DecoderBuffer>& buffer) { |
| 418 FUNCTION_DVLOG(2) << ": " << status; | 424 FUNCTION_DVLOG(2) << ": " << status << ", " |
| 425 << buffer->AsHumanReadableString(); |
| 426 |
| 419 DCHECK(task_runner_->BelongsToCurrentThread()); | 427 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 420 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR || | 428 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR || |
| 421 state_ == STATE_STOPPED) | 429 state_ == STATE_STOPPED) |
| 422 << state_; | 430 << state_; |
| 423 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; | 431 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; |
| 424 DCHECK(stop_cb_.is_null()); | 432 DCHECK(stop_cb_.is_null()); |
| 425 | 433 |
| 426 // Decoding has been stopped (e.g due to an error). | 434 // Decoding has been stopped (e.g due to an error). |
| 427 if (state_ != STATE_PENDING_DEMUXER_READ) { | 435 if (state_ != STATE_PENDING_DEMUXER_READ) { |
| 428 DCHECK(state_ == STATE_ERROR || state_ == STATE_STOPPED); | 436 DCHECK(state_ == STATE_ERROR || state_ == STATE_STOPPED); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 } | 538 } |
| 531 | 539 |
| 532 ReadFromDemuxerStream(); | 540 ReadFromDemuxerStream(); |
| 533 } | 541 } |
| 534 | 542 |
| 535 template <DemuxerStream::Type StreamType> | 543 template <DemuxerStream::Type StreamType> |
| 536 void DecoderStream<StreamType>::ResetDecoder() { | 544 void DecoderStream<StreamType>::ResetDecoder() { |
| 537 FUNCTION_DVLOG(2); | 545 FUNCTION_DVLOG(2); |
| 538 DCHECK(task_runner_->BelongsToCurrentThread()); | 546 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 539 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 547 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 540 state_ == STATE_ERROR) << state_; | 548 state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_; |
| 541 DCHECK(!reset_cb_.is_null()); | 549 DCHECK(!reset_cb_.is_null()); |
| 542 | 550 |
| 543 decoder_->Reset(base::Bind(&DecoderStream<StreamType>::OnDecoderReset, | 551 decoder_->Reset(base::Bind(&DecoderStream<StreamType>::OnDecoderReset, |
| 544 weak_factory_.GetWeakPtr())); | 552 weak_factory_.GetWeakPtr())); |
| 545 } | 553 } |
| 546 | 554 |
| 547 template <DemuxerStream::Type StreamType> | 555 template <DemuxerStream::Type StreamType> |
| 548 void DecoderStream<StreamType>::OnDecoderReset() { | 556 void DecoderStream<StreamType>::OnDecoderReset() { |
| 549 FUNCTION_DVLOG(2); | 557 FUNCTION_DVLOG(2); |
| 550 DCHECK(task_runner_->BelongsToCurrentThread()); | 558 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 551 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 559 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 552 state_ == STATE_ERROR) << state_; | 560 state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_; |
| 553 // If Reset() was called during pending read, read callback should be fired | 561 // If Reset() was called during pending read, read callback should be fired |
| 554 // before the reset callback is fired. | 562 // before the reset callback is fired. |
| 555 DCHECK(read_cb_.is_null()); | 563 DCHECK(read_cb_.is_null()); |
| 556 DCHECK(!reset_cb_.is_null()); | 564 DCHECK(!reset_cb_.is_null()); |
| 557 DCHECK(stop_cb_.is_null()); | 565 DCHECK(stop_cb_.is_null()); |
| 558 | 566 |
| 559 if (state_ != STATE_FLUSHING_DECODER) { | 567 if (state_ != STATE_FLUSHING_DECODER) { |
| 560 base::ResetAndReturn(&reset_cb_).Run(); | 568 base::ResetAndReturn(&reset_cb_).Run(); |
| 561 return; | 569 return; |
| 562 } | 570 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 579 decrypting_demuxer_stream_.reset(); | 587 decrypting_demuxer_stream_.reset(); |
| 580 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also | 588 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also |
| 581 // posted in Stop(). | 589 // posted in Stop(). |
| 582 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | 590 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
| 583 } | 591 } |
| 584 | 592 |
| 585 template class DecoderStream<DemuxerStream::VIDEO>; | 593 template class DecoderStream<DemuxerStream::VIDEO>; |
| 586 template class DecoderStream<DemuxerStream::AUDIO>; | 594 template class DecoderStream<DemuxerStream::AUDIO>; |
| 587 | 595 |
| 588 } // namespace media | 596 } // namespace media |
| OLD | NEW |