gapk: add optional throttling

When throttling is enabled, one voice frame will be processed every
20ms.  This is useful for e.g. playback of a file as a RTP stream.

Without this option, the entire file would generate a flood of RTP
messages, rather than a continuous stream.

Change-Id: I0dcd4248cc800b82142722aa36a811f0657b3e0c
changes/93/19493/2
Harald Welte 2 years ago
parent 5613b7d850
commit 75df4ca2a3
  1. 69
      src/app_osmo_gapk.c

@ -36,6 +36,7 @@
#include <osmocom/core/logging.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/select.h>
#include <osmocom/gapk/common.h>
#include <osmocom/gapk/codecs.h>
@ -67,6 +68,7 @@ struct gapk_options
/* RTP payload type */
uint8_t rtp_pt_in, rtp_pt_out;
int throttle;
int benchmark;
int verbose;
};
@ -75,6 +77,8 @@ struct gapk_state
{
struct gapk_options opts;
struct osmo_gapk_pq *pq;
struct osmo_fd timerfd; /* for optional throttling */
unsigned int num_frames;
int exit;
struct {
@ -139,6 +143,7 @@ print_help(char *progname)
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, " -t, --throttle\tEnable throttling (one codec frame every 20ms)\n");
fprintf(stdout, " -v, --verbose\t\t\tEnable debug messages\n");
fprintf(stdout, "\n");
@ -211,10 +216,11 @@ parse_options(struct gapk_state *state, int argc, char *argv[])
{"rtp-pt-in", 1, 0, 'p'},
{"rtp-pt-out", 1, 0, 'P'},
{"enable-benchmark", 0, 0, 'b'},
{"throttle", 0, 0, 't'},
{"verbose", 0, 0, 'v'},
{"help", 0, 0, 'h'},
};
const char *short_options = "i:o:I:O:f:g:p:P:bvh"
const char *short_options = "i:o:I:O:f:g:p:P:btvh"
#ifdef HAVE_ALSA
"a:A:"
#endif
@ -312,6 +318,10 @@ parse_options(struct gapk_state *state, int argc, char *argv[])
opt->benchmark = 1;
break;
case 't':
opt->throttle = 1;
break;
case 'v':
log_parse_category_mask(osmo_stderr_target, "DAPP");
opt->verbose = 1;
@ -667,23 +677,66 @@ make_processing_chain(struct gapk_state *gs)
return 0;
}
static int
timerfd_cb(struct osmo_fd *ofd, unsigned int what)
{
struct gapk_state *gs = ofd->data;
uint64_t expire_count;
int rc;
rc = read(ofd->fd, (void *)&expire_count, sizeof(expire_count));
if (rc < 0 && errno == EAGAIN)
return 0;
OSMO_ASSERT(rc == sizeof(expire_count));
while (expire_count--) {
gs->num_frames++;
rc = osmo_gapk_pq_execute(gs->pq);
if (rc < 0)
gs->exit = true;
}
return 0;
}
static int
run(struct gapk_state *gs)
{
struct osmo_gapk_pq_item *item;
int rv, frames;
int rv;
rv = osmo_gapk_pq_prepare(gs->pq);
if (rv)
return rv;
for (frames = 0; !gs->exit; frames++) {
rv = osmo_gapk_pq_execute(gs->pq);
if (rv)
break;
if (!gs->opts.throttle) {
for (gs->num_frames = 0; !gs->exit; gs->num_frames++) {
rv = osmo_gapk_pq_execute(gs->pq);
if (rv)
break;
}
} else {
/* setup timerfd based processing */
const struct timespec interval = {
.tv_sec = 0,
.tv_nsec = 20*1000*1000,
};
gs->timerfd.fd = -1;
rv = osmo_timerfd_setup(&gs->timerfd, timerfd_cb, gs);
OSMO_ASSERT(rv == 0);
rv = osmo_timerfd_schedule(&gs->timerfd, NULL, &interval);
OSMO_ASSERT(rv == 0);
/* actual processing loop */
while (!gs->exit)
osmo_select_main(0);
/* cleanup */
osmo_timerfd_disable(&gs->timerfd);
close(gs->timerfd.fd);
osmo_fd_unregister(&gs->timerfd);
}
LOGP(DAPP, LOGL_NOTICE, "Processed %d frames\n", frames);
LOGP(DAPP, LOGL_NOTICE, "Processed %d frames\n", gs->num_frames);
/* Wait for sink to process buffers */
item = llist_last_entry(&gs->pq->items, struct osmo_gapk_pq_item, list);
@ -693,7 +746,7 @@ run(struct gapk_state *gs)
continue;
}
return frames > 0 ? 0 : rv;
return gs->num_frames > 0 ? 0 : rv;
}

Loading…
Cancel
Save