OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/filters/ffmpeg_audio_decoder.h" | 5 #include "media/filters/ffmpeg_audio_decoder.h" |
6 | 6 |
7 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
8 #include "base/single_thread_task_runner.h" | 8 #include "base/single_thread_task_runner.h" |
9 #include "media/base/audio_buffer.h" | 9 #include "media/base/audio_buffer.h" |
10 #include "media/base/audio_bus.h" | 10 #include "media/base/audio_bus.h" |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 log_cb_(log_cb) { | 134 log_cb_(log_cb) { |
135 } | 135 } |
136 | 136 |
137 FFmpegAudioDecoder::~FFmpegAudioDecoder() { | 137 FFmpegAudioDecoder::~FFmpegAudioDecoder() { |
138 DCHECK_EQ(state_, kUninitialized); | 138 DCHECK_EQ(state_, kUninitialized); |
139 DCHECK(!codec_context_); | 139 DCHECK(!codec_context_); |
140 DCHECK(!av_frame_); | 140 DCHECK(!av_frame_); |
141 } | 141 } |
142 | 142 |
143 void FFmpegAudioDecoder::Initialize(const AudioDecoderConfig& config, | 143 void FFmpegAudioDecoder::Initialize(const AudioDecoderConfig& config, |
144 const PipelineStatusCB& status_cb) { | 144 const PipelineStatusCB& status_cb, |
| 145 const OutputCB& output_cb) { |
145 DCHECK(task_runner_->BelongsToCurrentThread()); | 146 DCHECK(task_runner_->BelongsToCurrentThread()); |
146 DCHECK(!config.is_encrypted()); | 147 DCHECK(!config.is_encrypted()); |
147 | 148 |
148 FFmpegGlue::InitializeFFmpeg(); | 149 FFmpegGlue::InitializeFFmpeg(); |
149 | 150 |
150 config_ = config; | 151 config_ = config; |
151 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); | 152 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); |
152 | 153 |
153 if (!config.IsValidConfig() || !ConfigureDecoder()) { | 154 if (!config.IsValidConfig() || !ConfigureDecoder()) { |
154 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 155 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
155 return; | 156 return; |
156 } | 157 } |
157 | 158 |
158 // Success! | 159 // Success! |
| 160 output_cb_ = BindToCurrentLoop(output_cb); |
159 state_ = kNormal; | 161 state_ = kNormal; |
160 initialize_cb.Run(PIPELINE_OK); | 162 initialize_cb.Run(PIPELINE_OK); |
161 } | 163 } |
162 | 164 |
163 void FFmpegAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 165 void FFmpegAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
164 const DecodeCB& decode_cb) { | 166 const DecodeCB& decode_cb) { |
165 DCHECK(task_runner_->BelongsToCurrentThread()); | 167 DCHECK(task_runner_->BelongsToCurrentThread()); |
166 DCHECK(!decode_cb.is_null()); | 168 DCHECK(!decode_cb.is_null()); |
167 CHECK_NE(state_, kUninitialized); | 169 CHECK_NE(state_, kUninitialized); |
168 DecodeCB decode_cb_bound = BindToCurrentLoop(decode_cb); | 170 DecodeCB decode_cb_bound = BindToCurrentLoop(decode_cb); |
169 | 171 |
170 if (state_ == kError) { | 172 if (state_ == kError) { |
171 decode_cb_bound.Run(kDecodeError, NULL); | 173 decode_cb_bound.Run(kDecodeError); |
172 return; | 174 return; |
173 } | 175 } |
174 | 176 |
175 // Return empty frames if decoding has finished. | 177 // Do nothing if decoding has finished. |
176 if (state_ == kDecodeFinished) { | 178 if (state_ == kDecodeFinished) { |
177 decode_cb_bound.Run(kOk, AudioBuffer::CreateEOSBuffer()); | 179 decode_cb_bound.Run(kOk); |
178 return; | |
179 } | |
180 | |
181 if (!buffer) { | |
182 decode_cb_bound.Run(kAborted, NULL); | |
183 return; | 180 return; |
184 } | 181 } |
185 | 182 |
186 DecodeBuffer(buffer, decode_cb_bound); | 183 DecodeBuffer(buffer, decode_cb_bound); |
187 } | 184 } |
188 | 185 |
189 scoped_refptr<AudioBuffer> FFmpegAudioDecoder::GetDecodeOutput() { | |
190 DCHECK(task_runner_->BelongsToCurrentThread()); | |
191 if (queued_audio_.empty()) | |
192 return NULL; | |
193 scoped_refptr<AudioBuffer> out = queued_audio_.front(); | |
194 queued_audio_.pop_front(); | |
195 return out; | |
196 } | |
197 | |
198 void FFmpegAudioDecoder::Reset(const base::Closure& closure) { | 186 void FFmpegAudioDecoder::Reset(const base::Closure& closure) { |
199 DCHECK(task_runner_->BelongsToCurrentThread()); | 187 DCHECK(task_runner_->BelongsToCurrentThread()); |
200 | 188 |
201 avcodec_flush_buffers(codec_context_.get()); | 189 avcodec_flush_buffers(codec_context_.get()); |
202 state_ = kNormal; | 190 state_ = kNormal; |
203 ResetTimestampState(); | 191 ResetTimestampState(); |
204 task_runner_->PostTask(FROM_HERE, closure); | 192 task_runner_->PostTask(FROM_HERE, closure); |
205 } | 193 } |
206 | 194 |
207 void FFmpegAudioDecoder::Stop() { | 195 void FFmpegAudioDecoder::Stop() { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 // When avcodec_decode_audio4() returns 0 data. | 238 // When avcodec_decode_audio4() returns 0 data. |
251 // kFlushCodec -> kError: | 239 // kFlushCodec -> kError: |
252 // When avcodec_decode_audio4() errors out. | 240 // When avcodec_decode_audio4() errors out. |
253 // (any state) -> kNormal: | 241 // (any state) -> kNormal: |
254 // Any time Reset() is called. | 242 // Any time Reset() is called. |
255 | 243 |
256 // Make sure we are notified if http://crbug.com/49709 returns. Issue also | 244 // Make sure we are notified if http://crbug.com/49709 returns. Issue also |
257 // occurs with some damaged files. | 245 // occurs with some damaged files. |
258 if (!buffer->end_of_stream() && buffer->timestamp() == kNoTimestamp()) { | 246 if (!buffer->end_of_stream() && buffer->timestamp() == kNoTimestamp()) { |
259 DVLOG(1) << "Received a buffer without timestamps!"; | 247 DVLOG(1) << "Received a buffer without timestamps!"; |
260 decode_cb.Run(kDecodeError, NULL); | 248 decode_cb.Run(kDecodeError); |
261 return; | 249 return; |
262 } | 250 } |
263 | 251 |
264 if (!buffer->end_of_stream() && !discard_helper_->initialized() && | 252 if (!buffer->end_of_stream() && !discard_helper_->initialized() && |
265 codec_context_->codec_id == AV_CODEC_ID_VORBIS && | 253 codec_context_->codec_id == AV_CODEC_ID_VORBIS && |
266 buffer->timestamp() < base::TimeDelta()) { | 254 buffer->timestamp() < base::TimeDelta()) { |
267 // Dropping frames for negative timestamps as outlined in section A.2 | 255 // Dropping frames for negative timestamps as outlined in section A.2 |
268 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html | 256 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html |
269 const int discard_frames = | 257 const int discard_frames = |
270 discard_helper_->TimeDeltaToFrames(-buffer->timestamp()); | 258 discard_helper_->TimeDeltaToFrames(-buffer->timestamp()); |
271 discard_helper_->Reset(discard_frames); | 259 discard_helper_->Reset(discard_frames); |
272 } | 260 } |
273 | 261 |
274 // Transition to kFlushCodec on the first end of stream buffer. | |
275 if (state_ == kNormal && buffer->end_of_stream()) { | |
276 state_ = kFlushCodec; | |
277 } | |
278 | |
279 if (!FFmpegDecode(buffer)) { | 262 if (!FFmpegDecode(buffer)) { |
280 state_ = kError; | 263 state_ = kError; |
281 decode_cb.Run(kDecodeError, NULL); | 264 decode_cb.Run(kDecodeError); |
282 return; | 265 return; |
283 } | 266 } |
284 | 267 |
285 if (queued_audio_.empty()) { | 268 if (buffer->end_of_stream()) { |
286 if (state_ == kFlushCodec) { | 269 state_ = kDecodeFinished; |
287 DCHECK(buffer->end_of_stream()); | 270 output_cb_.Run(AudioBuffer::CreateEOSBuffer()); |
288 state_ = kDecodeFinished; | |
289 decode_cb.Run(kOk, AudioBuffer::CreateEOSBuffer()); | |
290 return; | |
291 } | |
292 | |
293 decode_cb.Run(kNotEnoughData, NULL); | |
294 return; | |
295 } | 271 } |
296 | 272 |
297 decode_cb.Run(kOk, queued_audio_.front()); | 273 decode_cb.Run(kOk); |
298 queued_audio_.pop_front(); | |
299 } | 274 } |
300 | 275 |
301 bool FFmpegAudioDecoder::FFmpegDecode( | 276 bool FFmpegAudioDecoder::FFmpegDecode( |
302 const scoped_refptr<DecoderBuffer>& buffer) { | 277 const scoped_refptr<DecoderBuffer>& buffer) { |
303 DCHECK(queued_audio_.empty()); | |
304 | |
305 AVPacket packet; | 278 AVPacket packet; |
306 av_init_packet(&packet); | 279 av_init_packet(&packet); |
307 if (buffer->end_of_stream()) { | 280 if (buffer->end_of_stream()) { |
308 packet.data = NULL; | 281 packet.data = NULL; |
309 packet.size = 0; | 282 packet.size = 0; |
310 } else { | 283 } else { |
311 packet.data = const_cast<uint8*>(buffer->data()); | 284 packet.data = const_cast<uint8*>(buffer->data()); |
312 packet.size = buffer->data_size(); | 285 packet.size = buffer->data_size(); |
313 } | 286 } |
314 | 287 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 << ", Sample Format: " << av_frame_->format << " vs " | 328 << ", Sample Format: " << av_frame_->format << " vs " |
356 << av_sample_format_; | 329 << av_sample_format_; |
357 | 330 |
358 if (config_.codec() == kCodecAAC && | 331 if (config_.codec() == kCodecAAC && |
359 av_frame_->sample_rate == 2 * config_.samples_per_second()) { | 332 av_frame_->sample_rate == 2 * config_.samples_per_second()) { |
360 MEDIA_LOG(log_cb_) << "Implicit HE-AAC signalling is being used." | 333 MEDIA_LOG(log_cb_) << "Implicit HE-AAC signalling is being used." |
361 << " Please use mp4a.40.5 instead of mp4a.40.2 in" | 334 << " Please use mp4a.40.5 instead of mp4a.40.2 in" |
362 << " the mimetype."; | 335 << " the mimetype."; |
363 } | 336 } |
364 // This is an unrecoverable error, so bail out. | 337 // This is an unrecoverable error, so bail out. |
365 queued_audio_.clear(); | |
366 av_frame_unref(av_frame_.get()); | 338 av_frame_unref(av_frame_.get()); |
367 return false; | 339 return false; |
368 } | 340 } |
369 | 341 |
370 // Get the AudioBuffer that the data was decoded into. Adjust the number | 342 // Get the AudioBuffer that the data was decoded into. Adjust the number |
371 // of frames, in case fewer than requested were actually decoded. | 343 // of frames, in case fewer than requested were actually decoded. |
372 output = reinterpret_cast<AudioBuffer*>( | 344 output = reinterpret_cast<AudioBuffer*>( |
373 av_buffer_get_opaque(av_frame_->buf[0])); | 345 av_buffer_get_opaque(av_frame_->buf[0])); |
374 | 346 |
375 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), | 347 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), |
376 output->channel_count()); | 348 output->channel_count()); |
377 const int unread_frames = output->frame_count() - av_frame_->nb_samples; | 349 const int unread_frames = output->frame_count() - av_frame_->nb_samples; |
378 DCHECK_GE(unread_frames, 0); | 350 DCHECK_GE(unread_frames, 0); |
379 if (unread_frames > 0) | 351 if (unread_frames > 0) |
380 output->TrimEnd(unread_frames); | 352 output->TrimEnd(unread_frames); |
381 av_frame_unref(av_frame_.get()); | 353 av_frame_unref(av_frame_.get()); |
382 } | 354 } |
383 | 355 |
384 // WARNING: |av_frame_| no longer has valid data at this point. | 356 // WARNING: |av_frame_| no longer has valid data at this point. |
385 const int decoded_frames = frame_decoded ? output->frame_count() : 0; | 357 const int decoded_frames = frame_decoded ? output->frame_count() : 0; |
386 if (IsEndOfStream(result, decoded_frames, buffer)) { | 358 if (IsEndOfStream(result, decoded_frames, buffer)) { |
387 DCHECK_EQ(packet.size, 0); | 359 DCHECK_EQ(packet.size, 0); |
388 queued_audio_.push_back(AudioBuffer::CreateEOSBuffer()); | 360 output_cb_.Run(AudioBuffer::CreateEOSBuffer()); |
389 } else if (discard_helper_->ProcessBuffers(buffer, output)) { | 361 } else if (discard_helper_->ProcessBuffers(buffer, output)) { |
390 queued_audio_.push_back(output); | 362 output_cb_.Run(output); |
391 } | 363 } |
392 } while (packet.size > 0); | 364 } while (packet.size > 0); |
393 | 365 |
394 return true; | 366 return true; |
395 } | 367 } |
396 | 368 |
397 void FFmpegAudioDecoder::ReleaseFFmpegResources() { | 369 void FFmpegAudioDecoder::ReleaseFFmpegResources() { |
398 codec_context_.reset(); | 370 codec_context_.reset(); |
399 av_frame_.reset(); | 371 av_frame_.reset(); |
400 } | 372 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 | 425 |
454 ResetTimestampState(); | 426 ResetTimestampState(); |
455 return true; | 427 return true; |
456 } | 428 } |
457 | 429 |
458 void FFmpegAudioDecoder::ResetTimestampState() { | 430 void FFmpegAudioDecoder::ResetTimestampState() { |
459 discard_helper_->Reset(config_.codec_delay()); | 431 discard_helper_->Reset(config_.codec_delay()); |
460 } | 432 } |
461 | 433 |
462 } // namespace media | 434 } // namespace media |
OLD | NEW |