ID3.cpp revision f26400c9d01a0e2f71690d5ebc644270f098d590
1fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber/*
2fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *
4fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * you may not use this file except in compliance with the License.
6fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * You may obtain a copy of the License at
7fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *
8fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *
10fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * Unless required by applicable law or agreed to in writing, software
11fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * See the License for the specific language governing permissions and
14fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * limitations under the License.
15fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber */
16fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
17fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber//#define LOG_NDEBUG 0
18fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#define LOG_TAG "ID3"
19fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include <utils/Log.h>
20fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
21fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include "../include/ID3.h"
22fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
23f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
24fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include <media/stagefright/DataSource.h>
25fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include <media/stagefright/Utils.h>
26fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include <utils/String8.h>
27569e7f1b1444194d1aca5a0b23de154565ba12daMarco Nelissen#include <byteswap.h>
28fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
29fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubernamespace android {
30fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
3165997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huberstatic const size_t kMaxMetadataSize = 3 * 1024 * 1024;
3265997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber
3314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstruct MemorySource : public DataSource {
3414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    MemorySource(const uint8_t *data, size_t size)
3514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        : mData(data),
3614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber          mSize(size) {
3714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
3814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
3914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    virtual status_t initCheck() const {
4014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return OK;
4114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
4214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
4314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
4414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        off64_t available = (offset >= mSize) ? 0ll : mSize - offset;
4514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
4614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        size_t copy = (available > size) ? size : available;
4714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        memcpy(data, mData + offset, copy);
4814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
4914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return copy;
5014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
5114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
5214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberprivate:
5314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    const uint8_t *mData;
5414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t mSize;
5514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
5614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(MemorySource);
5714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber};
5814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
59ffd6ffc5429c45577fd8e9f8fa90e79bb91b8a84Dylan PowersID3::ID3(const sp<DataSource> &source, bool ignoreV1)
60fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mIsValid(false),
61fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mData(NULL),
62fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mSize(0),
63fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFirstFrameOffset(0),
6414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mVersion(ID3_UNKNOWN),
6514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mRawSize(0) {
6614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mIsValid = parseV2(source);
6714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
6814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!mIsValid && !ignoreV1) {
6914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mIsValid = parseV1(source);
7014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
7114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
7214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas HuberID3::ID3(const uint8_t *data, size_t size, bool ignoreV1)
7414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    : mIsValid(false),
7514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mData(NULL),
7614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mSize(0),
7714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mFirstFrameOffset(0),
7814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mVersion(ID3_UNKNOWN),
7914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mRawSize(0) {
8014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<MemorySource> source = new MemorySource(data, size);
8114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
8283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mIsValid = parseV2(source);
8383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
84ffd6ffc5429c45577fd8e9f8fa90e79bb91b8a84Dylan Powers    if (!mIsValid && !ignoreV1) {
8583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mIsValid = parseV1(source);
8683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
87fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
88fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
89fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::~ID3() {
90fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mData) {
91fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        free(mData);
92fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mData = NULL;
93fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
94fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
95fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
96fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::isValid() const {
97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mIsValid;
98fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
99fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
100fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Version ID3::version() const {
101fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mVersion;
102fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
103fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
104bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber// static
105bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huberbool ID3::ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x) {
106bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    *x = 0;
107bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    for (int32_t i = 0; i < 4; ++i) {
108bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (encoded[i] & 0x80) {
109bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
110bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
111bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
112bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        *x = ((*x) << 7) | encoded[i];
113bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    }
114bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
115bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    return true;
116bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber}
117bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
11883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV2(const sp<DataSource> &source) {
119bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huberstruct id3_header {
120bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    char id[3];
121bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t version_major;
122bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t version_minor;
123bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t flags;
124bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t enc_size[4];
125fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    };
126fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
127fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id3_header header;
128fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (source->readAt(
129fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                0, &header, sizeof(header)) != (ssize_t)sizeof(header)) {
130fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
131fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
132fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
133fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (memcmp(header.id, "ID3", 3)) {
134fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
135fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
136fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
137fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 0xff || header.version_minor == 0xff) {
138fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
139fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
140fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
141fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
142fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x3f) {
143fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // We only support the 2 high bits, if any of the lower bits are
144fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // set, we cannot guarantee to understand the tag format.
145fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
146fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
147fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
148fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x40) {
149fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // No compression scheme has been decided yet, ignore the
150fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // tag if compression is indicated.
151fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
152fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
153fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
154fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else if (header.version_major == 3) {
155fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x1f) {
156fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // We only support the 3 high bits, if any of the lower bits are
157fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // set, we cannot guarantee to understand the tag format.
158fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
159fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
160bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 4) {
161bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (header.flags & 0x0f) {
162bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            // The lower 4 bits are undefined in this spec.
163bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
164bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
165fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
166fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
167fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
168fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
169bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    size_t size;
170bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    if (!ParseSyncsafeInteger(header.enc_size, &size)) {
171bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        return false;
172fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
173fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
17465997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber    if (size > kMaxMetadataSize) {
17529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("skipping huge ID3 metadata of size %d", size);
17665997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber        return false;
17765997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber    }
17865997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber
179fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mData = (uint8_t *)malloc(size);
180fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
181fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mData == NULL) {
182fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
183fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
184fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
185fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mSize = size;
18614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mRawSize = mSize + sizeof(header);
187fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
188fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (source->readAt(sizeof(header), mData, mSize) != (ssize_t)mSize) {
189ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        free(mData);
190ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        mData = NULL;
191ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
192fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
193fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
194fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
195ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    if (header.version_major == 4) {
196428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        void *copy = malloc(size);
197428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        memcpy(copy, mData, size);
198428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
199428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
200428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (!success) {
201428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            memcpy(mData, copy, size);
202428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            mSize = size;
203428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
204428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            success = removeUnsynchronizationV2_4(true /* iTunesHack */);
205428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
206428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            if (success) {
2073856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
208428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            }
209428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        }
210428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
211428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        free(copy);
212428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        copy = NULL;
213428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
214428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (!success) {
215ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            free(mData);
216ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData = NULL;
217ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
218ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
219ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
220ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    } else if (header.flags & 0x80) {
2213856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("removing unsynchronization");
222ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
223fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        removeUnsynchronization();
224fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
225fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
226fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mFirstFrameOffset = 0;
227fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 3 && (header.flags & 0x40)) {
228fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // Version 2.3 has an optional extended header.
229fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
230fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mSize < 4) {
23183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
23283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
23383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
234fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
235fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
236fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
237fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t extendedHeaderSize = U32_AT(&mData[0]) + 4;
238fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
239fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize > mSize) {
24083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
24183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
24283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
243fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
244fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
245fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
246fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFirstFrameOffset = extendedHeaderSize;
247fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
248fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint16_t extendedFlags = 0;
249fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize >= 6) {
250fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            extendedFlags = U16_AT(&mData[4]);
251fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
252fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedHeaderSize >= 10) {
253fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                size_t paddingSize = U32_AT(&mData[6]);
254fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
255fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                if (mFirstFrameOffset + paddingSize > mSize) {
25683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    free(mData);
25783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mData = NULL;
25883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
259fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                    return false;
260fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                }
261fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
262fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mSize -= paddingSize;
263fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
264fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
265fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedFlags & 0x8000) {
2663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("have crc");
267fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
268fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
269bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 4 && (header.flags & 0x40)) {
270bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // Version 2.4 has an optional extended header, that's different
271bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // from Version 2.3's...
272bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
273bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (mSize < 4) {
274bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
275bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
276bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
277bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
278bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
279bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
280bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        size_t ext_size;
281bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (!ParseSyncsafeInteger(mData, &ext_size)) {
282bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
283bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
284bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
285bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
286bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
287bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
288bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (ext_size < 6 || ext_size > mSize) {
289bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
290bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
291bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
292bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
293bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
294bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
295bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        mFirstFrameOffset = ext_size;
296fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
297fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
298fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
299fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_2;
300bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 3) {
301fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_3;
302bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else {
303bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        CHECK_EQ(header.version_major, 4);
304bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        mVersion = ID3_V2_4;
305fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
306fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
307fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return true;
308fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
309fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
310fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::removeUnsynchronization() {
311fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i + 1 < mSize; ++i) {
312fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mData[i] == 0xff && mData[i + 1] == 0x00) {
313fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memmove(&mData[i + 1], &mData[i + 2], mSize - i - 2);
314fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            --mSize;
315fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
316fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
317fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
318fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
319ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huberstatic void WriteSyncsafeInteger(uint8_t *dst, size_t x) {
320ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    for (size_t i = 0; i < 4; ++i) {
321ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        dst[3 - i] = (x & 0x7f);
322ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        x >>= 7;
323ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    }
324ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber}
325ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
326428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huberbool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
327ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    size_t oldSize = mSize;
328ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
329ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    size_t offset = 0;
330ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    while (offset + 10 <= mSize) {
331ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
332ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            break;
333ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
334ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
335ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        size_t dataSize;
336428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (iTunesHack) {
337428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            dataSize = U32_AT(&mData[offset + 4]);
338428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        } else if (!ParseSyncsafeInteger(&mData[offset + 4], &dataSize)) {
339ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
340ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
341ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
342ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (offset + dataSize + 10 > mSize) {
343ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
344ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
345ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
346ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        uint16_t flags = U16_AT(&mData[offset + 8]);
347ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        uint16_t prevFlags = flags;
348ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
349ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (flags & 1) {
350ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            // Strip data length indicator
351ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
352ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            memmove(&mData[offset + 10], &mData[offset + 14], mSize - offset - 14);
353ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mSize -= 4;
354ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            dataSize -= 4;
355ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
356ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            flags &= ~1;
357ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
358ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
359ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (flags & 2) {
36072a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            // This file has "unsynchronization", so we have to replace occurrences
36172a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            // of 0xff 0x00 with just 0xff in order to get the real data.
362ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
36372a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            size_t readOffset = offset + 11;
36472a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            size_t writeOffset = offset + 11;
365ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            for (size_t i = 0; i + 1 < dataSize; ++i) {
36672a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                if (mData[readOffset - 1] == 0xff
36772a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                        && mData[readOffset] == 0x00) {
36872a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                    ++readOffset;
369ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                    --mSize;
370ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                    --dataSize;
371ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                }
37272a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                mData[writeOffset++] = mData[readOffset++];
373ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            }
37472a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            // move the remaining data following this frame
37572a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            memmove(&mData[writeOffset], &mData[readOffset], oldSize - readOffset);
376ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
377ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            flags &= ~2;
378ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
379ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
380428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (flags != prevFlags || iTunesHack) {
381ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            WriteSyncsafeInteger(&mData[offset + 4], dataSize);
382ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData[offset + 8] = flags >> 8;
383ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData[offset + 9] = flags & 0xff;
384ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
385ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
386ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        offset += 10 + dataSize;
387ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    }
388ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
389ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    memset(&mData[mSize], 0, oldSize - mSize);
390ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
391ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    return true;
392ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber}
393ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
394fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::Iterator(const ID3 &parent, const char *id)
395fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mParent(parent),
396fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mID(NULL),
397fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mOffset(mParent.mFirstFrameOffset),
398fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameData(NULL),
399fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameSize(0) {
400fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (id) {
401fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = strdup(id);
402fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
403fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
404fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
405fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
406fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
407fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::~Iterator() {
408fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mID) {
409fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        free(mID);
410fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = NULL;
411fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
412fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
413fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
414fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::Iterator::done() const {
415fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData == NULL;
416fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
417fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
418fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::next() {
419fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
420fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
421fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
422fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
423fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mOffset += mFrameSize;
424fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
425fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
426fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
427fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
428fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::getID(String8 *id) const {
429fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
430fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
431fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
432fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
433fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
434fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
435fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
436fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 3);
437bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
438fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 4);
43983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
44083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
44183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
44283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        switch (mOffset) {
44383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 3:
44483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TT2");
44583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
44683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 33:
44783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TP1");
44883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
44983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 63:
45083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TAL");
45183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
45283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 93:
45383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TYE");
45483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
45583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 97:
45683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("COM");
45783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
45883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 126:
45983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TRK");
46083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
46183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 127:
46283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TCO");
46383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
46483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            default:
46583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                CHECK(!"should not be here.");
46683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
46783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
468fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
469fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
470fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
471fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic void convertISO8859ToString8(
472fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data, size_t size,
473fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        String8 *s) {
474fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t utf8len = 0;
475fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i < size; ++i) {
4764c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        if (data[i] == '\0') {
477632a7dfdab89ffa79846ad37718d0582fd36affeKenny Root            size = i;
4784c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber            break;
4794c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        } else if (data[i] < 0x80) {
480fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            ++utf8len;
481fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
482fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            utf8len += 2;
483fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
484fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
485fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
486fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (utf8len == size) {
487fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // Only ASCII characters present.
488fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
489fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        s->setTo((const char *)data, size);
490fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
491fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
492fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
493fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    char *tmp = new char[utf8len];
494fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    char *ptr = tmp;
495fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i < size; ++i) {
4964c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        if (data[i] == '\0') {
4974c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber            break;
4984c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        } else if (data[i] < 0x80) {
499fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i];
500fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else if (data[i] < 0xc0) {
501fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = 0xc2;
502fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i];
503fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
504fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = 0xc3;
505fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i] - 64;
506fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
507fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
508fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
509fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    s->setTo(tmp, utf8len);
510fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
511fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    delete[] tmp;
512fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    tmp = NULL;
513fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
514fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
515b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// the 2nd argument is used to get the data following the \0 in a comment field
516b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getString(String8 *id, String8 *comment) const {
517b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    getstring(id, false);
518b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (comment != NULL) {
519b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        getstring(comment, true);
520b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    }
521b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen}
522b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen
523b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// comment fields (COM/COMM) contain an initial short descriptor, followed by \0,
524b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// followed by more data. The data following the \0 can be retrieved by setting
525b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// "otherdata" to true.
526b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getstring(String8 *id, bool otherdata) const {
527fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
528fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
529b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    const uint8_t *frameData = mFrameData;
530b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (frameData == NULL) {
531fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
532fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
533fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
534b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    uint8_t encoding = *frameData;
535b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen
53683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1) {
53783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        if (mOffset == 126 || mOffset == 127) {
53883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            // Special treatment for the track number and genre.
53983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            char tmp[16];
540b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen            sprintf(tmp, "%d", (int)*frameData);
54183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
54283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            id->setTo(tmp);
54383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            return;
54483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
54583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
546b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        convertISO8859ToString8(frameData, mFrameSize, id);
54783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return;
54883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
54983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
550fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = mFrameSize - getHeaderLength() - 1;
551b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (otherdata) {
552b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        // skip past the encoding, language, and the 0 separator
553b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        frameData += 4;
554b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        int32_t i = n - 4;
555b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        while(--i >= 0 && *++frameData != 0) ;
556b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        int skipped = (frameData - mFrameData);
55714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (skipped >= (int)n) {
558b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen            return;
559b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        }
560b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        n -= skipped;
561b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    }
562fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
563b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (encoding == 0x00) {
564fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // ISO 8859-1
565b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        convertISO8859ToString8(frameData + 1, n, id);
566b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    } else if (encoding == 0x03) {
567bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // UTF-8
568b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        id->setTo((const char *)(frameData + 1), n);
569b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    } else if (encoding == 0x02) {
570bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // UTF-16 BE, no byte order mark.
571bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // API wants number of characters, not number of bytes...
572bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        int len = n / 2;
573b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        const char16_t *framedata = (const char16_t *) (frameData + 1);
574bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        char16_t *framedatacopy = NULL;
575bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#if BYTE_ORDER == LITTLE_ENDIAN
576bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        framedatacopy = new char16_t[len];
577bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        for (int i = 0; i < len; i++) {
578bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            framedatacopy[i] = bswap_16(framedata[i]);
579bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
580bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        framedata = framedatacopy;
581bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#endif
582bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        id->setTo(framedata, len);
583bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (framedatacopy != NULL) {
584bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            delete[] framedatacopy;
585bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
586fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
587fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // UCS-2
58808e7eb983fcb9860a574e964ff905f75aab88d2fAndreas Huber        // API wants number of characters, not number of bytes...
5895a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        int len = n / 2;
590b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        const char16_t *framedata = (const char16_t *) (frameData + 1);
5915a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        char16_t *framedatacopy = NULL;
5925a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfffe) {
5935a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            // endianness marker doesn't match host endianness, convert
5945a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedatacopy = new char16_t[len];
5955a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            for (int i = 0; i < len; i++) {
596569e7f1b1444194d1aca5a0b23de154565ba12daMarco Nelissen                framedatacopy[i] = bswap_16(framedata[i]);
5975a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            }
5985a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata = framedatacopy;
5995a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
6005a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        // If the string starts with an endianness marker, skip it
6015a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfeff) {
6025a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata++;
6035a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            len--;
6045a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
6055a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        id->setTo(framedata, len);
6065a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (framedatacopy != NULL) {
6075a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            delete[] framedatacopy;
6085a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
609fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
610fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
611fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
612fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst uint8_t *ID3::Iterator::getData(size_t *length) const {
613fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
614fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
615fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
616fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
617fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
618fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
619fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = mFrameSize - getHeaderLength();
620fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
621fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData;
622fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
623fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
624fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubersize_t ID3::Iterator::getHeaderLength() const {
625fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
626fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 6;
627bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
628fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 10;
62983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
63083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
63183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return 0;
632fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
633fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
634fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
635fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::findFrame() {
636fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (;;) {
637fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameData = NULL;
638fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameSize = 0;
639fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
640fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mParent.mVersion == ID3_V2_2) {
641fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 6 > mParent.mSize) {
642fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
643fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
644fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
645fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0", 3)) {
646fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
647fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
648fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
649fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize =
650fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                (mParent.mData[mOffset + 3] << 16)
651fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | (mParent.mData[mOffset + 4] << 8)
652fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | mParent.mData[mOffset + 5];
653fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
654fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize += 6;
655fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
656fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
6573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
658fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                     mOffset, mFrameSize, mParent.mSize - mOffset - 6);
659fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
660fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
661fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
662fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 6];
663fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
664fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
665fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
666fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
667fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
668fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[4];
669fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 3);
670fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[3] = '\0';
671fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
672fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
673fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
674fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
675bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        } else if (mParent.mVersion == ID3_V2_3
676bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || mParent.mVersion == ID3_V2_4) {
677fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 10 > mParent.mSize) {
678fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
679fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
680fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
681fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0\0", 4)) {
682fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
683fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
684fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
685bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            size_t baseSize;
686bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            if (mParent.mVersion == ID3_V2_4) {
687bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                if (!ParseSyncsafeInteger(
688bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                            &mParent.mData[mOffset + 4], &baseSize)) {
689bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                    return;
690bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                }
691bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            } else {
692bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                baseSize = U32_AT(&mParent.mData[mOffset + 4]);
693bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
694bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
695bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mFrameSize = 10 + baseSize;
696fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
697fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
6983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
699fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                     mOffset, mFrameSize, mParent.mSize - mOffset - 10);
700fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
701fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
702fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
703bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]);
704bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
705ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000c))
706bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) {
707ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // Compression or encryption are not supported at this time.
708ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // Per-frame unsynchronization and data-length indicator
709ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // have already been taken care of.
710bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
7113856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("Skipping unsupported frame (compression, encryption "
712bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                     "or per-frame unsynchronization flagged");
713bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
714bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                mOffset += mFrameSize;
715bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                continue;
716bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
717bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
718fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 10];
719fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
720fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
721fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
722fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
723fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
724fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[5];
725fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 4);
726fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[4] = '\0';
727fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
728fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
729fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
730fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
73183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        } else {
73283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
73383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
73483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (mOffset >= mParent.mSize) {
73583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                return;
73683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
73783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
73883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mFrameData = &mParent.mData[mOffset];
73983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
74083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            switch (mOffset) {
74183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 3:
74283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 33:
74383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 63:
74483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 30;
74583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
74683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 93:
74783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 4;
74883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
74983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 97:
75083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    if (mParent.mVersion == ID3_V1) {
75183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 30;
75283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    } else {
75383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 29;
75483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    }
75583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
75683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 126:
75783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
75883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
75983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 127:
76083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
76183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
76283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                default:
76383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    CHECK(!"Should not be here, invalid offset.");
76483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
76583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
76683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
76783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (!mID) {
76883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
76983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
77083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
77183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            String8 id;
77283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            getID(&id);
77383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
77483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (id == mID) {
77583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
77683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
777fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
778fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
779fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mOffset += mFrameSize;
780fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
781fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
782fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
783fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic size_t StringSize(const uint8_t *start, uint8_t encoding) {
784bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    if (encoding == 0x00 || encoding == 0x03) {
785bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // ISO 8859-1 or UTF-8
786fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return strlen((const char *)start) + 1;
787fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
788fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
789fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // UCS-2
790fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = 0;
791fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (start[n] != '\0' || start[n + 1] != '\0') {
792fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        n += 2;
793fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
794fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
795be5016bac5c1b422d850e299d3cb11fecf0ac19dJesper Tragardh    // Add size of null termination.
796be5016bac5c1b422d850e299d3cb11fecf0ac19dJesper Tragardh    return n + 2;
797fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
798fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
799fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst void *
800fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::getAlbumArt(size_t *length, String8 *mime) const {
801fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
802fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mime->setTo("");
803fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
804bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    Iterator it(
805bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            *this,
806bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) ? "APIC" : "PIC");
807fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
808fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (!it.done()) {
809fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t size;
810fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data = it.getData(&size);
811fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
812bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) {
813fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
814fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mime->setTo((const char *)&data[1]);
815fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t mimeLen = strlen((const char *)&data[1]) + 1;
816fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
817fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[1 + mimeLen];
818fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
819fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
820fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
821fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
822fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
823fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
824fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
825fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
826fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[2 + mimeLen], encoding);
827fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
828f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen            if (size < 2 ||
829f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen                    size - 2 < mimeLen ||
830f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen                    size - 2 - mimeLen < descLen) {
831f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen                ALOGW("bogus album art sizes");
832f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen                return NULL;
833f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen            }
834fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 2 - mimeLen - descLen;
835fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
836fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[2 + mimeLen + descLen];
837fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
838fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
839fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
840fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&data[1], "PNG", 3)) {
841fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/png");
842fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "JPG", 3)) {
843fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/jpeg");
844fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "-->", 3)) {
845fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("text/plain");
846fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else {
847fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return NULL;
848fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
849fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
850fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
851fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[4];
852fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
853fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
854fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
855fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
856fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
857fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
858fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
859fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[5], encoding);
860fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
861fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 5 - descLen;
862fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
863fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[5 + descLen];
864fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
865fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
866fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
867fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return NULL;
868fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
869fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
87083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV1(const sp<DataSource> &source) {
87183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    const size_t V1_TAG_SIZE = 128;
87283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
873c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t size;
874c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (source->getSize(&size) != OK || size < (off64_t)V1_TAG_SIZE) {
87583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
87683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
87783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
87883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mData = (uint8_t *)malloc(V1_TAG_SIZE);
87983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (source->readAt(size - V1_TAG_SIZE, mData, V1_TAG_SIZE)
88083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            != (ssize_t)V1_TAG_SIZE) {
88183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
88283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
88383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
88483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
88583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
88683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
88783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (memcmp("TAG", mData, 3)) {
88883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
88983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
89083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
89183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
89283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
89383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
89483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mSize = V1_TAG_SIZE;
89583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mFirstFrameOffset = 3;
89683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
89783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mData[V1_TAG_SIZE - 3] != 0) {
89883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1;
89983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
90083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1_1;
90183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
90283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
90383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    return true;
90483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber}
905fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
906fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}  // namespace android
907