Refactor depacketizer to avoid H264 and AVC references -- no behavior changes

This commit is contained in:
Cameron Gutman 2015-12-12 00:06:37 -08:00
parent 260d716eb8
commit adcffa62d8

View File

@ -14,7 +14,7 @@ import com.limelight.utils.TimeHelper;
public class VideoDepacketizer { public class VideoDepacketizer {
// Current frame state // Current frame state
private int avcFrameDataLength = 0; private int frameDataLength = 0;
private ByteBufferDescriptor frameDataChainHead; private ByteBufferDescriptor frameDataChainHead;
private ByteBufferDescriptor frameDataChainTail; private ByteBufferDescriptor frameDataChainTail;
private VideoPacket backingPacketHead; private VideoPacket backingPacketHead;
@ -84,7 +84,7 @@ public class VideoDepacketizer {
} }
} }
private void dropAvcFrameState() private void dropFrameState()
{ {
// We'll need an IDR frame now if we're in strict mode // We'll need an IDR frame now if we're in strict mode
if (strictIdrFrameWait) { if (strictIdrFrameWait) {
@ -106,10 +106,10 @@ public class VideoDepacketizer {
controlListener.connectionDetectedFrameLoss(0, 0); controlListener.connectionDetectedFrameLoss(0, 0);
} }
cleanupAvcFrameState(); cleanupFrameState();
} }
private void cleanupAvcFrameState() private void cleanupFrameState()
{ {
backingPacketTail = null; backingPacketTail = null;
while (backingPacketHead != null) { while (backingPacketHead != null) {
@ -118,17 +118,17 @@ public class VideoDepacketizer {
} }
frameDataChainHead = frameDataChainTail = null; frameDataChainHead = frameDataChainTail = null;
avcFrameDataLength = 0; frameDataLength = 0;
} }
private void reassembleAvcFrame(int frameNumber) private void reassembleFrame(int frameNumber)
{ {
// This is the start of a new frame // This is the start of a new frame
if (frameDataChainHead != null) { if (frameDataChainHead != null) {
ByteBufferDescriptor firstBuffer = frameDataChainHead; ByteBufferDescriptor firstBuffer = frameDataChainHead;
int flags = 0; int flags = 0;
if (NAL.getSpecialSequenceDescriptor(firstBuffer, cachedSpecialDesc) && NAL.isAvcFrameStart(cachedSpecialDesc)) { if (NAL.getSpecialSequenceDescriptor(firstBuffer, cachedSpecialDesc) && NAL.isAnnexBFrameStart(cachedSpecialDesc)) {
switch (cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length]) { switch (cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length]) {
case 0x67: case 0x67:
case 0x68: case 0x68:
@ -140,7 +140,7 @@ public class VideoDepacketizer {
} }
} }
// Construct the H264 decode unit // Construct the video decode unit
DecodeUnit du = decodedUnits.pollFreeObject(); DecodeUnit du = decodedUnits.pollFreeObject();
if (du == null) { if (du == null) {
LimeLog.warning("Video decoder is too slow! Forced to drop decode units"); LimeLog.warning("Video decoder is too slow! Forced to drop decode units");
@ -154,13 +154,13 @@ public class VideoDepacketizer {
decodedUnits.clearPopulatedObjects(); decodedUnits.clearPopulatedObjects();
// Clear frame state and wait for an IDR // Clear frame state and wait for an IDR
dropAvcFrameState(); dropFrameState();
return; return;
} }
// Initialize the free DU // Initialize the free DU
du.initialize(DecodeUnit.TYPE_H264, frameDataChainHead, du.initialize(DecodeUnit.TYPE_H264, frameDataChainHead,
avcFrameDataLength, frameNumber, frameStartTime, flags, backingPacketHead); frameDataLength, frameNumber, frameStartTime, flags, backingPacketHead);
// Packets now owned by the DU // Packets now owned by the DU
backingPacketTail = backingPacketHead = null; backingPacketTail = backingPacketHead = null;
@ -171,7 +171,7 @@ public class VideoDepacketizer {
decodedUnits.addPopulatedObject(du); decodedUnits.addPopulatedObject(du);
// Clear old state // Clear old state
cleanupAvcFrameState(); cleanupFrameState();
// Clear frame drops // Clear frame drops
consecutiveFrameDrops = 0; consecutiveFrameDrops = 0;
@ -190,7 +190,7 @@ public class VideoDepacketizer {
frameDataChainHead = frameDataChainTail = desc; frameDataChainHead = frameDataChainTail = desc;
} }
avcFrameDataLength += desc.length; frameDataLength += desc.length;
} }
private void chainPacketToCurrentFrame(VideoPacket packet) { private void chainPacketToCurrentFrame(VideoPacket packet) {
@ -209,7 +209,7 @@ public class VideoDepacketizer {
private void addInputDataSlow(VideoPacket packet, ByteBufferDescriptor location) private void addInputDataSlow(VideoPacket packet, ByteBufferDescriptor location)
{ {
boolean isDecodingH264 = false; boolean isDecodingVideoData = false;
while (location.length != 0) while (location.length != 0)
{ {
@ -219,19 +219,19 @@ public class VideoDepacketizer {
// Check for a special sequence // Check for a special sequence
if (NAL.getSpecialSequenceDescriptor(location, cachedSpecialDesc)) if (NAL.getSpecialSequenceDescriptor(location, cachedSpecialDesc))
{ {
if (NAL.isAvcStartSequence(cachedSpecialDesc)) if (NAL.isAnnexBStartSequence(cachedSpecialDesc))
{ {
// We're decoding H264 now // We're decoding video data now
isDecodingH264 = true; isDecodingVideoData = true;
// Check if it's the end of the last frame // Check if it's the end of the last frame
if (NAL.isAvcFrameStart(cachedSpecialDesc)) if (NAL.isAnnexBFrameStart(cachedSpecialDesc))
{ {
// Update the global state that we're decoding a new frame // Update the global state that we're decoding a new frame
this.decodingFrame = true; this.decodingFrame = true;
// Reassemble any pending AVC NAL // Reassemble any pending NAL
reassembleAvcFrame(packet.getFrameIndex()); reassembleFrame(packet.getFrameIndex());
if (cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length] == 0x65) { if (cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length] == 0x65) {
// This is the NALU code for I-frame data // This is the NALU code for I-frame data
@ -245,14 +245,14 @@ public class VideoDepacketizer {
} }
else else
{ {
// Check if this is padding after a full AVC frame // Check if this is padding after a full video frame
if (isDecodingH264 && NAL.isPadding(cachedSpecialDesc)) { if (isDecodingVideoData && NAL.isPadding(cachedSpecialDesc)) {
// The decode unit is complete // The decode unit is complete
reassembleAvcFrame(packet.getFrameIndex()); reassembleFrame(packet.getFrameIndex());
} }
// Not decoding AVC // Not decoding video
isDecodingH264 = false; isDecodingVideoData = false;
// Just skip this byte // Just skip this byte
location.length--; location.length--;
@ -271,7 +271,7 @@ public class VideoDepacketizer {
{ {
// Only stop if we're decoding something or this // Only stop if we're decoding something or this
// isn't padding // isn't padding
if (isDecodingH264 || !NAL.isPadding(cachedSpecialDesc)) if (isDecodingVideoData || !NAL.isPadding(cachedSpecialDesc))
{ {
break; break;
} }
@ -283,7 +283,7 @@ public class VideoDepacketizer {
location.length--; location.length--;
} }
if (isDecodingH264 && decodingFrame) if (isDecodingVideoData && decodingFrame)
{ {
// The slow path may result in multiple decode units per packet. // The slow path may result in multiple decode units per packet.
// The VideoPacket objects only support being in 1 DU list, so we'll // The VideoPacket objects only support being in 1 DU list, so we'll
@ -364,7 +364,7 @@ public class VideoDepacketizer {
waitingForNextSuccessfulFrame = true; waitingForNextSuccessfulFrame = true;
// Clear the old state and wait for an IDR // Clear the old state and wait for an IDR
dropAvcFrameState(); dropFrameState();
} }
// Look for a non-frame start before a frame start // Look for a non-frame start before a frame start
else if (!firstPacket && !decodingFrame) { else if (!firstPacket && !decodingFrame) {
@ -378,7 +378,7 @@ public class VideoDepacketizer {
waitingForNextSuccessfulFrame = true; waitingForNextSuccessfulFrame = true;
dropAvcFrameState(); dropFrameState();
decodingFrame = false; decodingFrame = false;
return; return;
} }
@ -397,7 +397,7 @@ public class VideoDepacketizer {
// Wait until an IDR frame comes // Wait until an IDR frame comes
waitingForNextSuccessfulFrame = true; waitingForNextSuccessfulFrame = true;
dropAvcFrameState(); dropFrameState();
} }
else if (nextFrameNumber != frameIndex) { else if (nextFrameNumber != frameIndex) {
// Duplicate packet or FEC dup // Duplicate packet or FEC dup
@ -419,7 +419,7 @@ public class VideoDepacketizer {
waitingForNextSuccessfulFrame = true; waitingForNextSuccessfulFrame = true;
dropAvcFrameState(); dropFrameState();
decodingFrame = false; decodingFrame = false;
return; return;
@ -435,7 +435,7 @@ public class VideoDepacketizer {
if (firstPacket if (firstPacket
&& NAL.getSpecialSequenceDescriptor(cachedReassemblyDesc, cachedSpecialDesc) && NAL.getSpecialSequenceDescriptor(cachedReassemblyDesc, cachedSpecialDesc)
&& NAL.isAvcFrameStart(cachedSpecialDesc) && NAL.isAnnexBFrameStart(cachedSpecialDesc)
&& cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length] == 0x67) && cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length] == 0x67)
{ {
// The slow path doesn't update the frame start time by itself // The slow path doesn't update the frame start time by itself
@ -467,11 +467,11 @@ public class VideoDepacketizer {
if (waitingForIdrFrame) { if (waitingForIdrFrame) {
LimeLog.warning("Waiting for IDR frame"); LimeLog.warning("Waiting for IDR frame");
dropAvcFrameState(); dropFrameState();
return; return;
} }
reassembleAvcFrame(frameIndex); reassembleFrame(frameIndex);
startFrameNumber = nextFrameNumber; startFrameNumber = nextFrameNumber;
} }
@ -496,14 +496,14 @@ public class VideoDepacketizer {
class NAL { class NAL {
// This assumes that the buffer passed in is already a special sequence // This assumes that the buffer passed in is already a special sequence
public static boolean isAvcStartSequence(ByteBufferDescriptor specialSeq) public static boolean isAnnexBStartSequence(ByteBufferDescriptor specialSeq)
{ {
// The start sequence is 00 00 01 or 00 00 00 01 // The start sequence is 00 00 01 or 00 00 00 01
return (specialSeq.data[specialSeq.offset+specialSeq.length-1] == 0x01); return (specialSeq.data[specialSeq.offset+specialSeq.length-1] == 0x01);
} }
// This assumes that the buffer passed in is already a special sequence // This assumes that the buffer passed in is already a special sequence
public static boolean isAvcFrameStart(ByteBufferDescriptor specialSeq) public static boolean isAnnexBFrameStart(ByteBufferDescriptor specialSeq)
{ {
if (specialSeq.length != 4) if (specialSeq.length != 4)
return false; return false;
@ -537,7 +537,7 @@ class NAL {
if (buffer.length >= 4 && if (buffer.length >= 4 &&
buffer.data[buffer.offset+3] == 0x01) buffer.data[buffer.offset+3] == 0x01)
{ {
// It's the AVC start sequence 00 00 00 01 // It's the Annex B start sequence 00 00 00 01
outputDesc.reinitialize(buffer.data, buffer.offset, 4); outputDesc.reinitialize(buffer.data, buffer.offset, 4);
} }
else else