ID3.cpp revision fc9ba09e3bb368f823d473f5e2bb9aa32dba6289
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>
27fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
28fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubernamespace android {
29fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
30fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::ID3(const sp<DataSource> &source)
31fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mIsValid(false),
32fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mData(NULL),
33fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mSize(0),
34fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFirstFrameOffset(0),
35fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mVersion(ID3_UNKNOWN) {
36fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mIsValid = parse(source);
37fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
38fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
39fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::~ID3() {
40fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mData) {
41fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        free(mData);
42fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mData = NULL;
43fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
44fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
45fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
46fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::isValid() const {
47fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mIsValid;
48fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
49fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
50fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Version ID3::version() const {
51fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mVersion;
52fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
53fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
54fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::parse(const sp<DataSource> &source) {
55fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    struct id3_header {
56fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        char id[3];
57fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint8_t version_major;
58fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint8_t version_minor;
59fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint8_t flags;
60fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint8_t enc_size[4];
61fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    };
62fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
63fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id3_header header;
64fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (source->readAt(
65fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                0, &header, sizeof(header)) != (ssize_t)sizeof(header)) {
66fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
67fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
68fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
69fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (memcmp(header.id, "ID3", 3)) {
70fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
71fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
72fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
73fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 0xff || header.version_minor == 0xff) {
74fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
75fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
76fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
77fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
78fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x3f) {
79fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // We only support the 2 high bits, if any of the lower bits are
80fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // set, we cannot guarantee to understand the tag format.
81fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
82fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
83fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
84fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x40) {
85fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // No compression scheme has been decided yet, ignore the
86fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // tag if compression is indicated.
87fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
88fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
89fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
90fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else if (header.version_major == 3) {
91fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x1f) {
92fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // We only support the 3 high bits, if any of the lower bits are
93fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // set, we cannot guarantee to understand the tag format.
94fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
95fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
96fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
98fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
99fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
100fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t size = 0;
101fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (int32_t i = 0; i < 4; ++i) {
102fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.enc_size[i] & 0x80) {
103fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
104fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
105fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
106fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size = (size << 7) | header.enc_size[i];
107fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
108fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
109fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mData = (uint8_t *)malloc(size);
110fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
111fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mData == NULL) {
112fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
113fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
114fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
115fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mSize = size;
116fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
117fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (source->readAt(sizeof(header), mData, mSize) != (ssize_t)mSize) {
118fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
119fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
120fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
121fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.flags & 0x80) {
122fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        LOGI("removing unsynchronization");
123fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        removeUnsynchronization();
124fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
125fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
126fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mFirstFrameOffset = 0;
127fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 3 && (header.flags & 0x40)) {
128fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // Version 2.3 has an optional extended header.
129fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
130fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mSize < 4) {
131fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
132fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
133fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
134fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t extendedHeaderSize = U32_AT(&mData[0]) + 4;
135fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
136fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize > mSize) {
137fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
138fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
139fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
140fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFirstFrameOffset = extendedHeaderSize;
141fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
142fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint16_t extendedFlags = 0;
143fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize >= 6) {
144fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            extendedFlags = U16_AT(&mData[4]);
145fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
146fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedHeaderSize >= 10) {
147fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                size_t paddingSize = U32_AT(&mData[6]);
148fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
149fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                if (mFirstFrameOffset + paddingSize > mSize) {
150fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                    return false;
151fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                }
152fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
153fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mSize -= paddingSize;
154fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
155fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
156fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedFlags & 0x8000) {
157fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                LOGI("have crc");
158fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
159fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
160fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
161fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
162fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
163fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_2;
164fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
165fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        CHECK_EQ(header.version_major, 3);
166fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_3;
167fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
168fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
169fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return true;
170fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
171fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
172fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::removeUnsynchronization() {
173fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i + 1 < mSize; ++i) {
174fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mData[i] == 0xff && mData[i + 1] == 0x00) {
175fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memmove(&mData[i + 1], &mData[i + 2], mSize - i - 2);
176fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            --mSize;
177fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
178fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
179fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
180fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
181fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::Iterator(const ID3 &parent, const char *id)
182fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mParent(parent),
183fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mID(NULL),
184fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mOffset(mParent.mFirstFrameOffset),
185fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameData(NULL),
186fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameSize(0) {
187fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (id) {
188fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = strdup(id);
189fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
190fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
191fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
192fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
193fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
194fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::~Iterator() {
195fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mID) {
196fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        free(mID);
197fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = NULL;
198fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
199fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
200fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
201fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::Iterator::done() const {
202fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData == NULL;
203fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
204fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
205fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::next() {
206fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
207fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
208fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
209fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
210fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mOffset += mFrameSize;
211fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
212fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
213fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
214fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
215fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::getID(String8 *id) const {
216fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
217fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
218fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
219fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
220fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
221fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
222fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
223fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 3);
224fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
225fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        CHECK_EQ(mParent.mVersion, ID3_V2_3);
226fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 4);
227fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
228fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
229fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
230fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic void convertISO8859ToString8(
231fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data, size_t size,
232fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        String8 *s) {
233fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t utf8len = 0;
234fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i < size; ++i) {
235fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (data[i] < 0x80) {
236fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            ++utf8len;
237fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
238fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            utf8len += 2;
239fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
240fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
241fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
242fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (utf8len == size) {
243fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // Only ASCII characters present.
244fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
245fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        s->setTo((const char *)data, size);
246fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
247fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
248fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
249fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    char *tmp = new char[utf8len];
250fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    char *ptr = tmp;
251fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i < size; ++i) {
252fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (data[i] < 0x80) {
253fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i];
254fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else if (data[i] < 0xc0) {
255fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = 0xc2;
256fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i];
257fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
258fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = 0xc3;
259fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *ptr++ = data[i] - 64;
260fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
261fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
262fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
263fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    s->setTo(tmp, utf8len);
264fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
265fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    delete[] tmp;
266fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    tmp = NULL;
267fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
268fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
269fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::getString(String8 *id) const {
270fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
271fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
272fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
273fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
274fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
275fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
276fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = mFrameSize - getHeaderLength() - 1;
277fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
278fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (*mFrameData == 0x00) {
279fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // ISO 8859-1
280fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        convertISO8859ToString8(mFrameData + 1, n, id);
281fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
282fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // UCS-2
283fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char16_t *)(mFrameData + 1), n);
284fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
285fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
286fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
287fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst uint8_t *ID3::Iterator::getData(size_t *length) const {
288fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
289fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
290fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
291fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
292fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
293fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
294fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = mFrameSize - getHeaderLength();
295fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
296fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData;
297fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
298fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
299fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubersize_t ID3::Iterator::getHeaderLength() const {
300fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
301fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 6;
302fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
303fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        CHECK_EQ(mParent.mVersion, ID3_V2_3);
304fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 10;
305fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
306fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
307fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
308fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::findFrame() {
309fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (;;) {
310fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameData = NULL;
311fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameSize = 0;
312fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
313fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mParent.mVersion == ID3_V2_2) {
314fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 6 > mParent.mSize) {
315fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
316fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
317fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
318fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0", 3)) {
319fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
320fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
321fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
322fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize =
323fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                (mParent.mData[mOffset + 3] << 16)
324fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | (mParent.mData[mOffset + 4] << 8)
325fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | mParent.mData[mOffset + 5];
326fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
327fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize += 6;
328fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
329fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
330fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                LOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
331fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                     mOffset, mFrameSize, mParent.mSize - mOffset - 6);
332fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
333fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
334fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
335fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 6];
336fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
337fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
338fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
339fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
340fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
341fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[4];
342fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 3);
343fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[3] = '\0';
344fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
345fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
346fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
347fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
348fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
349fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            CHECK_EQ(mParent.mVersion, ID3_V2_3);
350fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
351fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 10 > mParent.mSize) {
352fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
353fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
354fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
355fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0\0", 4)) {
356fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
357fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
358fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
359fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize = 10 + U32_AT(&mParent.mData[mOffset + 4]);
360fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
361fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
362fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                LOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
363fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                     mOffset, mFrameSize, mParent.mSize - mOffset - 10);
364fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
365fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
366fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
367fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 10];
368fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
369fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
370fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
371fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
372fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
373fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[5];
374fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 4);
375fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[4] = '\0';
376fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
377fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
378fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
379fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
380fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
381fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
382fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mOffset += mFrameSize;
383fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
384fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
385fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
386fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic size_t StringSize(const uint8_t *start, uint8_t encoding) {
387fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (encoding== 0x00) {
388fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // ISO 8859-1
389fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return strlen((const char *)start) + 1;
390fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
391fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
392fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // UCS-2
393fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = 0;
394fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (start[n] != '\0' || start[n + 1] != '\0') {
395fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        n += 2;
396fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
397fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
398fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return n;
399fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
400fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
401fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst void *
402fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::getAlbumArt(size_t *length, String8 *mime) const {
403fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
404fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mime->setTo("");
405fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
406fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    Iterator it(*this, mVersion == ID3_V2_3 ? "APIC" : "PIC");
407fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
408fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (!it.done()) {
409fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t size;
410fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data = it.getData(&size);
411fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
412fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mVersion == ID3_V2_3) {
413fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
414fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mime->setTo((const char *)&data[1]);
415fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t mimeLen = strlen((const char *)&data[1]) + 1;
416fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
417fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[1 + mimeLen];
418fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
419fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
420fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
421fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
422fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
423fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
424fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
425fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
426fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[2 + mimeLen], encoding);
427fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
428fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 2 - mimeLen - descLen;
429fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
430fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[2 + mimeLen + descLen];
431fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
432fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
433fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
434fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&data[1], "PNG", 3)) {
435fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/png");
436fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "JPG", 3)) {
437fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/jpeg");
438fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "-->", 3)) {
439fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("text/plain");
440fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else {
441fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return NULL;
442fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
443fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
444fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
445fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[4];
446fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
447fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
448fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
449fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
450fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
451fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
452fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
453fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            size_t descLen = StringSize(&data[5], encoding);
454fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
455fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 5 - descLen;
456fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
457fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[5 + descLen];
458fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
459fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
460fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
461fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return NULL;
462fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
463fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
464fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
465fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}  // namespace android
466