258 lines
6.8 KiB
C++
Raw Normal View History

2025-02-27 17:59:18 +08:00
#include "rtpexternaltransmitter.h"
#include "rtperrors.h"
#include "rtpsession.h"
#include "rtpsessionparams.h"
#include "rtpbyteaddress.h"
#include "rtcpcompoundpacket.h"
#include "rtcpsrpacket.h"
#include "rtcprrpacket.h"
#include "rtcpbyepacket.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
using namespace std;
using namespace jrtplib;
void checkError(int status)
{
if (status >= 0)
return;
cerr << "An error occured in the RTP component: " << endl;
cerr << "Error description: " << RTPGetErrorString(status) << endl;
exit(-1);
}
class MyRTPSession : public RTPSession
{
protected:
void OnPollThreadStep()
{
//cerr << "OnPollThreadStep" << endl;
}
void OnPollThreadError(int err)
{
cerr << "POLL THREAD ERROR!" << endl;
checkError(err);
}
void OnRTCPCompoundPacket(RTCPCompoundPacket *p, const RTPTime &receivetime, const RTPAddress *senderaddress)
{
printf("%u.%06u RECEIVED\n",receivetime.GetSeconds(),receivetime.GetMicroSeconds());
DumpCompoundPacket(stdout,p);
}
void OnSendRTCPCompoundPacket(RTCPCompoundPacket *p)
{
RTPTime t = RTPTime::CurrentTime();
printf("%u.%06u SENDING\n",t.GetSeconds(),t.GetMicroSeconds());
DumpCompoundPacket(stdout,p);
}
void DumpCompoundPacket(FILE *f, RTCPCompoundPacket *p)
{
RTCPPacket *pack;
p->GotoFirstPacket();
while ((pack = p->GetNextPacket()) != 0)
{
if (pack->GetPacketType() == RTCPPacket::SR)
{
RTCPSRPacket *p = (RTCPSRPacket *)pack;
RTPTime t(p->GetNTPTimestamp());
fprintf(f," SR packet\n SSRC %27u\n",p->GetSenderSSRC());
fprintf(f," NTP timestamp: %10u.%06u\n RTP timestamp: %17u\n Packets sent: %18u\n Octets sent: %19u\n",t.GetSeconds(),t.GetMicroSeconds(),p->GetRTPTimestamp(),p->GetSenderPacketCount(),p->GetSenderOctetCount());
for (int i = 0 ; i < p->GetReceptionReportCount() ; i++)
fprintf(f," RR block %d\n SSRC %25u\n Fraction lost: %15d\n Packets lost: %16d\n Ext. high. seq. nr: %10u\n Jitter: %22u\n LSR: %25u\n DLSR: %24u\n",(i+1),
p->GetSSRC(i),(int)p->GetFractionLost(i),p->GetLostPacketCount(i),p->GetExtendedHighestSequenceNumber(i),p->GetJitter(i),p->GetLSR(i),
p->GetDLSR(i));
}
else if (pack->GetPacketType() == RTCPPacket::RR)
{
RTCPRRPacket *p = (RTCPRRPacket *)pack;
fprintf(f," RR packet\n SSRC %27u\n",p->GetSenderSSRC());
for (int i = 0 ; i < p->GetReceptionReportCount() ; i++)
fprintf(f," RR block %d\n SSRC %25u\n Fraction lost: %15d\n Packets lost: %16d\n Ext. high. seq. nr: %10u\n Jitter: %22u\n LSR: %25u\n DLSR: %24u\n",(i+1),
p->GetSSRC(i),(int)p->GetFractionLost(i),p->GetLostPacketCount(i),p->GetExtendedHighestSequenceNumber(i),p->GetJitter(i),p->GetLSR(i),
p->GetDLSR(i));
}
else if (pack->GetPacketType() == RTCPPacket::SDES)
{
RTCPSDESPacket *p = (RTCPSDESPacket *)pack;
char str[1024];
if (!p->GotoFirstChunk())
return;
do
{
fprintf(f," SDES Chunk:\n");
fprintf(f," SSRC: %26u\n",p->GetChunkSSRC());
if (p->GotoFirstItem())
{
do
{
switch (p->GetItemType())
{
case RTCPSDESPacket::None:
strcpy(str,"None ");
break;
case RTCPSDESPacket::CNAME:
strcpy(str,"CNAME: ");
break;
case RTCPSDESPacket::NAME:
strcpy(str,"NAME: ");
break;
case RTCPSDESPacket::EMAIL:
strcpy(str,"EMAIL: ");
break;
case RTCPSDESPacket::PHONE:
strcpy(str,"PHONE: ");
break;
case RTCPSDESPacket::LOC:
strcpy(str,"LOC: ");
break;
case RTCPSDESPacket::TOOL:
strcpy(str,"TOOL: ");
break;
case RTCPSDESPacket::NOTE:
strcpy(str,"NOTE: ");
break;
case RTCPSDESPacket::PRIV:
strcpy(str,"PRIV: ");
break;
case RTCPSDESPacket::Unknown:
default:
strcpy(str,"Unknown ");
}
fprintf(f," %s",str);
if (p->GetItemType() != RTCPSDESPacket::PRIV)
{
char str[1024];
memcpy(str,p->GetItemData(),p->GetItemLength());
str[p->GetItemLength()] = 0;
fprintf(f,"%24s\n",str);
}
} while (p->GotoNextItem());
}
} while (p->GotoNextChunk());
}
else if (pack->GetPacketType() == RTCPPacket::BYE)
{
fprintf(f," BYE packet:\n");
RTCPBYEPacket *p = (RTCPBYEPacket *)pack;
int num = p->GetSSRCCount();
int i;
for (i = 0 ; i < num ; i++)
fprintf(f," SSRC: %26u\n",p->GetSSRC(i));
if (p->HasReasonForLeaving())
{
char str[1024];
memcpy(str,p->GetReasonData(),p->GetReasonLength());
str[p->GetReasonLength()] = 0;
fprintf(f," Reason: %24s\n",str);
}
}
}
fprintf(f,"\n");
}
};
class DummySender : public RTPExternalSender
{
public:
DummySender() { }
bool SendRTP(const void *data, size_t len) { return true; }
bool SendRTCP(const void *data, size_t len) { return true; }
bool ComesFromThisSender(const RTPAddress *a) { return false; }
};
int main(void)
{
FILE *pFile = fopen("logfile.dat", "rb");
if (!pFile)
{
cerr << "Unable to open logfile.dat" << endl;
return -1;
}
DummySender sender;
RTPExternalTransmitter trans(0);
RTPExternalTransmissionParams params(&sender, 20);
checkError(trans.Init(true));
checkError(trans.Create(65535, &params));
RTPExternalTransmissionInfo *pTransInfo = (RTPExternalTransmissionInfo *)trans.GetTransmissionInfo();
RTPExternalPacketInjecter *pPacketInjecter = pTransInfo->GetPacketInjector();
trans.DeleteTransmissionInfo(pTransInfo);
MyRTPSession session;
RTPSessionParams sessParams;
sessParams.SetOwnTimestampUnit(1.0/5.0);
sessParams.SetProbationType(RTPSources::NoProbation);
checkError(session.Create(sessParams, &trans));
vector<uint8_t> data;
double fileStartTime = 0;
double realStartTime = 0;
uint8_t host[] = {1, 2, 3, 4};
RTPByteAddress addr(host, 4);
while (true)
{
char ident[4];
double t;
uint32_t dataLength;
if (fread(ident, 1, 4, pFile) != 4 || fread(&t, 1, sizeof(double), pFile) != sizeof(double) ||
fread(&dataLength, 1, sizeof(uint32_t), pFile) != sizeof(uint32_t))
break;
data.resize(dataLength);
if (fread(&data[0], 1, dataLength, pFile) != dataLength)
break;
if (realStartTime == 0)
{
realStartTime = RTPTime::CurrentTime().GetDouble();
fileStartTime = t;
}
else
{
// Busy wait until time to inject
while (true)
{
double curTime = RTPTime::CurrentTime().GetDouble();
if (curTime - realStartTime >= t - fileStartTime)
break;
}
}
// if (ident[2] == 'C')
// cerr << "Injecting RTCP packet of length " << dataLength << endl;
pPacketInjecter->InjectRTPorRTCP(&data[0], dataLength, addr);
}
fclose(pFile);
return 0;
}