From 89c1082b3d500e20346da8149e3a668b25495f11 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Mon, 9 Jul 2018 20:09:50 +0700 Subject: [PATCH] Make RTP payload type configurable For a long time the RTP payload type was hard-coded for outgoing frames. The problem is that according to RFC 3551 only GSM FR has a static payload type value (see table 4, value 3). For other codecs the payload type may be negotiated between the both sides dynamically (i.e. in range 96-127). Let's allow a binary/API user to configure this manually. Change-Id: Ia07ed4e13b4a70c8bb4181564a8190861fd269da Closes: OS#2482 --- include/osmocom/gapk/procqueue.h | 6 ++++-- src/app_osmo_gapk.c | 37 +++++++++++++++++++++++++++++--- src/pq_rtp.c | 35 ++++++++++++++++++++---------- tests/io/pq_rtp_test.c | 4 ++-- 4 files changed, 64 insertions(+), 18 deletions(-) diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index ac9253b..82c1cf9 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -89,8 +89,10 @@ int osmo_gapk_pq_queue_file_input(struct osmo_gapk_pq *pq, FILE *src, unsigned i int osmo_gapk_pq_queue_file_output(struct osmo_gapk_pq *pq, FILE *dst, unsigned int block_len); /* RTP */ -int osmo_gapk_pq_queue_rtp_input(struct osmo_gapk_pq *pq, int rtp_fd, unsigned int block_len); -int osmo_gapk_pq_queue_rtp_output(struct osmo_gapk_pq *pq, int rtp_fd, unsigned int block_len); +int osmo_gapk_pq_queue_rtp_input(struct osmo_gapk_pq *pq, int rtp_fd, + unsigned int block_len, uint8_t pt); +int osmo_gapk_pq_queue_rtp_output(struct osmo_gapk_pq *pq, int rtp_fd, + unsigned int block_len, uint8_t pt); /* ALSA */ int osmo_gapk_pq_queue_alsa_input(struct osmo_gapk_pq *pq, const char *hwdev, unsigned int blk_len); diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c index a4b93ef..91647ee 100644 --- a/src/app_osmo_gapk.c +++ b/src/app_osmo_gapk.c @@ -64,6 +64,9 @@ struct gapk_options const char *alsa_out; const struct osmo_gapk_format_desc *fmt_out; + /* RTP payload type */ + uint8_t rtp_pt_in, rtp_pt_out; + int benchmark; int verbose; }; @@ -133,6 +136,8 @@ print_help(char *progname) #endif fprintf(stdout, " -f, --input-format=FMT\tInput format (see below)\n"); fprintf(stdout, " -g, --output-format=FMT\tOutput format (see below)\n"); + fprintf(stdout, " -p --rtp-pt-in=TYPE\t\tRTP payload type for incoming frames\n"); + fprintf(stdout, " -P --rtp-pt-out=TYPE\t\tRTP payload type for outgoing frames\n"); fprintf(stdout, " -b, --enable-benchmark\tEnable codec benchmarking\n"); fprintf(stdout, " -v, --verbose\t\t\tEnable debug messages\n"); fprintf(stdout, "\n"); @@ -203,11 +208,13 @@ parse_options(struct gapk_state *state, int argc, char *argv[]) #endif {"input-format", 1, 0, 'f'}, {"output-format", 1, 0, 'g'}, + {"rtp-pt-in", 1, 0, 'p'}, + {"rtp-pt-out", 1, 0, 'P'}, {"enable-benchmark", 0, 0, 'b'}, {"verbose", 0, 0, 'v'}, {"help", 0, 0, 'h'}, }; - const char *short_options = "i:o:I:O:f:g:bvh" + const char *short_options = "i:o:I:O:f:g:p:P:bvh" #ifdef HAVE_ALSA "a:A:" #endif @@ -218,6 +225,10 @@ parse_options(struct gapk_state *state, int argc, char *argv[]) /* Set some defaults */ memset(opt, 0x00, sizeof(*opt)); + /* Default RTP payload type (GSM FR, see RFC 3551) */ + opt->rtp_pt_in = 3; + opt->rtp_pt_out = 3; + /* Parse */ while (1) { int c, rv; @@ -279,6 +290,24 @@ parse_options(struct gapk_state *state, int argc, char *argv[]) } break; + case 'p': + rv = atoi(optarg); + if (rv < 0 || rv > 0xff) { + LOGP(DAPP, LOGL_ERROR, "Invalid RTP payload type: %d\n", rv); + return -EINVAL; + } + opt->rtp_pt_in = rv; + break; + + case 'P': + rv = atoi(optarg); + if (rv < 0 || rv > 0xff) { + LOGP(DAPP, LOGL_ERROR, "Invalid RTP payload type: %d\n", rv); + return -EINVAL; + } + opt->rtp_pt_out = rv; + break; + case 'b': opt->benchmark = 1; break; @@ -540,7 +569,8 @@ make_processing_chain(struct gapk_state *gs) if (gs->in.file.fh) osmo_gapk_pq_queue_file_input(gs->pq, gs->in.file.fh, fmt_in->frame_len); else if (gs->in.rtp.fd != -1) - osmo_gapk_pq_queue_rtp_input(gs->pq, gs->in.rtp.fd, fmt_in->frame_len); + osmo_gapk_pq_queue_rtp_input(gs->pq, gs->in.rtp.fd, + fmt_in->frame_len, gs->opts.rtp_pt_in); #ifdef HAVE_ALSA else if (gs->opts.alsa_in) osmo_gapk_pq_queue_alsa_input(gs->pq, gs->opts.alsa_in, fmt_in->frame_len); @@ -618,7 +648,8 @@ make_processing_chain(struct gapk_state *gs) if (gs->out.file.fh) osmo_gapk_pq_queue_file_output(gs->pq, gs->out.file.fh, fmt_out->frame_len); else if (gs->out.rtp.fd != -1) - osmo_gapk_pq_queue_rtp_output(gs->pq, gs->out.rtp.fd, fmt_out->frame_len); + osmo_gapk_pq_queue_rtp_output(gs->pq, gs->out.rtp.fd, + fmt_out->frame_len, gs->opts.rtp_pt_out); #ifdef HAVE_ALSA else if (gs->opts.alsa_out) osmo_gapk_pq_queue_alsa_output(gs->pq, gs->opts.alsa_out, fmt_out->frame_len); diff --git a/src/pq_rtp.c b/src/pq_rtp.c index a50013a..81eeb19 100644 --- a/src/pq_rtp.c +++ b/src/pq_rtp.c @@ -70,8 +70,6 @@ struct rtp_x_hdr { #define RTP_VERSION 2 -#define RTP_PT_GSM_FULL 3 - struct pq_state_rtp { int fd; int blk_len; @@ -193,7 +191,8 @@ pq_cb_rtp_exit(void *_state) } static int -pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len, int in_out_n) +pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, + unsigned int blk_len, int in_out_n, uint8_t pt) { struct osmo_gapk_pq_item *item; struct pq_state_rtp *state; @@ -210,12 +209,20 @@ pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len, int i * per RTP frame */ state->duration = 160; + /** + * RTP payload type according to RFC 3551, + * section "6. Payload Type Definitions". + * + * Only GSM FR has a static payload type value (see table 4). + * For other codecs the payload type may be negotiated + * between the both sides dynamically (i.e. in range 96-127). + */ + state->payload_type = pt; + if (in_out_n == 0) { state->ssrc = rand(); state->sequence = random(); state->timestamp = random(); - /* FIXME: other payload types!! */ - state->payload_type = RTP_PT_GSM_FULL; } item = osmo_gapk_pq_add_item(pq); @@ -248,24 +255,30 @@ pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len, int i * This typically only makes sense as first item in the queue * \param pq Processing Queue to add this RTP input to * \param[in] udp_fd UDP file descriptor for the RTP input - * \param[in] blk_len Block Length to read from RTP */ + * \param[in] blk_len Block Length to read from RTP + * \param[in] pt Payload type according to RFC 3551 + */ int -osmo_gapk_pq_queue_rtp_input(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len) +osmo_gapk_pq_queue_rtp_input(struct osmo_gapk_pq *pq, int udp_fd, + unsigned int blk_len, uint8_t pt) { LOGPGAPK(LOGL_DEBUG, "PQ '%s': Adding RTP input (blk_len=%u)\n", pq->name, blk_len); - return pq_queue_rtp_op(pq, udp_fd, blk_len, 1); + return pq_queue_rtp_op(pq, udp_fd, blk_len, 1, pt); } /*! Add RTP output to processing queue. * This typically only makes sense as last item in the queue * \param pq Processing Queue to add this RTP output to * \param[in] udp_fd UDP file descriptor for the RTP output - * \param[in] blk_len Block Length to read from RTP */ + * \param[in] blk_len Block Length to read from RTP + * \param[in] pt Payload type according to RFC 3551 + */ int -osmo_gapk_pq_queue_rtp_output(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len) +osmo_gapk_pq_queue_rtp_output(struct osmo_gapk_pq *pq, int udp_fd, + unsigned int blk_len, uint8_t pt) { LOGPGAPK(LOGL_DEBUG, "PQ '%s': Adding RTP output (blk_len=%u)\n", pq->name, blk_len); - return pq_queue_rtp_op(pq, udp_fd, blk_len, 0); + return pq_queue_rtp_op(pq, udp_fd, blk_len, 0, pt); } diff --git a/tests/io/pq_rtp_test.c b/tests/io/pq_rtp_test.c index 2c1bd41..76f59d2 100644 --- a/tests/io/pq_rtp_test.c +++ b/tests/io/pq_rtp_test.c @@ -173,7 +173,7 @@ static int init_gen_queue(struct osmo_gapk_pq *pq, } /* Init an RTP sink */ - rc = osmo_gapk_pq_queue_rtp_output(pq, state->rtp_dst_fd, payload_len); + rc = osmo_gapk_pq_queue_rtp_output(pq, state->rtp_dst_fd, payload_len, 0x00); if (rc) { printf("Could not init an RTP sink\n"); return rc; @@ -210,7 +210,7 @@ static int init_chk_queue(struct osmo_gapk_pq *pq, } /* Init an RTP source on any available port */ - rc = osmo_gapk_pq_queue_rtp_input(pq, state->rtp_src_fd, payload_len); + rc = osmo_gapk_pq_queue_rtp_input(pq, state->rtp_src_fd, payload_len, 0x00); if (rc) { printf("Could not init an RTP sink\n"); return rc;