summaryrefslogtreecommitdiffstats
path: root/src/modules/rtp/rtp.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2006-04-16 00:16:53 +0000
committerLennart Poettering <lennart@poettering.net>2006-04-16 00:16:53 +0000
commitf1ddf052368ad96cf157297a50ffe52ee8f7ca39 (patch)
treedad94d135aeaa6b78adecbf208ffc0ef03a59acb /src/modules/rtp/rtp.c
parent1fec416db7db4ba8d2d2dd250187939f0b06dbd7 (diff)
* add RTP/SAP/SDP reciever module
* use server cookie as RTP SSRC * enable SVN keywords * add new option "loop" for RTP sender module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@716 fefdeb5f-60dc-0310-8127-8f9354f1896f
Diffstat (limited to 'src/modules/rtp/rtp.c')
-rw-r--r--src/modules/rtp/rtp.c162
1 files changed, 158 insertions, 4 deletions
diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c
index a3bce38b..ccd3b6c3 100644
--- a/src/modules/rtp/rtp.c
+++ b/src/modules/rtp/rtp.c
@@ -30,6 +30,7 @@
#include <errno.h>
#include <arpa/inet.h>
#include <unistd.h>
+#include <sys/ioctl.h>
#include <polypcore/log.h>
@@ -135,27 +136,114 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
return 0;
}
-pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd) {
+pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame_size) {
assert(c);
c->fd = fd;
+ c->frame_size = frame_size;
return c;
}
-int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk) {
+int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_memblock_stat *st) {
+ int size;
+ struct msghdr m;
+ struct iovec iov;
+ uint32_t header;
+ int cc;
+ ssize_t r;
+
assert(c);
assert(chunk);
+ chunk->memblock = NULL;
+
+ if (ioctl(c->fd, FIONREAD, &size) < 0) {
+ pa_log(__FILE__": FIONREAD failed: %s", strerror(errno));
+ goto fail;
+ }
+
+ if (!size)
+ return 0;
+
+ chunk->memblock = pa_memblock_new(size, st);
+
+ iov.iov_base = chunk->memblock->data;
+ iov.iov_len = size;
+
+ m.msg_name = NULL;
+ m.msg_namelen = 0;
+ m.msg_iov = &iov;
+ m.msg_iovlen = 1;
+ m.msg_control = NULL;
+ m.msg_controllen = 0;
+ m.msg_flags = 0;
+
+ if ((r = recvmsg(c->fd, &m, 0)) != size) {
+ pa_log(__FILE__": recvmsg() failed: %s", r < 0 ? strerror(errno) : "size mismatch");
+ goto fail;
+ }
+
+ if (size < 12) {
+ pa_log(__FILE__": RTP packet too short.");
+ goto fail;
+ }
+
+ memcpy(&header, chunk->memblock->data, sizeof(uint32_t));
+ memcpy(&c->timestamp, (uint8_t*) chunk->memblock->data + 4, sizeof(uint32_t));
+ memcpy(&c->ssrc, (uint8_t*) chunk->memblock->data + 8, sizeof(uint32_t));
+
+ header = ntohl(header);
+ c->timestamp = ntohl(c->timestamp);
+ c->ssrc = ntohl(c->ssrc);
+
+ if ((header >> 30) != 2) {
+ pa_log(__FILE__": Unsupported RTP version.");
+ goto fail;
+ }
+
+ if ((header >> 29) & 1) {
+ pa_log(__FILE__": RTP padding not supported.");
+ goto fail;
+ }
+
+ if ((header >> 28) & 1) {
+ pa_log(__FILE__": RTP header extensions not supported.");
+ goto fail;
+ }
+
+ cc = (header >> 24) & 0xF;
+ c->payload = (header >> 16) & 127;
+ c->sequence = header & 0xFFFF;
+
+ if (12 + cc*4 > size) {
+ pa_log(__FILE__": RTP packet too short. (CSRC)");
+ goto fail;
+ }
+
+ chunk->index = 12 + cc*4;
+ chunk->length = size - chunk->index;
+
+ if (chunk->length % c->frame_size != 0) {
+ pa_log(__FILE__": Vad RTP packet size.");
+ goto fail;
+ }
+
return 0;
+
+fail:
+ if (chunk->memblock)
+ pa_memblock_unref(chunk->memblock);
+
+ return -1;
}
-uint8_t pa_rtp_payload_type(const pa_sample_spec *ss) {
+uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) {
assert(ss);
if (ss->format == PA_SAMPLE_ULAW && ss->rate == 8000 && ss->channels == 1)
return 0;
if (ss->format == PA_SAMPLE_ALAW && ss->rate == 8000 && ss->channels == 1)
- return 0;
+ return 8;
if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 2)
return 10;
if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 1)
@@ -164,6 +252,41 @@ uint8_t pa_rtp_payload_type(const pa_sample_spec *ss) {
return 127;
}
+pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec *ss) {
+ assert(ss);
+
+ switch (payload) {
+ case 0:
+ ss->channels = 1;
+ ss->format = PA_SAMPLE_ULAW;
+ ss->rate = 8000;
+ break;
+
+ case 8:
+ ss->channels = 1;
+ ss->format = PA_SAMPLE_ALAW;
+ ss->rate = 8000;
+ break;
+
+ case 10:
+ ss->channels = 2;
+ ss->format = PA_SAMPLE_S16BE;
+ ss->rate = 44100;
+ break;
+
+ case 11:
+ ss->channels = 1;
+ ss->format = PA_SAMPLE_S16BE;
+ ss->rate = 44100;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ return ss;
+}
+
pa_sample_spec *pa_rtp_sample_spec_fixup(pa_sample_spec * ss) {
assert(ss);
@@ -192,3 +315,34 @@ void pa_rtp_context_destroy(pa_rtp_context *c) {
close(c->fd);
}
+
+const char* pa_rtp_format_to_string(pa_sample_format_t f) {
+ switch (f) {
+ case PA_SAMPLE_S16BE:
+ return "L16";
+ case PA_SAMPLE_U8:
+ return "L8";
+ case PA_SAMPLE_ALAW:
+ return "PCMA";
+ case PA_SAMPLE_ULAW:
+ return "PCMU";
+ default:
+ return NULL;
+ }
+}
+
+pa_sample_format_t pa_rtp_string_to_format(const char *s) {
+ assert(s);
+
+ if (!(strcmp(s, "L16")))
+ return PA_SAMPLE_S16BE;
+ else if (!strcmp(s, "L8"))
+ return PA_SAMPLE_U8;
+ else if (!strcmp(s, "PCMA"))
+ return PA_SAMPLE_ALAW;
+ else if (!strcmp(s, "PCMU"))
+ return PA_SAMPLE_ULAW;
+ else
+ return PA_SAMPLE_INVALID;
+}
+