| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/base/android/media_codec_audio_decoder.h" | 5 #include "media/base/android/audio_media_codec_decoder.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "media/base/android/media_statistics.h" | 9 #include "media/base/android/media_statistics.h" |
| 10 #include "media/base/android/sdk_media_codec_bridge.h" | 10 #include "media/base/android/sdk_media_codec_bridge.h" |
| 11 #include "media/base/audio_timestamp_helper.h" | 11 #include "media/base/audio_timestamp_helper.h" |
| 12 #include "media/base/demuxer_stream.h" | 12 #include "media/base/demuxer_stream.h" |
| 13 | 13 |
| 14 namespace { | 14 namespace { |
| 15 | 15 |
| 16 // Use 16bit PCM for audio output. Keep this value in sync with the output | 16 // Use 16bit PCM for audio output. Keep this value in sync with the output |
| 17 // format we passed to AudioTrack in MediaCodecBridge. | 17 // format we passed to AudioTrack in MediaCodecBridge. |
| 18 const int kBytesPerAudioOutputSample = 2; | 18 const int kBytesPerAudioOutputSample = 2; |
| 19 } | 19 } |
| 20 | 20 |
| 21 namespace media { | 21 namespace media { |
| 22 | 22 |
| 23 MediaCodecAudioDecoder::MediaCodecAudioDecoder( | 23 AudioMediaCodecDecoder::AudioMediaCodecDecoder( |
| 24 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, | 24 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
| 25 FrameStatistics* frame_statistics, | 25 FrameStatistics* frame_statistics, |
| 26 const base::Closure& request_data_cb, | 26 const base::Closure& request_data_cb, |
| 27 const base::Closure& starvation_cb, | 27 const base::Closure& starvation_cb, |
| 28 const base::Closure& decoder_drained_cb, | 28 const base::Closure& decoder_drained_cb, |
| 29 const base::Closure& stop_done_cb, | 29 const base::Closure& stop_done_cb, |
| 30 const base::Closure& waiting_for_decryption_key_cb, | 30 const base::Closure& waiting_for_decryption_key_cb, |
| 31 const base::Closure& error_cb, | 31 const base::Closure& error_cb, |
| 32 const SetTimeCallback& update_current_time_cb) | 32 const SetTimeCallback& update_current_time_cb) |
| 33 : MediaCodecDecoder("AudioDecoder", | 33 : MediaCodecDecoder("AudioDecoder", |
| 34 media_task_runner, | 34 media_task_runner, |
| 35 frame_statistics, | 35 frame_statistics, |
| 36 request_data_cb, | 36 request_data_cb, |
| 37 starvation_cb, | 37 starvation_cb, |
| 38 decoder_drained_cb, | 38 decoder_drained_cb, |
| 39 stop_done_cb, | 39 stop_done_cb, |
| 40 waiting_for_decryption_key_cb, | 40 waiting_for_decryption_key_cb, |
| 41 error_cb), | 41 error_cb), |
| 42 volume_(-1.0), | 42 volume_(-1.0), |
| 43 bytes_per_frame_(0), | 43 bytes_per_frame_(0), |
| 44 output_sampling_rate_(0), | 44 output_sampling_rate_(0), |
| 45 frame_count_(0), | 45 frame_count_(0), |
| 46 update_current_time_cb_(update_current_time_cb) { | 46 update_current_time_cb_(update_current_time_cb) {} |
| 47 } | |
| 48 | 47 |
| 49 MediaCodecAudioDecoder::~MediaCodecAudioDecoder() { | 48 AudioMediaCodecDecoder::~AudioMediaCodecDecoder() { |
| 50 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 49 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 51 DVLOG(1) << "AudioDecoder::~AudioDecoder()"; | 50 DVLOG(1) << "AudioDecoder::~AudioDecoder()"; |
| 52 ReleaseDecoderResources(); | 51 ReleaseDecoderResources(); |
| 53 } | 52 } |
| 54 | 53 |
| 55 const char* MediaCodecAudioDecoder::class_name() const { | 54 const char* AudioMediaCodecDecoder::class_name() const { |
| 56 return "AudioDecoder"; | 55 return "AudioDecoder"; |
| 57 } | 56 } |
| 58 | 57 |
| 59 bool MediaCodecAudioDecoder::HasStream() const { | 58 bool AudioMediaCodecDecoder::HasStream() const { |
| 60 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 59 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 61 | 60 |
| 62 return configs_.audio_codec != kUnknownAudioCodec; | 61 return configs_.audio_codec != kUnknownAudioCodec; |
| 63 } | 62 } |
| 64 | 63 |
| 65 void MediaCodecAudioDecoder::SetDemuxerConfigs(const DemuxerConfigs& configs) { | 64 void AudioMediaCodecDecoder::SetDemuxerConfigs(const DemuxerConfigs& configs) { |
| 66 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << configs; | 65 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << configs; |
| 67 | 66 |
| 68 configs_ = configs; | 67 configs_ = configs; |
| 69 if (!media_codec_bridge_) | 68 if (!media_codec_bridge_) |
| 70 output_sampling_rate_ = configs.audio_sampling_rate; | 69 output_sampling_rate_ = configs.audio_sampling_rate; |
| 71 } | 70 } |
| 72 | 71 |
| 73 bool MediaCodecAudioDecoder::IsContentEncrypted() const { | 72 bool AudioMediaCodecDecoder::IsContentEncrypted() const { |
| 74 // Make sure SetDemuxerConfigs() as been called. | 73 // Make sure SetDemuxerConfigs() as been called. |
| 75 DCHECK(configs_.audio_codec != kUnknownAudioCodec); | 74 DCHECK(configs_.audio_codec != kUnknownAudioCodec); |
| 76 return configs_.is_audio_encrypted; | 75 return configs_.is_audio_encrypted; |
| 77 } | 76 } |
| 78 | 77 |
| 79 void MediaCodecAudioDecoder::ReleaseDecoderResources() { | 78 void AudioMediaCodecDecoder::ReleaseDecoderResources() { |
| 80 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 79 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 81 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 80 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
| 82 | 81 |
| 83 DoEmergencyStop(); | 82 DoEmergencyStop(); |
| 84 | 83 |
| 85 ReleaseMediaCodec(); | 84 ReleaseMediaCodec(); |
| 86 } | 85 } |
| 87 | 86 |
| 88 void MediaCodecAudioDecoder::Flush() { | 87 void AudioMediaCodecDecoder::Flush() { |
| 89 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 88 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 90 | 89 |
| 91 MediaCodecDecoder::Flush(); | 90 MediaCodecDecoder::Flush(); |
| 92 frame_count_ = 0; | 91 frame_count_ = 0; |
| 93 } | 92 } |
| 94 | 93 |
| 95 void MediaCodecAudioDecoder::SetVolume(double volume) { | 94 void AudioMediaCodecDecoder::SetVolume(double volume) { |
| 96 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 95 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 97 | 96 |
| 98 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << volume; | 97 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << volume; |
| 99 | 98 |
| 100 volume_ = volume; | 99 volume_ = volume; |
| 101 SetVolumeInternal(); | 100 SetVolumeInternal(); |
| 102 } | 101 } |
| 103 | 102 |
| 104 void MediaCodecAudioDecoder::SetBaseTimestamp(base::TimeDelta base_timestamp) { | 103 void AudioMediaCodecDecoder::SetBaseTimestamp(base::TimeDelta base_timestamp) { |
| 105 // Called from Media thread and Decoder thread. When called from Media thread | 104 // Called from Media thread and Decoder thread. When called from Media thread |
| 106 // Decoder thread should not be running. | 105 // Decoder thread should not be running. |
| 107 | 106 |
| 108 DVLOG(1) << __FUNCTION__ << " " << base_timestamp; | 107 DVLOG(1) << __FUNCTION__ << " " << base_timestamp; |
| 109 | 108 |
| 110 base_timestamp_ = base_timestamp; | 109 base_timestamp_ = base_timestamp; |
| 111 if (audio_timestamp_helper_) | 110 if (audio_timestamp_helper_) |
| 112 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_); | 111 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_); |
| 113 } | 112 } |
| 114 | 113 |
| 115 bool MediaCodecAudioDecoder::IsCodecReconfigureNeeded( | 114 bool AudioMediaCodecDecoder::IsCodecReconfigureNeeded( |
| 116 const DemuxerConfigs& next) const { | 115 const DemuxerConfigs& next) const { |
| 117 if (always_reconfigure_for_tests_) | 116 if (always_reconfigure_for_tests_) |
| 118 return true; | 117 return true; |
| 119 | 118 |
| 120 return configs_.audio_codec != next.audio_codec || | 119 return configs_.audio_codec != next.audio_codec || |
| 121 configs_.audio_channels != next.audio_channels || | 120 configs_.audio_channels != next.audio_channels || |
| 122 configs_.audio_sampling_rate != next.audio_sampling_rate || | 121 configs_.audio_sampling_rate != next.audio_sampling_rate || |
| 123 configs_.is_audio_encrypted != next.is_audio_encrypted || | 122 configs_.is_audio_encrypted != next.is_audio_encrypted || |
| 124 configs_.audio_extra_data.size() != next.audio_extra_data.size() || | 123 configs_.audio_extra_data.size() != next.audio_extra_data.size() || |
| 125 !std::equal(configs_.audio_extra_data.begin(), | 124 !std::equal(configs_.audio_extra_data.begin(), |
| 126 configs_.audio_extra_data.end(), | 125 configs_.audio_extra_data.end(), |
| 127 next.audio_extra_data.begin()); | 126 next.audio_extra_data.begin()); |
| 128 } | 127 } |
| 129 | 128 |
| 130 MediaCodecDecoder::ConfigStatus MediaCodecAudioDecoder::ConfigureInternal( | 129 MediaCodecDecoder::ConfigStatus AudioMediaCodecDecoder::ConfigureInternal( |
| 131 jobject media_crypto) { | 130 jobject media_crypto) { |
| 132 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 131 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 133 | 132 |
| 134 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 133 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
| 135 | 134 |
| 136 if (configs_.audio_codec == kUnknownAudioCodec) { | 135 if (configs_.audio_codec == kUnknownAudioCodec) { |
| 137 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 136 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
| 138 << " configuration parameters are required"; | 137 << " configuration parameters are required"; |
| 139 return kConfigFailure; | 138 return kConfigFailure; |
| 140 } | 139 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 163 bytes_per_frame_ = kBytesPerAudioOutputSample * configs_.audio_channels; | 162 bytes_per_frame_ = kBytesPerAudioOutputSample * configs_.audio_channels; |
| 164 frame_count_ = 0; | 163 frame_count_ = 0; |
| 165 ResetTimestampHelper(); | 164 ResetTimestampHelper(); |
| 166 | 165 |
| 167 if (!codec_created_for_tests_cb_.is_null()) | 166 if (!codec_created_for_tests_cb_.is_null()) |
| 168 media_task_runner_->PostTask(FROM_HERE, codec_created_for_tests_cb_); | 167 media_task_runner_->PostTask(FROM_HERE, codec_created_for_tests_cb_); |
| 169 | 168 |
| 170 return kConfigOk; | 169 return kConfigOk; |
| 171 } | 170 } |
| 172 | 171 |
| 173 void MediaCodecAudioDecoder::OnOutputFormatChanged() { | 172 void AudioMediaCodecDecoder::OnOutputFormatChanged() { |
| 174 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 173 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 175 | 174 |
| 176 DCHECK(media_codec_bridge_); | 175 DCHECK(media_codec_bridge_); |
| 177 | 176 |
| 178 int old_sampling_rate = output_sampling_rate_; | 177 int old_sampling_rate = output_sampling_rate_; |
| 179 output_sampling_rate_ = media_codec_bridge_->GetOutputSamplingRate(); | 178 output_sampling_rate_ = media_codec_bridge_->GetOutputSamplingRate(); |
| 180 if (output_sampling_rate_ != old_sampling_rate) | 179 if (output_sampling_rate_ != old_sampling_rate) |
| 181 ResetTimestampHelper(); | 180 ResetTimestampHelper(); |
| 182 } | 181 } |
| 183 | 182 |
| 184 void MediaCodecAudioDecoder::Render(int buffer_index, | 183 void AudioMediaCodecDecoder::Render(int buffer_index, |
| 185 size_t offset, | 184 size_t offset, |
| 186 size_t size, | 185 size_t size, |
| 187 RenderMode render_mode, | 186 RenderMode render_mode, |
| 188 base::TimeDelta pts, | 187 base::TimeDelta pts, |
| 189 bool eos_encountered) { | 188 bool eos_encountered) { |
| 190 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 189 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 191 | 190 |
| 192 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts << " " | 191 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts << " " |
| 193 << AsString(render_mode); | 192 << AsString(render_mode); |
| 194 | 193 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 FROM_HERE, base::Bind(update_current_time_cb_, now_playing, | 255 FROM_HERE, base::Bind(update_current_time_cb_, now_playing, |
| 257 last_buffered, false)); | 256 last_buffered, false)); |
| 258 } | 257 } |
| 259 } | 258 } |
| 260 | 259 |
| 261 media_codec_bridge_->ReleaseOutputBuffer(buffer_index, false); | 260 media_codec_bridge_->ReleaseOutputBuffer(buffer_index, false); |
| 262 | 261 |
| 263 CheckLastFrame(eos_encountered, false); // no delayed tasks | 262 CheckLastFrame(eos_encountered, false); // no delayed tasks |
| 264 } | 263 } |
| 265 | 264 |
| 266 void MediaCodecAudioDecoder::SetVolumeInternal() { | 265 void AudioMediaCodecDecoder::SetVolumeInternal() { |
| 267 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 266 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 268 | 267 |
| 269 if (media_codec_bridge_) { | 268 if (media_codec_bridge_) { |
| 270 static_cast<AudioCodecBridge*>(media_codec_bridge_.get()) | 269 static_cast<AudioCodecBridge*>(media_codec_bridge_.get()) |
| 271 ->SetVolume(volume_); | 270 ->SetVolume(volume_); |
| 272 } | 271 } |
| 273 } | 272 } |
| 274 | 273 |
| 275 void MediaCodecAudioDecoder::ResetTimestampHelper() { | 274 void AudioMediaCodecDecoder::ResetTimestampHelper() { |
| 276 // Media thread or Decoder thread | 275 // Media thread or Decoder thread |
| 277 // When this method is called on Media thread, decoder thread | 276 // When this method is called on Media thread, decoder thread |
| 278 // should not be running. | 277 // should not be running. |
| 279 | 278 |
| 280 if (audio_timestamp_helper_) | 279 if (audio_timestamp_helper_) |
| 281 base_timestamp_ = audio_timestamp_helper_->GetTimestamp(); | 280 base_timestamp_ = audio_timestamp_helper_->GetTimestamp(); |
| 282 | 281 |
| 283 audio_timestamp_helper_.reset( | 282 audio_timestamp_helper_.reset( |
| 284 new AudioTimestampHelper(configs_.audio_sampling_rate)); | 283 new AudioTimestampHelper(configs_.audio_sampling_rate)); |
| 285 | 284 |
| 286 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_); | 285 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_); |
| 287 } | 286 } |
| 288 | 287 |
| 289 } // namespace media | 288 } // namespace media |
| OLD | NEW |