OggExtractor.cpp revision 1f7fba1ffbf5922d999ab52130efb73a35e72077
1388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber/*
2388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * Copyright (C) 2010 The Android Open Source Project
3388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *
4388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * you may not use this file except in compliance with the License.
6388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * You may obtain a copy of the License at
7388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *
8388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *
10388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * Unless required by applicable law or agreed to in writing, software
11388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * See the License for the specific language governing permissions and
14388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * limitations under the License.
15388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber */
16388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
17388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber//#define LOG_NDEBUG 0
18388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#define LOG_TAG "OggExtractor"
19388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <utils/Log.h>
20388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
21388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include "include/OggExtractor.h"
22388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
23388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <cutils/properties.h>
24388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/DataSource.h>
25388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MediaBuffer.h>
26388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MediaBufferGroup.h>
27388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MediaDebug.h>
28388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MediaDefs.h>
29388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MediaErrors.h>
30388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MediaSource.h>
31388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MetaData.h>
32388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/Utils.h>
33388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <utils/String8.h>
34388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
35388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberextern "C" {
36388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    #include <Tremolo/codec_internal.h>
37388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
38388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
39388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
40388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
41388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
42388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
43388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubernamespace android {
44388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
45388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstruct OggSource : public MediaSource {
46388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    OggSource(const sp<OggExtractor> &extractor);
47388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
48388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    virtual sp<MetaData> getFormat();
49388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
50388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    virtual status_t start(MetaData *params = NULL);
51388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    virtual status_t stop();
52388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
53388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    virtual status_t read(
54388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
55388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
56388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberprotected:
57388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    virtual ~OggSource();
58388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
59388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberprivate:
60388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    sp<OggExtractor> mExtractor;
61388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    bool mStarted;
62388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
63388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    OggSource(const OggSource &);
64388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    OggSource &operator=(const OggSource &);
65388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber};
66388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
67388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstruct MyVorbisExtractor {
68388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    MyVorbisExtractor(const sp<DataSource> &source);
69388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    virtual ~MyVorbisExtractor();
70388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
71388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    sp<MetaData> getFormat() const;
72388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
73388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    // Returns an approximate bitrate in bits per second.
74388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    uint64_t approxBitrate();
75388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
76388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    status_t seekToOffset(off_t offset);
77388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    status_t readNextPacket(MediaBuffer **buffer);
78388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
79eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    status_t init();
80388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
81c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    sp<MetaData> getFileMetaData() { return mFileMeta; }
82c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
83388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberprivate:
84388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    struct Page {
85388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        uint64_t mGranulePosition;
86388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        uint32_t mSerialNo;
87388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        uint32_t mPageNo;
88388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        uint8_t mFlags;
89388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        uint8_t mNumSegments;
90388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        uint8_t mLace[255];
91388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    };
92388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
93388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    sp<DataSource> mSource;
94388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    off_t mOffset;
95388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    Page mCurrentPage;
96388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    size_t mCurrentPageSize;
97388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    size_t mNextLaceIndex;
98388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
9934c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber    off_t mFirstDataOffset;
10034c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber
101388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    vorbis_info mVi;
102388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    vorbis_comment mVc;
103388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
104388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    sp<MetaData> mMeta;
105c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    sp<MetaData> mFileMeta;
106388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
107388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    ssize_t readPage(off_t offset, Page *page);
108388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    status_t findNextPage(off_t startOffset, off_t *pageOffset);
109388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
110eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    status_t verifyHeader(
111388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            MediaBuffer *buffer, uint8_t type);
112388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
113c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    void parseFileMetaData();
114c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    void extractAlbumArt(const void *data, size_t size);
115c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
116388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    MyVorbisExtractor(const MyVorbisExtractor &);
117388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    MyVorbisExtractor &operator=(const MyVorbisExtractor &);
118388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber};
119388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
120388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber////////////////////////////////////////////////////////////////////////////////
121388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
122388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberOggSource::OggSource(const sp<OggExtractor> &extractor)
123388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    : mExtractor(extractor),
124388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber      mStarted(false) {
125388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
126388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
127388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberOggSource::~OggSource() {
128388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (mStarted) {
129388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        stop();
130388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
131388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
132388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
133388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MetaData> OggSource::getFormat() {
134388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    return mExtractor->mImpl->getFormat();
135388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
136388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
137388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t OggSource::start(MetaData *params) {
138388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (mStarted) {
139388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        return INVALID_OPERATION;
140388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
141388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
142388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    mStarted = true;
143388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
144388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    return OK;
145388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
146388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
147388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t OggSource::stop() {
148388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    mStarted = false;
149388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
150388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    return OK;
151388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
152388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
153388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t OggSource::read(
154388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
155388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    *out = NULL;
156388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
157388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    int64_t seekTimeUs;
1586624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    ReadOptions::SeekMode mode;
1596624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
160388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        off_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll;
161388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        LOGI("seeking to offset %ld", pos);
162388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
163388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        if (mExtractor->mImpl->seekToOffset(pos) != OK) {
164388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            return ERROR_END_OF_STREAM;
165388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        }
166388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
167388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
168388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    MediaBuffer *packet;
169388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    status_t err = mExtractor->mImpl->readNextPacket(&packet);
170388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
171388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (err != OK) {
172388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        return err;
173388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
174388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
175388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#if 0
176388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    int64_t timeUs;
177388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) {
178388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        LOGI("found time = %lld us", timeUs);
179388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    } else {
180388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        LOGI("NO time");
181388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
182388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#endif
183388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
184388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    *out = packet;
185388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
186388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    return OK;
187388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
188388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
189388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber////////////////////////////////////////////////////////////////////////////////
190388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
191388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberMyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source)
192388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    : mSource(source),
193388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber      mOffset(0),
194388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber      mCurrentPageSize(0),
19534c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber      mNextLaceIndex(0),
19634c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber      mFirstDataOffset(-1) {
197388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    mCurrentPage.mNumSegments = 0;
198c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
199c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    vorbis_info_init(&mVi);
200c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    vorbis_comment_init(&mVc);
201388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
202388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
203388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberMyVorbisExtractor::~MyVorbisExtractor() {
204c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    vorbis_comment_clear(&mVc);
205c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    vorbis_info_clear(&mVi);
206388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
207388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
208388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MetaData> MyVorbisExtractor::getFormat() const {
209388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    return mMeta;
210388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
211388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
212388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t MyVorbisExtractor::findNextPage(
213388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        off_t startOffset, off_t *pageOffset) {
214388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    *pageOffset = startOffset;
215388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
216388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    for (;;) {
217388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        char signature[4];
218388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
219388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
220388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        if (n < 4) {
221388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            *pageOffset = 0;
222388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
223388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
224388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        }
225388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
226388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        if (!memcmp(signature, "OggS", 4)) {
227388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            if (*pageOffset > startOffset) {
228388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                LOGV("skipped %ld bytes of junk to reach next frame",
229388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                     *pageOffset - startOffset);
230388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            }
231388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
232388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            return OK;
233388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        }
234388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
235388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        ++*pageOffset;
236388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
237388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
238388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
239388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t MyVorbisExtractor::seekToOffset(off_t offset) {
24034c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber    if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) {
24134c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber        // Once we know where the actual audio data starts (past the headers)
24234c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber        // don't ever seek to anywhere before that.
24334c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber        offset = mFirstDataOffset;
24434c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber    }
24534c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber
246388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    off_t pageOffset;
247388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    status_t err = findNextPage(offset, &pageOffset);
248388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
249388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (err != OK) {
250388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        return err;
251388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
252388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
253388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    mOffset = pageOffset;
254388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
255388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    mCurrentPageSize = 0;
256388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    mCurrentPage.mNumSegments = 0;
257388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    mNextLaceIndex = 0;
258388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
259388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    // XXX what if new page continues packet from last???
260388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
261388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    return OK;
262388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
263388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
264388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberssize_t MyVorbisExtractor::readPage(off_t offset, Page *page) {
265388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    uint8_t header[27];
266388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (mSource->readAt(offset, header, sizeof(header))
267388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            < (ssize_t)sizeof(header)) {
268388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        LOGE("failed to read %d bytes at offset 0x%08lx", sizeof(header), offset);
269388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
270388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        return ERROR_IO;
271388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
272388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
273388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (memcmp(header, "OggS", 4)) {
274388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        return ERROR_MALFORMED;
275388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
276388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
277388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (header[4] != 0) {
278388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        // Wrong version.
279388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
280388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        return ERROR_UNSUPPORTED;
281388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
282388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
283388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    page->mFlags = header[5];
284388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
285388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (page->mFlags & ~7) {
286388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        // Only bits 0-2 are defined in version 0.
287388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        return ERROR_MALFORMED;
288388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
289388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
290388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    page->mGranulePosition = U64LE_AT(&header[6]);
291388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
292388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#if 0
293388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    printf("granulePosition = %llu (0x%llx)\n",
294388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber           page->mGranulePosition, page->mGranulePosition);
295388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#endif
296388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
297388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    page->mSerialNo = U32LE_AT(&header[14]);
298388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    page->mPageNo = U32LE_AT(&header[18]);
299388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
300388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    page->mNumSegments = header[26];
301388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (mSource->readAt(
302388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                offset + sizeof(header), page->mLace, page->mNumSegments)
303388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            < (ssize_t)page->mNumSegments) {
304388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        return ERROR_IO;
305388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
306388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
307388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    size_t totalSize = 0;;
308388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    for (size_t i = 0; i < page->mNumSegments; ++i) {
309388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        totalSize += page->mLace[i];
310388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
311388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
312eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber#if 0
313388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    String8 tmp;
314388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    for (size_t i = 0; i < page->mNumSegments; ++i) {
315388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        char x[32];
316388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]);
317388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
318388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        tmp.append(x);
319388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
320388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
321eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string());
322eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber#endif
323388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
324388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    return sizeof(header) + page->mNumSegments + totalSize;
325388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
326388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
327388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) {
328388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    *out = NULL;
329388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
330388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    MediaBuffer *buffer = NULL;
331388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    int64_t timeUs = -1;
332388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
333388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    for (;;) {
334388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        size_t i;
335388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        size_t packetSize = 0;
336388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        bool gotFullPacket = false;
337388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) {
338388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            uint8_t lace = mCurrentPage.mLace[i];
339388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
340388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            packetSize += lace;
341388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
342388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            if (lace < 255) {
343388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                gotFullPacket = true;
344388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                ++i;
345388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                break;
346388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            }
347388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        }
348388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
349388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        if (mNextLaceIndex < mCurrentPage.mNumSegments) {
350388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            off_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments;
351388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            for (size_t j = 0; j < mNextLaceIndex; ++j) {
352388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                dataOffset += mCurrentPage.mLace[j];
353388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            }
354388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
355388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            size_t fullSize = packetSize;
356388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            if (buffer != NULL) {
357388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                fullSize += buffer->range_length();
358388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            }
359388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            MediaBuffer *tmp = new MediaBuffer(fullSize);
360388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            if (buffer != NULL) {
361388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                memcpy(tmp->data(), buffer->data(), buffer->range_length());
362388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                tmp->set_range(0, buffer->range_length());
363388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                buffer->release();
3641f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber            } else {
365388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                // XXX Not only is this not technically the correct time for
366388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                // this packet, we also stamp every packet in this page
367388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                // with the same time. This needs fixing later.
3681f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber
3691f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber                if (mVi.rate) {
3701f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber                    // Rate may not have been initialized yet if we're currently
3711f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber                    // reading the configuration packets...
3721f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber                    // Fortunately, the timestamp doesn't matter for those.
3731f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber                    timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate;
3741f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber                }
375388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                tmp->set_range(0, 0);
376388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            }
377388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            buffer = tmp;
378388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
379388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            ssize_t n = mSource->readAt(
380388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                    dataOffset,
381388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                    (uint8_t *)buffer->data() + buffer->range_length(),
382388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                    packetSize);
383388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
384388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            if (n < (ssize_t)packetSize) {
385388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                LOGE("failed to read %d bytes at 0x%08lx", packetSize, dataOffset);
386388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                return ERROR_IO;
387388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            }
388388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
389388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            buffer->set_range(0, fullSize);
390388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
391388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            mNextLaceIndex = i;
392388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
393388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            if (gotFullPacket) {
394388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                // We've just read the entire packet.
395388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
396388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                if (timeUs >= 0) {
397388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
398388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                }
399388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
400388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                *out = buffer;
401388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
402388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                return OK;
403388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            }
404388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
405388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            // fall through, the buffer now contains the start of the packet.
406388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        }
407388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
408388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments);
409388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
410388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        mOffset += mCurrentPageSize;
411388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        ssize_t n = readPage(mOffset, &mCurrentPage);
412388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
413388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        if (n <= 0) {
414388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            if (buffer) {
415388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                buffer->release();
416388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                buffer = NULL;
417388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            }
418388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
419388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            LOGE("readPage returned %ld", n);
420388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
421388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            return n < 0 ? n : (status_t)ERROR_END_OF_STREAM;
422388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        }
423388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
424388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        mCurrentPageSize = n;
425388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        mNextLaceIndex = 0;
426388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
427388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        if (buffer != NULL) {
428388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            if ((mCurrentPage.mFlags & 1) == 0) {
429388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                // This page does not continue the packet, i.e. the packet
430388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                // is already complete.
431388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
432388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                if (timeUs >= 0) {
433388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
434388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                }
435388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
436388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                *out = buffer;
437388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
438388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                return OK;
439388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            }
440388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        }
441388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
442388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
443388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
444eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huberstatus_t MyVorbisExtractor::init() {
445388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    mMeta = new MetaData;
446388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
447388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
448388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    MediaBuffer *packet;
449eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    status_t err;
450eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    if ((err = readNextPacket(&packet)) != OK) {
451eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber        return err;
452eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    }
453388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    LOGV("read packet of size %d\n", packet->range_length());
454eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    err = verifyHeader(packet, 1);
455388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    packet->release();
456388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    packet = NULL;
457eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    if (err != OK) {
458eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber        return err;
459eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    }
460388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
461eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    if ((err = readNextPacket(&packet)) != OK) {
462eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber        return err;
463eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    }
464388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    LOGV("read packet of size %d\n", packet->range_length());
465eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    err = verifyHeader(packet, 3);
466388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    packet->release();
467388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    packet = NULL;
468eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    if (err != OK) {
469eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber        return err;
470eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    }
471388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
472eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    if ((err = readNextPacket(&packet)) != OK) {
473eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber        return err;
474eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    }
475388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    LOGV("read packet of size %d\n", packet->range_length());
476eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    err = verifyHeader(packet, 5);
477388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    packet->release();
478388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    packet = NULL;
479eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    if (err != OK) {
480eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber        return err;
481eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    }
48234c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber
48334c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber    mFirstDataOffset = mOffset + mCurrentPageSize;
484eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber
485eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    return OK;
486388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
487388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
488eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huberstatus_t MyVorbisExtractor::verifyHeader(
489388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        MediaBuffer *buffer, uint8_t type) {
490388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    const uint8_t *data =
491388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
492388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
493388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    size_t size = buffer->range_length();
494388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
495eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) {
496eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber        return ERROR_MALFORMED;
497eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    }
498388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
499388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    ogg_buffer buf;
500388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    buf.data = (uint8_t *)data;
501388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    buf.size = size;
502388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    buf.refcount = 1;
503388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    buf.ptr.owner = NULL;
504388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
505388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    ogg_reference ref;
506388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    ref.buffer = &buf;
507388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    ref.begin = 0;
508388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    ref.length = size;
509388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    ref.next = NULL;
510388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
511388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    oggpack_buffer bits;
512388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    oggpack_readinit(&bits, &ref);
513388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
514388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    CHECK_EQ(oggpack_read(&bits, 8), type);
515388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    for (size_t i = 0; i < 6; ++i) {
516388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        oggpack_read(&bits, 8);  // skip 'vorbis'
517388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
518388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
519388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    switch (type) {
520388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        case 1:
521388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        {
522388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits));
523388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
524388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            mMeta->setData(kKeyVorbisInfo, 0, data, size);
525388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            mMeta->setInt32(kKeySampleRate, mVi.rate);
526388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            mMeta->setInt32(kKeyChannelCount, mVi.channels);
527388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
528388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            LOGV("lower-bitrate = %ld", mVi.bitrate_lower);
529388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            LOGV("upper-bitrate = %ld", mVi.bitrate_upper);
530388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            LOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
531388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            LOGV("window-bitrate = %ld", mVi.bitrate_window);
532388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
533388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            off_t size;
534388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            if (mSource->getSize(&size) == OK) {
535388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                uint64_t bps = approxBitrate();
536388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
537388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber                mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
538388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            }
539388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            break;
540388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        }
541388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
542388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        case 3:
543388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        {
544eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber            if (0 != _vorbis_unpack_comment(&mVc, &bits)) {
545eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber                return ERROR_MALFORMED;
546eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber            }
547c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
548c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            parseFileMetaData();
549388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            break;
550388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        }
551388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
552388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        case 5:
553388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        {
554eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber            if (0 != _vorbis_unpack_books(&mVi, &bits)) {
555eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber                return ERROR_MALFORMED;
556eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber            }
557388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
558388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            mMeta->setData(kKeyVorbisBooks, 0, data, size);
559388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber            break;
560388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        }
561388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
562eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber
563eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    return OK;
564388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
565388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
566388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberuint64_t MyVorbisExtractor::approxBitrate() {
567388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (mVi.bitrate_nominal != 0) {
568388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        return mVi.bitrate_nominal;
569388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
570388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
571388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
572388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
573388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
574c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Hubervoid MyVorbisExtractor::parseFileMetaData() {
575c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    mFileMeta = new MetaData;
576c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
577c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
578c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    struct {
579c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        const char *const mTag;
580c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        uint32_t mKey;
581c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    } kMap[] = {
582c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        { "TITLE", kKeyTitle },
583c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        { "ARTIST", kKeyArtist },
584c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        { "ALBUM", kKeyAlbum },
585c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        { "COMPOSER", kKeyComposer },
586c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        { "GENRE", kKeyGenre },
587c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        { "AUTHOR", kKeyAuthor },
588c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        { "TRACKNUMBER", kKeyCDTrackNumber },
589c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        { "DISCNUMBER", kKeyDiscNumber },
590c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        { "DATE", kKeyDate },
591c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        { "LYRICIST", kKeyWriter },
592c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
593c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    };
594c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
595c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    for (int i = 0; i < mVc.comments; ++i) {
596c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        const char *comment = mVc.user_comments[i];
597c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
598c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
599c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            size_t tagLen = strlen(kMap[j].mTag);
600c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            if (!strncasecmp(kMap[j].mTag, comment, tagLen)
601c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber                    && comment[tagLen] == '=') {
602c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber                if (kMap[j].mKey == kKeyAlbumArt) {
603c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber                    extractAlbumArt(
604c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber                            &comment[tagLen + 1],
605c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber                            mVc.comment_lengths[i] - tagLen - 1);
606c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber                } else {
607c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber                    mFileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
608c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber                }
609c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            }
610c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        }
611c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
612c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    }
613c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
614c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber#if 0
615c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    for (int i = 0; i < mVc.comments; ++i) {
616c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        LOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
617c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    }
618c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber#endif
619c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber}
620c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
621c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber// The returned buffer should be free()d.
622c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huberstatic uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) {
623c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    *outSize = 0;
624c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
625c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    if ((size % 4) != 0) {
626c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        return NULL;
627c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    }
628c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
629c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    size_t n = size;
630c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    size_t padding = 0;
631c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    if (n >= 1 && s[n - 1] == '=') {
632c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        padding = 1;
633c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
634c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        if (n >= 2 && s[n - 2] == '=') {
635c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            padding = 2;
636c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        }
637c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    }
638c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
639c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    size_t outLen = 3 * size / 4 - padding;
640c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
641c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    *outSize = outLen;
642c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
643c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    void *buffer = malloc(outLen);
644c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
645c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    uint8_t *out = (uint8_t *)buffer;
646c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    size_t j = 0;
647c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    uint32_t accum = 0;
648c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    for (size_t i = 0; i < n; ++i) {
649c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        char c = s[i];
650c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        unsigned value;
651c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        if (c >= 'A' && c <= 'Z') {
652c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            value = c - 'A';
653c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        } else if (c >= 'a' && c <= 'z') {
654c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            value = 26 + c - 'a';
655c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        } else if (c >= '0' && c <= '9') {
656c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            value = 52 + c - '0';
657c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        } else if (c == '+') {
658c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            value = 62;
659c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        } else if (c == '/') {
660c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            value = 63;
661c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        } else if (c != '=') {
662c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            return NULL;
663c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        } else {
664c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            if (i < n - padding) {
665c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber                return NULL;
666c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            }
667c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
668c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            value = 0;
669c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        }
670c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
671c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        accum = (accum << 6) | value;
672c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
673c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        if (((i + 1) % 4) == 0) {
674c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            out[j++] = (accum >> 16);
675c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
676c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
677c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            if (j < outLen) { out[j++] = accum & 0xff; }
678c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
679c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            accum = 0;
680c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        }
681c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    }
682c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
683c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    return (uint8_t *)buffer;
684c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber}
685c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
686c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Hubervoid MyVorbisExtractor::extractAlbumArt(const void *data, size_t size) {
687c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    LOGV("extractAlbumArt from '%s'", (const char *)data);
688c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
689c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    size_t flacSize;
690c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize);
691c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
692c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    if (flac == NULL) {
693c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        LOGE("malformed base64 encoded data.");
694c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        return;
695c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    }
696c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
697c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    LOGV("got flac of size %d", flacSize);
698c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
699c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    uint32_t picType;
700c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    uint32_t typeLen;
701c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    uint32_t descLen;
702c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    uint32_t dataLen;
703c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    char type[128];
704c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
705c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    if (flacSize < 8) {
706c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        goto exit;
707c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    }
708c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
709c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    picType = U32_AT(flac);
710c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
711c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    if (picType != 3) {
712c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        // This is not a front cover.
713c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        goto exit;
714c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    }
715c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
716c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    typeLen = U32_AT(&flac[4]);
717c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    if (typeLen + 1 > sizeof(type)) {
718c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        goto exit;
719c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    }
720c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
721c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    if (flacSize < 8 + typeLen) {
722c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        goto exit;
723c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    }
724c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
725c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    memcpy(type, &flac[8], typeLen);
726c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    type[typeLen] = '\0';
727c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
728c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    LOGV("picType = %d, type = '%s'", picType, type);
729c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
730c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    if (!strcmp(type, "-->")) {
731c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        // This is not inline cover art, but an external url instead.
732c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        goto exit;
733c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    }
734c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
735c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    descLen = U32_AT(&flac[8 + typeLen]);
736c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
737c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    if (flacSize < 32 + typeLen + descLen) {
738c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        goto exit;
739c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    }
740c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
741c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
742c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
743c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    if (flacSize < 32 + typeLen + descLen + dataLen) {
744c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber        goto exit;
745c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    }
746c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
747c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    LOGV("got image data, %d trailing bytes",
748c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber         flacSize - 32 - typeLen - descLen - dataLen);
749c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
750c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    mFileMeta->setData(
751c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber            kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
752c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
753c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    mFileMeta->setCString(kKeyAlbumArtMIME, type);
754c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
755c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huberexit:
756c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    free(flac);
757c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    flac = NULL;
758c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber}
759c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber
760388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber////////////////////////////////////////////////////////////////////////////////
761388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
762388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberOggExtractor::OggExtractor(const sp<DataSource> &source)
763388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    : mDataSource(source),
764388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber      mInitCheck(NO_INIT),
765388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber      mImpl(NULL) {
766388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    mImpl = new MyVorbisExtractor(mDataSource);
767eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    mInitCheck = mImpl->seekToOffset(0);
768388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
769eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    if (mInitCheck == OK) {
770eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber        mInitCheck = mImpl->init();
771eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber    }
772388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
773388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
774388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberOggExtractor::~OggExtractor() {
775388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    delete mImpl;
776388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    mImpl = NULL;
777388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
778388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
779388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersize_t OggExtractor::countTracks() {
780388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    return mInitCheck != OK ? 0 : 1;
781388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
782388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
783388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MediaSource> OggExtractor::getTrack(size_t index) {
784388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (index >= 1) {
785388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        return NULL;
786388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
787388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
788388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    return new OggSource(this);
789388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
790388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
791388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MetaData> OggExtractor::getTrackMetaData(
792388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        size_t index, uint32_t flags) {
793388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (index >= 1) {
794388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        return NULL;
795388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
796388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
797388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    return mImpl->getFormat();
798388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
799388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
800388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MetaData> OggExtractor::getMetaData() {
801c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber    return mImpl->getFileMetaData();
802388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
803388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
804388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberbool SniffOgg(
805388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
806388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    char tmp[4];
807388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
808388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber        return false;
809388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    }
810388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
811388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG);
812388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    *confidence = 0.2f;
813388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
814388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber    return true;
815388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}
816388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber
817388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}  // namespace android
818