Loading media/libstagefright/timedtext/TextDescriptions.cpp +375 −252 Original line number Diff line number Diff line Loading @@ -30,9 +30,9 @@ status_t TextDescriptions::getParcelOfDescriptions( if (flags & IN_BAND_TEXT_3GPP) { if (flags & GLOBAL_DESCRIPTIONS) { return extract3GPPGlobalDescriptions(data, size, parcel, 0); return extract3GPPGlobalDescriptions(data, size, parcel); } else if (flags & LOCAL_DESCRIPTIONS) { return extract3GPPLocalDescriptions(data, size, timeMs, parcel, 0); return extract3GPPLocalDescriptions(data, size, timeMs, parcel); } } else if (flags & OUT_OF_BAND_TEXT_SRT) { if (flags & LOCAL_DESCRIPTIONS) { Loading Loading @@ -69,49 +69,68 @@ status_t TextDescriptions::extractSRTLocalDescriptions( // styles, and 'krok' box contains karaoke timing and positions. status_t TextDescriptions::extract3GPPLocalDescriptions( const uint8_t *data, ssize_t size, int timeMs, Parcel *parcel, int depth) { if (depth == 0) { int timeMs, Parcel *parcel) { parcel->writeInt32(KEY_LOCAL_SETTING); // write start time to display this text sample parcel->writeInt32(KEY_START_TIME); parcel->writeInt32(timeMs); if (size < 2) { return OK; } ssize_t textLen = (*data) << 8 | (*(data + 1)); if (size < textLen + 2) { return OK; } // write text sample length and text sample itself parcel->writeInt32(KEY_STRUCT_TEXT); parcel->writeInt32(textLen); parcel->writeInt32(textLen); parcel->write(data + 2, textLen); if (size > textLen) { if (size > textLen + 2) { data += (textLen + 2); size -= (textLen + 2); } else { return OK; } } while (size >= 8) { const uint8_t *tmpData = data; ssize_t chunkSize = U32_AT(tmpData); ssize_t chunkSize = U32_AT(tmpData); // size includes size and type uint32_t chunkType = U32_AT(tmpData + 4); if (chunkSize <= 0) { if (chunkSize <= 8 || chunkSize > size) { return OK; } size_t remaining = chunkSize - 8; tmpData += 8; switch(chunkType) { // 'styl' box specifies the style of the text. case FOURCC('s', 't', 'y', 'l'): { if (remaining < 2) { return OK; } size_t dataPos = parcel->dataPosition(); uint16_t count = U16_AT(tmpData); tmpData += 2; remaining -= 2; for (int i = 0; i < count; i++) { if (remaining < 12) { // roll back parcel->setDataPosition(dataPos); return OK; } parcel->writeInt32(KEY_STRUCT_STYLE_LIST); parcel->writeInt32(KEY_START_CHAR); parcel->writeInt32(U16_AT(tmpData)); Loading @@ -134,6 +153,7 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( parcel->writeInt32(rgba); tmpData += 12; remaining -= 12; } break; Loading @@ -143,6 +163,10 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( // time for the event. case FOURCC('k', 'r', 'o', 'k'): { if (remaining < 6) { return OK; } size_t dataPos = parcel->dataPosition(); parcel->writeInt32(KEY_STRUCT_KARAOKE_LIST); Loading @@ -151,9 +175,15 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( parcel->writeInt32(count); tmpData += 6; remaining -= 6; int lastEndTime = 0; for (int i = 0; i < count; i++) { if (remaining < 8) { // roll back parcel->setDataPosition(dataPos); return OK; } parcel->writeInt32(startTime + lastEndTime); lastEndTime = U32_AT(tmpData); Loading @@ -163,6 +193,7 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( parcel->writeInt32(U16_AT(tmpData + 6)); tmpData += 8; remaining -= 8; } break; Loading @@ -170,6 +201,10 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( // 'hlit' box specifies highlighted text case FOURCC('h', 'l', 'i', 't'): { if (remaining < 4) { return OK; } parcel->writeInt32(KEY_STRUCT_HIGHLIGHT_LIST); // the start char offset to highlight Loading @@ -177,35 +212,53 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( // the last char offset to highlight parcel->writeInt32(U16_AT(tmpData + 2)); tmpData += 4; remaining -= 4; break; } // 'hclr' box specifies the RGBA color: 8 bits each of // red, green, blue, and an alpha(transparency) value case FOURCC('h', 'c', 'l', 'r'): { if (remaining < 4) { return OK; } parcel->writeInt32(KEY_HIGHLIGHT_COLOR_RGBA); uint32_t rgba = *(tmpData) << 24 | *(tmpData + 1) << 16 | *(tmpData + 2) << 8 | *(tmpData + 3); parcel->writeInt32(rgba); tmpData += 4; remaining -= 4; break; } // 'dlay' box specifies a delay after a scroll in and/or // before scroll out. case FOURCC('d', 'l', 'a', 'y'): { if (remaining < 4) { return OK; } parcel->writeInt32(KEY_SCROLL_DELAY); uint32_t delay = *(tmpData) << 24 | *(tmpData + 1) << 16 | *(tmpData + 2) << 8 | *(tmpData + 3); parcel->writeInt32(delay); tmpData += 4; remaining -= 4; break; } // 'href' box for hyper text link case FOURCC('h', 'r', 'e', 'f'): { if (remaining < 5) { return OK; } size_t dataPos = parcel->dataPosition(); parcel->writeInt32(KEY_STRUCT_HYPER_TEXT_LIST); // the start offset of the text to be linked Loading @@ -214,40 +267,70 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( parcel->writeInt32(U16_AT(tmpData + 2)); // the number of bytes in the following URL int len = *(tmpData + 4); size_t len = *(tmpData + 4); parcel->writeInt32(len); remaining -= 5; if (remaining < len) { parcel->setDataPosition(dataPos); return OK; } // the linked-to URL parcel->writeInt32(len); parcel->write(tmpData + 5, len); tmpData += (5 + len); remaining -= len; if (remaining < 1) { parcel->setDataPosition(dataPos); return OK; } // the number of bytes in the following "alt" string len = *tmpData; parcel->writeInt32(len); tmpData += 1; remaining -= 1; if (remaining < len) { parcel->setDataPosition(dataPos); return OK; } // an "alt" string for user display parcel->writeInt32(len); parcel->write(tmpData + 1, len); parcel->write(tmpData, len); tmpData += 1; remaining -= 1; break; } // 'tbox' box to indicate the position of the text with values // of top, left, bottom and right case FOURCC('t', 'b', 'o', 'x'): { if (remaining < 8) { return OK; } parcel->writeInt32(KEY_STRUCT_TEXT_POS); parcel->writeInt32(U16_AT(tmpData)); parcel->writeInt32(U16_AT(tmpData + 2)); parcel->writeInt32(U16_AT(tmpData + 4)); parcel->writeInt32(U16_AT(tmpData + 6)); tmpData += 8; remaining -= 8; break; } // 'blnk' to specify the char range to be blinked case FOURCC('b', 'l', 'n', 'k'): { if (remaining < 4) { return OK; } parcel->writeInt32(KEY_STRUCT_BLINKING_TEXT_LIST); // start char offset Loading @@ -255,6 +338,8 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( // end char offset parcel->writeInt32(U16_AT(tmpData + 2)); tmpData += 4; remaining -= 4; break; } // 'twrp' box specifies text wrap behavior. If the value if 0x00, Loading @@ -262,9 +347,14 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( // 0x02-0xff are reserved. case FOURCC('t', 'w', 'r', 'p'): { if (remaining < 1) { return OK; } parcel->writeInt32(KEY_WRAP_TEXT); parcel->writeInt32(*tmpData); tmpData += 1; remaining -= 1; break; } default: Loading @@ -273,11 +363,8 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( } } if (size > chunkSize) { data += chunkSize; size -= chunkSize; // continue to parse next box return extract3GPPLocalDescriptions(data, size, 0, parcel, 1); } return OK; Loading @@ -285,24 +372,28 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( // To extract box 'tx3g' defined in 3GPP TS 26.245, and store it in a Parcel status_t TextDescriptions::extract3GPPGlobalDescriptions( const uint8_t *data, ssize_t size, Parcel *parcel, int depth) { const uint8_t *data, ssize_t size, Parcel *parcel) { parcel->writeInt32(KEY_GLOBAL_SETTING); while (size >= 8) { ssize_t chunkSize = U32_AT(data); uint32_t chunkType = U32_AT(data + 4); const uint8_t *tmpData = data; tmpData += 8; size_t remaining = size - 8; if (size < chunkSize) { return OK; } if (depth == 0) { parcel->writeInt32(KEY_GLOBAL_SETTING); } switch(chunkType) { case FOURCC('t', 'x', '3', 'g'): { if (remaining < 18) { // 8 just below, and another 10 a little further down return OK; } tmpData += 8; // skip the first 8 bytes remaining -=8; parcel->writeInt32(KEY_DISPLAY_FLAGS); parcel->writeInt32(U32_AT(tmpData)); Loading @@ -316,6 +407,11 @@ status_t TextDescriptions::extract3GPPGlobalDescriptions( parcel->writeInt32(rgba); tmpData += 10; remaining -= 10; if (remaining < 8) { return OK; } parcel->writeInt32(KEY_STRUCT_TEXT_POS); parcel->writeInt32(U16_AT(tmpData)); parcel->writeInt32(U16_AT(tmpData + 2)); Loading @@ -323,6 +419,11 @@ status_t TextDescriptions::extract3GPPGlobalDescriptions( parcel->writeInt32(U16_AT(tmpData + 6)); tmpData += 8; remaining -= 8; if (remaining < 12) { return OK; } parcel->writeInt32(KEY_STRUCT_STYLE_LIST); parcel->writeInt32(KEY_START_CHAR); parcel->writeInt32(U16_AT(tmpData)); Loading @@ -345,24 +446,50 @@ status_t TextDescriptions::extract3GPPGlobalDescriptions( parcel->writeInt32(rgba); tmpData += 12; remaining -= 12; if (remaining < 2) { return OK; } size_t dataPos = parcel->dataPosition(); parcel->writeInt32(KEY_STRUCT_FONT_LIST); uint16_t count = U16_AT(tmpData); parcel->writeInt32(count); tmpData += 2; remaining -= 2; for (int i = 0; i < count; i++) { if (remaining < 3) { // roll back parcel->setDataPosition(dataPos); return OK; } // font ID parcel->writeInt32(U16_AT(tmpData)); // font name length parcel->writeInt32(*(tmpData + 2)); int len = *(tmpData + 2); size_t len = *(tmpData + 2); tmpData += 3; remaining -= 3; parcel->write(tmpData + 3, len); tmpData += 3 + len; if (remaining < len) { // roll back parcel->setDataPosition(dataPos); return OK; } parcel->write(tmpData, len); tmpData += len; remaining -= len; } // there is a "DisparityBox" after this according to the spec, but we ignore it break; } default: Loading @@ -373,10 +500,6 @@ status_t TextDescriptions::extract3GPPGlobalDescriptions( data += chunkSize; size -= chunkSize; if (size > 0) { // continue to extract next 'tx3g' return extract3GPPGlobalDescriptions(data, size, parcel, 1); } return OK; Loading media/libstagefright/timedtext/TextDescriptions.h +2 −2 Original line number Diff line number Diff line Loading @@ -72,10 +72,10 @@ private: int timeMs, Parcel *parcel); static status_t extract3GPPGlobalDescriptions( const uint8_t *data, ssize_t size, Parcel *parcel, int depth); Parcel *parcel); static status_t extract3GPPLocalDescriptions( const uint8_t *data, ssize_t size, int timeMs, Parcel *parcel, int depth); int timeMs, Parcel *parcel); DISALLOW_EVIL_CONSTRUCTORS(TextDescriptions); }; Loading Loading
media/libstagefright/timedtext/TextDescriptions.cpp +375 −252 Original line number Diff line number Diff line Loading @@ -30,9 +30,9 @@ status_t TextDescriptions::getParcelOfDescriptions( if (flags & IN_BAND_TEXT_3GPP) { if (flags & GLOBAL_DESCRIPTIONS) { return extract3GPPGlobalDescriptions(data, size, parcel, 0); return extract3GPPGlobalDescriptions(data, size, parcel); } else if (flags & LOCAL_DESCRIPTIONS) { return extract3GPPLocalDescriptions(data, size, timeMs, parcel, 0); return extract3GPPLocalDescriptions(data, size, timeMs, parcel); } } else if (flags & OUT_OF_BAND_TEXT_SRT) { if (flags & LOCAL_DESCRIPTIONS) { Loading Loading @@ -69,49 +69,68 @@ status_t TextDescriptions::extractSRTLocalDescriptions( // styles, and 'krok' box contains karaoke timing and positions. status_t TextDescriptions::extract3GPPLocalDescriptions( const uint8_t *data, ssize_t size, int timeMs, Parcel *parcel, int depth) { if (depth == 0) { int timeMs, Parcel *parcel) { parcel->writeInt32(KEY_LOCAL_SETTING); // write start time to display this text sample parcel->writeInt32(KEY_START_TIME); parcel->writeInt32(timeMs); if (size < 2) { return OK; } ssize_t textLen = (*data) << 8 | (*(data + 1)); if (size < textLen + 2) { return OK; } // write text sample length and text sample itself parcel->writeInt32(KEY_STRUCT_TEXT); parcel->writeInt32(textLen); parcel->writeInt32(textLen); parcel->write(data + 2, textLen); if (size > textLen) { if (size > textLen + 2) { data += (textLen + 2); size -= (textLen + 2); } else { return OK; } } while (size >= 8) { const uint8_t *tmpData = data; ssize_t chunkSize = U32_AT(tmpData); ssize_t chunkSize = U32_AT(tmpData); // size includes size and type uint32_t chunkType = U32_AT(tmpData + 4); if (chunkSize <= 0) { if (chunkSize <= 8 || chunkSize > size) { return OK; } size_t remaining = chunkSize - 8; tmpData += 8; switch(chunkType) { // 'styl' box specifies the style of the text. case FOURCC('s', 't', 'y', 'l'): { if (remaining < 2) { return OK; } size_t dataPos = parcel->dataPosition(); uint16_t count = U16_AT(tmpData); tmpData += 2; remaining -= 2; for (int i = 0; i < count; i++) { if (remaining < 12) { // roll back parcel->setDataPosition(dataPos); return OK; } parcel->writeInt32(KEY_STRUCT_STYLE_LIST); parcel->writeInt32(KEY_START_CHAR); parcel->writeInt32(U16_AT(tmpData)); Loading @@ -134,6 +153,7 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( parcel->writeInt32(rgba); tmpData += 12; remaining -= 12; } break; Loading @@ -143,6 +163,10 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( // time for the event. case FOURCC('k', 'r', 'o', 'k'): { if (remaining < 6) { return OK; } size_t dataPos = parcel->dataPosition(); parcel->writeInt32(KEY_STRUCT_KARAOKE_LIST); Loading @@ -151,9 +175,15 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( parcel->writeInt32(count); tmpData += 6; remaining -= 6; int lastEndTime = 0; for (int i = 0; i < count; i++) { if (remaining < 8) { // roll back parcel->setDataPosition(dataPos); return OK; } parcel->writeInt32(startTime + lastEndTime); lastEndTime = U32_AT(tmpData); Loading @@ -163,6 +193,7 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( parcel->writeInt32(U16_AT(tmpData + 6)); tmpData += 8; remaining -= 8; } break; Loading @@ -170,6 +201,10 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( // 'hlit' box specifies highlighted text case FOURCC('h', 'l', 'i', 't'): { if (remaining < 4) { return OK; } parcel->writeInt32(KEY_STRUCT_HIGHLIGHT_LIST); // the start char offset to highlight Loading @@ -177,35 +212,53 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( // the last char offset to highlight parcel->writeInt32(U16_AT(tmpData + 2)); tmpData += 4; remaining -= 4; break; } // 'hclr' box specifies the RGBA color: 8 bits each of // red, green, blue, and an alpha(transparency) value case FOURCC('h', 'c', 'l', 'r'): { if (remaining < 4) { return OK; } parcel->writeInt32(KEY_HIGHLIGHT_COLOR_RGBA); uint32_t rgba = *(tmpData) << 24 | *(tmpData + 1) << 16 | *(tmpData + 2) << 8 | *(tmpData + 3); parcel->writeInt32(rgba); tmpData += 4; remaining -= 4; break; } // 'dlay' box specifies a delay after a scroll in and/or // before scroll out. case FOURCC('d', 'l', 'a', 'y'): { if (remaining < 4) { return OK; } parcel->writeInt32(KEY_SCROLL_DELAY); uint32_t delay = *(tmpData) << 24 | *(tmpData + 1) << 16 | *(tmpData + 2) << 8 | *(tmpData + 3); parcel->writeInt32(delay); tmpData += 4; remaining -= 4; break; } // 'href' box for hyper text link case FOURCC('h', 'r', 'e', 'f'): { if (remaining < 5) { return OK; } size_t dataPos = parcel->dataPosition(); parcel->writeInt32(KEY_STRUCT_HYPER_TEXT_LIST); // the start offset of the text to be linked Loading @@ -214,40 +267,70 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( parcel->writeInt32(U16_AT(tmpData + 2)); // the number of bytes in the following URL int len = *(tmpData + 4); size_t len = *(tmpData + 4); parcel->writeInt32(len); remaining -= 5; if (remaining < len) { parcel->setDataPosition(dataPos); return OK; } // the linked-to URL parcel->writeInt32(len); parcel->write(tmpData + 5, len); tmpData += (5 + len); remaining -= len; if (remaining < 1) { parcel->setDataPosition(dataPos); return OK; } // the number of bytes in the following "alt" string len = *tmpData; parcel->writeInt32(len); tmpData += 1; remaining -= 1; if (remaining < len) { parcel->setDataPosition(dataPos); return OK; } // an "alt" string for user display parcel->writeInt32(len); parcel->write(tmpData + 1, len); parcel->write(tmpData, len); tmpData += 1; remaining -= 1; break; } // 'tbox' box to indicate the position of the text with values // of top, left, bottom and right case FOURCC('t', 'b', 'o', 'x'): { if (remaining < 8) { return OK; } parcel->writeInt32(KEY_STRUCT_TEXT_POS); parcel->writeInt32(U16_AT(tmpData)); parcel->writeInt32(U16_AT(tmpData + 2)); parcel->writeInt32(U16_AT(tmpData + 4)); parcel->writeInt32(U16_AT(tmpData + 6)); tmpData += 8; remaining -= 8; break; } // 'blnk' to specify the char range to be blinked case FOURCC('b', 'l', 'n', 'k'): { if (remaining < 4) { return OK; } parcel->writeInt32(KEY_STRUCT_BLINKING_TEXT_LIST); // start char offset Loading @@ -255,6 +338,8 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( // end char offset parcel->writeInt32(U16_AT(tmpData + 2)); tmpData += 4; remaining -= 4; break; } // 'twrp' box specifies text wrap behavior. If the value if 0x00, Loading @@ -262,9 +347,14 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( // 0x02-0xff are reserved. case FOURCC('t', 'w', 'r', 'p'): { if (remaining < 1) { return OK; } parcel->writeInt32(KEY_WRAP_TEXT); parcel->writeInt32(*tmpData); tmpData += 1; remaining -= 1; break; } default: Loading @@ -273,11 +363,8 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( } } if (size > chunkSize) { data += chunkSize; size -= chunkSize; // continue to parse next box return extract3GPPLocalDescriptions(data, size, 0, parcel, 1); } return OK; Loading @@ -285,24 +372,28 @@ status_t TextDescriptions::extract3GPPLocalDescriptions( // To extract box 'tx3g' defined in 3GPP TS 26.245, and store it in a Parcel status_t TextDescriptions::extract3GPPGlobalDescriptions( const uint8_t *data, ssize_t size, Parcel *parcel, int depth) { const uint8_t *data, ssize_t size, Parcel *parcel) { parcel->writeInt32(KEY_GLOBAL_SETTING); while (size >= 8) { ssize_t chunkSize = U32_AT(data); uint32_t chunkType = U32_AT(data + 4); const uint8_t *tmpData = data; tmpData += 8; size_t remaining = size - 8; if (size < chunkSize) { return OK; } if (depth == 0) { parcel->writeInt32(KEY_GLOBAL_SETTING); } switch(chunkType) { case FOURCC('t', 'x', '3', 'g'): { if (remaining < 18) { // 8 just below, and another 10 a little further down return OK; } tmpData += 8; // skip the first 8 bytes remaining -=8; parcel->writeInt32(KEY_DISPLAY_FLAGS); parcel->writeInt32(U32_AT(tmpData)); Loading @@ -316,6 +407,11 @@ status_t TextDescriptions::extract3GPPGlobalDescriptions( parcel->writeInt32(rgba); tmpData += 10; remaining -= 10; if (remaining < 8) { return OK; } parcel->writeInt32(KEY_STRUCT_TEXT_POS); parcel->writeInt32(U16_AT(tmpData)); parcel->writeInt32(U16_AT(tmpData + 2)); Loading @@ -323,6 +419,11 @@ status_t TextDescriptions::extract3GPPGlobalDescriptions( parcel->writeInt32(U16_AT(tmpData + 6)); tmpData += 8; remaining -= 8; if (remaining < 12) { return OK; } parcel->writeInt32(KEY_STRUCT_STYLE_LIST); parcel->writeInt32(KEY_START_CHAR); parcel->writeInt32(U16_AT(tmpData)); Loading @@ -345,24 +446,50 @@ status_t TextDescriptions::extract3GPPGlobalDescriptions( parcel->writeInt32(rgba); tmpData += 12; remaining -= 12; if (remaining < 2) { return OK; } size_t dataPos = parcel->dataPosition(); parcel->writeInt32(KEY_STRUCT_FONT_LIST); uint16_t count = U16_AT(tmpData); parcel->writeInt32(count); tmpData += 2; remaining -= 2; for (int i = 0; i < count; i++) { if (remaining < 3) { // roll back parcel->setDataPosition(dataPos); return OK; } // font ID parcel->writeInt32(U16_AT(tmpData)); // font name length parcel->writeInt32(*(tmpData + 2)); int len = *(tmpData + 2); size_t len = *(tmpData + 2); tmpData += 3; remaining -= 3; parcel->write(tmpData + 3, len); tmpData += 3 + len; if (remaining < len) { // roll back parcel->setDataPosition(dataPos); return OK; } parcel->write(tmpData, len); tmpData += len; remaining -= len; } // there is a "DisparityBox" after this according to the spec, but we ignore it break; } default: Loading @@ -373,10 +500,6 @@ status_t TextDescriptions::extract3GPPGlobalDescriptions( data += chunkSize; size -= chunkSize; if (size > 0) { // continue to extract next 'tx3g' return extract3GPPGlobalDescriptions(data, size, parcel, 1); } return OK; Loading
media/libstagefright/timedtext/TextDescriptions.h +2 −2 Original line number Diff line number Diff line Loading @@ -72,10 +72,10 @@ private: int timeMs, Parcel *parcel); static status_t extract3GPPGlobalDescriptions( const uint8_t *data, ssize_t size, Parcel *parcel, int depth); Parcel *parcel); static status_t extract3GPPLocalDescriptions( const uint8_t *data, ssize_t size, int timeMs, Parcel *parcel, int depth); int timeMs, Parcel *parcel); DISALLOW_EVIL_CONSTRUCTORS(TextDescriptions); }; Loading