mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-27 02:09:14 -05:00
739 lines
22 KiB
C++
739 lines
22 KiB
C++
/*
|
|
|
|
This file is a part of JRTPLIB
|
|
Copyright (c) 1999-2017 Jori Liesenborgs
|
|
|
|
Contact: jori.liesenborgs@gmail.com
|
|
|
|
This library was developed at the Expertise Centre for Digital Media
|
|
(http://www.edm.uhasselt.be), a research center of the Hasselt University
|
|
(http://www.uhasselt.be). The library is based upon work done for
|
|
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
copy of this software and associated documentation files (the "Software"),
|
|
to deal in the Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
in all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
#include "rtcppacketbuilder.h"
|
|
#include "rtpsources.h"
|
|
#include "rtppacketbuilder.h"
|
|
#include "rtcpscheduler.h"
|
|
#include "rtpsourcedata.h"
|
|
#include "rtcpcompoundpacketbuilder.h"
|
|
|
|
namespace qrtplib
|
|
{
|
|
|
|
RTCPPacketBuilder::RTCPPacketBuilder(RTPSources &s, RTPPacketBuilder &pb) :
|
|
sources(s), rtppacketbuilder(pb), prevbuildtime(0, 0), transmissiondelay(0, 0)
|
|
{
|
|
init = false;
|
|
timeinit.Dummy();
|
|
}
|
|
|
|
RTCPPacketBuilder::~RTCPPacketBuilder()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
int RTCPPacketBuilder::Init(std::size_t maxpacksize, double tsunit, const void *cname, std::size_t cnamelen)
|
|
{
|
|
if (init)
|
|
return ERR_RTP_RTCPPACKETBUILDER_ALREADYINIT;
|
|
if (maxpacksize < RTP_MINPACKETSIZE)
|
|
return ERR_RTP_RTCPPACKETBUILDER_ILLEGALMAXPACKSIZE;
|
|
if (tsunit < 0.0)
|
|
return ERR_RTP_RTCPPACKETBUILDER_ILLEGALTIMESTAMPUNIT;
|
|
|
|
if (cnamelen > 255)
|
|
cnamelen = 255;
|
|
|
|
maxpacketsize = maxpacksize;
|
|
timestampunit = tsunit;
|
|
|
|
int status;
|
|
|
|
if ((status = ownsdesinfo.SetCNAME((const uint8_t *) cname, cnamelen)) < 0)
|
|
return status;
|
|
|
|
ClearAllSourceFlags();
|
|
|
|
interval_name = -1;
|
|
interval_email = -1;
|
|
interval_location = -1;
|
|
interval_phone = -1;
|
|
interval_tool = -1;
|
|
interval_note = -1;
|
|
|
|
sdesbuildcount = 0;
|
|
transmissiondelay = RTPTime(0, 0);
|
|
|
|
firstpacket = true;
|
|
processingsdes = false;
|
|
init = true;
|
|
return 0;
|
|
}
|
|
|
|
void RTCPPacketBuilder::Destroy()
|
|
{
|
|
if (!init)
|
|
return;
|
|
ownsdesinfo.Clear();
|
|
init = false;
|
|
}
|
|
|
|
int RTCPPacketBuilder::BuildNextPacket(RTCPCompoundPacket **pack)
|
|
{
|
|
if (!init)
|
|
return ERR_RTP_RTCPPACKETBUILDER_NOTINIT;
|
|
|
|
RTCPCompoundPacketBuilder *rtcpcomppack;
|
|
int status;
|
|
bool sender = false;
|
|
RTPSourceData *srcdat;
|
|
|
|
*pack = 0;
|
|
|
|
rtcpcomppack = new RTCPCompoundPacketBuilder();
|
|
|
|
if ((status = rtcpcomppack->InitBuild(maxpacketsize)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
return status;
|
|
}
|
|
|
|
if ((srcdat = sources.GetOwnSourceInfo()) != 0)
|
|
{
|
|
if (srcdat->IsSender())
|
|
sender = true;
|
|
}
|
|
|
|
uint32_t ssrc = rtppacketbuilder.GetSSRC();
|
|
RTPTime curtime = RTPTime::CurrentTime();
|
|
|
|
if (sender)
|
|
{
|
|
RTPTime rtppacktime = rtppacketbuilder.GetPacketTime();
|
|
uint32_t rtppacktimestamp = rtppacketbuilder.GetPacketTimestamp();
|
|
uint32_t packcount = rtppacketbuilder.GetPacketCount();
|
|
uint32_t octetcount = rtppacketbuilder.GetPayloadOctetCount();
|
|
RTPTime diff = curtime;
|
|
diff -= rtppacktime;
|
|
diff += transmissiondelay; // the sample being sampled at this very instant will need a larger timestamp
|
|
|
|
uint32_t tsdiff = (uint32_t) ((diff.GetDouble() / timestampunit) + 0.5);
|
|
uint32_t rtptimestamp = rtppacktimestamp + tsdiff;
|
|
RTPNTPTime ntptimestamp = curtime.GetNTPTime();
|
|
|
|
if ((status = rtcpcomppack->StartSenderReport(ssrc, ntptimestamp, rtptimestamp, packcount, octetcount)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
|
|
return status;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((status = rtcpcomppack->StartReceiverReport(ssrc)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
|
|
return status;
|
|
}
|
|
}
|
|
|
|
uint8_t *owncname;
|
|
std::size_t owncnamelen;
|
|
|
|
owncname = ownsdesinfo.GetCNAME(&owncnamelen);
|
|
|
|
if ((status = rtcpcomppack->AddSDESSource(ssrc)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
|
|
return status;
|
|
}
|
|
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::CNAME, owncname, owncnamelen)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
|
|
return status;
|
|
}
|
|
|
|
if (!processingsdes)
|
|
{
|
|
int added, skipped;
|
|
bool full, atendoflist;
|
|
|
|
if ((status = FillInReportBlocks(rtcpcomppack, curtime, sources.GetTotalCount(), &full, &added, &skipped, &atendoflist)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
return status;
|
|
}
|
|
|
|
if (full && added == 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
|
|
}
|
|
|
|
if (!full)
|
|
{
|
|
processingsdes = true;
|
|
sdesbuildcount++;
|
|
|
|
ClearAllSourceFlags();
|
|
|
|
doname = false;
|
|
doemail = false;
|
|
doloc = false;
|
|
dophone = false;
|
|
dotool = false;
|
|
donote = false;
|
|
if (interval_name > 0 && ((sdesbuildcount % interval_name) == 0))
|
|
doname = true;
|
|
if (interval_email > 0 && ((sdesbuildcount % interval_email) == 0))
|
|
doemail = true;
|
|
if (interval_location > 0 && ((sdesbuildcount % interval_location) == 0))
|
|
doloc = true;
|
|
if (interval_phone > 0 && ((sdesbuildcount % interval_phone) == 0))
|
|
dophone = true;
|
|
if (interval_tool > 0 && ((sdesbuildcount % interval_tool) == 0))
|
|
dotool = true;
|
|
if (interval_note > 0 && ((sdesbuildcount % interval_note) == 0))
|
|
donote = true;
|
|
|
|
bool processedall;
|
|
int itemcount;
|
|
|
|
if ((status = FillInSDES(rtcpcomppack, &full, &processedall, &itemcount)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
return status;
|
|
}
|
|
|
|
if (processedall)
|
|
{
|
|
processingsdes = false;
|
|
ClearAllSDESFlags();
|
|
if (!full && skipped > 0)
|
|
{
|
|
// if the packet isn't full and we skipped some
|
|
// sources that we already got in a previous packet,
|
|
// we can add some of them now
|
|
|
|
bool atendoflist;
|
|
|
|
if ((status = FillInReportBlocks(rtcpcomppack, curtime, skipped, &full, &added, &skipped, &atendoflist)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
return status;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else // previous sdes processing wasn't finished
|
|
{
|
|
bool processedall;
|
|
int itemcount;
|
|
bool full;
|
|
|
|
if ((status = FillInSDES(rtcpcomppack, &full, &processedall, &itemcount)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
return status;
|
|
}
|
|
|
|
if (itemcount == 0) // Big problem: packet size is too small to let any progress happen
|
|
{
|
|
delete rtcpcomppack;
|
|
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
|
|
}
|
|
|
|
if (processedall)
|
|
{
|
|
processingsdes = false;
|
|
ClearAllSDESFlags();
|
|
if (!full)
|
|
{
|
|
// if the packet isn't full and we skipped some
|
|
// we can add some report blocks
|
|
|
|
int added, skipped;
|
|
bool atendoflist;
|
|
|
|
if ((status = FillInReportBlocks(rtcpcomppack, curtime, sources.GetTotalCount(), &full, &added, &skipped, &atendoflist)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
return status;
|
|
}
|
|
if (atendoflist) // filled in all possible sources
|
|
ClearAllSourceFlags();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((status = rtcpcomppack->EndBuild()) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
return status;
|
|
}
|
|
|
|
*pack = rtcpcomppack;
|
|
firstpacket = false;
|
|
prevbuildtime = curtime;
|
|
return 0;
|
|
}
|
|
|
|
void RTCPPacketBuilder::ClearAllSourceFlags()
|
|
{
|
|
if (sources.GotoFirstSource())
|
|
{
|
|
do
|
|
{
|
|
RTPSourceData *srcdat = sources.GetCurrentSourceInfo();
|
|
srcdat->SetProcessedInRTCP(false);
|
|
} while (sources.GotoNextSource());
|
|
}
|
|
}
|
|
|
|
int RTCPPacketBuilder::FillInReportBlocks(RTCPCompoundPacketBuilder *rtcpcomppack, const RTPTime &curtime, int maxcount, bool *full, int *added, int *skipped, bool *atendoflist)
|
|
{
|
|
RTPSourceData *srcdat;
|
|
int addedcount = 0;
|
|
int skippedcount = 0;
|
|
bool done = false;
|
|
bool filled = false;
|
|
bool atend = false;
|
|
int status;
|
|
|
|
if (sources.GotoFirstSource())
|
|
{
|
|
do
|
|
{
|
|
bool shouldprocess = false;
|
|
|
|
srcdat = sources.GetCurrentSourceInfo();
|
|
if (!srcdat->IsOwnSSRC()) // don't send to ourselves
|
|
{
|
|
if (!srcdat->IsCSRC()) // p 35: no reports should go to CSRCs
|
|
{
|
|
if (srcdat->INF_HasSentData()) // if this isn't true, INF_GetLastRTPPacketTime() won't make any sense
|
|
{
|
|
if (firstpacket)
|
|
shouldprocess = true;
|
|
else
|
|
{
|
|
// p 35: only if rtp packets were received since the last RTP packet, a report block
|
|
// should be added
|
|
|
|
RTPTime lastrtptime = srcdat->INF_GetLastRTPPacketTime();
|
|
|
|
if (lastrtptime > prevbuildtime)
|
|
shouldprocess = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (shouldprocess)
|
|
{
|
|
if (srcdat->IsProcessedInRTCP()) // already covered this one
|
|
{
|
|
skippedcount++;
|
|
}
|
|
else
|
|
{
|
|
uint32_t rr_ssrc = srcdat->GetSSRC();
|
|
uint32_t num = srcdat->INF_GetNumPacketsReceivedInInterval();
|
|
uint32_t prevseq = srcdat->INF_GetSavedExtendedSequenceNumber();
|
|
uint32_t curseq = srcdat->INF_GetExtendedHighestSequenceNumber();
|
|
uint32_t expected = curseq - prevseq;
|
|
uint8_t fraclost;
|
|
|
|
if (expected < num) // got duplicates
|
|
fraclost = 0;
|
|
else
|
|
{
|
|
double lost = (double) (expected - num);
|
|
double frac = lost / ((double) expected);
|
|
fraclost = (uint8_t) (frac * 256.0);
|
|
}
|
|
|
|
expected = curseq - srcdat->INF_GetBaseSequenceNumber();
|
|
num = srcdat->INF_GetNumPacketsReceived();
|
|
|
|
uint32_t diff = expected - num;
|
|
int32_t *packlost = (int32_t *) &diff;
|
|
|
|
uint32_t jitter = srcdat->INF_GetJitter();
|
|
uint32_t lsr;
|
|
uint32_t dlsr;
|
|
|
|
if (!srcdat->SR_HasInfo())
|
|
{
|
|
lsr = 0;
|
|
dlsr = 0;
|
|
}
|
|
else
|
|
{
|
|
RTPNTPTime srtime = srcdat->SR_GetNTPTimestamp();
|
|
uint32_t m = (srtime.GetMSW() & 0xFFFF);
|
|
uint32_t l = ((srtime.GetLSW() >> 16) & 0xFFFF);
|
|
lsr = ((m << 16) | l);
|
|
|
|
RTPTime diff = curtime;
|
|
diff -= srcdat->SR_GetReceiveTime();
|
|
double diff2 = diff.GetDouble();
|
|
diff2 *= 65536.0;
|
|
dlsr = (uint32_t) diff2;
|
|
}
|
|
|
|
status = rtcpcomppack->AddReportBlock(rr_ssrc, fraclost, *packlost, curseq, jitter, lsr, dlsr);
|
|
if (status < 0)
|
|
{
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
{
|
|
done = true;
|
|
filled = true;
|
|
}
|
|
else
|
|
return status;
|
|
}
|
|
else
|
|
{
|
|
addedcount++;
|
|
if (addedcount >= maxcount)
|
|
{
|
|
done = true;
|
|
if (!sources.GotoNextSource())
|
|
atend = true;
|
|
}
|
|
srcdat->INF_StartNewInterval();
|
|
srcdat->SetProcessedInRTCP(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!done)
|
|
{
|
|
if (!sources.GotoNextSource())
|
|
{
|
|
atend = true;
|
|
done = true;
|
|
}
|
|
}
|
|
|
|
} while (!done);
|
|
}
|
|
|
|
*added = addedcount;
|
|
*skipped = skippedcount;
|
|
*full = filled;
|
|
|
|
if (!atend) // search for available sources
|
|
{
|
|
bool shouldprocess = false;
|
|
|
|
do
|
|
{
|
|
srcdat = sources.GetCurrentSourceInfo();
|
|
if (!srcdat->IsOwnSSRC()) // don't send to ourselves
|
|
{
|
|
if (!srcdat->IsCSRC()) // p 35: no reports should go to CSRCs
|
|
{
|
|
if (srcdat->INF_HasSentData()) // if this isn't true, INF_GetLastRTPPacketTime() won't make any sense
|
|
{
|
|
if (firstpacket)
|
|
shouldprocess = true;
|
|
else
|
|
{
|
|
// p 35: only if rtp packets were received since the last RTP packet, a report block
|
|
// should be added
|
|
|
|
RTPTime lastrtptime = srcdat->INF_GetLastRTPPacketTime();
|
|
|
|
if (lastrtptime > prevbuildtime)
|
|
shouldprocess = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (shouldprocess)
|
|
{
|
|
if (srcdat->IsProcessedInRTCP())
|
|
shouldprocess = false;
|
|
}
|
|
|
|
if (!shouldprocess)
|
|
{
|
|
if (!sources.GotoNextSource())
|
|
atend = true;
|
|
}
|
|
|
|
} while (!atend && !shouldprocess);
|
|
}
|
|
|
|
*atendoflist = atend;
|
|
return 0;
|
|
}
|
|
|
|
int RTCPPacketBuilder::FillInSDES(RTCPCompoundPacketBuilder *rtcpcomppack, bool *full, bool *processedall, int *added)
|
|
{
|
|
int status;
|
|
uint8_t *data;
|
|
std::size_t datalen;
|
|
|
|
*full = false;
|
|
*processedall = false;
|
|
*added = 0;
|
|
|
|
// We don't need to add a SSRC for our own data, this is still set
|
|
// from adding the CNAME
|
|
if (doname)
|
|
{
|
|
if (!ownsdesinfo.ProcessedName())
|
|
{
|
|
data = ownsdesinfo.GetName(&datalen);
|
|
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::NAME, data, datalen)) < 0)
|
|
{
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
{
|
|
*full = true;
|
|
return 0;
|
|
}
|
|
}
|
|
(*added)++;
|
|
ownsdesinfo.SetProcessedName(true);
|
|
}
|
|
}
|
|
if (doemail)
|
|
{
|
|
if (!ownsdesinfo.ProcessedEMail())
|
|
{
|
|
data = ownsdesinfo.GetEMail(&datalen);
|
|
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::EMAIL, data, datalen)) < 0)
|
|
{
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
{
|
|
*full = true;
|
|
return 0;
|
|
}
|
|
}
|
|
(*added)++;
|
|
ownsdesinfo.SetProcessedEMail(true);
|
|
}
|
|
}
|
|
if (doloc)
|
|
{
|
|
if (!ownsdesinfo.ProcessedLocation())
|
|
{
|
|
data = ownsdesinfo.GetLocation(&datalen);
|
|
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::LOC, data, datalen)) < 0)
|
|
{
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
{
|
|
*full = true;
|
|
return 0;
|
|
}
|
|
}
|
|
(*added)++;
|
|
ownsdesinfo.SetProcessedLocation(true);
|
|
}
|
|
}
|
|
if (dophone)
|
|
{
|
|
if (!ownsdesinfo.ProcessedPhone())
|
|
{
|
|
data = ownsdesinfo.GetPhone(&datalen);
|
|
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::PHONE, data, datalen)) < 0)
|
|
{
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
{
|
|
*full = true;
|
|
return 0;
|
|
}
|
|
}
|
|
(*added)++;
|
|
ownsdesinfo.SetProcessedPhone(true);
|
|
}
|
|
}
|
|
if (dotool)
|
|
{
|
|
if (!ownsdesinfo.ProcessedTool())
|
|
{
|
|
data = ownsdesinfo.GetTool(&datalen);
|
|
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::TOOL, data, datalen)) < 0)
|
|
{
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
{
|
|
*full = true;
|
|
return 0;
|
|
}
|
|
}
|
|
(*added)++;
|
|
ownsdesinfo.SetProcessedTool(true);
|
|
}
|
|
}
|
|
if (donote)
|
|
{
|
|
if (!ownsdesinfo.ProcessedNote())
|
|
{
|
|
data = ownsdesinfo.GetNote(&datalen);
|
|
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::NOTE, data, datalen)) < 0)
|
|
{
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
{
|
|
*full = true;
|
|
return 0;
|
|
}
|
|
}
|
|
(*added)++;
|
|
ownsdesinfo.SetProcessedNote(true);
|
|
}
|
|
}
|
|
|
|
*processedall = true;
|
|
return 0;
|
|
}
|
|
|
|
void RTCPPacketBuilder::ClearAllSDESFlags()
|
|
{
|
|
ownsdesinfo.ClearFlags();
|
|
}
|
|
|
|
int RTCPPacketBuilder::BuildBYEPacket(RTCPCompoundPacket **pack, const void *reason, std::size_t reasonlength, bool useSRifpossible)
|
|
{
|
|
if (!init)
|
|
return ERR_RTP_RTCPPACKETBUILDER_NOTINIT;
|
|
|
|
RTCPCompoundPacketBuilder *rtcpcomppack;
|
|
int status;
|
|
|
|
if (reasonlength > 255)
|
|
reasonlength = 255;
|
|
|
|
*pack = 0;
|
|
|
|
rtcpcomppack = new RTCPCompoundPacketBuilder();
|
|
|
|
if ((status = rtcpcomppack->InitBuild(maxpacketsize)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
return status;
|
|
}
|
|
|
|
uint32_t ssrc = rtppacketbuilder.GetSSRC();
|
|
bool useSR = false;
|
|
|
|
if (useSRifpossible)
|
|
{
|
|
RTPSourceData *srcdat;
|
|
|
|
if ((srcdat = sources.GetOwnSourceInfo()) != 0)
|
|
{
|
|
if (srcdat->IsSender())
|
|
useSR = true;
|
|
}
|
|
}
|
|
|
|
if (useSR)
|
|
{
|
|
RTPTime curtime = RTPTime::CurrentTime();
|
|
RTPTime rtppacktime = rtppacketbuilder.GetPacketTime();
|
|
uint32_t rtppacktimestamp = rtppacketbuilder.GetPacketTimestamp();
|
|
uint32_t packcount = rtppacketbuilder.GetPacketCount();
|
|
uint32_t octetcount = rtppacketbuilder.GetPayloadOctetCount();
|
|
RTPTime diff = curtime;
|
|
diff -= rtppacktime;
|
|
|
|
uint32_t tsdiff = (uint32_t) ((diff.GetDouble() / timestampunit) + 0.5);
|
|
uint32_t rtptimestamp = rtppacktimestamp + tsdiff;
|
|
RTPNTPTime ntptimestamp = curtime.GetNTPTime();
|
|
|
|
if ((status = rtcpcomppack->StartSenderReport(ssrc, ntptimestamp, rtptimestamp, packcount, octetcount)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
|
|
return status;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((status = rtcpcomppack->StartReceiverReport(ssrc)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
|
|
return status;
|
|
}
|
|
}
|
|
|
|
uint8_t *owncname;
|
|
std::size_t owncnamelen;
|
|
|
|
owncname = ownsdesinfo.GetCNAME(&owncnamelen);
|
|
|
|
if ((status = rtcpcomppack->AddSDESSource(ssrc)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
|
|
return status;
|
|
}
|
|
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::CNAME, owncname, owncnamelen)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
|
|
return status;
|
|
}
|
|
|
|
uint32_t ssrcs[1];
|
|
|
|
ssrcs[0] = ssrc;
|
|
|
|
if ((status = rtcpcomppack->AddBYEPacket(ssrcs, 1, (const uint8_t *) reason, reasonlength)) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
|
|
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
|
|
return status;
|
|
}
|
|
|
|
if ((status = rtcpcomppack->EndBuild()) < 0)
|
|
{
|
|
delete rtcpcomppack;
|
|
return status;
|
|
}
|
|
|
|
*pack = rtcpcomppack;
|
|
return 0;
|
|
}
|
|
|
|
} // end namespace
|
|
|