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/foundation/ABuffer.h>
     25 #include <media/stagefright/foundation/ADebug.h>
     26 #include <media/stagefright/foundation/base64.h>
     27 #include <media/stagefright/DataSource.h>
     28 #include <media/stagefright/MediaBuffer.h>
     29 #include <media/stagefright/MediaBufferGroup.h>
     30 #include <media/stagefright/MediaDefs.h>
     31 #include <media/stagefright/MediaErrors.h>
     32 #include <media/stagefright/MediaSource.h>
     33 #include <media/stagefright/MetaData.h>
     34 #include <media/stagefright/Utils.h>
     35 #include <utils/String8.h>
     36 
     37 extern "C" {
     38     #include <Tremolo/codec_internal.h>
     39 
     40     int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
     41     int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
     42     int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
     43     long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
     44 }
     45 
     46 namespace android {
     47 
     48 struct OggSource : public MediaSource {
     49     OggSource(const sp<OggExtractor> &extractor);
     50 
     51     virtual sp<MetaData> getFormat();
     52 
     53     virtual status_t start(MetaData *params = NULL);
     54     virtual status_t stop();
     55 
     56     virtual status_t read(
     57             MediaBuffer **buffer, const ReadOptions *options = NULL);
     58 
     59 protected:
     60     virtual ~OggSource();
     61 
     62 private:
     63     sp<OggExtractor> mExtractor;
     64     bool mStarted;
     65 
     66     OggSource(const OggSource &);
     67     OggSource &operator=(const OggSource &);
     68 };
     69 
     70 struct MyOggExtractor {
     71     MyOggExtractor(
     72             const sp<DataSource> &source,
     73             const char *mimeType,
     74             size_t numHeaders,
     75             int64_t seekPreRollUs);
     76     virtual ~MyOggExtractor();
     77 
     78     sp<MetaData> getFormat() const;
     79 
     80     // Returns an approximate bitrate in bits per second.
     81     virtual uint64_t approxBitrate() const = 0;
     82 
     83     status_t seekToTime(int64_t timeUs);
     84     status_t seekToOffset(off64_t offset);
     85     virtual status_t readNextPacket(MediaBuffer **buffer) = 0;
     86 
     87     status_t init();
     88 
     89     sp<MetaData> getFileMetaData() { return mFileMeta; }
     90 
     91 protected:
     92     struct Page {
     93         uint64_t mGranulePosition;
     94         int32_t mPrevPacketSize;
     95         uint64_t mPrevPacketPos;
     96         uint32_t mSerialNo;
     97         uint32_t mPageNo;
     98         uint8_t mFlags;
     99         uint8_t mNumSegments;
    100         uint8_t mLace[255];
    101     };
    102 
    103     struct TOCEntry {
    104         off64_t mPageOffset;
    105         int64_t mTimeUs;
    106     };
    107 
    108     sp<DataSource> mSource;
    109     off64_t mOffset;
    110     Page mCurrentPage;
    111     uint64_t mCurGranulePosition;
    112     uint64_t mPrevGranulePosition;
    113     size_t mCurrentPageSize;
    114     bool mFirstPacketInPage;
    115     uint64_t mCurrentPageSamples;
    116     size_t mNextLaceIndex;
    117 
    118     const char *mMimeType;
    119     size_t mNumHeaders;
    120     int64_t mSeekPreRollUs;
    121 
    122     off64_t mFirstDataOffset;
    123 
    124     vorbis_info mVi;
    125     vorbis_comment mVc;
    126 
    127     sp<MetaData> mMeta;
    128     sp<MetaData> mFileMeta;
    129 
    130     Vector<TOCEntry> mTableOfContents;
    131 
    132     ssize_t readPage(off64_t offset, Page *page);
    133     status_t findNextPage(off64_t startOffset, off64_t *pageOffset);
    134 
    135     virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const = 0;
    136 
    137     // Extract codec format, metadata tags, and various codec specific data;
    138     // the format and CSD's are required to setup the decoders for the enclosed media content.
    139     //
    140     // Valid values for `type` are:
    141     // 1 - bitstream identification header
    142     // 3 - comment header
    143     // 5 - codec setup header (Vorbis only)
    144     virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type) = 0;
    145 
    146     // Read the next ogg packet from the underlying data source; optionally
    147     // calculate the timestamp for the output packet whilst pretending
    148     // that we are parsing an Ogg Vorbis stream.
    149     //
    150     // *buffer is NULL'ed out immediately upon entry, and if successful a new buffer is allocated;
    151     // clients are responsible for releasing the original buffer.
    152     status_t _readNextPacket(MediaBuffer **buffer, bool calcVorbisTimestamp);
    153 
    154     int32_t getPacketBlockSize(MediaBuffer *buffer);
    155 
    156     void parseFileMetaData();
    157 
    158     status_t findPrevGranulePosition(off64_t pageOffset, uint64_t *granulePos);
    159 
    160     void buildTableOfContents();
    161 
    162     MyOggExtractor(const MyOggExtractor &);
    163     MyOggExtractor &operator=(const MyOggExtractor &);
    164 };
    165 
    166 struct MyVorbisExtractor : public MyOggExtractor {
    167     MyVorbisExtractor(const sp<DataSource> &source)
    168         : MyOggExtractor(source,
    169                 MEDIA_MIMETYPE_AUDIO_VORBIS,
    170                 /* numHeaders */ 3,
    171                 /* seekPreRollUs */ 0) {
    172     }
    173 
    174     virtual uint64_t approxBitrate() const;
    175 
    176     virtual status_t readNextPacket(MediaBuffer **buffer) {
    177         return _readNextPacket(buffer, /* calcVorbisTimestamp = */ true);
    178     }
    179 
    180 protected:
    181     virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const {
    182         if (granulePos > INT64_MAX / 1000000ll) {
    183             return INT64_MAX;
    184         }
    185         return granulePos * 1000000ll / mVi.rate;
    186     }
    187 
    188     virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type);
    189 };
    190 
    191 struct MyOpusExtractor : public MyOggExtractor {
    192     static const int32_t kOpusSampleRate = 48000;
    193     static const int64_t kOpusSeekPreRollUs = 80000; // 80 ms
    194 
    195     MyOpusExtractor(const sp<DataSource> &source)
    196         : MyOggExtractor(source, MEDIA_MIMETYPE_AUDIO_OPUS, /*numHeaders*/ 2, kOpusSeekPreRollUs),
    197           mChannelCount(0),
    198           mCodecDelay(0),
    199           mStartGranulePosition(-1) {
    200     }
    201 
    202     virtual uint64_t approxBitrate() const {
    203         return 0;
    204     }
    205 
    206     virtual status_t readNextPacket(MediaBuffer **buffer);
    207 
    208 protected:
    209     virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const;
    210     virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type);
    211 
    212 private:
    213     status_t verifyOpusHeader(MediaBuffer *buffer);
    214     status_t verifyOpusComments(MediaBuffer *buffer);
    215     uint32_t getNumSamplesInPacket(MediaBuffer *buffer) const;
    216 
    217     uint8_t mChannelCount;
    218     uint16_t mCodecDelay;
    219     int64_t mStartGranulePosition;
    220 };
    221 
    222 static void extractAlbumArt(
    223         const sp<MetaData> &fileMeta, const void *data, size_t size);
    224 
    225 ////////////////////////////////////////////////////////////////////////////////
    226 
    227 OggSource::OggSource(const sp<OggExtractor> &extractor)
    228     : mExtractor(extractor),
    229       mStarted(false) {
    230 }
    231 
    232 OggSource::~OggSource() {
    233     if (mStarted) {
    234         stop();
    235     }
    236 }
    237 
    238 sp<MetaData> OggSource::getFormat() {
    239     return mExtractor->mImpl->getFormat();
    240 }
    241 
    242 status_t OggSource::start(MetaData * /* params */) {
    243     if (mStarted) {
    244         return INVALID_OPERATION;
    245     }
    246 
    247     mStarted = true;
    248 
    249     return OK;
    250 }
    251 
    252 status_t OggSource::stop() {
    253     mStarted = false;
    254 
    255     return OK;
    256 }
    257 
    258 status_t OggSource::read(
    259         MediaBuffer **out, const ReadOptions *options) {
    260     *out = NULL;
    261 
    262     int64_t seekTimeUs;
    263     ReadOptions::SeekMode mode;
    264     if (options && options->getSeekTo(&seekTimeUs, &mode)) {
    265         status_t err = mExtractor->mImpl->seekToTime(seekTimeUs);
    266         if (err != OK) {
    267             return err;
    268         }
    269     }
    270 
    271     MediaBuffer *packet;
    272     status_t err = mExtractor->mImpl->readNextPacket(&packet);
    273 
    274     if (err != OK) {
    275         return err;
    276     }
    277 
    278 #if 0
    279     int64_t timeUs;
    280     if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) {
    281         ALOGI("found time = %lld us", timeUs);
    282     } else {
    283         ALOGI("NO time");
    284     }
    285 #endif
    286 
    287     packet->meta_data()->setInt32(kKeyIsSyncFrame, 1);
    288 
    289     *out = packet;
    290 
    291     return OK;
    292 }
    293 
    294 ////////////////////////////////////////////////////////////////////////////////
    295 
    296 MyOggExtractor::MyOggExtractor(
    297         const sp<DataSource> &source,
    298         const char *mimeType,
    299         size_t numHeaders,
    300         int64_t seekPreRollUs)
    301     : mSource(source),
    302       mOffset(0),
    303       mCurGranulePosition(0),
    304       mPrevGranulePosition(0),
    305       mCurrentPageSize(0),
    306       mFirstPacketInPage(true),
    307       mCurrentPageSamples(0),
    308       mNextLaceIndex(0),
    309       mMimeType(mimeType),
    310       mNumHeaders(numHeaders),
    311       mSeekPreRollUs(seekPreRollUs),
    312       mFirstDataOffset(-1) {
    313     mCurrentPage.mNumSegments = 0;
    314 
    315     vorbis_info_init(&mVi);
    316     vorbis_comment_init(&mVc);
    317 }
    318 
    319 MyOggExtractor::~MyOggExtractor() {
    320     vorbis_comment_clear(&mVc);
    321     vorbis_info_clear(&mVi);
    322 }
    323 
    324 sp<MetaData> MyOggExtractor::getFormat() const {
    325     return mMeta;
    326 }
    327 
    328 status_t MyOggExtractor::findNextPage(
    329         off64_t startOffset, off64_t *pageOffset) {
    330     *pageOffset = startOffset;
    331 
    332     for (;;) {
    333         char signature[4];
    334         ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
    335 
    336         if (n < 4) {
    337             *pageOffset = 0;
    338 
    339             return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
    340         }
    341 
    342         if (!memcmp(signature, "OggS", 4)) {
    343             if (*pageOffset > startOffset) {
    344                 ALOGV("skipped %lld bytes of junk to reach next frame",
    345                      (long long)(*pageOffset - startOffset));
    346             }
    347 
    348             return OK;
    349         }
    350 
    351         ++*pageOffset;
    352     }
    353 }
    354 
    355 // Given the offset of the "current" page, find the page immediately preceding
    356 // it (if any) and return its granule position.
    357 // To do this we back up from the "current" page's offset until we find any
    358 // page preceding it and then scan forward to just before the current page.
    359 status_t MyOggExtractor::findPrevGranulePosition(
    360         off64_t pageOffset, uint64_t *granulePos) {
    361     *granulePos = 0;
    362 
    363     off64_t prevPageOffset = 0;
    364     off64_t prevGuess = pageOffset;
    365     for (;;) {
    366         if (prevGuess >= 5000) {
    367             prevGuess -= 5000;
    368         } else {
    369             prevGuess = 0;
    370         }
    371 
    372         ALOGV("backing up %lld bytes", (long long)(pageOffset - prevGuess));
    373 
    374         status_t err = findNextPage(prevGuess, &prevPageOffset);
    375         if (err == ERROR_END_OF_STREAM) {
    376             // We are at the last page and didn't back off enough;
    377             // back off 5000 bytes more and try again.
    378             continue;
    379         } else if (err != OK) {
    380             return err;
    381         }
    382 
    383         if (prevPageOffset < pageOffset || prevGuess == 0) {
    384             break;
    385         }
    386     }
    387 
    388     if (prevPageOffset == pageOffset) {
    389         // We did not find a page preceding this one.
    390         return UNKNOWN_ERROR;
    391     }
    392 
    393     ALOGV("prevPageOffset at %lld, pageOffset at %lld",
    394             (long long)prevPageOffset, (long long)pageOffset);
    395 
    396     for (;;) {
    397         Page prevPage;
    398         ssize_t n = readPage(prevPageOffset, &prevPage);
    399 
    400         if (n <= 0) {
    401             return (status_t)n;
    402         }
    403 
    404         prevPageOffset += n;
    405 
    406         if (prevPageOffset == pageOffset) {
    407             *granulePos = prevPage.mGranulePosition;
    408             return OK;
    409         }
    410     }
    411 }
    412 
    413 status_t MyOggExtractor::seekToTime(int64_t timeUs) {
    414     timeUs -= mSeekPreRollUs;
    415     if (timeUs < 0) {
    416         timeUs = 0;
    417     }
    418 
    419     if (mTableOfContents.isEmpty()) {
    420         // Perform approximate seeking based on avg. bitrate.
    421         uint64_t bps = approxBitrate();
    422         if (bps <= 0) {
    423             return INVALID_OPERATION;
    424         }
    425 
    426         off64_t pos = timeUs * bps / 8000000ll;
    427 
    428         ALOGV("seeking to offset %lld", (long long)pos);
    429         return seekToOffset(pos);
    430     }
    431 
    432     size_t left = 0;
    433     size_t right_plus_one = mTableOfContents.size();
    434     while (left < right_plus_one) {
    435         size_t center = left + (right_plus_one - left) / 2;
    436 
    437         const TOCEntry &entry = mTableOfContents.itemAt(center);
    438 
    439         if (timeUs < entry.mTimeUs) {
    440             right_plus_one = center;
    441         } else if (timeUs > entry.mTimeUs) {
    442             left = center + 1;
    443         } else {
    444             left = center;
    445             break;
    446         }
    447     }
    448 
    449     if (left == mTableOfContents.size()) {
    450         --left;
    451     }
    452 
    453     const TOCEntry &entry = mTableOfContents.itemAt(left);
    454 
    455     ALOGV("seeking to entry %zu / %zu at offset %lld",
    456          left, mTableOfContents.size(), (long long)entry.mPageOffset);
    457 
    458     return seekToOffset(entry.mPageOffset);
    459 }
    460 
    461 status_t MyOggExtractor::seekToOffset(off64_t offset) {
    462     if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) {
    463         // Once we know where the actual audio data starts (past the headers)
    464         // don't ever seek to anywhere before that.
    465         offset = mFirstDataOffset;
    466     }
    467 
    468     off64_t pageOffset;
    469     status_t err = findNextPage(offset, &pageOffset);
    470 
    471     if (err != OK) {
    472         return err;
    473     }
    474 
    475     // We found the page we wanted to seek to, but we'll also need
    476     // the page preceding it to determine how many valid samples are on
    477     // this page.
    478     findPrevGranulePosition(pageOffset, &mPrevGranulePosition);
    479 
    480     mOffset = pageOffset;
    481 
    482     mCurrentPageSize = 0;
    483     mFirstPacketInPage = true;
    484     mCurrentPageSamples = 0;
    485     mCurrentPage.mNumSegments = 0;
    486     mCurrentPage.mPrevPacketSize = -1;
    487     mNextLaceIndex = 0;
    488 
    489     // XXX what if new page continues packet from last???
    490 
    491     return OK;
    492 }
    493 
    494 ssize_t MyOggExtractor::readPage(off64_t offset, Page *page) {
    495     uint8_t header[27];
    496     ssize_t n;
    497     if ((n = mSource->readAt(offset, header, sizeof(header)))
    498             < (ssize_t)sizeof(header)) {
    499         ALOGV("failed to read %zu bytes at offset %#016llx, got %zd bytes",
    500                 sizeof(header), (long long)offset, n);
    501 
    502         if (n < 0) {
    503             return n;
    504         } else if (n == 0) {
    505             return ERROR_END_OF_STREAM;
    506         } else {
    507             return ERROR_IO;
    508         }
    509     }
    510 
    511     if (memcmp(header, "OggS", 4)) {
    512         return ERROR_MALFORMED;
    513     }
    514 
    515     if (header[4] != 0) {
    516         // Wrong version.
    517 
    518         return ERROR_UNSUPPORTED;
    519     }
    520 
    521     page->mFlags = header[5];
    522 
    523     if (page->mFlags & ~7) {
    524         // Only bits 0-2 are defined in version 0.
    525         return ERROR_MALFORMED;
    526     }
    527 
    528     page->mGranulePosition = U64LE_AT(&header[6]);
    529 
    530 #if 0
    531     printf("granulePosition = %llu (0x%llx)\n",
    532            page->mGranulePosition, page->mGranulePosition);
    533 #endif
    534 
    535     page->mSerialNo = U32LE_AT(&header[14]);
    536     page->mPageNo = U32LE_AT(&header[18]);
    537 
    538     page->mNumSegments = header[26];
    539     if (mSource->readAt(
    540                 offset + sizeof(header), page->mLace, page->mNumSegments)
    541             < (ssize_t)page->mNumSegments) {
    542         return ERROR_IO;
    543     }
    544 
    545     size_t totalSize = 0;;
    546     for (size_t i = 0; i < page->mNumSegments; ++i) {
    547         totalSize += page->mLace[i];
    548     }
    549 
    550 #if 0
    551     String8 tmp;
    552     for (size_t i = 0; i < page->mNumSegments; ++i) {
    553         char x[32];
    554         sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]);
    555 
    556         tmp.append(x);
    557     }
    558 
    559     ALOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string());
    560 #endif
    561 
    562     return sizeof(header) + page->mNumSegments + totalSize;
    563 }
    564 
    565 status_t MyOpusExtractor::readNextPacket(MediaBuffer **out) {
    566     if (mOffset <= mFirstDataOffset && mStartGranulePosition < 0) {
    567         // The first sample might not start at time 0; find out where by subtracting
    568         // the number of samples on the first page from the granule position
    569         // (position of last complete sample) of the first page. This happens
    570         // the first time before we attempt to read a packet from the first page.
    571         MediaBuffer *mBuf;
    572         uint32_t numSamples = 0;
    573         uint64_t curGranulePosition = 0;
    574         while (true) {
    575             status_t err = _readNextPacket(&mBuf, /* calcVorbisTimestamp = */false);
    576             if (err != OK && err != ERROR_END_OF_STREAM) {
    577                 return err;
    578             }
    579             // First two pages are header pages.
    580             if (err == ERROR_END_OF_STREAM || mCurrentPage.mPageNo > 2) {
    581                 break;
    582             }
    583             curGranulePosition = mCurrentPage.mGranulePosition;
    584             numSamples += getNumSamplesInPacket(mBuf);
    585             mBuf->release();
    586             mBuf = NULL;
    587         }
    588 
    589         if (curGranulePosition > numSamples) {
    590             mStartGranulePosition = curGranulePosition - numSamples;
    591         } else {
    592             mStartGranulePosition = 0;
    593         }
    594         seekToOffset(0);
    595     }
    596 
    597     status_t err = _readNextPacket(out, /* calcVorbisTimestamp = */false);
    598     if (err != OK) {
    599         return err;
    600     }
    601 
    602     int32_t currentPageSamples;
    603     // Calculate timestamps by accumulating durations starting from the first sample of a page;
    604     // We assume that we only seek to page boundaries.
    605     if ((*out)->meta_data()->findInt32(kKeyValidSamples, &currentPageSamples)) {
    606         // first packet in page
    607         if (mOffset == mFirstDataOffset) {
    608             currentPageSamples -= mStartGranulePosition;
    609             (*out)->meta_data()->setInt32(kKeyValidSamples, currentPageSamples);
    610         }
    611         mCurGranulePosition = mCurrentPage.mGranulePosition - currentPageSamples;
    612     }
    613 
    614     int64_t timeUs = getTimeUsOfGranule(mCurGranulePosition);
    615     (*out)->meta_data()->setInt64(kKeyTime, timeUs);
    616 
    617     uint32_t frames = getNumSamplesInPacket(*out);
    618     mCurGranulePosition += frames;
    619     return OK;
    620 }
    621 
    622 uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBuffer *buffer) const {
    623     if (buffer == NULL || buffer->range_length() < 1) {
    624         return 0;
    625     }
    626 
    627     uint8_t *data = (uint8_t *)buffer->data() + buffer->range_offset();
    628     uint8_t toc = data[0];
    629     uint8_t config = (toc >> 3) & 0x1f;
    630     uint32_t frameSizesUs[] = {
    631         10000, 20000, 40000, 60000, // 0...3
    632         10000, 20000, 40000, 60000, // 4...7
    633         10000, 20000, 40000, 60000, // 8...11
    634         10000, 20000,               // 12...13
    635         10000, 20000,               // 14...15
    636         2500, 5000, 10000, 20000,   // 16...19
    637         2500, 5000, 10000, 20000,   // 20...23
    638         2500, 5000, 10000, 20000,   // 24...27
    639         2500, 5000, 10000, 20000    // 28...31
    640     };
    641     uint32_t frameSizeUs = frameSizesUs[config];
    642 
    643     uint32_t numFrames;
    644     uint8_t c = toc & 3;
    645     switch (c) {
    646     case 0:
    647         numFrames = 1;
    648         break;
    649     case 1:
    650     case 2:
    651         numFrames = 2;
    652         break;
    653     case 3:
    654         if (buffer->range_length() < 3) {
    655             numFrames = 0;
    656         } else {
    657             numFrames = data[2] & 0x3f;
    658         }
    659         break;
    660     default:
    661         TRESPASS();
    662     }
    663 
    664     uint32_t numSamples = frameSizeUs * numFrames * kOpusSampleRate / 1000000;
    665     return numSamples;
    666 }
    667 
    668 status_t MyOggExtractor::_readNextPacket(MediaBuffer **out, bool calcVorbisTimestamp) {
    669     *out = NULL;
    670 
    671     MediaBuffer *buffer = NULL;
    672     int64_t timeUs = -1;
    673 
    674     for (;;) {
    675         size_t i;
    676         size_t packetSize = 0;
    677         bool gotFullPacket = false;
    678         for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) {
    679             uint8_t lace = mCurrentPage.mLace[i];
    680 
    681             packetSize += lace;
    682 
    683             if (lace < 255) {
    684                 gotFullPacket = true;
    685                 ++i;
    686                 break;
    687             }
    688         }
    689 
    690         if (mNextLaceIndex < mCurrentPage.mNumSegments) {
    691             off64_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments;
    692             for (size_t j = 0; j < mNextLaceIndex; ++j) {
    693                 dataOffset += mCurrentPage.mLace[j];
    694             }
    695 
    696             size_t fullSize = packetSize;
    697             if (buffer != NULL) {
    698                 fullSize += buffer->range_length();
    699             }
    700             MediaBuffer *tmp = new MediaBuffer(fullSize);
    701             if (buffer != NULL) {
    702                 memcpy(tmp->data(), buffer->data(), buffer->range_length());
    703                 tmp->set_range(0, buffer->range_length());
    704                 buffer->release();
    705             } else {
    706                 tmp->set_range(0, 0);
    707             }
    708             buffer = tmp;
    709 
    710             ssize_t n = mSource->readAt(
    711                     dataOffset,
    712                     (uint8_t *)buffer->data() + buffer->range_length(),
    713                     packetSize);
    714 
    715             if (n < (ssize_t)packetSize) {
    716                 buffer->release();
    717                 ALOGV("failed to read %zu bytes at %#016llx, got %zd bytes",
    718                         packetSize, (long long)dataOffset, n);
    719                 return ERROR_IO;
    720             }
    721 
    722             buffer->set_range(0, fullSize);
    723 
    724             mNextLaceIndex = i;
    725 
    726             if (gotFullPacket) {
    727                 // We've just read the entire packet.
    728 
    729                 if (mFirstPacketInPage) {
    730                     buffer->meta_data()->setInt32(
    731                             kKeyValidSamples, mCurrentPageSamples);
    732                     mFirstPacketInPage = false;
    733                 }
    734 
    735                 if (calcVorbisTimestamp) {
    736                     int32_t curBlockSize = getPacketBlockSize(buffer);
    737                     if (mCurrentPage.mPrevPacketSize < 0) {
    738                         mCurrentPage.mPrevPacketSize = curBlockSize;
    739                         mCurrentPage.mPrevPacketPos =
    740                                 mCurrentPage.mGranulePosition - mCurrentPageSamples;
    741                         timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
    742                     } else {
    743                         // The effective block size is the average of the two overlapped blocks
    744                         int32_t actualBlockSize =
    745                                 (curBlockSize + mCurrentPage.mPrevPacketSize) / 2;
    746                         timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
    747                         // The actual size output by the decoder will be half the effective
    748                         // size, due to the overlap
    749                         mCurrentPage.mPrevPacketPos += actualBlockSize / 2;
    750                         mCurrentPage.mPrevPacketSize = curBlockSize;
    751                     }
    752                     buffer->meta_data()->setInt64(kKeyTime, timeUs);
    753                 }
    754                 *out = buffer;
    755 
    756                 return OK;
    757             }
    758 
    759             // fall through, the buffer now contains the start of the packet.
    760         }
    761 
    762         CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments);
    763 
    764         mOffset += mCurrentPageSize;
    765         ssize_t n = readPage(mOffset, &mCurrentPage);
    766 
    767         if (n <= 0) {
    768             if (buffer) {
    769                 buffer->release();
    770                 buffer = NULL;
    771             }
    772 
    773             ALOGV("readPage returned %zd", n);
    774 
    775             return n < 0 ? n : (status_t)ERROR_END_OF_STREAM;
    776         }
    777 
    778         // Prevent a harmless unsigned integer overflow by clamping to 0
    779         if (mCurrentPage.mGranulePosition >= mPrevGranulePosition) {
    780             mCurrentPageSamples =
    781                     mCurrentPage.mGranulePosition - mPrevGranulePosition;
    782         } else {
    783             mCurrentPageSamples = 0;
    784         }
    785         mFirstPacketInPage = true;
    786 
    787         mPrevGranulePosition = mCurrentPage.mGranulePosition;
    788 
    789         mCurrentPageSize = n;
    790         mNextLaceIndex = 0;
    791 
    792         if (buffer != NULL) {
    793             if ((mCurrentPage.mFlags & 1) == 0) {
    794                 // This page does not continue the packet, i.e. the packet
    795                 // is already complete.
    796 
    797                 if (timeUs >= 0) {
    798                     buffer->meta_data()->setInt64(kKeyTime, timeUs);
    799                 }
    800 
    801                 buffer->meta_data()->setInt32(
    802                         kKeyValidSamples, mCurrentPageSamples);
    803                 mFirstPacketInPage = false;
    804 
    805                 *out = buffer;
    806 
    807                 return OK;
    808             }
    809         }
    810     }
    811 }
    812 
    813 status_t MyOggExtractor::init() {
    814     mMeta = new MetaData;
    815     mMeta->setCString(kKeyMIMEType, mMimeType);
    816 
    817     status_t err;
    818     MediaBuffer *packet;
    819     for (size_t i = 0; i < mNumHeaders; ++i) {
    820         // ignore timestamp for configuration packets
    821         if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != OK) {
    822             return err;
    823         }
    824         ALOGV("read packet of size %zu\n", packet->range_length());
    825         err = verifyHeader(packet, /* type = */ i * 2 + 1);
    826         packet->release();
    827         packet = NULL;
    828         if (err != OK) {
    829             return err;
    830         }
    831     }
    832 
    833     mFirstDataOffset = mOffset + mCurrentPageSize;
    834 
    835     off64_t size;
    836     uint64_t lastGranulePosition;
    837     if (!(mSource->flags() & DataSource::kIsCachingDataSource)
    838             && mSource->getSize(&size) == OK
    839             && findPrevGranulePosition(size, &lastGranulePosition) == OK) {
    840         // Let's assume it's cheap to seek to the end.
    841         // The granule position of the final page in the stream will
    842         // give us the exact duration of the content, something that
    843         // we can only approximate using avg. bitrate if seeking to
    844         // the end is too expensive or impossible (live streaming).
    845 
    846         int64_t durationUs = getTimeUsOfGranule(lastGranulePosition);
    847 
    848         mMeta->setInt64(kKeyDuration, durationUs);
    849 
    850         buildTableOfContents();
    851     }
    852 
    853     return OK;
    854 }
    855 
    856 void MyOggExtractor::buildTableOfContents() {
    857     off64_t offset = mFirstDataOffset;
    858     Page page;
    859     ssize_t pageSize;
    860     while ((pageSize = readPage(offset, &page)) > 0) {
    861         mTableOfContents.push();
    862 
    863         TOCEntry &entry =
    864             mTableOfContents.editItemAt(mTableOfContents.size() - 1);
    865 
    866         entry.mPageOffset = offset;
    867         entry.mTimeUs = getTimeUsOfGranule(page.mGranulePosition);
    868 
    869         offset += (size_t)pageSize;
    870     }
    871 
    872     // Limit the maximum amount of RAM we spend on the table of contents,
    873     // if necessary thin out the table evenly to trim it down to maximum
    874     // size.
    875 
    876     static const size_t kMaxTOCSize = 8192;
    877     static const size_t kMaxNumTOCEntries = kMaxTOCSize / sizeof(TOCEntry);
    878 
    879     size_t numerator = mTableOfContents.size();
    880 
    881     if (numerator > kMaxNumTOCEntries) {
    882         size_t denom = numerator - kMaxNumTOCEntries;
    883 
    884         size_t accum = 0;
    885         for (ssize_t i = mTableOfContents.size() - 1; i >= 0; --i) {
    886             accum += denom;
    887             if (accum >= numerator) {
    888                 mTableOfContents.removeAt(i);
    889                 accum -= numerator;
    890             }
    891         }
    892     }
    893 }
    894 
    895 int32_t MyOggExtractor::getPacketBlockSize(MediaBuffer *buffer) {
    896     const uint8_t *data =
    897         (const uint8_t *)buffer->data() + buffer->range_offset();
    898 
    899     size_t size = buffer->range_length();
    900 
    901     ogg_buffer buf;
    902     buf.data = (uint8_t *)data;
    903     buf.size = size;
    904     buf.refcount = 1;
    905     buf.ptr.owner = NULL;
    906 
    907     ogg_reference ref;
    908     ref.buffer = &buf;
    909     ref.begin = 0;
    910     ref.length = size;
    911     ref.next = NULL;
    912 
    913     ogg_packet pack;
    914     pack.packet = &ref;
    915     pack.bytes = ref.length;
    916     pack.b_o_s = 0;
    917     pack.e_o_s = 0;
    918     pack.granulepos = 0;
    919     pack.packetno = 0;
    920 
    921     return vorbis_packet_blocksize(&mVi, &pack);
    922 }
    923 
    924 int64_t MyOpusExtractor::getTimeUsOfGranule(uint64_t granulePos) const {
    925     uint64_t pcmSamplePosition = 0;
    926     if (granulePos > mCodecDelay) {
    927         pcmSamplePosition = granulePos - mCodecDelay;
    928     }
    929     if (pcmSamplePosition > INT64_MAX / 1000000ll) {
    930         return INT64_MAX;
    931     }
    932     return pcmSamplePosition * 1000000ll / kOpusSampleRate;
    933 }
    934 
    935 status_t MyOpusExtractor::verifyHeader(MediaBuffer *buffer, uint8_t type) {
    936     switch (type) {
    937         // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean
    938         // header and comments such that we can share code with MyVorbisExtractor.
    939         case 1:
    940             return verifyOpusHeader(buffer);
    941         case 3:
    942             return verifyOpusComments(buffer);
    943         default:
    944             return INVALID_OPERATION;
    945     }
    946 }
    947 
    948 status_t MyOpusExtractor::verifyOpusHeader(MediaBuffer *buffer) {
    949     const size_t kOpusHeaderSize = 19;
    950     const uint8_t *data =
    951         (const uint8_t *)buffer->data() + buffer->range_offset();
    952 
    953     size_t size = buffer->range_length();
    954 
    955     if (size < kOpusHeaderSize
    956             || memcmp(data, "OpusHead", 8)
    957             || /* version = */ data[8] != 1) {
    958         return ERROR_MALFORMED;
    959     }
    960 
    961     mChannelCount = data[9];
    962     mCodecDelay = U16LE_AT(&data[10]);
    963 
    964     mMeta->setData(kKeyOpusHeader, 0, data, size);
    965     mMeta->setInt32(kKeySampleRate, kOpusSampleRate);
    966     mMeta->setInt32(kKeyChannelCount, mChannelCount);
    967     mMeta->setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/);
    968     mMeta->setInt64(kKeyOpusCodecDelay /* ns */,
    969             mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate);
    970 
    971     return OK;
    972 }
    973 
    974 status_t MyOpusExtractor::verifyOpusComments(MediaBuffer *buffer) {
    975     // add artificial framing bit so we can reuse _vorbis_unpack_comment
    976     int32_t commentSize = buffer->range_length() + 1;
    977     sp<ABuffer> aBuf = new ABuffer(commentSize);
    978     if (aBuf->capacity() <= buffer->range_length()) {
    979         return ERROR_MALFORMED;
    980     }
    981 
    982     uint8_t* commentData = aBuf->data();
    983     memcpy(commentData,
    984             (uint8_t *)buffer->data() + buffer->range_offset(),
    985             buffer->range_length());
    986 
    987     ogg_buffer buf;
    988     buf.data = commentData;
    989     buf.size = commentSize;
    990     buf.refcount = 1;
    991     buf.ptr.owner = NULL;
    992 
    993     ogg_reference ref;
    994     ref.buffer = &buf;
    995     ref.begin = 0;
    996     ref.length = commentSize;
    997     ref.next = NULL;
    998 
    999     oggpack_buffer bits;
   1000     oggpack_readinit(&bits, &ref);
   1001 
   1002     // skip 'OpusTags'
   1003     const char *OpusTags = "OpusTags";
   1004     const int32_t headerLen = strlen(OpusTags);
   1005     int32_t framingBitOffset = headerLen;
   1006     for (int i = 0; i < headerLen; ++i) {
   1007         char chr = oggpack_read(&bits, 8);
   1008         if (chr != OpusTags[i]) {
   1009             return ERROR_MALFORMED;
   1010         }
   1011     }
   1012 
   1013     int32_t vendorLen = oggpack_read(&bits, 32);
   1014     framingBitOffset += 4;
   1015     if (vendorLen < 0 || vendorLen > commentSize - 8) {
   1016         return ERROR_MALFORMED;
   1017     }
   1018     // skip vendor string
   1019     framingBitOffset += vendorLen;
   1020     for (int i = 0; i < vendorLen; ++i) {
   1021         oggpack_read(&bits, 8);
   1022     }
   1023 
   1024     int32_t n = oggpack_read(&bits, 32);
   1025     framingBitOffset += 4;
   1026     if (n < 0 || n > ((commentSize - oggpack_bytes(&bits)) >> 2)) {
   1027         return ERROR_MALFORMED;
   1028     }
   1029     for (int i = 0; i < n; ++i) {
   1030         int32_t len = oggpack_read(&bits, 32);
   1031         framingBitOffset += 4;
   1032         if (len  < 0 || len  > (commentSize - oggpack_bytes(&bits))) {
   1033             return ERROR_MALFORMED;
   1034         }
   1035         framingBitOffset += len;
   1036         for (int j = 0; j < len; ++j) {
   1037             oggpack_read(&bits, 8);
   1038         }
   1039     }
   1040     if (framingBitOffset < 0 || framingBitOffset >= commentSize) {
   1041         return ERROR_MALFORMED;
   1042     }
   1043     commentData[framingBitOffset] = 1;
   1044 
   1045     buf.data = commentData + headerLen;
   1046     buf.size = commentSize - headerLen;
   1047     buf.refcount = 1;
   1048     buf.ptr.owner = NULL;
   1049 
   1050     ref.buffer = &buf;
   1051     ref.begin = 0;
   1052     ref.length = commentSize - headerLen;
   1053     ref.next = NULL;
   1054 
   1055     oggpack_readinit(&bits, &ref);
   1056     int err = _vorbis_unpack_comment(&mVc, &bits);
   1057     if (0 != err) {
   1058         return ERROR_MALFORMED;
   1059     }
   1060 
   1061     parseFileMetaData();
   1062     return OK;
   1063 }
   1064 
   1065 status_t MyVorbisExtractor::verifyHeader(
   1066         MediaBuffer *buffer, uint8_t type) {
   1067     const uint8_t *data =
   1068         (const uint8_t *)buffer->data() + buffer->range_offset();
   1069 
   1070     size_t size = buffer->range_length();
   1071 
   1072     if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) {
   1073         return ERROR_MALFORMED;
   1074     }
   1075 
   1076     ogg_buffer buf;
   1077     buf.data = (uint8_t *)data;
   1078     buf.size = size;
   1079     buf.refcount = 1;
   1080     buf.ptr.owner = NULL;
   1081 
   1082     ogg_reference ref;
   1083     ref.buffer = &buf;
   1084     ref.begin = 0;
   1085     ref.length = size;
   1086     ref.next = NULL;
   1087 
   1088     oggpack_buffer bits;
   1089     oggpack_readinit(&bits, &ref);
   1090 
   1091     if (oggpack_read(&bits, 8) != type) {
   1092         return ERROR_MALFORMED;
   1093     }
   1094     for (size_t i = 0; i < 6; ++i) {
   1095         oggpack_read(&bits, 8);  // skip 'vorbis'
   1096     }
   1097 
   1098     switch (type) {
   1099         case 1:
   1100         {
   1101             if (0 != _vorbis_unpack_info(&mVi, &bits)) {
   1102                 return ERROR_MALFORMED;
   1103             }
   1104 
   1105             mMeta->setData(kKeyVorbisInfo, 0, data, size);
   1106             mMeta->setInt32(kKeySampleRate, mVi.rate);
   1107             mMeta->setInt32(kKeyChannelCount, mVi.channels);
   1108 
   1109             ALOGV("lower-bitrate = %ld", mVi.bitrate_lower);
   1110             ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
   1111             ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
   1112             ALOGV("window-bitrate = %ld", mVi.bitrate_window);
   1113             ALOGV("blocksizes: %d/%d",
   1114                     vorbis_info_blocksize(&mVi, 0),
   1115                     vorbis_info_blocksize(&mVi, 1)
   1116                     );
   1117 
   1118             off64_t size;
   1119             if (mSource->getSize(&size) == OK) {
   1120                 uint64_t bps = approxBitrate();
   1121                 if (bps != 0) {
   1122                     mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
   1123                 }
   1124             }
   1125             break;
   1126         }
   1127 
   1128         case 3:
   1129         {
   1130             if (0 != _vorbis_unpack_comment(&mVc, &bits)) {
   1131                 return ERROR_MALFORMED;
   1132             }
   1133 
   1134             parseFileMetaData();
   1135             break;
   1136         }
   1137 
   1138         case 5:
   1139         {
   1140             if (0 != _vorbis_unpack_books(&mVi, &bits)) {
   1141                 return ERROR_MALFORMED;
   1142             }
   1143 
   1144             mMeta->setData(kKeyVorbisBooks, 0, data, size);
   1145             break;
   1146         }
   1147     }
   1148 
   1149     return OK;
   1150 }
   1151 
   1152 uint64_t MyVorbisExtractor::approxBitrate() const {
   1153     if (mVi.bitrate_nominal != 0) {
   1154         return mVi.bitrate_nominal;
   1155     }
   1156 
   1157     return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
   1158 }
   1159 
   1160 void MyOggExtractor::parseFileMetaData() {
   1161     mFileMeta = new MetaData;
   1162     mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
   1163 
   1164     for (int i = 0; i < mVc.comments; ++i) {
   1165         const char *comment = mVc.user_comments[i];
   1166         size_t commentLength = mVc.comment_lengths[i];
   1167         parseVorbisComment(mFileMeta, comment, commentLength);
   1168         //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
   1169     }
   1170 }
   1171 
   1172 void parseVorbisComment(
   1173         const sp<MetaData> &fileMeta, const char *comment, size_t commentLength)
   1174 {
   1175     struct {
   1176         const char *const mTag;
   1177         uint32_t mKey;
   1178     } kMap[] = {
   1179         { "TITLE", kKeyTitle },
   1180         { "ARTIST", kKeyArtist },
   1181         { "ALBUMARTIST", kKeyAlbumArtist },
   1182         { "ALBUM ARTIST", kKeyAlbumArtist },
   1183         { "COMPILATION", kKeyCompilation },
   1184         { "ALBUM", kKeyAlbum },
   1185         { "COMPOSER", kKeyComposer },
   1186         { "GENRE", kKeyGenre },
   1187         { "AUTHOR", kKeyAuthor },
   1188         { "TRACKNUMBER", kKeyCDTrackNumber },
   1189         { "DISCNUMBER", kKeyDiscNumber },
   1190         { "DATE", kKeyDate },
   1191         { "YEAR", kKeyYear },
   1192         { "LYRICIST", kKeyWriter },
   1193         { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
   1194         { "ANDROID_LOOP", kKeyAutoLoop },
   1195     };
   1196 
   1197         for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
   1198             size_t tagLen = strlen(kMap[j].mTag);
   1199             if (!strncasecmp(kMap[j].mTag, comment, tagLen)
   1200                     && comment[tagLen] == '=') {
   1201                 if (kMap[j].mKey == kKeyAlbumArt) {
   1202                     extractAlbumArt(
   1203                             fileMeta,
   1204                             &comment[tagLen + 1],
   1205                             commentLength - tagLen - 1);
   1206                 } else if (kMap[j].mKey == kKeyAutoLoop) {
   1207                     if (!strcasecmp(&comment[tagLen + 1], "true")) {
   1208                         fileMeta->setInt32(kKeyAutoLoop, true);
   1209                     }
   1210                 } else {
   1211                     fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
   1212                 }
   1213             }
   1214         }
   1215 
   1216 }
   1217 
   1218 static void extractAlbumArt(
   1219         const sp<MetaData> &fileMeta, const void *data, size_t size) {
   1220     ALOGV("extractAlbumArt from '%s'", (const char *)data);
   1221 
   1222     sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size));
   1223     if (flacBuffer == NULL) {
   1224         ALOGE("malformed base64 encoded data.");
   1225         return;
   1226     }
   1227 
   1228     size_t flacSize = flacBuffer->size();
   1229     uint8_t *flac = flacBuffer->data();
   1230     ALOGV("got flac of size %zu", flacSize);
   1231 
   1232     uint32_t picType;
   1233     uint32_t typeLen;
   1234     uint32_t descLen;
   1235     uint32_t dataLen;
   1236     char type[128];
   1237 
   1238     if (flacSize < 8) {
   1239         return;
   1240     }
   1241 
   1242     picType = U32_AT(flac);
   1243 
   1244     if (picType != 3) {
   1245         // This is not a front cover.
   1246         return;
   1247     }
   1248 
   1249     typeLen = U32_AT(&flac[4]);
   1250     if (typeLen > sizeof(type) - 1) {
   1251         return;
   1252     }
   1253 
   1254     // we've already checked above that flacSize >= 8
   1255     if (flacSize - 8 < typeLen) {
   1256         return;
   1257     }
   1258 
   1259     memcpy(type, &flac[8], typeLen);
   1260     type[typeLen] = '\0';
   1261 
   1262     ALOGV("picType = %d, type = '%s'", picType, type);
   1263 
   1264     if (!strcmp(type, "-->")) {
   1265         // This is not inline cover art, but an external url instead.
   1266         return;
   1267     }
   1268 
   1269     if (flacSize < 32 || flacSize - 32 < typeLen) {
   1270         return;
   1271     }
   1272 
   1273     descLen = U32_AT(&flac[8 + typeLen]);
   1274     if (flacSize - 32 - typeLen < descLen) {
   1275         return;
   1276     }
   1277 
   1278     dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
   1279 
   1280     // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
   1281     if (flacSize - 32 - typeLen - descLen < dataLen) {
   1282         return;
   1283     }
   1284 
   1285     ALOGV("got image data, %zu trailing bytes",
   1286          flacSize - 32 - typeLen - descLen - dataLen);
   1287 
   1288     fileMeta->setData(
   1289             kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
   1290 
   1291     fileMeta->setCString(kKeyAlbumArtMIME, type);
   1292 }
   1293 
   1294 ////////////////////////////////////////////////////////////////////////////////
   1295 
   1296 OggExtractor::OggExtractor(const sp<DataSource> &source)
   1297     : mDataSource(source),
   1298       mInitCheck(NO_INIT),
   1299       mImpl(NULL) {
   1300     for (int i = 0; i < 2; ++i) {
   1301         if (mImpl != NULL) {
   1302             delete mImpl;
   1303         }
   1304         if (i == 0) {
   1305             mImpl = new MyVorbisExtractor(mDataSource);
   1306         } else {
   1307             mImpl = new MyOpusExtractor(mDataSource);
   1308         }
   1309         mInitCheck = mImpl->seekToOffset(0);
   1310 
   1311         if (mInitCheck == OK) {
   1312             mInitCheck = mImpl->init();
   1313             if (mInitCheck == OK) {
   1314                 break;
   1315             }
   1316         }
   1317     }
   1318 }
   1319 
   1320 OggExtractor::~OggExtractor() {
   1321     delete mImpl;
   1322     mImpl = NULL;
   1323 }
   1324 
   1325 size_t OggExtractor::countTracks() {
   1326     return mInitCheck != OK ? 0 : 1;
   1327 }
   1328 
   1329 sp<IMediaSource> OggExtractor::getTrack(size_t index) {
   1330     if (index >= 1) {
   1331         return NULL;
   1332     }
   1333 
   1334     return new OggSource(this);
   1335 }
   1336 
   1337 sp<MetaData> OggExtractor::getTrackMetaData(
   1338         size_t index, uint32_t /* flags */) {
   1339     if (index >= 1) {
   1340         return NULL;
   1341     }
   1342 
   1343     return mImpl->getFormat();
   1344 }
   1345 
   1346 sp<MetaData> OggExtractor::getMetaData() {
   1347     return mImpl->getFileMetaData();
   1348 }
   1349 
   1350 bool SniffOgg(
   1351         const sp<DataSource> &source, String8 *mimeType, float *confidence,
   1352         sp<AMessage> *) {
   1353     char tmp[4];
   1354     if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
   1355         return false;
   1356     }
   1357 
   1358     mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG);
   1359     *confidence = 0.2f;
   1360 
   1361     return true;
   1362 }
   1363 
   1364 }  // namespace android
   1365