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     explicit 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     explicit 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     explicit 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                 if (mBuf != NULL) {
    582                     mBuf->release();
    583                     mBuf = NULL;
    584                 }
    585                 break;
    586             }
    587             curGranulePosition = mCurrentPage.mGranulePosition;
    588             numSamples += getNumSamplesInPacket(mBuf);
    589             mBuf->release();
    590             mBuf = NULL;
    591         }
    592 
    593         if (curGranulePosition > numSamples) {
    594             mStartGranulePosition = curGranulePosition - numSamples;
    595         } else {
    596             mStartGranulePosition = 0;
    597         }
    598         seekToOffset(0);
    599     }
    600 
    601     status_t err = _readNextPacket(out, /* calcVorbisTimestamp = */false);
    602     if (err != OK) {
    603         return err;
    604     }
    605 
    606     int32_t currentPageSamples;
    607     // Calculate timestamps by accumulating durations starting from the first sample of a page;
    608     // We assume that we only seek to page boundaries.
    609     if ((*out)->meta_data()->findInt32(kKeyValidSamples, &currentPageSamples)) {
    610         // first packet in page
    611         if (mOffset == mFirstDataOffset) {
    612             currentPageSamples -= mStartGranulePosition;
    613             (*out)->meta_data()->setInt32(kKeyValidSamples, currentPageSamples);
    614         }
    615         mCurGranulePosition = mCurrentPage.mGranulePosition - currentPageSamples;
    616     }
    617 
    618     int64_t timeUs = getTimeUsOfGranule(mCurGranulePosition);
    619     (*out)->meta_data()->setInt64(kKeyTime, timeUs);
    620 
    621     uint32_t frames = getNumSamplesInPacket(*out);
    622     mCurGranulePosition += frames;
    623     return OK;
    624 }
    625 
    626 uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBuffer *buffer) const {
    627     if (buffer == NULL || buffer->range_length() < 1) {
    628         return 0;
    629     }
    630 
    631     uint8_t *data = (uint8_t *)buffer->data() + buffer->range_offset();
    632     uint8_t toc = data[0];
    633     uint8_t config = (toc >> 3) & 0x1f;
    634     uint32_t frameSizesUs[] = {
    635         10000, 20000, 40000, 60000, // 0...3
    636         10000, 20000, 40000, 60000, // 4...7
    637         10000, 20000, 40000, 60000, // 8...11
    638         10000, 20000,               // 12...13
    639         10000, 20000,               // 14...15
    640         2500, 5000, 10000, 20000,   // 16...19
    641         2500, 5000, 10000, 20000,   // 20...23
    642         2500, 5000, 10000, 20000,   // 24...27
    643         2500, 5000, 10000, 20000    // 28...31
    644     };
    645     uint32_t frameSizeUs = frameSizesUs[config];
    646 
    647     uint32_t numFrames;
    648     uint8_t c = toc & 3;
    649     switch (c) {
    650     case 0:
    651         numFrames = 1;
    652         break;
    653     case 1:
    654     case 2:
    655         numFrames = 2;
    656         break;
    657     case 3:
    658         if (buffer->range_length() < 3) {
    659             numFrames = 0;
    660         } else {
    661             numFrames = data[2] & 0x3f;
    662         }
    663         break;
    664     default:
    665         TRESPASS();
    666     }
    667 
    668     uint32_t numSamples = frameSizeUs * numFrames * kOpusSampleRate / 1000000;
    669     return numSamples;
    670 }
    671 
    672 status_t MyOggExtractor::_readNextPacket(MediaBuffer **out, bool calcVorbisTimestamp) {
    673     *out = NULL;
    674 
    675     MediaBuffer *buffer = NULL;
    676     int64_t timeUs = -1;
    677 
    678     for (;;) {
    679         size_t i;
    680         size_t packetSize = 0;
    681         bool gotFullPacket = false;
    682         for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) {
    683             uint8_t lace = mCurrentPage.mLace[i];
    684 
    685             packetSize += lace;
    686 
    687             if (lace < 255) {
    688                 gotFullPacket = true;
    689                 ++i;
    690                 break;
    691             }
    692         }
    693 
    694         if (mNextLaceIndex < mCurrentPage.mNumSegments) {
    695             off64_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments;
    696             for (size_t j = 0; j < mNextLaceIndex; ++j) {
    697                 dataOffset += mCurrentPage.mLace[j];
    698             }
    699 
    700             size_t fullSize = packetSize;
    701             if (buffer != NULL) {
    702                 fullSize += buffer->range_length();
    703             }
    704             if (fullSize > 16 * 1024 * 1024) { // arbitrary limit of 16 MB packet size
    705                 if (buffer != NULL) {
    706                     buffer->release();
    707                 }
    708                 ALOGE("b/36592202");
    709                 return ERROR_MALFORMED;
    710             }
    711             MediaBuffer *tmp = new (std::nothrow) MediaBuffer(fullSize);
    712             if (tmp == NULL) {
    713                 if (buffer != NULL) {
    714                     buffer->release();
    715                 }
    716                 ALOGE("b/36592202");
    717                 return ERROR_MALFORMED;
    718             }
    719             if (buffer != NULL) {
    720                 memcpy(tmp->data(), buffer->data(), buffer->range_length());
    721                 tmp->set_range(0, buffer->range_length());
    722                 buffer->release();
    723             } else {
    724                 tmp->set_range(0, 0);
    725             }
    726             buffer = tmp;
    727 
    728             ssize_t n = mSource->readAt(
    729                     dataOffset,
    730                     (uint8_t *)buffer->data() + buffer->range_length(),
    731                     packetSize);
    732 
    733             if (n < (ssize_t)packetSize) {
    734                 buffer->release();
    735                 ALOGV("failed to read %zu bytes at %#016llx, got %zd bytes",
    736                         packetSize, (long long)dataOffset, n);
    737                 return ERROR_IO;
    738             }
    739 
    740             buffer->set_range(0, fullSize);
    741 
    742             mNextLaceIndex = i;
    743 
    744             if (gotFullPacket) {
    745                 // We've just read the entire packet.
    746 
    747                 if (mFirstPacketInPage) {
    748                     buffer->meta_data()->setInt32(
    749                             kKeyValidSamples, mCurrentPageSamples);
    750                     mFirstPacketInPage = false;
    751                 }
    752 
    753                 if (calcVorbisTimestamp) {
    754                     int32_t curBlockSize = getPacketBlockSize(buffer);
    755                     if (mCurrentPage.mPrevPacketSize < 0) {
    756                         mCurrentPage.mPrevPacketSize = curBlockSize;
    757                         mCurrentPage.mPrevPacketPos =
    758                                 mCurrentPage.mGranulePosition - mCurrentPageSamples;
    759                         timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
    760                     } else {
    761                         // The effective block size is the average of the two overlapped blocks
    762                         int32_t actualBlockSize =
    763                                 (curBlockSize + mCurrentPage.mPrevPacketSize) / 2;
    764                         timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
    765                         // The actual size output by the decoder will be half the effective
    766                         // size, due to the overlap
    767                         mCurrentPage.mPrevPacketPos += actualBlockSize / 2;
    768                         mCurrentPage.mPrevPacketSize = curBlockSize;
    769                     }
    770                     buffer->meta_data()->setInt64(kKeyTime, timeUs);
    771                 }
    772                 *out = buffer;
    773 
    774                 return OK;
    775             }
    776 
    777             // fall through, the buffer now contains the start of the packet.
    778         }
    779 
    780         CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments);
    781 
    782         mOffset += mCurrentPageSize;
    783         ssize_t n = readPage(mOffset, &mCurrentPage);
    784 
    785         if (n <= 0) {
    786             if (buffer) {
    787                 buffer->release();
    788                 buffer = NULL;
    789             }
    790 
    791             ALOGV("readPage returned %zd", n);
    792 
    793             return n < 0 ? n : (status_t)ERROR_END_OF_STREAM;
    794         }
    795 
    796         // Prevent a harmless unsigned integer overflow by clamping to 0
    797         if (mCurrentPage.mGranulePosition >= mPrevGranulePosition) {
    798             mCurrentPageSamples =
    799                     mCurrentPage.mGranulePosition - mPrevGranulePosition;
    800         } else {
    801             mCurrentPageSamples = 0;
    802         }
    803         mFirstPacketInPage = true;
    804 
    805         mPrevGranulePosition = mCurrentPage.mGranulePosition;
    806 
    807         mCurrentPageSize = n;
    808         mNextLaceIndex = 0;
    809 
    810         if (buffer != NULL) {
    811             if ((mCurrentPage.mFlags & 1) == 0) {
    812                 // This page does not continue the packet, i.e. the packet
    813                 // is already complete.
    814 
    815                 if (timeUs >= 0) {
    816                     buffer->meta_data()->setInt64(kKeyTime, timeUs);
    817                 }
    818 
    819                 buffer->meta_data()->setInt32(
    820                         kKeyValidSamples, mCurrentPageSamples);
    821                 mFirstPacketInPage = false;
    822 
    823                 *out = buffer;
    824 
    825                 return OK;
    826             }
    827         }
    828     }
    829 }
    830 
    831 status_t MyOggExtractor::init() {
    832     mMeta = new MetaData;
    833     mMeta->setCString(kKeyMIMEType, mMimeType);
    834 
    835     status_t err;
    836     MediaBuffer *packet;
    837     for (size_t i = 0; i < mNumHeaders; ++i) {
    838         // ignore timestamp for configuration packets
    839         if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != OK) {
    840             return err;
    841         }
    842         ALOGV("read packet of size %zu\n", packet->range_length());
    843         err = verifyHeader(packet, /* type = */ i * 2 + 1);
    844         packet->release();
    845         packet = NULL;
    846         if (err != OK) {
    847             return err;
    848         }
    849     }
    850 
    851     mFirstDataOffset = mOffset + mCurrentPageSize;
    852 
    853     off64_t size;
    854     uint64_t lastGranulePosition;
    855     if (!(mSource->flags() & DataSource::kIsCachingDataSource)
    856             && mSource->getSize(&size) == OK
    857             && findPrevGranulePosition(size, &lastGranulePosition) == OK) {
    858         // Let's assume it's cheap to seek to the end.
    859         // The granule position of the final page in the stream will
    860         // give us the exact duration of the content, something that
    861         // we can only approximate using avg. bitrate if seeking to
    862         // the end is too expensive or impossible (live streaming).
    863 
    864         int64_t durationUs = getTimeUsOfGranule(lastGranulePosition);
    865 
    866         mMeta->setInt64(kKeyDuration, durationUs);
    867 
    868         buildTableOfContents();
    869     }
    870 
    871     return OK;
    872 }
    873 
    874 void MyOggExtractor::buildTableOfContents() {
    875     off64_t offset = mFirstDataOffset;
    876     Page page;
    877     ssize_t pageSize;
    878     while ((pageSize = readPage(offset, &page)) > 0) {
    879         mTableOfContents.push();
    880 
    881         TOCEntry &entry =
    882             mTableOfContents.editItemAt(mTableOfContents.size() - 1);
    883 
    884         entry.mPageOffset = offset;
    885         entry.mTimeUs = getTimeUsOfGranule(page.mGranulePosition);
    886 
    887         offset += (size_t)pageSize;
    888     }
    889 
    890     // Limit the maximum amount of RAM we spend on the table of contents,
    891     // if necessary thin out the table evenly to trim it down to maximum
    892     // size.
    893 
    894     static const size_t kMaxTOCSize = 8192;
    895     static const size_t kMaxNumTOCEntries = kMaxTOCSize / sizeof(TOCEntry);
    896 
    897     size_t numerator = mTableOfContents.size();
    898 
    899     if (numerator > kMaxNumTOCEntries) {
    900         size_t denom = numerator - kMaxNumTOCEntries;
    901 
    902         size_t accum = 0;
    903         for (ssize_t i = mTableOfContents.size() - 1; i >= 0; --i) {
    904             accum += denom;
    905             if (accum >= numerator) {
    906                 mTableOfContents.removeAt(i);
    907                 accum -= numerator;
    908             }
    909         }
    910     }
    911 }
    912 
    913 int32_t MyOggExtractor::getPacketBlockSize(MediaBuffer *buffer) {
    914     const uint8_t *data =
    915         (const uint8_t *)buffer->data() + buffer->range_offset();
    916 
    917     size_t size = buffer->range_length();
    918 
    919     ogg_buffer buf;
    920     buf.data = (uint8_t *)data;
    921     buf.size = size;
    922     buf.refcount = 1;
    923     buf.ptr.owner = NULL;
    924 
    925     ogg_reference ref;
    926     ref.buffer = &buf;
    927     ref.begin = 0;
    928     ref.length = size;
    929     ref.next = NULL;
    930 
    931     ogg_packet pack;
    932     pack.packet = &ref;
    933     pack.bytes = ref.length;
    934     pack.b_o_s = 0;
    935     pack.e_o_s = 0;
    936     pack.granulepos = 0;
    937     pack.packetno = 0;
    938 
    939     return vorbis_packet_blocksize(&mVi, &pack);
    940 }
    941 
    942 int64_t MyOpusExtractor::getTimeUsOfGranule(uint64_t granulePos) const {
    943     uint64_t pcmSamplePosition = 0;
    944     if (granulePos > mCodecDelay) {
    945         pcmSamplePosition = granulePos - mCodecDelay;
    946     }
    947     if (pcmSamplePosition > INT64_MAX / 1000000ll) {
    948         return INT64_MAX;
    949     }
    950     return pcmSamplePosition * 1000000ll / kOpusSampleRate;
    951 }
    952 
    953 status_t MyOpusExtractor::verifyHeader(MediaBuffer *buffer, uint8_t type) {
    954     switch (type) {
    955         // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean
    956         // header and comments such that we can share code with MyVorbisExtractor.
    957         case 1:
    958             return verifyOpusHeader(buffer);
    959         case 3:
    960             return verifyOpusComments(buffer);
    961         default:
    962             return INVALID_OPERATION;
    963     }
    964 }
    965 
    966 status_t MyOpusExtractor::verifyOpusHeader(MediaBuffer *buffer) {
    967     const size_t kOpusHeaderSize = 19;
    968     const uint8_t *data =
    969         (const uint8_t *)buffer->data() + buffer->range_offset();
    970 
    971     size_t size = buffer->range_length();
    972 
    973     if (size < kOpusHeaderSize
    974             || memcmp(data, "OpusHead", 8)
    975             || /* version = */ data[8] != 1) {
    976         return ERROR_MALFORMED;
    977     }
    978 
    979     mChannelCount = data[9];
    980     mCodecDelay = U16LE_AT(&data[10]);
    981 
    982     mMeta->setData(kKeyOpusHeader, 0, data, size);
    983     mMeta->setInt32(kKeySampleRate, kOpusSampleRate);
    984     mMeta->setInt32(kKeyChannelCount, mChannelCount);
    985     mMeta->setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/);
    986     mMeta->setInt64(kKeyOpusCodecDelay /* ns */,
    987             mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate);
    988 
    989     return OK;
    990 }
    991 
    992 status_t MyOpusExtractor::verifyOpusComments(MediaBuffer *buffer) {
    993     // add artificial framing bit so we can reuse _vorbis_unpack_comment
    994     int32_t commentSize = buffer->range_length() + 1;
    995     sp<ABuffer> aBuf = new ABuffer(commentSize);
    996     if (aBuf->capacity() <= buffer->range_length()) {
    997         return ERROR_MALFORMED;
    998     }
    999 
   1000     uint8_t* commentData = aBuf->data();
   1001     memcpy(commentData,
   1002             (uint8_t *)buffer->data() + buffer->range_offset(),
   1003             buffer->range_length());
   1004 
   1005     ogg_buffer buf;
   1006     buf.data = commentData;
   1007     buf.size = commentSize;
   1008     buf.refcount = 1;
   1009     buf.ptr.owner = NULL;
   1010 
   1011     ogg_reference ref;
   1012     ref.buffer = &buf;
   1013     ref.begin = 0;
   1014     ref.length = commentSize;
   1015     ref.next = NULL;
   1016 
   1017     oggpack_buffer bits;
   1018     oggpack_readinit(&bits, &ref);
   1019 
   1020     // skip 'OpusTags'
   1021     const char *OpusTags = "OpusTags";
   1022     const int32_t headerLen = strlen(OpusTags);
   1023     int32_t framingBitOffset = headerLen;
   1024     for (int i = 0; i < headerLen; ++i) {
   1025         char chr = oggpack_read(&bits, 8);
   1026         if (chr != OpusTags[i]) {
   1027             return ERROR_MALFORMED;
   1028         }
   1029     }
   1030 
   1031     int32_t vendorLen = oggpack_read(&bits, 32);
   1032     framingBitOffset += 4;
   1033     if (vendorLen < 0 || vendorLen > commentSize - 8) {
   1034         return ERROR_MALFORMED;
   1035     }
   1036     // skip vendor string
   1037     framingBitOffset += vendorLen;
   1038     for (int i = 0; i < vendorLen; ++i) {
   1039         oggpack_read(&bits, 8);
   1040     }
   1041 
   1042     int32_t n = oggpack_read(&bits, 32);
   1043     framingBitOffset += 4;
   1044     if (n < 0 || n > ((commentSize - oggpack_bytes(&bits)) >> 2)) {
   1045         return ERROR_MALFORMED;
   1046     }
   1047     for (int i = 0; i < n; ++i) {
   1048         int32_t len = oggpack_read(&bits, 32);
   1049         framingBitOffset += 4;
   1050         if (len  < 0 || len  > (commentSize - oggpack_bytes(&bits))) {
   1051             return ERROR_MALFORMED;
   1052         }
   1053         framingBitOffset += len;
   1054         for (int j = 0; j < len; ++j) {
   1055             oggpack_read(&bits, 8);
   1056         }
   1057     }
   1058     if (framingBitOffset < 0 || framingBitOffset >= commentSize) {
   1059         return ERROR_MALFORMED;
   1060     }
   1061     commentData[framingBitOffset] = 1;
   1062 
   1063     buf.data = commentData + headerLen;
   1064     buf.size = commentSize - headerLen;
   1065     buf.refcount = 1;
   1066     buf.ptr.owner = NULL;
   1067 
   1068     ref.buffer = &buf;
   1069     ref.begin = 0;
   1070     ref.length = commentSize - headerLen;
   1071     ref.next = NULL;
   1072 
   1073     oggpack_readinit(&bits, &ref);
   1074     int err = _vorbis_unpack_comment(&mVc, &bits);
   1075     if (0 != err) {
   1076         return ERROR_MALFORMED;
   1077     }
   1078 
   1079     parseFileMetaData();
   1080     return OK;
   1081 }
   1082 
   1083 status_t MyVorbisExtractor::verifyHeader(
   1084         MediaBuffer *buffer, uint8_t type) {
   1085     const uint8_t *data =
   1086         (const uint8_t *)buffer->data() + buffer->range_offset();
   1087 
   1088     size_t size = buffer->range_length();
   1089 
   1090     if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) {
   1091         return ERROR_MALFORMED;
   1092     }
   1093 
   1094     ogg_buffer buf;
   1095     buf.data = (uint8_t *)data;
   1096     buf.size = size;
   1097     buf.refcount = 1;
   1098     buf.ptr.owner = NULL;
   1099 
   1100     ogg_reference ref;
   1101     ref.buffer = &buf;
   1102     ref.begin = 0;
   1103     ref.length = size;
   1104     ref.next = NULL;
   1105 
   1106     oggpack_buffer bits;
   1107     oggpack_readinit(&bits, &ref);
   1108 
   1109     if (oggpack_read(&bits, 8) != type) {
   1110         return ERROR_MALFORMED;
   1111     }
   1112     for (size_t i = 0; i < 6; ++i) {
   1113         oggpack_read(&bits, 8);  // skip 'vorbis'
   1114     }
   1115 
   1116     switch (type) {
   1117         case 1:
   1118         {
   1119             if (0 != _vorbis_unpack_info(&mVi, &bits)) {
   1120                 return ERROR_MALFORMED;
   1121             }
   1122 
   1123             mMeta->setData(kKeyVorbisInfo, 0, data, size);
   1124             mMeta->setInt32(kKeySampleRate, mVi.rate);
   1125             mMeta->setInt32(kKeyChannelCount, mVi.channels);
   1126 
   1127             ALOGV("lower-bitrate = %ld", mVi.bitrate_lower);
   1128             ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
   1129             ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
   1130             ALOGV("window-bitrate = %ld", mVi.bitrate_window);
   1131             ALOGV("blocksizes: %d/%d",
   1132                     vorbis_info_blocksize(&mVi, 0),
   1133                     vorbis_info_blocksize(&mVi, 1)
   1134                     );
   1135 
   1136             off64_t size;
   1137             if (mSource->getSize(&size) == OK) {
   1138                 uint64_t bps = approxBitrate();
   1139                 if (bps != 0) {
   1140                     mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
   1141                 }
   1142             }
   1143             break;
   1144         }
   1145 
   1146         case 3:
   1147         {
   1148             if (0 != _vorbis_unpack_comment(&mVc, &bits)) {
   1149                 return ERROR_MALFORMED;
   1150             }
   1151 
   1152             parseFileMetaData();
   1153             break;
   1154         }
   1155 
   1156         case 5:
   1157         {
   1158             if (0 != _vorbis_unpack_books(&mVi, &bits)) {
   1159                 return ERROR_MALFORMED;
   1160             }
   1161 
   1162             mMeta->setData(kKeyVorbisBooks, 0, data, size);
   1163             break;
   1164         }
   1165     }
   1166 
   1167     return OK;
   1168 }
   1169 
   1170 uint64_t MyVorbisExtractor::approxBitrate() const {
   1171     if (mVi.bitrate_nominal != 0) {
   1172         return mVi.bitrate_nominal;
   1173     }
   1174 
   1175     return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
   1176 }
   1177 
   1178 void MyOggExtractor::parseFileMetaData() {
   1179     mFileMeta = new MetaData;
   1180     mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
   1181 
   1182     for (int i = 0; i < mVc.comments; ++i) {
   1183         const char *comment = mVc.user_comments[i];
   1184         size_t commentLength = mVc.comment_lengths[i];
   1185         parseVorbisComment(mFileMeta, comment, commentLength);
   1186         //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
   1187     }
   1188 }
   1189 
   1190 void parseVorbisComment(
   1191         const sp<MetaData> &fileMeta, const char *comment, size_t commentLength)
   1192 {
   1193     struct {
   1194         const char *const mTag;
   1195         uint32_t mKey;
   1196     } kMap[] = {
   1197         { "TITLE", kKeyTitle },
   1198         { "ARTIST", kKeyArtist },
   1199         { "ALBUMARTIST", kKeyAlbumArtist },
   1200         { "ALBUM ARTIST", kKeyAlbumArtist },
   1201         { "COMPILATION", kKeyCompilation },
   1202         { "ALBUM", kKeyAlbum },
   1203         { "COMPOSER", kKeyComposer },
   1204         { "GENRE", kKeyGenre },
   1205         { "AUTHOR", kKeyAuthor },
   1206         { "TRACKNUMBER", kKeyCDTrackNumber },
   1207         { "DISCNUMBER", kKeyDiscNumber },
   1208         { "DATE", kKeyDate },
   1209         { "YEAR", kKeyYear },
   1210         { "LYRICIST", kKeyWriter },
   1211         { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
   1212         { "ANDROID_LOOP", kKeyAutoLoop },
   1213     };
   1214 
   1215         for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
   1216             size_t tagLen = strlen(kMap[j].mTag);
   1217             if (!strncasecmp(kMap[j].mTag, comment, tagLen)
   1218                     && comment[tagLen] == '=') {
   1219                 if (kMap[j].mKey == kKeyAlbumArt) {
   1220                     extractAlbumArt(
   1221                             fileMeta,
   1222                             &comment[tagLen + 1],
   1223                             commentLength - tagLen - 1);
   1224                 } else if (kMap[j].mKey == kKeyAutoLoop) {
   1225                     if (!strcasecmp(&comment[tagLen + 1], "true")) {
   1226                         fileMeta->setInt32(kKeyAutoLoop, true);
   1227                     }
   1228                 } else {
   1229                     fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
   1230                 }
   1231             }
   1232         }
   1233 
   1234 }
   1235 
   1236 static void extractAlbumArt(
   1237         const sp<MetaData> &fileMeta, const void *data, size_t size) {
   1238     ALOGV("extractAlbumArt from '%s'", (const char *)data);
   1239 
   1240     sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size));
   1241     if (flacBuffer == NULL) {
   1242         ALOGE("malformed base64 encoded data.");
   1243         return;
   1244     }
   1245 
   1246     size_t flacSize = flacBuffer->size();
   1247     uint8_t *flac = flacBuffer->data();
   1248     ALOGV("got flac of size %zu", flacSize);
   1249 
   1250     uint32_t picType;
   1251     uint32_t typeLen;
   1252     uint32_t descLen;
   1253     uint32_t dataLen;
   1254     char type[128];
   1255 
   1256     if (flacSize < 8) {
   1257         return;
   1258     }
   1259 
   1260     picType = U32_AT(flac);
   1261 
   1262     if (picType != 3) {
   1263         // This is not a front cover.
   1264         return;
   1265     }
   1266 
   1267     typeLen = U32_AT(&flac[4]);
   1268     if (typeLen > sizeof(type) - 1) {
   1269         return;
   1270     }
   1271 
   1272     // we've already checked above that flacSize >= 8
   1273     if (flacSize - 8 < typeLen) {
   1274         return;
   1275     }
   1276 
   1277     memcpy(type, &flac[8], typeLen);
   1278     type[typeLen] = '\0';
   1279 
   1280     ALOGV("picType = %d, type = '%s'", picType, type);
   1281 
   1282     if (!strcmp(type, "-->")) {
   1283         // This is not inline cover art, but an external url instead.
   1284         return;
   1285     }
   1286 
   1287     if (flacSize < 32 || flacSize - 32 < typeLen) {
   1288         return;
   1289     }
   1290 
   1291     descLen = U32_AT(&flac[8 + typeLen]);
   1292     if (flacSize - 32 - typeLen < descLen) {
   1293         return;
   1294     }
   1295 
   1296     dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
   1297 
   1298     // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
   1299     if (flacSize - 32 - typeLen - descLen < dataLen) {
   1300         return;
   1301     }
   1302 
   1303     ALOGV("got image data, %zu trailing bytes",
   1304          flacSize - 32 - typeLen - descLen - dataLen);
   1305 
   1306     fileMeta->setData(
   1307             kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
   1308 
   1309     fileMeta->setCString(kKeyAlbumArtMIME, type);
   1310 }
   1311 
   1312 ////////////////////////////////////////////////////////////////////////////////
   1313 
   1314 OggExtractor::OggExtractor(const sp<DataSource> &source)
   1315     : mDataSource(source),
   1316       mInitCheck(NO_INIT),
   1317       mImpl(NULL) {
   1318     for (int i = 0; i < 2; ++i) {
   1319         if (mImpl != NULL) {
   1320             delete mImpl;
   1321         }
   1322         if (i == 0) {
   1323             mImpl = new MyVorbisExtractor(mDataSource);
   1324         } else {
   1325             mImpl = new MyOpusExtractor(mDataSource);
   1326         }
   1327         mInitCheck = mImpl->seekToOffset(0);
   1328 
   1329         if (mInitCheck == OK) {
   1330             mInitCheck = mImpl->init();
   1331             if (mInitCheck == OK) {
   1332                 break;
   1333             }
   1334         }
   1335     }
   1336 }
   1337 
   1338 OggExtractor::~OggExtractor() {
   1339     delete mImpl;
   1340     mImpl = NULL;
   1341 }
   1342 
   1343 size_t OggExtractor::countTracks() {
   1344     return mInitCheck != OK ? 0 : 1;
   1345 }
   1346 
   1347 sp<IMediaSource> OggExtractor::getTrack(size_t index) {
   1348     if (index >= 1) {
   1349         return NULL;
   1350     }
   1351 
   1352     return new OggSource(this);
   1353 }
   1354 
   1355 sp<MetaData> OggExtractor::getTrackMetaData(
   1356         size_t index, uint32_t /* flags */) {
   1357     if (index >= 1) {
   1358         return NULL;
   1359     }
   1360 
   1361     return mImpl->getFormat();
   1362 }
   1363 
   1364 sp<MetaData> OggExtractor::getMetaData() {
   1365     return mImpl->getFileMetaData();
   1366 }
   1367 
   1368 bool SniffOgg(
   1369         const sp<DataSource> &source, String8 *mimeType, float *confidence,
   1370         sp<AMessage> *) {
   1371     char tmp[4];
   1372     if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
   1373         return false;
   1374     }
   1375 
   1376     mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG);
   1377     *confidence = 0.2f;
   1378 
   1379     return true;
   1380 }
   1381 
   1382 }  // namespace android
   1383