Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7d34959b authored by Marco Nelissen's avatar Marco Nelissen Committed by Android Git Automerger
Browse files

am 16e12007: am 74888428: Merge "Fix timedtext parsing" into klp-dev

* commit '16e12007':
  Fix timedtext parsing
parents 75143f30 16e12007
Loading
Loading
Loading
Loading
+375 −252
Original line number Diff line number Diff line
@@ -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) {
@@ -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));
@@ -134,6 +153,7 @@ status_t TextDescriptions::extract3GPPLocalDescriptions(
                    parcel->writeInt32(rgba);

                    tmpData += 12;
                    remaining -= 12;
                }

                break;
@@ -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);

@@ -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);
@@ -163,6 +193,7 @@ status_t TextDescriptions::extract3GPPLocalDescriptions(
                    parcel->writeInt32(U16_AT(tmpData + 6));

                    tmpData += 8;
                    remaining -= 8;
                }

                break;
@@ -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
@@ -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
@@ -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
@@ -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,
@@ -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:
@@ -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;
@@ -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));

@@ -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));
@@ -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));
@@ -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:
@@ -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;
+2 −2
Original line number Diff line number Diff line
@@ -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);
};