add templating for property assignment - cf #2527

This commit is contained in:
jeanlf
2023-07-13 10:43:13 +02:00
parent 78b0704037
commit 14edcb23ae
7 changed files with 117 additions and 13 deletions

View File

@@ -35,6 +35,7 @@
- Allow running the session without mutexes
- Closed Caption decoding filter (CEA708)
- MPEG-H decoder using IIS mpeghdec
- Templating for property assignment
## MP4Box
- add track reordering option

View File

@@ -421,6 +421,15 @@ const char *gpac_doc =
"This will assign property `MyProp` to `Super Audio` for first audio PID declared.\n"
"EX gpac -i source.mp4:#MyProp=(Width+1280)HD\n"
"This will assign property `MyProp` to `HD` for PIDs with property `Width` greater than 1280.\n"
"\n"
"The property value can be templated using the following keywords:\n"
"- $GINC(init[,inc]) or @GINC(...): replaced by integer for each new output PID of the filter (see specific filter options for details on syntax)\n"
"- $PROP$ or @PROP@: replaced by serialized value of property `PROP` (name or 4CC) of the PID or with empty string if no such property\n"
"EX gpac -i source.ts:#ASID=$PID$\n"
"This will assign DASH AdaptationSet ID to the PID ID value.\n"
"EX gpac -i source.ts:#RepresentationID=$ServiceID$\n"
"This will assign DASH Representation ID to the PID ServiceID value.\n"
"\n"
"# Using option files\n"
"It is possible to use a file to define options of a filter, by specifying the target file name as an option without value, i.e. `:myopts.txt`.\n"
"Warning: Only local files are allowed.\n"

View File

@@ -2358,6 +2358,32 @@ gpac -i source.mp4:#MyProp=(Width+1280)HD
.br
This will assign property MyProp to HD for PIDs with property Width greater than 1280.
.br
.br
The property value can be templated using the following keywords:
.br
* $GINC(init[,inc]) or @GINC(...): replaced by integer for each new pid (see specific filter options for details on syntax)
.br
* $PROP$ or @PROP@: replaced by serialized value of property PROP (name or 4CC) or with empty string if no such property
.br
Example
.br
gpac -i source.ts:#ASID=$PID$
.br
.br
This will assign DASH AdaptationSet ID to the PID ID value.
.br
Example
.br
gpac -i source.ts:#RepresentationID=$ServiceID$
.br
.br
This will assign DASH Representation ID to the PID ServiceID value.
.br
.br
.SH Using option files
.LP

View File

@@ -982,8 +982,9 @@ static void gf_filter_set_arg(GF_Filter *filter, const GF_FilterArgs *a, GF_Prop
}
static void filter_translate_autoinc(GF_Filter *filter, char *value)
void filter_solve_prop_template(GF_Filter *filter, GF_FilterPid *pid, char **value)
{
char ref_prop_dump[GF_PROP_DUMP_ARG_SIZE];
u32 ainc_crc, i;
GF_FSAutoIncNum *auto_int=NULL;
u32 inc_count;
@@ -992,11 +993,45 @@ static void filter_translate_autoinc(GF_Filter *filter, char *value)
s32 increment=1;
char szInt[100];
char *search_str = *value;
while (1) {
char *step_sep;
char *inc_end, *inc_sep;
inc_sep = strstr(value, "$GINC(");
char *s1 = strchr(search_str, '$');
char *s2 = strchr(search_str, '@');
if (s1 && s2 && (s2<s1)) s1 = NULL;
inc_sep = s1 ? s1 : s2;
if (!inc_sep) return;
if (strncmp(inc_sep+1, "GINC(", 5)) {
char *next = pid ? strchr(inc_sep+1, inc_sep[0]) : NULL;
if (!next) {
search_str = inc_sep+1;
continue;
}
//check for prop
next[0] = 0;
const GF_PropertyValue *src_prop=NULL;
u32 ref_p4cc = gf_props_get_id(inc_sep+1);
if (ref_p4cc)
src_prop = gf_filter_pid_get_property(pid, ref_p4cc);
else
src_prop = gf_filter_pid_get_property_str(pid, inc_sep+1);
char *solved = src_prop ? (char*) gf_props_dump(ref_p4cc, src_prop, ref_prop_dump, GF_PROP_DUMP_DATA_INFO) : "";
inc_sep[0] = 0;
char *new_val = gf_strdup(*value);
gf_dynstrcat(&new_val, solved, NULL);
u32 len = (u32) strlen(new_val);
gf_dynstrcat(&new_val, next+1, NULL);
gf_free(*value);
*value = new_val;
search_str = new_val + len;
continue;
}
inc_end = strstr(inc_sep, ")");
if (!inc_end) return;
@@ -1018,10 +1053,11 @@ static void filter_translate_autoinc(GF_Filter *filter, char *value)
auto_int=NULL;
continue;
}
if (auto_int->filter == filter) {
if ((auto_int->filter == filter) && (auto_int->pid==pid)) {
sprintf(szInt, "%d", auto_int->inc_val);
break;
}
if (!assigned)
max_int = auto_int->inc_val;
else if ((increment>0) && (max_int < auto_int->inc_val))
@@ -1036,6 +1072,7 @@ static void filter_translate_autoinc(GF_Filter *filter, char *value)
GF_SAFEALLOC(auto_int, GF_FSAutoIncNum);
if (auto_int) {
auto_int->filter = filter;
auto_int->pid = pid;
auto_int->crc = ainc_crc;
if (assigned) auto_int->inc_val = max_int + increment;
else sscanf(szInt, "%d", &auto_int->inc_val);
@@ -1044,8 +1081,15 @@ static void filter_translate_autoinc(GF_Filter *filter, char *value)
}
if (auto_int) {
sprintf(szInt, "%d", auto_int->inc_val);
strcat(value, szInt);
strcat(value, inc_end);
char *new_val = gf_strdup(*value);
gf_dynstrcat(&new_val, szInt, NULL);
gf_dynstrcat(&new_val, inc_end, NULL);
u32 len = (u32) strlen(new_val);
gf_free(*value);
*value = new_val;
search_str = new_val + len;
} else {
search_str = inc_sep + 1;
}
}
}
@@ -1082,7 +1126,7 @@ GF_PropertyValue gf_filter_parse_prop_solve_env_var(GF_FilterSession *fs, GF_Fil
if (f && strstr(value, "$GINC(")) {
char *a_value = gf_strdup(value);
filter_translate_autoinc(f, a_value);
filter_solve_prop_template(f, NULL, &a_value);
argv = gf_props_parse_value(type, name, a_value, enum_values, fs->sep_list);
gf_free(a_value);
return argv;

View File

@@ -1669,8 +1669,6 @@ static Bool filter_pid_check_fragment(GF_FilterPid *src_pid, char *frag_name, Bo
//check for built-in property
p4cc = gf_props_get_id(frag_name);
if (!p4cc && !strcmp(frag_name, "PID") )
p4cc = GF_PROP_PID_ID;
if (!p4cc && (strlen(frag_name)==4))
p4cc = GF_4CC(frag_name[0], frag_name[1], frag_name[2], frag_name[3]);
@@ -3888,6 +3886,7 @@ static void gf_filter_pid_set_args_internal(GF_Filter *filter, GF_FilterPid *pid
//parse each arg
while (args) {
char ref_prop_dump[GF_PROP_DUMP_ARG_SIZE];
u32 p4cc=0;
u32 prop_type=GF_PROP_FORBIDEN;
Bool parse_prop = GF_TRUE;
@@ -4033,6 +4032,16 @@ static void gf_filter_pid_set_args_internal(GF_Filter *filter, GF_FilterPid *pid
if (!parse_prop)
goto skip_arg;
if (strchr(value, '$') || strchr(value, '@')) {
char *a_value = gf_strdup(value);
filter_solve_prop_template(filter, pid, &a_value);
strncpy(ref_prop_dump, a_value, GF_PROP_DUMP_ARG_SIZE-1);
ref_prop_dump[GF_PROP_DUMP_ARG_SIZE-1]=0;
gf_free(a_value);
value = (char*) ref_prop_dump;
if (!value[0])
goto skip_arg;
}
if (prop_type != GF_PROP_FORBIDEN) {
GF_PropertyValue p;

View File

@@ -1656,20 +1656,30 @@ static u32 gf_num_props = sizeof(GF_BuiltInProps) / sizeof(GF_BuiltInProperty);
GF_EXPORT
u32 gf_props_get_id(const char *name)
{
u32 i, len;
u32 i, len, prop_id=0;
if (!name) return 0;
len = (u32) strlen(name);
if (len==4) {
prop_id = GF_4CC(name[0], name[1], name[2], name[3]);
} else if ((len==3) && !strcmp(name, "PID")) {
return GF_PROP_PID_ID;
}
for (i=0; i<gf_num_props; i++) {
if (GF_BuiltInProps[i].name) {
GF_BuiltInProperty *prop = &GF_BuiltInProps[i];
if (prop_id && (prop->type==prop_id))
return prop->type;
if (prop->name) {
u32 j;
for (j=0; j<=len; j++) {
char c = GF_BuiltInProps[i].name[j];
char c = prop->name[j];
if (!c) break;
if (c != name[j])
break;
}
if ((j==len) && !GF_BuiltInProps[i].name[j])
return GF_BuiltInProps[i].type;
if ((j==len) && !prop->name[j])
return prop->type;
}
}
return 0;

View File

@@ -540,6 +540,7 @@ typedef struct
u32 crc;
s32 inc_val;
GF_Filter *filter;
GF_FilterPid *pid;
} GF_FSAutoIncNum;
#ifndef GPAC_DISABLE_3D
@@ -1149,6 +1150,10 @@ const GF_PropertyValue *gf_filter_pid_get_property_str_first(GF_FilterPid *pid,
void gf_filter_pid_set_args(GF_Filter *filter, GF_FilterPid *pid);
Bool gf_filter_aggregate_packets(GF_FilterPidInst *dst);
//solve property template, or jusr GINC() if pid is NULL
void filter_solve_prop_template(GF_Filter *filter, GF_FilterPid *pid, char **value);
enum
{
EDGE_STATUS_NONE=0,