1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Upgrade libsrt to v1.5.3. v5.0.183 v6.0.81 (#3808)

fix https://github.com/ossrs/srs/issues/3155
Build srt-1-fit fails with `standard attributes in middle of
decl-specifiers` on GCC 12,Arch Linux.

See https://github.com/Haivision/srt/releases/tag/v1.5.3
This commit is contained in:
Haibo Chen 2023-09-21 22:23:56 +08:00 committed by GitHub
parent f9bba0a9b0
commit c5e067fb0b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
94 changed files with 5974 additions and 6273 deletions

View file

@ -1,4 +1,48 @@
#if ENABLE_NEW_RCVBUFFER
/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2018 Haivision Systems Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
/*****************************************************************************
Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include <cmath>
#include <limits>
#include "buffer_rcv.h"
@ -31,15 +75,15 @@ namespace {
#define IF_RCVBUF_DEBUG(instr) (void)0
// Check if iFirstNonreadPos is in range [iStartPos, (iStartPos + iMaxPosInc) % iSize].
// Check if iFirstNonreadPos is in range [iStartPos, (iStartPos + iMaxPosOff) % iSize].
// The right edge is included because we expect iFirstNonreadPos to be
// right after the last valid packet position if all packets are available.
bool isInRange(int iStartPos, int iMaxPosInc, size_t iSize, int iFirstNonreadPos)
bool isInRange(int iStartPos, int iMaxPosOff, size_t iSize, int iFirstNonreadPos)
{
if (iFirstNonreadPos == iStartPos)
return true;
const int iLastPos = (iStartPos + iMaxPosInc) % iSize;
const int iLastPos = (iStartPos + iMaxPosOff) % iSize;
const bool isOverrun = iLastPos < iStartPos;
if (isOverrun)
@ -54,7 +98,7 @@ namespace {
* RcvBufferNew (circular buffer):
*
* |<------------------- m_iSize ----------------------------->|
* | |<----------- m_iMaxPosInc ------------>| |
* | |<----------- m_iMaxPosOff ------------>| |
* | | | |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+
* | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 0 |...| 0 | m_pUnit[]
@ -68,17 +112,17 @@ namespace {
* thread safety:
* m_iStartPos: CUDT::m_RecvLock
* m_iLastAckPos: CUDT::m_AckLock
* m_iMaxPosInc: none? (modified on add and ack
* m_iMaxPosOff: none? (modified on add and ack
*/
CRcvBufferNew::CRcvBufferNew(int initSeqNo, size_t size, CUnitQueue* unitqueue, bool bMessageAPI)
CRcvBuffer::CRcvBuffer(int initSeqNo, size_t size, CUnitQueue* unitqueue, bool bMessageAPI)
: m_entries(size)
, m_szSize(size) // TODO: maybe just use m_entries.size()
, m_pUnitQueue(unitqueue)
, m_iStartSeqNo(initSeqNo)
, m_iStartPos(0)
, m_iFirstNonreadPos(0)
, m_iMaxPosInc(0)
, m_iMaxPosOff(0)
, m_iNotch(0)
, m_numOutOfOrderPackets(0)
, m_iFirstReadableOutOfOrder(-1)
@ -91,9 +135,9 @@ CRcvBufferNew::CRcvBufferNew(int initSeqNo, size_t size, CUnitQueue* unitqueue,
SRT_ASSERT(size < size_t(std::numeric_limits<int>::max())); // All position pointers are integers
}
CRcvBufferNew::~CRcvBufferNew()
CRcvBuffer::~CRcvBuffer()
{
// Can be optimized by only iterating m_iMaxPosInc from m_iStartPos.
// Can be optimized by only iterating m_iMaxPosOff from m_iStartPos.
for (FixedArray<Entry>::iterator it = m_entries.begin(); it != m_entries.end(); ++it)
{
if (!it->pUnit)
@ -104,14 +148,14 @@ CRcvBufferNew::~CRcvBufferNew()
}
}
int CRcvBufferNew::insert(CUnit* unit)
int CRcvBuffer::insert(CUnit* unit)
{
SRT_ASSERT(unit != NULL);
const int32_t seqno = unit->m_Packet.getSeqNo();
const int offset = CSeqNo::seqoff(m_iStartSeqNo, seqno);
IF_RCVBUF_DEBUG(ScopedLog scoped_log);
IF_RCVBUF_DEBUG(scoped_log.ss << "CRcvBufferNew::insert: seqno " << seqno);
IF_RCVBUF_DEBUG(scoped_log.ss << "CRcvBuffer::insert: seqno " << seqno);
IF_RCVBUF_DEBUG(scoped_log.ss << " msgno " << unit->m_Packet.getMsgSeq(m_bPeerRexmitFlag));
IF_RCVBUF_DEBUG(scoped_log.ss << " m_iStartSeqNo " << m_iStartSeqNo << " offset " << offset);
@ -132,8 +176,8 @@ int CRcvBufferNew::insert(CUnit* unit)
SRT_ASSERT((m_iStartPos + offset) / m_szSize < 2);
const int pos = (m_iStartPos + offset) % m_szSize;
if (offset >= m_iMaxPosInc)
m_iMaxPosInc = offset + 1;
if (offset >= m_iMaxPosOff)
m_iMaxPosOff = offset + 1;
// Packet already exists
SRT_ASSERT(pos >= 0 && pos < int(m_szSize));
@ -144,7 +188,7 @@ int CRcvBufferNew::insert(CUnit* unit)
}
SRT_ASSERT(m_entries[pos].pUnit == NULL);
m_pUnitQueue->makeUnitGood(unit);
m_pUnitQueue->makeUnitTaken(unit);
m_entries[pos].pUnit = unit;
m_entries[pos].status = EntryState_Avail;
countBytes(1, (int)unit->m_Packet.getLength());
@ -162,10 +206,10 @@ int CRcvBufferNew::insert(CUnit* unit)
return 0;
}
int CRcvBufferNew::dropUpTo(int32_t seqno)
int CRcvBuffer::dropUpTo(int32_t seqno)
{
IF_RCVBUF_DEBUG(ScopedLog scoped_log);
IF_RCVBUF_DEBUG(scoped_log.ss << "CRcvBufferNew::dropUpTo: seqno " << seqno << " m_iStartSeqNo " << m_iStartSeqNo);
IF_RCVBUF_DEBUG(scoped_log.ss << "CRcvBuffer::dropUpTo: seqno " << seqno << " m_iStartSeqNo " << m_iStartSeqNo);
int len = CSeqNo::seqoff(m_iStartSeqNo, seqno);
if (len <= 0)
@ -174,9 +218,9 @@ int CRcvBufferNew::dropUpTo(int32_t seqno)
return 0;
}
m_iMaxPosInc -= len;
if (m_iMaxPosInc < 0)
m_iMaxPosInc = 0;
m_iMaxPosOff -= len;
if (m_iMaxPosOff < 0)
m_iMaxPosOff = 0;
const int iDropCnt = len;
while (len > 0)
@ -192,91 +236,87 @@ int CRcvBufferNew::dropUpTo(int32_t seqno)
m_iStartSeqNo = seqno;
// Move forward if there are "read/drop" entries.
releaseNextFillerEntries();
// Set nonread position to the starting position before updating,
// because start position was increased, and preceeding packets are invalid.
m_iFirstNonreadPos = m_iStartPos;
updateNonreadPos();
// If the nonread position is now behind the starting position, set it to the starting position and update.
// Preceding packets were likely missing, and the non read position can probably be moved further now.
if (CSeqNo::seqcmp(m_iFirstNonreadPos, m_iStartPos) < 0)
{
m_iFirstNonreadPos = m_iStartPos;
updateNonreadPos();
}
if (!m_tsbpd.isEnabled() && m_bMessageAPI)
updateFirstReadableOutOfOrder();
return iDropCnt;
}
int CRcvBufferNew::dropAll()
int CRcvBuffer::dropAll()
{
if (empty())
return 0;
const int end_seqno = CSeqNo::incseq(m_iStartSeqNo, m_iMaxPosInc);
const int end_seqno = CSeqNo::incseq(m_iStartSeqNo, m_iMaxPosOff);
return dropUpTo(end_seqno);
}
int CRcvBufferNew::dropMessage(int32_t seqnolo, int32_t seqnohi, int32_t msgno)
int CRcvBuffer::dropMessage(int32_t seqnolo, int32_t seqnohi, int32_t msgno, DropActionIfExists actionOnExisting)
{
IF_RCVBUF_DEBUG(ScopedLog scoped_log);
IF_RCVBUF_DEBUG(scoped_log.ss << "CRcvBufferNew::dropMessage: seqnolo " << seqnolo << " seqnohi " << seqnohi << " m_iStartSeqNo " << m_iStartSeqNo);
// TODO: count bytes as removed?
const int end_pos = incPos(m_iStartPos, m_iMaxPosInc);
if (msgno != 0)
{
IF_RCVBUF_DEBUG(scoped_log.ss << " msgno " << msgno);
int minDroppedOffset = -1;
int iDropCnt = 0;
for (int i = m_iStartPos; i != end_pos; i = incPos(i))
{
// TODO: Maybe check status?
if (!m_entries[i].pUnit)
continue;
IF_RCVBUF_DEBUG(scoped_log.ss << "CRcvBuffer::dropMessage(): %(" << seqnolo << " - " << seqnohi << ")"
<< " #" << msgno << " actionOnExisting=" << actionOnExisting << " m_iStartSeqNo=%"
<< m_iStartSeqNo);
// TODO: Break the loop if a massege has been found. No need to search further.
const int32_t msgseq = m_entries[i].pUnit->m_Packet.getMsgSeq(m_bPeerRexmitFlag);
if (msgseq == msgno)
{
++iDropCnt;
dropUnitInPos(i);
m_entries[i].status = EntryState_Drop;
if (minDroppedOffset == -1)
minDroppedOffset = offPos(m_iStartPos, i);
}
}
IF_RCVBUF_DEBUG(scoped_log.ss << " iDropCnt " << iDropCnt);
// Check if units before m_iFirstNonreadPos are dropped.
bool needUpdateNonreadPos = (minDroppedOffset != -1 && minDroppedOffset <= getRcvDataSize());
releaseNextFillerEntries();
if (needUpdateNonreadPos)
{
m_iFirstNonreadPos = m_iStartPos;
updateNonreadPos();
}
if (!m_tsbpd.isEnabled() && m_bMessageAPI)
{
if (!checkFirstReadableOutOfOrder())
m_iFirstReadableOutOfOrder = -1;
updateFirstReadableOutOfOrder();
}
return iDropCnt;
}
// Drop by packet seqno range.
// Drop by packet seqno range to also wipe those packets that do not exist in the buffer.
const int offset_a = CSeqNo::seqoff(m_iStartSeqNo, seqnolo);
const int offset_b = CSeqNo::seqoff(m_iStartSeqNo, seqnohi);
if (offset_b < 0)
{
LOGC(rbuflog.Debug, log << "CRcvBufferNew.dropMessage(): nothing to drop. Requested [" << seqnolo << "; "
<< seqnohi << "]. Buffer start " << m_iStartSeqNo << ".");
LOGC(rbuflog.Debug, log << "CRcvBuffer.dropMessage(): nothing to drop. Requested [" << seqnolo << "; "
<< seqnohi << "]. Buffer start " << m_iStartSeqNo << ".");
return 0;
}
const int start_off = max(0, offset_a);
const int last_pos = incPos(m_iStartPos, offset_b);
const bool bKeepExisting = (actionOnExisting == KEEP_EXISTING);
int minDroppedOffset = -1;
int iDropCnt = 0;
for (int i = incPos(m_iStartPos, start_off); i != end_pos && i != last_pos; i = incPos(i))
const int start_off = max(0, offset_a);
const int start_pos = incPos(m_iStartPos, start_off);
const int end_off = min((int) m_szSize - 1, offset_b + 1);
const int end_pos = incPos(m_iStartPos, end_off);
bool bDropByMsgNo = msgno > SRT_MSGNO_CONTROL; // Excluding both SRT_MSGNO_NONE (-1) and SRT_MSGNO_CONTROL (0).
for (int i = start_pos; i != end_pos; i = incPos(i))
{
// Don't drop messages, if all its packets are already in the buffer.
// TODO: Don't drop a several-packet message if all packets are in the buffer.
if (m_entries[i].pUnit && m_entries[i].pUnit->m_Packet.getMsgBoundary() == PB_SOLO)
// Check if the unit was already dropped earlier.
if (m_entries[i].status == EntryState_Drop)
continue;
if (m_entries[i].pUnit)
{
const PacketBoundary bnd = packetAt(i).getMsgBoundary();
// Don't drop messages, if all its packets are already in the buffer.
// TODO: Don't drop a several-packet message if all packets are in the buffer.
if (bKeepExisting && bnd == PB_SOLO)
{
bDropByMsgNo = false; // Solo packet, don't search for the rest of the message.
LOGC(rbuflog.Debug,
log << "CRcvBuffer::dropMessage(): Skipped dropping an existing SOLO packet %"
<< packetAt(i).getSeqNo() << ".");
continue;
}
const int32_t msgseq = packetAt(i).getMsgSeq(m_bPeerRexmitFlag);
if (msgno > SRT_MSGNO_CONTROL && msgseq != msgno)
{
LOGC(rbuflog.Warn, log << "CRcvBuffer.dropMessage(): Packet seqno %" << packetAt(i).getSeqNo() << " has msgno " << msgseq << " differs from requested " << msgno);
}
if (bDropByMsgNo && bnd == PB_FIRST)
{
// First packet of the message is about to be dropped. That was the only reason to search for msgno.
bDropByMsgNo = false;
}
}
dropUnitInPos(i);
++iDropCnt;
m_entries[i].status = EntryState_Drop;
@ -284,11 +324,48 @@ int CRcvBufferNew::dropMessage(int32_t seqnolo, int32_t seqnohi, int32_t msgno)
minDroppedOffset = offPos(m_iStartPos, i);
}
LOGC(rbuflog.Debug, log << "CRcvBufferNew.dropMessage(): [" << seqnolo << "; "
<< seqnohi << "].");
if (bDropByMsgNo)
{
// If msgno is specified, potentially not the whole message was dropped using seqno range.
// The sender might have removed the first packets of the message, and thus @a seqnolo may point to a packet in the middle.
// The sender should have the last packet of the message it is requesting to be dropped.
// Therefore we don't search forward, but need to check earlier packets in the RCV buffer.
// Try to drop by the message number in case the message starts earlier than @a seqnolo.
const int stop_pos = decPos(m_iStartPos);
for (int i = start_pos; i != stop_pos; i = decPos(i))
{
// Can't drop if message number is not known.
if (!m_entries[i].pUnit) // also dropped earlier.
continue;
const PacketBoundary bnd = packetAt(i).getMsgBoundary();
const int32_t msgseq = packetAt(i).getMsgSeq(m_bPeerRexmitFlag);
if (msgseq != msgno)
break;
if (bKeepExisting && bnd == PB_SOLO)
{
LOGC(rbuflog.Debug,
log << "CRcvBuffer::dropMessage(): Skipped dropping an existing SOLO message packet %"
<< packetAt(i).getSeqNo() << ".");
break;
}
++iDropCnt;
dropUnitInPos(i);
m_entries[i].status = EntryState_Drop;
// As the search goes backward, i is always earlier than minDroppedOffset.
minDroppedOffset = offPos(m_iStartPos, i);
// Break the loop if the start of the message has been found. No need to search further.
if (bnd == PB_FIRST)
break;
}
IF_RCVBUF_DEBUG(scoped_log.ss << " iDropCnt " << iDropCnt);
}
// Check if units before m_iFirstNonreadPos are dropped.
bool needUpdateNonreadPos = (minDroppedOffset != -1 && minDroppedOffset <= getRcvDataSize());
const bool needUpdateNonreadPos = (minDroppedOffset != -1 && minDroppedOffset <= getRcvDataSize());
releaseNextFillerEntries();
if (needUpdateNonreadPos)
{
@ -305,19 +382,19 @@ int CRcvBufferNew::dropMessage(int32_t seqnolo, int32_t seqnohi, int32_t msgno)
return iDropCnt;
}
int CRcvBufferNew::readMessage(char* data, size_t len, SRT_MSGCTRL* msgctrl)
int CRcvBuffer::readMessage(char* data, size_t len, SRT_MSGCTRL* msgctrl)
{
const bool canReadInOrder = hasReadableInorderPkts();
if (!canReadInOrder && m_iFirstReadableOutOfOrder < 0)
{
LOGC(rbuflog.Warn, log << "CRcvBufferNew.readMessage(): nothing to read. Ignored isRcvDataReady() result?");
LOGC(rbuflog.Warn, log << "CRcvBuffer.readMessage(): nothing to read. Ignored isRcvDataReady() result?");
return 0;
}
const int readPos = canReadInOrder ? m_iStartPos : m_iFirstReadableOutOfOrder;
IF_RCVBUF_DEBUG(ScopedLog scoped_log);
IF_RCVBUF_DEBUG(scoped_log.ss << "CRcvBufferNew::readMessage. m_iStartSeqNo " << m_iStartSeqNo << " m_iStartPos " << m_iStartPos << " readPos " << readPos);
IF_RCVBUF_DEBUG(scoped_log.ss << "CRcvBuffer::readMessage. m_iStartSeqNo " << m_iStartSeqNo << " m_iStartPos " << m_iStartPos << " readPos " << readPos);
size_t remain = len;
char* dst = data;
@ -329,11 +406,11 @@ int CRcvBufferNew::readMessage(char* data, size_t len, SRT_MSGCTRL* msgctrl)
SRT_ASSERT(m_entries[i].pUnit);
if (!m_entries[i].pUnit)
{
LOGC(rbuflog.Error, log << "CRcvBufferNew::readMessage(): null packet encountered.");
LOGC(rbuflog.Error, log << "CRcvBuffer::readMessage(): null packet encountered.");
break;
}
const CPacket& packet = m_entries[i].pUnit->m_Packet;
const CPacket& packet = packetAt(i);
const size_t pktsize = packet.getLength();
const int32_t pktseqno = packet.getSeqNo();
@ -368,8 +445,8 @@ int CRcvBufferNew::readMessage(char* data, size_t len, SRT_MSGCTRL* msgctrl)
if (updateStartPos)
{
m_iStartPos = incPos(i);
--m_iMaxPosInc;
SRT_ASSERT(m_iMaxPosInc >= 0);
--m_iMaxPosOff;
SRT_ASSERT(m_iMaxPosOff >= 0);
m_iStartSeqNo = CSeqNo::incseq(pktseqno);
}
else
@ -390,7 +467,7 @@ int CRcvBufferNew::readMessage(char* data, size_t len, SRT_MSGCTRL* msgctrl)
releaseNextFillerEntries();
if (!isInRange(m_iStartPos, m_iMaxPosInc, m_szSize, m_iFirstNonreadPos))
if (!isInRange(m_iStartPos, m_iMaxPosOff, m_szSize, m_iFirstNonreadPos))
{
m_iFirstNonreadPos = m_iStartPos;
//updateNonreadPos();
@ -440,7 +517,7 @@ namespace {
}
}
int CRcvBufferNew::readBufferTo(int len, copy_to_dst_f funcCopyToDst, void* arg)
int CRcvBuffer::readBufferTo(int len, copy_to_dst_f funcCopyToDst, void* arg)
{
int p = m_iStartPos;
const int end_pos = m_iFirstNonreadPos;
@ -458,7 +535,7 @@ int CRcvBufferNew::readBufferTo(int len, copy_to_dst_f funcCopyToDst, void* arg)
return -1;
}
const srt::CPacket& pkt = m_entries[p].pUnit->m_Packet;
const srt::CPacket& pkt = packetAt(p);
if (bTsbPdEnabled)
{
@ -486,8 +563,8 @@ int CRcvBufferNew::readBufferTo(int len, copy_to_dst_f funcCopyToDst, void* arg)
m_iNotch = 0;
m_iStartPos = p;
--m_iMaxPosInc;
SRT_ASSERT(m_iMaxPosInc >= 0);
--m_iMaxPosOff;
SRT_ASSERT(m_iMaxPosOff >= 0);
m_iStartSeqNo = CSeqNo::incseq(m_iStartSeqNo);
}
else
@ -502,8 +579,8 @@ int CRcvBufferNew::readBufferTo(int len, copy_to_dst_f funcCopyToDst, void* arg)
// Update positions
// Set nonread position to the starting position before updating,
// because start position was increased, and preceeding packets are invalid.
if (!isInRange(m_iStartPos, m_iMaxPosInc, m_szSize, m_iFirstNonreadPos))
// because start position was increased, and preceding packets are invalid.
if (!isInRange(m_iStartPos, m_iMaxPosOff, m_szSize, m_iFirstNonreadPos))
{
m_iFirstNonreadPos = m_iStartPos;
}
@ -516,22 +593,22 @@ int CRcvBufferNew::readBufferTo(int len, copy_to_dst_f funcCopyToDst, void* arg)
return iBytesRead;
}
int CRcvBufferNew::readBuffer(char* dst, int len)
int CRcvBuffer::readBuffer(char* dst, int len)
{
return readBufferTo(len, copyBytesToBuf, reinterpret_cast<void*>(dst));
}
int CRcvBufferNew::readBufferToFile(fstream& ofs, int len)
int CRcvBuffer::readBufferToFile(fstream& ofs, int len)
{
return readBufferTo(len, writeBytesToFile, reinterpret_cast<void*>(&ofs));
}
bool CRcvBufferNew::hasAvailablePackets() const
bool CRcvBuffer::hasAvailablePackets() const
{
return hasReadableInorderPkts() || (m_numOutOfOrderPackets > 0 && m_iFirstReadableOutOfOrder != -1);
}
int CRcvBufferNew::getRcvDataSize() const
int CRcvBuffer::getRcvDataSize() const
{
if (m_iFirstNonreadPos >= m_iStartPos)
return m_iFirstNonreadPos - m_iStartPos;
@ -539,36 +616,40 @@ int CRcvBufferNew::getRcvDataSize() const
return int(m_szSize + m_iFirstNonreadPos - m_iStartPos);
}
int CRcvBufferNew::getTimespan_ms() const
int CRcvBuffer::getTimespan_ms() const
{
if (!m_tsbpd.isEnabled())
return 0;
if (m_iMaxPosInc == 0)
if (m_iMaxPosOff == 0)
return 0;
const int lastpos = incPos(m_iStartPos, m_iMaxPosInc - 1);
int startpos = m_iStartPos;
while (m_entries[startpos].pUnit == NULL)
int lastpos = incPos(m_iStartPos, m_iMaxPosOff - 1);
// Normally the last position should always be non empty
// if TSBPD is enabled (reading out of order is not allowed).
// However if decryption of the last packet fails, it may be dropped
// from the buffer (AES-GCM), and the position will be empty.
SRT_ASSERT(m_entries[lastpos].pUnit != NULL || m_entries[lastpos].status == EntryState_Drop);
while (m_entries[lastpos].pUnit == NULL && lastpos != m_iStartPos)
{
if (startpos == lastpos)
break;
lastpos = decPos(lastpos);
}
if (m_entries[lastpos].pUnit == NULL)
return 0;
int startpos = m_iStartPos;
while (m_entries[startpos].pUnit == NULL && startpos != lastpos)
{
startpos = incPos(startpos);
}
if (m_entries[startpos].pUnit == NULL)
return 0;
// Should not happen
SRT_ASSERT(m_entries[lastpos].pUnit != NULL);
if (m_entries[lastpos].pUnit == NULL)
return 0;
const steady_clock::time_point startstamp =
getPktTsbPdTime(m_entries[startpos].pUnit->m_Packet.getMsgTimeStamp());
const steady_clock::time_point endstamp = getPktTsbPdTime(m_entries[lastpos].pUnit->m_Packet.getMsgTimeStamp());
getPktTsbPdTime(packetAt(startpos).getMsgTimeStamp());
const steady_clock::time_point endstamp = getPktTsbPdTime(packetAt(lastpos).getMsgTimeStamp());
if (endstamp < startstamp)
return 0;
@ -577,7 +658,7 @@ int CRcvBufferNew::getTimespan_ms() const
return static_cast<int>(count_milliseconds(endstamp - startstamp) + 1);
}
int CRcvBufferNew::getRcvDataSize(int& bytes, int& timespan) const
int CRcvBuffer::getRcvDataSize(int& bytes, int& timespan) const
{
ScopedLock lck(m_BytesCountLock);
bytes = m_iBytesCount;
@ -585,16 +666,16 @@ int CRcvBufferNew::getRcvDataSize(int& bytes, int& timespan) const
return m_iPktsCount;
}
CRcvBufferNew::PacketInfo CRcvBufferNew::getFirstValidPacketInfo() const
CRcvBuffer::PacketInfo CRcvBuffer::getFirstValidPacketInfo() const
{
const int end_pos = incPos(m_iStartPos, m_iMaxPosInc);
const int end_pos = incPos(m_iStartPos, m_iMaxPosOff);
for (int i = m_iStartPos; i != end_pos; i = incPos(i))
{
// TODO: Maybe check status?
if (!m_entries[i].pUnit)
continue;
const CPacket& packet = m_entries[i].pUnit->m_Packet;
const CPacket& packet = packetAt(i);
const PacketInfo info = { packet.getSeqNo(), i != m_iStartPos, getPktTsbPdTime(packet.getMsgTimeStamp()) };
return info;
}
@ -603,20 +684,20 @@ CRcvBufferNew::PacketInfo CRcvBufferNew::getFirstValidPacketInfo() const
return info;
}
std::pair<int, int> CRcvBufferNew::getAvailablePacketsRange() const
std::pair<int, int> CRcvBuffer::getAvailablePacketsRange() const
{
const int seqno_last = CSeqNo::incseq(m_iStartSeqNo, (int) countReadable());
return std::pair<int, int>(m_iStartSeqNo, seqno_last);
}
size_t CRcvBufferNew::countReadable() const
size_t CRcvBuffer::countReadable() const
{
if (m_iFirstNonreadPos >= m_iStartPos)
return m_iFirstNonreadPos - m_iStartPos;
return m_szSize + m_iFirstNonreadPos - m_iStartPos;
}
bool CRcvBufferNew::isRcvDataReady(time_point time_now) const
bool CRcvBuffer::isRcvDataReady(time_point time_now) const
{
const bool haveInorderPackets = hasReadableInorderPkts();
if (!m_tsbpd.isEnabled())
@ -636,7 +717,7 @@ bool CRcvBufferNew::isRcvDataReady(time_point time_now) const
return info.tsbpd_time <= time_now;
}
CRcvBufferNew::PacketInfo CRcvBufferNew::getFirstReadablePacketInfo(time_point time_now) const
CRcvBuffer::PacketInfo CRcvBuffer::getFirstReadablePacketInfo(time_point time_now) const
{
const PacketInfo unreadableInfo = {SRT_SEQNO_NONE, false, time_point()};
const bool hasInorderPackets = hasReadableInorderPkts();
@ -645,7 +726,7 @@ CRcvBufferNew::PacketInfo CRcvBufferNew::getFirstReadablePacketInfo(time_point t
{
if (hasInorderPackets)
{
const CPacket& packet = m_entries[m_iStartPos].pUnit->m_Packet;
const CPacket& packet = packetAt(m_iStartPos);
const PacketInfo info = {packet.getSeqNo(), false, time_point()};
return info;
}
@ -653,7 +734,7 @@ CRcvBufferNew::PacketInfo CRcvBufferNew::getFirstReadablePacketInfo(time_point t
if (m_iFirstReadableOutOfOrder >= 0)
{
SRT_ASSERT(m_numOutOfOrderPackets > 0);
const CPacket& packet = m_entries[m_iFirstReadableOutOfOrder].pUnit->m_Packet;
const CPacket& packet = packetAt(m_iFirstReadableOutOfOrder);
const PacketInfo info = {packet.getSeqNo(), true, time_point()};
return info;
}
@ -671,7 +752,7 @@ CRcvBufferNew::PacketInfo CRcvBufferNew::getFirstReadablePacketInfo(time_point t
return unreadableInfo;
}
void CRcvBufferNew::countBytes(int pkts, int bytes)
void CRcvBuffer::countBytes(int pkts, int bytes)
{
ScopedLock lock(m_BytesCountLock);
m_iBytesCount += bytes; // added or removed bytes from rcv buffer
@ -680,7 +761,7 @@ void CRcvBufferNew::countBytes(int pkts, int bytes)
m_uAvgPayloadSz = avg_iir<100>(m_uAvgPayloadSz, (unsigned) bytes);
}
void CRcvBufferNew::releaseUnitInPos(int pos)
void CRcvBuffer::releaseUnitInPos(int pos)
{
CUnit* tmp = m_entries[pos].pUnit;
m_entries[pos] = Entry(); // pUnit = NULL; status = Empty
@ -688,15 +769,15 @@ void CRcvBufferNew::releaseUnitInPos(int pos)
m_pUnitQueue->makeUnitFree(tmp);
}
bool CRcvBufferNew::dropUnitInPos(int pos)
bool CRcvBuffer::dropUnitInPos(int pos)
{
if (!m_entries[pos].pUnit)
return false;
if (m_tsbpd.isEnabled())
{
updateTsbPdTimeBase(m_entries[pos].pUnit->m_Packet.getMsgTimeStamp());
updateTsbPdTimeBase(packetAt(pos).getMsgTimeStamp());
}
else if (m_bMessageAPI && !m_entries[pos].pUnit->m_Packet.getMsgOrderFlag())
else if (m_bMessageAPI && !packetAt(pos).getMsgOrderFlag())
{
--m_numOutOfOrderPackets;
if (pos == m_iFirstReadableOutOfOrder)
@ -706,7 +787,7 @@ bool CRcvBufferNew::dropUnitInPos(int pos)
return true;
}
void CRcvBufferNew::releaseNextFillerEntries()
void CRcvBuffer::releaseNextFillerEntries()
{
int pos = m_iStartPos;
while (m_entries[pos].status == EntryState_Read || m_entries[pos].status == EntryState_Drop)
@ -715,24 +796,24 @@ void CRcvBufferNew::releaseNextFillerEntries()
releaseUnitInPos(pos);
pos = incPos(pos);
m_iStartPos = pos;
--m_iMaxPosInc;
if (m_iMaxPosInc < 0)
m_iMaxPosInc = 0;
--m_iMaxPosOff;
if (m_iMaxPosOff < 0)
m_iMaxPosOff = 0;
}
}
// TODO: Is this function complete? There are some comments left inside.
void CRcvBufferNew::updateNonreadPos()
void CRcvBuffer::updateNonreadPos()
{
if (m_iMaxPosInc == 0)
if (m_iMaxPosOff == 0)
return;
const int end_pos = incPos(m_iStartPos, m_iMaxPosInc); // The empty position right after the last valid entry.
const int end_pos = incPos(m_iStartPos, m_iMaxPosOff); // The empty position right after the last valid entry.
int pos = m_iFirstNonreadPos;
while (m_entries[pos].pUnit && m_entries[pos].status == EntryState_Avail)
{
if (m_bMessageAPI && (m_entries[pos].pUnit->m_Packet.getMsgBoundary() & PB_FIRST) == 0)
if (m_bMessageAPI && (packetAt(pos).getMsgBoundary() & PB_FIRST) == 0)
break;
for (int i = pos; i != end_pos; i = incPos(i))
@ -743,7 +824,7 @@ void CRcvBufferNew::updateNonreadPos()
}
// Check PB_LAST only in message mode.
if (!m_bMessageAPI || m_entries[i].pUnit->m_Packet.getMsgBoundary() & PB_LAST)
if (!m_bMessageAPI || packetAt(i).getMsgBoundary() & PB_LAST)
{
m_iFirstNonreadPos = incPos(i);
break;
@ -757,13 +838,13 @@ void CRcvBufferNew::updateNonreadPos()
}
}
int CRcvBufferNew::findLastMessagePkt()
int CRcvBuffer::findLastMessagePkt()
{
for (int i = m_iStartPos; i != m_iFirstNonreadPos; i = incPos(i))
{
SRT_ASSERT(m_entries[i].pUnit);
if (m_entries[i].pUnit->m_Packet.getMsgBoundary() & PB_LAST)
if (packetAt(i).getMsgBoundary() & PB_LAST)
{
return i;
}
@ -772,7 +853,7 @@ int CRcvBufferNew::findLastMessagePkt()
return -1;
}
void CRcvBufferNew::onInsertNotInOrderPacket(int insertPos)
void CRcvBuffer::onInsertNotInOrderPacket(int insertPos)
{
if (m_numOutOfOrderPackets == 0)
return;
@ -788,9 +869,9 @@ void CRcvBufferNew::onInsertNotInOrderPacket(int insertPos)
// Just a sanity check. This function is called when a new packet is added.
// So the should be unacknowledged packets.
SRT_ASSERT(m_iMaxPosInc > 0);
SRT_ASSERT(m_iMaxPosOff > 0);
SRT_ASSERT(m_entries[insertPos].pUnit);
const CPacket& pkt = m_entries[insertPos].pUnit->m_Packet;
const CPacket& pkt = packetAt(insertPos);
const PacketBoundary boundary = pkt.getMsgBoundary();
//if ((boundary & PB_FIRST) && (boundary & PB_LAST))
@ -816,19 +897,19 @@ void CRcvBufferNew::onInsertNotInOrderPacket(int insertPos)
return;
}
bool CRcvBufferNew::checkFirstReadableOutOfOrder()
bool CRcvBuffer::checkFirstReadableOutOfOrder()
{
if (m_numOutOfOrderPackets <= 0 || m_iFirstReadableOutOfOrder < 0 || m_iMaxPosInc == 0)
if (m_numOutOfOrderPackets <= 0 || m_iFirstReadableOutOfOrder < 0 || m_iMaxPosOff == 0)
return false;
const int endPos = incPos(m_iStartPos, m_iMaxPosInc);
const int endPos = incPos(m_iStartPos, m_iMaxPosOff);
int msgno = -1;
for (int pos = m_iFirstReadableOutOfOrder; pos != endPos; pos = incPos(pos))
{
if (!m_entries[pos].pUnit)
return false;
const CPacket& pkt = m_entries[pos].pUnit->m_Packet;
const CPacket& pkt = packetAt(pos);
if (pkt.getMsgOrderFlag())
return false;
@ -844,12 +925,12 @@ bool CRcvBufferNew::checkFirstReadableOutOfOrder()
return false;
}
void CRcvBufferNew::updateFirstReadableOutOfOrder()
void CRcvBuffer::updateFirstReadableOutOfOrder()
{
if (hasReadableInorderPkts() || m_numOutOfOrderPackets <= 0 || m_iFirstReadableOutOfOrder >= 0)
return;
if (m_iMaxPosInc == 0)
if (m_iMaxPosOff == 0)
return;
// TODO: unused variable outOfOrderPktsRemain?
@ -857,7 +938,7 @@ void CRcvBufferNew::updateFirstReadableOutOfOrder()
// Search further packets to the right.
// First check if there are packets to the right.
const int lastPos = (m_iStartPos + m_iMaxPosInc - 1) % m_szSize;
const int lastPos = (m_iStartPos + m_iMaxPosOff - 1) % m_szSize;
int posFirst = -1;
int posLast = -1;
@ -871,7 +952,7 @@ void CRcvBufferNew::updateFirstReadableOutOfOrder()
continue;
}
const CPacket& pkt = m_entries[pos].pUnit->m_Packet;
const CPacket& pkt = packetAt(pos);
if (pkt.getMsgOrderFlag()) // Skip in order packet
{
@ -907,11 +988,11 @@ void CRcvBufferNew::updateFirstReadableOutOfOrder()
return;
}
int CRcvBufferNew::scanNotInOrderMessageRight(const int startPos, int msgNo) const
int CRcvBuffer::scanNotInOrderMessageRight(const int startPos, int msgNo) const
{
// Search further packets to the right.
// First check if there are packets to the right.
const int lastPos = (m_iStartPos + m_iMaxPosInc - 1) % m_szSize;
const int lastPos = (m_iStartPos + m_iMaxPosOff - 1) % m_szSize;
if (startPos == lastPos)
return -1;
@ -922,7 +1003,7 @@ int CRcvBufferNew::scanNotInOrderMessageRight(const int startPos, int msgNo) con
if (!m_entries[pos].pUnit)
break;
const CPacket& pkt = m_entries[pos].pUnit->m_Packet;
const CPacket& pkt = packetAt(pos);
if (pkt.getMsgSeq(m_bPeerRexmitFlag) != msgNo)
{
@ -938,9 +1019,9 @@ int CRcvBufferNew::scanNotInOrderMessageRight(const int startPos, int msgNo) con
return -1;
}
int CRcvBufferNew::scanNotInOrderMessageLeft(const int startPos, int msgNo) const
int CRcvBuffer::scanNotInOrderMessageLeft(const int startPos, int msgNo) const
{
// Search preceeding packets to the left.
// Search preceding packets to the left.
// First check if there are packets to the left.
if (startPos == m_iStartPos)
return -1;
@ -953,7 +1034,7 @@ int CRcvBufferNew::scanNotInOrderMessageLeft(const int startPos, int msgNo) cons
if (!m_entries[pos].pUnit)
return -1;
const CPacket& pkt = m_entries[pos].pUnit->m_Packet;
const CPacket& pkt = packetAt(pos);
if (pkt.getMsgSeq(m_bPeerRexmitFlag) != msgNo)
{
@ -969,17 +1050,17 @@ int CRcvBufferNew::scanNotInOrderMessageLeft(const int startPos, int msgNo) cons
return -1;
}
bool CRcvBufferNew::addRcvTsbPdDriftSample(uint32_t usTimestamp, const time_point& tsPktArrival, int usRTTSample)
bool CRcvBuffer::addRcvTsbPdDriftSample(uint32_t usTimestamp, const time_point& tsPktArrival, int usRTTSample)
{
return m_tsbpd.addDriftSample(usTimestamp, tsPktArrival, usRTTSample);
}
void CRcvBufferNew::setTsbPdMode(const steady_clock::time_point& timebase, bool wrap, duration delay)
void CRcvBuffer::setTsbPdMode(const steady_clock::time_point& timebase, bool wrap, duration delay)
{
m_tsbpd.setTsbPdMode(timebase, wrap, delay);
}
void CRcvBufferNew::applyGroupTime(const steady_clock::time_point& timebase,
void CRcvBuffer::applyGroupTime(const steady_clock::time_point& timebase,
bool wrp,
uint32_t delay,
const steady_clock::duration& udrift)
@ -987,41 +1068,44 @@ void CRcvBufferNew::applyGroupTime(const steady_clock::time_point& timebase,
m_tsbpd.applyGroupTime(timebase, wrp, delay, udrift);
}
void CRcvBufferNew::applyGroupDrift(const steady_clock::time_point& timebase,
void CRcvBuffer::applyGroupDrift(const steady_clock::time_point& timebase,
bool wrp,
const steady_clock::duration& udrift)
{
m_tsbpd.applyGroupDrift(timebase, wrp, udrift);
}
CRcvBufferNew::time_point CRcvBufferNew::getTsbPdTimeBase(uint32_t usPktTimestamp) const
CRcvBuffer::time_point CRcvBuffer::getTsbPdTimeBase(uint32_t usPktTimestamp) const
{
return m_tsbpd.getTsbPdTimeBase(usPktTimestamp);
}
void CRcvBufferNew::updateTsbPdTimeBase(uint32_t usPktTimestamp)
void CRcvBuffer::updateTsbPdTimeBase(uint32_t usPktTimestamp)
{
m_tsbpd.updateTsbPdTimeBase(usPktTimestamp);
}
string CRcvBufferNew::strFullnessState(int iFirstUnackSeqNo, const time_point& tsNow) const
string CRcvBuffer::strFullnessState(int iFirstUnackSeqNo, const time_point& tsNow) const
{
stringstream ss;
ss << "Space avail " << getAvailSize(iFirstUnackSeqNo) << "/" << m_szSize;
ss << " pkts. ";
if (m_tsbpd.isEnabled() && m_iMaxPosInc > 0)
ss << "iFirstUnackSeqNo=" << iFirstUnackSeqNo << " m_iStartSeqNo=" << m_iStartSeqNo
<< " m_iStartPos=" << m_iStartPos << " m_iMaxPosOff=" << m_iMaxPosOff << ". ";
ss << "Space avail " << getAvailSize(iFirstUnackSeqNo) << "/" << m_szSize << " pkts. ";
if (m_tsbpd.isEnabled() && m_iMaxPosOff > 0)
{
const PacketInfo nextValidPkt = getFirstValidPacketInfo();
ss << "(TSBPD ready in ";
if (!is_zero(nextValidPkt.tsbpd_time))
{
ss << count_milliseconds(nextValidPkt.tsbpd_time - tsNow) << "ms";
const int iLastPos = incPos(m_iStartPos, m_iMaxPosInc - 1);
const int iLastPos = incPos(m_iStartPos, m_iMaxPosOff - 1);
if (m_entries[iLastPos].pUnit)
{
ss << ", timespan ";
const uint32_t usPktTimestamp = m_entries[iLastPos].pUnit->m_Packet.getMsgTimeStamp();
const uint32_t usPktTimestamp = packetAt(iLastPos).getMsgTimeStamp();
ss << count_milliseconds(m_tsbpd.getPktTsbPdTime(usPktTimestamp) - nextValidPkt.tsbpd_time);
ss << " ms";
}
@ -1030,7 +1114,6 @@ string CRcvBufferNew::strFullnessState(int iFirstUnackSeqNo, const time_point& t
{
ss << "n/a";
}
ss << "). ";
}
@ -1038,13 +1121,13 @@ string CRcvBufferNew::strFullnessState(int iFirstUnackSeqNo, const time_point& t
return ss.str();
}
CRcvBufferNew::time_point CRcvBufferNew::getPktTsbPdTime(uint32_t usPktTimestamp) const
CRcvBuffer::time_point CRcvBuffer::getPktTsbPdTime(uint32_t usPktTimestamp) const
{
return m_tsbpd.getPktTsbPdTime(usPktTimestamp);
}
/* Return moving average of acked data pkts, bytes, and timespan (ms) of the receive buffer */
int CRcvBufferNew::getRcvAvgDataSize(int& bytes, int& timespan)
int CRcvBuffer::getRcvAvgDataSize(int& bytes, int& timespan)
{
// Average number of packets and timespan could be small,
// so rounding is beneficial, while for the number of
@ -1056,7 +1139,7 @@ int CRcvBufferNew::getRcvAvgDataSize(int& bytes, int& timespan)
}
/* Update moving average of acked data pkts, bytes, and timespan (ms) of the receive buffer */
void CRcvBufferNew::updRcvAvgDataSize(const steady_clock::time_point& now)
void CRcvBuffer::updRcvAvgDataSize(const steady_clock::time_point& now)
{
if (!m_mavg.isTimeToUpdate(now))
return;
@ -1068,5 +1151,3 @@ void CRcvBufferNew::updRcvAvgDataSize(const steady_clock::time_point& now)
}
} // namespace srt
#endif // ENABLE_NEW_RCVBUFFER