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/filter_host.h" | 9 #include "media/base/filter_host.h" |
10 #include "media/base/limits.h" | 10 #include "media/base/limits.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
49 codec_context_(NULL), | 49 codec_context_(NULL), |
50 bits_per_channel_(0), | 50 bits_per_channel_(0), |
51 channel_layout_(CHANNEL_LAYOUT_NONE), | 51 channel_layout_(CHANNEL_LAYOUT_NONE), |
52 sample_rate_(0), | 52 sample_rate_(0), |
53 estimated_next_timestamp_(kNoTimestamp), | 53 estimated_next_timestamp_(kNoTimestamp), |
54 decoded_audio_size_(AVCODEC_MAX_AUDIO_FRAME_SIZE), | 54 decoded_audio_size_(AVCODEC_MAX_AUDIO_FRAME_SIZE), |
55 decoded_audio_(new uint8[decoded_audio_size_]), | 55 decoded_audio_(new uint8[decoded_audio_size_]), |
56 pending_reads_(0) { | 56 pending_reads_(0) { |
57 } | 57 } |
58 | 58 |
59 FFmpegAudioDecoder::~FFmpegAudioDecoder() {} | 59 FFmpegAudioDecoder::~FFmpegAudioDecoder() { |
60 // XXX: should we require Stop() to be called? this might end up getting | |
61 // called on a random thread due to refcounting. | |
62 if (codec_context_) { | |
63 av_free(codec_context_->extradata); | |
64 avcodec_close(codec_context_); | |
65 av_free(codec_context_); | |
66 } | |
67 } | |
60 | 68 |
61 void FFmpegAudioDecoder::Flush(FilterCallback* callback) { | 69 void FFmpegAudioDecoder::Flush(FilterCallback* callback) { |
62 message_loop_->PostTask( | 70 message_loop_->PostTask( |
63 FROM_HERE, | 71 FROM_HERE, |
64 NewRunnableMethod(this, &FFmpegAudioDecoder::DoFlush, callback)); | 72 NewRunnableMethod(this, &FFmpegAudioDecoder::DoFlush, callback)); |
65 } | 73 } |
66 | 74 |
67 void FFmpegAudioDecoder::Initialize( | 75 void FFmpegAudioDecoder::Initialize( |
68 DemuxerStream* stream, | 76 DemuxerStream* stream, |
69 FilterCallback* callback, | 77 FilterCallback* callback, |
(...skipping 25 matching lines...) Expand all Loading... | |
95 return sample_rate_; | 103 return sample_rate_; |
96 } | 104 } |
97 | 105 |
98 void FFmpegAudioDecoder::DoInitialize( | 106 void FFmpegAudioDecoder::DoInitialize( |
99 DemuxerStream* stream, | 107 DemuxerStream* stream, |
100 FilterCallback* callback, | 108 FilterCallback* callback, |
101 StatisticsCallback* stats_callback) { | 109 StatisticsCallback* stats_callback) { |
102 scoped_ptr<FilterCallback> c(callback); | 110 scoped_ptr<FilterCallback> c(callback); |
103 | 111 |
104 demuxer_stream_ = stream; | 112 demuxer_stream_ = stream; |
105 AVStream* av_stream = demuxer_stream_->GetAVStream(); | 113 AudioDecoderConfig* config = stream->audio_decoder_config(); |
Ami GONE FROM CHROMIUM
2011/09/12 20:54:21
Hopefully this can be a const& or at least a const
scherkus (not reviewing)
2011/09/19 21:19:45
Done.
| |
106 CHECK(av_stream); | |
107 | |
108 stats_callback_.reset(stats_callback); | 114 stats_callback_.reset(stats_callback); |
109 | 115 |
110 // Grab the AVStream's codec context and make sure we have sensible values. | 116 // Sanity checking. |
Ami GONE FROM CHROMIUM
2011/09/12 20:54:21
Shouldn't this be happening earlier (ideally durin
scherkus (not reviewing)
2011/09/19 21:19:45
I'm torn.. on one hand you could argue that said l
| |
111 codec_context_ = av_stream->codec; | 117 if (config->codec() == kUnknownAudioCodec || |
112 int bps = av_get_bits_per_sample_fmt(codec_context_->sample_fmt); | 118 config->channel_layout() == CHANNEL_LAYOUT_UNSUPPORTED || |
113 if (codec_context_->channels <= 0 || | 119 config->bits_per_channel() <= 0 || |
114 codec_context_->channels > Limits::kMaxChannels || | 120 config->bits_per_channel() > Limits::kMaxBitsPerSample || |
115 (codec_context_->channel_layout == 0 && codec_context_->channels > 2) || | 121 config->sample_rate() <= 0 || |
116 bps <= 0 || bps > Limits::kMaxBitsPerSample || | 122 config->sample_rate() > Limits::kMaxSampleRate) { |
117 codec_context_->sample_rate <= 0 || | |
118 codec_context_->sample_rate > Limits::kMaxSampleRate) { | |
119 DLOG(ERROR) << "Invalid audio stream -" | 123 DLOG(ERROR) << "Invalid audio stream -" |
120 << " channels: " << codec_context_->channels | 124 << " codec: " << config->codec() |
121 << " channel layout:" << codec_context_->channel_layout | 125 << " channel layout: " << config->channel_layout() |
122 << " bps: " << bps | 126 << " bits per channel: " << config->bits_per_channel() |
123 << " sample rate: " << codec_context_->sample_rate; | 127 << " sample rate: " << config->sample_rate(); |
124 | 128 |
129 // XXX: format error? | |
125 host()->SetError(PIPELINE_ERROR_DECODE); | 130 host()->SetError(PIPELINE_ERROR_DECODE); |
126 callback->Run(); | 131 callback->Run(); |
127 return; | 132 return; |
128 } | 133 } |
129 | 134 |
130 // Serialize calls to avcodec_open(). | 135 // Initialize AVCodecContext structure. |
136 codec_context_ = avcodec_alloc_context(); | |
137 AudioDecoderConfigToAVCodecContext(config, codec_context_); | |
138 | |
131 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); | 139 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); |
132 if (!codec || avcodec_open(codec_context_, codec) < 0) { | 140 if (!codec || avcodec_open(codec_context_, codec) < 0) { |
133 DLOG(ERROR) << "Could not initialize audio decoder: " | 141 DLOG(ERROR) << "Could not initialize audio decoder: " |
134 << codec_context_->codec_id; | 142 << codec_context_->codec_id; |
135 | 143 |
136 host()->SetError(PIPELINE_ERROR_DECODE); | 144 host()->SetError(PIPELINE_ERROR_DECODE); |
137 callback->Run(); | 145 callback->Run(); |
138 return; | 146 return; |
139 } | 147 } |
140 | 148 |
141 // Success! | 149 // Success! |
142 bits_per_channel_= av_get_bits_per_sample_fmt(codec_context_->sample_fmt); | 150 bits_per_channel_ = config->bits_per_channel(); |
143 channel_layout_ = | 151 channel_layout_ = config->channel_layout(); |
144 ChannelLayoutToChromeChannelLayout(codec_context_->channel_layout, | 152 sample_rate_ = config->sample_rate(); |
145 codec_context_->channels); | |
146 sample_rate_ = codec_context_->sample_rate; | |
147 | 153 |
148 callback->Run(); | 154 callback->Run(); |
149 } | 155 } |
150 | 156 |
151 void FFmpegAudioDecoder::DoFlush(FilterCallback* callback) { | 157 void FFmpegAudioDecoder::DoFlush(FilterCallback* callback) { |
152 avcodec_flush_buffers(codec_context_); | 158 avcodec_flush_buffers(codec_context_); |
153 estimated_next_timestamp_ = kNoTimestamp; | 159 estimated_next_timestamp_ = kNoTimestamp; |
154 | 160 |
155 callback->Run(); | 161 callback->Run(); |
156 delete callback; | 162 delete callback; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
268 | 274 |
269 base::TimeDelta FFmpegAudioDecoder::CalculateDuration(int size) { | 275 base::TimeDelta FFmpegAudioDecoder::CalculateDuration(int size) { |
270 int64 denominator = ChannelLayoutToChannelCount(channel_layout_) * | 276 int64 denominator = ChannelLayoutToChannelCount(channel_layout_) * |
271 bits_per_channel_ / 8 * sample_rate_; | 277 bits_per_channel_ / 8 * sample_rate_; |
272 double microseconds = size / | 278 double microseconds = size / |
273 (denominator / static_cast<double>(base::Time::kMicrosecondsPerSecond)); | 279 (denominator / static_cast<double>(base::Time::kMicrosecondsPerSecond)); |
274 return base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)); | 280 return base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)); |
275 } | 281 } |
276 | 282 |
277 } // namespace media | 283 } // namespace media |
OLD | NEW |