ID3.cpp revision e1e791727f709c7ab54d47b9cd46d4326a02e913
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) {
44b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross        off64_t available = (offset >= (off64_t)mSize) ? 0ll : mSize - offset;
4514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
46b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross        size_t copy = (available > (off64_t)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
59328abde67f57c026ac44e927f9244c40832499c8Oscar RydhéID3::ID3(const sp<DataSource> &source, bool ignoreV1, off64_t offset)
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) {
66328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    mIsValid = parseV2(source, offset);
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
82328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    mIsValid = parseV2(source, 0);
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
118328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhébool ID3::parseV2(const sp<DataSource> &source, off64_t offset) {
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(
129328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                offset, &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) {
175b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross        ALOGE("skipping huge ID3 metadata of size %zu", 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
188328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (source->readAt(offset + 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);
197b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        if (copy == NULL) {
198b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            free(mData);
199b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            mData = NULL;
200b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            ALOGE("b/24623447, no more memory");
201b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            return false;
202b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        }
203b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia
204428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        memcpy(copy, mData, size);
205428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
206428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
207428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (!success) {
208428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            memcpy(mData, copy, size);
209428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            mSize = size;
210428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
211428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            success = removeUnsynchronizationV2_4(true /* iTunesHack */);
212428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
213428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            if (success) {
2143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
215428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            }
216428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        }
217428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
218428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        free(copy);
219428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        copy = NULL;
220428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
221428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (!success) {
222ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            free(mData);
223ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData = NULL;
224ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
225ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
226ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
227ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    } else if (header.flags & 0x80) {
2283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("removing unsynchronization");
229ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
230fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        removeUnsynchronization();
231fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
232fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
233fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mFirstFrameOffset = 0;
234fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 3 && (header.flags & 0x40)) {
235fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // Version 2.3 has an optional extended header.
236fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
237fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mSize < 4) {
23883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
23983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
24083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
241fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
242fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
243fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
244b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        size_t extendedHeaderSize = U32_AT(&mData[0]);
245b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        if (extendedHeaderSize > SIZE_MAX - 4) {
246b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            free(mData);
247b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            mData = NULL;
248b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            ALOGE("b/24623447, extendedHeaderSize is too large");
249b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            return false;
250b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        }
251b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        extendedHeaderSize += 4;
252fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
253fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize > mSize) {
25483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
25583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
25683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
257fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
258fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
259fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
260fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFirstFrameOffset = extendedHeaderSize;
261fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
262fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint16_t extendedFlags = 0;
263fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize >= 6) {
264fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            extendedFlags = U16_AT(&mData[4]);
265fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
266fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedHeaderSize >= 10) {
267fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                size_t paddingSize = U32_AT(&mData[6]);
268fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
269b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia                if (paddingSize > SIZE_MAX - mFirstFrameOffset) {
270b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia                    ALOGE("b/24623447, paddingSize is too large");
271b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia                }
272b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia                if (paddingSize > mSize - mFirstFrameOffset) {
27383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    free(mData);
27483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mData = NULL;
27583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
276fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                    return false;
277fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                }
278fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
279fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mSize -= paddingSize;
280fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
281fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
282fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedFlags & 0x8000) {
2833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("have crc");
284fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
285fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
286bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 4 && (header.flags & 0x40)) {
287bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // Version 2.4 has an optional extended header, that's different
288bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // from Version 2.3's...
289bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
290bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (mSize < 4) {
291bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
292bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
293bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
294bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
295bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
296bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
297bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        size_t ext_size;
298bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (!ParseSyncsafeInteger(mData, &ext_size)) {
299bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
300bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
301bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
302bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
303bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
304bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
305bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (ext_size < 6 || ext_size > mSize) {
306bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
307bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
308bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
309bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
310bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
311bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
312bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        mFirstFrameOffset = ext_size;
313fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
314fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
315fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
316fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_2;
317bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 3) {
318fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_3;
319bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else {
320bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        CHECK_EQ(header.version_major, 4);
321bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        mVersion = ID3_V2_4;
322fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
323fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
324fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return true;
325fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
326fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
327fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::removeUnsynchronization() {
328fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i + 1 < mSize; ++i) {
329fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mData[i] == 0xff && mData[i + 1] == 0x00) {
330fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memmove(&mData[i + 1], &mData[i + 2], mSize - i - 2);
331fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            --mSize;
332fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
333fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
334fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
335fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
336ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huberstatic void WriteSyncsafeInteger(uint8_t *dst, size_t x) {
337ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    for (size_t i = 0; i < 4; ++i) {
338ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        dst[3 - i] = (x & 0x7f);
339ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        x >>= 7;
340ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    }
341ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber}
342ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
343428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huberbool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
344ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    size_t oldSize = mSize;
345ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
346ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    size_t offset = 0;
34709da86913ca97d7a818a8917b6601527e5e18a24Wei Jia    while (mSize >= 10 && offset <= mSize - 10) {
348ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
349ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            break;
350ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
351ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
352ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        size_t dataSize;
353428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (iTunesHack) {
354428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            dataSize = U32_AT(&mData[offset + 4]);
355428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        } else if (!ParseSyncsafeInteger(&mData[offset + 4], &dataSize)) {
356ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
357ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
358ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
35909da86913ca97d7a818a8917b6601527e5e18a24Wei Jia        if (dataSize > mSize - 10 - offset) {
360ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
361ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
362ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
363ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        uint16_t flags = U16_AT(&mData[offset + 8]);
364ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        uint16_t prevFlags = flags;
365ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
366ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (flags & 1) {
367ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            // Strip data length indicator
368ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
369c37f7f6fa0cb7f55cdc5b2d4ccbf2c87c3bc6c3bNeel Mehta            if (mSize < 14 || mSize - 14 < offset || dataSize < 4) {
37009da86913ca97d7a818a8917b6601527e5e18a24Wei Jia                return false;
37109da86913ca97d7a818a8917b6601527e5e18a24Wei Jia            }
372ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            memmove(&mData[offset + 10], &mData[offset + 14], mSize - offset - 14);
373ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mSize -= 4;
374ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            dataSize -= 4;
375ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
376ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            flags &= ~1;
377ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
378ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
379ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (flags & 2) {
38072a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            // This file has "unsynchronization", so we have to replace occurrences
38172a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            // of 0xff 0x00 with just 0xff in order to get the real data.
382ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
38372a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            size_t readOffset = offset + 11;
38472a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            size_t writeOffset = offset + 11;
385ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            for (size_t i = 0; i + 1 < dataSize; ++i) {
38672a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                if (mData[readOffset - 1] == 0xff
38772a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                        && mData[readOffset] == 0x00) {
38872a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                    ++readOffset;
389ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                    --mSize;
390ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                    --dataSize;
391ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                }
39272a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                mData[writeOffset++] = mData[readOffset++];
393ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            }
39472a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            // move the remaining data following this frame
39572a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            memmove(&mData[writeOffset], &mData[readOffset], oldSize - readOffset);
396ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
397ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            flags &= ~2;
398ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
399ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
400428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (flags != prevFlags || iTunesHack) {
401ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            WriteSyncsafeInteger(&mData[offset + 4], dataSize);
402ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData[offset + 8] = flags >> 8;
403ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData[offset + 9] = flags & 0xff;
404ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
405ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
406ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        offset += 10 + dataSize;
407ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    }
408ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
409ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    memset(&mData[mSize], 0, oldSize - mSize);
410ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
411ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    return true;
412ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber}
413ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
414fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::Iterator(const ID3 &parent, const char *id)
415fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mParent(parent),
416fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mID(NULL),
417fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mOffset(mParent.mFirstFrameOffset),
418fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameData(NULL),
419fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameSize(0) {
420fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (id) {
421fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = strdup(id);
422fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
423fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
424fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
425fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
426fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
427fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::~Iterator() {
428fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mID) {
429fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        free(mID);
430fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = NULL;
431fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
432fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
433fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
434fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::Iterator::done() const {
435fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData == NULL;
436fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
437fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
438fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::next() {
439fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
440fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
441fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
442fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
443fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mOffset += mFrameSize;
444fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
445fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
446fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
447fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
448fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::getID(String8 *id) const {
449fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
450fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
451fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
452fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
453fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
454fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
455fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
456fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 3);
457bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
458fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 4);
45983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
46083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
46183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
46283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        switch (mOffset) {
46383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 3:
46483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TT2");
46583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
46683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 33:
46783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TP1");
46883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
46983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 63:
47083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TAL");
47183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
47283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 93:
47383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TYE");
47483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
47583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 97:
47683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("COM");
47783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
47883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 126:
47983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TRK");
48083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
48183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 127:
48283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TCO");
48383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
48483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            default:
48583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                CHECK(!"should not be here.");
48683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
48783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
488fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
489fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
490fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
491fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
492b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// the 2nd argument is used to get the data following the \0 in a comment field
493b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getString(String8 *id, String8 *comment) const {
494b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    getstring(id, false);
495b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (comment != NULL) {
496b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        getstring(comment, true);
497b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    }
498b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen}
499b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen
500b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// comment fields (COM/COMM) contain an initial short descriptor, followed by \0,
501b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// followed by more data. The data following the \0 can be retrieved by setting
502b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// "otherdata" to true.
503b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getstring(String8 *id, bool otherdata) const {
504fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
505fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
506b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    const uint8_t *frameData = mFrameData;
507b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (frameData == NULL) {
508fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
509fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
510fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
511b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    uint8_t encoding = *frameData;
512b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen
51383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1) {
51483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        if (mOffset == 126 || mOffset == 127) {
51583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            // Special treatment for the track number and genre.
51683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            char tmp[16];
517b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen            sprintf(tmp, "%d", (int)*frameData);
51883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
51983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            id->setTo(tmp);
52083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            return;
52183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
52283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
523544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // this is supposed to be ISO-8859-1, but pass it up as-is to the caller, who will figure
524544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // out the real encoding
525544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        id->setTo((const char*)frameData, mFrameSize);
52683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return;
52783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
52883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
5293bf1e0fdf27e1188b8d3574ed073595b8eacb114Wei Jia    if (mFrameSize < getHeaderLength() + 1) {
5303bf1e0fdf27e1188b8d3574ed073595b8eacb114Wei Jia        return;
5313bf1e0fdf27e1188b8d3574ed073595b8eacb114Wei Jia    }
532fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = mFrameSize - getHeaderLength() - 1;
533b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (otherdata) {
534e1e791727f709c7ab54d47b9cd46d4326a02e913Roger        if (n < 5) {
535e1e791727f709c7ab54d47b9cd46d4326a02e913Roger            return;
536e1e791727f709c7ab54d47b9cd46d4326a02e913Roger        }
537b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        // skip past the encoding, language, and the 0 separator
538b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        frameData += 4;
539b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        int32_t i = n - 4;
540b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        while(--i >= 0 && *++frameData != 0) ;
541b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        int skipped = (frameData - mFrameData);
54214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (skipped >= (int)n) {
543b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen            return;
544b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        }
545b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        n -= skipped;
546b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    }
547fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
548b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (encoding == 0x00) {
549544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // supposedly ISO 8859-1
550544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        id->setTo((const char*)frameData + 1, n);
551b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    } else if (encoding == 0x03) {
552544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // supposedly UTF-8
553b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        id->setTo((const char *)(frameData + 1), n);
554b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    } else if (encoding == 0x02) {
555544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // supposedly UTF-16 BE, no byte order mark.
556bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // API wants number of characters, not number of bytes...
557bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        int len = n / 2;
558b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        const char16_t *framedata = (const char16_t *) (frameData + 1);
559bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        char16_t *framedatacopy = NULL;
560bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#if BYTE_ORDER == LITTLE_ENDIAN
561bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        framedatacopy = new char16_t[len];
562bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        for (int i = 0; i < len; i++) {
563bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            framedatacopy[i] = bswap_16(framedata[i]);
564bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
565bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        framedata = framedatacopy;
566bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#endif
567bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        id->setTo(framedata, len);
568bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (framedatacopy != NULL) {
569bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            delete[] framedatacopy;
570bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
571544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen    } else if (encoding == 0x01) {
572fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // UCS-2
57308e7eb983fcb9860a574e964ff905f75aab88d2fAndreas Huber        // API wants number of characters, not number of bytes...
5745a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        int len = n / 2;
575b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        const char16_t *framedata = (const char16_t *) (frameData + 1);
5765a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        char16_t *framedatacopy = NULL;
5775a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfffe) {
5785a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            // endianness marker doesn't match host endianness, convert
5795a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedatacopy = new char16_t[len];
5805a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            for (int i = 0; i < len; i++) {
581569e7f1b1444194d1aca5a0b23de154565ba12daMarco Nelissen                framedatacopy[i] = bswap_16(framedata[i]);
5825a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            }
5835a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata = framedatacopy;
5845a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
5855a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        // If the string starts with an endianness marker, skip it
5865a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfeff) {
5875a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata++;
5885a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            len--;
5895a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
590544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen
591544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // check if the resulting data consists entirely of 8-bit values
592544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        bool eightBit = true;
593544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        for (int i = 0; i < len; i++) {
594544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            if (framedata[i] > 0xff) {
595544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen                eightBit = false;
596544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen                break;
597544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            }
598544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        }
599544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        if (eightBit) {
600544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            // collapse to 8 bit, then let the media scanner client figure out the real encoding
601544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            char *frame8 = new char[len];
602544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            for (int i = 0; i < len; i++) {
603544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen                frame8[i] = framedata[i];
604544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            }
605544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            id->setTo(frame8, len);
606544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            delete [] frame8;
607544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        } else {
608544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            id->setTo(framedata, len);
609544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        }
610544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen
6115a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (framedatacopy != NULL) {
6125a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            delete[] framedatacopy;
6135a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
614fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
615fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
616fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
617fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst uint8_t *ID3::Iterator::getData(size_t *length) const {
618fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
619fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
620fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
621fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
622fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
623fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
624be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake    // Prevent integer underflow
625be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake    if (mFrameSize < getHeaderLength()) {
626be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake        return NULL;
627be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake    }
628be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake
629fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = mFrameSize - getHeaderLength();
630fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
631fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData;
632fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
633fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
634fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubersize_t ID3::Iterator::getHeaderLength() const {
635fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
636fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 6;
637bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
638fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 10;
63983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
64083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
64183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return 0;
642fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
643fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
644fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
645fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::findFrame() {
646fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (;;) {
647fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameData = NULL;
648fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameSize = 0;
649fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
650fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mParent.mVersion == ID3_V2_2) {
651fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 6 > mParent.mSize) {
652fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
653fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
654fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
655fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0", 3)) {
656fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
657fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
658fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
659fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize =
660fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                (mParent.mData[mOffset + 3] << 16)
661fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | (mParent.mData[mOffset + 4] << 8)
662fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | mParent.mData[mOffset + 5];
663fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
664ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            if (mFrameSize == 0) {
665ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen                return;
666ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            }
667ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            mFrameSize += 6; // add tag id and size field
668fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
669c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            // Prevent integer overflow in validation
670c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            if (SIZE_MAX - mOffset <= mFrameSize) {
671c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake                return;
672c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            }
673c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake
674fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
675b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross                ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
676b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross                    mOffset, mFrameSize, mParent.mSize - mOffset - (size_t)6);
677fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
678fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
679fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
680fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 6];
681fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
682fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
683fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
684fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
685fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
686fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[4];
687fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 3);
688fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[3] = '\0';
689fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
690fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
691fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
692fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
693bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        } else if (mParent.mVersion == ID3_V2_3
694bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || mParent.mVersion == ID3_V2_4) {
695fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 10 > mParent.mSize) {
696fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
697fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
698fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
699fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0\0", 4)) {
700fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
701fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
702fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
703c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            size_t baseSize = 0;
704bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            if (mParent.mVersion == ID3_V2_4) {
705bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                if (!ParseSyncsafeInteger(
706bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                            &mParent.mData[mOffset + 4], &baseSize)) {
707bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                    return;
708bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                }
709bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            } else {
710bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                baseSize = U32_AT(&mParent.mData[mOffset + 4]);
711bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
712bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
713ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            if (baseSize == 0) {
714ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen                return;
715ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            }
716ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen
717c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            // Prevent integer overflow when adding
718c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            if (SIZE_MAX - 10 <= baseSize) {
719c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake                return;
720c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            }
721c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake
722ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            mFrameSize = 10 + baseSize; // add tag id, size field and flags
723fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
724c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            // Prevent integer overflow in validation
725c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            if (SIZE_MAX - mOffset <= mFrameSize) {
726c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake                return;
727c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            }
728fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
729fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
730b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross                ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
731b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross                    mOffset, mFrameSize, mParent.mSize - mOffset - (size_t)10);
732fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
733fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
734fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
735bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]);
736bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
737ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000c))
738bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) {
739ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // Compression or encryption are not supported at this time.
740ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // Per-frame unsynchronization and data-length indicator
741ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // have already been taken care of.
742bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
7433856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("Skipping unsupported frame (compression, encryption "
744bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                     "or per-frame unsynchronization flagged");
745bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
746bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                mOffset += mFrameSize;
747bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                continue;
748bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
749bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
750fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 10];
751fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
752fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
753fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
754fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
755fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
756fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[5];
757fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 4);
758fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[4] = '\0';
759fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
760fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
761fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
762fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
76383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        } else {
76483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
76583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
76683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (mOffset >= mParent.mSize) {
76783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                return;
76883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
76983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
77083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mFrameData = &mParent.mData[mOffset];
77183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
77283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            switch (mOffset) {
77383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 3:
77483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 33:
77583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 63:
77683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 30;
77783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
77883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 93:
77983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 4;
78083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
78183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 97:
78283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    if (mParent.mVersion == ID3_V1) {
78383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 30;
78483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    } else {
78583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 29;
78683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    }
78783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
78883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 126:
78983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
79083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
79183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 127:
79283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
79383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
79483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                default:
79583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    CHECK(!"Should not be here, invalid offset.");
79683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
79783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
79883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
79983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (!mID) {
80083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
80183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
80283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
80383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            String8 id;
80483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            getID(&id);
80583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
80683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (id == mID) {
80783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
80883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
809fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
810fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
811fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mOffset += mFrameSize;
812fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
813fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
814fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
815fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic size_t StringSize(const uint8_t *start, uint8_t encoding) {
816bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    if (encoding == 0x00 || encoding == 0x03) {
817bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // ISO 8859-1 or UTF-8
818fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return strlen((const char *)start) + 1;
819fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
820fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
821fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // UCS-2
822fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = 0;
823fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (start[n] != '\0' || start[n + 1] != '\0') {
824fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        n += 2;
825fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
826fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
827be5016bac5c1b422d850e299d3cb11fecf0ac19dJesper Tragardh    // Add size of null termination.
828be5016bac5c1b422d850e299d3cb11fecf0ac19dJesper Tragardh    return n + 2;
829fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
830fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
831fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst void *
832fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::getAlbumArt(size_t *length, String8 *mime) const {
833fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
834fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mime->setTo("");
835fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
836bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    Iterator it(
837bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            *this,
838bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) ? "APIC" : "PIC");
839fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
840fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (!it.done()) {
841fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t size;
842fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data = it.getData(&size);
843be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake        if (!data) {
844be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake            return NULL;
845be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake        }
846fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
847bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) {
848fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
849fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mime->setTo((const char *)&data[1]);
850fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t mimeLen = strlen((const char *)&data[1]) + 1;
851fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
852fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
853b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            uint8_t picType = data[1 + mimeLen];
854fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
855fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
856fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
857fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
858fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
859fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
860fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
861fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[2 + mimeLen], encoding);
862fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
863f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen            if (size < 2 ||
864f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen                    size - 2 < mimeLen ||
865f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen                    size - 2 - mimeLen < descLen) {
866f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen                ALOGW("bogus album art sizes");
867f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen                return NULL;
868f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen            }
869fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 2 - mimeLen - descLen;
870fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
871fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[2 + mimeLen + descLen];
872fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
873fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
874fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
875fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&data[1], "PNG", 3)) {
876fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/png");
877fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "JPG", 3)) {
878fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/jpeg");
879fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "-->", 3)) {
880fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("text/plain");
881fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else {
882fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return NULL;
883fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
884fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
885fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
886fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[4];
887fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
888fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
889fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
890fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
891fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
892fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
893fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
894fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[5], encoding);
895fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
896fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 5 - descLen;
897fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
898fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[5 + descLen];
899fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
900fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
901fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
902fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return NULL;
903fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
904fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
90583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV1(const sp<DataSource> &source) {
90683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    const size_t V1_TAG_SIZE = 128;
90783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
908c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t size;
909c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (source->getSize(&size) != OK || size < (off64_t)V1_TAG_SIZE) {
91083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
91183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
91283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
91383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mData = (uint8_t *)malloc(V1_TAG_SIZE);
91483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (source->readAt(size - V1_TAG_SIZE, mData, V1_TAG_SIZE)
91583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            != (ssize_t)V1_TAG_SIZE) {
91683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
91783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
91883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
91983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
92083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
92183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
92283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (memcmp("TAG", mData, 3)) {
92383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
92483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
92583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
92683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
92783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
92883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
92983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mSize = V1_TAG_SIZE;
93083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mFirstFrameOffset = 3;
93183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
93283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mData[V1_TAG_SIZE - 3] != 0) {
93383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1;
93483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
93583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1_1;
93683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
93783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
93883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    return true;
93983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber}
940fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
941fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}  // namespace android
942