OggExtractor.cpp revision c7fc37a3dab9bd1f96713649f351b5990e6316ff
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>
24ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/DataSource.h>
25ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaBuffer.h>
26ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaBufferGroup.h>
27ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaDebug.h>
28ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaDefs.h>
29ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaErrors.h>
30ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaSource.h>
31ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MetaData.h>
32ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/Utils.h>
33ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <utils/String8.h>
34ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
35ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberextern "C" {
36ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    #include <Tremolo/codec_internal.h>
37ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
38ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
39ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
40ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
41ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
42ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
43ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubernamespace android {
44ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
45ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstruct OggSource : public MediaSource {
46ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    OggSource(const sp<OggExtractor> &extractor);
47ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
48ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    virtual sp<MetaData> getFormat();
49ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
50ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    virtual status_t start(MetaData *params = NULL);
51ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    virtual status_t stop();
52ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
53ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    virtual status_t read(
54ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
55ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
56ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberprotected:
57ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    virtual ~OggSource();
58ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
59ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberprivate:
60ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    sp<OggExtractor> mExtractor;
61ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    bool mStarted;
62ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
63ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    OggSource(const OggSource &);
64ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    OggSource &operator=(const OggSource &);
65ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber};
66ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
67ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstruct MyVorbisExtractor {
68ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MyVorbisExtractor(const sp<DataSource> &source);
69ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    virtual ~MyVorbisExtractor();
70ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
71ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    sp<MetaData> getFormat() const;
72ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
73ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    // Returns an approximate bitrate in bits per second.
74ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    uint64_t approxBitrate();
75ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
76c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t seekToOffset(off64_t offset);
77ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    status_t readNextPacket(MediaBuffer **buffer);
78ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
795a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    status_t init();
80ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    sp<MetaData> getFileMetaData() { return mFileMeta; }
824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
83ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberprivate:
84ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    struct Page {
85ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint64_t mGranulePosition;
86ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint32_t mSerialNo;
87ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint32_t mPageNo;
88ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint8_t mFlags;
89ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint8_t mNumSegments;
90ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint8_t mLace[255];
91ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    };
92ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
93ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    sp<DataSource> mSource;
94c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mOffset;
95ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    Page mCurrentPage;
96db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    uint64_t mPrevGranulePosition;
97ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t mCurrentPageSize;
98db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    bool mFirstPacketInPage;
99db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    uint64_t mCurrentPageSamples;
100ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t mNextLaceIndex;
101ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
102c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mFirstDataOffset;
10396f52cde23982f668592418a9548045237d5e327Andreas Huber
104ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    vorbis_info mVi;
105ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    vorbis_comment mVc;
106ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
107ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    sp<MetaData> mMeta;
1084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    sp<MetaData> mFileMeta;
109ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
110c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ssize_t readPage(off64_t offset, Page *page);
111c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t findNextPage(off64_t startOffset, off64_t *pageOffset);
112ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1135a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    status_t verifyHeader(
114ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            MediaBuffer *buffer, uint8_t type);
115ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    void parseFileMetaData();
1174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    void extractAlbumArt(const void *data, size_t size);
1184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
119c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    uint64_t findPrevGranulePosition(off64_t pageOffset);
120db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
121ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MyVorbisExtractor(const MyVorbisExtractor &);
122ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MyVorbisExtractor &operator=(const MyVorbisExtractor &);
123ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber};
124ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
125ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
126ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
127ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::OggSource(const sp<OggExtractor> &extractor)
128ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mExtractor(extractor),
129ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mStarted(false) {
130ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
131ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
132ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::~OggSource() {
133ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mStarted) {
134ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        stop();
135ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
136ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
137ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
138ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggSource::getFormat() {
139ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mExtractor->mImpl->getFormat();
140ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
141ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
142ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::start(MetaData *params) {
143ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mStarted) {
144ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return INVALID_OPERATION;
145ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
146ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
147ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mStarted = true;
148ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
149ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
150ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
151ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
152ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::stop() {
153ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mStarted = false;
154ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
155ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
156ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
157ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
158ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::read(
159ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
160ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = NULL;
161ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
162ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t seekTimeUs;
163abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
164abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
165c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll;
1663e8843e8db702c8c9c97df2b4a31b66ea12961e6Andreas Huber        LOGV("seeking to offset %ld", pos);
167ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
168ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (mExtractor->mImpl->seekToOffset(pos) != OK) {
169ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return ERROR_END_OF_STREAM;
170ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
171ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
172ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
173ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MediaBuffer *packet;
174ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    status_t err = mExtractor->mImpl->readNextPacket(&packet);
175ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
176ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (err != OK) {
177ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return err;
178ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
179ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
180ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0
181ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t timeUs;
182ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) {
183ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        LOGI("found time = %lld us", timeUs);
184ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    } else {
185ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        LOGI("NO time");
186ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
187ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif
188ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1898bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    packet->meta_data()->setInt32(kKeyIsSyncFrame, 1);
1908bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
191ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = packet;
192ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
193ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
194ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
195ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
196ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
197ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
198ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberMyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source)
199ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mSource(source),
200ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mOffset(0),
201db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber      mPrevGranulePosition(0),
202ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mCurrentPageSize(0),
203db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber      mFirstPacketInPage(true),
204db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber      mCurrentPageSamples(0),
20596f52cde23982f668592418a9548045237d5e327Andreas Huber      mNextLaceIndex(0),
20696f52cde23982f668592418a9548045237d5e327Andreas Huber      mFirstDataOffset(-1) {
207ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPage.mNumSegments = 0;
2084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
2094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_info_init(&mVi);
2104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_comment_init(&mVc);
211ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
212ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
213ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberMyVorbisExtractor::~MyVorbisExtractor() {
2144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_comment_clear(&mVc);
2154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_info_clear(&mVi);
216ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
217ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
218ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> MyVorbisExtractor::getFormat() const {
219ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mMeta;
220ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
221ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
222ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::findNextPage(
223c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t startOffset, off64_t *pageOffset) {
224ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *pageOffset = startOffset;
225ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
226ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (;;) {
227ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        char signature[4];
228ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
229ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
230ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (n < 4) {
231ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            *pageOffset = 0;
232ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
233ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
234ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
235ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
236ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (!memcmp(signature, "OggS", 4)) {
237ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (*pageOffset > startOffset) {
238ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                LOGV("skipped %ld bytes of junk to reach next frame",
239ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                     *pageOffset - startOffset);
240ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
241ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
242ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return OK;
243ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
244ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
245ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ++*pageOffset;
246ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
247ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
248ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
249db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// Given the offset of the "current" page, find the page immediately preceding
250db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// it (if any) and return its granule position.
251db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// To do this we back up from the "current" page's offset until we find any
252db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// page preceding it and then scan forward to just before the current page.
253c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Donguint64_t MyVorbisExtractor::findPrevGranulePosition(off64_t pageOffset) {
254c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t prevPageOffset = 0;
255c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t prevGuess = pageOffset;
256db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    for (;;) {
257db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (prevGuess >= 5000) {
258db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            prevGuess -= 5000;
259db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        } else {
260db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            prevGuess = 0;
261db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
262db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
263db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        LOGV("backing up %ld bytes", pageOffset - prevGuess);
264db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
265db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        CHECK_EQ(findNextPage(prevGuess, &prevPageOffset), (status_t)OK);
266db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
267db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (prevPageOffset < pageOffset || prevGuess == 0) {
268db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            break;
269db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
270db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    }
271db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
272db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    if (prevPageOffset == pageOffset) {
273db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        // We did not find a page preceding this one.
274db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        return 0;
275db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    }
276db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
277db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    LOGV("prevPageOffset at %ld, pageOffset at %ld", prevPageOffset, pageOffset);
278db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
279db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    for (;;) {
280db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        Page prevPage;
281db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        ssize_t n = readPage(prevPageOffset, &prevPage);
282db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
283db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (n <= 0) {
284db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            return 0;
285db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
286db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
287db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        prevPageOffset += n;
288db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
289db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (prevPageOffset == pageOffset) {
290db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            return prevPage.mGranulePosition;
291db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
292db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    }
293db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber}
294db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
295c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MyVorbisExtractor::seekToOffset(off64_t offset) {
29696f52cde23982f668592418a9548045237d5e327Andreas Huber    if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) {
29796f52cde23982f668592418a9548045237d5e327Andreas Huber        // Once we know where the actual audio data starts (past the headers)
29896f52cde23982f668592418a9548045237d5e327Andreas Huber        // don't ever seek to anywhere before that.
29996f52cde23982f668592418a9548045237d5e327Andreas Huber        offset = mFirstDataOffset;
30096f52cde23982f668592418a9548045237d5e327Andreas Huber    }
30196f52cde23982f668592418a9548045237d5e327Andreas Huber
302c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t pageOffset;
303ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    status_t err = findNextPage(offset, &pageOffset);
304ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
305ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (err != OK) {
306ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return err;
307ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
308ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
309db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    // We found the page we wanted to seek to, but we'll also need
310db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    // the page preceding it to determine how many valid samples are on
311db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    // this page.
312db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    mPrevGranulePosition = findPrevGranulePosition(pageOffset);
313db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
314ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mOffset = pageOffset;
315ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
316ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPageSize = 0;
317db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    mFirstPacketInPage = true;
318db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    mCurrentPageSamples = 0;
319ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPage.mNumSegments = 0;
320ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mNextLaceIndex = 0;
321ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
322ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    // XXX what if new page continues packet from last???
323ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
324ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
325ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
326ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
327c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MyVorbisExtractor::readPage(off64_t offset, Page *page) {
328ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    uint8_t header[27];
329ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mSource->readAt(offset, header, sizeof(header))
330ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            < (ssize_t)sizeof(header)) {
3313e8843e8db702c8c9c97df2b4a31b66ea12961e6Andreas Huber        LOGV("failed to read %d bytes at offset 0x%08lx", sizeof(header), offset);
332ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
333ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_IO;
334ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
335ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
336ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (memcmp(header, "OggS", 4)) {
337ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_MALFORMED;
338ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
339ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
340ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (header[4] != 0) {
341ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        // Wrong version.
342ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
343ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_UNSUPPORTED;
344ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
345ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
346ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mFlags = header[5];
347ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
348ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (page->mFlags & ~7) {
349ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        // Only bits 0-2 are defined in version 0.
350ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_MALFORMED;
351ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
352ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
353ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mGranulePosition = U64LE_AT(&header[6]);
354ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
355ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0
356ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    printf("granulePosition = %llu (0x%llx)\n",
357ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber           page->mGranulePosition, page->mGranulePosition);
358ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif
359ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
360ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mSerialNo = U32LE_AT(&header[14]);
361ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mPageNo = U32LE_AT(&header[18]);
362ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
363ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mNumSegments = header[26];
364ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mSource->readAt(
365ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                offset + sizeof(header), page->mLace, page->mNumSegments)
366ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            < (ssize_t)page->mNumSegments) {
367ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_IO;
368ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
369ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
370ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t totalSize = 0;;
371ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < page->mNumSegments; ++i) {
372ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        totalSize += page->mLace[i];
373ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
374ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
3755a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#if 0
376ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    String8 tmp;
377ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < page->mNumSegments; ++i) {
378ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        char x[32];
379ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]);
380ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
381ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        tmp.append(x);
382ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
383ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
3845a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string());
3855a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#endif
386ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
387ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return sizeof(header) + page->mNumSegments + totalSize;
388ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
389ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
390ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) {
391ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = NULL;
392ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
393ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MediaBuffer *buffer = NULL;
394ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t timeUs = -1;
395ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
396ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (;;) {
397ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        size_t i;
398ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        size_t packetSize = 0;
399ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        bool gotFullPacket = false;
400ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) {
401ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            uint8_t lace = mCurrentPage.mLace[i];
402ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
403ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            packetSize += lace;
404ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
405ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (lace < 255) {
406ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                gotFullPacket = true;
407ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                ++i;
408ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                break;
409ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
410ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
411ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
412ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (mNextLaceIndex < mCurrentPage.mNumSegments) {
413c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments;
414ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            for (size_t j = 0; j < mNextLaceIndex; ++j) {
415ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                dataOffset += mCurrentPage.mLace[j];
416ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
417ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
418ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            size_t fullSize = packetSize;
419ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer != NULL) {
420ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                fullSize += buffer->range_length();
421ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
422ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            MediaBuffer *tmp = new MediaBuffer(fullSize);
423ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer != NULL) {
424ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                memcpy(tmp->data(), buffer->data(), buffer->range_length());
425ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                tmp->set_range(0, buffer->range_length());
426ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer->release();
427ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber            } else {
428ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // XXX Not only is this not technically the correct time for
429ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // this packet, we also stamp every packet in this page
430ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // with the same time. This needs fixing later.
431ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber
432ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber                if (mVi.rate) {
433ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber                    // Rate may not have been initialized yet if we're currently
434ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber                    // reading the configuration packets...
435ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber                    // Fortunately, the timestamp doesn't matter for those.
436ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber                    timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate;
437ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber                }
438ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                tmp->set_range(0, 0);
439ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
440ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            buffer = tmp;
441ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
442ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            ssize_t n = mSource->readAt(
443ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    dataOffset,
444ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    (uint8_t *)buffer->data() + buffer->range_length(),
445ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    packetSize);
446ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
447ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (n < (ssize_t)packetSize) {
4483e8843e8db702c8c9c97df2b4a31b66ea12961e6Andreas Huber                LOGV("failed to read %d bytes at 0x%08lx", packetSize, dataOffset);
449ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return ERROR_IO;
450ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
451ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
452ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            buffer->set_range(0, fullSize);
453ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
454ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mNextLaceIndex = i;
455ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
456ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (gotFullPacket) {
457ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // We've just read the entire packet.
458ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
459ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                if (timeUs >= 0) {
460ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
461ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                }
462ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
463db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                if (mFirstPacketInPage) {
464db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                    buffer->meta_data()->setInt32(
465db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                            kKeyValidSamples, mCurrentPageSamples);
466db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                    mFirstPacketInPage = false;
467db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                }
468db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
469ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                *out = buffer;
470ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
471ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return OK;
472ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
473ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
474ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            // fall through, the buffer now contains the start of the packet.
475ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
476ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
477ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments);
478ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
479ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mOffset += mCurrentPageSize;
480ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ssize_t n = readPage(mOffset, &mCurrentPage);
481ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
482ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (n <= 0) {
483ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer) {
484ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer->release();
485ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer = NULL;
486ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
487ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
4883e8843e8db702c8c9c97df2b4a31b66ea12961e6Andreas Huber            LOGV("readPage returned %ld", n);
489ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
490ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return n < 0 ? n : (status_t)ERROR_END_OF_STREAM;
491ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
492ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
493db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        mCurrentPageSamples =
494db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            mCurrentPage.mGranulePosition - mPrevGranulePosition;
495db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        mFirstPacketInPage = true;
496db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
497db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        mPrevGranulePosition = mCurrentPage.mGranulePosition;
498db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
499ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mCurrentPageSize = n;
500ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mNextLaceIndex = 0;
501ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
502ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (buffer != NULL) {
503ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if ((mCurrentPage.mFlags & 1) == 0) {
504ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // This page does not continue the packet, i.e. the packet
505ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // is already complete.
506ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
507ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                if (timeUs >= 0) {
508ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
509ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                }
510ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
511db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                buffer->meta_data()->setInt32(
512db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                        kKeyValidSamples, mCurrentPageSamples);
513db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                mFirstPacketInPage = false;
514db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
515ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                *out = buffer;
516ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
517ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return OK;
518ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
519ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
520ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
521ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
522ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5235a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huberstatus_t MyVorbisExtractor::init() {
524ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mMeta = new MetaData;
525ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
526ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
527ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MediaBuffer *packet;
5285a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    status_t err;
5295a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if ((err = readNextPacket(&packet)) != OK) {
5305a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return err;
5315a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
532ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    LOGV("read packet of size %d\n", packet->range_length());
5335a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    err = verifyHeader(packet, 1);
534ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet->release();
535ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet = NULL;
5365a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if (err != OK) {
5375a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return err;
5385a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
539ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5405a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if ((err = readNextPacket(&packet)) != OK) {
5415a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return err;
5425a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
543ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    LOGV("read packet of size %d\n", packet->range_length());
5445a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    err = verifyHeader(packet, 3);
545ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet->release();
546ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet = NULL;
5475a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if (err != OK) {
5485a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return err;
5495a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
550ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5515a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if ((err = readNextPacket(&packet)) != OK) {
5525a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return err;
5535a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
554ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    LOGV("read packet of size %d\n", packet->range_length());
5555a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    err = verifyHeader(packet, 5);
556ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet->release();
557ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet = NULL;
5585a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if (err != OK) {
5595a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return err;
5605a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
56196f52cde23982f668592418a9548045237d5e327Andreas Huber
56296f52cde23982f668592418a9548045237d5e327Andreas Huber    mFirstDataOffset = mOffset + mCurrentPageSize;
5635a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber
5645a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    return OK;
565ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
566ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5675a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huberstatus_t MyVorbisExtractor::verifyHeader(
568ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        MediaBuffer *buffer, uint8_t type) {
569ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    const uint8_t *data =
570ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
571ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
572ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t size = buffer->range_length();
573ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5745a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) {
5755a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return ERROR_MALFORMED;
5765a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
577ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
578ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ogg_buffer buf;
579ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.data = (uint8_t *)data;
580ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.size = size;
581ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.refcount = 1;
582ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.ptr.owner = NULL;
583ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
584ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ogg_reference ref;
585ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.buffer = &buf;
586ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.begin = 0;
587ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.length = size;
588ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.next = NULL;
589ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
590ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    oggpack_buffer bits;
591ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    oggpack_readinit(&bits, &ref);
592ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
593ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    CHECK_EQ(oggpack_read(&bits, 8), type);
594ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < 6; ++i) {
595ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        oggpack_read(&bits, 8);  // skip 'vorbis'
596ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
597ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
598ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    switch (type) {
599ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 1:
600ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
601ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits));
602ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
603ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setData(kKeyVorbisInfo, 0, data, size);
604ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setInt32(kKeySampleRate, mVi.rate);
605ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setInt32(kKeyChannelCount, mVi.channels);
606ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
607ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            LOGV("lower-bitrate = %ld", mVi.bitrate_lower);
608ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            LOGV("upper-bitrate = %ld", mVi.bitrate_upper);
609ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            LOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
610ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            LOGV("window-bitrate = %ld", mVi.bitrate_window);
611ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
612c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t size;
613ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (mSource->getSize(&size) == OK) {
614ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                uint64_t bps = approxBitrate();
615ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
616ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
617ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
618ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
619ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
620ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
621ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 3:
622ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
6235a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            if (0 != _vorbis_unpack_comment(&mVc, &bits)) {
6245a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber                return ERROR_MALFORMED;
6255a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            }
6264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6274595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            parseFileMetaData();
628ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
629ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
630ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
631ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 5:
632ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
6335a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            if (0 != _vorbis_unpack_books(&mVi, &bits)) {
6345a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber                return ERROR_MALFORMED;
6355a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            }
636ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
637ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setData(kKeyVorbisBooks, 0, data, size);
638ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
639ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
640ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
6415a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber
6425a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    return OK;
643ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
644ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
645ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberuint64_t MyVorbisExtractor::approxBitrate() {
646ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mVi.bitrate_nominal != 0) {
647ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return mVi.bitrate_nominal;
648ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
649ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
650ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
651ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
652ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
6534595be952e3b1d6776a023e3f447c057797f1505Andreas Hubervoid MyVorbisExtractor::parseFileMetaData() {
6544595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta = new MetaData;
6554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
6564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    struct {
6584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        const char *const mTag;
6594595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        uint32_t mKey;
6604595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    } kMap[] = {
6614595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "TITLE", kKeyTitle },
6624595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "ARTIST", kKeyArtist },
6634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "ALBUM", kKeyAlbum },
6644595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "COMPOSER", kKeyComposer },
6654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "GENRE", kKeyGenre },
6664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "AUTHOR", kKeyAuthor },
6674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "TRACKNUMBER", kKeyCDTrackNumber },
6684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "DISCNUMBER", kKeyDiscNumber },
6694595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "DATE", kKeyDate },
6704595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "LYRICIST", kKeyWriter },
6714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
6728ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber        { "ANDROID_LOOP", kKeyAutoLoop },
6734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    };
6744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    for (int i = 0; i < mVc.comments; ++i) {
6764595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        const char *comment = mVc.user_comments[i];
6774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
6794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            size_t tagLen = strlen(kMap[j].mTag);
6804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (!strncasecmp(kMap[j].mTag, comment, tagLen)
6814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                    && comment[tagLen] == '=') {
6824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                if (kMap[j].mKey == kKeyAlbumArt) {
6834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                    extractAlbumArt(
6844595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                            &comment[tagLen + 1],
6854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                            mVc.comment_lengths[i] - tagLen - 1);
6868ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber                } else if (kMap[j].mKey == kKeyAutoLoop) {
6878ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber                    if (!strcasecmp(&comment[tagLen + 1], "true")) {
6888ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber                        mFileMeta->setInt32(kKeyAutoLoop, true);
6898ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber                    }
6904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                } else {
6914595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                    mFileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
6924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                }
6934595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            }
6944595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
6954595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
6964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber#if 0
6984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    for (int i = 0; i < mVc.comments; ++i) {
6994595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        LOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
7004595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
7014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber#endif
7024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber}
7034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber// The returned buffer should be free()d.
7054595be952e3b1d6776a023e3f447c057797f1505Andreas Huberstatic uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) {
7064595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    *outSize = 0;
7074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if ((size % 4) != 0) {
7094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        return NULL;
7104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
7114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t n = size;
7134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t padding = 0;
7144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (n >= 1 && s[n - 1] == '=') {
7154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        padding = 1;
7164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        if (n >= 2 && s[n - 2] == '=') {
7184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            padding = 2;
7194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
7204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
7214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t outLen = 3 * size / 4 - padding;
7234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    *outSize = outLen;
7254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    void *buffer = malloc(outLen);
7274595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint8_t *out = (uint8_t *)buffer;
7294595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t j = 0;
7304595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t accum = 0;
7314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    for (size_t i = 0; i < n; ++i) {
7324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        char c = s[i];
7334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        unsigned value;
7344595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        if (c >= 'A' && c <= 'Z') {
7354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = c - 'A';
7364595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c >= 'a' && c <= 'z') {
7374595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 26 + c - 'a';
7384595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c >= '0' && c <= '9') {
7394595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 52 + c - '0';
7404595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c == '+') {
7414595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 62;
7424595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c == '/') {
7434595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 63;
7444595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c != '=') {
7454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            return NULL;
7464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else {
7474595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (i < n - padding) {
7484595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                return NULL;
7494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            }
7504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 0;
7524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
7534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7544595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        accum = (accum << 6) | value;
7554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        if (((i + 1) % 4) == 0) {
7574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            out[j++] = (accum >> 16);
7584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7594595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
7604595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (j < outLen) { out[j++] = accum & 0xff; }
7614595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7624595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            accum = 0;
7634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
7644595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
7654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    return (uint8_t *)buffer;
7674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber}
7684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7694595be952e3b1d6776a023e3f447c057797f1505Andreas Hubervoid MyVorbisExtractor::extractAlbumArt(const void *data, size_t size) {
7704595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    LOGV("extractAlbumArt from '%s'", (const char *)data);
7714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7724595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t flacSize;
7734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize);
7744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flac == NULL) {
7764595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        LOGE("malformed base64 encoded data.");
7774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        return;
7784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
7794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    LOGV("got flac of size %d", flacSize);
7814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t picType;
7834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t typeLen;
7844595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t descLen;
7854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t dataLen;
7864595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    char type[128];
7874595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7884595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 8) {
7894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
7904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
7914595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    picType = U32_AT(flac);
7934595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7944595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (picType != 3) {
7954595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        // This is not a front cover.
7964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
7974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
7984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7994595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    typeLen = U32_AT(&flac[4]);
8004595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (typeLen + 1 > sizeof(type)) {
8014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
8024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
8034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 8 + typeLen) {
8054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
8064595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
8074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    memcpy(type, &flac[8], typeLen);
8094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    type[typeLen] = '\0';
8104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    LOGV("picType = %d, type = '%s'", picType, type);
8124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (!strcmp(type, "-->")) {
8144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        // This is not inline cover art, but an external url instead.
8154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
8164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
8174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    descLen = U32_AT(&flac[8 + typeLen]);
8194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 32 + typeLen + descLen) {
8214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
8224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
8234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
8254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 32 + typeLen + descLen + dataLen) {
8274595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
8284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
8294595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8304595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    LOGV("got image data, %d trailing bytes",
8314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber         flacSize - 32 - typeLen - descLen - dataLen);
8324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta->setData(
8344595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
8354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8364595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta->setCString(kKeyAlbumArtMIME, type);
8374595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8384595be952e3b1d6776a023e3f447c057797f1505Andreas Huberexit:
8394595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    free(flac);
8404595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    flac = NULL;
8414595be952e3b1d6776a023e3f447c057797f1505Andreas Huber}
8424595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
843ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
844ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
845ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::OggExtractor(const sp<DataSource> &source)
846ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mDataSource(source),
847ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mInitCheck(NO_INIT),
848ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mImpl(NULL) {
849ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mImpl = new MyVorbisExtractor(mDataSource);
8505a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    mInitCheck = mImpl->seekToOffset(0);
851ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
8525a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if (mInitCheck == OK) {
8535a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        mInitCheck = mImpl->init();
8545a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
855ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
856ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
857ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::~OggExtractor() {
858ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    delete mImpl;
859ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mImpl = NULL;
860ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
861ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
862ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersize_t OggExtractor::countTracks() {
863ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mInitCheck != OK ? 0 : 1;
864ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
865ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
866ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MediaSource> OggExtractor::getTrack(size_t index) {
867ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (index >= 1) {
868ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return NULL;
869ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
870ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
871ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return new OggSource(this);
872ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
873ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
874ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getTrackMetaData(
875ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        size_t index, uint32_t flags) {
876ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (index >= 1) {
877ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return NULL;
878ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
879ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
880ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mImpl->getFormat();
881ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
882ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
883ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getMetaData() {
8844595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    return mImpl->getFileMetaData();
885ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
886ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
887ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberbool SniffOgg(
8885a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
8895a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        sp<AMessage> *) {
890ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    char tmp[4];
891ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
892ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return false;
893ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
894ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
895ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG);
896ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *confidence = 0.2f;
897ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
898ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return true;
899ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
900ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
901ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}  // namespace android
902