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

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

Issue 2276343005: Delete MediaCodecPlayer, it's time! (Closed)
Patch Set: Created 4 years, 3 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/audio_media_codec_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 AudioMediaCodecDecoder::AudioMediaCodecDecoder(
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 output_sampling_rate_(0),
44 output_num_channels_(0),
45 frame_count_(0),
46 update_current_time_cb_(update_current_time_cb) {}
47
48 AudioMediaCodecDecoder::~AudioMediaCodecDecoder() {
49 DCHECK(media_task_runner_->BelongsToCurrentThread());
50 DVLOG(1) << "AudioDecoder::~AudioDecoder()";
51 ReleaseDecoderResources();
52 }
53
54 const char* AudioMediaCodecDecoder::class_name() const {
55 return "AudioDecoder";
56 }
57
58 bool AudioMediaCodecDecoder::HasStream() const {
59 DCHECK(media_task_runner_->BelongsToCurrentThread());
60
61 return configs_.audio_codec != kUnknownAudioCodec;
62 }
63
64 void AudioMediaCodecDecoder::SetDemuxerConfigs(const DemuxerConfigs& configs) {
65 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << configs;
66
67 configs_ = configs;
68 if (!media_codec_bridge_) {
69 output_sampling_rate_ = configs.audio_sampling_rate;
70 output_num_channels_ = configs.audio_channels;
71 }
72 }
73
74 bool AudioMediaCodecDecoder::IsContentEncrypted() const {
75 // Make sure SetDemuxerConfigs() as been called.
76 DCHECK(configs_.audio_codec != kUnknownAudioCodec);
77 return configs_.is_audio_encrypted;
78 }
79
80 void AudioMediaCodecDecoder::ReleaseDecoderResources() {
81 DCHECK(media_task_runner_->BelongsToCurrentThread());
82 DVLOG(1) << class_name() << "::" << __FUNCTION__;
83
84 DoEmergencyStop();
85
86 ReleaseMediaCodec();
87 }
88
89 void AudioMediaCodecDecoder::Flush() {
90 DCHECK(media_task_runner_->BelongsToCurrentThread());
91
92 MediaCodecDecoder::Flush();
93 frame_count_ = 0;
94 }
95
96 void AudioMediaCodecDecoder::SetVolume(double volume) {
97 DCHECK(media_task_runner_->BelongsToCurrentThread());
98
99 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << volume;
100
101 volume_ = volume;
102 SetVolumeInternal();
103 }
104
105 void AudioMediaCodecDecoder::SetBaseTimestamp(base::TimeDelta base_timestamp) {
106 // Called from Media thread and Decoder thread. When called from Media thread
107 // Decoder thread should not be running.
108
109 DVLOG(1) << __FUNCTION__ << " " << base_timestamp;
110
111 base_timestamp_ = base_timestamp;
112 if (audio_timestamp_helper_)
113 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_);
114 }
115
116 bool AudioMediaCodecDecoder::IsCodecReconfigureNeeded(
117 const DemuxerConfigs& next) const {
118 if (always_reconfigure_for_tests_)
119 return true;
120
121 return configs_.audio_codec != next.audio_codec ||
122 configs_.audio_channels != next.audio_channels ||
123 configs_.audio_sampling_rate != next.audio_sampling_rate ||
124 configs_.is_audio_encrypted != next.is_audio_encrypted ||
125 configs_.audio_extra_data.size() != next.audio_extra_data.size() ||
126 !std::equal(configs_.audio_extra_data.begin(),
127 configs_.audio_extra_data.end(),
128 next.audio_extra_data.begin());
129 }
130
131 MediaCodecDecoder::ConfigStatus AudioMediaCodecDecoder::ConfigureInternal(
132 jobject media_crypto) {
133 DCHECK(media_task_runner_->BelongsToCurrentThread());
134
135 DVLOG(1) << class_name() << "::" << __FUNCTION__;
136
137 if (configs_.audio_codec == kUnknownAudioCodec) {
138 DVLOG(0) << class_name() << "::" << __FUNCTION__
139 << " configuration parameters are required";
140 return kConfigFailure;
141 }
142
143 media_codec_bridge_.reset(AudioCodecBridge::Create(configs_.audio_codec));
144 if (!media_codec_bridge_)
145 return kConfigFailure;
146
147 if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))
148 ->ConfigureAndStart(
149 configs_.audio_codec, configs_.audio_sampling_rate,
150 configs_.audio_channels, &configs_.audio_extra_data[0],
151 configs_.audio_extra_data.size(), configs_.audio_codec_delay_ns,
152 configs_.audio_seek_preroll_ns, true, media_crypto)) {
153 DVLOG(0) << class_name() << "::" << __FUNCTION__
154 << " failed: cannot start audio codec";
155
156 media_codec_bridge_.reset();
157 return kConfigFailure;
158 }
159
160 DVLOG(0) << class_name() << "::" << __FUNCTION__ << " succeeded";
161
162 // ConfigureAndStart() creates AudioTrack with sampling rate and channel count
163 // from |configs_|. Keep |output_...| in sync to detect the changes that might
164 // come with OnOutputFormatChanged().
165 output_sampling_rate_ = configs_.audio_sampling_rate;
166 output_num_channels_ = configs_.audio_channels;
167
168 SetVolumeInternal();
169
170 frame_count_ = 0;
171 ResetTimestampHelper();
172
173 if (!codec_created_for_tests_cb_.is_null())
174 media_task_runner_->PostTask(FROM_HERE, codec_created_for_tests_cb_);
175
176 return kConfigOk;
177 }
178
179 bool AudioMediaCodecDecoder::OnOutputFormatChanged() {
180 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
181
182 DCHECK(media_codec_bridge_);
183
184 // Recreate AudioTrack if either sample rate or output channel count changed.
185 // If we cannot obtain these values we assume they did not change.
186 bool needs_recreate_audio_track = false;
187
188 const int old_sampling_rate = output_sampling_rate_;
189 MediaCodecStatus status =
190 media_codec_bridge_->GetOutputSamplingRate(&output_sampling_rate_);
191
192 if (status == MEDIA_CODEC_OK && old_sampling_rate != output_sampling_rate_) {
193 DCHECK_GT(output_sampling_rate_, 0);
194 DVLOG(2) << __FUNCTION__ << ": new sampling rate " << output_sampling_rate_;
195 needs_recreate_audio_track = true;
196
197 ResetTimestampHelper();
198 }
199
200 const int old_num_channels = output_num_channels_;
201 status = media_codec_bridge_->GetOutputChannelCount(&output_num_channels_);
202
203 if (status == MEDIA_CODEC_OK && old_num_channels != output_num_channels_) {
204 DCHECK_GT(output_num_channels_, 0);
205 DVLOG(2) << __FUNCTION__ << ": new channel count " << output_num_channels_;
206 needs_recreate_audio_track = true;
207 }
208
209 if (needs_recreate_audio_track &&
210 !static_cast<AudioCodecBridge*>(media_codec_bridge_.get())
211 ->CreateAudioTrack(output_sampling_rate_, output_num_channels_)) {
212 DLOG(ERROR) << __FUNCTION__ << ": cannot create AudioTrack";
213 return false;
214 }
215
216 return true;
217 }
218
219 bool AudioMediaCodecDecoder::Render(int buffer_index,
220 size_t offset,
221 size_t size,
222 RenderMode render_mode,
223 base::TimeDelta pts,
224 bool eos_encountered) {
225 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
226
227 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts << " "
228 << AsString(render_mode);
229
230 const bool do_play = (render_mode != kRenderSkip);
231
232 if (do_play) {
233 AudioCodecBridge* audio_codec =
234 static_cast<AudioCodecBridge*>(media_codec_bridge_.get());
235
236 DCHECK(audio_codec);
237
238 const bool postpone = (render_mode == kRenderAfterPreroll);
239
240 int64_t head_position;
241 MediaCodecStatus status = audio_codec->PlayOutputBuffer(
242 buffer_index, size, offset, postpone, &head_position);
243
244 if (status != MEDIA_CODEC_OK) {
245 DLOG(ERROR) << class_name() << "::" << __FUNCTION__ << " pts:" << pts
246 << " PlayOutputBuffer failed for index:" << buffer_index;
247 media_codec_bridge_->ReleaseOutputBuffer(buffer_index, false);
248 return false;
249 }
250
251 base::TimeTicks current_time = base::TimeTicks::Now();
252
253 frame_statistics_->IncrementFrameCount();
254
255 // Reset the base timestamp if we have not started playing.
256 // SetBaseTimestamp() must be called before AddFrames() since it resets the
257 // internal frame count.
258 if (postpone && !frame_count_)
259 SetBaseTimestamp(pts);
260
261 const size_t bytes_per_frame =
262 kBytesPerAudioOutputSample * output_num_channels_;
263 const size_t new_frames_count = size / bytes_per_frame;
264 frame_count_ += new_frames_count;
265 audio_timestamp_helper_->AddFrames(new_frames_count);
266
267 if (postpone) {
268 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts
269 << " POSTPONE";
270
271 // Let the player adjust the start time.
272 media_task_runner_->PostTask(
273 FROM_HERE, base::Bind(update_current_time_cb_, pts, pts, true));
274 } else {
275 int64_t frames_to_play = frame_count_ - head_position;
276
277 DCHECK_GE(frames_to_play, 0) << class_name() << "::" << __FUNCTION__
278 << " pts:" << pts
279 << " frame_count_:" << frame_count_
280 << " head_position:" << head_position;
281
282 base::TimeDelta last_buffered = audio_timestamp_helper_->GetTimestamp();
283 base::TimeDelta now_playing =
284 last_buffered -
285 audio_timestamp_helper_->GetFrameDuration(frames_to_play);
286
287 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts
288 << " will play: [" << now_playing << "," << last_buffered << "]";
289
290 // Statistics
291 if (!next_frame_time_limit_.is_null() &&
292 next_frame_time_limit_ < current_time) {
293 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " LATE FRAME delay:"
294 << current_time - next_frame_time_limit_;
295 frame_statistics_->IncrementLateFrameCount();
296 }
297
298 next_frame_time_limit_ = current_time + (last_buffered - now_playing);
299
300 media_task_runner_->PostTask(
301 FROM_HERE, base::Bind(update_current_time_cb_, now_playing,
302 last_buffered, false));
303 }
304 }
305
306 media_codec_bridge_->ReleaseOutputBuffer(buffer_index, false);
307
308 CheckLastFrame(eos_encountered, false); // no delayed tasks
309
310 return true;
311 }
312
313 void AudioMediaCodecDecoder::SetVolumeInternal() {
314 DCHECK(media_task_runner_->BelongsToCurrentThread());
315
316 if (media_codec_bridge_) {
317 static_cast<AudioCodecBridge*>(media_codec_bridge_.get())
318 ->SetVolume(volume_);
319 }
320 }
321
322 void AudioMediaCodecDecoder::ResetTimestampHelper() {
323 // Media thread or Decoder thread
324 // When this method is called on Media thread, decoder thread
325 // should not be running.
326
327 if (audio_timestamp_helper_)
328 base_timestamp_ = audio_timestamp_helper_->GetTimestamp();
329
330 audio_timestamp_helper_.reset(
331 new AudioTimestampHelper(output_sampling_rate_));
332
333 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_);
334 }
335
336 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/audio_media_codec_decoder.h ('k') | media/base/android/media_codec_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698