ID3.cpp revision 47c1a5f7c13d82aa8834fd4543bd1d713b97808e
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
3347c1a5f7c13d82aa8834fd4543bd1d713b97808eDylan PowersID3::ID3(const sp<DataSource> &source, bool ignoreV1)
34fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mIsValid(false),
35fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mData(NULL),
36fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mSize(0),
37fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFirstFrameOffset(0),
38fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mVersion(ID3_UNKNOWN) {
3983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mIsValid = parseV2(source);
4083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
4147c1a5f7c13d82aa8834fd4543bd1d713b97808eDylan Powers    if (!mIsValid && !ignoreV1) {
4283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mIsValid = parseV1(source);
4383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
44fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
45fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
46fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::~ID3() {
47fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mData) {
48fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        free(mData);
49fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mData = NULL;
50fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
51fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
52fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
53fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::isValid() const {
54fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mIsValid;
55fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
56fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
57fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Version ID3::version() const {
58fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mVersion;
59fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
60fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
61bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber// static
62bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huberbool ID3::ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x) {
63bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    *x = 0;
64bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    for (int32_t i = 0; i < 4; ++i) {
65bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (encoded[i] & 0x80) {
66bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
67bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
68bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
69bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        *x = ((*x) << 7) | encoded[i];
70bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    }
71bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
72bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    return true;
73bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber}
74bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
7583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV2(const sp<DataSource> &source) {
76bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huberstruct id3_header {
77bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    char id[3];
78bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t version_major;
79bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t version_minor;
80bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t flags;
81bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t enc_size[4];
82fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    };
83fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
84fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id3_header header;
85fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (source->readAt(
86fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                0, &header, sizeof(header)) != (ssize_t)sizeof(header)) {
87fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
88fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
89fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
90fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (memcmp(header.id, "ID3", 3)) {
91fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
92fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
93fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
94fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 0xff || header.version_minor == 0xff) {
95fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
96fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
98fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
99fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x3f) {
100fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // We only support the 2 high bits, if any of the lower bits are
101fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // set, we cannot guarantee to understand the tag format.
102fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
103fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
104fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
105fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x40) {
106fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // No compression scheme has been decided yet, ignore the
107fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // tag if compression is indicated.
108fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
109fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
110fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
111fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else if (header.version_major == 3) {
112fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x1f) {
113fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // We only support the 3 high bits, if any of the lower bits are
114fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // set, we cannot guarantee to understand the tag format.
115fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
116fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
117bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 4) {
118bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (header.flags & 0x0f) {
119bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            // The lower 4 bits are undefined in this spec.
120bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
121bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
122fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
123fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
124fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
125fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
126bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    size_t size;
127bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    if (!ParseSyncsafeInteger(header.enc_size, &size)) {
128bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        return false;
129fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
130fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
13165997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber    if (size > kMaxMetadataSize) {
13229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("skipping huge ID3 metadata of size %d", size);
13365997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber        return false;
13465997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber    }
13565997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber
136fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mData = (uint8_t *)malloc(size);
137fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
138fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mData == NULL) {
139fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
140fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
141fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
142fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mSize = size;
143fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
144fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (source->readAt(sizeof(header), mData, mSize) != (ssize_t)mSize) {
145ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        free(mData);
146ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        mData = NULL;
147ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
148fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
149fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
150fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
151ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    if (header.version_major == 4) {
152428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        void *copy = malloc(size);
153428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        memcpy(copy, mData, size);
154428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
155428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
156428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (!success) {
157428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            memcpy(mData, copy, size);
158428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            mSize = size;
159428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
160428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            success = removeUnsynchronizationV2_4(true /* iTunesHack */);
161428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
162428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            if (success) {
1633856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
164428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            }
165428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        }
166428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
167428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        free(copy);
168428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        copy = NULL;
169428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
170428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (!success) {
171ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            free(mData);
172ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData = NULL;
173ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
174ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
175ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
176ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    } else if (header.flags & 0x80) {
1773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("removing unsynchronization");
178ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
179fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        removeUnsynchronization();
180fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
181fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
182fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mFirstFrameOffset = 0;
183fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 3 && (header.flags & 0x40)) {
184fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // Version 2.3 has an optional extended header.
185fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
186fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mSize < 4) {
18783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
18883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
18983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
190fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
191fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
192fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
193fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t extendedHeaderSize = U32_AT(&mData[0]) + 4;
194fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
195fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize > mSize) {
19683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
19783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
19883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
199fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
200fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
201fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
202fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFirstFrameOffset = extendedHeaderSize;
203fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
204fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint16_t extendedFlags = 0;
205fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize >= 6) {
206fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            extendedFlags = U16_AT(&mData[4]);
207fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
208fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedHeaderSize >= 10) {
209fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                size_t paddingSize = U32_AT(&mData[6]);
210fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
211fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                if (mFirstFrameOffset + paddingSize > mSize) {
21283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    free(mData);
21383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mData = NULL;
21483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
215fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                    return false;
216fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                }
217fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
218fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mSize -= paddingSize;
219fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
220fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
221fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedFlags & 0x8000) {
2223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("have crc");
223fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
224fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
225bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 4 && (header.flags & 0x40)) {
226bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // Version 2.4 has an optional extended header, that's different
227bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // from Version 2.3's...
228bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
229bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (mSize < 4) {
230bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
231bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
232bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
233bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
234bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
235bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
236bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        size_t ext_size;
237bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (!ParseSyncsafeInteger(mData, &ext_size)) {
238bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
239bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
240bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
241bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
242bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
243bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
244bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (ext_size < 6 || ext_size > mSize) {
245bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
246bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
247bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
248bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
249bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
250bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
251bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        mFirstFrameOffset = ext_size;
252fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
253fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
254fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
255fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_2;
256bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 3) {
257fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_3;
258bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else {
259bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        CHECK_EQ(header.version_major, 4);
260bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        mVersion = ID3_V2_4;
261fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
262fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
263fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return true;
264fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
265fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
266fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::removeUnsynchronization() {
267fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i + 1 < mSize; ++i) {
268fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mData[i] == 0xff && mData[i + 1] == 0x00) {
269fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memmove(&mData[i + 1], &mData[i + 2], mSize - i - 2);
270fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            --mSize;
271fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
272fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
273fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
274fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
275ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huberstatic void WriteSyncsafeInteger(uint8_t *dst, size_t x) {
276ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    for (size_t i = 0; i < 4; ++i) {
277ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        dst[3 - i] = (x & 0x7f);
278ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        x >>= 7;
279ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    }
280ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber}
281ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
282428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huberbool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
283ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    size_t oldSize = mSize;
284ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
285ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    size_t offset = 0;
286ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    while (offset + 10 <= mSize) {
287ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
288ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            break;
289ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
290ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
291ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        size_t dataSize;
292428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (iTunesHack) {
293428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            dataSize = U32_AT(&mData[offset + 4]);
294428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        } else if (!ParseSyncsafeInteger(&mData[offset + 4], &dataSize)) {
295ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
296ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
297ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
298ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (offset + dataSize + 10 > mSize) {
299ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
300ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
301ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
302ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        uint16_t flags = U16_AT(&mData[offset + 8]);
303ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        uint16_t prevFlags = flags;
304ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
305ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (flags & 1) {
306ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            // Strip data length indicator
307ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
308ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            memmove(&mData[offset + 10], &mData[offset + 14], mSize - offset - 14);
309ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mSize -= 4;
310ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            dataSize -= 4;
311ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
312ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            flags &= ~1;
313ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
314ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
315ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (flags & 2) {
316ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            // Unsynchronization added.
317ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
318ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            for (size_t i = 0; i + 1 < dataSize; ++i) {
319ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                if (mData[offset + 10 + i] == 0xff
320ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                        && mData[offset + 11 + i] == 0x00) {
321ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                    memmove(&mData[offset + 11 + i], &mData[offset + 12 + i],
322ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                            mSize - offset - 12 - i);
323ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                    --mSize;
324ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                    --dataSize;
325ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                }
326ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            }
327ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
328ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            flags &= ~2;
329ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
330ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
331428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (flags != prevFlags || iTunesHack) {
332ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            WriteSyncsafeInteger(&mData[offset + 4], dataSize);
333ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData[offset + 8] = flags >> 8;
334ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData[offset + 9] = flags & 0xff;
335ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
336ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
337ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        offset += 10 + dataSize;
338ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    }
339ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
340ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    memset(&mData[mSize], 0, oldSize - mSize);
341ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
342ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    return true;
343ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber}
344ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
345fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::Iterator(const ID3 &parent, const char *id)
346fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mParent(parent),
347fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mID(NULL),
348fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mOffset(mParent.mFirstFrameOffset),
349fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameData(NULL),
350fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameSize(0) {
351fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (id) {
352fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = strdup(id);
353fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
354fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
355fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
356fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
357fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
358fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::~Iterator() {
359fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mID) {
360fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        free(mID);
361fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = NULL;
362fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
363fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
364fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
365fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::Iterator::done() const {
366fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData == NULL;
367fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
368fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
369fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::next() {
370fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
371fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
372fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
373fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
374fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mOffset += mFrameSize;
375fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
376fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
377fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
378fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
379fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::getID(String8 *id) const {
380fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
381fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
382fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
383fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
384fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
385fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
386fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
387fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 3);
388bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
389fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 4);
39083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
39183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
39283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
39383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        switch (mOffset) {
39483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 3:
39583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TT2");
39683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
39783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 33:
39883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TP1");
39983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
40083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 63:
40183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TAL");
40283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
40383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 93:
40483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TYE");
40583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
40683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 97:
40783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("COM");
40883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
40983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 126:
41083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TRK");
41183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
41283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 127:
41383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TCO");
41483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
41583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            default:
41683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                CHECK(!"should not be here.");
41783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
41883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
419fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
420fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
421fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
422fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic void convertISO8859ToString8(
423fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data, size_t size,
424fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        String8 *s) {
425fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t utf8len = 0;
426fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i < size; ++i) {
4274c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        if (data[i] == '\0') {
428632a7dfdab89ffa79846ad37718d0582fd36affeKenny Root            size = i;
4294c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber            break;
4304c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        } else if (data[i] < 0x80) {
431fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            ++utf8len;
432fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
433fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            utf8len += 2;
434fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
435fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
436fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
437fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (utf8len == size) {
438fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // Only ASCII characters present.
439fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
440fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        s->setTo((const char *)data, size);
441fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
442fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
443fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
444fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    char *tmp = new char[utf8len];
445fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    char *ptr = tmp;
446fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i < size; ++i) {
4474c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        if (data[i] == '\0') {
4484c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber            break;
4494c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        } else if (data[i] < 0x80) {
450fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i];
451fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else if (data[i] < 0xc0) {
452fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = 0xc2;
453fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i];
454fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
455fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = 0xc3;
456fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i] - 64;
457fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
458fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
459fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
460fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    s->setTo(tmp, utf8len);
461fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
462fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    delete[] tmp;
463fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    tmp = NULL;
464fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
465fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
466b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// the 2nd argument is used to get the data following the \0 in a comment field
467b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getString(String8 *id, String8 *comment) const {
468b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    getstring(id, false);
469b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (comment != NULL) {
470b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        getstring(comment, true);
471b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    }
472b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen}
473b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen
474b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// comment fields (COM/COMM) contain an initial short descriptor, followed by \0,
475b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// followed by more data. The data following the \0 can be retrieved by setting
476b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// "otherdata" to true.
477b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getstring(String8 *id, bool otherdata) const {
478fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
479fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
480b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    const uint8_t *frameData = mFrameData;
481b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (frameData == NULL) {
482fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
483fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
484fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
485b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    uint8_t encoding = *frameData;
486b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen
48783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1) {
48883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        if (mOffset == 126 || mOffset == 127) {
48983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            // Special treatment for the track number and genre.
49083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            char tmp[16];
491b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen            sprintf(tmp, "%d", (int)*frameData);
49283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
49383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            id->setTo(tmp);
49483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            return;
49583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
49683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
497b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        convertISO8859ToString8(frameData, mFrameSize, id);
49883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return;
49983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
50083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
501fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = mFrameSize - getHeaderLength() - 1;
502b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (otherdata) {
503b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        // skip past the encoding, language, and the 0 separator
504b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        frameData += 4;
505b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        int32_t i = n - 4;
506b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        while(--i >= 0 && *++frameData != 0) ;
507b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        int skipped = (frameData - mFrameData);
508b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        if (skipped >= n) {
509b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen            return;
510b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        }
511b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        n -= skipped;
512b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    }
513fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
514b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (encoding == 0x00) {
515fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // ISO 8859-1
516b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        convertISO8859ToString8(frameData + 1, n, id);
517b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    } else if (encoding == 0x03) {
518bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // UTF-8
519b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        id->setTo((const char *)(frameData + 1), n);
520b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    } else if (encoding == 0x02) {
521bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // UTF-16 BE, no byte order mark.
522bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // API wants number of characters, not number of bytes...
523bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        int len = n / 2;
524b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        const char16_t *framedata = (const char16_t *) (frameData + 1);
525bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        char16_t *framedatacopy = NULL;
526bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#if BYTE_ORDER == LITTLE_ENDIAN
527bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        framedatacopy = new char16_t[len];
528bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        for (int i = 0; i < len; i++) {
529bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            framedatacopy[i] = bswap_16(framedata[i]);
530bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
531bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        framedata = framedatacopy;
532bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#endif
533bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        id->setTo(framedata, len);
534bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (framedatacopy != NULL) {
535bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            delete[] framedatacopy;
536bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
537fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
538fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // UCS-2
53908e7eb983fcb9860a574e964ff905f75aab88d2fAndreas Huber        // API wants number of characters, not number of bytes...
5405a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        int len = n / 2;
541b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        const char16_t *framedata = (const char16_t *) (frameData + 1);
5425a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        char16_t *framedatacopy = NULL;
5435a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfffe) {
5445a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            // endianness marker doesn't match host endianness, convert
5455a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedatacopy = new char16_t[len];
5465a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            for (int i = 0; i < len; i++) {
547569e7f1b1444194d1aca5a0b23de154565ba12daMarco Nelissen                framedatacopy[i] = bswap_16(framedata[i]);
5485a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            }
5495a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata = framedatacopy;
5505a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
5515a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        // If the string starts with an endianness marker, skip it
5525a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfeff) {
5535a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata++;
5545a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            len--;
5555a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
5565a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        id->setTo(framedata, len);
5575a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (framedatacopy != NULL) {
5585a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            delete[] framedatacopy;
5595a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
560fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
561fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
562fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
563fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst uint8_t *ID3::Iterator::getData(size_t *length) const {
564fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
565fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
566fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
567fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
568fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
569fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
570fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = mFrameSize - getHeaderLength();
571fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
572fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData;
573fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
574fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
575fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubersize_t ID3::Iterator::getHeaderLength() const {
576fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
577fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 6;
578bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
579fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 10;
58083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
58183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
58283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return 0;
583fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
584fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
585fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
586fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::findFrame() {
587fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (;;) {
588fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameData = NULL;
589fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameSize = 0;
590fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
591fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mParent.mVersion == ID3_V2_2) {
592fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 6 > mParent.mSize) {
593fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
594fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
595fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
596fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0", 3)) {
597fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
598fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
599fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
600fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize =
601fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                (mParent.mData[mOffset + 3] << 16)
602fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | (mParent.mData[mOffset + 4] << 8)
603fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | mParent.mData[mOffset + 5];
604fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
605fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize += 6;
606fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
607fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
6083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
609fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                     mOffset, mFrameSize, mParent.mSize - mOffset - 6);
610fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
611fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
612fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
613fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 6];
614fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
615fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
616fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
617fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
618fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
619fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[4];
620fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 3);
621fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[3] = '\0';
622fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
623fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
624fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
625fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
626bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        } else if (mParent.mVersion == ID3_V2_3
627bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || mParent.mVersion == ID3_V2_4) {
628fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 10 > mParent.mSize) {
629fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
630fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
631fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
632fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0\0", 4)) {
633fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
634fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
635fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
636bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            size_t baseSize;
637bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            if (mParent.mVersion == ID3_V2_4) {
638bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                if (!ParseSyncsafeInteger(
639bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                            &mParent.mData[mOffset + 4], &baseSize)) {
640bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                    return;
641bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                }
642bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            } else {
643bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                baseSize = U32_AT(&mParent.mData[mOffset + 4]);
644bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
645bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
646bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mFrameSize = 10 + baseSize;
647fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
648fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
6493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
650fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                     mOffset, mFrameSize, mParent.mSize - mOffset - 10);
651fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
652fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
653fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
654bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]);
655bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
656ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000c))
657bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) {
658ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // Compression or encryption are not supported at this time.
659ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // Per-frame unsynchronization and data-length indicator
660ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // have already been taken care of.
661bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
6623856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("Skipping unsupported frame (compression, encryption "
663bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                     "or per-frame unsynchronization flagged");
664bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
665bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                mOffset += mFrameSize;
666bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                continue;
667bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
668bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
669fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 10];
670fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
671fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
672fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
673fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
674fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
675fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[5];
676fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 4);
677fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[4] = '\0';
678fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
679fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
680fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
681fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
68283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        } else {
68383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
68483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
68583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (mOffset >= mParent.mSize) {
68683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                return;
68783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
68883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
68983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mFrameData = &mParent.mData[mOffset];
69083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
69183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            switch (mOffset) {
69283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 3:
69383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 33:
69483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 63:
69583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 30;
69683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
69783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 93:
69883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 4;
69983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
70083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 97:
70183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    if (mParent.mVersion == ID3_V1) {
70283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 30;
70383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    } else {
70483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 29;
70583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    }
70683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
70783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 126:
70883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
70983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
71083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 127:
71183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
71283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
71383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                default:
71483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    CHECK(!"Should not be here, invalid offset.");
71583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
71683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
71783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
71883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (!mID) {
71983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
72083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
72183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
72283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            String8 id;
72383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            getID(&id);
72483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
72583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (id == mID) {
72683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
72783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
728fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
729fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
730fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mOffset += mFrameSize;
731fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
732fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
733fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
734fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic size_t StringSize(const uint8_t *start, uint8_t encoding) {
735bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    if (encoding == 0x00 || encoding == 0x03) {
736bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // ISO 8859-1 or UTF-8
737fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return strlen((const char *)start) + 1;
738fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
739fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
740fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // UCS-2
741fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = 0;
742fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (start[n] != '\0' || start[n + 1] != '\0') {
743fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        n += 2;
744fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
745fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
746be5016bac5c1b422d850e299d3cb11fecf0ac19dJesper Tragardh    // Add size of null termination.
747be5016bac5c1b422d850e299d3cb11fecf0ac19dJesper Tragardh    return n + 2;
748fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
749fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
750fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst void *
751fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::getAlbumArt(size_t *length, String8 *mime) const {
752fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
753fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mime->setTo("");
754fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
755bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    Iterator it(
756bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            *this,
757bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) ? "APIC" : "PIC");
758fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
759fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (!it.done()) {
760fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t size;
761fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data = it.getData(&size);
762fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
763bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) {
764fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
765fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mime->setTo((const char *)&data[1]);
766fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t mimeLen = strlen((const char *)&data[1]) + 1;
767fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
768fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[1 + mimeLen];
769fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
770fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
771fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
772fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
773fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
774fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
775fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
776fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
777fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[2 + mimeLen], encoding);
778fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
779fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 2 - mimeLen - descLen;
780fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
781fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[2 + mimeLen + descLen];
782fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
783fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
784fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
785fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&data[1], "PNG", 3)) {
786fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/png");
787fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "JPG", 3)) {
788fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/jpeg");
789fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "-->", 3)) {
790fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("text/plain");
791fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else {
792fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return NULL;
793fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
794fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
795fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
796fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[4];
797fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
798fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
799fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
800fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
801fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
802fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
803fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
804fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[5], encoding);
805fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
806fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 5 - descLen;
807fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
808fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[5 + descLen];
809fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
810fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
811fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
812fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return NULL;
813fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
814fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
81583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV1(const sp<DataSource> &source) {
81683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    const size_t V1_TAG_SIZE = 128;
81783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
818c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t size;
819c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (source->getSize(&size) != OK || size < (off64_t)V1_TAG_SIZE) {
82083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
82183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
82283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
82383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mData = (uint8_t *)malloc(V1_TAG_SIZE);
82483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (source->readAt(size - V1_TAG_SIZE, mData, V1_TAG_SIZE)
82583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            != (ssize_t)V1_TAG_SIZE) {
82683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
82783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
82883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
82983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
83083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
83183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
83283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (memcmp("TAG", mData, 3)) {
83383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
83483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
83583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
83683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
83783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
83883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
83983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mSize = V1_TAG_SIZE;
84083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mFirstFrameOffset = 3;
84183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
84283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mData[V1_TAG_SIZE - 3] != 0) {
84383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1;
84483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
84583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1_1;
84683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
84783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
84883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    return true;
84983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber}
850fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
851fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}  // namespace android
852