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>
2659acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik 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 {
182894aa94e101f9ff9a074f2bcc4d1fb989cf9ea04Chad Brubaker        if (granulePos > INT64_MAX / 1000000ll) {
183894aa94e101f9ff9a074f2bcc4d1fb989cf9ea04Chad Brubaker            return INT64_MAX;
184894aa94e101f9ff9a074f2bcc4d1fb989cf9ea04Chad Brubaker        }
1858c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return granulePos * 1000000ll / mVi.rate;
1868c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
1878c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
1888c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type);
1898c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih};
1908c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
1918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstruct MyOpusExtractor : public MyOggExtractor {
1928c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    static const int32_t kOpusSampleRate = 48000;
1938c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    static const int64_t kOpusSeekPreRollUs = 80000; // 80 ms
1948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
1958c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    MyOpusExtractor(const sp<DataSource> &source)
1968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        : MyOggExtractor(source, MEDIA_MIMETYPE_AUDIO_OPUS, /*numHeaders*/ 2, kOpusSeekPreRollUs),
1978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih          mChannelCount(0),
198819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih          mCodecDelay(0),
199819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih          mStartGranulePosition(-1) {
2008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
2018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
2028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual uint64_t approxBitrate() const {
2038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return 0;
2048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
2058c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
2068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual status_t readNextPacket(MediaBuffer **buffer);
2078c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
2088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihprotected:
2098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const;
2108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type);
2118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
2128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihprivate:
2138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    status_t verifyOpusHeader(MediaBuffer *buffer);
2148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    status_t verifyOpusComments(MediaBuffer *buffer);
2158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint32_t getNumSamplesInPacket(MediaBuffer *buffer) const;
2168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
2178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint8_t mChannelCount;
2188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint16_t mCodecDelay;
219819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih    int64_t mStartGranulePosition;
220ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber};
221ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
222856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt(
223856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        const sp<MetaData> &fileMeta, const void *data, size_t size);
224856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten
225ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
226ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
227ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::OggSource(const sp<OggExtractor> &extractor)
228ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mExtractor(extractor),
229ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mStarted(false) {
230ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
231ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
232ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::~OggSource() {
233ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mStarted) {
234ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        stop();
235ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
236ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
237ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
238ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggSource::getFormat() {
239ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mExtractor->mImpl->getFormat();
240ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
241ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
24284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t OggSource::start(MetaData * /* params */) {
243ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mStarted) {
244ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return INVALID_OPERATION;
245ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
246ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
247ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mStarted = true;
248ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
249ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
250ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
251ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
252ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::stop() {
253ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mStarted = false;
254ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
255ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
256ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
257ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
258ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::read(
259ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
260ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = NULL;
261ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
262ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t seekTimeUs;
263abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
264abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
2658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        status_t err = mExtractor->mImpl->seekToTime(seekTimeUs);
2668c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (err != OK) {
2678c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return err;
268ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
269ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
270ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
271ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MediaBuffer *packet;
2728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    status_t err = mExtractor->mImpl->readNextPacket(&packet);
273ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
274ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (err != OK) {
275ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return err;
276ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
277ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
278ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0
279ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t timeUs;
280ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) {
281df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("found time = %lld us", timeUs);
282ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    } else {
283df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("NO time");
284ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
285ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif
286ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
2878bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    packet->meta_data()->setInt32(kKeyIsSyncFrame, 1);
2888bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
289ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = packet;
290ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
291ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
292ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
293ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
294ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
295ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
2968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert ShihMyOggExtractor::MyOggExtractor(
2978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        const sp<DataSource> &source,
2988c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        const char *mimeType,
2998c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        size_t numHeaders,
3008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        int64_t seekPreRollUs)
301ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mSource(source),
302ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mOffset(0),
3038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih      mCurGranulePosition(0),
304db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber      mPrevGranulePosition(0),
305ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mCurrentPageSize(0),
306db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber      mFirstPacketInPage(true),
307db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber      mCurrentPageSamples(0),
30896f52cde23982f668592418a9548045237d5e327Andreas Huber      mNextLaceIndex(0),
3098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih      mMimeType(mimeType),
3108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih      mNumHeaders(numHeaders),
3118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih      mSeekPreRollUs(seekPreRollUs),
31296f52cde23982f668592418a9548045237d5e327Andreas Huber      mFirstDataOffset(-1) {
313ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPage.mNumSegments = 0;
3144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
3154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_info_init(&mVi);
3164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_comment_init(&mVc);
317ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
318ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
3198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert ShihMyOggExtractor::~MyOggExtractor() {
3204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_comment_clear(&mVc);
3214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_info_clear(&mVi);
322ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
323ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
3248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihsp<MetaData> MyOggExtractor::getFormat() const {
325ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mMeta;
326ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
327ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
3288c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::findNextPage(
329c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t startOffset, off64_t *pageOffset) {
330ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *pageOffset = startOffset;
331ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
332ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (;;) {
333ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        char signature[4];
334ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
335ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
336ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (n < 4) {
337ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            *pageOffset = 0;
338ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
339ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
340ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
341ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
342ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (!memcmp(signature, "OggS", 4)) {
343ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (*pageOffset > startOffset) {
3443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("skipped %lld bytes of junk to reach next frame",
345ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                     (long long)(*pageOffset - startOffset));
346ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
347ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
348ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return OK;
349ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
350ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
351ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ++*pageOffset;
352ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
353ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
354ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
355db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// Given the offset of the "current" page, find the page immediately preceding
356db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// it (if any) and return its granule position.
357db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// To do this we back up from the "current" page's offset until we find any
358db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// page preceding it and then scan forward to just before the current page.
3598c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::findPrevGranulePosition(
3603fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        off64_t pageOffset, uint64_t *granulePos) {
3613fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    *granulePos = 0;
3623fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
363c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t prevPageOffset = 0;
364c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t prevGuess = pageOffset;
365db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    for (;;) {
366db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (prevGuess >= 5000) {
367db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            prevGuess -= 5000;
368db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        } else {
369db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            prevGuess = 0;
370db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
371db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
372ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("backing up %lld bytes", (long long)(pageOffset - prevGuess));
373db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
3743fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        status_t err = findNextPage(prevGuess, &prevPageOffset);
3758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (err == ERROR_END_OF_STREAM) {
3768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            // We are at the last page and didn't back off enough;
3778c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            // back off 5000 bytes more and try again.
3788c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            continue;
3798c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        } else if (err != OK) {
3803fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            return err;
3813fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        }
382db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
383db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (prevPageOffset < pageOffset || prevGuess == 0) {
384db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            break;
385db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
386db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    }
387db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
388db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    if (prevPageOffset == pageOffset) {
389db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        // We did not find a page preceding this one.
3903fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        return UNKNOWN_ERROR;
391db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    }
392db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
3933856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("prevPageOffset at %lld, pageOffset at %lld",
394ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar            (long long)prevPageOffset, (long long)pageOffset);
395db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
396db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    for (;;) {
397db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        Page prevPage;
398db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        ssize_t n = readPage(prevPageOffset, &prevPage);
399db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
400db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (n <= 0) {
4013fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            return (status_t)n;
402db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
403db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
404db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        prevPageOffset += n;
405db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
406db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (prevPageOffset == pageOffset) {
4073fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            *granulePos = prevPage.mGranulePosition;
4083fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            return OK;
409db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
410db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    }
411db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber}
412db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
4138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::seekToTime(int64_t timeUs) {
4148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    timeUs -= mSeekPreRollUs;
4158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (timeUs < 0) {
4168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        timeUs = 0;
4178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
4188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
4193fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    if (mTableOfContents.isEmpty()) {
4203fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // Perform approximate seeking based on avg. bitrate.
4218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        uint64_t bps = approxBitrate();
4228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (bps <= 0) {
4238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return INVALID_OPERATION;
4248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
4253fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
4268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        off64_t pos = timeUs * bps / 8000000ll;
4273fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
428ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("seeking to offset %lld", (long long)pos);
4293fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        return seekToOffset(pos);
4303fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
4313fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
4323fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    size_t left = 0;
433225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar    size_t right_plus_one = mTableOfContents.size();
434225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar    while (left < right_plus_one) {
435225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar        size_t center = left + (right_plus_one - left) / 2;
4363fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
4373fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        const TOCEntry &entry = mTableOfContents.itemAt(center);
4383fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
4393fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        if (timeUs < entry.mTimeUs) {
440225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar            right_plus_one = center;
4413fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        } else if (timeUs > entry.mTimeUs) {
4423fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            left = center + 1;
4433fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        } else {
444225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar            left = center;
4453fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            break;
4463fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        }
4473fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
4483fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
449225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar    if (left == mTableOfContents.size()) {
450225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar        --left;
451225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar    }
452225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar
4533fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    const TOCEntry &entry = mTableOfContents.itemAt(left);
4543fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
455a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("seeking to entry %zu / %zu at offset %lld",
456ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar         left, mTableOfContents.size(), (long long)entry.mPageOffset);
4573fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
4583fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    return seekToOffset(entry.mPageOffset);
4593fd91baee812919f53a85c5c05f32606313f8334Andreas Huber}
4603fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
4618c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::seekToOffset(off64_t offset) {
46296f52cde23982f668592418a9548045237d5e327Andreas Huber    if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) {
46396f52cde23982f668592418a9548045237d5e327Andreas Huber        // Once we know where the actual audio data starts (past the headers)
46496f52cde23982f668592418a9548045237d5e327Andreas Huber        // don't ever seek to anywhere before that.
46596f52cde23982f668592418a9548045237d5e327Andreas Huber        offset = mFirstDataOffset;
46696f52cde23982f668592418a9548045237d5e327Andreas Huber    }
46796f52cde23982f668592418a9548045237d5e327Andreas Huber
468c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t pageOffset;
469ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    status_t err = findNextPage(offset, &pageOffset);
470ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
471ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (err != OK) {
472ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return err;
473ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
474ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
475db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    // We found the page we wanted to seek to, but we'll also need
476db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    // the page preceding it to determine how many valid samples are on
477db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    // this page.
4783fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    findPrevGranulePosition(pageOffset, &mPrevGranulePosition);
479db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
480ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mOffset = pageOffset;
481ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
482ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPageSize = 0;
483db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    mFirstPacketInPage = true;
484db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    mCurrentPageSamples = 0;
485ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPage.mNumSegments = 0;
4867a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    mCurrentPage.mPrevPacketSize = -1;
487ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mNextLaceIndex = 0;
488ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
489ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    // XXX what if new page continues packet from last???
490ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
491ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
492ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
493ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
4948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihssize_t MyOggExtractor::readPage(off64_t offset, Page *page) {
495ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    uint8_t header[27];
496df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber    ssize_t n;
497df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber    if ((n = mSource->readAt(offset, header, sizeof(header)))
498ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            < (ssize_t)sizeof(header)) {
499ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("failed to read %zu bytes at offset %#016llx, got %zd bytes",
500ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                sizeof(header), (long long)offset, n);
501ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
502df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber        if (n < 0) {
503df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber            return n;
504df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber        } else if (n == 0) {
505df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber            return ERROR_END_OF_STREAM;
506df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber        } else {
507df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber            return ERROR_IO;
508df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber        }
509ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
510ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
511ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (memcmp(header, "OggS", 4)) {
512ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_MALFORMED;
513ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
514ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
515ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (header[4] != 0) {
516ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        // Wrong version.
517ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
518ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_UNSUPPORTED;
519ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
520ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
521ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mFlags = header[5];
522ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
523ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (page->mFlags & ~7) {
524ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        // Only bits 0-2 are defined in version 0.
525ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_MALFORMED;
526ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
527ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
528ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mGranulePosition = U64LE_AT(&header[6]);
529ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
530ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0
531ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    printf("granulePosition = %llu (0x%llx)\n",
532ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber           page->mGranulePosition, page->mGranulePosition);
533ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif
534ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
535ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mSerialNo = U32LE_AT(&header[14]);
536ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mPageNo = U32LE_AT(&header[18]);
537ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
538ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mNumSegments = header[26];
539ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mSource->readAt(
540ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                offset + sizeof(header), page->mLace, page->mNumSegments)
541ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            < (ssize_t)page->mNumSegments) {
542ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_IO;
543ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
544ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
545ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t totalSize = 0;;
546ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < page->mNumSegments; ++i) {
547ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        totalSize += page->mLace[i];
548ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
549ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5505a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#if 0
551ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    String8 tmp;
552ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < page->mNumSegments; ++i) {
553ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        char x[32];
554ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]);
555ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
556ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        tmp.append(x);
557ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
558ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string());
5605a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#endif
561ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
562ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return sizeof(header) + page->mNumSegments + totalSize;
563ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
564ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::readNextPacket(MediaBuffer **out) {
566819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih    if (mOffset <= mFirstDataOffset && mStartGranulePosition < 0) {
567819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        // The first sample might not start at time 0; find out where by subtracting
568819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        // the number of samples on the first page from the granule position
569819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        // (position of last complete sample) of the first page. This happens
570819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        // the first time before we attempt to read a packet from the first page.
571819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        MediaBuffer *mBuf;
572819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        uint32_t numSamples = 0;
573819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        uint64_t curGranulePosition = 0;
574819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        while (true) {
575819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            status_t err = _readNextPacket(&mBuf, /* calcVorbisTimestamp = */false);
576819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            if (err != OK && err != ERROR_END_OF_STREAM) {
577819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih                return err;
578819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            }
579819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            // First two pages are header pages.
580819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            if (err == ERROR_END_OF_STREAM || mCurrentPage.mPageNo > 2) {
581d9b32c160663d04afc5cf91fe2ed893c45074765Dongwon Kang                if (mBuf != NULL) {
582d9b32c160663d04afc5cf91fe2ed893c45074765Dongwon Kang                    mBuf->release();
583d9b32c160663d04afc5cf91fe2ed893c45074765Dongwon Kang                    mBuf = NULL;
584d9b32c160663d04afc5cf91fe2ed893c45074765Dongwon Kang                }
585819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih                break;
586819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            }
587819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            curGranulePosition = mCurrentPage.mGranulePosition;
588819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            numSamples += getNumSamplesInPacket(mBuf);
589819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            mBuf->release();
590819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            mBuf = NULL;
591819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        }
592819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih
593819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        if (curGranulePosition > numSamples) {
594819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            mStartGranulePosition = curGranulePosition - numSamples;
595819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        } else {
596819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            mStartGranulePosition = 0;
597819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        }
598819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        seekToOffset(0);
599819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih    }
600819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih
6018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    status_t err = _readNextPacket(out, /* calcVorbisTimestamp = */false);
6028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (err != OK) {
6038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return err;
6048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
6058c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int32_t currentPageSamples;
6078c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // Calculate timestamps by accumulating durations starting from the first sample of a page;
6088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // We assume that we only seek to page boundaries.
6098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if ((*out)->meta_data()->findInt32(kKeyValidSamples, &currentPageSamples)) {
6108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        // first packet in page
611819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        if (mOffset == mFirstDataOffset) {
612819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            currentPageSamples -= mStartGranulePosition;
613819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih            (*out)->meta_data()->setInt32(kKeyValidSamples, currentPageSamples);
614819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih        }
6158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        mCurGranulePosition = mCurrentPage.mGranulePosition - currentPageSamples;
6168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
6178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int64_t timeUs = getTimeUsOfGranule(mCurGranulePosition);
6198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    (*out)->meta_data()->setInt64(kKeyTime, timeUs);
6208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint32_t frames = getNumSamplesInPacket(*out);
6228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mCurGranulePosition += frames;
6238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    return OK;
6248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}
6258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihuint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBuffer *buffer) const {
6278c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (buffer == NULL || buffer->range_length() < 1) {
6288c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return 0;
6298c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
6308c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint8_t *data = (uint8_t *)buffer->data() + buffer->range_offset();
6328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint8_t toc = data[0];
6338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint8_t config = (toc >> 3) & 0x1f;
6348c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint32_t frameSizesUs[] = {
6358c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        10000, 20000, 40000, 60000, // 0...3
6368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        10000, 20000, 40000, 60000, // 4...7
6378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        10000, 20000, 40000, 60000, // 8...11
6388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        10000, 20000,               // 12...13
6398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        10000, 20000,               // 14...15
6408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        2500, 5000, 10000, 20000,   // 16...19
6418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        2500, 5000, 10000, 20000,   // 20...23
6428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        2500, 5000, 10000, 20000,   // 24...27
6438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        2500, 5000, 10000, 20000    // 28...31
6448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    };
6458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint32_t frameSizeUs = frameSizesUs[config];
6468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint32_t numFrames;
6488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint8_t c = toc & 3;
6498c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    switch (c) {
6508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    case 0:
6518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        numFrames = 1;
6528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        break;
6538c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    case 1:
6548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    case 2:
6558c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        numFrames = 2;
6568c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        break;
6578c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    case 3:
6588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (buffer->range_length() < 3) {
6598c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            numFrames = 0;
6608c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        } else {
6618c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            numFrames = data[2] & 0x3f;
6628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
6638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        break;
6648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    default:
6658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        TRESPASS();
6668c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
6678c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6688c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint32_t numSamples = frameSizeUs * numFrames * kOpusSampleRate / 1000000;
6698c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    return numSamples;
6708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}
6718c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
6728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::_readNextPacket(MediaBuffer **out, bool calcVorbisTimestamp) {
673ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = NULL;
674ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
675ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MediaBuffer *buffer = NULL;
676ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t timeUs = -1;
677ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
678ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (;;) {
679ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        size_t i;
680ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        size_t packetSize = 0;
681ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        bool gotFullPacket = false;
682ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) {
683ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            uint8_t lace = mCurrentPage.mLace[i];
684ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
685ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            packetSize += lace;
686ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
687ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (lace < 255) {
688ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                gotFullPacket = true;
689ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                ++i;
690ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                break;
691ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
692ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
693ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
694ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (mNextLaceIndex < mCurrentPage.mNumSegments) {
695c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments;
696ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            for (size_t j = 0; j < mNextLaceIndex; ++j) {
697ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                dataOffset += mCurrentPage.mLace[j];
698ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
699ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
700ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            size_t fullSize = packetSize;
701ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer != NULL) {
702ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                fullSize += buffer->range_length();
703ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
7041f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen            if (fullSize > 16 * 1024 * 1024) { // arbitrary limit of 16 MB packet size
7051f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen                if (buffer != NULL) {
7061f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen                    buffer->release();
7071f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen                }
7081f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen                ALOGE("b/36592202");
7091f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen                return ERROR_MALFORMED;
7101f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen            }
7111f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen            MediaBuffer *tmp = new (std::nothrow) MediaBuffer(fullSize);
7121f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen            if (tmp == NULL) {
7131f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen                if (buffer != NULL) {
7141f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen                    buffer->release();
7151f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen                }
7161f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen                ALOGE("b/36592202");
7171f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen                return ERROR_MALFORMED;
7181f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen            }
719ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer != NULL) {
720ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                memcpy(tmp->data(), buffer->data(), buffer->range_length());
721ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                tmp->set_range(0, buffer->range_length());
722ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer->release();
723ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber            } else {
724ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                tmp->set_range(0, 0);
725ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
726ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            buffer = tmp;
727ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
728ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            ssize_t n = mSource->readAt(
729ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    dataOffset,
730ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    (uint8_t *)buffer->data() + buffer->range_length(),
731ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    packetSize);
732ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
733ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (n < (ssize_t)packetSize) {
734a6f2946f15be11db7c2b013fbe69126a799cbf97Wei Jia                buffer->release();
735ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                ALOGV("failed to read %zu bytes at %#016llx, got %zd bytes",
736ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                        packetSize, (long long)dataOffset, n);
737ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return ERROR_IO;
738ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
739ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
740ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            buffer->set_range(0, fullSize);
741ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
742ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mNextLaceIndex = i;
743ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
744ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (gotFullPacket) {
745ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // We've just read the entire packet.
746ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
747db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                if (mFirstPacketInPage) {
748db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                    buffer->meta_data()->setInt32(
749db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                            kKeyValidSamples, mCurrentPageSamples);
750db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                    mFirstPacketInPage = false;
751db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                }
752db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
7538c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih                if (calcVorbisTimestamp) {
7548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih                    int32_t curBlockSize = getPacketBlockSize(buffer);
7557a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    if (mCurrentPage.mPrevPacketSize < 0) {
7567a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        mCurrentPage.mPrevPacketSize = curBlockSize;
7577a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        mCurrentPage.mPrevPacketPos =
7587a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                                mCurrentPage.mGranulePosition - mCurrentPageSamples;
7597a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
7607a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    } else {
7617a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        // The effective block size is the average of the two overlapped blocks
7627a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        int32_t actualBlockSize =
7637a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                                (curBlockSize + mCurrentPage.mPrevPacketSize) / 2;
7647a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
7657a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        // The actual size output by the decoder will be half the effective
7667a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        // size, due to the overlap
7677a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        mCurrentPage.mPrevPacketPos += actualBlockSize / 2;
7687a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                        mCurrentPage.mPrevPacketSize = curBlockSize;
7697a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    }
7707a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
7717a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                }
772ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                *out = buffer;
773ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
774ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return OK;
775ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
776ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
777ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            // fall through, the buffer now contains the start of the packet.
778ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
779ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
780ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments);
781ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
782ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mOffset += mCurrentPageSize;
783ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ssize_t n = readPage(mOffset, &mCurrentPage);
784ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
785ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (n <= 0) {
786ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer) {
787ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer->release();
788ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer = NULL;
789ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
790ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
791a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("readPage returned %zd", n);
792ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
793ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return n < 0 ? n : (status_t)ERROR_END_OF_STREAM;
794ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
795ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
7962369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker        // Prevent a harmless unsigned integer overflow by clamping to 0
7972369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker        if (mCurrentPage.mGranulePosition >= mPrevGranulePosition) {
7982369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker            mCurrentPageSamples =
7992369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker                    mCurrentPage.mGranulePosition - mPrevGranulePosition;
8002369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker        } else {
8012369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker            mCurrentPageSamples = 0;
8022369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker        }
803db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        mFirstPacketInPage = true;
804db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
805db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        mPrevGranulePosition = mCurrentPage.mGranulePosition;
806db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
807ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mCurrentPageSize = n;
808ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mNextLaceIndex = 0;
809ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
810ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (buffer != NULL) {
811ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if ((mCurrentPage.mFlags & 1) == 0) {
812ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // This page does not continue the packet, i.e. the packet
813ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // is already complete.
814ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
815ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                if (timeUs >= 0) {
816ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
817ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                }
818ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
819db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                buffer->meta_data()->setInt32(
820db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                        kKeyValidSamples, mCurrentPageSamples);
821db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                mFirstPacketInPage = false;
822db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
823ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                *out = buffer;
824ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
825ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return OK;
826ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
827ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
828ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
829ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
830ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
8318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::init() {
832ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mMeta = new MetaData;
8338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mMeta->setCString(kKeyMIMEType, mMimeType);
834ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
8355a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    status_t err;
8368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    MediaBuffer *packet;
8378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    for (size_t i = 0; i < mNumHeaders; ++i) {
8388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        // ignore timestamp for configuration packets
8398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != OK) {
8408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return err;
8418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
8428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        ALOGV("read packet of size %zu\n", packet->range_length());
8438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        err = verifyHeader(packet, /* type = */ i * 2 + 1);
8448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        packet->release();
8458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        packet = NULL;
8468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (err != OK) {
8478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return err;
8488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
8495a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
85096f52cde23982f668592418a9548045237d5e327Andreas Huber
85196f52cde23982f668592418a9548045237d5e327Andreas Huber    mFirstDataOffset = mOffset + mCurrentPageSize;
8525a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber
8533fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    off64_t size;
8543fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    uint64_t lastGranulePosition;
8553fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    if (!(mSource->flags() & DataSource::kIsCachingDataSource)
8563fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            && mSource->getSize(&size) == OK
8573fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            && findPrevGranulePosition(size, &lastGranulePosition) == OK) {
8583fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // Let's assume it's cheap to seek to the end.
8593fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // The granule position of the final page in the stream will
8603fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // give us the exact duration of the content, something that
8613fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // we can only approximate using avg. bitrate if seeking to
8623fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // the end is too expensive or impossible (live streaming).
8633fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        int64_t durationUs = getTimeUsOfGranule(lastGranulePosition);
8653fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8663fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        mMeta->setInt64(kKeyDuration, durationUs);
8673fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8683fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        buildTableOfContents();
8693fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
8703fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8715a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    return OK;
872ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
873ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
8748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihvoid MyOggExtractor::buildTableOfContents() {
8753fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    off64_t offset = mFirstDataOffset;
8763fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    Page page;
8773fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    ssize_t pageSize;
8783fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    while ((pageSize = readPage(offset, &page)) > 0) {
8793fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        mTableOfContents.push();
8803fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8813fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        TOCEntry &entry =
8823fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            mTableOfContents.editItemAt(mTableOfContents.size() - 1);
8833fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8843fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        entry.mPageOffset = offset;
8858c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        entry.mTimeUs = getTimeUsOfGranule(page.mGranulePosition);
8863fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8873fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        offset += (size_t)pageSize;
8883fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
8893fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8903fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    // Limit the maximum amount of RAM we spend on the table of contents,
8913fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    // if necessary thin out the table evenly to trim it down to maximum
8923fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    // size.
8933fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8943fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    static const size_t kMaxTOCSize = 8192;
8953fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    static const size_t kMaxNumTOCEntries = kMaxTOCSize / sizeof(TOCEntry);
8963fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8973fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    size_t numerator = mTableOfContents.size();
8983fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
8993fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    if (numerator > kMaxNumTOCEntries) {
9003fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        size_t denom = numerator - kMaxNumTOCEntries;
9013fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
9023fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        size_t accum = 0;
9033fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        for (ssize_t i = mTableOfContents.size() - 1; i >= 0; --i) {
9043fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            accum += denom;
9053fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            if (accum >= numerator) {
9063fd91baee812919f53a85c5c05f32606313f8334Andreas Huber                mTableOfContents.removeAt(i);
9073fd91baee812919f53a85c5c05f32606313f8334Andreas Huber                accum -= numerator;
9083fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            }
9093fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        }
9103fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
9113fd91baee812919f53a85c5c05f32606313f8334Andreas Huber}
9123fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
9138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihint32_t MyOggExtractor::getPacketBlockSize(MediaBuffer *buffer) {
9147a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    const uint8_t *data =
9157a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen        (const uint8_t *)buffer->data() + buffer->range_offset();
9167a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen
9177a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    size_t size = buffer->range_length();
9187a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen
9197a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ogg_buffer buf;
9207a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    buf.data = (uint8_t *)data;
9217a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    buf.size = size;
9227a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    buf.refcount = 1;
9237a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    buf.ptr.owner = NULL;
9247a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen
9257a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ogg_reference ref;
9267a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ref.buffer = &buf;
9277a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ref.begin = 0;
9287a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ref.length = size;
9297a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ref.next = NULL;
9307a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen
9317a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    ogg_packet pack;
9327a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    pack.packet = &ref;
9337a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    pack.bytes = ref.length;
9347a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    pack.b_o_s = 0;
9357a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    pack.e_o_s = 0;
9367a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    pack.granulepos = 0;
9377a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    pack.packetno = 0;
9387a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen
9397a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen    return vorbis_packet_blocksize(&mVi, &pack);
9407a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen}
9417a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen
9428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihint64_t MyOpusExtractor::getTimeUsOfGranule(uint64_t granulePos) const {
9438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint64_t pcmSamplePosition = 0;
9448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (granulePos > mCodecDelay) {
9458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        pcmSamplePosition = granulePos - mCodecDelay;
9468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
947894aa94e101f9ff9a074f2bcc4d1fb989cf9ea04Chad Brubaker    if (pcmSamplePosition > INT64_MAX / 1000000ll) {
948894aa94e101f9ff9a074f2bcc4d1fb989cf9ea04Chad Brubaker        return INT64_MAX;
949894aa94e101f9ff9a074f2bcc4d1fb989cf9ea04Chad Brubaker    }
9508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    return pcmSamplePosition * 1000000ll / kOpusSampleRate;
9518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}
9528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9538c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::verifyHeader(MediaBuffer *buffer, uint8_t type) {
9548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    switch (type) {
9558c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean
9568c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        // header and comments such that we can share code with MyVorbisExtractor.
9578c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        case 1:
9588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return verifyOpusHeader(buffer);
9598c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        case 3:
9608c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return verifyOpusComments(buffer);
9618c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        default:
9628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return INVALID_OPERATION;
9638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
9648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}
9658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9668c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::verifyOpusHeader(MediaBuffer *buffer) {
9678c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    const size_t kOpusHeaderSize = 19;
9688c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    const uint8_t *data =
9698c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        (const uint8_t *)buffer->data() + buffer->range_offset();
9708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9718c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    size_t size = buffer->range_length();
9728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9738c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (size < kOpusHeaderSize
9748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            || memcmp(data, "OpusHead", 8)
9758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            || /* version = */ data[8] != 1) {
9768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return ERROR_MALFORMED;
9778c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
9788c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9798c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mChannelCount = data[9];
9808c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mCodecDelay = U16LE_AT(&data[10]);
9818c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9828c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mMeta->setData(kKeyOpusHeader, 0, data, size);
9838c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mMeta->setInt32(kKeySampleRate, kOpusSampleRate);
9848c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mMeta->setInt32(kKeyChannelCount, mChannelCount);
9858c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mMeta->setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/);
9868c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    mMeta->setInt64(kKeyOpusCodecDelay /* ns */,
9872d93abfb06455176b7f2fcde0d9fd4dfe7a0973cChad Brubaker            mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate);
9888c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9898c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    return OK;
9908c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}
9918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
9928c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::verifyOpusComments(MediaBuffer *buffer) {
9938c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // add artificial framing bit so we can reuse _vorbis_unpack_comment
9948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int32_t commentSize = buffer->range_length() + 1;
9958c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    sp<ABuffer> aBuf = new ABuffer(commentSize);
9968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (aBuf->capacity() <= buffer->range_length()) {
9978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return ERROR_MALFORMED;
9988c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
9998c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    uint8_t* commentData = aBuf->data();
10018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    memcpy(commentData,
10028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            (uint8_t *)buffer->data() + buffer->range_offset(),
10038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            buffer->range_length());
10048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10058c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ogg_buffer buf;
10068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.data = commentData;
10078c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.size = commentSize;
10088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.refcount = 1;
10098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.ptr.owner = NULL;
10108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ogg_reference ref;
10128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.buffer = &buf;
10138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.begin = 0;
10148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.length = commentSize;
10158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.next = NULL;
10168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    oggpack_buffer bits;
10188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    oggpack_readinit(&bits, &ref);
10198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // skip 'OpusTags'
10218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    const char *OpusTags = "OpusTags";
10228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    const int32_t headerLen = strlen(OpusTags);
10238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int32_t framingBitOffset = headerLen;
10248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    for (int i = 0; i < headerLen; ++i) {
10258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        char chr = oggpack_read(&bits, 8);
10268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (chr != OpusTags[i]) {
10278c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return ERROR_MALFORMED;
10288c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
10298c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10308c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int32_t vendorLen = oggpack_read(&bits, 32);
10328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    framingBitOffset += 4;
10338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (vendorLen < 0 || vendorLen > commentSize - 8) {
10348c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return ERROR_MALFORMED;
10358c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    // skip vendor string
10378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    framingBitOffset += vendorLen;
10388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    for (int i = 0; i < vendorLen; ++i) {
10398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        oggpack_read(&bits, 8);
10408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int32_t n = oggpack_read(&bits, 32);
10438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    framingBitOffset += 4;
10448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (n < 0 || n > ((commentSize - oggpack_bytes(&bits)) >> 2)) {
10458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return ERROR_MALFORMED;
10468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    for (int i = 0; i < n; ++i) {
10488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        int32_t len = oggpack_read(&bits, 32);
10498c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        framingBitOffset += 4;
10508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (len  < 0 || len  > (commentSize - oggpack_bytes(&bits))) {
10518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            return ERROR_MALFORMED;
10528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
10538c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        framingBitOffset += len;
10548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        for (int j = 0; j < len; ++j) {
10558c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            oggpack_read(&bits, 8);
10568c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
10578c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (framingBitOffset < 0 || framingBitOffset >= commentSize) {
10598c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return ERROR_MALFORMED;
10608c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10618c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    commentData[framingBitOffset] = 1;
10628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.data = commentData + headerLen;
10648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.size = commentSize - headerLen;
10658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.refcount = 1;
10668c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    buf.ptr.owner = NULL;
10678c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10688c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.buffer = &buf;
10698c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.begin = 0;
10708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.length = commentSize - headerLen;
10718c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    ref.next = NULL;
10728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10738c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    oggpack_readinit(&bits, &ref);
10748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    int err = _vorbis_unpack_comment(&mVc, &bits);
10758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    if (0 != err) {
10768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        return ERROR_MALFORMED;
10778c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    }
10788c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10798c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    parseFileMetaData();
10808c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    return OK;
10818c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}
10828c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih
10835a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huberstatus_t MyVorbisExtractor::verifyHeader(
1084ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        MediaBuffer *buffer, uint8_t type) {
1085ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    const uint8_t *data =
1086ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
1087ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1088ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t size = buffer->range_length();
1089ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
10905a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) {
10915a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return ERROR_MALFORMED;
10925a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
1093ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1094ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ogg_buffer buf;
1095ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.data = (uint8_t *)data;
1096ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.size = size;
1097ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.refcount = 1;
1098ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.ptr.owner = NULL;
1099ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1100ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ogg_reference ref;
1101ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.buffer = &buf;
1102ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.begin = 0;
1103ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.length = size;
1104ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.next = NULL;
1105ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1106ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    oggpack_buffer bits;
1107ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    oggpack_readinit(&bits, &ref);
1108ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1109fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen    if (oggpack_read(&bits, 8) != type) {
1110fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen        return ERROR_MALFORMED;
1111fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen    }
1112ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < 6; ++i) {
1113ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        oggpack_read(&bits, 8);  // skip 'vorbis'
1114ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
1115ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1116ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    switch (type) {
1117ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 1:
1118ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
1119fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen            if (0 != _vorbis_unpack_info(&mVi, &bits)) {
1120fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen                return ERROR_MALFORMED;
1121fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen            }
1122ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1123ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setData(kKeyVorbisInfo, 0, data, size);
1124ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setInt32(kKeySampleRate, mVi.rate);
1125ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setInt32(kKeyChannelCount, mVi.channels);
1126ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
11273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("lower-bitrate = %ld", mVi.bitrate_lower);
11283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
11293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
11303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("window-bitrate = %ld", mVi.bitrate_window);
11317a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen            ALOGV("blocksizes: %d/%d",
11327a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    vorbis_info_blocksize(&mVi, 0),
11337a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    vorbis_info_blocksize(&mVi, 1)
11347a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen                    );
1135ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1136c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t size;
1137ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (mSource->getSize(&size) == OK) {
1138ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                uint64_t bps = approxBitrate();
1139f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang                if (bps != 0) {
1140f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang                    mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
1141f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang                }
1142ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
1143ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
1144ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
1145ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1146ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 3:
1147ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
11485a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            if (0 != _vorbis_unpack_comment(&mVc, &bits)) {
11495a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber                return ERROR_MALFORMED;
11505a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            }
11514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
11524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            parseFileMetaData();
1153ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
1154ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
1155ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1156ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 5:
1157ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
11585a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            if (0 != _vorbis_unpack_books(&mVi, &bits)) {
11595a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber                return ERROR_MALFORMED;
11605a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            }
1161ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1162ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setData(kKeyVorbisBooks, 0, data, size);
1163ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
1164ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
1165ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
11665a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber
11675a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    return OK;
1168ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1169ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
11708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihuint64_t MyVorbisExtractor::approxBitrate() const {
1171ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mVi.bitrate_nominal != 0) {
1172ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return mVi.bitrate_nominal;
1173ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
1174ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1175ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
1176ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1177ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
11788c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihvoid MyOggExtractor::parseFileMetaData() {
11794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta = new MetaData;
11804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
11814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1182856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten    for (int i = 0; i < mVc.comments; ++i) {
1183856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        const char *comment = mVc.user_comments[i];
1184856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        size_t commentLength = mVc.comment_lengths[i];
1185856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        parseVorbisComment(mFileMeta, comment, commentLength);
1186df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
1187856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten    }
1188856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten}
1189856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten
1190856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenvoid parseVorbisComment(
1191856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        const sp<MetaData> &fileMeta, const char *comment, size_t commentLength)
1192856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten{
11934595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    struct {
11944595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        const char *const mTag;
11954595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        uint32_t mKey;
11964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    } kMap[] = {
11974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "TITLE", kKeyTitle },
11984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "ARTIST", kKeyArtist },
119911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        { "ALBUMARTIST", kKeyAlbumArtist },
120011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        { "ALBUM ARTIST", kKeyAlbumArtist },
120111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        { "COMPILATION", kKeyCompilation },
12024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "ALBUM", kKeyAlbum },
12034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "COMPOSER", kKeyComposer },
12044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "GENRE", kKeyGenre },
12054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "AUTHOR", kKeyAuthor },
12064595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "TRACKNUMBER", kKeyCDTrackNumber },
12074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "DISCNUMBER", kKeyDiscNumber },
12084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "DATE", kKeyDate },
120975c6d4267db3cca1d06292cae09a40e2d1fcedbdAndreas Lillvik        { "YEAR", kKeyYear },
12104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "LYRICIST", kKeyWriter },
12114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
12128ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber        { "ANDROID_LOOP", kKeyAutoLoop },
12134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    };
12144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
12164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            size_t tagLen = strlen(kMap[j].mTag);
12174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (!strncasecmp(kMap[j].mTag, comment, tagLen)
12184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                    && comment[tagLen] == '=') {
12194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                if (kMap[j].mKey == kKeyAlbumArt) {
12204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                    extractAlbumArt(
1221856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten                            fileMeta,
12224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                            &comment[tagLen + 1],
1223856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten                            commentLength - tagLen - 1);
12248ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber                } else if (kMap[j].mKey == kKeyAutoLoop) {
12258ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber                    if (!strcasecmp(&comment[tagLen + 1], "true")) {
1226856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten                        fileMeta->setInt32(kKeyAutoLoop, true);
12278ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber                    }
12284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                } else {
1229856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten                    fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
12304595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                }
12314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            }
12324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
12334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12344595be952e3b1d6776a023e3f447c057797f1505Andreas Huber}
12354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1236856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt(
1237856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        const sp<MetaData> &fileMeta, const void *data, size_t size) {
12383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("extractAlbumArt from '%s'", (const char *)data);
12394595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
124059acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim    sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size));
124159acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim    if (flacBuffer == NULL) {
124229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("malformed base64 encoded data.");
12434595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        return;
12444595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
124659acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim    size_t flacSize = flacBuffer->size();
124759acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim    uint8_t *flac = flacBuffer->data();
1248a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("got flac of size %zu", flacSize);
12494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t picType;
12514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t typeLen;
12524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t descLen;
12534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t dataLen;
12544595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    char type[128];
12554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 8) {
125759acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim        return;
12584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12594595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12604595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    picType = U32_AT(flac);
12614595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12624595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (picType != 3) {
12634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        // This is not a front cover.
126459acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim        return;
12654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    typeLen = U32_AT(&flac[4]);
1268c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen    if (typeLen > sizeof(type) - 1) {
126959acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim        return;
12704595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1272c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen    // we've already checked above that flacSize >= 8
1273c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen    if (flacSize - 8 < typeLen) {
127459acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim        return;
12754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12764595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    memcpy(type, &flac[8], typeLen);
12784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    type[typeLen] = '\0';
12794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("picType = %d, type = '%s'", picType, type);
12814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (!strcmp(type, "-->")) {
12834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        // This is not inline cover art, but an external url instead.
128459acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim        return;
12854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12864595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1287a86fef32894a90811c2e175152763bc3994c769fWonsik Kim    if (flacSize < 32 || flacSize - 32 < typeLen) {
128859acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim        return;
1289a86fef32894a90811c2e175152763bc3994c769fWonsik Kim    }
12904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1291a86fef32894a90811c2e175152763bc3994c769fWonsik Kim    descLen = U32_AT(&flac[8 + typeLen]);
1292a86fef32894a90811c2e175152763bc3994c769fWonsik Kim    if (flacSize - 32 - typeLen < descLen) {
129359acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim        return;
12944595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
12954595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
12964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
12974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1298c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen    // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
1299c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen    if (flacSize - 32 - typeLen - descLen < dataLen) {
130059acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim        return;
13014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
13024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1303a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("got image data, %zu trailing bytes",
13044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber         flacSize - 32 - typeLen - descLen - dataLen);
13054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1306856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten    fileMeta->setData(
13074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
13084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1309856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten    fileMeta->setCString(kKeyAlbumArtMIME, type);
13104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber}
13114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1312ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
1313ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1314ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::OggExtractor(const sp<DataSource> &source)
1315ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mDataSource(source),
1316ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mInitCheck(NO_INIT),
1317ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mImpl(NULL) {
13188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih    for (int i = 0; i < 2; ++i) {
13198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (mImpl != NULL) {
13208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            delete mImpl;
13218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
13228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (i == 0) {
13238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            mImpl = new MyVorbisExtractor(mDataSource);
13248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        } else {
13258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            mImpl = new MyOpusExtractor(mDataSource);
13268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
13278c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        mInitCheck = mImpl->seekToOffset(0);
1328ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
13298c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        if (mInitCheck == OK) {
13308c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            mInitCheck = mImpl->init();
13318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            if (mInitCheck == OK) {
13328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih                break;
13338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih            }
13348c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih        }
13355a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
1336ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1337ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1338ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::~OggExtractor() {
1339ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    delete mImpl;
1340ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mImpl = NULL;
1341ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1342ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1343ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersize_t OggExtractor::countTracks() {
1344ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mInitCheck != OK ? 0 : 1;
1345ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1346ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1347b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissensp<IMediaSource> OggExtractor::getTrack(size_t index) {
1348ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (index >= 1) {
1349ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return NULL;
1350ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
1351ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1352ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return new OggSource(this);
1353ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1354ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1355ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getTrackMetaData(
135684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        size_t index, uint32_t /* flags */) {
1357ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (index >= 1) {
1358ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return NULL;
1359ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
1360ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1361ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mImpl->getFormat();
1362ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1363ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1364ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getMetaData() {
13654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    return mImpl->getFileMetaData();
1366ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1367ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1368ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberbool SniffOgg(
13695a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
13705a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        sp<AMessage> *) {
1371ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    char tmp[4];
1372ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
1373ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return false;
1374ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
1375ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1376ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG);
1377ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *confidence = 0.2f;
1378ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1379ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return true;
1380ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1381ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1382ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}  // namespace android
1383