Skip to content

Commit

Permalink
defer link mode improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
jeanlf committed Apr 23, 2024
1 parent 1bb8fb4 commit 737a84a
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 43 deletions.
105 changes: 82 additions & 23 deletions applications/gpac/gpac.c
Expand Up @@ -122,6 +122,7 @@ static Bool revert_cache_file(void *cbck, char *item_name, char *item_path, GF_F
#ifdef GPAC_DEFER_MODE
static GF_Err print_pid_props(char *arg);
static GF_Err probe_pid_link(char *arg);
static GF_Err print_pid_dests(char *arg);
#endif

#ifdef WIN32
Expand Down Expand Up @@ -1004,6 +1005,7 @@ int gpac_main(int _argc, char **_argv)
|| !strcmp(arg, "-g")
|| !strcmp(arg, "-pi")
|| !strcmp(arg, "-pl")
|| !strcmp(arg, "-pd")
|| !strcmp(arg, "-se")
) {
#endif
Expand Down Expand Up @@ -1215,11 +1217,11 @@ static int gpac_run()
f = gf_list_get(loaded_filters, gf_list_count(loaded_filters)-1-relink);
}
if (!f) {
fprintf(stderr, "Invalid filter index in %s\n", arg);
GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("Invalid filter index in %s\n", arg));
e=GF_BAD_PARAM;
ERR_EXIT
}
fprintf(stderr, "Relinking filter %s\n", gf_filter_get_name(f));
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Relinking filter %s\n", gf_filter_get_name(f)));
while (retry && gf_fs_check_filter(session, f)) {
retry--;
e = gf_filter_reconnect_output(f, NULL);
Expand All @@ -1232,7 +1234,7 @@ static int gpac_run()
continue;
}
if (e) {
fprintf(stderr, "Error relinking filter %s\n", gf_filter_get_name(f));
GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("Error relinking filter %s\n", gf_filter_get_name(f)));
ERR_EXIT
}
if (do_run)
Expand All @@ -1247,24 +1249,20 @@ static int gpac_run()
e = GF_NOT_SUPPORTED;
ERR_EXIT
}
fprintf(stderr, "\n");
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("\n"));
}
continue;
} else if (!strcmp(arg, "-f")) {
fprintf(stderr, "Running session\n");
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Running session\n"));
run_sess();
continue;
} else if (!strcmp(arg, "-g")) {
gf_fs_print_connections(session);
fprintf(stderr, "\n");
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("\n"));
continue;
} else if (!strcmp(arg, "-s")) {
gf_fs_print_stats(session);
fprintf(stderr, "\n");
continue;
} else if (!strcmp(arg, "-stat")) {
//gf_fs_print_stats(session);
fprintf(stderr, "\n");
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("\n"));
continue;
} else if (!strncmp(arg, "-pi", 3)) {
e = print_pid_props(arg);
Expand All @@ -1276,8 +1274,14 @@ static int gpac_run()
ERR_EXIT
}
continue;
} else if (!strncmp(arg, "-pd", 3)) {
e = print_pid_dests(arg);
if (e) {
ERR_EXIT
}
continue;
} else if (!strncmp(arg, "-se", 3)) {
fprintf(stderr, "Sending PLAY event\n");
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Sending PLAY event\n"));
gf_fs_send_deferred_play(session);
}
}
Expand Down Expand Up @@ -1932,7 +1936,7 @@ static GF_Err print_pid_props(char *arg)
if (e) return e;
u32 j, count = gf_filter_get_opid_count(f);
if (!count) {
fprintf(stderr, "Filter %s has no output\n", gf_filter_get_name(f));
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Filter %s has no output\n", gf_filter_get_name(f)));
return GF_OK;
}
for (j=0; j<count;j++) {
Expand All @@ -1941,47 +1945,102 @@ static GF_Err print_pid_props(char *arg)
GF_FilterPid *pid = gf_filter_get_opid(f, j);
if ((p_idx>=0) && (p_idx != j)) continue;
if (prefix=='-') {
fprintf(stderr, "Filter %s PID #%d name: %s\n", gf_filter_get_name(f), j, gf_filter_pid_get_name(pid) );
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Filter %s PID #%d name: %s\n", gf_filter_get_name(f), j, gf_filter_pid_get_name(pid) ));
continue;
}
fprintf(stderr, "Filter %s PID %s properties:\n", gf_filter_get_name(f), gf_filter_pid_get_name(pid) );
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Filter %s PID %s properties:\n", gf_filter_get_name(f), gf_filter_pid_get_name(pid) ));
while (1) {
u32 p4cc=0;
const char *pname=NULL;
const GF_PropertyValue *p = gf_filter_pid_enum_properties(pid, &prop_idx, &p4cc, &pname);
if (!p) break;
fprintf(stdout, "Prop %s: %s\n", p4cc ? gf_props_4cc_get_name(p4cc) : pname, gf_props_dump(p4cc, p, szDump, GF_PROP_DUMP_DATA_NONE));
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Prop %s: %s\n", p4cc ? gf_props_4cc_get_name(p4cc) : pname, gf_props_dump(p4cc, p, szDump, GF_PROP_DUMP_DATA_NONE)));
}
prop_idx=0;
while (prefix=='+') {
u32 p4cc=0;
const char *pname=NULL;
const GF_PropertyValue *p = gf_filter_pid_enum_info(pid, &prop_idx, &p4cc, &pname);
if (!p) break;
fprintf(stdout, "Info %s: %s\n", p4cc ? gf_props_4cc_get_name(p4cc) : pname, gf_props_dump(p4cc, p, szDump, GF_PROP_DUMP_DATA_NONE));
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Info %s: %s\n", p4cc ? gf_props_4cc_get_name(p4cc) : pname, gf_props_dump(p4cc, p, szDump, GF_PROP_DUMP_DATA_NONE)));
}
fprintf(stderr, "\n");
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("\n"));
}
if (prefix=='-') {
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("\n"));
}
return GF_OK;
}
static GF_Err probe_pid_link(char *arg)
{
GF_Filter *f;
s32 opid_idx;
u8 prefix;
char *fname = strchr(arg, '@');
if (!fname) return GF_BAD_PARAM;
if (!fname) {
GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("Missing `@` directive in probe link\n"));
return GF_BAD_PARAM;
}

GF_Err e = extract_filter_and_pid(arg, &f, &opid_idx, NULL);
GF_Err e = extract_filter_and_pid(arg, &f, &opid_idx, &prefix);
if (e) return e;
if (opid_idx<0) opid_idx=0;
char *res = NULL;
e = gf_filter_probe_link(f, opid_idx, fname+1, &res);
if (prefix=='+')
e = gf_filter_probe_links(f, opid_idx, fname+1, &res);
else
e = gf_filter_probe_link(f, opid_idx, fname+1, &res);

if (res) {
fprintf(stdout, "Probed chain from %s to %s: %s\n\n", gf_filter_get_name(f), fname+1, res);
if (!res[0]) {
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Probed chain from %s to %s: direct connection\n\n", gf_filter_get_name(f), fname+1));
} else if (strchr(res, '|')) {
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Probed chains from %s to %s:\n", gf_filter_get_name(f), fname+1));
char *cur=res;
while (1) {
u32 distance=0;
u32 priority=0;
char *sep = strchr(cur, '|');
if (sep) sep[0] = 0;
char *w_sep = strchr(cur, ',');
if (w_sep) {
w_sep[0] = 0;
sscanf(cur, "%u;%u", &distance, &priority);
w_sep[0] = ',';
}
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("\t- %s (priority %u distance %u)\n", w_sep ? w_sep+1 : cur, priority, distance));
if (!sep) break;
sep[0] = '|';
cur = sep+1;
}
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("\n"));
} else {
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Probed chain from %s to %s: %s\n", gf_filter_get_name(f), fname+1, res));
}
gf_free(res);
} else {
fprintf(stdout, "No filter chain from %s to %s: %s\n\n", gf_filter_get_name(f), fname+1, gf_error_to_string(e));
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("No filter chain from %s to %s: %s\n\n", gf_filter_get_name(f), fname+1, gf_error_to_string(e)));
}
return GF_OK;
}

static GF_Err print_pid_dests(char *arg)
{
GF_Filter *f;
s32 p_idx;
u8 prefix;
char *res;
GF_Err e = extract_filter_and_pid(arg, &f, &p_idx, &prefix);
if (e) return e;

e = gf_filter_get_possible_destinations(f, p_idx, &res);
if (res) {
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Possible destinations for %s: %s\n", gf_filter_get_name(f), res));
gf_free(res);
} else if (e==GF_FILTER_NOT_FOUND){
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("No destinations for %s\n", gf_filter_get_name(f)));
} else {
GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Failed to probe possible destinations for %s: %s\n\n", gf_filter_get_name(f), gf_error_to_string(e)));
}
return GF_OK;
}
Expand Down
8 changes: 5 additions & 3 deletions applications/gpac/gpac_help.c
Expand Up @@ -888,9 +888,9 @@ static const char *gpac_defer =
"This mode can be used to test loading filters one by one and asking for link resolution explicitly.\n"
"This is mostly used to reproduce how sessions are build in more complex applications.\n"
"\n"
"The options `rl`, `pi` and `pl` allow adressing a filter by index `F` in a list.\n"
"The options `rl`, `pi`, `pl` and `pd` allow adressing a filter by index `F` in a list.\n"
"- if the option is suffixed with an `x` (e.g. `rlx=`), `F=0` means the last filter in the list of filters in the session\n"
"- otherwise, `F=0` means the last filter located before the option\n"
"- otherwise, `F=0` means the last filter declared before the option\n"
"\n"
"The relink options `-rl` and `-rlx` always flush the session (run until no more tasks are scheduled).\n"
"The last run can be omitted.\n"
Expand All @@ -910,7 +910,9 @@ static GF_GPACArg gpac_defer_args[] =
GF_DEF_ARG("pi=[+|-][F[:i]]", NULL, "print PID properties (all or of index `i`) of filter `F` (default 0)\n"
"- if prefixed with `-`: only list PIDs\n"
"- if prefixed with `+`: also print PID info", NULL, NULL, GF_ARG_STRING, GF_ARG_HINT_EXPERT),
GF_DEF_ARG("pl=[F[:i]]@NAME", NULL, "probe filter chain from filter `F` (default 0) to the given filter `NAME`", NULL, NULL, GF_ARG_STRING, GF_ARG_HINT_EXPERT),
GF_DEF_ARG("pl=[+][F[:i]]@NAME", NULL, "probe filter chain from filter `F` (default 0) to the given filter `NAME`: \n"
"- if prefixed with `+`: print all known chains and their priorities", NULL, NULL, GF_ARG_STRING, GF_ARG_HINT_EXPERT),
GF_DEF_ARG("pd=[F[:i]]", NULL, "print possible PID destinations (all or of index `i`) of filter `F` (default 0)", NULL, NULL, GF_ARG_STRING, GF_ARG_HINT_EXPERT),
GF_DEF_ARG("f", NULL, "flush session until no more tasks", NULL, NULL, GF_ARG_BOOL, GF_ARG_HINT_EXPERT),
GF_DEF_ARG("g", NULL, "print graph", NULL, NULL, GF_ARG_BOOL, GF_ARG_HINT_EXPERT),
GF_DEF_ARG("s", NULL, "print stats", NULL, NULL, GF_ARG_BOOL, GF_ARG_HINT_EXPERT),
Expand Down
17 changes: 16 additions & 1 deletion include/gpac/filters.h
Expand Up @@ -3315,11 +3315,26 @@ Bool gf_filter_relocate_url(GF_Filter *filter, const char *service_url, const ch
*/
GF_Err gf_filter_probe_link(GF_Filter *filter, u32 opid_idx, const char *fname, char **result_chain);

/*! Probes for possible link resolution towards a given filter description. Same as \ref gf_filter_probe_link but tests multiple links
The syntax for each chain is `D;P,filters` with:
- `D`: distance between the source and target, as seen by the graph resolver (some filters may hide their distance)
- `P`: priority of the chain
- `filters`: comma-separated list of filters
\param filter target filter
\param opid_idx output pid index of target filter
\param fname textual description of filter - If a source is used, returns an error. Destination can be identified using dst=URL pattern
\param result_chain resulting chains separated by a pipe character ('|') or NULL if error. MUST be freed by caller
\return error if any
*/
GF_Err gf_filter_probe_links(GF_Filter *filter, u32 opid_idx, const char *fname, char **result_chain);

/*! Gets list of possible destinations for this filter
\param filter target filter
\param opid_idx output pid index of target filter. If negative, will check destinations for any of the output pids
\param result_list resulting list as comma-separated list, or NULL if error. MUST be freed by caller. An empty chain means direct connection is possible
\return error if any, GF_FILTER_NOT_FOUND if no available chain
\return error if any, GF_FILTER_NOT_FOUND if no available destinations
*/
GF_Err gf_filter_get_possible_destinations(GF_Filter *filter, s32 opid_idx, char **result_list);

Expand Down
1 change: 1 addition & 0 deletions src/export.cpp
Expand Up @@ -2545,6 +2545,7 @@
#pragma comment (linker, EXPORT_SYMBOL(gf_filter_meta_set_instances ) )
#pragma comment (linker, EXPORT_SYMBOL(gf_filter_meta_get_instances ) )
#pragma comment (linker, EXPORT_SYMBOL(gf_filter_probe_link ) )
#pragma comment (linker, EXPORT_SYMBOL(gf_filter_probe_links ) )
#pragma comment (linker, EXPORT_SYMBOL(gf_filter_get_possible_destinations ) )

#pragma comment (linker, EXPORT_SYMBOL(gf_filter_pck_discard ) )
Expand Down
50 changes: 42 additions & 8 deletions src/filter_core/filter.c
Expand Up @@ -5593,15 +5593,15 @@ void gf_filter_dump_buffers(GF_Filter *f)
}
#endif

GF_EXPORT
GF_Err gf_filter_probe_link(GF_Filter *filter, u32 opid_idx, const char *fname, char **res_chain)
static GF_Err gf_filter_probe_link_internal(GF_Filter *filter, u32 opid_idx, const char *fname, Bool all_links, char **res_chain)
{
char *fdesc=NULL;
char szFmt[20];
GF_Filter *new_f;
GF_Err e;
GF_FilterPid *opid=NULL;
GF_FilterSession *fs;
GF_List *tmp_blacklist;
if (!filter || !fname || !res_chain) return GF_BAD_PARAM;
*res_chain = NULL;
fs = filter->session;
Expand Down Expand Up @@ -5632,27 +5632,58 @@ GF_Err gf_filter_probe_link(GF_Filter *filter, u32 opid_idx, const char *fname,
gf_fs_lock_filters(fs, GF_FALSE);
return e;
}
tmp_blacklist = gf_list_new();
while (1) {
GF_LinkInfo link_info;
const GF_FilterRegister *last_freg = NULL;
GF_List *fchain = gf_filter_pid_compute_link(opid, new_f, tmp_blacklist, &link_info);
if (!fchain) break;
if (*res_chain && (*res_chain)[0]) {
gf_dynstrcat(res_chain, "|", NULL);
}
if (all_links) {
char szTmp[20];
sprintf(szTmp, "%u;%u,", link_info.distance, link_info.priority);
gf_dynstrcat(res_chain, szTmp, NULL);
}

GF_List *fchain = gf_filter_pid_compute_link(opid, new_f);
if (fchain) {
u32 i, count = gf_list_count(fchain);
for (i=0; i<count; i+=2) {
const GF_FilterRegister *freg = gf_list_get(fchain, i);
gf_dynstrcat(res_chain, freg->name, ",");
if ((i+2==count) && (freg == new_f->freg))
break;
gf_dynstrcat(res_chain, freg->name, i ? "," : NULL);
last_freg = freg;
}
gf_list_del(fchain);
} else {
e = GF_FILTER_NOT_FOUND;
if (! *res_chain) *res_chain = gf_strdup("");
if (!last_freg) break;
gf_list_add(tmp_blacklist, (void*)last_freg);
if (!all_links) break;
}
gf_list_del(tmp_blacklist);

gf_list_del_item(fs->filters, new_f);
if (!new_f->finalized && new_f->freg->finalize) {
new_f->freg->finalize(new_f);
}
gf_filter_del(new_f);
gf_fs_lock_filters(fs, GF_FALSE);
return e;
if (*res_chain) return GF_OK;
return GF_FILTER_NOT_FOUND;
}

GF_EXPORT
GF_Err gf_filter_probe_links(GF_Filter *filter, u32 opid_idx, const char *fname, char **res_chain)
{
return gf_filter_probe_link_internal(filter, opid_idx, fname, GF_TRUE, res_chain);
}

GF_EXPORT
GF_Err gf_filter_probe_link(GF_Filter *filter, u32 opid_idx, const char *fname, char **res_chain)
{
return gf_filter_probe_link_internal(filter, opid_idx, fname, GF_FALSE, res_chain);
}


GF_EXPORT
Expand All @@ -5664,6 +5695,8 @@ GF_Err gf_filter_get_possible_destinations(GF_Filter *filter, s32 opid_idx, char
if (opid_idx>=0) {
opid = gf_list_get(filter->output_pids, opid_idx);
if (opid==NULL) return GF_BAD_PARAM;
} else {
if (!filter->num_output_pids) return GF_FILTER_NOT_FOUND;
}
*res_list = NULL;
count = gf_list_count(filter->session->links);
Expand Down Expand Up @@ -5696,5 +5729,6 @@ GF_Err gf_filter_get_possible_destinations(GF_Filter *filter, s32 opid_idx, char
gf_dynstrcat(res_list, src->freg->name, ",");
}
}
if (! *res_list) return GF_FILTER_NOT_FOUND;
return GF_OK;
}

0 comments on commit 737a84a

Please sign in to comment.