OLD | NEW |
| (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 | |
OLD | NEW |