mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-21 06:59:59 -05:00
rtp: Hide RTP implementation details from module-rtp-*
This moves RTP implementation-specific information out of module-rtp-send/recv. This is basically done by making the pa_rtp_context structure opaque from the perspective of these modules. We can then potentially replace the underlying RTP implementation with something else transparently. One RTP detail that does "leak" is the RTP timestamp. We provide this to module-rtp-recv so that it can perform rate adjustments to match the sender rate. Signed-off-by: Arun Raghavan <arun@arunraghavan.net>
This commit is contained in:
parent
0548cdc6d6
commit
d15291bbbb
4 changed files with 94 additions and 61 deletions
|
|
@ -40,13 +40,31 @@
|
|||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/arpa-inet.h>
|
||||
#include <pulsecore/poll.h>
|
||||
|
||||
#include "rtp.h"
|
||||
|
||||
int pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint8_t payload, size_t mtu, size_t frame_size) {
|
||||
pa_assert(c);
|
||||
typedef struct pa_rtp_context {
|
||||
int fd;
|
||||
uint16_t sequence;
|
||||
uint32_t timestamp;
|
||||
uint32_t ssrc;
|
||||
uint8_t payload;
|
||||
size_t frame_size;
|
||||
size_t mtu;
|
||||
|
||||
uint8_t *recv_buf;
|
||||
size_t recv_buf_size;
|
||||
pa_memchunk memchunk;
|
||||
} pa_rtp_context;
|
||||
|
||||
pa_rtp_context* pa_rtp_context_new_send(int fd, uint8_t payload, size_t mtu, size_t frame_size) {
|
||||
pa_rtp_context *c;
|
||||
|
||||
pa_assert(fd >= 0);
|
||||
|
||||
c = pa_xnew0(pa_rtp_context, 1);
|
||||
|
||||
c->fd = fd;
|
||||
c->sequence = (uint16_t) (rand()*rand());
|
||||
c->timestamp = 0;
|
||||
|
|
@ -59,7 +77,7 @@ int pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint8_t payload, size_t
|
|||
c->recv_buf_size = 0;
|
||||
pa_memchunk_reset(&c->memchunk);
|
||||
|
||||
return 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
#define MAX_IOVECS 16
|
||||
|
|
@ -151,19 +169,23 @@ int pa_rtp_send(pa_rtp_context *c, pa_memblockq *q) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame_size) {
|
||||
pa_assert(c);
|
||||
pa_rtp_context* pa_rtp_context_new_recv(int fd, uint8_t payload, size_t frame_size) {
|
||||
pa_rtp_context *c;
|
||||
|
||||
c = pa_xnew0(pa_rtp_context, 1);
|
||||
|
||||
c->fd = fd;
|
||||
c->payload = payload;
|
||||
c->frame_size = frame_size;
|
||||
|
||||
c->recv_buf_size = 2000;
|
||||
c->recv_buf = pa_xmalloc(c->recv_buf_size);
|
||||
pa_memchunk_reset(&c->memchunk);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, struct timeval *tstamp) {
|
||||
int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, uint32_t *rtp_tstamp, struct timeval *tstamp) {
|
||||
int size;
|
||||
size_t audio_length;
|
||||
size_t metadata_length;
|
||||
|
|
@ -171,6 +193,8 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, struct
|
|||
struct cmsghdr *cm;
|
||||
struct iovec iov;
|
||||
uint32_t header;
|
||||
uint32_t ssrc;
|
||||
uint8_t payload;
|
||||
unsigned cc;
|
||||
ssize_t r;
|
||||
uint8_t aux[1024];
|
||||
|
|
@ -246,12 +270,12 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, struct
|
|||
}
|
||||
|
||||
memcpy(&header, iov.iov_base, sizeof(uint32_t));
|
||||
memcpy(&c->timestamp, (uint8_t*) iov.iov_base + 4, sizeof(uint32_t));
|
||||
memcpy(&c->ssrc, (uint8_t*) iov.iov_base + 8, sizeof(uint32_t));
|
||||
memcpy(rtp_tstamp, (uint8_t*) iov.iov_base + 4, sizeof(uint32_t));
|
||||
memcpy(&ssrc, (uint8_t*) iov.iov_base + 8, sizeof(uint32_t));
|
||||
|
||||
header = ntohl(header);
|
||||
c->timestamp = ntohl(c->timestamp);
|
||||
c->ssrc = ntohl(c->ssrc);
|
||||
*rtp_tstamp = ntohl(*rtp_tstamp);
|
||||
ssrc = ntohl(c->ssrc);
|
||||
|
||||
if ((header >> 30) != 2) {
|
||||
pa_log_warn("Unsupported RTP version.");
|
||||
|
|
@ -268,12 +292,22 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, struct
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (ssrc != c->ssrc) {
|
||||
pa_log_debug("Got unexpected SSRC");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cc = (header >> 24) & 0xF;
|
||||
c->payload = (uint8_t) ((header >> 16) & 127U);
|
||||
payload = (uint8_t) ((header >> 16) & 127U);
|
||||
c->sequence = (uint16_t) (header & 0xFFFFU);
|
||||
|
||||
metadata_length = 12 + cc * 4;
|
||||
|
||||
if (payload != c->payload) {
|
||||
pa_log_debug("Got unexpected payload: %u", payload);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (metadata_length > (unsigned) size) {
|
||||
pa_log_warn("RTP packet too short. (CSRC)");
|
||||
goto fail;
|
||||
|
|
@ -388,7 +422,7 @@ int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) {
|
|||
return ss->format == PA_SAMPLE_S16BE;
|
||||
}
|
||||
|
||||
void pa_rtp_context_destroy(pa_rtp_context *c) {
|
||||
void pa_rtp_context_free(pa_rtp_context *c) {
|
||||
pa_assert(c);
|
||||
|
||||
pa_assert_se(pa_close(c->fd) == 0);
|
||||
|
|
@ -397,8 +431,7 @@ void pa_rtp_context_destroy(pa_rtp_context *c) {
|
|||
pa_memblock_unref(c->memchunk.memblock);
|
||||
|
||||
pa_xfree(c->recv_buf);
|
||||
c->recv_buf = NULL;
|
||||
c->recv_buf_size = 0;
|
||||
pa_xfree(c);
|
||||
}
|
||||
|
||||
const char* pa_rtp_format_to_string(pa_sample_format_t f) {
|
||||
|
|
@ -418,3 +451,21 @@ pa_sample_format_t pa_rtp_string_to_format(const char *s) {
|
|||
else
|
||||
return PA_SAMPLE_INVALID;
|
||||
}
|
||||
|
||||
size_t pa_rtp_context_get_frame_size(pa_rtp_context *c) {
|
||||
return c->frame_size;
|
||||
}
|
||||
|
||||
pa_rtpoll_item* pa_rtp_context_get_rtpoll_item(pa_rtp_context *c, pa_rtpoll *rtpoll) {
|
||||
pa_rtpoll_item *item;
|
||||
struct pollfd *p;
|
||||
|
||||
item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_LATE, 1);
|
||||
|
||||
p = pa_rtpoll_item_get_pollfd(item, NULL);
|
||||
p->fd = c->fd;
|
||||
p->events = POLLIN;
|
||||
p->revents = 0;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue