Perform PLC for each lost packet in the FEC block

This commit is contained in:
Cameron Gutman 2021-06-03 21:03:46 -05:00
parent a8aed6b344
commit 509a17dbc3
2 changed files with 33 additions and 15 deletions

View File

@ -153,13 +153,17 @@ static bool queuePacketToLbq(PQUEUED_AUDIO_PACKET* packet) {
} }
static void decodeInputData(PQUEUED_AUDIO_PACKET packet) { static void decodeInputData(PQUEUED_AUDIO_PACKET packet) {
PRTP_PACKET rtp; // If the packet size is zero, this is a placeholder for a missing
// packet. Trigger packet loss concealment logic in libopus by
// invoking the decoder with a NULL buffer.
if (packet->header.size == 0) {
AudioCallbacks.decodeAndPlaySample(NULL, 0);
return;
}
rtp = (PRTP_PACKET)&packet->data[0]; PRTP_PACKET rtp = (PRTP_PACKET)&packet->data[0];
if (lastSeq != 0 && (unsigned short)(lastSeq + 1) != rtp->sequenceNumber) { if (lastSeq != 0 && (unsigned short)(lastSeq + 1) != rtp->sequenceNumber) {
Limelog("Received OOS audio data (expected %d, but got %d)\n", lastSeq + 1, rtp->sequenceNumber); Limelog("Received OOS audio data (expected %d, but got %d)\n", lastSeq + 1, rtp->sequenceNumber);
AudioCallbacks.decodeAndPlaySample(NULL, 0);
} }
lastSeq = rtp->sequenceNumber; lastSeq = rtp->sequenceNumber;

View File

@ -501,21 +501,31 @@ int RtpaAddPacket(PRTP_AUDIO_QUEUE queue, PRTP_PACKET packet, uint16_t length) {
PRTP_PACKET RtpaGetQueuedPacket(PRTP_AUDIO_QUEUE queue, uint16_t customHeaderLength, uint16_t* length) { PRTP_PACKET RtpaGetQueuedPacket(PRTP_AUDIO_QUEUE queue, uint16_t customHeaderLength, uint16_t* length) {
validateFecBlockState(queue); validateFecBlockState(queue);
// If we're returning audio data even with discontinuities, find the next data packet // If we're returning audio data even with discontinuities, we'll fill in blank entries
// for packets that were lost and could not be recovered.
if (queue->blockHead != NULL && queue->blockHead->allowDiscontinuity) { if (queue->blockHead != NULL && queue->blockHead->allowDiscontinuity) {
PRTPA_FEC_BLOCK nextBlock = queue->blockHead; PRTPA_FEC_BLOCK nextBlock = queue->blockHead;
PRTP_PACKET lostPacket;
while (nextBlock->nextDataPacketIndex < RTPA_DATA_SHARDS) { LC_ASSERT(nextBlock->fecHeader.baseSequenceNumber + nextBlock->nextDataPacketIndex == queue->nextRtpSequenceNumber);
LC_ASSERT(nextBlock->fecHeader.baseSequenceNumber + nextBlock->nextDataPacketIndex == queue->nextRtpSequenceNumber); if (nextBlock->marks[nextBlock->nextDataPacketIndex]) {
if (nextBlock->marks[nextBlock->nextDataPacketIndex]) { // This packet is missing. Return an empty entry to let the caller
// This packet is missing. Skip it. // know to perform packet loss concealment for this frame.
nextBlock->nextDataPacketIndex++; lostPacket = malloc(customHeaderLength);
queue->nextRtpSequenceNumber++; if (lostPacket == NULL) {
} return NULL;
else {
LC_ASSERT(queueHasPacketReady(queue));
break;
} }
// Lost packet placeholder entries have no associated data
*length = 0;
// Move on to the next data shard
nextBlock->nextDataPacketIndex++;
queue->nextRtpSequenceNumber++;
}
else {
lostPacket = NULL;
LC_ASSERT(queueHasPacketReady(queue));
} }
// If we've read everything from this FEC block, remove and free it // If we've read everything from this FEC block, remove and free it
@ -525,6 +535,10 @@ PRTP_PACKET RtpaGetQueuedPacket(PRTP_AUDIO_QUEUE queue, uint16_t customHeaderLen
else { else {
validateFecBlockState(queue); validateFecBlockState(queue);
} }
if (lostPacket != NULL) {
return lostPacket;
}
} }
// Return the next RTP sequence number by indexing into the most recent FEC block // Return the next RTP sequence number by indexing into the most recent FEC block