Fix some potential after free errors on TestCompletionCallback
[chromium-blink-merge.git] / media / filters / audio_file_reader.cc
blob60771cd51a3ec753ceff91c4a46f224ab7388583
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 "base/logging.h"
8 #include "base/time.h"
9 #include "media/base/audio_bus.h"
10 #include "media/ffmpeg/ffmpeg_common.h"
11 #include "media/filters/ffmpeg_glue.h"
13 namespace media {
15 AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol)
16 : codec_context_(NULL),
17 stream_index_(0),
18 protocol_(protocol),
19 channels_(0),
20 sample_rate_(0),
21 av_sample_format_(0) {
24 AudioFileReader::~AudioFileReader() {
25 Close();
28 base::TimeDelta AudioFileReader::duration() const {
29 const AVRational av_time_base = {1, AV_TIME_BASE};
31 // Add one microsecond to avoid rounding-down errors which can occur when
32 // |duration| has been calculated from an exact number of sample-frames.
33 // One microsecond is much less than the time of a single sample-frame
34 // at any real-world sample-rate.
35 return ConvertFromTimeBase(
36 av_time_base, glue_->format_context()->duration + 1);
39 int64 AudioFileReader::number_of_frames() const {
40 return static_cast<int64>(duration().InSecondsF() * sample_rate());
43 bool AudioFileReader::Open() {
44 glue_.reset(new FFmpegGlue(protocol_));
45 AVFormatContext* format_context = glue_->format_context();
47 // Open FFmpeg AVFormatContext.
48 if (!glue_->OpenContext()) {
49 DLOG(WARNING) << "AudioFileReader::Open() : error in avformat_open_input()";
50 return false;
53 // Get the codec context.
54 codec_context_ = NULL;
55 for (size_t i = 0; i < format_context->nb_streams; ++i) {
56 AVCodecContext* c = format_context->streams[i]->codec;
57 if (c->codec_type == AVMEDIA_TYPE_AUDIO) {
58 codec_context_ = c;
59 stream_index_ = i;
60 break;
64 // Get the codec.
65 if (!codec_context_)
66 return false;
68 int result = avformat_find_stream_info(format_context, NULL);
69 if (result < 0) {
70 DLOG(WARNING)
71 << "AudioFileReader::Open() : error in avformat_find_stream_info()";
72 return false;
75 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
76 if (codec) {
77 // MP3 decodes to S16P which we don't support, tell it to use S16 instead.
78 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P)
79 codec_context_->request_sample_fmt = AV_SAMPLE_FMT_S16;
81 if ((result = avcodec_open2(codec_context_, codec, NULL)) < 0) {
82 DLOG(WARNING) << "AudioFileReader::Open() : could not open codec -"
83 << " result: " << result;
84 return false;
87 // Ensure avcodec_open2() respected our format request.
88 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P) {
89 DLOG(ERROR) << "AudioFileReader::Open() : unable to configure a"
90 << " supported sample format - "
91 << codec_context_->sample_fmt;
92 return false;
94 } else {
95 DLOG(WARNING) << "AudioFileReader::Open() : could not find codec -"
96 << " result: " << result;
97 return false;
100 // Verify the channel layout is supported by Chrome. Acts as a sanity check
101 // against invalid files. See http://crbug.com/171962
102 if (ChannelLayoutToChromeChannelLayout(
103 codec_context_->channel_layout, codec_context_->channels) ==
104 CHANNEL_LAYOUT_UNSUPPORTED) {
105 return false;
108 // Store initial values to guard against midstream configuration changes.
109 channels_ = codec_context_->channels;
110 sample_rate_ = codec_context_->sample_rate;
111 av_sample_format_ = codec_context_->sample_fmt;
113 return true;
116 void AudioFileReader::Close() {
117 if (codec_context_) {
118 avcodec_close(codec_context_);
119 codec_context_ = NULL;
123 int AudioFileReader::Read(AudioBus* audio_bus) {
124 DCHECK(glue_.get() && codec_context_) <<
125 "AudioFileReader::Read() : reader is not opened!";
127 DCHECK_EQ(audio_bus->channels(), channels());
128 if (audio_bus->channels() != channels())
129 return 0;
131 size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt);
133 // Holds decoded audio.
134 scoped_ptr_malloc<AVFrame, ScopedPtrAVFree> av_frame(avcodec_alloc_frame());
136 // Read until we hit EOF or we've read the requested number of frames.
137 AVPacket packet;
138 int current_frame = 0;
139 bool continue_decoding = true;
141 while (current_frame < audio_bus->frames() && continue_decoding &&
142 av_read_frame(glue_->format_context(), &packet) >= 0 &&
143 av_dup_packet(&packet) >= 0) {
144 // Skip packets from other streams.
145 if (packet.stream_index != stream_index_) {
146 av_free_packet(&packet);
147 continue;
150 // Make a shallow copy of packet so we can slide packet.data as frames are
151 // decoded from the packet; otherwise av_free_packet() will corrupt memory.
152 AVPacket packet_temp = packet;
153 do {
154 avcodec_get_frame_defaults(av_frame.get());
155 int frame_decoded = 0;
156 int result = avcodec_decode_audio4(
157 codec_context_, av_frame.get(), &frame_decoded, &packet_temp);
159 if (result < 0) {
160 DLOG(WARNING)
161 << "AudioFileReader::Read() : error in avcodec_decode_audio4() -"
162 << result;
163 continue_decoding = false;
164 break;
167 // Update packet size and data pointer in case we need to call the decoder
168 // with the remaining bytes from this packet.
169 packet_temp.size -= result;
170 packet_temp.data += result;
172 if (!frame_decoded)
173 continue;
175 // Determine the number of sample-frames we just decoded. Check overflow.
176 int frames_read = av_frame->nb_samples;
177 if (frames_read < 0) {
178 continue_decoding = false;
179 break;
182 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS
183 int channels = av_get_channel_layout_nb_channels(
184 av_frame->channel_layout);
185 #else
186 int channels = av_frame->channels;
187 #endif
188 if (av_frame->sample_rate != sample_rate_ ||
189 channels != channels_ ||
190 av_frame->format != av_sample_format_) {
191 DLOG(ERROR) << "Unsupported midstream configuration change!"
192 << " Sample Rate: " << av_frame->sample_rate << " vs "
193 << sample_rate_
194 << ", Channels: " << channels << " vs "
195 << channels_
196 << ", Sample Format: " << av_frame->format << " vs "
197 << av_sample_format_;
199 // This is an unrecoverable error, so bail out.
200 continue_decoding = false;
201 break;
204 // Truncate, if necessary, if the destination isn't big enough.
205 if (current_frame + frames_read > audio_bus->frames())
206 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 // Zero any remaining frames.
237 audio_bus->ZeroFramesPartial(
238 current_frame, audio_bus->frames() - current_frame);
240 // Returns the actual number of sample-frames decoded.
241 // Ideally this represents the "true" exact length of the file.
242 return current_frame;
245 } // namespace media