| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "media/base/android/audio_decoder_job.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/lazy_instance.h" | |
| 9 #include "base/threading/thread.h" | |
| 10 #include "media/base/android/sdk_media_codec_bridge.h" | |
| 11 #include "media/base/audio_timestamp_helper.h" | |
| 12 #include "media/base/timestamp_constants.h" | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 // Use 16bit PCM for audio output. Keep this value in sync with the output | |
| 17 // format we passed to AudioTrack in MediaCodecBridge. | |
| 18 const int kBytesPerAudioOutputSample = 2; | |
| 19 } | |
| 20 | |
| 21 namespace media { | |
| 22 | |
| 23 class AudioDecoderThread : public base::Thread { | |
| 24 public: | |
| 25 AudioDecoderThread() : base::Thread("MediaSource_AudioDecoderThread") { | |
| 26 Start(); | |
| 27 } | |
| 28 }; | |
| 29 | |
| 30 // TODO(qinmin): Check if it is tolerable to use worker pool to handle all the | |
| 31 // decoding tasks so that we don't need a global thread here. | |
| 32 // http://crbug.com/245750 | |
| 33 base::LazyInstance<AudioDecoderThread>::Leaky | |
| 34 g_audio_decoder_thread = LAZY_INSTANCE_INITIALIZER; | |
| 35 | |
| 36 AudioDecoderJob::AudioDecoderJob( | |
| 37 const base::Closure& request_data_cb, | |
| 38 const base::Closure& on_demuxer_config_changed_cb) | |
| 39 : MediaDecoderJob(g_audio_decoder_thread.Pointer()->task_runner(), | |
| 40 request_data_cb, | |
| 41 on_demuxer_config_changed_cb), | |
| 42 audio_codec_(kUnknownAudioCodec), | |
| 43 config_num_channels_(0), | |
| 44 config_sampling_rate_(0), | |
| 45 volume_(-1.0), | |
| 46 output_sampling_rate_(0), | |
| 47 output_num_channels_(0), | |
| 48 frame_count_(0) {} | |
| 49 | |
| 50 AudioDecoderJob::~AudioDecoderJob() {} | |
| 51 | |
| 52 bool AudioDecoderJob::HasStream() const { | |
| 53 return audio_codec_ != kUnknownAudioCodec; | |
| 54 } | |
| 55 | |
| 56 void AudioDecoderJob::Flush() { | |
| 57 MediaDecoderJob::Flush(); | |
| 58 frame_count_ = 0; | |
| 59 } | |
| 60 | |
| 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 config_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 | |
| 72 if (!media_codec_bridge_) { | |
| 73 output_sampling_rate_ = config_sampling_rate_; | |
| 74 output_num_channels_ = config_num_channels_; | |
| 75 } | |
| 76 } | |
| 77 | |
| 78 void AudioDecoderJob::SetVolume(double volume) { | |
| 79 volume_ = volume; | |
| 80 SetVolumeInternal(); | |
| 81 } | |
| 82 | |
| 83 void AudioDecoderJob::SetBaseTimestamp(base::TimeDelta base_timestamp) { | |
| 84 DCHECK(!is_decoding()); | |
| 85 base_timestamp_ = base_timestamp; | |
| 86 if (audio_timestamp_helper_) | |
| 87 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_); | |
| 88 } | |
| 89 | |
| 90 void AudioDecoderJob::ResetTimestampHelper() { | |
| 91 if (audio_timestamp_helper_) | |
| 92 base_timestamp_ = audio_timestamp_helper_->GetTimestamp(); | |
| 93 audio_timestamp_helper_.reset( | |
| 94 new AudioTimestampHelper(output_sampling_rate_)); | |
| 95 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_); | |
| 96 } | |
| 97 | |
| 98 void AudioDecoderJob::ReleaseOutputBuffer( | |
| 99 int output_buffer_index, | |
| 100 size_t offset, | |
| 101 size_t size, | |
| 102 bool render_output, | |
| 103 bool /* is_late_frame */, | |
| 104 base::TimeDelta current_presentation_timestamp, | |
| 105 MediaCodecStatus status, | |
| 106 const DecoderCallback& callback) { | |
| 107 render_output = render_output && (size != 0u); | |
| 108 bool is_audio_underrun = false; | |
| 109 | |
| 110 // Ignore input value. | |
| 111 current_presentation_timestamp = kNoTimestamp; | |
| 112 | |
| 113 if (render_output) { | |
| 114 int64_t head_position; | |
| 115 MediaCodecStatus play_status = | |
| 116 (static_cast<AudioCodecBridge*>(media_codec_bridge_.get())) | |
| 117 ->PlayOutputBuffer(output_buffer_index, size, offset, false, | |
| 118 &head_position); | |
| 119 if (play_status == MEDIA_CODEC_OK) { | |
| 120 base::TimeTicks current_time = base::TimeTicks::Now(); | |
| 121 | |
| 122 size_t bytes_per_frame = | |
| 123 kBytesPerAudioOutputSample * output_num_channels_; | |
| 124 size_t new_frames_count = size / bytes_per_frame; | |
| 125 frame_count_ += new_frames_count; | |
| 126 audio_timestamp_helper_->AddFrames(new_frames_count); | |
| 127 int64_t frames_to_play = frame_count_ - head_position; | |
| 128 DCHECK_GE(frames_to_play, 0); | |
| 129 | |
| 130 const base::TimeDelta last_buffered = | |
| 131 audio_timestamp_helper_->GetTimestamp(); | |
| 132 | |
| 133 current_presentation_timestamp = | |
| 134 last_buffered - | |
| 135 audio_timestamp_helper_->GetFrameDuration(frames_to_play); | |
| 136 | |
| 137 // Potential audio underrun is considered a late frame for UMA. | |
| 138 is_audio_underrun = !next_frame_time_limit_.is_null() && | |
| 139 next_frame_time_limit_ < current_time; | |
| 140 | |
| 141 next_frame_time_limit_ = | |
| 142 current_time + (last_buffered - current_presentation_timestamp); | |
| 143 } else { | |
| 144 DLOG(ERROR) << __FUNCTION__ << ": PlayOutputBuffer failed for index:" | |
| 145 << output_buffer_index; | |
| 146 | |
| 147 // Override output status. | |
| 148 status = MEDIA_CODEC_ERROR; | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 media_codec_bridge_->ReleaseOutputBuffer(output_buffer_index, false); | |
| 153 | |
| 154 callback.Run(status, is_audio_underrun, current_presentation_timestamp, | |
| 155 audio_timestamp_helper_->GetTimestamp()); | |
| 156 } | |
| 157 | |
| 158 bool AudioDecoderJob::ComputeTimeToRender() const { | |
| 159 return false; | |
| 160 } | |
| 161 | |
| 162 bool AudioDecoderJob::AreDemuxerConfigsChanged( | |
| 163 const DemuxerConfigs& configs) const { | |
| 164 return audio_codec_ != configs.audio_codec || | |
| 165 config_num_channels_ != configs.audio_channels || | |
| 166 config_sampling_rate_ != configs.audio_sampling_rate || | |
| 167 is_content_encrypted() != configs.is_audio_encrypted || | |
| 168 audio_extra_data_.size() != configs.audio_extra_data.size() || | |
| 169 !std::equal(audio_extra_data_.begin(), audio_extra_data_.end(), | |
| 170 configs.audio_extra_data.begin()); | |
| 171 } | |
| 172 | |
| 173 MediaDecoderJob::MediaDecoderJobStatus | |
| 174 AudioDecoderJob::CreateMediaCodecBridgeInternal() { | |
| 175 media_codec_bridge_.reset(AudioCodecBridge::Create(audio_codec_)); | |
| 176 if (!media_codec_bridge_) | |
| 177 return STATUS_FAILURE; | |
| 178 | |
| 179 if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get())) | |
| 180 ->ConfigureAndStart(audio_codec_, config_sampling_rate_, | |
| 181 config_num_channels_, &audio_extra_data_[0], | |
| 182 audio_extra_data_.size(), audio_codec_delay_ns_, | |
| 183 audio_seek_preroll_ns_, true, | |
| 184 GetMediaCrypto())) { | |
| 185 media_codec_bridge_.reset(); | |
| 186 return STATUS_FAILURE; | |
| 187 } | |
| 188 | |
| 189 // ConfigureAndStart() creates AudioTrack with |config_sampling_rate_| | |
| 190 // and |config_num_channels_|. Keep |output_...| in sync to detect the changes | |
| 191 // that might come with OnOutputFormatChanged(). | |
| 192 output_sampling_rate_ = config_sampling_rate_; | |
| 193 output_num_channels_ = config_num_channels_; | |
| 194 | |
| 195 SetVolumeInternal(); | |
| 196 | |
| 197 // Reset values used to track codec bridge output | |
| 198 frame_count_ = 0; | |
| 199 ResetTimestampHelper(); | |
| 200 | |
| 201 return STATUS_SUCCESS; | |
| 202 } | |
| 203 | |
| 204 void AudioDecoderJob::SetVolumeInternal() { | |
| 205 if (media_codec_bridge_) { | |
| 206 static_cast<AudioCodecBridge*>(media_codec_bridge_.get())->SetVolume( | |
| 207 volume_); | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 bool AudioDecoderJob::OnOutputFormatChanged() { | |
| 212 DCHECK(media_codec_bridge_); | |
| 213 | |
| 214 // Recreate AudioTrack if either sample rate or output channel count changed. | |
| 215 // If we cannot obtain these values we assume they did not change. | |
| 216 bool needs_recreate_audio_track = false; | |
| 217 | |
| 218 const int old_sampling_rate = output_sampling_rate_; | |
| 219 MediaCodecStatus status = | |
| 220 media_codec_bridge_->GetOutputSamplingRate(&output_sampling_rate_); | |
| 221 | |
| 222 if (status == MEDIA_CODEC_OK && old_sampling_rate != output_sampling_rate_) { | |
| 223 DCHECK_GT(output_sampling_rate_, 0); | |
| 224 DVLOG(2) << __FUNCTION__ << ": new sampling rate " << output_sampling_rate_; | |
| 225 needs_recreate_audio_track = true; | |
| 226 | |
| 227 ResetTimestampHelper(); | |
| 228 } | |
| 229 | |
| 230 const int old_num_channels = output_num_channels_; | |
| 231 status = media_codec_bridge_->GetOutputChannelCount(&output_num_channels_); | |
| 232 | |
| 233 if (status == MEDIA_CODEC_OK && old_num_channels != output_num_channels_) { | |
| 234 DCHECK_GT(output_num_channels_, 0); | |
| 235 DVLOG(2) << __FUNCTION__ << ": new channel count " << output_num_channels_; | |
| 236 needs_recreate_audio_track = true; | |
| 237 } | |
| 238 | |
| 239 if (needs_recreate_audio_track && | |
| 240 !static_cast<AudioCodecBridge*>(media_codec_bridge_.get()) | |
| 241 ->CreateAudioTrack(output_sampling_rate_, output_num_channels_)) { | |
| 242 DLOG(ERROR) << __FUNCTION__ << ": cannot create AudioTrack"; | |
| 243 return false; | |
| 244 } | |
| 245 | |
| 246 return true; | |
| 247 } | |
| 248 | |
| 249 } // namespace media | |
| OLD | NEW |