Home | History | Annotate | Download | only in base
      1 // Copyright 2013 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/base/audio_buffer.h"
      6 
      7 #include "base/logging.h"
      8 #include "media/base/audio_bus.h"
      9 #include "media/base/buffers.h"
     10 #include "media/base/limits.h"
     11 
     12 namespace media {
     13 
     14 AudioBuffer::AudioBuffer(SampleFormat sample_format,
     15                          int channel_count,
     16                          int frame_count,
     17                          bool create_buffer,
     18                          const uint8* const* data,
     19                          const base::TimeDelta timestamp,
     20                          const base::TimeDelta duration)
     21     : sample_format_(sample_format),
     22       channel_count_(channel_count),
     23       adjusted_frame_count_(frame_count),
     24       trim_start_(0),
     25       end_of_stream_(!create_buffer && data == NULL && frame_count == 0),
     26       timestamp_(timestamp),
     27       duration_(duration) {
     28   CHECK_GE(channel_count, 0);
     29   CHECK_LE(channel_count, limits::kMaxChannels);
     30   CHECK_GE(frame_count, 0);
     31   int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format);
     32   DCHECK_LE(bytes_per_channel, kChannelAlignment);
     33   int data_size = frame_count * bytes_per_channel;
     34 
     35   // Empty buffer?
     36   if (!create_buffer)
     37     return;
     38 
     39   if (sample_format == kSampleFormatPlanarF32 ||
     40       sample_format == kSampleFormatPlanarS16) {
     41     // Planar data, so need to allocate buffer for each channel.
     42     // Determine per channel data size, taking into account alignment.
     43     int block_size_per_channel =
     44         (data_size + kChannelAlignment - 1) & ~(kChannelAlignment - 1);
     45     DCHECK_GE(block_size_per_channel, data_size);
     46 
     47     // Allocate a contiguous buffer for all the channel data.
     48     data_.reset(static_cast<uint8*>(base::AlignedAlloc(
     49         channel_count * block_size_per_channel, kChannelAlignment)));
     50     channel_data_.reserve(channel_count);
     51 
     52     // Copy each channel's data into the appropriate spot.
     53     for (int i = 0; i < channel_count; ++i) {
     54       channel_data_.push_back(data_.get() + i * block_size_per_channel);
     55       if (data)
     56         memcpy(channel_data_[i], data[i], data_size);
     57     }
     58     return;
     59   }
     60 
     61   // Remaining formats are interleaved data.
     62   DCHECK(sample_format_ == kSampleFormatU8 ||
     63          sample_format_ == kSampleFormatS16 ||
     64          sample_format_ == kSampleFormatS32 ||
     65          sample_format_ == kSampleFormatF32) << sample_format_;
     66   // Allocate our own buffer and copy the supplied data into it. Buffer must
     67   // contain the data for all channels.
     68   data_size *= channel_count;
     69   data_.reset(
     70       static_cast<uint8*>(base::AlignedAlloc(data_size, kChannelAlignment)));
     71   channel_data_.reserve(1);
     72   channel_data_.push_back(data_.get());
     73   if (data)
     74     memcpy(data_.get(), data[0], data_size);
     75 }
     76 
     77 AudioBuffer::~AudioBuffer() {}
     78 
     79 // static
     80 scoped_refptr<AudioBuffer> AudioBuffer::CopyFrom(
     81     SampleFormat sample_format,
     82     int channel_count,
     83     int frame_count,
     84     const uint8* const* data,
     85     const base::TimeDelta timestamp,
     86     const base::TimeDelta duration) {
     87   // If you hit this CHECK you likely have a bug in a demuxer. Go fix it.
     88   CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
     89   CHECK(data[0]);
     90   return make_scoped_refptr(new AudioBuffer(sample_format,
     91                                             channel_count,
     92                                             frame_count,
     93                                             true,
     94                                             data,
     95                                             timestamp,
     96                                             duration));
     97 }
     98 
     99 // static
    100 scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer(SampleFormat sample_format,
    101                                                      int channel_count,
    102                                                      int frame_count) {
    103   CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
    104   return make_scoped_refptr(new AudioBuffer(sample_format,
    105                                             channel_count,
    106                                             frame_count,
    107                                             true,
    108                                             NULL,
    109                                             kNoTimestamp(),
    110                                             kNoTimestamp()));
    111 }
    112 
    113 // static
    114 scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer(
    115     int channel_count,
    116     int frame_count,
    117     const base::TimeDelta timestamp,
    118     const base::TimeDelta duration) {
    119   CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
    120   // Since data == NULL, format doesn't matter.
    121   return make_scoped_refptr(new AudioBuffer(kSampleFormatF32,
    122                                             channel_count,
    123                                             frame_count,
    124                                             false,
    125                                             NULL,
    126                                             timestamp,
    127                                             duration));
    128 }
    129 
    130 // static
    131 scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() {
    132   return make_scoped_refptr(new AudioBuffer(
    133       kUnknownSampleFormat, 1, 0, false, NULL, kNoTimestamp(), kNoTimestamp()));
    134 }
    135 
    136 // Convert int16 values in the range [kint16min, kint16max] to [-1.0, 1.0].
    137 static inline float ConvertS16ToFloat(int16 value) {
    138   return value * (value < 0 ? -1.0f / kint16min : 1.0f / kint16max);
    139 }
    140 
    141 void AudioBuffer::ReadFrames(int frames_to_copy,
    142                              int source_frame_offset,
    143                              int dest_frame_offset,
    144                              AudioBus* dest) {
    145   // Deinterleave each channel (if necessary) and convert to 32bit
    146   // floating-point with nominal range -1.0 -> +1.0 (if necessary).
    147 
    148   // |dest| must have the same number of channels, and the number of frames
    149   // specified must be in range.
    150   DCHECK(!end_of_stream());
    151   DCHECK_EQ(dest->channels(), channel_count_);
    152   DCHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_);
    153   DCHECK_LE(dest_frame_offset + frames_to_copy, dest->frames());
    154 
    155   // Move the start past any frames that have been trimmed.
    156   source_frame_offset += trim_start_;
    157 
    158   if (!data_) {
    159     // Special case for an empty buffer.
    160     dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy);
    161     return;
    162   }
    163 
    164   if (sample_format_ == kSampleFormatPlanarF32) {
    165     // Format is planar float32. Copy the data from each channel as a block.
    166     for (int ch = 0; ch < channel_count_; ++ch) {
    167       const float* source_data =
    168           reinterpret_cast<const float*>(channel_data_[ch]) +
    169           source_frame_offset;
    170       memcpy(dest->channel(ch) + dest_frame_offset,
    171              source_data,
    172              sizeof(float) * frames_to_copy);
    173     }
    174     return;
    175   }
    176 
    177   if (sample_format_ == kSampleFormatPlanarS16) {
    178     // Format is planar signed16. Convert each value into float and insert into
    179     // output channel data.
    180     for (int ch = 0; ch < channel_count_; ++ch) {
    181       const int16* source_data =
    182           reinterpret_cast<const int16*>(channel_data_[ch]) +
    183           source_frame_offset;
    184       float* dest_data = dest->channel(ch) + dest_frame_offset;
    185       for (int i = 0; i < frames_to_copy; ++i) {
    186         dest_data[i] = ConvertS16ToFloat(source_data[i]);
    187       }
    188     }
    189     return;
    190   }
    191 
    192   if (sample_format_ == kSampleFormatF32) {
    193     // Format is interleaved float32. Copy the data into each channel.
    194     const float* source_data = reinterpret_cast<const float*>(data_.get()) +
    195                                source_frame_offset * channel_count_;
    196     for (int ch = 0; ch < channel_count_; ++ch) {
    197       float* dest_data = dest->channel(ch) + dest_frame_offset;
    198       for (int i = 0, offset = ch; i < frames_to_copy;
    199            ++i, offset += channel_count_) {
    200         dest_data[i] = source_data[offset];
    201       }
    202     }
    203     return;
    204   }
    205 
    206   // Remaining formats are integer interleaved data. Use the deinterleaving code
    207   // in AudioBus to copy the data.
    208   DCHECK(sample_format_ == kSampleFormatU8 ||
    209          sample_format_ == kSampleFormatS16 ||
    210          sample_format_ == kSampleFormatS32);
    211   int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_);
    212   int frame_size = channel_count_ * bytes_per_channel;
    213   const uint8* source_data = data_.get() + source_frame_offset * frame_size;
    214   dest->FromInterleavedPartial(
    215       source_data, dest_frame_offset, frames_to_copy, bytes_per_channel);
    216 }
    217 
    218 void AudioBuffer::TrimStart(int frames_to_trim) {
    219   CHECK_GE(frames_to_trim, 0);
    220   CHECK_LE(frames_to_trim, adjusted_frame_count_);
    221 
    222   // Adjust timestamp_ and duration_ to reflect the smaller number of frames.
    223   double offset = static_cast<double>(duration_.InMicroseconds()) *
    224                   frames_to_trim / adjusted_frame_count_;
    225   base::TimeDelta offset_as_time =
    226       base::TimeDelta::FromMicroseconds(static_cast<int64>(offset));
    227   timestamp_ += offset_as_time;
    228   duration_ -= offset_as_time;
    229 
    230   // Finally adjust the number of frames in this buffer and where the start
    231   // really is.
    232   adjusted_frame_count_ -= frames_to_trim;
    233   trim_start_ += frames_to_trim;
    234 }
    235 
    236 void AudioBuffer::TrimEnd(int frames_to_trim) {
    237   CHECK_GE(frames_to_trim, 0);
    238   CHECK_LE(frames_to_trim, adjusted_frame_count_);
    239 
    240   // Adjust duration_ only to reflect the smaller number of frames.
    241   double offset = static_cast<double>(duration_.InMicroseconds()) *
    242                   frames_to_trim / adjusted_frame_count_;
    243   base::TimeDelta offset_as_time =
    244       base::TimeDelta::FromMicroseconds(static_cast<int64>(offset));
    245   duration_ -= offset_as_time;
    246 
    247   // Finally adjust the number of frames in this buffer.
    248   adjusted_frame_count_ -= frames_to_trim;
    249 }
    250 
    251 }  // namespace media
    252