SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
rtcppacketbuilder.cpp
Go to the documentation of this file.
1 /*
2 
3  This file is a part of JRTPLIB
4  Copyright (c) 1999-2017 Jori Liesenborgs
5 
6  Contact: jori.liesenborgs@gmail.com
7 
8  This library was developed at the Expertise Centre for Digital Media
9  (http://www.edm.uhasselt.be), a research center of the Hasselt University
10  (http://www.uhasselt.be). The library is based upon work done for
11  my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
12 
13  Permission is hereby granted, free of charge, to any person obtaining a
14  copy of this software and associated documentation files (the "Software"),
15  to deal in the Software without restriction, including without limitation
16  the rights to use, copy, modify, merge, publish, distribute, sublicense,
17  and/or sell copies of the Software, and to permit persons to whom the
18  Software is furnished to do so, subject to the following conditions:
19 
20  The above copyright notice and this permission notice shall be included
21  in all copies or substantial portions of the Software.
22 
23  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29  IN THE SOFTWARE.
30 
31  */
32 
33 #include "rtcppacketbuilder.h"
34 #include "rtpsources.h"
35 #include "rtppacketbuilder.h"
36 #include "rtcpscheduler.h"
37 #include "rtpsourcedata.h"
39 
40 namespace qrtplib
41 {
42 
44  sources(s), rtppacketbuilder(pb), prevbuildtime(0, 0), transmissiondelay(0, 0)
45 {
46  init = false;
47  timeinit.Dummy();
48 }
49 
51 {
52  Destroy();
53 }
54 
55 int RTCPPacketBuilder::Init(std::size_t maxpacksize, double tsunit, const void *cname, std::size_t cnamelen)
56 {
57  if (init)
59  if (maxpacksize < RTP_MINPACKETSIZE)
61  if (tsunit < 0.0)
63 
64  if (cnamelen > 255)
65  cnamelen = 255;
66 
67  maxpacketsize = maxpacksize;
68  timestampunit = tsunit;
69 
70  int status;
71 
72  if ((status = ownsdesinfo.SetCNAME((const uint8_t *) cname, cnamelen)) < 0)
73  return status;
74 
76 
77  interval_name = -1;
78  interval_email = -1;
79  interval_location = -1;
80  interval_phone = -1;
81  interval_tool = -1;
82  interval_note = -1;
83 
84  sdesbuildcount = 0;
85  transmissiondelay = RTPTime(0, 0);
86 
87  firstpacket = true;
88  processingsdes = false;
89  init = true;
90  return 0;
91 }
92 
94 {
95  if (!init)
96  return;
98  init = false;
99 }
100 
102 {
103  if (!init)
105 
106  RTCPCompoundPacketBuilder *rtcpcomppack;
107  int status;
108  bool sender = false;
109  RTPSourceData *srcdat;
110 
111  *pack = 0;
112 
113  rtcpcomppack = new RTCPCompoundPacketBuilder();
114 
115  if ((status = rtcpcomppack->InitBuild(maxpacketsize)) < 0)
116  {
117  delete rtcpcomppack;
118  return status;
119  }
120 
121  if ((srcdat = sources.GetOwnSourceInfo()) != 0)
122  {
123  if (srcdat->IsSender())
124  sender = true;
125  }
126 
128  RTPTime curtime = RTPTime::CurrentTime();
129 
130  if (sender)
131  {
132  RTPTime rtppacktime = rtppacketbuilder.GetPacketTime();
133  uint32_t rtppacktimestamp = rtppacketbuilder.GetPacketTimestamp();
136  RTPTime diff = curtime;
137  diff -= rtppacktime;
138  diff += transmissiondelay; // the sample being sampled at this very instant will need a larger timestamp
139 
140  uint32_t tsdiff = (uint32_t) ((diff.GetDouble() / timestampunit) + 0.5);
141  uint32_t rtptimestamp = rtppacktimestamp + tsdiff;
142  RTPNTPTime ntptimestamp = curtime.GetNTPTime();
143 
144  if ((status = rtcpcomppack->StartSenderReport(ssrc, ntptimestamp, rtptimestamp, packcount, octetcount)) < 0)
145  {
146  delete rtcpcomppack;
149  return status;
150  }
151  }
152  else
153  {
154  if ((status = rtcpcomppack->StartReceiverReport(ssrc)) < 0)
155  {
156  delete rtcpcomppack;
159  return status;
160  }
161  }
162 
163  uint8_t *owncname;
164  std::size_t owncnamelen;
165 
166  owncname = ownsdesinfo.GetCNAME(&owncnamelen);
167 
168  if ((status = rtcpcomppack->AddSDESSource(ssrc)) < 0)
169  {
170  delete rtcpcomppack;
173  return status;
174  }
175  if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::CNAME, owncname, owncnamelen)) < 0)
176  {
177  delete rtcpcomppack;
180  return status;
181  }
182 
183  if (!processingsdes)
184  {
185  int added, skipped;
186  bool full, atendoflist;
187 
188  if ((status = FillInReportBlocks(rtcpcomppack, curtime, sources.GetTotalCount(), &full, &added, &skipped, &atendoflist)) < 0)
189  {
190  delete rtcpcomppack;
191  return status;
192  }
193 
194  if (full && added == 0)
195  {
196  delete rtcpcomppack;
198  }
199 
200  if (!full)
201  {
202  processingsdes = true;
203  sdesbuildcount++;
204 
206 
207  doname = false;
208  doemail = false;
209  doloc = false;
210  dophone = false;
211  dotool = false;
212  donote = false;
213  if (interval_name > 0 && ((sdesbuildcount % interval_name) == 0))
214  doname = true;
215  if (interval_email > 0 && ((sdesbuildcount % interval_email) == 0))
216  doemail = true;
217  if (interval_location > 0 && ((sdesbuildcount % interval_location) == 0))
218  doloc = true;
219  if (interval_phone > 0 && ((sdesbuildcount % interval_phone) == 0))
220  dophone = true;
221  if (interval_tool > 0 && ((sdesbuildcount % interval_tool) == 0))
222  dotool = true;
223  if (interval_note > 0 && ((sdesbuildcount % interval_note) == 0))
224  donote = true;
225 
226  bool processedall;
227  int itemcount;
228 
229  if ((status = FillInSDES(rtcpcomppack, &full, &processedall, &itemcount)) < 0)
230  {
231  delete rtcpcomppack;
232  return status;
233  }
234 
235  if (processedall)
236  {
237  processingsdes = false;
239  if (!full && skipped > 0)
240  {
241  // if the packet isn't full and we skipped some
242  // sources that we already got in a previous packet,
243  // we can add some of them now
244 
245  bool atendoflist;
246 
247  if ((status = FillInReportBlocks(rtcpcomppack, curtime, skipped, &full, &added, &skipped, &atendoflist)) < 0)
248  {
249  delete rtcpcomppack;
250  return status;
251  }
252  }
253  }
254  }
255  }
256  else // previous sdes processing wasn't finished
257  {
258  bool processedall;
259  int itemcount;
260  bool full;
261 
262  if ((status = FillInSDES(rtcpcomppack, &full, &processedall, &itemcount)) < 0)
263  {
264  delete rtcpcomppack;
265  return status;
266  }
267 
268  if (itemcount == 0) // Big problem: packet size is too small to let any progress happen
269  {
270  delete rtcpcomppack;
272  }
273 
274  if (processedall)
275  {
276  processingsdes = false;
278  if (!full)
279  {
280  // if the packet isn't full and we skipped some
281  // we can add some report blocks
282 
283  int added, skipped;
284  bool atendoflist;
285 
286  if ((status = FillInReportBlocks(rtcpcomppack, curtime, sources.GetTotalCount(), &full, &added, &skipped, &atendoflist)) < 0)
287  {
288  delete rtcpcomppack;
289  return status;
290  }
291  if (atendoflist) // filled in all possible sources
293  }
294  }
295  }
296 
297  if ((status = rtcpcomppack->EndBuild()) < 0)
298  {
299  delete rtcpcomppack;
300  return status;
301  }
302 
303  *pack = rtcpcomppack;
304  firstpacket = false;
305  prevbuildtime = curtime;
306  return 0;
307 }
308 
310 {
311  if (sources.GotoFirstSource())
312  {
313  do
314  {
316  srcdat->SetProcessedInRTCP(false);
317  } while (sources.GotoNextSource());
318  }
319 }
320 
321 int RTCPPacketBuilder::FillInReportBlocks(RTCPCompoundPacketBuilder *rtcpcomppack, const RTPTime &curtime, int maxcount, bool *full, int *added, int *skipped, bool *atendoflist)
322 {
323  RTPSourceData *srcdat;
324  int addedcount = 0;
325  int skippedcount = 0;
326  bool done = false;
327  bool filled = false;
328  bool atend = false;
329  int status;
330 
331  if (sources.GotoFirstSource())
332  {
333  do
334  {
335  bool shouldprocess = false;
336 
337  srcdat = sources.GetCurrentSourceInfo();
338  if (!srcdat->IsOwnSSRC()) // don't send to ourselves
339  {
340  if (!srcdat->IsCSRC()) // p 35: no reports should go to CSRCs
341  {
342  if (srcdat->INF_HasSentData()) // if this isn't true, INF_GetLastRTPPacketTime() won't make any sense
343  {
344  if (firstpacket)
345  shouldprocess = true;
346  else
347  {
348  // p 35: only if rtp packets were received since the last RTP packet, a report block
349  // should be added
350 
351  RTPTime lastrtptime = srcdat->INF_GetLastRTPPacketTime();
352 
353  if (lastrtptime > prevbuildtime)
354  shouldprocess = true;
355  }
356  }
357  }
358  }
359 
360  if (shouldprocess)
361  {
362  if (srcdat->IsProcessedInRTCP()) // already covered this one
363  {
364  skippedcount++;
365  }
366  else
367  {
368  uint32_t rr_ssrc = srcdat->GetSSRC();
370  uint32_t prevseq = srcdat->INF_GetSavedExtendedSequenceNumber();
372  uint32_t expected = curseq - prevseq;
373  uint8_t fraclost;
374 
375  if (expected < num) // got duplicates
376  fraclost = 0;
377  else
378  {
379  double lost = (double) (expected - num);
380  double frac = lost / ((double) expected);
381  fraclost = (uint8_t) (frac * 256.0);
382  }
383 
384  expected = curseq - srcdat->INF_GetBaseSequenceNumber();
385  num = srcdat->INF_GetNumPacketsReceived();
386 
387  uint32_t diff = expected - num;
388  int32_t *packlost = (int32_t *) &diff;
389 
390  uint32_t jitter = srcdat->INF_GetJitter();
391  uint32_t lsr;
392  uint32_t dlsr;
393 
394  if (!srcdat->SR_HasInfo())
395  {
396  lsr = 0;
397  dlsr = 0;
398  }
399  else
400  {
401  RTPNTPTime srtime = srcdat->SR_GetNTPTimestamp();
402  uint32_t m = (srtime.GetMSW() & 0xFFFF);
403  uint32_t l = ((srtime.GetLSW() >> 16) & 0xFFFF);
404  lsr = ((m << 16) | l);
405 
406  RTPTime diff = curtime;
407  diff -= srcdat->SR_GetReceiveTime();
408  double diff2 = diff.GetDouble();
409  diff2 *= 65536.0;
410  dlsr = (uint32_t) diff2;
411  }
412 
413  status = rtcpcomppack->AddReportBlock(rr_ssrc, fraclost, *packlost, curseq, jitter, lsr, dlsr);
414  if (status < 0)
415  {
417  {
418  done = true;
419  filled = true;
420  }
421  else
422  return status;
423  }
424  else
425  {
426  addedcount++;
427  if (addedcount >= maxcount)
428  {
429  done = true;
430  if (!sources.GotoNextSource())
431  atend = true;
432  }
433  srcdat->INF_StartNewInterval();
434  srcdat->SetProcessedInRTCP(true);
435  }
436  }
437  }
438 
439  if (!done)
440  {
441  if (!sources.GotoNextSource())
442  {
443  atend = true;
444  done = true;
445  }
446  }
447 
448  } while (!done);
449  }
450 
451  *added = addedcount;
452  *skipped = skippedcount;
453  *full = filled;
454 
455  if (!atend) // search for available sources
456  {
457  bool shouldprocess = false;
458 
459  do
460  {
461  srcdat = sources.GetCurrentSourceInfo();
462  if (!srcdat->IsOwnSSRC()) // don't send to ourselves
463  {
464  if (!srcdat->IsCSRC()) // p 35: no reports should go to CSRCs
465  {
466  if (srcdat->INF_HasSentData()) // if this isn't true, INF_GetLastRTPPacketTime() won't make any sense
467  {
468  if (firstpacket)
469  shouldprocess = true;
470  else
471  {
472  // p 35: only if rtp packets were received since the last RTP packet, a report block
473  // should be added
474 
475  RTPTime lastrtptime = srcdat->INF_GetLastRTPPacketTime();
476 
477  if (lastrtptime > prevbuildtime)
478  shouldprocess = true;
479  }
480  }
481  }
482  }
483 
484  if (shouldprocess)
485  {
486  if (srcdat->IsProcessedInRTCP())
487  shouldprocess = false;
488  }
489 
490  if (!shouldprocess)
491  {
492  if (!sources.GotoNextSource())
493  atend = true;
494  }
495 
496  } while (!atend && !shouldprocess);
497  }
498 
499  *atendoflist = atend;
500  return 0;
501 }
502 
503 int RTCPPacketBuilder::FillInSDES(RTCPCompoundPacketBuilder *rtcpcomppack, bool *full, bool *processedall, int *added)
504 {
505  int status;
506  uint8_t *data;
507  std::size_t datalen;
508 
509  *full = false;
510  *processedall = false;
511  *added = 0;
512 
513  // We don't need to add a SSRC for our own data, this is still set
514  // from adding the CNAME
515  if (doname)
516  {
517  if (!ownsdesinfo.ProcessedName())
518  {
519  data = ownsdesinfo.GetName(&datalen);
520  if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::NAME, data, datalen)) < 0)
521  {
523  {
524  *full = true;
525  return 0;
526  }
527  }
528  (*added)++;
530  }
531  }
532  if (doemail)
533  {
535  {
536  data = ownsdesinfo.GetEMail(&datalen);
537  if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::EMAIL, data, datalen)) < 0)
538  {
540  {
541  *full = true;
542  return 0;
543  }
544  }
545  (*added)++;
547  }
548  }
549  if (doloc)
550  {
552  {
553  data = ownsdesinfo.GetLocation(&datalen);
554  if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::LOC, data, datalen)) < 0)
555  {
557  {
558  *full = true;
559  return 0;
560  }
561  }
562  (*added)++;
564  }
565  }
566  if (dophone)
567  {
569  {
570  data = ownsdesinfo.GetPhone(&datalen);
571  if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::PHONE, data, datalen)) < 0)
572  {
574  {
575  *full = true;
576  return 0;
577  }
578  }
579  (*added)++;
581  }
582  }
583  if (dotool)
584  {
585  if (!ownsdesinfo.ProcessedTool())
586  {
587  data = ownsdesinfo.GetTool(&datalen);
588  if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::TOOL, data, datalen)) < 0)
589  {
591  {
592  *full = true;
593  return 0;
594  }
595  }
596  (*added)++;
598  }
599  }
600  if (donote)
601  {
602  if (!ownsdesinfo.ProcessedNote())
603  {
604  data = ownsdesinfo.GetNote(&datalen);
605  if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::NOTE, data, datalen)) < 0)
606  {
608  {
609  *full = true;
610  return 0;
611  }
612  }
613  (*added)++;
615  }
616  }
617 
618  *processedall = true;
619  return 0;
620 }
621 
623 {
625 }
626 
627 int RTCPPacketBuilder::BuildBYEPacket(RTCPCompoundPacket **pack, const void *reason, std::size_t reasonlength, bool useSRifpossible)
628 {
629  if (!init)
631 
632  RTCPCompoundPacketBuilder *rtcpcomppack;
633  int status;
634 
635  if (reasonlength > 255)
636  reasonlength = 255;
637 
638  *pack = 0;
639 
640  rtcpcomppack = new RTCPCompoundPacketBuilder();
641 
642  if ((status = rtcpcomppack->InitBuild(maxpacketsize)) < 0)
643  {
644  delete rtcpcomppack;
645  return status;
646  }
647 
649  bool useSR = false;
650 
651  if (useSRifpossible)
652  {
653  RTPSourceData *srcdat;
654 
655  if ((srcdat = sources.GetOwnSourceInfo()) != 0)
656  {
657  if (srcdat->IsSender())
658  useSR = true;
659  }
660  }
661 
662  if (useSR)
663  {
664  RTPTime curtime = RTPTime::CurrentTime();
665  RTPTime rtppacktime = rtppacketbuilder.GetPacketTime();
666  uint32_t rtppacktimestamp = rtppacketbuilder.GetPacketTimestamp();
669  RTPTime diff = curtime;
670  diff -= rtppacktime;
671 
672  uint32_t tsdiff = (uint32_t) ((diff.GetDouble() / timestampunit) + 0.5);
673  uint32_t rtptimestamp = rtppacktimestamp + tsdiff;
674  RTPNTPTime ntptimestamp = curtime.GetNTPTime();
675 
676  if ((status = rtcpcomppack->StartSenderReport(ssrc, ntptimestamp, rtptimestamp, packcount, octetcount)) < 0)
677  {
678  delete rtcpcomppack;
681  return status;
682  }
683  }
684  else
685  {
686  if ((status = rtcpcomppack->StartReceiverReport(ssrc)) < 0)
687  {
688  delete rtcpcomppack;
691  return status;
692  }
693  }
694 
695  uint8_t *owncname;
696  std::size_t owncnamelen;
697 
698  owncname = ownsdesinfo.GetCNAME(&owncnamelen);
699 
700  if ((status = rtcpcomppack->AddSDESSource(ssrc)) < 0)
701  {
702  delete rtcpcomppack;
705  return status;
706  }
707  if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::CNAME, owncname, owncnamelen)) < 0)
708  {
709  delete rtcpcomppack;
712  return status;
713  }
714 
715  uint32_t ssrcs[1];
716 
717  ssrcs[0] = ssrc;
718 
719  if ((status = rtcpcomppack->AddBYEPacket(ssrcs, 1, (const uint8_t *) reason, reasonlength)) < 0)
720  {
721  delete rtcpcomppack;
724  return status;
725  }
726 
727  if ((status = rtcpcomppack->EndBuild()) < 0)
728  {
729  delete rtcpcomppack;
730  return status;
731  }
732 
733  *pack = rtcpcomppack;
734  return 0;
735 }
736 
737 } // end namespace
738 
uint32_t INF_GetExtendedHighestSequenceNumber() const
#define ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT
Definition: rtperrors.h:95
uint8_t * GetTool(std::size_t *len) const
Definition: rtcpsdesinfo.h:153
RTPSourceData * GetOwnSourceInfo()
Definition: rtpsources.h:243
double GetDouble() const
RTPTimeInitializerObject timeinit
int BuildBYEPacket(RTCPCompoundPacket **pack, const void *reason, std::size_t reasonlength, bool useSRifpossible=true)
RTCPSDESInfoInternal ownsdesinfo
#define ERR_RTP_RTCPPACKETBUILDER_ILLEGALTIMESTAMPUNIT
Definition: rtperrors.h:101
RTPTime SR_GetReceiveTime() const
int GetTotalCount() const
Definition: rtpsources.h:281
uint8_t * GetCNAME(std::size_t *len) const
Definition: rtcpsdesinfo.h:123
#define ERR_RTP_RTCPPACKETBUILDER_ALREADYINIT
Definition: rtperrors.h:99
int32_t INF_GetNumPacketsReceived() const
uint8_t * GetNote(std::size_t *len) const
Definition: rtcpsdesinfo.h:159
int InitBuild(std::size_t maxpacketsize)
RTPSourceData * GetCurrentSourceInfo()
Definition: rtpsources.cpp:609
uint32_t INF_GetSavedExtendedSequenceNumber() const
uint32_t GetMSW() const
unsigned int uint32_t
Definition: rtptypes_win.h:46
uint8_t * GetLocation(std::size_t *len) const
Definition: rtcpsdesinfo.h:147
int BuildNextPacket(RTCPCompoundPacket **pack)
int FillInSDES(RTCPCompoundPacketBuilder *pack, bool *full, bool *processedall, int *added)
RTPNTPTime SR_GetNTPTimestamp() const
uint32_t INF_GetBaseSequenceNumber() const
#define RTP_MINPACKETSIZE
Definition: rtpdefines.h:39
int SetCNAME(const uint8_t *s, std::size_t l)
Definition: rtcpsdesinfo.h:70
unsigned char uint8_t
Definition: rtptypes_win.h:42
bool IsProcessedInRTCP() const
uint8_t * GetName(std::size_t *len) const
Definition: rtcpsdesinfo.h:129
uint8_t * GetEMail(std::size_t *len) const
Definition: rtcpsdesinfo.h:135
#define ERR_RTP_RTCPPACKETBUILDER_ILLEGALMAXPACKSIZE
Definition: rtperrors.h:100
uint32_t GetPacketTimestamp() const
int AddReportBlock(uint32_t ssrc, uint8_t fractionlost, int32_t packetslost, uint32_t exthighestseq, uint32_t jitter, uint32_t lsr, uint32_t dlsr)
uint32_t GetSSRC() const
int int32_t
Definition: rtptypes_win.h:45
uint8_t * GetPhone(std::size_t *len) const
Definition: rtcpsdesinfo.h:141
uint32_t GetLSW() const
uint32_t INF_GetNumPacketsReceivedInInterval() const
#define ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON
Definition: rtperrors.h:103
RTPNTPTime GetNTPTime() const
int AddBYEPacket(uint32_t *ssrcs, uint8_t numssrcs, const void *reasondata, uint8_t reasonlength)
static RTPTime CurrentTime()
int FillInReportBlocks(RTCPCompoundPacketBuilder *pack, const RTPTime &curtime, int maxcount, bool *full, int *added, int *skipped, bool *atendoflist)
int Init(std::size_t maxpacksize, double timestampunit, const void *cname, std::size_t cnamelen)
#define ERR_RTP_RTCPPACKETBUILDER_NOTINIT
Definition: rtperrors.h:102
RTCPPacketBuilder(RTPSources &sources, RTPPacketBuilder &rtppackbuilder)
RTPPacketBuilder & rtppacketbuilder
uint32_t INF_GetJitter() const
void SetProcessedInRTCP(bool v)
int StartSenderReport(uint32_t senderssrc, const RTPNTPTime &ntptimestamp, uint32_t rtptimestamp, uint32_t packetcount, uint32_t octetcount)
RTPTime INF_GetLastRTPPacketTime() const
bool INF_HasSentData() const
int AddSDESNormalItem(RTCPSDESPacket::ItemType t, const void *itemdata, uint8_t itemlength)