Home | History | Annotate | Download | only in libstagefright
      1 /*
      2  * Copyright (C) 2010 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 "OggExtractor"
     19 #include <utils/Log.h>
     20 
     21 #include "include/OggExtractor.h"
     22 
     23 #include <cutils/properties.h>
     24 #include <media/stagefright/DataSource.h>
     25 #include <media/stagefright/MediaBuffer.h>
     26 #include <media/stagefright/MediaBufferGroup.h>
     27 #include <media/stagefright/MediaDebug.h>
     28 #include <media/stagefright/MediaDefs.h>
     29 #include <media/stagefright/MediaErrors.h>
     30 #include <media/stagefright/MediaSource.h>
     31 #include <media/stagefright/MetaData.h>
     32 #include <media/stagefright/Utils.h>
     33 #include <utils/String8.h>
     34 
     35 extern "C" {
     36     #include <Tremolo/codec_internal.h>
     37 
     38     int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
     39     int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
     40     int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
     41 }
     42 
     43 namespace android {
     44 
     45 struct OggSource : public MediaSource {
     46     OggSource(const sp<OggExtractor> &extractor);
     47 
     48     virtual sp<MetaData> getFormat();
     49 
     50     virtual status_t start(MetaData *params = NULL);
     51     virtual status_t stop();
     52 
     53     virtual status_t read(
     54             MediaBuffer **buffer, const ReadOptions *options = NULL);
     55 
     56 protected:
     57     virtual ~OggSource();
     58 
     59 private:
     60     sp<OggExtractor> mExtractor;
     61     bool mStarted;
     62 
     63     OggSource(const OggSource &);
     64     OggSource &operator=(const OggSource &);
     65 };
     66 
     67 struct MyVorbisExtractor {
     68     MyVorbisExtractor(const sp<DataSource> &source);
     69     virtual ~MyVorbisExtractor();
     70 
     71     sp<MetaData> getFormat() const;
     72 
     73     // Returns an approximate bitrate in bits per second.
     74     uint64_t approxBitrate();
     75 
     76     status_t seekToOffset(off_t offset);
     77     status_t readNextPacket(MediaBuffer **buffer);
     78 
     79     void init();
     80 
     81 private:
     82     struct Page {
     83         uint64_t mGranulePosition;
     84         uint32_t mSerialNo;
     85         uint32_t mPageNo;
     86         uint8_t mFlags;
     87         uint8_t mNumSegments;
     88         uint8_t mLace[255];
     89     };
     90 
     91     sp<DataSource> mSource;
     92     off_t mOffset;
     93     Page mCurrentPage;
     94     size_t mCurrentPageSize;
     95     size_t mNextLaceIndex;
     96 
     97     off_t mFirstDataOffset;
     98 
     99     vorbis_info mVi;
    100     vorbis_comment mVc;
    101 
    102     sp<MetaData> mMeta;
    103 
    104     ssize_t readPage(off_t offset, Page *page);
    105     status_t findNextPage(off_t startOffset, off_t *pageOffset);
    106 
    107     void verifyHeader(
    108             MediaBuffer *buffer, uint8_t type);
    109 
    110     MyVorbisExtractor(const MyVorbisExtractor &);
    111     MyVorbisExtractor &operator=(const MyVorbisExtractor &);
    112 };
    113 
    114 ////////////////////////////////////////////////////////////////////////////////
    115 
    116 OggSource::OggSource(const sp<OggExtractor> &extractor)
    117     : mExtractor(extractor),
    118       mStarted(false) {
    119 }
    120 
    121 OggSource::~OggSource() {
    122     if (mStarted) {
    123         stop();
    124     }
    125 }
    126 
    127 sp<MetaData> OggSource::getFormat() {
    128     return mExtractor->mImpl->getFormat();
    129 }
    130 
    131 status_t OggSource::start(MetaData *params) {
    132     if (mStarted) {
    133         return INVALID_OPERATION;
    134     }
    135 
    136     mStarted = true;
    137 
    138     return OK;
    139 }
    140 
    141 status_t OggSource::stop() {
    142     mStarted = false;
    143 
    144     return OK;
    145 }
    146 
    147 status_t OggSource::read(
    148         MediaBuffer **out, const ReadOptions *options) {
    149     *out = NULL;
    150 
    151     int64_t seekTimeUs;
    152     if (options && options->getSeekTo(&seekTimeUs)) {
    153         off_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll;
    154         LOGI("seeking to offset %ld", pos);
    155 
    156         if (mExtractor->mImpl->seekToOffset(pos) != OK) {
    157             return ERROR_END_OF_STREAM;
    158         }
    159     }
    160 
    161     MediaBuffer *packet;
    162     status_t err = mExtractor->mImpl->readNextPacket(&packet);
    163 
    164     if (err != OK) {
    165         return err;
    166     }
    167 
    168 #if 0
    169     int64_t timeUs;
    170     if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) {
    171         LOGI("found time = %lld us", timeUs);
    172     } else {
    173         LOGI("NO time");
    174     }
    175 #endif
    176 
    177     *out = packet;
    178 
    179     return OK;
    180 }
    181 
    182 ////////////////////////////////////////////////////////////////////////////////
    183 
    184 MyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source)
    185     : mSource(source),
    186       mOffset(0),
    187       mCurrentPageSize(0),
    188       mNextLaceIndex(0),
    189       mFirstDataOffset(-1) {
    190     mCurrentPage.mNumSegments = 0;
    191 }
    192 
    193 MyVorbisExtractor::~MyVorbisExtractor() {
    194 }
    195 
    196 sp<MetaData> MyVorbisExtractor::getFormat() const {
    197     return mMeta;
    198 }
    199 
    200 status_t MyVorbisExtractor::findNextPage(
    201         off_t startOffset, off_t *pageOffset) {
    202     *pageOffset = startOffset;
    203 
    204     for (;;) {
    205         char signature[4];
    206         ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
    207 
    208         if (n < 4) {
    209             *pageOffset = 0;
    210 
    211             return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
    212         }
    213 
    214         if (!memcmp(signature, "OggS", 4)) {
    215             if (*pageOffset > startOffset) {
    216                 LOGV("skipped %ld bytes of junk to reach next frame",
    217                      *pageOffset - startOffset);
    218             }
    219 
    220             return OK;
    221         }
    222 
    223         ++*pageOffset;
    224     }
    225 }
    226 
    227 status_t MyVorbisExtractor::seekToOffset(off_t offset) {
    228     if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) {
    229         // Once we know where the actual audio data starts (past the headers)
    230         // don't ever seek to anywhere before that.
    231         offset = mFirstDataOffset;
    232     }
    233 
    234     off_t pageOffset;
    235     status_t err = findNextPage(offset, &pageOffset);
    236 
    237     if (err != OK) {
    238         return err;
    239     }
    240 
    241     mOffset = pageOffset;
    242 
    243     mCurrentPageSize = 0;
    244     mCurrentPage.mNumSegments = 0;
    245     mNextLaceIndex = 0;
    246 
    247     // XXX what if new page continues packet from last???
    248 
    249     return OK;
    250 }
    251 
    252 ssize_t MyVorbisExtractor::readPage(off_t offset, Page *page) {
    253     uint8_t header[27];
    254     if (mSource->readAt(offset, header, sizeof(header))
    255             < (ssize_t)sizeof(header)) {
    256         LOGE("failed to read %d bytes at offset 0x%08lx", sizeof(header), offset);
    257 
    258         return ERROR_IO;
    259     }
    260 
    261     if (memcmp(header, "OggS", 4)) {
    262         return ERROR_MALFORMED;
    263     }
    264 
    265     if (header[4] != 0) {
    266         // Wrong version.
    267 
    268         return ERROR_UNSUPPORTED;
    269     }
    270 
    271     page->mFlags = header[5];
    272 
    273     if (page->mFlags & ~7) {
    274         // Only bits 0-2 are defined in version 0.
    275         return ERROR_MALFORMED;
    276     }
    277 
    278     page->mGranulePosition = U64LE_AT(&header[6]);
    279 
    280 #if 0
    281     printf("granulePosition = %llu (0x%llx)\n",
    282            page->mGranulePosition, page->mGranulePosition);
    283 #endif
    284 
    285     page->mSerialNo = U32LE_AT(&header[14]);
    286     page->mPageNo = U32LE_AT(&header[18]);
    287 
    288     page->mNumSegments = header[26];
    289     if (mSource->readAt(
    290                 offset + sizeof(header), page->mLace, page->mNumSegments)
    291             < (ssize_t)page->mNumSegments) {
    292         return ERROR_IO;
    293     }
    294 
    295     size_t totalSize = 0;;
    296     for (size_t i = 0; i < page->mNumSegments; ++i) {
    297         totalSize += page->mLace[i];
    298     }
    299 
    300     String8 tmp;
    301     for (size_t i = 0; i < page->mNumSegments; ++i) {
    302         char x[32];
    303         sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]);
    304 
    305         tmp.append(x);
    306     }
    307 
    308     LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string());
    309 
    310     return sizeof(header) + page->mNumSegments + totalSize;
    311 }
    312 
    313 status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) {
    314     *out = NULL;
    315 
    316     MediaBuffer *buffer = NULL;
    317     int64_t timeUs = -1;
    318 
    319     for (;;) {
    320         size_t i;
    321         size_t packetSize = 0;
    322         bool gotFullPacket = false;
    323         for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) {
    324             uint8_t lace = mCurrentPage.mLace[i];
    325 
    326             packetSize += lace;
    327 
    328             if (lace < 255) {
    329                 gotFullPacket = true;
    330                 ++i;
    331                 break;
    332             }
    333         }
    334 
    335         if (mNextLaceIndex < mCurrentPage.mNumSegments) {
    336             off_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments;
    337             for (size_t j = 0; j < mNextLaceIndex; ++j) {
    338                 dataOffset += mCurrentPage.mLace[j];
    339             }
    340 
    341             size_t fullSize = packetSize;
    342             if (buffer != NULL) {
    343                 fullSize += buffer->range_length();
    344             }
    345             MediaBuffer *tmp = new MediaBuffer(fullSize);
    346             if (buffer != NULL) {
    347                 memcpy(tmp->data(), buffer->data(), buffer->range_length());
    348                 tmp->set_range(0, buffer->range_length());
    349                 buffer->release();
    350             } else {
    351                 // XXX Not only is this not technically the correct time for
    352                 // this packet, we also stamp every packet in this page
    353                 // with the same time. This needs fixing later.
    354                 timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate;
    355                 tmp->set_range(0, 0);
    356             }
    357             buffer = tmp;
    358 
    359             ssize_t n = mSource->readAt(
    360                     dataOffset,
    361                     (uint8_t *)buffer->data() + buffer->range_length(),
    362                     packetSize);
    363 
    364             if (n < (ssize_t)packetSize) {
    365                 LOGE("failed to read %d bytes at 0x%08lx", packetSize, dataOffset);
    366                 return ERROR_IO;
    367             }
    368 
    369             buffer->set_range(0, fullSize);
    370 
    371             mNextLaceIndex = i;
    372 
    373             if (gotFullPacket) {
    374                 // We've just read the entire packet.
    375 
    376                 if (timeUs >= 0) {
    377                     buffer->meta_data()->setInt64(kKeyTime, timeUs);
    378                 }
    379 
    380                 *out = buffer;
    381 
    382                 return OK;
    383             }
    384 
    385             // fall through, the buffer now contains the start of the packet.
    386         }
    387 
    388         CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments);
    389 
    390         mOffset += mCurrentPageSize;
    391         ssize_t n = readPage(mOffset, &mCurrentPage);
    392 
    393         if (n <= 0) {
    394             if (buffer) {
    395                 buffer->release();
    396                 buffer = NULL;
    397             }
    398 
    399             LOGE("readPage returned %ld", n);
    400 
    401             return n < 0 ? n : (status_t)ERROR_END_OF_STREAM;
    402         }
    403 
    404         mCurrentPageSize = n;
    405         mNextLaceIndex = 0;
    406 
    407         if (buffer != NULL) {
    408             if ((mCurrentPage.mFlags & 1) == 0) {
    409                 // This page does not continue the packet, i.e. the packet
    410                 // is already complete.
    411 
    412                 if (timeUs >= 0) {
    413                     buffer->meta_data()->setInt64(kKeyTime, timeUs);
    414                 }
    415 
    416                 *out = buffer;
    417 
    418                 return OK;
    419             }
    420         }
    421     }
    422 }
    423 
    424 void MyVorbisExtractor::init() {
    425     vorbis_info_init(&mVi);
    426 
    427     vorbis_comment mVc;
    428 
    429     mMeta = new MetaData;
    430     mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
    431 
    432     MediaBuffer *packet;
    433     CHECK_EQ(readNextPacket(&packet), OK);
    434     LOGV("read packet of size %d\n", packet->range_length());
    435     verifyHeader(packet, 1);
    436     packet->release();
    437     packet = NULL;
    438 
    439     CHECK_EQ(readNextPacket(&packet), OK);
    440     LOGV("read packet of size %d\n", packet->range_length());
    441     verifyHeader(packet, 3);
    442     packet->release();
    443     packet = NULL;
    444 
    445     CHECK_EQ(readNextPacket(&packet), OK);
    446     LOGV("read packet of size %d\n", packet->range_length());
    447     verifyHeader(packet, 5);
    448     packet->release();
    449     packet = NULL;
    450 
    451     mFirstDataOffset = mOffset + mCurrentPageSize;
    452 }
    453 
    454 void MyVorbisExtractor::verifyHeader(
    455         MediaBuffer *buffer, uint8_t type) {
    456     const uint8_t *data =
    457         (const uint8_t *)buffer->data() + buffer->range_offset();
    458 
    459     size_t size = buffer->range_length();
    460 
    461     CHECK(size >= 7);
    462 
    463     CHECK_EQ(data[0], type);
    464     CHECK(!memcmp(&data[1], "vorbis", 6));
    465 
    466     ogg_buffer buf;
    467     buf.data = (uint8_t *)data;
    468     buf.size = size;
    469     buf.refcount = 1;
    470     buf.ptr.owner = NULL;
    471 
    472     ogg_reference ref;
    473     ref.buffer = &buf;
    474     ref.begin = 0;
    475     ref.length = size;
    476     ref.next = NULL;
    477 
    478     oggpack_buffer bits;
    479     oggpack_readinit(&bits, &ref);
    480 
    481     CHECK_EQ(oggpack_read(&bits, 8), type);
    482     for (size_t i = 0; i < 6; ++i) {
    483         oggpack_read(&bits, 8);  // skip 'vorbis'
    484     }
    485 
    486     switch (type) {
    487         case 1:
    488         {
    489             CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits));
    490 
    491             mMeta->setData(kKeyVorbisInfo, 0, data, size);
    492             mMeta->setInt32(kKeySampleRate, mVi.rate);
    493             mMeta->setInt32(kKeyChannelCount, mVi.channels);
    494 
    495             LOGV("lower-bitrate = %ld", mVi.bitrate_lower);
    496             LOGV("upper-bitrate = %ld", mVi.bitrate_upper);
    497             LOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
    498             LOGV("window-bitrate = %ld", mVi.bitrate_window);
    499 
    500             off_t size;
    501             if (mSource->getSize(&size) == OK) {
    502                 uint64_t bps = approxBitrate();
    503 
    504                 mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
    505             }
    506             break;
    507         }
    508 
    509         case 3:
    510         {
    511             CHECK_EQ(0, _vorbis_unpack_comment(&mVc, &bits));
    512             break;
    513         }
    514 
    515         case 5:
    516         {
    517             CHECK_EQ(0, _vorbis_unpack_books(&mVi, &bits));
    518 
    519             mMeta->setData(kKeyVorbisBooks, 0, data, size);
    520             break;
    521         }
    522     }
    523 }
    524 
    525 uint64_t MyVorbisExtractor::approxBitrate() {
    526     if (mVi.bitrate_nominal != 0) {
    527         return mVi.bitrate_nominal;
    528     }
    529 
    530     return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
    531 }
    532 
    533 ////////////////////////////////////////////////////////////////////////////////
    534 
    535 OggExtractor::OggExtractor(const sp<DataSource> &source)
    536     : mDataSource(source),
    537       mInitCheck(NO_INIT),
    538       mImpl(NULL) {
    539     mImpl = new MyVorbisExtractor(mDataSource);
    540     CHECK_EQ(mImpl->seekToOffset(0), OK);
    541     mImpl->init();
    542 
    543     mInitCheck = OK;
    544 }
    545 
    546 OggExtractor::~OggExtractor() {
    547     delete mImpl;
    548     mImpl = NULL;
    549 }
    550 
    551 size_t OggExtractor::countTracks() {
    552     return mInitCheck != OK ? 0 : 1;
    553 }
    554 
    555 sp<MediaSource> OggExtractor::getTrack(size_t index) {
    556     if (index >= 1) {
    557         return NULL;
    558     }
    559 
    560     return new OggSource(this);
    561 }
    562 
    563 sp<MetaData> OggExtractor::getTrackMetaData(
    564         size_t index, uint32_t flags) {
    565     if (index >= 1) {
    566         return NULL;
    567     }
    568 
    569     return mImpl->getFormat();
    570 }
    571 
    572 sp<MetaData> OggExtractor::getMetaData() {
    573     sp<MetaData> meta = new MetaData;
    574 
    575     if (mInitCheck != OK) {
    576         return meta;
    577     }
    578 
    579     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
    580 
    581     return meta;
    582 }
    583 
    584 bool SniffOgg(
    585         const sp<DataSource> &source, String8 *mimeType, float *confidence) {
    586     char tmp[4];
    587     if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
    588         return false;
    589     }
    590 
    591     mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG);
    592     *confidence = 0.2f;
    593 
    594     return true;
    595 }
    596 
    597 }  // namespace android
    598