| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "media/base/android/audio_media_codec_decoder.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "media/base/android/media_statistics.h" | |
| 10 #include "media/base/android/sdk_media_codec_bridge.h" | |
| 11 #include "media/base/audio_timestamp_helper.h" | |
| 12 #include "media/base/demuxer_stream.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 AudioMediaCodecDecoder::AudioMediaCodecDecoder( | |
| 24 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, | |
| 25 FrameStatistics* frame_statistics, | |
| 26 const base::Closure& request_data_cb, | |
| 27 const base::Closure& starvation_cb, | |
| 28 const base::Closure& decoder_drained_cb, | |
| 29 const base::Closure& stop_done_cb, | |
| 30 const base::Closure& waiting_for_decryption_key_cb, | |
| 31 const base::Closure& error_cb, | |
| 32 const SetTimeCallback& update_current_time_cb) | |
| 33 : MediaCodecDecoder("AudioDecoder", | |
| 34 media_task_runner, | |
| 35 frame_statistics, | |
| 36 request_data_cb, | |
| 37 starvation_cb, | |
| 38 decoder_drained_cb, | |
| 39 stop_done_cb, | |
| 40 waiting_for_decryption_key_cb, | |
| 41 error_cb), | |
| 42 volume_(-1.0), | |
| 43 output_sampling_rate_(0), | |
| 44 output_num_channels_(0), | |
| 45 frame_count_(0), | |
| 46 update_current_time_cb_(update_current_time_cb) {} | |
| 47 | |
| 48 AudioMediaCodecDecoder::~AudioMediaCodecDecoder() { | |
| 49 DCHECK(media_task_runner_->BelongsToCurrentThread()); | |
| 50 DVLOG(1) << "AudioDecoder::~AudioDecoder()"; | |
| 51 ReleaseDecoderResources(); | |
| 52 } | |
| 53 | |
| 54 const char* AudioMediaCodecDecoder::class_name() const { | |
| 55 return "AudioDecoder"; | |
| 56 } | |
| 57 | |
| 58 bool AudioMediaCodecDecoder::HasStream() const { | |
| 59 DCHECK(media_task_runner_->BelongsToCurrentThread()); | |
| 60 | |
| 61 return configs_.audio_codec != kUnknownAudioCodec; | |
| 62 } | |
| 63 | |
| 64 void AudioMediaCodecDecoder::SetDemuxerConfigs(const DemuxerConfigs& configs) { | |
| 65 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << configs; | |
| 66 | |
| 67 configs_ = configs; | |
| 68 if (!media_codec_bridge_) { | |
| 69 output_sampling_rate_ = configs.audio_sampling_rate; | |
| 70 output_num_channels_ = configs.audio_channels; | |
| 71 } | |
| 72 } | |
| 73 | |
| 74 bool AudioMediaCodecDecoder::IsContentEncrypted() const { | |
| 75 // Make sure SetDemuxerConfigs() as been called. | |
| 76 DCHECK(configs_.audio_codec != kUnknownAudioCodec); | |
| 77 return configs_.is_audio_encrypted; | |
| 78 } | |
| 79 | |
| 80 void AudioMediaCodecDecoder::ReleaseDecoderResources() { | |
| 81 DCHECK(media_task_runner_->BelongsToCurrentThread()); | |
| 82 DVLOG(1) << class_name() << "::" << __FUNCTION__; | |
| 83 | |
| 84 DoEmergencyStop(); | |
| 85 | |
| 86 ReleaseMediaCodec(); | |
| 87 } | |
| 88 | |
| 89 void AudioMediaCodecDecoder::Flush() { | |
| 90 DCHECK(media_task_runner_->BelongsToCurrentThread()); | |
| 91 | |
| 92 MediaCodecDecoder::Flush(); | |
| 93 frame_count_ = 0; | |
| 94 } | |
| 95 | |
| 96 void AudioMediaCodecDecoder::SetVolume(double volume) { | |
| 97 DCHECK(media_task_runner_->BelongsToCurrentThread()); | |
| 98 | |
| 99 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << volume; | |
| 100 | |
| 101 volume_ = volume; | |
| 102 SetVolumeInternal(); | |
| 103 } | |
| 104 | |
| 105 void AudioMediaCodecDecoder::SetBaseTimestamp(base::TimeDelta base_timestamp) { | |
| 106 // Called from Media thread and Decoder thread. When called from Media thread | |
| 107 // Decoder thread should not be running. | |
| 108 | |
| 109 DVLOG(1) << __FUNCTION__ << " " << base_timestamp; | |
| 110 | |
| 111 base_timestamp_ = base_timestamp; | |
| 112 if (audio_timestamp_helper_) | |
| 113 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_); | |
| 114 } | |
| 115 | |
| 116 bool AudioMediaCodecDecoder::IsCodecReconfigureNeeded( | |
| 117 const DemuxerConfigs& next) const { | |
| 118 if (always_reconfigure_for_tests_) | |
| 119 return true; | |
| 120 | |
| 121 return configs_.audio_codec != next.audio_codec || | |
| 122 configs_.audio_channels != next.audio_channels || | |
| 123 configs_.audio_sampling_rate != next.audio_sampling_rate || | |
| 124 configs_.is_audio_encrypted != next.is_audio_encrypted || | |
| 125 configs_.audio_extra_data.size() != next.audio_extra_data.size() || | |
| 126 !std::equal(configs_.audio_extra_data.begin(), | |
| 127 configs_.audio_extra_data.end(), | |
| 128 next.audio_extra_data.begin()); | |
| 129 } | |
| 130 | |
| 131 MediaCodecDecoder::ConfigStatus AudioMediaCodecDecoder::ConfigureInternal( | |
| 132 jobject media_crypto) { | |
| 133 DCHECK(media_task_runner_->BelongsToCurrentThread()); | |
| 134 | |
| 135 DVLOG(1) << class_name() << "::" << __FUNCTION__; | |
| 136 | |
| 137 if (configs_.audio_codec == kUnknownAudioCodec) { | |
| 138 DVLOG(0) << class_name() << "::" << __FUNCTION__ | |
| 139 << " configuration parameters are required"; | |
| 140 return kConfigFailure; | |
| 141 } | |
| 142 | |
| 143 media_codec_bridge_.reset(AudioCodecBridge::Create(configs_.audio_codec)); | |
| 144 if (!media_codec_bridge_) | |
| 145 return kConfigFailure; | |
| 146 | |
| 147 if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get())) | |
| 148 ->ConfigureAndStart( | |
| 149 configs_.audio_codec, configs_.audio_sampling_rate, | |
| 150 configs_.audio_channels, &configs_.audio_extra_data[0], | |
| 151 configs_.audio_extra_data.size(), configs_.audio_codec_delay_ns, | |
| 152 configs_.audio_seek_preroll_ns, true, media_crypto)) { | |
| 153 DVLOG(0) << class_name() << "::" << __FUNCTION__ | |
| 154 << " failed: cannot start audio codec"; | |
| 155 | |
| 156 media_codec_bridge_.reset(); | |
| 157 return kConfigFailure; | |
| 158 } | |
| 159 | |
| 160 DVLOG(0) << class_name() << "::" << __FUNCTION__ << " succeeded"; | |
| 161 | |
| 162 // ConfigureAndStart() creates AudioTrack with sampling rate and channel count | |
| 163 // from |configs_|. Keep |output_...| in sync to detect the changes that might | |
| 164 // come with OnOutputFormatChanged(). | |
| 165 output_sampling_rate_ = configs_.audio_sampling_rate; | |
| 166 output_num_channels_ = configs_.audio_channels; | |
| 167 | |
| 168 SetVolumeInternal(); | |
| 169 | |
| 170 frame_count_ = 0; | |
| 171 ResetTimestampHelper(); | |
| 172 | |
| 173 if (!codec_created_for_tests_cb_.is_null()) | |
| 174 media_task_runner_->PostTask(FROM_HERE, codec_created_for_tests_cb_); | |
| 175 | |
| 176 return kConfigOk; | |
| 177 } | |
| 178 | |
| 179 bool AudioMediaCodecDecoder::OnOutputFormatChanged() { | |
| 180 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | |
| 181 | |
| 182 DCHECK(media_codec_bridge_); | |
| 183 | |
| 184 // Recreate AudioTrack if either sample rate or output channel count changed. | |
| 185 // If we cannot obtain these values we assume they did not change. | |
| 186 bool needs_recreate_audio_track = false; | |
| 187 | |
| 188 const int old_sampling_rate = output_sampling_rate_; | |
| 189 MediaCodecStatus status = | |
| 190 media_codec_bridge_->GetOutputSamplingRate(&output_sampling_rate_); | |
| 191 | |
| 192 if (status == MEDIA_CODEC_OK && old_sampling_rate != output_sampling_rate_) { | |
| 193 DCHECK_GT(output_sampling_rate_, 0); | |
| 194 DVLOG(2) << __FUNCTION__ << ": new sampling rate " << output_sampling_rate_; | |
| 195 needs_recreate_audio_track = true; | |
| 196 | |
| 197 ResetTimestampHelper(); | |
| 198 } | |
| 199 | |
| 200 const int old_num_channels = output_num_channels_; | |
| 201 status = media_codec_bridge_->GetOutputChannelCount(&output_num_channels_); | |
| 202 | |
| 203 if (status == MEDIA_CODEC_OK && old_num_channels != output_num_channels_) { | |
| 204 DCHECK_GT(output_num_channels_, 0); | |
| 205 DVLOG(2) << __FUNCTION__ << ": new channel count " << output_num_channels_; | |
| 206 needs_recreate_audio_track = true; | |
| 207 } | |
| 208 | |
| 209 if (needs_recreate_audio_track && | |
| 210 !static_cast<AudioCodecBridge*>(media_codec_bridge_.get()) | |
| 211 ->CreateAudioTrack(output_sampling_rate_, output_num_channels_)) { | |
| 212 DLOG(ERROR) << __FUNCTION__ << ": cannot create AudioTrack"; | |
| 213 return false; | |
| 214 } | |
| 215 | |
| 216 return true; | |
| 217 } | |
| 218 | |
| 219 bool AudioMediaCodecDecoder::Render(int buffer_index, | |
| 220 size_t offset, | |
| 221 size_t size, | |
| 222 RenderMode render_mode, | |
| 223 base::TimeDelta pts, | |
| 224 bool eos_encountered) { | |
| 225 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | |
| 226 | |
| 227 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts << " " | |
| 228 << AsString(render_mode); | |
| 229 | |
| 230 const bool do_play = (render_mode != kRenderSkip); | |
| 231 | |
| 232 if (do_play) { | |
| 233 AudioCodecBridge* audio_codec = | |
| 234 static_cast<AudioCodecBridge*>(media_codec_bridge_.get()); | |
| 235 | |
| 236 DCHECK(audio_codec); | |
| 237 | |
| 238 const bool postpone = (render_mode == kRenderAfterPreroll); | |
| 239 | |
| 240 int64_t head_position; | |
| 241 MediaCodecStatus status = audio_codec->PlayOutputBuffer( | |
| 242 buffer_index, size, offset, postpone, &head_position); | |
| 243 | |
| 244 if (status != MEDIA_CODEC_OK) { | |
| 245 DLOG(ERROR) << class_name() << "::" << __FUNCTION__ << " pts:" << pts | |
| 246 << " PlayOutputBuffer failed for index:" << buffer_index; | |
| 247 media_codec_bridge_->ReleaseOutputBuffer(buffer_index, false); | |
| 248 return false; | |
| 249 } | |
| 250 | |
| 251 base::TimeTicks current_time = base::TimeTicks::Now(); | |
| 252 | |
| 253 frame_statistics_->IncrementFrameCount(); | |
| 254 | |
| 255 // Reset the base timestamp if we have not started playing. | |
| 256 // SetBaseTimestamp() must be called before AddFrames() since it resets the | |
| 257 // internal frame count. | |
| 258 if (postpone && !frame_count_) | |
| 259 SetBaseTimestamp(pts); | |
| 260 | |
| 261 const size_t bytes_per_frame = | |
| 262 kBytesPerAudioOutputSample * output_num_channels_; | |
| 263 const size_t new_frames_count = size / bytes_per_frame; | |
| 264 frame_count_ += new_frames_count; | |
| 265 audio_timestamp_helper_->AddFrames(new_frames_count); | |
| 266 | |
| 267 if (postpone) { | |
| 268 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts | |
| 269 << " POSTPONE"; | |
| 270 | |
| 271 // Let the player adjust the start time. | |
| 272 media_task_runner_->PostTask( | |
| 273 FROM_HERE, base::Bind(update_current_time_cb_, pts, pts, true)); | |
| 274 } else { | |
| 275 int64_t frames_to_play = frame_count_ - head_position; | |
| 276 | |
| 277 DCHECK_GE(frames_to_play, 0) << class_name() << "::" << __FUNCTION__ | |
| 278 << " pts:" << pts | |
| 279 << " frame_count_:" << frame_count_ | |
| 280 << " head_position:" << head_position; | |
| 281 | |
| 282 base::TimeDelta last_buffered = audio_timestamp_helper_->GetTimestamp(); | |
| 283 base::TimeDelta now_playing = | |
| 284 last_buffered - | |
| 285 audio_timestamp_helper_->GetFrameDuration(frames_to_play); | |
| 286 | |
| 287 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts | |
| 288 << " will play: [" << now_playing << "," << last_buffered << "]"; | |
| 289 | |
| 290 // Statistics | |
| 291 if (!next_frame_time_limit_.is_null() && | |
| 292 next_frame_time_limit_ < current_time) { | |
| 293 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " LATE FRAME delay:" | |
| 294 << current_time - next_frame_time_limit_; | |
| 295 frame_statistics_->IncrementLateFrameCount(); | |
| 296 } | |
| 297 | |
| 298 next_frame_time_limit_ = current_time + (last_buffered - now_playing); | |
| 299 | |
| 300 media_task_runner_->PostTask( | |
| 301 FROM_HERE, base::Bind(update_current_time_cb_, now_playing, | |
| 302 last_buffered, false)); | |
| 303 } | |
| 304 } | |
| 305 | |
| 306 media_codec_bridge_->ReleaseOutputBuffer(buffer_index, false); | |
| 307 | |
| 308 CheckLastFrame(eos_encountered, false); // no delayed tasks | |
| 309 | |
| 310 return true; | |
| 311 } | |
| 312 | |
| 313 void AudioMediaCodecDecoder::SetVolumeInternal() { | |
| 314 DCHECK(media_task_runner_->BelongsToCurrentThread()); | |
| 315 | |
| 316 if (media_codec_bridge_) { | |
| 317 static_cast<AudioCodecBridge*>(media_codec_bridge_.get()) | |
| 318 ->SetVolume(volume_); | |
| 319 } | |
| 320 } | |
| 321 | |
| 322 void AudioMediaCodecDecoder::ResetTimestampHelper() { | |
| 323 // Media thread or Decoder thread | |
| 324 // When this method is called on Media thread, decoder thread | |
| 325 // should not be running. | |
| 326 | |
| 327 if (audio_timestamp_helper_) | |
| 328 base_timestamp_ = audio_timestamp_helper_->GetTimestamp(); | |
| 329 | |
| 330 audio_timestamp_helper_.reset( | |
| 331 new AudioTimestampHelper(output_sampling_rate_)); | |
| 332 | |
| 333 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_); | |
| 334 } | |
| 335 | |
| 336 } // namespace media | |
| OLD | NEW |