Home | History | Annotate | Download | only in android
      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 
     13 namespace {
     14 
     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;
     18 }
     19 
     20 namespace media {
     21 
     22 class 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
     32 base::LazyInstance<AudioDecoderThread>::Leaky
     33     g_audio_decoder_thread = LAZY_INSTANCE_INITIALIZER;
     34 
     35 AudioDecoderJob::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 
     48 AudioDecoderJob::~AudioDecoderJob() {}
     49 
     50 bool AudioDecoderJob::HasStream() const {
     51   return audio_codec_ != kUnknownAudioCodec;
     52 }
     53 
     54 void AudioDecoderJob::SetDemuxerConfigs(const DemuxerConfigs& configs) {
     55   // TODO(qinmin): split DemuxerConfig for audio and video separately so we
     56   // can simply store the stucture here.
     57   audio_codec_ = configs.audio_codec;
     58   num_channels_ = configs.audio_channels;
     59   sampling_rate_ = configs.audio_sampling_rate;
     60   set_is_content_encrypted(configs.is_audio_encrypted);
     61   audio_extra_data_ = configs.audio_extra_data;
     62   bytes_per_frame_ = kBytesPerAudioOutputSample * num_channels_;
     63 }
     64 
     65 void AudioDecoderJob::SetVolume(double volume) {
     66   volume_ = volume;
     67   SetVolumeInternal();
     68 }
     69 
     70 void AudioDecoderJob::SetBaseTimestamp(base::TimeDelta base_timestamp) {
     71   DCHECK(!is_decoding());
     72   base_timestamp_ = base_timestamp;
     73   if (audio_timestamp_helper_)
     74     audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_);
     75 }
     76 
     77 void AudioDecoderJob::ReleaseOutputBuffer(
     78     int output_buffer_index,
     79     size_t size,
     80     bool render_output,
     81     base::TimeDelta current_presentation_timestamp,
     82     const ReleaseOutputCompletionCallback& callback) {
     83   render_output = render_output && (size != 0u);
     84   if (render_output) {
     85     int64 head_position = (static_cast<AudioCodecBridge*>(
     86         media_codec_bridge_.get()))->PlayOutputBuffer(
     87             output_buffer_index, size);
     88     audio_timestamp_helper_->AddFrames(size / bytes_per_frame_);
     89     int64 frames_to_play =
     90         audio_timestamp_helper_->frame_count() - head_position;
     91     DCHECK_GE(frames_to_play, 0);
     92     current_presentation_timestamp =
     93         audio_timestamp_helper_->GetTimestamp() -
     94         audio_timestamp_helper_->GetFrameDuration(frames_to_play);
     95   } else {
     96     current_presentation_timestamp = kNoTimestamp();
     97   }
     98   media_codec_bridge_->ReleaseOutputBuffer(output_buffer_index, false);
     99 
    100   callback.Run(current_presentation_timestamp,
    101                audio_timestamp_helper_->GetTimestamp());
    102 }
    103 
    104 bool AudioDecoderJob::ComputeTimeToRender() const {
    105   return false;
    106 }
    107 
    108 bool 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 
    120 bool 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 
    142 void 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