03a01412d301e8514f30af81bec35e13d8236ef4
[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*) chunk.memblock->data + 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_unref(mb[i]);
121
122                 c->sequence++;
123             } else
124                 k = 0;
125
126             c->timestamp += skip/c->frame_size;
127
128             if (k < 0) {
129                 if (errno != EAGAIN) /* If the queue is full, just ignore it */
130                     pa_log("sendmsg() failed: %s", pa_cstrerror(errno));
131                 return -1;
132             }
133
134             if (r < 0 || pa_memblockq_get_length(q) < size)
135                 break;
136
137             n = 0;
138             skip = 0;
139             iov_idx = 1;
140         }
141     }
142
143     return 0;
144 }
145
146 pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame_size) {
147     assert(c);
148
149     c->fd = fd;
150     c->frame_size = frame_size;
151     return c;
152 }
153
154 int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
155     int size;
156     struct msghdr m;
157     struct iovec iov;
158     uint32_t header;
159     int cc;
160     ssize_t r;
161
162     assert(c);
163     assert(chunk);
164
165     chunk->memblock = NULL;
166
167     if (ioctl(c->fd, FIONREAD, &size) < 0) {
168         pa_log("FIONREAD failed: %s", pa_cstrerror(errno));
169         goto fail;
170     }
171
172     if (!size)
173         return 0;
174
175     chunk->memblock = pa_memblock_new(pool, size);
176
177     iov.iov_base = chunk->memblock->data;
178     iov.iov_len = size;
179
180     m.msg_name = NULL;
181     m.msg_namelen = 0;
182     m.msg_iov = &iov;
183     m.msg_iovlen = 1;
184     m.msg_control = NULL;
185     m.msg_controllen = 0;
186     m.msg_flags = 0;
187
188     if ((r = recvmsg(c->fd, &m, 0)) != size) {
189         pa_log("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch");
190         goto fail;
191     }
192
193     if (size < 12) {
194         pa_log("RTP packet too short.");
195         goto fail;
196     }
197
198     memcpy(&header, chunk->memblock->data, sizeof(uint32_t));
199     memcpy(&c->timestamp, (uint8_t*) chunk->memblock->data + 4, sizeof(uint32_t));
200     memcpy(&c->ssrc, (uint8_t*) chunk->memblock->data + 8, sizeof(uint32_t));
201
202     header = ntohl(header);
203     c->timestamp = ntohl(c->timestamp);
204     c->ssrc = ntohl(c->ssrc);
205
206     if ((header >> 30) != 2) {
207         pa_log("Unsupported RTP version.");
208         goto fail;
209     }
210
211     if ((header >> 29) & 1) {
212         pa_log("RTP padding not supported.");
213         goto fail;
214     }
215
216     if ((header >> 28) & 1) {
217         pa_log("RTP header extensions not supported.");
218         goto fail;
219     }
220
221     cc = (header >> 24) & 0xF;
222     c->payload = (header >> 16) & 127;
223     c->sequence = header & 0xFFFF;
224
225     if (12 + cc*4 > size) {
226         pa_log("RTP packet too short. (CSRC)");
227         goto fail;
228     }
229
230     chunk->index = 12 + cc*4;
231     chunk->length = size - chunk->index;
232
233     if (chunk->length % c->frame_size != 0) {
234         pa_log("Vad RTP packet size.");
235         goto fail;
236     }
237
238     return 0;
239
240 fail:
241     if (chunk->memblock)
242         pa_memblock_unref(chunk->memblock);
243
244     return -1;
245 }
246
247 uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) {
248     assert(ss);
249
250     if (ss->format == PA_SAMPLE_ULAW && ss->rate == 8000 && ss->channels == 1)
251         return 0;
252     if (ss->format == PA_SAMPLE_ALAW && ss->rate == 8000 && ss->channels == 1)
253         return 8;
254     if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 2)
255         return 10;
256     if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 1)
257         return 11;
258
259     return 127;
260 }
261
262 pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec *ss) {
263     assert(ss);
264
265     switch (payload) {
266         case 0:
267             ss->channels = 1;
268             ss->format = PA_SAMPLE_ULAW;
269             ss->rate = 8000;
270             break;
271
272         case 8:
273             ss->channels = 1;
274             ss->format = PA_SAMPLE_ALAW;
275             ss->rate = 8000;
276             break;
277
278         case 10:
279             ss->channels = 2;
280             ss->format = PA_SAMPLE_S16BE;
281             ss->rate = 44100;
282             break;
283
284         case 11:
285             ss->channels = 1;
286             ss->format = PA_SAMPLE_S16BE;
287             ss->rate = 44100;
288             break;
289
290         default:
291             return NULL;
292     }
293
294     return ss;
295 }
296
297 pa_sample_spec *pa_rtp_sample_spec_fixup(pa_sample_spec * ss) {
298     assert(ss);
299
300     if (!pa_rtp_sample_spec_valid(ss))
301         ss->format = PA_SAMPLE_S16BE;
302
303     assert(pa_rtp_sample_spec_valid(ss));
304     return ss;
305 }
306
307 int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) {
308     assert(ss);
309
310     if (!pa_sample_spec_valid(ss))
311         return 0;
312
313     return
314         ss->format == PA_SAMPLE_U8 ||
315         ss->format == PA_SAMPLE_ALAW ||
316         ss->format == PA_SAMPLE_ULAW ||
317         ss->format == PA_SAMPLE_S16BE;
318 }
319
320 void pa_rtp_context_destroy(pa_rtp_context *c) {
321     assert(c);
322
323     close(c->fd);
324 }
325
326 const char* pa_rtp_format_to_string(pa_sample_format_t f) {
327     switch (f) {
328         case PA_SAMPLE_S16BE:
329             return "L16";
330         case PA_SAMPLE_U8:
331             return "L8";
332         case PA_SAMPLE_ALAW:
333             return "PCMA";
334         case PA_SAMPLE_ULAW:
335             return "PCMU";
336         default:
337             return NULL;
338     }
339 }
340
341 pa_sample_format_t pa_rtp_string_to_format(const char *s) {
342     assert(s);
343
344     if (!(strcmp(s, "L16")))
345         return PA_SAMPLE_S16BE;
346     else if (!strcmp(s, "L8"))
347         return PA_SAMPLE_U8;
348     else if (!strcmp(s, "PCMA"))
349         return PA_SAMPLE_ALAW;
350     else if (!strcmp(s, "PCMU"))
351         return PA_SAMPLE_ULAW;
352     else
353         return PA_SAMPLE_INVALID;
354 }
355