Skip to content

Commit

Permalink
support for isobmff rsot in muxer
Browse files Browse the repository at this point in the history
  • Loading branch information
jeanlf committed May 15, 2024
1 parent 618ecc5 commit 55a5d64
Show file tree
Hide file tree
Showing 12 changed files with 145 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/gpac/filters.h
Original file line number Diff line number Diff line change
Expand Up @@ -1344,6 +1344,7 @@ enum
//we also use this property on PID to signal sample-accurate seek info is present
GF_PROP_PCK_SKIP_BEGIN = GF_4CC('P','C','K','S'),
GF_PROP_PCK_SKIP_PRES = GF_4CC('P','C','K','D'),
GF_PROP_PCK_ORIG_DUR = GF_4CC('P','C','O','D'),
//internal for DASH forward mode
GF_PROP_PID_DASH_FWD = GF_4CC('D','F','W','D'),
GF_PROP_PCK_DASH_MANIFEST = GF_4CC('D','M','P','D'),
Expand Down
10 changes: 10 additions & 0 deletions include/gpac/internal/isomedia_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ enum
GF_ISOM_BOX_TYPE_LEVA = GF_4CC( 'l', 'e', 'v', 'a' ),
GF_ISOM_BOX_TYPE_PCRB = GF_4CC( 'p', 'c', 'r', 'b' ),
GF_ISOM_BOX_TYPE_EMSG = GF_4CC( 'e', 'm', 's', 'g' ),
GF_ISOM_BOX_TYPE_RSOT = GF_4CC( 'r', 's', 'o', 't' ),

/*3GPP text / MPEG-4 StreamingText*/
GF_ISOM_BOX_TYPE_FTAB = GF_4CC( 'f', 't', 'a', 'b' ),
Expand Down Expand Up @@ -2708,6 +2709,14 @@ typedef struct
u64 baseMediaDecodeTime;
} GF_TFBaseMediaDecodeTimeBox;


typedef struct
{
GF_ISOM_FULL_BOX
u32 original_duration;
u32 elapsed_duration;
} GF_TFOriginalDurationBox;

typedef struct
{
GF_ISOM_BOX
Expand Down Expand Up @@ -2735,6 +2744,7 @@ typedef struct
/*when data caching is on*/
u32 DataCache;
GF_TFBaseMediaDecodeTimeBox *tfdt;
GF_TFOriginalDurationBox *rsot;

u64 moof_start_in_bs;
#ifdef GF_ENABLE_CTRN
Expand Down
10 changes: 10 additions & 0 deletions include/gpac/isomedia.h
Original file line number Diff line number Diff line change
Expand Up @@ -4737,6 +4737,16 @@ GF_Err gf_isom_allocate_sidx(GF_ISOFile *isom_file, s32 subsegs_per_sidx, Bool d
*/
GF_Err gf_isom_setup_track_fragment_template(GF_ISOFile *isom_file, GF_ISOTrackID TrackID, u8 *boxes, u32 boxes_size, u8 force_traf_flags);

/*! sets up track fragment defaults using the given template. The template shall be a serialized array of one or more trex boxes
\param isom_file the target ISO file
\param TrackID ID of the target track
\param orig_dur last sample original duration
\param elapsed_dur first sample elapsed duration
\return error if any
*/
GF_Err gf_isom_set_fragment_original_duration(GF_ISOFile *movie, GF_ISOTrackID TrackID, u32 orig_dur, u32 elapsed_dur);

#ifdef GF_ENABLE_CTRN
/*! enables track fragment inheriting from a given traf.
This shall only be set when the inherited traf shares exactly the same syntax except the sample sizes, this library does not compute which
Expand Down
2 changes: 2 additions & 0 deletions share/doc/man/gpac-filters.1
Original file line number Diff line number Diff line change
Expand Up @@ -2543,6 +2543,8 @@ uncv (enum, default: prof): use uncv (ISO 23001-17) for raw video
.br
trunv1 (bool, default: false): force using version 1 of trun regardless of media type or CMAF brand
.br
rsot (bool, default: false): inject redundant sample timing info when ^resent
.br

.br
.SH rfqcp
Expand Down
5 changes: 5 additions & 0 deletions share/doc/man/gpac.1
Original file line number Diff line number Diff line change
Expand Up @@ -4022,6 +4022,11 @@ Amount of media to skip from beginning of packet in PID timescale
Packet and any following with CTS greater than this packet shall not be presented (used by reframer to create edit lists)
.br
.TP
.B OriginalDuration (PCOD,frac, P)
.br
Elapsed time (.num) and original duration (.den, 0 if last copy of packet) for redundant packets
.br
.TP
.B HLSRef (HPLR,luint,DP)
.br
HLS playlist reference, gives a unique ID identifying media mux, and indicated in packets carrying child playlists
Expand Down
1 change: 1 addition & 0 deletions src/filter_core/filter_props.c
Original file line number Diff line number Diff line change
Expand Up @@ -1694,6 +1694,7 @@ GF_BuiltInProperty GF_BuiltInProps [] =

DEC_PROP_F( 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),
DEC_PROP_F( 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),
DEC_PROP_F( GF_PROP_PCK_ORIG_DUR, "OriginalDuration", "Elapsed time (.num) and original duration (.den, 0 if last copy of packet) for redundant packets", GF_PROP_FRACTION, GF_PROP_FLAG_PCK),

DEC_PROP_F( GF_PROP_PCK_HLS_REF, "HLSRef", "HLS playlist reference, gives a unique ID identifying media mux, and indicated in packets carrying child playlists", GF_PROP_LUINT, GF_PROP_FLAG_PCK|GF_PROP_FLAG_GSF_REM),
DEC_PROP_F( GF_PROP_PID_LLHLS, "LLHLS", "HLS low latency mode", GF_PROP_UINT, GF_PROP_FLAG_GSF_REM),
Expand Down
12 changes: 12 additions & 0 deletions src/filters/dasher.c
Original file line number Diff line number Diff line change
Expand Up @@ -9636,6 +9636,11 @@ static GF_Err dasher_process(GF_Filter *filter)
u64 diff=0;
u8 dep_flags = gf_filter_pck_get_dependency_flags(pck);
u64 ts = gf_filter_pck_get_cts(pck);
GF_Fraction pck_orig_dur;
pck_orig_dur.num = split_dur_next;
pck_orig_dur.den = split_dur ? gf_filter_pck_get_duration(pck) : 0;
gf_filter_pck_set_property(dst, GF_PROP_PCK_ORIG_DUR, &PROP_FRAC(pck_orig_dur));

if (ts != GF_FILTER_NO_TS) {
cts += ds->first_cts;
gf_assert(cts >= ts);
Expand Down Expand Up @@ -9664,9 +9669,16 @@ static GF_Err dasher_process(GF_Filter *filter)

//if split, adjust duration - this may happen on a split packet, if it covered 3 or more segments
if (split_dur) {
GF_Fraction pck_orig_dur;
u32 cumulated_split_dur = split_dur;
if (dst)
gf_filter_pck_set_duration(dst, split_dur);

//original dur
pck_orig_dur.num = ds->split_dur_next;
pck_orig_dur.den = dur;
gf_filter_pck_set_property(dst, GF_PROP_PCK_ORIG_DUR, &PROP_FRAC(pck_orig_dur));

//adjust dur
cumulated_split_dur += (u32) (cts - orig_cts);
gf_assert( dur > split_dur);
Expand Down
8 changes: 7 additions & 1 deletion src/filters/mux_isom.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ typedef struct
Bool m4sys, dref;
GF_Fraction dur;
u32 pack3gp, ctmode;
Bool importer, pack_nal, moof_first, abs_offset, fsap, tfdt_traf, keep_utc, pps_inband;
Bool importer, pack_nal, moof_first, abs_offset, fsap, tfdt_traf, keep_utc, pps_inband, rsot;
u32 xps_inband, moovpad;
u32 block_size;
u32 store, tktpl, mudta;
Expand Down Expand Up @@ -6686,6 +6686,11 @@ static GF_Err mp4_mux_process_fragmented(GF_MP4MuxCtx *ctx)
//process packet
e = mp4_mux_process_sample(ctx, tkw, pck, GF_TRUE);

p = ctx->rsot ? gf_filter_pck_get_property(pck, GF_PROP_PCK_ORIG_DUR) : NULL;
if (p) {
gf_isom_set_fragment_original_duration(ctx->file, tkw->track_id, p->value.frac.den, (u32) p->value.frac.num);
}

//discard
gf_filter_pid_drop_packet(tkw->ipid);

Expand Down Expand Up @@ -8339,6 +8344,7 @@ static const GF_FilterArgs MP4MuxArgs[] =
"- prof: enabled and write profile if known\n"
"- tiny: enabled and write reduced version if profile known and compatible", GF_PROP_UINT, "prof", "off|gen|prof|tiny", GF_FS_ARG_HINT_EXPERT},
{ OFFS(trunv1), "force using version 1 of trun regardless of media type or CMAF brand", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT},
{ OFFS(rsot), "inject redundant sample timing info when ^resent", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT},
{0}
};

Expand Down
66 changes: 66 additions & 0 deletions src/isomedia/box_code_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -6509,6 +6509,9 @@ GF_Err traf_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem)
case GF_ISOM_BOX_TYPE_TFDT:
BOX_FIELD_ASSIGN(tfdt, GF_TFBaseMediaDecodeTimeBox)
return GF_OK;
case GF_ISOM_BOX_TYPE_RSOT:
BOX_FIELD_ASSIGN(rsot, GF_TFOriginalDurationBox)
return GF_OK;
case GF_ISOM_BOX_TYPE_SUBS:
BOX_FIELD_LIST_ASSIGN(sub_samples)
return GF_OK;
Expand Down Expand Up @@ -6592,6 +6595,7 @@ GF_Err traf_box_size(GF_Box *s)
gf_isom_check_position_list(s, ptr->sub_samples, &pos);

gf_isom_check_position(s, (GF_Box *)ptr->tfdt, &pos);
gf_isom_check_position(s, (GF_Box *)ptr->rsot, &pos);

//cmaf-like
if (ptr->truns_first) {
Expand Down Expand Up @@ -9801,6 +9805,68 @@ GF_Err tfdt_box_size(GF_Box *s)

#endif /*GPAC_DISABLE_ISOM_WRITE*/

GF_Box *rsot_box_new()
{
ISOM_DECL_BOX_ALLOC(GF_TFOriginalDurationBox, GF_ISOM_BOX_TYPE_RSOT);
return (GF_Box *)tmp;
}

void rsot_box_del(GF_Box *s)
{
gf_free(s);
}

/*this is using chpl format according to some NeroRecode samples*/
GF_Err rsot_box_read(GF_Box *s,GF_BitStream *bs)
{
GF_TFOriginalDurationBox *ptr = (GF_TFOriginalDurationBox *)s;

if (ptr->flags & 1) {
ISOM_DECREASE_SIZE(ptr, 4);
ptr->original_duration = gf_bs_read_u32(bs);
}
if (ptr->flags & 2) {
ISOM_DECREASE_SIZE(ptr, 4);
ptr->elapsed_duration = (u32) gf_bs_read_u32(bs);
}
return GF_OK;
}

#ifndef GPAC_DISABLE_ISOM_WRITE

GF_Err rsot_box_write(GF_Box *s, GF_BitStream *bs)
{
GF_Err e;
GF_TFOriginalDurationBox *ptr = (GF_TFOriginalDurationBox *) s;
e = gf_isom_full_box_write(s, bs);
if (e) return e;

if (ptr->flags & 1) {
gf_bs_write_u32(bs, ptr->original_duration);
}
if (ptr->flags & 2) {
gf_bs_write_u32(bs, (u32) ptr->elapsed_duration);
}
return GF_OK;
}

GF_Err rsot_box_size(GF_Box *s)
{
GF_TFOriginalDurationBox *ptr = (GF_TFOriginalDurationBox *)s;

if (ptr->original_duration) {
ptr->flags |= 1;
ptr->size+=4;
}
if (ptr->elapsed_duration) {
ptr->flags |= 2;
ptr->size+=4;
}
return GF_OK;
}

#endif /*GPAC_DISABLE_ISOM_WRITE*/

#endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/


Expand Down
11 changes: 11 additions & 0 deletions src/isomedia/box_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -5204,6 +5204,17 @@ GF_Err tfdt_box_dump(GF_Box *a, FILE * trace)
gf_isom_box_dump_done("TrackFragmentBaseMediaDecodeTimeBox", a, trace);
return GF_OK;
}
GF_Err rsot_box_dump(GF_Box *a, FILE * trace)
{
GF_TFOriginalDurationBox *ptr = (GF_TFOriginalDurationBox*) a;
if (!a) return GF_BAD_PARAM;
gf_isom_box_dump_start(a, "RedundantSampleOriginalTimingBox", trace);
if (ptr->flags & 1) gf_fprintf(trace, " originalDuration=\"%u\"", ptr->original_duration);
if (ptr->flags & 2) gf_fprintf(trace, " elapsedDuration=\"%u\"", ptr->elapsed_duration);
gf_fprintf(trace, ">\n");
gf_isom_box_dump_done("RedundantSampleOriginalTimingBox", a, trace);
return GF_OK;
}
#endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/

GF_Err rvcc_box_dump(GF_Box *a, FILE * trace)
Expand Down
2 changes: 2 additions & 0 deletions src/isomedia/box_funcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,7 @@ ISOM_BOX_IMPL_DECL(ssix)
ISOM_BOX_IMPL_DECL(leva)
ISOM_BOX_IMPL_DECL(pcrb)
ISOM_BOX_IMPL_DECL(tfdt)
ISOM_BOX_IMPL_DECL(rsot)
ISOM_BOX_IMPL_DECL(emsg)

#endif
Expand Down Expand Up @@ -1310,6 +1311,7 @@ static struct box_registry_entry {
FBOX_DEFINE_FLAGS(GF_ISOM_BOX_TYPE_CTRN, trun, "traf", 0, 0),
#endif
FBOX_DEFINE( GF_ISOM_BOX_TYPE_TFDT, tfdt, "traf", 1),
FBOX_DEFINE_FLAGS(GF_ISOM_BOX_TYPE_RSOT, rsot, "traf", 0, 0x000001|0x000002),
BOX_DEFINE( GF_ISOM_BOX_TYPE_STYP, ftyp, "file"),
FBOX_DEFINE( GF_ISOM_BOX_TYPE_PRFT, prft, "file", 1),
FBOX_DEFINE( GF_ISOM_BOX_TYPE_SIDX, sidx, "file", 1),
Expand Down
18 changes: 18 additions & 0 deletions src/isomedia/movie_fragments.c
Original file line number Diff line number Diff line change
Expand Up @@ -3148,6 +3148,24 @@ GF_Err gf_isom_fragment_add_subsample(GF_ISOFile *movie, GF_ISOTrackID TrackID,
return gf_isom_add_subsample_info(subs, last_sample, subSampleSize, priority, reserved, discardable);
}


GF_Err gf_isom_set_fragment_original_duration(GF_ISOFile *movie, GF_ISOTrackID TrackID, u32 orig_dur, u32 elapsed_dur)
{
GF_TrackFragmentBox *traf;
if (!movie->moof || !(movie->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY) ) return GF_BAD_PARAM;

traf = gf_isom_get_traf(movie, TrackID);
if (!traf) return GF_BAD_PARAM;

if (!traf->rsot) {
traf->rsot = (GF_TFOriginalDurationBox *) gf_isom_box_new_parent(&traf->child_boxes, GF_ISOM_BOX_TYPE_RSOT);
if (!traf->rsot) return GF_OUT_OF_MEM;
}
if (orig_dur) traf->rsot->original_duration = orig_dur;
if (elapsed_dur) traf->rsot->elapsed_duration = elapsed_dur;
return GF_OK;
}

#if 0 //unused
static GF_Err gf_isom_copy_sample_group_entry_to_traf(GF_TrackFragmentBox *traf, GF_SampleTableBox *stbl, u32 grouping_type, u32 grouping_type_parameter, u32 sampleGroupDescriptionIndex, Bool sgpd_in_traf)
{
Expand Down

0 comments on commit 55a5d64

Please sign in to comment.