ID3.cpp revision 65997f022fa3f557ba864ecc99a1aa33df54c2db
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
6183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV2(const sp<DataSource> &source) {
62fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    struct id3_header {
63fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        char id[3];
64fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint8_t version_major;
65fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint8_t version_minor;
66fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint8_t flags;
67fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint8_t enc_size[4];
68fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    };
69fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
70fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id3_header header;
71fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (source->readAt(
72fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                0, &header, sizeof(header)) != (ssize_t)sizeof(header)) {
73fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
74fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
75fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
76fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (memcmp(header.id, "ID3", 3)) {
77fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
78fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
79fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
80fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 0xff || header.version_minor == 0xff) {
81fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
82fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
83fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
84fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
85fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x3f) {
86fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // We only support the 2 high bits, if any of the lower bits are
87fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // set, we cannot guarantee to understand the tag format.
88fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
89fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
90fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
91fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x40) {
92fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // No compression scheme has been decided yet, ignore the
93fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // tag if compression is indicated.
94fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
95fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
96fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else if (header.version_major == 3) {
98fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x1f) {
99fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // We only support the 3 high bits, if any of the lower bits are
100fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // set, we cannot guarantee to understand the tag format.
101fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
102fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
103fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
104fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
105fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
106fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
107fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t size = 0;
108fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (int32_t i = 0; i < 4; ++i) {
109fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.enc_size[i] & 0x80) {
110fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
111fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
112fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
113fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size = (size << 7) | header.enc_size[i];
114fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
115fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
11665997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber    if (size > kMaxMetadataSize) {
11765997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber        LOGE("skipping huge ID3 metadata of size %d", size);
11865997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber        return false;
11965997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber    }
12065997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber
121fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mData = (uint8_t *)malloc(size);
122fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
123fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mData == NULL) {
124fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
125fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
126fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
127fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mSize = size;
128fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
129fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (source->readAt(sizeof(header), mData, mSize) != (ssize_t)mSize) {
130fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
131fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
132fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
133fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.flags & 0x80) {
13483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        LOGV("removing unsynchronization");
135fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        removeUnsynchronization();
136fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
137fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
138fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mFirstFrameOffset = 0;
139fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 3 && (header.flags & 0x40)) {
140fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // Version 2.3 has an optional extended header.
141fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
142fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mSize < 4) {
14383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
14483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
14583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
146fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
147fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
148fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
149fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t extendedHeaderSize = U32_AT(&mData[0]) + 4;
150fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
151fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize > mSize) {
15283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
15383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
15483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
155fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
156fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
157fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
158fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFirstFrameOffset = extendedHeaderSize;
159fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
160fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint16_t extendedFlags = 0;
161fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize >= 6) {
162fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            extendedFlags = U16_AT(&mData[4]);
163fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
164fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedHeaderSize >= 10) {
165fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                size_t paddingSize = U32_AT(&mData[6]);
166fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
167fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                if (mFirstFrameOffset + paddingSize > mSize) {
16883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    free(mData);
16983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mData = NULL;
17083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
171fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                    return false;
172fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                }
173fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
174fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mSize -= paddingSize;
175fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
176fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
177fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedFlags & 0x8000) {
17883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                LOGV("have crc");
179fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
180fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
181fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
182fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
183fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
184fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_2;
185fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
186fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        CHECK_EQ(header.version_major, 3);
187fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_3;
188fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
189fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
190fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return true;
191fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
192fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
193fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::removeUnsynchronization() {
194fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i + 1 < mSize; ++i) {
195fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mData[i] == 0xff && mData[i + 1] == 0x00) {
196fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memmove(&mData[i + 1], &mData[i + 2], mSize - i - 2);
197fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            --mSize;
198fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
199fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
200fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
201fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
202fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::Iterator(const ID3 &parent, const char *id)
203fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mParent(parent),
204fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mID(NULL),
205fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mOffset(mParent.mFirstFrameOffset),
206fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameData(NULL),
207fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameSize(0) {
208fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (id) {
209fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = strdup(id);
210fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
211fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
212fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
213fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
214fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
215fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::~Iterator() {
216fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mID) {
217fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        free(mID);
218fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = NULL;
219fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
220fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
221fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
222fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::Iterator::done() const {
223fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData == NULL;
224fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
225fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
226fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::next() {
227fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
228fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
229fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
230fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
231fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mOffset += mFrameSize;
232fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
233fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
234fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
235fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
236fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::getID(String8 *id) const {
237fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
238fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
239fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
240fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
241fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
242fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
243fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
244fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 3);
24583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else if (mParent.mVersion == ID3_V2_3) {
246fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 4);
24783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
24883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
24983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
25083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        switch (mOffset) {
25183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 3:
25283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TT2");
25383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
25483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 33:
25583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TP1");
25683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
25783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 63:
25883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TAL");
25983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
26083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 93:
26183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TYE");
26283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
26383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 97:
26483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("COM");
26583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
26683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 126:
26783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TRK");
26883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
26983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 127:
27083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TCO");
27183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
27283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            default:
27383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                CHECK(!"should not be here.");
27483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
27583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
276fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
277fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
278fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
279fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic void convertISO8859ToString8(
280fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data, size_t size,
281fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        String8 *s) {
282fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t utf8len = 0;
283fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i < size; ++i) {
2844c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        if (data[i] == '\0') {
285632a7dfdab89ffa79846ad37718d0582fd36affeKenny Root            size = i;
2864c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber            break;
2874c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        } else if (data[i] < 0x80) {
288fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            ++utf8len;
289fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
290fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            utf8len += 2;
291fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
292fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
293fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
294fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (utf8len == size) {
295fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // Only ASCII characters present.
296fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
297fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        s->setTo((const char *)data, size);
298fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
299fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
300fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
301fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    char *tmp = new char[utf8len];
302fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    char *ptr = tmp;
303fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i < size; ++i) {
3044c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        if (data[i] == '\0') {
3054c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber            break;
3064c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        } else if (data[i] < 0x80) {
307fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i];
308fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else if (data[i] < 0xc0) {
309fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = 0xc2;
310fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i];
311fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
312fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = 0xc3;
313fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i] - 64;
314fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
315fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
316fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
317fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    s->setTo(tmp, utf8len);
318fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
319fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    delete[] tmp;
320fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    tmp = NULL;
321fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
322fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
323fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::getString(String8 *id) const {
324fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
325fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
326fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
327fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
328fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
329fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
33083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1) {
33183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        if (mOffset == 126 || mOffset == 127) {
33283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            // Special treatment for the track number and genre.
33383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            char tmp[16];
33483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            sprintf(tmp, "%d", (int)*mFrameData);
33583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
33683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            id->setTo(tmp);
33783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            return;
33883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
33983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
3404c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber        convertISO8859ToString8(mFrameData, mFrameSize, id);
34183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return;
34283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
34383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
344fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = mFrameSize - getHeaderLength() - 1;
345fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
346fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (*mFrameData == 0x00) {
347fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // ISO 8859-1
348fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        convertISO8859ToString8(mFrameData + 1, n, id);
349fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
350fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // UCS-2
35108e7eb983fcb9860a574e964ff905f75aab88d2fAndreas Huber        // API wants number of characters, not number of bytes...
3525a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        int len = n / 2;
3535a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        const char16_t *framedata = (const char16_t *) (mFrameData + 1);
3545a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        char16_t *framedatacopy = NULL;
3555a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfffe) {
3565a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            // endianness marker doesn't match host endianness, convert
3575a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedatacopy = new char16_t[len];
3585a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            for (int i = 0; i < len; i++) {
359569e7f1b1444194d1aca5a0b23de154565ba12daMarco Nelissen                framedatacopy[i] = bswap_16(framedata[i]);
3605a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            }
3615a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata = framedatacopy;
3625a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
3635a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        // If the string starts with an endianness marker, skip it
3645a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfeff) {
3655a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata++;
3665a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            len--;
3675a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
3685a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        id->setTo(framedata, len);
3695a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (framedatacopy != NULL) {
3705a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            delete[] framedatacopy;
3715a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
372fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
373fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
374fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
375fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst uint8_t *ID3::Iterator::getData(size_t *length) const {
376fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
377fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
378fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
379fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
380fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
381fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
382fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = mFrameSize - getHeaderLength();
383fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
384fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData;
385fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
386fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
387fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubersize_t ID3::Iterator::getHeaderLength() const {
388fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
389fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 6;
39083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else if (mParent.mVersion == ID3_V2_3) {
391fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 10;
39283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
39383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
39483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return 0;
395fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
396fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
397fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
398fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::findFrame() {
399fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (;;) {
400fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameData = NULL;
401fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameSize = 0;
402fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
403fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mParent.mVersion == ID3_V2_2) {
404fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 6 > mParent.mSize) {
405fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
406fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
407fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
408fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0", 3)) {
409fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
410fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
411fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
412fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize =
413fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                (mParent.mData[mOffset + 3] << 16)
414fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | (mParent.mData[mOffset + 4] << 8)
415fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | mParent.mData[mOffset + 5];
416fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
417fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize += 6;
418fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
419fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
420fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                LOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
421fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                     mOffset, mFrameSize, mParent.mSize - mOffset - 6);
422fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
423fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
424fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
425fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 6];
426fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
427fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
428fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
429fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
430fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
431fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[4];
432fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 3);
433fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[3] = '\0';
434fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
435fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
436fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
437fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
43883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        } else if (mParent.mVersion == ID3_V2_3) {
439fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 10 > mParent.mSize) {
440fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
441fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
442fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
443fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0\0", 4)) {
444fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
445fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
446fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
447fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize = 10 + U32_AT(&mParent.mData[mOffset + 4]);
448fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
449fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
450fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                LOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
451fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                     mOffset, mFrameSize, mParent.mSize - mOffset - 10);
452fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
453fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
454fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
455fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 10];
456fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
457fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
458fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
459fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
460fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
461fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[5];
462fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 4);
463fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[4] = '\0';
464fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
465fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
466fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
467fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
46883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        } else {
46983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
47083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
47183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (mOffset >= mParent.mSize) {
47283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                return;
47383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
47483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
47583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mFrameData = &mParent.mData[mOffset];
47683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
47783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            switch (mOffset) {
47883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 3:
47983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 33:
48083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 63:
48183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 30;
48283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
48383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 93:
48483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 4;
48583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
48683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 97:
48783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    if (mParent.mVersion == ID3_V1) {
48883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 30;
48983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    } else {
49083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 29;
49183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    }
49283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
49383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 126:
49483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
49583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
49683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 127:
49783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
49883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
49983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                default:
50083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    CHECK(!"Should not be here, invalid offset.");
50183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
50283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
50383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
50483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (!mID) {
50583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
50683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
50783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
50883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            String8 id;
50983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            getID(&id);
51083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
51183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (id == mID) {
51283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
51383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
514fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
515fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
516fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mOffset += mFrameSize;
517fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
518fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
519fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
520fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic size_t StringSize(const uint8_t *start, uint8_t encoding) {
521fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (encoding== 0x00) {
522fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // ISO 8859-1
523fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return strlen((const char *)start) + 1;
524fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
525fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
526fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // UCS-2
527fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = 0;
528fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (start[n] != '\0' || start[n + 1] != '\0') {
529fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        n += 2;
530fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
531fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
532fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return n;
533fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
534fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
535fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst void *
536fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::getAlbumArt(size_t *length, String8 *mime) const {
537fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
538fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mime->setTo("");
539fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
540fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    Iterator it(*this, mVersion == ID3_V2_3 ? "APIC" : "PIC");
541fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
542fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (!it.done()) {
543fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t size;
544fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data = it.getData(&size);
545fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
546fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mVersion == ID3_V2_3) {
547fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
548fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mime->setTo((const char *)&data[1]);
549fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t mimeLen = strlen((const char *)&data[1]) + 1;
550fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
551fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[1 + mimeLen];
552fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
553fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
554fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
555fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
556fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
557fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
558fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
559fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
560fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[2 + mimeLen], encoding);
561fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
562fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 2 - mimeLen - descLen;
563fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
564fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[2 + mimeLen + descLen];
565fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
566fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
567fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
568fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&data[1], "PNG", 3)) {
569fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/png");
570fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "JPG", 3)) {
571fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/jpeg");
572fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "-->", 3)) {
573fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("text/plain");
574fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else {
575fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return NULL;
576fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
577fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
578fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
579fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[4];
580fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
581fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
582fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
583fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
584fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
585fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
586fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
587fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[5], encoding);
588fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
589fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 5 - descLen;
590fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
591fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[5 + descLen];
592fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
593fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
594fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
595fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return NULL;
596fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
597fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
59883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV1(const sp<DataSource> &source) {
59983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    const size_t V1_TAG_SIZE = 128;
60083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
60183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    off_t size;
60283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (source->getSize(&size) != OK || size < (off_t)V1_TAG_SIZE) {
60383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
60483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
60583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
60683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mData = (uint8_t *)malloc(V1_TAG_SIZE);
60783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (source->readAt(size - V1_TAG_SIZE, mData, V1_TAG_SIZE)
60883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            != (ssize_t)V1_TAG_SIZE) {
60983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
61083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
61183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
61283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
61383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
61483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
61583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (memcmp("TAG", mData, 3)) {
61683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
61783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
61883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
61983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
62083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
62183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
62283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mSize = V1_TAG_SIZE;
62383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mFirstFrameOffset = 3;
62483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
62583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mData[V1_TAG_SIZE - 3] != 0) {
62683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1;
62783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
62883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1_1;
62983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
63083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
63183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    return true;
63283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber}
633fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
634fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}  // namespace android
635