Home | History | Annotate | Download | only in libstagefright
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "WAVExtractor"
     19 #include <utils/Log.h>
     20 
     21 #include "include/WAVExtractor.h"
     22 
     23 #include <media/stagefright/DataSource.h>
     24 #include <media/stagefright/MediaBufferGroup.h>
     25 #include <media/stagefright/MediaDebug.h>
     26 #include <media/stagefright/MediaDefs.h>
     27 #include <media/stagefright/MediaErrors.h>
     28 #include <media/stagefright/MediaSource.h>
     29 #include <media/stagefright/MetaData.h>
     30 #include <utils/String8.h>
     31 
     32 namespace android {
     33 
     34 enum {
     35     WAVE_FORMAT_PCM = 1,
     36     WAVE_FORMAT_ALAW = 6,
     37     WAVE_FORMAT_MULAW = 7,
     38 };
     39 
     40 static uint32_t U32_LE_AT(const uint8_t *ptr) {
     41     return ptr[3] << 24 | ptr[2] << 16 | ptr[1] << 8 | ptr[0];
     42 }
     43 
     44 static uint16_t U16_LE_AT(const uint8_t *ptr) {
     45     return ptr[1] << 8 | ptr[0];
     46 }
     47 
     48 struct WAVSource : public MediaSource {
     49     WAVSource(
     50             const sp<DataSource> &dataSource,
     51             const sp<MetaData> &meta,
     52             uint16_t waveFormat,
     53             int32_t bitsPerSample,
     54             off64_t offset, size_t size);
     55 
     56     virtual status_t start(MetaData *params = NULL);
     57     virtual status_t stop();
     58     virtual sp<MetaData> getFormat();
     59 
     60     virtual status_t read(
     61             MediaBuffer **buffer, const ReadOptions *options = NULL);
     62 
     63 protected:
     64     virtual ~WAVSource();
     65 
     66 private:
     67     static const size_t kMaxFrameSize;
     68 
     69     sp<DataSource> mDataSource;
     70     sp<MetaData> mMeta;
     71     uint16_t mWaveFormat;
     72     int32_t mSampleRate;
     73     int32_t mNumChannels;
     74     int32_t mBitsPerSample;
     75     off64_t mOffset;
     76     size_t mSize;
     77     bool mStarted;
     78     MediaBufferGroup *mGroup;
     79     off64_t mCurrentPos;
     80 
     81     WAVSource(const WAVSource &);
     82     WAVSource &operator=(const WAVSource &);
     83 };
     84 
     85 WAVExtractor::WAVExtractor(const sp<DataSource> &source)
     86     : mDataSource(source),
     87       mValidFormat(false) {
     88     mInitCheck = init();
     89 }
     90 
     91 WAVExtractor::~WAVExtractor() {
     92 }
     93 
     94 sp<MetaData> WAVExtractor::getMetaData() {
     95     sp<MetaData> meta = new MetaData;
     96 
     97     if (mInitCheck != OK) {
     98         return meta;
     99     }
    100 
    101     meta->setCString(kKeyMIMEType, "audio/x-wav");
    102 
    103     return meta;
    104 }
    105 
    106 size_t WAVExtractor::countTracks() {
    107     return mInitCheck == OK ? 1 : 0;
    108 }
    109 
    110 sp<MediaSource> WAVExtractor::getTrack(size_t index) {
    111     if (mInitCheck != OK || index > 0) {
    112         return NULL;
    113     }
    114 
    115     return new WAVSource(
    116             mDataSource, mTrackMeta,
    117             mWaveFormat, mBitsPerSample, mDataOffset, mDataSize);
    118 }
    119 
    120 sp<MetaData> WAVExtractor::getTrackMetaData(
    121         size_t index, uint32_t flags) {
    122     if (mInitCheck != OK || index > 0) {
    123         return NULL;
    124     }
    125 
    126     return mTrackMeta;
    127 }
    128 
    129 status_t WAVExtractor::init() {
    130     uint8_t header[12];
    131     if (mDataSource->readAt(
    132                 0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
    133         return NO_INIT;
    134     }
    135 
    136     if (memcmp(header, "RIFF", 4) || memcmp(&header[8], "WAVE", 4)) {
    137         return NO_INIT;
    138     }
    139 
    140     size_t totalSize = U32_LE_AT(&header[4]);
    141 
    142     off64_t offset = 12;
    143     size_t remainingSize = totalSize;
    144     while (remainingSize >= 8) {
    145         uint8_t chunkHeader[8];
    146         if (mDataSource->readAt(offset, chunkHeader, 8) < 8) {
    147             return NO_INIT;
    148         }
    149 
    150         remainingSize -= 8;
    151         offset += 8;
    152 
    153         uint32_t chunkSize = U32_LE_AT(&chunkHeader[4]);
    154 
    155         if (chunkSize > remainingSize) {
    156             return NO_INIT;
    157         }
    158 
    159         if (!memcmp(chunkHeader, "fmt ", 4)) {
    160             if (chunkSize < 16) {
    161                 return NO_INIT;
    162             }
    163 
    164             uint8_t formatSpec[16];
    165             if (mDataSource->readAt(offset, formatSpec, 16) < 16) {
    166                 return NO_INIT;
    167             }
    168 
    169             mWaveFormat = U16_LE_AT(formatSpec);
    170             if (mWaveFormat != WAVE_FORMAT_PCM
    171                     && mWaveFormat != WAVE_FORMAT_ALAW
    172                     && mWaveFormat != WAVE_FORMAT_MULAW) {
    173                 return ERROR_UNSUPPORTED;
    174             }
    175 
    176             mNumChannels = U16_LE_AT(&formatSpec[2]);
    177             if (mNumChannels != 1 && mNumChannels != 2) {
    178                 return ERROR_UNSUPPORTED;
    179             }
    180 
    181             mSampleRate = U32_LE_AT(&formatSpec[4]);
    182 
    183             if (mSampleRate == 0) {
    184                 return ERROR_MALFORMED;
    185             }
    186 
    187             mBitsPerSample = U16_LE_AT(&formatSpec[14]);
    188 
    189             if (mWaveFormat == WAVE_FORMAT_PCM) {
    190                 if (mBitsPerSample != 8 && mBitsPerSample != 16
    191                     && mBitsPerSample != 24) {
    192                     return ERROR_UNSUPPORTED;
    193                 }
    194             } else {
    195                 CHECK(mWaveFormat == WAVE_FORMAT_MULAW
    196                         || mWaveFormat == WAVE_FORMAT_ALAW);
    197                 if (mBitsPerSample != 8) {
    198                     return ERROR_UNSUPPORTED;
    199                 }
    200             }
    201 
    202             mValidFormat = true;
    203         } else if (!memcmp(chunkHeader, "data", 4)) {
    204             if (mValidFormat) {
    205                 mDataOffset = offset;
    206                 mDataSize = chunkSize;
    207 
    208                 mTrackMeta = new MetaData;
    209 
    210                 switch (mWaveFormat) {
    211                     case WAVE_FORMAT_PCM:
    212                         mTrackMeta->setCString(
    213                                 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
    214                         break;
    215                     case WAVE_FORMAT_ALAW:
    216                         mTrackMeta->setCString(
    217                                 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_ALAW);
    218                         break;
    219                     default:
    220                         CHECK_EQ(mWaveFormat, WAVE_FORMAT_MULAW);
    221                         mTrackMeta->setCString(
    222                                 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_MLAW);
    223                         break;
    224                 }
    225 
    226                 mTrackMeta->setInt32(kKeyChannelCount, mNumChannels);
    227                 mTrackMeta->setInt32(kKeySampleRate, mSampleRate);
    228 
    229                 size_t bytesPerSample = mBitsPerSample >> 3;
    230 
    231                 int64_t durationUs =
    232                     1000000LL * (mDataSize / (mNumChannels * bytesPerSample))
    233                         / mSampleRate;
    234 
    235                 mTrackMeta->setInt64(kKeyDuration, durationUs);
    236 
    237                 return OK;
    238             }
    239         }
    240 
    241         offset += chunkSize;
    242     }
    243 
    244     return NO_INIT;
    245 }
    246 
    247 const size_t WAVSource::kMaxFrameSize = 32768;
    248 
    249 WAVSource::WAVSource(
    250         const sp<DataSource> &dataSource,
    251         const sp<MetaData> &meta,
    252         uint16_t waveFormat,
    253         int32_t bitsPerSample,
    254         off64_t offset, size_t size)
    255     : mDataSource(dataSource),
    256       mMeta(meta),
    257       mWaveFormat(waveFormat),
    258       mSampleRate(0),
    259       mNumChannels(0),
    260       mBitsPerSample(bitsPerSample),
    261       mOffset(offset),
    262       mSize(size),
    263       mStarted(false),
    264       mGroup(NULL) {
    265     CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate));
    266     CHECK(mMeta->findInt32(kKeyChannelCount, &mNumChannels));
    267 
    268     mMeta->setInt32(kKeyMaxInputSize, kMaxFrameSize);
    269 }
    270 
    271 WAVSource::~WAVSource() {
    272     if (mStarted) {
    273         stop();
    274     }
    275 }
    276 
    277 status_t WAVSource::start(MetaData *params) {
    278     LOGV("WAVSource::start");
    279 
    280     CHECK(!mStarted);
    281 
    282     mGroup = new MediaBufferGroup;
    283     mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
    284 
    285     if (mBitsPerSample == 8) {
    286         // As a temporary buffer for 8->16 bit conversion.
    287         mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
    288     }
    289 
    290     mCurrentPos = mOffset;
    291 
    292     mStarted = true;
    293 
    294     return OK;
    295 }
    296 
    297 status_t WAVSource::stop() {
    298     LOGV("WAVSource::stop");
    299 
    300     CHECK(mStarted);
    301 
    302     delete mGroup;
    303     mGroup = NULL;
    304 
    305     mStarted = false;
    306 
    307     return OK;
    308 }
    309 
    310 sp<MetaData> WAVSource::getFormat() {
    311     LOGV("WAVSource::getFormat");
    312 
    313     return mMeta;
    314 }
    315 
    316 status_t WAVSource::read(
    317         MediaBuffer **out, const ReadOptions *options) {
    318     *out = NULL;
    319 
    320     int64_t seekTimeUs;
    321     ReadOptions::SeekMode mode;
    322     if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
    323         int64_t pos = (seekTimeUs * mSampleRate) / 1000000 * mNumChannels * (mBitsPerSample >> 3);
    324         if (pos > mSize) {
    325             pos = mSize;
    326         }
    327         mCurrentPos = pos + mOffset;
    328     }
    329 
    330     MediaBuffer *buffer;
    331     status_t err = mGroup->acquire_buffer(&buffer);
    332     if (err != OK) {
    333         return err;
    334     }
    335 
    336     size_t maxBytesToRead =
    337         mBitsPerSample == 8 ? kMaxFrameSize / 2 : kMaxFrameSize;
    338 
    339     size_t maxBytesAvailable =
    340         (mCurrentPos - mOffset >= (off64_t)mSize)
    341             ? 0 : mSize - (mCurrentPos - mOffset);
    342 
    343     if (maxBytesToRead > maxBytesAvailable) {
    344         maxBytesToRead = maxBytesAvailable;
    345     }
    346 
    347     ssize_t n = mDataSource->readAt(
    348             mCurrentPos, buffer->data(),
    349             maxBytesToRead);
    350 
    351     if (n <= 0) {
    352         buffer->release();
    353         buffer = NULL;
    354 
    355         return ERROR_END_OF_STREAM;
    356     }
    357 
    358     buffer->set_range(0, n);
    359 
    360     if (mWaveFormat == WAVE_FORMAT_PCM) {
    361         if (mBitsPerSample == 8) {
    362             // Convert 8-bit unsigned samples to 16-bit signed.
    363 
    364             MediaBuffer *tmp;
    365             CHECK_EQ(mGroup->acquire_buffer(&tmp), OK);
    366 
    367             // The new buffer holds the sample number of samples, but each
    368             // one is 2 bytes wide.
    369             tmp->set_range(0, 2 * n);
    370 
    371             int16_t *dst = (int16_t *)tmp->data();
    372             const uint8_t *src = (const uint8_t *)buffer->data();
    373             ssize_t numBytes = n;
    374 
    375             while (numBytes-- > 0) {
    376                 *dst++ = ((int16_t)(*src) - 128) * 256;
    377                 ++src;
    378             }
    379 
    380             buffer->release();
    381             buffer = tmp;
    382         } else if (mBitsPerSample == 24) {
    383             // Convert 24-bit signed samples to 16-bit signed.
    384 
    385             const uint8_t *src =
    386                 (const uint8_t *)buffer->data() + buffer->range_offset();
    387             int16_t *dst = (int16_t *)src;
    388 
    389             size_t numSamples = buffer->range_length() / 3;
    390             for (size_t i = 0; i < numSamples; ++i) {
    391                 int32_t x = (int32_t)(src[0] | src[1] << 8 | src[2] << 16);
    392                 x = (x << 8) >> 8;  // sign extension
    393 
    394                 x = x >> 8;
    395                 *dst++ = (int16_t)x;
    396                 src += 3;
    397             }
    398 
    399             buffer->set_range(buffer->range_offset(), 2 * numSamples);
    400         }
    401     }
    402 
    403     size_t bytesPerSample = mBitsPerSample >> 3;
    404 
    405     buffer->meta_data()->setInt64(
    406             kKeyTime,
    407             1000000LL * (mCurrentPos - mOffset)
    408                 / (mNumChannels * bytesPerSample) / mSampleRate);
    409 
    410     buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
    411     mCurrentPos += n;
    412 
    413     *out = buffer;
    414 
    415     return OK;
    416 }
    417 
    418 ////////////////////////////////////////////////////////////////////////////////
    419 
    420 bool SniffWAV(
    421         const sp<DataSource> &source, String8 *mimeType, float *confidence,
    422         sp<AMessage> *) {
    423     char header[12];
    424     if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
    425         return false;
    426     }
    427 
    428     if (memcmp(header, "RIFF", 4) || memcmp(&header[8], "WAVE", 4)) {
    429         return false;
    430     }
    431 
    432     sp<MediaExtractor> extractor = new WAVExtractor(source);
    433     if (extractor->countTracks() == 0) {
    434         return false;
    435     }
    436 
    437     *mimeType = MEDIA_MIMETYPE_CONTAINER_WAV;
    438     *confidence = 0.3f;
    439 
    440     return true;
    441 }
    442 
    443 }  // namespace android
    444 
    445