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

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

Issue 1682923003: Rename browser side MediaCodec-based decoders (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Reformatted to make bots happy Created 4 years, 10 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 2015 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/media_codec_audio_decoder.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "media/base/android/media_statistics.h"
10 #include "media/base/android/sdk_media_codec_bridge.h"
11 #include "media/base/audio_timestamp_helper.h"
12 #include "media/base/demuxer_stream.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 MediaCodecAudioDecoder::MediaCodecAudioDecoder(
24 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
25 FrameStatistics* frame_statistics,
26 const base::Closure& request_data_cb,
27 const base::Closure& starvation_cb,
28 const base::Closure& decoder_drained_cb,
29 const base::Closure& stop_done_cb,
30 const base::Closure& waiting_for_decryption_key_cb,
31 const base::Closure& error_cb,
32 const SetTimeCallback& update_current_time_cb)
33 : MediaCodecDecoder("AudioDecoder",
34 media_task_runner,
35 frame_statistics,
36 request_data_cb,
37 starvation_cb,
38 decoder_drained_cb,
39 stop_done_cb,
40 waiting_for_decryption_key_cb,
41 error_cb),
42 volume_(-1.0),
43 bytes_per_frame_(0),
44 output_sampling_rate_(0),
45 frame_count_(0),
46 update_current_time_cb_(update_current_time_cb) {
47 }
48
49 MediaCodecAudioDecoder::~MediaCodecAudioDecoder() {
50 DCHECK(media_task_runner_->BelongsToCurrentThread());
51 DVLOG(1) << "AudioDecoder::~AudioDecoder()";
52 ReleaseDecoderResources();
53 }
54
55 const char* MediaCodecAudioDecoder::class_name() const {
56 return "AudioDecoder";
57 }
58
59 bool MediaCodecAudioDecoder::HasStream() const {
60 DCHECK(media_task_runner_->BelongsToCurrentThread());
61
62 return configs_.audio_codec != kUnknownAudioCodec;
63 }
64
65 void MediaCodecAudioDecoder::SetDemuxerConfigs(const DemuxerConfigs& configs) {
66 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << configs;
67
68 configs_ = configs;
69 if (!media_codec_bridge_)
70 output_sampling_rate_ = configs.audio_sampling_rate;
71 }
72
73 bool MediaCodecAudioDecoder::IsContentEncrypted() const {
74 // Make sure SetDemuxerConfigs() as been called.
75 DCHECK(configs_.audio_codec != kUnknownAudioCodec);
76 return configs_.is_audio_encrypted;
77 }
78
79 void MediaCodecAudioDecoder::ReleaseDecoderResources() {
80 DCHECK(media_task_runner_->BelongsToCurrentThread());
81 DVLOG(1) << class_name() << "::" << __FUNCTION__;
82
83 DoEmergencyStop();
84
85 ReleaseMediaCodec();
86 }
87
88 void MediaCodecAudioDecoder::Flush() {
89 DCHECK(media_task_runner_->BelongsToCurrentThread());
90
91 MediaCodecDecoder::Flush();
92 frame_count_ = 0;
93 }
94
95 void MediaCodecAudioDecoder::SetVolume(double volume) {
96 DCHECK(media_task_runner_->BelongsToCurrentThread());
97
98 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << volume;
99
100 volume_ = volume;
101 SetVolumeInternal();
102 }
103
104 void MediaCodecAudioDecoder::SetBaseTimestamp(base::TimeDelta base_timestamp) {
105 // Called from Media thread and Decoder thread. When called from Media thread
106 // Decoder thread should not be running.
107
108 DVLOG(1) << __FUNCTION__ << " " << base_timestamp;
109
110 base_timestamp_ = base_timestamp;
111 if (audio_timestamp_helper_)
112 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_);
113 }
114
115 bool MediaCodecAudioDecoder::IsCodecReconfigureNeeded(
116 const DemuxerConfigs& next) const {
117 if (always_reconfigure_for_tests_)
118 return true;
119
120 return configs_.audio_codec != next.audio_codec ||
121 configs_.audio_channels != next.audio_channels ||
122 configs_.audio_sampling_rate != next.audio_sampling_rate ||
123 configs_.is_audio_encrypted != next.is_audio_encrypted ||
124 configs_.audio_extra_data.size() != next.audio_extra_data.size() ||
125 !std::equal(configs_.audio_extra_data.begin(),
126 configs_.audio_extra_data.end(),
127 next.audio_extra_data.begin());
128 }
129
130 MediaCodecDecoder::ConfigStatus MediaCodecAudioDecoder::ConfigureInternal(
131 jobject media_crypto) {
132 DCHECK(media_task_runner_->BelongsToCurrentThread());
133
134 DVLOG(1) << class_name() << "::" << __FUNCTION__;
135
136 if (configs_.audio_codec == kUnknownAudioCodec) {
137 DVLOG(0) << class_name() << "::" << __FUNCTION__
138 << " configuration parameters are required";
139 return kConfigFailure;
140 }
141
142 media_codec_bridge_.reset(AudioCodecBridge::Create(configs_.audio_codec));
143 if (!media_codec_bridge_)
144 return kConfigFailure;
145
146 if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))
147 ->ConfigureAndStart(
148 configs_.audio_codec, configs_.audio_sampling_rate,
149 configs_.audio_channels, &configs_.audio_extra_data[0],
150 configs_.audio_extra_data.size(), configs_.audio_codec_delay_ns,
151 configs_.audio_seek_preroll_ns, true, media_crypto)) {
152 DVLOG(0) << class_name() << "::" << __FUNCTION__
153 << " failed: cannot start audio codec";
154
155 media_codec_bridge_.reset();
156 return kConfigFailure;
157 }
158
159 DVLOG(0) << class_name() << "::" << __FUNCTION__ << " succeeded";
160
161 SetVolumeInternal();
162
163 bytes_per_frame_ = kBytesPerAudioOutputSample * configs_.audio_channels;
164 frame_count_ = 0;
165 ResetTimestampHelper();
166
167 if (!codec_created_for_tests_cb_.is_null())
168 media_task_runner_->PostTask(FROM_HERE, codec_created_for_tests_cb_);
169
170 return kConfigOk;
171 }
172
173 void MediaCodecAudioDecoder::OnOutputFormatChanged() {
174 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
175
176 DCHECK(media_codec_bridge_);
177
178 int old_sampling_rate = output_sampling_rate_;
179 output_sampling_rate_ = media_codec_bridge_->GetOutputSamplingRate();
180 if (output_sampling_rate_ != old_sampling_rate)
181 ResetTimestampHelper();
182 }
183
184 void MediaCodecAudioDecoder::Render(int buffer_index,
185 size_t offset,
186 size_t size,
187 RenderMode render_mode,
188 base::TimeDelta pts,
189 bool eos_encountered) {
190 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
191
192 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts << " "
193 << AsString(render_mode);
194
195 const bool do_play = (render_mode != kRenderSkip);
196
197 if (do_play) {
198 AudioCodecBridge* audio_codec =
199 static_cast<AudioCodecBridge*>(media_codec_bridge_.get());
200
201 DCHECK(audio_codec);
202
203 const bool postpone = (render_mode == kRenderAfterPreroll);
204
205 int64_t head_position =
206 audio_codec->PlayOutputBuffer(buffer_index, size, offset, postpone);
207
208 base::TimeTicks current_time = base::TimeTicks::Now();
209
210 frame_statistics_->IncrementFrameCount();
211
212 // Reset the base timestamp if we have not started playing.
213 // SetBaseTimestamp() must be called before AddFrames() since it resets the
214 // internal frame count.
215 if (postpone && !frame_count_)
216 SetBaseTimestamp(pts);
217
218 size_t new_frames_count = size / bytes_per_frame_;
219 frame_count_ += new_frames_count;
220 audio_timestamp_helper_->AddFrames(new_frames_count);
221
222 if (postpone) {
223 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts
224 << " POSTPONE";
225
226 // Let the player adjust the start time.
227 media_task_runner_->PostTask(
228 FROM_HERE, base::Bind(update_current_time_cb_, pts, pts, true));
229 } else {
230 int64_t frames_to_play = frame_count_ - head_position;
231
232 DCHECK_GE(frames_to_play, 0) << class_name() << "::" << __FUNCTION__
233 << " pts:" << pts
234 << " frame_count_:" << frame_count_
235 << " head_position:" << head_position;
236
237 base::TimeDelta last_buffered = audio_timestamp_helper_->GetTimestamp();
238 base::TimeDelta now_playing =
239 last_buffered -
240 audio_timestamp_helper_->GetFrameDuration(frames_to_play);
241
242 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts
243 << " will play: [" << now_playing << "," << last_buffered << "]";
244
245 // Statistics
246 if (!next_frame_time_limit_.is_null() &&
247 next_frame_time_limit_ < current_time) {
248 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " LATE FRAME delay:"
249 << current_time - next_frame_time_limit_;
250 frame_statistics_->IncrementLateFrameCount();
251 }
252
253 next_frame_time_limit_ = current_time + (last_buffered - now_playing);
254
255 media_task_runner_->PostTask(
256 FROM_HERE, base::Bind(update_current_time_cb_, now_playing,
257 last_buffered, false));
258 }
259 }
260
261 media_codec_bridge_->ReleaseOutputBuffer(buffer_index, false);
262
263 CheckLastFrame(eos_encountered, false); // no delayed tasks
264 }
265
266 void MediaCodecAudioDecoder::SetVolumeInternal() {
267 DCHECK(media_task_runner_->BelongsToCurrentThread());
268
269 if (media_codec_bridge_) {
270 static_cast<AudioCodecBridge*>(media_codec_bridge_.get())
271 ->SetVolume(volume_);
272 }
273 }
274
275 void MediaCodecAudioDecoder::ResetTimestampHelper() {
276 // Media thread or Decoder thread
277 // When this method is called on Media thread, decoder thread
278 // should not be running.
279
280 if (audio_timestamp_helper_)
281 base_timestamp_ = audio_timestamp_helper_->GetTimestamp();
282
283 audio_timestamp_helper_.reset(
284 new AudioTimestampHelper(configs_.audio_sampling_rate));
285
286 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_);
287 }
288
289 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/media_codec_audio_decoder.h ('k') | media/base/android/media_codec_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698