mirror of https://gerrit.osmocom.org/gapk
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
This commit is contained in:
parent
5613b7d850
commit
75df4ca2a3
|
@ -36,6 +36,7 @@
|
||||||
#include <osmocom/core/logging.h>
|
#include <osmocom/core/logging.h>
|
||||||
#include <osmocom/core/socket.h>
|
#include <osmocom/core/socket.h>
|
||||||
#include <osmocom/core/utils.h>
|
#include <osmocom/core/utils.h>
|
||||||
|
#include <osmocom/core/select.h>
|
||||||
|
|
||||||
#include <osmocom/gapk/common.h>
|
#include <osmocom/gapk/common.h>
|
||||||
#include <osmocom/gapk/codecs.h>
|
#include <osmocom/gapk/codecs.h>
|
||||||
|
@ -67,6 +68,7 @@ struct gapk_options
|
||||||
/* RTP payload type */
|
/* RTP payload type */
|
||||||
uint8_t rtp_pt_in, rtp_pt_out;
|
uint8_t rtp_pt_in, rtp_pt_out;
|
||||||
|
|
||||||
|
int throttle;
|
||||||
int benchmark;
|
int benchmark;
|
||||||
int verbose;
|
int verbose;
|
||||||
};
|
};
|
||||||
|
@ -75,6 +77,8 @@ struct gapk_state
|
||||||
{
|
{
|
||||||
struct gapk_options opts;
|
struct gapk_options opts;
|
||||||
struct osmo_gapk_pq *pq;
|
struct osmo_gapk_pq *pq;
|
||||||
|
struct osmo_fd timerfd; /* for optional throttling */
|
||||||
|
unsigned int num_frames;
|
||||||
int exit;
|
int exit;
|
||||||
|
|
||||||
struct {
|
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-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, " -P --rtp-pt-out=TYPE\t\tRTP payload type for outgoing frames\n");
|
||||||
fprintf(stdout, " -b, --enable-benchmark\tEnable codec benchmarking\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, " -v, --verbose\t\t\tEnable debug messages\n");
|
||||||
fprintf(stdout, "\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-in", 1, 0, 'p'},
|
||||||
{"rtp-pt-out", 1, 0, 'P'},
|
{"rtp-pt-out", 1, 0, 'P'},
|
||||||
{"enable-benchmark", 0, 0, 'b'},
|
{"enable-benchmark", 0, 0, 'b'},
|
||||||
|
{"throttle", 0, 0, 't'},
|
||||||
{"verbose", 0, 0, 'v'},
|
{"verbose", 0, 0, 'v'},
|
||||||
{"help", 0, 0, 'h'},
|
{"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
|
#ifdef HAVE_ALSA
|
||||||
"a:A:"
|
"a:A:"
|
||||||
#endif
|
#endif
|
||||||
|
@ -312,6 +318,10 @@ parse_options(struct gapk_state *state, int argc, char *argv[])
|
||||||
opt->benchmark = 1;
|
opt->benchmark = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
opt->throttle = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
log_parse_category_mask(osmo_stderr_target, "DAPP");
|
log_parse_category_mask(osmo_stderr_target, "DAPP");
|
||||||
opt->verbose = 1;
|
opt->verbose = 1;
|
||||||
|
@ -667,23 +677,66 @@ make_processing_chain(struct gapk_state *gs)
|
||||||
return 0;
|
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
|
static int
|
||||||
run(struct gapk_state *gs)
|
run(struct gapk_state *gs)
|
||||||
{
|
{
|
||||||
struct osmo_gapk_pq_item *item;
|
struct osmo_gapk_pq_item *item;
|
||||||
int rv, frames;
|
int rv;
|
||||||
|
|
||||||
rv = osmo_gapk_pq_prepare(gs->pq);
|
rv = osmo_gapk_pq_prepare(gs->pq);
|
||||||
if (rv)
|
if (rv)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
for (frames = 0; !gs->exit; frames++) {
|
if (!gs->opts.throttle) {
|
||||||
rv = osmo_gapk_pq_execute(gs->pq);
|
for (gs->num_frames = 0; !gs->exit; gs->num_frames++) {
|
||||||
if (rv)
|
rv = osmo_gapk_pq_execute(gs->pq);
|
||||||
break;
|
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 */
|
/* Wait for sink to process buffers */
|
||||||
item = llist_last_entry(&gs->pq->items, struct osmo_gapk_pq_item, list);
|
item = llist_last_entry(&gs->pq->items, struct osmo_gapk_pq_item, list);
|
||||||
|
@ -693,7 +746,7 @@ run(struct gapk_state *gs)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return frames > 0 ? 0 : rv;
|
return gs->num_frames > 0 ? 0 : rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue