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;
}