OggExtractor.cpp revision 4595be952e3b1d6776a023e3f447c057797f1505
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
76ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    status_t seekToOffset(off_t offset);
77ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    status_t readNextPacket(MediaBuffer **buffer);
78ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
79ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    void 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;
94ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    off_t mOffset;
95ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    Page mCurrentPage;
96ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t mCurrentPageSize;
97ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t mNextLaceIndex;
98ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
9996f52cde23982f668592418a9548045237d5e327Andreas Huber    off_t mFirstDataOffset;
10096f52cde23982f668592418a9548045237d5e327Andreas Huber
101ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    vorbis_info mVi;
102ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    vorbis_comment mVc;
103ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
104ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    sp<MetaData> mMeta;
1054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    sp<MetaData> mFileMeta;
106ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
107ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ssize_t readPage(off_t offset, Page *page);
108ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    status_t findNextPage(off_t startOffset, off_t *pageOffset);
109ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
110ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    void verifyHeader(
111ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            MediaBuffer *buffer, uint8_t type);
112ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
1134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    void parseFileMetaData();
1144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    void extractAlbumArt(const void *data, size_t size);
1154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
116ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MyVorbisExtractor(const MyVorbisExtractor &);
117ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MyVorbisExtractor &operator=(const MyVorbisExtractor &);
118ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber};
119ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
120ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
121ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
122ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::OggSource(const sp<OggExtractor> &extractor)
123ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mExtractor(extractor),
124ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mStarted(false) {
125ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
126ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
127ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::~OggSource() {
128ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mStarted) {
129ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        stop();
130ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
131ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
132ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
133ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggSource::getFormat() {
134ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mExtractor->mImpl->getFormat();
135ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
136ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
137ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::start(MetaData *params) {
138ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mStarted) {
139ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return INVALID_OPERATION;
140ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
141ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
142ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mStarted = true;
143ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
144ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
145ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
146ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
147ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::stop() {
148ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mStarted = false;
149ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
150ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
151ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
152ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
153ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::read(
154ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
155ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = NULL;
156ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
157ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t seekTimeUs;
158ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (options && options->getSeekTo(&seekTimeUs)) {
159ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        off_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll;
160ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        LOGI("seeking to offset %ld", pos);
161ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
162ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (mExtractor->mImpl->seekToOffset(pos) != OK) {
163ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return ERROR_END_OF_STREAM;
164ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
165ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
166ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
167ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MediaBuffer *packet;
168ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    status_t err = mExtractor->mImpl->readNextPacket(&packet);
169ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
170ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (err != OK) {
171ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return err;
172ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
173ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
174ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0
175ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t timeUs;
176ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) {
177ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        LOGI("found time = %lld us", timeUs);
178ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    } else {
179ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        LOGI("NO time");
180ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
181ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif
182ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
183ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = packet;
184ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
185ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
186ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
187ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
188ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
189ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
190ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberMyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source)
191ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mSource(source),
192ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mOffset(0),
193ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mCurrentPageSize(0),
19496f52cde23982f668592418a9548045237d5e327Andreas Huber      mNextLaceIndex(0),
19596f52cde23982f668592418a9548045237d5e327Andreas Huber      mFirstDataOffset(-1) {
196ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPage.mNumSegments = 0;
1974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
1984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_info_init(&mVi);
1994595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_comment_init(&mVc);
200ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
201ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
202ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberMyVorbisExtractor::~MyVorbisExtractor() {
2034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_comment_clear(&mVc);
2044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    vorbis_info_clear(&mVi);
205ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
206ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
207ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> MyVorbisExtractor::getFormat() const {
208ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mMeta;
209ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
210ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
211ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::findNextPage(
212ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        off_t startOffset, off_t *pageOffset) {
213ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *pageOffset = startOffset;
214ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
215ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (;;) {
216ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        char signature[4];
217ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
218ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
219ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (n < 4) {
220ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            *pageOffset = 0;
221ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
222ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
223ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
224ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
225ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (!memcmp(signature, "OggS", 4)) {
226ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (*pageOffset > startOffset) {
227ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                LOGV("skipped %ld bytes of junk to reach next frame",
228ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                     *pageOffset - startOffset);
229ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
230ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
231ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return OK;
232ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
233ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
234ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ++*pageOffset;
235ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
236ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
237ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
238ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::seekToOffset(off_t offset) {
23996f52cde23982f668592418a9548045237d5e327Andreas Huber    if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) {
24096f52cde23982f668592418a9548045237d5e327Andreas Huber        // Once we know where the actual audio data starts (past the headers)
24196f52cde23982f668592418a9548045237d5e327Andreas Huber        // don't ever seek to anywhere before that.
24296f52cde23982f668592418a9548045237d5e327Andreas Huber        offset = mFirstDataOffset;
24396f52cde23982f668592418a9548045237d5e327Andreas Huber    }
24496f52cde23982f668592418a9548045237d5e327Andreas Huber
245ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    off_t pageOffset;
246ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    status_t err = findNextPage(offset, &pageOffset);
247ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
248ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (err != OK) {
249ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return err;
250ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
251ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
252ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mOffset = pageOffset;
253ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
254ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPageSize = 0;
255ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mCurrentPage.mNumSegments = 0;
256ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mNextLaceIndex = 0;
257ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
258ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    // XXX what if new page continues packet from last???
259ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
260ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return OK;
261ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
262ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
263ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberssize_t MyVorbisExtractor::readPage(off_t offset, Page *page) {
264ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    uint8_t header[27];
265ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mSource->readAt(offset, header, sizeof(header))
266ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            < (ssize_t)sizeof(header)) {
267ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        LOGE("failed to read %d bytes at offset 0x%08lx", sizeof(header), offset);
268ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
269ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_IO;
270ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
271ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
272ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (memcmp(header, "OggS", 4)) {
273ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_MALFORMED;
274ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
275ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
276ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (header[4] != 0) {
277ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        // Wrong version.
278ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
279ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_UNSUPPORTED;
280ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
281ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
282ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mFlags = header[5];
283ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
284ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (page->mFlags & ~7) {
285ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        // Only bits 0-2 are defined in version 0.
286ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_MALFORMED;
287ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
288ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
289ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mGranulePosition = U64LE_AT(&header[6]);
290ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
291ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0
292ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    printf("granulePosition = %llu (0x%llx)\n",
293ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber           page->mGranulePosition, page->mGranulePosition);
294ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif
295ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
296ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mSerialNo = U32LE_AT(&header[14]);
297ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mPageNo = U32LE_AT(&header[18]);
298ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
299ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    page->mNumSegments = header[26];
300ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mSource->readAt(
301ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                offset + sizeof(header), page->mLace, page->mNumSegments)
302ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            < (ssize_t)page->mNumSegments) {
303ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return ERROR_IO;
304ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
305ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
306ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t totalSize = 0;;
307ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < page->mNumSegments; ++i) {
308ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        totalSize += page->mLace[i];
309ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
310ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
311ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    String8 tmp;
312ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < page->mNumSegments; ++i) {
313ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        char x[32];
314ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]);
315ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
316ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        tmp.append(x);
317ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
318ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
3194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    // LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string());
320ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
321ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return sizeof(header) + page->mNumSegments + totalSize;
322ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
323ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
324ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) {
325ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *out = NULL;
326ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
327ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MediaBuffer *buffer = NULL;
328ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    int64_t timeUs = -1;
329ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
330ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (;;) {
331ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        size_t i;
332ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        size_t packetSize = 0;
333ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        bool gotFullPacket = false;
334ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) {
335ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            uint8_t lace = mCurrentPage.mLace[i];
336ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
337ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            packetSize += lace;
338ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
339ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (lace < 255) {
340ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                gotFullPacket = true;
341ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                ++i;
342ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                break;
343ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
344ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
345ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
346ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (mNextLaceIndex < mCurrentPage.mNumSegments) {
347ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            off_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments;
348ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            for (size_t j = 0; j < mNextLaceIndex; ++j) {
349ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                dataOffset += mCurrentPage.mLace[j];
350ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
351ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
352ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            size_t fullSize = packetSize;
353ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer != NULL) {
354ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                fullSize += buffer->range_length();
355ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
356ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            MediaBuffer *tmp = new MediaBuffer(fullSize);
357ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer != NULL) {
358ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                memcpy(tmp->data(), buffer->data(), buffer->range_length());
359ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                tmp->set_range(0, buffer->range_length());
360ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer->release();
361ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            } else {
362ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // XXX Not only is this not technically the correct time for
363ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // this packet, we also stamp every packet in this page
364ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // with the same time. This needs fixing later.
365ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate;
366ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                tmp->set_range(0, 0);
367ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
368ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            buffer = tmp;
369ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
370ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            ssize_t n = mSource->readAt(
371ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    dataOffset,
372ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    (uint8_t *)buffer->data() + buffer->range_length(),
373ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    packetSize);
374ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
375ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (n < (ssize_t)packetSize) {
376ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                LOGE("failed to read %d bytes at 0x%08lx", packetSize, dataOffset);
377ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return ERROR_IO;
378ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
379ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
380ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            buffer->set_range(0, fullSize);
381ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
382ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mNextLaceIndex = i;
383ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
384ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (gotFullPacket) {
385ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // We've just read the entire packet.
386ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
387ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                if (timeUs >= 0) {
388ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
389ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                }
390ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
391ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                *out = buffer;
392ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
393ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return OK;
394ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
395ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
396ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            // fall through, the buffer now contains the start of the packet.
397ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
398ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
399ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments);
400ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
401ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mOffset += mCurrentPageSize;
402ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        ssize_t n = readPage(mOffset, &mCurrentPage);
403ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
404ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (n <= 0) {
405ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (buffer) {
406ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer->release();
407ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                buffer = NULL;
408ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
409ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
410ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            LOGE("readPage returned %ld", n);
411ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
412ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            return n < 0 ? n : (status_t)ERROR_END_OF_STREAM;
413ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
414ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
415ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mCurrentPageSize = n;
416ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        mNextLaceIndex = 0;
417ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
418ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        if (buffer != NULL) {
419ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if ((mCurrentPage.mFlags & 1) == 0) {
420ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // This page does not continue the packet, i.e. the packet
421ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                // is already complete.
422ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
423ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                if (timeUs >= 0) {
424ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
425ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                }
426ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
427ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                *out = buffer;
428ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
429ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                return OK;
430ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
431ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
432ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
433ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
434ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
435ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubervoid MyVorbisExtractor::init() {
436ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mMeta = new MetaData;
437ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
438ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
439ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    MediaBuffer *packet;
440ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    CHECK_EQ(readNextPacket(&packet), OK);
441ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    LOGV("read packet of size %d\n", packet->range_length());
442ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    verifyHeader(packet, 1);
443ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet->release();
444ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet = NULL;
445ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
446ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    CHECK_EQ(readNextPacket(&packet), OK);
447ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    LOGV("read packet of size %d\n", packet->range_length());
448ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    verifyHeader(packet, 3);
449ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet->release();
450ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet = NULL;
451ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
452ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    CHECK_EQ(readNextPacket(&packet), OK);
453ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    LOGV("read packet of size %d\n", packet->range_length());
454ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    verifyHeader(packet, 5);
455ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet->release();
456ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    packet = NULL;
45796f52cde23982f668592418a9548045237d5e327Andreas Huber
45896f52cde23982f668592418a9548045237d5e327Andreas Huber    mFirstDataOffset = mOffset + mCurrentPageSize;
459ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
460ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
461ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubervoid MyVorbisExtractor::verifyHeader(
462ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        MediaBuffer *buffer, uint8_t type) {
463ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    const uint8_t *data =
464ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
465ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
466ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    size_t size = buffer->range_length();
467ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
468ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    CHECK(size >= 7);
469ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
470ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    CHECK_EQ(data[0], type);
471ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    CHECK(!memcmp(&data[1], "vorbis", 6));
472ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
473ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ogg_buffer buf;
474ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.data = (uint8_t *)data;
475ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.size = size;
476ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.refcount = 1;
477ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    buf.ptr.owner = NULL;
478ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
479ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ogg_reference ref;
480ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.buffer = &buf;
481ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.begin = 0;
482ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.length = size;
483ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    ref.next = NULL;
484ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
485ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    oggpack_buffer bits;
486ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    oggpack_readinit(&bits, &ref);
487ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
488ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    CHECK_EQ(oggpack_read(&bits, 8), type);
489ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    for (size_t i = 0; i < 6; ++i) {
490ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        oggpack_read(&bits, 8);  // skip 'vorbis'
491ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
492ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
493ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    switch (type) {
494ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 1:
495ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
496ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits));
497ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
498ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setData(kKeyVorbisInfo, 0, data, size);
499ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setInt32(kKeySampleRate, mVi.rate);
500ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setInt32(kKeyChannelCount, mVi.channels);
501ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
502ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            LOGV("lower-bitrate = %ld", mVi.bitrate_lower);
503ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            LOGV("upper-bitrate = %ld", mVi.bitrate_upper);
504ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            LOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
505ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            LOGV("window-bitrate = %ld", mVi.bitrate_window);
506ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
507ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            off_t size;
508ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            if (mSource->getSize(&size) == OK) {
509ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                uint64_t bps = approxBitrate();
510ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
511ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber                mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
512ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            }
513ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
514ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
515ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
516ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 3:
517ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
518ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            CHECK_EQ(0, _vorbis_unpack_comment(&mVc, &bits));
5194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
5204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            parseFileMetaData();
521ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
522ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
523ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
524ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        case 5:
525ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        {
526ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            CHECK_EQ(0, _vorbis_unpack_books(&mVi, &bits));
527ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
528ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            mMeta->setData(kKeyVorbisBooks, 0, data, size);
529ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber            break;
530ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        }
531ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
532ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
533ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
534ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberuint64_t MyVorbisExtractor::approxBitrate() {
535ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (mVi.bitrate_nominal != 0) {
536ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return mVi.bitrate_nominal;
537ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
538ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
539ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
540ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
541ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
5424595be952e3b1d6776a023e3f447c057797f1505Andreas Hubervoid MyVorbisExtractor::parseFileMetaData() {
5434595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta = new MetaData;
5444595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
5454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
5464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    struct {
5474595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        const char *const mTag;
5484595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        uint32_t mKey;
5494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    } kMap[] = {
5504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "TITLE", kKeyTitle },
5514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "ARTIST", kKeyArtist },
5524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "ALBUM", kKeyAlbum },
5534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "COMPOSER", kKeyComposer },
5544595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "GENRE", kKeyGenre },
5554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "AUTHOR", kKeyAuthor },
5564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "TRACKNUMBER", kKeyCDTrackNumber },
5574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "DISCNUMBER", kKeyDiscNumber },
5584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "DATE", kKeyDate },
5594595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "LYRICIST", kKeyWriter },
5604595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
5614595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    };
5624595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
5634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    for (int i = 0; i < mVc.comments; ++i) {
5644595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        const char *comment = mVc.user_comments[i];
5654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
5664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
5674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            size_t tagLen = strlen(kMap[j].mTag);
5684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (!strncasecmp(kMap[j].mTag, comment, tagLen)
5694595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                    && comment[tagLen] == '=') {
5704595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                if (kMap[j].mKey == kKeyAlbumArt) {
5714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                    extractAlbumArt(
5724595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                            &comment[tagLen + 1],
5734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                            mVc.comment_lengths[i] - tagLen - 1);
5744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                } else {
5754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                    mFileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
5764595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                }
5774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            }
5784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
5794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
5804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
5814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
5824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber#if 0
5834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    for (int i = 0; i < mVc.comments; ++i) {
5844595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        LOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
5854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
5864595be952e3b1d6776a023e3f447c057797f1505Andreas Huber#endif
5874595be952e3b1d6776a023e3f447c057797f1505Andreas Huber}
5884595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
5894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber// The returned buffer should be free()d.
5904595be952e3b1d6776a023e3f447c057797f1505Andreas Huberstatic uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) {
5914595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    *outSize = 0;
5924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
5934595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if ((size % 4) != 0) {
5944595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        return NULL;
5954595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
5964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
5974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t n = size;
5984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t padding = 0;
5994595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (n >= 1 && s[n - 1] == '=') {
6004595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        padding = 1;
6014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        if (n >= 2 && s[n - 2] == '=') {
6034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            padding = 2;
6044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
6054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
6064595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t outLen = 3 * size / 4 - padding;
6084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    *outSize = outLen;
6104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    void *buffer = malloc(outLen);
6124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint8_t *out = (uint8_t *)buffer;
6144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t j = 0;
6154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t accum = 0;
6164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    for (size_t i = 0; i < n; ++i) {
6174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        char c = s[i];
6184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        unsigned value;
6194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        if (c >= 'A' && c <= 'Z') {
6204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = c - 'A';
6214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c >= 'a' && c <= 'z') {
6224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 26 + c - 'a';
6234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c >= '0' && c <= '9') {
6244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 52 + c - '0';
6254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c == '+') {
6264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 62;
6274595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c == '/') {
6284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 63;
6294595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else if (c != '=') {
6304595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            return NULL;
6314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        } else {
6324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (i < n - padding) {
6334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber                return NULL;
6344595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            }
6354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6364595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            value = 0;
6374595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
6384595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6394595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        accum = (accum << 6) | value;
6404595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6414595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        if (((i + 1) % 4) == 0) {
6424595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            out[j++] = (accum >> 16);
6434595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6444595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
6454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            if (j < outLen) { out[j++] = accum & 0xff; }
6464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6474595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            accum = 0;
6484595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        }
6494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
6504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    return (uint8_t *)buffer;
6524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber}
6534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6544595be952e3b1d6776a023e3f447c057797f1505Andreas Hubervoid MyVorbisExtractor::extractAlbumArt(const void *data, size_t size) {
6554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    LOGV("extractAlbumArt from '%s'", (const char *)data);
6564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    size_t flacSize;
6584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize);
6594595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6604595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flac == NULL) {
6614595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        LOGE("malformed base64 encoded data.");
6624595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        return;
6634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
6644595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    LOGV("got flac of size %d", flacSize);
6664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t picType;
6684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t typeLen;
6694595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t descLen;
6704595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    uint32_t dataLen;
6714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    char type[128];
6724595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 8) {
6744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
6754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
6764595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    picType = U32_AT(flac);
6784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (picType != 3) {
6804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        // This is not a front cover.
6814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
6824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
6834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6844595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    typeLen = U32_AT(&flac[4]);
6854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (typeLen + 1 > sizeof(type)) {
6864595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
6874595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
6884595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 8 + typeLen) {
6904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
6914595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
6924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6934595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    memcpy(type, &flac[8], typeLen);
6944595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    type[typeLen] = '\0';
6954595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    LOGV("picType = %d, type = '%s'", picType, type);
6974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
6984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (!strcmp(type, "-->")) {
6994595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        // This is not inline cover art, but an external url instead.
7004595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
7014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
7024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    descLen = U32_AT(&flac[8 + typeLen]);
7044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 32 + typeLen + descLen) {
7064595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
7074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
7084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
7104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    if (flacSize < 32 + typeLen + descLen + dataLen) {
7124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber        goto exit;
7134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    }
7144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    LOGV("got image data, %d trailing bytes",
7164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber         flacSize - 32 - typeLen - descLen - dataLen);
7174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta->setData(
7194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber            kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
7204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    mFileMeta->setCString(kKeyAlbumArtMIME, type);
7224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
7234595be952e3b1d6776a023e3f447c057797f1505Andreas Huberexit:
7244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    free(flac);
7254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    flac = NULL;
7264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber}
7274595be952e3b1d6776a023e3f447c057797f1505Andreas Huber
728ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber////////////////////////////////////////////////////////////////////////////////
729ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
730ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::OggExtractor(const sp<DataSource> &source)
731ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    : mDataSource(source),
732ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mInitCheck(NO_INIT),
733ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber      mImpl(NULL) {
734ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mImpl = new MyVorbisExtractor(mDataSource);
735ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    CHECK_EQ(mImpl->seekToOffset(0), OK);
736ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mImpl->init();
737ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
738ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mInitCheck = OK;
739ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
740ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
741ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::~OggExtractor() {
742ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    delete mImpl;
743ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mImpl = NULL;
744ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
745ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
746ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersize_t OggExtractor::countTracks() {
747ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mInitCheck != OK ? 0 : 1;
748ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
749ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
750ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MediaSource> OggExtractor::getTrack(size_t index) {
751ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (index >= 1) {
752ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return NULL;
753ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
754ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
755ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return new OggSource(this);
756ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
757ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
758ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getTrackMetaData(
759ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        size_t index, uint32_t flags) {
760ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (index >= 1) {
761ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return NULL;
762ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
763ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
764ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return mImpl->getFormat();
765ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
766ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
767ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getMetaData() {
7684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber    return mImpl->getFileMetaData();
769ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
770ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
771ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberbool SniffOgg(
772ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
773ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    char tmp[4];
774ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
775ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber        return false;
776ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    }
777ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
778ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG);
779ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    *confidence = 0.2f;
780ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
781ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    return true;
782ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}
783ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber
784ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}  // namespace android
785