mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-21 12:03:02 +00:00
Add H265 support to depacketizer
This commit is contained in:
parent
adcffa62d8
commit
d8c7d10ed6
@ -3,14 +3,9 @@ package com.limelight.nvstream.av;
|
|||||||
import com.limelight.nvstream.av.video.VideoPacket;
|
import com.limelight.nvstream.av.video.VideoPacket;
|
||||||
|
|
||||||
public class DecodeUnit {
|
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_CODEC_CONFIG = 0x1;
|
||||||
public static final int DU_FLAG_SYNC_FRAME = 0x2;
|
public static final int DU_FLAG_SYNC_FRAME = 0x2;
|
||||||
|
|
||||||
private int type;
|
|
||||||
private ByteBufferDescriptor bufferHead;
|
private ByteBufferDescriptor bufferHead;
|
||||||
private int dataLength;
|
private int dataLength;
|
||||||
private int frameNumber;
|
private int frameNumber;
|
||||||
@ -21,10 +16,9 @@ public class DecodeUnit {
|
|||||||
public 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)
|
int frameNumber, long receiveTimestamp, int flags, VideoPacket backingPacketHead)
|
||||||
{
|
{
|
||||||
this.type = type;
|
|
||||||
this.bufferHead = bufferHead;
|
this.bufferHead = bufferHead;
|
||||||
this.dataLength = dataLength;
|
this.dataLength = dataLength;
|
||||||
this.frameNumber = frameNumber;
|
this.frameNumber = frameNumber;
|
||||||
@ -33,11 +27,6 @@ public class DecodeUnit {
|
|||||||
this.backingPacketHead = backingPacketHead;
|
this.backingPacketHead = backingPacketHead;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getReceiveTimestamp()
|
public long getReceiveTimestamp()
|
||||||
{
|
{
|
||||||
return receiveTimestamp;
|
return receiveTimestamp;
|
||||||
|
@ -130,11 +130,23 @@ public class VideoDepacketizer {
|
|||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (NAL.getSpecialSequenceDescriptor(firstBuffer, cachedSpecialDesc) && NAL.isAnnexBFrameStart(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 0x68:
|
// H265
|
||||||
|
case 0x40: // VPS
|
||||||
|
case 0x42: // SPS
|
||||||
|
case 0x44: // PPS
|
||||||
flags |= DecodeUnit.DU_FLAG_CODEC_CONFIG;
|
flags |= DecodeUnit.DU_FLAG_CODEC_CONFIG;
|
||||||
break;
|
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;
|
flags |= DecodeUnit.DU_FLAG_SYNC_FRAME;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -159,8 +171,8 @@ public class VideoDepacketizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the free DU
|
// Initialize the free DU
|
||||||
du.initialize(DecodeUnit.TYPE_H264, frameDataChainHead,
|
du.initialize(frameDataChainHead, frameDataLength, frameNumber,
|
||||||
frameDataLength, frameNumber, frameStartTime, flags, backingPacketHead);
|
frameStartTime, flags, backingPacketHead);
|
||||||
|
|
||||||
// Packets now owned by the DU
|
// Packets now owned by the DU
|
||||||
backingPacketTail = backingPacketHead = null;
|
backingPacketTail = backingPacketHead = null;
|
||||||
@ -233,7 +245,8 @@ public class VideoDepacketizer {
|
|||||||
// Reassemble any pending NAL
|
// Reassemble any pending NAL
|
||||||
reassembleFrame(packet.getFrameIndex());
|
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
|
// This is the NALU code for I-frame data
|
||||||
waitingForIdrFrame = false;
|
waitingForIdrFrame = false;
|
||||||
}
|
}
|
||||||
@ -433,10 +446,7 @@ public class VideoDepacketizer {
|
|||||||
}
|
}
|
||||||
lastPacketInStream = streamPacketIndex;
|
lastPacketInStream = streamPacketIndex;
|
||||||
|
|
||||||
if (firstPacket
|
if (firstPacket && isIdrFrameStart(cachedReassemblyDesc))
|
||||||
&& NAL.getSpecialSequenceDescriptor(cachedReassemblyDesc, cachedSpecialDesc)
|
|
||||||
&& NAL.isAnnexBFrameStart(cachedSpecialDesc)
|
|
||||||
&& 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
|
||||||
frameStartTime = TimeHelper.getMonotonicMillis();
|
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
|
public DecodeUnit takeNextDecodeUnit() throws InterruptedException
|
||||||
{
|
{
|
||||||
return decodedUnits.takePopulatedObject();
|
return decodedUnits.takePopulatedObject();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user