ID3.cpp revision 607612858f3afad1ade51a098aafa2a41523b5f7
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>
24607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang#include <media/stagefright/foundation/ByteUtils.h>
25fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include <media/stagefright/DataSource.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) {
80c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick    sp<MemorySource> source = new (std::nothrow) MemorySource(data, size);
81c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick
82c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick    if (source == NULL)
83c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick        return;
8414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
85328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    mIsValid = parseV2(source, 0);
8683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
87ffd6ffc5429c45577fd8e9f8fa90e79bb91b8a84Dylan Powers    if (!mIsValid && !ignoreV1) {
8883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mIsValid = parseV1(source);
8983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
90fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
91fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
92fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::~ID3() {
93fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mData) {
94fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        free(mData);
95fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mData = NULL;
96fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
98fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
99fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::isValid() const {
100fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mIsValid;
101fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
102fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
103fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Version ID3::version() const {
104fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mVersion;
105fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
106fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
107bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber// static
108bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huberbool ID3::ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x) {
109bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    *x = 0;
110bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    for (int32_t i = 0; i < 4; ++i) {
111bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (encoded[i] & 0x80) {
112bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
113bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
114bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
115bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        *x = ((*x) << 7) | encoded[i];
116bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    }
117bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
118bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    return true;
119bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber}
120bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
121328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhébool ID3::parseV2(const sp<DataSource> &source, off64_t offset) {
122bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huberstruct id3_header {
123bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    char id[3];
124bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t version_major;
125bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t version_minor;
126bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t flags;
127bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t enc_size[4];
128fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    };
129fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
130fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id3_header header;
131fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (source->readAt(
132328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                offset, &header, sizeof(header)) != (ssize_t)sizeof(header)) {
133fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
134fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
135fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
136fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (memcmp(header.id, "ID3", 3)) {
137fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
138fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
139fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
140fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 0xff || header.version_minor == 0xff) {
141fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
142fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
143fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
144fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
145fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x3f) {
146fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // We only support the 2 high bits, if any of the lower bits are
147fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // set, we cannot guarantee to understand the tag format.
148fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
149fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
150fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
151fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x40) {
152fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // No compression scheme has been decided yet, ignore the
153fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // tag if compression is indicated.
154fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
155fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
156fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
157fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else if (header.version_major == 3) {
158fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x1f) {
159fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // We only support the 3 high bits, if any of the lower bits are
160fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // set, we cannot guarantee to understand the tag format.
161fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
162fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
163bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 4) {
164bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (header.flags & 0x0f) {
165bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            // The lower 4 bits are undefined in this spec.
166bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
167bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
168fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
169fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
170fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
171fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
172bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    size_t size;
173bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    if (!ParseSyncsafeInteger(header.enc_size, &size)) {
174bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        return false;
175fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
176fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
17765997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber    if (size > kMaxMetadataSize) {
178b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross        ALOGE("skipping huge ID3 metadata of size %zu", size);
17965997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber        return false;
18065997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber    }
18165997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber
182fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mData = (uint8_t *)malloc(size);
183fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
184fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mData == NULL) {
185fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
186fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
187fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
188fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mSize = size;
18914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mRawSize = mSize + sizeof(header);
190fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
191328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (source->readAt(offset + sizeof(header), mData, mSize) != (ssize_t)mSize) {
192ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        free(mData);
193ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        mData = NULL;
194ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
195fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
196fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
197fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
198ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    if (header.version_major == 4) {
199428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        void *copy = malloc(size);
200b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        if (copy == NULL) {
201b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            free(mData);
202b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            mData = NULL;
203b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            ALOGE("b/24623447, no more memory");
204b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            return false;
205b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        }
206b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia
207428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        memcpy(copy, mData, size);
208428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
209428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
210428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (!success) {
211428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            memcpy(mData, copy, size);
212428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            mSize = size;
213428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
214428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            success = removeUnsynchronizationV2_4(true /* iTunesHack */);
215428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
216428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            if (success) {
2173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
218428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            }
219428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        }
220428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
221428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        free(copy);
222428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        copy = NULL;
223428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
224428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (!success) {
225ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            free(mData);
226ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData = NULL;
227ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
228ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
229ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
230ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    } else if (header.flags & 0x80) {
2313856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("removing unsynchronization");
232ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
233fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        removeUnsynchronization();
234fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
235fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
236fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mFirstFrameOffset = 0;
237fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 3 && (header.flags & 0x40)) {
238fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // Version 2.3 has an optional extended header.
239fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
240fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mSize < 4) {
24183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
24283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
24383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
244fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
245fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
246fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
247b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        size_t extendedHeaderSize = U32_AT(&mData[0]);
248b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        if (extendedHeaderSize > SIZE_MAX - 4) {
249b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            free(mData);
250b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            mData = NULL;
251b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            ALOGE("b/24623447, extendedHeaderSize is too large");
252b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            return false;
253b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        }
254b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        extendedHeaderSize += 4;
255fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
256fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize > mSize) {
25783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
25883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
25983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
260fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
261fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
262fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
263fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFirstFrameOffset = extendedHeaderSize;
264fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
265fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint16_t extendedFlags = 0;
266fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize >= 6) {
267fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            extendedFlags = U16_AT(&mData[4]);
268fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
269fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedHeaderSize >= 10) {
270fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                size_t paddingSize = U32_AT(&mData[6]);
271fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
272b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia                if (paddingSize > SIZE_MAX - mFirstFrameOffset) {
273b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia                    ALOGE("b/24623447, paddingSize is too large");
274b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia                }
275b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia                if (paddingSize > mSize - mFirstFrameOffset) {
27683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    free(mData);
27783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mData = NULL;
27883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
279fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                    return false;
280fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                }
281fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
282fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mSize -= paddingSize;
283fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
284fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
285fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedFlags & 0x8000) {
2863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("have crc");
287fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
288fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
289bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 4 && (header.flags & 0x40)) {
290bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // Version 2.4 has an optional extended header, that's different
291bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // from Version 2.3's...
292bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
293bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (mSize < 4) {
294bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
295bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
296bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
297bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
298bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
299bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
300bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        size_t ext_size;
301bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (!ParseSyncsafeInteger(mData, &ext_size)) {
302bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
303bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
304bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
305bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
306bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
307bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
308bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (ext_size < 6 || ext_size > mSize) {
309bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
310bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
311bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
312bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
313bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
314bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
315bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        mFirstFrameOffset = ext_size;
316fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
317fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
318fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
319fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_2;
320bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 3) {
321fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_3;
322bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else {
323bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        CHECK_EQ(header.version_major, 4);
324bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        mVersion = ID3_V2_4;
325fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
326fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
327fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return true;
328fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
329fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
330fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::removeUnsynchronization() {
331fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i + 1 < mSize; ++i) {
332fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mData[i] == 0xff && mData[i + 1] == 0x00) {
333fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memmove(&mData[i + 1], &mData[i + 2], mSize - i - 2);
334fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            --mSize;
335fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
336fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
337fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
338fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
339ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huberstatic void WriteSyncsafeInteger(uint8_t *dst, size_t x) {
340ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    for (size_t i = 0; i < 4; ++i) {
341ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        dst[3 - i] = (x & 0x7f);
342ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        x >>= 7;
343ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    }
344ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber}
345ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
346428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huberbool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
347ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    size_t oldSize = mSize;
348ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
349ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    size_t offset = 0;
35009da86913ca97d7a818a8917b6601527e5e18a24Wei Jia    while (mSize >= 10 && offset <= mSize - 10) {
351ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
352ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            break;
353ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
354ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
355ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        size_t dataSize;
356428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (iTunesHack) {
357428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            dataSize = U32_AT(&mData[offset + 4]);
358428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        } else if (!ParseSyncsafeInteger(&mData[offset + 4], &dataSize)) {
359ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
360ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
361ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
36209da86913ca97d7a818a8917b6601527e5e18a24Wei Jia        if (dataSize > mSize - 10 - offset) {
363ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
364ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
365ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
366ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        uint16_t flags = U16_AT(&mData[offset + 8]);
367ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        uint16_t prevFlags = flags;
368ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
369ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (flags & 1) {
370ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            // Strip data length indicator
371ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
372c37f7f6fa0cb7f55cdc5b2d4ccbf2c87c3bc6c3bNeel Mehta            if (mSize < 14 || mSize - 14 < offset || dataSize < 4) {
37309da86913ca97d7a818a8917b6601527e5e18a24Wei Jia                return false;
37409da86913ca97d7a818a8917b6601527e5e18a24Wei Jia            }
375ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            memmove(&mData[offset + 10], &mData[offset + 14], mSize - offset - 14);
376ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mSize -= 4;
377ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            dataSize -= 4;
378ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
379ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            flags &= ~1;
380ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
381ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
382d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen        if ((flags & 2) && (dataSize >= 2)) {
38372a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            // This file has "unsynchronization", so we have to replace occurrences
38472a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            // of 0xff 0x00 with just 0xff in order to get the real data.
385ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
38672a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            size_t readOffset = offset + 11;
38772a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            size_t writeOffset = offset + 11;
388ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            for (size_t i = 0; i + 1 < dataSize; ++i) {
38972a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                if (mData[readOffset - 1] == 0xff
39072a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                        && mData[readOffset] == 0x00) {
39172a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                    ++readOffset;
392ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                    --mSize;
393ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                    --dataSize;
394ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                }
39572a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                mData[writeOffset++] = mData[readOffset++];
396ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            }
39772a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            // move the remaining data following this frame
398d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen            if (readOffset <= oldSize) {
399d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen                memmove(&mData[writeOffset], &mData[readOffset], oldSize - readOffset);
400d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen            } else {
401d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen                ALOGE("b/34618607 (%zu %zu %zu %zu)", readOffset, writeOffset, oldSize, mSize);
402d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen                android_errorWriteLog(0x534e4554, "34618607");
403d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen            }
404ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
405ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
406d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen        flags &= ~2;
407428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (flags != prevFlags || iTunesHack) {
408ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            WriteSyncsafeInteger(&mData[offset + 4], dataSize);
409ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData[offset + 8] = flags >> 8;
410ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData[offset + 9] = flags & 0xff;
411ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
412ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
413ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        offset += 10 + dataSize;
414ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    }
415ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
416ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    memset(&mData[mSize], 0, oldSize - mSize);
417ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
418ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    return true;
419ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber}
420ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
421fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::Iterator(const ID3 &parent, const char *id)
422fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mParent(parent),
423fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mID(NULL),
424fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mOffset(mParent.mFirstFrameOffset),
425fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameData(NULL),
426fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameSize(0) {
427fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (id) {
428fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = strdup(id);
429fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
430fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
431fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
432fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
433fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
434fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::~Iterator() {
435fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mID) {
436fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        free(mID);
437fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = NULL;
438fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
439fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
440fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
441fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::Iterator::done() const {
442fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData == NULL;
443fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
444fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
445fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::next() {
446fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
447fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
448fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
449fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
450fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mOffset += mFrameSize;
451fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
452fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
453fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
454fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
455fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::getID(String8 *id) const {
456fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
457fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
458fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
459fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
460fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
461fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
462fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
463fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 3);
464bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
465fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 4);
46683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
46783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
46883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
46983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        switch (mOffset) {
47083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 3:
47183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TT2");
47283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
47383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 33:
47483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TP1");
47583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
47683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 63:
47783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TAL");
47883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
47983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 93:
48083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TYE");
48183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
48283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 97:
48383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("COM");
48483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
48583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 126:
48683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TRK");
48783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
48883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 127:
48983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TCO");
49083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
49183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            default:
49283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                CHECK(!"should not be here.");
49383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
49483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
495fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
496fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
497fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
498fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
499b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// the 2nd argument is used to get the data following the \0 in a comment field
500b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getString(String8 *id, String8 *comment) const {
501b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    getstring(id, false);
502b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (comment != NULL) {
503b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        getstring(comment, true);
504b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    }
505b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen}
506b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen
507b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// comment fields (COM/COMM) contain an initial short descriptor, followed by \0,
508b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// followed by more data. The data following the \0 can be retrieved by setting
509b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// "otherdata" to true.
510b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getstring(String8 *id, bool otherdata) const {
511fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
512fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
513b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    const uint8_t *frameData = mFrameData;
514b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (frameData == NULL) {
515fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
516fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
517fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
518b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    uint8_t encoding = *frameData;
519b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen
52083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1) {
52183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        if (mOffset == 126 || mOffset == 127) {
52283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            // Special treatment for the track number and genre.
52383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            char tmp[16];
5242c9cb62d0160fc4353d89fd9d648725794e7995eGeorge Burgess IV            snprintf(tmp, sizeof(tmp), "%d", (int)*frameData);
52583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
52683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            id->setTo(tmp);
52783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            return;
52883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
52983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
530544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // this is supposed to be ISO-8859-1, but pass it up as-is to the caller, who will figure
531544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // out the real encoding
532544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        id->setTo((const char*)frameData, mFrameSize);
53383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return;
53483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
53583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
5363bf1e0fdf27e1188b8d3574ed073595b8eacb114Wei Jia    if (mFrameSize < getHeaderLength() + 1) {
5373bf1e0fdf27e1188b8d3574ed073595b8eacb114Wei Jia        return;
5383bf1e0fdf27e1188b8d3574ed073595b8eacb114Wei Jia    }
539fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = mFrameSize - getHeaderLength() - 1;
540b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (otherdata) {
541e1e791727f709c7ab54d47b9cd46d4326a02e913Roger        if (n < 5) {
542e1e791727f709c7ab54d47b9cd46d4326a02e913Roger            return;
543e1e791727f709c7ab54d47b9cd46d4326a02e913Roger        }
544b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        // skip past the encoding, language, and the 0 separator
545b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        frameData += 4;
546b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        int32_t i = n - 4;
547b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        while(--i >= 0 && *++frameData != 0) ;
548b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        int skipped = (frameData - mFrameData);
54914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (skipped >= (int)n) {
550b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen            return;
551b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        }
552b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        n -= skipped;
553b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    }
554fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
555d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick    if (n <= 0) {
556d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick       return;
557d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick    }
558d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick
559b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (encoding == 0x00) {
560544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // supposedly ISO 8859-1
561544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        id->setTo((const char*)frameData + 1, n);
562b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    } else if (encoding == 0x03) {
563544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // supposedly UTF-8
564b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        id->setTo((const char *)(frameData + 1), n);
565b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    } else if (encoding == 0x02) {
566544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // supposedly UTF-16 BE, no byte order mark.
567bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // API wants number of characters, not number of bytes...
568bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        int len = n / 2;
569b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        const char16_t *framedata = (const char16_t *) (frameData + 1);
570bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        char16_t *framedatacopy = NULL;
571bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#if BYTE_ORDER == LITTLE_ENDIAN
572c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick        if (len > 0) {
573c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick            framedatacopy = new (std::nothrow) char16_t[len];
574d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            if (framedatacopy == NULL) {
575d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                return;
576c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick            }
577d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            for (int i = 0; i < len; i++) {
578d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                framedatacopy[i] = bswap_16(framedata[i]);
579d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            }
580d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            framedata = framedatacopy;
581bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
582bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#endif
583bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        id->setTo(framedata, len);
584bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (framedatacopy != NULL) {
585bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            delete[] framedatacopy;
586bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
587544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen    } else if (encoding == 0x01) {
588fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // UCS-2
58908e7eb983fcb9860a574e964ff905f75aab88d2fAndreas Huber        // API wants number of characters, not number of bytes...
5905a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        int len = n / 2;
591b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        const char16_t *framedata = (const char16_t *) (frameData + 1);
5925a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        char16_t *framedatacopy = NULL;
5935a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfffe) {
594d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            // endianness marker != host endianness, convert & skip
595d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            if (len <= 1) {
596d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                return;         // nothing after the marker
597d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            }
598d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            framedatacopy = new (std::nothrow) char16_t[len];
599d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            if (framedatacopy == NULL) {
600d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                return;
601d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            }
602d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            for (int i = 0; i < len; i++) {
603d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                framedatacopy[i] = bswap_16(framedata[i]);
604d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            }
605d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            framedata = framedatacopy;
606d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            // and skip over the marker
607d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            framedata++;
608d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            len--;
609d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick        } else if (*framedata == 0xfeff) {
610d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            // endianness marker == host endianness, skip it
611d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            if (len <= 1) {
612d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                return;         // nothing after the marker
6135a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            }
6145a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata++;
6155a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            len--;
6165a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
617544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen
618544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // check if the resulting data consists entirely of 8-bit values
619544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        bool eightBit = true;
620544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        for (int i = 0; i < len; i++) {
621544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            if (framedata[i] > 0xff) {
622544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen                eightBit = false;
623544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen                break;
624544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            }
625544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        }
626d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick        if (eightBit) {
627544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            // collapse to 8 bit, then let the media scanner client figure out the real encoding
628c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick            char *frame8 = new (std::nothrow) char[len];
629c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick            if (frame8 != NULL) {
630c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick                for (int i = 0; i < len; i++) {
631c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick                    frame8[i] = framedata[i];
632c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick                }
633c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick                id->setTo(frame8, len);
634c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick                delete [] frame8;
635d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            } else {
636d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                id->setTo(framedata, len);
637544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            }
638544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        } else {
639544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            id->setTo(framedata, len);
640544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        }
641544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen
6425a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (framedatacopy != NULL) {
6435a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            delete[] framedatacopy;
6445a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
645fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
646fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
647fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
648fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst uint8_t *ID3::Iterator::getData(size_t *length) const {
649fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
650fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
651fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
652fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
653fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
654fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
655be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake    // Prevent integer underflow
656be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake    if (mFrameSize < getHeaderLength()) {
657be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake        return NULL;
658be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake    }
659be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake
660fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = mFrameSize - getHeaderLength();
661fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
662fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData;
663fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
664fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
665fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubersize_t ID3::Iterator::getHeaderLength() const {
666fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
667fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 6;
668bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
669fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 10;
67083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
67183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
67283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return 0;
673fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
674fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
675fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
676fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::findFrame() {
677fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (;;) {
678fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameData = NULL;
679fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameSize = 0;
680fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
681fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mParent.mVersion == ID3_V2_2) {
682fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 6 > mParent.mSize) {
683fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
684fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
685fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
686fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0", 3)) {
687fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
688fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
689fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
690fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize =
691fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                (mParent.mData[mOffset + 3] << 16)
692fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | (mParent.mData[mOffset + 4] << 8)
693fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | mParent.mData[mOffset + 5];
694fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
695ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            if (mFrameSize == 0) {
696ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen                return;
697ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            }
698ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            mFrameSize += 6; // add tag id and size field
699fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
700c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            // Prevent integer overflow in validation
701c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            if (SIZE_MAX - mOffset <= mFrameSize) {
702c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake                return;
703c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            }
704c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake
705fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
706b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross                ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
707b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross                    mOffset, mFrameSize, mParent.mSize - mOffset - (size_t)6);
708fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
709fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
710fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
711fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 6];
712fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
713fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
714fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
715fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
716fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
717fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[4];
718fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 3);
719fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[3] = '\0';
720fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
721fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
722fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
723fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
724bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        } else if (mParent.mVersion == ID3_V2_3
725bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || mParent.mVersion == ID3_V2_4) {
726fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 10 > mParent.mSize) {
727fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
728fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
729fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
730fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0\0", 4)) {
731fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
732fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
733fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
734c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            size_t baseSize = 0;
735bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            if (mParent.mVersion == ID3_V2_4) {
736bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                if (!ParseSyncsafeInteger(
737bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                            &mParent.mData[mOffset + 4], &baseSize)) {
738bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                    return;
739bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                }
740bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            } else {
741bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                baseSize = U32_AT(&mParent.mData[mOffset + 4]);
742bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
743bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
744ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            if (baseSize == 0) {
745ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen                return;
746ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            }
747ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen
748c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            // Prevent integer overflow when adding
749c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            if (SIZE_MAX - 10 <= baseSize) {
750c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake                return;
751c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            }
752c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake
753ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            mFrameSize = 10 + baseSize; // add tag id, size field and flags
754fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
755c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            // Prevent integer overflow in validation
756c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            if (SIZE_MAX - mOffset <= mFrameSize) {
757c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake                return;
758c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            }
759fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
760fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
761b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross                ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
762b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross                    mOffset, mFrameSize, mParent.mSize - mOffset - (size_t)10);
763fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
764fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
765fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
766bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]);
767bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
768ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000c))
769bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) {
770ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // Compression or encryption are not supported at this time.
771ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // Per-frame unsynchronization and data-length indicator
772ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // have already been taken care of.
773bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
7743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("Skipping unsupported frame (compression, encryption "
775bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                     "or per-frame unsynchronization flagged");
776bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
777bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                mOffset += mFrameSize;
778bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                continue;
779bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
780bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
781fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 10];
782fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
783fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
784fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
785fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
786fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
787fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[5];
788fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 4);
789fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[4] = '\0';
790fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
791fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
792fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
793fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
79483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        } else {
79583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
79683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
79783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (mOffset >= mParent.mSize) {
79883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                return;
79983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
80083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
80183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mFrameData = &mParent.mData[mOffset];
80283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
80383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            switch (mOffset) {
80483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 3:
80583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 33:
80683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 63:
80783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 30;
80883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
80983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 93:
81083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 4;
81183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
81283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 97:
81383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    if (mParent.mVersion == ID3_V1) {
81483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 30;
81583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    } else {
81683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 29;
81783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    }
81883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
81983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 126:
82083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
82183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
82283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 127:
82383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
82483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
82583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                default:
82683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    CHECK(!"Should not be here, invalid offset.");
82783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
82883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
82983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
83083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (!mID) {
83183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
83283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
83383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
83483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            String8 id;
83583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            getID(&id);
83683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
83783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (id == mID) {
83883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
83983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
840fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
841fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
842fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mOffset += mFrameSize;
843fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
844fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
845fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
846ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick// return includes terminator;  if unterminated, returns > limit
847ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essickstatic size_t StringSize(const uint8_t *start, size_t limit, uint8_t encoding) {
848ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick
849bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    if (encoding == 0x00 || encoding == 0x03) {
850bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // ISO 8859-1 or UTF-8
851ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick        return strnlen((const char *)start, limit) + 1;
852fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
853fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
854fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // UCS-2
855fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = 0;
856ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick    while ((n+1 < limit) && (start[n] != '\0' || start[n + 1] != '\0')) {
857fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        n += 2;
858fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
859ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick    n += 2;
860ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick    return n;
861fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
862fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
863fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst void *
864fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::getAlbumArt(size_t *length, String8 *mime) const {
865fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
866fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mime->setTo("");
867fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
868bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    Iterator it(
869bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            *this,
870bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) ? "APIC" : "PIC");
871fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
872fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (!it.done()) {
873fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t size;
874fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data = it.getData(&size);
875be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake        if (!data) {
876be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake            return NULL;
877be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake        }
878fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
879bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) {
880fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
881ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            size_t consumed = 1;
882ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick
883ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            // *always* in an 8-bit encoding
884ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            size_t mimeLen = StringSize(&data[consumed], size - consumed, 0x00);
885ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            if (mimeLen > size - consumed) {
886ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                ALOGW("bogus album art size: mime");
887ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                return NULL;
888ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            }
889ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            mime->setTo((const char *)&data[consumed]);
890ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            consumed += mimeLen;
891fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
892fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
893ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            uint8_t picType = data[consumed];
894fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
895fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
896fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
897fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
898fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
899fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
900fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
901ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            consumed++;
902ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            if (consumed >= size) {
903ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                ALOGW("bogus album art size: pic type");
904ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                return NULL;
905ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            }
906ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick
907ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            size_t descLen = StringSize(&data[consumed], size - consumed, encoding);
908ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            consumed += descLen;
909fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
910ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            if (consumed >= size) {
911ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                ALOGW("bogus album art size: description");
912f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen                return NULL;
913f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen            }
914fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
915ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            *length = size - consumed;
916ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick
917ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            return &data[consumed];
918fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
919fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
920fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
921ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            if (size <= 5) {
922ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                return NULL;
923ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            }
924ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick
925fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&data[1], "PNG", 3)) {
926fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/png");
927fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "JPG", 3)) {
928fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/jpeg");
929fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "-->", 3)) {
930fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("text/plain");
931fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else {
932fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return NULL;
933fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
934fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
935fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
936fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[4];
937fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
938fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
939fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
940fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
941fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
942fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
943fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
944ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            size_t descLen = StringSize(&data[5], size - 5, encoding);
945ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            if (descLen > size - 5) {
946ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                return NULL;
947ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            }
948fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
949fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 5 - descLen;
950fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
951fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[5 + descLen];
952fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
953fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
954fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
955fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return NULL;
956fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
957fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
95883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV1(const sp<DataSource> &source) {
95983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    const size_t V1_TAG_SIZE = 128;
96083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
961c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t size;
962c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (source->getSize(&size) != OK || size < (off64_t)V1_TAG_SIZE) {
96383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
96483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
96583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
96683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mData = (uint8_t *)malloc(V1_TAG_SIZE);
96783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (source->readAt(size - V1_TAG_SIZE, mData, V1_TAG_SIZE)
96883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            != (ssize_t)V1_TAG_SIZE) {
96983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
97083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
97183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
97283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
97383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
97483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
97583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (memcmp("TAG", mData, 3)) {
97683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
97783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
97883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
97983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
98083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
98183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
98283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mSize = V1_TAG_SIZE;
98383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mFirstFrameOffset = 3;
98483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
98583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mData[V1_TAG_SIZE - 3] != 0) {
98683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1;
98783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
98883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1_1;
98983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
99083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
99183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    return true;
99283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber}
993fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
994fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}  // namespace android
995