| Index: media/base/android/audio_decoder_job.cc
|
| diff --git a/media/base/android/audio_decoder_job.cc b/media/base/android/audio_decoder_job.cc
|
| index d089796ccc65cc1de197aa75b2b1f25a58b7ca7e..580c63f13af6994576000f4f9cfe0a1b32241c4b 100644
|
| --- a/media/base/android/audio_decoder_job.cc
|
| +++ b/media/base/android/audio_decoder_job.cc
|
| @@ -8,6 +8,14 @@
|
| #include "base/lazy_instance.h"
|
| #include "base/threading/thread.h"
|
| #include "media/base/android/media_codec_bridge.h"
|
| +#include "media/base/audio_timestamp_helper.h"
|
| +
|
| +namespace {
|
| +
|
| +// Use 16bit PCM for audio output. Keep this value in sync with the output
|
| +// format we passed to AudioTrack in MediaCodecBridge.
|
| +const int kBytesPerAudioOutputSample = 2;
|
| +}
|
|
|
| namespace media {
|
|
|
| @@ -35,19 +43,26 @@ AudioDecoderJob* AudioDecoderJob::Create(
|
| scoped_ptr<AudioCodecBridge> codec(AudioCodecBridge::Create(audio_codec));
|
| if (codec && codec->Start(audio_codec, sample_rate, channel_count, extra_data,
|
| extra_data_size, true, media_crypto)) {
|
| - return new AudioDecoderJob(codec.Pass(), request_data_cb);
|
| + scoped_ptr<AudioTimestampHelper> audio_timestamp_helper(
|
| + new AudioTimestampHelper(sample_rate));
|
| + return new AudioDecoderJob(
|
| + audio_timestamp_helper.Pass(), codec.Pass(),
|
| + kBytesPerAudioOutputSample * channel_count, request_data_cb);
|
| }
|
| -
|
| LOG(ERROR) << "Failed to create AudioDecoderJob.";
|
| return NULL;
|
| }
|
|
|
| AudioDecoderJob::AudioDecoderJob(
|
| + scoped_ptr<AudioTimestampHelper> audio_timestamp_helper,
|
| scoped_ptr<AudioCodecBridge> audio_codec_bridge,
|
| + int bytes_per_frame,
|
| const base::Closure& request_data_cb)
|
| : MediaDecoderJob(g_audio_decoder_thread.Pointer()->message_loop_proxy(),
|
| audio_codec_bridge.get(), request_data_cb),
|
| - audio_codec_bridge_(audio_codec_bridge.Pass()) {
|
| + bytes_per_frame_(bytes_per_frame),
|
| + audio_codec_bridge_(audio_codec_bridge.Pass()),
|
| + audio_timestamp_helper_(audio_timestamp_helper.Pass()) {
|
| }
|
|
|
| AudioDecoderJob::~AudioDecoderJob() {
|
| @@ -57,17 +72,33 @@ void AudioDecoderJob::SetVolume(double volume) {
|
| audio_codec_bridge_->SetVolume(volume);
|
| }
|
|
|
| +void AudioDecoderJob::SetBaseTimestamp(base::TimeDelta base_timestamp) {
|
| + audio_timestamp_helper_->SetBaseTimestamp(base_timestamp);
|
| +}
|
| +
|
| void AudioDecoderJob::ReleaseOutputBuffer(
|
| int output_buffer_index,
|
| size_t size,
|
| bool render_output,
|
| + base::TimeDelta current_presentation_timestamp,
|
| const ReleaseOutputCompletionCallback& callback) {
|
| - size_t size_to_render = render_output ? size : 0u;
|
| - if (size_to_render)
|
| - audio_codec_bridge_->PlayOutputBuffer(output_buffer_index, size_to_render);
|
| + render_output = render_output && (size != 0u);
|
| + if (render_output) {
|
| + int64 head_position = audio_codec_bridge_->PlayOutputBuffer(
|
| + output_buffer_index, size);
|
| + audio_timestamp_helper_->AddFrames(size / (bytes_per_frame_));
|
| + int64 frames_to_play =
|
| + audio_timestamp_helper_->frame_count() - head_position;
|
| + DCHECK_GE(frames_to_play, 0);
|
| + current_presentation_timestamp =
|
| + audio_timestamp_helper_->GetTimestamp() -
|
| + audio_timestamp_helper_->GetFrameDuration(frames_to_play);
|
| + } else {
|
| + current_presentation_timestamp = kNoTimestamp();
|
| + }
|
| audio_codec_bridge_->ReleaseOutputBuffer(output_buffer_index, false);
|
| -
|
| - callback.Run(size_to_render);
|
| + callback.Run(current_presentation_timestamp,
|
| + audio_timestamp_helper_->GetTimestamp());
|
| }
|
|
|
| bool AudioDecoderJob::ComputeTimeToRender() const {
|
|
|