Merge HUGE set of changes temporarily into a branch, to allow me to move them from...
[profile/ivi/pulseaudio-panda.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 <assert.h>
29 #include <fcntl.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <arpa/inet.h>
34 #include <unistd.h>
35 #include <sys/ioctl.h>
36
37 #ifdef HAVE_SYS_FILIO_H
38 #include <sys/filio.h>
39 #endif
40
41 #include <pulsecore/core-error.h>
42 #include <pulsecore/log.h>
43
44 #include "rtp.h"
45
46 pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload, size_t frame_size) {
47     assert(c);
48     assert(fd >= 0);
49
50     c->fd = fd;
51     c->sequence = (uint16_t) (rand()*rand());
52     c->timestamp = 0;
53     c->ssrc = ssrc ? ssrc : (uint32_t) (rand()*rand());
54     c->payload = payload & 127;
55     c->frame_size = frame_size;
56
57     return c;
58 }
59
60 #define MAX_IOVECS 16
61
62 int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
63     struct iovec iov[MAX_IOVECS];
64     pa_memblock* mb[MAX_IOVECS];
65     int iov_idx = 1;
66     size_t n = 0, skip = 0;
67
68     assert(c);
69     assert(size > 0);
70     assert(q);
71
72     if (pa_memblockq_get_length(q) < size)
73         return 0;
74
75     for (;;) {
76         int r;
77         pa_memchunk chunk;
78
79         if ((r = pa_memblockq_peek(q, &chunk)) >= 0) {
80
81             size_t k = n + chunk.length > size ? size - n : chunk.length;
82
83             if (chunk.memblock) {
84                 iov[iov_idx].iov_base = (void*)((uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index);
85                 iov[iov_idx].iov_len = k;
86                 mb[iov_idx] = chunk.memblock;
87                 iov_idx ++;
88
89                 n += k;
90             }
91
92             skip += k;
93             pa_memblockq_drop(q, &chunk, k);
94         }
95
96         if (r < 0 || !chunk.memblock || n >= size || iov_idx >= MAX_IOVECS) {
97             uint32_t header[3];
98             struct msghdr m;
99             int k, i;
100
101             if (n > 0) {
102                 header[0] = htonl(((uint32_t) 2 << 30) | ((uint32_t) c->payload << 16) | ((uint32_t) c->sequence));
103                 header[1] = htonl(c->timestamp);
104                 header[2] = htonl(c->ssrc);
105
106                 iov[0].iov_base = (void*)header;
107                 iov[0].iov_len = sizeof(header);
108
109                 m.msg_name = NULL;
110                 m.msg_namelen = 0;
111                 m.msg_iov = iov;
112                 m.msg_iovlen = iov_idx;
113                 m.msg_control = NULL;
114                 m.msg_controllen = 0;
115                 m.msg_flags = 0;
116
117                 k = sendmsg(c->fd, &m, MSG_DONTWAIT);
118
119                 for (i = 1; i < iov_idx; i++) {
120                     pa_memblock_release(mb[i]);
121                     pa_memblock_unref(mb[i]);
122                 }
123
124                 c->sequence++;
125             } else
126                 k = 0;
127
128             c->timestamp += skip/c->frame_size;
129
130             if (k < 0) {
131                 if (errno != EAGAIN) /* If the queue is full, just ignore it */
132                     pa_log("sendmsg() failed: %s", pa_cstrerror(errno));
133                 return -1;
134             }
135
136             if (r < 0 || pa_memblockq_get_length(q) < size)
137                 break;
138
139             n = 0;
140             skip = 0;
141             iov_idx = 1;
142         }
143     }
144
145     return 0;
146 }
147
148 pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame_size) {
149     assert(c);
150
151     c->fd = fd;
152     c->frame_size = frame_size;
153     return c;
154 }
155
156 int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
157     int size;
158     struct msghdr m;
159     struct iovec iov;
160     uint32_t header;
161     int cc;
162     ssize_t r;
163
164     assert(c);
165     assert(chunk);
166
167     chunk->memblock = NULL;
168
169     if (ioctl(c->fd, FIONREAD, &size) < 0) {
170         pa_log("FIONREAD failed: %s", pa_cstrerror(errno));
171         goto fail;
172     }
173
174     if (!size)
175         return 0;
176
177     chunk->memblock = pa_memblock_new(pool, size);
178
179     iov.iov_base = pa_memblock_acquire(chunk->memblock);
180     iov.iov_len = size;
181
182     m.msg_name = NULL;
183     m.msg_namelen = 0;
184     m.msg_iov = &iov;
185     m.msg_iovlen = 1;
186     m.msg_control = NULL;
187     m.msg_controllen = 0;
188     m.msg_flags = 0;
189
190     if ((r = recvmsg(c->fd, &m, 0)) != size) {
191         pa_log("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch");
192         goto fail;
193     }
194
195     if (size < 12) {
196         pa_log("RTP packet too short.");
197         goto fail;
198     }
199
200     memcpy(&header, iov.iov_base, sizeof(uint32_t));
201     memcpy(&c->timestamp, (uint8_t*) iov.iov_base + 4, sizeof(uint32_t));
202     memcpy(&c->ssrc, (uint8_t*) iov.iov_base + 8, sizeof(uint32_t));
203
204     header = ntohl(header);
205     c->timestamp = ntohl(c->timestamp);
206     c->ssrc = ntohl(c->ssrc);
207
208     if ((header >> 30) != 2) {
209         pa_log("Unsupported RTP version.");
210         goto fail;
211     }
212
213     if ((header >> 29) & 1) {
214         pa_log("RTP padding not supported.");
215         goto fail;
216     }
217
218     if ((header >> 28) & 1) {
219         pa_log("RTP header extensions not supported.");
220         goto fail;
221     }
222
223     cc = (header >> 24) & 0xF;
224     c->payload = (header >> 16) & 127;
225     c->sequence = header & 0xFFFF;
226
227     if (12 + cc*4 > size) {
228         pa_log("RTP packet too short. (CSRC)");
229         goto fail;
230     }
231
232     chunk->index = 12 + cc*4;
233     chunk->length = size - chunk->index;
234
235     if (chunk->length % c->frame_size != 0) {
236         pa_log("Vad RTP packet size.");
237         goto fail;
238     }
239
240     return 0;
241
242 fail:
243     if (chunk->memblock) {
244         pa_memblock_release(chunk->memblock);
245         pa_memblock_unref(chunk->memblock);
246     }
247
248     return -1;
249 }
250
251 uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) {
252     assert(ss);
253
254     if (ss->format == PA_SAMPLE_ULAW && ss->rate == 8000 && ss->channels == 1)
255         return 0;
256     if (ss->format == PA_SAMPLE_ALAW && ss->rate == 8000 && ss->channels == 1)
257         return 8;
258     if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 2)
259         return 10;
260     if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 1)
261         return 11;
262
263     return 127;
264 }
265
266 pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec *ss) {
267     assert(ss);
268
269     switch (payload) {
270         case 0:
271             ss->channels = 1;
272             ss->format = PA_SAMPLE_ULAW;
273             ss->rate = 8000;
274             break;
275
276         case 8:
277             ss->channels = 1;
278             ss->format = PA_SAMPLE_ALAW;
279             ss->rate = 8000;
280             break;
281
282         case 10:
283             ss->channels = 2;
284             ss->format = PA_SAMPLE_S16BE;
285             ss->rate = 44100;
286             break;
287
288         case 11:
289             ss->channels = 1;
290             ss->format = PA_SAMPLE_S16BE;
291             ss->rate = 44100;
292             break;
293
294         default:
295             return NULL;
296     }
297
298     return ss;
299 }
300
301 pa_sample_spec *pa_rtp_sample_spec_fixup(pa_sample_spec * ss) {
302     assert(ss);
303
304     if (!pa_rtp_sample_spec_valid(ss))
305         ss->format = PA_SAMPLE_S16BE;
306
307     assert(pa_rtp_sample_spec_valid(ss));
308     return ss;
309 }
310
311 int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) {
312     assert(ss);
313
314     if (!pa_sample_spec_valid(ss))
315         return 0;
316
317     return
318         ss->format == PA_SAMPLE_U8 ||
319         ss->format == PA_SAMPLE_ALAW ||
320         ss->format == PA_SAMPLE_ULAW ||
321         ss->format == PA_SAMPLE_S16BE;
322 }
323
324 void pa_rtp_context_destroy(pa_rtp_context *c) {
325     assert(c);
326
327     close(c->fd);
328 }
329
330 const char* pa_rtp_format_to_string(pa_sample_format_t f) {
331     switch (f) {
332         case PA_SAMPLE_S16BE:
333             return "L16";
334         case PA_SAMPLE_U8:
335             return "L8";
336         case PA_SAMPLE_ALAW:
337             return "PCMA";
338         case PA_SAMPLE_ULAW:
339             return "PCMU";
340         default:
341             return NULL;
342     }
343 }
344
345 pa_sample_format_t pa_rtp_string_to_format(const char *s) {
346     assert(s);
347
348     if (!(strcmp(s, "L16")))
349         return PA_SAMPLE_S16BE;
350     else if (!strcmp(s, "L8"))
351         return PA_SAMPLE_U8;
352     else if (!strcmp(s, "PCMA"))
353         return PA_SAMPLE_ALAW;
354     else if (!strcmp(s, "PCMU"))
355         return PA_SAMPLE_ULAW;
356     else
357         return PA_SAMPLE_INVALID;
358 }
359