in src/mkvgen/src/NalAdapter.c [11:134]
STATUS adaptFrameNalsFromAnnexBToAvcc(PBYTE pFrameData, UINT32 frameDataSize, BOOL removeEpb, PBYTE pAdaptedFrameData, PUINT32 pAdaptedFrameDataSize)
{
STATUS retStatus = STATUS_SUCCESS;
UINT32 i = 0, zeroCount = 0, runSize = 0;
BOOL markerFound = FALSE;
PBYTE pCurPnt = pFrameData, pAdaptedCurPnt = pAdaptedFrameData, pRunStart = NULL;
CHK(pFrameData != NULL && pAdaptedFrameDataSize != NULL, STATUS_NULL_ARG);
// Validate only when removeEpb flag is set which is the case when we need to split the NALus for
// CPD processing. For frame adaptation we might have a certain bloat due to bad encoder adaptation flag
if (removeEpb && pAdaptedFrameData != NULL && HANDLING_TRAILING_NALU_ZERO) {
CHK(*pAdaptedFrameDataSize >= frameDataSize, STATUS_INVALID_ARG_LEN);
}
// Quick check for small size
CHK(frameDataSize != 0, retStatus);
// Calculate the size after adaptation
// NOTE: We will not check for the correct buffer size for performance reasons.
for (i = 0; i < frameDataSize; i++) {
if (*pCurPnt == 0x00) {
// Found a zero - increment the consecutive zero count
zeroCount++;
// Reset the last marker
markerFound = FALSE;
} else if (zeroCount > MAX_ANNEX_B_ZERO_COUNT) {
// Ensure we don't have over 3 zero's in a row. However, some broken encoders produce zero-es
// at the end of NALUs which ends up with 4 zeroes
CHK(FALSE, STATUS_MKV_INVALID_ANNEXB_NALU_IN_FRAME_DATA);
} else if (*pCurPnt == 0x01 && (zeroCount >= 2 && zeroCount <= MAX_ANNEX_B_ZERO_COUNT)) {
// Found the Annex-B NAL
// Check if we have previous run and fix it up
if (pRunStart != NULL && pAdaptedFrameData != NULL) {
// Fix-up the previous run by recording the size in Big-Endian format
PUT_UNALIGNED_BIG_ENDIAN((PINT32) pRunStart, runSize);
}
// Store the beginning of the run
pRunStart = pAdaptedCurPnt;
// Increment the adapted pointer to 4 bytes
pAdaptedCurPnt += 4;
// Store an indicator that we have a marker
markerFound = TRUE;
// Start the new run
zeroCount = 0;
runSize = 0;
} else if (removeEpb && *pCurPnt == 0x03 && zeroCount == 2 && (i < frameDataSize - 1) &&
((*(pCurPnt + 1) == 0x00) || (*(pCurPnt + 1) == 0x01) || (*(pCurPnt + 1) == 0x02) || (*(pCurPnt + 1) == 0x03))) {
// Removing the EPB
pAdaptedCurPnt += zeroCount;
// If the adapted frame is specified then copy the zeros and then the current byte
if (pAdaptedFrameData != NULL) {
while (zeroCount != 0) {
*(pAdaptedCurPnt - zeroCount) = 0x00;
zeroCount--;
}
}
// Reset the zero count
zeroCount = 0;
runSize = 0;
} else {
// Advance the current pointer and the run size to the number of zeros so far
// as well as add the zeros to the adapted buffer if any
runSize += zeroCount + 1; // for the current byte
pAdaptedCurPnt += zeroCount + 1;
// If the adapted frame is specified then copy the zeros and then the current byte
if (pAdaptedFrameData != NULL) {
*(pAdaptedCurPnt - 1) = *pCurPnt;
while (zeroCount != 0) {
*(pAdaptedCurPnt - 1 - zeroCount) = 0x00;
zeroCount--;
}
}
zeroCount = 0;
markerFound = FALSE;
}
// Iterate the current
pCurPnt++;
}
// We could still have last few zeros at the end of the frame data and need to fix-up the last NAL
pAdaptedCurPnt += zeroCount;
if (pAdaptedFrameData != NULL) {
// The last remaining zeros should go towards the run size
runSize += zeroCount;
while (zeroCount != 0) {
*(pAdaptedCurPnt - zeroCount) = 0x00;
zeroCount--;
}
// Fix-up the last run
if (pRunStart != NULL) {
PUT_UNALIGNED_BIG_ENDIAN((PINT32) pRunStart, runSize);
}
// Also, handle the case where there is a last 001/0001 at the end of the frame - we will fill with 0s
if (markerFound) {
PUT_UNALIGNED_BIG_ENDIAN((PUINT32) pAdaptedCurPnt - 1, 0);
}
}
CleanUp:
if (STATUS_SUCCEEDED(retStatus) && pAdaptedFrameDataSize != NULL) {
// NOTE: Due to EPB removal we could in fact make the adaptation buffer smaller than the original
// We will require at least the original size buffer.
*pAdaptedFrameDataSize = (removeEpb && HANDLING_TRAILING_NALU_ZERO) ? MAX(frameDataSize, (UINT32)(pAdaptedCurPnt - pAdaptedFrameData))
: (UINT32)(pAdaptedCurPnt - pAdaptedFrameData);
}
return retStatus;
}