Fix handling of 3 byte Annex B start sequences

This commit is contained in:
Cameron Gutman
2022-09-05 18:46:42 -05:00
parent 0bd81b8261
commit 65e40279ea
2 changed files with 24 additions and 10 deletions
+23 -9
View File
@@ -142,7 +142,6 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
[_displayLink invalidate]; [_displayLink invalidate];
} }
#define FRAME_START_PREFIX_SIZE 4
#define NALU_START_PREFIX_SIZE 3 #define NALU_START_PREFIX_SIZE 3
#define NAL_LENGTH_PREFIX_SIZE 4 #define NAL_LENGTH_PREFIX_SIZE 4
@@ -162,19 +161,32 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
OSStatus status; OSStatus status;
size_t oldOffset = CMBlockBufferGetDataLength(existingBuffer); size_t oldOffset = CMBlockBufferGetDataLength(existingBuffer);
// If we're at index 1 (first NALU in frame), enqueue this buffer to the memory block // If we're the first NALU in frame, enqueue this buffer to the memory block
// so it can handle freeing it when the block buffer is destroyed // so it can handle freeing it when the block buffer is destroyed
if (offset == 1) { if (offset == 0 || offset == 1) {
int dataLength = nalLength - NALU_START_PREFIX_SIZE; int dataLength = nalLength - NALU_START_PREFIX_SIZE;
// If we get here with offset 0, this is a 3 byte Annex B prefix. This means
// we don't have enough space to do an in-place Annex B -> AVCC fixup.
// To allow the in-place fixup to work, prepend a 1 byte buffer.
if (offset == 0) {
status = CMBlockBufferAppendMemoryBlock(existingBuffer, NULL, 1,
kCFAllocatorDefault,
NULL, 0, 1, 0);
if (status != noErr) {
Log(LOG_E, @"CMBlockBufferAppendMemoryBlock failed: %d", (int)status);
return;
}
}
// Pass the real buffer pointer directly (no offset) // Pass the real buffer pointer directly (no offset)
// This will give it to the block buffer to free when it's released. // This will give it to the block buffer to free when it's released.
// All further calls to CMBlockBufferAppendMemoryBlock will do so // All further calls to CMBlockBufferAppendMemoryBlock will do so
// at an offset and will not be asking the buffer to be freed. // at an offset and will not be asking the buffer to be freed.
status = CMBlockBufferAppendMemoryBlock(existingBuffer, data, status = CMBlockBufferAppendMemoryBlock(existingBuffer, data,
nalLength + 1, // Add 1 for the offset we decremented nalLength + offset,
kCFAllocatorDefault, kCFAllocatorDefault,
NULL, 0, nalLength + 1, 0); NULL, 0, nalLength + offset, 0);
if (status != noErr) { if (status != noErr) {
Log(LOG_E, @"CMBlockBufferReplaceDataBytes failed: %d", (int)status); Log(LOG_E, @"CMBlockBufferReplaceDataBytes failed: %d", (int)status);
return; return;
@@ -229,9 +241,11 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
OSStatus status; OSStatus status;
if (bufferType != BUFFER_TYPE_PICDATA) { if (bufferType != BUFFER_TYPE_PICDATA) {
int startLen = data[2] == 0x01 ? 3 : 4;
if (bufferType == BUFFER_TYPE_VPS) { if (bufferType == BUFFER_TYPE_VPS) {
Log(LOG_I, @"Got VPS"); Log(LOG_I, @"Got VPS");
vpsData = [NSData dataWithBytes:&data[FRAME_START_PREFIX_SIZE] length:length - FRAME_START_PREFIX_SIZE]; vpsData = [NSData dataWithBytes:&data[startLen] length:length - startLen];
waitingForVps = false; waitingForVps = false;
// We got a new VPS so wait for a new SPS to match it // We got a new VPS so wait for a new SPS to match it
@@ -239,14 +253,14 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
} }
else if (bufferType == BUFFER_TYPE_SPS) { else if (bufferType == BUFFER_TYPE_SPS) {
Log(LOG_I, @"Got SPS"); Log(LOG_I, @"Got SPS");
spsData = [NSData dataWithBytes:&data[FRAME_START_PREFIX_SIZE] length:length - FRAME_START_PREFIX_SIZE]; spsData = [NSData dataWithBytes:&data[startLen] length:length - startLen];
waitingForSps = false; waitingForSps = false;
// We got a new SPS so wait for a new PPS to match it // We got a new SPS so wait for a new PPS to match it
waitingForPps = true; waitingForPps = true;
} else if (bufferType == BUFFER_TYPE_PPS) { } else if (bufferType == BUFFER_TYPE_PPS) {
Log(LOG_I, @"Got PPS"); Log(LOG_I, @"Got PPS");
ppsData = [NSData dataWithBytes:&data[FRAME_START_PREFIX_SIZE] length:length - FRAME_START_PREFIX_SIZE]; ppsData = [NSData dataWithBytes:&data[startLen] length:length - startLen];
waitingForPps = false; waitingForPps = false;
} }
@@ -331,7 +345,7 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
} }
int lastOffset = -1; int lastOffset = -1;
for (int i = 0; i < length - FRAME_START_PREFIX_SIZE; i++) { for (int i = 0; i < length - NALU_START_PREFIX_SIZE; i++) {
// Search for a NALU // Search for a NALU
if (data[i] == 0 && data[i+1] == 0 && data[i+2] == 1) { if (data[i] == 0 && data[i+1] == 0 && data[i+2] == 1) {
// It's the start of a new NALU // It's the start of a new NALU