in src/source/codec/nalu.c [230:375]
int NALU_convertAnnexBToAvccInPlace(uint8_t *pAnnexbBuf, uint32_t uAnnexbBufLen, uint32_t uAnnexbBufSize, uint32_t *pAvccLen)
{
int xRes = KVS_ERRNO_NONE;
uint32_t i = 0;
Nal_t xNals[ MAX_NALU_COUNT_IN_A_FRAME ];
uint32_t uNalRbspCount = 0;
uint32_t uAvccTotalLen = 0;
uint32_t uAvccIdx = 0;
if (pAnnexbBuf == NULL || uAnnexbBufLen <= 4 || pAvccLen == NULL)
{
LogError("Invalid argument");
xRes = KVS_ERRNO_FAIL;
}
else if (!NALU_isAnnexBFrame(pAnnexbBuf, uAnnexbBufLen))
{
LogInfo("It's not a Annex-B frame, skip convert");
}
else
{
/* Go through all Annex-B buffer and record all RBSP begin and length first. */
while (i < uAnnexbBufLen - 4)
{
if (uNalRbspCount > MAX_NALU_COUNT_IN_A_FRAME)
{
break;
}
if (pAnnexbBuf[i] == 0x00)
{
if (pAnnexbBuf[i+1] == 0x00)
{
if (pAnnexbBuf[i+2] == 0x00)
{
if (pAnnexbBuf[i+3] == 0x01)
{
/* 0x00000001 is start code of NAL. */
if (uNalRbspCount > 0)
{
xNals[uNalRbspCount-1].uNalLen = i - xNals[uNalRbspCount-1].uNalBeginIdx;
}
i += 4;
xNals[uNalRbspCount++].uNalBeginIdx = i;
}
else if (pAnnexbBuf[i + 3] == 0x00)
{
/* 0x00000000 is not allowed. */
LogInfo("Invalid NALU format");
xRes = KVS_ERRNO_FAIL;
break;
}
else
{
/* 0x000000XX is acceptable. */
i += 4;
}
}
else if (pAnnexbBuf[i+2] == 0x01)
{
/* 0x000001 is start code of NAL */
if (uNalRbspCount > 0)
{
xNals[uNalRbspCount-1].uNalLen = i - xNals[uNalRbspCount-1].uNalBeginIdx;
}
i += 3;
xNals[uNalRbspCount++].uNalBeginIdx = i;
}
else
{
/* 0x0000XX is acceptable. It includes EPB case and we reserve EPB byte. */
i += 3;
}
}
else
{
/* 0x00XX is acceptable. */
i += 2;
}
}
else
{
/* 0xXX is acceptable. */
i++;
}
}
if (uNalRbspCount == 0)
{
LogInfo("No NALU is found in Annex-B frame");
xRes = KVS_ERRNO_FAIL;
}
else if (uNalRbspCount > MAX_NALU_COUNT_IN_A_FRAME)
{
LogError("NAL RBSP count exceeds max count");
xRes = KVS_ERRNO_FAIL;
}
else
{
/* Update the last BSPS. */
xNals[ uNalRbspCount - 1 ].uNalLen = uAnnexbBufLen - xNals[ uNalRbspCount - 1 ].uNalBeginIdx;
/* Calculate needed size if we convert it to Avcc format. */
uAvccTotalLen = 4 * uNalRbspCount;
for (i=0; i<uNalRbspCount; i++)
{
uAvccTotalLen += xNals[i].uNalLen;
}
if (uAvccTotalLen > uAnnexbBufSize)
{
/* We don't have enough space to convert Annex-B to Avcc in place. */
LogInfo("No available space to convert Annex-B inplace");
*pAvccLen = 0;
xRes = KVS_ERRNO_FAIL;
}
else
{
/* move RBSP from back to head */
i = uNalRbspCount - 1;
uAvccIdx = uAvccTotalLen;
do
{
/* move RBSP */
uAvccIdx -= xNals[i].uNalLen;
memmove(pAnnexbBuf + uAvccIdx, pAnnexbBuf + xNals[i].uNalBeginIdx, xNals[i].uNalLen);
/* fill length info */
uAvccIdx -= 4;
PUT_UNALIGNED_4_byte_BE(pAnnexbBuf + uAvccIdx, xNals[i].uNalLen);
if (i == 0)
{
break;
}
i--;
} while (true);
*pAvccLen = uAvccTotalLen;
}
}
}
return xRes;
}