blob: c33c3c3e95506d5287a327714f8830e85230b3bd [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 2001,2002,2004 Federico Montesino Pouzols <fedemp@altern.org>.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation; either version 2 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program; if not, write to the Free Software
15// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16//
17// As a special exception, you may use this file as part of a free software
18// library without restriction. Specifically, if other files instantiate
19// templates or use macros or inline functions from this file, or you compile
20// this file and link it with other files to produce an executable, this
21// file does not by itself cause the resulting executable to be covered by
22// the GNU General Public License. This exception does not however
23// invalidate any other reasons why the executable file might be covered by
24// the GNU General Public License.
25//
26// This exception applies only to the code released under the name GNU
27// ccRTP. If you copy code from other releases into a copy of GNU
28// ccRTP, as the General Public License permits, the exception does
29// not apply to the code that you add in this way. To avoid misleading
30// anyone as to the status of such modified files, you must delete
31// this exception notice from them.
32//
33// If you write modifications of your own for GNU ccRTP, it is your choice
34// whether to permit this exception to apply to your modifications.
35// If you do not wish that, delete this exception notice.
36//
37
38/**
39 * @file ioqueue.h
40 *
41 * @short Generic RTP input/output queues.
42 **/
43
Alexandre Lisionddd731e2014-01-31 11:50:08 -050044#ifndef CCXX_RTP_IOQUEUE_H_
Emeric Vigier2f625822012-08-06 11:09:52 -040045#define CCXX_RTP_IOQUEUE_H_
46
47#include <ccrtp/iqueue.h>
48#include <ccrtp/oqueue.h>
49
Alexandre Lisionddd731e2014-01-31 11:50:08 -050050NAMESPACE_COMMONCPP
Emeric Vigier2f625822012-08-06 11:09:52 -040051
52/**
53 * @defgroup ioqueue Generic RTP input/output queues.
54 * @{
55 **/
56
57/**
58 * @class RTPDataQueue
59 *
60 * A packet queue handler for building different kinds of RTP protocol
61 * systems. The queue manages both incoming and outgoing RTP packets,
62 * as well as synchronization and transmission/reception timers. By
63 * making the queue handler a seperate base class it becomes possible
64 * to define RTP classes for RTP profiles and sessions of different
65 * types.
66 *
67 * Outgoing packets are sent via the OutgoingDataQueue::putData method.
68 *
69 * Incoming packets can be retrieved via IncomingDataQueue::getData
70 * method.
71 *
72 * @author David Sugar <dyfet@ostel.com>
73 * @short RTP data queue handler.
74 */
75class __EXPORT RTPDataQueue :
Alexandre Lisionddd731e2014-01-31 11:50:08 -050076 public IncomingDataQueue,
77 public OutgoingDataQueue
Emeric Vigier2f625822012-08-06 11:09:52 -040078{
79public:
Alexandre Lisionddd731e2014-01-31 11:50:08 -050080 /**
81 * @enum Tos rtp.h cc++/rtp.h
82 * @short Type of network service the application uses.
83 *
84 * If the application uses enhanced network service, for
85 * instance Integrated Services or Differentiated Services, it
86 * <em>has not</em> to ensure fair competition with TCP,
87 * provided that the requested service is actually being
88 * delivered. Whenever the application uses best-effort
89 * service or the requested enhanced service is not actually
90 * being delivered, it <em>has</em> to ensure fair competition
91 * with TCP. By default, best-effot is assumed.
92 *
93 * @note Although not required, RTP packets are always sent on
94 * top of UDP segments. No other underlying transport protocol
95 * is supported at present.
96 *
97 * @todo implement fair competition with tcp
98 **/
99 typedef enum {
100 tosBestEffort, ///< Best-effort network service
101 tosEnhanced ///< Enhanced network service
102 } Tos;
Emeric Vigier2f625822012-08-06 11:09:52 -0400103
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500104 /**
105 * Specify the kind of service the application expects to use.
106 *
107 * @param tos type of service the application expects to use
108 *
109 * @note If enhanced service is specified but packet loss is
110 * high (the requested service does not appear to actually be
111 * delivered) ccRTP defaults to best-effort suitable
112 * behaviour: guarantee fair competition with TCP.
113 *
114 * @todo Implement fair competition with tcp
115 **/
116 inline void
117 setTypeOfService(Tos tos)
118 { typeOfService = tos; }
Emeric Vigier2f625822012-08-06 11:09:52 -0400119
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500120 /**
121 * Enable packet queue processing in the stack. This method
122 * will not any thread of execution.
123 **/
124 inline void enableStack()
125 { dataServiceActive = true; }
Emeric Vigier2f625822012-08-06 11:09:52 -0400126
127 /**
128 * Disable packet queue processing in the stack.
129 **/
130 inline void disableStack()
131 { dataServiceActive = false; }
132
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500133 /**
134 * Get active connection state flag.
135 *
136 * @return true if connection "active".
137 */
138 inline bool
139 isActive() const
140 { return dataServiceActive; }
Emeric Vigier2f625822012-08-06 11:09:52 -0400141
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500142 /**
143 * Get the timestamp that should be given for a packet whose
144 * payload sampling instant corresponds to the current system
145 * time.
146 *
147 * The timestamp applications should provide for each packet
148 * represents the sampling instant of its payload and should
149 * not be a reading of the system clock. Nevertheless, the
150 * internal operation of the RTP stack relies on the accuracy
151 * of the provided timestamp, since several computations
152 * assume that there is a certain degree of correspondence
153 * between the timestamp and the system clock.
154 *
155 * It is recommended that applications use this method in
156 * order to <em>periodically adjust the RTP timestamp</em>.
157 *
158 * In particular, it is advisable getting the timestamp
159 * corresponding to the first sampling instant or any instant
160 * after a period of inactivity through a call to this method.
161 *
162 * Applications should use the nominal sampling or
163 * any other value provided by the coder in order to compute
164 * the next timestamps with minimum computational requirement.
165 *
166 * For instance, an application using an RTP profile that
167 * specifies a fixed sampling rate of 8 Khz with eight bits
168 * per sample, continuously transmitting audio blocks 80
169 * octets long, would transmit 100 packets every
170 * second. Every packet would carry a timestamp 80 units
171 * greater than the previous one. So, the first timestamp
172 * would be obtained from this method, whereas the following
173 * ones would be computed adding 80 every time. Also the
174 * timestamp should be increased for every block whether
175 * it is put in the queue or dropped.
176 *
177 * The aforementioned increment can be obtained from the
178 * RTPDataQueue::getTimestampIncrement() method rather than
179 * computing it by hand in the application.
180 *
181 * @note Frame based applications must follow a specific
182 * timestamping method, probably specified in a profile.
183 *
184 * @note You should take into account that by default ccRTP
185 * assumes that the application begins sampling at the queue
186 * creation time. Moreover, the first sampling instant is
187 * assigned a "user visible" timestamp of 0, although the RTP
188 * stack will then add internally a ramdom offset unknown to
189 * the application. That is to say, the application may count
190 * samples from 0 in order to get the timestamp for the next
191 * packet, provided that the first sampling instant is the
192 * same as the queue creation time. Nevertheless, this
193 * simpler way of starting will not be as accurate as it would
194 * be if the application got at least the first timestamp
195 * through getCurrentTimestamp. <em>We provide this option
196 * since ccRTP interface is evolving, but we admit that it is
197 * ugly, we could remove this option or even replace uint32
198 * timestamps with a restrictively regulated object;
199 * suggestions are gladly welcomed</em>
200 **/
201 uint32
202 getCurrentTimestamp() const;
Emeric Vigier2f625822012-08-06 11:09:52 -0400203
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500204 /**
205 * Specify the bandwidth of the current session.
206 *
207 * @param bw bandwidth of the current session, in bits/s.
208 *
209 * @see AVPQueue::setControlBandwidth()
210 */
211 void
212 setSessionBandwidth(uint32 bw)
213 { sessionBw = bw; }
Emeric Vigier2f625822012-08-06 11:09:52 -0400214
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500215 uint32
216 getDefaultSessionBandwidth() const
217 { return defaultSessionBw; }
Emeric Vigier2f625822012-08-06 11:09:52 -0400218
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500219 uint32
220 getSessionBandwidth() const
221 { return sessionBw; }
Emeric Vigier2f625822012-08-06 11:09:52 -0400222
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500223 /**
224 * Set the packet timeclock for synchronizing timestamps.
225 **/
226 inline void
227 setTimeclock()
228 { timeclock.setTimer(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400229
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500230 /**
231 * Get the packet timeclock for synchronizing timestamps.
232 *
233 * @return runtime in milliseconds since last set.
234 */
235 inline timeout_t
236 getTimeclock() const
237 { return timeclock.getElapsed(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400238
239protected:
240
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500241 /**
242 * Constructor. This will generate a random application SSRC
243 * identifier.
244 *
245 * @param size an estimation of the number of participants in
246 * the session
247 **/
248 RTPDataQueue(uint32 size = defaultMembersHashSize);
Emeric Vigier2f625822012-08-06 11:09:52 -0400249
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500250 /**
251 * Using this constructor you can start a session with the
252 * given ssrc, instead of the usual randomly generated
253 * one. This is necessary when you need to initiate several
254 * sessions having the same SSRC identifier, for instance, to
255 * implement layered encoding, in which case each layer is
256 * managed through a different session but all sessions share
257 * the same SSRC identifier.
258 *
259 * @warning This doesn't seem to be a good solution
260 *
261 * @param ssrc Synchronization SouRCe identifier for this session
262 * @param size an estimation of the number of participants in the
263 * session
264 */
265 RTPDataQueue(uint32* ssrc, uint32 size = defaultMembersHashSize);
Emeric Vigier2f625822012-08-06 11:09:52 -0400266
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500267 /**
268 * The queue destructor flushes the queue and stops all
269 * services.
270 */
271 inline virtual
272 ~RTPDataQueue()
273 { endQueue(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400274
275 /**
276 * A plugin point for timer tick driven events.
277 */
278 inline virtual void
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500279 timerTick()
280 { return; }
Emeric Vigier2f625822012-08-06 11:09:52 -0400281
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500282 void renewLocalSSRC()
283 {IncomingDataQueue::renewLocalSSRC();}
Emeric Vigier2f625822012-08-06 11:09:52 -0400284
285private:
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500286 RTPDataQueue(const RTPDataQueue &o);
Emeric Vigier2f625822012-08-06 11:09:52 -0400287
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500288 RTPDataQueue&
289 operator=(const RTPDataQueue &o);
Emeric Vigier2f625822012-08-06 11:09:52 -0400290
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500291 /**
292 * Global queue initialization.
293 *
294 * @param localSSRC local 32-bit SSRC identifier
295 **/
296 void
297 initQueue();
Emeric Vigier2f625822012-08-06 11:09:52 -0400298
299protected:
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500300 /**
301 * This method ends the queue.
302 */
303 void
304 endQueue();
Emeric Vigier2f625822012-08-06 11:09:52 -0400305
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500306 /**
307 * This function is used to check for and schedule against
308 * arriving packets based on the derived connection type.
309 *
310 * @return true if packet waiting for processing.
311 * @param number of microseconds to wait.
312 */
313 virtual bool
314 isPendingData(microtimeout_t timeout) = 0;
Emeric Vigier2f625822012-08-06 11:09:52 -0400315
316private:
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500317 // true if connection "active"
318 volatile bool dataServiceActive;
319 Tos typeOfService;
320 TimerPort timeclock;
321 /* RTP session bandwidth control */
322 static const uint32 defaultSessionBw;
323 uint32 sessionBw;
Emeric Vigier2f625822012-08-06 11:09:52 -0400324
325
326};
327
328/** @}*/ // ioqueue
329
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500330END_NAMESPACE
Emeric Vigier2f625822012-08-06 11:09:52 -0400331
332#endif //CCXX_RTP_IOQUEUE_H_
333
334/** EMACS **
335 * Local variables:
336 * mode: c++
337 * c-basic-offset: 8
338 * End:
339 */