]> code.delx.au - pulseaudio/blob - src/modules/rtp/rtp.c
make rtp send socket low delay
[pulseaudio] / src / modules / rtp / rtp.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2006 Lennart Poettering
7
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published
10 by the Free Software Foundation; either version 2 of the License,
11 or (at your option) any later version.
12
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 USA.
22 ***/
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <fcntl.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <arpa/inet.h>
33 #include <unistd.h>
34 #include <sys/ioctl.h>
35
36 #ifdef HAVE_SYS_FILIO_H
37 #include <sys/filio.h>
38 #endif
39
40 #include <pulsecore/core-error.h>
41 #include <pulsecore/log.h>
42 #include <pulsecore/macro.h>
43 #include <pulsecore/core-util.h>
44
45 #include "rtp.h"
46
47 pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload, size_t frame_size) {
48 pa_assert(c);
49 pa_assert(fd >= 0);
50
51 c->fd = fd;
52 c->sequence = (uint16_t) (rand()*rand());
53 c->timestamp = 0;
54 c->ssrc = ssrc ? ssrc : (uint32_t) (rand()*rand());
55 c->payload = payload & 127;
56 c->frame_size = frame_size;
57
58 return c;
59 }
60
61 #define MAX_IOVECS 16
62
63 int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
64 struct iovec iov[MAX_IOVECS];
65 pa_memblock* mb[MAX_IOVECS];
66 int iov_idx = 1;
67 size_t n = 0;
68
69 pa_assert(c);
70 pa_assert(size > 0);
71 pa_assert(q);
72
73 if (pa_memblockq_get_length(q) < size)
74 return 0;
75
76 for (;;) {
77 int r;
78 pa_memchunk chunk;
79
80 pa_memchunk_reset(&chunk);
81
82 if ((r = pa_memblockq_peek(q, &chunk)) >= 0) {
83
84 size_t k = n + chunk.length > size ? size - n : chunk.length;
85
86 pa_assert(chunk.memblock);
87
88 iov[iov_idx].iov_base = ((uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index);
89 iov[iov_idx].iov_len = k;
90 mb[iov_idx] = chunk.memblock;
91 iov_idx ++;
92
93 n += k;
94 pa_memblockq_drop(q, k);
95 }
96
97 pa_assert(n % c->frame_size == 0);
98
99 if (r < 0 || n >= size || iov_idx >= MAX_IOVECS) {
100 uint32_t header[3];
101 struct msghdr m;
102 int k, i;
103
104 if (n > 0) {
105 header[0] = htonl(((uint32_t) 2 << 30) | ((uint32_t) c->payload << 16) | ((uint32_t) c->sequence));
106 header[1] = htonl(c->timestamp);
107 header[2] = htonl(c->ssrc);
108
109 iov[0].iov_base = (void*)header;
110 iov[0].iov_len = sizeof(header);
111
112 m.msg_name = NULL;
113 m.msg_namelen = 0;
114 m.msg_iov = iov;
115 m.msg_iovlen = iov_idx;
116 m.msg_control = NULL;
117 m.msg_controllen = 0;
118 m.msg_flags = 0;
119
120 k = sendmsg(c->fd, &m, MSG_DONTWAIT);
121
122 for (i = 1; i < iov_idx; i++) {
123 pa_memblock_release(mb[i]);
124 pa_memblock_unref(mb[i]);
125 }
126
127 c->sequence++;
128 } else
129 k = 0;
130
131 c->timestamp += n/c->frame_size;
132
133 if (k < 0) {
134 if (errno != EAGAIN && errno != EINTR) /* If the queue is full, just ignore it */
135 pa_log("sendmsg() failed: %s", pa_cstrerror(errno));
136 return -1;
137 }
138
139 if (r < 0 || pa_memblockq_get_length(q) < size)
140 break;
141
142 n = 0;
143 iov_idx = 1;
144 }
145 }
146
147 return 0;
148 }
149
150 pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame_size) {
151 pa_assert(c);
152
153 c->fd = fd;
154 c->frame_size = frame_size;
155 return c;
156 }
157
158 int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
159 int size;
160 struct msghdr m;
161 struct iovec iov;
162 uint32_t header;
163 int cc;
164 ssize_t r;
165
166 pa_assert(c);
167 pa_assert(chunk);
168
169 chunk->memblock = NULL;
170
171 if (ioctl(c->fd, FIONREAD, &size) < 0) {
172 pa_log_warn("FIONREAD failed: %s", pa_cstrerror(errno));
173 goto fail;
174 }
175
176 if (!size)
177 return 0;
178
179 chunk->memblock = pa_memblock_new(pool, size);
180
181 iov.iov_base = pa_memblock_acquire(chunk->memblock);
182 iov.iov_len = size;
183
184 m.msg_name = NULL;
185 m.msg_namelen = 0;
186 m.msg_iov = &iov;
187 m.msg_iovlen = 1;
188 m.msg_control = NULL;
189 m.msg_controllen = 0;
190 m.msg_flags = 0;
191
192 if ((r = recvmsg(c->fd, &m, 0)) != size) {
193 if (r < 0 && errno != EAGAIN && errno != EINTR)
194 pa_log_warn("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch");
195
196 goto fail;
197 }
198
199 if (size < 12) {
200 pa_log_warn("RTP packet too short.");
201 goto fail;
202 }
203
204 memcpy(&header, iov.iov_base, sizeof(uint32_t));
205 memcpy(&c->timestamp, (uint8_t*) iov.iov_base + 4, sizeof(uint32_t));
206 memcpy(&c->ssrc, (uint8_t*) iov.iov_base + 8, sizeof(uint32_t));
207
208 header = ntohl(header);
209 c->timestamp = ntohl(c->timestamp);
210 c->ssrc = ntohl(c->ssrc);
211
212 if ((header >> 30) != 2) {
213 pa_log_warn("Unsupported RTP version.");
214 goto fail;
215 }
216
217 if ((header >> 29) & 1) {
218 pa_log_warn("RTP padding not supported.");
219 goto fail;
220 }
221
222 if ((header >> 28) & 1) {
223 pa_log_warn("RTP header extensions not supported.");
224 goto fail;
225 }
226
227 cc = (header >> 24) & 0xF;
228 c->payload = (header >> 16) & 127;
229 c->sequence = header & 0xFFFF;
230
231 if (12 + cc*4 > size) {
232 pa_log_warn("RTP packet too short. (CSRC)");
233 goto fail;
234 }
235
236 chunk->index = 12 + cc*4;
237 chunk->length = size - chunk->index;
238
239 if (chunk->length % c->frame_size != 0) {
240 pa_log_warn("Bad RTP packet size.");
241 goto fail;
242 }
243
244 return 0;
245
246 fail:
247 if (chunk->memblock) {
248 pa_memblock_release(chunk->memblock);
249 pa_memblock_unref(chunk->memblock);
250 }
251
252 return -1;
253 }
254
255 uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) {
256 pa_assert(ss);
257
258 if (ss->format == PA_SAMPLE_ULAW && ss->rate == 8000 && ss->channels == 1)
259 return 0;
260 if (ss->format == PA_SAMPLE_ALAW && ss->rate == 8000 && ss->channels == 1)
261 return 8;
262 if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 2)
263 return 10;
264 if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 1)
265 return 11;
266
267 return 127;
268 }
269
270 pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec *ss) {
271 pa_assert(ss);
272
273 switch (payload) {
274 case 0:
275 ss->channels = 1;
276 ss->format = PA_SAMPLE_ULAW;
277 ss->rate = 8000;
278 break;
279
280 case 8:
281 ss->channels = 1;
282 ss->format = PA_SAMPLE_ALAW;
283 ss->rate = 8000;
284 break;
285
286 case 10:
287 ss->channels = 2;
288 ss->format = PA_SAMPLE_S16BE;
289 ss->rate = 44100;
290 break;
291
292 case 11:
293 ss->channels = 1;
294 ss->format = PA_SAMPLE_S16BE;
295 ss->rate = 44100;
296 break;
297
298 default:
299 return NULL;
300 }
301
302 return ss;
303 }
304
305 pa_sample_spec *pa_rtp_sample_spec_fixup(pa_sample_spec * ss) {
306 pa_assert(ss);
307
308 if (!pa_rtp_sample_spec_valid(ss))
309 ss->format = PA_SAMPLE_S16BE;
310
311 pa_assert(pa_rtp_sample_spec_valid(ss));
312 return ss;
313 }
314
315 int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) {
316 pa_assert(ss);
317
318 if (!pa_sample_spec_valid(ss))
319 return 0;
320
321 return
322 ss->format == PA_SAMPLE_U8 ||
323 ss->format == PA_SAMPLE_ALAW ||
324 ss->format == PA_SAMPLE_ULAW ||
325 ss->format == PA_SAMPLE_S16BE;
326 }
327
328 void pa_rtp_context_destroy(pa_rtp_context *c) {
329 pa_assert(c);
330
331 pa_close(c->fd);
332 }
333
334 const char* pa_rtp_format_to_string(pa_sample_format_t f) {
335 switch (f) {
336 case PA_SAMPLE_S16BE:
337 return "L16";
338 case PA_SAMPLE_U8:
339 return "L8";
340 case PA_SAMPLE_ALAW:
341 return "PCMA";
342 case PA_SAMPLE_ULAW:
343 return "PCMU";
344 default:
345 return NULL;
346 }
347 }
348
349 pa_sample_format_t pa_rtp_string_to_format(const char *s) {
350 pa_assert(s);
351
352 if (!(strcmp(s, "L16")))
353 return PA_SAMPLE_S16BE;
354 else if (!strcmp(s, "L8"))
355 return PA_SAMPLE_U8;
356 else if (!strcmp(s, "PCMA"))
357 return PA_SAMPLE_ALAW;
358 else if (!strcmp(s, "PCMU"))
359 return PA_SAMPLE_ULAW;
360 else
361 return PA_SAMPLE_INVALID;
362 }
363