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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 buffer.swap(reinterpret_cast<AudioBuffer**>(&opaque)); | 116 buffer.swap(reinterpret_cast<AudioBuffer**>(&opaque)); |
117 frame->buf[0] = av_buffer_create( | 117 frame->buf[0] = av_buffer_create( |
118 frame->data[0], buffer_size_in_bytes, ReleaseAudioBufferImpl, opaque, 0); | 118 frame->data[0], buffer_size_in_bytes, ReleaseAudioBufferImpl, opaque, 0); |
119 return 0; | 119 return 0; |
120 } | 120 } |
121 | 121 |
122 FFmpegAudioDecoder::FFmpegAudioDecoder( | 122 FFmpegAudioDecoder::FFmpegAudioDecoder( |
123 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) | 123 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) |
124 : task_runner_(task_runner), | 124 : task_runner_(task_runner), |
125 state_(kUninitialized), | 125 state_(kUninitialized), |
126 bytes_per_channel_(0), | |
127 channel_layout_(CHANNEL_LAYOUT_NONE), | |
128 channels_(0), | |
129 samples_per_second_(0), | |
130 av_sample_format_(0), | 126 av_sample_format_(0), |
131 last_input_timestamp_(kNoTimestamp()), | 127 last_input_timestamp_(kNoTimestamp()), |
132 output_frames_to_drop_(0) {} | 128 output_frames_to_drop_(0) {} |
133 | 129 |
134 FFmpegAudioDecoder::~FFmpegAudioDecoder() { | 130 FFmpegAudioDecoder::~FFmpegAudioDecoder() { |
135 DCHECK_EQ(state_, kUninitialized); | 131 DCHECK_EQ(state_, kUninitialized); |
136 DCHECK(!codec_context_); | 132 DCHECK(!codec_context_); |
137 DCHECK(!av_frame_); | 133 DCHECK(!av_frame_); |
138 } | 134 } |
139 | 135 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 | 181 |
186 scoped_refptr<AudioBuffer> FFmpegAudioDecoder::GetDecodeOutput() { | 182 scoped_refptr<AudioBuffer> FFmpegAudioDecoder::GetDecodeOutput() { |
187 DCHECK(task_runner_->BelongsToCurrentThread()); | 183 DCHECK(task_runner_->BelongsToCurrentThread()); |
188 if (queued_audio_.empty()) | 184 if (queued_audio_.empty()) |
189 return NULL; | 185 return NULL; |
190 scoped_refptr<AudioBuffer> out = queued_audio_.front(); | 186 scoped_refptr<AudioBuffer> out = queued_audio_.front(); |
191 queued_audio_.pop_front(); | 187 queued_audio_.pop_front(); |
192 return out; | 188 return out; |
193 } | 189 } |
194 | 190 |
195 int FFmpegAudioDecoder::bits_per_channel() { | |
196 DCHECK(task_runner_->BelongsToCurrentThread()); | |
197 return bytes_per_channel_ * 8; | |
198 } | |
199 | |
200 ChannelLayout FFmpegAudioDecoder::channel_layout() { | |
201 DCHECK(task_runner_->BelongsToCurrentThread()); | |
202 return channel_layout_; | |
203 } | |
204 | |
205 int FFmpegAudioDecoder::samples_per_second() { | |
206 DCHECK(task_runner_->BelongsToCurrentThread()); | |
207 return samples_per_second_; | |
208 } | |
209 | |
210 void FFmpegAudioDecoder::Reset(const base::Closure& closure) { | 191 void FFmpegAudioDecoder::Reset(const base::Closure& closure) { |
211 DCHECK(task_runner_->BelongsToCurrentThread()); | 192 DCHECK(task_runner_->BelongsToCurrentThread()); |
212 | 193 |
213 avcodec_flush_buffers(codec_context_.get()); | 194 avcodec_flush_buffers(codec_context_.get()); |
214 state_ = kNormal; | 195 state_ = kNormal; |
215 ResetTimestampState(); | 196 ResetTimestampState(); |
216 task_runner_->PostTask(FROM_HERE, closure); | 197 task_runner_->PostTask(FROM_HERE, closure); |
217 } | 198 } |
218 | 199 |
219 void FFmpegAudioDecoder::Stop(const base::Closure& closure) { | 200 void FFmpegAudioDecoder::Stop(const base::Closure& closure) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 decode_cb.Run(kDecodeError, NULL); | 255 decode_cb.Run(kDecodeError, NULL); |
275 return; | 256 return; |
276 } | 257 } |
277 | 258 |
278 if (!buffer->end_of_stream()) { | 259 if (!buffer->end_of_stream()) { |
279 if (last_input_timestamp_ == kNoTimestamp() && | 260 if (last_input_timestamp_ == kNoTimestamp() && |
280 codec_context_->codec_id == AV_CODEC_ID_VORBIS && | 261 codec_context_->codec_id == AV_CODEC_ID_VORBIS && |
281 buffer->timestamp() < base::TimeDelta()) { | 262 buffer->timestamp() < base::TimeDelta()) { |
282 // Dropping frames for negative timestamps as outlined in section A.2 | 263 // Dropping frames for negative timestamps as outlined in section A.2 |
283 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html | 264 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html |
284 output_frames_to_drop_ = floor( | 265 output_frames_to_drop_ = floor(0.5 + -buffer->timestamp().InSecondsF() * |
285 0.5 + -buffer->timestamp().InSecondsF() * samples_per_second_); | 266 config_.samples_per_second()); |
286 } else { | 267 } else { |
287 if (last_input_timestamp_ != kNoTimestamp() && | 268 if (last_input_timestamp_ != kNoTimestamp() && |
288 buffer->timestamp() < last_input_timestamp_) { | 269 buffer->timestamp() < last_input_timestamp_) { |
289 const base::TimeDelta diff = | 270 const base::TimeDelta diff = |
290 buffer->timestamp() - last_input_timestamp_; | 271 buffer->timestamp() - last_input_timestamp_; |
291 DLOG(WARNING) | 272 DLOG(WARNING) |
292 << "Input timestamps are not monotonically increasing! " | 273 << "Input timestamps are not monotonically increasing! " |
293 << " ts " << buffer->timestamp().InMicroseconds() << " us" | 274 << " ts " << buffer->timestamp().InMicroseconds() << " us" |
294 << " diff " << diff.InMicroseconds() << " us"; | 275 << " diff " << diff.InMicroseconds() << " us"; |
295 } | 276 } |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 } else { | 361 } else { |
381 output_timestamp_helper_->SetBaseTimestamp(buffer->timestamp()); | 362 output_timestamp_helper_->SetBaseTimestamp(buffer->timestamp()); |
382 } | 363 } |
383 } | 364 } |
384 | 365 |
385 scoped_refptr<AudioBuffer> output; | 366 scoped_refptr<AudioBuffer> output; |
386 int decoded_frames = 0; | 367 int decoded_frames = 0; |
387 int original_frames = 0; | 368 int original_frames = 0; |
388 int channels = DetermineChannels(av_frame_.get()); | 369 int channels = DetermineChannels(av_frame_.get()); |
389 if (frame_decoded) { | 370 if (frame_decoded) { |
390 | |
391 // TODO(rileya) Remove this check once we properly support midstream audio | |
392 // config changes. | |
393 if (av_frame_->sample_rate != config_.samples_per_second() || | 371 if (av_frame_->sample_rate != config_.samples_per_second() || |
394 channels != channels_ || | 372 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || |
395 av_frame_->format != av_sample_format_) { | 373 av_frame_->format != av_sample_format_) { |
396 DLOG(ERROR) << "Unsupported midstream configuration change!" | 374 DLOG(ERROR) << "Unsupported midstream configuration change!" |
397 << " Sample Rate: " << av_frame_->sample_rate << " vs " | 375 << " Sample Rate: " << av_frame_->sample_rate << " vs " |
398 << samples_per_second_ | 376 << config_.samples_per_second() |
399 << ", Channels: " << channels << " vs " | 377 << ", Channels: " << channels << " vs " |
400 << channels_ | 378 << ChannelLayoutToChannelCount(config_.channel_layout()) |
401 << ", Sample Format: " << av_frame_->format << " vs " | 379 << ", Sample Format: " << av_frame_->format << " vs " |
402 << av_sample_format_; | 380 << av_sample_format_; |
403 | 381 |
404 // This is an unrecoverable error, so bail out. | 382 // This is an unrecoverable error, so bail out. |
405 queued_audio_.clear(); | 383 queued_audio_.clear(); |
406 av_frame_unref(av_frame_.get()); | 384 av_frame_unref(av_frame_.get()); |
407 return false; | 385 return false; |
408 } | 386 } |
409 | 387 |
410 // Get the AudioBuffer that the data was decoded into. Adjust the number | 388 // Get the AudioBuffer that the data was decoded into. Adjust the number |
411 // of frames, in case fewer than requested were actually decoded. | 389 // of frames, in case fewer than requested were actually decoded. |
412 output = reinterpret_cast<AudioBuffer*>( | 390 output = reinterpret_cast<AudioBuffer*>( |
413 av_buffer_get_opaque(av_frame_->buf[0])); | 391 av_buffer_get_opaque(av_frame_->buf[0])); |
414 | 392 |
415 DCHECK_EQ(channels_, output->channel_count()); | 393 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), |
| 394 output->channel_count()); |
416 original_frames = av_frame_->nb_samples; | 395 original_frames = av_frame_->nb_samples; |
417 int unread_frames = output->frame_count() - original_frames; | 396 int unread_frames = output->frame_count() - original_frames; |
418 DCHECK_GE(unread_frames, 0); | 397 DCHECK_GE(unread_frames, 0); |
419 if (unread_frames > 0) | 398 if (unread_frames > 0) |
420 output->TrimEnd(unread_frames); | 399 output->TrimEnd(unread_frames); |
421 | 400 |
422 // If there are frames to drop, get rid of as many as we can. | 401 // If there are frames to drop, get rid of as many as we can. |
423 if (output_frames_to_drop_ > 0) { | 402 if (output_frames_to_drop_ > 0) { |
424 int drop = std::min(output->frame_count(), output_frames_to_drop_); | 403 int drop = std::min(output->frame_count(), output_frames_to_drop_); |
425 output->TrimStart(drop); | 404 output->TrimStart(drop); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 << " bits per channel: " << config_.bits_per_channel() | 447 << " bits per channel: " << config_.bits_per_channel() |
469 << " samples per second: " << config_.samples_per_second(); | 448 << " samples per second: " << config_.samples_per_second(); |
470 return false; | 449 return false; |
471 } | 450 } |
472 | 451 |
473 if (config_.is_encrypted()) { | 452 if (config_.is_encrypted()) { |
474 DLOG(ERROR) << "Encrypted audio stream not supported"; | 453 DLOG(ERROR) << "Encrypted audio stream not supported"; |
475 return false; | 454 return false; |
476 } | 455 } |
477 | 456 |
478 // TODO(rileya) Remove this check once we properly support midstream audio | |
479 // config changes. | |
480 if (codec_context_.get() && | |
481 (bytes_per_channel_ != config_.bytes_per_channel() || | |
482 channel_layout_ != config_.channel_layout() || | |
483 samples_per_second_ != config_.samples_per_second())) { | |
484 DVLOG(1) << "Unsupported config change :"; | |
485 DVLOG(1) << "\tbytes_per_channel : " << bytes_per_channel_ | |
486 << " -> " << config_.bytes_per_channel(); | |
487 DVLOG(1) << "\tchannel_layout : " << channel_layout_ | |
488 << " -> " << config_.channel_layout(); | |
489 DVLOG(1) << "\tsample_rate : " << samples_per_second_ | |
490 << " -> " << config_.samples_per_second(); | |
491 return false; | |
492 } | |
493 | |
494 // Release existing decoder resources if necessary. | 457 // Release existing decoder resources if necessary. |
495 ReleaseFFmpegResources(); | 458 ReleaseFFmpegResources(); |
496 | 459 |
497 // Initialize AVCodecContext structure. | 460 // Initialize AVCodecContext structure. |
498 codec_context_.reset(avcodec_alloc_context3(NULL)); | 461 codec_context_.reset(avcodec_alloc_context3(NULL)); |
499 AudioDecoderConfigToAVCodecContext(config_, codec_context_.get()); | 462 AudioDecoderConfigToAVCodecContext(config_, codec_context_.get()); |
500 | 463 |
501 codec_context_->opaque = this; | 464 codec_context_->opaque = this; |
502 codec_context_->get_buffer2 = GetAudioBuffer; | 465 codec_context_->get_buffer2 = GetAudioBuffer; |
503 codec_context_->refcounted_frames = 1; | 466 codec_context_->refcounted_frames = 1; |
504 | 467 |
505 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); | 468 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); |
506 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { | 469 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { |
507 DLOG(ERROR) << "Could not initialize audio decoder: " | 470 DLOG(ERROR) << "Could not initialize audio decoder: " |
508 << codec_context_->codec_id; | 471 << codec_context_->codec_id; |
509 ReleaseFFmpegResources(); | 472 ReleaseFFmpegResources(); |
510 state_ = kUninitialized; | 473 state_ = kUninitialized; |
511 return false; | 474 return false; |
512 } | 475 } |
513 | 476 |
514 // Success! | 477 // Success! |
515 av_frame_.reset(av_frame_alloc()); | 478 av_frame_.reset(av_frame_alloc()); |
516 channel_layout_ = config_.channel_layout(); | |
517 samples_per_second_ = config_.samples_per_second(); | |
518 output_timestamp_helper_.reset( | 479 output_timestamp_helper_.reset( |
519 new AudioTimestampHelper(config_.samples_per_second())); | 480 new AudioTimestampHelper(config_.samples_per_second())); |
520 | 481 |
521 // Store initial values to guard against midstream configuration changes. | 482 av_sample_format_ = codec_context_->sample_fmt; |
522 channels_ = codec_context_->channels; | 483 |
523 if (channels_ != ChannelLayoutToChannelCount(channel_layout_)) { | 484 if (codec_context_->channels != |
| 485 ChannelLayoutToChannelCount(config_.channel_layout())) { |
524 DLOG(ERROR) << "Audio configuration specified " | 486 DLOG(ERROR) << "Audio configuration specified " |
525 << ChannelLayoutToChannelCount(channel_layout_) | 487 << ChannelLayoutToChannelCount(config_.channel_layout()) |
526 << " channels, but FFmpeg thinks the file contains " | 488 << " channels, but FFmpeg thinks the file contains " |
527 << channels_ << " channels"; | 489 << codec_context_->channels << " channels"; |
528 ReleaseFFmpegResources(); | 490 ReleaseFFmpegResources(); |
529 state_ = kUninitialized; | 491 state_ = kUninitialized; |
530 return false; | 492 return false; |
531 } | 493 } |
532 av_sample_format_ = codec_context_->sample_fmt; | |
533 sample_format_ = AVSampleFormatToSampleFormat( | |
534 static_cast<AVSampleFormat>(av_sample_format_)); | |
535 bytes_per_channel_ = SampleFormatToBytesPerChannel(sample_format_); | |
536 | |
537 return true; | 494 return true; |
538 } | 495 } |
539 | 496 |
540 void FFmpegAudioDecoder::ResetTimestampState() { | 497 void FFmpegAudioDecoder::ResetTimestampState() { |
541 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); | 498 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); |
542 last_input_timestamp_ = kNoTimestamp(); | 499 last_input_timestamp_ = kNoTimestamp(); |
543 output_frames_to_drop_ = 0; | 500 output_frames_to_drop_ = 0; |
544 } | 501 } |
545 | 502 |
546 } // namespace media | 503 } // namespace media |
OLD | NEW |