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