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
changes/28/9928/4
Vadim Yanitskiy 4 years ago
parent 62717b6375
commit 89c1082b3d
  1. 6
      include/osmocom/gapk/procqueue.h
  2. 37
      src/app_osmo_gapk.c
  3. 35
      src/pq_rtp.c
  4. 4
      tests/io/pq_rtp_test.c

@ -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);

@ -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);

@ -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);
}

@ -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;

Loading…
Cancel
Save