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 |