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) { |
| 568 state_ = STATE_NORMAL; |
560 base::ResetAndReturn(&reset_cb_).Run(); | 569 base::ResetAndReturn(&reset_cb_).Run(); |
561 return; | 570 return; |
562 } | 571 } |
563 | 572 |
564 // The resetting process will be continued in OnDecoderReinitialized(). | 573 // The resetting process will be continued in OnDecoderReinitialized(). |
565 ReinitializeDecoder(); | 574 ReinitializeDecoder(); |
566 } | 575 } |
567 | 576 |
568 template <DemuxerStream::Type StreamType> | 577 template <DemuxerStream::Type StreamType> |
569 void DecoderStream<StreamType>::StopDecoder() { | 578 void DecoderStream<StreamType>::StopDecoder() { |
570 FUNCTION_DVLOG(2); | 579 FUNCTION_DVLOG(2); |
571 DCHECK(task_runner_->BelongsToCurrentThread()); | 580 DCHECK(task_runner_->BelongsToCurrentThread()); |
572 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; | 581 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; |
573 DCHECK(!stop_cb_.is_null()); | 582 DCHECK(!stop_cb_.is_null()); |
574 | 583 |
575 state_ = STATE_STOPPED; | 584 state_ = STATE_STOPPED; |
576 decoder_->Stop(); | 585 decoder_->Stop(); |
577 stream_ = NULL; | 586 stream_ = NULL; |
578 decoder_.reset(); | 587 decoder_.reset(); |
579 decrypting_demuxer_stream_.reset(); | 588 decrypting_demuxer_stream_.reset(); |
580 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also | 589 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also |
581 // posted in Stop(). | 590 // posted in Stop(). |
582 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | 591 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
583 } | 592 } |
584 | 593 |
585 template class DecoderStream<DemuxerStream::VIDEO>; | 594 template class DecoderStream<DemuxerStream::VIDEO>; |
586 template class DecoderStream<DemuxerStream::AUDIO>; | 595 template class DecoderStream<DemuxerStream::AUDIO>; |
587 | 596 |
588 } // namespace media | 597 } // namespace media |
OLD | NEW |