- add sources.
[platform/framework/web/crosswalk.git] / src / media / filters / audio_file_reader.cc
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.
4
5 #include "media/filters/audio_file_reader.h"
6
7 #include "base/logging.h"
8 #include "base/time/time.h"
9 #include "media/base/audio_bus.h"
10 #include "media/ffmpeg/ffmpeg_common.h"
11 #include "media/filters/ffmpeg_glue.h"
12
13 namespace media {
14
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) {
22 }
23
24 AudioFileReader::~AudioFileReader() {
25   Close();
26 }
27
28 base::TimeDelta AudioFileReader::duration() const {
29   const AVRational av_time_base = {1, AV_TIME_BASE};
30
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);
37 }
38
39 int64 AudioFileReader::number_of_frames() const {
40   return static_cast<int64>(duration().InSecondsF() * sample_rate());
41 }
42
43 bool AudioFileReader::Open() {
44   glue_.reset(new FFmpegGlue(protocol_));
45   AVFormatContext* format_context = glue_->format_context();
46
47   // Open FFmpeg AVFormatContext.
48   if (!glue_->OpenContext()) {
49     DLOG(WARNING) << "AudioFileReader::Open() : error in avformat_open_input()";
50     return false;
51   }
52
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;
61     }
62   }
63
64   // Get the codec.
65   if (!codec_context_)
66     return false;
67
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;
73   }
74
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;
80
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;
85     }
86
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;
93     }
94   } else {
95     DLOG(WARNING) << "AudioFileReader::Open() : could not find codec -"
96                   << " result: " << result;
97     return false;
98   }
99
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;
106   }
107
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;
112
113   return true;
114 }
115
116 void AudioFileReader::Close() {
117   // |codec_context_| is a stream inside glue_->format_context(), so it is
118   // closed when |glue_| is disposed.
119   glue_.reset();
120   codec_context_ = NULL;
121 }
122
123 int AudioFileReader::Read(AudioBus* audio_bus) {
124   DCHECK(glue_.get() && codec_context_) <<
125       "AudioFileReader::Read() : reader is not opened!";
126
127   DCHECK_EQ(audio_bus->channels(), channels());
128   if (audio_bus->channels() != channels())
129     return 0;
130
131   size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt);
132
133   // Holds decoded audio.
134   scoped_ptr_malloc<AVFrame, ScopedPtrAVFreeFrame> av_frame(
135       avcodec_alloc_frame());
136
137   // Read until we hit EOF or we've read the requested number of frames.
138   AVPacket packet;
139   int current_frame = 0;
140   bool continue_decoding = true;
141
142   while (current_frame < audio_bus->frames() && continue_decoding &&
143          av_read_frame(glue_->format_context(), &packet) >= 0 &&
144          av_dup_packet(&packet) >= 0) {
145     // Skip packets from other streams.
146     if (packet.stream_index != stream_index_) {
147       av_free_packet(&packet);
148       continue;
149     }
150
151     // Make a shallow copy of packet so we can slide packet.data as frames are
152     // decoded from the packet; otherwise av_free_packet() will corrupt memory.
153     AVPacket packet_temp = packet;
154     do {
155       avcodec_get_frame_defaults(av_frame.get());
156       int frame_decoded = 0;
157       int result = avcodec_decode_audio4(
158           codec_context_, av_frame.get(), &frame_decoded, &packet_temp);
159
160       if (result < 0) {
161         DLOG(WARNING)
162             << "AudioFileReader::Read() : error in avcodec_decode_audio4() -"
163             << result;
164         continue_decoding = false;
165         break;
166       }
167
168       // Update packet size and data pointer in case we need to call the decoder
169       // with the remaining bytes from this packet.
170       packet_temp.size -= result;
171       packet_temp.data += result;
172
173       if (!frame_decoded)
174         continue;
175
176       // Determine the number of sample-frames we just decoded.  Check overflow.
177       int frames_read = av_frame->nb_samples;
178       if (frames_read < 0) {
179         continue_decoding = false;
180         break;
181       }
182
183 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS
184       int channels = av_get_channel_layout_nb_channels(
185           av_frame->channel_layout);
186 #else
187       int channels = av_frame->channels;
188 #endif
189       if (av_frame->sample_rate != sample_rate_ ||
190           channels != channels_ ||
191           av_frame->format != av_sample_format_) {
192         DLOG(ERROR) << "Unsupported midstream configuration change!"
193                     << " Sample Rate: " << av_frame->sample_rate << " vs "
194                     << sample_rate_
195                     << ", Channels: " << channels << " vs "
196                     << channels_
197                     << ", Sample Format: " << av_frame->format << " vs "
198                     << av_sample_format_;
199
200         // This is an unrecoverable error, so bail out.
201         continue_decoding = false;
202         break;
203       }
204
205       // Truncate, if necessary, if the destination isn't big enough.
206       if (current_frame + frames_read > audio_bus->frames())
207         frames_read = audio_bus->frames() - current_frame;
208
209       // Deinterleave each channel and convert to 32bit floating-point with
210       // nominal range -1.0 -> +1.0.  If the output is already in float planar
211       // format, just copy it into the AudioBus.
212       if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT) {
213         float* decoded_audio_data = reinterpret_cast<float*>(av_frame->data[0]);
214         int channels = audio_bus->channels();
215         for (int ch = 0; ch < channels; ++ch) {
216           float* bus_data = audio_bus->channel(ch) + current_frame;
217           for (int i = 0, offset = ch; i < frames_read;
218                ++i, offset += channels) {
219             bus_data[i] = decoded_audio_data[offset];
220           }
221         }
222       } else if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLTP) {
223         for (int ch = 0; ch < audio_bus->channels(); ++ch) {
224           memcpy(audio_bus->channel(ch) + current_frame,
225                  av_frame->extended_data[ch], sizeof(float) * frames_read);
226         }
227       } else {
228         audio_bus->FromInterleavedPartial(
229             av_frame->data[0], current_frame, frames_read, bytes_per_sample);
230       }
231
232       current_frame += frames_read;
233     } while (packet_temp.size > 0);
234     av_free_packet(&packet);
235   }
236
237   // Zero any remaining frames.
238   audio_bus->ZeroFramesPartial(
239       current_frame, audio_bus->frames() - current_frame);
240
241   // Returns the actual number of sample-frames decoded.
242   // Ideally this represents the "true" exact length of the file.
243   return current_frame;
244 }
245
246 }  // namespace media