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