summaryrefslogtreecommitdiffstats
path: root/src/modules/rtp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/rtp')
l---------[-rw-r--r--]src/modules/rtp/Makefile14
-rw-r--r--src/modules/rtp/headerlist.c186
-rw-r--r--src/modules/rtp/headerlist.h46
-rw-r--r--src/modules/rtp/module-rtp-recv.c20
-rw-r--r--src/modules/rtp/module-rtp-send.c42
-rw-r--r--src/modules/rtp/rtp.c21
-rw-r--r--src/modules/rtp/rtsp_client.c542
-rw-r--r--src/modules/rtp/rtsp_client.h73
-rw-r--r--src/modules/rtp/sap.c28
-rw-r--r--src/modules/rtp/sdp.c8
10 files changed, 918 insertions, 62 deletions
diff --git a/src/modules/rtp/Makefile b/src/modules/rtp/Makefile
index 316beb72..efe5a336 100644..120000
--- a/src/modules/rtp/Makefile
+++ b/src/modules/rtp/Makefile
@@ -1,13 +1 @@
-# This is a dirty trick just to ease compilation with emacs
-#
-# This file is not intended to be distributed or anything
-#
-# So: don't touch it, even better ignore it!
-
-all:
- $(MAKE) -C ../..
-
-clean:
- $(MAKE) -C ../.. clean
-
-.PHONY: all clean
+../../pulse/Makefile \ No newline at end of file
diff --git a/src/modules/rtp/headerlist.c b/src/modules/rtp/headerlist.c
new file mode 100644
index 00000000..0fef835b
--- /dev/null
+++ b/src/modules/rtp/headerlist.c
@@ -0,0 +1,186 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2008 Colin Guthrie
+ Copyright 2007 Lennart Poettering
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <pulse/xmalloc.h>
+
+#include <pulsecore/hashmap.h>
+#include <pulsecore/strbuf.h>
+#include <pulsecore/core-util.h>
+
+#include "headerlist.h"
+
+struct header {
+ char *key;
+ void *value;
+ size_t nbytes;
+};
+
+#define MAKE_HASHMAP(p) ((pa_hashmap*) (p))
+#define MAKE_HEADERLIST(p) ((pa_headerlist*) (p))
+
+static void header_free(struct header *hdr) {
+ pa_assert(hdr);
+
+ pa_xfree(hdr->key);
+ pa_xfree(hdr->value);
+ pa_xfree(hdr);
+}
+
+pa_headerlist* pa_headerlist_new(void) {
+ return MAKE_HEADERLIST(pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func));
+}
+
+void pa_headerlist_free(pa_headerlist* p) {
+ struct header *hdr;
+
+ while ((hdr = pa_hashmap_steal_first(MAKE_HASHMAP(p))))
+ header_free(hdr);
+
+ pa_hashmap_free(MAKE_HASHMAP(p), NULL, NULL);
+}
+
+int pa_headerlist_puts(pa_headerlist *p, const char *key, const char *value) {
+ struct header *hdr;
+ pa_bool_t add = FALSE;
+
+ pa_assert(p);
+ pa_assert(key);
+
+ if (!(hdr = pa_hashmap_get(MAKE_HASHMAP(p), key))) {
+ hdr = pa_xnew(struct header, 1);
+ hdr->key = pa_xstrdup(key);
+ add = TRUE;
+ } else
+ pa_xfree(hdr->value);
+
+ hdr->value = pa_xstrdup(value);
+ hdr->nbytes = strlen(value)+1;
+
+ if (add)
+ pa_hashmap_put(MAKE_HASHMAP(p), hdr->key, hdr);
+
+ return 0;
+}
+
+int pa_headerlist_putsappend(pa_headerlist *p, const char *key, const char *value) {
+ struct header *hdr;
+ pa_bool_t add = FALSE;
+
+ pa_assert(p);
+ pa_assert(key);
+
+ if (!(hdr = pa_hashmap_get(MAKE_HASHMAP(p), key))) {
+ hdr = pa_xnew(struct header, 1);
+ hdr->key = pa_xstrdup(key);
+ hdr->value = pa_xstrdup(value);
+ add = TRUE;
+ } else {
+ void *newval = pa_sprintf_malloc("%s%s", (char*)hdr->value, value);
+ pa_xfree(hdr->value);
+ hdr->value = newval;
+ }
+ hdr->nbytes = strlen(hdr->value)+1;
+
+ if (add)
+ pa_hashmap_put(MAKE_HASHMAP(p), hdr->key, hdr);
+
+ return 0;
+}
+
+const char *pa_headerlist_gets(pa_headerlist *p, const char *key) {
+ struct header *hdr;
+
+ pa_assert(p);
+ pa_assert(key);
+
+ if (!(hdr = pa_hashmap_get(MAKE_HASHMAP(p), key)))
+ return NULL;
+
+ if (hdr->nbytes <= 0)
+ return NULL;
+
+ if (((char*) hdr->value)[hdr->nbytes-1] != 0)
+ return NULL;
+
+ if (strlen((char*) hdr->value) != hdr->nbytes-1)
+ return NULL;
+
+ return (char*) hdr->value;
+}
+
+int pa_headerlist_remove(pa_headerlist *p, const char *key) {
+ struct header *hdr;
+
+ pa_assert(p);
+ pa_assert(key);
+
+ if (!(hdr = pa_hashmap_remove(MAKE_HASHMAP(p), key)))
+ return -1;
+
+ header_free(hdr);
+ return 0;
+}
+
+const char *pa_headerlist_iterate(pa_headerlist *p, void **state) {
+ struct header *hdr;
+
+ if (!(hdr = pa_hashmap_iterate(MAKE_HASHMAP(p), state, NULL)))
+ return NULL;
+
+ return hdr->key;
+}
+
+char *pa_headerlist_to_string(pa_headerlist *p) {
+ const char *key;
+ void *state = NULL;
+ pa_strbuf *buf;
+
+ pa_assert(p);
+
+ buf = pa_strbuf_new();
+
+ while ((key = pa_headerlist_iterate(p, &state))) {
+
+ const char *v;
+
+ if ((v = pa_headerlist_gets(p, key)))
+ pa_strbuf_printf(buf, "%s: %s\r\n", key, v);
+ }
+
+ return pa_strbuf_tostring_free(buf);
+}
+
+int pa_headerlist_contains(pa_headerlist *p, const char *key) {
+ pa_assert(p);
+ pa_assert(key);
+
+ if (!(pa_hashmap_get(MAKE_HASHMAP(p), key)))
+ return 0;
+
+ return 1;
+}
diff --git a/src/modules/rtp/headerlist.h b/src/modules/rtp/headerlist.h
new file mode 100644
index 00000000..4b9c6433
--- /dev/null
+++ b/src/modules/rtp/headerlist.h
@@ -0,0 +1,46 @@
+#ifndef foopulseheaderlisthfoo
+#define foopulseheaderlisthfoo
+
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2008 Colin Guthrie
+ Copyright 2007 Lennart Poettering
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <pulsecore/macro.h>
+
+typedef struct pa_headerlist pa_headerlist;
+
+pa_headerlist* pa_headerlist_new(void);
+void pa_headerlist_free(pa_headerlist* p);
+
+int pa_headerlist_puts(pa_headerlist *p, const char *key, const char *value);
+int pa_headerlist_putsappend(pa_headerlist *p, const char *key, const char *value);
+
+const char *pa_headerlist_gets(pa_headerlist *p, const char *key);
+
+int pa_headerlist_remove(pa_headerlist *p, const char *key);
+
+const char *pa_headerlist_iterate(pa_headerlist *p, void **state);
+
+char *pa_headerlist_to_string(pa_headerlist *p);
+
+int pa_headerlist_contains(pa_headerlist *p, const char *key);
+
+#endif
diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c
index e04e4611..e35773cc 100644
--- a/src/modules/rtp/module-rtp-recv.c
+++ b/src/modules/rtp/module-rtp-recv.c
@@ -238,25 +238,25 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
else
delta = j;
- pa_memblockq_seek(s->memblockq, delta * s->rtp_context.frame_size, PA_SEEK_RELATIVE);
+ pa_memblockq_seek(s->memblockq, delta * (int64_t) s->rtp_context.frame_size, PA_SEEK_RELATIVE);
pa_rtclock_get(&now);
- pa_smoother_put(s->smoother, pa_timeval_load(&now), pa_bytes_to_usec(pa_memblockq_get_write_index(s->memblockq), &s->sink_input->sample_spec));
+ pa_smoother_put(s->smoother, pa_timeval_load(&now), pa_bytes_to_usec((uint64_t) pa_memblockq_get_write_index(s->memblockq), &s->sink_input->sample_spec));
if (pa_memblockq_push(s->memblockq, &chunk) < 0) {
pa_log_warn("Queue overrun");
- pa_memblockq_seek(s->memblockq, chunk.length, PA_SEEK_RELATIVE);
+ pa_memblockq_seek(s->memblockq, (int64_t) chunk.length, PA_SEEK_RELATIVE);
}
- pa_log("blocks in q: %u", pa_memblockq_get_nblocks(s->memblockq));
+/* pa_log("blocks in q: %u", pa_memblockq_get_nblocks(s->memblockq)); */
pa_memblock_unref(chunk.memblock);
/* The next timestamp we expect */
- s->offset = s->rtp_context.timestamp + (chunk.length / s->rtp_context.frame_size);
+ s->offset = s->rtp_context.timestamp + (uint32_t) (chunk.length / s->rtp_context.frame_size);
- pa_atomic_store(&s->timestamp, now.tv_sec);
+ pa_atomic_store(&s->timestamp, (int) now.tv_sec);
if (s->last_rate_update + RATE_UPDATE_INTERVAL < pa_timeval_load(&now)) {
pa_usec_t wi, ri, render_delay, sink_delay = 0, latency, fix;
@@ -265,7 +265,7 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
pa_log("Updating sample rate");
wi = pa_smoother_get(s->smoother, pa_timeval_load(&now));
- ri = pa_bytes_to_usec(pa_memblockq_get_read_index(s->memblockq), &s->sink_input->sample_spec);
+ ri = pa_bytes_to_usec((uint64_t) pa_memblockq_get_read_index(s->memblockq), &s->sink_input->sample_spec);
if (PA_MSGOBJECT(s->sink_input->sink)->process_msg(PA_MSGOBJECT(s->sink_input->sink), PA_SINK_MESSAGE_GET_LATENCY, &sink_delay, 0, NULL) < 0)
sink_delay = 0;
@@ -291,7 +291,7 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
fix = latency - s->intended_latency;
/* How many samples is this per second? */
- fix_samples = fix * s->sink_input->thread_info.sample_spec.rate / RATE_UPDATE_INTERVAL;
+ fix_samples = (unsigned) (fix * (pa_usec_t) s->sink_input->thread_info.sample_spec.rate / (pa_usec_t) RATE_UPDATE_INTERVAL);
/* Check if deviation is in bounds */
if (fix_samples > s->sink_input->sample_spec.rate*.20)
@@ -431,7 +431,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
s->smoother = pa_smoother_new(PA_USEC_PER_SEC*5, PA_USEC_PER_SEC*2, TRUE, 10);
pa_smoother_set_time_offset(s->smoother, pa_timeval_load(&now));
s->last_rate_update = pa_timeval_load(&now);
- pa_atomic_store(&s->timestamp, now.tv_sec);
+ pa_atomic_store(&s->timestamp, (int) now.tv_sec);
if ((fd = mcast_socket((const struct sockaddr*) &sdp_info->sa, sdp_info->salen)) < 0)
goto fail;
@@ -566,7 +566,7 @@ static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event
} else {
struct timeval now;
pa_rtclock_get(&now);
- pa_atomic_store(&s->timestamp, now.tv_sec);
+ pa_atomic_store(&s->timestamp, (int) now.tv_sec);
pa_sdp_info_destroy(&info);
}
diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c
index 5e542253..8d1e92fe 100644
--- a/src/modules/rtp/module-rtp-send.c
+++ b/src/modules/rtp/module-rtp-send.c
@@ -67,10 +67,12 @@ PA_MODULE_USAGE(
"destination=<destination IP address> "
"port=<port number> "
"mtu=<maximum transfer unit> "
- "loop=<loopback to local host?>"
+ "loop=<loopback to local host?> "
+ "ttl=<ttl value>"
);
#define DEFAULT_PORT 46000
+#define DEFAULT_TTL 1
#define SAP_PORT 9875
#define DEFAULT_DESTINATION "224.0.0.56"
#define MEMBLOCKQ_MAXLENGTH (1024*170)
@@ -86,6 +88,7 @@ static const char* const valid_modargs[] = {
"port",
"mtu" ,
"loop",
+ "ttl",
NULL
};
@@ -167,7 +170,9 @@ int pa__init(pa_module*m) {
pa_modargs *ma = NULL;
const char *dest;
uint32_t port = DEFAULT_PORT, mtu;
- int af, fd = -1, sap_fd = -1;
+ uint32_t ttl = DEFAULT_TTL;
+ sa_family_t af;
+ int fd = -1, sap_fd = -1;
pa_source *s;
pa_sample_spec ss;
pa_channel_map cm;
@@ -219,14 +224,14 @@ int pa__init(pa_module*m) {
payload = pa_rtp_payload_from_sample_spec(&ss);
- mtu = pa_frame_align(DEFAULT_MTU, &ss);
+ mtu = (uint32_t) pa_frame_align(DEFAULT_MTU, &ss);
if (pa_modargs_get_value_u32(ma, "mtu", &mtu) < 0 || mtu < 1 || mtu % pa_frame_size(&ss) != 0) {
pa_log("Invalid MTU.");
goto fail;
}
- port = DEFAULT_PORT + ((rand() % 512) << 1);
+ port = DEFAULT_PORT + ((uint32_t) (rand() % 512) << 1);
if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) {
pa_log("port= expects a numerical argument between 1 and 65535.");
goto fail;
@@ -235,16 +240,21 @@ int pa__init(pa_module*m) {
if (port & 1)
pa_log_warn("Port number not even as suggested in RFC3550!");
+ if (pa_modargs_get_value_u32(ma, "ttl", &ttl) < 0 || ttl < 1 || ttl > 0xFF) {
+ pa_log("ttl= expects a numerical argument between 1 and 255.");
+ goto fail;
+ }
+
dest = pa_modargs_get_value(ma, "destination", DEFAULT_DESTINATION);
if (inet_pton(AF_INET6, dest, &sa6.sin6_addr) > 0) {
sa6.sin6_family = af = AF_INET6;
- sa6.sin6_port = htons(port);
+ sa6.sin6_port = htons((uint16_t) port);
sap_sa6 = sa6;
sap_sa6.sin6_port = htons(SAP_PORT);
} else if (inet_pton(AF_INET, dest, &sa4.sin_addr) > 0) {
sa4.sin_family = af = AF_INET;
- sa4.sin_port = htons(port);
+ sa4.sin_port = htons((uint16_t) port);
sap_sa4 = sa4;
sap_sa4.sin_port = htons(SAP_PORT);
} else {
@@ -257,7 +267,7 @@ int pa__init(pa_module*m) {
goto fail;
}
- if (connect(fd, af == AF_INET ? (struct sockaddr*) &sa4 : (struct sockaddr*) &sa6, af == AF_INET ? sizeof(sa4) : sizeof(sa6)) < 0) {
+ if (connect(fd, af == AF_INET ? (struct sockaddr*) &sa4 : (struct sockaddr*) &sa6, (socklen_t) (af == AF_INET ? sizeof(sa4) : sizeof(sa6))) < 0) {
pa_log("connect() failed: %s", pa_cstrerror(errno));
goto fail;
}
@@ -267,7 +277,7 @@ int pa__init(pa_module*m) {
goto fail;
}
- if (connect(sap_fd, af == AF_INET ? (struct sockaddr*) &sap_sa4 : (struct sockaddr*) &sap_sa6, af == AF_INET ? sizeof(sap_sa4) : sizeof(sap_sa6)) < 0) {
+ if (connect(sap_fd, af == AF_INET ? (struct sockaddr*) &sap_sa4 : (struct sockaddr*) &sap_sa6, (socklen_t) (af == AF_INET ? sizeof(sap_sa4) : sizeof(sap_sa6))) < 0) {
pa_log("connect() failed: %s", pa_cstrerror(errno));
goto fail;
}
@@ -279,6 +289,15 @@ int pa__init(pa_module*m) {
goto fail;
}
+ if (ttl != DEFAULT_TTL) {
+ int _ttl = (int) ttl;
+
+ if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &_ttl, sizeof(_ttl)) < 0) {
+ pa_log("IP_MULTICAST_TTL failed: %s", pa_cstrerror(errno));
+ goto fail;
+ }
+ }
+
/* If the socket queue is full, let's drop packets */
pa_make_fd_nonblock(fd);
pa_make_udp_socket_low_delay(fd);
@@ -290,13 +309,14 @@ int pa__init(pa_module*m) {
pa_proplist_sets(data.proplist, "rtp.destination", dest);
pa_proplist_setf(data.proplist, "rtp.mtu", "%lu", (unsigned long) mtu);
pa_proplist_setf(data.proplist, "rtp.port", "%lu", (unsigned long) port);
+ pa_proplist_setf(data.proplist, "rtp.ttl", "%lu", (unsigned long) ttl);
data.driver = __FILE__;
data.module = m;
data.source = s;
pa_source_output_new_data_set_sample_spec(&data, &ss);
pa_source_output_new_data_set_channel_map(&data, &cm);
- o = pa_source_output_new(m->core, &data, 0);
+ o = pa_source_output_new(m->core, &data, PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND);
pa_source_output_new_data_done(&data);
if (!o) {
@@ -335,14 +355,14 @@ int pa__init(pa_module*m) {
p = pa_sdp_build(af,
af == AF_INET ? (void*) &((struct sockaddr_in*) &sa_dst)->sin_addr : (void*) &((struct sockaddr_in6*) &sa_dst)->sin6_addr,
af == AF_INET ? (void*) &sa4.sin_addr : (void*) &sa6.sin6_addr,
- n, port, payload, &ss);
+ n, (uint16_t) port, payload, &ss);
pa_xfree(n);
pa_rtp_context_init_send(&u->rtp_context, fd, m->core->cookie, payload, pa_frame_size(&ss));
pa_sap_context_init_send(&u->sap_context, sap_fd, p);
- pa_log_info("RTP stream initialized with mtu %u on %s:%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, u->rtp_context.ssrc, payload, u->rtp_context.sequence);
+ pa_log_info("RTP stream initialized with mtu %u on %s:%u ttl=%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, ttl, u->rtp_context.ssrc, payload, u->rtp_context.sequence);
pa_log_info("SDP-Data:\n%s\nEOF", p);
pa_sap_send(&u->sap_context, 0);
diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c
index 5a33ebc2..88351010 100644
--- a/src/modules/rtp/rtp.c
+++ b/src/modules/rtp/rtp.c
@@ -50,7 +50,7 @@ pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssr
c->sequence = (uint16_t) (rand()*rand());
c->timestamp = 0;
c->ssrc = ssrc ? ssrc : (uint32_t) (rand()*rand());
- c->payload = payload & 127;
+ c->payload = (uint8_t) (payload & 127U);
c->frame_size = frame_size;
pa_memchunk_reset(&c->memchunk);
@@ -99,7 +99,8 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
if (r < 0 || n >= size || iov_idx >= MAX_IOVECS) {
uint32_t header[3];
struct msghdr m;
- int k, i;
+ ssize_t k;
+ int i;
if (n > 0) {
header[0] = htonl(((uint32_t) 2 << 30) | ((uint32_t) c->payload << 16) | ((uint32_t) c->sequence));
@@ -112,7 +113,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
m.msg_name = NULL;
m.msg_namelen = 0;
m.msg_iov = iov;
- m.msg_iovlen = iov_idx;
+ m.msg_iovlen = (size_t) iov_idx;
m.msg_control = NULL;
m.msg_controllen = 0;
m.msg_flags = 0;
@@ -128,7 +129,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
} else
k = 0;
- c->timestamp += n/c->frame_size;
+ c->timestamp += (unsigned) (n/c->frame_size);
if (k < 0) {
if (errno != EAGAIN && errno != EINTR) /* If the queue is full, just ignore it */
@@ -162,7 +163,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
struct msghdr m;
struct iovec iov;
uint32_t header;
- int cc;
+ unsigned cc;
ssize_t r;
pa_assert(c);
@@ -197,7 +198,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
chunk->index = c->memchunk.index;
iov.iov_base = (uint8_t*) pa_memblock_acquire(chunk->memblock) + chunk->index;
- iov.iov_len = size;
+ iov.iov_len = (size_t) size;
m.msg_name = NULL;
m.msg_namelen = 0;
@@ -246,16 +247,16 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
}
cc = (header >> 24) & 0xF;
- c->payload = (header >> 16) & 127;
- c->sequence = header & 0xFFFF;
+ c->payload = (uint8_t) ((header >> 16) & 127U);
+ c->sequence = (uint16_t) (header & 0xFFFFU);
- if (12 + cc*4 > size) {
+ if (12 + cc*4 > (unsigned) size) {
pa_log_warn("RTP packet too short. (CSRC)");
goto fail;
}
chunk->index += 12 + cc*4;
- chunk->length = size - 12 + cc*4;
+ chunk->length = (size_t) size - 12 + cc*4;
if (chunk->length % c->frame_size != 0) {
pa_log_warn("Bad RTP packet size.");
diff --git a/src/modules/rtp/rtsp_client.c b/src/modules/rtp/rtsp_client.c
new file mode 100644
index 00000000..9eb3d964
--- /dev/null
+++ b/src/modules/rtp/rtsp_client.c
@@ -0,0 +1,542 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2008 Colin Guthrie
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
+#include <pulse/xmalloc.h>
+
+#include <pulsecore/core-error.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/socket-util.h>
+#include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/strbuf.h>
+#include <pulsecore/poll.h>
+#include <pulsecore/ioline.h>
+
+#include "rtsp_client.h"
+
+struct pa_rtsp_client {
+ pa_mainloop_api *mainloop;
+ char *hostname;
+ uint16_t port;
+
+ pa_socket_client *sc;
+ pa_iochannel *io;
+ pa_ioline *ioline;
+
+ pa_rtsp_cb_t callback;
+
+ void *userdata;
+ const char *useragent;
+
+ pa_rtsp_state state;
+ uint8_t waiting;
+
+ pa_headerlist* headers;
+ char *last_header;
+ pa_strbuf *header_buffer;
+ pa_headerlist* response_headers;
+
+ char *localip;
+ char *url;
+ uint16_t rtp_port;
+ uint32_t cseq;
+ char *session;
+ char *transport;
+};
+
+pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char* hostname, uint16_t port, const char* useragent) {
+ pa_rtsp_client *c;
+
+ pa_assert(mainloop);
+ pa_assert(hostname);
+ pa_assert(port > 0);
+
+ c = pa_xnew0(pa_rtsp_client, 1);
+ c->mainloop = mainloop;
+ c->hostname = pa_xstrdup(hostname);
+ c->port = port;
+ c->headers = pa_headerlist_new();
+
+ if (useragent)
+ c->useragent = useragent;
+ else
+ c->useragent = "PulseAudio RTSP Client";
+
+ return c;
+}
+
+
+void pa_rtsp_client_free(pa_rtsp_client* c) {
+ if (c) {
+ if (c->sc)
+ pa_socket_client_unref(c->sc);
+ if (c->ioline)
+ pa_ioline_close(c->ioline);
+ else if (c->io)
+ pa_iochannel_free(c->io);
+
+ pa_xfree(c->hostname);
+ pa_xfree(c->url);
+ pa_xfree(c->localip);
+ pa_xfree(c->session);
+ pa_xfree(c->transport);
+ pa_xfree(c->last_header);
+ if (c->header_buffer)
+ pa_strbuf_free(c->header_buffer);
+ if (c->response_headers)
+ pa_headerlist_free(c->response_headers);
+ pa_headerlist_free(c->headers);
+ }
+ pa_xfree(c);
+}
+
+
+static void headers_read(pa_rtsp_client *c) {
+ char* token;
+ char delimiters[] = ";";
+
+ pa_assert(c);
+ pa_assert(c->response_headers);
+ pa_assert(c->callback);
+
+ /* Deal with a SETUP response */
+ if (STATE_SETUP == c->state) {
+ const char* token_state = NULL;
+ const char* pc = NULL;
+ c->session = pa_xstrdup(pa_headerlist_gets(c->response_headers, "Session"));
+ c->transport = pa_xstrdup(pa_headerlist_gets(c->response_headers, "Transport"));
+
+ if (!c->session || !c->transport) {
+ pa_headerlist_free(c->response_headers);
+ c->response_headers = NULL;
+ pa_log("Invalid SETUP response.");
+ return;
+ }
+
+ /* Now parse out the server port component of the response. */
+ while ((token = pa_split(c->transport, delimiters, &token_state))) {
+ if ((pc = strstr(token, "="))) {
+ if (0 == strncmp(token, "server_port", 11)) {
+ pa_atou(pc+1, (uint32_t*)(&c->rtp_port));
+ pa_xfree(token);
+ break;
+ }
+ }
+ pa_xfree(token);
+ }
+ if (0 == c->rtp_port) {
+ /* Error no server_port in response */
+ pa_headerlist_free(c->response_headers);
+ c->response_headers = NULL;
+ pa_log("Invalid SETUP response (no port number).");
+ return;
+ }
+ }
+
+ /* Call our callback */
+ c->callback(c, c->state, c->response_headers, c->userdata);
+
+ pa_headerlist_free(c->response_headers);
+ c->response_headers = NULL;
+}
+
+
+static void line_callback(pa_ioline *line, const char *s, void *userdata) {
+ char *delimpos;
+ char *s2, *s2p;
+
+ pa_rtsp_client *c = userdata;
+ pa_assert(line);
+ pa_assert(c);
+ pa_assert(c->callback);
+
+ if (!s) {
+ /* Keep the ioline/iochannel open as they will be freed automatically */
+ c->ioline = NULL;
+ c->io = NULL;
+ c->callback(c, STATE_DISCONNECTED, NULL, c->userdata);
+ return;
+ }
+
+ s2 = pa_xstrdup(s);
+ /* Trim trailing carriage returns */
+ s2p = s2 + strlen(s2) - 1;
+ while (s2p >= s2 && '\r' == *s2p) {
+ *s2p = '\0';
+ s2p -= 1;
+ }
+ if (c->waiting && 0 == strcmp("RTSP/1.0 200 OK", s2)) {
+ c->waiting = 0;
+ pa_assert(!c->response_headers);
+ c->response_headers = pa_headerlist_new();
+ goto exit;
+ }
+ if (c->waiting) {
+ pa_log_warn("Unexpected response: %s", s2);
+ goto exit;;
+ }
+ if (!strlen(s2)) {
+ /* End of headers */
+ /* We will have a header left from our looping itteration, so add it in :) */
+ if (c->last_header) {
+ /* This is not a continuation header so let's dump it into our proplist */
+ pa_headerlist_puts(c->response_headers, c->last_header, pa_strbuf_tostring_free(c->header_buffer));
+ pa_xfree(c->last_header);
+ c->last_header = NULL;
+ c->header_buffer= NULL;
+ }
+
+ pa_log_debug("Full response received. Dispatching");
+ headers_read(c);
+ c->waiting = 1;
+ goto exit;
+ }
+
+ /* Read and parse a header (we know it's not empty) */
+ /* TODO: Move header reading into the headerlist. */
+
+ /* If the first character is a space, it's a continuation header */
+ if (c->last_header && ' ' == s2[0]) {
+ pa_assert(c->header_buffer);
+
+ /* Add this line to the buffer (sans the space. */
+ pa_strbuf_puts(c->header_buffer, &(s2[1]));
+ goto exit;
+ }
+
+ if (c->last_header) {
+ /* This is not a continuation header so let's dump the full
+ header/value into our proplist */
+ pa_headerlist_puts(c->response_headers, c->last_header, pa_strbuf_tostring_free(c->header_buffer));
+ pa_xfree(c->last_header);
+ c->last_header = NULL;
+ c->header_buffer = NULL;
+ }
+
+ delimpos = strstr(s2, ":");
+ if (!delimpos) {
+ pa_log_warn("Unexpected response when expecting header: %s", s);
+ goto exit;
+ }
+
+ pa_assert(!c->header_buffer);
+ pa_assert(!c->last_header);
+
+ c->header_buffer = pa_strbuf_new();
+ if (strlen(delimpos) > 1) {
+ /* Cut our line off so we can copy the header name out */
+ *delimpos++ = '\0';
+
+ /* Trim the front of any spaces */
+ while (' ' == *delimpos)
+ ++delimpos;
+
+ pa_strbuf_puts(c->header_buffer, delimpos);
+ } else {
+ /* Cut our line off so we can copy the header name out */
+ *delimpos = '\0';
+ }
+
+ /* Save the header name */
+ c->last_header = pa_xstrdup(s2);
+ exit:
+ pa_xfree(s2);
+}
+
+
+static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata) {
+ pa_rtsp_client *c = userdata;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ } sa;
+ socklen_t sa_len = sizeof(sa);
+
+ pa_assert(sc);
+ pa_assert(c);
+ pa_assert(STATE_CONNECT == c->state);
+ pa_assert(c->sc == sc);
+ pa_socket_client_unref(c->sc);
+ c->sc = NULL;
+
+ if (!io) {
+ pa_log("Connection failed: %s", pa_cstrerror(errno));
+ return;
+ }
+ pa_assert(!c->io);
+ c->io = io;
+
+ c->ioline = pa_ioline_new(io);
+ pa_ioline_set_callback(c->ioline, line_callback, c);
+
+ /* Get the local IP address for use externally */
+ if (0 == getsockname(pa_iochannel_get_recv_fd(io), &sa.sa, &sa_len)) {
+ char buf[INET6_ADDRSTRLEN];
+ const char *res = NULL;
+
+ if (AF_INET == sa.sa.sa_family) {
+ if ((res = inet_ntop(sa.sa.sa_family, &sa.in.sin_addr, buf, sizeof(buf)))) {
+ c->localip = pa_xstrdup(res);
+ }
+ } else if (AF_INET6 == sa.sa.sa_family) {
+ if ((res = inet_ntop(AF_INET6, &sa.in6.sin6_addr, buf, sizeof(buf)))) {
+ c->localip = pa_sprintf_malloc("[%s]", res);
+ }
+ }
+ }
+ pa_log_debug("Established RTSP connection from local ip %s", c->localip);
+
+ if (c->callback)
+ c->callback(c, c->state, NULL, c->userdata);
+}
+
+int pa_rtsp_connect(pa_rtsp_client *c) {
+ pa_assert(c);
+ pa_assert(!c->sc);
+
+ pa_xfree(c->session);
+ c->session = NULL;
+
+ if (!(c->sc = pa_socket_client_new_string(c->mainloop, c->hostname, c->port))) {
+ pa_log("failed to connect to server '%s:%d'", c->hostname, c->port);
+ return -1;
+ }
+
+ pa_socket_client_set_callback(c->sc, on_connection, c);
+ c->waiting = 1;
+ c->state = STATE_CONNECT;
+ return 0;
+}
+
+void pa_rtsp_set_callback(pa_rtsp_client *c, pa_rtsp_cb_t callback, void *userdata) {
+ pa_assert(c);
+
+ c->callback = callback;
+ c->userdata = userdata;
+}
+
+void pa_rtsp_disconnect(pa_rtsp_client *c) {
+ pa_assert(c);
+
+ if (c->io)
+ pa_iochannel_free(c->io);
+ c->io = NULL;
+}
+
+
+const char* pa_rtsp_localip(pa_rtsp_client* c) {
+ pa_assert(c);
+
+ return c->localip;
+}
+
+uint32_t pa_rtsp_serverport(pa_rtsp_client* c) {
+ pa_assert(c);
+
+ return c->rtp_port;
+}
+
+void pa_rtsp_set_url(pa_rtsp_client* c, const char* url) {
+ pa_assert(c);
+
+ c->url = pa_xstrdup(url);
+}
+
+void pa_rtsp_add_header(pa_rtsp_client *c, const char* key, const char* value)
+{
+ pa_assert(c);
+ pa_assert(key);
+ pa_assert(value);
+
+ pa_headerlist_puts(c->headers, key, value);
+}
+
+void pa_rtsp_remove_header(pa_rtsp_client *c, const char* key)
+{
+ pa_assert(c);
+ pa_assert(key);
+
+ pa_headerlist_remove(c->headers, key);
+}
+
+static int rtsp_exec(pa_rtsp_client* c, const char* cmd,
+ const char* content_type, const char* content,
+ int expect_response,
+ pa_headerlist* headers) {
+ pa_strbuf* buf;
+ char* hdrs;
+ ssize_t l;
+
+ pa_assert(c);
+ pa_assert(c->url);
+
+ if (!cmd)
+ return -1;
+
+ pa_log_debug("Sending command: %s", cmd);
+
+ buf = pa_strbuf_new();
+ pa_strbuf_printf(buf, "%s %s RTSP/1.0\r\nCSeq: %d\r\n", cmd, c->url, ++c->cseq);
+ if (c->session)
+ pa_strbuf_printf(buf, "Session: %s\r\n", c->session);
+
+ /* Add the headers */
+ if (headers) {
+ hdrs = pa_headerlist_to_string(headers);
+ pa_strbuf_puts(buf, hdrs);
+ pa_xfree(hdrs);
+ }
+
+ if (content_type && content) {
+ pa_strbuf_printf(buf, "Content-Type: %s\r\nContent-Length: %d\r\n",
+ content_type, (int)strlen(content));
+ }
+
+ pa_strbuf_printf(buf, "User-Agent: %s\r\n", c->useragent);
+
+ if (c->headers) {
+ hdrs = pa_headerlist_to_string(c->headers);
+ pa_strbuf_puts(buf, hdrs);
+ pa_xfree(hdrs);
+ }
+
+ pa_strbuf_puts(buf, "\r\n");
+
+ if (content_type && content) {
+ pa_strbuf_puts(buf, content);
+ }
+
+ /* Our packet is created... now we can send it :) */
+ hdrs = pa_strbuf_tostring_free(buf);
+ /*pa_log_debug("Submitting request:");
+ pa_log_debug(hdrs);*/
+ l = pa_iochannel_write(c->io, hdrs, strlen(hdrs));
+ pa_xfree(hdrs);
+
+ return 0;
+}
+
+
+int pa_rtsp_announce(pa_rtsp_client *c, const char* sdp) {
+ pa_assert(c);
+ if (!sdp)
+ return -1;
+
+ c->state = STATE_ANNOUNCE;
+ return rtsp_exec(c, "ANNOUNCE", "application/sdp", sdp, 1, NULL);
+}
+
+
+int pa_rtsp_setup(pa_rtsp_client* c) {
+ pa_headerlist* headers;
+ int rv;
+
+ pa_assert(c);
+
+ headers = pa_headerlist_new();
+ pa_headerlist_puts(headers, "Transport", "RTP/AVP/TCP;unicast;interleaved=0-1;mode=record");
+
+ c->state = STATE_SETUP;
+ rv = rtsp_exec(c, "SETUP", NULL, NULL, 1, headers);
+ pa_headerlist_free(headers);
+ return rv;
+}
+
+
+int pa_rtsp_record(pa_rtsp_client* c, uint16_t* seq, uint32_t* rtptime) {
+ pa_headerlist* headers;
+ int rv;
+ char *info;
+
+ pa_assert(c);
+ if (!c->session) {
+ /* No seesion in progres */
+ return -1;
+ }
+
+ /* Todo: Generate these values randomly as per spec */
+ *seq = *rtptime = 0;
+
+ headers = pa_headerlist_new();
+ pa_headerlist_puts(headers, "Range", "npt=0-");
+ info = pa_sprintf_malloc("seq=%u;rtptime=%u", *seq, *rtptime);
+ pa_headerlist_puts(headers, "RTP-Info", info);
+ pa_xfree(info);
+
+ c->state = STATE_RECORD;
+ rv = rtsp_exec(c, "RECORD", NULL, NULL, 1, headers);
+ pa_headerlist_free(headers);
+ return rv;
+}
+
+
+int pa_rtsp_teardown(pa_rtsp_client *c) {
+ pa_assert(c);
+
+ c->state = STATE_TEARDOWN;
+ return rtsp_exec(c, "TEARDOWN", NULL, NULL, 0, NULL);
+}
+
+
+int pa_rtsp_setparameter(pa_rtsp_client *c, const char* param) {
+ pa_assert(c);
+ if (!param)
+ return -1;
+
+ c->state = STATE_SET_PARAMETER;
+ return rtsp_exec(c, "SET_PARAMETER", "text/parameters", param, 1, NULL);
+}
+
+
+int pa_rtsp_flush(pa_rtsp_client *c, uint16_t seq, uint32_t rtptime) {
+ pa_headerlist* headers;
+ int rv;
+ char *info;
+
+ pa_assert(c);
+
+ headers = pa_headerlist_new();
+ info = pa_sprintf_malloc("seq=%u;rtptime=%u", seq, rtptime);
+ pa_headerlist_puts(headers, "RTP-Info", info);
+ pa_xfree(info);
+
+ c->state = STATE_FLUSH;
+ rv = rtsp_exec(c, "FLUSH", NULL, NULL, 1, headers);
+ pa_headerlist_free(headers);
+ return rv;
+}
diff --git a/src/modules/rtp/rtsp_client.h b/src/modules/rtp/rtsp_client.h
new file mode 100644
index 00000000..88fb3839
--- /dev/null
+++ b/src/modules/rtp/rtsp_client.h
@@ -0,0 +1,73 @@
+#ifndef foortspclienthfoo
+#define foortspclienthfoo
+
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2008 Colin Guthrie
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <inttypes.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netdb.h>
+
+#include <pulsecore/memblockq.h>
+#include <pulsecore/memchunk.h>
+#include <pulsecore/socket-client.h>
+#include <pulse/mainloop-api.h>
+
+#include "headerlist.h"
+
+typedef struct pa_rtsp_client pa_rtsp_client;
+typedef enum {
+ STATE_CONNECT,
+ STATE_ANNOUNCE,
+ STATE_SETUP,
+ STATE_RECORD,
+ STATE_FLUSH,
+ STATE_TEARDOWN,
+ STATE_SET_PARAMETER,
+ STATE_DISCONNECTED
+} pa_rtsp_state;
+typedef void (*pa_rtsp_cb_t)(pa_rtsp_client *c, pa_rtsp_state state, pa_headerlist* hl, void *userdata);
+
+pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char* hostname, uint16_t port, const char* useragent);
+void pa_rtsp_client_free(pa_rtsp_client* c);
+
+int pa_rtsp_connect(pa_rtsp_client* c);
+void pa_rtsp_set_callback(pa_rtsp_client *c, pa_rtsp_cb_t callback, void *userdata);
+
+void pa_rtsp_disconnect(pa_rtsp_client* c);
+
+const char* pa_rtsp_localip(pa_rtsp_client* c);
+uint32_t pa_rtsp_serverport(pa_rtsp_client* c);
+void pa_rtsp_set_url(pa_rtsp_client* c, const char* url);
+void pa_rtsp_add_header(pa_rtsp_client *c, const char* key, const char* value);
+void pa_rtsp_remove_header(pa_rtsp_client *c, const char* key);
+
+int pa_rtsp_announce(pa_rtsp_client* c, const char* sdp);
+
+int pa_rtsp_setup(pa_rtsp_client* c);
+int pa_rtsp_record(pa_rtsp_client* c, uint16_t* seq, uint32_t* rtptime);
+int pa_rtsp_teardown(pa_rtsp_client* c);
+
+int pa_rtsp_setparameter(pa_rtsp_client* c, const char* param);
+int pa_rtsp_flush(pa_rtsp_client* c, uint16_t seq, uint32_t rtptime);
+
+#endif
diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c
index 5d9b58fa..b0c95aa5 100644
--- a/src/modules/rtp/sap.c
+++ b/src/modules/rtp/sap.c
@@ -76,7 +76,7 @@ int pa_sap_send(pa_sap_context *c, pa_bool_t goodbye) {
socklen_t salen = sizeof(sa_buf);
struct iovec iov[4];
struct msghdr m;
- int k;
+ ssize_t k;
if (getsockname(c->fd, sa, &salen) < 0) {
pa_log("getsockname() failed: %s\n", pa_cstrerror(errno));
@@ -94,7 +94,7 @@ int pa_sap_send(pa_sap_context *c, pa_bool_t goodbye) {
iov[0].iov_len = sizeof(header);
iov[1].iov_base = sa->sa_family == AF_INET ? (void*) &((struct sockaddr_in*) sa)->sin_addr : (void*) &((struct sockaddr_in6*) sa)->sin6_addr;
- iov[1].iov_len = sa->sa_family == AF_INET ? 4 : 16;
+ iov[1].iov_len = sa->sa_family == AF_INET ? 4U : 16U;
iov[2].iov_base = (char*) MIME_TYPE;
iov[2].iov_len = sizeof(MIME_TYPE);
@@ -113,7 +113,7 @@ int pa_sap_send(pa_sap_context *c, pa_bool_t goodbye) {
if ((k = sendmsg(c->fd, &m, MSG_DONTWAIT)) < 0)
pa_log_warn("sendmsg() failed: %s\n", pa_cstrerror(errno));
- return k;
+ return (int) k;
}
pa_sap_context* pa_sap_context_init_recv(pa_sap_context *c, int fd) {
@@ -128,10 +128,10 @@ pa_sap_context* pa_sap_context_init_recv(pa_sap_context *c, int fd) {
int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye) {
struct msghdr m;
struct iovec iov;
- int size, k;
+ int size;
char *buf = NULL, *e;
uint32_t header;
- int six, ac;
+ unsigned six, ac, k;
ssize_t r;
pa_assert(c);
@@ -142,11 +142,11 @@ int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye) {
goto fail;
}
- buf = pa_xnew(char, size+1);
+ buf = pa_xnew(char, (unsigned) size+1);
buf[size] = 0;
iov.iov_base = buf;
- iov.iov_len = size;
+ iov.iov_len = (size_t) size;
m.msg_name = NULL;
m.msg_namelen = 0;
@@ -184,21 +184,21 @@ int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye) {
goto fail;
}
- six = (header >> 28) & 1;
- ac = (header >> 16) & 0xFF;
+ six = (header >> 28) & 1U;
+ ac = (header >> 16) & 0xFFU;
- k = 4 + (six ? 16 : 4) + ac*4;
- if (size < k) {
+ k = 4 + (six ? 16U : 4U) + ac*4U;
+ if ((unsigned) size < k) {
pa_log_warn("SAP packet too short (AD).");
goto fail;
}
e = buf + k;
- size -= k;
+ size -= (int) k;
if ((unsigned) size >= sizeof(MIME_TYPE) && !strcmp(e, MIME_TYPE)) {
e += sizeof(MIME_TYPE);
- size -= sizeof(MIME_TYPE);
+ size -= (int) sizeof(MIME_TYPE);
} else if ((unsigned) size < sizeof(PA_SDP_HEADER)-1 || strncmp(e, PA_SDP_HEADER, sizeof(PA_SDP_HEADER)-1)) {
pa_log_warn("Invalid SDP header.");
goto fail;
@@ -207,7 +207,7 @@ int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye) {
if (c->sdp_data)
pa_xfree(c->sdp_data);
- c->sdp_data = pa_xstrndup(e, size);
+ c->sdp_data = pa_xstrndup(e, (unsigned) size);
pa_xfree(buf);
*goodbye = !!((header >> 26) & 1);
diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c
index cef90433..59989e1a 100644
--- a/src/modules/rtp/sdp.c
+++ b/src/modules/rtp/sdp.c
@@ -55,7 +55,7 @@ char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, u
if (!(u = pa_get_user_name(un, sizeof(un))))
u = "-";
- ntp = time(NULL) + 2208988800U;
+ ntp = (uint32_t) time(NULL) + 2208988800U;
pa_assert_se(a = inet_ntop(af, src, buf_src, sizeof(buf_src)));
pa_assert_se(a = inet_ntop(af, dst, buf_dst, sizeof(buf_dst)));
@@ -99,10 +99,10 @@ static pa_sample_spec *parse_sdp_sample_spec(pa_sample_spec *ss, char *c) {
return NULL;
if (sscanf(c, "%u/%u", &rate, &channels) == 2) {
- ss->rate = rate;
- ss->channels = channels;
+ ss->rate = (uint32_t) rate;
+ ss->channels = (uint8_t) channels;
} else if (sscanf(c, "%u", &rate) == 2) {
- ss->rate = rate;
+ ss->rate = (uint32_t) rate;
ss->channels = 1;
} else
return NULL;