657 lines
21 KiB
C++
657 lines
21 KiB
C++
/*
|
|
*
|
|
* @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);
|
|
}
|
|
|
|
}
|