Add H265 support to depacketizer

This commit is contained in:
Cameron Gutman 2015-12-12 01:32:07 -08:00
parent adcffa62d8
commit d8c7d10ed6
2 changed files with 28 additions and 22 deletions

View File

@ -3,14 +3,9 @@ package com.limelight.nvstream.av;
import com.limelight.nvstream.av.video.VideoPacket;
public class DecodeUnit {
public static final int TYPE_UNKNOWN = 0;
public static final int TYPE_H264 = 1;
public static final int TYPE_OPUS = 2;
public static final int DU_FLAG_CODEC_CONFIG = 0x1;
public static final int DU_FLAG_SYNC_FRAME = 0x2;
private int type;
private ByteBufferDescriptor bufferHead;
private int dataLength;
private int frameNumber;
@ -21,10 +16,9 @@ public class DecodeUnit {
public DecodeUnit() {
}
public void initialize(int type, ByteBufferDescriptor bufferHead, int dataLength,
public void initialize(ByteBufferDescriptor bufferHead, int dataLength,
int frameNumber, long receiveTimestamp, int flags, VideoPacket backingPacketHead)
{
this.type = type;
this.bufferHead = bufferHead;
this.dataLength = dataLength;
this.frameNumber = frameNumber;
@ -33,11 +27,6 @@ public class DecodeUnit {
this.backingPacketHead = backingPacketHead;
}
public int getType()
{
return type;
}
public long getReceiveTimestamp()
{
return receiveTimestamp;

View File

@ -130,11 +130,23 @@ public class VideoDepacketizer {
int flags = 0;
if (NAL.getSpecialSequenceDescriptor(firstBuffer, cachedSpecialDesc) && NAL.isAnnexBFrameStart(cachedSpecialDesc)) {
switch (cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length]) {
case 0x67:
case 0x68:
// H265
case 0x40: // VPS
case 0x42: // SPS
case 0x44: // PPS
flags |= DecodeUnit.DU_FLAG_CODEC_CONFIG;
break;
case 0x65:
case 0x26: // I-frame
flags |= DecodeUnit.DU_FLAG_SYNC_FRAME;
break;
// H264
case 0x67: // SPS
case 0x68: // PPS
flags |= DecodeUnit.DU_FLAG_CODEC_CONFIG;
break;
case 0x65: // I-frame
flags |= DecodeUnit.DU_FLAG_SYNC_FRAME;
break;
}
@ -159,8 +171,8 @@ public class VideoDepacketizer {
}
// Initialize the free DU
du.initialize(DecodeUnit.TYPE_H264, frameDataChainHead,
frameDataLength, frameNumber, frameStartTime, flags, backingPacketHead);
du.initialize(frameDataChainHead, frameDataLength, frameNumber,
frameStartTime, flags, backingPacketHead);
// Packets now owned by the DU
backingPacketTail = backingPacketHead = null;
@ -233,7 +245,8 @@ public class VideoDepacketizer {
// Reassemble any pending NAL
reassembleFrame(packet.getFrameIndex());
if (cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length] == 0x65) {
if (cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length] == 0x65 || // H264 I-Frame
cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length] == 0x26) { // H265 I-Frame
// This is the NALU code for I-frame data
waitingForIdrFrame = false;
}
@ -433,10 +446,7 @@ public class VideoDepacketizer {
}
lastPacketInStream = streamPacketIndex;
if (firstPacket
&& NAL.getSpecialSequenceDescriptor(cachedReassemblyDesc, cachedSpecialDesc)
&& NAL.isAnnexBFrameStart(cachedSpecialDesc)
&& cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length] == 0x67)
if (firstPacket && isIdrFrameStart(cachedReassemblyDesc))
{
// The slow path doesn't update the frame start time by itself
frameStartTime = TimeHelper.getMonotonicMillis();
@ -477,6 +487,13 @@ public class VideoDepacketizer {
}
}
private boolean isIdrFrameStart(ByteBufferDescriptor desc) {
return NAL.getSpecialSequenceDescriptor(desc, cachedSpecialDesc) &&
NAL.isAnnexBFrameStart(cachedSpecialDesc) &&
(cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length] == 0x67 || // H264 SPS
cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length] == 0x40); // H265 VPS
}
public DecodeUnit takeNextDecodeUnit() throws InterruptedException
{
return decodedUnits.takePopulatedObject();