jrtplib  3.8.0
rtcpcompoundpacketbuilder.h
Go to the documentation of this file.
1 /*
2 
3  This file is a part of JRTPLIB
4  Copyright (c) 1999-2010 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 
37 #ifndef RTCPCOMPOUNDPACKETBUILDER_H
38 
39 #define RTCPCOMPOUNDPACKETBUILDER_H
40 
41 #include "rtpconfig.h"
42 #include "rtcpcompoundpacket.h"
43 #include "rtptimeutilities.h"
44 #include "rtcpsdespacket.h"
45 #include "rtperrors.h"
46 #include <list>
47 
48 class RTPMemoryManager;
49 
57 {
58 public:
62 
67  int InitBuild(size_t maxpacketsize);
68 
73  int InitBuild(void *externalbuffer,size_t buffersize);
74 
80  int StartSenderReport(uint32_t senderssrc,const RTPNTPTime &ntptimestamp,uint32_t rtptimestamp,
81  uint32_t packetcount,uint32_t octetcount);
82 
88  int StartReceiverReport(uint32_t senderssrc);
89 
94  int AddReportBlock(uint32_t ssrc,uint8_t fractionlost,int32_t packetslost,uint32_t exthighestseq,
95  uint32_t jitter,uint32_t lsr,uint32_t dlsr);
96 
98  int AddSDESSource(uint32_t ssrc);
99 
104  int AddSDESNormalItem(RTCPSDESPacket::ItemType t,const void *itemdata,uint8_t itemlength);
105 #ifdef RTP_SUPPORT_SDESPRIV
106 
107  int AddSDESPrivateItem(const void *prefixdata,uint8_t prefixlength,const void *valuedata,
108  uint8_t valuelength);
109 #endif // RTP_SUPPORT_SDESPRIV
110 
116  int AddBYEPacket(uint32_t *ssrcs,uint8_t numssrcs,const void *reasondata,uint8_t reasonlength);
117 
122  int AddAPPPacket(uint8_t subtype,uint32_t ssrc,const uint8_t name[4],const void *appdata,size_t appdatalen);
123 
128  int EndBuild();
129 
130 #ifdef RTP_SUPPORT_RTCPUNKNOWN
131 
134  int AddUnknownPacket(uint8_t payload_type, uint8_t subtype, uint32_t ssrc, const void *data, size_t len);
135 #endif // RTP_SUPPORT_RTCPUNKNOWN
136 private:
137  class Buffer
138  {
139  public:
140  Buffer():packetdata(0),packetlength(0) { }
141  Buffer(uint8_t *data,size_t len):packetdata(data),packetlength(len) { }
142 
143  uint8_t *packetdata;
144  size_t packetlength;
145  };
146 
147  class Report : public RTPMemoryObject
148  {
149  public:
150  Report(RTPMemoryManager *mgr) : RTPMemoryObject(mgr)
151  {
152  headerdata = (uint8_t *)headerdata32;
153  isSR = false;
154  headerlength = 0;
155  }
156  ~Report() { Clear(); }
157 
158  void Clear()
159  {
160  std::list<Buffer>::const_iterator it;
161  for (it = reportblocks.begin() ; it != reportblocks.end() ; it++)
162  {
163  if ((*it).packetdata)
164  RTPDeleteByteArray((*it).packetdata,GetMemoryManager());
165  }
166  reportblocks.clear();
167  isSR = false;
168  headerlength = 0;
169  }
170 
171  size_t NeededBytes()
172  {
173  size_t x,n,d,r;
174  n = reportblocks.size();
175  if (n == 0)
176  {
177  if (headerlength == 0)
178  return 0;
179  x = sizeof(RTCPCommonHeader)+headerlength;
180  }
181  else
182  {
183  x = n*sizeof(RTCPReceiverReport);
184  d = n/31; // max 31 reportblocks per report
185  r = n%31;
186  if (r != 0)
187  d++;
188  x += d*(sizeof(RTCPCommonHeader)+sizeof(uint32_t)); /* header and SSRC */
189  if (isSR)
190  x += sizeof(RTCPSenderReport);
191  }
192  return x;
193  }
194 
195  size_t NeededBytesWithExtraReportBlock()
196  {
197  size_t x,n,d,r;
198  n = reportblocks.size() + 1; // +1 for the extra block
199  x = n*sizeof(RTCPReceiverReport);
200  d = n/31; // max 31 reportblocks per report
201  r = n%31;
202  if (r != 0)
203  d++;
204  x += d*(sizeof(RTCPCommonHeader)+sizeof(uint32_t)); /* header and SSRC */
205  if (isSR)
206  x += sizeof(RTCPSenderReport);
207  return x;
208  }
209 
210  bool isSR;
211 
212  uint8_t *headerdata;
213  uint32_t headerdata32[(sizeof(uint32_t)+sizeof(RTCPSenderReport))/sizeof(uint32_t)]; // either for ssrc and sender info or just ssrc
214  size_t headerlength;
215  std::list<Buffer> reportblocks;
216  };
217 
218  class SDESSource : public RTPMemoryObject
219  {
220  public:
221  SDESSource(uint32_t s,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),ssrc(s),totalitemsize(0) { }
222  ~SDESSource()
223  {
224  std::list<Buffer>::const_iterator it;
225  for (it = items.begin() ; it != items.end() ; it++)
226  {
227  if ((*it).packetdata)
228  RTPDeleteByteArray((*it).packetdata,GetMemoryManager());
229  }
230  items.clear();
231  }
232 
233  size_t NeededBytes()
234  {
235  size_t x,r;
236  x = totalitemsize + 1; // +1 for the 0 byte which terminates the item list
237  r = x%sizeof(uint32_t);
238  if (r != 0)
239  x += (sizeof(uint32_t)-r); // make sure it ends on a 32 bit boundary
240  x += sizeof(uint32_t); // for ssrc
241  return x;
242  }
243 
244  size_t NeededBytesWithExtraItem(uint8_t itemdatalength)
245  {
246  size_t x,r;
247  x = totalitemsize + sizeof(RTCPSDESHeader) + (size_t)itemdatalength + 1;
248  r = x%sizeof(uint32_t);
249  if (r != 0)
250  x += (sizeof(uint32_t)-r); // make sure it ends on a 32 bit boundary
251  x += sizeof(uint32_t); // for ssrc
252  return x;
253  }
254 
255  void AddItem(uint8_t *buf,size_t len)
256  {
257  Buffer b(buf,len);
258  totalitemsize += len;
259  items.push_back(b);
260  }
261 
262  uint32_t ssrc;
263  std::list<Buffer> items;
264  private:
265  size_t totalitemsize;
266  };
267 
268  class SDES : public RTPMemoryObject
269  {
270  public:
271  SDES(RTPMemoryManager *mgr) : RTPMemoryObject(mgr) { sdesit = sdessources.end(); }
272  ~SDES() { Clear(); }
273 
274  void Clear()
275  {
276  std::list<SDESSource *>::const_iterator it;
277 
278  for (it = sdessources.begin() ; it != sdessources.end() ; it++)
279  RTPDelete(*it,GetMemoryManager());
280  sdessources.clear();
281  }
282 
283  int AddSSRC(uint32_t ssrc)
284  {
285  SDESSource *s = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_SDESSOURCE) SDESSource(ssrc,GetMemoryManager());
286  if (s == 0)
287  return ERR_RTP_OUTOFMEM;
288  sdessources.push_back(s);
289  sdesit = sdessources.end();
290  sdesit--;
291  return 0;
292  }
293 
294  int AddItem(uint8_t *buf,size_t len)
295  {
296  if (sdessources.empty())
297  return ERR_RTP_RTCPCOMPPACKBUILDER_NOCURRENTSOURCE;
298  (*sdesit)->AddItem(buf,len);
299  return 0;
300  }
301 
302  size_t NeededBytes()
303  {
304  std::list<SDESSource *>::const_iterator it;
305  size_t x = 0;
306  size_t n,d,r;
307 
308  if (sdessources.empty())
309  return 0;
310 
311  for (it = sdessources.begin() ; it != sdessources.end() ; it++)
312  x += (*it)->NeededBytes();
313  n = sdessources.size();
314  d = n/31;
315  r = n%31;
316  if (r != 0)
317  d++;
318  x += d*sizeof(RTCPCommonHeader);
319  return x;
320  }
321 
322  size_t NeededBytesWithExtraItem(uint8_t itemdatalength)
323  {
324  std::list<SDESSource *>::const_iterator it;
325  size_t x = 0;
326  size_t n,d,r;
327 
328  if (sdessources.empty())
329  return 0;
330 
331  for (it = sdessources.begin() ; it != sdesit ; it++)
332  x += (*it)->NeededBytes();
333  x += (*sdesit)->NeededBytesWithExtraItem(itemdatalength);
334  n = sdessources.size();
335  d = n/31;
336  r = n%31;
337  if (r != 0)
338  d++;
339  x += d*sizeof(RTCPCommonHeader);
340  return x;
341  }
342 
343  size_t NeededBytesWithExtraSource()
344  {
345  std::list<SDESSource *>::const_iterator it;
346  size_t x = 0;
347  size_t n,d,r;
348 
349  if (sdessources.empty())
350  return 0;
351 
352  for (it = sdessources.begin() ; it != sdessources.end() ; it++)
353  x += (*it)->NeededBytes();
354 
355  // for the extra source we'll need at least 8 bytes (ssrc and four 0 bytes)
356  x += sizeof(uint32_t)*2;
357 
358  n = sdessources.size() + 1; // also, the number of sources will increase
359  d = n/31;
360  r = n%31;
361  if (r != 0)
362  d++;
363  x += d*sizeof(RTCPCommonHeader);
364  return x;
365  }
366 
367  std::list<SDESSource *> sdessources;
368  private:
369  std::list<SDESSource *>::const_iterator sdesit;
370  };
371 
372  size_t maximumpacketsize;
373  uint8_t *buffer;
374  bool external;
375  bool arebuilding;
376 
377  Report report;
378  SDES sdes;
379 
380  std::list<Buffer> byepackets;
381  size_t byesize;
382 
383  std::list<Buffer> apppackets;
384  size_t appsize;
385 
386 #ifdef RTP_SUPPORT_RTCPUNKNOWN
387  std::list<Buffer> unknownpackets;
388  size_t unknownsize;
389 #endif // RTP_SUPPORT_RTCPUNKNOWN
390 
391  void ClearBuildBuffers();
392 };
393 
394 #endif // RTCPCOMPOUNDPACKETBUILDER_H
395 
int AddSDESNormalItem(RTCPSDESPacket::ItemType t, const void *itemdata, uint8_t itemlength)
Adds a normal (non-private) SDES item of type t to the current SDES chunk.
RTCPCompoundPacketBuilder(RTPMemoryManager *memmgr=0)
Constructs an RTCPCompoundPacketBuilder instance, optionally installing a memory manager.
A memory manager.
Definition: rtpmemorymanager.h:144
int AddUnknownPacket(uint8_t payload_type, uint8_t subtype, uint32_t ssrc, const void *data, size_t len)
Adds the RTCP packet specified by the arguments to the compound packet.
int StartReceiverReport(uint32_t senderssrc)
Adds a receiver report to the compound packet.
int AddAPPPacket(uint8_t subtype, uint32_t ssrc, const uint8_t name[4], const void *appdata, size_t appdatalen)
Adds the APP packet specified by the arguments to the compound packet.
Represents an RTCP compound packet.
Definition: rtcpcompoundpacket.h:50
int StartSenderReport(uint32_t senderssrc, const RTPNTPTime &ntptimestamp, uint32_t rtptimestamp, uint32_t packetcount, uint32_t octetcount)
Adds a sender report to the compound packet.
This class can be used to construct an RTCP compound packet.
Definition: rtcpcompoundpacketbuilder.h:56
int AddReportBlock(uint32_t ssrc, uint8_t fractionlost, int32_t packetslost, uint32_t exthighestseq, uint32_t jitter, uint32_t lsr, uint32_t dlsr)
Adds the report block information specified by the function's arguments.
int AddBYEPacket(uint32_t *ssrcs, uint8_t numssrcs, const void *reasondata, uint8_t reasonlength)
Adds a BYE packet to the compound packet.
int AddSDESSource(uint32_t ssrc)
Starts an SDES chunk for participant ssrc.
#define RTPMEM_TYPE_CLASS_SDESSOURCE
Buffer to store an SDESSource instance.
Definition: rtpmemorymanager.h:138
ItemType
Identifies the type of an SDES item.
Definition: rtcpsdespacket.h:56
int InitBuild(size_t maxpacketsize)
Starts building an RTCP compound packet with maximum size maxpacketsize.
int EndBuild()
Finishes building the compound packet.
This is a simple wrapper for the most significant word (MSW) and least significant word (LSW) of an N...
Definition: rtptimeutilities.h:58
int AddSDESPrivateItem(const void *prefixdata, uint8_t prefixlength, const void *valuedata, uint8_t valuelength)
Adds an SDES PRIV item described by the function's arguments to the current SDES chunk.