merge glitch-free branch back into trunk
[profile/ivi/pulseaudio.git] / 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     pa_memchunk_reset(&c->memchunk);
59
60     return c;
61 }
62
63 #define MAX_IOVECS 16
64
65 int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
66     struct iovec iov[MAX_IOVECS];
67     pa_memblock* mb[MAX_IOVECS];
68     int iov_idx = 1;
69     size_t n = 0;
70
71     pa_assert(c);
72     pa_assert(size > 0);
73     pa_assert(q);
74
75     if (pa_memblockq_get_length(q) < size)
76         return 0;
77
78     for (;;) {
79         int r;
80         pa_memchunk chunk;
81
82         pa_memchunk_reset(&chunk);
83
84         if ((r = pa_memblockq_peek(q, &chunk)) >= 0) {
85
86             size_t k = n + chunk.length > size ? size - n : chunk.length;
87
88             pa_assert(chunk.memblock);
89
90             iov[iov_idx].iov_base = ((uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index);
91             iov[iov_idx].iov_len = k;
92             mb[iov_idx] = chunk.memblock;
93             iov_idx ++;
94
95             n += k;
96             pa_memblockq_drop(q, k);
97         }
98
99         pa_assert(n % c->frame_size == 0);
100
101         if (r < 0 || n >= size || iov_idx >= MAX_IOVECS) {
102             uint32_t header[3];
103             struct msghdr m;
104             int k, i;
105
106             if (n > 0) {
107                 header[0] = htonl(((uint32_t) 2 << 30) | ((uint32_t) c->payload << 16) | ((uint32_t) c->sequence));
108                 header[1] = htonl(c->timestamp);
109                 header[2] = htonl(c->ssrc);
110
111                 iov[0].iov_base = (void*)header;
112                 iov[0].iov_len = sizeof(header);
113
114                 m.msg_name = NULL;
115                 m.msg_namelen = 0;
116                 m.msg_iov = iov;
117                 m.msg_iovlen = iov_idx;
118                 m.msg_control = NULL;
119                 m.msg_controllen = 0;
120                 m.msg_flags = 0;
121
122                 k = sendmsg(c->fd, &m, MSG_DONTWAIT);
123
124                 for (i = 1; i < iov_idx; i++) {
125                     pa_memblock_release(mb[i]);
126                     pa_memblock_unref(mb[i]);
127                 }
128
129                 c->sequence++;
130             } else
131                 k = 0;
132
133             c->timestamp += n/c->frame_size;
134
135             if (k < 0) {
136                 if (errno != EAGAIN && errno != EINTR) /* If the queue is full, just ignore it */
137                     pa_log("sendmsg() failed: %s", pa_cstrerror(errno));
138                 return -1;
139             }
140
141             if (r < 0 || pa_memblockq_get_length(q) < size)
142                 break;
143
144             n = 0;
145             iov_idx = 1;
146         }
147     }
148
149     return 0;
150 }
151
152 pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame_size) {
153     pa_assert(c);
154
155     c->fd = fd;
156     c->frame_size = frame_size;
157
158     pa_memchunk_reset(&c->memchunk);
159     return c;
160 }
161
162 int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
163     int size;
164     struct msghdr m;
165     struct iovec iov;
166     uint32_t header;
167     int cc;
168     ssize_t r;
169
170     pa_assert(c);
171     pa_assert(chunk);
172
173     pa_memchunk_reset(chunk);
174
175     if (ioctl(c->fd, FIONREAD, &size) < 0) {
176         pa_log_warn("FIONREAD failed: %s", pa_cstrerror(errno));
177         goto fail;
178     }
179
180     if (size <= 0)
181         return 0;
182
183     if (c->memchunk.length < (unsigned) size) {
184         size_t l;
185
186         if (c->memchunk.memblock)
187             pa_memblock_unref(c->memchunk.memblock);
188
189         l = PA_MAX((size_t) size, pa_mempool_block_size_max(pool));
190
191         c->memchunk.memblock = pa_memblock_new(pool, l);
192         c->memchunk.index = 0;
193         c->memchunk.length = pa_memblock_get_length(c->memchunk.memblock);
194     }
195
196     pa_assert(c->memchunk.length >= (size_t) size);
197
198     chunk->memblock = pa_memblock_ref(c->memchunk.memblock);
199     chunk->index = c->memchunk.index;
200
201     iov.iov_base = (uint8_t*) pa_memblock_acquire(chunk->memblock) + chunk->index;
202     iov.iov_len = size;
203
204     m.msg_name = NULL;
205     m.msg_namelen = 0;
206     m.msg_iov = &iov;
207     m.msg_iovlen = 1;
208     m.msg_control = NULL;
209     m.msg_controllen = 0;
210     m.msg_flags = 0;
211
212     r = recvmsg(c->fd, &m, 0);
213     pa_memblock_release(chunk->memblock);
214
215     if (r != size) {
216         if (r < 0 && errno != EAGAIN && errno != EINTR)
217             pa_log_warn("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch");
218
219         goto fail;
220     }
221
222     if (size < 12) {
223         pa_log_warn("RTP packet too short.");
224         goto fail;
225     }
226
227     memcpy(&header, iov.iov_base, sizeof(uint32_t));
228     memcpy(&c->timestamp, (uint8_t*) iov.iov_base + 4, sizeof(uint32_t));
229     memcpy(&c->ssrc, (uint8_t*) iov.iov_base + 8, sizeof(uint32_t));
230
231     header = ntohl(header);
232     c->timestamp = ntohl(c->timestamp);
233     c->ssrc = ntohl(c->ssrc);
234
235     if ((header >> 30) != 2) {
236         pa_log_warn("Unsupported RTP version.");
237         goto fail;
238     }
239
240     if ((header >> 29) & 1) {
241         pa_log_warn("RTP padding not supported.");
242         goto fail;
243     }
244
245     if ((header >> 28) & 1) {
246         pa_log_warn("RTP header extensions not supported.");
247         goto fail;
248     }
249
250     cc = (header >> 24) & 0xF;
251     c->payload = (header >> 16) & 127;
252     c->sequence = header & 0xFFFF;
253
254     if (12 + cc*4 > size) {
255         pa_log_warn("RTP packet too short. (CSRC)");
256         goto fail;
257     }
258
259     chunk->index += 12 + cc*4;
260     chunk->length = size - 12 + cc*4;
261
262     if (chunk->length % c->frame_size != 0) {
263         pa_log_warn("Bad RTP packet size.");
264         goto fail;
265     }
266
267     c->memchunk.index = chunk->index + chunk->length;
268     c->memchunk.length = pa_memblock_get_length(c->memchunk.memblock) - c->memchunk.index;
269
270     if (c->memchunk.length <= 0) {
271         pa_memblock_unref(c->memchunk.memblock);
272         pa_memchunk_reset(&c->memchunk);
273     }
274
275     return 0;
276
277 fail:
278     if (chunk->memblock)
279         pa_memblock_unref(chunk->memblock);
280
281     return -1;
282 }
283
284 uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) {
285     pa_assert(ss);
286
287     if (ss->format == PA_SAMPLE_ULAW && ss->rate == 8000 && ss->channels == 1)
288         return 0;
289     if (ss->format == PA_SAMPLE_ALAW && ss->rate == 8000 && ss->channels == 1)
290         return 8;
291     if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 2)
292         return 10;
293     if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 1)
294         return 11;
295
296     return 127;
297 }
298
299 pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec *ss) {
300     pa_assert(ss);
301
302     switch (payload) {
303         case 0:
304             ss->channels = 1;
305             ss->format = PA_SAMPLE_ULAW;
306             ss->rate = 8000;
307             break;
308
309         case 8:
310             ss->channels = 1;
311             ss->format = PA_SAMPLE_ALAW;
312             ss->rate = 8000;
313             break;
314
315         case 10:
316             ss->channels = 2;
317             ss->format = PA_SAMPLE_S16BE;
318             ss->rate = 44100;
319             break;
320
321         case 11:
322             ss->channels = 1;
323             ss->format = PA_SAMPLE_S16BE;
324             ss->rate = 44100;
325             break;
326
327         default:
328             return NULL;
329     }
330
331     return ss;
332 }
333
334 pa_sample_spec *pa_rtp_sample_spec_fixup(pa_sample_spec * ss) {
335     pa_assert(ss);
336
337     if (!pa_rtp_sample_spec_valid(ss))
338         ss->format = PA_SAMPLE_S16BE;
339
340     pa_assert(pa_rtp_sample_spec_valid(ss));
341     return ss;
342 }
343
344 int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) {
345     pa_assert(ss);
346
347     if (!pa_sample_spec_valid(ss))
348         return 0;
349
350     return
351         ss->format == PA_SAMPLE_U8 ||
352         ss->format == PA_SAMPLE_ALAW ||
353         ss->format == PA_SAMPLE_ULAW ||
354         ss->format == PA_SAMPLE_S16BE;
355 }
356
357 void pa_rtp_context_destroy(pa_rtp_context *c) {
358     pa_assert(c);
359
360     pa_assert_se(pa_close(c->fd) == 0);
361
362     if (c->memchunk.memblock)
363         pa_memblock_unref(c->memchunk.memblock);
364 }
365
366 const char* pa_rtp_format_to_string(pa_sample_format_t f) {
367     switch (f) {
368         case PA_SAMPLE_S16BE:
369             return "L16";
370         case PA_SAMPLE_U8:
371             return "L8";
372         case PA_SAMPLE_ALAW:
373             return "PCMA";
374         case PA_SAMPLE_ULAW:
375             return "PCMU";
376         default:
377             return NULL;
378     }
379 }
380
381 pa_sample_format_t pa_rtp_string_to_format(const char *s) {
382     pa_assert(s);
383
384     if (!(strcmp(s, "L16")))
385         return PA_SAMPLE_S16BE;
386     else if (!strcmp(s, "L8"))
387         return PA_SAMPLE_U8;
388     else if (!strcmp(s, "PCMA"))
389         return PA_SAMPLE_ALAW;
390     else if (!strcmp(s, "PCMU"))
391         return PA_SAMPLE_ULAW;
392     else
393         return PA_SAMPLE_INVALID;
394 }