Index: media/filters/android/media_codec_audio_decoder.cc |
diff --git a/media/filters/android/media_codec_audio_decoder.cc b/media/filters/android/media_codec_audio_decoder.cc |
index aa559cfa5806579578626192d81bc28ca189f3e7..8d4a4217c77d27411eaabb9c9739e3e103898552 100644 |
--- a/media/filters/android/media_codec_audio_decoder.cc |
+++ b/media/filters/android/media_codec_audio_decoder.cc |
@@ -11,7 +11,9 @@ |
#include "base/thread_task_runner_handle.h" |
#include "media/base/android/sdk_media_codec_bridge.h" |
#include "media/base/audio_buffer.h" |
+#include "media/base/audio_timestamp_helper.h" |
#include "media/base/bind_to_current_loop.h" |
+#include "media/base/timestamp_constants.h" |
namespace media { |
@@ -116,6 +118,8 @@ void MediaCodecAudioDecoder::Initialize(const AudioDecoderConfig& config, |
} |
config_ = config; |
+ timestamp_helper_.reset( |
+ new AudioTimestampHelper(config_.samples_per_second())); |
output_cb_ = BindToCurrentLoop(output_cb); |
SetState(STATE_READY); |
@@ -126,8 +130,15 @@ void MediaCodecAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
const DecodeCB& decode_cb) { |
DecodeCB bound_decode_cb = BindToCurrentLoop(decode_cb); |
+ if (!buffer->end_of_stream() && buffer->timestamp() == kNoTimestamp()) { |
+ DVLOG(2) << __FUNCTION__ << " " << buffer->AsHumanReadableString() |
+ << ": no timestamp, skipping this buffer"; |
+ bound_decode_cb.Run(kDecodeError); |
+ return; |
+ } |
+ |
if (state_ == STATE_ERROR) { |
- // We get here if an error happens in DecodeOutput() or Reset(). |
+ // We get here if an error happens in DequeueOutput() or Reset(). |
DVLOG(2) << __FUNCTION__ << " " << buffer->AsHumanReadableString() |
<< ": Error state, returning decode error for all buffers"; |
ClearInputQueue(kDecodeError); |
@@ -171,6 +182,9 @@ void MediaCodecAudioDecoder::Reset(const base::Closure& closure) { |
success = !!media_codec_; |
} |
+ // Reset AudioTimestampHelper. |
+ timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); |
+ |
SetState(success ? STATE_READY : STATE_ERROR); |
task_runner_->PostTask(FROM_HERE, closure); |
@@ -204,6 +218,16 @@ void MediaCodecAudioDecoder::DoIOTask() { |
bool MediaCodecAudioDecoder::QueueInput() { |
DVLOG(2) << __FUNCTION__; |
+ bool did_work = false; |
+ while (QueueOneInputBuffer()) |
+ did_work = true; |
+ |
+ return did_work; |
+} |
+ |
+bool MediaCodecAudioDecoder::QueueOneInputBuffer() { |
+ DVLOG(2) << __FUNCTION__; |
+ |
if (input_queue_.empty()) |
return false; |
@@ -277,6 +301,7 @@ MediaCodecAudioDecoder::DequeueInputBuffer() { |
media_codec_->DequeueInputBuffer(NoWaitTimeout(), &input_buf_index); |
switch (status) { |
case media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER: |
+ DVLOG(2) << __FUNCTION__ << ": MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER"; |
break; |
case media::MEDIA_CODEC_ERROR: |
@@ -501,8 +526,17 @@ void MediaCodecAudioDecoder::OnDecodedFrame(const OutputBufferInfo& out) { |
kSampleFormatS16, config_.channel_layout(), channel_count, |
config_.samples_per_second(), frame_count); |
- // Set timestamp. |
- audio_buffer->set_timestamp(out.pts); |
+ // Calculate and set buffer timestamp. |
+ |
+ const bool first_buffer = |
+ timestamp_helper_->base_timestamp() == kNoTimestamp(); |
+ if (first_buffer) { |
+ // Clamp the base timestamp to zero. |
+ timestamp_helper_->SetBaseTimestamp(std::max(base::TimeDelta(), out.pts)); |
+ } |
+ |
+ audio_buffer->set_timestamp(timestamp_helper_->GetTimestamp()); |
+ timestamp_helper_->AddFrames(frame_count); |
// Copy data into AudioBuffer. |
CHECK_LE(out.size, audio_buffer->data_size()); |