1ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber/*
2ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * Copyright (C) 2010 The Android Open Source Project
3ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *
4ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * you may not use this file except in compliance with the License.
6ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * You may obtain a copy of the License at
7ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *
8ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *
10ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * Unless required by applicable law or agreed to in writing, software
11ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * See the License for the specific language governing permissions and
14ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * limitations under the License.
15ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber */
16ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
17ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//#define LOG_NDEBUG 0
18ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#define LOG_TAG "OggExtractor"
19ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <utils/Log.h>
20ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
21ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include "include/OggExtractor.h"
22ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
23ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <cutils/properties.h>
248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih#include <media/stagefright/foundation/ABuffer.h>
25f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
2674814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim#include <media/stagefright/foundation/base64.h>
27ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/DataSource.h>
28ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaBuffer.h>
29ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaBufferGroup.h>
30ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaDefs.h>
31ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaErrors.h>
32ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaSource.h>
33ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MetaData.h>
34ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/Utils.h>
35ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <utils/String8.h>
36ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
37ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberextern "C" {
38ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    #include <Tremolo/codec_internal.h>
39ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
40ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
41ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
42ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
437a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
44ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
45ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
46ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubernamespace android {
47ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
48ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstruct OggSource : public MediaSource {
49ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    OggSource(const sp<OggExtractor> &extractor);
50ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
51ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    virtual sp<MetaData> getFormat();
52ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
53ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    virtual status_t start(MetaData *params = NULL);
54ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    virtual status_t stop();
55ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
56ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    virtual status_t read(
57ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
58ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
59ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberprotected:
60ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    virtual ~OggSource();
61ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
62ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberprivate:
63ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    sp<OggExtractor> mExtractor;
64ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    bool mStarted;
65ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
66ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    OggSource(const OggSource &);
67ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    OggSource &operator=(const OggSource &);
68ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber};
69ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstruct MyOggExtractor {
718c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    MyOggExtractor(
728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            const sp<DataSource> &source,
738c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            const char *mimeType,
748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            size_t numHeaders,
758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            int64_t seekPreRollUs);
768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual ~MyOggExtractor();
77ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
78ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    sp<MetaData> getFormat() const;
79ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
80ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    // Returns an approximate bitrate in bits per second.
818c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual uint64_t approxBitrate() const = 0;
82ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
833fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    status_t seekToTime(int64_t timeUs);
84c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t seekToOffset(off64_t offset);
858c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual status_t readNextPacket(MediaBuffer **buffer) = 0;
86ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
875a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    status_t init();
88ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    sp<MetaData> getFileMetaData() { return mFileMeta; }
904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihprotected:
92ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    struct Page {
93ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint64_t mGranulePosition;
947a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen        int32_t mPrevPacketSize;
957a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen        uint64_t mPrevPacketPos;
96ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint32_t mSerialNo;
97ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint32_t mPageNo;
98ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint8_t mFlags;
99ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint8_t mNumSegments;
100ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint8_t mLace[255];
101ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    };
102ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1033fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    struct TOCEntry {
1043fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        off64_t mPageOffset;
1053fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        int64_t mTimeUs;
1063fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    };
1073fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
108ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    sp<DataSource> mSource;
109c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mOffset;
110ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    Page mCurrentPage;
1118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint64_t mCurGranulePosition;
112db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    uint64_t mPrevGranulePosition;
113ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t mCurrentPageSize;
114db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    bool mFirstPacketInPage;
115db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    uint64_t mCurrentPageSamples;
116ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t mNextLaceIndex;
117ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    const char *mMimeType;
1198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    size_t mNumHeaders;
1208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int64_t mSeekPreRollUs;
1218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
122c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mFirstDataOffset;
12396f52cde23982f668592418a9548045237d5e327Andreas Huber
124ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    vorbis_info mVi;
125ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    vorbis_comment mVc;
126ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
127ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    sp<MetaData> mMeta;
1284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    sp<MetaData> mFileMeta;
129ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1303fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    Vector<TOCEntry> mTableOfContents;
1313fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
132c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ssize_t readPage(off64_t offset, Page *page);
133c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t findNextPage(off64_t startOffset, off64_t *pageOffset);
134ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1358c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const = 0;
1368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
1378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // Extract codec format, metadata tags, and various codec specific data;
1388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // the format and CSD's are required to setup the decoders for the enclosed media content.
1398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    //
1408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // Valid values for `type` are:
1418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // 1 - bitstream identification header
1428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // 3 - comment header
1438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // 5 - codec setup header (Vorbis only)
1448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type) = 0;
1458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
1468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // Read the next ogg packet from the underlying data source; optionally
1478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // calculate the timestamp for the output packet whilst pretending
1488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // that we are parsing an Ogg Vorbis stream.
1498c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    //
1508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // *buffer is NULL'ed out immediately upon entry, and if successful a new buffer is allocated;
1518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // clients are responsible for releasing the original buffer.
1528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    status_t _readNextPacket(MediaBuffer **buffer, bool calcVorbisTimestamp);
153ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int32_t getPacketBlockSize(MediaBuffer *buffer);
1557a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen
1564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    void parseFileMetaData();
1574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1583fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    status_t findPrevGranulePosition(off64_t pageOffset, uint64_t *granulePos);
1593fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
1603fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    void buildTableOfContents();
161db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
1628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    MyOggExtractor(const MyOggExtractor &);
1638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    MyOggExtractor &operator=(const MyOggExtractor &);
1648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih};
1658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
1668c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstruct MyVorbisExtractor : public MyOggExtractor {
1678c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    MyVorbisExtractor(const sp<DataSource> &source)
1688c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        : MyOggExtractor(source,
1698c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih                MEDIA_MIMETYPE_AUDIO_VORBIS,
1708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih                /* numHeaders */ 3,
1718c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih                /* seekPreRollUs */ 0) {
1728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
1738c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
1748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual uint64_t approxBitrate() const;
1758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
1768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual status_t readNextPacket(MediaBuffer **buffer) {
1778c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return _readNextPacket(buffer, /* calcVorbisTimestamp = */ true);
1788c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
1798c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
1808c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihprotected:
1818c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const {
1828c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return granulePos * 1000000ll / mVi.rate;
1838c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
1848c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
1858c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type);
1868c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih};
1878c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
1888c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstruct MyOpusExtractor : public MyOggExtractor {
1898c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    static const int32_t kOpusSampleRate = 48000;
1908c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    static const int64_t kOpusSeekPreRollUs = 80000; // 80 ms
1918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
1928c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    MyOpusExtractor(const sp<DataSource> &source)
1938c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        : MyOggExtractor(source, MEDIA_MIMETYPE_AUDIO_OPUS, /*numHeaders*/ 2, kOpusSeekPreRollUs),
1948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih          mChannelCount(0),
195819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih          mCodecDelay(0),
196819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih          mStartGranulePosition(-1) {
1978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
1988c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
1998c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual uint64_t approxBitrate() const {
2008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return 0;
2018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
2028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
2038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual status_t readNextPacket(MediaBuffer **buffer);
2048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
2058c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihprotected:
2068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const;
2078c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type);
2088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
2098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihprivate:
2108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    status_t verifyOpusHeader(MediaBuffer *buffer);
2118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    status_t verifyOpusComments(MediaBuffer *buffer);
2128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint32_t getNumSamplesInPacket(MediaBuffer *buffer) const;
2138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
2148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint8_t mChannelCount;
2158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint16_t mCodecDelay;
216819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih    int64_t mStartGranulePosition;
217ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber};
218ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
219856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt(
220856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        const sp<MetaData> &fileMeta, const void *data, size_t size);
221856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten
222ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
223ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
224ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::OggSource(const sp<OggExtractor> &extractor)
225ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mExtractor(extractor),
226ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mStarted(false) {
227ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
228ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
229ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::~OggSource() {
230ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mStarted) {
231ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        stop();
232ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
233ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
234ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
235ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggSource::getFormat() {
236ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mExtractor->mImpl->getFormat();
237ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
238ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
23984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t OggSource::start(MetaData * /* params */) {
240ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mStarted) {
241ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return INVALID_OPERATION;
242ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
243ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
244ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mStarted = true;
245ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
246ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
247ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
248ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
249ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::stop() {
250ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mStarted = false;
251ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
252ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
253ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
254ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
255ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::read(
256ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
257ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = NULL;
258ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
259ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t seekTimeUs;
260abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
261abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
2628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        status_t err = mExtractor->mImpl->seekToTime(seekTimeUs);
2638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (err != OK) {
2648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return err;
265ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
266ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
267ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
268ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MediaBuffer *packet;
2698c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    status_t err = mExtractor->mImpl->readNextPacket(&packet);
270ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
271ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (err != OK) {
272ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return err;
273ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
274ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
275ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0
276ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t timeUs;
277ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) {
278df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("found time = %lld us", timeUs);
279ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    } else {
280df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("NO time");
281ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
282ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif
283ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
2848bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    packet->meta_data()->setInt32(kKeyIsSyncFrame, 1);
2858bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
286ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = packet;
287ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
288ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
289ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
290ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
291ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
292ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
2938c10a80cf1af68f15eb39552ca116ec6f04fc173Robert ShihMyOggExtractor::MyOggExtractor(
2948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        const sp<DataSource> &source,
2958c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        const char *mimeType,
2968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        size_t numHeaders,
2978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        int64_t seekPreRollUs)
298ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mSource(source),
299ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mOffset(0),
3008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih      mCurGranulePosition(0),
301db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber      mPrevGranulePosition(0),
302ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mCurrentPageSize(0),
303db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber      mFirstPacketInPage(true),
304db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber      mCurrentPageSamples(0),
30596f52cde23982f668592418a9548045237d5e327Andreas Huber      mNextLaceIndex(0),
3068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih      mMimeType(mimeType),
3078c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih      mNumHeaders(numHeaders),
3088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih      mSeekPreRollUs(seekPreRollUs),
30996f52cde23982f668592418a9548045237d5e327Andreas Huber      mFirstDataOffset(-1) {
310ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPage.mNumSegments = 0;
3114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
3124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_info_init(&mVi);
3134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_comment_init(&mVc);
314ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
315ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
3168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert ShihMyOggExtractor::~MyOggExtractor() {
3174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_comment_clear(&mVc);
3184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_info_clear(&mVi);
319ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
320ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
3218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihsp<MetaData> MyOggExtractor::getFormat() const {
322ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mMeta;
323ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
324ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
3258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::findNextPage(
326c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t startOffset, off64_t *pageOffset) {
327ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *pageOffset = startOffset;
328ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
329ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (;;) {
330ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        char signature[4];
331ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
332ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
333ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (n < 4) {
334ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            *pageOffset = 0;
335ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
336ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
337ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
338ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
339ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (!memcmp(signature, "OggS", 4)) {
340ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (*pageOffset > startOffset) {
3413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("skipped %lld bytes of junk to reach next frame",
342ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                     (long long)(*pageOffset - startOffset));
343ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
344ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
345ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return OK;
346ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
347ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
348ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ++*pageOffset;
349ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
350ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
351ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
352db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// Given the offset of the "current" page, find the page immediately preceding
353db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// it (if any) and return its granule position.
354db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// To do this we back up from the "current" page's offset until we find any
355db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// page preceding it and then scan forward to just before the current page.
3568c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::findPrevGranulePosition(
3573fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        off64_t pageOffset, uint64_t *granulePos) {
3583fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    *granulePos = 0;
3593fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
360c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t prevPageOffset = 0;
361c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t prevGuess = pageOffset;
362db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    for (;;) {
363db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (prevGuess >= 5000) {
364db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            prevGuess -= 5000;
365db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        } else {
366db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            prevGuess = 0;
367db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
368db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
369ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("backing up %lld bytes", (long long)(pageOffset - prevGuess));
370db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
3713fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        status_t err = findNextPage(prevGuess, &prevPageOffset);
3728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (err == ERROR_END_OF_STREAM) {
3738c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            // We are at the last page and didn't back off enough;
3748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            // back off 5000 bytes more and try again.
3758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            continue;
3768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        } else if (err != OK) {
3773fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            return err;
3783fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        }
379db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
380db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (prevPageOffset < pageOffset || prevGuess == 0) {
381db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            break;
382db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
383db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    }
384db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
385db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    if (prevPageOffset == pageOffset) {
386db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        // We did not find a page preceding this one.
3873fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        return UNKNOWN_ERROR;
388db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    }
389db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
3903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("prevPageOffset at %lld, pageOffset at %lld",
391ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar            (long long)prevPageOffset, (long long)pageOffset);
392db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
393db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    for (;;) {
394db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        Page prevPage;
395db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        ssize_t n = readPage(prevPageOffset, &prevPage);
396db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
397db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (n <= 0) {
3983fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            return (status_t)n;
399db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
400db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
401db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        prevPageOffset += n;
402db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
403db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (prevPageOffset == pageOffset) {
4043fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            *granulePos = prevPage.mGranulePosition;
4053fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            return OK;
406db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
407db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    }
408db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber}
409db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
4108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::seekToTime(int64_t timeUs) {
4118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    timeUs -= mSeekPreRollUs;
4128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (timeUs < 0) {
4138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        timeUs = 0;
4148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
4158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
4163fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    if (mTableOfContents.isEmpty()) {
4173fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // Perform approximate seeking based on avg. bitrate.
4188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        uint64_t bps = approxBitrate();
4198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (bps <= 0) {
4208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return INVALID_OPERATION;
4218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
4223fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
4238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        off64_t pos = timeUs * bps / 8000000ll;
4243fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
425ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("seeking to offset %lld", (long long)pos);
4263fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        return seekToOffset(pos);
4273fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
4283fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
4293fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    size_t left = 0;
430225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar    size_t right_plus_one = mTableOfContents.size();
431225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar    while (left < right_plus_one) {
432225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar        size_t center = left + (right_plus_one - left) / 2;
4333fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
4343fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        const TOCEntry &entry = mTableOfContents.itemAt(center);
4353fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
4363fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        if (timeUs < entry.mTimeUs) {
437225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar            right_plus_one = center;
4383fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        } else if (timeUs > entry.mTimeUs) {
4393fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            left = center + 1;
4403fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        } else {
441225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar            left = center;
4423fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            break;
4433fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        }
4443fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
4453fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
446225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar    if (left == mTableOfContents.size()) {
447225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar        --left;
448225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar    }
449225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar
4503fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    const TOCEntry &entry = mTableOfContents.itemAt(left);
4513fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
452a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("seeking to entry %zu / %zu at offset %lld",
453ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar         left, mTableOfContents.size(), (long long)entry.mPageOffset);
4543fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
4553fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    return seekToOffset(entry.mPageOffset);
4563fd91baee812919f53a85c5c05f32606313f8334Andreas Huber}
4573fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
4588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::seekToOffset(off64_t offset) {
45996f52cde23982f668592418a9548045237d5e327Andreas Huber    if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) {
46096f52cde23982f668592418a9548045237d5e327Andreas Huber        // Once we know where the actual audio data starts (past the headers)
46196f52cde23982f668592418a9548045237d5e327Andreas Huber        // don't ever seek to anywhere before that.
46296f52cde23982f668592418a9548045237d5e327Andreas Huber        offset = mFirstDataOffset;
46396f52cde23982f668592418a9548045237d5e327Andreas Huber    }
46496f52cde23982f668592418a9548045237d5e327Andreas Huber
465c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t pageOffset;
466ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    status_t err = findNextPage(offset, &pageOffset);
467ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
468ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (err != OK) {
469ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return err;
470ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
471ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
472db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    // We found the page we wanted to seek to, but we'll also need
473db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    // the page preceding it to determine how many valid samples are on
474db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    // this page.
4753fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    findPrevGranulePosition(pageOffset, &mPrevGranulePosition);
476db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
477ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mOffset = pageOffset;
478ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
479ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPageSize = 0;
480db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    mFirstPacketInPage = true;
481db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    mCurrentPageSamples = 0;
482ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPage.mNumSegments = 0;
4837a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    mCurrentPage.mPrevPacketSize = -1;
484ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mNextLaceIndex = 0;
485ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
486ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    // XXX what if new page continues packet from last???
487ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
488ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
489ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
490ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
4918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihssize_t MyOggExtractor::readPage(off64_t offset, Page *page) {
492ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    uint8_t header[27];
493df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber    ssize_t n;
494df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber    if ((n = mSource->readAt(offset, header, sizeof(header)))
495ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            < (ssize_t)sizeof(header)) {
496ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("failed to read %zu bytes at offset %#016llx, got %zd bytes",
497ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                sizeof(header), (long long)offset, n);
498ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
499df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber        if (n < 0) {
500df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber            return n;
501df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber        } else if (n == 0) {
502df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber            return ERROR_END_OF_STREAM;
503df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber        } else {
504df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber            return ERROR_IO;
505df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber        }
506ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
507ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
508ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (memcmp(header, "OggS", 4)) {
509ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_MALFORMED;
510ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
511ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
512ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (header[4] != 0) {
513ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        // Wrong version.
514ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
515ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_UNSUPPORTED;
516ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
517ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
518ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mFlags = header[5];
519ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
520ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (page->mFlags & ~7) {
521ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        // Only bits 0-2 are defined in version 0.
522ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_MALFORMED;
523ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
524ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
525ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mGranulePosition = U64LE_AT(&header[6]);
526ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
527ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0
528ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    printf("granulePosition = %llu (0x%llx)\n",
529ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber           page->mGranulePosition, page->mGranulePosition);
530ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif
531ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
532ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mSerialNo = U32LE_AT(&header[14]);
533ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mPageNo = U32LE_AT(&header[18]);
534ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
535ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mNumSegments = header[26];
536ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mSource->readAt(
537ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                offset + sizeof(header), page->mLace, page->mNumSegments)
538ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            < (ssize_t)page->mNumSegments) {
539ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_IO;
540ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
541ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
542ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t totalSize = 0;;
543ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < page->mNumSegments; ++i) {
544ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        totalSize += page->mLace[i];
545ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
546ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5475a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#if 0
548ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    String8 tmp;
549ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < page->mNumSegments; ++i) {
550ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        char x[32];
551ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]);
552ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
553ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        tmp.append(x);
554ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
555ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5563856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string());
5575a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#endif
558ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
559ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return sizeof(header) + page->mNumSegments + totalSize;
560ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
561ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::readNextPacket(MediaBuffer **out) {
563819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih    if (mOffset <= mFirstDataOffset && mStartGranulePosition < 0) {
564819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        // The first sample might not start at time 0; find out where by subtracting
565819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        // the number of samples on the first page from the granule position
566819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        // (position of last complete sample) of the first page. This happens
567819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        // the first time before we attempt to read a packet from the first page.
568819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        MediaBuffer *mBuf;
569819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        uint32_t numSamples = 0;
570819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        uint64_t curGranulePosition = 0;
571819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        while (true) {
572819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            status_t err = _readNextPacket(&mBuf, /* calcVorbisTimestamp = */false);
573819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            if (err != OK && err != ERROR_END_OF_STREAM) {
574819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih                return err;
575819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            }
576819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            // First two pages are header pages.
577819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            if (err == ERROR_END_OF_STREAM || mCurrentPage.mPageNo > 2) {
578819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih                break;
579819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            }
580819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            curGranulePosition = mCurrentPage.mGranulePosition;
581819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            numSamples += getNumSamplesInPacket(mBuf);
582819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            mBuf->release();
583819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            mBuf = NULL;
584819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        }
585819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih
586819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        if (curGranulePosition > numSamples) {
587819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            mStartGranulePosition = curGranulePosition - numSamples;
588819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        } else {
589819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            mStartGranulePosition = 0;
590819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        }
591819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        seekToOffset(0);
592819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih    }
593819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih
5948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    status_t err = _readNextPacket(out, /* calcVorbisTimestamp = */false);
5958c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (err != OK) {
5968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return err;
5978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
5988c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
5998c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int32_t currentPageSamples;
6008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // Calculate timestamps by accumulating durations starting from the first sample of a page;
6018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // We assume that we only seek to page boundaries.
6028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if ((*out)->meta_data()->findInt32(kKeyValidSamples, &currentPageSamples)) {
6038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        // first packet in page
604819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        if (mOffset == mFirstDataOffset) {
605819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            currentPageSamples -= mStartGranulePosition;
606819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            (*out)->meta_data()->setInt32(kKeyValidSamples, currentPageSamples);
607819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        }
6088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        mCurGranulePosition = mCurrentPage.mGranulePosition - currentPageSamples;
6098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
6108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int64_t timeUs = getTimeUsOfGranule(mCurGranulePosition);
6128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    (*out)->meta_data()->setInt64(kKeyTime, timeUs);
6138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint32_t frames = getNumSamplesInPacket(*out);
6158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mCurGranulePosition += frames;
6168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    return OK;
6178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}
6188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihuint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBuffer *buffer) const {
6208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (buffer == NULL || buffer->range_length() < 1) {
6218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return 0;
6228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
6238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint8_t *data = (uint8_t *)buffer->data() + buffer->range_offset();
6258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint8_t toc = data[0];
6268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint8_t config = (toc >> 3) & 0x1f;
6278c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint32_t frameSizesUs[] = {
6288c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        10000, 20000, 40000, 60000, // 0...3
6298c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        10000, 20000, 40000, 60000, // 4...7
6308c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        10000, 20000, 40000, 60000, // 8...11
6318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        10000, 20000,               // 12...13
6328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        10000, 20000,               // 14...15
6338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        2500, 5000, 10000, 20000,   // 16...19
6348c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        2500, 5000, 10000, 20000,   // 20...23
6358c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        2500, 5000, 10000, 20000,   // 24...27
6368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        2500, 5000, 10000, 20000    // 28...31
6378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    };
6388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint32_t frameSizeUs = frameSizesUs[config];
6398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint32_t numFrames;
6418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint8_t c = toc & 3;
6428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    switch (c) {
6438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    case 0:
6448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        numFrames = 1;
6458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        break;
6468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    case 1:
6478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    case 2:
6488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        numFrames = 2;
6498c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        break;
6508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    case 3:
6518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (buffer->range_length() < 3) {
6528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            numFrames = 0;
6538c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        } else {
6548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            numFrames = data[2] & 0x3f;
6558c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
6568c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        break;
6578c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    default:
6588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        TRESPASS();
6598c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
6608c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6618c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint32_t numSamples = frameSizeUs * numFrames * kOpusSampleRate / 1000000;
6628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    return numSamples;
6638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}
6648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::_readNextPacket(MediaBuffer **out, bool calcVorbisTimestamp) {
666ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = NULL;
667ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
668ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MediaBuffer *buffer = NULL;
669ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t timeUs = -1;
670ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
671ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (;;) {
672ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        size_t i;
673ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        size_t packetSize = 0;
674ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        bool gotFullPacket = false;
675ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) {
676ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            uint8_t lace = mCurrentPage.mLace[i];
677ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
678ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            packetSize += lace;
679ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
680ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (lace < 255) {
681ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                gotFullPacket = true;
682ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                ++i;
683ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                break;
684ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
685ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
686ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
687ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (mNextLaceIndex < mCurrentPage.mNumSegments) {
688c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments;
689ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            for (size_t j = 0; j < mNextLaceIndex; ++j) {
690ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                dataOffset += mCurrentPage.mLace[j];
691ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
692ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
693ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            size_t fullSize = packetSize;
694ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer != NULL) {
695ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                fullSize += buffer->range_length();
696ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
697ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            MediaBuffer *tmp = new MediaBuffer(fullSize);
698ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer != NULL) {
699ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                memcpy(tmp->data(), buffer->data(), buffer->range_length());
700ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                tmp->set_range(0, buffer->range_length());
701ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer->release();
702ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber            } else {
703ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                tmp->set_range(0, 0);
704ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
705ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            buffer = tmp;
706ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
707ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            ssize_t n = mSource->readAt(
708ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    dataOffset,
709ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    (uint8_t *)buffer->data() + buffer->range_length(),
710ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    packetSize);
711ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
712ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (n < (ssize_t)packetSize) {
713ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                ALOGV("failed to read %zu bytes at %#016llx, got %zd bytes",
714ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                        packetSize, (long long)dataOffset, n);
715ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return ERROR_IO;
716ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
717ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
718ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            buffer->set_range(0, fullSize);
719ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
720ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mNextLaceIndex = i;
721ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
722ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (gotFullPacket) {
723ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // We've just read the entire packet.
724ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
725db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                if (mFirstPacketInPage) {
726db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                    buffer->meta_data()->setInt32(
727db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                            kKeyValidSamples, mCurrentPageSamples);
728db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                    mFirstPacketInPage = false;
729db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                }
730db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
7318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih                if (calcVorbisTimestamp) {
7328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih                    int32_t curBlockSize = getPacketBlockSize(buffer);
7337a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    if (mCurrentPage.mPrevPacketSize < 0) {
7347a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        mCurrentPage.mPrevPacketSize = curBlockSize;
7357a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        mCurrentPage.mPrevPacketPos =
7367a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                                mCurrentPage.mGranulePosition - mCurrentPageSamples;
7377a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
7387a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    } else {
7397a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        // The effective block size is the average of the two overlapped blocks
7407a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        int32_t actualBlockSize =
7417a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                                (curBlockSize + mCurrentPage.mPrevPacketSize) / 2;
7427a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
7437a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        // The actual size output by the decoder will be half the effective
7447a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        // size, due to the overlap
7457a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        mCurrentPage.mPrevPacketPos += actualBlockSize / 2;
7467a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        mCurrentPage.mPrevPacketSize = curBlockSize;
7477a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    }
7487a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
7497a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                }
750ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                *out = buffer;
751ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
752ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return OK;
753ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
754ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
755ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            // fall through, the buffer now contains the start of the packet.
756ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
757ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
758ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments);
759ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
760ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mOffset += mCurrentPageSize;
761ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ssize_t n = readPage(mOffset, &mCurrentPage);
762ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
763ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (n <= 0) {
764ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer) {
765ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer->release();
766ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer = NULL;
767ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
768ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
769a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("readPage returned %zd", n);
770ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
771ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return n < 0 ? n : (status_t)ERROR_END_OF_STREAM;
772ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
773ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
774db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        mCurrentPageSamples =
775db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            mCurrentPage.mGranulePosition - mPrevGranulePosition;
776db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        mFirstPacketInPage = true;
777db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
778db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        mPrevGranulePosition = mCurrentPage.mGranulePosition;
779db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
780ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mCurrentPageSize = n;
781ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mNextLaceIndex = 0;
782ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
783ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (buffer != NULL) {
784ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if ((mCurrentPage.mFlags & 1) == 0) {
785ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // This page does not continue the packet, i.e. the packet
786ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // is already complete.
787ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
788ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                if (timeUs >= 0) {
789ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
790ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                }
791ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
792db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                buffer->meta_data()->setInt32(
793db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                        kKeyValidSamples, mCurrentPageSamples);
794db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                mFirstPacketInPage = false;
795db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
796ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                *out = buffer;
797ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
798ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return OK;
799ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
800ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
801ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
802ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
803ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
8048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::init() {
805ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mMeta = new MetaData;
8068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mMeta->setCString(kKeyMIMEType, mMimeType);
807ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
8085a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    status_t err;
8098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    MediaBuffer *packet;
8108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    for (size_t i = 0; i < mNumHeaders; ++i) {
8118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        // ignore timestamp for configuration packets
8128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != OK) {
8138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return err;
8148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
8158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        ALOGV("read packet of size %zu\n", packet->range_length());
8168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        err = verifyHeader(packet, /* type = */ i * 2 + 1);
8178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        packet->release();
8188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        packet = NULL;
8198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (err != OK) {
8208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return err;
8218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
8225a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
82396f52cde23982f668592418a9548045237d5e327Andreas Huber
82496f52cde23982f668592418a9548045237d5e327Andreas Huber    mFirstDataOffset = mOffset + mCurrentPageSize;
8255a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber
8263fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    off64_t size;
8273fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    uint64_t lastGranulePosition;
8283fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    if (!(mSource->flags() & DataSource::kIsCachingDataSource)
8293fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            && mSource->getSize(&size) == OK
8303fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            && findPrevGranulePosition(size, &lastGranulePosition) == OK) {
8313fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // Let's assume it's cheap to seek to the end.
8323fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // The granule position of the final page in the stream will
8333fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // give us the exact duration of the content, something that
8343fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // we can only approximate using avg. bitrate if seeking to
8353fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // the end is too expensive or impossible (live streaming).
8363fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        int64_t durationUs = getTimeUsOfGranule(lastGranulePosition);
8383fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8393fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        mMeta->setInt64(kKeyDuration, durationUs);
8403fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8413fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        buildTableOfContents();
8423fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
8433fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8445a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    return OK;
845ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
846ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
8478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihvoid MyOggExtractor::buildTableOfContents() {
8483fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    off64_t offset = mFirstDataOffset;
8493fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    Page page;
8503fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    ssize_t pageSize;
8513fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    while ((pageSize = readPage(offset, &page)) > 0) {
8523fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        mTableOfContents.push();
8533fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8543fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        TOCEntry &entry =
8553fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            mTableOfContents.editItemAt(mTableOfContents.size() - 1);
8563fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8573fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        entry.mPageOffset = offset;
8588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        entry.mTimeUs = getTimeUsOfGranule(page.mGranulePosition);
8593fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8603fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        offset += (size_t)pageSize;
8613fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
8623fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8633fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    // Limit the maximum amount of RAM we spend on the table of contents,
8643fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    // if necessary thin out the table evenly to trim it down to maximum
8653fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    // size.
8663fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8673fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    static const size_t kMaxTOCSize = 8192;
8683fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    static const size_t kMaxNumTOCEntries = kMaxTOCSize / sizeof(TOCEntry);
8693fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8703fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    size_t numerator = mTableOfContents.size();
8713fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8723fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    if (numerator > kMaxNumTOCEntries) {
8733fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        size_t denom = numerator - kMaxNumTOCEntries;
8743fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8753fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        size_t accum = 0;
8763fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        for (ssize_t i = mTableOfContents.size() - 1; i >= 0; --i) {
8773fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            accum += denom;
8783fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            if (accum >= numerator) {
8793fd91baee812919f53a85c5c05f32606313f8334Andreas Huber                mTableOfContents.removeAt(i);
8803fd91baee812919f53a85c5c05f32606313f8334Andreas Huber                accum -= numerator;
8813fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            }
8823fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        }
8833fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
8843fd91baee812919f53a85c5c05f32606313f8334Andreas Huber}
8853fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8868c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihint32_t MyOggExtractor::getPacketBlockSize(MediaBuffer *buffer) {
8877a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    const uint8_t *data =
8887a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen        (const uint8_t *)buffer->data() + buffer->range_offset();
8897a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen
8907a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    size_t size = buffer->range_length();
8917a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen
8927a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ogg_buffer buf;
8937a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    buf.data = (uint8_t *)data;
8947a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    buf.size = size;
8957a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    buf.refcount = 1;
8967a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    buf.ptr.owner = NULL;
8977a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen
8987a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ogg_reference ref;
8997a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ref.buffer = &buf;
9007a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ref.begin = 0;
9017a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ref.length = size;
9027a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ref.next = NULL;
9037a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen
9047a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ogg_packet pack;
9057a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    pack.packet = &ref;
9067a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    pack.bytes = ref.length;
9077a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    pack.b_o_s = 0;
9087a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    pack.e_o_s = 0;
9097a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    pack.granulepos = 0;
9107a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    pack.packetno = 0;
9117a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen
9127a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    return vorbis_packet_blocksize(&mVi, &pack);
9137a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen}
9147a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen
9158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihint64_t MyOpusExtractor::getTimeUsOfGranule(uint64_t granulePos) const {
9168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint64_t pcmSamplePosition = 0;
9178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (granulePos > mCodecDelay) {
9188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        pcmSamplePosition = granulePos - mCodecDelay;
9198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
9208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    return pcmSamplePosition * 1000000ll / kOpusSampleRate;
9218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}
9228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::verifyHeader(MediaBuffer *buffer, uint8_t type) {
9248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    switch (type) {
9258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean
9268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        // header and comments such that we can share code with MyVorbisExtractor.
9278c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        case 1:
9288c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return verifyOpusHeader(buffer);
9298c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        case 3:
9308c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return verifyOpusComments(buffer);
9318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        default:
9328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return INVALID_OPERATION;
9338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
9348c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}
9358c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::verifyOpusHeader(MediaBuffer *buffer) {
9378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    const size_t kOpusHeaderSize = 19;
9388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    const uint8_t *data =
9398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        (const uint8_t *)buffer->data() + buffer->range_offset();
9408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    size_t size = buffer->range_length();
9428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (size < kOpusHeaderSize
9448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            || memcmp(data, "OpusHead", 8)
9458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            || /* version = */ data[8] != 1) {
9468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return ERROR_MALFORMED;
9478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
9488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9498c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mChannelCount = data[9];
9508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mCodecDelay = U16LE_AT(&data[10]);
9518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mMeta->setData(kKeyOpusHeader, 0, data, size);
9538c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mMeta->setInt32(kKeySampleRate, kOpusSampleRate);
9548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mMeta->setInt32(kKeyChannelCount, mChannelCount);
9558c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mMeta->setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/);
9568c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mMeta->setInt64(kKeyOpusCodecDelay /* ns */,
9578c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            mCodecDelay /* sample/s */ * 1000000000 / kOpusSampleRate);
9588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9598c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    return OK;
9608c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}
9618c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::verifyOpusComments(MediaBuffer *buffer) {
9638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // add artificial framing bit so we can reuse _vorbis_unpack_comment
9648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int32_t commentSize = buffer->range_length() + 1;
9658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    sp<ABuffer> aBuf = new ABuffer(commentSize);
9668c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (aBuf->capacity() <= buffer->range_length()) {
9678c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return ERROR_MALFORMED;
9688c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
9698c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint8_t* commentData = aBuf->data();
9718c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    memcpy(commentData,
9728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            (uint8_t *)buffer->data() + buffer->range_offset(),
9738c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            buffer->range_length());
9748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ogg_buffer buf;
9768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.data = commentData;
9778c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.size = commentSize;
9788c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.refcount = 1;
9798c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.ptr.owner = NULL;
9808c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9818c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ogg_reference ref;
9828c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.buffer = &buf;
9838c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.begin = 0;
9848c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.length = commentSize;
9858c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.next = NULL;
9868c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9878c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    oggpack_buffer bits;
9888c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    oggpack_readinit(&bits, &ref);
9898c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9908c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // skip 'OpusTags'
9918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    const char *OpusTags = "OpusTags";
9928c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    const int32_t headerLen = strlen(OpusTags);
9938c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int32_t framingBitOffset = headerLen;
9948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    for (int i = 0; i < headerLen; ++i) {
9958c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        char chr = oggpack_read(&bits, 8);
9968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (chr != OpusTags[i]) {
9978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return ERROR_MALFORMED;
9988c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
9998c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int32_t vendorLen = oggpack_read(&bits, 32);
10028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    framingBitOffset += 4;
10038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (vendorLen < 0 || vendorLen > commentSize - 8) {
10048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return ERROR_MALFORMED;
10058c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // skip vendor string
10078c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    framingBitOffset += vendorLen;
10088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    for (int i = 0; i < vendorLen; ++i) {
10098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        oggpack_read(&bits, 8);
10108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int32_t n = oggpack_read(&bits, 32);
10138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    framingBitOffset += 4;
10148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (n < 0 || n > ((commentSize - oggpack_bytes(&bits)) >> 2)) {
10158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return ERROR_MALFORMED;
10168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    for (int i = 0; i < n; ++i) {
10188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        int32_t len = oggpack_read(&bits, 32);
10198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        framingBitOffset += 4;
10208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (len  < 0 || len  > (commentSize - oggpack_bytes(&bits))) {
10218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return ERROR_MALFORMED;
10228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
10238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        framingBitOffset += len;
10248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        for (int j = 0; j < len; ++j) {
10258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            oggpack_read(&bits, 8);
10268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
10278c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10288c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (framingBitOffset < 0 || framingBitOffset >= commentSize) {
10298c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return ERROR_MALFORMED;
10308c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    commentData[framingBitOffset] = 1;
10328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.data = commentData + headerLen;
10348c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.size = commentSize - headerLen;
10358c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.refcount = 1;
10368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.ptr.owner = NULL;
10378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.buffer = &buf;
10398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.begin = 0;
10408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.length = commentSize - headerLen;
10418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.next = NULL;
10428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    oggpack_readinit(&bits, &ref);
10448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int err = _vorbis_unpack_comment(&mVc, &bits);
10458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (0 != err) {
10468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return ERROR_MALFORMED;
10478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10498c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    parseFileMetaData();
10508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    return OK;
10518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}
10528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10535a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huberstatus_t MyVorbisExtractor::verifyHeader(
1054ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        MediaBuffer *buffer, uint8_t type) {
1055ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    const uint8_t *data =
1056ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
1057ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1058ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t size = buffer->range_length();
1059ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
10605a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) {
10615a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return ERROR_MALFORMED;
10625a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
1063ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1064ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ogg_buffer buf;
1065ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.data = (uint8_t *)data;
1066ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.size = size;
1067ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.refcount = 1;
1068ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.ptr.owner = NULL;
1069ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1070ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ogg_reference ref;
1071ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.buffer = &buf;
1072ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.begin = 0;
1073ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.length = size;
1074ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.next = NULL;
1075ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1076ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    oggpack_buffer bits;
1077ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    oggpack_readinit(&bits, &ref);
1078ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1079fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen    if (oggpack_read(&bits, 8) != type) {
1080fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen        return ERROR_MALFORMED;
1081fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen    }
1082ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < 6; ++i) {
1083ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        oggpack_read(&bits, 8);  // skip 'vorbis'
1084ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
1085ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1086ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    switch (type) {
1087ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 1:
1088ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
1089fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen            if (0 != _vorbis_unpack_info(&mVi, &bits)) {
1090fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen                return ERROR_MALFORMED;
1091fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen            }
1092ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1093ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setData(kKeyVorbisInfo, 0, data, size);
1094ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setInt32(kKeySampleRate, mVi.rate);
1095ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setInt32(kKeyChannelCount, mVi.channels);
1096ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
10973856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("lower-bitrate = %ld", mVi.bitrate_lower);
10983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
10993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
11003856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("window-bitrate = %ld", mVi.bitrate_window);
11017a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen            ALOGV("blocksizes: %d/%d",
11027a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    vorbis_info_blocksize(&mVi, 0),
11037a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    vorbis_info_blocksize(&mVi, 1)
11047a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    );
1105ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1106c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t size;
1107ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (mSource->getSize(&size) == OK) {
1108ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                uint64_t bps = approxBitrate();
1109f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang                if (bps != 0) {
1110f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang                    mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
1111f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang                }
1112ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
1113ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
1114ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
1115ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1116ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 3:
1117ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
11185a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            if (0 != _vorbis_unpack_comment(&mVc, &bits)) {
11195a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber                return ERROR_MALFORMED;
11205a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            }
11214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
11224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            parseFileMetaData();
1123ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
1124ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
1125ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1126ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 5:
1127ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
11285a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            if (0 != _vorbis_unpack_books(&mVi, &bits)) {
11295a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber                return ERROR_MALFORMED;
11305a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            }
1131ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1132ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setData(kKeyVorbisBooks, 0, data, size);
1133ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
1134ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
1135ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
11365a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber
11375a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    return OK;
1138ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1139ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
11408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihuint64_t MyVorbisExtractor::approxBitrate() const {
1141ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mVi.bitrate_nominal != 0) {
1142ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return mVi.bitrate_nominal;
1143ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
1144ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1145ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
1146ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1147ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
11488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihvoid MyOggExtractor::parseFileMetaData() {
11494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta = new MetaData;
11504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
11514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1152856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten    for (int i = 0; i < mVc.comments; ++i) {
1153856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        const char *comment = mVc.user_comments[i];
1154856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        size_t commentLength = mVc.comment_lengths[i];
1155856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        parseVorbisComment(mFileMeta, comment, commentLength);
1156df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
1157856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten    }
1158856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten}
1159856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten
1160856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenvoid parseVorbisComment(
1161856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        const sp<MetaData> &fileMeta, const char *comment, size_t commentLength)
1162856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten{
11634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    struct {
11644595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        const char *const mTag;
11654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        uint32_t mKey;
11664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    } kMap[] = {
11674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "TITLE", kKeyTitle },
11684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "ARTIST", kKeyArtist },
116911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        { "ALBUMARTIST", kKeyAlbumArtist },
117011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        { "ALBUM ARTIST", kKeyAlbumArtist },
117111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        { "COMPILATION", kKeyCompilation },
11724595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "ALBUM", kKeyAlbum },
11734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "COMPOSER", kKeyComposer },
11744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "GENRE", kKeyGenre },
11754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "AUTHOR", kKeyAuthor },
11764595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "TRACKNUMBER", kKeyCDTrackNumber },
11774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "DISCNUMBER", kKeyDiscNumber },
11784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "DATE", kKeyDate },
117975c6d4267db3cca1d06292cae09a40e2d1fcedbdAndreas Lillvik        { "YEAR", kKeyYear },
11804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "LYRICIST", kKeyWriter },
11814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
11828ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber        { "ANDROID_LOOP", kKeyAutoLoop },
11834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    };
11844595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
11854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
11864595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            size_t tagLen = strlen(kMap[j].mTag);
11874595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (!strncasecmp(kMap[j].mTag, comment, tagLen)
11884595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                    && comment[tagLen] == '=') {
11894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                if (kMap[j].mKey == kKeyAlbumArt) {
11904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                    extractAlbumArt(
1191856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten                            fileMeta,
11924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                            &comment[tagLen + 1],
1193856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten                            commentLength - tagLen - 1);
11948ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber                } else if (kMap[j].mKey == kKeyAutoLoop) {
11958ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber                    if (!strcasecmp(&comment[tagLen + 1], "true")) {
1196856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten                        fileMeta->setInt32(kKeyAutoLoop, true);
11978ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber                    }
11984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                } else {
1199856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten                    fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
12004595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                }
12014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            }
12024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
12034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber}
12054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1206856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt(
1207856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        const sp<MetaData> &fileMeta, const void *data, size_t size) {
12083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("extractAlbumArt from '%s'", (const char *)data);
12094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
121074814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim    sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size));
121174814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim    if (flacBuffer == NULL) {
121229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("malformed base64 encoded data.");
12134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        return;
12144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
121674814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim    size_t flacSize = flacBuffer->size();
121774814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim    uint8_t *flac = flacBuffer->data();
1218a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("got flac of size %zu", flacSize);
12194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t picType;
12214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t typeLen;
12224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t descLen;
12234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t dataLen;
12244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    char type[128];
12254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 8) {
122774814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim        return;
12284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12294595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12304595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    picType = U32_AT(flac);
12314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (picType != 3) {
12334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        // This is not a front cover.
123474814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim        return;
12354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12364595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12374595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    typeLen = U32_AT(&flac[4]);
1238c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen    if (typeLen > sizeof(type) - 1) {
123974814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim        return;
12404595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12414595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1242c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen    // we've already checked above that flacSize >= 8
1243c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen    if (flacSize - 8 < typeLen) {
124474814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim        return;
12454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12474595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    memcpy(type, &flac[8], typeLen);
12484595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    type[typeLen] = '\0';
12494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12503856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("picType = %d, type = '%s'", picType, type);
12514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (!strcmp(type, "-->")) {
12534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        // This is not inline cover art, but an external url instead.
125474814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim        return;
12554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    descLen = U32_AT(&flac[8 + typeLen]);
12584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1259c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen    if (flacSize < 32 ||
1260c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen        flacSize - 32 < typeLen ||
1261c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen        flacSize - 32 - typeLen < descLen) {
126274814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim        return;
12634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12644595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
12664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1267c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen
1268c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen    // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
1269c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen    if (flacSize - 32 - typeLen - descLen < dataLen) {
127074814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim        return;
12714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12724595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1273a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("got image data, %zu trailing bytes",
12744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber         flacSize - 32 - typeLen - descLen - dataLen);
12754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1276856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten    fileMeta->setData(
12774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
12784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1279856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten    fileMeta->setCString(kKeyAlbumArtMIME, type);
12804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber}
12814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1282ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
1283ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1284ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::OggExtractor(const sp<DataSource> &source)
1285ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mDataSource(source),
1286ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mInitCheck(NO_INIT),
1287ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mImpl(NULL) {
12888c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    for (int i = 0; i < 2; ++i) {
12898c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (mImpl != NULL) {
12908c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            delete mImpl;
12918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
12928c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (i == 0) {
12938c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            mImpl = new MyVorbisExtractor(mDataSource);
12948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        } else {
12958c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            mImpl = new MyOpusExtractor(mDataSource);
12968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
12978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        mInitCheck = mImpl->seekToOffset(0);
1298ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
12998c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (mInitCheck == OK) {
13008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            mInitCheck = mImpl->init();
13018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            if (mInitCheck == OK) {
13028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih                break;
13038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            }
13048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
13055a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
1306ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1307ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1308ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::~OggExtractor() {
1309ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    delete mImpl;
1310ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mImpl = NULL;
1311ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1312ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1313ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersize_t OggExtractor::countTracks() {
1314ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mInitCheck != OK ? 0 : 1;
1315ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1316ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1317ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MediaSource> OggExtractor::getTrack(size_t index) {
1318ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (index >= 1) {
1319ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return NULL;
1320ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
1321ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1322ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return new OggSource(this);
1323ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1324ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1325ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getTrackMetaData(
132684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        size_t index, uint32_t /* flags */) {
1327ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (index >= 1) {
1328ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return NULL;
1329ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
1330ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1331ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mImpl->getFormat();
1332ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1333ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1334ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getMetaData() {
13354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    return mImpl->getFileMetaData();
1336ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1337ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1338ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberbool SniffOgg(
13395a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
13405a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        sp<AMessage> *) {
1341ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    char tmp[4];
1342ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
1343ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return false;
1344ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
1345ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1346ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG);
1347ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *confidence = 0.2f;
1348ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1349ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return true;
1350ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1351ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1352ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}  // namespace android
1353