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

Commit e2cce813 authored by Chong Zhang's avatar Chong Zhang Committed by Android (Google) Code Review
Browse files

Merge "process all SEI messages for CC extraction"

parents 8f7b7fa4 78acc89e
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