OggExtractor.cpp revision 20e7a377ce22e260772f0c0276870cee5a92648e
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
36extern "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
45namespace android {
46
47struct 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
58protected:
59    virtual ~OggSource();
60
61private:
62    sp<OggExtractor> mExtractor;
63    bool mStarted;
64
65    OggSource(const OggSource &);
66    OggSource &operator=(const OggSource &);
67};
68
69struct 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
90protected:
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
165struct 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
179protected:
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
187struct 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
204protected:
205    virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const;
206    virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type);
207
208private:
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
218static void extractAlbumArt(
219        const sp<MetaData> &fileMeta, const void *data, size_t size);
220
221////////////////////////////////////////////////////////////////////////////////
222
223OggSource::OggSource(const sp<OggExtractor> &extractor)
224    : mExtractor(extractor),
225      mStarted(false) {
226}
227
228OggSource::~OggSource() {
229    if (mStarted) {
230        stop();
231    }
232}
233
234sp<MetaData> OggSource::getFormat() {
235    return mExtractor->mImpl->getFormat();
236}
237
238status_t OggSource::start(MetaData * /* params */) {
239    if (mStarted) {
240        return INVALID_OPERATION;
241    }
242
243    mStarted = true;
244
245    return OK;
246}
247
248status_t OggSource::stop() {
249    mStarted = false;
250
251    return OK;
252}
253
254status_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
292MyOggExtractor::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
315MyOggExtractor::~MyOggExtractor() {
316    vorbis_comment_clear(&mVc);
317    vorbis_info_clear(&mVi);
318}
319
320sp<MetaData> MyOggExtractor::getFormat() const {
321    return mMeta;
322}
323
324status_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.
355status_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
409status_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
457status_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
490ssize_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
561status_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
618uint32_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
664status_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        // Prevent a harmless unsigned integer overflow by clamping to 0
774        if (mCurrentPage.mGranulePosition >= mPrevGranulePosition) {
775            mCurrentPageSamples =
776                    mCurrentPage.mGranulePosition - mPrevGranulePosition;
777        } else {
778            mCurrentPageSamples = 0;
779        }
780        mFirstPacketInPage = true;
781
782        mPrevGranulePosition = mCurrentPage.mGranulePosition;
783
784        mCurrentPageSize = n;
785        mNextLaceIndex = 0;
786
787        if (buffer != NULL) {
788            if ((mCurrentPage.mFlags & 1) == 0) {
789                // This page does not continue the packet, i.e. the packet
790                // is already complete.
791
792                if (timeUs >= 0) {
793                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
794                }
795
796                buffer->meta_data()->setInt32(
797                        kKeyValidSamples, mCurrentPageSamples);
798                mFirstPacketInPage = false;
799
800                *out = buffer;
801
802                return OK;
803            }
804        }
805    }
806}
807
808status_t MyOggExtractor::init() {
809    mMeta = new MetaData;
810    mMeta->setCString(kKeyMIMEType, mMimeType);
811
812    status_t err;
813    MediaBuffer *packet;
814    for (size_t i = 0; i < mNumHeaders; ++i) {
815        // ignore timestamp for configuration packets
816        if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != OK) {
817            return err;
818        }
819        ALOGV("read packet of size %zu\n", packet->range_length());
820        err = verifyHeader(packet, /* type = */ i * 2 + 1);
821        packet->release();
822        packet = NULL;
823        if (err != OK) {
824            return err;
825        }
826    }
827
828    mFirstDataOffset = mOffset + mCurrentPageSize;
829
830    off64_t size;
831    uint64_t lastGranulePosition;
832    if (!(mSource->flags() & DataSource::kIsCachingDataSource)
833            && mSource->getSize(&size) == OK
834            && findPrevGranulePosition(size, &lastGranulePosition) == OK) {
835        // Let's assume it's cheap to seek to the end.
836        // The granule position of the final page in the stream will
837        // give us the exact duration of the content, something that
838        // we can only approximate using avg. bitrate if seeking to
839        // the end is too expensive or impossible (live streaming).
840
841        int64_t durationUs = getTimeUsOfGranule(lastGranulePosition);
842
843        mMeta->setInt64(kKeyDuration, durationUs);
844
845        buildTableOfContents();
846    }
847
848    return OK;
849}
850
851void MyOggExtractor::buildTableOfContents() {
852    off64_t offset = mFirstDataOffset;
853    Page page;
854    ssize_t pageSize;
855    while ((pageSize = readPage(offset, &page)) > 0) {
856        mTableOfContents.push();
857
858        TOCEntry &entry =
859            mTableOfContents.editItemAt(mTableOfContents.size() - 1);
860
861        entry.mPageOffset = offset;
862        entry.mTimeUs = getTimeUsOfGranule(page.mGranulePosition);
863
864        offset += (size_t)pageSize;
865    }
866
867    // Limit the maximum amount of RAM we spend on the table of contents,
868    // if necessary thin out the table evenly to trim it down to maximum
869    // size.
870
871    static const size_t kMaxTOCSize = 8192;
872    static const size_t kMaxNumTOCEntries = kMaxTOCSize / sizeof(TOCEntry);
873
874    size_t numerator = mTableOfContents.size();
875
876    if (numerator > kMaxNumTOCEntries) {
877        size_t denom = numerator - kMaxNumTOCEntries;
878
879        size_t accum = 0;
880        for (ssize_t i = mTableOfContents.size() - 1; i >= 0; --i) {
881            accum += denom;
882            if (accum >= numerator) {
883                mTableOfContents.removeAt(i);
884                accum -= numerator;
885            }
886        }
887    }
888}
889
890int32_t MyOggExtractor::getPacketBlockSize(MediaBuffer *buffer) {
891    const uint8_t *data =
892        (const uint8_t *)buffer->data() + buffer->range_offset();
893
894    size_t size = buffer->range_length();
895
896    ogg_buffer buf;
897    buf.data = (uint8_t *)data;
898    buf.size = size;
899    buf.refcount = 1;
900    buf.ptr.owner = NULL;
901
902    ogg_reference ref;
903    ref.buffer = &buf;
904    ref.begin = 0;
905    ref.length = size;
906    ref.next = NULL;
907
908    ogg_packet pack;
909    pack.packet = &ref;
910    pack.bytes = ref.length;
911    pack.b_o_s = 0;
912    pack.e_o_s = 0;
913    pack.granulepos = 0;
914    pack.packetno = 0;
915
916    return vorbis_packet_blocksize(&mVi, &pack);
917}
918
919int64_t MyOpusExtractor::getTimeUsOfGranule(uint64_t granulePos) const {
920    uint64_t pcmSamplePosition = 0;
921    if (granulePos > mCodecDelay) {
922        pcmSamplePosition = granulePos - mCodecDelay;
923    }
924    return pcmSamplePosition * 1000000ll / kOpusSampleRate;
925}
926
927status_t MyOpusExtractor::verifyHeader(MediaBuffer *buffer, uint8_t type) {
928    switch (type) {
929        // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean
930        // header and comments such that we can share code with MyVorbisExtractor.
931        case 1:
932            return verifyOpusHeader(buffer);
933        case 3:
934            return verifyOpusComments(buffer);
935        default:
936            return INVALID_OPERATION;
937    }
938}
939
940status_t MyOpusExtractor::verifyOpusHeader(MediaBuffer *buffer) {
941    const size_t kOpusHeaderSize = 19;
942    const uint8_t *data =
943        (const uint8_t *)buffer->data() + buffer->range_offset();
944
945    size_t size = buffer->range_length();
946
947    if (size < kOpusHeaderSize
948            || memcmp(data, "OpusHead", 8)
949            || /* version = */ data[8] != 1) {
950        return ERROR_MALFORMED;
951    }
952
953    mChannelCount = data[9];
954    mCodecDelay = U16LE_AT(&data[10]);
955
956    mMeta->setData(kKeyOpusHeader, 0, data, size);
957    mMeta->setInt32(kKeySampleRate, kOpusSampleRate);
958    mMeta->setInt32(kKeyChannelCount, mChannelCount);
959    mMeta->setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/);
960    mMeta->setInt64(kKeyOpusCodecDelay /* ns */,
961            mCodecDelay /* sample/s */ * 1000000000 / kOpusSampleRate);
962
963    return OK;
964}
965
966status_t MyOpusExtractor::verifyOpusComments(MediaBuffer *buffer) {
967    // add artificial framing bit so we can reuse _vorbis_unpack_comment
968    int32_t commentSize = buffer->range_length() + 1;
969    sp<ABuffer> aBuf = new ABuffer(commentSize);
970    if (aBuf->capacity() <= buffer->range_length()) {
971        return ERROR_MALFORMED;
972    }
973
974    uint8_t* commentData = aBuf->data();
975    memcpy(commentData,
976            (uint8_t *)buffer->data() + buffer->range_offset(),
977            buffer->range_length());
978
979    ogg_buffer buf;
980    buf.data = commentData;
981    buf.size = commentSize;
982    buf.refcount = 1;
983    buf.ptr.owner = NULL;
984
985    ogg_reference ref;
986    ref.buffer = &buf;
987    ref.begin = 0;
988    ref.length = commentSize;
989    ref.next = NULL;
990
991    oggpack_buffer bits;
992    oggpack_readinit(&bits, &ref);
993
994    // skip 'OpusTags'
995    const char *OpusTags = "OpusTags";
996    const int32_t headerLen = strlen(OpusTags);
997    int32_t framingBitOffset = headerLen;
998    for (int i = 0; i < headerLen; ++i) {
999        char chr = oggpack_read(&bits, 8);
1000        if (chr != OpusTags[i]) {
1001            return ERROR_MALFORMED;
1002        }
1003    }
1004
1005    int32_t vendorLen = oggpack_read(&bits, 32);
1006    framingBitOffset += 4;
1007    if (vendorLen < 0 || vendorLen > commentSize - 8) {
1008        return ERROR_MALFORMED;
1009    }
1010    // skip vendor string
1011    framingBitOffset += vendorLen;
1012    for (int i = 0; i < vendorLen; ++i) {
1013        oggpack_read(&bits, 8);
1014    }
1015
1016    int32_t n = oggpack_read(&bits, 32);
1017    framingBitOffset += 4;
1018    if (n < 0 || n > ((commentSize - oggpack_bytes(&bits)) >> 2)) {
1019        return ERROR_MALFORMED;
1020    }
1021    for (int i = 0; i < n; ++i) {
1022        int32_t len = oggpack_read(&bits, 32);
1023        framingBitOffset += 4;
1024        if (len  < 0 || len  > (commentSize - oggpack_bytes(&bits))) {
1025            return ERROR_MALFORMED;
1026        }
1027        framingBitOffset += len;
1028        for (int j = 0; j < len; ++j) {
1029            oggpack_read(&bits, 8);
1030        }
1031    }
1032    if (framingBitOffset < 0 || framingBitOffset >= commentSize) {
1033        return ERROR_MALFORMED;
1034    }
1035    commentData[framingBitOffset] = 1;
1036
1037    buf.data = commentData + headerLen;
1038    buf.size = commentSize - headerLen;
1039    buf.refcount = 1;
1040    buf.ptr.owner = NULL;
1041
1042    ref.buffer = &buf;
1043    ref.begin = 0;
1044    ref.length = commentSize - headerLen;
1045    ref.next = NULL;
1046
1047    oggpack_readinit(&bits, &ref);
1048    int err = _vorbis_unpack_comment(&mVc, &bits);
1049    if (0 != err) {
1050        return ERROR_MALFORMED;
1051    }
1052
1053    parseFileMetaData();
1054    return OK;
1055}
1056
1057status_t MyVorbisExtractor::verifyHeader(
1058        MediaBuffer *buffer, uint8_t type) {
1059    const uint8_t *data =
1060        (const uint8_t *)buffer->data() + buffer->range_offset();
1061
1062    size_t size = buffer->range_length();
1063
1064    if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) {
1065        return ERROR_MALFORMED;
1066    }
1067
1068    ogg_buffer buf;
1069    buf.data = (uint8_t *)data;
1070    buf.size = size;
1071    buf.refcount = 1;
1072    buf.ptr.owner = NULL;
1073
1074    ogg_reference ref;
1075    ref.buffer = &buf;
1076    ref.begin = 0;
1077    ref.length = size;
1078    ref.next = NULL;
1079
1080    oggpack_buffer bits;
1081    oggpack_readinit(&bits, &ref);
1082
1083    if (oggpack_read(&bits, 8) != type) {
1084        return ERROR_MALFORMED;
1085    }
1086    for (size_t i = 0; i < 6; ++i) {
1087        oggpack_read(&bits, 8);  // skip 'vorbis'
1088    }
1089
1090    switch (type) {
1091        case 1:
1092        {
1093            if (0 != _vorbis_unpack_info(&mVi, &bits)) {
1094                return ERROR_MALFORMED;
1095            }
1096
1097            mMeta->setData(kKeyVorbisInfo, 0, data, size);
1098            mMeta->setInt32(kKeySampleRate, mVi.rate);
1099            mMeta->setInt32(kKeyChannelCount, mVi.channels);
1100
1101            ALOGV("lower-bitrate = %ld", mVi.bitrate_lower);
1102            ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
1103            ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
1104            ALOGV("window-bitrate = %ld", mVi.bitrate_window);
1105            ALOGV("blocksizes: %d/%d",
1106                    vorbis_info_blocksize(&mVi, 0),
1107                    vorbis_info_blocksize(&mVi, 1)
1108                    );
1109
1110            off64_t size;
1111            if (mSource->getSize(&size) == OK) {
1112                uint64_t bps = approxBitrate();
1113                if (bps != 0) {
1114                    mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
1115                }
1116            }
1117            break;
1118        }
1119
1120        case 3:
1121        {
1122            if (0 != _vorbis_unpack_comment(&mVc, &bits)) {
1123                return ERROR_MALFORMED;
1124            }
1125
1126            parseFileMetaData();
1127            break;
1128        }
1129
1130        case 5:
1131        {
1132            if (0 != _vorbis_unpack_books(&mVi, &bits)) {
1133                return ERROR_MALFORMED;
1134            }
1135
1136            mMeta->setData(kKeyVorbisBooks, 0, data, size);
1137            break;
1138        }
1139    }
1140
1141    return OK;
1142}
1143
1144uint64_t MyVorbisExtractor::approxBitrate() const {
1145    if (mVi.bitrate_nominal != 0) {
1146        return mVi.bitrate_nominal;
1147    }
1148
1149    return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
1150}
1151
1152void MyOggExtractor::parseFileMetaData() {
1153    mFileMeta = new MetaData;
1154    mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
1155
1156    for (int i = 0; i < mVc.comments; ++i) {
1157        const char *comment = mVc.user_comments[i];
1158        size_t commentLength = mVc.comment_lengths[i];
1159        parseVorbisComment(mFileMeta, comment, commentLength);
1160        //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
1161    }
1162}
1163
1164void parseVorbisComment(
1165        const sp<MetaData> &fileMeta, const char *comment, size_t commentLength)
1166{
1167    struct {
1168        const char *const mTag;
1169        uint32_t mKey;
1170    } kMap[] = {
1171        { "TITLE", kKeyTitle },
1172        { "ARTIST", kKeyArtist },
1173        { "ALBUMARTIST", kKeyAlbumArtist },
1174        { "ALBUM ARTIST", kKeyAlbumArtist },
1175        { "COMPILATION", kKeyCompilation },
1176        { "ALBUM", kKeyAlbum },
1177        { "COMPOSER", kKeyComposer },
1178        { "GENRE", kKeyGenre },
1179        { "AUTHOR", kKeyAuthor },
1180        { "TRACKNUMBER", kKeyCDTrackNumber },
1181        { "DISCNUMBER", kKeyDiscNumber },
1182        { "DATE", kKeyDate },
1183        { "YEAR", kKeyYear },
1184        { "LYRICIST", kKeyWriter },
1185        { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
1186        { "ANDROID_LOOP", kKeyAutoLoop },
1187    };
1188
1189        for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
1190            size_t tagLen = strlen(kMap[j].mTag);
1191            if (!strncasecmp(kMap[j].mTag, comment, tagLen)
1192                    && comment[tagLen] == '=') {
1193                if (kMap[j].mKey == kKeyAlbumArt) {
1194                    extractAlbumArt(
1195                            fileMeta,
1196                            &comment[tagLen + 1],
1197                            commentLength - tagLen - 1);
1198                } else if (kMap[j].mKey == kKeyAutoLoop) {
1199                    if (!strcasecmp(&comment[tagLen + 1], "true")) {
1200                        fileMeta->setInt32(kKeyAutoLoop, true);
1201                    }
1202                } else {
1203                    fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
1204                }
1205            }
1206        }
1207
1208}
1209
1210// The returned buffer should be free()d.
1211static uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) {
1212    *outSize = 0;
1213
1214    if ((size % 4) != 0) {
1215        return NULL;
1216    }
1217
1218    size_t n = size;
1219    size_t padding = 0;
1220    if (n >= 1 && s[n - 1] == '=') {
1221        padding = 1;
1222
1223        if (n >= 2 && s[n - 2] == '=') {
1224            padding = 2;
1225        }
1226    }
1227
1228    size_t outLen = 3 * size / 4 - padding;
1229
1230    *outSize = outLen;
1231
1232    void *buffer = malloc(outLen);
1233
1234    uint8_t *out = (uint8_t *)buffer;
1235    size_t j = 0;
1236    uint32_t accum = 0;
1237    for (size_t i = 0; i < n; ++i) {
1238        char c = s[i];
1239        unsigned value;
1240        if (c >= 'A' && c <= 'Z') {
1241            value = c - 'A';
1242        } else if (c >= 'a' && c <= 'z') {
1243            value = 26 + c - 'a';
1244        } else if (c >= '0' && c <= '9') {
1245            value = 52 + c - '0';
1246        } else if (c == '+') {
1247            value = 62;
1248        } else if (c == '/') {
1249            value = 63;
1250        } else if (c != '=') {
1251            return NULL;
1252        } else {
1253            if (i < n - padding) {
1254                return NULL;
1255            }
1256
1257            value = 0;
1258        }
1259
1260        accum = (accum << 6) | value;
1261
1262        if (((i + 1) % 4) == 0) {
1263            out[j++] = (accum >> 16);
1264
1265            if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
1266            if (j < outLen) { out[j++] = accum & 0xff; }
1267
1268            accum = 0;
1269        }
1270    }
1271
1272    return (uint8_t *)buffer;
1273}
1274
1275static void extractAlbumArt(
1276        const sp<MetaData> &fileMeta, const void *data, size_t size) {
1277    ALOGV("extractAlbumArt from '%s'", (const char *)data);
1278
1279    size_t flacSize;
1280    uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize);
1281
1282    if (flac == NULL) {
1283        ALOGE("malformed base64 encoded data.");
1284        return;
1285    }
1286
1287    ALOGV("got flac of size %zu", flacSize);
1288
1289    uint32_t picType;
1290    uint32_t typeLen;
1291    uint32_t descLen;
1292    uint32_t dataLen;
1293    char type[128];
1294
1295    if (flacSize < 8) {
1296        goto exit;
1297    }
1298
1299    picType = U32_AT(flac);
1300
1301    if (picType != 3) {
1302        // This is not a front cover.
1303        goto exit;
1304    }
1305
1306    typeLen = U32_AT(&flac[4]);
1307    if (typeLen > sizeof(type) - 1) {
1308        goto exit;
1309    }
1310
1311    // we've already checked above that flacSize >= 8
1312    if (flacSize - 8 < typeLen) {
1313        goto exit;
1314    }
1315
1316    memcpy(type, &flac[8], typeLen);
1317    type[typeLen] = '\0';
1318
1319    ALOGV("picType = %d, type = '%s'", picType, type);
1320
1321    if (!strcmp(type, "-->")) {
1322        // This is not inline cover art, but an external url instead.
1323        goto exit;
1324    }
1325
1326    descLen = U32_AT(&flac[8 + typeLen]);
1327
1328    if (flacSize < 32 ||
1329        flacSize - 32 < typeLen ||
1330        flacSize - 32 - typeLen < descLen) {
1331        goto exit;
1332    }
1333
1334    dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
1335
1336
1337    // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
1338    if (flacSize - 32 - typeLen - descLen < dataLen) {
1339        goto exit;
1340    }
1341
1342    ALOGV("got image data, %zu trailing bytes",
1343         flacSize - 32 - typeLen - descLen - dataLen);
1344
1345    fileMeta->setData(
1346            kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
1347
1348    fileMeta->setCString(kKeyAlbumArtMIME, type);
1349
1350exit:
1351    free(flac);
1352    flac = NULL;
1353}
1354
1355////////////////////////////////////////////////////////////////////////////////
1356
1357OggExtractor::OggExtractor(const sp<DataSource> &source)
1358    : mDataSource(source),
1359      mInitCheck(NO_INIT),
1360      mImpl(NULL) {
1361    for (int i = 0; i < 2; ++i) {
1362        if (mImpl != NULL) {
1363            delete mImpl;
1364        }
1365        if (i == 0) {
1366            mImpl = new MyVorbisExtractor(mDataSource);
1367        } else {
1368            mImpl = new MyOpusExtractor(mDataSource);
1369        }
1370        mInitCheck = mImpl->seekToOffset(0);
1371
1372        if (mInitCheck == OK) {
1373            mInitCheck = mImpl->init();
1374            if (mInitCheck == OK) {
1375                break;
1376            }
1377        }
1378    }
1379}
1380
1381OggExtractor::~OggExtractor() {
1382    delete mImpl;
1383    mImpl = NULL;
1384}
1385
1386size_t OggExtractor::countTracks() {
1387    return mInitCheck != OK ? 0 : 1;
1388}
1389
1390sp<MediaSource> OggExtractor::getTrack(size_t index) {
1391    if (index >= 1) {
1392        return NULL;
1393    }
1394
1395    return new OggSource(this);
1396}
1397
1398sp<MetaData> OggExtractor::getTrackMetaData(
1399        size_t index, uint32_t /* flags */) {
1400    if (index >= 1) {
1401        return NULL;
1402    }
1403
1404    return mImpl->getFormat();
1405}
1406
1407sp<MetaData> OggExtractor::getMetaData() {
1408    return mImpl->getFileMetaData();
1409}
1410
1411bool SniffOgg(
1412        const sp<DataSource> &source, String8 *mimeType, float *confidence,
1413        sp<AMessage> *) {
1414    char tmp[4];
1415    if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
1416        return false;
1417    }
1418
1419    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG);
1420    *confidence = 0.2f;
1421
1422    return true;
1423}
1424
1425}  // namespace android
1426