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"
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"
17 AudioFileReader::AudioFileReader(FFmpegURLProtocol
* protocol
)
18 : codec_context_(NULL
),
24 av_sample_format_(0) {
27 AudioFileReader::~AudioFileReader() {
31 bool AudioFileReader::Open() {
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()";
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
) {
62 const int result
= avformat_find_stream_info(format_context
, NULL
);
65 << "AudioFileReader::Open() : error in avformat_find_stream_info()";
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_
) <
79 bool AudioFileReader::OpenDecoder() {
80 AVCodec
* codec
= avcodec_find_decoder(codec_context_
->codec_id
);
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
);
88 DLOG(WARNING
) << "AudioFileReader::Open() : could not open codec -"
89 << " result: " << result
;
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
;
101 DLOG(WARNING
) << "AudioFileReader::Open() : could not find codec.";
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
) {
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
;
120 void AudioFileReader::Close() {
121 // |codec_context_| is a stream inside glue_->format_context(), so it is
122 // closed when |glue_| is disposed.
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())
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.
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
;
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
);
160 << "AudioFileReader::Read() : error in avcodec_decode_audio4() -"
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
;
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;
180 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS
181 int channels
= av_get_channel_layout_nb_channels(
182 av_frame
->channel_layout
);
184 int channels
= av_frame
->channels
;
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 "
192 << ", Channels: " << channels
<< " vs "
194 << ", Sample Format: " << av_frame
->format
<< " vs "
195 << av_sample_format_
;
197 // This is an unrecoverable error, so bail out.
198 continue_decoding
= false;
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
);
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
);
287 bool AudioFileReader::SeekForTesting(base::TimeDelta seek_time
) {
288 return av_seek_frame(glue_
->format_context(),
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_
];