Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PLI: handle picture loss rtcp packet #308

Merged
merged 2 commits into from
Mar 30, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/include/com/amazonaws/kinesis/video/webrtcclient/Include.h
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,17 @@ typedef VOID (*RtcOnFrame)(UINT64, PFrame);
*/
typedef VOID (*RtcOnBandwidthEstimation)(UINT64, DOUBLE);

/**
* @brief RtcOnPictureLoss is fired everytime a Picture Loss Indication (PLI)
* feedback message is received. Receiving such message normally indicates that
* you sent a video frame which receiver could not decode.
* It may happen either because of packet loss or for any other reason.
* Generating an intra frame (aka keyframe, aka I-frame) in response to such message is considered a good strategy.
*
* See https://tools.ietf.org/html/rfc4585#section-6.3 for more details
*/
typedef VOID (*RtcOnPictureLoss)(UINT64);


/**
* @brief RtcOnMessage is fired when a message is received for the DataChannel
Expand Down
39 changes: 39 additions & 0 deletions src/source/PeerConnection/Rtcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@ STATUS onRtcpPacket(PKvsPeerConnection pKvsPeerConnection, PBYTE pBuff, UINT32 b
isRembPacket(rtcpPacket.payload, rtcpPacket.payloadLength) == STATUS_SUCCESS)
{
CHK_STATUS(onRtcpRembPacket(&rtcpPacket, pKvsPeerConnection));
} else if (rtcpPacket.header.packetType == RTCP_PACKET_TYPE_PAYLOAD_SPECIFIC_FEEDBACK &&
rtcpPacket.header.receptionReportCount == RTCP_PSFB_PLI)
{
CHK_STATUS(onRtcpPLIPacket(&rtcpPacket, pKvsPeerConnection));
}


currentOffset += (rtcpPacket.payloadLength + RTCP_PACKET_HEADER_LEN);
}

Expand Down Expand Up @@ -70,3 +75,37 @@ STATUS onRtcpRembPacket(PRtcpPacket pRtcpPacket, PKvsPeerConnection pKvsPeerConn

return retStatus;
}

STATUS onRtcpPLIPacket(PRtcpPacket pRtcpPacket, PKvsPeerConnection pKvsPeerConnection)
{
STATUS retStatus = STATUS_SUCCESS;
UINT32 mediaSSRC = 0;
PDoubleListNode pCurNode = NULL;
PKvsRtpTransceiver pTransceiver = NULL;
UINT64 item;

CHK(pKvsPeerConnection != NULL && pRtcpPacket != NULL, STATUS_NULL_ARG);
mediaSSRC = getInt32(*(PUINT32) (pRtcpPacket->payload + (SIZEOF(UINT32))));
zhuker marked this conversation as resolved.
Show resolved Hide resolved

CHK_STATUS(doubleListGetHeadNode(pKvsPeerConnection->pTransceievers, &pCurNode));
while(pCurNode != NULL && pTransceiver == NULL) {
CHK_STATUS(doubleListGetNodeData(pCurNode, &item));
CHK(item != 0, STATUS_INTERNAL_ERROR);

pTransceiver = (PKvsRtpTransceiver) item;
if (pTransceiver->sender.ssrc != mediaSSRC && pTransceiver->sender.rtxSsrc != mediaSSRC) {
pTransceiver = NULL;
}

pCurNode = pCurNode->pNext;
}

CHK_ERR(pTransceiver != NULL, STATUS_RTCP_INPUT_SSRC_INVALID, "Received PLI for non existing ssrcs: ssrc %lu", mediaSSRC);
if (pTransceiver->onPictureLoss != NULL) {
pTransceiver->onPictureLoss(pTransceiver->onPictureLossCustomData);
}

CleanUp:

return retStatus;
}
1 change: 1 addition & 0 deletions src/source/PeerConnection/Rtcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extern "C" {

STATUS onRtcpPacket(PKvsPeerConnection, PBYTE, UINT32);
STATUS onRtcpRembPacket(PRtcpPacket, PKvsPeerConnection);
STATUS onRtcpPLIPacket(PRtcpPacket, PKvsPeerConnection);

#ifdef __cplusplus
}
Expand Down
2 changes: 2 additions & 0 deletions src/source/PeerConnection/Rtp.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ typedef struct {

UINT64 onBandwidthEstimationCustomData;
RtcOnBandwidthEstimation onBandwidthEstimation;
UINT64 onPictureLossCustomData;
RtcOnPictureLoss onPictureLoss;

PBYTE peerFrameBuffer;
UINT32 peerFrameBufferSize;
Expand Down
1 change: 1 addition & 0 deletions src/source/Rtcp/RtcpPacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ typedef enum {

typedef enum {
RTCP_FEEDBACK_MESSAGE_TYPE_NACK = 1,
RTCP_PSFB_PLI = 1, //https://tools.ietf.org/html/rfc4585#section-6.3
RTCP_FEEDBACK_MESSAGE_TYPE_APPLICATION_LAYER_FEEDBACK = 15,
} RTCP_FEEDBACK_MESSAGE_TYPE;

Expand Down
24 changes: 24 additions & 0 deletions tst/RtcpFunctionalityTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,30 @@ TEST_F(RtcpFunctionalityTest, rembValueGet) {
EXPECT_EQ(STATUS_RTCP_INPUT_REMB_INVALID, rembValueGet(invalidSSRCLength, SIZEOF(invalidSSRCLength), &maximumBitRate, ssrcList, &ssrcListLen));
}

static void on_PLI_callback(UINT64 opaque) {
*(PBOOL) opaque = TRUE;
}

TEST_F(RtcpFunctionalityTest, onpli) {
initializeEndianness();
zhuker marked this conversation as resolved.
Show resolved Hide resolved
BYTE rawRtcpPacket[] = {0x81, 0xCE, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x1D, 0xC8, 0x69, 0x91};
RtcpPacket rtcpPacket = {0};
zhuker marked this conversation as resolved.
Show resolved Hide resolved
EXPECT_EQ(STATUS_SUCCESS, setRtcpPacketFromBytes(rawRtcpPacket, SIZEOF(rawRtcpPacket), &rtcpPacket));
ASSERT_TRUE(rtcpPacket.header.packetType == RTCP_PACKET_TYPE_PAYLOAD_SPECIFIC_FEEDBACK &&
rtcpPacket.header.receptionReportCount == RTCP_PSFB_PLI);
KvsPeerConnection kpc = {0};
doubleListCreate(&kpc.pTransceievers);
KvsRtpTransceiver kvsRtpTransceiver;
MEMSET(&kvsRtpTransceiver, 0, sizeof(KvsRtpTransceiver));
kvsRtpTransceiver.sender.ssrc = 0x1DC86991;
BOOL on_picture_loss_called = FALSE;
kvsRtpTransceiver.onPictureLossCustomData = (UINT64) &on_picture_loss_called;
kvsRtpTransceiver.onPictureLoss = on_PLI_callback;
doubleListInsertItemHead(kpc.pTransceievers, (UINT64) &kvsRtpTransceiver);
onRtcpPLIPacket(&rtcpPacket, &kpc);
zhuker marked this conversation as resolved.
Show resolved Hide resolved
ASSERT_TRUE(on_picture_loss_called);
}

}
}
}
Expand Down