ID3.cpp revision bebd11b5a406bc4243cb7bd55f6849841bf911a7
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
23fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include <media/stagefright/DataSource.h>
24fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include <media/stagefright/MediaDebug.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
33fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::ID3(const sp<DataSource> &source)
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
4183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (!mIsValid) {
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) {
13265997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber        LOGE("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) {
145fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
146fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
147fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
148fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.flags & 0x80) {
14983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        LOGV("removing unsynchronization");
150fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        removeUnsynchronization();
151fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
152fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
153fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mFirstFrameOffset = 0;
154fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 3 && (header.flags & 0x40)) {
155fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // Version 2.3 has an optional extended header.
156fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
157fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mSize < 4) {
15883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
15983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
16083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
161fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
162fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
163fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
164fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t extendedHeaderSize = U32_AT(&mData[0]) + 4;
165fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
166fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize > mSize) {
16783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
16883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
16983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
170fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
171fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
172fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
173fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFirstFrameOffset = extendedHeaderSize;
174fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
175fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint16_t extendedFlags = 0;
176fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize >= 6) {
177fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            extendedFlags = U16_AT(&mData[4]);
178fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
179fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedHeaderSize >= 10) {
180fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                size_t paddingSize = U32_AT(&mData[6]);
181fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
182fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                if (mFirstFrameOffset + paddingSize > mSize) {
18383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    free(mData);
18483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mData = NULL;
18583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
186fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                    return false;
187fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                }
188fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
189fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mSize -= paddingSize;
190fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
191fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
192fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedFlags & 0x8000) {
19383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                LOGV("have crc");
194fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
195fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
196bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 4 && (header.flags & 0x40)) {
197bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // Version 2.4 has an optional extended header, that's different
198bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // from Version 2.3's...
199bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
200bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (mSize < 4) {
201bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
202bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
203bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
204bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
205bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
206bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
207bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        size_t ext_size;
208bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (!ParseSyncsafeInteger(mData, &ext_size)) {
209bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
210bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
211bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
212bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
213bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
214bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
215bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (ext_size < 6 || ext_size > mSize) {
216bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
217bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
218bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
219bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
220bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
221bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
222bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        mFirstFrameOffset = ext_size;
223fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
224fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
225fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
226fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_2;
227bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 3) {
228fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_3;
229bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else {
230bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        CHECK_EQ(header.version_major, 4);
231bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        mVersion = ID3_V2_4;
232fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
233fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
234fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return true;
235fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
236fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
237fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::removeUnsynchronization() {
238fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i + 1 < mSize; ++i) {
239fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mData[i] == 0xff && mData[i + 1] == 0x00) {
240fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memmove(&mData[i + 1], &mData[i + 2], mSize - i - 2);
241fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            --mSize;
242fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
243fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
244fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
245fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
246fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::Iterator(const ID3 &parent, const char *id)
247fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mParent(parent),
248fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mID(NULL),
249fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mOffset(mParent.mFirstFrameOffset),
250fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameData(NULL),
251fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameSize(0) {
252fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (id) {
253fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = strdup(id);
254fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
255fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
256fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
257fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
258fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
259fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::~Iterator() {
260fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mID) {
261fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        free(mID);
262fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = NULL;
263fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
264fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
265fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
266fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::Iterator::done() const {
267fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData == NULL;
268fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
269fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
270fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::next() {
271fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
272fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
273fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
274fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
275fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mOffset += mFrameSize;
276fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
277fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
278fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
279fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
280fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::getID(String8 *id) const {
281fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
282fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
283fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
284fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
285fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
286fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
287fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
288fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 3);
289bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
290fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 4);
29183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
29283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
29383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
29483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        switch (mOffset) {
29583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 3:
29683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TT2");
29783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
29883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 33:
29983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TP1");
30083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
30183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 63:
30283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TAL");
30383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
30483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 93:
30583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TYE");
30683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
30783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 97:
30883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("COM");
30983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
31083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 126:
31183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TRK");
31283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
31383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 127:
31483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TCO");
31583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
31683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            default:
31783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                CHECK(!"should not be here.");
31883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
31983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
320fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
321fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
322fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
323fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic void convertISO8859ToString8(
324fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data, size_t size,
325fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        String8 *s) {
326fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t utf8len = 0;
327fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i < size; ++i) {
3284c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        if (data[i] == '\0') {
329632a7dfdab89ffa79846ad37718d0582fd36affeKenny Root            size = i;
3304c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber            break;
3314c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        } else if (data[i] < 0x80) {
332fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            ++utf8len;
333fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
334fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            utf8len += 2;
335fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
336fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
337fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
338fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (utf8len == size) {
339fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // Only ASCII characters present.
340fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
341fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        s->setTo((const char *)data, size);
342fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
343fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
344fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
345fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    char *tmp = new char[utf8len];
346fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    char *ptr = tmp;
347fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i < size; ++i) {
3484c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        if (data[i] == '\0') {
3494c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber            break;
3504c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        } else if (data[i] < 0x80) {
351fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i];
352fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else if (data[i] < 0xc0) {
353fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = 0xc2;
354fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i];
355fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
356fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = 0xc3;
357fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i] - 64;
358fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
359fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
360fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
361fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    s->setTo(tmp, utf8len);
362fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
363fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    delete[] tmp;
364fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    tmp = NULL;
365fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
366fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
367fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::getString(String8 *id) const {
368fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
369fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
370fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
371fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
372fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
373fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
37483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1) {
37583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        if (mOffset == 126 || mOffset == 127) {
37683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            // Special treatment for the track number and genre.
37783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            char tmp[16];
37883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            sprintf(tmp, "%d", (int)*mFrameData);
37983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
38083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            id->setTo(tmp);
38183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            return;
38283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
38383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
3844c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        convertISO8859ToString8(mFrameData, mFrameSize, id);
38583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return;
38683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
38783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
388fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = mFrameSize - getHeaderLength() - 1;
389fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
390fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (*mFrameData == 0x00) {
391fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // ISO 8859-1
392fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        convertISO8859ToString8(mFrameData + 1, n, id);
393bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (*mFrameData == 0x03) {
394bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // UTF-8
395bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        id->setTo((const char *)(mFrameData + 1), n);
396bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (*mFrameData == 0x02) {
397bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // UTF-16 BE, no byte order mark.
398bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // API wants number of characters, not number of bytes...
399bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        int len = n / 2;
400bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        const char16_t *framedata = (const char16_t *) (mFrameData + 1);
401bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        char16_t *framedatacopy = NULL;
402bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#if BYTE_ORDER == LITTLE_ENDIAN
403bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        framedatacopy = new char16_t[len];
404bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        for (int i = 0; i < len; i++) {
405bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            framedatacopy[i] = bswap_16(framedata[i]);
406bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
407bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        framedata = framedatacopy;
408bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#endif
409bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        id->setTo(framedata, len);
410bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (framedatacopy != NULL) {
411bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            delete[] framedatacopy;
412bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
413fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
414fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // UCS-2
41508e7eb983fcb9860a574e964ff905f75aab88d2fAndreas Huber        // API wants number of characters, not number of bytes...
4165a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        int len = n / 2;
4175a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        const char16_t *framedata = (const char16_t *) (mFrameData + 1);
4185a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        char16_t *framedatacopy = NULL;
4195a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfffe) {
4205a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            // endianness marker doesn't match host endianness, convert
4215a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedatacopy = new char16_t[len];
4225a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            for (int i = 0; i < len; i++) {
423569e7f1b1444194d1aca5a0b23de154565ba12daMarco Nelissen                framedatacopy[i] = bswap_16(framedata[i]);
4245a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            }
4255a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata = framedatacopy;
4265a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
4275a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        // If the string starts with an endianness marker, skip it
4285a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfeff) {
4295a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata++;
4305a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            len--;
4315a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
4325a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        id->setTo(framedata, len);
4335a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (framedatacopy != NULL) {
4345a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            delete[] framedatacopy;
4355a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
436fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
437fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
438fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
439fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst uint8_t *ID3::Iterator::getData(size_t *length) const {
440fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
441fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
442fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
443fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
444fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
445fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
446fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = mFrameSize - getHeaderLength();
447fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
448fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData;
449fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
450fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
451fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubersize_t ID3::Iterator::getHeaderLength() const {
452fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
453fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 6;
454bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
455fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 10;
45683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
45783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
45883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return 0;
459fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
460fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
461fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
462fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::findFrame() {
463fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (;;) {
464fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameData = NULL;
465fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameSize = 0;
466fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
467fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mParent.mVersion == ID3_V2_2) {
468fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 6 > mParent.mSize) {
469fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
470fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
471fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
472fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0", 3)) {
473fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
474fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
475fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
476fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize =
477fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                (mParent.mData[mOffset + 3] << 16)
478fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | (mParent.mData[mOffset + 4] << 8)
479fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | mParent.mData[mOffset + 5];
480fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
481fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize += 6;
482fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
483fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
484fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                LOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
485fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                     mOffset, mFrameSize, mParent.mSize - mOffset - 6);
486fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
487fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
488fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
489fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 6];
490fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
491fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
492fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
493fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
494fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
495fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[4];
496fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 3);
497fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[3] = '\0';
498fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
499fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
500fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
501fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
502bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        } else if (mParent.mVersion == ID3_V2_3
503bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || mParent.mVersion == ID3_V2_4) {
504fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 10 > mParent.mSize) {
505fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
506fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
507fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
508fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0\0", 4)) {
509fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
510fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
511fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
512bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            size_t baseSize;
513bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            if (mParent.mVersion == ID3_V2_4) {
514bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                if (!ParseSyncsafeInteger(
515bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                            &mParent.mData[mOffset + 4], &baseSize)) {
516bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                    return;
517bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                }
518bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            } else {
519bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                baseSize = U32_AT(&mParent.mData[mOffset + 4]);
520bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
521bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
522bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mFrameSize = 10 + baseSize;
523fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
524fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
525fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                LOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
526fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                     mOffset, mFrameSize, mParent.mSize - mOffset - 10);
527fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
528fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
529fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
530bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]);
531bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
532bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000e))
533bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) {
534bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                // Compression, Encryption or per-Frame unsynchronization
535bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                // are not supported at this time.
536bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
537bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                LOGV("Skipping unsupported frame (compression, encryption "
538bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                     "or per-frame unsynchronization flagged");
539bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
540bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                mOffset += mFrameSize;
541bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                continue;
542bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
543bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
544fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 10];
545fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
546fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
547fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
548fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
549fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
550fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[5];
551fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 4);
552fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[4] = '\0';
553fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
554fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
555fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
556fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
55783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        } else {
55883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
55983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
56083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (mOffset >= mParent.mSize) {
56183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                return;
56283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
56383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
56483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mFrameData = &mParent.mData[mOffset];
56583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
56683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            switch (mOffset) {
56783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 3:
56883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 33:
56983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 63:
57083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 30;
57183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
57283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 93:
57383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 4;
57483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
57583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 97:
57683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    if (mParent.mVersion == ID3_V1) {
57783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 30;
57883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    } else {
57983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 29;
58083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    }
58183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
58283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 126:
58383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
58483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
58583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 127:
58683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
58783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
58883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                default:
58983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    CHECK(!"Should not be here, invalid offset.");
59083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
59183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
59283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
59383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (!mID) {
59483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
59583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
59683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
59783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            String8 id;
59883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            getID(&id);
59983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
60083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (id == mID) {
60183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
60283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
603fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
604fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
605fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mOffset += mFrameSize;
606fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
607fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
608fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
609fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic size_t StringSize(const uint8_t *start, uint8_t encoding) {
610bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    if (encoding == 0x00 || encoding == 0x03) {
611bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // ISO 8859-1 or UTF-8
612fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return strlen((const char *)start) + 1;
613fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
614fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
615fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // UCS-2
616fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = 0;
617fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (start[n] != '\0' || start[n + 1] != '\0') {
618fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        n += 2;
619fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
620fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
621fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return n;
622fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
623fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
624fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst void *
625fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::getAlbumArt(size_t *length, String8 *mime) const {
626fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
627fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mime->setTo("");
628fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
629bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    Iterator it(
630bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            *this,
631bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) ? "APIC" : "PIC");
632fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
633fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (!it.done()) {
634fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t size;
635fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data = it.getData(&size);
636fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
637bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) {
638fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
639fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mime->setTo((const char *)&data[1]);
640fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t mimeLen = strlen((const char *)&data[1]) + 1;
641fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
642fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[1 + mimeLen];
643fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
644fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
645fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
646fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
647fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
648fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
649fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
650fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
651fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[2 + mimeLen], encoding);
652fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
653fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 2 - mimeLen - descLen;
654fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
655fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[2 + mimeLen + descLen];
656fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
657fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
658fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
659fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&data[1], "PNG", 3)) {
660fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/png");
661fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "JPG", 3)) {
662fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/jpeg");
663fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "-->", 3)) {
664fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("text/plain");
665fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else {
666fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return NULL;
667fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
668fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
669fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
670fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[4];
671fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
672fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
673fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
674fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
675fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
676fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
677fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
678fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[5], encoding);
679fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
680fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 5 - descLen;
681fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
682fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[5 + descLen];
683fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
684fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
685fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
686fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return NULL;
687fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
688fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
68983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV1(const sp<DataSource> &source) {
69083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    const size_t V1_TAG_SIZE = 128;
69183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
69283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    off_t size;
69383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (source->getSize(&size) != OK || size < (off_t)V1_TAG_SIZE) {
69483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
69583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
69683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
69783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mData = (uint8_t *)malloc(V1_TAG_SIZE);
69883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (source->readAt(size - V1_TAG_SIZE, mData, V1_TAG_SIZE)
69983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            != (ssize_t)V1_TAG_SIZE) {
70083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
70183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
70283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
70383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
70483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
70583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
70683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (memcmp("TAG", mData, 3)) {
70783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
70883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
70983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
71083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
71183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
71283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
71383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mSize = V1_TAG_SIZE;
71483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mFirstFrameOffset = 3;
71583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
71683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mData[V1_TAG_SIZE - 3] != 0) {
71783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1;
71883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
71983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1_1;
72083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
72183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
72283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    return true;
72383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber}
724fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
725fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}  // namespace android
726