[FFmpeg-devel] [vf_ass.c] 2 lines of code that need your attention
Stefano Sabatini
stefasab at gmail.com
Tue Mar 27 02:22:23 CEST 2012
On date Thursday 2012-03-22 21:06:21 +0100, Nicolas George encoded:
> Le duodi 2 germinal, an CCXX, Stefano Sabatini a écrit :
> > And now I see that both VLC and MPlayer use a more complex logic...
>
> As far as I can see, the logic for the font size in ASS is, in deductive
> order (v for virtual, p for pixels):
>
> em_h_v = Fontsize * SclaleY/100
> em_h_p = Fontsize * SclaleY/100 * video_h / PlayResY
> em_w_p = Fontsize * SclaleX/100 * video_h / PlayResY
> em_w_v = Fontsize * SclaleX/100 * video_h / PlayResY * PlayResX / video_w
>
> This works when video_w and video_h are the pixels dimensions of the video
> for which the ASS file has been conceived. Note that it completely
> disregards any kind of aspect ratio.
>
> So, assuming the ASS file has been designed for the original unscaled video
> and we only scaled (no crop, no pad), we need an extra scaling on the X
> direction with ratio current_sar / original_sar = original_iar / current_iar
> (where iar is the aspect ratio in pixels, with dar = sar * iar).
OK so this is assuming that original_dar == current_dar.
> Now, reading the sources for libass, I find that ass_set_aspect_ratio takes
> two arguments: aspect and storage_aspect (and sar does not mean _sample_
> aspect!), which seems to be display aspects, and computes the extra X
> scaling as storage_aspect / aspect.
>
> Therefore, the correct call would probably be:
>
> ass_set_aspect_ratio(ass, current_iar, original_iar);
>
> although the following should work too:
>
> ass_set_aspect_ratio(ass, original_sar, current_sar);
>
> It seems to be somewhat like what mplayer does.
>
> Attached is a patch that does just that. I believe the dar option has not
> been around for enough time to make its removal a problem, especially since
> it did not work.
Sure, just remember to bump micro so we know where to point out when
users complain ;-).
> Regards,
>
> --
> Nicolas George
> From d8eedbcb25b7c12b7257e9d144caf7290fcabd50 Mon Sep 17 00:00:00 2001
> From: Nicolas George <nicolas.george at normalesup.org>
> Date: Thu, 22 Mar 2012 20:59:36 +0100
> Subject: [PATCH] ass: fix aspect ratio computation.
>
>
> Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
> ---
> doc/filters.texi | 7 ++++---
> libavfilter/vf_ass.c | 23 +++++++++++------------
> 2 files changed, 15 insertions(+), 15 deletions(-)
>
> diff --git a/doc/filters.texi b/doc/filters.texi
> index ac3e841..16b07e1 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -761,9 +761,10 @@ separated by ":".
> A description of the accepted options follows.
>
> @table @option
> - at item dar
> -Specifies the display aspect ratio adopted for rendering the
> -subtitles. Default value is "1.0".
> + at item original_size
> +Specifies the size of the original video, the video for which the ASS file
> +was composed. Due to a misdesign in ASS aspect ratio arithmetic, this is
> +necessary to correctly scale the fonts if the aspect ratio has been changed.
> @end table
>
> For example, to render the file @file{sub.ass} on top of the input
> diff --git a/libavfilter/vf_ass.c b/libavfilter/vf_ass.c
> index bf13287..1cf886b 100644
> --- a/libavfilter/vf_ass.c
> +++ b/libavfilter/vf_ass.c
> @@ -45,14 +45,14 @@ typedef struct {
> char *filename;
> uint8_t rgba_map[4];
> int pix_step[4]; ///< steps per pixel for each plane of the main output
> - char *dar_str;
> - AVRational dar;
> + char *original_size_str;
> + int original_w, original_h;
> } AssContext;
>
> #define OFFSET(x) offsetof(AssContext, x)
>
> static const AVOption ass_options[] = {
> - {"dar", "set subtitles display aspect ratio", OFFSET(dar_str), AV_OPT_TYPE_STRING, {.str = "1.0"}, CHAR_MIN, CHAR_MAX },
> + {"original_size", "set the size of the original video (used to scale fonts)", OFFSET(original_size_str), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX },
> {NULL},
> };
>
> @@ -107,10 +107,11 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
> return ret;
> }
>
> - if (av_parse_ratio(&ass->dar, ass->dar_str, 100, 0, ctx) < 0 ||
> - ass->dar.num < 0 || ass->dar.den <= 0) {
> + if (ass->original_size_str &&
> + av_parse_video_size(&ass->original_w, &ass->original_h,
> + ass->original_size_str) < 0) {
> av_log(ctx, AV_LOG_ERROR,
> - "Invalid string '%s' or value for display aspect ratio.\n", ass->dar_str);
> + "Invalid original size '%s'.\n", ass->original_size_str);
> return AVERROR(EINVAL);
> }
>
> @@ -136,8 +137,6 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
> }
>
> ass_set_fonts(ass->renderer, NULL, NULL, 1, NULL, 1);
> -
> - av_log(ctx, AV_LOG_INFO, "dar:%f\n", av_q2d(ass->dar));
> return 0;
> }
>
> @@ -146,7 +145,7 @@ static av_cold void uninit(AVFilterContext *ctx)
> AssContext *ass = ctx->priv;
>
> av_freep(&ass->filename);
> - av_freep(&ass->dar_str);
> + av_freep(&ass->original_size_str);
> if (ass->track)
> ass_free_track(ass->track);
> if (ass->renderer)
> @@ -173,8 +172,6 @@ static int config_input(AVFilterLink *inlink)
> {
> AssContext *ass = inlink->dst->priv;
> const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[inlink->format];
> - double sar = inlink->sample_aspect_ratio.num ?
> - av_q2d(inlink->sample_aspect_ratio) : 1;
>
> av_image_fill_max_pixsteps(ass->pix_step, NULL, pix_desc);
> ff_fill_rgba_map(ass->rgba_map, inlink->format);
> @@ -183,7 +180,9 @@ static int config_input(AVFilterLink *inlink)
> ass->vsub = pix_desc->log2_chroma_h;
>
> ass_set_frame_size (ass->renderer, inlink->w, inlink->h);
> - ass_set_aspect_ratio(ass->renderer, av_q2d(ass->dar), sar);
> + if (ass->original_w && ass->original_h)
> + ass_set_aspect_ratio(ass->renderer, (double)inlink->w / inlink->h,
> + (double)ass->original_w / ass->original_h);
>
> return 0;
> }
Looks good, and many thanks for investigating on the issue.
--
FFmpeg = Formidable and Fiendish Meaningful Plastic Exciting Gadget
More information about the ffmpeg-devel
mailing list