[FFmpeg-devel] [PATCH 10/23] lavc/movtextdec: allow setting subtitle frame dimensions
John Stebbins
jstebbins at jetheaddev.com
Thu Apr 9 02:05:40 EEST 2020
On Wed, 2020-04-08 at 10:31 -0700, Philip Langdale wrote:
> On Mon, 6 Apr 2020 11:52:05 -0600
> John Stebbins <jstebbins at jetheaddev.com> wrote:
>
> > Font sizes are relative to the subtitle frame dimensions. If the
> > expected frame dimensions are not known, the font sizes will most
> > likely be incorrect.
> > ---
> > libavcodec/ass.c | 30 +++++++++++++++++++++++-------
> > libavcodec/ass.h | 28 ++++++++++++++++++++++++++++
> > libavcodec/movtextdec.c | 30 +++++++++++++++++++++++++++++-
> > 3 files changed, 80 insertions(+), 8 deletions(-)
> >
> > diff --git a/libavcodec/ass.c b/libavcodec/ass.c
> > index a51673fb4e..7c26e3fd6d 100644
> > --- a/libavcodec/ass.c
> > +++ b/libavcodec/ass.c
> > @@ -26,11 +26,13 @@
> > #include "libavutil/bprint.h"
> > #include "libavutil/common.h"
> >
> > -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 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)
> > {
> > avctx->subtitle_header = av_asprintf(
> > "[Script Info]\r\n"
> > @@ -67,8 +69,8 @@ int ff_ass_subtitle_header(AVCodecContext *avctx,
> > "[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) : "",
> > - ASS_DEFAULT_PLAYRESX, ASS_DEFAULT_PLAYRESY,
> > - font, font_size, color, color, back_color,
> > back_color,
> > + 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)
> > @@ -77,6 +79,20 @@ int ff_ass_subtitle_header(AVCodecContext
> > *avctx,
> > return 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)
> > +{
> > + 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);
> > +}
> > +
> > int ff_ass_subtitle_header_default(AVCodecContext *avctx)
> > {
> > return ff_ass_subtitle_header(avctx, ASS_DEFAULT_FONT,
> > diff --git a/libavcodec/ass.h b/libavcodec/ass.h
> > index 314b43b686..2c260e4e78 100644
> > --- a/libavcodec/ass.h
> > +++ b/libavcodec/ass.h
> > @@ -47,6 +47,34 @@ 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,
> > + 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. *
> > diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c
> > index f3a504b47b..4b4da5e0d9 100644
> > --- a/libavcodec/movtextdec.c
> > +++ b/libavcodec/movtextdec.c
> > @@ -21,6 +21,7 @@
> >
> > #include "avcodec.h"
> > #include "ass.h"
> > +#include "libavutil/opt.h"
> > #include "libavutil/avstring.h"
> > #include "libavutil/common.h"
> > #include "libavutil/bprint.h"
> > @@ -96,6 +97,7 @@ typedef struct {
> > } TextWrapBox;
> >
> > typedef struct {
> > + AVClass *class;
> > StyleBox **s;
> > StyleBox *s_temp;
> > HighlightBox h;
> > @@ -110,6 +112,8 @@ typedef struct {
> > int size_var;
> > int count_s, count_f;
> > int readorder;
> > + int frame_width;
> > + int frame_height;
> > } MovTextContext;
> >
> > typedef struct {
> > @@ -481,9 +485,17 @@ static int mov_text_init(AVCodecContext
> > *avctx) {
> > MovTextContext *m = avctx->priv_data;
> > ret = mov_text_tx3g(avctx, m);
> > if (ret == 0) {
> > - return ff_ass_subtitle_header(avctx, m->d.font,
> > m->d.fontsize,
> > + if (!m->frame_width || !m->frame_height) {
> > + m->frame_width = ASS_DEFAULT_PLAYRESX;
> > + m->frame_height = ASS_DEFAULT_PLAYRESY;
> > + }
> > + return ff_ass_subtitle_header_full(avctx,
> > + m->frame_width, m->frame_height,
> > + m->d.font, m->d.fontsize,
> > + (255 - m->d.alpha) << 24 |
> > RGB_TO_BGR(m->d.color), (255 - m->d.alpha) << 24 |
> > RGB_TO_BGR(m->d.color), (255 - m->d.back_alpha) << 24 |
> > RGB_TO_BGR(m->d.back_color),
> > + (255 - m->d.back_alpha) << 24 |
> > RGB_TO_BGR(m->d.back_color), m->d.bold, m->d.italic, m-
> > >d.underline,
> > ASS_DEFAULT_BORDERSTYLE, m->d.alignment);
> > } else
> > @@ -601,12 +613,28 @@ static void mov_text_flush(AVCodecContext
> > *avctx) m->readorder = 0;
> > }
> >
> > +#define OFFSET(x) offsetof(MovTextContext, x)
> > +#define FLAGS AV_OPT_FLAG_DECODING_PARAM |
> > AV_OPT_FLAG_SUBTITLE_PARAM
> > +static const AVOption options[] = {
> > + { "width", "Frame width, usually video width",
> > OFFSET(frame_width), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS
> > },
> > + { "height", "Frame height, usually video height",
> > OFFSET(frame_height), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS
> > },
> > + { NULL },
> > +};
> > +
> > +static const AVClass mov_text_decoder_class = {
> > + .class_name = "MOV text decoder",
> > + .item_name = av_default_item_name,
> > + .option = options,
> > + .version = LIBAVUTIL_VERSION_INT,
> > +};
> > +
> > AVCodec ff_movtext_decoder = {
> > .name = "mov_text",
> > .long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text
> > subtitle"),
> > .type = AVMEDIA_TYPE_SUBTITLE,
> > .id = AV_CODEC_ID_MOV_TEXT,
> > .priv_data_size = sizeof(MovTextContext),
> > + .priv_class = &mov_text_decoder_class,
> > .init = mov_text_init,
> > .decode = mov_text_decode_frame,
> > .close = mov_text_decode_close,
>
> LGTM. When I last looked at frame dimensions, I could never
> find a sane way to set these values to the actual video frame
> dimensions. I'm guess you couldn't either? :-)
>
>
They could also be provided through AVCodecContext.with/height. But I
thought this made the API more clear and provides a way to give some
help text.
But yeah, since this is information that relates to a completely
different stream, there's no automatic way to get this information. It
must be supplied by higher level code.
More information about the ffmpeg-devel
mailing list