Fix mishandling of IDR frames with a VUI or AUD NAL

This commit is contained in:
Cameron Gutman
2022-09-11 23:34:38 -05:00
parent e453a4d548
commit 50603ac16e
+25 -18
View File
@@ -138,7 +138,7 @@ void destroyVideoDepacketizer(void) {
cleanupFrameState(); cleanupFrameState();
} }
static bool getAnnexBStartSequence(PBUFFER_DESC current, PBUFFER_DESC candidate) { static bool getAnnexBStartSequence(PBUFFER_DESC current, PBUFFER_DESC startSeq) {
if (current->length < 3) { if (current->length < 3) {
return false; return false;
} }
@@ -148,17 +148,21 @@ static bool getAnnexBStartSequence(PBUFFER_DESC current, PBUFFER_DESC candidate)
if (current->data[current->offset + 2] == 0) { if (current->data[current->offset + 2] == 0) {
if (current->length >= 4 && current->data[current->offset + 3] == 1) { if (current->length >= 4 && current->data[current->offset + 3] == 1) {
// Frame start // Frame start
candidate->data = current->data; if (startSeq != NULL) {
candidate->offset = current->offset; startSeq->data = current->data;
candidate->length = 4; startSeq->offset = current->offset;
startSeq->length = 4;
}
return true; return true;
} }
} }
else if (current->data[current->offset + 2] == 1) { else if (current->data[current->offset + 2] == 1) {
// NAL start // NAL start
candidate->data = current->data; if (startSeq != NULL) {
candidate->offset = current->offset; startSeq->data = current->data;
candidate->length = 3; startSeq->offset = current->offset;
startSeq->length = 3;
}
return true; return true;
} }
} }
@@ -239,12 +243,18 @@ void LiCompleteVideoFrame(VIDEO_FRAME_HANDLE handle, int drStatus) {
} }
} }
static bool isSeqReferenceFrameStart(PBUFFER_DESC startSeq) { static bool isSeqReferenceFrameStart(PBUFFER_DESC buffer) {
BUFFER_DESC startSeq;
if (!getAnnexBStartSequence(buffer, &startSeq)) {
return false;
}
if (NegotiatedVideoFormat & VIDEO_FORMAT_MASK_H264) { if (NegotiatedVideoFormat & VIDEO_FORMAT_MASK_H264) {
return H264_NAL_TYPE(startSeq->data[startSeq->offset + startSeq->length]) == 5; return H264_NAL_TYPE(startSeq.data[startSeq.offset + startSeq.length]) == 5;
} }
else if (NegotiatedVideoFormat & VIDEO_FORMAT_MASK_H265) { else if (NegotiatedVideoFormat & VIDEO_FORMAT_MASK_H265) {
switch (HEVC_NAL_TYPE(startSeq->data[startSeq->offset + startSeq->length])) { switch (HEVC_NAL_TYPE(startSeq.data[startSeq.offset + startSeq.length])) {
case 16: case 16:
case 17: case 17:
case 18: case 18:
@@ -312,9 +322,9 @@ static void skipToNextNalOrEnd(PBUFFER_DESC buffer) {
} }
// Loop until we find an Annex B start sequence (3 or 4 byte) // Loop until we find an Annex B start sequence (3 or 4 byte)
while (!getAnnexBStartSequence(buffer, &startSeq)) { while (!getAnnexBStartSequence(buffer, NULL)) {
if (buffer->length == 0) { if (buffer->length == 0) {
// Reach the end of the buffer // Reached the end of the buffer
return; return;
} }
@@ -514,17 +524,14 @@ static void queueFragment(PLENTRY_INTERNAL* existingEntry, char* data, int offse
// Process an RTP Payload using the slow path that handles multiple NALUs per packet // Process an RTP Payload using the slow path that handles multiple NALUs per packet
static void processRtpPayloadSlow(PBUFFER_DESC currentPos, PLENTRY_INTERNAL* existingEntry) { static void processRtpPayloadSlow(PBUFFER_DESC currentPos, PLENTRY_INTERNAL* existingEntry) {
BUFFER_DESC startSeq;
// We should not have any NALUs when processing the first packet in an IDR frame // We should not have any NALUs when processing the first packet in an IDR frame
LC_ASSERT(nalChainHead == NULL); LC_ASSERT(nalChainHead == NULL);
LC_ASSERT(nalChainTail == NULL); LC_ASSERT(nalChainTail == NULL);
while (currentPos->length != 0) { while (currentPos->length != 0) {
// Skip through any padding bytes // Skip through any padding bytes
if (!getAnnexBStartSequence(currentPos, &startSeq)) { if (!getAnnexBStartSequence(currentPos, NULL)) {
skipToNextNal(currentPos); skipToNextNal(currentPos);
getAnnexBStartSequence(currentPos, &startSeq);
} }
// Skip any prepended AUD or SEI NALUs. We may have padding between // Skip any prepended AUD or SEI NALUs. We may have padding between
@@ -544,7 +551,7 @@ static void processRtpPayloadSlow(PBUFFER_DESC currentPos, PLENTRY_INTERNAL* exi
// Now we're decoding a frame // Now we're decoding a frame
decodingFrame = true; decodingFrame = true;
if (isSeqReferenceFrameStart(&startSeq)) { if (isSeqReferenceFrameStart(currentPos)) {
// No longer waiting for an IDR frame // No longer waiting for an IDR frame
waitingForIdrFrame = false; waitingForIdrFrame = false;
@@ -563,7 +570,7 @@ static void processRtpPayloadSlow(PBUFFER_DESC currentPos, PLENTRY_INTERNAL* exi
if (containsPicData) { if (containsPicData) {
while (currentPos->length != 0) { while (currentPos->length != 0) {
// Any NALUs we encounter on the way to the end of the packet must be reference frame slices // Any NALUs we encounter on the way to the end of the packet must be reference frame slices
LC_ASSERT(getAnnexBStartSequence(currentPos, &startSeq) && isSeqReferenceFrameStart(&startSeq)); LC_ASSERT(isSeqReferenceFrameStart(currentPos));
skipToNextNalOrEnd(currentPos); skipToNextNalOrEnd(currentPos);
} }
} }