Always request an IDR frame if packet loss occurs because we don't know if we missed a full frame (partial revert of last commit). Remove the last bit of active NAL parsing.

This commit is contained in:
Cameron Gutman 2013-11-28 21:02:31 -05:00
parent b0d138b7f2
commit fb437f11a0

View File

@ -8,18 +8,12 @@ import com.limelight.nvstream.av.AvDecodeUnit;
import com.limelight.nvstream.av.AvRtpPacket; import com.limelight.nvstream.av.AvRtpPacket;
import com.limelight.nvstream.av.ConnectionStatusListener; import com.limelight.nvstream.av.ConnectionStatusListener;
import android.media.MediaCodec;
public class AvVideoDepacketizer { public class AvVideoDepacketizer {
// Current NAL state // Current NAL state
private LinkedList<AvByteBufferDescriptor> avcNalDataChain = null; private LinkedList<AvByteBufferDescriptor> avcNalDataChain = null;
private int avcNalDataLength = 0; private int avcNalDataLength = 0;
// Cached buffer descriptor to save on allocations
// Only safe to use in decode thread!!!!
private AvByteBufferDescriptor cachedDesc;
// Sequencing state // Sequencing state
private short lastSequenceNumber; private short lastSequenceNumber;
@ -31,73 +25,20 @@ public class AvVideoDepacketizer {
public AvVideoDepacketizer(ConnectionStatusListener controlListener) public AvVideoDepacketizer(ConnectionStatusListener controlListener)
{ {
this.controlListener = controlListener; this.controlListener = controlListener;
this.cachedDesc = new AvByteBufferDescriptor(null, 0, 0);
} }
private boolean clearAvcNalState() private void clearAvcNalState()
{ {
if (avcNalDataChain != null && avcNalDataLength != 0) {
avcNalDataChain = null; avcNalDataChain = null;
avcNalDataLength = 0; avcNalDataLength = 0;
return true;
} }
return false; private void reassembleAvcNal()
}
private boolean reassembleAvcNal()
{ {
// This is the start of a new NAL // This is the start of a new NAL
if (avcNalDataChain != null && avcNalDataLength != 0) if (avcNalDataChain != null && avcNalDataLength != 0) {
{
int flags = 0;
// Check if this is a special NAL unit
AvByteBufferDescriptor header = avcNalDataChain.getFirst();
if (NAL.getSpecialSequenceDescriptor(header, cachedDesc))
{
// The next byte after the special sequence is the NAL header
byte nalHeader = cachedDesc.data[cachedDesc.offset+cachedDesc.length];
switch (nalHeader)
{
// SPS and PPS
case 0x67:
case 0x68:
System.out.println("Codec config");
flags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
break;
// IDR
case 0x65:
System.out.println("Reference frame");
flags |= MediaCodec.BUFFER_FLAG_SYNC_FRAME;
break;
// non-IDR frame
case 0x61:
break;
// Unknown type
default:
System.out.printf("Unknown NAL header: %02x %02x %02x %02x %02x\n",
header.data[header.offset], header.data[header.offset+1],
header.data[header.offset+2], header.data[header.offset+3],
header.data[header.offset+4]);
break;
}
}
else
{
System.out.printf("Invalid NAL: %02x %02x %02x %02x %02x\n",
header.data[header.offset], header.data[header.offset+1],
header.data[header.offset+2], header.data[header.offset+3],
header.data[header.offset+4]);
}
// Construct the H264 decode unit // Construct the H264 decode unit
AvDecodeUnit du = new AvDecodeUnit(AvDecodeUnit.TYPE_H264, avcNalDataChain, avcNalDataLength, flags); AvDecodeUnit du = new AvDecodeUnit(AvDecodeUnit.TYPE_H264, avcNalDataChain, avcNalDataLength, 0);
if (!decodedUnits.offer(du)) { if (!decodedUnits.offer(du)) {
// We need a new IDR frame since we're discarding data now // We need a new IDR frame since we're discarding data now
decodedUnits.clear(); decodedUnits.clear();
@ -105,12 +46,8 @@ public class AvVideoDepacketizer {
} }
// Clear old state // Clear old state
avcNalDataChain = null; clearAvcNalState();
avcNalDataLength = 0;
return true;
} }
return false;
} }
public void addInputData(AvVideoPacket packet) public void addInputData(AvVideoPacket packet)
@ -172,11 +109,11 @@ public class AvVideoDepacketizer {
System.out.println("Received OOS video data (expected "+(lastSequenceNumber + 1)+", got "+seq+")"); System.out.println("Received OOS video data (expected "+(lastSequenceNumber + 1)+", got "+seq+")");
// Reset the depacketizer state // Reset the depacketizer state
if (clearAvcNalState()) { clearAvcNalState();
// Request an IDR frame if we had to drop a NAL
// Request an IDR frame
controlListener.connectionNeedsResync(); controlListener.connectionNeedsResync();
} }
}
lastSequenceNumber = seq; lastSequenceNumber = seq;