diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 90c7f113a3..58544b40ba 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -224,10 +224,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
@@ -269,7 +269,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
@@ -449,7 +449,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 \
@@ -472,7 +472,7 @@ OBJS-$(CONFIG_MDEC_DECODER)            += mdec.o mpeg12.o mpeg12data.o
 OBJS-$(CONFIG_MEDIA100_DECODER)        += media100.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_MISC4_DECODER)           += misc4.o
 OBJS-$(CONFIG_MJPEG_DECODER)           += mjpegdec.o mjpegdec_common.o
@@ -488,8 +488,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
@@ -530,7 +530,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_MSNSIREN_DECODER)        += siren.o
@@ -580,7 +580,7 @@ OBJS-$(CONFIG_PHM_ENCODER)             += pnmenc.o float2half.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
@@ -615,7 +615,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
@@ -630,7 +630,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
@@ -666,13 +666,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
@@ -682,8 +682,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
@@ -703,7 +703,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
@@ -759,7 +759,7 @@ 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_VQC_DECODER)             += vqcdec.o
@@ -769,8 +769,8 @@ OBJS-$(CONFIG_WBMP_DECODER)            += wbmpdec.o
 OBJS-$(CONFIG_WBMP_ENCODER)            += wbmpenc.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
@@ -1057,7 +1057,7 @@ OBJS-$(CONFIG_PCM_ALAW_AT_ENCODER)        += audiotoolboxenc.o
 OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER)       += audiotoolboxenc.o
 OBJS-$(CONFIG_LIBAOM_AV1_DECODER)         += libaomdec.o libaom.o
 OBJS-$(CONFIG_LIBAOM_AV1_ENCODER)         += libaomenc.o libaom.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
@@ -1110,7 +1110,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 <aurel@gnuage.org>
- *
- * 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 89d7b51894..2571118ee9 100644
--- a/libavcodec/assdec.c
+++ b/libavcodec/assdec.c
@@ -22,9 +22,9 @@
 #include <string.h>
 
 #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 db6fd25dd7..9bbcdd9054 100644
--- a/libavcodec/assenc.c
+++ b/libavcodec/assenc.c
@@ -24,8 +24,8 @@
 #include <string.h>
 
 #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 61eda9ff56..6636ec34ac 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 08349a9ec8..9108050291 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 f40517e22e..e69ffb5653 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 486aa1724e..1afc13ce21 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 786a3845fd..d254b1cd93 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 f799252bf2..3c9e84c5e9 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 7aa74d7c9d..6f87e30904 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 8639acf0b0..896323156c 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 b09ff78ea4..4b17f31662 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 e84c4bc6b8..07ef1cb0d0 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 8697f5b149..9eb30fe7d2 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 7e36a2200c..245e6a37c5 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 209f69505f..f860d05c00 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 b9aebff002..604175ddc2 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 fb05c38968..c3f873147c 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, "</span>");
 
-        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 690f00dc47..b255484464 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 4369aacb74..2df31f8fba 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, "<b>");
@@ -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 4ab4fcb01b..0eba374477 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 728cfb1ab5..1a46f8d589 100644
--- a/libavcodec/ass.c
+++ b/libavutil/ass.c
@@ -19,22 +19,23 @@
  * 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"
 #include "version.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"
@@ -69,34 +70,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,
@@ -104,10 +102,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",
@@ -115,61 +114,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 <aurel@gnuage.org>
+ *
+ * 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 <aurel@gnuage.org>
+ *
+ * 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 */
