Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "media/base/data_buffer.h" | 8 #include "media/base/data_buffer.h" |
| 9 #include "media/base/demuxer.h" | 9 #include "media/base/demuxer.h" |
| 10 #include "media/base/filter_host.h" | 10 #include "media/base/filter_host.h" |
| 11 #include "media/base/limits.h" | |
| 12 #include "media/ffmpeg/ffmpeg_common.h" | 11 #include "media/ffmpeg/ffmpeg_common.h" |
| 13 | 12 |
| 14 namespace media { | 13 namespace media { |
| 15 | 14 |
| 16 // Returns true if the decode result was an error. | 15 // Returns true if the decode result was an error. |
| 17 static bool IsErrorResult(int result, int decoded_size) { | 16 static bool IsErrorResult(int result, int decoded_size) { |
| 18 return result < 0 || | 17 return result < 0 || |
| 19 decoded_size < 0 || | 18 decoded_size < 0 || |
| 20 decoded_size > AVCODEC_MAX_AUDIO_FRAME_SIZE; | 19 decoded_size > AVCODEC_MAX_AUDIO_FRAME_SIZE; |
| 21 } | 20 } |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 51 bits_per_channel_(0), | 50 bits_per_channel_(0), |
| 52 channel_layout_(CHANNEL_LAYOUT_NONE), | 51 channel_layout_(CHANNEL_LAYOUT_NONE), |
| 53 sample_rate_(0), | 52 sample_rate_(0), |
| 54 decoded_audio_size_(AVCODEC_MAX_AUDIO_FRAME_SIZE), | 53 decoded_audio_size_(AVCODEC_MAX_AUDIO_FRAME_SIZE), |
| 55 decoded_audio_(static_cast<uint8*>(av_malloc(decoded_audio_size_))), | 54 decoded_audio_(static_cast<uint8*>(av_malloc(decoded_audio_size_))), |
| 56 pending_reads_(0) { | 55 pending_reads_(0) { |
| 57 } | 56 } |
| 58 | 57 |
| 59 FFmpegAudioDecoder::~FFmpegAudioDecoder() { | 58 FFmpegAudioDecoder::~FFmpegAudioDecoder() { |
| 60 av_free(decoded_audio_); | 59 av_free(decoded_audio_); |
| 60 | |
| 61 // XXX: should we require Stop() to be called? this might end up getting | |
| 62 // called on a random thread due to refcounting. | |
| 63 if (codec_context_) { | |
| 64 av_free(codec_context_->extradata); | |
| 65 avcodec_close(codec_context_); | |
| 66 av_free(codec_context_); | |
| 67 } | |
| 61 } | 68 } |
| 62 | 69 |
| 63 void FFmpegAudioDecoder::Flush(FilterCallback* callback) { | 70 void FFmpegAudioDecoder::Flush(FilterCallback* callback) { |
| 64 message_loop_->PostTask( | 71 message_loop_->PostTask( |
| 65 FROM_HERE, | 72 FROM_HERE, |
| 66 NewRunnableMethod(this, &FFmpegAudioDecoder::DoFlush, callback)); | 73 NewRunnableMethod(this, &FFmpegAudioDecoder::DoFlush, callback)); |
| 67 } | 74 } |
| 68 | 75 |
| 69 void FFmpegAudioDecoder::Initialize( | 76 void FFmpegAudioDecoder::Initialize( |
| 70 DemuxerStream* stream, | 77 DemuxerStream* stream, |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 98 return sample_rate_; | 105 return sample_rate_; |
| 99 } | 106 } |
| 100 | 107 |
| 101 void FFmpegAudioDecoder::DoInitialize( | 108 void FFmpegAudioDecoder::DoInitialize( |
| 102 const scoped_refptr<DemuxerStream>& stream, | 109 const scoped_refptr<DemuxerStream>& stream, |
| 103 FilterCallback* callback, | 110 FilterCallback* callback, |
| 104 StatisticsCallback* stats_callback) { | 111 StatisticsCallback* stats_callback) { |
| 105 scoped_ptr<FilterCallback> c(callback); | 112 scoped_ptr<FilterCallback> c(callback); |
| 106 | 113 |
| 107 demuxer_stream_ = stream; | 114 demuxer_stream_ = stream; |
| 108 AVStream* av_stream = demuxer_stream_->GetAVStream(); | 115 const AudioDecoderConfig& config = stream->audio_decoder_config(); |
| 109 CHECK(av_stream); | |
| 110 | |
| 111 stats_callback_.reset(stats_callback); | 116 stats_callback_.reset(stats_callback); |
| 112 | 117 |
| 113 // Grab the AVStream's codec context and make sure we have sensible values. | 118 if (!config.IsValidConfig()) { |
|
Ami GONE FROM CHROMIUM
2011/09/20 20:34:50
This is better, but my point was that it would be
scherkus (not reviewing)
2011/09/21 18:19:16
You're right in that the correct place for this ch
| |
| 114 codec_context_ = av_stream->codec; | |
| 115 int bps = av_get_bits_per_sample_fmt(codec_context_->sample_fmt); | |
| 116 if (codec_context_->channels <= 0 || | |
| 117 codec_context_->channels > Limits::kMaxChannels || | |
| 118 (codec_context_->channel_layout == 0 && codec_context_->channels > 2) || | |
| 119 bps <= 0 || bps > Limits::kMaxBitsPerSample || | |
| 120 codec_context_->sample_rate <= 0 || | |
| 121 codec_context_->sample_rate > Limits::kMaxSampleRate) { | |
| 122 DLOG(ERROR) << "Invalid audio stream -" | 119 DLOG(ERROR) << "Invalid audio stream -" |
| 123 << " channels: " << codec_context_->channels | 120 << " codec: " << config.codec() |
| 124 << " channel layout:" << codec_context_->channel_layout | 121 << " channel layout: " << config.channel_layout() |
| 125 << " bps: " << bps | 122 << " bits per channel: " << config.bits_per_channel() |
| 126 << " sample rate: " << codec_context_->sample_rate; | 123 << " sample rate: " << config.sample_rate(); |
| 127 | 124 |
| 128 host()->SetError(PIPELINE_ERROR_DECODE); | 125 host()->SetError(DECODER_ERROR_NOT_SUPPORTED); |
| 129 callback->Run(); | 126 callback->Run(); |
| 130 return; | 127 return; |
| 131 } | 128 } |
| 132 | 129 |
| 133 // Serialize calls to avcodec_open(). | 130 // Initialize AVCodecContext structure. |
| 131 codec_context_ = avcodec_alloc_context(); | |
| 132 AudioDecoderConfigToAVCodecContext(config, codec_context_); | |
| 133 | |
| 134 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); | 134 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); |
| 135 if (!codec || avcodec_open(codec_context_, codec) < 0) { | 135 if (!codec || avcodec_open(codec_context_, codec) < 0) { |
| 136 DLOG(ERROR) << "Could not initialize audio decoder: " | 136 DLOG(ERROR) << "Could not initialize audio decoder: " |
| 137 << codec_context_->codec_id; | 137 << codec_context_->codec_id; |
| 138 | 138 |
| 139 host()->SetError(PIPELINE_ERROR_DECODE); | 139 host()->SetError(DECODER_ERROR_NOT_SUPPORTED); |
| 140 callback->Run(); | 140 callback->Run(); |
| 141 return; | 141 return; |
| 142 } | 142 } |
| 143 | 143 |
| 144 // Success! | 144 // Success! |
| 145 bits_per_channel_ = av_get_bits_per_sample_fmt(codec_context_->sample_fmt); | 145 bits_per_channel_ = config.bits_per_channel(); |
| 146 channel_layout_ = | 146 channel_layout_ = config.channel_layout(); |
| 147 ChannelLayoutToChromeChannelLayout(codec_context_->channel_layout, | 147 sample_rate_ = config.sample_rate(); |
| 148 codec_context_->channels); | |
| 149 sample_rate_ = codec_context_->sample_rate; | |
| 150 | 148 |
| 151 callback->Run(); | 149 callback->Run(); |
| 152 } | 150 } |
| 153 | 151 |
| 154 void FFmpegAudioDecoder::DoFlush(FilterCallback* callback) { | 152 void FFmpegAudioDecoder::DoFlush(FilterCallback* callback) { |
| 155 avcodec_flush_buffers(codec_context_); | 153 avcodec_flush_buffers(codec_context_); |
| 156 estimated_next_timestamp_ = kNoTimestamp; | 154 estimated_next_timestamp_ = kNoTimestamp; |
| 157 | 155 |
| 158 callback->Run(); | 156 callback->Run(); |
| 159 delete callback; | 157 delete callback; |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 286 | 284 |
| 287 base::TimeDelta FFmpegAudioDecoder::CalculateDuration(int size) { | 285 base::TimeDelta FFmpegAudioDecoder::CalculateDuration(int size) { |
| 288 int64 denominator = ChannelLayoutToChannelCount(channel_layout_) * | 286 int64 denominator = ChannelLayoutToChannelCount(channel_layout_) * |
| 289 bits_per_channel_ / 8 * sample_rate_; | 287 bits_per_channel_ / 8 * sample_rate_; |
| 290 double microseconds = size / | 288 double microseconds = size / |
| 291 (denominator / static_cast<double>(base::Time::kMicrosecondsPerSecond)); | 289 (denominator / static_cast<double>(base::Time::kMicrosecondsPerSecond)); |
| 292 return base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)); | 290 return base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)); |
| 293 } | 291 } |
| 294 | 292 |
| 295 } // namespace media | 293 } // namespace media |
| OLD | NEW |