Skip to content

Commit

Permalink
ausrc, aufile, gst: replace duration by callback handler
Browse files Browse the repository at this point in the history
Retrieving the duration of an audio file may lead to long blocking
delay. E.g. gst_element_query_duration()
Now a callback handler can be called by the application only if
needed.
  • Loading branch information
cspiel1 committed Aug 12, 2024
1 parent edc2fb1 commit 2281983
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 30 deletions.
5 changes: 5 additions & 0 deletions include/baresip.h
Original file line number Diff line number Diff line change
Expand Up @@ -581,13 +581,16 @@ typedef void (ausrc_error_h)(int err, const char *str, void *arg);
typedef int (ausrc_alloc_h)(struct ausrc_st **stp, const struct ausrc *ausrc,
struct ausrc_prm *prm, const char *device,
ausrc_read_h *rh, ausrc_error_h *errh, void *arg);
typedef int (ausrc_info_h)(const struct ausrc *ausrc,
struct ausrc_prm *prm, const char *device);

/** Defines an Audio Source */
struct ausrc {
struct le le;
const char *name;
struct list dev_list;
ausrc_alloc_h *alloch;
ausrc_info_h *infoh;
};

int ausrc_register(struct ausrc **asp, struct list *ausrcl, const char *name,
Expand All @@ -597,6 +600,8 @@ int ausrc_alloc(struct ausrc_st **stp, struct list *ausrcl,
const char *name,
struct ausrc_prm *prm, const char *device,
ausrc_read_h *rh, ausrc_error_h *errh, void *arg);
int ausrc_info(struct list *ausrcl,
const char *name, struct ausrc_prm *prm, const char *device);


/*
Expand Down
4 changes: 4 additions & 0 deletions modules/aufile/aufile.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ static int module_init(void)
aufile_src_alloc);
err |= auplay_register(&auplay, baresip_auplayl(), "aufile",
aufile_play_alloc);
if (err)
return err;

ausrc->infoh = aufile_info_handler;
return err;
}

Expand Down
2 changes: 2 additions & 0 deletions modules/aufile/aufile.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ int aufile_play_alloc(struct auplay_st **stp, const struct auplay *ap,
int aufile_src_alloc(struct ausrc_st **stp, const struct ausrc *as,
struct ausrc_prm *prm, const char *dev,
ausrc_read_h *rh, ausrc_error_h *errh, void *arg);
int aufile_info_handler(const struct ausrc *as,
struct ausrc_prm *prm, const char *dev);
29 changes: 28 additions & 1 deletion modules/aufile/aufile_src.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,6 @@ int aufile_src_alloc(struct ausrc_st **stp, const struct ausrc *as,
/* return wav format to caller */
prm->srate = fprm.srate;
prm->ch = fprm.channels;
prm->duration = aufile_get_length(st->aufile, &fprm);

if (!rh)
goto out;
Expand Down Expand Up @@ -271,3 +270,31 @@ int aufile_src_alloc(struct ausrc_st **stp, const struct ausrc *as,

return err;
}


int aufile_info_handler(const struct ausrc *as,
struct ausrc_prm *prm, const char *dev)
{
int err;
(void)as;

if (!prm || !str_isset(dev))
return EINVAL;

struct aufile *aufile;
struct aufile_prm fprm;
err = aufile_open(&aufile, &fprm, dev, AUFILE_READ);
if (err) {
warning("aufile: failed to open file '%s' (%m)\n", dev, err);
goto out;
}

prm->srate = fprm.srate;
prm->ch = fprm.channels;
prm->fmt = fprm.fmt;
prm->duration = aufile_get_length(aufile, &fprm);

out:
mem_deref(aufile);
return err;
}
27 changes: 9 additions & 18 deletions modules/debug_cmd/debug_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,11 @@ static void fileinfo_destruct(void *arg)
}


static void print_fileinfo(struct fileinfo_st *st)
static void print_fileinfo(struct ausrc_prm *prm)
{
double s = ((float) st->prm.duration) / 1000;
double s = ((float) prm->duration) / 1000;

if (st->prm.duration) {
if (prm->duration) {
info("debug_cmd: length = %1.3lf seconds\n", s);
module_event("debug_cmd", "aufileinfo", NULL, NULL,
"length = %lf seconds", s);
Expand Down Expand Up @@ -222,7 +222,7 @@ static int cmd_aufileinfo(struct re_printf *pf, void *arg)
char *path;
char aumod[16];
const char *file = carg->prm;
struct fileinfo_st *st = NULL;
struct ausrc_prm prm;

if (!str_isset(file)) {
re_hprintf(pf, "fileplay: filename not specified\n");
Expand All @@ -247,25 +247,16 @@ static int cmd_aufileinfo(struct re_printf *pf, void *arg)
conf_config()->audio.audio_path, file) < 0)
return ENOMEM;

st = mem_zalloc(sizeof(*st), fileinfo_destruct);
if (!st) {
err = ENOMEM;
goto out;
}

err = ausrc_alloc(&st->ausrc, baresip_ausrcl(),
aumod,
&st->prm, path, NULL, NULL, st);
err = ausrc_info(baresip_ausrcl(), aumod, &prm, path);
if (err) {
warning("debug_cmd: %s - ausrc %s does not support empty read "
"handler or reading source %s failed. (%m)\n",
__func__, aumod, carg->prm, err);
warning("debug_cmd: %s - ausrc %s does not support info query "
"or reading source %s failed. (%m)\n",
__func__, aumod, carg->prm, err);
goto out;
}

print_fileinfo(st);
print_fileinfo(&prm);
out:
mem_deref(st);

mem_deref(path);
return err;
Expand Down
76 changes: 65 additions & 11 deletions modules/gst/gst.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,13 +345,13 @@ static int gst_setup(struct ausrc_st *st)
}


static int setup_uri(struct ausrc_st *st, const char *device)
static int setup_uri(char **urip, const char *device)
{
int err = 0;

if (g_regex_match_simple(
uri_regex, device, 0, G_REGEX_MATCH_NOTEMPTY)) {
err = str_dup(&st->uri, device);
err = str_dup(urip, device);
}
else {
if (!access(device, R_OK)) {
Expand All @@ -360,7 +360,7 @@ static int setup_uri(struct ausrc_st *st, const char *device)
if (re_snprintf(uri, urilength, "file://%s",
device) < 0)
return ENOMEM;
st->uri = uri;
*urip = uri;
}
else {
err = errno;
Expand Down Expand Up @@ -437,7 +437,7 @@ static int gst_alloc(struct ausrc_st **stp, const struct ausrc *as,
st->rh = rh;
st->arg = arg;

err = setup_uri(st, device);
err = setup_uri(&st->uri, device);
if (err) goto out;

st->ptime = prm->ptime;
Expand Down Expand Up @@ -487,18 +487,67 @@ static int gst_alloc(struct ausrc_st **stp, const struct ausrc *as,
mem_deref(st);
else {
*stp = st;
gst_element_get_state(st->pipeline, NULL, NULL, 500*1000*1000);
gint64 duration = 0;
gst_element_query_duration(st->pipeline,
GST_FORMAT_TIME,
&duration);
prm->duration = duration / 1000000;
}

return err;
}


static int gst_info_handler(const struct ausrc *as,
struct ausrc_prm *prm, const char *device)
{
int err;
(void)as;

if (!prm || !str_isset(device))
return EINVAL;

char *uri = NULL;
err = setup_uri(&uri, device);
if (err) goto out;

GstElement *pipeline = gst_pipeline_new("pipeline");
if (!pipeline) {
warning("gst: failed to create pipeline element\n");
return ENOMEM;
}

GstElement *playbin = gst_element_factory_make("playbin", NULL);
GstElement *sink = gst_element_factory_make("fakesink", NULL);
if (!playbin || !sink) {
err = ENOMEM;
if (playbin)
gst_object_unref(playbin);
if (sink)
gst_object_unref(sink);
gst_object_unref(pipeline);
goto out;
}

gst_bin_add(GST_BIN(pipeline), playbin);
g_object_set(G_OBJECT(playbin),
"uri", uri,
"audio-sink", sink, NULL);

gst_element_set_state(pipeline, GST_STATE_PLAYING);
gst_element_get_state(pipeline, NULL, NULL, 500*1000*1000);
gint64 duration = 0;
gst_element_query_duration(pipeline,
GST_FORMAT_TIME,
&duration);

prm->duration = (size_t) duration;

/* Note: other prm fields are currently not set */

out:
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline));
mem_deref(uri);
return err;
}


static int mod_gst_init(void)
{
gchar *s;
Expand All @@ -511,7 +560,12 @@ static int mod_gst_init(void)

g_free(s);

return ausrc_register(&ausrc, baresip_ausrcl(), "gst", gst_alloc);
int err = ausrc_register(&ausrc, baresip_ausrcl(), "gst", gst_alloc);
if (err)
return err;

ausrc->infoh = gst_info_handler;
return 0;
}


Expand Down
26 changes: 26 additions & 0 deletions src/ausrc.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,29 @@ int ausrc_alloc(struct ausrc_st **stp, struct list *ausrcl,

return as->alloch(stp, as, prm, device, rh, errh, arg);
}


/**
* Retreive audio parameters of an audio source
*
* @param ausrcl List of Audio Sources
* @param name Name of Audio Source
* @param prm Audio Source parameters
* @param device Name of Audio Source device (driver specific)
*
* @return 0 if success, otherwise errorcode
*/
int ausrc_info(struct list *ausrcl,
const char *name, struct ausrc_prm *prm, const char *device)
{
struct ausrc *as;

as = (struct ausrc *)ausrc_find(ausrcl, name);
if (!as)
return ENOENT;

if (!as->infoh)
return EINVAL;

return as->infoh(as, prm, device);
}

0 comments on commit 2281983

Please sign in to comment.