Skip to content

Commit

Permalink
chapter support in filters - cf #2209
Browse files Browse the repository at this point in the history
  • Loading branch information
jeanlf committed Jul 22, 2022
1 parent d485955 commit 2969863
Show file tree
Hide file tree
Showing 17 changed files with 322 additions and 65 deletions.
9 changes: 7 additions & 2 deletions include/gpac/filters.h
Expand Up @@ -793,8 +793,10 @@ typedef enum
/*! 4CC on unsigned 32 bit integer*/
GF_PROP_4CC = 25,
/*! 4CC list on unsigned 32 bit integer, memory is ALWAYS duplicated when setting the property*/
GF_PROP_4CC_LIST = 26,

GF_PROP_4CC_LIST = 26,
/*! string list, memory is duplicated when setting the property - to use only with property assignment functions*/
GF_PROP_STRING_LIST_COPY = 27,

/*! last non-enum property*/
GF_PROP_LAST_NON_ENUM,

Expand Down Expand Up @@ -1216,6 +1218,9 @@ enum
GF_PROP_PID_ORIG_CRYPT_SCHEME = GF_4CC('P','O','C','S'),
GF_PROP_PID_TIMESHIFT_SEGS = GF_4CC('P','T','S','N'),

GF_PROP_PID_CHAP_TIMES = GF_4CC('C','H','P','T'),
GF_PROP_PID_CHAP_NAMES = GF_4CC('C','H','P','N'),

//internal for HLS playlist reference, gives a unique ID identifying media mux, and indicated in packets carrying child playlists
GF_PROP_PCK_HLS_REF = GF_4CC('H','P','L','R'),
//internal for HLS low latency
Expand Down
2 changes: 1 addition & 1 deletion include/gpac/isomedia.h
Expand Up @@ -2239,7 +2239,7 @@ GF_Err gf_isom_add_chapter(GF_ISOFile *isom_file, u32 trackNumber, u64 timestamp
/*! deletes copyright
\param isom_file the target ISO file
\param trackNumber the target track
\param index the 1-based index of the copyright notice to remove, or 0 to remove all copyrights
\param index the 1-based index of the copyright notice to remove, or 0 to remove all chapters
\return error if any
*/
GF_Err gf_isom_remove_chapter(GF_ISOFile *isom_file, u32 trackNumber, u32 index);
Expand Down
10 changes: 7 additions & 3 deletions share/doc/man/gpac-filters.1
Expand Up @@ -2161,7 +2161,7 @@ store (enum, default: inter): file storage mode
.br
* fstart: write samples as they arrive and moov before mdat
.br
* tight: uses per-sample interleaving of all tracks (requires temporary storage of all media)
* tight: uses per-sample interleaving of all tracks (requires temporary storage of all media)
.br
* frag: fragments the file using cdur duration
.br
Expand Down Expand Up @@ -4142,6 +4142,8 @@ Note: When sources are ISOBMFF files or segments on local storage or GF_FileIO o
.br
* sprops=STR: assigns properties described in STR to all PIDs of the main content during a splice (cf below). STR is formatted according to gpac -h doc using the default parameter set.
.br
* chap=NAME: assigns chapter name at the start of next URL (filter always removes source chapter names).
.br

.br
The following global options (applying to the filter, not the sources) may also be set in the playlist:
Expand Down Expand Up @@ -5145,7 +5147,7 @@ Output multiplexers allowing segmented output must obey the following:
.br
* subs_sidx=0: indicates an SIDX shall be generated - only added if not already specified by user
.br
* xps_inband=all|no: indicates AVC/HEVC/... parameter sets shall be sent inband or out of band
* xps_inband=all|no|both: indicates AVC/HEVC/... parameter sets shall be sent inband, out of band, or both
.br
* nofragdef: indicates fragment defaults should be set in each segment rather than in init segment
.br
Expand Down Expand Up @@ -5212,6 +5214,8 @@ bs_switch (enum, default: def): bitstream switching mode (single init segment)
.br
* inband: moves decoder config inband if possible
.br
* both: inband and outband parameter sets
.br
* pps: moves PPS and APS inband, keep VPS,SPS and DCI out of band (used for VVC RPR)
.br
* force: enables it even if only one representation
Expand Down Expand Up @@ -10580,7 +10584,7 @@ Authors: GPAC developers, see git repo history (-log)
.br
For bug reports, feature requests, more information and source code, visit https://github.com/gpac/gpac
.br
build: 2.1-DEV-rev221-ge0cac167f-master
build: 2.1-DEV-rev252-gd48595585-master
.br
Copyright: (c) 2000-2022 Telecom Paris distributed under LGPL v2.1+ - http://gpac.io
.br
Expand Down
17 changes: 16 additions & 1 deletion share/doc/man/gpac.1
Expand Up @@ -1097,6 +1097,11 @@ hack for PIFF PSEC files generated by 0.9.0 and 1.0 MP4Box with wrong subsample_
.br
hack for old vvdec+libavcodec supporting only annexB format
.br
.TP
.B \-heif-hevc-urn
.br
use HEVC URN for alpha and depth in HEIF instead of MPEG-B URN (HEIF first edition)
.br
.SH libgpac logs options:
.LP
.br
Expand Down Expand Up @@ -3592,6 +3597,16 @@ PID is a HAS manifest
PID has potentially empty times between packets
.br
.TP
.B ChapTimes (CHPT,uintl,D )
.br
Chapter start times
.br
.TP
.B ChapNames (CHPN,strl,D )
.br
Chapter names
.br
.TP
.B SkipBegin (PCKS,uint, P)
.br
Amount of media to skip from beginning of packet in PID timescale
Expand Down Expand Up @@ -4711,7 +4726,7 @@ Authors: GPAC developers, see git repo history (-log)
.br
For bug reports, feature requests, more information and source code, visit https://github.com/gpac/gpac
.br
build: 2.1-DEV-rev221-ge0cac167f-master
build: 2.1-DEV-rev252-gd48595585-master
.br
Copyright: (c) 2000-2022 Telecom Paris distributed under LGPL v2.1+ - http://gpac.io
.br
Expand Down
2 changes: 1 addition & 1 deletion share/doc/man/mp4box.1
Expand Up @@ -2855,7 +2855,7 @@ Authors: GPAC developers, see git repo history (-log)
.br
For bug reports, feature requests, more information and source code, visit https://github.com/gpac/gpac
.br
build: 2.1-DEV-rev221-ge0cac167f-master
build: 2.1-DEV-rev252-gd48595585-master
.br
Copyright: (c) 2000-2022 Telecom Paris distributed under LGPL v2.1+ - http://gpac.io
.br
Expand Down
42 changes: 42 additions & 0 deletions share/gui/extensions/player/player.js
Expand Up @@ -665,6 +665,10 @@ extension = {
}
}

wnd.chapters = gw_new_icon(wnd.infobar, 'chapters');
wnd.chapters.extension = this;
wnd.chapters.hide();

wnd.loop = gw_new_icon(wnd.infobar, 'play_once');
wnd.loop.extension = this;
wnd.loop.add_icon(gwskin.images.play_loop);
Expand Down Expand Up @@ -897,6 +901,11 @@ extension = {
if (this.extension.root_odm && !this.extension.dynamic_scene && !this.extension.root_odm.is_over)
is_over = false;


if (this.chapters.visible) {
full_w += control_icon_size;
}

} else {
this.stats.hide();
this.stop.hide();
Expand Down Expand Up @@ -1679,6 +1688,8 @@ extension = {
this.services = [];

var root_odm = this.root_odm;
let chaps = null;
this.controler.chapters.hide();
if (root_odm) {
for (var res_i = 0; res_i < root_odm.nb_resources; res_i++) {
var m = root_odm.get_resource(res_i);
Expand All @@ -1694,8 +1705,39 @@ extension = {
this.services.push(m);
}
}
chaps = root_odm.get_chapters();
}

if (chaps) {
if (!this.controler.chapters.visible) {
this.controler.chapters.show();
this.controler.layout();
}

this.controler.chapters.on_click = function () {

if (this.extension.channels_wnd) {
this.extension.channels_wnd.close();
return;
}
var wnd = gw_new_popup(this.extension.controler.channels, 'up');
this.extension.channels_wnd = wnd;
wnd.extension = this.extension;

wnd.on_close = function () {
this.extension.channels_wnd = null;
}

chaps.forEach(chap => {
wnd.add_menu_item(chap.name, function () {
this.extension.movie_control.mediaStartTime = chap.start/1000.0;
});
});
wnd.on_display_size(gw_display_width, gw_display_height);
wnd.show();
}
}

if (this.services.length <= 1) {
this.controler.channels.hide();
this.controler.channels.on_click = function () { }
Expand Down
4 changes: 3 additions & 1 deletion share/gui/gwlib.js
Expand Up @@ -845,6 +845,8 @@ gwskin.images.view360 = 'icons/image.svg';
gwskin.labels.view360 = 'VR';
gwskin.images.sensors = 'icons/compass.svg';
gwskin.labels.sensors = 'Orientation';
gwskin.images.chapters = 'icons/chapter.svg';
gwskin.labels.chapters = 'Chapters';


gwskin.mime_video_default_ext = " mp4 mp4s m4s 3gp 3gpp m2ts ts trp m3u8 mpd avi mov ";
Expand Down Expand Up @@ -3649,7 +3651,7 @@ function gw_new_popup(anchor, type)
var s = children[i].get_label().length;
if (s>max_s) max_s = s;
}

max_s *= 0.66;
for (var i=0; i<children.length; i++) {
children[i].set_size(max_s * gwskin.default_text_font_size, gwskin.default_icon_height);
}
Expand Down
7 changes: 7 additions & 0 deletions share/gui/icons/chapter.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 32 additions & 4 deletions src/filter_core/filter_props.c
Expand Up @@ -945,7 +945,7 @@ GF_List *gf_props_get_list(GF_PropertyMap *map)
}
#endif

static void gf_props_assign_value(GF_PropertyEntry *prop, const GF_PropertyValue *value, Bool is_old_prop)
static GF_Err gf_props_assign_value(GF_PropertyEntry *prop, const GF_PropertyValue *value, Bool is_old_prop)
{
char *src_ptr;
//remember source pointer
Expand All @@ -960,6 +960,7 @@ static void gf_props_assign_value(GF_PropertyEntry *prop, const GF_PropertyValue

if (prop->prop.type == GF_PROP_STRING) {
prop->prop.value.string = value->value.string ? gf_strdup(value->value.string) : NULL;
if (value->value.string && !prop->prop.value.string) return GF_OUT_OF_MEM;
} else if (prop->prop.type == GF_PROP_STRING_NO_COPY) {
prop->prop.value.string = value->value.string;
prop->prop.type = GF_PROP_STRING;
Expand All @@ -969,6 +970,10 @@ static void gf_props_assign_value(GF_PropertyEntry *prop, const GF_PropertyValue
if (prop->alloc_size < value->value.data.size) {
prop->alloc_size = value->value.data.size;
prop->prop.value.data.ptr = gf_realloc(prop->prop.value.data.ptr, sizeof(char) * value->value.data.size);
if (!prop->prop.value.data.ptr) {
prop->alloc_size = 0;
return GF_OUT_OF_MEM;
}
assert(prop->alloc_size);
}
memcpy(prop->prop.value.data.ptr, value->value.data.ptr, value->value.data.size);
Expand All @@ -985,15 +990,31 @@ static void gf_props_assign_value(GF_PropertyEntry *prop, const GF_PropertyValue
else if (prop->prop.type == GF_PROP_SINT_LIST) it_size = sizeof(s32);
else if (prop->prop.type == GF_PROP_VEC2I_LIST) it_size = sizeof(GF_PropVec2i);
prop->prop.value.uint_list.vals = gf_malloc(it_size * value->value.uint_list.nb_items);
if (value->value.uint_list.nb_items)
memcpy(prop->prop.value.uint_list.vals, value->value.uint_list.vals, it_size * value->value.uint_list.nb_items);
if (!value->value.uint_list.nb_items) return GF_OUT_OF_MEM;
memcpy(prop->prop.value.uint_list.vals, value->value.uint_list.vals, it_size * value->value.uint_list.nb_items);
prop->prop.value.uint_list.nb_items = value->value.uint_list.nb_items;
}
else if (prop->prop.type == GF_PROP_STRING_LIST_COPY) {
u32 i;
prop->prop.type = GF_PROP_STRING_LIST;
prop->prop.value.string_list.nb_items = value->value.string_list.nb_items;
prop->prop.value.string_list.vals = gf_malloc(sizeof(char*)*value->value.string_list.nb_items);
if (!prop->prop.value.string_list.vals) return GF_OUT_OF_MEM;
memset(prop->prop.value.string_list.vals, 0, sizeof(char*)*value->value.string_list.nb_items);
for (i=0; i<prop->prop.value.string_list.nb_items; i++) {
if (value->value.string_list.vals[i]) {
prop->prop.value.string_list.vals[i] = gf_strdup(value->value.string_list.vals[i]);
if (!prop->prop.value.string_list.vals[i]) return GF_OUT_OF_MEM;
}
}
}
return GF_OK;
}

GF_Err gf_props_insert_property(GF_PropertyMap *map, u32 hash, u32 p4cc, const char *name, char *dyn_name, const GF_PropertyValue *value)
{
GF_PropertyEntry *prop;
GF_Err e;
#if GF_PROPS_HASHTABLE_SIZE
u32 i, count;
#endif
Expand Down Expand Up @@ -1039,7 +1060,11 @@ GF_Err gf_props_insert_property(GF_PropertyMap *map, u32 hash, u32 p4cc, const c
prop->name_alloc=GF_TRUE;
}

gf_props_assign_value(prop, value, GF_FALSE);
e = gf_props_assign_value(prop, value, GF_FALSE);
if (e) {
gf_props_del_property(prop);
return e;
}

#if GF_PROPS_HASHTABLE_SIZE
return gf_list_add(map->hash_table[hash], prop);
Expand Down Expand Up @@ -1558,6 +1583,9 @@ GF_BuiltInProperty GF_BuiltInProps [] =
{ GF_PROP_PID_IS_MANIFEST, "IsManifest", "PID is a HAS manifest", GF_PROP_BOOL, GF_PROP_FLAG_GSF_REM},
{ GF_PROP_PID_SPARSE, "Sparse", "PID has potentially empty times between packets", GF_PROP_BOOL, GF_PROP_FLAG_GSF_REM},

{ GF_PROP_PID_CHAP_TIMES, "ChapTimes", "Chapter start times", GF_PROP_UINT_LIST, GF_PROP_FLAG_GSF_REM},
{ GF_PROP_PID_CHAP_NAMES, "ChapNames", "Chapter names", GF_PROP_STRING_LIST, GF_PROP_FLAG_GSF_REM},

{ GF_PROP_PCK_SKIP_BEGIN, "SkipBegin", "Amount of media to skip from beginning of packet in PID timescale", GF_PROP_UINT, GF_PROP_FLAG_PCK},
{ GF_PROP_PCK_SKIP_PRES, "SkipPres", "Packet and any following with CTS greater than this packet shall not be presented (used by reframer to create edit lists)", GF_PROP_BOOL, GF_PROP_FLAG_PCK},

Expand Down

0 comments on commit 2969863

Please sign in to comment.