mirror of
https://github.com/gpac/gpac.git
synced 2026-01-12 00:05:22 +08:00
add templating for property assignment - cf #2527
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user