ID3.cpp revision 544ad2be674423238c47650d2c8588ba7dfc9ed2
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 Huber
472b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// the 2nd argument is used to get the data following the \0 in a comment field
473b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getString(String8 *id, String8 *comment) const {
474b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    getstring(id, false);
475b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (comment != NULL) {
476b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        getstring(comment, true);
477b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    }
478b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen}
479b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen
480b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// comment fields (COM/COMM) contain an initial short descriptor, followed by \0,
481b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// followed by more data. The data following the \0 can be retrieved by setting
482b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// "otherdata" to true.
483b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getstring(String8 *id, bool otherdata) const {
484fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
485fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
486b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    const uint8_t *frameData = mFrameData;
487b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (frameData == NULL) {
488fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
489fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
490fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
491b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    uint8_t encoding = *frameData;
492b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen
49383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1) {
49483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        if (mOffset == 126 || mOffset == 127) {
49583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            // Special treatment for the track number and genre.
49683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            char tmp[16];
497b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen            sprintf(tmp, "%d", (int)*frameData);
49883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
49983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            id->setTo(tmp);
50083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            return;
50183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
50283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
503544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // this is supposed to be ISO-8859-1, but pass it up as-is to the caller, who will figure
504544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // out the real encoding
505544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        id->setTo((const char*)frameData, mFrameSize);
50683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return;
50783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
50883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
509fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = mFrameSize - getHeaderLength() - 1;
510b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (otherdata) {
511b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        // skip past the encoding, language, and the 0 separator
512b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        frameData += 4;
513b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        int32_t i = n - 4;
514b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        while(--i >= 0 && *++frameData != 0) ;
515b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        int skipped = (frameData - mFrameData);
51614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (skipped >= (int)n) {
517b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen            return;
518b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        }
519b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        n -= skipped;
520b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    }
521fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
522b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (encoding == 0x00) {
523544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // supposedly ISO 8859-1
524544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        id->setTo((const char*)frameData + 1, n);
525b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    } else if (encoding == 0x03) {
526544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // supposedly UTF-8
527b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        id->setTo((const char *)(frameData + 1), n);
528b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    } else if (encoding == 0x02) {
529544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // supposedly UTF-16 BE, no byte order mark.
530bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // API wants number of characters, not number of bytes...
531bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        int len = n / 2;
532b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        const char16_t *framedata = (const char16_t *) (frameData + 1);
533bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        char16_t *framedatacopy = NULL;
534bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#if BYTE_ORDER == LITTLE_ENDIAN
535bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        framedatacopy = new char16_t[len];
536bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        for (int i = 0; i < len; i++) {
537bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            framedatacopy[i] = bswap_16(framedata[i]);
538bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
539bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        framedata = framedatacopy;
540bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#endif
541bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        id->setTo(framedata, len);
542bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (framedatacopy != NULL) {
543bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            delete[] framedatacopy;
544bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
545544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen    } else if (encoding == 0x01) {
546fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // UCS-2
54708e7eb983fcb9860a574e964ff905f75aab88d2fAndreas Huber        // API wants number of characters, not number of bytes...
5485a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        int len = n / 2;
549b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        const char16_t *framedata = (const char16_t *) (frameData + 1);
5505a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        char16_t *framedatacopy = NULL;
5515a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfffe) {
5525a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            // endianness marker doesn't match host endianness, convert
5535a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedatacopy = new char16_t[len];
5545a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            for (int i = 0; i < len; i++) {
555569e7f1b1444194d1aca5a0b23de154565ba12daMarco Nelissen                framedatacopy[i] = bswap_16(framedata[i]);
5565a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            }
5575a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata = framedatacopy;
5585a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
5595a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        // If the string starts with an endianness marker, skip it
5605a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfeff) {
5615a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata++;
5625a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            len--;
5635a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
564544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen
565544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // check if the resulting data consists entirely of 8-bit values
566544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        bool eightBit = true;
567544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        for (int i = 0; i < len; i++) {
568544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            if (framedata[i] > 0xff) {
569544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen                eightBit = false;
570544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen                break;
571544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            }
572544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        }
573544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        if (eightBit) {
574544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            // collapse to 8 bit, then let the media scanner client figure out the real encoding
575544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            char *frame8 = new char[len];
576544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            for (int i = 0; i < len; i++) {
577544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen                frame8[i] = framedata[i];
578544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            }
579544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            id->setTo(frame8, len);
580544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            delete [] frame8;
581544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        } else {
582544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            id->setTo(framedata, len);
583544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        }
584544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen
5855a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (framedatacopy != NULL) {
5865a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            delete[] framedatacopy;
5875a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
588fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
589fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
590fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
591fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst uint8_t *ID3::Iterator::getData(size_t *length) const {
592fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
593fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
594fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
595fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
596fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
597fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
598fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = mFrameSize - getHeaderLength();
599fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
600fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData;
601fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
602fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
603fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubersize_t ID3::Iterator::getHeaderLength() const {
604fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
605fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 6;
606bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
607fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 10;
60883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
60983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
61083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return 0;
611fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
612fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
613fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
614fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::findFrame() {
615fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (;;) {
616fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameData = NULL;
617fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameSize = 0;
618fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
619fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mParent.mVersion == ID3_V2_2) {
620fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 6 > mParent.mSize) {
621fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
622fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
623fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
624fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0", 3)) {
625fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
626fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
627fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
628fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize =
629fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                (mParent.mData[mOffset + 3] << 16)
630fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | (mParent.mData[mOffset + 4] << 8)
631fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | mParent.mData[mOffset + 5];
632fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
633fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize += 6;
634fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
635fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
6363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
637fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                     mOffset, mFrameSize, mParent.mSize - mOffset - 6);
638fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
639fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
640fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
641fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 6];
642fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
643fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
644fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
645fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
646fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
647fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[4];
648fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 3);
649fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[3] = '\0';
650fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
651fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
652fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
653fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
654bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        } else if (mParent.mVersion == ID3_V2_3
655bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || mParent.mVersion == ID3_V2_4) {
656fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 10 > mParent.mSize) {
657fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
658fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
659fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
660fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0\0", 4)) {
661fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
662fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
663fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
664bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            size_t baseSize;
665bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            if (mParent.mVersion == ID3_V2_4) {
666bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                if (!ParseSyncsafeInteger(
667bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                            &mParent.mData[mOffset + 4], &baseSize)) {
668bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                    return;
669bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                }
670bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            } else {
671bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                baseSize = U32_AT(&mParent.mData[mOffset + 4]);
672bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
673bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
674bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mFrameSize = 10 + baseSize;
675fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
676fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
6773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
678fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                     mOffset, mFrameSize, mParent.mSize - mOffset - 10);
679fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
680fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
681fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
682bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]);
683bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
684ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000c))
685bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) {
686ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // Compression or encryption are not supported at this time.
687ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // Per-frame unsynchronization and data-length indicator
688ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // have already been taken care of.
689bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
6903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("Skipping unsupported frame (compression, encryption "
691bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                     "or per-frame unsynchronization flagged");
692bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
693bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                mOffset += mFrameSize;
694bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                continue;
695bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
696bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
697fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 10];
698fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
699fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
700fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
701fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
702fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
703fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[5];
704fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 4);
705fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[4] = '\0';
706fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
707fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
708fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
709fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
71083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        } else {
71183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
71283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
71383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (mOffset >= mParent.mSize) {
71483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                return;
71583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
71683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
71783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mFrameData = &mParent.mData[mOffset];
71883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
71983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            switch (mOffset) {
72083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 3:
72183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 33:
72283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 63:
72383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 30;
72483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
72583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 93:
72683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 4;
72783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
72883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 97:
72983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    if (mParent.mVersion == ID3_V1) {
73083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 30;
73183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    } else {
73283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 29;
73383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    }
73483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
73583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 126:
73683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
73783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
73883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 127:
73983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
74083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
74183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                default:
74283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    CHECK(!"Should not be here, invalid offset.");
74383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
74483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
74583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
74683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (!mID) {
74783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
74883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
74983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
75083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            String8 id;
75183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            getID(&id);
75283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
75383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (id == mID) {
75483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
75583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
756fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
757fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
758fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mOffset += mFrameSize;
759fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
760fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
761fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
762fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic size_t StringSize(const uint8_t *start, uint8_t encoding) {
763bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    if (encoding == 0x00 || encoding == 0x03) {
764bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // ISO 8859-1 or UTF-8
765fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return strlen((const char *)start) + 1;
766fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
767fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
768fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // UCS-2
769fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = 0;
770fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (start[n] != '\0' || start[n + 1] != '\0') {
771fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        n += 2;
772fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
773fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
774be5016bac5c1b422d850e299d3cb11fecf0ac19dJesper Tragardh    // Add size of null termination.
775be5016bac5c1b422d850e299d3cb11fecf0ac19dJesper Tragardh    return n + 2;
776fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
777fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
778fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst void *
779fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::getAlbumArt(size_t *length, String8 *mime) const {
780fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
781fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mime->setTo("");
782fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
783bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    Iterator it(
784bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            *this,
785bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) ? "APIC" : "PIC");
786fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
787fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (!it.done()) {
788fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t size;
789fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data = it.getData(&size);
790fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
791bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) {
792fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
793fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mime->setTo((const char *)&data[1]);
794fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t mimeLen = strlen((const char *)&data[1]) + 1;
795fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
796fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[1 + mimeLen];
797fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
798fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
799fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
800fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
801fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
802fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
803fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
804fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
805fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[2 + mimeLen], encoding);
806fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
807fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 2 - mimeLen - descLen;
808fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
809fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[2 + mimeLen + descLen];
810fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
811fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
812fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
813fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&data[1], "PNG", 3)) {
814fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/png");
815fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "JPG", 3)) {
816fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/jpeg");
817fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "-->", 3)) {
818fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("text/plain");
819fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else {
820fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return NULL;
821fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
822fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
823fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
824fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[4];
825fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
826fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
827fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
828fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
829fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
830fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
831fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
832fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[5], encoding);
833fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
834fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 5 - descLen;
835fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
836fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[5 + descLen];
837fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
838fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
839fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
840fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return NULL;
841fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
842fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
84383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV1(const sp<DataSource> &source) {
84483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    const size_t V1_TAG_SIZE = 128;
84583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
846c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t size;
847c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (source->getSize(&size) != OK || size < (off64_t)V1_TAG_SIZE) {
84883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
84983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
85083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
85183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mData = (uint8_t *)malloc(V1_TAG_SIZE);
85283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (source->readAt(size - V1_TAG_SIZE, mData, V1_TAG_SIZE)
85383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            != (ssize_t)V1_TAG_SIZE) {
85483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
85583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
85683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
85783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
85883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
85983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
86083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (memcmp("TAG", mData, 3)) {
86183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
86283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
86383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
86483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
86583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
86683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
86783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mSize = V1_TAG_SIZE;
86883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mFirstFrameOffset = 3;
86983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
87083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mData[V1_TAG_SIZE - 3] != 0) {
87183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1;
87283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
87383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1_1;
87483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
87583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
87683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    return true;
87783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber}
878fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
879fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}  // namespace android
880