/*
 * TTML subtitle muxer
 * Copyright (c) 2020 24i
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
/**
 * @file
 * TTML subtitle muxer
 * @see https://www.w3.org/TR/ttml1/
 * @see https://www.w3.org/TR/ttml2/
 * @see https://www.w3.org/TR/ttml-imsc/rec
 */
#include "libavutil/avstring.h"
#include "avformat.h"
#include "internal.h"
#include "mux.h"
#include "ttmlenc.h"
#include "libavcodec/ttmlenc.h"
#include "libavutil/internal.h"
enum TTMLPacketType {
    PACKET_TYPE_PARAGRAPH,
    PACKET_TYPE_DOCUMENT,
};
struct TTMLHeaderParameters {
    const char *tt_element_params;
    const char *pre_body_elements;
};
typedef struct TTMLMuxContext {
    enum TTMLPacketType input_type;
    unsigned int document_written;
} TTMLMuxContext;
static const char ttml_header_text[] =
"\n"
"\n"
"%s"
"  \n"
"    
pts); avio_w8(pb, '\n'); ttml_write_time(pb, " end", pkt->pts + pkt->duration); avio_printf(pb, ">"); avio_write(pb, pkt->data, pkt->size); avio_printf(pb, "
\n"); break; case PACKET_TYPE_DOCUMENT: // dump the given document out as-is. if (ttml_ctx->document_written) { av_log(ctx, AV_LOG_ERROR, "Attempting to write multiple TTML documents into a " "single document! The XML specification forbids this " "as there has to be a single root tag.\n"); return AVERROR(EINVAL); } avio_write(pb, pkt->data, pkt->size); ttml_ctx->document_written = 1; break; default: av_log(ctx, AV_LOG_ERROR, "Internal error: invalid TTML input packet type: %d!\n", ttml_ctx->input_type); return AVERROR_BUG; } return 0; } static int ttml_write_trailer(AVFormatContext *ctx) { TTMLMuxContext *ttml_ctx = ctx->priv_data; AVIOContext *pb = ctx->pb; if (ttml_ctx->input_type == PACKET_TYPE_PARAGRAPH) avio_printf(pb, ttml_footer_text); return 0; } const FFOutputFormat ff_ttml_muxer = { .p.name = "ttml", .p.long_name = NULL_IF_CONFIG_SMALL("TTML subtitle"), .p.extensions = "ttml", .p.mime_type = "text/ttml", .priv_data_size = sizeof(TTMLMuxContext), .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, .p.subtitle_codec = AV_CODEC_ID_TTML, .write_header = ttml_write_header, .write_packet = ttml_write_packet, .write_trailer = ttml_write_trailer, };