From patchwork Sun Jun 26 16:35:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aman Karmani X-Patchwork-Id: 36464 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:8b27:b0:88:1bbf:7fd2 with SMTP id l39csp1540119pzh; Sun, 26 Jun 2022 09:37:12 -0700 (PDT) X-Google-Smtp-Source: AGRyM1vSvGYBeJHObPXccwSk85wT8YSnSF7kiK9kJ0FYhW6VTaDsi0iUKeKS2Fp7SOXvzByD5YMo X-Received: by 2002:a05:6402:528f:b0:42a:c778:469e with SMTP id en15-20020a056402528f00b0042ac778469emr11625168edb.404.1656261432003; Sun, 26 Jun 2022 09:37:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1656261431; cv=none; d=google.com; s=arc-20160816; b=BwI3bVRywQiIZBTZbv0B9fKarI4w8gPRofDxFn89xQQm0IHoMHxtD1FgkO5XHHWq1O 7ElBF35ikil1c5MT6Iu4vDKoV3my+DLyaihScUDfyxAb/qInz1auTnmh9SqrvZS9S6rJ FH+RDe4rzMB7PTrq+srVgKo4MGDqkwMXwVu5ygeM+W0hedGCln2MKKc60W86Flt72Ta0 r66N0RgimB7SoTLnPylgH4PpkJVIxNx1OR465jOqy8tECp8fR1PNjoZEn+tHBflsX2UC 2OvgFW9U1vKO4LxUDpdazRzd4Jd7sewTQ+uVHG8o08TE/aJHVrD4X7CRMDLhyU+tB3es ew+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:to:mime-version:fcc:date:references :in-reply-to:message-id:from:dkim-signature:delivered-to; bh=gN6x2sgzVZUi2+hiNul6kgkfPNdNSRCqCYXtlDrsUWc=; b=A60x+kDcghdcEUzs9N2odK+YEnPVvrWEOwIzEZLTzSoAm3lnwjAGOkagaDRFhwfK6r /oi1sbQ2AjjnmVvvCTzwmMqKDbBKWzA8lpFWNhG+fYXDDcHfLYV7tH4sxEzKnCd4qONu 1ERijTRNzt1/OGAf8xejaxhsU6DBf56PUA6v5HtjV+QtKc+Mwbl1fCs05SJ1eNUaAGAs 8VsfyT8yoH0gzjf9oHewyeIojJZBeqWXcbhdiUDhaDg0+JllgqaQEHXKXCqIMfEw/78N UCPRtAtLnr6YJvDlm8tz1Dr+Muqx0mAGLlMKgAc6EzZDcFPyx7M+wXon4TNxXenlVu/C V9XA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=AWPjPIEC; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id k12-20020a17090666cc00b00718cd011cd9si6377326ejp.59.2022.06.26.09.37.11; Sun, 26 Jun 2022 09:37:11 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=AWPjPIEC; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 162CF68B81E; Sun, 26 Jun 2022 19:35:43 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.173]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5A97068B808 for ; Sun, 26 Jun 2022 19:35:32 +0300 (EEST) Received: by mail-pf1-f173.google.com with SMTP id w6so6923969pfw.5 for ; Sun, 26 Jun 2022 09:35:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:message-id:in-reply-to:references:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=Ym8pWO/MYVCoPzqWD2He+lVgVHVqYQVpep7VdsfAGLY=; b=AWPjPIECJ3BgtkOs9u+SBqiY8bAz37jR+9AIvfhfOIYx6x5FO1r8fHNttEZUh7DCFQ 3AoxKjTbyxjgnhgow/2FVGccTgPTV9lOTpuxI1js9JP4n3M5K7T9tqqkNeKQgG4eTb89 S1OR4a4R0v+Prs8hsQdLP4c+rXVAYZ/GvTG4FM1T3ip4/1/Vp6ea9/ZMyeYJVEELVWre vBB1AVICBtmbmjZgLrBTLw1fj741ES5sW/xbnsjbY7pdAtaWJfE4/EYUVyO+UWkoxebp pX7ovpjOpWbqjaiMPYTD7l3f7T90SgorqHqmyYqGUjOFAGGO+og6LfMmokyRh3q4+X56 wHAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:message-id:in-reply-to:references:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=Ym8pWO/MYVCoPzqWD2He+lVgVHVqYQVpep7VdsfAGLY=; b=z/hCiZnhDgtd4vOUEzPuta3x6s5VwCbjjJXK0CwpI/TyQz2heI7A1YbUk8UHaR+Uzm nXFMBaivgv3p7rDqwax7YvgLFTiT7ivrs5Ffp57/y8+JJS9kvO967pJCxmGo3qrLv3mi gK+iKQ/9yh2TTPcFBnuLid3vYCwDrEWIeB+/cjzjRQcdzxAF6zlBWvpCYh0+kh1jcvbi iB6j3N6p1VZ3wKAcKpch+JL2V+es5IiK7wx8Melwu3H6vCYQ3mKSceadRjQFPehe6VRt DfYentha9wHuP1/4JTf+zdsmPX8kG95Ma7ZDVr0Nh22zEN25Rj7XSnpAEjv0Y6YH66xP GLdQ== X-Gm-Message-State: AJIora91rrmnKBzfwB3FWCwK+u4GmWsWfFX7BRsi0rK/BGBd05D3JADD FPjH9Vrt41oLw3IyvhqIHEMosCDgCyLCwQ== X-Received: by 2002:a65:6b92:0:b0:39c:c97b:1b57 with SMTP id d18-20020a656b92000000b0039cc97b1b57mr8744243pgw.517.1656261330108; Sun, 26 Jun 2022 09:35:30 -0700 (PDT) Received: from [127.0.0.1] (master.gitmailbox.com. [34.83.118.50]) by smtp.gmail.com with ESMTPSA id f1-20020a635541000000b003fcfdc9946dsm5237551pgm.51.2022.06.26.09.35.29 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sun, 26 Jun 2022 09:35:29 -0700 (PDT) From: softworkz X-Google-Original-From: softworkz Message-Id: <4903cdd1cd10f71740f1623a0dc3e8edfe67ca21.1656261322.git.ffmpegagent@gmail.com> In-Reply-To: References: Date: Sun, 26 Jun 2022 16:35:03 +0000 Fcc: Sent MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Subject: [FFmpeg-devel] [PATCH v6 06/25] avcodec, avutil: Move ass helper functions to avutil as avpriv_ and extend ass dialog parsing X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Cc: Michael Niedermayer , softworkz , Andriy Gelman , Andreas Rheinhardt Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 9QdGYp3pGAPD From: softworkz Also add - hard_space callback (for upcoming fix) - extensible callback (for future extension) - new API which allows tag filtering Signed-off-by: softworkz --- libavcodec/Makefile | 56 +++--- libavcodec/ass.h | 151 +++++---------- libavcodec/ass_split.h | 191 ------------------- libavcodec/assdec.c | 2 +- libavcodec/assenc.c | 2 +- libavcodec/ccaption_dec.c | 20 +- libavcodec/jacosubdec.c | 2 +- libavcodec/libaribb24.c | 2 +- libavcodec/libzvbi-teletextdec.c | 14 +- libavcodec/microdvddec.c | 7 +- libavcodec/movtextdec.c | 3 +- libavcodec/movtextenc.c | 20 +- libavcodec/mpl2dec.c | 2 +- libavcodec/realtextdec.c | 2 +- libavcodec/samidec.c | 2 +- libavcodec/srtdec.c | 2 +- libavcodec/srtenc.c | 16 +- libavcodec/subviewerdec.c | 2 +- libavcodec/textdec.c | 4 +- libavcodec/ttmlenc.c | 15 +- libavcodec/webvttdec.c | 2 +- libavcodec/webvttenc.c | 16 +- libavutil/Makefile | 2 + {libavcodec => libavutil}/ass.c | 115 ++++-------- libavutil/ass_internal.h | 135 ++++++++++++++ {libavcodec => libavutil}/ass_split.c | 179 +++++++++++++++--- libavutil/ass_split_internal.h | 254 ++++++++++++++++++++++++++ 27 files changed, 726 insertions(+), 492 deletions(-) delete mode 100644 libavcodec/ass_split.h rename {libavcodec => libavutil}/ass.c (59%) create mode 100644 libavutil/ass_internal.h rename {libavcodec => libavutil}/ass_split.c (71%) create mode 100644 libavutil/ass_split_internal.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3b8f7b5e01..4bfc90b6e9 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -221,10 +221,10 @@ OBJS-$(CONFIG_APNG_DECODER) += png.o pngdec.o pngdsp.o OBJS-$(CONFIG_APNG_ENCODER) += png.o pngenc.o OBJS-$(CONFIG_ARBC_DECODER) += arbc.o OBJS-$(CONFIG_ARGO_DECODER) += argo.o -OBJS-$(CONFIG_SSA_DECODER) += assdec.o ass.o -OBJS-$(CONFIG_SSA_ENCODER) += assenc.o ass.o -OBJS-$(CONFIG_ASS_DECODER) += assdec.o ass.o -OBJS-$(CONFIG_ASS_ENCODER) += assenc.o ass.o +OBJS-$(CONFIG_SSA_DECODER) += assdec.o +OBJS-$(CONFIG_SSA_ENCODER) += assenc.o +OBJS-$(CONFIG_ASS_DECODER) += assdec.o +OBJS-$(CONFIG_ASS_ENCODER) += assenc.o OBJS-$(CONFIG_ASV1_DECODER) += asvdec.o asv.o mpeg12data.o OBJS-$(CONFIG_ASV1_ENCODER) += asvenc.o asv.o mpeg12data.o OBJS-$(CONFIG_ASV2_DECODER) += asvdec.o asv.o mpeg12data.o @@ -265,7 +265,7 @@ OBJS-$(CONFIG_BRENDER_PIX_DECODER) += brenderpix.o OBJS-$(CONFIG_C93_DECODER) += c93.o OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ cavsdata.o -OBJS-$(CONFIG_CCAPTION_DECODER) += ccaption_dec.o ass.o +OBJS-$(CONFIG_CCAPTION_DECODER) += ccaption_dec.o OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o OBJS-$(CONFIG_CDTOONS_DECODER) += cdtoons.o OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o @@ -442,7 +442,7 @@ OBJS-$(CONFIG_INTERPLAY_ACM_DECODER) += interplayacm.o OBJS-$(CONFIG_INTERPLAY_DPCM_DECODER) += dpcm.o OBJS-$(CONFIG_INTERPLAY_VIDEO_DECODER) += interplayvideo.o OBJS-$(CONFIG_IPU_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o -OBJS-$(CONFIG_JACOSUB_DECODER) += jacosubdec.o ass.o +OBJS-$(CONFIG_JACOSUB_DECODER) += jacosubdec.o OBJS-$(CONFIG_JPEG2000_ENCODER) += j2kenc.o mqcenc.o mqc.o jpeg2000.o \ jpeg2000dwt.o OBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dec.o jpeg2000.o jpeg2000dsp.o \ @@ -464,7 +464,7 @@ OBJS-$(CONFIG_MAGICYUV_ENCODER) += magicyuvenc.o OBJS-$(CONFIG_MDEC_DECODER) += mdec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_METASOUND_DECODER) += metasound.o metasound_data.o \ twinvq.o -OBJS-$(CONFIG_MICRODVD_DECODER) += microdvddec.o ass.o +OBJS-$(CONFIG_MICRODVD_DECODER) += microdvddec.o OBJS-$(CONFIG_MIMIC_DECODER) += mimic.o OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o mjpegdec_common.o OBJS-$(CONFIG_MJPEG_QSV_DECODER) += qsvdec.o @@ -479,8 +479,8 @@ OBJS-$(CONFIG_MLP_ENCODER) += mlpenc.o mlp.o OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o OBJS-$(CONFIG_MOBICLIP_DECODER) += mobiclip.o OBJS-$(CONFIG_MOTIONPIXELS_DECODER) += motionpixels.o -OBJS-$(CONFIG_MOVTEXT_DECODER) += movtextdec.o ass.o -OBJS-$(CONFIG_MOVTEXT_ENCODER) += movtextenc.o ass_split.o +OBJS-$(CONFIG_MOVTEXT_DECODER) += movtextdec.o +OBJS-$(CONFIG_MOVTEXT_ENCODER) += movtextenc.o OBJS-$(CONFIG_MP1_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP1FLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MP2_DECODER) += mpegaudiodec_fixed.o @@ -521,7 +521,7 @@ OBJS-$(CONFIG_MPEG4_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_MPEG4_OMX_ENCODER) += omx.o OBJS-$(CONFIG_MPEG4_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_MPEG4_V4L2M2M_ENCODER) += v4l2_m2m_enc.o -OBJS-$(CONFIG_MPL2_DECODER) += mpl2dec.o ass.o +OBJS-$(CONFIG_MPL2_DECODER) += mpl2dec.o OBJS-$(CONFIG_MSA1_DECODER) += mss3.o OBJS-$(CONFIG_MSCC_DECODER) += mscc.o OBJS-$(CONFIG_MSMPEG4V1_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o @@ -574,7 +574,7 @@ OBJS-$(CONFIG_PGX_DECODER) += pgxdec.o OBJS-$(CONFIG_PHOTOCD_DECODER) += photocd.o OBJS-$(CONFIG_PICTOR_DECODER) += pictordec.o cga_data.o OBJS-$(CONFIG_PIXLET_DECODER) += pixlet.o -OBJS-$(CONFIG_PJS_DECODER) += textdec.o ass.o +OBJS-$(CONFIG_PJS_DECODER) += textdec.o OBJS-$(CONFIG_PNG_DECODER) += png.o pngdec.o pngdsp.o OBJS-$(CONFIG_PNG_ENCODER) += png.o pngenc.o OBJS-$(CONFIG_PPM_DECODER) += pnmdec.o pnm.o @@ -609,7 +609,7 @@ OBJS-$(CONFIG_RALF_DECODER) += ralf.o OBJS-$(CONFIG_RASC_DECODER) += rasc.o OBJS-$(CONFIG_RAWVIDEO_DECODER) += rawdec.o OBJS-$(CONFIG_RAWVIDEO_ENCODER) += rawenc.o -OBJS-$(CONFIG_REALTEXT_DECODER) += realtextdec.o ass.o +OBJS-$(CONFIG_REALTEXT_DECODER) += realtextdec.o OBJS-$(CONFIG_RL2_DECODER) += rl2.o OBJS-$(CONFIG_ROQ_DECODER) += roqvideodec.o roqvideo.o OBJS-$(CONFIG_ROQ_ENCODER) += roqvideoenc.o roqvideo.o elbg.o @@ -624,7 +624,7 @@ OBJS-$(CONFIG_RV20_DECODER) += rv10.o OBJS-$(CONFIG_RV20_ENCODER) += rv20enc.o OBJS-$(CONFIG_RV30_DECODER) += rv30.o rv34.o rv30dsp.o OBJS-$(CONFIG_RV40_DECODER) += rv40.o rv34.o rv40dsp.o -OBJS-$(CONFIG_SAMI_DECODER) += samidec.o ass.o htmlsubtitles.o +OBJS-$(CONFIG_SAMI_DECODER) += samidec.o htmlsubtitles.o OBJS-$(CONFIG_S302M_DECODER) += s302m.o OBJS-$(CONFIG_S302M_ENCODER) += s302menc.o OBJS-$(CONFIG_SANM_DECODER) += sanm.o @@ -659,13 +659,13 @@ OBJS-$(CONFIG_SPEEDHQ_ENCODER) += speedhq.o mpeg12data.o mpeg12enc.o spe OBJS-$(CONFIG_SPEEX_DECODER) += speexdec.o OBJS-$(CONFIG_SP5X_DECODER) += sp5xdec.o OBJS-$(CONFIG_SRGC_DECODER) += mscc.o -OBJS-$(CONFIG_SRT_DECODER) += srtdec.o ass.o htmlsubtitles.o -OBJS-$(CONFIG_SRT_ENCODER) += srtenc.o ass_split.o -OBJS-$(CONFIG_STL_DECODER) += textdec.o ass.o -OBJS-$(CONFIG_SUBRIP_DECODER) += srtdec.o ass.o htmlsubtitles.o -OBJS-$(CONFIG_SUBRIP_ENCODER) += srtenc.o ass_split.o -OBJS-$(CONFIG_SUBVIEWER1_DECODER) += textdec.o ass.o -OBJS-$(CONFIG_SUBVIEWER_DECODER) += subviewerdec.o ass.o +OBJS-$(CONFIG_SRT_DECODER) += srtdec.o htmlsubtitles.o +OBJS-$(CONFIG_SRT_ENCODER) += srtenc.o +OBJS-$(CONFIG_STL_DECODER) += textdec.o +OBJS-$(CONFIG_SUBRIP_DECODER) += srtdec.o htmlsubtitles.o +OBJS-$(CONFIG_SUBRIP_ENCODER) += srtenc.o +OBJS-$(CONFIG_SUBVIEWER1_DECODER) += textdec.o +OBJS-$(CONFIG_SUBVIEWER_DECODER) += subviewerdec.o OBJS-$(CONFIG_SUNRAST_DECODER) += sunrast.o OBJS-$(CONFIG_SUNRAST_ENCODER) += sunrastenc.o OBJS-$(CONFIG_LIBRSVG_DECODER) += librsvgdec.o @@ -675,8 +675,8 @@ OBJS-$(CONFIG_SVQ1_DECODER) += svq1dec.o svq1.o h263data.o OBJS-$(CONFIG_SVQ1_ENCODER) += svq1enc.o svq1.o h263data.o \ h263.o ituh263enc.o OBJS-$(CONFIG_SVQ3_DECODER) += svq3.o mpegutils.o h264data.o -OBJS-$(CONFIG_TEXT_DECODER) += textdec.o ass.o -OBJS-$(CONFIG_TEXT_ENCODER) += srtenc.o ass_split.o +OBJS-$(CONFIG_TEXT_DECODER) += textdec.o +OBJS-$(CONFIG_TEXT_ENCODER) += srtenc.o OBJS-$(CONFIG_TAK_DECODER) += takdec.o tak.o takdsp.o OBJS-$(CONFIG_TARGA_DECODER) += targa.o OBJS-$(CONFIG_TARGA_ENCODER) += targaenc.o rle.o @@ -696,7 +696,7 @@ OBJS-$(CONFIG_TSCC_DECODER) += tscc.o msrledec.o OBJS-$(CONFIG_TSCC2_DECODER) += tscc2.o OBJS-$(CONFIG_TTA_DECODER) += tta.o ttadata.o ttadsp.o OBJS-$(CONFIG_TTA_ENCODER) += ttaenc.o ttaencdsp.o ttadata.o -OBJS-$(CONFIG_TTML_ENCODER) += ttmlenc.o ass_split.o +OBJS-$(CONFIG_TTML_ENCODER) += ttmlenc.o OBJS-$(CONFIG_TWINVQ_DECODER) += twinvqdec.o twinvq.o metasound_data.o OBJS-$(CONFIG_TXD_DECODER) += txd.o OBJS-$(CONFIG_ULTI_DECODER) += ulti.o @@ -753,15 +753,15 @@ OBJS-$(CONFIG_VP9_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_VP9_RKMPP_DECODER) += rkmppdec.o OBJS-$(CONFIG_VP9_VAAPI_ENCODER) += vaapi_encode_vp9.o OBJS-$(CONFIG_VP9_QSV_ENCODER) += qsvenc_vp9.o -OBJS-$(CONFIG_VPLAYER_DECODER) += textdec.o ass.o +OBJS-$(CONFIG_VPLAYER_DECODER) += textdec.o OBJS-$(CONFIG_VP9_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o wavpackdata.o dsd.o OBJS-$(CONFIG_WAVPACK_ENCODER) += wavpackdata.o wavpackenc.o OBJS-$(CONFIG_WCMV_DECODER) += wcmv.o OBJS-$(CONFIG_WEBP_DECODER) += webp.o -OBJS-$(CONFIG_WEBVTT_DECODER) += webvttdec.o ass.o -OBJS-$(CONFIG_WEBVTT_ENCODER) += webvttenc.o ass_split.o +OBJS-$(CONFIG_WEBVTT_DECODER) += webvttdec.o +OBJS-$(CONFIG_WEBVTT_ENCODER) += webvttenc.o OBJS-$(CONFIG_WMALOSSLESS_DECODER) += wmalosslessdec.o wma_common.o OBJS-$(CONFIG_WMAPRO_DECODER) += wmaprodec.o wma.o wma_common.o OBJS-$(CONFIG_WMAV1_DECODER) += wmadec.o wma.o wma_common.o aactab.o @@ -1051,7 +1051,7 @@ OBJS-$(CONFIG_PCM_ALAW_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o -OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o +OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o OBJS-$(CONFIG_LIBCODEC2_ENCODER) += libcodec2.o @@ -1104,7 +1104,7 @@ OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o OBJS-$(CONFIG_LIBXAVS2_ENCODER) += libxavs2.o OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o -OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o ass.o +OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o # parsers OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o diff --git a/libavcodec/ass.h b/libavcodec/ass.h index 4dffe923d9..8bc13d7ab8 100644 --- a/libavcodec/ass.h +++ b/libavcodec/ass.h @@ -23,124 +23,73 @@ #define AVCODEC_ASS_H #include "avcodec.h" -#include "libavutil/bprint.h" - -#define ASS_DEFAULT_PLAYRESX 384 -#define ASS_DEFAULT_PLAYRESY 288 - -/** - * @name Default values for ASS style - * @{ - */ -#define ASS_DEFAULT_FONT "Arial" -#define ASS_DEFAULT_FONT_SIZE 16 -#define ASS_DEFAULT_COLOR 0xffffff -#define ASS_DEFAULT_BACK_COLOR 0 -#define ASS_DEFAULT_BOLD 0 -#define ASS_DEFAULT_ITALIC 0 -#define ASS_DEFAULT_UNDERLINE 0 -#define ASS_DEFAULT_ALIGNMENT 2 -#define ASS_DEFAULT_BORDERSTYLE 1 -/** @} */ +#include "libavutil/ass_internal.h" typedef struct FFASSDecoderContext { int readorder; } FFASSDecoderContext; -/** - * Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS. - * Can specify all fields explicitly - * - * @param avctx pointer to the AVCodecContext - * @param play_res_x subtitle frame width - * @param play_res_y subtitle frame height - * @param font name of the default font face to use - * @param font_size default font size to use - * @param primary_color default text color to use (ABGR) - * @param secondary_color default secondary text color to use (ABGR) - * @param outline_color default outline color to use (ABGR) - * @param back_color default background color to use (ABGR) - * @param bold 1 for bold text, 0 for normal text - * @param italic 1 for italic text, 0 for normal text - * @param underline 1 for underline text, 0 for normal text - * @param border_style 1 for outline, 3 for opaque box - * @param alignment position of the text (left, center, top...), defined after - * the layout of the numpad (1-3 sub, 4-6 mid, 7-9 top) - * @return >= 0 on success otherwise an error code <0 - */ -int ff_ass_subtitle_header_full(AVCodecContext *avctx, +static inline int ff_ass_subtitle_header_full(AVCodecContext *avctx, int play_res_x, int play_res_y, const char *font, int font_size, int primary_color, int secondary_color, int outline_color, int back_color, int bold, int italic, int underline, - int border_style, int alignment); -/** - * Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS. - * - * @param avctx pointer to the AVCodecContext - * @param font name of the default font face to use - * @param font_size default font size to use - * @param color default text color to use (ABGR) - * @param back_color default background color to use (ABGR) - * @param bold 1 for bold text, 0 for normal text - * @param italic 1 for italic text, 0 for normal text - * @param underline 1 for underline text, 0 for normal text - * @param alignment position of the text (left, center, top...), defined after - * the layout of the numpad (1-3 sub, 4-6 mid, 7-9 top) - * @return >= 0 on success otherwise an error code <0 - */ -int ff_ass_subtitle_header(AVCodecContext *avctx, - const char *font, int font_size, - int color, int back_color, - int bold, int italic, int underline, - int border_style, int alignment); + int border_style, int alignment) +{ + avctx->subtitle_header = (uint8_t *)avpriv_ass_get_subtitle_header_full( + play_res_x, play_res_y, font, font_size, + primary_color, secondary_color, outline_color, + back_color, bold,italic,underline,border_style,alignment, + !(avctx->flags & AV_CODEC_FLAG_BITEXACT)); -/** - * Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS - * with default style. - * - * @param avctx pointer to the AVCodecContext - * @return >= 0 on success otherwise an error code <0 - */ -int ff_ass_subtitle_header_default(AVCodecContext *avctx); + if (!avctx->subtitle_header) + return AVERROR(ENOMEM); + avctx->subtitle_header_size = strlen((char *)avctx->subtitle_header); + return 0; +} -/** - * Craft an ASS dialog string. - */ -char *ff_ass_get_dialog(int readorder, int layer, const char *style, - const char *speaker, const char *text); +static inline int ff_ass_subtitle_header_default(AVCodecContext *avctx) +{ + avctx->subtitle_header = (uint8_t *)avpriv_ass_get_subtitle_header_default(!(avctx->flags & AV_CODEC_FLAG_BITEXACT)); -/** - * Add an ASS dialog to a subtitle. - */ -int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, - int readorder, int layer, const char *style, - const char *speaker); + if (!avctx->subtitle_header) + return AVERROR(ENOMEM); + avctx->subtitle_header_size = strlen((char *)avctx->subtitle_header); + return 0; +} + +static inline void ff_ass_decoder_flush(AVCodecContext *avctx) +{ + FFASSDecoderContext *s = avctx->priv_data; + if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP)) + s->readorder = 0; +} /** * Add an ASS dialog to a subtitle. */ -int ff_ass_add_rect2(AVSubtitle *sub, const char *dialog, - int readorder, int layer, const char *style, - const char *speaker, unsigned *nb_rect_allocated); +static inline int avpriv_ass_add_rect(AVSubtitle *sub, const char *dialog, + int readorder, int layer, const char *style, + const char *speaker) +{ + char *ass_str; + AVSubtitleRect **rects; -/** - * Helper to flush a text subtitles decoder making use of the - * FFASSDecoderContext. - */ -void ff_ass_decoder_flush(AVCodecContext *avctx); + rects = av_realloc_array(sub->rects, sub->num_rects+1, sizeof(*sub->rects)); + if (!rects) + return AVERROR(ENOMEM); + sub->rects = rects; + rects[sub->num_rects] = av_mallocz(sizeof(*rects[0])); + if (!rects[sub->num_rects]) + return AVERROR(ENOMEM); + rects[sub->num_rects]->type = SUBTITLE_ASS; + ass_str = avpriv_ass_get_dialog(readorder, layer, style, speaker, dialog); + if (!ass_str) + return AVERROR(ENOMEM); + rects[sub->num_rects]->ass = ass_str; + sub->num_rects++; + return 0; +} -/** - * Escape a text subtitle using ASS syntax into an AVBPrint buffer. - * Newline characters will be escaped to \N. - * - * @param buf pointer to an initialized AVBPrint buffer - * @param p source text - * @param size size of the source text - * @param linebreaks additional newline chars, which will be escaped to \N - * @param keep_ass_markup braces and backslash will not be escaped if set - */ -void ff_ass_bprint_text_event(AVBPrint *buf, const char *p, int size, - const char *linebreaks, int keep_ass_markup); #endif /* AVCODEC_ASS_H */ diff --git a/libavcodec/ass_split.h b/libavcodec/ass_split.h deleted file mode 100644 index a45fb9b8a1..0000000000 --- a/libavcodec/ass_split.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * SSA/ASS spliting functions - * Copyright (c) 2010 Aurelien Jacobs - * - * 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 - */ - -#ifndef AVCODEC_ASS_SPLIT_H -#define AVCODEC_ASS_SPLIT_H - -/** - * fields extracted from the [Script Info] section - */ -typedef struct { - char *script_type; /**< SSA script format version (eg. v4.00) */ - char *collisions; /**< how subtitles are moved to prevent collisions */ - int play_res_x; /**< video width that ASS coords are referring to */ - int play_res_y; /**< video height that ASS coords are referring to */ - float timer; /**< time multiplier to apply to SSA clock (in %) */ -} ASSScriptInfo; - -/** - * fields extracted from the [V4(+) Styles] section - */ -typedef struct { - char *name; /**< name of the tyle (case sensitive) */ - char *font_name; /**< font face (case sensitive) */ - int font_size; /**< font height */ - int primary_color; /**< color that a subtitle will normally appear in */ - int secondary_color; - int outline_color; /**< color for outline in ASS, called tertiary in SSA */ - int back_color; /**< color of the subtitle outline or shadow */ - int bold; /**< whether text is bold (1) or not (0) */ - int italic; /**< whether text is italic (1) or not (0) */ - int underline; /**< whether text is underlined (1) or not (0) */ - int strikeout; - float scalex; - float scaley; - float spacing; - float angle; - int border_style; - float outline; - float shadow; - int alignment; /**< position of the text (left, center, top...), - defined after the layout of the numpad - (1-3 sub, 4-6 mid, 7-9 top) */ - int margin_l; - int margin_r; - int margin_v; - int alpha_level; - int encoding; -} ASSStyle; - -/** - * fields extracted from the [Events] section - */ -typedef struct { - int readorder; - int layer; /**< higher numbered layers are drawn over lower numbered */ - int start; /**< start time of the dialog in centiseconds */ - int end; /**< end time of the dialog in centiseconds */ - char *style; /**< name of the ASSStyle to use with this dialog */ - char *name; - int margin_l; - int margin_r; - int margin_v; - char *effect; - char *text; /**< actual text which will be displayed as a subtitle, - can include style override control codes (see - ff_ass_split_override_codes()) */ -} ASSDialog; - -/** - * structure containing the whole split ASS data - */ -typedef struct { - ASSScriptInfo script_info; /**< general information about the SSA script*/ - ASSStyle *styles; /**< array of split out styles */ - int styles_count; /**< number of ASSStyle in the styles array */ - ASSDialog *dialogs; /**< array of split out dialogs */ - int dialogs_count; /**< number of ASSDialog in the dialogs array*/ -} ASS; - -/** - * This struct can be casted to ASS to access to the split data. - */ -typedef struct ASSSplitContext ASSSplitContext; - -/** - * Split a full ASS file or a ASS header from a string buffer and store - * the split structure in a newly allocated context. - * - * @param buf String containing the ASS formatted data. - * @return Newly allocated struct containing split data. - */ -ASSSplitContext *ff_ass_split(const char *buf); - -/** - * Free a dialogue obtained from ff_ass_split_dialog(). - */ -void ff_ass_free_dialog(ASSDialog **dialogp); - -/** - * Split one ASS Dialogue line from a string buffer. - * - * @param ctx Context previously initialized by ff_ass_split(). - * @param buf String containing the ASS "Dialogue" line. - * @return Pointer to the split ASSDialog. Must be freed with ff_ass_free_dialog() - */ -ASSDialog *ff_ass_split_dialog(ASSSplitContext *ctx, const char *buf); - -/** - * Free all the memory allocated for an ASSSplitContext. - * - * @param ctx Context previously initialized by ff_ass_split(). - */ -void ff_ass_split_free(ASSSplitContext *ctx); - - -/** - * Set of callback functions corresponding to each override codes that can - * be encountered in a "Dialogue" Text field. - */ -typedef struct { - /** - * @defgroup ass_styles ASS styles - * @{ - */ - void (*text)(void *priv, const char *text, int len); - void (*new_line)(void *priv, int forced); - void (*style)(void *priv, char style, int close); - void (*color)(void *priv, unsigned int /* color */, unsigned int color_id); - void (*alpha)(void *priv, int alpha, int alpha_id); - void (*font_name)(void *priv, const char *name); - void (*font_size)(void *priv, int size); - void (*alignment)(void *priv, int alignment); - void (*cancel_overrides)(void *priv, const char *style); - /** @} */ - - /** - * @defgroup ass_functions ASS functions - * @{ - */ - void (*move)(void *priv, int x1, int y1, int x2, int y2, int t1, int t2); - void (*origin)(void *priv, int x, int y); - /** @} */ - - /** - * @defgroup ass_end end of Dialogue Event - * @{ - */ - void (*end)(void *priv); - /** @} */ -} ASSCodesCallbacks; - -/** - * Split override codes out of a ASS "Dialogue" Text field. - * - * @param callbacks Set of callback functions called for each override code - * encountered. - * @param priv Opaque pointer passed to the callback functions. - * @param buf The ASS "Dialogue" Text field to split. - * @return >= 0 on success otherwise an error code <0 - */ -int ff_ass_split_override_codes(const ASSCodesCallbacks *callbacks, void *priv, - const char *buf); - -/** - * Find an ASSStyle structure by its name. - * - * @param ctx Context previously initialized by ff_ass_split(). - * @param style name of the style to search for. - * @return the ASSStyle corresponding to style, or NULL if style can't be found - */ -ASSStyle *ff_ass_style_get(ASSSplitContext *ctx, const char *style); - -#endif /* AVCODEC_ASS_SPLIT_H */ diff --git a/libavcodec/assdec.c b/libavcodec/assdec.c index f43b500aa7..1a1363471d 100644 --- a/libavcodec/assdec.c +++ b/libavcodec/assdec.c @@ -22,9 +22,9 @@ #include #include "avcodec.h" -#include "ass.h" #include "codec_internal.h" #include "config_components.h" +#include "libavutil/ass_internal.h" #include "libavutil/internal.h" #include "libavutil/mem.h" diff --git a/libavcodec/assenc.c b/libavcodec/assenc.c index 2ac40d5afe..391d690133 100644 --- a/libavcodec/assenc.c +++ b/libavcodec/assenc.c @@ -24,8 +24,8 @@ #include #include "avcodec.h" -#include "ass.h" #include "codec_internal.h" +#include "libavutil/ass_internal.h" #include "libavutil/avstring.h" #include "libavutil/internal.h" #include "libavutil/mem.h" diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c index 34f0513b1a..5f706d985f 100644 --- a/libavcodec/ccaption_dec.c +++ b/libavcodec/ccaption_dec.c @@ -272,15 +272,12 @@ static av_cold int init_decoder(AVCodecContext *avctx) ctx->bg_color = CCCOL_BLACK; ctx->rollup = 2; ctx->cursor_row = 10; - ret = ff_ass_subtitle_header(avctx, "Monospace", + ret = ff_ass_subtitle_header_full(avctx, ASS_DEFAULT_PLAYRESX, ASS_DEFAULT_PLAYRESY, "Monospace", ASS_DEFAULT_FONT_SIZE, - ASS_DEFAULT_COLOR, - ASS_DEFAULT_BACK_COLOR, - ASS_DEFAULT_BOLD, - ASS_DEFAULT_ITALIC, - ASS_DEFAULT_UNDERLINE, - 3, - ASS_DEFAULT_ALIGNMENT); + ASS_DEFAULT_COLOR, ASS_DEFAULT_COLOR, + ASS_DEFAULT_BACK_COLOR, ASS_DEFAULT_BACK_COLOR, + ASS_DEFAULT_BOLD, ASS_DEFAULT_ITALIC, ASS_DEFAULT_UNDERLINE, + 3, ASS_DEFAULT_ALIGNMENT); if (ret < 0) { return ret; } @@ -850,7 +847,6 @@ static int decode(AVCodecContext *avctx, AVSubtitle *sub, int len = avpkt->size; int ret = 0; int i; - unsigned nb_rect_allocated = 0; for (i = 0; i < len; i += 3) { uint8_t hi, cc_type = bptr[i] & 1; @@ -887,7 +883,7 @@ static int decode(AVCodecContext *avctx, AVSubtitle *sub, AV_TIME_BASE_Q, ms_tb); else sub->end_display_time = -1; - ret = ff_ass_add_rect2(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL, &nb_rect_allocated); + ret = avpriv_ass_add_rect(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL); if (ret < 0) return ret; ctx->last_real_time = sub->pts; @@ -897,7 +893,7 @@ static int decode(AVCodecContext *avctx, AVSubtitle *sub, if (!bptr && !ctx->real_time && ctx->buffer[!ctx->buffer_index].str[0]) { bidx = !ctx->buffer_index; - ret = ff_ass_add_rect2(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL, &nb_rect_allocated); + ret = avpriv_ass_add_rect(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL); if (ret < 0) return ret; sub->pts = ctx->buffer_time[1]; @@ -915,7 +911,7 @@ static int decode(AVCodecContext *avctx, AVSubtitle *sub, capture_screen(ctx); ctx->buffer_changed = 0; - ret = ff_ass_add_rect2(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL, &nb_rect_allocated); + ret = avpriv_ass_add_rect(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL); if (ret < 0) return ret; sub->end_display_time = -1; diff --git a/libavcodec/jacosubdec.c b/libavcodec/jacosubdec.c index e3bf9f4226..40abdebcc6 100644 --- a/libavcodec/jacosubdec.c +++ b/libavcodec/jacosubdec.c @@ -182,7 +182,7 @@ static int jacosub_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, av_bprint_init(&buffer, JSS_MAX_LINESIZE, JSS_MAX_LINESIZE); jacosub_to_ass(avctx, &buffer, ptr); - ret = ff_ass_add_rect(sub, buffer.str, s->readorder++, 0, NULL, NULL); + ret = avpriv_ass_add_rect(sub, buffer.str, s->readorder++, 0, NULL, NULL); av_bprint_finalize(&buffer, NULL); if (ret < 0) return ret; diff --git a/libavcodec/libaribb24.c b/libavcodec/libaribb24.c index 9658e1d5ac..360e20834b 100644 --- a/libavcodec/libaribb24.c +++ b/libavcodec/libaribb24.c @@ -274,7 +274,7 @@ next_region: av_log(avctx, AV_LOG_DEBUG, "Styled ASS line: %s\n", buf.str); - ret = ff_ass_add_rect(sub, buf.str, b24->read_order++, + ret = avpriv_ass_add_rect(sub, buf.str, b24->read_order++, 0, NULL, NULL); } diff --git a/libavcodec/libzvbi-teletextdec.c b/libavcodec/libzvbi-teletextdec.c index 2aab10a548..54a78342f2 100644 --- a/libavcodec/libzvbi-teletextdec.c +++ b/libavcodec/libzvbi-teletextdec.c @@ -153,12 +153,12 @@ static char *create_ass_text(TeletextContext *ctx, const char *text) AVBPrint buf; av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); - ff_ass_bprint_text_event(&buf, text, strlen(text), "", 0); + avpriv_ass_bprint_text_event(&buf, text, strlen(text), "", 0); if (!av_bprint_is_complete(&buf)) { av_bprint_finalize(&buf, NULL); return NULL; } - dialog = ff_ass_get_dialog(ctx->readorder++, 0, NULL, NULL, buf.str); + dialog = avpriv_ass_get_dialog(ctx->readorder++, 0, NULL, NULL, buf.str); av_bprint_finalize(&buf, NULL); return dialog; } @@ -225,7 +225,7 @@ static int gen_sub_text(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_page } av_log(ctx, AV_LOG_DEBUG, "subtext:%s:txetbus\n", sub_rect->ass); } else { - sub_rect->type = SUBTITLE_NONE; + sub_rect->type = AV_SUBTITLE_FMT_NONE; } av_bprint_finalize(&buf, NULL); return 0; @@ -395,7 +395,7 @@ static int gen_sub_ass(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_page if (buf.len) { sub_rect->type = SUBTITLE_ASS; - sub_rect->ass = ff_ass_get_dialog(ctx->readorder++, 0, is_subtitle_page ? "Subtitle" : "Teletext", NULL, buf.str); + sub_rect->ass = avpriv_ass_get_dialog(ctx->readorder++, 0, is_subtitle_page ? "Subtitle" : "Teletext", NULL, buf.str); if (!sub_rect->ass) { av_bprint_finalize(&buf, NULL); @@ -403,7 +403,7 @@ static int gen_sub_ass(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_page } av_log(ctx, AV_LOG_DEBUG, "subtext:%s:txetbus\n", sub_rect->ass); } else { - sub_rect->type = SUBTITLE_NONE; + sub_rect->type = AV_SUBTITLE_FMT_NONE; } av_bprint_finalize(&buf, NULL); return 0; @@ -463,7 +463,7 @@ static int gen_sub_bitmap(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_pa if (vc >= vcend) { av_log(ctx, AV_LOG_DEBUG, "dropping empty page %3x\n", page->pgno); - sub_rect->type = SUBTITLE_NONE; + sub_rect->type = AV_SUBTITLE_FMT_NONE; return 0; } @@ -696,7 +696,7 @@ static int teletext_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, sub->num_rects = 0; sub->pts = ctx->pages->pts; - if (ctx->pages->sub_rect->type != SUBTITLE_NONE) { + if (ctx->pages->sub_rect->type != AV_SUBTITLE_FMT_NONE) { sub->rects = av_malloc(sizeof(*sub->rects)); if (sub->rects) { sub->num_rects = 1; diff --git a/libavcodec/microdvddec.c b/libavcodec/microdvddec.c index f36ad51468..de17400edd 100644 --- a/libavcodec/microdvddec.c +++ b/libavcodec/microdvddec.c @@ -309,7 +309,7 @@ static int microdvd_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, } } if (new_line.len) { - int ret = ff_ass_add_rect(sub, new_line.str, s->readorder++, 0, NULL, NULL); + int ret = avpriv_ass_add_rect(sub, new_line.str, s->readorder++, 0, NULL, NULL); av_bprint_finalize(&new_line, NULL); if (ret < 0) return ret; @@ -362,8 +362,9 @@ static int microdvd_init(AVCodecContext *avctx) } } } - return ff_ass_subtitle_header(avctx, font_buf.str, font_size, color, - ASS_DEFAULT_BACK_COLOR, bold, italic, + return ff_ass_subtitle_header_full(avctx, ASS_DEFAULT_PLAYRESX, ASS_DEFAULT_PLAYRESY, + font_buf.str, font_size, color, color, + ASS_DEFAULT_BACK_COLOR, ASS_DEFAULT_BACK_COLOR, bold, italic, underline, ASS_DEFAULT_BORDERSTYLE, alignment); } diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index 70162b4888..8f2459d45b 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -22,7 +22,6 @@ #include "avcodec.h" #include "ass.h" #include "libavutil/opt.h" -#include "libavutil/avstring.h" #include "libavutil/common.h" #include "libavutil/bprint.h" #include "libavutil/intreadwrite.h" @@ -553,7 +552,7 @@ static int mov_text_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, } else text_to_ass(&buf, ptr, end, avctx); - ret = ff_ass_add_rect(sub, buf.str, m->readorder++, 0, NULL, NULL); + ret = avpriv_ass_add_rect(sub, buf.str, m->readorder++, 0, NULL, NULL); av_bprint_finalize(&buf, NULL); if (ret < 0) return ret; diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c index 728338f2cc..6f0b7a8a5c 100644 --- a/libavcodec/movtextenc.c +++ b/libavcodec/movtextenc.c @@ -26,8 +26,8 @@ #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" #include "libavutil/common.h" -#include "ass_split.h" -#include "ass.h" +#include "libavutil/ass_split_internal.h" +#include "libavutil/ass_internal.h" #include "bytestream.h" #include "codec_internal.h" @@ -167,7 +167,7 @@ static int mov_text_encode_close(AVCodecContext *avctx) { MovTextContext *s = avctx->priv_data; - ff_ass_split_free(s->ass_ctx); + avpriv_ass_split_free(s->ass_ctx); av_freep(&s->style_attributes); av_freep(&s->fonts); av_bprint_finalize(&s->buffer, NULL); @@ -222,7 +222,7 @@ static int encode_sample_description(AVCodecContext *avctx) else s->font_scale_factor = 1; - style = ff_ass_style_get(s->ass_ctx, "Default"); + style = avpriv_ass_style_get(s->ass_ctx, "Default"); if (!style && ass->styles_count) { style = &ass->styles[0]; } @@ -329,7 +329,7 @@ static av_cold int mov_text_encode_init(AVCodecContext *avctx) av_bprint_init(&s->buffer, 0, AV_BPRINT_SIZE_UNLIMITED); - s->ass_ctx = ff_ass_split(avctx->subtitle_header); + s->ass_ctx = avpriv_ass_split(avctx->subtitle_header); if (!s->ass_ctx) return AVERROR_INVALIDDATA; ret = encode_sample_description(avctx); @@ -566,7 +566,7 @@ static void mov_text_ass_style_set(MovTextContext *s, ASSStyle *style) static void mov_text_dialog(MovTextContext *s, ASSDialog *dialog) { - ASSStyle *style = ff_ass_style_get(s->ass_ctx, dialog->style); + ASSStyle *style = avpriv_ass_style_get(s->ass_ctx, dialog->style); s->ass_dialog_style = style; mov_text_ass_style_set(s, style); @@ -580,7 +580,7 @@ static void mov_text_cancel_overrides_cb(void *priv, const char *style_name) if (!style_name || !*style_name) style = s->ass_dialog_style; else - style= ff_ass_style_get(s->ass_ctx, style_name); + style= avpriv_ass_style_get(s->ass_ctx, style_name); mov_text_ass_style_set(s, style); } @@ -652,12 +652,12 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, return AVERROR(EINVAL); } - dialog = ff_ass_split_dialog(s->ass_ctx, ass); + dialog = avpriv_ass_split_dialog(s->ass_ctx, ass); if (!dialog) return AVERROR(ENOMEM); mov_text_dialog(s, dialog); - ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text); - ff_ass_free_dialog(&dialog); + avpriv_ass_split_override_codes(&mov_text_callbacks, s, dialog->text); + avpriv_ass_free_dialog(&dialog); } if (s->buffer.len > UINT16_MAX) diff --git a/libavcodec/mpl2dec.c b/libavcodec/mpl2dec.c index 56f008b65c..175bd319e1 100644 --- a/libavcodec/mpl2dec.c +++ b/libavcodec/mpl2dec.c @@ -73,7 +73,7 @@ static int mpl2_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); if (ptr && avpkt->size > 0 && *ptr && !mpl2_event_to_ass(&buf, ptr)) - ret = ff_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL); + ret = avpriv_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL); av_bprint_finalize(&buf, NULL); if (ret < 0) return ret; diff --git a/libavcodec/realtextdec.c b/libavcodec/realtextdec.c index c3e138a7ba..49d42a1d4d 100644 --- a/libavcodec/realtextdec.c +++ b/libavcodec/realtextdec.c @@ -66,7 +66,7 @@ static int realtext_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, av_bprint_init(&buf, 0, 4096); if (ptr && avpkt->size > 0 && !rt_event_to_ass(&buf, ptr)) - ret = ff_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL); + ret = avpriv_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL); av_bprint_finalize(&buf, NULL); if (ret < 0) return ret; diff --git a/libavcodec/samidec.c b/libavcodec/samidec.c index cf5dec955b..f35d312c2b 100644 --- a/libavcodec/samidec.c +++ b/libavcodec/samidec.c @@ -143,7 +143,7 @@ static int sami_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, if (ret < 0) return ret; // TODO: pass escaped sami->encoded_source.str as source - ret = ff_ass_add_rect(sub, sami->full.str, sami->readorder++, 0, NULL, NULL); + ret = avpriv_ass_add_rect(sub, sami->full.str, sami->readorder++, 0, NULL, NULL); if (ret < 0) return ret; } diff --git a/libavcodec/srtdec.c b/libavcodec/srtdec.c index b2df34474e..ccf5981263 100644 --- a/libavcodec/srtdec.c +++ b/libavcodec/srtdec.c @@ -79,7 +79,7 @@ static int srt_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, ret = srt_to_ass(avctx, &buffer, avpkt->data, x1, y1, x2, y2); if (ret >= 0) - ret = ff_ass_add_rect(sub, buffer.str, s->readorder++, 0, NULL, NULL); + ret = avpriv_ass_add_rect(sub, buffer.str, s->readorder++, 0, NULL, NULL); av_bprint_finalize(&buffer, NULL); if (ret < 0) return ret; diff --git a/libavcodec/srtenc.c b/libavcodec/srtenc.c index 51456c8b9d..2baa6e70ad 100644 --- a/libavcodec/srtenc.c +++ b/libavcodec/srtenc.c @@ -25,9 +25,9 @@ #include "avcodec.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" -#include "ass_split.h" -#include "ass.h" #include "codec_internal.h" +#include "libavutil/ass_split_internal.h" +#include "libavutil/ass_internal.h" #define SRT_STACK_SIZE 64 @@ -96,7 +96,7 @@ static void srt_stack_push_pop(SRTContext *s, const char c, int close) static void srt_style_apply(SRTContext *s, const char *style) { - ASSStyle *st = ff_ass_style_get(s->ass_ctx, style); + ASSStyle *st = avpriv_ass_style_get(s->ass_ctx, style); if (st) { int c = st->primary_color & 0xFFFFFF; if (st->font_name && strcmp(st->font_name, ASS_DEFAULT_FONT) || @@ -137,7 +137,7 @@ static av_cold int srt_encode_init(AVCodecContext *avctx) { SRTContext *s = avctx->priv_data; s->avctx = avctx; - s->ass_ctx = ff_ass_split(avctx->subtitle_header); + s->ass_ctx = avpriv_ass_split(avctx->subtitle_header); av_bprint_init(&s->buffer, 0, AV_BPRINT_SIZE_UNLIMITED); return s->ass_ctx ? 0 : AVERROR_INVALIDDATA; } @@ -247,14 +247,14 @@ static int encode_frame(AVCodecContext *avctx, return AVERROR(EINVAL); } - dialog = ff_ass_split_dialog(s->ass_ctx, ass); + dialog = avpriv_ass_split_dialog(s->ass_ctx, ass); if (!dialog) return AVERROR(ENOMEM); s->alignment_applied = 0; if (avctx->codec_id == AV_CODEC_ID_SUBRIP) srt_style_apply(s, dialog->style); - ff_ass_split_override_codes(cb, s, dialog->text); - ff_ass_free_dialog(&dialog); + avpriv_ass_split_override_codes(cb, s, dialog->text); + avpriv_ass_free_dialog(&dialog); } if (!av_bprint_is_complete(&s->buffer)) @@ -286,7 +286,7 @@ static int text_encode_frame(AVCodecContext *avctx, static int srt_encode_close(AVCodecContext *avctx) { SRTContext *s = avctx->priv_data; - ff_ass_split_free(s->ass_ctx); + avpriv_ass_split_free(s->ass_ctx); av_bprint_finalize(&s->buffer, NULL); return 0; } diff --git a/libavcodec/subviewerdec.c b/libavcodec/subviewerdec.c index 2bda5fa5c1..8651453e3f 100644 --- a/libavcodec/subviewerdec.c +++ b/libavcodec/subviewerdec.c @@ -57,7 +57,7 @@ static int subviewer_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); if (ptr && avpkt->size > 0 && !subviewer_event_to_ass(&buf, ptr)) - ret = ff_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL); + ret = avpriv_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL); av_bprint_finalize(&buf, NULL); if (ret < 0) return ret; diff --git a/libavcodec/textdec.c b/libavcodec/textdec.c index d509452391..06a25e7128 100644 --- a/libavcodec/textdec.c +++ b/libavcodec/textdec.c @@ -55,8 +55,8 @@ static int text_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); if (ptr && avpkt->size > 0 && *ptr) { - ff_ass_bprint_text_event(&buf, ptr, avpkt->size, text->linebreaks, text->keep_ass_markup); - ret = ff_ass_add_rect(sub, buf.str, text->readorder++, 0, NULL, NULL); + avpriv_ass_bprint_text_event(&buf, ptr, avpkt->size, text->linebreaks, text->keep_ass_markup); + ret = avpriv_ass_add_rect(sub, buf.str, text->readorder++, 0, NULL, NULL); } av_bprint_finalize(&buf, NULL); if (ret < 0) diff --git a/libavcodec/ttmlenc.c b/libavcodec/ttmlenc.c index be1d8fb2e8..d4f11a87d2 100644 --- a/libavcodec/ttmlenc.c +++ b/libavcodec/ttmlenc.c @@ -32,8 +32,7 @@ #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/internal.h" -#include "ass_split.h" -#include "ass.h" +#include "libavutil/ass_split_internal.h" #include "ttmlenc.h" typedef struct { @@ -95,7 +94,7 @@ static int ttml_encode_frame(AVCodecContext *avctx, uint8_t *buf, return AVERROR(EINVAL); } - dialog = ff_ass_split_dialog(s->ass_ctx, ass); + dialog = avpriv_ass_split_dialog(s->ass_ctx, ass); if (!dialog) return AVERROR(ENOMEM); @@ -107,7 +106,7 @@ static int ttml_encode_frame(AVCodecContext *avctx, uint8_t *buf, av_bprintf(&s->buffer, "\">"); } - ret = ff_ass_split_override_codes(&ttml_callbacks, s, dialog->text); + ret = avpriv_ass_split_override_codes(&ttml_callbacks, s, dialog->text); if (ret < 0) { int log_level = (ret != AVERROR_INVALIDDATA || avctx->err_recognition & AV_EF_EXPLODE) ? @@ -118,7 +117,7 @@ static int ttml_encode_frame(AVCodecContext *avctx, uint8_t *buf, av_err2str(ret)); if (log_level == AV_LOG_ERROR) { - ff_ass_free_dialog(&dialog); + avpriv_ass_free_dialog(&dialog); return ret; } } @@ -126,7 +125,7 @@ static int ttml_encode_frame(AVCodecContext *avctx, uint8_t *buf, if (dialog->style) av_bprintf(&s->buffer, ""); - ff_ass_free_dialog(&dialog); + avpriv_ass_free_dialog(&dialog); } if (!av_bprint_is_complete(&s->buffer)) @@ -148,7 +147,7 @@ static av_cold int ttml_encode_close(AVCodecContext *avctx) { TTMLContext *s = avctx->priv_data; - ff_ass_split_free(s->ass_ctx); + avpriv_ass_split_free(s->ass_ctx); av_bprint_finalize(&s->buffer, NULL); @@ -372,7 +371,7 @@ static av_cold int ttml_encode_init(AVCodecContext *avctx) av_bprint_init(&s->buffer, 0, AV_BPRINT_SIZE_UNLIMITED); - if (!(s->ass_ctx = ff_ass_split(avctx->subtitle_header))) { + if (!(s->ass_ctx = avpriv_ass_split(avctx->subtitle_header))) { return AVERROR_INVALIDDATA; } diff --git a/libavcodec/webvttdec.c b/libavcodec/webvttdec.c index fcf1062d86..549e60fe62 100644 --- a/libavcodec/webvttdec.c +++ b/libavcodec/webvttdec.c @@ -90,7 +90,7 @@ static int webvtt_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); if (ptr && avpkt->size > 0 && !webvtt_event_to_ass(&buf, ptr)) - ret = ff_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL); + ret = avpriv_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL); av_bprint_finalize(&buf, NULL); if (ret < 0) return ret; diff --git a/libavcodec/webvttenc.c b/libavcodec/webvttenc.c index e433bb4579..24d60c5dc1 100644 --- a/libavcodec/webvttenc.c +++ b/libavcodec/webvttenc.c @@ -24,9 +24,9 @@ #include "avcodec.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" -#include "ass_split.h" -#include "ass.h" #include "codec_internal.h" +#include "libavutil/ass_split_internal.h" +#include "libavutil/ass_internal.h" #define WEBVTT_STACK_SIZE 64 typedef struct { @@ -93,7 +93,7 @@ static void webvtt_stack_push_pop(WebVTTContext *s, const char c, int close) static void webvtt_style_apply(WebVTTContext *s, const char *style) { - ASSStyle *st = ff_ass_style_get(s->ass_ctx, style); + ASSStyle *st = avpriv_ass_style_get(s->ass_ctx, style); if (st) { if (st->bold != ASS_DEFAULT_BOLD) { webvtt_print(s, ""); @@ -172,12 +172,12 @@ static int webvtt_encode_frame(AVCodecContext *avctx, return AVERROR(EINVAL); } - dialog = ff_ass_split_dialog(s->ass_ctx, ass); + dialog = avpriv_ass_split_dialog(s->ass_ctx, ass); if (!dialog) return AVERROR(ENOMEM); webvtt_style_apply(s, dialog->style); - ff_ass_split_override_codes(&webvtt_callbacks, s, dialog->text); - ff_ass_free_dialog(&dialog); + avpriv_ass_split_override_codes(&webvtt_callbacks, s, dialog->text); + avpriv_ass_free_dialog(&dialog); } if (!av_bprint_is_complete(&s->buffer)) @@ -197,7 +197,7 @@ static int webvtt_encode_frame(AVCodecContext *avctx, static int webvtt_encode_close(AVCodecContext *avctx) { WebVTTContext *s = avctx->priv_data; - ff_ass_split_free(s->ass_ctx); + avpriv_ass_split_free(s->ass_ctx); av_bprint_finalize(&s->buffer, NULL); return 0; } @@ -206,7 +206,7 @@ static av_cold int webvtt_encode_init(AVCodecContext *avctx) { WebVTTContext *s = avctx->priv_data; s->avctx = avctx; - s->ass_ctx = ff_ass_split(avctx->subtitle_header); + s->ass_ctx = avpriv_ass_split(avctx->subtitle_header); av_bprint_init(&s->buffer, 0, AV_BPRINT_SIZE_UNLIMITED); return s->ass_ctx ? 0 : AVERROR_INVALIDDATA; } diff --git a/libavutil/Makefile b/libavutil/Makefile index 48f78c81e5..9da830c0b5 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -103,6 +103,8 @@ BUILT_HEADERS = avconfig.h \ OBJS = adler32.o \ aes.o \ aes_ctr.o \ + ass.o \ + ass_split.o \ audio_fifo.o \ avstring.o \ avsscanf.o \ diff --git a/libavcodec/ass.c b/libavutil/ass.c similarity index 59% rename from libavcodec/ass.c rename to libavutil/ass.c index a1e560d7ff..6739132acf 100644 --- a/libavcodec/ass.c +++ b/libavutil/ass.c @@ -19,21 +19,22 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avcodec.h" -#include "ass.h" +#include "ass_internal.h" + +#include "subfmt.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/common.h" -int ff_ass_subtitle_header_full(AVCodecContext *avctx, - int play_res_x, int play_res_y, - const char *font, int font_size, - int primary_color, int secondary_color, - int outline_color, int back_color, - int bold, int italic, int underline, - int border_style, int alignment) +char* avpriv_ass_get_subtitle_header_full(int play_res_x, int play_res_y, + const char *font, int font_size, + int primary_color, int secondary_color, + int outline_color, int back_color, + int bold, int italic, int underline, + int border_style, int alignment, + int print_av_version) { - avctx->subtitle_header = av_asprintf( + char* header = av_asprintf( "[Script Info]\r\n" "; Script generated by FFmpeg/Lavc%s\r\n" "ScriptType: v4.00+\r\n" @@ -68,34 +69,31 @@ int ff_ass_subtitle_header_full(AVCodecContext *avctx, "\r\n" "[Events]\r\n" "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\r\n", - !(avctx->flags & AV_CODEC_FLAG_BITEXACT) ? AV_STRINGIFY(LIBAVCODEC_VERSION) : "", + print_av_version ? AV_STRINGIFY(LIBAVCODEC_VERSION) : "", play_res_x, play_res_y, font, font_size, primary_color, secondary_color, outline_color, back_color, -bold, -italic, -underline, border_style, alignment); - if (!avctx->subtitle_header) - return AVERROR(ENOMEM); - avctx->subtitle_header_size = strlen(avctx->subtitle_header); - return 0; + return header; } -int ff_ass_subtitle_header(AVCodecContext *avctx, - const char *font, int font_size, +char* avpriv_ass_get_subtitle_header(const char *font, int font_size, int color, int back_color, int bold, int italic, int underline, - int border_style, int alignment) + int border_style, int alignment, + int print_av_version) { - return ff_ass_subtitle_header_full(avctx, - ASS_DEFAULT_PLAYRESX, ASS_DEFAULT_PLAYRESY, - font, font_size, color, color, - back_color, back_color, - bold, italic, underline, - border_style, alignment); + return avpriv_ass_get_subtitle_header_full(ASS_DEFAULT_PLAYRESX, ASS_DEFAULT_PLAYRESY, + font, font_size, color, color, + back_color, back_color, + bold, italic, underline, + border_style, alignment, + print_av_version); } -int ff_ass_subtitle_header_default(AVCodecContext *avctx) +char* avpriv_ass_get_subtitle_header_default(int print_av_version) { - return ff_ass_subtitle_header(avctx, ASS_DEFAULT_FONT, + return avpriv_ass_get_subtitle_header(ASS_DEFAULT_FONT, ASS_DEFAULT_FONT_SIZE, ASS_DEFAULT_COLOR, ASS_DEFAULT_BACK_COLOR, @@ -103,10 +101,11 @@ int ff_ass_subtitle_header_default(AVCodecContext *avctx) ASS_DEFAULT_ITALIC, ASS_DEFAULT_UNDERLINE, ASS_DEFAULT_BORDERSTYLE, - ASS_DEFAULT_ALIGNMENT); + ASS_DEFAULT_ALIGNMENT, + print_av_version); } -char *ff_ass_get_dialog(int readorder, int layer, const char *style, +char *avpriv_ass_get_dialog(int readorder, int layer, const char *style, const char *speaker, const char *text) { return av_asprintf("%d,%d,%s,%s,0,0,0,,%s", @@ -114,61 +113,17 @@ char *ff_ass_get_dialog(int readorder, int layer, const char *style, speaker ? speaker : "", text); } -int ff_ass_add_rect2(AVSubtitle *sub, const char *dialog, - int readorder, int layer, const char *style, - const char *speaker, unsigned *nb_rect_allocated) -{ - AVSubtitleRect **rects = sub->rects, *rect; - char *ass_str; - uint64_t new_nb = 0; - - if (sub->num_rects >= UINT_MAX) - return AVERROR(ENOMEM); - - if (nb_rect_allocated && *nb_rect_allocated <= sub->num_rects) { - if (sub->num_rects < UINT_MAX / 17 * 16) { - new_nb = sub->num_rects + sub->num_rects/16 + 1; - } else - new_nb = UINT_MAX; - } else if (!nb_rect_allocated) - new_nb = sub->num_rects + 1; - - if (new_nb) { - rects = av_realloc_array(rects, new_nb, sizeof(*sub->rects)); - if (!rects) - return AVERROR(ENOMEM); - if (nb_rect_allocated) - *nb_rect_allocated = new_nb; - sub->rects = rects; - } - - rect = av_mallocz(sizeof(*rect)); - if (!rect) - return AVERROR(ENOMEM); - rects[sub->num_rects++] = rect; - rect->type = SUBTITLE_ASS; - ass_str = ff_ass_get_dialog(readorder, layer, style, speaker, dialog); - if (!ass_str) - return AVERROR(ENOMEM); - rect->ass = ass_str; - return 0; -} - -int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, - int readorder, int layer, const char *style, - const char *speaker) +char *avpriv_ass_get_dialog_ex(int readorder, int layer, const char *style, + const char *speaker, int margin_l, int margin_r, + int margin_v, const char *effect, const char *text) { - return ff_ass_add_rect2(sub, dialog, readorder, layer, style, speaker, NULL); -} - -void ff_ass_decoder_flush(AVCodecContext *avctx) -{ - FFASSDecoderContext *s = avctx->priv_data; - if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP)) - s->readorder = 0; + return av_asprintf("%d,%d,%s,%s,%d,%d,%d,%s,%s", + readorder, layer, style ? style : "Default", + speaker ? speaker : "", margin_l, margin_r, + margin_v, effect ? effect : "", text); } -void ff_ass_bprint_text_event(AVBPrint *buf, const char *p, int size, +void avpriv_ass_bprint_text_event(AVBPrint *buf, const char *p, int size, const char *linebreaks, int keep_ass_markup) { const char *p_end = p + size; diff --git a/libavutil/ass_internal.h b/libavutil/ass_internal.h new file mode 100644 index 0000000000..fc4e6232fb --- /dev/null +++ b/libavutil/ass_internal.h @@ -0,0 +1,135 @@ +/* + * SSA/ASS common functions + * Copyright (c) 2010 Aurelien Jacobs + * + * 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 + */ + +#ifndef AVUTIL_ASS_INTERNAL_H +#define AVUTIL_ASS_INTERNAL_H + +#include "subfmt.h" +#include "libavutil/bprint.h" + +#define ASS_DEFAULT_PLAYRESX 384 +#define ASS_DEFAULT_PLAYRESY 288 + +/** + * @name Default values for ASS style + * @{ + */ +#define ASS_DEFAULT_FONT "Arial" +#define ASS_DEFAULT_FONT_SIZE 16 +#define ASS_DEFAULT_COLOR 0xffffff +#define ASS_DEFAULT_BACK_COLOR 0 +#define ASS_DEFAULT_BOLD 0 +#define ASS_DEFAULT_ITALIC 0 +#define ASS_DEFAULT_UNDERLINE 0 +#define ASS_DEFAULT_ALIGNMENT 2 +#define ASS_DEFAULT_BORDERSTYLE 1 +/** @} */ + +/** + * Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS. + * Can specify all fields explicitly + * + * @param play_res_x subtitle frame width + * @param play_res_y subtitle frame height + * @param font name of the default font face to use + * @param font_size default font size to use + * @param primary_color default text color to use (ABGR) + * @param secondary_color default secondary text color to use (ABGR) + * @param outline_color default outline color to use (ABGR) + * @param back_color default background color to use (ABGR) + * @param bold 1 for bold text, 0 for normal text + * @param italic 1 for italic text, 0 for normal text + * @param underline 1 for underline text, 0 for normal text + * @param border_style 1 for outline, 3 for opaque box + * @param alignment position of the text (left, center, top...), defined after + * the layout of the numpad (1-3 sub, 4-6 mid, 7-9 top) + * @param print_av_version include library version in header + * @return a string containing the subtitle header that needs + * to be released via av_free() + */ +char* avpriv_ass_get_subtitle_header_full(int play_res_x, int play_res_y, + const char *font, int font_size, + int primary_color, int secondary_color, + int outline_color, int back_color, + int bold, int italic, int underline, + int border_style, int alignment, + int print_av_version); + +/** + * Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS. + * + * @param font name of the default font face to use + * @param font_size default font size to use + * @param color default text color to use (ABGR) + * @param back_color default background color to use (ABGR) + * @param bold 1 for bold text, 0 for normal text + * @param italic 1 for italic text, 0 for normal text + * @param underline 1 for underline text, 0 for normal text + * @param border_style 1 for outline, 3 for opaque box + * @param alignment position of the text (left, center, top...), defined after + * the layout of the numpad (1-3 sub, 4-6 mid, 7-9 top) + * @param print_av_version include library version in header + * @return a string containing the subtitle header that needs + * to be released via av_free() + */ +char* avpriv_ass_get_subtitle_header(const char *font, int font_size, + int color, int back_color, + int bold, int italic, int underline, + int border_style, int alignment, + int print_av_version); + +/** + * Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS + * with default style. + * + * @param print_av_version include library version in header + * @return a string containing the subtitle header that needs + * to be released via av_free() + */ +char* avpriv_ass_get_subtitle_header_default(int print_av_version); + +/** + * Craft an ASS dialog string. + */ +char *avpriv_ass_get_dialog(int readorder, int layer, const char *style, + const char *speaker, const char *text); + +/** + * Craft an ASS dialog string. + */ +char *avpriv_ass_get_dialog_ex(int readorder, int layer, const char *style, + const char *speaker, int margin_l, int margin_r, + int margin_v, const char *effect, const char *text); + +/** + * Escape a text subtitle using ASS syntax into an AVBPrint buffer. + * Newline characters will be escaped to \N. + * + * @param buf pointer to an initialized AVBPrint buffer + * @param p source text + * @param size size of the source text + * @param linebreaks additional newline chars, which will be escaped to \N + * @param keep_ass_markup braces and backslash will not be escaped if set + */ +void avpriv_ass_bprint_text_event(AVBPrint *buf, const char *p, int size, + const char *linebreaks, int keep_ass_markup); + +#endif /* AVUTIL_ASS_INTERNAL_H */ diff --git a/libavcodec/ass_split.c b/libavutil/ass_split.c similarity index 71% rename from libavcodec/ass_split.c rename to libavutil/ass_split.c index 73ef6196c5..3e5e24e2fa 100644 --- a/libavcodec/ass_split.c +++ b/libavutil/ass_split.c @@ -28,7 +28,7 @@ #include "libavutil/error.h" #include "libavutil/macros.h" #include "libavutil/mem.h" -#include "ass_split.h" +#include "ass_split_internal.h" typedef enum { ASS_STR, @@ -379,7 +379,7 @@ static int ass_split(ASSSplitContext *ctx, const char *buf) return buf ? 0 : AVERROR_INVALIDDATA; } -ASSSplitContext *ff_ass_split(const char *buf) +ASSSplitContext *avpriv_ass_split(const char *buf) { ASSSplitContext *ctx = av_mallocz(sizeof(*ctx)); if (!ctx) @@ -388,7 +388,7 @@ ASSSplitContext *ff_ass_split(const char *buf) buf += 3; ctx->current_section = -1; if (ass_split(ctx, buf) < 0) { - ff_ass_split_free(ctx); + avpriv_ass_split_free(ctx); return NULL; } return ctx; @@ -418,7 +418,7 @@ static void free_section(ASSSplitContext *ctx, const ASSSection *section) av_freep((uint8_t *)&ctx->ass + section->offset); } -void ff_ass_free_dialog(ASSDialog **dialogp) +void avpriv_ass_free_dialog(ASSDialog **dialogp) { ASSDialog *dialog = *dialogp; if (!dialog) @@ -430,7 +430,7 @@ void ff_ass_free_dialog(ASSDialog **dialogp) av_freep(dialogp); } -ASSDialog *ff_ass_split_dialog(ASSSplitContext *ctx, const char *buf) +ASSDialog *avpriv_ass_split_dialog(ASSSplitContext *ctx, const char *buf) { int i; static const ASSFields fields[] = { @@ -457,7 +457,7 @@ ASSDialog *ff_ass_split_dialog(ASSSplitContext *ctx, const char *buf) buf = skip_space(buf); len = last ? strlen(buf) : strcspn(buf, ","); if (len >= INT_MAX) { - ff_ass_free_dialog(&dialog); + avpriv_ass_free_dialog(&dialog); return NULL; } convert_func[type](ptr, buf, len); @@ -467,7 +467,7 @@ ASSDialog *ff_ass_split_dialog(ASSSplitContext *ctx, const char *buf) return dialog; } -void ff_ass_split_free(ASSSplitContext *ctx) +void avpriv_ass_split_free(ASSSplitContext *ctx) { if (ctx) { int i; @@ -479,87 +479,209 @@ void ff_ass_split_free(ASSSplitContext *ctx) } } +static int ass_remove_empty_braces(AVBPrint* buffer) +{ + char* tmp; + int ret = 0, n = 0; -int ff_ass_split_override_codes(const ASSCodesCallbacks *callbacks, void *priv, - const char *buf) + if (buffer == NULL || buffer->len == 0 || !av_bprint_is_complete(buffer)) + return 0; + + ret = av_bprint_finalize(buffer, &tmp); + if (ret) + return ret; + + for (unsigned i = 0; i < buffer->len; i++) { + if (tmp[i] == '{' && tmp[i+1] == '}') + i++; + else + tmp[n++] = tmp[i]; + } + + tmp[n++] = '\0'; + + av_bprint_init(buffer, n, n); + av_bprint_append_data(buffer, tmp, n - 1); + av_free(tmp); + + return ret; +} + +static void ass_write_filtered_line(AVBPrint* buffer, const char *buf, int len, enum ASSSplitComponents keep_flags, enum ASSSplitComponents split_component) +{ + if (buffer == NULL || buf == NULL || len == 0) + return; + + if (split_component != ASS_SPLIT_ANY && !(keep_flags & split_component)) + return; + + + av_bprint_append_data(buffer, buf, len - 1); +} + +int avpriv_ass_filter_override_codes(const ASSCodesCallbacks *callbacks, void *priv, const char *buf, AVBPrint* outbuffer, enum ASSSplitComponents keep_flags) { const char *text = NULL; char new_line[2]; - int text_len = 0; + int text_len = 0, ret = 0; while (buf && *buf) { - if (text && callbacks->text && - (sscanf(buf, "\\%1[nN]", new_line) == 1 || - !strncmp(buf, "{\\", 2))) { - callbacks->text(priv, text, text_len); + + if (text && (sscanf(buf, "\\%1[nN]", new_line) == 1 || !strncmp(buf, "{\\", 2))) { + ass_write_filtered_line(outbuffer, text, text_len + 1, keep_flags, ASS_SPLIT_TEXT | ASS_SPLIT_TEXT2); + + if (callbacks->text) + callbacks->text(priv, text, text_len); text = NULL; } + if (sscanf(buf, "\\%1[nN]", new_line) == 1) { if (callbacks->new_line) callbacks->new_line(priv, new_line[0] == 'N'); + ass_write_filtered_line(outbuffer, buf, 3, keep_flags, ASS_SPLIT_ANY); buf += 2; } else if (!strncmp(buf, "{\\", 2)) { + ass_write_filtered_line(outbuffer, buf, 2, keep_flags, ASS_SPLIT_ANY); buf++; while (*buf == '\\') { - char style[2], c[2], sep[2], c_num[2] = "0", tmp[128] = {0}; + char style[4], c[2], axis[3], sep[3], c_num[2] = "0", tmp[128] = {0}; unsigned int color = 0xFFFFFFFF; - int len, size = -1, an = -1, alpha = -1; - int x1, y1, x2, y2, t1 = -1, t2 = -1; + int len, size = -1, an = -1, alpha = -1, scale = 0; + float f1 = 1; + int x1, y1, x2, y2, x3, t1 = -1, t2 = -1, t3 = -1, t4 = -1, accel = 1; if (sscanf(buf, "\\%1[bisu]%1[01\\}]%n", style, c, &len) > 1) { int close = c[0] == '0' ? 1 : c[0] == '1' ? 0 : -1; len += close != -1; + switch (c[0]) { + case 'b': + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_FONT_BOLD); + break; + case 'u': + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_FONT_UNDERLINE); + break; + case 'i': + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_FONT_ITALIC); + break; + case 'a': + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_FONT_STRIKEOUT); + break; + } if (callbacks->style) callbacks->style(priv, style[0], close); } else if (sscanf(buf, "\\c%1[\\}]%n", sep, &len) > 0 || sscanf(buf, "\\c&H%X&%1[\\}]%n", &color, sep, &len) > 1 || sscanf(buf, "\\%1[1234]c%1[\\}]%n", c_num, sep, &len) > 1 || sscanf(buf, "\\%1[1234]c&H%X&%1[\\}]%n", c_num, &color, sep, &len) > 2) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_COLOR); if (callbacks->color) callbacks->color(priv, color, c_num[0] - '0'); } else if (sscanf(buf, "\\alpha%1[\\}]%n", sep, &len) > 0 || sscanf(buf, "\\alpha&H%2X&%1[\\}]%n", &alpha, sep, &len) > 1 || sscanf(buf, "\\%1[1234]a%1[\\}]%n", c_num, sep, &len) > 1 || sscanf(buf, "\\%1[1234]a&H%2X&%1[\\}]%n", c_num, &alpha, sep, &len) > 2) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_ALPHA); if (callbacks->alpha) callbacks->alpha(priv, alpha, c_num[0] - '0'); } else if (sscanf(buf, "\\fn%1[\\}]%n", sep, &len) > 0 || sscanf(buf, "\\fn%127[^\\}]%1[\\}]%n", tmp, sep, &len) > 1) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_FONT_NAME); if (callbacks->font_name) callbacks->font_name(priv, tmp[0] ? tmp : NULL); } else if (sscanf(buf, "\\fs%1[\\}]%n", sep, &len) > 0 || sscanf(buf, "\\fs%u%1[\\}]%n", &size, sep, &len) > 1) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_FONT_SIZE); if (callbacks->font_size) callbacks->font_size(priv, size); + } else if (sscanf(buf, "\\fscx%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\fscx%f%1[\\}]%n", &f1, sep, &len) > 1) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_FONT_SCALE); + } else if (sscanf(buf, "\\fscy%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\fscy%f%1[\\}]%n", &f1, sep, &len) > 1) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_FONT_SCALE); + } else if (sscanf(buf, "\\fsp%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\fsp%u%1[\\}]%n", &size, sep, &len) > 1) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_FONT_SPACING); + } else if (sscanf(buf, "\\fe%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\fe%u%1[\\}]%n", &size, sep, &len) > 1) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_FONT_CHARSET); + } else if (sscanf(buf, "\\bord%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\bord%u%1[\\}]%n", &size, sep, &len) > 1) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_TEXT_BORDER); + } else if (sscanf(buf, "\\shad%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\shad%u%1[\\}]%n", &size, sep, &len) > 1) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_TEXT_SHADOW); + } else if (sscanf(buf, "\\fr%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\fr%u%1[\\}]%n", &x1, sep, &len) > 1 || + sscanf(buf, "\\fr%1[xyz]%1[\\}]%n", axis, sep, &len) > 1 || + sscanf(buf, "\\fr%1[xyz]%u%1[\\}]%n", axis, &size, sep, &len) > 2) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_TEXT_ROTATE); + } else if (sscanf(buf, "\\blur%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\blur%u%1[\\}]%n", &size, sep, &len) > 1) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_TEXT_BLUR); + } else if (sscanf(buf, "\\be%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\be%u%1[\\}]%n", &size, sep, &len) > 1) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_TEXT_BLUR); + } else if (sscanf(buf, "\\q%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\q%u%1[\\}]%n", &size, sep, &len) > 1) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_TEXT_WRAP); } else if (sscanf(buf, "\\a%1[\\}]%n", sep, &len) > 0 || sscanf(buf, "\\a%2u%1[\\}]%n", &an, sep, &len) > 1 || sscanf(buf, "\\an%1[\\}]%n", sep, &len) > 0 || sscanf(buf, "\\an%1u%1[\\}]%n", &an, sep, &len) > 1) { if (an != -1 && buf[2] != 'n') an = (an&3) + (an&4 ? 6 : an&8 ? 3 : 0); + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_TEXT_ALIGNMENT); if (callbacks->alignment) callbacks->alignment(priv, an); } else if (sscanf(buf, "\\r%1[\\}]%n", sep, &len) > 0 || sscanf(buf, "\\r%127[^\\}]%1[\\}]%n", tmp, sep, &len) > 1) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_CANCELLING); if (callbacks->cancel_overrides) callbacks->cancel_overrides(priv, tmp); } else if (sscanf(buf, "\\move(%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, sep, &len) > 4 || sscanf(buf, "\\move(%d,%d,%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, &t1, &t2, sep, &len) > 6) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_MOVE); if (callbacks->move) callbacks->move(priv, x1, y1, x2, y2, t1, t2); } else if (sscanf(buf, "\\pos(%d,%d)%1[\\}]%n", &x1, &y1, sep, &len) > 2) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_POS); if (callbacks->move) callbacks->move(priv, x1, y1, x1, y1, -1, -1); } else if (sscanf(buf, "\\org(%d,%d)%1[\\}]%n", &x1, &y1, sep, &len) > 2) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_ORIGIN); if (callbacks->origin) callbacks->origin(priv, x1, y1); + } else if (sscanf(buf, "\\t(%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\t(%d,%d,%1[\\}]%n", &t1, &t2, sep, &len) > 2 || + sscanf(buf, "\\t(%d,%d,%d,%1[\\}]%n", &t1, &t2, &accel, sep, &len) > 3) { + + len = strcspn(buf, ")") + 2; + + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_ANIMATE); + if (callbacks->animate) + callbacks->animate(priv, t1, t2, accel, tmp); + } else if (sscanf(buf, "\\fade(%d,%d,%d,%d,%d,%d,%d)%1[\\}]%n", &x1, &x2, &x3, &t1, &t2, &t3, &t4, sep, &len) > 7) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_FADE); + } else if (sscanf(buf, "\\fad(%d,%d)%1[\\}]%n", &t1, &t2, sep, &len) > 2) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_FADE); + } else if (sscanf(buf, "\\clip(%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, sep, &len) > 4) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_CLIP); + } else if (sscanf(buf, "\\p%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\p%u%1[\\}]%n", &scale, sep, &len) > 1) { + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_DRAW); + if (callbacks->drawing_mode) + callbacks->drawing_mode(priv, scale); } else { - len = strcspn(buf+1, "\\}") + 2; /* skip unknown code */ - } + len = strcspn(buf+1, "\\}") + 2; /* unknown code */ + ass_write_filtered_line(outbuffer, buf, len, keep_flags, ASS_SPLIT_UNKNOWN); + } buf += len - 1; } if (*buf++ != '}') return AVERROR_INVALIDDATA; - } else { + + ass_write_filtered_line(outbuffer, "}", 2, keep_flags, ASS_SPLIT_ANY); + } else { if (!text) { text = buf; text_len = 1; @@ -568,14 +690,27 @@ int ff_ass_split_override_codes(const ASSCodesCallbacks *callbacks, void *priv, buf++; } } + if (text) + ass_write_filtered_line(outbuffer, text, text_len + 1, keep_flags, ASS_SPLIT_TEXT | ASS_SPLIT_TEXT2); if (text && callbacks->text) callbacks->text(priv, text, text_len); if (callbacks->end) callbacks->end(priv); - return 0; + + if (outbuffer) + ret = ass_remove_empty_braces(outbuffer); + + return ret; +} + + +int avpriv_ass_split_override_codes(const ASSCodesCallbacks *callbacks, void *priv, + const char *buf) +{ + return avpriv_ass_filter_override_codes(callbacks, priv, buf, NULL, 0); } -ASSStyle *ff_ass_style_get(ASSSplitContext *ctx, const char *style) +ASSStyle *avpriv_ass_style_get(ASSSplitContext *ctx, const char *style) { ASS *ass = &ctx->ass; int i; diff --git a/libavutil/ass_split_internal.h b/libavutil/ass_split_internal.h new file mode 100644 index 0000000000..5d82aa8886 --- /dev/null +++ b/libavutil/ass_split_internal.h @@ -0,0 +1,254 @@ +/* + * SSA/ASS spliting functions + * Copyright (c) 2010 Aurelien Jacobs + * + * 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 + */ + +#ifndef AVUTIL_ASS_SPLIT_INTERNAL_H +#define AVUTIL_ASS_SPLIT_INTERNAL_H + +#include "bprint.h" + +enum ASSSplitComponents +{ + ASS_SPLIT_ANY = 0, + ASS_SPLIT_TEXT = (1 << 0), + ASS_SPLIT_TEXT2 = (1 << 1), // Same semantics as ASS_SPLIT_TEXT. To work around help output default display. + ASS_SPLIT_COLOR = (1 << 2), + ASS_SPLIT_ALPHA = (1 << 3), + ASS_SPLIT_FONT_NAME = (1 << 4), + ASS_SPLIT_FONT_SIZE = (1 << 5), + ASS_SPLIT_FONT_SCALE = (1 << 6), + ASS_SPLIT_FONT_SPACING = (1 << 7), + ASS_SPLIT_FONT_CHARSET = (1 << 8), + ASS_SPLIT_FONT_BOLD = (1 << 9), + ASS_SPLIT_FONT_ITALIC = (1 << 10), + ASS_SPLIT_FONT_UNDERLINE = (1 << 11), + ASS_SPLIT_FONT_STRIKEOUT = (1 << 12), + ASS_SPLIT_TEXT_BORDER = (1 << 13), + ASS_SPLIT_TEXT_SHADOW = (1 << 14), + ASS_SPLIT_TEXT_ROTATE = (1 << 15), + ASS_SPLIT_TEXT_BLUR = (1 << 16), + ASS_SPLIT_TEXT_WRAP = (1 << 17), + ASS_SPLIT_TEXT_ALIGNMENT = (1 << 18), + ASS_SPLIT_CANCELLING = (1 << 19), + ASS_SPLIT_MOVE = (1 << 20), + ASS_SPLIT_POS = (1 << 21), + ASS_SPLIT_ORIGIN = (1 << 22), + ASS_SPLIT_DRAW = (1 << 23), + ASS_SPLIT_ANIMATE = (1 << 24), + ASS_SPLIT_FADE = (1 << 25), + ASS_SPLIT_CLIP = (1 << 26), + ASS_SPLIT_UNKNOWN = (1 << 27), + + ASS_SPLIT_BASIC = ASS_SPLIT_TEXT2 | ASS_SPLIT_COLOR | ASS_SPLIT_ALPHA | ASS_SPLIT_FONT_NAME | ASS_SPLIT_FONT_SIZE | ASS_SPLIT_FONT_SCALE | ASS_SPLIT_FONT_SPACING | ASS_SPLIT_FONT_CHARSET | ASS_SPLIT_FONT_BOLD | ASS_SPLIT_FONT_ITALIC | ASS_SPLIT_FONT_UNDERLINE | ASS_SPLIT_FONT_STRIKEOUT | ASS_SPLIT_TEXT_BORDER | ASS_SPLIT_TEXT_SHADOW | ASS_SPLIT_TEXT_WRAP | ASS_SPLIT_TEXT_ALIGNMENT | ASS_SPLIT_POS | ASS_SPLIT_CANCELLING, + ASS_SPLIT_ALL_KNOWN = ASS_SPLIT_TEXT2 | ASS_SPLIT_COLOR | ASS_SPLIT_ALPHA | ASS_SPLIT_FONT_NAME | ASS_SPLIT_FONT_SIZE | ASS_SPLIT_FONT_SCALE | ASS_SPLIT_FONT_SPACING | ASS_SPLIT_FONT_CHARSET | ASS_SPLIT_FONT_BOLD | ASS_SPLIT_FONT_ITALIC | ASS_SPLIT_FONT_UNDERLINE | ASS_SPLIT_FONT_STRIKEOUT | ASS_SPLIT_TEXT_BORDER | ASS_SPLIT_TEXT_SHADOW | ASS_SPLIT_TEXT_ROTATE | ASS_SPLIT_TEXT_BLUR | ASS_SPLIT_TEXT_WRAP | ASS_SPLIT_TEXT_ALIGNMENT | ASS_SPLIT_CANCELLING | ASS_SPLIT_POS | ASS_SPLIT_MOVE | ASS_SPLIT_ORIGIN | ASS_SPLIT_DRAW | ASS_SPLIT_ANIMATE | ASS_SPLIT_FADE | ASS_SPLIT_CLIP, +}; + + /** + * fields extracted from the [Script Info] section + */ + typedef struct { + char *script_type; /**< SSA script format version (eg. v4.00) */ + char *collisions; /**< how subtitles are moved to prevent collisions */ + int play_res_x; /**< video width that ASS coords are referring to */ + int play_res_y; /**< video height that ASS coords are referring to */ + float timer; /**< time multiplier to apply to SSA clock (in %) */ +} ASSScriptInfo; + +/** + * fields extracted from the [V4(+) Styles] section + */ +typedef struct { + char *name; /**< name of the tyle (case sensitive) */ + char *font_name; /**< font face (case sensitive) */ + int font_size; /**< font height */ + int primary_color; /**< color that a subtitle will normally appear in */ + int secondary_color; + int outline_color; /**< color for outline in ASS, called tertiary in SSA */ + int back_color; /**< color of the subtitle outline or shadow */ + int bold; /**< whether text is bold (1) or not (0) */ + int italic; /**< whether text is italic (1) or not (0) */ + int underline; /**< whether text is underlined (1) or not (0) */ + int strikeout; + float scalex; + float scaley; + float spacing; + float angle; + int border_style; + float outline; + float shadow; + int alignment; /**< position of the text (left, center, top...), + defined after the layout of the numpad + (1-3 sub, 4-6 mid, 7-9 top) */ + int margin_l; + int margin_r; + int margin_v; + int alpha_level; + int encoding; +} ASSStyle; + +/** + * fields extracted from the [Events] section + */ +typedef struct { + int readorder; + int layer; /**< higher numbered layers are drawn over lower numbered */ + int start; /**< start time of the dialog in centiseconds */ + int end; /**< end time of the dialog in centiseconds */ + char *style; /**< name of the ASSStyle to use with this dialog */ + char *name; + int margin_l; + int margin_r; + int margin_v; + char *effect; + char *text; /**< actual text which will be displayed as a subtitle, + can include style override control codes (see + avpriv_ass_split_override_codes()) */ +} ASSDialog; + +/** + * structure containing the whole split ASS data + */ +typedef struct { + ASSScriptInfo script_info; /**< general information about the SSA script*/ + ASSStyle *styles; /**< array of split out styles */ + int styles_count; /**< number of ASSStyle in the styles array */ + ASSDialog *dialogs; /**< array of split out dialogs */ + int dialogs_count; /**< number of ASSDialog in the dialogs array*/ +} ASS; + +/** + * This struct can be casted to ASS to access to the split data. + */ +typedef struct ASSSplitContext ASSSplitContext; + +/** + * Split a full ASS file or a ASS header from a string buffer and store + * the split structure in a newly allocated context. + * + * @param buf String containing the ASS formatted data. + * @return Newly allocated struct containing split data. + */ +ASSSplitContext *avpriv_ass_split(const char *buf); + +/** + * Free a dialogue obtained from avpriv_ass_split_dialog(). + */ +void avpriv_ass_free_dialog(ASSDialog **dialogp); + +/** + * Split one ASS Dialogue line from a string buffer. + * + * @param ctx Context previously initialized by ff_ass_split(). + * @param buf String containing the ASS "Dialogue" line. + * @return Pointer to the split ASSDialog. Must be freed with + * ff_ass_free_dialog() + */ +ASSDialog *avpriv_ass_split_dialog(ASSSplitContext *ctx, const char *buf); + +/** + * Free all the memory allocated for an ASSSplitContext. + * + * @param ctx Context previously initialized by ff_ass_split(). + */ +void avpriv_ass_split_free(ASSSplitContext *ctx); + +/** + * Set of callback functions corresponding to each override codes that can + * be encountered in a "Dialogue" Text field. + */ +typedef struct { + /** + * @defgroup ass_styles ASS styles + * @{ + */ + void (*text)(void *priv, const char *text, int len); + void (*hard_space)(void *priv); + void (*new_line)(void *priv, int forced); + void (*style)(void *priv, char style, int close); + void (*color)(void *priv, unsigned int /* color */, unsigned int color_id); + void (*alpha)(void *priv, int alpha, int alpha_id); + void (*font_name)(void *priv, const char *name); + void (*font_size)(void *priv, int size); + void (*alignment)(void *priv, int alignment); + void (*cancel_overrides)(void *priv, const char *style); + /** @} */ + + /** + * @defgroup ass_functions ASS functions + * @{ + */ + void (*move)(void *priv, int x1, int y1, int x2, int y2, int t1, int t2); + void (*animate)(void *priv, int t1, int t2, int accel, char *style); + void (*origin)(void *priv, int x, int y); + void (*drawing_mode)(void *priv, int scale); + /** @} */ + + /** + * @defgroup ass_ext ASS extensible parsing callback + * @{ + */ + void (*ext)(void *priv, int ext_id, const char *text, int p1, int p2); + /** @} */ + + /** + * @defgroup ass_end end of Dialogue Event + * @{ + */ + void (*end)(void *priv); + /** @} */ +} ASSCodesCallbacks; + +/** + * Split override codes out of a ASS "Dialogue" Text field. + * + * @param callbacks Set of callback functions called for each override code + * encountered. + * @param priv Opaque pointer passed to the callback functions. + * @param buf The ASS "Dialogue" Text field to split. + * @param outbuffer The output buffer. + * @param keep_flags Flags for filtering ass codes. + * @return >= 0 on success otherwise an error code <0 + */ +int avpriv_ass_filter_override_codes(const ASSCodesCallbacks *callbacks, + void *priv, const char *buf, + AVBPrint *outbuffer, enum ASSSplitComponents keep_flags); + +/** + * Split override codes out of a ASS "Dialogue" Text field. + * + * @param callbacks Set of callback functions called for each override code + * encountered. + * @param priv Opaque pointer passed to the callback functions. + * @param buf The ASS "Dialogue" Text field to split. + * @return >= 0 on success otherwise an error code <0 + */ +int avpriv_ass_split_override_codes(const ASSCodesCallbacks *callbacks, + void *priv, const char *buf); + +/** + * Find an ASSStyle structure by its name. + * + * @param ctx Context previously initialized by ff_ass_split(). + * @param style name of the style to search for. + * @return the ASSStyle corresponding to style, or NULL if style can't be found + */ +ASSStyle *avpriv_ass_style_get(ASSSplitContext *ctx, const char *style); + +#endif /* AVUTIL_ASS_SPLIT_INTERNAL_H */