OggExtractor.cpp revision f1d5aa162c02a16b7195a43a9bcea4d592600ac4
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>
24f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
25ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/DataSource.h>
26ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaBuffer.h>
27ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaBufferGroup.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
763fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    status_t seekToTime(int64_t timeUs);
77c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t seekToOffset(off64_t offset);
78ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    status_t readNextPacket(MediaBuffer **buffer);
79ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
805a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    status_t init();
81ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    sp<MetaData> getFileMetaData() { return mFileMeta; }
834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
84ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberprivate:
85ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    struct Page {
86ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint64_t mGranulePosition;
87ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint32_t mSerialNo;
88ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint32_t mPageNo;
89ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint8_t mFlags;
90ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint8_t mNumSegments;
91ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        uint8_t mLace[255];
92ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    };
93ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
943fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    struct TOCEntry {
953fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        off64_t mPageOffset;
963fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        int64_t mTimeUs;
973fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    };
983fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
99ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    sp<DataSource> mSource;
100c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mOffset;
101ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    Page mCurrentPage;
102db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    uint64_t mPrevGranulePosition;
103ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t mCurrentPageSize;
104db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    bool mFirstPacketInPage;
105db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    uint64_t mCurrentPageSamples;
106ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t mNextLaceIndex;
107ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
108c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mFirstDataOffset;
10996f52cde23982f668592418a9548045237d5e327Andreas Huber
110ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    vorbis_info mVi;
111ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    vorbis_comment mVc;
112ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
113ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    sp<MetaData> mMeta;
1144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    sp<MetaData> mFileMeta;
115ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1163fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    Vector<TOCEntry> mTableOfContents;
1173fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
118c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ssize_t readPage(off64_t offset, Page *page);
119c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t findNextPage(off64_t startOffset, off64_t *pageOffset);
120ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1215a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    status_t verifyHeader(
122ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            MediaBuffer *buffer, uint8_t type);
123ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    void parseFileMetaData();
1254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1263fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    status_t findPrevGranulePosition(off64_t pageOffset, uint64_t *granulePos);
1273fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
1283fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    void buildTableOfContents();
129db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
130ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MyVorbisExtractor(const MyVorbisExtractor &);
131ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MyVorbisExtractor &operator=(const MyVorbisExtractor &);
132ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber};
133ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
134856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt(
135856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        const sp<MetaData> &fileMeta, const void *data, size_t size);
136856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten
137ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
138ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
139ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::OggSource(const sp<OggExtractor> &extractor)
140ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mExtractor(extractor),
141ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mStarted(false) {
142ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
143ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
144ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::~OggSource() {
145ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mStarted) {
146ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        stop();
147ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
148ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
149ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
150ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggSource::getFormat() {
151ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mExtractor->mImpl->getFormat();
152ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
153ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
154ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::start(MetaData *params) {
155ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mStarted) {
156ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return INVALID_OPERATION;
157ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
158ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
159ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mStarted = true;
160ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
161ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
162ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
163ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
164ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::stop() {
165ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mStarted = false;
166ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
167ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
168ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
169ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
170ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::read(
171ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
172ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = NULL;
173ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
174ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t seekTimeUs;
175abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
176abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
1773fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        if (mExtractor->mImpl->seekToTime(seekTimeUs) != OK) {
178ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return ERROR_END_OF_STREAM;
179ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
180ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
181ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
182ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MediaBuffer *packet;
183ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    status_t err = mExtractor->mImpl->readNextPacket(&packet);
184ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
185ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (err != OK) {
186ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return err;
187ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
188ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
189ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0
190ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t timeUs;
191ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) {
192df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("found time = %lld us", timeUs);
193ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    } else {
194df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("NO time");
195ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
196ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif
197ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1988bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    packet->meta_data()->setInt32(kKeyIsSyncFrame, 1);
1998bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
200ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = packet;
201ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
202ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
203ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
204ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
205ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
206ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
207ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberMyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source)
208ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mSource(source),
209ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mOffset(0),
210db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber      mPrevGranulePosition(0),
211ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mCurrentPageSize(0),
212db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber      mFirstPacketInPage(true),
213db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber      mCurrentPageSamples(0),
21496f52cde23982f668592418a9548045237d5e327Andreas Huber      mNextLaceIndex(0),
21596f52cde23982f668592418a9548045237d5e327Andreas Huber      mFirstDataOffset(-1) {
216ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPage.mNumSegments = 0;
2174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
2184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_info_init(&mVi);
2194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_comment_init(&mVc);
220ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
221ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
222ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberMyVorbisExtractor::~MyVorbisExtractor() {
2234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_comment_clear(&mVc);
2244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_info_clear(&mVi);
225ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
226ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
227ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> MyVorbisExtractor::getFormat() const {
228ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mMeta;
229ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
230ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
231ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::findNextPage(
232c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t startOffset, off64_t *pageOffset) {
233ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *pageOffset = startOffset;
234ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
235ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (;;) {
236ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        char signature[4];
237ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
238ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
239ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (n < 4) {
240ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            *pageOffset = 0;
241ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
242ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
243ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
244ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
245ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (!memcmp(signature, "OggS", 4)) {
246ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (*pageOffset > startOffset) {
2473856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("skipped %lld bytes of junk to reach next frame",
248ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                     *pageOffset - startOffset);
249ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
250ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
251ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return OK;
252ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
253ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
254ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ++*pageOffset;
255ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
256ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
257ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
258db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// Given the offset of the "current" page, find the page immediately preceding
259db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// it (if any) and return its granule position.
260db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// To do this we back up from the "current" page's offset until we find any
261db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// page preceding it and then scan forward to just before the current page.
2623fd91baee812919f53a85c5c05f32606313f8334Andreas Huberstatus_t MyVorbisExtractor::findPrevGranulePosition(
2633fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        off64_t pageOffset, uint64_t *granulePos) {
2643fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    *granulePos = 0;
2653fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
266c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t prevPageOffset = 0;
267c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t prevGuess = pageOffset;
268db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    for (;;) {
269db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (prevGuess >= 5000) {
270db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            prevGuess -= 5000;
271db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        } else {
272db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            prevGuess = 0;
273db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
274db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
2753856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("backing up %lld bytes", pageOffset - prevGuess);
276db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
2773fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        status_t err = findNextPage(prevGuess, &prevPageOffset);
2783fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        if (err != OK) {
2793fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            return err;
2803fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        }
281db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
282db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (prevPageOffset < pageOffset || prevGuess == 0) {
283db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            break;
284db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
285db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    }
286db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
287db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    if (prevPageOffset == pageOffset) {
288db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        // We did not find a page preceding this one.
2893fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        return UNKNOWN_ERROR;
290db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    }
291db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
2923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("prevPageOffset at %lld, pageOffset at %lld",
2933fd91baee812919f53a85c5c05f32606313f8334Andreas Huber         prevPageOffset, pageOffset);
294db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
295db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    for (;;) {
296db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        Page prevPage;
297db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        ssize_t n = readPage(prevPageOffset, &prevPage);
298db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
299db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (n <= 0) {
3003fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            return (status_t)n;
301db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
302db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
303db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        prevPageOffset += n;
304db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
305db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        if (prevPageOffset == pageOffset) {
3063fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            *granulePos = prevPage.mGranulePosition;
3073fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            return OK;
308db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        }
309db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    }
310db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber}
311db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
3123fd91baee812919f53a85c5c05f32606313f8334Andreas Huberstatus_t MyVorbisExtractor::seekToTime(int64_t timeUs) {
3133fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    if (mTableOfContents.isEmpty()) {
3143fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // Perform approximate seeking based on avg. bitrate.
3153fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
3163fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        off64_t pos = timeUs * approxBitrate() / 8000000ll;
3173fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
3183856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("seeking to offset %lld", pos);
3193fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        return seekToOffset(pos);
3203fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
3213fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
3223fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    size_t left = 0;
3233fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    size_t right = mTableOfContents.size();
3243fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    while (left < right) {
3253fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        size_t center = left / 2 + right / 2 + (left & right & 1);
3263fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
3273fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        const TOCEntry &entry = mTableOfContents.itemAt(center);
3283fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
3293fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        if (timeUs < entry.mTimeUs) {
3303fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            right = center;
3313fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        } else if (timeUs > entry.mTimeUs) {
3323fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            left = center + 1;
3333fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        } else {
3343fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            left = right = center;
3353fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            break;
3363fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        }
3373fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
3383fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
3393fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    const TOCEntry &entry = mTableOfContents.itemAt(left);
3403fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
3413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("seeking to entry %d / %d at offset %lld",
3423fd91baee812919f53a85c5c05f32606313f8334Andreas Huber         left, mTableOfContents.size(), entry.mPageOffset);
3433fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
3443fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    return seekToOffset(entry.mPageOffset);
3453fd91baee812919f53a85c5c05f32606313f8334Andreas Huber}
3463fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
347c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MyVorbisExtractor::seekToOffset(off64_t offset) {
34896f52cde23982f668592418a9548045237d5e327Andreas Huber    if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) {
34996f52cde23982f668592418a9548045237d5e327Andreas Huber        // Once we know where the actual audio data starts (past the headers)
35096f52cde23982f668592418a9548045237d5e327Andreas Huber        // don't ever seek to anywhere before that.
35196f52cde23982f668592418a9548045237d5e327Andreas Huber        offset = mFirstDataOffset;
35296f52cde23982f668592418a9548045237d5e327Andreas Huber    }
35396f52cde23982f668592418a9548045237d5e327Andreas Huber
354c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t pageOffset;
355ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    status_t err = findNextPage(offset, &pageOffset);
356ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
357ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (err != OK) {
358ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return err;
359ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
360ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
361db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    // We found the page we wanted to seek to, but we'll also need
362db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    // the page preceding it to determine how many valid samples are on
363db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    // this page.
3643fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    findPrevGranulePosition(pageOffset, &mPrevGranulePosition);
365db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
366ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mOffset = pageOffset;
367ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
368ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPageSize = 0;
369db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    mFirstPacketInPage = true;
370db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber    mCurrentPageSamples = 0;
371ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPage.mNumSegments = 0;
372ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mNextLaceIndex = 0;
373ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
374ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    // XXX what if new page continues packet from last???
375ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
376ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
377ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
378ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
379c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MyVorbisExtractor::readPage(off64_t offset, Page *page) {
380ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    uint8_t header[27];
381df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber    ssize_t n;
382df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber    if ((n = mSource->readAt(offset, header, sizeof(header)))
383ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            < (ssize_t)sizeof(header)) {
3843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("failed to read %d bytes at offset 0x%016llx, got %ld bytes",
385df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber             sizeof(header), offset, n);
386ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
387df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber        if (n < 0) {
388df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber            return n;
389df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber        } else if (n == 0) {
390df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber            return ERROR_END_OF_STREAM;
391df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber        } else {
392df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber            return ERROR_IO;
393df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber        }
394ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
395ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
396ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (memcmp(header, "OggS", 4)) {
397ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_MALFORMED;
398ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
399ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
400ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (header[4] != 0) {
401ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        // Wrong version.
402ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
403ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_UNSUPPORTED;
404ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
405ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
406ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mFlags = header[5];
407ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
408ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (page->mFlags & ~7) {
409ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        // Only bits 0-2 are defined in version 0.
410ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_MALFORMED;
411ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
412ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
413ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mGranulePosition = U64LE_AT(&header[6]);
414ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
415ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0
416ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    printf("granulePosition = %llu (0x%llx)\n",
417ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber           page->mGranulePosition, page->mGranulePosition);
418ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif
419ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
420ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mSerialNo = U32LE_AT(&header[14]);
421ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mPageNo = U32LE_AT(&header[18]);
422ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
423ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mNumSegments = header[26];
424ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mSource->readAt(
425ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                offset + sizeof(header), page->mLace, page->mNumSegments)
426ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            < (ssize_t)page->mNumSegments) {
427ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_IO;
428ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
429ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
430ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t totalSize = 0;;
431ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < page->mNumSegments; ++i) {
432ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        totalSize += page->mLace[i];
433ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
434ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
4355a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#if 0
436ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    String8 tmp;
437ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < page->mNumSegments; ++i) {
438ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        char x[32];
439ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]);
440ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
441ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        tmp.append(x);
442ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
443ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
4443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string());
4455a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#endif
446ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
447ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return sizeof(header) + page->mNumSegments + totalSize;
448ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
449ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
450ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) {
451ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = NULL;
452ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
453ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MediaBuffer *buffer = NULL;
454ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t timeUs = -1;
455ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
456ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (;;) {
457ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        size_t i;
458ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        size_t packetSize = 0;
459ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        bool gotFullPacket = false;
460ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) {
461ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            uint8_t lace = mCurrentPage.mLace[i];
462ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
463ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            packetSize += lace;
464ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
465ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (lace < 255) {
466ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                gotFullPacket = true;
467ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                ++i;
468ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                break;
469ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
470ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
471ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
472ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (mNextLaceIndex < mCurrentPage.mNumSegments) {
473c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments;
474ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            for (size_t j = 0; j < mNextLaceIndex; ++j) {
475ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                dataOffset += mCurrentPage.mLace[j];
476ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
477ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
478ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            size_t fullSize = packetSize;
479ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer != NULL) {
480ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                fullSize += buffer->range_length();
481ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
482ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            MediaBuffer *tmp = new MediaBuffer(fullSize);
483ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer != NULL) {
484ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                memcpy(tmp->data(), buffer->data(), buffer->range_length());
485ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                tmp->set_range(0, buffer->range_length());
486ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer->release();
487ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber            } else {
488ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // XXX Not only is this not technically the correct time for
489ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // this packet, we also stamp every packet in this page
490ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // with the same time. This needs fixing later.
491ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber
492ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber                if (mVi.rate) {
493ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber                    // Rate may not have been initialized yet if we're currently
494ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber                    // reading the configuration packets...
495ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber                    // Fortunately, the timestamp doesn't matter for those.
496ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber                    timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate;
497ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber                }
498ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                tmp->set_range(0, 0);
499ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
500ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            buffer = tmp;
501ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
502ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            ssize_t n = mSource->readAt(
503ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    dataOffset,
504ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    (uint8_t *)buffer->data() + buffer->range_length(),
505ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    packetSize);
506ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
507ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (n < (ssize_t)packetSize) {
5083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("failed to read %d bytes at 0x%016llx, got %ld bytes",
509df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber                     packetSize, dataOffset, n);
510ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return ERROR_IO;
511ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
512ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
513ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            buffer->set_range(0, fullSize);
514ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
515ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mNextLaceIndex = i;
516ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
517ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (gotFullPacket) {
518ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // We've just read the entire packet.
519ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
520ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                if (timeUs >= 0) {
521ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
522ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                }
523ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
524db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                if (mFirstPacketInPage) {
525db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                    buffer->meta_data()->setInt32(
526db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                            kKeyValidSamples, mCurrentPageSamples);
527db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                    mFirstPacketInPage = false;
528db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                }
529db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
530ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                *out = buffer;
531ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
532ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return OK;
533ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
534ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
535ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            // fall through, the buffer now contains the start of the packet.
536ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
537ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
538ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments);
539ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
540ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mOffset += mCurrentPageSize;
541ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ssize_t n = readPage(mOffset, &mCurrentPage);
542ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
543ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (n <= 0) {
544ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer) {
545ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer->release();
546ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer = NULL;
547ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
548ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("readPage returned %ld", n);
550ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
551ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return n < 0 ? n : (status_t)ERROR_END_OF_STREAM;
552ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
553ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
554db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        mCurrentPageSamples =
555db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber            mCurrentPage.mGranulePosition - mPrevGranulePosition;
556db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        mFirstPacketInPage = true;
557db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
558db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber        mPrevGranulePosition = mCurrentPage.mGranulePosition;
559db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
560ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mCurrentPageSize = n;
561ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mNextLaceIndex = 0;
562ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
563ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (buffer != NULL) {
564ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if ((mCurrentPage.mFlags & 1) == 0) {
565ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // This page does not continue the packet, i.e. the packet
566ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // is already complete.
567ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
568ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                if (timeUs >= 0) {
569ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
570ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                }
571ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
572db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                buffer->meta_data()->setInt32(
573db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                        kKeyValidSamples, mCurrentPageSamples);
574db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber                mFirstPacketInPage = false;
575db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber
576ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                *out = buffer;
577ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
578ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return OK;
579ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
580ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
581ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
582ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
583ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5845a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huberstatus_t MyVorbisExtractor::init() {
585ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mMeta = new MetaData;
586ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
587ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
588ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MediaBuffer *packet;
5895a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    status_t err;
5905a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if ((err = readNextPacket(&packet)) != OK) {
5915a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return err;
5925a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
5933856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("read packet of size %d\n", packet->range_length());
5945a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    err = verifyHeader(packet, 1);
595ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet->release();
596ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet = NULL;
5975a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if (err != OK) {
5985a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return err;
5995a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
600ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
6015a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if ((err = readNextPacket(&packet)) != OK) {
6025a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return err;
6035a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
6043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("read packet of size %d\n", packet->range_length());
6055a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    err = verifyHeader(packet, 3);
606ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet->release();
607ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet = NULL;
6085a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if (err != OK) {
6095a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return err;
6105a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
611ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
6125a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if ((err = readNextPacket(&packet)) != OK) {
6135a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return err;
6145a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
6153856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("read packet of size %d\n", packet->range_length());
6165a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    err = verifyHeader(packet, 5);
617ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet->release();
618ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet = NULL;
6195a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if (err != OK) {
6205a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return err;
6215a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
62296f52cde23982f668592418a9548045237d5e327Andreas Huber
62396f52cde23982f668592418a9548045237d5e327Andreas Huber    mFirstDataOffset = mOffset + mCurrentPageSize;
6245a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber
6253fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    off64_t size;
6263fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    uint64_t lastGranulePosition;
6273fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    if (!(mSource->flags() & DataSource::kIsCachingDataSource)
6283fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            && mSource->getSize(&size) == OK
6293fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            && findPrevGranulePosition(size, &lastGranulePosition) == OK) {
6303fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // Let's assume it's cheap to seek to the end.
6313fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // The granule position of the final page in the stream will
6323fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // give us the exact duration of the content, something that
6333fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // we can only approximate using avg. bitrate if seeking to
6343fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        // the end is too expensive or impossible (live streaming).
6353fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
6363fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        int64_t durationUs = lastGranulePosition * 1000000ll / mVi.rate;
6373fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
6383fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        mMeta->setInt64(kKeyDuration, durationUs);
6393fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
6403fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        buildTableOfContents();
6413fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
6423fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
6435a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    return OK;
644ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
645ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
6463fd91baee812919f53a85c5c05f32606313f8334Andreas Hubervoid MyVorbisExtractor::buildTableOfContents() {
6473fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    off64_t offset = mFirstDataOffset;
6483fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    Page page;
6493fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    ssize_t pageSize;
6503fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    while ((pageSize = readPage(offset, &page)) > 0) {
6513fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        mTableOfContents.push();
6523fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
6533fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        TOCEntry &entry =
6543fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            mTableOfContents.editItemAt(mTableOfContents.size() - 1);
6553fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
6563fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        entry.mPageOffset = offset;
6573fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        entry.mTimeUs = page.mGranulePosition * 1000000ll / mVi.rate;
6583fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
6593fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        offset += (size_t)pageSize;
6603fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
6613fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
6623fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    // Limit the maximum amount of RAM we spend on the table of contents,
6633fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    // if necessary thin out the table evenly to trim it down to maximum
6643fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    // size.
6653fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
6663fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    static const size_t kMaxTOCSize = 8192;
6673fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    static const size_t kMaxNumTOCEntries = kMaxTOCSize / sizeof(TOCEntry);
6683fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
6693fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    size_t numerator = mTableOfContents.size();
6703fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
6713fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    if (numerator > kMaxNumTOCEntries) {
6723fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        size_t denom = numerator - kMaxNumTOCEntries;
6733fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
6743fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        size_t accum = 0;
6753fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        for (ssize_t i = mTableOfContents.size() - 1; i >= 0; --i) {
6763fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            accum += denom;
6773fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            if (accum >= numerator) {
6783fd91baee812919f53a85c5c05f32606313f8334Andreas Huber                mTableOfContents.removeAt(i);
6793fd91baee812919f53a85c5c05f32606313f8334Andreas Huber                accum -= numerator;
6803fd91baee812919f53a85c5c05f32606313f8334Andreas Huber            }
6813fd91baee812919f53a85c5c05f32606313f8334Andreas Huber        }
6823fd91baee812919f53a85c5c05f32606313f8334Andreas Huber    }
6833fd91baee812919f53a85c5c05f32606313f8334Andreas Huber}
6843fd91baee812919f53a85c5c05f32606313f8334Andreas Huber
6855a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huberstatus_t MyVorbisExtractor::verifyHeader(
686ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        MediaBuffer *buffer, uint8_t type) {
687ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    const uint8_t *data =
688ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
689ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
690ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t size = buffer->range_length();
691ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
6925a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) {
6935a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        return ERROR_MALFORMED;
6945a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
695ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
696ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ogg_buffer buf;
697ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.data = (uint8_t *)data;
698ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.size = size;
699ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.refcount = 1;
700ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.ptr.owner = NULL;
701ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
702ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ogg_reference ref;
703ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.buffer = &buf;
704ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.begin = 0;
705ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.length = size;
706ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.next = NULL;
707ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
708ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    oggpack_buffer bits;
709ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    oggpack_readinit(&bits, &ref);
710ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
711ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    CHECK_EQ(oggpack_read(&bits, 8), type);
712ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < 6; ++i) {
713ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        oggpack_read(&bits, 8);  // skip 'vorbis'
714ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
715ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
716ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    switch (type) {
717ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 1:
718ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
719ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits));
720ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
721ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setData(kKeyVorbisInfo, 0, data, size);
722ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setInt32(kKeySampleRate, mVi.rate);
723ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setInt32(kKeyChannelCount, mVi.channels);
724ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
7253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("lower-bitrate = %ld", mVi.bitrate_lower);
7263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
7273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
7283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("window-bitrate = %ld", mVi.bitrate_window);
729ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
730c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t size;
731ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (mSource->getSize(&size) == OK) {
732ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                uint64_t bps = approxBitrate();
733f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang                if (bps != 0) {
734f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang                    mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
735f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang                }
736ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
737ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
738ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
739ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
740ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 3:
741ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
7425a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            if (0 != _vorbis_unpack_comment(&mVc, &bits)) {
7435a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber                return ERROR_MALFORMED;
7445a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            }
7454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            parseFileMetaData();
747ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
748ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
749ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
750ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 5:
751ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
7525a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            if (0 != _vorbis_unpack_books(&mVi, &bits)) {
7535a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber                return ERROR_MALFORMED;
7545a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber            }
755ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
756ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setData(kKeyVorbisBooks, 0, data, size);
757ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
758ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
759ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
7605a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber
7615a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    return OK;
762ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
763ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
764ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberuint64_t MyVorbisExtractor::approxBitrate() {
765ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mVi.bitrate_nominal != 0) {
766ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return mVi.bitrate_nominal;
767ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
768ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
769ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
770ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
771ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
7724595be952e3b1d6776a023e3f447c057797f1505Andreas Hubervoid MyVorbisExtractor::parseFileMetaData() {
7734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta = new MetaData;
7744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
7754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
776856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten    for (int i = 0; i < mVc.comments; ++i) {
777856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        const char *comment = mVc.user_comments[i];
778856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        size_t commentLength = mVc.comment_lengths[i];
779856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        parseVorbisComment(mFileMeta, comment, commentLength);
780df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
781856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten    }
782856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten}
783856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten
784856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenvoid parseVorbisComment(
785856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        const sp<MetaData> &fileMeta, const char *comment, size_t commentLength)
786856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten{
7874595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    struct {
7884595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        const char *const mTag;
7894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        uint32_t mKey;
7904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    } kMap[] = {
7914595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "TITLE", kKeyTitle },
7924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "ARTIST", kKeyArtist },
79311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        { "ALBUMARTIST", kKeyAlbumArtist },
79411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        { "ALBUM ARTIST", kKeyAlbumArtist },
79511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        { "COMPILATION", kKeyCompilation },
7964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "ALBUM", kKeyAlbum },
7974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "COMPOSER", kKeyComposer },
7984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "GENRE", kKeyGenre },
7994595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "AUTHOR", kKeyAuthor },
8004595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "TRACKNUMBER", kKeyCDTrackNumber },
8014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "DISCNUMBER", kKeyDiscNumber },
8024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "DATE", kKeyDate },
8034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "LYRICIST", kKeyWriter },
8044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
8058ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber        { "ANDROID_LOOP", kKeyAutoLoop },
8064595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    };
8074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
8094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            size_t tagLen = strlen(kMap[j].mTag);
8104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (!strncasecmp(kMap[j].mTag, comment, tagLen)
8114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                    && comment[tagLen] == '=') {
8124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                if (kMap[j].mKey == kKeyAlbumArt) {
8134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                    extractAlbumArt(
814856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten                            fileMeta,
8154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                            &comment[tagLen + 1],
816856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten                            commentLength - tagLen - 1);
8178ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber                } else if (kMap[j].mKey == kKeyAutoLoop) {
8188ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber                    if (!strcasecmp(&comment[tagLen + 1], "true")) {
819856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten                        fileMeta->setInt32(kKeyAutoLoop, true);
8208ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber                    }
8214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                } else {
822856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten                    fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
8234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                }
8244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            }
8254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
8264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8274595be952e3b1d6776a023e3f447c057797f1505Andreas Huber}
8284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8294595be952e3b1d6776a023e3f447c057797f1505Andreas Huber// The returned buffer should be free()d.
8304595be952e3b1d6776a023e3f447c057797f1505Andreas Huberstatic uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) {
8314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    *outSize = 0;
8324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if ((size % 4) != 0) {
8344595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        return NULL;
8354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
8364595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8374595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t n = size;
8384595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t padding = 0;
8394595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (n >= 1 && s[n - 1] == '=') {
8404595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        padding = 1;
8414595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8424595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        if (n >= 2 && s[n - 2] == '=') {
8434595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            padding = 2;
8444595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
8454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
8464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8474595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t outLen = 3 * size / 4 - padding;
8484595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    *outSize = outLen;
8504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    void *buffer = malloc(outLen);
8524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint8_t *out = (uint8_t *)buffer;
8544595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t j = 0;
8554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t accum = 0;
8564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    for (size_t i = 0; i < n; ++i) {
8574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        char c = s[i];
8584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        unsigned value;
8594595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        if (c >= 'A' && c <= 'Z') {
8604595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = c - 'A';
8614595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c >= 'a' && c <= 'z') {
8624595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 26 + c - 'a';
8634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c >= '0' && c <= '9') {
8644595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 52 + c - '0';
8654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c == '+') {
8664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 62;
8674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c == '/') {
8684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 63;
8694595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c != '=') {
8704595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            return NULL;
8714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else {
8724595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (i < n - padding) {
8734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                return NULL;
8744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            }
8754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8764595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 0;
8774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
8784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        accum = (accum << 6) | value;
8804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        if (((i + 1) % 4) == 0) {
8824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            out[j++] = (accum >> 16);
8834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8844595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
8854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (j < outLen) { out[j++] = accum & 0xff; }
8864595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8874595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            accum = 0;
8884595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
8894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
8904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8914595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    return (uint8_t *)buffer;
8924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber}
8934595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
894856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt(
895856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten        const sp<MetaData> &fileMeta, const void *data, size_t size) {
8963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("extractAlbumArt from '%s'", (const char *)data);
8974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
8984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t flacSize;
8994595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize);
9004595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flac == NULL) {
90229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("malformed base64 encoded data.");
9034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        return;
9044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
9054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9063856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("got flac of size %d", flacSize);
9074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t picType;
9094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t typeLen;
9104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t descLen;
9114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t dataLen;
9124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    char type[128];
9134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 8) {
9154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
9164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
9174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    picType = U32_AT(flac);
9194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (picType != 3) {
9214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        // This is not a front cover.
9224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
9234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
9244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    typeLen = U32_AT(&flac[4]);
9264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (typeLen + 1 > sizeof(type)) {
9274595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
9284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
9294595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9304595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 8 + typeLen) {
9314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
9324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
9334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9344595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    memcpy(type, &flac[8], typeLen);
9354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    type[typeLen] = '\0';
9364595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("picType = %d, type = '%s'", picType, type);
9384595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9394595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (!strcmp(type, "-->")) {
9404595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        // This is not inline cover art, but an external url instead.
9414595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
9424595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
9434595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9444595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    descLen = U32_AT(&flac[8 + typeLen]);
9454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 32 + typeLen + descLen) {
9474595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
9484595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
9494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
9514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 32 + typeLen + descLen + dataLen) {
9534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
9544595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
9554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9563856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("got image data, %d trailing bytes",
9574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber         flacSize - 32 - typeLen - descLen - dataLen);
9584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
959856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten    fileMeta->setData(
9604595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
9614595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
962856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten    fileMeta->setCString(kKeyAlbumArtMIME, type);
9634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
9644595be952e3b1d6776a023e3f447c057797f1505Andreas Huberexit:
9654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    free(flac);
9664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    flac = NULL;
9674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber}
9684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
969ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
970ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
971ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::OggExtractor(const sp<DataSource> &source)
972ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mDataSource(source),
973ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mInitCheck(NO_INIT),
974ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mImpl(NULL) {
975ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mImpl = new MyVorbisExtractor(mDataSource);
9765a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    mInitCheck = mImpl->seekToOffset(0);
977ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
9785a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    if (mInitCheck == OK) {
9795a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber        mInitCheck = mImpl->init();
9805a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber    }
981ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
982ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
983ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::~OggExtractor() {
984ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    delete mImpl;
985ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mImpl = NULL;
986ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
987ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
988ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersize_t OggExtractor::countTracks() {
989ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mInitCheck != OK ? 0 : 1;
990ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
991ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
992ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MediaSource> OggExtractor::getTrack(size_t index) {
993ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (index >= 1) {
994ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return NULL;
995ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
996ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
997ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return new OggSource(this);
998ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
999ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1000ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getTrackMetaData(
1001ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        size_t index, uint32_t flags) {
1002ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (index >= 1) {
1003ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return NULL;
1004ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
1005ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1006ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mImpl->getFormat();
1007ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1008ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1009ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getMetaData() {
10104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    return mImpl->getFileMetaData();
1011ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1012ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1013ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberbool SniffOgg(
10145a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
10155a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        sp<AMessage> *) {
1016ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    char tmp[4];
1017ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
1018ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return false;
1019ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
1020ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1021ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG);
1022ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *confidence = 0.2f;
1023ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1024ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return true;
1025ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
1026ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1027ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}  // namespace android
1028