cb882cee42e1a8938fe8e462d7934a9af5a4adb9
[platform/framework/web/crosswalk.git] / src / media / base / android / audio_decoder_job.cc
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::SetVolume(double volume) {
55   volume_ = volume;
56   SetVolumeInternal();
57 }
58
59 void 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
66 void 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
93 bool AudioDecoderJob::ComputeTimeToRender() const {
94   return false;
95 }
96
97 void 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
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