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/media_codec_bridge.h" 11#include "media/base/audio_timestamp_helper.h" 12 13namespace { 14 15// Use 16bit PCM for audio output. Keep this value in sync with the output 16// format we passed to AudioTrack in MediaCodecBridge. 17const int kBytesPerAudioOutputSample = 2; 18} 19 20namespace media { 21 22class AudioDecoderThread : public base::Thread { 23 public: 24 AudioDecoderThread() : base::Thread("MediaSource_AudioDecoderThread") { 25 Start(); 26 } 27}; 28 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 32base::LazyInstance<AudioDecoderThread>::Leaky 33 g_audio_decoder_thread = LAZY_INSTANCE_INITIALIZER; 34 35AudioDecoderJob::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 sampling_rate_(0), 44 volume_(-1.0), 45 bytes_per_frame_(0) { 46} 47 48AudioDecoderJob::~AudioDecoderJob() {} 49 50bool AudioDecoderJob::HasStream() const { 51 return audio_codec_ != kUnknownAudioCodec; 52} 53 54void AudioDecoderJob::SetVolume(double volume) { 55 volume_ = volume; 56 SetVolumeInternal(); 57} 58 59void AudioDecoderJob::SetBaseTimestamp(base::TimeDelta base_timestamp) { 60 DCHECK(!is_decoding()); 61 base_timestamp_ = base_timestamp; 62 if (audio_timestamp_helper_) 63 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_); 64} 65 66void AudioDecoderJob::ReleaseOutputBuffer( 67 int output_buffer_index, 68 size_t size, 69 bool render_output, 70 base::TimeDelta current_presentation_timestamp, 71 const ReleaseOutputCompletionCallback& callback) { 72 render_output = render_output && (size != 0u); 73 if (render_output) { 74 int64 head_position = (static_cast<AudioCodecBridge*>( 75 media_codec_bridge_.get()))->PlayOutputBuffer( 76 output_buffer_index, size); 77 audio_timestamp_helper_->AddFrames(size / bytes_per_frame_); 78 int64 frames_to_play = 79 audio_timestamp_helper_->frame_count() - head_position; 80 DCHECK_GE(frames_to_play, 0); 81 current_presentation_timestamp = 82 audio_timestamp_helper_->GetTimestamp() - 83 audio_timestamp_helper_->GetFrameDuration(frames_to_play); 84 } else { 85 current_presentation_timestamp = kNoTimestamp(); 86 } 87 media_codec_bridge_->ReleaseOutputBuffer(output_buffer_index, false); 88 89 callback.Run(current_presentation_timestamp, 90 audio_timestamp_helper_->GetTimestamp()); 91} 92 93bool AudioDecoderJob::ComputeTimeToRender() const { 94 return false; 95} 96 97void AudioDecoderJob::UpdateDemuxerConfigs(const DemuxerConfigs& configs) { 98 // TODO(qinmin): split DemuxerConfig for audio and video separately so we 99 // can simply store the stucture here. 100 audio_codec_ = configs.audio_codec; 101 num_channels_ = configs.audio_channels; 102 sampling_rate_ = configs.audio_sampling_rate; 103 set_is_content_encrypted(configs.is_audio_encrypted); 104 audio_extra_data_ = configs.audio_extra_data; 105 bytes_per_frame_ = kBytesPerAudioOutputSample * num_channels_; 106} 107 108bool AudioDecoderJob::AreDemuxerConfigsChanged( 109 const DemuxerConfigs& configs) const { 110 return audio_codec_ != configs.audio_codec || 111 num_channels_ != configs.audio_channels || 112 sampling_rate_ != configs.audio_sampling_rate || 113 is_content_encrypted() != configs.is_audio_encrypted || 114 audio_extra_data_.size() != configs.audio_extra_data.size() || 115 !std::equal(audio_extra_data_.begin(), 116 audio_extra_data_.end(), 117 configs.audio_extra_data.begin()); 118} 119 120bool AudioDecoderJob::CreateMediaCodecBridgeInternal() { 121 media_codec_bridge_.reset(AudioCodecBridge::Create(audio_codec_)); 122 if (!media_codec_bridge_) 123 return false; 124 125 if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))->Start( 126 audio_codec_, sampling_rate_, num_channels_, &audio_extra_data_[0], 127 audio_extra_data_.size(), true, GetMediaCrypto().obj())) { 128 media_codec_bridge_.reset(); 129 return false; 130 } 131 132 SetVolumeInternal(); 133 134 // Need to pass the base timestamp to the new decoder. 135 if (audio_timestamp_helper_) 136 base_timestamp_ = audio_timestamp_helper_->GetTimestamp(); 137 audio_timestamp_helper_.reset(new AudioTimestampHelper(sampling_rate_)); 138 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_); 139 return true; 140} 141 142void AudioDecoderJob::SetVolumeInternal() { 143 if (media_codec_bridge_) { 144 static_cast<AudioCodecBridge*>(media_codec_bridge_.get())->SetVolume( 145 volume_); 146 } 147} 148 149} // namespace media 150