From 9b55009e8f6e81bdc19172b4469b58646464dc80 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 2 Oct 2019 23:00:28 +0200 Subject: f_autoconvert: provide a function to determine if conversion works This adds the function as seen in the f_autoconvert.h part of the patch. It's pretty simple, but goes along with an intrusive code move. I guess the resulting code is slightly nicer anyway. --- filters/f_autoconvert.c | 103 +++++++++++++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 41 deletions(-) (limited to 'filters/f_autoconvert.c') diff --git a/filters/f_autoconvert.c b/filters/f_autoconvert.c index 2e039c260c..76c93363ca 100644 --- a/filters/f_autoconvert.c +++ b/filters/f_autoconvert.c @@ -169,33 +169,17 @@ void mp_autoconvert_add_srate(struct mp_autoconvert *c, int rate) p->force_update = true; } -static void handle_video_frame(struct mp_filter *f) +// If this returns true, and *out==NULL, no conversion is necessary. +static bool build_image_converter(struct mp_autoconvert *c, struct mp_log *log, + struct mp_image *img, struct mp_filter **f_out) { + struct mp_filter *f = c->f; struct priv *p = f->priv; - struct mp_image *img = p->sub.frame.data; - - if (p->force_update) - p->in_imgfmt = p->in_subfmt = 0; - - if (img->imgfmt == p->in_imgfmt && img->params.hw_subfmt == p->in_subfmt) { - mp_subfilter_continue(&p->sub); - return; - } - - if (!mp_subfilter_drain_destroy(&p->sub)) { - p->in_imgfmt = p->in_subfmt = 0; - return; - } - - p->in_imgfmt = img->params.imgfmt; - p->in_subfmt = img->params.hw_subfmt; - p->force_update = false; + *f_out = NULL; - if (!p->num_imgfmts) { - mp_subfilter_continue(&p->sub); - return; - } + if (!p->num_imgfmts) + return true; bool different_subfmt = false; @@ -204,10 +188,8 @@ static void handle_video_frame(struct mp_filter *f) bool samesubffmt = img->params.hw_subfmt == p->subfmts[n]; if (samefmt && !samesubffmt) different_subfmt = true; - if (samefmt && (samesubffmt || !p->subfmts[n])) { - mp_subfilter_continue(&p->sub); - return; - } + if (samefmt && (samesubffmt || !p->subfmts[n])) + return true; } struct mp_stream_info *info = mp_filter_find_stream_info(f); @@ -229,7 +211,7 @@ static void handle_video_frame(struct mp_filter *f) // This should not happen. But not enough guarantee to make it an assert(). if (imgfmt_is_sw != !img->hwctx) - MP_WARN(p, "Unexpected AVFrame/imgfmt hardware context mismatch.\n"); + mp_warn(log, "Unexpected AVFrame/imgfmt hardware context mismatch.\n"); bool dst_all_hw = true; bool dst_have_sw = false; @@ -248,7 +230,7 @@ static void handle_video_frame(struct mp_filter *f) // We can probably use this! Very lazy and very approximate. struct mp_hwupload *upload = mp_hwupload_create(conv, fmts[0]); if (upload) { - MP_INFO(p, "HW-uploading to %s\n", mp_imgfmt_to_name(fmts[0])); + mp_info(log, "HW-uploading to %s\n", mp_imgfmt_to_name(fmts[0])); filters[2] = upload->f; fmts = upload->upload_fmts; num_fmts = upload->num_upload_fmts; @@ -257,7 +239,7 @@ static void handle_video_frame(struct mp_filter *f) } else if (p->vo_convert && different_subfmt && info && info->hwdec_devs) { for (int n = 0; subfmt_converters[n].hw_imgfmt; n++) { if (subfmt_converters[n].hw_imgfmt == img->imgfmt) { - MP_INFO(p, "Using HW sub-conversion.\n"); + mp_info(log, "Using HW sub-conversion.\n"); filters[2] = subfmt_converters[n].create(conv); if (filters[2]) { need_sws = false; @@ -270,10 +252,10 @@ static void handle_video_frame(struct mp_filter *f) int src_fmt = img->imgfmt; if (hw_to_sw) { - MP_INFO(p, "HW-downloading from %s\n", mp_imgfmt_to_name(img->imgfmt)); + mp_info(log, "HW-downloading from %s\n", mp_imgfmt_to_name(img->imgfmt)); int res_fmt = mp_image_hw_download_get_sw_format(img); if (!res_fmt) { - MP_ERR(p, "cannot copy surface of this format to CPU memory\n"); + mp_err(log, "cannot copy surface of this format to CPU memory\n"); goto fail; } struct mp_hwdownload *hwd = mp_hwdownload_create(conv); @@ -287,13 +269,13 @@ static void handle_video_frame(struct mp_filter *f) // Create a new conversion filter. struct mp_sws_filter *sws = mp_sws_filter_create(conv); if (!sws) { - MP_ERR(p, "error creating conversion filter\n"); - return; + mp_err(log, "error creating conversion filter\n"); + goto fail; } int out = mp_sws_find_best_out_format(src_fmt, fmts, num_fmts); if (!out) { - MP_ERR(p, "can't find video conversion for %s\n", + mp_err(log, "can't find video conversion for %s\n", mp_imgfmt_to_name(src_fmt)); goto fail; } @@ -303,7 +285,7 @@ static void handle_video_frame(struct mp_filter *f) talloc_free(sws->f); } else { sws->out_format = out; - MP_INFO(p, "Converting %s -> %s\n", mp_imgfmt_to_name(src_fmt), + mp_info(log, "Converting %s -> %s\n", mp_imgfmt_to_name(src_fmt), mp_imgfmt_to_name(sws->out_format)); filters[1] = sws->f; } @@ -311,14 +293,53 @@ static void handle_video_frame(struct mp_filter *f) mp_chain_filters(conv->ppins[0], conv->ppins[1], filters, 3); - p->sub.filter = conv; - mp_subfilter_continue(&p->sub); - return; + *f_out = conv; + return true; fail: talloc_free(conv); - mp_filter_internal_mark_failed(f); - return; + return false; +} + +bool mp_autoconvert_probe_input_video(struct mp_autoconvert *c, + struct mp_image *img) +{ + struct mp_filter *conv = NULL; + bool res = build_image_converter(c, mp_null_log, img, &conv); + talloc_free(conv); + return res; +} + +static void handle_video_frame(struct mp_filter *f) +{ + struct priv *p = f->priv; + + struct mp_image *img = p->sub.frame.data; + + if (p->force_update) + p->in_imgfmt = p->in_subfmt = 0; + + if (img->imgfmt == p->in_imgfmt && img->params.hw_subfmt == p->in_subfmt) { + mp_subfilter_continue(&p->sub); + return; + } + + if (!mp_subfilter_drain_destroy(&p->sub)) { + p->in_imgfmt = p->in_subfmt = 0; + return; + } + + p->in_imgfmt = img->params.imgfmt; + p->in_subfmt = img->params.hw_subfmt; + p->force_update = false; + + struct mp_filter *conv = NULL; + if (build_image_converter(&p->public, p->log, img, &conv)) { + p->sub.filter = conv; + mp_subfilter_continue(&p->sub); + } else { + mp_filter_internal_mark_failed(f); + } } static void handle_audio_frame(struct mp_filter *f) -- cgit v1.2.3