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