Darwin-Streaming-Server/RTCPUtilitiesLib/RTCPAPPNADUPacket.cpp

658 lines
21 KiB
C++
Raw Normal View History

/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: RTCPAPPNADUPacket.cpp
Contains: RTCPAPPNADUPacket de-packetizing classes
*/
#include "RTCPAPPNADUPacket.h"
#include "MyAssert.h"
#include "OS.h"
#include "OSMemory.h"
#include "StrPtrLen.h"
/* RTCPNaduPacket
data: One or more of the following data format blocks may appear
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| subtype | PT=APP=204 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC/CSRC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| name (ASCII) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <-------- data block
| SSRC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Playout Delay | NSN |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved | NUN | Free Buffer Space (FBS) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
char RTCPNaduPacket::sRTCPTestBuffer[];
RTCPNaduPacket::RTCPNaduPacket(Bool16 debug = false):
RTCPAPPPacket(debug),
fNaduDataBuffer(NULL),
fNumBlocks(0)
{
}
void RTCPNaduPacket::GetTestPacket(StrPtrLen* resultPtr)
{
/*
Compound test packet
lengths are 32 bit words, include header, are minus 1
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| RC | PT=RR=201 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| subtype | PT=SDES=202 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| subtype | PT=APP=204 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC/CSRC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| name (ASCII) | PSS0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+----app specific data PSS0
| SSRC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Playout Delay | NSN |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved | NUN | Free Buffer Space (FBS) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ----app data may repeat
// rtcp common header
typedef struct {
unsigned int version:2; // protocol version
unsigned int p:1; // padding flag
unsigned int count:5; // varies by packet type
unsigned int pt:8; // RTCP packet type
u_int16 length; // pkt len in words, w/o this word can be 0
} rtcp_common_t;
// rtcp compound packet starts with rtcp rr header
// rr data may be empty or not
// nadu app header follows rr header and data if any
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#if 1 //full receiver report with SDES and Nadu
UInt32 *theWriterStart = (UInt32*)sRTCPTestBuffer;
UInt32 *theWriter = (UInt32*)sRTCPTestBuffer;
*(theWriter++) = htonl(0x81c90007); // 1 RR packet header, full report
*(theWriter++) = htonl(0x2935F2D6); // 1 Sender SSRC = 691401430
*(theWriter++) = htonl(0x6078CE22); // 1 SSRC_1 = 1618529826
*(theWriter++) = htonl(0x01000001); // fraction lost | cumulative num packets lost 1% , 1 packet
*(theWriter++) = htonl(0x0000361A); // extended highest seq number received = 13850
*(theWriter++) = htonl(0x00C7ED4D); // interarrival jitter = 13102413
*(theWriter++) = htonl(0x00000000); // LSR last sender report = 0
*(theWriter++) = htonl(0x04625238); // Delay since last SR (DLSR) = 73552440 (garbage)
*(theWriter++) = htonl(0x81ca0005); // 1 SDES packet header,
*(theWriter++) = htonl(0x2935F2D6); // 1 Sender SSRC = 691401430
*(theWriter++) = htonl(0x010A5344); // 1 CNAME = 01, len=10, "SD"
*(theWriter++) = htonl(0x45532043); // 1 CNAME = "ES C"
*(theWriter++) = htonl(0x4e414d45); // 1 CNAME = "NAME"
*(theWriter++) = htonl(0x00000000); // NULL item = end of list + 32bit padding
*(theWriter++) = htonl(0x80CC0000); // 1 APP packet header, needs len -> assigned beow
UInt32 *appPacketLenStart = theWriter;
*(theWriter++) = htonl(FOUR_CHARS_TO_INT('S', 'S', 'R', 'C')); //nadu ssrc
*(theWriter++) = htonl(FOUR_CHARS_TO_INT('P', 'S', 'S', '0')); //nadu app packet name
// first (typically only) ssrc block
*(theWriter++) = htonl(0x423A35C7); //ssrc = 1111111111
*(theWriter++) = htonl(0x2B6756CE); //delay | nsn = 11111 | 22222
*(theWriter++) = htonl(0xFFFFAD9C); //nun | fbs= 31 | 44444
// optional 2nd or more ssrc blocks
*(theWriter++) = htonl(0x84746B8E); //ssrc = 222222222
*(theWriter++) = htonl(0x2B6756CE); //delay | nsn = 11111 | 22222
*(theWriter++) = htonl(0xFFFFAD9C); //nun | fbs= 31 | 44444
UInt16 *packetLenOffsetPtr = &( (UInt16*)theWriterStart)[29];
UInt16 packetLenInWords = htons( ((UInt32*)theWriter - (UInt32*)appPacketLenStart) ) ;
*packetLenOffsetPtr = packetLenInWords;
qtss_printf("packetLenInWords =%lu\n", ntohs(packetLenInWords));
UInt32 len = (char*)theWriter - (char*)theWriterStart;
if (resultPtr)
resultPtr->Set(sRTCPTestBuffer, len);
#endif
#if 0 //full receiver report with Nadu
UInt32 *theWriterStart = (UInt32*)sRTCPTestBuffer;
UInt32 *theWriter = (UInt32*)sRTCPTestBuffer;
*(theWriter++) = htonl(0x80c90007); // 1 RR packet header, empty len is ok but could be a full report
*(theWriter++) = htonl(0x2935F2D6); // 1 SSRC = 691401430
*(theWriter++) = htonl(0x6078CE22); // 1 SSRC_1 = 1618529826
*(theWriter++) = htonl(0x01000001); // fraction lost | cumulative num packets lost 1% , 1 packet
*(theWriter++) = htonl(0x0000361A); // extended highest seq number received = 13850
*(theWriter++) = htonl(0x00C7ED4D); // interarrival jitter = 13102413
*(theWriter++) = htonl(0x00000000); // LSR last sender report = 0
*(theWriter++) = htonl(0x04625238); // Delay since last SR (DLSR) = 73552440 (garbage)
*(theWriter++) = htonl(0x80CC0000); // 1 APP packet header, needs len -> assigned beow
UInt32 *appPacketLenStart = theWriter;
*(theWriter++) = htonl(FOUR_CHARS_TO_INT('S', 'S', 'R', 'C')); //nadu ssrc
*(theWriter++) = htonl(FOUR_CHARS_TO_INT('P', 'S', 'S', '0')); //nadu app packet name
// first (typically only) ssrc block
*(theWriter++) = htonl(0x423A35C7); //ssrc = 1111111111
*(theWriter++) = htonl(0x2B6756CE); //delay | nsn = 11111 | 22222
*(theWriter++) = htonl(0xFFFFAD9C); //nun | fbs= 31 | 44444
// optional 2nd or more ssrc blocks
*(theWriter++) = htonl(0x84746B8E); //ssrc = 222222222
*(theWriter++) = htonl(0x2B6756CE); //delay | nsn = 11111 | 22222
*(theWriter++) = htonl(0xFFFFAD9C); //nun | fbs= 31 | 44444
UInt16 *packetLenOffsetPtr = &( (UInt16*)theWriterStart)[17];
UInt16 packetLenInWords = htons( (UInt32*)theWriter - (UInt32*)appPacketLenStart) ;
*packetLenOffsetPtr = packetLenInWords;
UInt32 len = (char*)theWriter - (char*)theWriterStart;
if (resultPtr)
resultPtr->Set(sRTCPTestBuffer, len);
#endif
#if 0 //empty receiver report with NADU
UInt32 *theWriterStart = (UInt32*)sRTCPTestBuffer;
UInt32 *theWriter = (UInt32*)sRTCPTestBuffer;
*(theWriter++) = htonl(0x80c90000); // 1 RR packet header, empty len is ok but could be a full report
*(theWriter++) = htonl(0x80CC0000); // 1 APP packet header, needs len -> assigned beow
UInt32 *appPacketLenStart = theWriter;
*(theWriter++) = htonl(FOUR_CHARS_TO_INT('S', 'S', 'R', 'C')); //nadu ssrc
*(theWriter++) = htonl(FOUR_CHARS_TO_INT('P', 'S', 'S', '0')); //nadu app packet name
// first (typically only) ssrc block
*(theWriter++) = htonl(0x423A35C7); //ssrc = 1111111111
*(theWriter++) = htonl(0x2B6756CE); //delay | nsn = 11111 | 22222
*(theWriter++) = htonl(0xFFFFAD9C); //nun | fbs= 31 | 44444
// optional 2nd or more ssrc blocks
*(theWriter++) = htonl(0x84746B8E); //ssrc = 222222222
*(theWriter++) = htonl(0x2B6756CE); //delay | nsn = 11111 | 22222
*(theWriter++) = htonl(0xFFFFAD9C); //nun | fbs= 31 | 44444
UInt16 *packetLenOffsetPtr = &( (UInt16*)theWriterStart)[3];
UInt16 packetLenInWords = htons( (UInt32*)theWriter - (UInt32*)appPacketLenStart) ;
*packetLenOffsetPtr = packetLenInWords;
UInt32 len = (char*)theWriter - (char*)theWriterStart;
if (resultPtr)
resultPtr->Set(sRTCPTestBuffer, len);
#endif
/*
sample run of the test packet below:
----------------------------------------
RTPStream::TestRTCPPackets received packet inPacketPtr.Ptr=0xf0080568 inPacketPtr.len =20
testing RTCPNaduPacket using packet inPacketPtr.Ptr=0xe2c38 inPacketPtr.len =40
>recv sess=1: RTCP RR recv_sec=6.812 type=video size=40 H_vers=2, H_pad=0, H_rprt_count=0, H_type=201, H_length=0, H_ssrc=-2134114296
>recv sess=1: RTCP APP recv_sec=6.813 type=video size=36 H_vers=2, H_pad=0, H_rprt_count=0, H_type=204, H_length=8, H_ssrc=1397969475
NADU Packet
Block Index = 0 (h_ssrc = 1111111111, h_playoutdelay = 11111, h_sequence_num = 22222, h_nun_unit_num = 31, h_fbs_free_buf = 44444)
Block Index = 1 (h_ssrc = 2222222222, h_playoutdelay = 11111, h_sequence_num = 22222, h_nun_unit_num = 31, h_fbs_free_buf = 44444)
Dumping Nadu List (list size = 3 record count=48)
-------------------------------------------------------------
NADU Record: list_index = 2 list_recordID = 48
Block Index = 0 (h_ssrc = 1111111111, h_playoutdelay = 11111, h_sequence_num = 22222, h_nun_unit_num = 31, h_fbs_free_buf = 44444)
Block Index = 1 (h_ssrc = 2222222222, h_playoutdelay = 11111, h_sequence_num = 22222, h_nun_unit_num = 31, h_fbs_free_buf = 44444)
NADU Record: list_index = 1 list_recordID = 47
Block Index = 0 (h_ssrc = 1111111111, h_playoutdelay = 11111, h_sequence_num = 22222, h_nun_unit_num = 31, h_fbs_free_buf = 44444)
Block Index = 1 (h_ssrc = 2222222222, h_playoutdelay = 11111, h_sequence_num = 22222, h_nun_unit_num = 31, h_fbs_free_buf = 44444)
NADU Record: list_index = 0 list_recordID = 46
Block Index = 0 (h_ssrc = 1111111111, h_playoutdelay = 11111, h_sequence_num = 22222, h_nun_unit_num = 31, h_fbs_free_buf = 44444)
Block Index = 1 (h_ssrc = 2222222222, h_playoutdelay = 11111, h_sequence_num = 22222, h_nun_unit_num = 31, h_fbs_free_buf = 44444)
*/
}
// use if you don't know what kind of packet this is
Bool16 RTCPNaduPacket::ParseNaduPacket(UInt8* inPacketBuffer, UInt32 inPacketLength)
{
if (!this->ParseAPPPacket(inPacketBuffer, inPacketLength))
return false;
if (this->GetAppPacketName() != RTCPNaduPacket::kNaduPacketName)
return false;
return true;
}
Bool16 RTCPNaduPacket::ParseAPPData(UInt8* inPacketBuffer, UInt32 inPacketLength)
{
if (!this->ParseNaduPacket(inPacketBuffer, inPacketLength) )
return false;
UInt32 *naduDataBuffer = (UInt32 *) (this->GetPacketBuffer()+kNaduDataOffset);
int wordsLen = this->GetPacketLength() - 2;
if (wordsLen < 3) // min is 3
return false;
if (0 !=(wordsLen % 3))// blocks are 3x32bits so there is a bad block somewhere.
return false;
fNumBlocks = wordsLen / 3;
if (0 == fNumBlocks)
return false;
if (fNumBlocks > 100) // too many
return false;
fNaduDataBuffer = naduDataBuffer;
if (0) //testing
this->DumpNaduPacket();
return true;
}
void RTCPNaduPacket::DumpNaduPacket()
{
char printName[5];
(void) this->GetAppPacketName(printName, sizeof(printName));
qtss_printf(" H_app_packet_name = %s, ", printName );
qtss_printf("\n");
SInt32 count = 0;
for (; count < fNumBlocks ; count ++)
{
UInt32 ssrc = this->GetSSRC(count);
UInt32 ssrcIndex = this->GetSSRCBlockIndex(ssrc);
UInt16 playoutDelay = this->GetPlayOutDelay(count);
UInt16 nsn = this->GetNSN(count);
UInt16 nun = this->GetNUN(count);
UInt16 fbs = this->GetFBS(count);
qtss_printf(" ");
qtss_printf("RTCP APP NADU Report[%"_U32BITARG_"] ", ssrcIndex);
qtss_printf("h_ssrc = %"_U32BITARG_, ssrc);
qtss_printf(", h_playoutdelay = %u", playoutDelay);
qtss_printf(", h_sequence_num = %u", nsn);
qtss_printf(", h_nun_unit_num = %u", nun);
qtss_printf(", h_fbs_free_buf = %u", fbs);
qtss_printf("\n");
}
}
SInt32 RTCPNaduPacket::GetSSRCBlockIndex(UInt32 inSSRC)
{
UInt32 *blockBuffer = NULL;
SInt32 count = 0;
UInt32 ssrc = 0;
if (NULL == fNaduDataBuffer)
return -1;
for (; count < fNumBlocks ; count ++)
{
blockBuffer = fNaduDataBuffer + (count * 3);
ssrc = (UInt32) ntohl(*(UInt32*)&blockBuffer[kOffsetNaduSSRC]);
if (ssrc == inSSRC)
return count;
}
return -1;
}
UInt32 RTCPNaduPacket::GetSSRC(SInt32 index)
{
if (index < 0)
return 0;
if (NULL == fNaduDataBuffer)
return 0;
if (index >= fNumBlocks)
return 0;
UInt32 *blockBufferPtr = fNaduDataBuffer + (index * 3);
UInt32 ssrc = (UInt32) ntohl(*(UInt32*)&blockBufferPtr[kOffsetNaduSSRC]);
return ssrc;
}
UInt16 RTCPNaduPacket::GetPlayOutDelay(SInt32 index)
{
if (index < 0)
return 0;
if (NULL == fNaduDataBuffer)
return 0;
if (index >= fNumBlocks)
return 0;
UInt32 *blockBufferPtr = fNaduDataBuffer + (index * 3);
UInt16 delay = (UInt16) ( ( ntohl(*(UInt32*)&blockBufferPtr[kOffsetNaduPlayoutDelay]) & kPlayoutMask) >> 16);
return delay;
}
UInt16 RTCPNaduPacket::GetNSN(SInt32 index)
{
if (index < 0)
return 0;
if (NULL == fNaduDataBuffer)
return 0;
if (index >= fNumBlocks)
return 0;
UInt32 *blockBufferPtr = fNaduDataBuffer + (index * 3);
UInt16 nsn = (UInt16) ( ntohl(blockBufferPtr[kOffsetNSN]) & kNSNMask );
return nsn;
}
UInt16 RTCPNaduPacket::GetNUN(SInt32 index)
{
if (index < 0)
return 0;
if (NULL == fNaduDataBuffer)
return 0;
if (index >= fNumBlocks)
return 0;
UInt32 *blockBufferPtr = fNaduDataBuffer + (index * 3);
UInt16 nun = (UInt16) ((ntohl(blockBufferPtr[kOffsetNUN]) & kNUNMask) >> 16);
return nun;
}
UInt16 RTCPNaduPacket::GetFBS(SInt32 index)
{
if (index < 0)
return 0;
if (NULL == fNaduDataBuffer)
return 0;
if (index >= fNumBlocks)
return 0;
UInt32 *blockBufferPtr = fNaduDataBuffer + (index * 3);
UInt16 fbs = (UInt16) ntohl(blockBufferPtr[kOffsetFBS]) & kFBSMask;
return fbs;
}
void RTCPNaduPacket::Dump()
{
this->DumpNaduPacket();
}
/* class NaduReport */
NaduReport::NaduReport(UInt8* inPacketBuffer, UInt32 inPacketLength, UInt32 id)
{
fPacketBuffer = NEW UInt8[inPacketLength+1];
fPacketBuffer[inPacketLength] = 0;
fLength = inPacketLength;
::memcpy(fPacketBuffer, inPacketBuffer, inPacketLength);
fNaduPacket.ParseAPPData(fPacketBuffer, inPacketLength);
fid = id;
}
/* class NaduList */
void NaduList::Initialize(UInt32 listSize)
{
fNaduReportList = NEW NaduReport *[listSize];
::memset( (void *) fNaduReportList, 0, sizeof(NaduReport*) * listSize); //initialize ptr array with 0.
fListSize = listSize;
}
NaduReport* NaduList::GetReport(UInt32 id)
{
if (NULL == fNaduReportList)
return NULL;
NaduReport *result = fNaduReportList[this->IDtoIndex(id)];
if (result && result->getID() == id)
return result;
return NULL;
}
UInt32 NaduList::GetReportIndex(UInt32 id)
{
if (NULL == fNaduReportList)
return 0;
UInt32 index = this->IDtoIndex(id);
NaduReport *result = fNaduReportList[index];
if (result && result->getID() == id)
return index;
return 0;
}
NaduReport* NaduList::GetLastReport()
{
if (NULL == fNaduReportList || fcurrentIndexCount == 0)
return NULL;
UInt32 index = this->IDtoIndex(fcurrentIndexCount);
return fNaduReportList[index];
}
NaduReport* NaduList::GetPreviousReport(NaduReport* theReport)
{
if (NULL == theReport)
return NULL;
return this->GetReport(theReport->getID() - 1);
}
NaduReport* NaduList::GetNextReport(NaduReport* theReport)
{
if (NULL == theReport)
return NULL;
return this->GetReport(theReport->getID() + 1);
}
NaduReport* NaduList::GetEarliestReport()
{
if ( fcurrentIndexCount > fListSize)
return fNaduReportList[fcurrentIndexCount % fListSize];
return fNaduReportList[0];
}
Bool16 NaduList::AddReport(UInt8* inPacketBuffer, UInt32 inPacketLength, UInt32 *outID)
{
if (NULL == fNaduReportList)
return false;
UInt32 resultID = ++fcurrentIndexCount;
UInt32 index =this->IDtoIndex(fcurrentIndexCount);
if (fNaduReportList[index] != 0)
delete fNaduReportList[index];
fNaduReportList[index] = NEW NaduReport(inPacketBuffer,inPacketLength, resultID);
if (outID)
*outID = resultID;
return true;
}
UInt32 NaduList::LastReportedFreeBuffSizeBytes()
{
NaduReport* currentReportPtr = this->GetLastReport();
if (NULL == currentReportPtr)
return 0;
RTCPNaduPacket *theNADUPacketData = currentReportPtr->GetNaduPacket();
if (NULL == theNADUPacketData)
return 0;
return ((UInt32) theNADUPacketData->GetFBS(0)) * 64; //64 byte blocks are in the report
}
UInt32 NaduList::LastReportedTimeDelayMilli()
{
NaduReport* currentReportPtr = this->GetLastReport();
if (NULL == currentReportPtr)
return 0;
RTCPNaduPacket *theNADUPacketData = currentReportPtr->GetNaduPacket();
if (NULL == theNADUPacketData)
return 0;
return theNADUPacketData->GetPlayOutDelay(0);
}
UInt16 NaduList::GetLastReportedNSN()
{
NaduReport* currentReportPtr = this->GetLastReport();
if (NULL == currentReportPtr)
return 0;
RTCPNaduPacket *theNADUPacketData = currentReportPtr->GetNaduPacket();
if (NULL == theNADUPacketData)
return 0;
return theNADUPacketData->GetNSN(0);
}
void NaduList::DumpList()
{
qtss_printf("\nDumping Nadu List (list size = %"_U32BITARG_" record count=%"_U32BITARG_")\n",fListSize, fcurrentIndexCount);
qtss_printf("-------------------------------------------------------------\n");
NaduReport* lastReportPtr = this->GetLastReport();
NaduReport* earliestReportPtr = this->GetEarliestReport();
UInt32 thisID = 0;
UInt32 stopID = 0;
if (earliestReportPtr)
stopID = earliestReportPtr->getID();
while (lastReportPtr)
{
thisID = lastReportPtr->getID();
qtss_printf("NADU Record: list_index = %"_U32BITARG_" list_recordID = %"_U32BITARG_"\n", this->GetReportIndex(thisID), thisID);
lastReportPtr->GetNaduPacket()->Dump();
if (thisID == stopID)
break;
thisID --;
lastReportPtr = this->GetReport(thisID);
}
}