Stop using legacy GrContext member function aliases.
[chromium-blink-merge.git] / media / filters / audio_file_reader.cc
blob3b14355cd414652892730e4c725380be34f25784
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
3 // found in the LICENSE file.
5 #include "media/filters/audio_file_reader.h"
7 #include <cmath>
9 #include "base/logging.h"
10 #include "base/time/time.h"
11 #include "media/base/audio_bus.h"
12 #include "media/ffmpeg/ffmpeg_common.h"
13 #include "media/filters/ffmpeg_glue.h"
15 namespace media {
17 AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol)
18 : codec_context_(NULL),
19 stream_index_(0),
20 protocol_(protocol),
21 channels_(0),
22 sample_rate_(0),
23 end_padding_(0),
24 av_sample_format_(0) {
27 AudioFileReader::~AudioFileReader() {
28 Close();
31 bool AudioFileReader::Open() {
32 if (!OpenDemuxer())
33 return false;
34 return OpenDecoder();
37 bool AudioFileReader::OpenDemuxer() {
38 glue_.reset(new FFmpegGlue(protocol_));
39 AVFormatContext* format_context = glue_->format_context();
41 // Open FFmpeg AVFormatContext.
42 if (!glue_->OpenContext()) {
43 DLOG(WARNING) << "AudioFileReader::Open() : error in avformat_open_input()";
44 return false;
47 // Get the codec context.
48 codec_context_ = NULL;
49 for (size_t i = 0; i < format_context->nb_streams; ++i) {
50 AVCodecContext* c = format_context->streams[i]->codec;
51 if (c->codec_type == AVMEDIA_TYPE_AUDIO) {
52 codec_context_ = c;
53 stream_index_ = i;
54 break;
58 // Get the codec.
59 if (!codec_context_)
60 return false;
62 const int result = avformat_find_stream_info(format_context, NULL);
63 if (result < 0) {
64 DLOG(WARNING)
65 << "AudioFileReader::Open() : error in avformat_find_stream_info()";
66 return false;
69 // Attempt to extract end padding for mp3 files.
70 if (strcmp(format_context->iformat->name, "mp3") == 0 &&
71 (av_opt_get_int(format_context->priv_data, "end_pad", 0, &end_padding_) <
72 0 ||
73 end_padding_ < 0)) {
74 end_padding_ = 0;
76 return true;
79 bool AudioFileReader::OpenDecoder() {
80 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
81 if (codec) {
82 // MP3 decodes to S16P which we don't support, tell it to use S16 instead.
83 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P)
84 codec_context_->request_sample_fmt = AV_SAMPLE_FMT_S16;
86 const int result = avcodec_open2(codec_context_, codec, NULL);
87 if (result < 0) {
88 DLOG(WARNING) << "AudioFileReader::Open() : could not open codec -"
89 << " result: " << result;
90 return false;
93 // Ensure avcodec_open2() respected our format request.
94 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P) {
95 DLOG(ERROR) << "AudioFileReader::Open() : unable to configure a"
96 << " supported sample format - "
97 << codec_context_->sample_fmt;
98 return false;
100 } else {
101 DLOG(WARNING) << "AudioFileReader::Open() : could not find codec.";
102 return false;
105 // Verify the channel layout is supported by Chrome. Acts as a sanity check
106 // against invalid files. See http://crbug.com/171962
107 if (ChannelLayoutToChromeChannelLayout(
108 codec_context_->channel_layout, codec_context_->channels) ==
109 CHANNEL_LAYOUT_UNSUPPORTED) {
110 return false;
113 // Store initial values to guard against midstream configuration changes.
114 channels_ = codec_context_->channels;
115 sample_rate_ = codec_context_->sample_rate;
116 av_sample_format_ = codec_context_->sample_fmt;
117 return true;
120 void AudioFileReader::Close() {
121 // |codec_context_| is a stream inside glue_->format_context(), so it is
122 // closed when |glue_| is disposed.
123 glue_.reset();
124 codec_context_ = NULL;
127 int AudioFileReader::Read(AudioBus* audio_bus) {
128 DCHECK(glue_.get() && codec_context_) <<
129 "AudioFileReader::Read() : reader is not opened!";
131 DCHECK_EQ(audio_bus->channels(), channels());
132 if (audio_bus->channels() != channels())
133 return 0;
135 size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt);
137 // Holds decoded audio.
138 scoped_ptr<AVFrame, ScopedPtrAVFreeFrame> av_frame(av_frame_alloc());
140 // Read until we hit EOF or we've read the requested number of frames.
141 AVPacket packet;
142 int current_frame = 0;
143 bool continue_decoding = true;
145 while (current_frame < audio_bus->frames() && continue_decoding &&
146 ReadPacket(&packet)) {
147 // Make a shallow copy of packet so we can slide packet.data as frames are
148 // decoded from the packet; otherwise av_free_packet() will corrupt memory.
149 AVPacket packet_temp = packet;
150 do {
151 // Reset frame to default values.
152 av_frame_unref(av_frame.get());
154 int frame_decoded = 0;
155 int result = avcodec_decode_audio4(
156 codec_context_, av_frame.get(), &frame_decoded, &packet_temp);
158 if (result < 0) {
159 DLOG(WARNING)
160 << "AudioFileReader::Read() : error in avcodec_decode_audio4() -"
161 << result;
162 break;
165 // Update packet size and data pointer in case we need to call the decoder
166 // with the remaining bytes from this packet.
167 packet_temp.size -= result;
168 packet_temp.data += result;
170 if (!frame_decoded)
171 continue;
173 // Determine the number of sample-frames we just decoded. Check overflow.
174 int frames_read = av_frame->nb_samples;
175 if (frames_read < 0) {
176 continue_decoding = false;
177 break;
180 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS
181 int channels = av_get_channel_layout_nb_channels(
182 av_frame->channel_layout);
183 #else
184 int channels = av_frame->channels;
185 #endif
186 if (av_frame->sample_rate != sample_rate_ ||
187 channels != channels_ ||
188 av_frame->format != av_sample_format_) {
189 DLOG(ERROR) << "Unsupported midstream configuration change!"
190 << " Sample Rate: " << av_frame->sample_rate << " vs "
191 << sample_rate_
192 << ", Channels: " << channels << " vs "
193 << channels_
194 << ", Sample Format: " << av_frame->format << " vs "
195 << av_sample_format_;
197 // This is an unrecoverable error, so bail out.
198 continue_decoding = false;
199 break;
202 // Truncate, if necessary, if the destination isn't big enough.
203 if (current_frame + frames_read > audio_bus->frames()) {
204 DLOG(ERROR) << "Truncating decoded data due to output size.";
205 frames_read = audio_bus->frames() - current_frame;
208 // Deinterleave each channel and convert to 32bit floating-point with
209 // nominal range -1.0 -> +1.0. If the output is already in float planar
210 // format, just copy it into the AudioBus.
211 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT) {
212 float* decoded_audio_data = reinterpret_cast<float*>(av_frame->data[0]);
213 int channels = audio_bus->channels();
214 for (int ch = 0; ch < channels; ++ch) {
215 float* bus_data = audio_bus->channel(ch) + current_frame;
216 for (int i = 0, offset = ch; i < frames_read;
217 ++i, offset += channels) {
218 bus_data[i] = decoded_audio_data[offset];
221 } else if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLTP) {
222 for (int ch = 0; ch < audio_bus->channels(); ++ch) {
223 memcpy(audio_bus->channel(ch) + current_frame,
224 av_frame->extended_data[ch], sizeof(float) * frames_read);
226 } else {
227 audio_bus->FromInterleavedPartial(
228 av_frame->data[0], current_frame, frames_read, bytes_per_sample);
231 current_frame += frames_read;
232 } while (packet_temp.size > 0);
233 av_free_packet(&packet);
236 // If decoding completed successfully try to strip end padding.
237 if (continue_decoding && end_padding_ <= current_frame) {
238 DCHECK_GE(end_padding_, 0);
239 current_frame -= end_padding_;
242 // Zero any remaining frames.
243 audio_bus->ZeroFramesPartial(
244 current_frame, audio_bus->frames() - current_frame);
246 // Returns the actual number of sample-frames decoded.
247 // Ideally this represents the "true" exact length of the file.
248 return current_frame;
251 base::TimeDelta AudioFileReader::GetDuration() const {
252 const AVRational av_time_base = {1, AV_TIME_BASE};
254 // Add one microsecond to avoid rounding-down errors which can occur when
255 // |duration| has been calculated from an exact number of sample-frames.
256 // One microsecond is much less than the time of a single sample-frame
257 // at any real-world sample-rate.
258 return ConvertFromTimeBase(av_time_base,
259 glue_->format_context()->duration + 1);
262 int AudioFileReader::GetNumberOfFrames() const {
263 return static_cast<int>(ceil(GetDuration().InSecondsF() * sample_rate()));
266 bool AudioFileReader::OpenDemuxerForTesting() {
267 return OpenDemuxer();
270 bool AudioFileReader::ReadPacketForTesting(AVPacket* output_packet) {
271 return ReadPacket(output_packet);
274 bool AudioFileReader::ReadPacket(AVPacket* output_packet) {
275 while (av_read_frame(glue_->format_context(), output_packet) >= 0 &&
276 av_dup_packet(output_packet) >= 0) {
277 // Skip packets from other streams.
278 if (output_packet->stream_index != stream_index_) {
279 av_free_packet(output_packet);
280 continue;
282 return true;
284 return false;
287 bool AudioFileReader::SeekForTesting(base::TimeDelta seek_time) {
288 return av_seek_frame(glue_->format_context(),
289 stream_index_,
290 ConvertToTimeBase(codec_context_->time_base, seek_time),
291 AVSEEK_FLAG_BACKWARD) >= 0;
294 const AVStream* AudioFileReader::GetAVStreamForTesting() const {
295 return glue_->format_context()->streams[stream_index_];
298 } // namespace media