1 // Copyright 2015 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/media_codec_audio_decoder.h"
8 #include "base/logging.h"
9 #include "media/base/android/media_codec_bridge.h"
10 #include "media/base/audio_timestamp_helper.h"
11 #include "media/base/demuxer_stream.h"
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;
22 MediaCodecAudioDecoder::MediaCodecAudioDecoder(
23 const scoped_refptr
<base::SingleThreadTaskRunner
>& media_task_runner
,
24 const base::Closure
& request_data_cb
,
25 const base::Closure
& starvation_cb
,
26 const base::Closure
& stop_done_cb
,
27 const base::Closure
& error_cb
,
28 const SetTimeCallback
& update_current_time_cb
)
29 : MediaCodecDecoder(media_task_runner
,
37 output_sampling_rate_(0),
39 update_current_time_cb_(update_current_time_cb
) {
42 MediaCodecAudioDecoder::~MediaCodecAudioDecoder() {
43 DVLOG(1) << "AudioDecoder::~AudioDecoder()";
44 ReleaseDecoderResources();
47 const char* MediaCodecAudioDecoder::class_name() const {
48 return "AudioDecoder";
51 bool MediaCodecAudioDecoder::HasStream() const {
52 DCHECK(media_task_runner_
->BelongsToCurrentThread());
54 return configs_
.audio_codec
!= kUnknownAudioCodec
;
57 void MediaCodecAudioDecoder::SetDemuxerConfigs(const DemuxerConfigs
& configs
) {
58 DCHECK(media_task_runner_
->BelongsToCurrentThread());
60 DVLOG(1) << class_name() << "::" << __FUNCTION__
<< " " << configs
;
63 if (!media_codec_bridge_
)
64 output_sampling_rate_
= configs
.audio_sampling_rate
;
67 void MediaCodecAudioDecoder::Flush() {
68 DCHECK(media_task_runner_
->BelongsToCurrentThread());
70 MediaCodecDecoder::Flush();
74 void MediaCodecAudioDecoder::SetVolume(double volume
) {
75 DCHECK(media_task_runner_
->BelongsToCurrentThread());
77 DVLOG(1) << class_name() << "::" << __FUNCTION__
<< " " << volume
;
83 void MediaCodecAudioDecoder::SetBaseTimestamp(base::TimeDelta base_timestamp
) {
84 DCHECK(media_task_runner_
->BelongsToCurrentThread());
86 DVLOG(1) << __FUNCTION__
<< " " << base_timestamp
;
88 base_timestamp_
= base_timestamp
;
89 if (audio_timestamp_helper_
)
90 audio_timestamp_helper_
->SetBaseTimestamp(base_timestamp_
);
93 bool MediaCodecAudioDecoder::IsCodecReconfigureNeeded(
94 const DemuxerConfigs
& curr
,
95 const DemuxerConfigs
& next
) const {
96 return curr
.audio_codec
!= next
.audio_codec
||
97 curr
.audio_channels
!= next
.audio_channels
||
98 curr
.audio_sampling_rate
!= next
.audio_sampling_rate
||
99 next
.is_audio_encrypted
!= next
.is_audio_encrypted
||
100 curr
.audio_extra_data
.size() != next
.audio_extra_data
.size() ||
101 !std::equal(curr
.audio_extra_data
.begin(), curr
.audio_extra_data
.end(),
102 next
.audio_extra_data
.begin());
105 MediaCodecDecoder::ConfigStatus
MediaCodecAudioDecoder::ConfigureInternal() {
106 DCHECK(media_task_runner_
->BelongsToCurrentThread());
108 DVLOG(1) << class_name() << "::" << __FUNCTION__
;
110 media_codec_bridge_
.reset(AudioCodecBridge::Create(configs_
.audio_codec
));
111 if (!media_codec_bridge_
)
112 return CONFIG_FAILURE
;
114 if (!(static_cast<AudioCodecBridge
*>(media_codec_bridge_
.get()))
116 configs_
.audio_codec
,
117 configs_
.audio_sampling_rate
,
118 configs_
.audio_channels
,
119 &configs_
.audio_extra_data
[0],
120 configs_
.audio_extra_data
.size(),
121 configs_
.audio_codec_delay_ns
,
122 configs_
.audio_seek_preroll_ns
,
124 GetMediaCrypto().obj())) {
125 DVLOG(1) << class_name() << "::" << __FUNCTION__
<< " failed";
127 media_codec_bridge_
.reset();
128 return CONFIG_FAILURE
;
131 DVLOG(1) << class_name() << "::" << __FUNCTION__
<< " succeeded";
135 bytes_per_frame_
= kBytesPerAudioOutputSample
* configs_
.audio_channels
;
137 ResetTimestampHelper();
142 void MediaCodecAudioDecoder::OnOutputFormatChanged() {
143 DCHECK(decoder_thread_
.task_runner()->BelongsToCurrentThread());
145 DCHECK(media_codec_bridge_
);
147 int old_sampling_rate
= output_sampling_rate_
;
148 output_sampling_rate_
= media_codec_bridge_
->GetOutputSamplingRate();
149 if (output_sampling_rate_
!= old_sampling_rate
)
150 ResetTimestampHelper();
153 void MediaCodecAudioDecoder::Render(int buffer_index
,
157 bool eos_encountered
) {
158 DCHECK(decoder_thread_
.task_runner()->BelongsToCurrentThread());
160 DVLOG(2) << class_name() << "::" << __FUNCTION__
<< " pts:" << pts
;
162 render_output
= render_output
&& (size
!= 0u);
165 int64 head_position
=
166 (static_cast<AudioCodecBridge
*>(media_codec_bridge_
.get()))
167 ->PlayOutputBuffer(buffer_index
, size
);
169 size_t new_frames_count
= size
/ bytes_per_frame_
;
170 frame_count_
+= new_frames_count
;
171 audio_timestamp_helper_
->AddFrames(new_frames_count
);
172 int64 frames_to_play
= frame_count_
- head_position
;
173 DCHECK_GE(frames_to_play
, 0);
175 base::TimeDelta last_buffered
= audio_timestamp_helper_
->GetTimestamp();
176 base::TimeDelta now_playing
=
178 audio_timestamp_helper_
->GetFrameDuration(frames_to_play
);
180 DVLOG(2) << class_name() << "::" << __FUNCTION__
<< " pts:" << pts
181 << " will play: [" << now_playing
<< "," << last_buffered
<< "]";
183 media_task_runner_
->PostTask(
185 base::Bind(update_current_time_cb_
, now_playing
, last_buffered
));
188 media_codec_bridge_
->ReleaseOutputBuffer(buffer_index
, false);
190 CheckLastFrame(eos_encountered
, false); // no delayed tasks
193 void MediaCodecAudioDecoder::SetVolumeInternal() {
194 DCHECK(media_task_runner_
->BelongsToCurrentThread());
196 if (media_codec_bridge_
) {
197 static_cast<AudioCodecBridge
*>(media_codec_bridge_
.get())
198 ->SetVolume(volume_
);
202 void MediaCodecAudioDecoder::ResetTimestampHelper() {
203 // Media thread or Decoder thread
204 // When this method is called on Media thread, decoder thread
205 // should not be running.
207 if (audio_timestamp_helper_
)
208 base_timestamp_
= audio_timestamp_helper_
->GetTimestamp();
210 audio_timestamp_helper_
.reset(
211 new AudioTimestampHelper(configs_
.audio_sampling_rate
));
213 audio_timestamp_helper_
->SetBaseTimestamp(base_timestamp_
);