Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added reframer_ts_vtt filter. #7

Open
wants to merge 7 commits into
base: integration
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion include/gpac/internal/media_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,15 @@ void gf_media_format_ttxt_sdp(GP_RTPPacketizer *builder, char *payload_name, cha


#ifndef GPAC_DISABLE_VTT
#include <gpac/webvtt.h>

typedef enum {
WEBVTT_PARSER_STATE_WAITING_SIGNATURE,
WEBVTT_PARSER_STATE_WAITING_HEADER,
WEBVTT_PARSER_STATE_WAITING_CUE,
WEBVTT_PARSER_STATE_WAITING_CUE_TIMESTAMP,
WEBVTT_PARSER_STATE_WAITING_CUE_PAYLOAD
} GF_WebVTTParserState;

typedef struct _webvtt_parser GF_WebVTTParser;
typedef struct _webvtt_sample GF_WebVTTSample;
Expand All @@ -1141,11 +1150,11 @@ GF_Err gf_webvtt_parser_parse(GF_WebVTTParser *parser);
void gf_webvtt_parser_del(GF_WebVTTParser *parser);
void gf_webvtt_parser_suspend(GF_WebVTTParser *vttparser);
void gf_webvtt_parser_restart(GF_WebVTTParser *parser);
void gf_webvtt_parser_force_state(GF_WebVTTParser *parser, GF_WebVTTParserState state);
GF_Err gf_webvtt_parser_parse_payload(GF_WebVTTParser *parser, u64 start, u64 end, const char *vtt_pre, const char *vtt_cueid, const char *vtt_settings);
GF_Err gf_webvtt_parser_flush(GF_WebVTTParser *parser);
GF_Err gf_webvtt_parser_parse_ext(GF_WebVTTParser *parser, FILE *ext_file, Bool in_eos);

#include <gpac/webvtt.h>
void gf_webvtt_parser_cue_callback(GF_WebVTTParser *parser, void (*on_cue_read)(void *, GF_WebVTTCue *), void *udta);
GF_Err gf_webvtt_merge_cues(GF_WebVTTParser *parser, u64 start, GF_List *cues);
GF_Err gf_webvtt_parser_finalize(GF_WebVTTParser *parser, u64 duration);
Expand Down
2 changes: 2 additions & 0 deletions include/gpac/mpegts.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ extern "C" {
enum {
GF_M2TS_META_ID3 = GF_4CC('I','D','3',' '),
GF_M2TS_META_KLVA = GF_4CC('K','L','V','A'),
GF_M2TS_META_WVTT = GF_4CC('W','V','T','T'),
};


Expand Down Expand Up @@ -298,6 +299,7 @@ typedef enum
GF_M2TS_DVB_SUBTITLE = 0x154,
GF_M2TS_METADATA_ID3_HLS = 0x155,
GF_M2TS_METADATA_ID3_KLVA = 0x156,
GF_M2TS_METADATA_WVTT = 0x157,

} GF_M2TSStreamType;

Expand Down
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ endif
SCENEGRAPH_CFLAGS=
MEDIATOOLS_CFLAGS=

LIBGPAC_FILTERS+=filters/bs_agg.o filters/bs_split.o filters/bsrw.o filters/compose.o filters/dasher.o filters/dec_ac52.o filters/dec_bifs.o filters/dec_faad.o filters/dec_img.o filters/dec_j2k.o filters/dec_laser.o filters/dec_mad.o filters/dec_mediacodec.o filters/dec_nvdec.o filters/dec_nvdec_sdk.o filters/dec_odf.o filters/dec_theora.o filters/dec_ttml.o filters/dec_ttxt.o filters/dec_uncv.o filters/dec_vorbis.o filters/dec_vtb.o filters/dec_webvtt.o filters/dec_xvid.o filters/decrypt_cenc_isma.o filters/dmx_avi.o filters/dmx_dash.o filters/dmx_ghi.o filters/dmx_gsf.o filters/dmx_m2ts.o filters/dmx_mpegps.o filters/dmx_nhml.o filters/dmx_nhnt.o filters/dmx_ogg.o filters/dmx_saf.o filters/dmx_vobsub.o filters/enc_jpg.o filters/enc_png.o filters/encrypt_cenc_isma.o filters/evg_rescale.o filters/filelist.o filters/hevcmerge.o filters/hevcsplit.o filters/in_dvb4linux.o filters/in_file.o filters/in_http.o filters/in_pipe.o filters/in_route.o filters/in_route_repair.o filters/in_rtp.o filters/in_rtp_rtsp.o filters/in_rtp_sdp.o filters/in_rtp_signaling.o filters/in_rtp_stream.o filters/in_sock.o filters/inspect.o filters/io_fcryp.o filters/isoffin_load.o filters/isoffin_read.o filters/isoffin_read_ch.o filters/jsfilter.o filters/load_bt_xmt.o filters/load_svg.o filters/load_text.o filters/mux_avi.o filters/mux_gsf.o filters/mux_isom.o filters/mux_ts.o filters/mux_ogg.o filters/out_audio.o filters/out_file.o filters/out_http.o filters/out_pipe.o filters/out_route.o filters/out_rtp.o filters/out_rtsp.o filters/out_sock.o filters/out_video.o filters/reframer.o filters/reframe_ac3.o filters/reframe_adts.o filters/reframe_latm.o filters/reframe_amr.o filters/reframe_av1.o filters/reframe_flac.o filters/reframe_h263.o filters/reframe_img.o filters/reframe_mhas.o filters/reframe_mp3.o filters/reframe_mpgvid.o filters/reframe_nalu.o filters/reframe_prores.o filters/reframe_qcp.o filters/reframe_rawvid.o filters/reframe_rawpcm.o filters/reframe_truehd.o filters/resample_audio.o filters/restamp.o filters/tileagg.o filters/tilesplit.o filters/tssplit.o filters/ttml_conv.o filters/unit_test_filter.o filters/rewind.o filters/rewrite_adts.o filters/rewrite_mhas.o filters/rewrite_mp4v.o filters/rewrite_nalu.o filters/rewrite_obu.o filters/vflip.o filters/vcrop.o filters/write_generic.o filters/write_nhml.o filters/write_nhnt.o filters/write_qcp.o filters/write_tx3g.o filters/write_vtt.o ../modules/dektec_out/dektec_video_decl.o filters/dec_opensvc.o filters/unframer.o filters/dec_scte35.o
LIBGPAC_FILTERS+=filters/bs_agg.o filters/bs_split.o filters/bsrw.o filters/compose.o filters/dasher.o filters/dec_ac52.o filters/dec_bifs.o filters/dec_faad.o filters/dec_img.o filters/dec_j2k.o filters/dec_laser.o filters/dec_mad.o filters/dec_mediacodec.o filters/dec_nvdec.o filters/dec_nvdec_sdk.o filters/dec_odf.o filters/dec_theora.o filters/dec_ttml.o filters/dec_ttxt.o filters/dec_uncv.o filters/dec_vorbis.o filters/dec_vtb.o filters/dec_webvtt.o filters/dec_xvid.o filters/decrypt_cenc_isma.o filters/dmx_avi.o filters/dmx_dash.o filters/dmx_ghi.o filters/dmx_gsf.o filters/dmx_m2ts.o filters/dmx_mpegps.o filters/dmx_nhml.o filters/dmx_nhnt.o filters/dmx_ogg.o filters/dmx_saf.o filters/dmx_vobsub.o filters/enc_jpg.o filters/enc_png.o filters/encrypt_cenc_isma.o filters/evg_rescale.o filters/filelist.o filters/hevcmerge.o filters/hevcsplit.o filters/in_dvb4linux.o filters/in_file.o filters/in_http.o filters/in_pipe.o filters/in_route.o filters/in_route_repair.o filters/in_rtp.o filters/in_rtp_rtsp.o filters/in_rtp_sdp.o filters/in_rtp_signaling.o filters/in_rtp_stream.o filters/in_sock.o filters/inspect.o filters/io_fcryp.o filters/isoffin_load.o filters/isoffin_read.o filters/isoffin_read_ch.o filters/jsfilter.o filters/load_bt_xmt.o filters/load_svg.o filters/load_text.o filters/mux_avi.o filters/mux_gsf.o filters/mux_isom.o filters/mux_ts.o filters/mux_ogg.o filters/out_audio.o filters/out_file.o filters/out_http.o filters/out_pipe.o filters/out_route.o filters/out_rtp.o filters/out_rtsp.o filters/out_sock.o filters/out_video.o filters/reframer.o filters/reframe_ac3.o filters/reframe_adts.o filters/reframe_latm.o filters/reframe_amr.o filters/reframe_av1.o filters/reframe_flac.o filters/reframe_h263.o filters/reframe_img.o filters/reframe_mhas.o filters/reframe_mp3.o filters/reframe_mpgvid.o filters/reframe_nalu.o filters/reframe_prores.o filters/reframe_qcp.o filters/reframe_rawvid.o filters/reframe_rawpcm.o filters/reframe_truehd.o filters/resample_audio.o filters/restamp.o filters/tileagg.o filters/tilesplit.o filters/tssplit.o filters/ttml_conv.o filters/unit_test_filter.o filters/rewind.o filters/rewrite_adts.o filters/rewrite_mhas.o filters/rewrite_mp4v.o filters/rewrite_nalu.o filters/rewrite_obu.o filters/vflip.o filters/vcrop.o filters/write_generic.o filters/write_nhml.o filters/write_nhnt.o filters/write_qcp.o filters/write_tx3g.o filters/reframe_ts_wvtt.o filters/write_vtt.o ../modules/dektec_out/dektec_video_decl.o filters/dec_opensvc.o filters/unframer.o filters/dec_scte35.o
LIBGPAC_FILTERS_FFMPEG=filters/ff_common.o filters/ff_avf.o filters/ff_dec.o filters/ff_dmx.o filters/ff_enc.o filters/ff_rescale.o filters/ff_mx.o filters/ff_bsf.o
LIBGPAC_FILTERS_LIBCAPTION=filters/dec_cc.o
LIBGPAC_FILTERS_MPEGHDEC=filters/dec_mpeghdec.o
Expand Down
4 changes: 3 additions & 1 deletion src/filter_core/filter_register.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ REG_DEC(writegen)
REG_DEC(ufnalu)
REG_DEC(writeqcp)
REG_DEC(ufvtt)
REG_DEC(rftsvtt)
estigma88 marked this conversation as resolved.
Show resolved Hide resolved
REG_DEC(nhntw)
REG_DEC(nhmlw)
REG_DEC(vobsubdmx)
Expand Down Expand Up @@ -205,7 +206,7 @@ typedef struct

#define REG_IT(__n) { #__n , __n##_register }

BuiltinReg BuiltinFilters [] = {
BuiltinReg BuiltinFilters[] = {
REG_IT(inspect),
REG_IT(probe),
REG_IT(compositor),
Expand Down Expand Up @@ -270,6 +271,7 @@ BuiltinReg BuiltinFilters [] = {
REG_IT(ufnalu),
REG_IT(writeqcp),
REG_IT(ufvtt),
REG_IT(rftsvtt),
REG_IT(nhntw),
REG_IT(nhmlw),
REG_IT(vobsubdmx),
Expand Down
24 changes: 19 additions & 5 deletions src/filters/dmx_m2ts.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,11 @@ static void m2tsdmx_declare_pid(GF_M2TSDmxCtx *ctx, GF_M2TS_PES *stream, GF_ESD
//fallthrough
case GF_M2TS_SCTE35_SPLICE_INFO_SECTIONS:
return; //ignore actively: these streams will be attached verbatim as properties to audio and/or video packets
case GF_M2TS_METADATA_WVTT:
stype = GF_STREAM_TEXT;
codecid = GF_M2TS_META_WVTT;
stream->flags |= GF_M2TS_ES_FULL_AU;
break;
default:
GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[M2TSDmx] Stream type 0x%02X not supported - ignoring pid\n", stream->stream_type));
return;
Expand All @@ -431,13 +436,15 @@ static void m2tsdmx_declare_pid(GF_M2TSDmxCtx *ctx, GF_M2TS_PES *stream, GF_ESD
for (i=0; i<gf_filter_get_opid_count(ctx->filter); i++) {
opid = gf_filter_get_opid(ctx->filter, i);
const GF_PropertyValue *p = gf_filter_pid_get_property(opid, GF_PROP_PID_ID);
if (p && (p->value.uint == stream->pid))
if (p && (p->value.uint == stream->pid)) {
break;
}
opid = NULL;
}

if (!opid)
if (!opid) {
opid = gf_filter_pid_new(ctx->filter);
}

stream->user = opid;
stream->flags |= GF_M2TS_ES_ALREADY_DECLARED;
Expand Down Expand Up @@ -591,7 +598,6 @@ static void m2tsdmx_declare_pid(GF_M2TSDmxCtx *ctx, GF_M2TS_PES *stream, GF_ESD
}

m2tsdmx_update_sdt(ctx->ts, opid);

gf_m2ts_set_pes_framing((GF_M2TS_PES *)stream, GF_M2TS_PES_FRAMING_DEFAULT);
}

Expand Down Expand Up @@ -745,7 +751,10 @@ static void m2tsdmx_send_packet(GF_M2TSDmxCtx *ctx, GF_M2TS_PES_PCK *pck)

/*pcr not initialized, don't send any data*/
// if (! pck->stream->program->first_dts) return;
if (!pck->stream->user) return;

if (!pck->stream->user) {
return;
}
opid = pck->stream->user;

u8 *ptr = pck->data;
Expand Down Expand Up @@ -795,6 +804,8 @@ static void m2tsdmx_send_packet(GF_M2TSDmxCtx *ctx, GF_M2TS_PES_PCK *pck)
}


// if (pck->stream->pid == 65) GF_LOG(GF_LOG_ERROR, GF_LOG_CONDITION, ("m2tsdmx_send_packet: creating packet %llu\n", len));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need it?


dst_pck = gf_filter_pck_new_alloc(opid, len, &data);
if (!dst_pck) return;
memcpy(data, ptr, len);
Expand Down Expand Up @@ -1337,8 +1348,11 @@ static GF_Err m2tsdmx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool i
}
return GF_OK;
}
if (! gf_filter_pid_check_caps(pid))

if (! gf_filter_pid_check_caps(pid)) {
GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TSDMx] caps not supported \"%s\"\n", gf_filter_pid_get_name(pid)));
return GF_NOT_SUPPORTED;
}

//by default for all URLs, send packets as soon as the program is configured
ctx->mux_tune_state = DMX_TUNE_DONE;
Expand Down
233 changes: 233 additions & 0 deletions src/filters/reframe_ts_wvtt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
#include <gpac/filters.h>
#include <gpac/constants.h>
#include <gpac/bitstream.h>
#include <gpac/webvtt.h>
#include <gpac/mpegts.h>
#include <gpac/internal/media_dev.h>
#include <gpac/internal/isomedia_dev.h>

#include <stdio.h>

#ifndef GPAC_DISABLE_VTT


#define REFRAME_TS_WVTT_DEFAULT_TIMESCALE 90000

///////////////////////////////////////////////////////////////////////////////

typedef struct
{
u32 timescale;
GF_FilterPid *ipid;
GF_FilterPid *opid;
} GF_ReframeTsVttCtx;

///////////////////////////////////////////////////////////////////////////////
// Callbacks for WebVTT parser

static GF_Err reframe_ts_wvtt_parse_callback_report(void *user, GF_Err e, char *message, const char *line) {
GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("reframe_ts_wvtt_parse_callback_report: line: %s, message: %s\n", line, message));
return e;
}

static void reframe_ts_wvtt_parse_callback_header(void *user, const char *config)
{
// nothing to do
}

static void reframe_ts_wvtt_parse_callback_sample(void *user, GF_WebVTTSample *sample) {

if (!sample) {
return;
}

// in milliseconds
u64 start = gf_webvtt_sample_get_start(sample);
u64 end = gf_webvtt_sample_get_end(sample);

if (!gf_isom_webvtt_cues_count(sample)) {
return;
}

GF_ISOSample *iso_sample = NULL;
iso_sample = gf_isom_webvtt_to_sample(sample);
jadarve marked this conversation as resolved.
Show resolved Hide resolved

if (iso_sample) {
GF_ReframeTsVttCtx* ctx = (GF_ReframeTsVttCtx*) user;
GF_FilterPacket *pck;
u8 *pck_data;

pck = gf_filter_pck_new_alloc(ctx->opid, iso_sample->dataLength, &pck_data);
if (pck)
{
memcpy(pck_data, iso_sample->data, iso_sample->dataLength);
gf_filter_pck_set_cts(pck, (u64)(ctx->timescale * start / 1000));
gf_filter_pck_set_sap(pck, GF_FILTER_SAP_1);

if (end && (end >= start))
{
gf_filter_pck_set_duration(pck, (u32)(ctx->timescale * (end - start) / 1000));
}
gf_filter_pck_send(pck);
}

gf_isom_sample_del(&iso_sample);
}

gf_webvtt_sample_del(sample);
}

static void reframe_ts_wvtt_cue_callback(void *user, GF_WebVTTCue *cue) {
// nothing to do
}


///////////////////////////////////////////////////////////////////////////////
// Filter callbacks

static GF_Err reframe_ts_wvtt_initialize(GF_Filter *filter)
{
return GF_OK;
}

GF_Err reframe_ts_wvtt_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
{
GF_ReframeTsVttCtx *ctx = gf_filter_get_udta(filter);

if (is_remove)
{
GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("reframe_ts_wvtt_configure_pid: is_remove\n"));
ctx->ipid = NULL;
if (ctx->opid) {
gf_filter_pid_remove(ctx->opid);
ctx->opid = NULL;
}
return GF_OK;
}

if (!gf_filter_pid_check_caps(pid)) {
GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("reframe_ts_wvtt_configure_pid: not supported\n"));
return GF_NOT_SUPPORTED;
}

GF_PropertyValue *p = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
if (!p) {
GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("reframe_ts_wvtt_configure_pid: no codec id\n"));
return GF_NOT_SUPPORTED;
}

char *pid_name = gf_filter_pid_get_name(pid);

GF_PropertyValue* timescale = gf_filter_pid_get_property(pid, GF_PROP_PID_TIMESCALE);
if (!timescale) {
GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("reframe_ts_wvtt_configure_pid: no timescale using default value\n"));
ctx->timescale = REFRAME_TS_WVTT_DEFAULT_TIMESCALE;
} else {
ctx->timescale = timescale->value.uint;
}

ctx->ipid = pid;
ctx->opid = gf_filter_pid_new(filter);

// configure output PID properties
gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA((u8 *)"WEBVTT", 7));
gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_DATA((u8 *)"text/vtt", 9));
gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_TEXT));
gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_WEBVTT));
gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, &PROP_BOOL(GF_FALSE));
gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_TIMESCALE, &PROP_UINT(ctx->timescale));

return GF_OK;
}

GF_Err reframe_ts_wvtt_process(GF_Filter *filter)
{
GF_ReframeTsVttCtx *ctx = gf_filter_get_udta(filter);
GF_FilterPacket *pck = NULL;
u32 pck_size;
u8 *pck_data = NULL;
// u64 start_ts, end_ts;

// GF_List *cues;
// Bool keep_ref = GF_TRUE;

pck = gf_filter_pid_get_packet(ctx->ipid);
if (!pck) {
if (gf_filter_pid_is_eos(ctx->ipid)) {
gf_filter_pid_set_eos(ctx->opid);
return GF_EOS;
}
return GF_OK;
}

pck_data = (char *)gf_filter_pck_get_data(pck, &pck_size);
// GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("reframe_ts_wvtt_process: len %d\n", pck_size));


///////////////////////////////////////////////////////
GF_WebVTTParser *parser = gf_webvtt_parser_new();

// create a memory file to read the packet data
FILE *mem_file = fmemopen(pck_data, pck_size, "r");

// Assume UTF-8 encoding
gf_webvtt_parser_init(parser, mem_file, 0, GF_FALSE, ctx, reframe_ts_wvtt_parse_callback_report, reframe_ts_wvtt_parse_callback_sample, reframe_ts_wvtt_parse_callback_header);

// as the input packets do not contain the WEBVTT signature at the beginning
// we have to force the parser to start looking for cues immediately
gf_webvtt_parser_force_state(parser, WEBVTT_PARSER_STATE_WAITING_CUE);

// the parser will call reframe_ts_wvtt_parse_callback_sample for each sample found
gf_webvtt_parser_parse(parser);
gf_webvtt_parser_del(parser);

///////////////////////////////////////////////////////
// cleanup
gf_filter_pid_drop_packet(ctx->ipid);
fclose(mem_file);

return GF_OK;
}

static void reframe_ts_wvtt_finalize(GF_Filter *filter)
{
// nothing to do
}

static const GF_FilterCapability ReframeTsVttCaps[] =
{
// receive a text stream using the custom 4CC code for WVTT in TS
CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_TEXT),
CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_CODECID, GF_M2TS_META_WVTT),

// then, produce a Metadata stream with WebVTT cues
CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_TEXT),
CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_WEBVTT),
CAP_BOOL(GF_CAPS_OUTPUT, GF_PROP_PID_UNFRAMED, GF_FALSE),
{0},
};

#define OFFS(_n) #_n, offsetof(GF_ReframeTsVttCtx, _n)

GF_FilterRegister ReframeTsWebVTT = {
.name = "rftsvtt",
GF_FS_SET_DESCRIPTION("Reframer for WebVTT subtitles in Transport Stream")
GF_FS_SET_HELP("Transform Transport Stream PES metadata content to WebVTT cues")
.private_size = sizeof(GF_ReframeTsVttCtx),
.initialize = reframe_ts_wvtt_initialize,
.finalize = reframe_ts_wvtt_finalize,
SETCAPS(ReframeTsVttCaps),
.configure_pid = reframe_ts_wvtt_configure_pid,
.process = reframe_ts_wvtt_process};

const GF_FilterRegister *rftsvtt_register(GF_FilterSession *session)
{
return &ReframeTsWebVTT;
}
#else
const GF_FilterRegister *rftsvtt_register(GF_FilterSession *session)
{
return NULL;
}

#endif /*GPAC_DISABLE_VTT*/
Loading