Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: media/base/android/audio_decoder_job.cc

Issue 2283493003: Delete browser MSE implementation. (Closed)
Patch Set: Actually delete MSP. Cleanse references. Remove AudioTrack usage. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/sdk_media_codec_bridge.h"
11 #include "media/base/audio_timestamp_helper.h"
12 #include "media/base/timestamp_constants.h"
13
14 namespace {
15
16 // Use 16bit PCM for audio output. Keep this value in sync with the output
17 // format we passed to AudioTrack in MediaCodecBridge.
18 const int kBytesPerAudioOutputSample = 2;
19 }
20
21 namespace media {
22
23 class AudioDecoderThread : public base::Thread {
24 public:
25 AudioDecoderThread() : base::Thread("MediaSource_AudioDecoderThread") {
26 Start();
27 }
28 };
29
30 // TODO(qinmin): Check if it is tolerable to use worker pool to handle all the
31 // decoding tasks so that we don't need a global thread here.
32 // http://crbug.com/245750
33 base::LazyInstance<AudioDecoderThread>::Leaky
34 g_audio_decoder_thread = LAZY_INSTANCE_INITIALIZER;
35
36 AudioDecoderJob::AudioDecoderJob(
37 const base::Closure& request_data_cb,
38 const base::Closure& on_demuxer_config_changed_cb)
39 : MediaDecoderJob(g_audio_decoder_thread.Pointer()->task_runner(),
40 request_data_cb,
41 on_demuxer_config_changed_cb),
42 audio_codec_(kUnknownAudioCodec),
43 config_num_channels_(0),
44 config_sampling_rate_(0),
45 volume_(-1.0),
46 output_sampling_rate_(0),
47 output_num_channels_(0),
48 frame_count_(0) {}
49
50 AudioDecoderJob::~AudioDecoderJob() {}
51
52 bool AudioDecoderJob::HasStream() const {
53 return audio_codec_ != kUnknownAudioCodec;
54 }
55
56 void AudioDecoderJob::Flush() {
57 MediaDecoderJob::Flush();
58 frame_count_ = 0;
59 }
60
61 void AudioDecoderJob::SetDemuxerConfigs(const DemuxerConfigs& configs) {
62 // TODO(qinmin): split DemuxerConfig for audio and video separately so we
63 // can simply store the stucture here.
64 audio_codec_ = configs.audio_codec;
65 config_num_channels_ = configs.audio_channels;
66 config_sampling_rate_ = configs.audio_sampling_rate;
67 set_is_content_encrypted(configs.is_audio_encrypted);
68 audio_extra_data_ = configs.audio_extra_data;
69 audio_codec_delay_ns_ = configs.audio_codec_delay_ns;
70 audio_seek_preroll_ns_ = configs.audio_seek_preroll_ns;
71
72 if (!media_codec_bridge_) {
73 output_sampling_rate_ = config_sampling_rate_;
74 output_num_channels_ = config_num_channels_;
75 }
76 }
77
78 void AudioDecoderJob::SetVolume(double volume) {
79 volume_ = volume;
80 SetVolumeInternal();
81 }
82
83 void AudioDecoderJob::SetBaseTimestamp(base::TimeDelta base_timestamp) {
84 DCHECK(!is_decoding());
85 base_timestamp_ = base_timestamp;
86 if (audio_timestamp_helper_)
87 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_);
88 }
89
90 void AudioDecoderJob::ResetTimestampHelper() {
91 if (audio_timestamp_helper_)
92 base_timestamp_ = audio_timestamp_helper_->GetTimestamp();
93 audio_timestamp_helper_.reset(
94 new AudioTimestampHelper(output_sampling_rate_));
95 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_);
96 }
97
98 void AudioDecoderJob::ReleaseOutputBuffer(
99 int output_buffer_index,
100 size_t offset,
101 size_t size,
102 bool render_output,
103 bool /* is_late_frame */,
104 base::TimeDelta current_presentation_timestamp,
105 MediaCodecStatus status,
106 const DecoderCallback& callback) {
107 render_output = render_output && (size != 0u);
108 bool is_audio_underrun = false;
109
110 // Ignore input value.
111 current_presentation_timestamp = kNoTimestamp;
112
113 if (render_output) {
114 int64_t head_position;
115 MediaCodecStatus play_status =
116 (static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))
117 ->PlayOutputBuffer(output_buffer_index, size, offset, false,
118 &head_position);
119 if (play_status == MEDIA_CODEC_OK) {
120 base::TimeTicks current_time = base::TimeTicks::Now();
121
122 size_t bytes_per_frame =
123 kBytesPerAudioOutputSample * output_num_channels_;
124 size_t new_frames_count = size / bytes_per_frame;
125 frame_count_ += new_frames_count;
126 audio_timestamp_helper_->AddFrames(new_frames_count);
127 int64_t frames_to_play = frame_count_ - head_position;
128 DCHECK_GE(frames_to_play, 0);
129
130 const base::TimeDelta last_buffered =
131 audio_timestamp_helper_->GetTimestamp();
132
133 current_presentation_timestamp =
134 last_buffered -
135 audio_timestamp_helper_->GetFrameDuration(frames_to_play);
136
137 // Potential audio underrun is considered a late frame for UMA.
138 is_audio_underrun = !next_frame_time_limit_.is_null() &&
139 next_frame_time_limit_ < current_time;
140
141 next_frame_time_limit_ =
142 current_time + (last_buffered - current_presentation_timestamp);
143 } else {
144 DLOG(ERROR) << __FUNCTION__ << ": PlayOutputBuffer failed for index:"
145 << output_buffer_index;
146
147 // Override output status.
148 status = MEDIA_CODEC_ERROR;
149 }
150 }
151
152 media_codec_bridge_->ReleaseOutputBuffer(output_buffer_index, false);
153
154 callback.Run(status, is_audio_underrun, current_presentation_timestamp,
155 audio_timestamp_helper_->GetTimestamp());
156 }
157
158 bool AudioDecoderJob::ComputeTimeToRender() const {
159 return false;
160 }
161
162 bool AudioDecoderJob::AreDemuxerConfigsChanged(
163 const DemuxerConfigs& configs) const {
164 return audio_codec_ != configs.audio_codec ||
165 config_num_channels_ != configs.audio_channels ||
166 config_sampling_rate_ != configs.audio_sampling_rate ||
167 is_content_encrypted() != configs.is_audio_encrypted ||
168 audio_extra_data_.size() != configs.audio_extra_data.size() ||
169 !std::equal(audio_extra_data_.begin(), audio_extra_data_.end(),
170 configs.audio_extra_data.begin());
171 }
172
173 MediaDecoderJob::MediaDecoderJobStatus
174 AudioDecoderJob::CreateMediaCodecBridgeInternal() {
175 media_codec_bridge_.reset(AudioCodecBridge::Create(audio_codec_));
176 if (!media_codec_bridge_)
177 return STATUS_FAILURE;
178
179 if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))
180 ->ConfigureAndStart(audio_codec_, config_sampling_rate_,
181 config_num_channels_, &audio_extra_data_[0],
182 audio_extra_data_.size(), audio_codec_delay_ns_,
183 audio_seek_preroll_ns_, true,
184 GetMediaCrypto())) {
185 media_codec_bridge_.reset();
186 return STATUS_FAILURE;
187 }
188
189 // ConfigureAndStart() creates AudioTrack with |config_sampling_rate_|
190 // and |config_num_channels_|. Keep |output_...| in sync to detect the changes
191 // that might come with OnOutputFormatChanged().
192 output_sampling_rate_ = config_sampling_rate_;
193 output_num_channels_ = config_num_channels_;
194
195 SetVolumeInternal();
196
197 // Reset values used to track codec bridge output
198 frame_count_ = 0;
199 ResetTimestampHelper();
200
201 return STATUS_SUCCESS;
202 }
203
204 void AudioDecoderJob::SetVolumeInternal() {
205 if (media_codec_bridge_) {
206 static_cast<AudioCodecBridge*>(media_codec_bridge_.get())->SetVolume(
207 volume_);
208 }
209 }
210
211 bool AudioDecoderJob::OnOutputFormatChanged() {
212 DCHECK(media_codec_bridge_);
213
214 // Recreate AudioTrack if either sample rate or output channel count changed.
215 // If we cannot obtain these values we assume they did not change.
216 bool needs_recreate_audio_track = false;
217
218 const int old_sampling_rate = output_sampling_rate_;
219 MediaCodecStatus status =
220 media_codec_bridge_->GetOutputSamplingRate(&output_sampling_rate_);
221
222 if (status == MEDIA_CODEC_OK && old_sampling_rate != output_sampling_rate_) {
223 DCHECK_GT(output_sampling_rate_, 0);
224 DVLOG(2) << __FUNCTION__ << ": new sampling rate " << output_sampling_rate_;
225 needs_recreate_audio_track = true;
226
227 ResetTimestampHelper();
228 }
229
230 const int old_num_channels = output_num_channels_;
231 status = media_codec_bridge_->GetOutputChannelCount(&output_num_channels_);
232
233 if (status == MEDIA_CODEC_OK && old_num_channels != output_num_channels_) {
234 DCHECK_GT(output_num_channels_, 0);
235 DVLOG(2) << __FUNCTION__ << ": new channel count " << output_num_channels_;
236 needs_recreate_audio_track = true;
237 }
238
239 if (needs_recreate_audio_track &&
240 !static_cast<AudioCodecBridge*>(media_codec_bridge_.get())
241 ->CreateAudioTrack(output_sampling_rate_, output_num_channels_)) {
242 DLOG(ERROR) << __FUNCTION__ << ": cannot create AudioTrack";
243 return false;
244 }
245
246 return true;
247 }
248
249 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698