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