Fix video corruption caused by the first packet in the IDR frame getting chained multiple times, resulting in the reference count of other packets in the I-frame returning to zero prematurely

This commit is contained in:
Cameron Gutman 2015-10-31 15:29:52 -07:00
parent df59c99f80
commit fc1c26b5d7

View File

@ -194,9 +194,6 @@ public class VideoDepacketizer {
} }
private void chainPacketToCurrentFrame(VideoPacket packet) { private void chainPacketToCurrentFrame(VideoPacket packet) {
// It's possible to get more than one NAL from a packet but we can cheaply
// check for this condition because all duplicates must be contiguous
if (backingPacketTail != packet) {
packet.referencePacket(); packet.referencePacket();
packet.nextPacket = null; packet.nextPacket = null;
@ -209,7 +206,6 @@ public class VideoDepacketizer {
backingPacketHead = backingPacketTail = packet; backingPacketHead = backingPacketTail = packet;
} }
} }
}
private void addInputDataSlow(VideoPacket packet, ByteBufferDescriptor location) private void addInputDataSlow(VideoPacket packet, ByteBufferDescriptor location)
{ {
@ -289,6 +285,21 @@ public class VideoDepacketizer {
if (isDecodingH264 && decodingFrame) if (isDecodingH264 && decodingFrame)
{ {
// The slow path may result in multiple decode units per packet.
// The VideoPacket objects only support being in 1 DU list, so we'll
// copy this data into a new array rather than reference the packet, if
// this NALU ends before the end of the frame. Only copying if this doesn't
// go to the end of the frame means we'll be only copying the SPS and PPS which
// are quite small, while the actual I-frame data is referenced via the packet.
if (location.length != 0) {
// Copy the packet data into a new array
byte[] dataCopy = new byte[location.offset-start];
System.arraycopy(location.data, start, dataCopy, 0, dataCopy.length);
// Chain a descriptor referencing the copied data
chainBufferToCurrentFrame(new ByteBufferDescriptor(dataCopy, 0, dataCopy.length));
}
else {
// Chain this packet to the current frame // Chain this packet to the current frame
chainPacketToCurrentFrame(packet); chainPacketToCurrentFrame(packet);
@ -297,6 +308,7 @@ public class VideoDepacketizer {
} }
} }
} }
}
private void addInputDataFast(VideoPacket packet, ByteBufferDescriptor location, boolean firstPacket) private void addInputDataFast(VideoPacket packet, ByteBufferDescriptor location, boolean firstPacket)
{ {