]>
code.delx.au - pulseaudio/blob - src/modules/rtp/rtp.c
f0ab7d8a49f5643290215cd434b04c35b15f4d75
4 This file is part of PulseAudio.
6 Copyright 2006 Lennart Poettering
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.
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.
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
33 #include <arpa/inet.h>
35 #include <sys/ioctl.h>
37 #ifdef HAVE_SYS_FILIO_H
38 #include <sys/filio.h>
41 #include <pulsecore/core-error.h>
42 #include <pulsecore/log.h>
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
) {
51 c
->sequence
= (uint16_t) (rand()*rand());
53 c
->ssrc
= ssrc
? ssrc
: (uint32_t) (rand()*rand());
54 c
->payload
= payload
& 127;
55 c
->frame_size
= frame_size
;
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
];
66 size_t n
= 0, skip
= 0;
72 if (pa_memblockq_get_length(q
) < size
)
79 if ((r
= pa_memblockq_peek(q
, &chunk
)) >= 0) {
81 size_t k
= n
+ chunk
.length
> size
? size
- n
: chunk
.length
;
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
;
93 pa_memblockq_drop(q
, &chunk
, k
);
96 if (r
< 0 || !chunk
.memblock
|| n
>= size
|| iov_idx
>= MAX_IOVECS
) {
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
);
106 iov
[0].iov_base
= (void*)header
;
107 iov
[0].iov_len
= sizeof(header
);
112 m
.msg_iovlen
= iov_idx
;
113 m
.msg_control
= NULL
;
114 m
.msg_controllen
= 0;
117 k
= sendmsg(c
->fd
, &m
, MSG_DONTWAIT
);
119 for (i
= 1; i
< iov_idx
; i
++) {
120 pa_memblock_release(mb
[i
]);
121 pa_memblock_unref(mb
[i
]);
128 c
->timestamp
+= skip
/c
->frame_size
;
131 if (errno
!= EAGAIN
) /* If the queue is full, just ignore it */
132 pa_log("sendmsg() failed: %s", pa_cstrerror(errno
));
136 if (r
< 0 || pa_memblockq_get_length(q
) < size
)
148 pa_rtp_context
* pa_rtp_context_init_recv(pa_rtp_context
*c
, int fd
, size_t frame_size
) {
152 c
->frame_size
= frame_size
;
156 int pa_rtp_recv(pa_rtp_context
*c
, pa_memchunk
*chunk
, pa_mempool
*pool
) {
167 chunk
->memblock
= NULL
;
169 if (ioctl(c
->fd
, FIONREAD
, &size
) < 0) {
170 pa_log("FIONREAD failed: %s", pa_cstrerror(errno
));
177 chunk
->memblock
= pa_memblock_new(pool
, size
);
179 iov
.iov_base
= pa_memblock_acquire(chunk
->memblock
);
186 m
.msg_control
= NULL
;
187 m
.msg_controllen
= 0;
190 if ((r
= recvmsg(c
->fd
, &m
, 0)) != size
) {
191 pa_log("recvmsg() failed: %s", r
< 0 ? pa_cstrerror(errno
) : "size mismatch");
196 pa_log("RTP packet too short.");
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));
204 header
= ntohl(header
);
205 c
->timestamp
= ntohl(c
->timestamp
);
206 c
->ssrc
= ntohl(c
->ssrc
);
208 if ((header
>> 30) != 2) {
209 pa_log("Unsupported RTP version.");
213 if ((header
>> 29) & 1) {
214 pa_log("RTP padding not supported.");
218 if ((header
>> 28) & 1) {
219 pa_log("RTP header extensions not supported.");
223 cc
= (header
>> 24) & 0xF;
224 c
->payload
= (header
>> 16) & 127;
225 c
->sequence
= header
& 0xFFFF;
227 if (12 + cc
*4 > size
) {
228 pa_log("RTP packet too short. (CSRC)");
232 chunk
->index
= 12 + cc
*4;
233 chunk
->length
= size
- chunk
->index
;
235 if (chunk
->length
% c
->frame_size
!= 0) {
236 pa_log("Vad RTP packet size.");
243 if (chunk
->memblock
) {
244 pa_memblock_release(chunk
->memblock
);
245 pa_memblock_unref(chunk
->memblock
);
251 uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec
*ss
) {
254 if (ss
->format
== PA_SAMPLE_ULAW
&& ss
->rate
== 8000 && ss
->channels
== 1)
256 if (ss
->format
== PA_SAMPLE_ALAW
&& ss
->rate
== 8000 && ss
->channels
== 1)
258 if (ss
->format
== PA_SAMPLE_S16BE
&& ss
->rate
== 44100 && ss
->channels
== 2)
260 if (ss
->format
== PA_SAMPLE_S16BE
&& ss
->rate
== 44100 && ss
->channels
== 1)
266 pa_sample_spec
*pa_rtp_sample_spec_from_payload(uint8_t payload
, pa_sample_spec
*ss
) {
272 ss
->format
= PA_SAMPLE_ULAW
;
278 ss
->format
= PA_SAMPLE_ALAW
;
284 ss
->format
= PA_SAMPLE_S16BE
;
290 ss
->format
= PA_SAMPLE_S16BE
;
301 pa_sample_spec
*pa_rtp_sample_spec_fixup(pa_sample_spec
* ss
) {
304 if (!pa_rtp_sample_spec_valid(ss
))
305 ss
->format
= PA_SAMPLE_S16BE
;
307 assert(pa_rtp_sample_spec_valid(ss
));
311 int pa_rtp_sample_spec_valid(const pa_sample_spec
*ss
) {
314 if (!pa_sample_spec_valid(ss
))
318 ss
->format
== PA_SAMPLE_U8
||
319 ss
->format
== PA_SAMPLE_ALAW
||
320 ss
->format
== PA_SAMPLE_ULAW
||
321 ss
->format
== PA_SAMPLE_S16BE
;
324 void pa_rtp_context_destroy(pa_rtp_context
*c
) {
330 const char* pa_rtp_format_to_string(pa_sample_format_t f
) {
332 case PA_SAMPLE_S16BE
:
345 pa_sample_format_t
pa_rtp_string_to_format(const char *s
) {
348 if (!(strcmp(s
, "L16")))
349 return PA_SAMPLE_S16BE
;
350 else if (!strcmp(s
, "L8"))
352 else if (!strcmp(s
, "PCMA"))
353 return PA_SAMPLE_ALAW
;
354 else if (!strcmp(s
, "PCMU"))
355 return PA_SAMPLE_ULAW
;
357 return PA_SAMPLE_INVALID
;