OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/base/android/media_codec_audio_decoder.h" | 5 #include "media/base/android/media_codec_audio_decoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "media/base/android/media_codec_bridge.h" | 9 #include "media/base/android/media_codec_bridge.h" |
10 #include "media/base/android/media_statistics.h" | |
10 #include "media/base/audio_timestamp_helper.h" | 11 #include "media/base/audio_timestamp_helper.h" |
11 #include "media/base/demuxer_stream.h" | 12 #include "media/base/demuxer_stream.h" |
12 | 13 |
13 namespace { | 14 namespace { |
14 | 15 |
15 // Use 16bit PCM for audio output. Keep this value in sync with the output | 16 // Use 16bit PCM for audio output. Keep this value in sync with the output |
16 // format we passed to AudioTrack in MediaCodecBridge. | 17 // format we passed to AudioTrack in MediaCodecBridge. |
17 const int kBytesPerAudioOutputSample = 2; | 18 const int kBytesPerAudioOutputSample = 2; |
18 } | 19 } |
19 | 20 |
20 namespace media { | 21 namespace media { |
21 | 22 |
22 MediaCodecAudioDecoder::MediaCodecAudioDecoder( | 23 MediaCodecAudioDecoder::MediaCodecAudioDecoder( |
23 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, | 24 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
24 const base::Closure& request_data_cb, | 25 const base::Closure& request_data_cb, |
25 const base::Closure& starvation_cb, | 26 const base::Closure& starvation_cb, |
26 const base::Closure& decoder_drained_cb, | 27 const base::Closure& decoder_drained_cb, |
27 const base::Closure& stop_done_cb, | 28 const base::Closure& stop_done_cb, |
28 const base::Closure& key_required_cb, | 29 const base::Closure& key_required_cb, |
29 const base::Closure& error_cb, | 30 const base::Closure& error_cb, |
30 const SetTimeCallback& update_current_time_cb) | 31 const SetTimeCallback& update_current_time_cb, |
32 FrameStatistics* frame_statistics) | |
31 : MediaCodecDecoder(media_task_runner, | 33 : MediaCodecDecoder(media_task_runner, |
32 request_data_cb, | 34 request_data_cb, |
33 starvation_cb, | 35 starvation_cb, |
34 decoder_drained_cb, | 36 decoder_drained_cb, |
35 stop_done_cb, | 37 stop_done_cb, |
36 key_required_cb, | 38 key_required_cb, |
37 error_cb, | 39 error_cb, |
38 "AudioDecoder"), | 40 "AudioDecoder", |
41 frame_statistics), | |
39 volume_(-1.0), | 42 volume_(-1.0), |
40 bytes_per_frame_(0), | 43 bytes_per_frame_(0), |
41 output_sampling_rate_(0), | 44 output_sampling_rate_(0), |
42 frame_count_(0), | 45 frame_count_(0), |
43 update_current_time_cb_(update_current_time_cb) { | 46 update_current_time_cb_(update_current_time_cb) { |
44 } | 47 } |
45 | 48 |
46 MediaCodecAudioDecoder::~MediaCodecAudioDecoder() { | 49 MediaCodecAudioDecoder::~MediaCodecAudioDecoder() { |
47 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 50 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
48 DVLOG(1) << "AudioDecoder::~AudioDecoder()"; | 51 DVLOG(1) << "AudioDecoder::~AudioDecoder()"; |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
198 AudioCodecBridge* audio_codec = | 201 AudioCodecBridge* audio_codec = |
199 static_cast<AudioCodecBridge*>(media_codec_bridge_.get()); | 202 static_cast<AudioCodecBridge*>(media_codec_bridge_.get()); |
200 | 203 |
201 DCHECK(audio_codec); | 204 DCHECK(audio_codec); |
202 | 205 |
203 const bool postpone = (render_mode == kRenderAfterPreroll); | 206 const bool postpone = (render_mode == kRenderAfterPreroll); |
204 | 207 |
205 int64 head_position = | 208 int64 head_position = |
206 audio_codec->PlayOutputBuffer(buffer_index, size, offset, postpone); | 209 audio_codec->PlayOutputBuffer(buffer_index, size, offset, postpone); |
207 | 210 |
211 base::TimeTicks current_time = base::TimeTicks::Now(); | |
212 | |
213 if (frame_statistics_) | |
214 frame_statistics_->AddFrame(); | |
xhwang
2015/09/30 21:02:57
When can frame_statistics_ be null? Is it only in
Tima Vaisburd
2015/10/01 20:05:15
Done.
| |
215 | |
208 // Reset the base timestamp if we have not started playing. | 216 // Reset the base timestamp if we have not started playing. |
209 // SetBaseTimestamp() must be called before AddFrames() since it resets the | 217 // SetBaseTimestamp() must be called before AddFrames() since it resets the |
210 // internal frame count. | 218 // internal frame count. |
211 if (postpone && !frame_count_) | 219 if (postpone && !frame_count_) |
212 SetBaseTimestamp(pts); | 220 SetBaseTimestamp(pts); |
213 | 221 |
214 size_t new_frames_count = size / bytes_per_frame_; | 222 size_t new_frames_count = size / bytes_per_frame_; |
215 frame_count_ += new_frames_count; | 223 frame_count_ += new_frames_count; |
216 audio_timestamp_helper_->AddFrames(new_frames_count); | 224 audio_timestamp_helper_->AddFrames(new_frames_count); |
217 | 225 |
(...skipping 13 matching lines...) Expand all Loading... | |
231 << " head_position:" << head_position; | 239 << " head_position:" << head_position; |
232 | 240 |
233 base::TimeDelta last_buffered = audio_timestamp_helper_->GetTimestamp(); | 241 base::TimeDelta last_buffered = audio_timestamp_helper_->GetTimestamp(); |
234 base::TimeDelta now_playing = | 242 base::TimeDelta now_playing = |
235 last_buffered - | 243 last_buffered - |
236 audio_timestamp_helper_->GetFrameDuration(frames_to_play); | 244 audio_timestamp_helper_->GetFrameDuration(frames_to_play); |
237 | 245 |
238 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts | 246 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " pts:" << pts |
239 << " will play: [" << now_playing << "," << last_buffered << "]"; | 247 << " will play: [" << now_playing << "," << last_buffered << "]"; |
240 | 248 |
249 // Statistics | |
250 if (frame_statistics_ && !next_frame_time_limit_.is_null() && | |
251 next_frame_time_limit_ < current_time) | |
252 frame_statistics_->AddLateFrame(current_time - next_frame_time_limit_); | |
253 | |
254 next_frame_time_limit_ = current_time + (last_buffered - now_playing); | |
255 | |
241 media_task_runner_->PostTask( | 256 media_task_runner_->PostTask( |
242 FROM_HERE, base::Bind(update_current_time_cb_, now_playing, | 257 FROM_HERE, base::Bind(update_current_time_cb_, now_playing, |
243 last_buffered, false)); | 258 last_buffered, false)); |
244 } | 259 } |
245 } | 260 } |
246 | 261 |
247 media_codec_bridge_->ReleaseOutputBuffer(buffer_index, false); | 262 media_codec_bridge_->ReleaseOutputBuffer(buffer_index, false); |
248 | 263 |
249 CheckLastFrame(eos_encountered, false); // no delayed tasks | 264 if (CheckLastFrame(eos_encountered, false)) { // no delayed tasks |
265 // This is the last frame | |
266 next_frame_time_limit_ = base::TimeTicks(); | |
267 } | |
250 } | 268 } |
251 | 269 |
252 void MediaCodecAudioDecoder::SetVolumeInternal() { | 270 void MediaCodecAudioDecoder::SetVolumeInternal() { |
253 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 271 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
254 | 272 |
255 if (media_codec_bridge_) { | 273 if (media_codec_bridge_) { |
256 static_cast<AudioCodecBridge*>(media_codec_bridge_.get()) | 274 static_cast<AudioCodecBridge*>(media_codec_bridge_.get()) |
257 ->SetVolume(volume_); | 275 ->SetVolume(volume_); |
258 } | 276 } |
259 } | 277 } |
260 | 278 |
261 void MediaCodecAudioDecoder::ResetTimestampHelper() { | 279 void MediaCodecAudioDecoder::ResetTimestampHelper() { |
262 // Media thread or Decoder thread | 280 // Media thread or Decoder thread |
263 // When this method is called on Media thread, decoder thread | 281 // When this method is called on Media thread, decoder thread |
264 // should not be running. | 282 // should not be running. |
265 | 283 |
266 if (audio_timestamp_helper_) | 284 if (audio_timestamp_helper_) |
267 base_timestamp_ = audio_timestamp_helper_->GetTimestamp(); | 285 base_timestamp_ = audio_timestamp_helper_->GetTimestamp(); |
268 | 286 |
269 audio_timestamp_helper_.reset( | 287 audio_timestamp_helper_.reset( |
270 new AudioTimestampHelper(configs_.audio_sampling_rate)); | 288 new AudioTimestampHelper(configs_.audio_sampling_rate)); |
271 | 289 |
272 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_); | 290 audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_); |
273 } | 291 } |
274 | 292 |
275 } // namespace media | 293 } // namespace media |
OLD | NEW |