mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-20 03:23:07 +00:00
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:
parent
b0d138b7f2
commit
fb437f11a0
@ -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 boolean reassembleAvcNal()
|
private void 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,10 +109,10 @@ 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
|
|
||||||
controlListener.connectionNeedsResync();
|
// Request an IDR frame
|
||||||
}
|
controlListener.connectionNeedsResync();
|
||||||
}
|
}
|
||||||
|
|
||||||
lastSequenceNumber = seq;
|
lastSequenceNumber = seq;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user