Chromium Code Reviews| 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/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "base/message_loop_proxy.h" | 10 #include "base/message_loop_proxy.h" |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 36 // 3. An end of stream buffer is received. | 36 // 3. An end of stream buffer is received. |
| 37 return result == 0 && decoded_size == 0 && input->IsEndOfStream(); | 37 return result == 0 && decoded_size == 0 && input->IsEndOfStream(); |
| 38 } | 38 } |
| 39 | 39 |
| 40 FFmpegAudioDecoder::FFmpegAudioDecoder( | 40 FFmpegAudioDecoder::FFmpegAudioDecoder( |
| 41 const scoped_refptr<base::MessageLoopProxy>& message_loop) | 41 const scoped_refptr<base::MessageLoopProxy>& message_loop) |
| 42 : message_loop_(message_loop), | 42 : message_loop_(message_loop), |
| 43 codec_context_(NULL), | 43 codec_context_(NULL), |
| 44 bits_per_channel_(0), | 44 bits_per_channel_(0), |
| 45 channel_layout_(CHANNEL_LAYOUT_NONE), | 45 channel_layout_(CHANNEL_LAYOUT_NONE), |
| 46 channels_(0), | |
| 46 samples_per_second_(0), | 47 samples_per_second_(0), |
| 48 av_sample_format_(0), | |
| 47 bytes_per_frame_(0), | 49 bytes_per_frame_(0), |
| 48 last_input_timestamp_(kNoTimestamp()), | 50 last_input_timestamp_(kNoTimestamp()), |
| 49 output_bytes_to_drop_(0), | 51 output_bytes_to_drop_(0), |
| 50 av_frame_(NULL) { | 52 av_frame_(NULL) { |
| 51 } | 53 } |
| 52 | 54 |
| 53 void FFmpegAudioDecoder::Initialize( | 55 void FFmpegAudioDecoder::Initialize( |
| 54 const scoped_refptr<DemuxerStream>& stream, | 56 const scoped_refptr<DemuxerStream>& stream, |
| 55 const PipelineStatusCB& status_cb, | 57 const PipelineStatusCB& status_cb, |
| 56 const StatisticsCB& statistics_cb) { | 58 const StatisticsCB& statistics_cb) { |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 } | 298 } |
| 297 | 299 |
| 298 // Success! | 300 // Success! |
| 299 av_frame_ = avcodec_alloc_frame(); | 301 av_frame_ = avcodec_alloc_frame(); |
| 300 bits_per_channel_ = config.bits_per_channel(); | 302 bits_per_channel_ = config.bits_per_channel(); |
| 301 channel_layout_ = config.channel_layout(); | 303 channel_layout_ = config.channel_layout(); |
| 302 samples_per_second_ = config.samples_per_second(); | 304 samples_per_second_ = config.samples_per_second(); |
| 303 output_timestamp_helper_.reset(new AudioTimestampHelper( | 305 output_timestamp_helper_.reset(new AudioTimestampHelper( |
| 304 config.bytes_per_frame(), config.samples_per_second())); | 306 config.bytes_per_frame(), config.samples_per_second())); |
| 305 bytes_per_frame_ = config.bytes_per_frame(); | 307 bytes_per_frame_ = config.bytes_per_frame(); |
| 308 | |
| 309 // Store initial values to guard against mid-frame configuration changes. | |
|
scherkus (not reviewing)
2013/02/12 02:16:56
consistent terminology nit: s/mid-frame/mid-stream
DaleCurtis
2013/02/12 02:41:24
Done.
| |
| 310 channels_ = codec_context_->channels; | |
| 311 av_sample_format_ = codec_context_->sample_fmt; | |
| 312 | |
| 306 return true; | 313 return true; |
| 307 } | 314 } |
| 308 | 315 |
| 309 void FFmpegAudioDecoder::ReleaseFFmpegResources() { | 316 void FFmpegAudioDecoder::ReleaseFFmpegResources() { |
| 310 if (codec_context_) { | 317 if (codec_context_) { |
| 311 av_free(codec_context_->extradata); | 318 av_free(codec_context_->extradata); |
| 312 avcodec_close(codec_context_); | 319 avcodec_close(codec_context_); |
| 313 av_free(codec_context_); | 320 av_free(codec_context_); |
| 314 } | 321 } |
| 315 | 322 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 380 // If we have to drop samples it always means the timeline starts at 0. | 387 // If we have to drop samples it always means the timeline starts at 0. |
| 381 DCHECK_EQ(codec_context_->codec_id, CODEC_ID_VORBIS); | 388 DCHECK_EQ(codec_context_->codec_id, CODEC_ID_VORBIS); |
| 382 output_timestamp_helper_->SetBaseTimestamp(base::TimeDelta()); | 389 output_timestamp_helper_->SetBaseTimestamp(base::TimeDelta()); |
| 383 } else { | 390 } else { |
| 384 output_timestamp_helper_->SetBaseTimestamp(input->GetTimestamp()); | 391 output_timestamp_helper_->SetBaseTimestamp(input->GetTimestamp()); |
| 385 } | 392 } |
| 386 } | 393 } |
| 387 | 394 |
| 388 int decoded_audio_size = 0; | 395 int decoded_audio_size = 0; |
| 389 if (frame_decoded) { | 396 if (frame_decoded) { |
| 390 int output_sample_rate = av_frame_->sample_rate; | 397 if (av_frame_->sample_rate != samples_per_second_ || |
| 391 if (output_sample_rate != samples_per_second_) { | 398 av_frame_->channels != channels_ || |
| 392 DLOG(ERROR) << "Output sample rate (" << output_sample_rate | 399 av_frame_->format != av_sample_format_) { |
| 393 << ") doesn't match expected rate " << samples_per_second_; | 400 DLOG(ERROR) << "Unsupported mid-frame configuration change!" |
|
scherkus (not reviewing)
2013/02/12 02:16:56
consistent terminology nit: s/mid-frame/mid-stream
DaleCurtis
2013/02/12 02:41:24
Done.
| |
| 401 << " Sample Rate: " << av_frame_->sample_rate << " vs " | |
| 402 << samples_per_second_ | |
| 403 << ", Channels: " << av_frame_->channels << " vs " | |
| 404 << channels_ | |
| 405 << ", Sample Format: " << av_frame_->format << " vs " | |
| 406 << av_sample_format_; | |
| 394 | 407 |
| 395 // This is an unrecoverable error, so bail out. | 408 // This is an unrecoverable error, so bail out. |
| 396 QueuedAudioBuffer queue_entry = { kDecodeError, NULL }; | 409 QueuedAudioBuffer queue_entry = { kDecodeError, NULL }; |
| 397 queued_audio_.push_back(queue_entry); | 410 queued_audio_.push_back(queue_entry); |
| 398 break; | 411 break; |
| 399 } | 412 } |
| 400 | 413 |
| 401 decoded_audio_size = av_samples_get_buffer_size( | 414 decoded_audio_size = av_samples_get_buffer_size( |
| 402 NULL, codec_context_->channels, av_frame_->nb_samples, | 415 NULL, codec_context_->channels, av_frame_->nb_samples, |
| 403 codec_context_->sample_fmt, 1); | 416 codec_context_->sample_fmt, 1); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 474 // Decoding finished successfully, update statistics. | 487 // Decoding finished successfully, update statistics. |
| 475 if (result > 0) { | 488 if (result > 0) { |
| 476 PipelineStatistics statistics; | 489 PipelineStatistics statistics; |
| 477 statistics.audio_bytes_decoded = result; | 490 statistics.audio_bytes_decoded = result; |
| 478 statistics_cb_.Run(statistics); | 491 statistics_cb_.Run(statistics); |
| 479 } | 492 } |
| 480 } while (packet.size > 0); | 493 } while (packet.size > 0); |
| 481 } | 494 } |
| 482 | 495 |
| 483 } // namespace media | 496 } // namespace media |
| OLD | NEW |