Index: media/base/android/media_codec_decoder.cc |
diff --git a/media/base/android/media_codec_decoder.cc b/media/base/android/media_codec_decoder.cc |
index 6d7119f408590b5372261766708adb741119b779..6965a51fb6ca267a4fd9b56408de15b0471bad32 100644 |
--- a/media/base/android/media_codec_decoder.cc |
+++ b/media/base/android/media_codec_decoder.cc |
@@ -50,7 +50,7 @@ MediaCodecDecoder::MediaCodecDecoder( |
stop_done_cb_(stop_done_cb), |
error_cb_(error_cb), |
state_(kStopped), |
- preroll_mode_(kPrerollTillPTS), |
+ is_prepared_(false), |
eos_enqueued_(false), |
completed_(false), |
last_frame_posted_(false), |
@@ -95,17 +95,18 @@ void MediaCodecDecoder::Flush() { |
drain_decoder_ = false; |
au_queue_.Flush(); |
+ // |is_prepared_| is set on the decoder thread, it shouldn't be running now. |
+ DCHECK(!decoder_thread_.IsRunning()); |
+ is_prepared_ = false; |
+ |
#ifndef NDEBUG |
// We check and reset |verify_next_frame_is_key_| on Decoder thread. |
- // This DCHECK ensures we won't need to lock this variable. |
- DCHECK(!decoder_thread_.IsRunning()); |
+ // We have just DCHECKed that decoder thread is not running. |
// For video the first frame after flush must be key frame. |
verify_next_frame_is_key_ = true; |
#endif |
- preroll_mode_ = kPrerollTillPTS; |
- |
if (media_codec_bridge_) { |
// MediaCodecBridge::Reset() performs MediaCodecBridge.flush() |
MediaCodecStatus flush_status = media_codec_bridge_->Reset(); |
@@ -122,8 +123,12 @@ void MediaCodecDecoder::ReleaseMediaCodec() { |
DVLOG(1) << class_name() << "::" << __FUNCTION__; |
+ DCHECK(!decoder_thread_.IsRunning()); |
+ |
media_codec_bridge_.reset(); |
- preroll_mode_ = kPrerollTillPTS; |
+ |
+ // |is_prepared_| is set on the decoder thread, it shouldn't be running now. |
+ is_prepared_ = false; |
} |
bool MediaCodecDecoder::IsPrefetchingOrPlaying() const { |
@@ -163,14 +168,15 @@ bool MediaCodecDecoder::IsCompleted() const { |
bool MediaCodecDecoder::NotCompletedAndNeedsPreroll() const { |
DCHECK(media_task_runner_->BelongsToCurrentThread()); |
- return HasStream() && preroll_mode_ != kNoPreroll && !completed_; |
+ return HasStream() && !completed_ && |
+ (!is_prepared_ || preroll_timestamp_ != base::TimeDelta()); |
} |
-void MediaCodecDecoder::SetDecodingUntilOutputIsPresent() { |
+void MediaCodecDecoder::SetPrerollTimestamp(base::TimeDelta preroll_timestamp) { |
DCHECK(media_task_runner_->BelongsToCurrentThread()); |
- DVLOG(1) << class_name() << "::" << __FUNCTION__; |
+ DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": " << preroll_timestamp; |
- preroll_mode_ = kPrerollTillOutputIsPresent; |
+ preroll_timestamp_ = preroll_timestamp; |
} |
base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() { |
@@ -242,12 +248,11 @@ MediaCodecDecoder::ConfigStatus MediaCodecDecoder::Configure() { |
return result; |
} |
-bool MediaCodecDecoder::Preroll(base::TimeDelta preroll_timestamp, |
- const base::Closure& preroll_done_cb) { |
+bool MediaCodecDecoder::Preroll(const base::Closure& preroll_done_cb) { |
DCHECK(media_task_runner_->BelongsToCurrentThread()); |
DVLOG(1) << class_name() << "::" << __FUNCTION__ |
- << " preroll_timestamp:" << preroll_timestamp; |
+ << " preroll_timestamp:" << preroll_timestamp_; |
DecoderState state = GetState(); |
if (state != kPrefetched) { |
@@ -263,16 +268,12 @@ bool MediaCodecDecoder::Preroll(base::TimeDelta preroll_timestamp, |
} |
DCHECK(!decoder_thread_.IsRunning()); |
- DCHECK(preroll_mode_ != kNoPreroll); |
preroll_done_cb_ = preroll_done_cb; |
// We only synchronize video stream. |
DissociatePTSFromTime(); // associaton will happen after preroll is done. |
- preroll_timestamp_ = (preroll_mode_ == kPrerollTillPTS) ? preroll_timestamp |
- : base::TimeDelta(); |
- |
last_frame_posted_ = false; |
// Start the decoder thread |
@@ -313,7 +314,8 @@ bool MediaCodecDecoder::Start(base::TimeDelta start_timestamp) { |
// We only synchronize video stream. |
AssociateCurrentTimeWithPTS(start_timestamp); |
- preroll_timestamp_ = base::TimeDelta(); |
+ |
+ DCHECK(preroll_timestamp_ == base::TimeDelta()); |
// Start the decoder thread |
if (!decoder_thread_.IsRunning()) { |
@@ -373,8 +375,8 @@ void MediaCodecDecoder::RequestToStop() { |
media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); |
break; |
case kStopping: |
- break; // ignore |
case kStopped: |
Tima Vaisburd
2015/09/03 19:55:27
Moved kStopped here so RequestToStop will be ignor
|
+ break; // ignore |
case kPrefetching: |
case kPrefetched: |
// There is nothing to wait for, we can sent notification right away. |
@@ -399,16 +401,18 @@ void MediaCodecDecoder::OnLastFrameRendered(bool eos_encountered) { |
SetState(kStopped); |
completed_ = (eos_encountered && !drain_decoder_); |
+ // If the stream is completed during preroll we need to report it since |
+ // another stream might be running and the player waits for two callbacks. |
if (completed_ && !preroll_done_cb_.is_null()) { |
+ preroll_timestamp_ = base::TimeDelta(); |
liberato (no reviews please)
2015/09/04 21:59:13
there's a kNoTimestamp that you might want to cons
Tima Vaisburd
2015/09/04 23:17:35
Zero timestamp compares nicely at line 807, it was
|
media_task_runner_->PostTask(FROM_HERE, |
base::ResetAndReturn(&preroll_done_cb_)); |
} |
if (eos_encountered && drain_decoder_) { |
- ReleaseMediaCodec(); |
drain_decoder_ = false; |
eos_enqueued_ = false; |
- preroll_mode_ = kPrerollTillOutputIsPresent; |
+ ReleaseMediaCodec(); |
media_task_runner_->PostTask(FROM_HERE, decoder_drained_cb_); |
} |
@@ -420,14 +424,14 @@ void MediaCodecDecoder::OnPrerollDone() { |
DVLOG(1) << class_name() << "::" << __FUNCTION__; |
- preroll_mode_ = kNoPreroll; |
+ preroll_timestamp_ = base::TimeDelta(); |
- // The state might be kStopping. |
- if (GetState() == kPrerolling) { |
+ // The state might be kStopping (?) |
+ if (GetState() == kPrerolling) |
SetState(kPrerolled); |
- media_task_runner_->PostTask(FROM_HERE, |
- base::ResetAndReturn(&preroll_done_cb_)); |
- } |
+ |
+ if (!preroll_done_cb_.is_null()) |
+ base::ResetAndReturn(&preroll_done_cb_).Run(); |
} |
void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { |
@@ -578,6 +582,7 @@ void MediaCodecDecoder::ProcessNextFrame() { |
// We can stop processing, the |au_queue_| and MediaCodec queues can freeze. |
// We only need to let finish the delayed rendering tasks. |
+ DVLOG(1) << class_name() << "::" << __FUNCTION__ << " kStopping, returning"; |
return; |
} |
@@ -797,6 +802,8 @@ bool MediaCodecDecoder::DepleteOutputBufferQueue() { |
case MEDIA_CODEC_OK: |
// We got the decoded frame. |
+ is_prepared_ = true; |
+ |
if (pts < preroll_timestamp_) |
render_mode = kRenderSkip; |
else if (GetState() == kPrerolling) |