Loading media/libstagefright/id3/ID3.cpp +114 −23 Original line number Diff line number Diff line Loading @@ -58,6 +58,20 @@ ID3::Version ID3::version() const { return mVersion; } // static bool ID3::ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x) { *x = 0; for (int32_t i = 0; i < 4; ++i) { if (encoded[i] & 0x80) { return false; } *x = ((*x) << 7) | encoded[i]; } return true; } bool ID3::parseV2(const sp<DataSource> &source) { struct id3_header { char id[3]; Loading Loading @@ -100,17 +114,18 @@ bool ID3::parseV2(const sp<DataSource> &source) { // set, we cannot guarantee to understand the tag format. return false; } } else { } else if (header.version_major == 4) { if (header.flags & 0x0f) { // The lower 4 bits are undefined in this spec. return false; } size_t size = 0; for (int32_t i = 0; i < 4; ++i) { if (header.enc_size[i] & 0x80) { } else { return false; } size = (size << 7) | header.enc_size[i]; size_t size; if (!ParseSyncsafeInteger(header.enc_size, &size)) { return false; } if (size > kMaxMetadataSize) { Loading Loading @@ -178,13 +193,42 @@ bool ID3::parseV2(const sp<DataSource> &source) { LOGV("have crc"); } } } else if (header.version_major == 4 && (header.flags & 0x40)) { // Version 2.4 has an optional extended header, that's different // from Version 2.3's... if (mSize < 4) { free(mData); mData = NULL; return false; } size_t ext_size; if (!ParseSyncsafeInteger(mData, &ext_size)) { free(mData); mData = NULL; return false; } if (ext_size < 6 || ext_size > mSize) { free(mData); mData = NULL; return false; } mFirstFrameOffset = ext_size; } if (header.version_major == 2) { mVersion = ID3_V2_2; } else { CHECK_EQ(header.version_major, 3); } else if (header.version_major == 3) { mVersion = ID3_V2_3; } else { CHECK_EQ(header.version_major, 4); mVersion = ID3_V2_4; } return true; Loading Loading @@ -242,7 +286,7 @@ void ID3::Iterator::getID(String8 *id) const { if (mParent.mVersion == ID3_V2_2) { id->setTo((const char *)&mParent.mData[mOffset], 3); } else if (mParent.mVersion == ID3_V2_3) { } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) { id->setTo((const char *)&mParent.mData[mOffset], 4); } else { CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1); Loading Loading @@ -346,6 +390,26 @@ void ID3::Iterator::getString(String8 *id) const { if (*mFrameData == 0x00) { // ISO 8859-1 convertISO8859ToString8(mFrameData + 1, n, id); } else if (*mFrameData == 0x03) { // UTF-8 id->setTo((const char *)(mFrameData + 1), n); } else if (*mFrameData == 0x02) { // UTF-16 BE, no byte order mark. // API wants number of characters, not number of bytes... int len = n / 2; const char16_t *framedata = (const char16_t *) (mFrameData + 1); char16_t *framedatacopy = NULL; #if BYTE_ORDER == LITTLE_ENDIAN framedatacopy = new char16_t[len]; for (int i = 0; i < len; i++) { framedatacopy[i] = bswap_16(framedata[i]); } framedata = framedatacopy; #endif id->setTo(framedata, len); if (framedatacopy != NULL) { delete[] framedatacopy; } } else { // UCS-2 // API wants number of characters, not number of bytes... Loading Loading @@ -387,7 +451,7 @@ const uint8_t *ID3::Iterator::getData(size_t *length) const { size_t ID3::Iterator::getHeaderLength() const { if (mParent.mVersion == ID3_V2_2) { return 6; } else if (mParent.mVersion == ID3_V2_3) { } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) { return 10; } else { CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1); Loading Loading @@ -435,7 +499,8 @@ void ID3::Iterator::findFrame() { if (!strcmp(id, mID)) { break; } } else if (mParent.mVersion == ID3_V2_3) { } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) { if (mOffset + 10 > mParent.mSize) { return; } Loading @@ -444,7 +509,17 @@ void ID3::Iterator::findFrame() { return; } mFrameSize = 10 + U32_AT(&mParent.mData[mOffset + 4]); size_t baseSize; if (mParent.mVersion == ID3_V2_4) { if (!ParseSyncsafeInteger( &mParent.mData[mOffset + 4], &baseSize)) { return; } } else { baseSize = U32_AT(&mParent.mData[mOffset + 4]); } mFrameSize = 10 + baseSize; if (mOffset + mFrameSize > mParent.mSize) { LOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)", Loading @@ -452,6 +527,20 @@ void ID3::Iterator::findFrame() { return; } uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]); if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000e)) || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) { // Compression, Encryption or per-Frame unsynchronization // are not supported at this time. LOGV("Skipping unsupported frame (compression, encryption " "or per-frame unsynchronization flagged"); mOffset += mFrameSize; continue; } mFrameData = &mParent.mData[mOffset + 10]; if (!mID) { Loading Loading @@ -518,8 +607,8 @@ void ID3::Iterator::findFrame() { } static size_t StringSize(const uint8_t *start, uint8_t encoding) { if (encoding== 0x00) { // ISO 8859-1 if (encoding == 0x00 || encoding == 0x03) { // ISO 8859-1 or UTF-8 return strlen((const char *)start) + 1; } Loading @@ -537,13 +626,15 @@ ID3::getAlbumArt(size_t *length, String8 *mime) const { *length = 0; mime->setTo(""); Iterator it(*this, mVersion == ID3_V2_3 ? "APIC" : "PIC"); Iterator it( *this, (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) ? "APIC" : "PIC"); while (!it.done()) { size_t size; const uint8_t *data = it.getData(&size); if (mVersion == ID3_V2_3) { if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) { uint8_t encoding = data[0]; mime->setTo((const char *)&data[1]); size_t mimeLen = strlen((const char *)&data[1]) + 1; Loading media/libstagefright/include/ID3.h +4 −1 Original line number Diff line number Diff line Loading @@ -31,7 +31,8 @@ struct ID3 { ID3_V1, ID3_V1_1, ID3_V2_2, ID3_V2_3 ID3_V2_3, ID3_V2_4, }; ID3(const sp<DataSource> &source); Loading Loading @@ -80,6 +81,8 @@ private: bool parseV2(const sp<DataSource> &source); void removeUnsynchronization(); static bool ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x); ID3(const ID3 &); ID3 &operator=(const ID3 &); }; Loading Loading
media/libstagefright/id3/ID3.cpp +114 −23 Original line number Diff line number Diff line Loading @@ -58,6 +58,20 @@ ID3::Version ID3::version() const { return mVersion; } // static bool ID3::ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x) { *x = 0; for (int32_t i = 0; i < 4; ++i) { if (encoded[i] & 0x80) { return false; } *x = ((*x) << 7) | encoded[i]; } return true; } bool ID3::parseV2(const sp<DataSource> &source) { struct id3_header { char id[3]; Loading Loading @@ -100,17 +114,18 @@ bool ID3::parseV2(const sp<DataSource> &source) { // set, we cannot guarantee to understand the tag format. return false; } } else { } else if (header.version_major == 4) { if (header.flags & 0x0f) { // The lower 4 bits are undefined in this spec. return false; } size_t size = 0; for (int32_t i = 0; i < 4; ++i) { if (header.enc_size[i] & 0x80) { } else { return false; } size = (size << 7) | header.enc_size[i]; size_t size; if (!ParseSyncsafeInteger(header.enc_size, &size)) { return false; } if (size > kMaxMetadataSize) { Loading Loading @@ -178,13 +193,42 @@ bool ID3::parseV2(const sp<DataSource> &source) { LOGV("have crc"); } } } else if (header.version_major == 4 && (header.flags & 0x40)) { // Version 2.4 has an optional extended header, that's different // from Version 2.3's... if (mSize < 4) { free(mData); mData = NULL; return false; } size_t ext_size; if (!ParseSyncsafeInteger(mData, &ext_size)) { free(mData); mData = NULL; return false; } if (ext_size < 6 || ext_size > mSize) { free(mData); mData = NULL; return false; } mFirstFrameOffset = ext_size; } if (header.version_major == 2) { mVersion = ID3_V2_2; } else { CHECK_EQ(header.version_major, 3); } else if (header.version_major == 3) { mVersion = ID3_V2_3; } else { CHECK_EQ(header.version_major, 4); mVersion = ID3_V2_4; } return true; Loading Loading @@ -242,7 +286,7 @@ void ID3::Iterator::getID(String8 *id) const { if (mParent.mVersion == ID3_V2_2) { id->setTo((const char *)&mParent.mData[mOffset], 3); } else if (mParent.mVersion == ID3_V2_3) { } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) { id->setTo((const char *)&mParent.mData[mOffset], 4); } else { CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1); Loading Loading @@ -346,6 +390,26 @@ void ID3::Iterator::getString(String8 *id) const { if (*mFrameData == 0x00) { // ISO 8859-1 convertISO8859ToString8(mFrameData + 1, n, id); } else if (*mFrameData == 0x03) { // UTF-8 id->setTo((const char *)(mFrameData + 1), n); } else if (*mFrameData == 0x02) { // UTF-16 BE, no byte order mark. // API wants number of characters, not number of bytes... int len = n / 2; const char16_t *framedata = (const char16_t *) (mFrameData + 1); char16_t *framedatacopy = NULL; #if BYTE_ORDER == LITTLE_ENDIAN framedatacopy = new char16_t[len]; for (int i = 0; i < len; i++) { framedatacopy[i] = bswap_16(framedata[i]); } framedata = framedatacopy; #endif id->setTo(framedata, len); if (framedatacopy != NULL) { delete[] framedatacopy; } } else { // UCS-2 // API wants number of characters, not number of bytes... Loading Loading @@ -387,7 +451,7 @@ const uint8_t *ID3::Iterator::getData(size_t *length) const { size_t ID3::Iterator::getHeaderLength() const { if (mParent.mVersion == ID3_V2_2) { return 6; } else if (mParent.mVersion == ID3_V2_3) { } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) { return 10; } else { CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1); Loading Loading @@ -435,7 +499,8 @@ void ID3::Iterator::findFrame() { if (!strcmp(id, mID)) { break; } } else if (mParent.mVersion == ID3_V2_3) { } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) { if (mOffset + 10 > mParent.mSize) { return; } Loading @@ -444,7 +509,17 @@ void ID3::Iterator::findFrame() { return; } mFrameSize = 10 + U32_AT(&mParent.mData[mOffset + 4]); size_t baseSize; if (mParent.mVersion == ID3_V2_4) { if (!ParseSyncsafeInteger( &mParent.mData[mOffset + 4], &baseSize)) { return; } } else { baseSize = U32_AT(&mParent.mData[mOffset + 4]); } mFrameSize = 10 + baseSize; if (mOffset + mFrameSize > mParent.mSize) { LOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)", Loading @@ -452,6 +527,20 @@ void ID3::Iterator::findFrame() { return; } uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]); if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000e)) || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) { // Compression, Encryption or per-Frame unsynchronization // are not supported at this time. LOGV("Skipping unsupported frame (compression, encryption " "or per-frame unsynchronization flagged"); mOffset += mFrameSize; continue; } mFrameData = &mParent.mData[mOffset + 10]; if (!mID) { Loading Loading @@ -518,8 +607,8 @@ void ID3::Iterator::findFrame() { } static size_t StringSize(const uint8_t *start, uint8_t encoding) { if (encoding== 0x00) { // ISO 8859-1 if (encoding == 0x00 || encoding == 0x03) { // ISO 8859-1 or UTF-8 return strlen((const char *)start) + 1; } Loading @@ -537,13 +626,15 @@ ID3::getAlbumArt(size_t *length, String8 *mime) const { *length = 0; mime->setTo(""); Iterator it(*this, mVersion == ID3_V2_3 ? "APIC" : "PIC"); Iterator it( *this, (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) ? "APIC" : "PIC"); while (!it.done()) { size_t size; const uint8_t *data = it.getData(&size); if (mVersion == ID3_V2_3) { if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) { uint8_t encoding = data[0]; mime->setTo((const char *)&data[1]); size_t mimeLen = strlen((const char *)&data[1]) + 1; Loading
media/libstagefright/include/ID3.h +4 −1 Original line number Diff line number Diff line Loading @@ -31,7 +31,8 @@ struct ID3 { ID3_V1, ID3_V1_1, ID3_V2_2, ID3_V2_3 ID3_V2_3, ID3_V2_4, }; ID3(const sp<DataSource> &source); Loading Loading @@ -80,6 +81,8 @@ private: bool parseV2(const sp<DataSource> &source); void removeUnsynchronization(); static bool ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x); ID3(const ID3 &); ID3 &operator=(const ID3 &); }; Loading