STATUS depayH264FromRtpPayload()

in libraries/amazon/amazon-kinesis-video-streams-webrtc-sdk-c/patch/src/source/Rtp/Codecs/RtpH264Payloader.c [304:453]


STATUS depayH264FromRtpPayload(PBYTE pRawPacket, UINT32 packetLength, PBYTE pNaluData, PUINT32 pNaluLength, PBOOL pIsStart)
{
    ENTERS();
    STATUS retStatus = STATUS_SUCCESS;
    UINT32 naluLength = 0;
    UINT8 naluType = 0;
    UINT8 naluRefIdc = 0;
    UINT8 indicator = 0;
    BOOL sizeCalculationOnly = (pNaluData == NULL);
    BOOL isStartingPacket = FALSE;
    PBYTE pCurPtr = pRawPacket;
    static BYTE start4ByteCode[] = {0x00, 0x00, 0x00, 0x01};
    UINT16 subNaluSize = 0;

    CHK(pRawPacket != NULL && pNaluLength != NULL, STATUS_NULL_ARG);
    CHK(packetLength > 0, retStatus);

    // TODO: Add support for Aggregate Packets https://tools.ietf.org/html/rfc6184#section-5.7
    // indicator for types https://tools.ietf.org/html/rfc3984#section-5.2
    indicator = *pRawPacket & NAL_TYPE_MASK;
    switch (indicator) {
        case FU_A_INDICATOR:
            // FU-A indicator
            naluRefIdc = *pCurPtr & 0x60;
            pCurPtr++;
            naluType = *pCurPtr & 0x1f;
            isStartingPacket = (*pCurPtr & (1 << 7)) != 0;
            if (isStartingPacket) {
                naluLength = packetLength - FU_A_HEADER_SIZE + 1;
            } else {
                naluLength = packetLength - FU_A_HEADER_SIZE;
            }
            break;
        case FU_B_INDICATOR:
            // FU-B indicator
            naluLength = packetLength - FU_A_HEADER_SIZE + 1;
            break;
        case STAP_A_INDICATOR:
            pCurPtr += STAP_A_HEADER_SIZE;
            do {
                subNaluSize = getUnalignedInt16BigEndian(pCurPtr);
                pCurPtr += SIZEOF(UINT16);
                naluLength += subNaluSize + SIZEOF(start4ByteCode);
                pCurPtr += subNaluSize;
            } while (subNaluSize > 0 && pCurPtr < pRawPacket + packetLength);
            isStartingPacket = TRUE;
            break;
        case STAP_B_INDICATOR:
            pCurPtr += STAP_B_HEADER_SIZE;
            do {
                subNaluSize = getUnalignedInt16BigEndian(pCurPtr);
                pCurPtr += SIZEOF(UINT16);
                naluLength += subNaluSize + SIZEOF(start4ByteCode);
                pCurPtr += subNaluSize;
            } while (subNaluSize > 0 && pCurPtr < pRawPacket + packetLength);
            isStartingPacket = TRUE;
            break;
        default:
            // Single NALU https://tools.ietf.org/html/rfc6184#section-5.6
            naluLength = packetLength;
            isStartingPacket = TRUE;
    }

    if (isStartingPacket && indicator != STAP_A_INDICATOR && indicator != STAP_B_INDICATOR) {
        naluLength += SIZEOF(start4ByteCode);
    }

    // Only return size if given buffer is NULL
    CHK(!sizeCalculationOnly, retStatus);
    CHK(naluLength <= *pNaluLength, STATUS_BUFFER_TOO_SMALL);

    if (isStartingPacket && indicator != STAP_A_INDICATOR && indicator != STAP_B_INDICATOR) {
        MEMCPY(pNaluData, start4ByteCode, SIZEOF(start4ByteCode));
        naluLength -= SIZEOF(start4ByteCode);
        pNaluData += SIZEOF(start4ByteCode);
    }
    switch (indicator) {
        case FU_A_INDICATOR:
            DLOGS("FU_A_INDICATOR starting packet %d len %d", isStartingPacket, naluLength);
            if (isStartingPacket) {
                MEMCPY(pNaluData + 1, pRawPacket + FU_A_HEADER_SIZE, naluLength - 1);
                *pNaluData = naluRefIdc | naluType;
            } else {
                MEMCPY(pNaluData, pRawPacket + FU_A_HEADER_SIZE, naluLength);
            }
            break;
        case FU_B_INDICATOR:
            DLOGS("FU_B_INDICATOR starting packet %d len %d", isStartingPacket, naluLength);
            if (isStartingPacket) {
                MEMCPY(pNaluData + 1, pRawPacket + FU_B_HEADER_SIZE, naluLength - 1);
                *pNaluData = naluRefIdc | naluType;
            } else {
                MEMCPY(pNaluData, pRawPacket + FU_B_HEADER_SIZE, naluLength);
            }
            break;
        case STAP_A_INDICATOR:
            naluLength = 0;
            pCurPtr = pRawPacket + STAP_A_HEADER_SIZE;
            do {
                subNaluSize = getUnalignedInt16BigEndian(pCurPtr);
                pCurPtr += SIZEOF(UINT16);
                MEMCPY(pNaluData, start4ByteCode, SIZEOF(start4ByteCode));
                pNaluData += SIZEOF(start4ByteCode);
                MEMCPY(pNaluData, pCurPtr, subNaluSize);
                pCurPtr += subNaluSize;
                pNaluData += subNaluSize;
                naluLength += SIZEOF(start4ByteCode) + subNaluSize;
            } while (subNaluSize > 0 && pCurPtr < pRawPacket + packetLength);
            DLOGS("STAP_A_INDICATOR starting packet %d len %d", isStartingPacket, naluLength);
            break;
        case STAP_B_INDICATOR:
            naluLength = 0;
            pCurPtr = pRawPacket + STAP_A_HEADER_SIZE;
            do {
                subNaluSize = getUnalignedInt16BigEndian(pCurPtr);
                pCurPtr += SIZEOF(UINT16);
                MEMCPY(pNaluData, start4ByteCode, SIZEOF(start4ByteCode));
                pNaluData += SIZEOF(start4ByteCode);
                MEMCPY(pNaluData, pCurPtr, subNaluSize);
                pCurPtr += subNaluSize;
                pNaluData += subNaluSize;
                naluLength += SIZEOF(start4ByteCode) + subNaluSize;
            } while (subNaluSize > 0 && pCurPtr < pRawPacket + packetLength);
            DLOGS("STAP_B_INDICATOR starting packet %d len %d", isStartingPacket, naluLength);
            break;
        default:
            DLOGS("Single NALU %d len %d", isStartingPacket, packetLength);
            MEMCPY(pNaluData, pRawPacket, naluLength);
    }
    if (isStartingPacket && indicator != STAP_A_INDICATOR && indicator != STAP_B_INDICATOR) {
        naluLength += SIZEOF(start4ByteCode);
    }
    DLOGS("Wrote naluLength %d isStartingPacket %d", naluLength, isStartingPacket);

CleanUp:
    if (STATUS_FAILED(retStatus) && sizeCalculationOnly) {
        naluLength = 0;
    }

    if (pNaluLength != NULL) {
        *pNaluLength = naluLength;
    }

    if (pIsStart != NULL) {
        *pIsStart = isStartingPacket;
    }

    LEAVES();
    return retStatus;
}