Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(979)

Unified Diff: media/base/android/media_codec_audio_decoder.cc

Issue 1128383003: Implementation of MediaCodecPlayer stage 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: AccessUnitQueue::GetInfo() returns result by value Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/base/android/media_codec_audio_decoder.cc
diff --git a/media/base/android/media_codec_audio_decoder.cc b/media/base/android/media_codec_audio_decoder.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6806787fee1f5426dd8fad85b73f0371fc9400a7
--- /dev/null
+++ b/media/base/android/media_codec_audio_decoder.cc
@@ -0,0 +1,213 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/android/media_codec_audio_decoder.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "media/base/android/media_codec_bridge.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/base/demuxer_stream.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 {
+
+MediaCodecAudioDecoder::MediaCodecAudioDecoder(
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
+ const base::Closure& request_data_cb,
+ const base::Closure& starvation_cb,
+ const base::Closure& stop_done_cb,
+ const base::Closure& error_cb,
+ const SetTimeCallback& update_current_time_cb)
+ : MediaCodecDecoder(media_task_runner,
+ request_data_cb,
+ starvation_cb,
+ stop_done_cb,
+ error_cb,
+ "AudioDecoder"),
+ volume_(-1.0),
+ bytes_per_frame_(0),
+ output_sampling_rate_(0),
+ frame_count_(0),
+ update_current_time_cb_(update_current_time_cb) {
+}
+
+MediaCodecAudioDecoder::~MediaCodecAudioDecoder() {
+ DVLOG(1) << "AudioDecoder::~AudioDecoder()";
+}
+
+bool MediaCodecAudioDecoder::HasStream() const {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ return configs_.audio_codec != kUnknownAudioCodec;
+}
+
+void MediaCodecAudioDecoder::SetDemuxerConfigs(const DemuxerConfigs& configs) {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ DVLOG(1) << class_name() << "::" << __FUNCTION__;
+
+ configs_ = configs;
+ if (!media_codec_bridge_)
+ output_sampling_rate_ = configs.audio_sampling_rate;
+}
+
+void MediaCodecAudioDecoder::Flush() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ MediaCodecDecoder::Flush();
+ frame_count_ = 0;
+}
+
+void MediaCodecAudioDecoder::SetVolume(double volume) {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << volume;
+
+ volume_ = volume;
+ SetVolumeInternal();
+}
+
+void MediaCodecAudioDecoder::SetBaseTimestamp(base::TimeDelta base_timestamp) {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ DVLOG(1) << __FUNCTION__ << " " << base_timestamp;
+
+ base_timestamp_ = base_timestamp;
+ if (audio_timestamp_helper_)
+ audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_);
+}
+
+bool MediaCodecAudioDecoder::IsCodecReconfigureNeeded(
+ const DemuxerConfigs& curr,
+ const DemuxerConfigs& next) const {
+ return curr.audio_codec != next.audio_codec ||
+ curr.audio_channels != next.audio_channels ||
+ curr.audio_sampling_rate != next.audio_sampling_rate ||
+ next.is_audio_encrypted != next.is_audio_encrypted ||
+ curr.audio_extra_data.size() != next.audio_extra_data.size() ||
+ !std::equal(curr.audio_extra_data.begin(),
+ curr.audio_extra_data.end(),
+ next.audio_extra_data.begin());
+}
+
+MediaCodecDecoder::ConfigStatus
+MediaCodecAudioDecoder::ConfigureInternal() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ DVLOG(1) << class_name() << "::" << __FUNCTION__;
+
+ media_codec_bridge_.reset(AudioCodecBridge::Create(configs_.audio_codec));
+ if (!media_codec_bridge_)
+ return CONFIG_FAILURE;
+
+ if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))->Start(
+ configs_.audio_codec,
+ configs_.audio_sampling_rate,
+ configs_.audio_channels,
+ &configs_.audio_extra_data[0],
+ configs_.audio_extra_data.size(),
+ configs_.audio_codec_delay_ns,
+ configs_.audio_seek_preroll_ns,
+ true,
+ GetMediaCrypto().obj())) {
+
+ DVLOG(1) << class_name() << "::" << __FUNCTION__ << " failed";
+
+ media_codec_bridge_.reset();
+ return CONFIG_FAILURE;
+ }
+
+ DVLOG(1) << class_name() << "::" << __FUNCTION__ << " succeeded";
+
+ SetVolumeInternal();
+
+ bytes_per_frame_ = kBytesPerAudioOutputSample * configs_.audio_channels;
+ frame_count_ = 0;
+ ResetTimestampHelper();
+
+ return CONFIG_OK;
+}
+
+void MediaCodecAudioDecoder::OnOutputFormatChanged() {
+ DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
+
+ DCHECK(media_codec_bridge_);
+
+ int old_sampling_rate = output_sampling_rate_;
+ output_sampling_rate_ = media_codec_bridge_->GetOutputSamplingRate();
+ if (output_sampling_rate_ != old_sampling_rate)
+ ResetTimestampHelper();
+}
+
+void MediaCodecAudioDecoder::Render(int buffer_index,
+ size_t size,
+ bool render_output,
+ base::TimeDelta pts,
+ bool eos_encountered) {
+ DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
+
+ DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts;
+
+ render_output = render_output && (size != 0u);
+
+ if (render_output) {
+ int64 head_position =
+ (static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))
+ ->PlayOutputBuffer(buffer_index, size);
+
+ size_t new_frames_count = size / bytes_per_frame_;
+ frame_count_ += new_frames_count;
+ audio_timestamp_helper_->AddFrames(new_frames_count);
+ int64 frames_to_play = frame_count_ - head_position;
+ DCHECK_GE(frames_to_play, 0);
+
+ base::TimeDelta last_buffered = audio_timestamp_helper_->GetTimestamp();
+ base::TimeDelta now_playing =
+ last_buffered -
+ audio_timestamp_helper_->GetFrameDuration(frames_to_play);
+
+ DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts
+ << " will play: [" << now_playing << "," << last_buffered << "]";
+
+ media_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(update_current_time_cb_, now_playing, last_buffered));
+ }
+
+ media_codec_bridge_->ReleaseOutputBuffer(buffer_index, false);
+
+ CheckLastFrame(eos_encountered, false); // no delayed tasks
+}
+
+void MediaCodecAudioDecoder::SetVolumeInternal() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ if (media_codec_bridge_) {
+ static_cast<AudioCodecBridge*>(media_codec_bridge_.get())->SetVolume(
+ volume_);
+ }
+}
+
+void MediaCodecAudioDecoder::ResetTimestampHelper() {
+ // Media thread or Decoder thread
+ // When this method is called on Media thread, decoder thread
+ // should not be running.
+
+ if (audio_timestamp_helper_)
+ base_timestamp_ = audio_timestamp_helper_->GetTimestamp();
+
+ audio_timestamp_helper_.reset(
+ new AudioTimestampHelper(configs_.audio_sampling_rate));
+
+ audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_);
+}
+
+} // namespace media

Powered by Google App Engine
This is Rietveld 408576698