Skip to content
Draft
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
1 change: 1 addition & 0 deletions doc/overview.mkdoc
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
@item @ref upipe_a52f_mgr_alloc @item linear pipe gathering A52 audio streams into frames @item @tt -lupipe-framers
@item @ref upipe_telxf_mgr_alloc @item linear pipe gathering teletext streams into frames @item @tt -lupipe-framers
@item @ref upipe_dvbsubf_mgr_alloc @item linear pipe gathering DVB subtitling streams into frames @item @tt -lupipe-framers
@item @ref upipe_ttmlf_mgr_alloc @item linear pipe gathering DVB TTML subtitling streams into frames @item @tt -lupipe-framers
@item @ref upipe_vtrim_mgr_alloc @item pipe trimming dead frames off a video stream @item @tt -lupipe-framers
@item @ref upipe_ffmt_mgr_alloc @item linear pipe transforming the format into another specified (potentially for an encoder) @item @tt -lupipe-filters
@item @ref upipe_fdec_mgr_alloc @item linear pipe decoding a stream @item @tt -lupipe-filters
Expand Down
2 changes: 2 additions & 0 deletions include/upipe-framers/upipe_auto_framer.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ enum upipe_autof_mgr_command {
UPIPE_AUTOF_MGR_GET_SET_MGR(opusf, OPUSF)
UPIPE_AUTOF_MGR_GET_SET_MGR(s302f, S302F)
UPIPE_AUTOF_MGR_GET_SET_MGR(id3v2f, ID3V2F)
UPIPE_AUTOF_MGR_GET_SET_MGR(ttmlf, TTMLF)
#undef UPIPE_AUTOF_MGR_GET_SET_MGR
};

Expand Down Expand Up @@ -93,6 +94,7 @@ UPIPE_AUTOF_MGR_GET_SET_MGR2(telxf, TELXF)
UPIPE_AUTOF_MGR_GET_SET_MGR2(dvbsubf, DVBSUBF)
UPIPE_AUTOF_MGR_GET_SET_MGR2(opusf, OPUSF)
UPIPE_AUTOF_MGR_GET_SET_MGR2(s302f, S302F)
UPIPE_AUTOF_MGR_GET_SET_MGR2(ttmlf, TTMLF)
#undef UPIPE_AUTOF_MGR_GET_SET_MGR2

#ifdef __cplusplus
Expand Down
36 changes: 36 additions & 0 deletions include/upipe-framers/upipe_ttml_framer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2026 Open Broadcast Systems Ltd
*
* Authors: Kieran Kunhya
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/

/** @file
* @short Upipe module building frames from chunks of a DVB TTML subtitle
* stream
*/

#ifndef _UPIPE_FRAMERS_UPIPE_TTML_FRAMER_H_
/** @hidden */
#define _UPIPE_FRAMERS_UPIPE_TTML_FRAMER_H_
#ifdef __cplusplus
extern "C" {
#endif

#include "upipe/upipe.h"

#define UPIPE_TTMLF_SIGNATURE UBASE_FOURCC('t','t','m','f')
/** We only accept the EN 303 560 PES data fields. */
#define UPIPE_TTMLF_EXPECTED_FLOW_DEF "block.dvb_ttml_subtitle."

/** @This returns the management structure for all ttmlf pipes.
*
* @return pointer to manager
*/
struct upipe_mgr *upipe_ttmlf_mgr_alloc(void);

#ifdef __cplusplus
}
#endif
#endif
2 changes: 2 additions & 0 deletions include/upipe-ts/upipe_ts_demux.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ enum upipe_ts_demux_mgr_command {
UPIPE_TS_DEMUX_MGR_GET_SET_MGR(ts_eitd, TS_EITD)
UPIPE_TS_DEMUX_MGR_GET_SET_MGR(ts_pesd, TS_PESD)
UPIPE_TS_DEMUX_MGR_GET_SET_MGR(ts_scte35d, TS_SCTE35D)
UPIPE_TS_DEMUX_MGR_GET_SET_MGR(ts_ttmld, TS_TTMLD)

UPIPE_TS_DEMUX_MGR_GET_SET_MGR(autof, AUTOF)
#undef UPIPE_TS_DEMUX_MGR_GET_SET_MGR
Expand Down Expand Up @@ -240,6 +241,7 @@ UPIPE_TS_DEMUX_MGR_GET_SET_MGR2(ts_pmtd, TS_PMTD)
UPIPE_TS_DEMUX_MGR_GET_SET_MGR2(ts_eitd, TS_EITD)
UPIPE_TS_DEMUX_MGR_GET_SET_MGR2(ts_pesd, TS_PESD)
UPIPE_TS_DEMUX_MGR_GET_SET_MGR2(ts_scte35d, TS_SCTE35D)
UPIPE_TS_DEMUX_MGR_GET_SET_MGR2(ts_ttmld, TS_TTMLD)

UPIPE_TS_DEMUX_MGR_GET_SET_MGR2(autof, AUTOF)
#undef UPIPE_TS_DEMUX_MGR_GET_SET_MGR2
Expand Down
34 changes: 34 additions & 0 deletions include/upipe-ts/upipe_ts_ttml_decaps.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2026 Open Broadcast Systems Ltd
*
* Authors: Kieran Kunhya
*
* SPDX-License-Identifier: MIT
*/

/** @file
* @short Upipe module decapsulating DVB TTML subtitle segments from PES
* payloads (EN 303 560 5.2.2.2)
*/

#ifndef _UPIPE_TS_UPIPE_TS_TTML_DECAPS_H_
/** @hidden */
#define _UPIPE_TS_UPIPE_TS_TTML_DECAPS_H_
#ifdef __cplusplus
extern "C" {
#endif

#include "upipe/upipe.h"

#define UPIPE_TS_TTMLD_SIGNATURE UBASE_FOURCC('t','s','t','t')

/** @This returns the management structure for all ts_ttmld pipes.
*
* @return pointer to manager
*/
struct upipe_mgr *upipe_ts_ttmld_mgr_alloc(void);

#ifdef __cplusplus
}
#endif
#endif
14 changes: 14 additions & 0 deletions include/upipe-ts/uref_ts_flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,20 @@ UREF_ATTR_SMALL_UNSIGNED_VA(ts_flow, sub_composition, "t.subcomp[%" PRIu8"]",
UREF_ATTR_SMALL_UNSIGNED_VA(ts_flow, sub_ancillary, "t.subanc[%" PRIu8"]",
subtitling ancillary page according to EN 300 468, uint8_t nb, nb)

/* TTML subtitling, EN 303 560 */
UREF_ATTR_SMALL_UNSIGNED(ts_flow, ttml_purpose, "t.ttmlpurpose",
subtitle purpose according to EN 303 560)
UREF_ATTR_SMALL_UNSIGNED(ts_flow, ttml_tts_suitability, "t.ttmltts",
text-to-speech suitability according to EN 303 560)
UREF_ATTR_SMALL_UNSIGNED(ts_flow, ttml_profiles, "t.ttmlprofiles",
number of TTML processor profiles)
UREF_ATTR_SMALL_UNSIGNED_VA(ts_flow, ttml_profile, "t.ttmlprofile[%" PRIu8"]",
TTML processor profile according to EN 303 560, uint8_t nb, nb)
UREF_ATTR_UNSIGNED(ts_flow, ttml_qualifier, "t.ttmlqualifier",
presentation qualifier according to EN 303 560)
UREF_ATTR_SMALL_UNSIGNED(ts_flow, ttml_essential_fonts, "t.ttmlfonts",
number of downloadable fonts required to present the subtitles)

/* SDT */
UREF_ATTR_UNSIGNED(ts_flow, tsid, "t.tsid", transport stream ID)
UREF_ATTR_UNSIGNED(ts_flow, onid, "t.onid", original network ID)
Expand Down
33 changes: 33 additions & 0 deletions include/upipe-ts/uref_ts_ttml.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2026 Open Broadcast Systems Ltd
*
* Authors: Kieran Kunhya
*
* SPDX-License-Identifier: MIT
*/

/** @file
* @short Upipe attributes for DVB TTML subtitle segments
*/

#ifndef _UPIPE_TS_UREF_TS_TTML_H_
/** @hidden */
#define _UPIPE_TS_UREF_TS_TTML_H_
#ifdef __cplusplus
extern "C" {
#endif

#include "upipe/uref_attr.h"

/** @This is the flow definition of a stream of TTML documents. */
#define UREF_TS_TTML_FLOW_DEF "block.ttml.pic.sub."

/* The media time of the segment is the instant of the TTML timeline
* that the PTS of its PES packet corresponds to (EN 303 560 5.2.4.1). */
UREF_ATTR_UNSIGNED(ts_ttml, mediatime, "t.ttml.mediatime",
segment media time in UCLOCK_FREQ units)

#ifdef __cplusplus
}
#endif
#endif
62 changes: 62 additions & 0 deletions include/upipe-ttml/upipe_ttml_dec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2026 Open Broadcast Systems Ltd
*
* Authors: Kieran Kunhya
*
* SPDX-License-Identifier: MIT
*/

/** @file
* @short Upipe DVB TTML subtitle decoder
*/

#ifndef _UPIPE_TTML_UPIPE_TTML_DEC_H_
/** @hidden */
#define _UPIPE_TTML_UPIPE_TTML_DEC_H_
#ifdef __cplusplus
extern "C" {
#endif

#include "upipe/upipe.h"

#define UPIPE_TTMLD_SIGNATURE UBASE_FOURCC('t','t','m','l')

/** @This enumerates the ttmld pipe commands. */
enum upipe_ttmld_command {
/** sentinel */
UPIPE_TTMLD_SENTINEL = UPIPE_CONTROL_LOCAL,
/** set the size of the canvas the regions are positioned on
* (uint64_t, uint64_t) */
UPIPE_TTMLD_SET_CANVAS_SIZE,
};

/** @This sets the size of the canvas the regions are positioned on.
*
* The TTML root container is mapped onto it, so it is the size of the picture
* the subtitles are composed with. It has to be set before the first
* document, and set again whenever that picture changes size: the pipe has no
* default, because a canvas of the wrong size puts every region in the wrong
* place rather than merely rendering them at the wrong resolution.
*
* @param upipe description structure of the pipe
* @param hsize width of the canvas
* @param vsize height of the canvas
* @return an error code
*/
static inline int upipe_ttmld_set_canvas_size(struct upipe *upipe,
uint64_t hsize, uint64_t vsize)
{
return upipe_control(upipe, UPIPE_TTMLD_SET_CANVAS_SIZE,
UPIPE_TTMLD_SIGNATURE, hsize, vsize);
}

/** @This returns the management structure for all ttmld pipes.
*
* @return pointer to manager
*/
struct upipe_mgr *upipe_ttmld_mgr_alloc(void);

#ifdef __cplusplus
}
#endif
#endif
127 changes: 127 additions & 0 deletions include/upipe/uref_text.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright (C) 2026 Open Broadcast Systems Ltd
*
* Authors: Kieran Kunhya
*
* SPDX-License-Identifier: MIT
*/

/** @file
* @short Upipe attributes describing a styled text page
*
* A page is a list of regions laid out on a canvas, each holding a list of
* styled runs. The producer resolves the styling and positions the regions;
* the renderer measures the runs, breaks them into lines and draws them.
*
* The runs of all the regions form a single array in region order: the runs of
* region r start after the runs of every region before it.
*/

#ifndef _UPIPE_UREF_TEXT_H_
/** @hidden */
#define _UPIPE_UREF_TEXT_H_
#ifdef __cplusplus
extern "C" {
#endif

#include "upipe/uref_attr.h"

/** @This is the flow definition of a styled text page. */
#define UREF_TEXT_FLOW_DEF "void.text."

/** @This enumerates how the lines of a region are aligned in the block
* progression direction (tts:displayAlign). */
enum uref_text_display_align {
/** at the top of the region */
UREF_TEXT_DISPLAY_ALIGN_BEFORE = 0,
/** in the middle of the region */
UREF_TEXT_DISPLAY_ALIGN_CENTER = 1,
/** at the bottom of the region */
UREF_TEXT_DISPLAY_ALIGN_AFTER = 2,
};

/** @This enumerates how a line is aligned in the region (tts:textAlign). */
enum uref_text_align {
/** at the left of the region */
UREF_TEXT_ALIGN_START = 0,
/** in the middle of the region */
UREF_TEXT_ALIGN_CENTER = 1,
/** at the right of the region */
UREF_TEXT_ALIGN_END = 2,
};

/** @This enumerates how the lines of a block are aligned relative to each
* other (ebutts:multiRowAlign). */
enum uref_text_multi_row_align {
/** follow tts:textAlign */
UREF_TEXT_MULTI_ROW_ALIGN_AUTO = 0,
/** at the left of the block */
UREF_TEXT_MULTI_ROW_ALIGN_START = 1,
/** in the middle of the block */
UREF_TEXT_MULTI_ROW_ALIGN_CENTER = 2,
/** at the right of the block */
UREF_TEXT_MULTI_ROW_ALIGN_END = 3,
};

/** the run is emboldened */
#define UREF_TEXT_RUN_BOLD 0x01
/** the run is sheared */
#define UREF_TEXT_RUN_ITALIC 0x02
/** the run is underlined */
#define UREF_TEXT_RUN_UNDERLINE 0x04
/** the run starts a new line */
#define UREF_TEXT_RUN_BREAK 0x08

/* page */
UREF_ATTR_UNSIGNED(text, canvas_hsize, "x.chsize",
width of the canvas the regions are positioned on)
UREF_ATTR_UNSIGNED(text, canvas_vsize, "x.cvsize",
height of the canvas the regions are positioned on)
UREF_ATTR_SMALL_UNSIGNED(text, regions, "x.regions", number of regions)

/* regions */
UREF_ATTR_UNSIGNED_VA(text, region_x, "x.rx[%" PRIu8"]",
left of the region on the canvas, uint8_t nb, nb)
UREF_ATTR_UNSIGNED_VA(text, region_y, "x.ry[%" PRIu8"]",
top of the region on the canvas, uint8_t nb, nb)
UREF_ATTR_UNSIGNED_VA(text, region_hsize, "x.rw[%" PRIu8"]",
width of the region, uint8_t nb, nb)
UREF_ATTR_UNSIGNED_VA(text, region_vsize, "x.rh[%" PRIu8"]",
height of the region, uint8_t nb, nb)
UREF_ATTR_SMALL_UNSIGNED_VA(text, region_display_align, "x.rda[%" PRIu8"]",
block alignment according to @ref uref_text_display_align,
uint8_t nb, nb)
UREF_ATTR_SMALL_UNSIGNED_VA(text, region_text_align, "x.rta[%" PRIu8"]",
line alignment according to @ref uref_text_align, uint8_t nb, nb)
UREF_ATTR_SMALL_UNSIGNED_VA(text, region_multi_row_align, "x.rmra[%" PRIu8"]",
row alignment according to @ref uref_text_multi_row_align,
uint8_t nb, nb)
UREF_ATTR_UNSIGNED_VA(text, region_line_height, "x.rlh[%" PRIu8"]",
line height in pixels or 0 for normal, uint8_t nb, nb)
UREF_ATTR_UNSIGNED_VA(text, region_line_padding, "x.rlp[%" PRIu8"]",
horizontal padding of the line backgrounds in pixels, uint8_t nb, nb)
UREF_ATTR_UNSIGNED_VA(text, region_background, "x.rbg[%" PRIu8"]",
region background colour as packed RGBA, uint8_t nb, nb)
UREF_ATTR_VOID_VA(text, region_no_wrap, "x.rnw[%" PRIu8"]",
the lines of the region are not wrapped, uint8_t nb, nb)
UREF_ATTR_VOID_VA(text, region_fill_line_gap, "x.rflg[%" PRIu8"]",
the line backgrounds cover the whole line height, uint8_t nb, nb)
UREF_ATTR_SMALL_UNSIGNED_VA(text, region_runs, "x.rruns[%" PRIu8"]",
number of runs in the region, uint8_t nb, nb)

/* runs */
UREF_ATTR_STRING_VA(text, run_text, "x.rt[%" PRIu8"]",
UTF-8 text of the run, uint8_t nb, nb)
UREF_ATTR_UNSIGNED_VA(text, run_font_size, "x.rfs[%" PRIu8"]",
font size of the run in pixels, uint8_t nb, nb)
UREF_ATTR_UNSIGNED_VA(text, run_color, "x.rfg[%" PRIu8"]",
foreground colour of the run as packed RGBA, uint8_t nb, nb)
UREF_ATTR_UNSIGNED_VA(text, run_background, "x.rrbg[%" PRIu8"]",
background colour of the run as packed RGBA, uint8_t nb, nb)
UREF_ATTR_SMALL_UNSIGNED_VA(text, run_flags, "x.rfl[%" PRIu8"]",
style flags of the run, uint8_t nb, nb)

#ifdef __cplusplus
}
#endif
#endif
1 change: 1 addition & 0 deletions lib/Build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ subdirs = \
upipe-swresample \
upipe-swscale \
upipe-ts \
upipe-ttml \
upipe-v210 \
upipe-x264 \
upipe-x265 \
Expand Down
2 changes: 2 additions & 0 deletions lib/upipe-framers/Build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ libupipe_framers-includes = \
upipe_s337_decaps.h \
upipe_s337_framer.h \
upipe_telx_framer.h \
upipe_ttml_framer.h \
upipe_video_trim.h \
uref_dvbsub_flow.h \
uref_h264.h \
Expand Down Expand Up @@ -47,6 +48,7 @@ libupipe_framers-src = \
upipe_s337_decaps.c \
upipe_s337_framer.c \
upipe_telx_framer.c \
upipe_ttml_framer.c \
upipe_video_trim.c

libupipe_framers-libs = \
Expand Down
Loading
Loading