Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / media / base / android / audio_decoder_job.cc
blob25de5a145d6cf434e81df991f0dfa74aa86dad1e
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/base/android/audio_decoder_job.h"
7 #include "base/bind.h"
8 #include "base/lazy_instance.h"
9 #include "base/threading/thread.h"
10 #include "media/base/android/media_codec_bridge.h"
11 #include "media/base/audio_timestamp_helper.h"
13 namespace {
15 // Use 16bit PCM for audio output. Keep this value in sync with the output
16 // format we passed to AudioTrack in MediaCodecBridge.
17 const int kBytesPerAudioOutputSample = 2;
20 namespace media {
22 class AudioDecoderThread : public base::Thread {
23 public:
24 AudioDecoderThread() : base::Thread("MediaSource_AudioDecoderThread") {
25 Start();
29 // TODO(qinmin): Check if it is tolerable to use worker pool to handle all the
30 // decoding tasks so that we don't need a global thread here.
31 // http://crbug.com/245750
32 base::LazyInstance<AudioDecoderThread>::Leaky
33 g_audio_decoder_thread = LAZY_INSTANCE_INITIALIZER;
35 AudioDecoderJob::AudioDecoderJob(
36 const base::Closure& request_data_cb,
37 const base::Closure& on_demuxer_config_changed_cb)
38 : MediaDecoderJob(g_audio_decoder_thread.Pointer()->message_loop_proxy(),
39 request_data_cb,
40 on_demuxer_config_changed_cb),
41 audio_codec_(kUnknownAudioCodec),
42 num_channels_(0),
43 config_sampling_rate_(0),
44 volume_(-1.0),
45 bytes_per_frame_(0),
46 output_sampling_rate_(0),
47 frame_count_(0) {
50 AudioDecoderJob::~AudioDecoderJob() {}
52 bool AudioDecoderJob::HasStream() const {
53 return audio_codec_ != kUnknownAudioCodec;
56 void AudioDecoderJob::Flush() {
57 MediaDecoderJob::Flush();
58 frame_count_ = 0;
61 void AudioDecoderJob::SetDemuxerConfigs(const DemuxerConfigs& configs) {
62 // TODO(qinmin): split DemuxerConfig for audio and video separately so we
63 // can simply store the stucture here.
64 audio_codec_ = configs.audio_codec;
65 num_channels_ = configs.audio_channels;
66 config_sampling_rate_ = configs.audio_sampling_rate;
67 set_is_content_encrypted(configs.is_audio_encrypted);
68 audio_extra_data_ = configs.audio_extra_data;
69 audio_codec_delay_ns_ = configs.audio_codec_delay_ns;
70 audio_seek_preroll_ns_ = configs.audio_seek_preroll_ns;
71 bytes_per_frame_ = kBytesPerAudioOutputSample * num_channels_;
72 if (!media_codec_bridge_)
73 output_sampling_rate_ = config_sampling_rate_;
76 void AudioDecoderJob::SetVolume(double volume) {
77 volume_ = volume;
78 SetVolumeInternal();
81 void AudioDecoderJob::SetBaseTimestamp(base::TimeDelta base_timestamp) {
82 DCHECK(!is_decoding());
83 base_timestamp_ = base_timestamp;
84 if (audio_timestamp_helper_)
85 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_);
88 void AudioDecoderJob::ResetTimestampHelper() {
89 if (audio_timestamp_helper_)
90 base_timestamp_ = audio_timestamp_helper_->GetTimestamp();
91 audio_timestamp_helper_.reset(
92 new AudioTimestampHelper(output_sampling_rate_));
93 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_);
96 void AudioDecoderJob::ReleaseOutputBuffer(
97 int output_buffer_index,
98 size_t size,
99 bool render_output,
100 base::TimeDelta current_presentation_timestamp,
101 const ReleaseOutputCompletionCallback& callback) {
102 render_output = render_output && (size != 0u);
103 if (render_output) {
104 int64 head_position = (static_cast<AudioCodecBridge*>(
105 media_codec_bridge_.get()))->PlayOutputBuffer(
106 output_buffer_index, size);
107 size_t new_frames_count = size / bytes_per_frame_;
108 frame_count_ += new_frames_count;
109 audio_timestamp_helper_->AddFrames(new_frames_count);
110 int64 frames_to_play = frame_count_ - head_position;
111 DCHECK_GE(frames_to_play, 0);
112 current_presentation_timestamp =
113 audio_timestamp_helper_->GetTimestamp() -
114 audio_timestamp_helper_->GetFrameDuration(frames_to_play);
115 } else {
116 current_presentation_timestamp = kNoTimestamp();
118 media_codec_bridge_->ReleaseOutputBuffer(output_buffer_index, false);
120 callback.Run(current_presentation_timestamp,
121 audio_timestamp_helper_->GetTimestamp());
124 bool AudioDecoderJob::ComputeTimeToRender() const {
125 return false;
128 bool AudioDecoderJob::AreDemuxerConfigsChanged(
129 const DemuxerConfigs& configs) const {
130 return audio_codec_ != configs.audio_codec ||
131 num_channels_ != configs.audio_channels ||
132 config_sampling_rate_ != configs.audio_sampling_rate ||
133 is_content_encrypted() != configs.is_audio_encrypted ||
134 audio_extra_data_.size() != configs.audio_extra_data.size() ||
135 !std::equal(audio_extra_data_.begin(),
136 audio_extra_data_.end(),
137 configs.audio_extra_data.begin());
140 MediaDecoderJob::MediaDecoderJobStatus
141 AudioDecoderJob::CreateMediaCodecBridgeInternal() {
142 media_codec_bridge_.reset(AudioCodecBridge::Create(audio_codec_));
143 if (!media_codec_bridge_)
144 return STATUS_FAILURE;
146 if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))->Start(
147 audio_codec_, config_sampling_rate_, num_channels_, &audio_extra_data_[0],
148 audio_extra_data_.size(), audio_codec_delay_ns_, audio_seek_preroll_ns_,
149 true, GetMediaCrypto().obj())) {
150 media_codec_bridge_.reset();
151 return STATUS_FAILURE;
154 SetVolumeInternal();
156 // Reset values used to track codec bridge output
157 frame_count_ = 0;
158 ResetTimestampHelper();
160 return STATUS_SUCCESS;
163 void AudioDecoderJob::SetVolumeInternal() {
164 if (media_codec_bridge_) {
165 static_cast<AudioCodecBridge*>(media_codec_bridge_.get())->SetVolume(
166 volume_);
170 void AudioDecoderJob::OnOutputFormatChanged() {
171 DCHECK(media_codec_bridge_);
173 int old_sampling_rate = output_sampling_rate_;
174 output_sampling_rate_ = media_codec_bridge_->GetOutputSamplingRate();
175 if (output_sampling_rate_ != old_sampling_rate)
176 ResetTimestampHelper();
179 } // namespace media