[Extensions Toolbar] Move context menu logic to view delegates
[chromium-blink-merge.git] / media / filters / audio_file_reader.cc
blob967fcb2668d30412aef4b75774b582b6a414cb35
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 av_sample_format_(0) {
26 AudioFileReader::~AudioFileReader() {
27 Close();
30 bool AudioFileReader::Open() {
31 if (!OpenDemuxer())
32 return false;
33 return OpenDecoder();
36 bool AudioFileReader::OpenDemuxer() {
37 glue_.reset(new FFmpegGlue(protocol_));
38 AVFormatContext* format_context = glue_->format_context();
40 // Open FFmpeg AVFormatContext.
41 if (!glue_->OpenContext()) {
42 DLOG(WARNING) << "AudioFileReader::Open() : error in avformat_open_input()";
43 return false;
46 // Get the codec context.
47 codec_context_ = NULL;
48 for (size_t i = 0; i < format_context->nb_streams; ++i) {
49 AVCodecContext* c = format_context->streams[i]->codec;
50 if (c->codec_type == AVMEDIA_TYPE_AUDIO) {
51 codec_context_ = c;
52 stream_index_ = i;
53 break;
57 // Get the codec.
58 if (!codec_context_)
59 return false;
61 const int result = avformat_find_stream_info(format_context, NULL);
62 if (result < 0) {
63 DLOG(WARNING)
64 << "AudioFileReader::Open() : error in avformat_find_stream_info()";
65 return false;
68 return true;
71 bool AudioFileReader::OpenDecoder() {
72 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
73 if (codec) {
74 // MP3 decodes to S16P which we don't support, tell it to use S16 instead.
75 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P)
76 codec_context_->request_sample_fmt = AV_SAMPLE_FMT_S16;
78 const int result = avcodec_open2(codec_context_, codec, NULL);
79 if (result < 0) {
80 DLOG(WARNING) << "AudioFileReader::Open() : could not open codec -"
81 << " result: " << result;
82 return false;
85 // Ensure avcodec_open2() respected our format request.
86 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P) {
87 DLOG(ERROR) << "AudioFileReader::Open() : unable to configure a"
88 << " supported sample format - "
89 << codec_context_->sample_fmt;
90 return false;
92 } else {
93 DLOG(WARNING) << "AudioFileReader::Open() : could not find codec.";
94 return false;
97 // Verify the channel layout is supported by Chrome. Acts as a sanity check
98 // against invalid files. See http://crbug.com/171962
99 if (ChannelLayoutToChromeChannelLayout(
100 codec_context_->channel_layout, codec_context_->channels) ==
101 CHANNEL_LAYOUT_UNSUPPORTED) {
102 return false;
105 // Store initial values to guard against midstream configuration changes.
106 channels_ = codec_context_->channels;
107 sample_rate_ = codec_context_->sample_rate;
108 av_sample_format_ = codec_context_->sample_fmt;
109 return true;
112 void AudioFileReader::Close() {
113 // |codec_context_| is a stream inside glue_->format_context(), so it is
114 // closed when |glue_| is disposed.
115 glue_.reset();
116 codec_context_ = NULL;
119 int AudioFileReader::Read(AudioBus* audio_bus) {
120 DCHECK(glue_.get() && codec_context_) <<
121 "AudioFileReader::Read() : reader is not opened!";
123 DCHECK_EQ(audio_bus->channels(), channels());
124 if (audio_bus->channels() != channels())
125 return 0;
127 size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt);
129 // Holds decoded audio.
130 scoped_ptr<AVFrame, ScopedPtrAVFreeFrame> av_frame(av_frame_alloc());
132 // Read until we hit EOF or we've read the requested number of frames.
133 AVPacket packet;
134 int current_frame = 0;
135 bool continue_decoding = true;
137 while (current_frame < audio_bus->frames() && continue_decoding &&
138 ReadPacket(&packet)) {
139 // Make a shallow copy of packet so we can slide packet.data as frames are
140 // decoded from the packet; otherwise av_free_packet() will corrupt memory.
141 AVPacket packet_temp = packet;
142 do {
143 // Reset frame to default values.
144 av_frame_unref(av_frame.get());
146 int frame_decoded = 0;
147 int result = avcodec_decode_audio4(
148 codec_context_, av_frame.get(), &frame_decoded, &packet_temp);
150 if (result < 0) {
151 DLOG(WARNING)
152 << "AudioFileReader::Read() : error in avcodec_decode_audio4() -"
153 << result;
154 break;
157 // Update packet size and data pointer in case we need to call the decoder
158 // with the remaining bytes from this packet.
159 packet_temp.size -= result;
160 packet_temp.data += result;
162 if (!frame_decoded)
163 continue;
165 // Determine the number of sample-frames we just decoded. Check overflow.
166 int frames_read = av_frame->nb_samples;
167 if (frames_read < 0) {
168 continue_decoding = false;
169 break;
172 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS
173 int channels = av_get_channel_layout_nb_channels(
174 av_frame->channel_layout);
175 #else
176 int channels = av_frame->channels;
177 #endif
178 if (av_frame->sample_rate != sample_rate_ ||
179 channels != channels_ ||
180 av_frame->format != av_sample_format_) {
181 DLOG(ERROR) << "Unsupported midstream configuration change!"
182 << " Sample Rate: " << av_frame->sample_rate << " vs "
183 << sample_rate_
184 << ", Channels: " << channels << " vs "
185 << channels_
186 << ", Sample Format: " << av_frame->format << " vs "
187 << av_sample_format_;
189 // This is an unrecoverable error, so bail out.
190 continue_decoding = false;
191 break;
194 // Truncate, if necessary, if the destination isn't big enough.
195 if (current_frame + frames_read > audio_bus->frames()) {
196 DLOG(ERROR) << "Truncating decoded data due to output size.";
197 frames_read = audio_bus->frames() - current_frame;
200 // Deinterleave each channel and convert to 32bit floating-point with
201 // nominal range -1.0 -> +1.0. If the output is already in float planar
202 // format, just copy it into the AudioBus.
203 if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT) {
204 float* decoded_audio_data = reinterpret_cast<float*>(av_frame->data[0]);
205 int channels = audio_bus->channels();
206 for (int ch = 0; ch < channels; ++ch) {
207 float* bus_data = audio_bus->channel(ch) + current_frame;
208 for (int i = 0, offset = ch; i < frames_read;
209 ++i, offset += channels) {
210 bus_data[i] = decoded_audio_data[offset];
213 } else if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLTP) {
214 for (int ch = 0; ch < audio_bus->channels(); ++ch) {
215 memcpy(audio_bus->channel(ch) + current_frame,
216 av_frame->extended_data[ch], sizeof(float) * frames_read);
218 } else {
219 audio_bus->FromInterleavedPartial(
220 av_frame->data[0], current_frame, frames_read, bytes_per_sample);
223 current_frame += frames_read;
224 } while (packet_temp.size > 0);
225 av_free_packet(&packet);
228 // Zero any remaining frames.
229 audio_bus->ZeroFramesPartial(
230 current_frame, audio_bus->frames() - current_frame);
232 // Returns the actual number of sample-frames decoded.
233 // Ideally this represents the "true" exact length of the file.
234 return current_frame;
237 base::TimeDelta AudioFileReader::GetDuration() const {
238 const AVRational av_time_base = {1, AV_TIME_BASE};
240 // Add one microsecond to avoid rounding-down errors which can occur when
241 // |duration| has been calculated from an exact number of sample-frames.
242 // One microsecond is much less than the time of a single sample-frame
243 // at any real-world sample-rate.
244 return ConvertFromTimeBase(av_time_base,
245 glue_->format_context()->duration + 1);
248 int AudioFileReader::GetNumberOfFrames() const {
249 return static_cast<int>(ceil(GetDuration().InSecondsF() * sample_rate()));
252 bool AudioFileReader::OpenDemuxerForTesting() {
253 return OpenDemuxer();
256 bool AudioFileReader::ReadPacketForTesting(AVPacket* output_packet) {
257 return ReadPacket(output_packet);
260 bool AudioFileReader::ReadPacket(AVPacket* output_packet) {
261 while (av_read_frame(glue_->format_context(), output_packet) >= 0 &&
262 av_dup_packet(output_packet) >= 0) {
263 // Skip packets from other streams.
264 if (output_packet->stream_index != stream_index_) {
265 av_free_packet(output_packet);
266 continue;
268 return true;
270 return false;
273 bool AudioFileReader::SeekForTesting(base::TimeDelta seek_time) {
274 return av_seek_frame(glue_->format_context(),
275 stream_index_,
276 ConvertToTimeBase(codec_context_->time_base, seek_time),
277 AVSEEK_FLAG_BACKWARD) >= 0;
280 const AVStream* AudioFileReader::GetAVStreamForTesting() const {
281 return glue_->format_context()->streams[stream_index_];
284 } // namespace media