mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-04 05:30:32 -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
 | 
						|
 |