ID3.cpp revision f26400c9d01a0e2f71690d5ebc644270f098d590
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 3314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstruct MemorySource : public DataSource { 3414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber MemorySource(const uint8_t *data, size_t size) 3514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber : mData(data), 3614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSize(size) { 3714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 3814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 3914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber virtual status_t initCheck() const { 4014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 4114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 4214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 4314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber virtual ssize_t readAt(off64_t offset, void *data, size_t size) { 4414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber off64_t available = (offset >= mSize) ? 0ll : mSize - offset; 4514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 4614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t copy = (available > size) ? size : available; 4714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber memcpy(data, mData + offset, copy); 4814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 4914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return copy; 5014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 5114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 5214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberprivate: 5314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const uint8_t *mData; 5414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t mSize; 5514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 5614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(MemorySource); 5714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}; 5814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 59ffd6ffc5429c45577fd8e9f8fa90e79bb91b8a84Dylan PowersID3::ID3(const sp<DataSource> &source, bool ignoreV1) 60fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber : mIsValid(false), 61fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mData(NULL), 62fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mSize(0), 63fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFirstFrameOffset(0), 6414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mVersion(ID3_UNKNOWN), 6514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mRawSize(0) { 6614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mIsValid = parseV2(source); 6714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 6814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!mIsValid && !ignoreV1) { 6914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mIsValid = parseV1(source); 7014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 7114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 7214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas HuberID3::ID3(const uint8_t *data, size_t size, bool ignoreV1) 7414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber : mIsValid(false), 7514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mData(NULL), 7614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSize(0), 7714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mFirstFrameOffset(0), 7814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mVersion(ID3_UNKNOWN), 7914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mRawSize(0) { 8014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<MemorySource> source = new MemorySource(data, size); 8114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 8283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mIsValid = parseV2(source); 8383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 84ffd6ffc5429c45577fd8e9f8fa90e79bb91b8a84Dylan Powers if (!mIsValid && !ignoreV1) { 8583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mIsValid = parseV1(source); 8683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 87fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 88fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 89fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::~ID3() { 90fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mData) { 91fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber free(mData); 92fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mData = NULL; 93fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 94fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 95fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 96fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::isValid() const { 97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return mIsValid; 98fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 99fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 100fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Version ID3::version() const { 101fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return mVersion; 102fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 103fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 104bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber// static 105bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huberbool ID3::ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x) { 106bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber *x = 0; 107bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber for (int32_t i = 0; i < 4; ++i) { 108bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (encoded[i] & 0x80) { 109bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber return false; 110bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 111bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 112bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber *x = ((*x) << 7) | encoded[i]; 113bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 114bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 115bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber return true; 116bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber} 117bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 11883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV2(const sp<DataSource> &source) { 119bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huberstruct id3_header { 120bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber char id[3]; 121bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber uint8_t version_major; 122bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber uint8_t version_minor; 123bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber uint8_t flags; 124bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber uint8_t enc_size[4]; 125fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber }; 126fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 127fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber id3_header header; 128fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (source->readAt( 129fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 0, &header, sizeof(header)) != (ssize_t)sizeof(header)) { 130fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 131fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 132fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 133fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (memcmp(header.id, "ID3", 3)) { 134fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 135fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 136fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 137fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (header.version_major == 0xff || header.version_minor == 0xff) { 138fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 139fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 140fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 141fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (header.version_major == 2) { 142fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (header.flags & 0x3f) { 143fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // We only support the 2 high bits, if any of the lower bits are 144fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // set, we cannot guarantee to understand the tag format. 145fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 146fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 147fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 148fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (header.flags & 0x40) { 149fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // No compression scheme has been decided yet, ignore the 150fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // tag if compression is indicated. 151fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 152fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 153fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 154fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else if (header.version_major == 3) { 155fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (header.flags & 0x1f) { 156fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // We only support the 3 high bits, if any of the lower bits are 157fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // set, we cannot guarantee to understand the tag format. 158fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 159fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 160bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else if (header.version_major == 4) { 161bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (header.flags & 0x0f) { 162bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber // The lower 4 bits are undefined in this spec. 163bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber return false; 164bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 165fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else { 166fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 167fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 168fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 169bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber size_t size; 170bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (!ParseSyncsafeInteger(header.enc_size, &size)) { 171bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber return false; 172fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 173fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 17465997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber if (size > kMaxMetadataSize) { 17529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("skipping huge ID3 metadata of size %d", size); 17665997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber return false; 17765997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber } 17865997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber 179fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mData = (uint8_t *)malloc(size); 180fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 181fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mData == NULL) { 182fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 183fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 184fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 185fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mSize = size; 18614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mRawSize = mSize + sizeof(header); 187fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 188fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (source->readAt(sizeof(header), mData, mSize) != (ssize_t)mSize) { 189ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber free(mData); 190ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber mData = NULL; 191ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 192fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 193fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 194fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 195ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber if (header.version_major == 4) { 196428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber void *copy = malloc(size); 197428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber memcpy(copy, mData, size); 198428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber 199428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber bool success = removeUnsynchronizationV2_4(false /* iTunesHack */); 200428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber if (!success) { 201428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber memcpy(mData, copy, size); 202428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber mSize = size; 203428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber 204428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber success = removeUnsynchronizationV2_4(true /* iTunesHack */); 205428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber 206428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber if (success) { 2073856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Had to apply the iTunes hack to parse this ID3 tag"); 208428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber } 209428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber } 210428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber 211428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber free(copy); 212428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber copy = NULL; 213428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber 214428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber if (!success) { 215ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber free(mData); 216ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber mData = NULL; 217ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 218ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber return false; 219ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber } 220ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber } else if (header.flags & 0x80) { 2213856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("removing unsynchronization"); 222ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 223fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber removeUnsynchronization(); 224fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 225fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 226fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFirstFrameOffset = 0; 227fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (header.version_major == 3 && (header.flags & 0x40)) { 228fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // Version 2.3 has an optional extended header. 229fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 230fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mSize < 4) { 23183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber free(mData); 23283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mData = NULL; 23383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 234fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 235fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 236fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 237fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t extendedHeaderSize = U32_AT(&mData[0]) + 4; 238fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 239fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (extendedHeaderSize > mSize) { 24083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber free(mData); 24183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mData = NULL; 24283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 243fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 244fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 245fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 246fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFirstFrameOffset = extendedHeaderSize; 247fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 248fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber uint16_t extendedFlags = 0; 249fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (extendedHeaderSize >= 6) { 250fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber extendedFlags = U16_AT(&mData[4]); 251fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 252fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (extendedHeaderSize >= 10) { 253fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t paddingSize = U32_AT(&mData[6]); 254fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 255fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mFirstFrameOffset + paddingSize > mSize) { 25683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber free(mData); 25783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mData = NULL; 25883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 259fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 260fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 261fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 262fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mSize -= paddingSize; 263fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 264fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 265fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (extendedFlags & 0x8000) { 2663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("have crc"); 267fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 268fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 269bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else if (header.version_major == 4 && (header.flags & 0x40)) { 270bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber // Version 2.4 has an optional extended header, that's different 271bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber // from Version 2.3's... 272bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 273bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (mSize < 4) { 274bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber free(mData); 275bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber mData = NULL; 276bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 277bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber return false; 278bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 279bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 280bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber size_t ext_size; 281bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (!ParseSyncsafeInteger(mData, &ext_size)) { 282bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber free(mData); 283bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber mData = NULL; 284bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 285bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber return false; 286bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 287bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 288bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (ext_size < 6 || ext_size > mSize) { 289bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber free(mData); 290bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber mData = NULL; 291bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 292bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber return false; 293bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 294bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 295bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber mFirstFrameOffset = ext_size; 296fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 297fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 298fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (header.version_major == 2) { 299fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mVersion = ID3_V2_2; 300bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else if (header.version_major == 3) { 301fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mVersion = ID3_V2_3; 302bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else { 303bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber CHECK_EQ(header.version_major, 4); 304bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber mVersion = ID3_V2_4; 305fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 306fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 307fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return true; 308fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 309fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 310fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::removeUnsynchronization() { 311fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber for (size_t i = 0; i + 1 < mSize; ++i) { 312fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mData[i] == 0xff && mData[i + 1] == 0x00) { 313fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber memmove(&mData[i + 1], &mData[i + 2], mSize - i - 2); 314fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber --mSize; 315fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 316fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 317fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 318fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 319ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huberstatic void WriteSyncsafeInteger(uint8_t *dst, size_t x) { 320ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber for (size_t i = 0; i < 4; ++i) { 321ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber dst[3 - i] = (x & 0x7f); 322ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber x >>= 7; 323ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber } 324ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber} 325ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 326428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huberbool ID3::removeUnsynchronizationV2_4(bool iTunesHack) { 327ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber size_t oldSize = mSize; 328ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 329ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber size_t offset = 0; 330ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber while (offset + 10 <= mSize) { 331ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber if (!memcmp(&mData[offset], "\0\0\0\0", 4)) { 332ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber break; 333ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber } 334ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 335ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber size_t dataSize; 336428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber if (iTunesHack) { 337428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber dataSize = U32_AT(&mData[offset + 4]); 338428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber } else if (!ParseSyncsafeInteger(&mData[offset + 4], &dataSize)) { 339ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber return false; 340ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber } 341ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 342ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber if (offset + dataSize + 10 > mSize) { 343ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber return false; 344ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber } 345ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 346ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber uint16_t flags = U16_AT(&mData[offset + 8]); 347ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber uint16_t prevFlags = flags; 348ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 349ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber if (flags & 1) { 350ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber // Strip data length indicator 351ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 352ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber memmove(&mData[offset + 10], &mData[offset + 14], mSize - offset - 14); 353ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber mSize -= 4; 354ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber dataSize -= 4; 355ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 356ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber flags &= ~1; 357ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber } 358ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 359ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber if (flags & 2) { 36072a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen // This file has "unsynchronization", so we have to replace occurrences 36172a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen // of 0xff 0x00 with just 0xff in order to get the real data. 362ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 36372a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen size_t readOffset = offset + 11; 36472a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen size_t writeOffset = offset + 11; 365ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber for (size_t i = 0; i + 1 < dataSize; ++i) { 36672a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen if (mData[readOffset - 1] == 0xff 36772a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen && mData[readOffset] == 0x00) { 36872a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen ++readOffset; 369ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber --mSize; 370ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber --dataSize; 371ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber } 37272a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen mData[writeOffset++] = mData[readOffset++]; 373ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber } 37472a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen // move the remaining data following this frame 37572a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen memmove(&mData[writeOffset], &mData[readOffset], oldSize - readOffset); 376ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 377ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber flags &= ~2; 378ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber } 379ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 380428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber if (flags != prevFlags || iTunesHack) { 381ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber WriteSyncsafeInteger(&mData[offset + 4], dataSize); 382ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber mData[offset + 8] = flags >> 8; 383ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber mData[offset + 9] = flags & 0xff; 384ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber } 385ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 386ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber offset += 10 + dataSize; 387ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber } 388ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 389ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber memset(&mData[mSize], 0, oldSize - mSize); 390ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 391ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber return true; 392ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber} 393ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber 394fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::Iterator(const ID3 &parent, const char *id) 395fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber : mParent(parent), 396fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mID(NULL), 397fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mOffset(mParent.mFirstFrameOffset), 398fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameData(NULL), 399fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameSize(0) { 400fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (id) { 401fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mID = strdup(id); 402fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 403fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 404fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber findFrame(); 405fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 406fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 407fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::~Iterator() { 408fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mID) { 409fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber free(mID); 410fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mID = NULL; 411fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 412fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 413fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 414fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::Iterator::done() const { 415fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return mFrameData == NULL; 416fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 417fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 418fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::next() { 419fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mFrameData == NULL) { 420fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 421fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 422fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 423fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mOffset += mFrameSize; 424fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 425fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber findFrame(); 426fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 427fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 428fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::getID(String8 *id) const { 429fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber id->setTo(""); 430fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 431fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mFrameData == NULL) { 432fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 433fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 434fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 435fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mParent.mVersion == ID3_V2_2) { 436fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber id->setTo((const char *)&mParent.mData[mOffset], 3); 437bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) { 438fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber id->setTo((const char *)&mParent.mData[mOffset], 4); 43983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } else { 44083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1); 44183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 44283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber switch (mOffset) { 44383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 3: 44483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber id->setTo("TT2"); 44583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 44683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 33: 44783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber id->setTo("TP1"); 44883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 44983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 63: 45083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber id->setTo("TAL"); 45183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 45283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 93: 45383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber id->setTo("TYE"); 45483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 45583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 97: 45683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber id->setTo("COM"); 45783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 45883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 126: 45983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber id->setTo("TRK"); 46083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 46183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 127: 46283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber id->setTo("TCO"); 46383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 46483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber default: 46583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber CHECK(!"should not be here."); 46683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 46783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 468fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 469fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 470fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 471fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic void convertISO8859ToString8( 472fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber const uint8_t *data, size_t size, 473fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber String8 *s) { 474fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t utf8len = 0; 475fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber for (size_t i = 0; i < size; ++i) { 4764c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber if (data[i] == '\0') { 477632a7dfdab89ffa79846ad37718d0582fd36affeKenny Root size = i; 4784c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber break; 4794c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber } else if (data[i] < 0x80) { 480fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber ++utf8len; 481fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else { 482fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber utf8len += 2; 483fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 484fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 485fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 486fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (utf8len == size) { 487fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // Only ASCII characters present. 488fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 489fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber s->setTo((const char *)data, size); 490fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 491fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 492fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 493fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber char *tmp = new char[utf8len]; 494fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber char *ptr = tmp; 495fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber for (size_t i = 0; i < size; ++i) { 4964c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber if (data[i] == '\0') { 4974c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber break; 4984c23b7d543cd95250e766cef7558d0f4c941ddcbAndreas Huber } else if (data[i] < 0x80) { 499fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *ptr++ = data[i]; 500fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else if (data[i] < 0xc0) { 501fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *ptr++ = 0xc2; 502fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *ptr++ = data[i]; 503fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else { 504fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *ptr++ = 0xc3; 505fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *ptr++ = data[i] - 64; 506fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 507fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 508fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 509fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber s->setTo(tmp, utf8len); 510fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 511fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber delete[] tmp; 512fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber tmp = NULL; 513fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 514fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 515b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// the 2nd argument is used to get the data following the \0 in a comment field 516b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getString(String8 *id, String8 *comment) const { 517b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen getstring(id, false); 518b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen if (comment != NULL) { 519b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen getstring(comment, true); 520b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen } 521b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen} 522b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen 523b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// comment fields (COM/COMM) contain an initial short descriptor, followed by \0, 524b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// followed by more data. The data following the \0 can be retrieved by setting 525b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// "otherdata" to true. 526b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getstring(String8 *id, bool otherdata) const { 527fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber id->setTo(""); 528fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 529b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen const uint8_t *frameData = mFrameData; 530b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen if (frameData == NULL) { 531fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 532fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 533fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 534b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen uint8_t encoding = *frameData; 535b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen 53683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1) { 53783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (mOffset == 126 || mOffset == 127) { 53883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber // Special treatment for the track number and genre. 53983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber char tmp[16]; 540b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen sprintf(tmp, "%d", (int)*frameData); 54183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 54283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber id->setTo(tmp); 54383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return; 54483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 54583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 546b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen convertISO8859ToString8(frameData, mFrameSize, id); 54783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return; 54883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 54983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 550fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t n = mFrameSize - getHeaderLength() - 1; 551b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen if (otherdata) { 552b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen // skip past the encoding, language, and the 0 separator 553b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen frameData += 4; 554b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen int32_t i = n - 4; 555b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen while(--i >= 0 && *++frameData != 0) ; 556b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen int skipped = (frameData - mFrameData); 55714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (skipped >= (int)n) { 558b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen return; 559b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen } 560b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen n -= skipped; 561b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen } 562fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 563b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen if (encoding == 0x00) { 564fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // ISO 8859-1 565b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen convertISO8859ToString8(frameData + 1, n, id); 566b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen } else if (encoding == 0x03) { 567bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber // UTF-8 568b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen id->setTo((const char *)(frameData + 1), n); 569b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen } else if (encoding == 0x02) { 570bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber // UTF-16 BE, no byte order mark. 571bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber // API wants number of characters, not number of bytes... 572bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber int len = n / 2; 573b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen const char16_t *framedata = (const char16_t *) (frameData + 1); 574bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber char16_t *framedatacopy = NULL; 575bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#if BYTE_ORDER == LITTLE_ENDIAN 576bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber framedatacopy = new char16_t[len]; 577bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber for (int i = 0; i < len; i++) { 578bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber framedatacopy[i] = bswap_16(framedata[i]); 579bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 580bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber framedata = framedatacopy; 581bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#endif 582bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber id->setTo(framedata, len); 583bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (framedatacopy != NULL) { 584bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber delete[] framedatacopy; 585bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 586fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else { 587fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // UCS-2 58808e7eb983fcb9860a574e964ff905f75aab88d2fAndreas Huber // API wants number of characters, not number of bytes... 5895a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen int len = n / 2; 590b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen const char16_t *framedata = (const char16_t *) (frameData + 1); 5915a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen char16_t *framedatacopy = NULL; 5925a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen if (*framedata == 0xfffe) { 5935a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen // endianness marker doesn't match host endianness, convert 5945a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen framedatacopy = new char16_t[len]; 5955a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen for (int i = 0; i < len; i++) { 596569e7f1b1444194d1aca5a0b23de154565ba12daMarco Nelissen framedatacopy[i] = bswap_16(framedata[i]); 5975a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen } 5985a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen framedata = framedatacopy; 5995a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen } 6005a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen // If the string starts with an endianness marker, skip it 6015a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen if (*framedata == 0xfeff) { 6025a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen framedata++; 6035a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen len--; 6045a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen } 6055a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen id->setTo(framedata, len); 6065a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen if (framedatacopy != NULL) { 6075a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen delete[] framedatacopy; 6085a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen } 609fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 610fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 611fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 612fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst uint8_t *ID3::Iterator::getData(size_t *length) const { 613fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *length = 0; 614fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 615fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mFrameData == NULL) { 616fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return NULL; 617fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 618fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 619fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *length = mFrameSize - getHeaderLength(); 620fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 621fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return mFrameData; 622fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 623fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 624fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubersize_t ID3::Iterator::getHeaderLength() const { 625fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mParent.mVersion == ID3_V2_2) { 626fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return 6; 627bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) { 628fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return 10; 62983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } else { 63083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1); 63183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return 0; 632fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 633fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 634fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 635fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::findFrame() { 636fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber for (;;) { 637fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameData = NULL; 638fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameSize = 0; 639fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 640fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mParent.mVersion == ID3_V2_2) { 641fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mOffset + 6 > mParent.mSize) { 642fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 643fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 644fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 645fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!memcmp(&mParent.mData[mOffset], "\0\0\0", 3)) { 646fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 647fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 648fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 649fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameSize = 650fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber (mParent.mData[mOffset + 3] << 16) 651fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber | (mParent.mData[mOffset + 4] << 8) 652fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber | mParent.mData[mOffset + 5]; 653fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 654fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameSize += 6; 655fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 656fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mOffset + mFrameSize > mParent.mSize) { 6573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)", 658fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mOffset, mFrameSize, mParent.mSize - mOffset - 6); 659fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 660fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 661fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 662fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameData = &mParent.mData[mOffset + 6]; 663fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 664fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!mID) { 665fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber break; 666fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 667fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 668fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber char id[4]; 669fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber memcpy(id, &mParent.mData[mOffset], 3); 670fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber id[3] = '\0'; 671fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 672fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!strcmp(id, mID)) { 673fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber break; 674fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 675bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else if (mParent.mVersion == ID3_V2_3 676bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber || mParent.mVersion == ID3_V2_4) { 677fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mOffset + 10 > mParent.mSize) { 678fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 679fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 680fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 681fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!memcmp(&mParent.mData[mOffset], "\0\0\0\0", 4)) { 682fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 683fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 684fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 685bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber size_t baseSize; 686bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (mParent.mVersion == ID3_V2_4) { 687bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (!ParseSyncsafeInteger( 688bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber &mParent.mData[mOffset + 4], &baseSize)) { 689bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber return; 690bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 691bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } else { 692bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber baseSize = U32_AT(&mParent.mData[mOffset + 4]); 693bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 694bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 695bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber mFrameSize = 10 + baseSize; 696fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 697fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mOffset + mFrameSize > mParent.mSize) { 6983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)", 699fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mOffset, mFrameSize, mParent.mSize - mOffset - 10); 700fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return; 701fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 702fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 703bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]); 704bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 705ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000c)) 706bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) { 707ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber // Compression or encryption are not supported at this time. 708ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber // Per-frame unsynchronization and data-length indicator 709ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber // have already been taken care of. 710bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 7113856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Skipping unsupported frame (compression, encryption " 712bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber "or per-frame unsynchronization flagged"); 713bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 714bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber mOffset += mFrameSize; 715bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber continue; 716bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber } 717bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber 718fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mFrameData = &mParent.mData[mOffset + 10]; 719fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 720fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!mID) { 721fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber break; 722fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 723fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 724fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber char id[5]; 725fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber memcpy(id, &mParent.mData[mOffset], 4); 726fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber id[4] = '\0'; 727fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 728fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!strcmp(id, mID)) { 729fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber break; 730fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 73183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } else { 73283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1); 73383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 73483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (mOffset >= mParent.mSize) { 73583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return; 73683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 73783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 73883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameData = &mParent.mData[mOffset]; 73983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 74083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber switch (mOffset) { 74183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 3: 74283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 33: 74383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 63: 74483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameSize = 30; 74583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 74683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 93: 74783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameSize = 4; 74883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 74983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 97: 75083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (mParent.mVersion == ID3_V1) { 75183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameSize = 30; 75283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } else { 75383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameSize = 29; 75483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 75583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 75683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 126: 75783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameSize = 1; 75883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 75983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber case 127: 76083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFrameSize = 1; 76183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 76283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber default: 76383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber CHECK(!"Should not be here, invalid offset."); 76483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 76583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 76683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 76783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (!mID) { 76883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 76983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 77083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 77183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber String8 id; 77283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber getID(&id); 77383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 77483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (id == mID) { 77583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber break; 77683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 777fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 778fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 779fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mOffset += mFrameSize; 780fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 781fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 782fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 783fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic size_t StringSize(const uint8_t *start, uint8_t encoding) { 784bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (encoding == 0x00 || encoding == 0x03) { 785bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber // ISO 8859-1 or UTF-8 786fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return strlen((const char *)start) + 1; 787fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 788fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 789fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // UCS-2 790fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t n = 0; 791fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber while (start[n] != '\0' || start[n + 1] != '\0') { 792fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber n += 2; 793fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 794fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 795be5016bac5c1b422d850e299d3cb11fecf0ac19dJesper Tragardh // Add size of null termination. 796be5016bac5c1b422d850e299d3cb11fecf0ac19dJesper Tragardh return n + 2; 797fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 798fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 799fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst void * 800fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::getAlbumArt(size_t *length, String8 *mime) const { 801fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *length = 0; 802fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mime->setTo(""); 803fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 804bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber Iterator it( 805bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber *this, 806bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) ? "APIC" : "PIC"); 807fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 808fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber while (!it.done()) { 809fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t size; 810fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber const uint8_t *data = it.getData(&size); 811fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 812bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) { 813fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber uint8_t encoding = data[0]; 814fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mime->setTo((const char *)&data[1]); 815fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t mimeLen = strlen((const char *)&data[1]) + 1; 816fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 817fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber uint8_t picType = data[1 + mimeLen]; 818fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0 819fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (picType != 0x03) { 820fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // Front Cover Art 821fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber it.next(); 822fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber continue; 823fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 824fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif 825fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 826fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t descLen = StringSize(&data[2 + mimeLen], encoding); 827fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 828f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen if (size < 2 || 829f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen size - 2 < mimeLen || 830f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen size - 2 - mimeLen < descLen) { 831f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen ALOGW("bogus album art sizes"); 832f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen return NULL; 833f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen } 834fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *length = size - 2 - mimeLen - descLen; 835fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 836fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return &data[2 + mimeLen + descLen]; 837fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else { 838fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber uint8_t encoding = data[0]; 839fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 840fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!memcmp(&data[1], "PNG", 3)) { 841fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mime->setTo("image/png"); 842fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else if (!memcmp(&data[1], "JPG", 3)) { 843fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mime->setTo("image/jpeg"); 844fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else if (!memcmp(&data[1], "-->", 3)) { 845fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mime->setTo("text/plain"); 846fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } else { 847fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return NULL; 848fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 849fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 850fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0 851fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber uint8_t picType = data[4]; 852fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (picType != 0x03) { 853fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // Front Cover Art 854fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber it.next(); 855fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber continue; 856fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 857fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif 858fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 859fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t descLen = StringSize(&data[5], encoding); 860fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 861fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *length = size - 5 - descLen; 862fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 863fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return &data[5 + descLen]; 864fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 865fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 866fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 867fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return NULL; 868fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 869fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 87083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huberbool ID3::parseV1(const sp<DataSource> &source) { 87183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber const size_t V1_TAG_SIZE = 128; 87283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 873c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t size; 874c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (source->getSize(&size) != OK || size < (off64_t)V1_TAG_SIZE) { 87583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return false; 87683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 87783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 87883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mData = (uint8_t *)malloc(V1_TAG_SIZE); 87983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (source->readAt(size - V1_TAG_SIZE, mData, V1_TAG_SIZE) 88083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber != (ssize_t)V1_TAG_SIZE) { 88183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber free(mData); 88283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mData = NULL; 88383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 88483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return false; 88583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 88683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 88783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (memcmp("TAG", mData, 3)) { 88883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber free(mData); 88983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mData = NULL; 89083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 89183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return false; 89283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 89383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 89483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mSize = V1_TAG_SIZE; 89583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mFirstFrameOffset = 3; 89683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 89783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber if (mData[V1_TAG_SIZE - 3] != 0) { 89883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mVersion = ID3_V1; 89983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } else { 90083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber mVersion = ID3_V1_1; 90183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber } 90283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber 90383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber return true; 90483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber} 905fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 906fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} // namespace android 907