]> code.delx.au - pulseaudio/blob - src/modules/rtp/rtp.c
really create glitch-free branch
[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 pa_memchunk_reset(chunk);
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 r = recvmsg(c->fd, &m, 0);
193 pa_memblock_release(chunk->memblock);
194
195 if (r != size) {
196 if (r < 0 && errno != EAGAIN && errno != EINTR)
197 pa_log_warn("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch");
198
199 goto fail;
200 }
201
202 if (size < 12) {
203 pa_log_warn("RTP packet too short.");
204 goto fail;
205 }
206
207 memcpy(&header, iov.iov_base, sizeof(uint32_t));
208 memcpy(&c->timestamp, (uint8_t*) iov.iov_base + 4, sizeof(uint32_t));
209 memcpy(&c->ssrc, (uint8_t*) iov.iov_base + 8, sizeof(uint32_t));
210
211 header = ntohl(header);
212 c->timestamp = ntohl(c->timestamp);
213 c->ssrc = ntohl(c->ssrc);
214
215 if ((header >> 30) != 2) {
216 pa_log_warn("Unsupported RTP version.");
217 goto fail;
218 }
219
220 if ((header >> 29) & 1) {
221 pa_log_warn("RTP padding not supported.");
222 goto fail;
223 }
224
225 if ((header >> 28) & 1) {
226 pa_log_warn("RTP header extensions not supported.");
227 goto fail;
228 }
229
230 cc = (header >> 24) & 0xF;
231 c->payload = (header >> 16) & 127;
232 c->sequence = header & 0xFFFF;
233
234 if (12 + cc*4 > size) {
235 pa_log_warn("RTP packet too short. (CSRC)");
236 goto fail;
237 }
238
239 chunk->index = 12 + cc*4;
240 chunk->length = size - chunk->index;
241
242 if (chunk->length % c->frame_size != 0) {
243 pa_log_warn("Bad RTP packet size.");
244 goto fail;
245 }
246
247 return 0;
248
249 fail:
250 if (chunk->memblock)
251 pa_memblock_unref(chunk->memblock);
252
253 return -1;
254 }
255
256 uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) {
257 pa_assert(ss);
258
259 if (ss->format == PA_SAMPLE_ULAW && ss->rate == 8000 && ss->channels == 1)
260 return 0;
261 if (ss->format == PA_SAMPLE_ALAW && ss->rate == 8000 && ss->channels == 1)
262 return 8;
263 if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 2)
264 return 10;
265 if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 1)
266 return 11;
267
268 return 127;
269 }
270
271 pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec *ss) {
272 pa_assert(ss);
273
274 switch (payload) {
275 case 0:
276 ss->channels = 1;
277 ss->format = PA_SAMPLE_ULAW;
278 ss->rate = 8000;
279 break;
280
281 case 8:
282 ss->channels = 1;
283 ss->format = PA_SAMPLE_ALAW;
284 ss->rate = 8000;
285 break;
286
287 case 10:
288 ss->channels = 2;
289 ss->format = PA_SAMPLE_S16BE;
290 ss->rate = 44100;
291 break;
292
293 case 11:
294 ss->channels = 1;
295 ss->format = PA_SAMPLE_S16BE;
296 ss->rate = 44100;
297 break;
298
299 default:
300 return NULL;
301 }
302
303 return ss;
304 }
305
306 pa_sample_spec *pa_rtp_sample_spec_fixup(pa_sample_spec * ss) {
307 pa_assert(ss);
308
309 if (!pa_rtp_sample_spec_valid(ss))
310 ss->format = PA_SAMPLE_S16BE;
311
312 pa_assert(pa_rtp_sample_spec_valid(ss));
313 return ss;
314 }
315
316 int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) {
317 pa_assert(ss);
318
319 if (!pa_sample_spec_valid(ss))
320 return 0;
321
322 return
323 ss->format == PA_SAMPLE_U8 ||
324 ss->format == PA_SAMPLE_ALAW ||
325 ss->format == PA_SAMPLE_ULAW ||
326 ss->format == PA_SAMPLE_S16BE;
327 }
328
329 void pa_rtp_context_destroy(pa_rtp_context *c) {
330 pa_assert(c);
331
332 pa_close(c->fd);
333 }
334
335 const char* pa_rtp_format_to_string(pa_sample_format_t f) {
336 switch (f) {
337 case PA_SAMPLE_S16BE:
338 return "L16";
339 case PA_SAMPLE_U8:
340 return "L8";
341 case PA_SAMPLE_ALAW:
342 return "PCMA";
343 case PA_SAMPLE_ULAW:
344 return "PCMU";
345 default:
346 return NULL;
347 }
348 }
349
350 pa_sample_format_t pa_rtp_string_to_format(const char *s) {
351 pa_assert(s);
352
353 if (!(strcmp(s, "L16")))
354 return PA_SAMPLE_S16BE;
355 else if (!strcmp(s, "L8"))
356 return PA_SAMPLE_U8;
357 else if (!strcmp(s, "PCMA"))
358 return PA_SAMPLE_ALAW;
359 else if (!strcmp(s, "PCMU"))
360 return PA_SAMPLE_ULAW;
361 else
362 return PA_SAMPLE_INVALID;
363 }
364