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.
rtppacket.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 "rtppacket.h"
34 #include "rtpstructs.h"
35 #include "rtpdefines.h"
36 #include "rtperrors.h"
37 #include "rtprawpacket.h"
38 #include <string.h>
39 
40 namespace qrtplib
41 {
42 
44 {
45  hasextension = false;
46  hasmarker = false;
47  numcsrcs = 0;
48  payloadtype = 0;
49  extseqnr = 0;
50  timestamp = 0;
51  ssrc = 0;
52  packet = 0;
53  payload = 0;
54  packetlength = 0;
55  payloadlength = 0;
56  extid = 0;
57  extension = 0;
58  extensionlength = 0;
59  error = 0;
60  externalbuffer = false;
61 }
62 
64  receivetime(rawpack.GetReceiveTime())
65 {
66  Clear();
67  error = ParseRawPacket(rawpack);
68 }
69 
72  const void *payloaddata,
73  unsigned int payloadlen,
74  uint16_t seqnr,
76  uint32_t ssrc,
77  bool gotmarker,
79  const uint32_t *csrcs,
80  bool gotextension,
81  uint16_t extensionid,
82  uint16_t extensionlen_numwords,
83  const void *extensiondata,
84  unsigned int maxpacksize) :
85  receivetime(0, 0)
86 {
87  Clear();
89  payloadtype,
90  payloaddata,
91  payloadlen,
92  seqnr,
93  timestamp,
94  ssrc,
95  gotmarker,
96  numcsrcs,
97  csrcs,
98  gotextension,
99  extensionid,
100  extensionlen_numwords,
101  extensiondata,
102  0,
103  maxpacksize);
104 }
105 
108  const void *payloaddata,
109  unsigned int payloadlen,
110  uint16_t seqnr,
112  uint32_t ssrc,
113  bool gotmarker,
115  const uint32_t *csrcs,
116  bool gotextension,
117  uint16_t extensionid,
118  uint16_t extensionlen_numwords,
119  const void *extensiondata,
120  void *buffer,
121  unsigned int buffersize) :
122  receivetime(0, 0)
123 {
124  Clear();
125  if (buffer == 0)
127  else if (buffersize <= 0)
129  else
130  error = BuildPacket(
131  payloadtype,
132  payloaddata,
133  payloadlen,
134  seqnr,
135  timestamp,
136  ssrc,
137  gotmarker,
138  numcsrcs,
139  csrcs,
140  gotextension,
141  extensionid,
142  extensionlen_numwords,
143  extensiondata,
144  buffer,
145  buffersize);
146 }
147 
149 {
150  uint8_t *packetbytes;
151  unsigned int packetlen;
153  RTPHeader *rtpheader;
154  bool marker;
155  int csrccount;
156  bool hasextension;
157  int payloadoffset, payloadlength;
158  int numpadbytes;
159  RTPExtensionHeader *rtpextheader;
160 
161  if (!rawpack.IsRTP()) // If we didn't receive it on the RTP port, we'll ignore it
163 
164  // The length should be at least the size of the RTP header
165  packetlen = rawpack.GetDataLength();
166  if (packetlen < sizeof(RTPHeader))
168 
169  packetbytes = (uint8_t *) rawpack.GetData();
170  rtpheader = (RTPHeader *) packetbytes;
171 
172  // The version number should be correct
173  if (rtpheader->version != RTP_VERSION)
175 
176  // We'll check if this is possibly a RTCP packet. For this to be possible
177  // the marker bit and payload type combined should be either an SR or RR
178  // identifier
179  marker = (rtpheader->marker == 0) ? false : true;
180  payloadtype = rtpheader->payloadtype;
181  if (marker)
182  {
183  if (payloadtype == (RTP_RTCPTYPE_SR & 127)) // don't check high bit (this was the marker!!)
185  if (payloadtype == (RTP_RTCPTYPE_RR & 127))
187  }
188 
189  csrccount = rtpheader->csrccount;
190  payloadoffset = sizeof(RTPHeader) + (int) (csrccount * sizeof(uint32_t));
191 
192  if (rtpheader->padding) // adjust payload length to take padding into account
193  {
194  numpadbytes = (int) packetbytes[packetlen - 1]; // last byte contains number of padding bytes
195  if (numpadbytes <= 0)
197  }
198  else
199  numpadbytes = 0;
200 
201  hasextension = (rtpheader->extension == 0) ? false : true;
202  if (hasextension) // got header extension
203  {
204  rtpextheader = (RTPExtensionHeader *) (packetbytes + payloadoffset);
205  payloadoffset += sizeof(RTPExtensionHeader);
206 
207  uint16_t exthdrlen = m_endian.qToHost(rtpextheader->length);
208  payloadoffset += ((int) exthdrlen) * sizeof(uint32_t);
209  }
210  else
211  {
212  rtpextheader = 0;
213  }
214 
215  payloadlength = packetlen - numpadbytes - payloadoffset;
216  if (payloadlength < 0)
218 
219  // Now, we've got a valid packet, so we can create a new instance of RTPPacket
220  // and fill in the members
221 
223  if (hasextension)
224  {
225  RTPPacket::extid = m_endian.qToHost(rtpextheader->extid);
226  RTPPacket::extensionlength = ((int) m_endian.qToHost(rtpextheader->length)) * sizeof(uint32_t);
227  RTPPacket::extension = ((uint8_t *) rtpextheader) + sizeof(RTPExtensionHeader);
228  }
229 
230  RTPPacket::hasmarker = marker;
231  RTPPacket::numcsrcs = csrccount;
233 
234  // Note: we don't fill in the EXTENDED sequence number here, since we
235  // don't have information about the source here. We just fill in the low
236  // 16 bits
238 
240  RTPPacket::ssrc = m_endian.qToHost(rtpheader->ssrc);
241  RTPPacket::packet = packetbytes;
242  RTPPacket::payload = packetbytes + payloadoffset;
243  RTPPacket::packetlength = packetlen;
245 
246  return 0;
247 }
248 
250 {
251  if (num >= numcsrcs)
252  return 0;
253 
254  uint8_t *csrcpos;
255  uint32_t *csrcval_nbo;
256  uint32_t csrcval_hbo;
257 
258  csrcpos = packet + sizeof(RTPHeader) + num * sizeof(uint32_t);
259  csrcval_nbo = (uint32_t *) csrcpos;
260  csrcval_hbo = m_endian.qToHost(*csrcval_nbo);
261  return csrcval_hbo;
262 }
263 
266  const void *payloaddata,
267  unsigned int payloadlen,
268  uint16_t seqnr,
270  uint32_t ssrc,
271  bool gotmarker,
273  const uint32_t *csrcs,
274  bool gotextension,
275  uint16_t extensionid,
276  uint16_t extensionlen_numwords,
277  const void *extensiondata,
278  void *buffer,
279  unsigned int maxsize)
280 {
281  if (numcsrcs > RTP_MAXCSRCS)
283 
284  if (payloadtype > 127) // high bit should not be used
286  if (payloadtype == 72 || payloadtype == 73) // could cause confusion with rtcp types
288 
289  packetlength = sizeof(RTPHeader);
290  packetlength += sizeof(uint32_t) * ((unsigned int) numcsrcs);
291  if (gotextension)
292  {
293  packetlength += sizeof(RTPExtensionHeader);
294  packetlength += sizeof(uint32_t) * ((unsigned int) extensionlen_numwords);
295  }
296  packetlength += payloadlen;
297 
298  if (maxsize > 0 && packetlength > maxsize)
299  {
300  packetlength = 0;
302  }
303 
304  // Ok, now we'll just fill in...
305 
306  RTPHeader *rtphdr;
307 
308  if (buffer == 0)
309  {
310  packet = new uint8_t[packetlength];
311  externalbuffer = false;
312  }
313  else
314  {
315  packet = (uint8_t *) buffer;
316  externalbuffer = true;
317  }
318 
319  RTPPacket::hasmarker = gotmarker;
320  RTPPacket::hasextension = gotextension;
323  RTPPacket::extseqnr = (uint32_t) seqnr;
326  RTPPacket::payloadlength = payloadlen;
327  RTPPacket::extid = extensionid;
328  RTPPacket::extensionlength = ((unsigned int) extensionlen_numwords) * sizeof(uint32_t);
329 
330  rtphdr = (RTPHeader *) packet;
331  rtphdr->version = RTP_VERSION;
332  rtphdr->padding = 0;
333  if (gotmarker)
334  rtphdr->marker = 1;
335  else
336  rtphdr->marker = 0;
337  if (gotextension)
338  rtphdr->extension = 1;
339  else
340  rtphdr->extension = 0;
341  rtphdr->csrccount = numcsrcs;
342  rtphdr->payloadtype = payloadtype & 127; // make sure high bit isn't set
343  rtphdr->sequencenumber = qToBigEndian(seqnr);
344  rtphdr->timestamp = qToBigEndian(timestamp);
345  rtphdr->ssrc = qToBigEndian(ssrc);
346 
347  uint32_t *curcsrc;
348  int i;
349 
350  curcsrc = (uint32_t *) (packet + sizeof(RTPHeader));
351  for (i = 0; i < numcsrcs; i++, curcsrc++)
352  *curcsrc = qToBigEndian(csrcs[i]);
353 
354  payload = packet + sizeof(RTPHeader) + ((unsigned int) numcsrcs) * sizeof(uint32_t);
355  if (gotextension)
356  {
358 
359  rtpexthdr->extid = qToBigEndian(extensionid);
360  rtpexthdr->length = qToBigEndian((uint16_t) extensionlen_numwords);
361 
362  payload += sizeof(RTPExtensionHeader);
363  memcpy(payload, extensiondata, RTPPacket::extensionlength);
364 
366  }
367  memcpy(payload, payloaddata, payloadlen);
368  return 0;
369 }
370 
371 } // end namespace
372 
uint8_t * payload
Definition: rtppacket.h:243
#define ERR_RTP_PACKET_INVALIDPACKET
Definition: rtperrors.h:77
T qToHost(const T &x) const
Definition: rtpendian.h:27
unsigned int extensionlength
Definition: rtppacket.h:248
RTPEndian m_endian
Definition: rtppacket.h:235
uint8_t * extension
Definition: rtppacket.h:247
unsigned int uint32_t
Definition: rtptypes_win.h:46
#define RTP_RTCPTYPE_RR
Definition: rtpdefines.h:51
#define ERR_RTP_PACKET_ILLEGALBUFFERSIZE
Definition: rtperrors.h:76
uint32_t extseqnr
Definition: rtppacket.h:242
RTPPacket(RTPRawPacket &rawpack)
Definition: rtppacket.cpp:63
uint32_t timestamp
Definition: rtppacket.h:242
int BuildPacket(uint8_t payloadtype, const void *payloaddata, unsigned int payloadlen, uint16_t seqnr, uint32_t timestamp, uint32_t ssrc, bool gotmarker, uint8_t numcsrcs, const uint32_t *csrcs, bool gotextension, uint16_t extensionid, uint16_t extensionlen_numwords, const void *extensiondata, void *buffer, unsigned int maxsize)
Definition: rtppacket.cpp:264
#define ERR_RTP_PACKET_TOOMANYCSRCS
Definition: rtperrors.h:78
unsigned char uint8_t
Definition: rtptypes_win.h:42
unsigned int packetlength
Definition: rtppacket.h:244
uint8_t * packet
Definition: rtppacket.h:243
unsigned short uint16_t
Definition: rtptypes_win.h:44
int32_t i
Definition: decimators.h:244
uint16_t sequencenumber
Definition: rtpstructs.h:67
#define RTP_MAXCSRCS
Definition: rtpdefines.h:38
RTPTime GetReceiveTime() const
Definition: rtppacket.h:225
#define RTP_RTCPTYPE_SR
Definition: rtpdefines.h:50
#define ERR_RTP_PACKET_EXTERNALBUFFERNULL
Definition: rtperrors.h:75
#define ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE
Definition: rtperrors.h:74
uint32_t timestamp
Definition: rtpstructs.h:68
uint8_t payloadtype
Definition: rtpstructs.h:63
std::size_t GetDataLength() const
Definition: rtprawpacket.h:70
unsigned int payloadlength
Definition: rtppacket.h:244
int ParseRawPacket(RTPRawPacket &rawpack)
Definition: rtppacket.cpp:148
#define RTP_VERSION
Definition: rtpdefines.h:37
bool IsRTP() const
Definition: rtprawpacket.h:88
uint8_t payloadtype
Definition: rtppacket.h:241
#define ERR_RTP_PACKET_BADPAYLOADTYPE
Definition: rtperrors.h:73
uint32_t GetCSRC(int num) const
Definition: rtppacket.cpp:249
RTPTime receivetime
Definition: rtppacket.h:252