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

Commit 78acc89e authored by Chong Zhang's avatar Chong Zhang
Browse files

process all SEI messages for CC extraction

bug: 19297083
Change-Id: I5b89e35cc2bd5fb2f332872941e7978f15a6f403
parent 9fdb3bd4
Loading
Loading
Loading
Loading
+47 −19
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <inttypes.h>

#include "avc_utils.h"
#include "NuPlayerCCDecoder.h"

#include <media/stagefright/foundation/ABitReader.h>
@@ -185,17 +186,38 @@ int32_t NuPlayer::CCDecoder::getTrackIndex(size_t channel) const {

// returns true if a new CC track is found
bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
    int64_t timeUs;
    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));

    sp<ABuffer> sei;
    if (!accessUnit->meta()->findBuffer("sei", &sei) || sei == NULL) {
        return false;
    }

    int64_t timeUs;
    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));

    bool trackAdded = false;

    NALBitReader br(sei->data() + 1, sei->size() - 1);
    const NALPosition *nal = (NALPosition *) sei->data();

    for (size_t i = 0; i < sei->size() / sizeof(NALPosition); ++i, ++nal) {
        trackAdded |= parseSEINalUnit(
                timeUs, accessUnit->data() + nal->nalOffset, nal->nalSize);
    }

    return trackAdded;
}

// returns true if a new CC track is found
bool NuPlayer::CCDecoder::parseSEINalUnit(
        int64_t timeUs, const uint8_t *nalStart, size_t nalSize) {
    unsigned nalType = nalStart[0] & 0x1f;

    // the buffer should only have SEI in it
    if (nalType != 6) {
        return false;
    }

    bool trackAdded = false;
    NALBitReader br(nalStart + 1, nalSize - 1);
    // sei_message()
    while (br.atLeastNumBitsLeft(16)) { // at least 16-bit for sei_message()
        uint32_t payload_type = 0;
@@ -214,6 +236,8 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {

        // sei_payload()
        if (payload_type == 4) {
            bool isCC = false;
            if (payload_size > 1 + 2 + 4 + 1) {
                // user_data_registered_itu_t_t35()

                // ATSC A/72: 6.4.2
@@ -224,10 +248,13 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {

                payload_size -= 1 + 2 + 4 + 1;

            if (itu_t_t35_country_code == 0xB5
                isCC = itu_t_t35_country_code == 0xB5
                        && itu_t_t35_provider_code == 0x0031
                        && user_identifier == 'GA94'
                    && user_data_type_code == 0x3) {
                        && user_data_type_code == 0x3;
            }

            if (isCC && payload_size > 2) {
                // MPEG_cc_data()
                // ATSC A/53 Part 4: 6.2.3.1
                br.skipBits(1); //process_em_data_flag
@@ -243,7 +270,7 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
                    sp<ABuffer> ccBuf = new ABuffer(cc_count * sizeof(CCData));
                    ccBuf->setRange(0, 0);

                    for (size_t i = 0; i < cc_count; i++) {
                    for (size_t i = 0; i < cc_count && payload_size >= 3; i++) {
                        uint8_t marker = br.getBits(5);
                        CHECK_EQ(marker, 0x1f);

@@ -253,6 +280,8 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
                        uint8_t cc_data_1 = br.getBits(8) & 0x7f;
                        uint8_t cc_data_2 = br.getBits(8) & 0x7f;

                        payload_size -= 3;

                        if (cc_valid
                                && (cc_type == 0 || cc_type == 1)) {
                            CCData cc(cc_type, cc_data_1, cc_data_2);
@@ -269,7 +298,6 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
                            }
                        }
                    }
                    payload_size -= cc_count * 3;

                    mCCMap.add(timeUs, ccBuf);
                    break;
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ private:
    bool isTrackValid(size_t index) const;
    int32_t getTrackIndex(size_t channel) const;
    bool extractFromSEI(const sp<ABuffer> &accessUnit);
    bool parseSEINalUnit(int64_t timeUs, const uint8_t *nalStart, size_t nalSize);
    sp<ABuffer> filterCCBuf(const sp<ABuffer> &ccBuf, size_t index);

    DISALLOW_EVIL_CONSTRUCTORS(CCDecoder);
+5 −0
Original line number Diff line number Diff line
@@ -36,6 +36,11 @@ enum {
    kAVCProfileCAVLC444Intra = 0x2c
};

struct NALPosition {
    size_t nalOffset;
    size_t nalSize;
};

// Optionally returns sample aspect ratio as well.
void FindAVCDimensions(
        const sp<ABuffer> &seqParamSet,
+16 −9
Original line number Diff line number Diff line
@@ -730,11 +730,6 @@ int64_t ElementaryStreamQueue::fetchTimestamp(size_t size) {
    return timeUs;
}

struct NALPosition {
    size_t nalOffset;
    size_t nalSize;
};

sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() {
    const uint8_t *data = mBuffer->data();

@@ -742,6 +737,7 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() {
    Vector<NALPosition> nals;

    size_t totalSize = 0;
    size_t seiCount = 0;

    status_t err;
    const uint8_t *nalStart;
@@ -771,6 +767,9 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() {
            // next frame.

            flush = true;
        } else if (nalType == 6 && nalSize > 0) {
            // found non-zero sized SEI
            ++seiCount;
        }

        if (flush) {
@@ -779,21 +778,29 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() {

            size_t auSize = 4 * nals.size() + totalSize;
            sp<ABuffer> accessUnit = new ABuffer(auSize);
            sp<ABuffer> sei;

            if (seiCount > 0) {
                sei = new ABuffer(seiCount * sizeof(NALPosition));
                accessUnit->meta()->setBuffer("sei", sei);
            }

#if !LOG_NDEBUG
            AString out;
#endif

            size_t dstOffset = 0;
            size_t seiIndex = 0;
            for (size_t i = 0; i < nals.size(); ++i) {
                const NALPosition &pos = nals.itemAt(i);

                unsigned nalType = mBuffer->data()[pos.nalOffset] & 0x1f;

                if (nalType == 6) {
                    sp<ABuffer> sei = new ABuffer(pos.nalSize);
                    memcpy(sei->data(), mBuffer->data() + pos.nalOffset, pos.nalSize);
                    accessUnit->meta()->setBuffer("sei", sei);
                if (nalType == 6 && pos.nalSize > 0) {
                    CHECK_LT(seiIndex, sei->size() / sizeof(NALPosition));
                    NALPosition &seiPos = ((NALPosition *)sei->data())[seiIndex++];
                    seiPos.nalOffset = dstOffset + 4;
                    seiPos.nalSize = pos.nalSize;
                }

#if !LOG_NDEBUG