Home | History | Annotate | Download | only in android
      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 "content/renderer/media/android/audio_decoder_android.h"
      6 
      7 #include <errno.h>
      8 #include <fcntl.h>
      9 #include <limits.h>
     10 #include <sys/mman.h>
     11 #include <unistd.h>
     12 #include <vector>
     13 
     14 #include "base/file_descriptor_posix.h"
     15 #include "base/logging.h"
     16 #include "base/memory/shared_memory.h"
     17 #include "base/posix/eintr_wrapper.h"
     18 #include "content/common/view_messages.h"
     19 #include "media/base/android/webaudio_media_codec_info.h"
     20 #include "media/base/audio_bus.h"
     21 #include "media/base/limits.h"
     22 #include "third_party/WebKit/public/platform/WebAudioBus.h"
     23 
     24 namespace content {
     25 
     26 class AudioDecoderIO {
     27  public:
     28   AudioDecoderIO(const char* data, size_t data_size);
     29   ~AudioDecoderIO();
     30   bool ShareEncodedToProcess(base::SharedMemoryHandle* handle);
     31 
     32   // Returns true if AudioDecoderIO was successfully created.
     33   bool IsValid() const;
     34 
     35   int read_fd() const { return read_fd_; }
     36   int write_fd() const { return write_fd_; }
     37 
     38  private:
     39   // Shared memory that will hold the encoded audio data.  This is
     40   // used by MediaCodec for decoding.
     41   base::SharedMemory encoded_shared_memory_;
     42 
     43   // A pipe used to communicate with MediaCodec.  MediaCodec owns
     44   // write_fd_ and writes to it.
     45   int read_fd_;
     46   int write_fd_;
     47 
     48   DISALLOW_COPY_AND_ASSIGN(AudioDecoderIO);
     49 };
     50 
     51 AudioDecoderIO::AudioDecoderIO(const char* data, size_t data_size)
     52     : read_fd_(-1),
     53       write_fd_(-1) {
     54 
     55   if (!data || !data_size || data_size > 0x80000000)
     56     return;
     57 
     58   // Create the shared memory and copy our data to it so that
     59   // MediaCodec can access it.
     60   encoded_shared_memory_.CreateAndMapAnonymous(data_size);
     61 
     62   if (!encoded_shared_memory_.memory())
     63     return;
     64 
     65   memcpy(encoded_shared_memory_.memory(), data, data_size);
     66 
     67   // Create a pipe for reading/writing the decoded PCM data
     68   int pipefd[2];
     69 
     70   if (pipe(pipefd))
     71     return;
     72 
     73   read_fd_ = pipefd[0];
     74   write_fd_ = pipefd[1];
     75 }
     76 
     77 AudioDecoderIO::~AudioDecoderIO() {
     78   // Close the read end of the pipe.  The write end should have been
     79   // closed by MediaCodec.
     80   if (read_fd_ >= 0 && close(read_fd_)) {
     81     DVLOG(1) << "Cannot close read fd " << read_fd_
     82              << ": " << strerror(errno);
     83   }
     84 }
     85 
     86 bool AudioDecoderIO::IsValid() const {
     87   return read_fd_ >= 0 && write_fd_ >= 0 &&
     88       encoded_shared_memory_.memory();
     89 }
     90 
     91 bool AudioDecoderIO::ShareEncodedToProcess(base::SharedMemoryHandle* handle) {
     92   return encoded_shared_memory_.ShareToProcess(
     93       base::Process::Current().handle(),
     94       handle);
     95 }
     96 
     97 static float ConvertSampleToFloat(int16_t sample) {
     98   const float kMaxScale = 1.0f / std::numeric_limits<int16_t>::max();
     99   const float kMinScale = -1.0f / std::numeric_limits<int16_t>::min();
    100 
    101   return sample * (sample < 0 ? kMinScale : kMaxScale);
    102 }
    103 
    104 // A basic WAVE file decoder.  See
    105 // https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ for a
    106 // basic guide to the WAVE file format.
    107 class WAVEDecoder {
    108  public:
    109   WAVEDecoder(const uint8* data, size_t data_size);
    110   ~WAVEDecoder();
    111 
    112   // Try to decode the data as a WAVE file.  If the data is a supported
    113   // WAVE file, |destination_bus| is filled with the decoded data and
    114   // DecodeWAVEFile returns true.  Otherwise, DecodeWAVEFile returns
    115   // false.
    116   bool DecodeWAVEFile(WebKit::WebAudioBus* destination_bus);
    117 
    118  private:
    119   // Minimum number of bytes in a WAVE file to hold all of the data we
    120   // need to interpret it as a WAVE file.
    121   static const unsigned kMinimumWAVLength = 44;
    122 
    123   // Number of bytes in the chunk ID field.
    124   static const unsigned kChunkIDLength = 4;
    125 
    126   // Number of bytes in the chunk size field.
    127   static const unsigned kChunkSizeLength = 4;
    128 
    129   // Number of bytes in the format field of the "RIFF" chunk.
    130   static const unsigned kFormatFieldLength = 4;
    131 
    132   // Number of bytes in a valid "fmt" chunk.
    133   static const unsigned kFMTChunkLength = 16;
    134 
    135   // Supported audio format in a WAVE file.
    136   // TODO(rtoy): Consider supporting other formats here, if necessary.
    137   static const int16_t kAudioFormatPCM = 1;
    138 
    139   // Maximum number (inclusive) of bytes per sample supported by this
    140   // decoder.
    141   static const unsigned kMaximumBytesPerSample = 3;
    142 
    143   // Read an unsigned integer of |length| bytes from |buffer|.  The
    144   // integer is interpreted as being in little-endian order.
    145   uint32_t ReadUnsignedInteger(const uint8_t* buffer, size_t length);
    146 
    147   // Read a PCM sample from the WAVE data at |pcm_data|.
    148   int16_t ReadPCMSample(const uint8_t* pcm_data);
    149 
    150   // Read a WAVE chunk header including the chunk ID and chunk size.
    151   // Returns false if the header could not be read.
    152   bool ReadChunkHeader();
    153 
    154   // Read and parse the "fmt" chunk.  Returns false if the fmt chunk
    155   // could not be read or contained unsupported formats.
    156   bool ReadFMTChunk();
    157 
    158   // Read data chunk and save it to |destination_bus|.  Returns false
    159   // if the data chunk could not be read correctly.
    160   bool CopyDataChunkToBus(WebKit::WebAudioBus* destination_bus);
    161 
    162   // The WAVE chunk ID that identifies the chunk.
    163   uint8_t chunk_id_[kChunkIDLength];
    164 
    165   // The number of bytes in the data portion of the chunk.
    166   size_t chunk_size_;
    167 
    168   // The current position within the WAVE file.
    169   const uint8_t* buffer_;
    170 
    171   // Points one byte past the end of the in-memory WAVE file.  Used for
    172   // detecting if we've reached the end of the file.
    173   const uint8_t* buffer_end_;
    174 
    175   size_t bytes_per_sample_;
    176 
    177   uint16_t number_of_channels_;
    178 
    179   // Sample rate of the WAVE data, in Hz.
    180   uint32_t sample_rate_;
    181 
    182   DISALLOW_COPY_AND_ASSIGN(WAVEDecoder);
    183 };
    184 
    185 WAVEDecoder::WAVEDecoder(const uint8_t* encoded_data, size_t data_size)
    186     : buffer_(encoded_data),
    187       buffer_end_(encoded_data + 1),
    188       bytes_per_sample_(0),
    189       number_of_channels_(0),
    190       sample_rate_(0) {
    191   if (buffer_ + data_size > buffer_)
    192     buffer_end_ = buffer_ + data_size;
    193 }
    194 
    195 WAVEDecoder::~WAVEDecoder() {}
    196 
    197 uint32_t WAVEDecoder::ReadUnsignedInteger(const uint8_t* buffer,
    198                                           size_t length) {
    199   unsigned value = 0;
    200 
    201   if (length == 0 || length > sizeof(value)) {
    202     DCHECK(false) << "ReadUnsignedInteger: Invalid length: " << length;
    203     return 0;
    204   }
    205 
    206   // All integer fields in a WAVE file are little-endian.
    207   for (size_t k = length; k > 0; --k)
    208     value = (value << 8) + buffer[k - 1];
    209 
    210   return value;
    211 }
    212 
    213 int16_t WAVEDecoder::ReadPCMSample(const uint8_t* pcm_data) {
    214   uint32_t unsigned_sample = ReadUnsignedInteger(pcm_data, bytes_per_sample_);
    215   int16_t sample;
    216 
    217   // Convert the unsigned data into a 16-bit PCM sample.
    218   switch (bytes_per_sample_) {
    219     case 1:
    220       sample = (unsigned_sample - 128) << 8;
    221       break;
    222     case 2:
    223       sample = static_cast<int16_t>(unsigned_sample);
    224       break;
    225     case 3:
    226       // Android currently converts 24-bit WAVE data into 16-bit
    227       // samples by taking the high-order 16 bits without rounding.
    228       // We do the same here for consistency.
    229       sample = static_cast<int16_t>(unsigned_sample >> 8);
    230       break;
    231     default:
    232       sample = 0;
    233       break;
    234   }
    235   return sample;
    236 }
    237 
    238 bool WAVEDecoder::ReadChunkHeader() {
    239   if (buffer_ + kChunkIDLength + kChunkSizeLength >= buffer_end_)
    240     return false;
    241 
    242   memcpy(chunk_id_, buffer_, kChunkIDLength);
    243 
    244   chunk_size_ = ReadUnsignedInteger(buffer_ + kChunkIDLength, kChunkSizeLength);
    245 
    246   // Adjust for padding
    247   if (chunk_size_ % 2)
    248     ++chunk_size_;
    249 
    250   return true;
    251 }
    252 
    253 bool WAVEDecoder::ReadFMTChunk() {
    254   // The fmt chunk has basic info about the format of the audio
    255   // data.  Only a basic PCM format is supported.
    256   if (chunk_size_ < kFMTChunkLength) {
    257     DVLOG(1) << "FMT chunk too short: " << chunk_size_;
    258     return 0;
    259   }
    260 
    261   uint16_t audio_format = ReadUnsignedInteger(buffer_, 2);
    262 
    263   if (audio_format != kAudioFormatPCM) {
    264     DVLOG(1) << "Audio format not supported: " << audio_format;
    265     return false;
    266   }
    267 
    268   number_of_channels_ = ReadUnsignedInteger(buffer_ + 2, 2);
    269   sample_rate_ = ReadUnsignedInteger(buffer_ + 4, 4);
    270   unsigned bits_per_sample = ReadUnsignedInteger(buffer_ + 14, 2);
    271 
    272   // Sanity checks.
    273 
    274   if (!number_of_channels_ ||
    275       number_of_channels_ > media::limits::kMaxChannels) {
    276     DVLOG(1) << "Unsupported number of channels: " << number_of_channels_;
    277     return false;
    278   }
    279 
    280   if (sample_rate_ < media::limits::kMinSampleRate ||
    281       sample_rate_ > media::limits::kMaxSampleRate) {
    282     DVLOG(1) << "Unsupported sample rate: " << sample_rate_;
    283     return false;
    284   }
    285 
    286   // We only support 8, 16, and 24 bits per sample.
    287   if (bits_per_sample == 8 || bits_per_sample == 16 || bits_per_sample == 24) {
    288     bytes_per_sample_ = bits_per_sample / 8;
    289     return true;
    290   }
    291 
    292   DVLOG(1) << "Unsupported bits per sample: " << bits_per_sample;
    293   return false;
    294 }
    295 
    296 bool WAVEDecoder::CopyDataChunkToBus(WebKit::WebAudioBus* destination_bus) {
    297   // The data chunk contains the audio data itself.
    298   if (!bytes_per_sample_ || bytes_per_sample_ > kMaximumBytesPerSample) {
    299     DVLOG(1) << "WARNING: data chunk without preceeding fmt chunk,"
    300              << " or invalid bytes per sample.";
    301     return false;
    302   }
    303 
    304   VLOG(0) << "Decoding WAVE file: " << number_of_channels_ << " channels, "
    305           << sample_rate_ << " kHz, "
    306           << chunk_size_ / bytes_per_sample_ / number_of_channels_
    307           << " frames, " << 8 * bytes_per_sample_ << " bits/sample";
    308 
    309   // Create the destination bus of the appropriate size and then decode
    310   // the data into the bus.
    311   size_t number_of_frames =
    312       chunk_size_ / bytes_per_sample_ / number_of_channels_;
    313 
    314   destination_bus->initialize(
    315       number_of_channels_, number_of_frames, sample_rate_);
    316 
    317   for (size_t m = 0; m < number_of_frames; ++m) {
    318     for (uint16_t k = 0; k < number_of_channels_; ++k) {
    319       int16_t sample = ReadPCMSample(buffer_);
    320 
    321       buffer_ += bytes_per_sample_;
    322       destination_bus->channelData(k)[m] = ConvertSampleToFloat(sample);
    323     }
    324   }
    325 
    326   return true;
    327 }
    328 
    329 bool WAVEDecoder::DecodeWAVEFile(WebKit::WebAudioBus* destination_bus) {
    330   // Parse and decode WAVE file. If we can't parse it, return false.
    331 
    332   if (buffer_ + kMinimumWAVLength > buffer_end_) {
    333     DVLOG(1) << "Buffer too small to contain full WAVE header: ";
    334     return false;
    335   }
    336 
    337   // Do we have a RIFF file?
    338   ReadChunkHeader();
    339   if (memcmp(chunk_id_, "RIFF", kChunkIDLength) != 0) {
    340     DVLOG(1) << "RIFF missing";
    341     return false;
    342   }
    343   buffer_ += kChunkIDLength + kChunkSizeLength;
    344 
    345   // Check the format field of the RIFF chunk
    346   memcpy(chunk_id_, buffer_, kFormatFieldLength);
    347   if (memcmp(chunk_id_, "WAVE", kFormatFieldLength) != 0) {
    348     DVLOG(1) << "Invalid WAVE file:  missing WAVE header";
    349     return false;
    350   }
    351   // Advance past the format field
    352   buffer_ += kFormatFieldLength;
    353 
    354   // We have a WAVE file.  Start parsing the chunks.
    355 
    356   while (buffer_ < buffer_end_) {
    357     if (!ReadChunkHeader()) {
    358       DVLOG(1) << "Couldn't read chunk header";
    359       return false;
    360     }
    361 
    362     // Consume the chunk ID and chunk size
    363     buffer_ += kChunkIDLength + kChunkSizeLength;
    364 
    365     // Make sure we can read all chunk_size bytes.
    366     if (buffer_ + chunk_size_ > buffer_end_) {
    367       DVLOG(1) << "Insufficient bytes to read chunk of size " << chunk_size_;
    368       return false;
    369     }
    370 
    371     if (memcmp(chunk_id_, "fmt ", kChunkIDLength) == 0) {
    372       if (!ReadFMTChunk())
    373         return false;
    374     } else if (memcmp(chunk_id_, "data", kChunkIDLength) == 0) {
    375       // Return after reading the data chunk, whether we succeeded or
    376       // not.
    377       return CopyDataChunkToBus(destination_bus);
    378     } else {
    379       // Ignore these chunks that we don't know about.
    380       VLOG(0) << "Ignoring WAVE chunk `" << chunk_id_ << "' size "
    381               << chunk_size_;
    382     }
    383 
    384     // Advance to next chunk.
    385     buffer_ += chunk_size_;
    386   }
    387 
    388   // If we get here, that means we didn't find a data chunk, so we
    389   // couldn't handle this WAVE file.
    390 
    391   return false;
    392 }
    393 
    394 // The number of frames is known so preallocate the destination
    395 // bus and copy the pcm data to the destination bus as it's being
    396 // received.
    397 static void CopyPcmDataToBus(int input_fd,
    398                              WebKit::WebAudioBus* destination_bus,
    399                              size_t number_of_frames,
    400                              unsigned number_of_channels,
    401                              double file_sample_rate) {
    402   destination_bus->initialize(number_of_channels,
    403                               number_of_frames,
    404                               file_sample_rate);
    405 
    406   int16_t pipe_data[PIPE_BUF / sizeof(int16_t)];
    407   size_t decoded_frames = 0;
    408   ssize_t nread;
    409 
    410   while ((nread = HANDLE_EINTR(read(input_fd, pipe_data, sizeof(pipe_data)))) >
    411          0) {
    412     size_t samples_in_pipe = nread / sizeof(int16_t);
    413     for (size_t m = 0; m < samples_in_pipe; m += number_of_channels) {
    414       if (decoded_frames >= number_of_frames)
    415         break;
    416 
    417       for (size_t k = 0; k < number_of_channels; ++k) {
    418         int16_t sample = pipe_data[m + k];
    419         destination_bus->channelData(k)[decoded_frames] =
    420             ConvertSampleToFloat(sample);
    421       }
    422       ++decoded_frames;
    423     }
    424   }
    425 }
    426 
    427 // The number of frames is unknown, so keep reading and buffering
    428 // until there's no more data and then copy the data to the
    429 // destination bus.
    430 static void BufferAndCopyPcmDataToBus(int input_fd,
    431                                       WebKit::WebAudioBus* destination_bus,
    432                                       unsigned number_of_channels,
    433                                       double file_sample_rate) {
    434   int16_t pipe_data[PIPE_BUF / sizeof(int16_t)];
    435   std::vector<int16_t> decoded_samples;
    436   ssize_t nread;
    437 
    438   while ((nread = HANDLE_EINTR(read(input_fd, pipe_data, sizeof(pipe_data)))) >
    439          0) {
    440     size_t samples_in_pipe = nread / sizeof(int16_t);
    441     if (decoded_samples.size() + samples_in_pipe > decoded_samples.capacity()) {
    442       decoded_samples.reserve(std::max(samples_in_pipe,
    443                                        2 * decoded_samples.capacity()));
    444     }
    445     std::copy(pipe_data,
    446               pipe_data + samples_in_pipe,
    447               back_inserter(decoded_samples));
    448   }
    449 
    450   DVLOG(1) << "Total samples read = " << decoded_samples.size();
    451 
    452   // Convert the samples and save them in the audio bus.
    453   size_t number_of_samples = decoded_samples.size();
    454   size_t number_of_frames = decoded_samples.size() / number_of_channels;
    455   size_t decoded_frames = 0;
    456 
    457   destination_bus->initialize(number_of_channels,
    458                               number_of_frames,
    459                               file_sample_rate);
    460 
    461   for (size_t m = 0; m < number_of_samples; m += number_of_channels) {
    462     for (size_t k = 0; k < number_of_channels; ++k) {
    463       int16_t sample = decoded_samples[m + k];
    464       destination_bus->channelData(k)[decoded_frames] =
    465           ConvertSampleToFloat(sample);
    466     }
    467     ++decoded_frames;
    468   }
    469 }
    470 
    471 static bool TryWAVEFileDecoder(WebKit::WebAudioBus* destination_bus,
    472                                const uint8_t* encoded_data,
    473                                size_t data_size) {
    474   WAVEDecoder decoder(encoded_data, data_size);
    475 
    476   return decoder.DecodeWAVEFile(destination_bus);
    477 }
    478 
    479 // To decode audio data, we want to use the Android MediaCodec class.
    480 // But this can't run in a sandboxed process so we need initiate the
    481 // request to MediaCodec in the browser.  To do this, we create a
    482 // shared memory buffer that holds the audio data.  We send a message
    483 // to the browser to start the decoder using this buffer and one end
    484 // of a pipe.  The MediaCodec class will decode the data from the
    485 // shared memory and write the PCM samples back to us over a pipe.
    486 bool DecodeAudioFileData(WebKit::WebAudioBus* destination_bus, const char* data,
    487                          size_t data_size, double sample_rate,
    488                          scoped_refptr<ThreadSafeSender> sender) {
    489   // Try to decode the data as a WAVE file first.  If it can't be
    490   // decoded, use MediaCodec.  See crbug.com/259048.
    491   if (TryWAVEFileDecoder(
    492           destination_bus, reinterpret_cast<const uint8_t*>(data), data_size)) {
    493     return true;
    494   }
    495 
    496   AudioDecoderIO audio_decoder(data, data_size);
    497 
    498   if (!audio_decoder.IsValid())
    499     return false;
    500 
    501   base::SharedMemoryHandle encoded_data_handle;
    502   audio_decoder.ShareEncodedToProcess(&encoded_data_handle);
    503   base::FileDescriptor fd(audio_decoder.write_fd(), true);
    504 
    505   DVLOG(1) << "DecodeAudioFileData: Starting MediaCodec";
    506 
    507   // Start MediaCodec processing in the browser which will read from
    508   // encoded_data_handle for our shared memory and write the decoded
    509   // PCM samples (16-bit integer) to our pipe.
    510 
    511   sender->Send(new ViewHostMsg_RunWebAudioMediaCodec(
    512       encoded_data_handle, fd, data_size));
    513 
    514   // First, read the number of channels, the sample rate, and the
    515   // number of frames and a flag indicating if the file is an
    516   // ogg/vorbis file.  This must be coordinated with
    517   // WebAudioMediaCodecBridge!
    518   //
    519   // If we know the number of samples, we can create the destination
    520   // bus directly and do the conversion directly to the bus instead of
    521   // buffering up everything before saving the data to the bus.
    522 
    523   int input_fd = audio_decoder.read_fd();
    524   struct media::WebAudioMediaCodecInfo info;
    525 
    526   DVLOG(1) << "Reading audio file info from fd " << input_fd;
    527   ssize_t nread = HANDLE_EINTR(read(input_fd, &info, sizeof(info)));
    528   DVLOG(1) << "read:  " << nread << " bytes:\n"
    529            << " 0: number of channels = " << info.channel_count << "\n"
    530            << " 1: sample rate        = " << info.sample_rate << "\n"
    531            << " 2: number of frames   = " << info.number_of_frames << "\n";
    532 
    533   if (nread != sizeof(info))
    534     return false;
    535 
    536   unsigned number_of_channels = info.channel_count;
    537   double file_sample_rate = static_cast<double>(info.sample_rate);
    538   size_t number_of_frames = info.number_of_frames;
    539 
    540   // Sanity checks
    541   if (!number_of_channels ||
    542       number_of_channels > media::limits::kMaxChannels ||
    543       file_sample_rate < media::limits::kMinSampleRate ||
    544       file_sample_rate > media::limits::kMaxSampleRate) {
    545     return false;
    546   }
    547 
    548   if (number_of_frames > 0) {
    549     CopyPcmDataToBus(input_fd,
    550                      destination_bus,
    551                      number_of_frames,
    552                      number_of_channels,
    553                      file_sample_rate);
    554   } else {
    555     BufferAndCopyPcmDataToBus(input_fd,
    556                               destination_bus,
    557                               number_of_channels,
    558                               file_sample_rate);
    559   }
    560 
    561   return true;
    562 }
    563 
    564 }  // namespace content
    565