Home | History | Annotate | Download | only in filters
      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   if (codec_context_) {
    118     avcodec_close(codec_context_);
    119     codec_context_ = NULL;
    120   }
    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, ScopedPtrAVFree> av_frame(avcodec_alloc_frame());
    135 
    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;
    140 
    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;
    148     }
    149 
    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);
    158 
    159       if (result < 0) {
    160         DLOG(WARNING)
    161             << "AudioFileReader::Read() : error in avcodec_decode_audio4() -"
    162             << result;
    163         continue_decoding = false;
    164         break;
    165       }
    166 
    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;
    171 
    172       if (!frame_decoded)
    173         continue;
    174 
    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;
    180       }
    181 
    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_;
    198 
    199         // This is an unrecoverable error, so bail out.
    200         continue_decoding = false;
    201         break;
    202       }
    203 
    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;
    207 
    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];
    219           }
    220         }
    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);
    225         }
    226       } else {
    227         audio_bus->FromInterleavedPartial(
    228             av_frame->data[0], current_frame, frames_read, bytes_per_sample);
    229       }
    230 
    231       current_frame += frames_read;
    232     } while (packet_temp.size > 0);
    233     av_free_packet(&packet);
    234   }
    235 
    236   // Zero any remaining frames.
    237   audio_bus->ZeroFramesPartial(
    238       current_frame, audio_bus->frames() - current_frame);
    239 
    240   // Returns the actual number of sample-frames decoded.
    241   // Ideally this represents the "true" exact length of the file.
    242   return current_frame;
    243 }
    244 
    245 }  // namespace media
    246