From patchwork Tue Mar 30 08:23:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Jan_Ekstr=C3=B6m?= X-Patchwork-Id: 26649 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 6A9E244A0F6 for ; Tue, 30 Mar 2021 11:30:28 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 4E98A689B09; Tue, 30 Mar 2021 11:30:28 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lf1-f45.google.com (mail-lf1-f45.google.com [209.85.167.45]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 613C468028B for ; Tue, 30 Mar 2021 11:30:21 +0300 (EEST) Received: by mail-lf1-f45.google.com with SMTP id 12so12143817lfq.13 for ; Tue, 30 Mar 2021 01:30:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=7ZdffR6VTqK9gxQdmDxFJY8eo35zn1YjPRwkPheLq3w=; b=X1926460HXId9ATdhEdsO160/EN1lGuqJIAiu/xpQugbr5Z7yv1YVJ19ykSo5l0Jyh VB3eB1Nad7dGVT5VofJimlE5CKeWOldDXjsoIK1TVZ1bUShXK25odA8r1BiphSnRi3nz B/ub7zSI6TgEk0D930ScFO3VuYGAdSmJK3bQr02bEkmnJxPGiGNa0ha4KTDeUKL46wwS kBZo75Mtvt/aYfr9ZFmb9/ekA4izqeBHQ8ObmNREvm3W7LWLG84XDq1+XF3OqtOeDvDK Ls0Hly9HWfYPX45BuNODTk+GoKgdPGgCc8GbNJqziWt96eeRGmRK/bdp6obCUc4rP/FA sTFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=7ZdffR6VTqK9gxQdmDxFJY8eo35zn1YjPRwkPheLq3w=; b=DDd+15Bw5RNHHNzhS/PysRLU/OYuYGQMuOEq/zPgAxaM0j8OvG1zw2RxpJ5jzC5s2G fUyFKv7LLrbnFlQOYVl+KtGu3cxNnVRVZhRwNF26+ODolqPT4bagVR/1bmMLyD5u/6nD 9t1yLQgqEUfrpCGxekTrYM/wGhktfF14VlGLEDxW7BzXH51N5oJubKYkpg5mhPW4xrRh A4aFtRj+raM5vc6Lp+lmxTkA8zw7WeP98BT2RPCyxALcfg3sFb+JwXNgZ8+fLN2BMZsG TjQlw4izOp9lIwnAy8sevfOPCl2cstLXVVnxZV6gjtTaT3rFDzaPS9f+o1Fca06JgHsf eCjw== X-Gm-Message-State: AOAM531mIO4rh8wDTGou2ox4jIb6oTP1j5dskfpSWR7qnVW/amSNXw5c biXKdlUBZTAfQDFqYTN6A1RFCWEMoqs= X-Google-Smtp-Source: ABdhPJxRNA/+6MOPE2smdMrX9xaKf9CuMWvcRQJ2lq1Xo5T6imyLJ2iZVAiFhmfQYy8Op0MPeu8Pwg== X-Received: by 2002:a2e:bc1e:: with SMTP id b30mr11567794ljf.351.1617092630232; Tue, 30 Mar 2021 01:23:50 -0700 (PDT) Received: from localhost.localdomain (91-159-194-103.elisa-laajakaista.fi. [91.159.194.103]) by smtp.gmail.com with ESMTPSA id d34sm2089414lfv.102.2021.03.30.01.23.49 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Mar 2021 01:23:49 -0700 (PDT) From: =?utf-8?q?Jan_Ekstr=C3=B6m?= To: ffmpeg-devel@ffmpeg.org Date: Tue, 30 Mar 2021 11:23:43 +0300 Message-Id: <20210330082346.8404-2-jeebjp@gmail.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210330082346.8404-1-jeebjp@gmail.com> References: <20210330082346.8404-1-jeebjp@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/4] avcodec/ttmlenc: split header writing into its own function X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Jan Ekström Signed-off-by: Jan Ekström --- libavcodec/ttmlenc.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/libavcodec/ttmlenc.c b/libavcodec/ttmlenc.c index 3972b4368c..e3c155fdd1 100644 --- a/libavcodec/ttmlenc.c +++ b/libavcodec/ttmlenc.c @@ -173,16 +173,8 @@ static av_cold int ttml_encode_close(AVCodecContext *avctx) return 0; } -static av_cold int ttml_encode_init(AVCodecContext *avctx) +static int ttml_write_header_content(AVCodecContext *avctx) { - TTMLContext *s = avctx->priv_data; - - s->avctx = avctx; - - if (!(s->ass_ctx = ff_ass_split(avctx->subtitle_header))) { - return AVERROR_INVALIDDATA; - } - if (!(avctx->extradata = av_mallocz(TTMLENC_EXTRADATA_SIGNATURE_SIZE + 1 + AV_INPUT_BUFFER_PADDING_SIZE))) { return AVERROR(ENOMEM); @@ -192,8 +184,25 @@ static av_cold int ttml_encode_init(AVCodecContext *avctx) memcpy(avctx->extradata, TTMLENC_EXTRADATA_SIGNATURE, TTMLENC_EXTRADATA_SIGNATURE_SIZE); + return 0; +} + +static av_cold int ttml_encode_init(AVCodecContext *avctx) +{ + TTMLContext *s = avctx->priv_data; + int ret = AVERROR_BUG; + s->avctx = avctx; + av_bprint_init(&s->buffer, 0, AV_BPRINT_SIZE_UNLIMITED); + if (!(s->ass_ctx = ff_ass_split(avctx->subtitle_header))) { + return AVERROR_INVALIDDATA; + } + + if ((ret = ttml_write_header_content(avctx)) < 0) { + return ret; + } + return 0; } From patchwork Tue Mar 30 08:23:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Jan_Ekstr=C3=B6m?= X-Patchwork-Id: 26652 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 8DD8E44A116 for ; Tue, 30 Mar 2021 11:50:46 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6ED8E688152; Tue, 30 Mar 2021 11:50:46 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lj1-f179.google.com (mail-lj1-f179.google.com [209.85.208.179]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4059C680506 for ; Tue, 30 Mar 2021 11:50:40 +0300 (EEST) Received: by mail-lj1-f179.google.com with SMTP id r20so19029489ljk.4 for ; Tue, 30 Mar 2021 01:50:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=HfbHFdud78Lu3zbQBkpl90wCwbTbOCjMHYMQl5ACnUs=; b=ILgMyqR7pJ4953pZwOa9un8vhXiFnUHNLT2A9WsSmritFEj0RWmeQdviyyp33WfhEX QBQAE75BpcrNAZuhaojCnQcmYIp0doTWenCJeyUswiQPJ4mMB7nVD17rJ4q7Ko48Zk22 6xXG9SMxi+8GIyxu1lOfi24J+tsuzvGJCrTWnfhDo07QYrXBQiGALJNSF0CK4tswYj47 yfUbZ4en3J/HfTRZ4QNmfsu9UJtTBsYHsg5+2fmMFSWxVREhz+gMuH1PBmUjZbQjrKiO 3UzdrdWfr2eWNfXXnGYQuZifttwZdzrW5X/6BY2qIo6ZPJXbX02ThPJV0oB4Wjr1mJCC hYzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=HfbHFdud78Lu3zbQBkpl90wCwbTbOCjMHYMQl5ACnUs=; b=g1CZtNMyudMD0jJAWxpjIvUE5hCeBLhekJQCXqC9bwXJ3oKeSUO2i5Z4CmEbH7cFSq L/t22i6PhUoO7AIQxeTLV0OqcnqBaJZk7sSxpuLP6ckS5ebjS24DMGJdmOuNuASycx7x jbPprOw2MkHphP9FijzpGvHYOMPa/y5NngXMqrngPLfMH3AFZ3+29Io7Ufk8MbENWEpS g5F1Q7nmyjs1y5KLXkfVxk06ShkE0Rg4cFto28eQXn/8oEfAbyW+65S0fAkel803GPD7 dINdG3B5ISdTDJTUUHRe+uzJOIJ5KJ1iYKtbTmWq7uSBiejERW/WxEXH0U9+A5GPBjQ+ DB3w== X-Gm-Message-State: AOAM530y2lH3xO8/6qZVoTchHwqmTVeOCwA/KigYNRwmKyYh/re/VL8a uQ9K1H5caArG4NkbPeCICthQ0qRMO4Q= X-Google-Smtp-Source: ABdhPJyp/Z2AxRsCdifGdAn4QMfsg3ZxymYA0xAJX4+zB5Exag3vG2UEV0Hssv2gaPzCZqhsoDQpZQ== X-Received: by 2002:a2e:9310:: with SMTP id e16mr20419156ljh.226.1617092630884; Tue, 30 Mar 2021 01:23:50 -0700 (PDT) Received: from localhost.localdomain (91-159-194-103.elisa-laajakaista.fi. [91.159.194.103]) by smtp.gmail.com with ESMTPSA id d34sm2089414lfv.102.2021.03.30.01.23.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Mar 2021 01:23:50 -0700 (PDT) From: =?utf-8?q?Jan_Ekstr=C3=B6m?= To: ffmpeg-devel@ffmpeg.org Date: Tue, 30 Mar 2021 11:23:44 +0300 Message-Id: <20210330082346.8404-3-jeebjp@gmail.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210330082346.8404-1-jeebjp@gmail.com> References: <20210330082346.8404-1-jeebjp@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/4] avformat/ttmlenc: enable writing out additional header values X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Jan Ekström 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 --- 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[] = "\n" "\n" +"%s" " \n" "
\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; + + 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); + + 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)); +} + 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, }; From patchwork Tue Mar 30 08:23:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Jan_Ekstr=C3=B6m?= X-Patchwork-Id: 26647 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 36620449D2D for ; Tue, 30 Mar 2021 11:29:54 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E6868689BC9; Tue, 30 Mar 2021 11:29:53 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lf1-f46.google.com (mail-lf1-f46.google.com [209.85.167.46]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 09B7568028B for ; Tue, 30 Mar 2021 11:29:48 +0300 (EEST) Received: by mail-lf1-f46.google.com with SMTP id o10so22487448lfb.9 for ; Tue, 30 Mar 2021 01:29:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=w1A9nDJeskKbUHIBECk1bmukr7G+ECPcPp3cGlFz5vA=; b=uq2WLMU0SUGpS+AeUsjoLTnE3R11xMuBL8KUBx75RHFgug/HUX3Z8svqaFzFr2e3P/ fSjk7Syz2KjB+NWo8z12srZ0C7YxY5PJ/hAZWz6pgU7m6U7LMxW15GUq6h1OzG2Dg2Gc tYq2yEbmjJElm1TMy+SQKoVTPjqJi9/kbAhH7UAtnY6d28Mjrus0YDttS3fKFsrehQc2 xeOB9bS/8e5W7myHUOgb3UbQPRYnvhl0Zo6raKb6Y4TbCtyWTwB8yz5Y6ad8CVFkKUwi YklSMPrYp9/UgovpMzc9cpvTgNBdMiBIMZjOYOPO8SXb46fVM3zhOVhu9zzdvptMvPM5 AEtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=w1A9nDJeskKbUHIBECk1bmukr7G+ECPcPp3cGlFz5vA=; b=B/yrk6k/130gRnqZx+MxtzMIneqMOScpqR8DX8+kqKoA0UzPIopfu/eVNDtUWZpgvA /Ecyauqi6IZuZSyjXBLX/jQMlZZ0Nkn8zHicj2BUqCqyJQ/tKdVD2AAAyvZLqy7Skrrp L8NaMFcvy0npVtTHUC9iRe3zGS7xWllso0C3GjHqRJG9VBn9RKxOp8IyuuLJqwfNdoIW FogRpAgSFtZmkDvlV/Ui3KmvE4yFB7F6YXJmstDaNxaiaSaH5RFqGpAbHcJUci/0uU9W lWAR7WeguQ0BOGtat/xoYcubFPmZW34VPQyDykU3DwbLTQc0sSZvbsX8vGGIjWNDhWvt tfdw== X-Gm-Message-State: AOAM530MKJ3zY+/z28tgYA71OYNvdOXJqvvr8IAXBvW9kTwkraMIEqJM amtazQesdnW3dawYfr/yTUXA0Tpbehc= X-Google-Smtp-Source: ABdhPJwkUtekmO6phRRIRgUS3iS6UBu+TvJD9b8urnpEoP592SktTi6Bftwiwx5j/vyXjHnXVa6+Lw== X-Received: by 2002:a2e:8590:: with SMTP id b16mr20565829lji.53.1617092631652; Tue, 30 Mar 2021 01:23:51 -0700 (PDT) Received: from localhost.localdomain (91-159-194-103.elisa-laajakaista.fi. [91.159.194.103]) by smtp.gmail.com with ESMTPSA id d34sm2089414lfv.102.2021.03.30.01.23.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Mar 2021 01:23:51 -0700 (PDT) From: =?utf-8?q?Jan_Ekstr=C3=B6m?= To: ffmpeg-devel@ffmpeg.org Date: Tue, 30 Mar 2021 11:23:45 +0300 Message-Id: <20210330082346.8404-4-jeebjp@gmail.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210330082346.8404-1-jeebjp@gmail.com> References: <20210330082346.8404-1-jeebjp@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/4] avcodec/ttmlenc: add initial support for regions and styles X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Jan Ekström Attempts to utilize the TTML cell resolution as a mapping to the reference resolution, and maps font size to cell size. Additionally sets the display and text alignment according to the ASS alignment number. Signed-off-by: Jan Ekström --- libavcodec/ttmlenc.c | 257 +++++++++++++++++++++++++++++++++++-- libavcodec/ttmlenc.h | 3 +- tests/ref/fate/sub-ttmlenc | 86 +++++++------ 3 files changed, 294 insertions(+), 52 deletions(-) diff --git a/libavcodec/ttmlenc.c b/libavcodec/ttmlenc.c index e3c155fdd1..7e6add62e1 100644 --- a/libavcodec/ttmlenc.c +++ b/libavcodec/ttmlenc.c @@ -82,6 +82,7 @@ static int ttml_encode_frame(AVCodecContext *avctx, uint8_t *buf, { TTMLContext *s = avctx->priv_data; ASSDialog *dialog; + AVBPrint local_bprint = { 0 }; int i; av_bprint_clear(&s->buffer); @@ -100,20 +101,41 @@ static int ttml_encode_frame(AVCodecContext *avctx, uint8_t *buf, dialog = ff_ass_split_dialog(s->ass_ctx, ass, 0, &num); for (; dialog && num--; dialog++) { - int ret = ff_ass_split_override_codes(&ttml_callbacks, s, - dialog->text); - int log_level = (ret != AVERROR_INVALIDDATA || - avctx->err_recognition & AV_EF_EXPLODE) ? - AV_LOG_ERROR : AV_LOG_WARNING; + if (dialog->style) { + av_bprint_init(&local_bprint, 0, AV_BPRINT_SIZE_UNLIMITED); + + av_bprint_escape(&local_bprint, dialog->style, NULL, + AV_ESCAPE_MODE_XML, + AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES); + if (!av_bprint_is_complete(&local_bprint)) { + return AVERROR(ENOMEM); + } - if (ret < 0) { - av_log(avctx, log_level, - "Splitting received ASS dialog failed: %s\n", - av_err2str(ret)); + av_bprintf(&s->buffer, "", + local_bprint.str); - if (log_level == AV_LOG_ERROR) - return ret; + av_bprint_finalize(&local_bprint, NULL); } + + { + int ret = ff_ass_split_override_codes(&ttml_callbacks, s, + dialog->text); + int log_level = (ret != AVERROR_INVALIDDATA || + avctx->err_recognition & AV_EF_EXPLODE) ? + AV_LOG_ERROR : AV_LOG_WARNING; + + if (ret < 0) { + av_log(avctx, log_level, + "Splitting received ASS dialog failed: %s\n", + av_err2str(ret)); + + if (log_level == AV_LOG_ERROR) + return ret; + } + } + + if (dialog->style) + av_bprintf(&s->buffer, ""); } } else { #endif @@ -121,6 +143,22 @@ static int ttml_encode_frame(AVCodecContext *avctx, uint8_t *buf, if (!dialog) return AVERROR(ENOMEM); + if (dialog->style) { + av_bprint_init(&local_bprint, 0, AV_BPRINT_SIZE_UNLIMITED); + + av_bprint_escape(&local_bprint, dialog->style, NULL, + AV_ESCAPE_MODE_XML, + AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES); + if (!av_bprint_is_complete(&local_bprint)) { + return AVERROR(ENOMEM); + } + + av_bprintf(&s->buffer, "", + local_bprint.str); + + av_bprint_finalize(&local_bprint, NULL); + } + { int ret = ff_ass_split_override_codes(&ttml_callbacks, s, dialog->text); @@ -140,6 +178,9 @@ static int ttml_encode_frame(AVCodecContext *avctx, uint8_t *buf, } } + if (dialog->style) + av_bprintf(&s->buffer, ""); + ff_ass_free_dialog(&dialog); } #if FF_API_ASS_TIMING @@ -173,17 +214,205 @@ static av_cold int ttml_encode_close(AVCodecContext *avctx) return 0; } +static const char *ttml_get_display_alignment(int alignment) +{ + switch (alignment) { + case 1: + case 2: + case 3: + return "after"; + case 4: + case 5: + case 6: + return "center"; + case 7: + case 8: + case 9: + return "before"; + default: + return NULL; + } +} + +static const char *ttml_get_text_alignment(int alignment) +{ + switch (alignment) { + case 1: + case 4: + case 7: + return "left"; + case 2: + case 5: + case 8: + return "center"; + case 3: + case 6: + case 9: + return "right"; + default: + return NULL; + } +} + +// if we set cell resolution to our script reference resolution, +// then a single line is a single "point" on our canvas. Thus, by setting our +// font size to font size in cells, we should gain a similar enough scale +// without resorting to explicit pixel based font sizing, which is frowned +// upon in the TTML community. +static const char ttml_region_base[] = +" \n"; + +static int ttml_write_region(AVCodecContext *avctx, AVBPrint *buf, + ASSStyle *style) +{ + if (!style) + return AVERROR_INVALIDDATA; + + if (!style->name) { + av_log(avctx, AV_LOG_ERROR, "Subtitle style name not set!\n"); + return AVERROR_INVALIDDATA; + } + + if (style->font_size < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid font size for TTML: %d!\n", + style->font_size); + return AVERROR_INVALIDDATA; + } + + { + const char *display_alignment = + ttml_get_display_alignment(style->alignment); + const char *text_alignment = + ttml_get_text_alignment(style->alignment); + char *style_name = NULL; + char *font_name = NULL; + AVBPrint local_bprint = { 0 }; + int ret = AVERROR_BUG; + + if (!display_alignment || !text_alignment) { + av_log(avctx, AV_LOG_ERROR, + "Failed to convert ASS style alignment %d of style %s to " + "TTML display and text alignment!\n", + style->alignment, + style->name); + return AVERROR_INVALIDDATA; + } + + av_bprint_init(&local_bprint, 0, AV_BPRINT_SIZE_UNLIMITED); + av_bprint_escape(&local_bprint, style->name, NULL, + AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES); + if (!av_bprint_is_complete(&local_bprint)) { + return AVERROR(ENOMEM); + } + + if ((ret = av_bprint_finalize(&local_bprint, &style_name)) < 0) + return ret; + + av_bprintf(buf, ttml_region_base, style_name, + display_alignment, text_alignment, style->font_size); + + if (style->font_name) { + av_bprint_init(&local_bprint, 0, AV_BPRINT_SIZE_UNLIMITED); + av_bprint_escape(&local_bprint, style->font_name, NULL, + AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES); + if (!av_bprint_is_complete(&local_bprint)) { + ret = AVERROR(ENOMEM); + goto fail; + } + + if ((ret = av_bprint_finalize(&local_bprint, &font_name)) < 0) + goto fail; + + av_bprintf(buf, ttml_region_font_family, font_name); + } + + + av_bprintf(buf, ttml_region_footer); + + ret = 0; + +fail: + av_freep(&style_name); + av_freep(&font_name); + return ret; + } +} + static int ttml_write_header_content(AVCodecContext *avctx) { - if (!(avctx->extradata = av_mallocz(TTMLENC_EXTRADATA_SIGNATURE_SIZE + - 1 + AV_INPUT_BUFFER_PADDING_SIZE))) { + TTMLContext *s = avctx->priv_data; + ASS *ass = (ASS *)s->ass_ctx; + ASSScriptInfo script_info = ass->script_info; + const size_t base_extradata_size = TTMLENC_EXTRADATA_SIGNATURE_SIZE + 1 + + AV_INPUT_BUFFER_PADDING_SIZE; + size_t additional_extradata_size = 0; + ASSStyle *style = ff_ass_style_get(s->ass_ctx, "Default"); + + if (!script_info.play_res_x || script_info.play_res_x < 0 || + !script_info.play_res_y || script_info.play_res_y < 0) { + av_log(avctx, AV_LOG_ERROR, + "Invalid subtitle reference resolution %dx%d!\n", + script_info.play_res_x, script_info.play_res_y); + return AVERROR_INVALIDDATA; + } + + // write the first string in extradata, attributes in the base "tt" element. + av_bprintf(&s->buffer, ttml_default_namespacing); + // the cell resolution is in character cells, so not exactly 1:1 against + // a pixel based resolution, but as the tts:extent in the root + // "tt" element is frowned upon (and disallowed in the EBU-TT profile), + // we mimic the reference resolution by setting it as the cell resolution. + av_bprintf(&s->buffer, " ttp:cellResolution=\"%d %d\"\n", + script_info.play_res_x, script_info.play_res_y); + av_bprint_chars(&s->buffer, '\0', 1); + + // write the second string in extradata, head element containing the styles + av_bprintf(&s->buffer, " \n"); + av_bprintf(&s->buffer, " \n"); + + for (int i = 0; i < ass->styles_count; i++) { + int ret = AVERROR_BUG; + style = &ass->styles[i]; + + if ((ret = ttml_write_region(avctx, &s->buffer, style)) < 0) + return ret; + } + + av_bprintf(&s->buffer, " \n"); + av_bprintf(&s->buffer, " \n"); + + if (!av_bprint_is_complete(&s->buffer)) { return AVERROR(ENOMEM); } - avctx->extradata_size = TTMLENC_EXTRADATA_SIGNATURE_SIZE; + additional_extradata_size = s->buffer.len; + + // and now, write the contents of the AVB + if (!(avctx->extradata = + av_mallocz(base_extradata_size + additional_extradata_size))) { + return AVERROR(ENOMEM); + } + + avctx->extradata_size = + TTMLENC_EXTRADATA_SIGNATURE_SIZE + additional_extradata_size; memcpy(avctx->extradata, TTMLENC_EXTRADATA_SIGNATURE, TTMLENC_EXTRADATA_SIGNATURE_SIZE); + if (additional_extradata_size) + memcpy(avctx->extradata + TTMLENC_EXTRADATA_SIGNATURE_SIZE, + s->buffer.str, additional_extradata_size); + + av_bprint_clear(&s->buffer); + return 0; } diff --git a/libavcodec/ttmlenc.h b/libavcodec/ttmlenc.h index c3bb11478d..467f35c7a6 100644 --- a/libavcodec/ttmlenc.h +++ b/libavcodec/ttmlenc.h @@ -28,6 +28,7 @@ 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"; +" xmlns:tts=\"http://www.w3.org/ns/ttml#styling\"\n" +" xmlns:ttp=\"http://www.w3.org/ns/ttml#parameter\"\n"; #endif /* AVCODEC_TTMLENC_H */ diff --git a/tests/ref/fate/sub-ttmlenc b/tests/ref/fate/sub-ttmlenc index 51eab97817..6d0a8067fc 100644 --- a/tests/ref/fate/sub-ttmlenc +++ b/tests/ref/fate/sub-ttmlenc @@ -3,120 +3,132 @@ xmlns="http://www.w3.org/ns/ttml" xmlns:ttm="http://www.w3.org/ns/ttml#metadata" xmlns:tts="http://www.w3.org/ns/ttml#styling" + xmlns:ttp="http://www.w3.org/ns/ttml#parameter" + ttp:cellResolution="384 288" xml:lang=""> + + + + +

Don't show this text it may be used to insert hidden data

+ end="00:00:00.000">Don't show this text it may be used to insert hidden data

SubRip subtitles capability tester 1.3o by ale5000
Use VLC 1.1 or higher as reference for most things and MPC Home Cinema for others
This text should be blue
This text should be red
This text should be black
If you see this with the normal font, the player don't (fully) support font face

+ end="00:00:04.500">SubRip subtitles capability tester 1.3o by ale5000
Use VLC 1.1 or higher as reference for most things and MPC Home Cinema for others
This text should be blue
This text should be red
This text should be black
If you see this with the normal font, the player don't (fully) support font face

Hidden

+ end="00:00:04.500">Hidden

This text should be small
This text should be normal
This text should be big

+ end="00:00:07.500">This text should be small
This text should be normal
This text should be big

This should be an E with an accent: È
日本語
This text should be bold, italics and underline
This text should be small and green
This text should be small and red
This text should be big and brown

+ end="00:00:11.500">This should be an E with an accent: È
日本語
This text should be bold, italics and underline
This text should be small and green
This text should be small and red
This text should be big and brown

This line should be bold
This line should be italics
This line should be underline
This line should be strikethrough
Both lines
should be underline

+ end="00:00:14.500">This line should be bold
This line should be italics
This line should be underline
This line should be strikethrough
Both lines
should be underline

>
It would be a good thing to
hide invalid html tags that are closed and show the text in them
but show un-closed invalid html tags
Show not opened tags
<

+ end="00:00:17.500">>
It would be a good thing to
hide invalid html tags that are closed and show the text in them
but show un-closed invalid html tags
Show not opened tags
<

and also
hide invalid html tags with parameters that are closed and show the text in them
but show un-closed invalid html tags
This text should be showed underlined without problems also: 2<3,5>1,4<6
This shouldn't be underlined

+ end="00:00:20.500">and also
hide invalid html tags with parameters that are closed and show the text in them
but show un-closed invalid html tags
This text should be showed underlined without problems also: 2<3,5>1,4<6
This shouldn't be underlined

This text should be in the normal position...

+ end="00:00:21.500">This text should be in the normal position...

This text should NOT be in the normal position

+ end="00:00:22.500">This text should NOT be in the normal position

Implementation is the same of the ASS tag
This text should be at the
top and horizontally centered

+ end="00:00:24.500">Implementation is the same of the ASS tag
This text should be at the
top and horizontally centered

This text should be at the
middle and horizontally centered

+ end="00:00:24.500">This text should be at the
middle and horizontally centered

This text should be at the
bottom and horizontally centered

+ end="00:00:24.500">This text should be at the
bottom and horizontally centered

This text should be at the
top and horizontally at the left

+ end="00:00:26.500">This text should be at the
top and horizontally at the left

This text should be at the
middle and horizontally at the left
(The second position must be ignored)

+ end="00:00:26.500">This text should be at the
middle and horizontally at the left
(The second position must be ignored)

This text should be at the
bottom and horizontally at the left

+ end="00:00:26.500">This text should be at the
bottom and horizontally at the left

This text should be at the
top and horizontally at the right

+ end="00:00:28.500">This text should be at the
top and horizontally at the right

This text should be at the
middle and horizontally at the right

+ end="00:00:28.500">This text should be at the
middle and horizontally at the right

This text should be at the
bottom and horizontally at the right

+ end="00:00:28.500">This text should be at the
bottom and horizontally at the right

This could be the most difficult thing to implement

+ end="00:00:31.500">This could be the most difficult thing to implement

First text

+ end="00:00:50.500">First text

Second, it shouldn't overlap first

+ end="00:00:35.500">Second, it shouldn't overlap first

Third, it should replace second

+ end="00:00:37.500">Third, it should replace second

Fourth, it shouldn't overlap first and third

+ end="00:00:50.500">Fourth, it shouldn't overlap first and third

Fifth, it should replace third

+ end="00:00:45.500">Fifth, it should replace third

Sixth, it shouldn't be
showed overlapped

+ end="00:00:50.500">Sixth, it shouldn't be
showed overlapped

TEXT 1 (bottom)

+ end="00:00:52.500">TEXT 1 (bottom)

text 2

+ end="00:00:52.500">text 2

Hide these tags:
also hide these tags:
but show this: {normal text}

+ end="00:00:54.500">Hide these tags:
also hide these tags:
but show this: {normal text}


\ N is a forced line break
\ h is a hard space
Normal spaces at the start and at the end of the line are trimmed while hard spaces are not trimmed.
The\hline\hwill\hnever\hbreak\hautomatically\hright\hbefore\hor\hafter\ha\hhard\hspace.\h:-D

+ end="00:01:00.500">
\ N is a forced line break
\ h is a hard space
Normal spaces at the start and at the end of the line are trimmed while hard spaces are not trimmed.
The\hline\hwill\hnever\hbreak\hautomatically\hright\hbefore\hor\hafter\ha\hhard\hspace.\h:-D


\h\h\h\h\hA (05 hard spaces followed by a letter)
A (Normal spaces followed by a letter)
A (No hard spaces followed by a letter)

+ end="00:00:56.500">
\h\h\h\h\hA (05 hard spaces followed by a letter)
A (Normal spaces followed by a letter)
A (No hard spaces followed by a letter)

\h\h\h\h\hA (05 hard spaces followed by a letter)
A (Normal spaces followed by a letter)
A (No hard spaces followed by a letter)
Show this: \TEST and this: \-)

+ end="00:00:58.500">\h\h\h\h\hA (05 hard spaces followed by a letter)
A (Normal spaces followed by a letter)
A (No hard spaces followed by a letter)
Show this: \TEST and this: \-)


A letter followed by 05 hard spaces: A\h\h\h\h\h
A letter followed by normal spaces: A
A letter followed by no hard spaces: A
05 hard spaces between letters: A\h\h\h\h\hA
5 normal spaces between letters: A A

^--Forced line break

+ end="00:01:00.500">
A letter followed by 05 hard spaces: A\h\h\h\h\h
A letter followed by normal spaces: A
A letter followed by no hard spaces: A
05 hard spaces between letters: A\h\h\h\h\hA
5 normal spaces between letters: A A

^--Forced line break

Both line should be strikethrough,
yes.
Correctly closed tags
should be hidden.

+ end="00:01:02.500">Both line should be strikethrough,
yes.
Correctly closed tags
should be hidden.

It shouldn't be strikethrough,
not opened tag showed as text.
Not opened tag showed as text.

+ end="00:01:04.500">It shouldn't be strikethrough,
not opened tag showed as text.
Not opened tag showed as text.

Three lines should be strikethrough,
yes.
Not closed tags showed as text

+ end="00:01:06.500">Three lines should be strikethrough,
yes.
Not closed tags showed as text

Both line should be strikethrough but
the wrong closing tag should be showed

+ end="00:01:08.500">Both line should be strikethrough but
the wrong closing tag should be showed

From patchwork Tue Mar 30 08:23:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Jan_Ekstr=C3=B6m?= X-Patchwork-Id: 26650 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id D3F8144A327 for ; Tue, 30 Mar 2021 11:31:42 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id BEA28689B09; Tue, 30 Mar 2021 11:31:42 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 07C5C680BE8 for ; Tue, 30 Mar 2021 11:31:36 +0300 (EEST) Received: by mail-wr1-f53.google.com with SMTP id x7so15344764wrw.10 for ; Tue, 30 Mar 2021 01:31:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=5IsX+DiASszvR1SsdwKF9b44o7Nmx3g9qa05EarHnB4=; b=bByIuY3TaGMK2GGfI/cmOvLBDy0A24WxCh2UDEgRSm5SaJHPPc6xUHoY9cTa1GjiMg AdygBAJh25zSV4uzSu/DdqAdKb0OFcMGpBF9a1GX3zpBIbZYPP/0+T5EBnyEnzykKA8i TVLm9BvjRpY7MPDSnH2vjrqYY5n76DATeJ17pOQGkz1ORWQToajU0O6wND+BlPN7hw2O VDbIqb0lSYInwSKbJIZs4UmM+m3lb3MsuJu8jW1VCWLgON+pyo8am5RYE9HuUF77AC+Y qVzZGVjglHZ69oV34+21ZP67iERfcKHut7Vr8Qqj4ySkmAnRWU2Im5z9v06I3HyXLnkb gbVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=5IsX+DiASszvR1SsdwKF9b44o7Nmx3g9qa05EarHnB4=; b=nETn7mmGW7IgFTXEeuY4nXgSDHfeK1+xY9/TcHsEqCyl40Lg+cC1yDNchl9LmK9bBr jIeUuXT33k8Lg6aBrIPqfD2yX0lAY9hN/6lbNwBYQyILJ/7cIH2DSpiRaLpEJhVS+Rsz wTj7tPHbSgpHIZWnufLZSqZiYABPHwa0CU8oxMB6I2zpM7CSoDBFsgX946ZKlDuLRkO2 ycOs4z5/iw1tylhurINQ3UhPxdEzWPWWp4thLIBqIgqwzefGVM2P5+9hb6T0k6YM02U1 PgM5B5RroI2ujdKwMOusE0c8SsE0CYm+kcX3qpGTWwQzDuVuA1rVjBuFlzMyuaGTez4E 8Atg== X-Gm-Message-State: AOAM531ohpQ9rTwaxCzom3lZ1uWMC5r+xPoRZuMXGDsLvZo5Fiew90R/ PeJ2I4k5fEda8WvaBcZusXpokFvK0Kc= X-Google-Smtp-Source: ABdhPJz0OKcrbq+ShSKIt7y0LABrfi2/oNBDj8fZx0OKIdCZoUfI8ur8U0RKyTOKMHvV5lmNHCnrPA== X-Received: by 2002:a19:ef02:: with SMTP id n2mr18417318lfh.141.1617092632324; Tue, 30 Mar 2021 01:23:52 -0700 (PDT) Received: from localhost.localdomain (91-159-194-103.elisa-laajakaista.fi. [91.159.194.103]) by smtp.gmail.com with ESMTPSA id d34sm2089414lfv.102.2021.03.30.01.23.51 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Mar 2021 01:23:51 -0700 (PDT) From: =?utf-8?q?Jan_Ekstr=C3=B6m?= To: ffmpeg-devel@ffmpeg.org Date: Tue, 30 Mar 2021 11:23:46 +0300 Message-Id: <20210330082346.8404-5-jeebjp@gmail.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210330082346.8404-1-jeebjp@gmail.com> References: <20210330082346.8404-1-jeebjp@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 4/4] avcodec/ttmlenc: add support for region positioning and sizing X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Jan Ekström The ASS margins are utilized to generate percentual values, as the usage of cell-based sizing and offsetting seems to be not too well supported by renderers. Signed-off-by: Jan Ekström --- libavcodec/ttmlenc.c | 41 ++++++++++++++++++++++++++++++++++++-- tests/ref/fate/sub-ttmlenc | 2 ++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/libavcodec/ttmlenc.c b/libavcodec/ttmlenc.c index 7e6add62e1..a08b1ada2e 100644 --- a/libavcodec/ttmlenc.c +++ b/libavcodec/ttmlenc.c @@ -254,6 +254,26 @@ static const char *ttml_get_text_alignment(int alignment) } } +static void ttml_get_origin(ASSScriptInfo script_info, ASSStyle *style, + int *origin_left, int *origin_top) +{ + *origin_left = av_rescale(style->margin_l, 100, script_info.play_res_x); + *origin_top = + av_rescale((style->alignment >= 7) ? style->margin_v : 0, + 100, script_info.play_res_x); +} + +static void ttml_get_extent(ASSScriptInfo script_info, ASSStyle *style, + int *width, int *height) +{ + *width = av_rescale(script_info.play_res_x - style->margin_r, + 100, script_info.play_res_x); + *height = av_rescale((style->alignment <= 3) ? + script_info.play_res_y - style->margin_v : + script_info.play_res_y, + 100, script_info.play_res_y); +} + // if we set cell resolution to our script reference resolution, // then a single line is a single "point" on our canvas. Thus, by setting our // font size to font size in cells, we should gain a similar enough scale @@ -261,6 +281,8 @@ static const char *ttml_get_text_alignment(int alignment) // upon in the TTML community. static const char ttml_region_base[] = " \n"; static int ttml_write_region(AVCodecContext *avctx, AVBPrint *buf, - ASSStyle *style) + ASSScriptInfo script_info, ASSStyle *style) { if (!style) return AVERROR_INVALIDDATA; @@ -288,11 +310,22 @@ static int ttml_write_region(AVCodecContext *avctx, AVBPrint *buf, return AVERROR_INVALIDDATA; } + if (style->margin_l < 0 || style->margin_r < 0 || style->margin_v < 0) { + av_log(avctx, AV_LOG_ERROR, + "One or more negative margin values in subtitle style: " + "left: %d, right: %d, vertical: %d!\n", + style->margin_l, style->margin_r, style->margin_v); + } + { const char *display_alignment = ttml_get_display_alignment(style->alignment); const char *text_alignment = ttml_get_text_alignment(style->alignment); + int origin_left = 0; + int origin_top = 0; + int width = 0; + int height = 0; char *style_name = NULL; char *font_name = NULL; AVBPrint local_bprint = { 0 }; @@ -307,6 +340,9 @@ static int ttml_write_region(AVCodecContext *avctx, AVBPrint *buf, return AVERROR_INVALIDDATA; } + ttml_get_origin(script_info, style, &origin_left, &origin_top); + ttml_get_extent(script_info, style, &width, &height); + av_bprint_init(&local_bprint, 0, AV_BPRINT_SIZE_UNLIMITED); av_bprint_escape(&local_bprint, style->name, NULL, AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES); @@ -318,6 +354,7 @@ static int ttml_write_region(AVCodecContext *avctx, AVBPrint *buf, return ret; av_bprintf(buf, ttml_region_base, style_name, + origin_left, origin_top, width, height, display_alignment, text_alignment, style->font_size); if (style->font_name) { @@ -383,7 +420,7 @@ static int ttml_write_header_content(AVCodecContext *avctx) int ret = AVERROR_BUG; style = &ass->styles[i]; - if ((ret = ttml_write_region(avctx, &s->buffer, style)) < 0) + if ((ret = ttml_write_region(avctx, &s->buffer, script_info, style)) < 0) return ret; } diff --git a/tests/ref/fate/sub-ttmlenc b/tests/ref/fate/sub-ttmlenc index 6d0a8067fc..4df8f8796f 100644 --- a/tests/ref/fate/sub-ttmlenc +++ b/tests/ref/fate/sub-ttmlenc @@ -9,6 +9,8 @@