[FFmpeg-devel] [PATCH 2/4] avformat/ttmlenc: enable writing out additional header values
Andreas Rheinhardt
andreas.rheinhardt at outlook.com
Tue Mar 30 12:18:47 EEST 2021
Jan Ekström:
> From: Jan Ekström <jan.ekstrom at 24i.com>
>
> This way the encoder may pass on the following values to the muxer:
> 1) Additional root "tt" element attributes, such as the subtitle
> canvas reference size.
> 2) Anything before the body element of the document, such as regions
> in the head element, which can configure styles.
>
> Signed-off-by: Jan Ekström <jan.ekstrom at 24i.com>
> ---
> libavcodec/ttmlenc.h | 5 +++
> libavformat/ttmlenc.c | 78 ++++++++++++++++++++++++++++++++++++++++---
> 2 files changed, 78 insertions(+), 5 deletions(-)
>
> diff --git a/libavcodec/ttmlenc.h b/libavcodec/ttmlenc.h
> index c1dd5ec990..c3bb11478d 100644
> --- a/libavcodec/ttmlenc.h
> +++ b/libavcodec/ttmlenc.h
> @@ -25,4 +25,9 @@
> #define TTMLENC_EXTRADATA_SIGNATURE "lavc-ttmlenc"
> #define TTMLENC_EXTRADATA_SIGNATURE_SIZE (sizeof(TTMLENC_EXTRADATA_SIGNATURE) - 1)
>
> +static const char ttml_default_namespacing[] =
> +" xmlns=\"http://www.w3.org/ns/ttml\"\n"
> +" xmlns:ttm=\"http://www.w3.org/ns/ttml#metadata\"\n"
> +" xmlns:tts=\"http://www.w3.org/ns/ttml#styling\"\n";
> +
> #endif /* AVCODEC_TTMLENC_H */
> diff --git a/libavformat/ttmlenc.c b/libavformat/ttmlenc.c
> index 940f8bbd4e..5d9ad6b756 100644
> --- a/libavformat/ttmlenc.c
> +++ b/libavformat/ttmlenc.c
> @@ -37,18 +37,23 @@ enum TTMLPacketType {
> PACKET_TYPE_DOCUMENT,
> };
>
> +struct TTMLHeaderParameters {
> + char *tt_element_params;
> + char *pre_body_elements;
> +};
> +
> typedef struct TTMLMuxContext {
> enum TTMLPacketType input_type;
> unsigned int document_written;
> + struct TTMLHeaderParameters header_params;
> } TTMLMuxContext;
>
> static const char ttml_header_text[] =
> "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
> "<tt\n"
> -" xmlns=\"http://www.w3.org/ns/ttml\"\n"
> -" xmlns:ttm=\"http://www.w3.org/ns/ttml#metadata\"\n"
> -" xmlns:tts=\"http://www.w3.org/ns/ttml#styling\"\n"
> +"%s"
> " xml:lang=\"%s\">\n"
> +"%s"
> " <body>\n"
> " <div>\n";
>
> @@ -72,6 +77,47 @@ static void ttml_write_time(AVIOContext *pb, const char tag[],
> tag, hour, min, sec, millisec);
> }
>
> +static int ttml_set_header_values_from_extradata(
> + AVCodecParameters *par, struct TTMLHeaderParameters *header_params)
> +{
> + size_t additional_data_size =
> + par->extradata_size - TTMLENC_EXTRADATA_SIGNATURE_SIZE;
> +
Missing check that extradata_size is >= TTMLENC_EXTRADATA_SIGNATURE_SIZE.
> + if (!additional_data_size) {
> + header_params->tt_element_params =
> + av_strndup(ttml_default_namespacing,
> + sizeof(ttml_default_namespacing) - 1);
> + header_params->pre_body_elements = av_strndup("", 1);
Why are you using av_strndup and not the ordinary av_strdup here?
Anyway, these allocations and the ones below are unnecessary as you only
need all of this when writing the header.
> +
> + if (!header_params->tt_element_params ||
> + !header_params->pre_body_elements)
> + return AVERROR(ENOMEM);
> +
> + return 0;
> + }
> +
> + {
> + char *value =
> + (char *)par->extradata + TTMLENC_EXTRADATA_SIGNATURE_SIZE;
> + size_t value_size = av_strnlen(value, additional_data_size);
> +
> + if (!(header_params->tt_element_params = av_strndup(value, value_size)))
> + return AVERROR(ENOMEM);
> +
> + additional_data_size -= value_size + 1;
> + value += value_size + 1;
> + if (additional_data_size <= 0)
> + return AVERROR_INVALIDDATA;
> +
> + value_size = av_strnlen(value, additional_data_size);
> +
> + if (!(header_params->pre_body_elements = av_strndup(value, value_size)))
> + return AVERROR(ENOMEM);
> +
> + return 0;
> + }
> +}
> +
> static int ttml_write_header(AVFormatContext *ctx)
> {
> TTMLMuxContext *ttml_ctx = ctx->priv_data;
> @@ -103,8 +149,21 @@ static int ttml_write_header(AVFormatContext *ctx)
>
> avpriv_set_pts_info(st, 64, 1, 1000);
>
> - if (ttml_ctx->input_type == PACKET_TYPE_PARAGRAPH)
> - avio_printf(pb, ttml_header_text, printed_lang);
> + if (ttml_ctx->input_type == PACKET_TYPE_PARAGRAPH) {
> + int ret = ttml_set_header_values_from_extradata(
> + st->codecpar, &ttml_ctx->header_params);
> + if (ret < 0) {
> + av_log(ctx, AV_LOG_ERROR,
> + "Failed to parse TTML header values from extradata: "
> + "%s!\n", av_err2str(ret));
> + return ret;
> + }
> +
> + avio_printf(pb, ttml_header_text,
> + ttml_ctx->header_params.tt_element_params,
> + printed_lang,
> + ttml_ctx->header_params.pre_body_elements);
> + }
> }
>
> return 0;
> @@ -159,6 +218,14 @@ static int ttml_write_trailer(AVFormatContext *ctx)
> return 0;
> }
>
> +static void ttml_free(AVFormatContext *ctx)
> +{
> + TTMLMuxContext *ttml_ctx = ctx->priv_data;
> +
> + av_freep(&(ttml_ctx->header_params.tt_element_params));
> + av_freep(&(ttml_ctx->header_params.pre_body_elements));
Unnecessary parentheses (on top of these allocations being unnecessary).
> +}
> +
> AVOutputFormat ff_ttml_muxer = {
> .name = "ttml",
> .long_name = NULL_IF_CONFIG_SMALL("TTML subtitle"),
> @@ -171,4 +238,5 @@ AVOutputFormat ff_ttml_muxer = {
> .write_header = ttml_write_header,
> .write_packet = ttml_write_packet,
> .write_trailer = ttml_write_trailer,
> + .deinit = ttml_free,
> };
>
More information about the ffmpeg-devel
mailing list