mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2026-06-16 22:00:55 +00:00
Add presentation timestamp to video frame metadata
This commit is contained in:
+3
-1
@@ -218,8 +218,10 @@ static void ReceiveThreadProc(void* context) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// RTP sequence number must be in host order for the RTP queue
|
// Convert fields to host byte-order
|
||||||
rtp->sequenceNumber = htons(rtp->sequenceNumber);
|
rtp->sequenceNumber = htons(rtp->sequenceNumber);
|
||||||
|
rtp->timestamp = htonl(rtp->timestamp);
|
||||||
|
rtp->ssrc = htonl(rtp->ssrc);
|
||||||
|
|
||||||
queueStatus = RtpqAddPacket(&rtpReorderQueue, (PRTP_PACKET)packet, &packet->q.rentry);
|
queueStatus = RtpqAddPacket(&rtpReorderQueue, (PRTP_PACKET)packet, &packet->q.rentry);
|
||||||
if (RTPQ_HANDLE_NOW(queueStatus)) {
|
if (RTPQ_HANDLE_NOW(queueStatus)) {
|
||||||
|
|||||||
@@ -122,6 +122,11 @@ typedef struct _DECODE_UNIT {
|
|||||||
// shares the same epoch as this value.
|
// shares the same epoch as this value.
|
||||||
unsigned long long receiveTimeMs;
|
unsigned long long receiveTimeMs;
|
||||||
|
|
||||||
|
// Presentation time in milliseconds with the epoch at the first captured frame.
|
||||||
|
// This can be used to aid frame pacing or to drop old frames that were queued too
|
||||||
|
// long prior to display.
|
||||||
|
unsigned int presentationTimeMs;
|
||||||
|
|
||||||
// Length of the entire buffer chain in bytes
|
// Length of the entire buffer chain in bytes
|
||||||
int fullLength;
|
int fullLength;
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ static int queuePacket(PRTP_FEC_QUEUE queue, PRTPFEC_QUEUE_ENTRY newEntry, int h
|
|||||||
newEntry->prev = NULL;
|
newEntry->prev = NULL;
|
||||||
newEntry->next = NULL;
|
newEntry->next = NULL;
|
||||||
|
|
||||||
|
// 90 KHz video clock
|
||||||
|
newEntry->presentationTimeMs = packet->timestamp / 90;
|
||||||
|
|
||||||
if (queue->bufferHead == NULL) {
|
if (queue->bufferHead == NULL) {
|
||||||
LC_ASSERT(queue->bufferSize == 0);
|
LC_ASSERT(queue->bufferSize == 0);
|
||||||
queue->bufferHead = queue->bufferTail = newEntry;
|
queue->bufferHead = queue->bufferTail = newEntry;
|
||||||
@@ -158,6 +161,8 @@ cleanup_packets:
|
|||||||
PRTP_PACKET rtpPacket = (PRTP_PACKET) packets[i];
|
PRTP_PACKET rtpPacket = (PRTP_PACKET) packets[i];
|
||||||
rtpPacket->sequenceNumber = U16(i + queue->bufferLowestSequenceNumber);
|
rtpPacket->sequenceNumber = U16(i + queue->bufferLowestSequenceNumber);
|
||||||
rtpPacket->header = queue->bufferHead->packet->header;
|
rtpPacket->header = queue->bufferHead->packet->header;
|
||||||
|
rtpPacket->timestamp = queue->bufferHead->packet->timestamp;
|
||||||
|
rtpPacket->ssrc = queue->bufferHead->packet->ssrc;
|
||||||
|
|
||||||
int dataOffset = sizeof(*rtpPacket);
|
int dataOffset = sizeof(*rtpPacket);
|
||||||
if (rtpPacket->header & FLAG_EXTENSION) {
|
if (rtpPacket->header & FLAG_EXTENSION) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ typedef struct _RTPFEC_QUEUE_ENTRY {
|
|||||||
int length;
|
int length;
|
||||||
int isParity;
|
int isParity;
|
||||||
unsigned long long receiveTimeMs;
|
unsigned long long receiveTimeMs;
|
||||||
|
unsigned int presentationTimeMs;
|
||||||
|
|
||||||
struct _RTPFEC_QUEUE_ENTRY* next;
|
struct _RTPFEC_QUEUE_ENTRY* next;
|
||||||
struct _RTPFEC_QUEUE_ENTRY* prev;
|
struct _RTPFEC_QUEUE_ENTRY* prev;
|
||||||
|
|||||||
+2
-1
@@ -33,7 +33,8 @@ typedef struct _RTP_PACKET {
|
|||||||
char header;
|
char header;
|
||||||
char packetType;
|
char packetType;
|
||||||
unsigned short sequenceNumber;
|
unsigned short sequenceNumber;
|
||||||
char reserved[8];
|
unsigned int timestamp;
|
||||||
|
unsigned int ssrc;
|
||||||
} RTP_PACKET, *PRTP_PACKET;
|
} RTP_PACKET, *PRTP_PACKET;
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ static unsigned int lastPacketInStream;
|
|||||||
static int decodingFrame;
|
static int decodingFrame;
|
||||||
static int strictIdrFrameWait;
|
static int strictIdrFrameWait;
|
||||||
static unsigned long long firstPacketReceiveTime;
|
static unsigned long long firstPacketReceiveTime;
|
||||||
|
static unsigned int firstPacketPresentationTime;
|
||||||
static int dropStatePending;
|
static int dropStatePending;
|
||||||
static int idrFrameProcessed;
|
static int idrFrameProcessed;
|
||||||
|
|
||||||
@@ -47,6 +48,7 @@ void initializeVideoDepacketizer(int pktSize) {
|
|||||||
lastPacketInStream = UINT32_MAX;
|
lastPacketInStream = UINT32_MAX;
|
||||||
decodingFrame = 0;
|
decodingFrame = 0;
|
||||||
firstPacketReceiveTime = 0;
|
firstPacketReceiveTime = 0;
|
||||||
|
firstPacketPresentationTime = 0;
|
||||||
dropStatePending = 0;
|
dropStatePending = 0;
|
||||||
idrFrameProcessed = 0;
|
idrFrameProcessed = 0;
|
||||||
strictIdrFrameWait = !isReferenceFrameInvalidationEnabled();
|
strictIdrFrameWait = !isReferenceFrameInvalidationEnabled();
|
||||||
@@ -261,6 +263,7 @@ static void reassembleFrame(int frameNumber) {
|
|||||||
qdu->decodeUnit.fullLength = nalChainDataLength;
|
qdu->decodeUnit.fullLength = nalChainDataLength;
|
||||||
qdu->decodeUnit.frameNumber = frameNumber;
|
qdu->decodeUnit.frameNumber = frameNumber;
|
||||||
qdu->decodeUnit.receiveTimeMs = firstPacketReceiveTime;
|
qdu->decodeUnit.receiveTimeMs = firstPacketReceiveTime;
|
||||||
|
qdu->decodeUnit.presentationTimeMs = firstPacketPresentationTime;
|
||||||
|
|
||||||
// IDR frames will have leading CSD buffers
|
// IDR frames will have leading CSD buffers
|
||||||
if (nalChainHead->bufferType != BUFFER_TYPE_PICDATA) {
|
if (nalChainHead->bufferType != BUFFER_TYPE_PICDATA) {
|
||||||
@@ -497,7 +500,9 @@ static int isFirstPacket(char flags) {
|
|||||||
|
|
||||||
// Process an RTP Payload
|
// Process an RTP Payload
|
||||||
// The caller will free *existingEntry unless we NULL it
|
// The caller will free *existingEntry unless we NULL it
|
||||||
void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length, unsigned long long receiveTimeMs, PLENTRY_INTERNAL* existingEntry) {
|
void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length,
|
||||||
|
unsigned long long receiveTimeMs, unsigned int presentationTimeMs,
|
||||||
|
PLENTRY_INTERNAL* existingEntry) {
|
||||||
BUFFER_DESC currentPos;
|
BUFFER_DESC currentPos;
|
||||||
int frameIndex;
|
int frameIndex;
|
||||||
char flags;
|
char flags;
|
||||||
@@ -563,6 +568,7 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length, unsigned long l
|
|||||||
// We're now decoding a frame
|
// We're now decoding a frame
|
||||||
decodingFrame = 1;
|
decodingFrame = 1;
|
||||||
firstPacketReceiveTime = receiveTimeMs;
|
firstPacketReceiveTime = receiveTimeMs;
|
||||||
|
firstPacketPresentationTime = presentationTimeMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastPacketInStream = streamPacketIndex;
|
lastPacketInStream = streamPacketIndex;
|
||||||
@@ -694,6 +700,7 @@ void queueRtpPacket(PRTPFEC_QUEUE_ENTRY queueEntryPtr) {
|
|||||||
processRtpPayload((PNV_VIDEO_PACKET)(((char*)queueEntry.packet) + dataOffset),
|
processRtpPayload((PNV_VIDEO_PACKET)(((char*)queueEntry.packet) + dataOffset),
|
||||||
queueEntry.length - dataOffset,
|
queueEntry.length - dataOffset,
|
||||||
queueEntry.receiveTimeMs,
|
queueEntry.receiveTimeMs,
|
||||||
|
queueEntry.presentationTimeMs,
|
||||||
&existingEntry);
|
&existingEntry);
|
||||||
|
|
||||||
if (existingEntry != NULL) {
|
if (existingEntry != NULL) {
|
||||||
|
|||||||
+3
-1
@@ -116,9 +116,11 @@ static void ReceiveThreadProc(void* context) {
|
|||||||
// as quickly, since we're now just keeping the NAT session open.
|
// as quickly, since we're now just keeping the NAT session open.
|
||||||
receivedDataFromPeer = 1;
|
receivedDataFromPeer = 1;
|
||||||
|
|
||||||
// RTP sequence number must be in host order for the RTP queue
|
// Convert fields to host byte-order
|
||||||
packet = (PRTP_PACKET)&buffer[0];
|
packet = (PRTP_PACKET)&buffer[0];
|
||||||
packet->sequenceNumber = htons(packet->sequenceNumber);
|
packet->sequenceNumber = htons(packet->sequenceNumber);
|
||||||
|
packet->timestamp = htonl(packet->timestamp);
|
||||||
|
packet->ssrc = htonl(packet->ssrc);
|
||||||
|
|
||||||
queueStatus = RtpfAddPacket(&rtpQueue, packet, err, (PRTPFEC_QUEUE_ENTRY)&buffer[receiveSize]);
|
queueStatus = RtpfAddPacket(&rtpQueue, packet, err, (PRTPFEC_QUEUE_ENTRY)&buffer[receiveSize]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user