ID3.cpp revision f1d5aa162c02a16b7195a43a9bcea4d592600ac4
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 33fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::ID3(const sp<DataSource> &source) 34fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber : mIsValid(false), 35fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mData(NULL), 36fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mSize(0), 37fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFirstFrameOffset(0), 38fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mVersion(ID3_UNKNOWN) { 3983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mIsValid = parseV2(source); 4083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 4183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (!mIsValid) { 4283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mIsValid = parseV1(source); 4383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 44fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 45fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 46fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::~ID3() { 47fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mData) { 48fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber free(mData); 49fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mData = NULL; 50fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 51fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 52fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 53fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::isValid() const { 54fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return mIsValid; 55fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 56fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 57fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Version ID3::version() const { 58fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return mVersion; 59fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 60fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 61bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber// static 62bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huberbool ID3::ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x) { 63bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber *x = 0; 64bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber for (int32_t i = 0; i < 4; ++i) { 65bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (encoded[i] & 0x80) { 66bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber return false; 67bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 68bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 69bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber *x = ((*x) << 7) | encoded[i]; 70bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 71bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 72bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber return true; 73bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber} 74bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 7583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV2(const sp<DataSource> &source) { 76bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huberstruct id3_header { 77bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber char id[3]; 78bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber uint8_t version_major; 79bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber uint8_t version_minor; 80bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber uint8_t flags; 81bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber uint8_t enc_size[4]; 82fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber }; 83fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 84fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber id3_header header; 85fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (source->readAt( 86fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 0, &header, sizeof(header)) != (ssize_t)sizeof(header)) { 87fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 88fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 89fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 90fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (memcmp(header.id, "ID3", 3)) { 91fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 92fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 93fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 94fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (header.version_major == 0xff || header.version_minor == 0xff) { 95fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 96fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 98fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (header.version_major == 2) { 99fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (header.flags & 0x3f) { 100fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // We only support the 2 high bits, if any of the lower bits are 101fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // set, we cannot guarantee to understand the tag format. 102fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 103fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 104fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 105fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (header.flags & 0x40) { 106fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // No compression scheme has been decided yet, ignore the 107fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // tag if compression is indicated. 108fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 109fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 110fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 111fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else if (header.version_major == 3) { 112fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (header.flags & 0x1f) { 113fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // We only support the 3 high bits, if any of the lower bits are 114fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // set, we cannot guarantee to understand the tag format. 115fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 116fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 117bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else if (header.version_major == 4) { 118bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (header.flags & 0x0f) { 119bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber // The lower 4 bits are undefined in this spec. 120bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber return false; 121bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 122fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else { 123fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 124fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 125fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 126bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber size_t size; 127bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (!ParseSyncsafeInteger(header.enc_size, &size)) { 128bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber return false; 129fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 130fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 13165997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber if (size > kMaxMetadataSize) { 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 466fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::getString(String8 *id) const { 467fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber id->setTo(""); 468fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 469fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mFrameData == NULL) { 470fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 471fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 472fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 47383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1) { 47483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (mOffset == 126 || mOffset == 127) { 47583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber // Special treatment for the track number and genre. 47683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber char tmp[16]; 47783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber sprintf(tmp, "%d", (int)*mFrameData); 47883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 47983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber id->setTo(tmp); 48083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return; 48183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 48283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 4834c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber convertISO8859ToString8(mFrameData, mFrameSize, id); 48483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return; 48583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 48683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 487fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t n = mFrameSize - getHeaderLength() - 1; 488fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 489fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (*mFrameData == 0x00) { 490fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // ISO 8859-1 491fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber convertISO8859ToString8(mFrameData + 1, n, id); 492bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else if (*mFrameData == 0x03) { 493bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber // UTF-8 494bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber id->setTo((const char *)(mFrameData + 1), n); 495bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else if (*mFrameData == 0x02) { 496bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber // UTF-16 BE, no byte order mark. 497bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber // API wants number of characters, not number of bytes... 498bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber int len = n / 2; 499bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber const char16_t *framedata = (const char16_t *) (mFrameData + 1); 500bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber char16_t *framedatacopy = NULL; 501bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#if BYTE_ORDER == LITTLE_ENDIAN 502bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber framedatacopy = new char16_t[len]; 503bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber for (int i = 0; i < len; i++) { 504bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber framedatacopy[i] = bswap_16(framedata[i]); 505bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 506bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber framedata = framedatacopy; 507bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#endif 508bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber id->setTo(framedata, len); 509bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (framedatacopy != NULL) { 510bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber delete[] framedatacopy; 511bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 512fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else { 513fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // UCS-2 51408e7eb983fcb9860a574e964ff905f75aab88d2fAndreas Huber // API wants number of characters, not number of bytes... 5155a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen int len = n / 2; 5165a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen const char16_t *framedata = (const char16_t *) (mFrameData + 1); 5175a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen char16_t *framedatacopy = NULL; 5185a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen if (*framedata == 0xfffe) { 5195a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen // endianness marker doesn't match host endianness, convert 5205a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen framedatacopy = new char16_t[len]; 5215a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen for (int i = 0; i < len; i++) { 522569e7f1b1444194d1aca5a0b23de154565ba12daMarco Nelissen framedatacopy[i] = bswap_16(framedata[i]); 5235a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen } 5245a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen framedata = framedatacopy; 5255a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen } 5265a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen // If the string starts with an endianness marker, skip it 5275a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen if (*framedata == 0xfeff) { 5285a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen framedata++; 5295a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen len--; 5305a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen } 5315a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen id->setTo(framedata, len); 5325a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen if (framedatacopy != NULL) { 5335a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen delete[] framedatacopy; 5345a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen } 535fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 536fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 537fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 538fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst uint8_t *ID3::Iterator::getData(size_t *length) const { 539fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *length = 0; 540fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 541fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mFrameData == NULL) { 542fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return NULL; 543fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 544fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 545fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *length = mFrameSize - getHeaderLength(); 546fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 547fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return mFrameData; 548fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 549fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 550fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubersize_t ID3::Iterator::getHeaderLength() const { 551fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mParent.mVersion == ID3_V2_2) { 552fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return 6; 553bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) { 554fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return 10; 55583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } else { 55683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1); 55783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return 0; 558fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 559fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 560fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 561fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::findFrame() { 562fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber for (;;) { 563fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameData = NULL; 564fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameSize = 0; 565fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 566fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mParent.mVersion == ID3_V2_2) { 567fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mOffset + 6 > mParent.mSize) { 568fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 569fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 570fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 571fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!memcmp(&mParent.mData[mOffset], "\0\0\0", 3)) { 572fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 573fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 574fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 575fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameSize = 576fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber (mParent.mData[mOffset + 3] << 16) 577fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber | (mParent.mData[mOffset + 4] << 8) 578fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber | mParent.mData[mOffset + 5]; 579fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 580fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameSize += 6; 581fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 582fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mOffset + mFrameSize > mParent.mSize) { 5833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)", 584fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mOffset, mFrameSize, mParent.mSize - mOffset - 6); 585fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 586fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 587fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 588fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameData = &mParent.mData[mOffset + 6]; 589fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 590fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!mID) { 591fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber break; 592fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 593fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 594fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber char id[4]; 595fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber memcpy(id, &mParent.mData[mOffset], 3); 596fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber id[3] = '\0'; 597fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 598fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!strcmp(id, mID)) { 599fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber break; 600fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 601bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else if (mParent.mVersion == ID3_V2_3 602bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber || mParent.mVersion == ID3_V2_4) { 603fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mOffset + 10 > mParent.mSize) { 604fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 605fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 606fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 607fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!memcmp(&mParent.mData[mOffset], "\0\0\0\0", 4)) { 608fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 609fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 610fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 611bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber size_t baseSize; 612bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (mParent.mVersion == ID3_V2_4) { 613bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (!ParseSyncsafeInteger( 614bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber &mParent.mData[mOffset + 4], &baseSize)) { 615bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber return; 616bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 617bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else { 618bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber baseSize = U32_AT(&mParent.mData[mOffset + 4]); 619bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 620bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 621bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber mFrameSize = 10 + baseSize; 622fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 623fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mOffset + mFrameSize > mParent.mSize) { 6243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)", 625fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mOffset, mFrameSize, mParent.mSize - mOffset - 10); 626fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 627fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 628fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 629bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]); 630bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 631ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000c)) 632bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) { 633ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber // Compression or encryption are not supported at this time. 634ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber // Per-frame unsynchronization and data-length indicator 635ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber // have already been taken care of. 636bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 6373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Skipping unsupported frame (compression, encryption " 638bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber "or per-frame unsynchronization flagged"); 639bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 640bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber mOffset += mFrameSize; 641bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber continue; 642bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 643bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 644fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameData = &mParent.mData[mOffset + 10]; 645fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 646fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!mID) { 647fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber break; 648fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 649fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 650fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber char id[5]; 651fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber memcpy(id, &mParent.mData[mOffset], 4); 652fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber id[4] = '\0'; 653fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 654fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!strcmp(id, mID)) { 655fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber break; 656fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 65783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } else { 65883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1); 65983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 66083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (mOffset >= mParent.mSize) { 66183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return; 66283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 66383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 66483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameData = &mParent.mData[mOffset]; 66583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 66683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber switch (mOffset) { 66783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 3: 66883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 33: 66983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 63: 67083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameSize = 30; 67183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 67283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 93: 67383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameSize = 4; 67483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 67583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 97: 67683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (mParent.mVersion == ID3_V1) { 67783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameSize = 30; 67883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } else { 67983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameSize = 29; 68083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 68183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 68283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 126: 68383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameSize = 1; 68483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 68583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 127: 68683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameSize = 1; 68783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 68883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber default: 68983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber CHECK(!"Should not be here, invalid offset."); 69083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 69183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 69283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 69383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (!mID) { 69483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 69583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 69683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 69783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber String8 id; 69883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber getID(&id); 69983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 70083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (id == mID) { 70183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 70283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 703fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 704fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 705fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mOffset += mFrameSize; 706fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 707fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 708fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 709fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic size_t StringSize(const uint8_t *start, uint8_t encoding) { 710bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (encoding == 0x00 || encoding == 0x03) { 711bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber // ISO 8859-1 or UTF-8 712fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return strlen((const char *)start) + 1; 713fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 714fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 715fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // UCS-2 716fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t n = 0; 717fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber while (start[n] != '\0' || start[n + 1] != '\0') { 718fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber n += 2; 719fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 720fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 721fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return n; 722fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 723fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 724fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst void * 725fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::getAlbumArt(size_t *length, String8 *mime) const { 726fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *length = 0; 727fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mime->setTo(""); 728fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 729bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber Iterator it( 730bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber *this, 731bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) ? "APIC" : "PIC"); 732fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 733fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber while (!it.done()) { 734fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t size; 735fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber const uint8_t *data = it.getData(&size); 736fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 737bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) { 738fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber uint8_t encoding = data[0]; 739fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mime->setTo((const char *)&data[1]); 740fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t mimeLen = strlen((const char *)&data[1]) + 1; 741fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 742fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber uint8_t picType = data[1 + mimeLen]; 743fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0 744fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (picType != 0x03) { 745fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // Front Cover Art 746fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber it.next(); 747fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber continue; 748fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 749fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif 750fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 751fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t descLen = StringSize(&data[2 + mimeLen], encoding); 752fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 753fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *length = size - 2 - mimeLen - descLen; 754fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 755fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return &data[2 + mimeLen + descLen]; 756fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else { 757fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber uint8_t encoding = data[0]; 758fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 759fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!memcmp(&data[1], "PNG", 3)) { 760fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mime->setTo("image/png"); 761fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else if (!memcmp(&data[1], "JPG", 3)) { 762fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mime->setTo("image/jpeg"); 763fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else if (!memcmp(&data[1], "-->", 3)) { 764fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mime->setTo("text/plain"); 765fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else { 766fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return NULL; 767fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 768fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 769fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0 770fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber uint8_t picType = data[4]; 771fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (picType != 0x03) { 772fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // Front Cover Art 773fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber it.next(); 774fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber continue; 775fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 776fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif 777fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 778fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t descLen = StringSize(&data[5], encoding); 779fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 780fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *length = size - 5 - descLen; 781fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 782fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return &data[5 + descLen]; 783fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 784fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 785fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 786fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return NULL; 787fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 788fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 78983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV1(const sp<DataSource> &source) { 79083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber const size_t V1_TAG_SIZE = 128; 79183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 792c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t size; 793c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (source->getSize(&size) != OK || size < (off64_t)V1_TAG_SIZE) { 79483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return false; 79583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 79683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 79783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mData = (uint8_t *)malloc(V1_TAG_SIZE); 79883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (source->readAt(size - V1_TAG_SIZE, mData, V1_TAG_SIZE) 79983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber != (ssize_t)V1_TAG_SIZE) { 80083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber free(mData); 80183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mData = NULL; 80283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 80383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return false; 80483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 80583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 80683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (memcmp("TAG", mData, 3)) { 80783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber free(mData); 80883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mData = NULL; 80983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 81083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return false; 81183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 81283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 81383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mSize = V1_TAG_SIZE; 81483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFirstFrameOffset = 3; 81583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 81683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (mData[V1_TAG_SIZE - 3] != 0) { 81783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mVersion = ID3_V1; 81883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } else { 81983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mVersion = ID3_V1_1; 82083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 82183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 82283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return true; 82383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber} 824fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 825fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} // namespace android 826