From patchwork Sun May 28 09:13:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 41857 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:c51c:b0:10c:5e6f:955f with SMTP id gm28csp987566pzb; Sun, 28 May 2023 02:16:13 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ7jfbjgT5+hIf+DCNycQpH/E86nQA4lX7v7MaG4/v4ifceDfxdmLDIPOpYoAR8uIkBj9dkZ X-Received: by 2002:a17:907:843:b0:965:a72a:b2ae with SMTP id ww3-20020a170907084300b00965a72ab2aemr6835312ejb.60.1685265373671; Sun, 28 May 2023 02:16:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685265373; cv=none; d=google.com; s=arc-20160816; b=ut8JwZVBtT2f1Ap8MdcRlYybnJ3hNkOAaUxZAZgpxfO3z3kF8k66XSJQRQtqB6Ph/Z QOJDT8Nhpfq4fLlkVWw9RtkNWzN8fnIt89NLoK8zoAvvX7v3ddjKJ4FTYtG5LaKEyw4k Sqjh6zAPcBDb6SSrV7FogAAlYz94OYRl8hLynA8htKVTYdCFf9AbuSwXoCSdAdDvWHvO GIKdsEuwlggsd2HMBvdtsp3QGsg9VVY5PvXDuve+V97/vAyxj87DOfh23uZM6C8ToM8s DXe0aUbxipcg9hH/JhVy2WTuYHKauzOyjSdIb7UTrtrx9Q48/dr4R0wvdHXHB5gvc5DH e6lA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=zsORcgjGTEee7/O9ohU6jMTlkzg27llffBFRa+jXBHU=; b=TixDkm8QOywEoNQrzmCEpppS1CbhNtHi36/AmFvsv2+2BTbhziFoevOKbATR9EEQSu U7vSrDGMDtTBIkK/9PLoKJqIb9OO9N8ChxyMKWseVozL6upt+mi219C55fvfduQg3AlA D/rE6zLgvd1W+WFNWwY5+nUCutapGCQZNZTSKbEJThvKrveVriDIHcgTtoc3ozpiY+V6 WlkjnLYbYhPUrFW4TNr0F0DqFXHF0BBCqTkLSNzK/5b/FJDFaynDTUPoBoqOxjpVqz/l uvkwiKJSFp5wRarDyOBz/iTC+Tkefb8Ri2Zz4ztkndxZlv2RlyEutSqpXAsd8+brvpm1 f8GQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id p19-20020a17090653d300b00973839f677csi681100ejo.514.2023.05.28.02.16.13; Sun, 28 May 2023 02:16:13 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9609268C23C; Sun, 28 May 2023 12:15:03 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2A62968C1ED for ; Sun, 28 May 2023 12:14:56 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id D3D4C2404F5 for ; Sun, 28 May 2023 11:14:55 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id VTlIrjLzUsFf for ; Sun, 28 May 2023 11:14:53 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id A91252406CB for ; Sun, 28 May 2023 11:14:47 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 570033A05CB for ; Sun, 28 May 2023 11:14:41 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Sun, 28 May 2023 11:13:59 +0200 Message-Id: <20230528091416.17927-7-anton@khirnov.net> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230528091416.17927-1-anton@khirnov.net> References: <20230528091416.17927-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 07/24] fftools/ffmpeg_filter: move some functions higher up X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: yIYPpSqK9WIK Needed by the following commit. --- fftools/ffmpeg_filter.c | 374 ++++++++++++++++++++-------------------- 1 file changed, 187 insertions(+), 187 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index a8c4ef321f..5169a3ca82 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -246,6 +246,193 @@ static void choose_channel_layouts(OutputFilter *ofilter, AVBPrint *bprint) av_bprint_chars(bprint, ':', 1); } +static int read_binary(const char *path, uint8_t **data, int *len) +{ + AVIOContext *io = NULL; + int64_t fsize; + int ret; + + *data = NULL; + *len = 0; + + ret = avio_open2(&io, path, AVIO_FLAG_READ, &int_cb, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot open file '%s': %s\n", + path, av_err2str(ret)); + return ret; + } + + fsize = avio_size(io); + if (fsize < 0 || fsize > INT_MAX) { + av_log(NULL, AV_LOG_ERROR, "Cannot obtain size of file %s\n", path); + ret = AVERROR(EIO); + goto fail; + } + + *data = av_malloc(fsize); + if (!*data) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = avio_read(io, *data, fsize); + if (ret != fsize) { + av_log(NULL, AV_LOG_ERROR, "Error reading file %s\n", path); + ret = ret < 0 ? ret : AVERROR(EIO); + goto fail; + } + + *len = fsize; + + ret = 0; +fail: + avio_close(io); + if (ret < 0) { + av_freep(data); + *len = 0; + } + return ret; +} + +static int filter_opt_apply(AVFilterContext *f, const char *key, const char *val) +{ + const AVOption *o = NULL; + int ret; + + ret = av_opt_set(f, key, val, AV_OPT_SEARCH_CHILDREN); + if (ret >= 0) + return 0; + + if (ret == AVERROR_OPTION_NOT_FOUND && key[0] == '/') + o = av_opt_find(f, key + 1, NULL, 0, AV_OPT_SEARCH_CHILDREN); + if (!o) + goto err_apply; + + // key is a valid option name prefixed with '/' + // interpret value as a path from which to load the actual option value + key++; + + if (o->type == AV_OPT_TYPE_BINARY) { + uint8_t *data; + int len; + + ret = read_binary(val, &data, &len); + if (ret < 0) + goto err_load; + + ret = av_opt_set_bin(f, key, data, len, AV_OPT_SEARCH_CHILDREN); + av_freep(&data); + } else { + char *data = file_read(val); + if (!data) { + ret = AVERROR(EIO); + goto err_load; + } + + ret = av_opt_set(f, key, data, AV_OPT_SEARCH_CHILDREN); + av_freep(&data); + } + if (ret < 0) + goto err_apply; + + return 0; + +err_apply: + av_log(NULL, AV_LOG_ERROR, + "Error applying option '%s' to filter '%s': %s\n", + key, f->filter->name, av_err2str(ret)); + return ret; +err_load: + av_log(NULL, AV_LOG_ERROR, + "Error loading value for option '%s' from file '%s'\n", + key, val); + return ret; +} + +static int graph_opts_apply(AVFilterGraphSegment *seg) +{ + for (size_t i = 0; i < seg->nb_chains; i++) { + AVFilterChain *ch = seg->chains[i]; + + for (size_t j = 0; j < ch->nb_filters; j++) { + AVFilterParams *p = ch->filters[j]; + const AVDictionaryEntry *e = NULL; + + av_assert0(p->filter); + + while ((e = av_dict_iterate(p->opts, e))) { + int ret = filter_opt_apply(p->filter, e->key, e->value); + if (ret < 0) + return ret; + } + + av_dict_free(&p->opts); + } + } + + return 0; +} + +static int graph_parse(AVFilterGraph *graph, const char *desc, + AVFilterInOut **inputs, AVFilterInOut **outputs, + AVBufferRef *hw_device) +{ + AVFilterGraphSegment *seg; + int ret; + + *inputs = NULL; + *outputs = NULL; + + ret = avfilter_graph_segment_parse(graph, desc, 0, &seg); + if (ret < 0) + return ret; + + ret = avfilter_graph_segment_create_filters(seg, 0); + if (ret < 0) + goto fail; + + if (hw_device) { + for (int i = 0; i < graph->nb_filters; i++) { + AVFilterContext *f = graph->filters[i]; + + if (!(f->filter->flags & AVFILTER_FLAG_HWDEVICE)) + continue; + f->hw_device_ctx = av_buffer_ref(hw_device); + if (!f->hw_device_ctx) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + } + + ret = graph_opts_apply(seg); + if (ret < 0) + goto fail; + + ret = avfilter_graph_segment_apply(seg, 0, inputs, outputs); + +fail: + avfilter_graph_segment_free(&seg); + return ret; +} + +static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in) +{ + AVFilterContext *ctx = inout->filter_ctx; + AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; + int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs; + char *res; + + if (nb_pads > 1) + res = av_strdup(ctx->filter->name); + else + res = av_asprintf("%s:%s", ctx->filter->name, + avfilter_pad_get_name(pads, inout->pad_idx)); + if (!res) + report_and_exit(AVERROR(ENOMEM)); + return res; +} + static OutputFilter *ofilter_alloc(FilterGraph *fg) { OutputFilter *ofilter; @@ -395,23 +582,6 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost, return 0; } -static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in) -{ - AVFilterContext *ctx = inout->filter_ctx; - AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; - int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs; - char *res; - - if (nb_pads > 1) - res = av_strdup(ctx->filter->name); - else - res = av_asprintf("%s:%s", ctx->filter->name, - avfilter_pad_get_name(pads, inout->pad_idx)); - if (!res) - report_and_exit(AVERROR(ENOMEM)); - return res; -} - static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) { FilterGraphPriv *fgp = fgp_from_fg(fg); @@ -480,176 +650,6 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) } } -static int read_binary(const char *path, uint8_t **data, int *len) -{ - AVIOContext *io = NULL; - int64_t fsize; - int ret; - - *data = NULL; - *len = 0; - - ret = avio_open2(&io, path, AVIO_FLAG_READ, &int_cb, NULL); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Cannot open file '%s': %s\n", - path, av_err2str(ret)); - return ret; - } - - fsize = avio_size(io); - if (fsize < 0 || fsize > INT_MAX) { - av_log(NULL, AV_LOG_ERROR, "Cannot obtain size of file %s\n", path); - ret = AVERROR(EIO); - goto fail; - } - - *data = av_malloc(fsize); - if (!*data) { - ret = AVERROR(ENOMEM); - goto fail; - } - - ret = avio_read(io, *data, fsize); - if (ret != fsize) { - av_log(NULL, AV_LOG_ERROR, "Error reading file %s\n", path); - ret = ret < 0 ? ret : AVERROR(EIO); - goto fail; - } - - *len = fsize; - - ret = 0; -fail: - avio_close(io); - if (ret < 0) { - av_freep(data); - *len = 0; - } - return ret; -} - -static int filter_opt_apply(AVFilterContext *f, const char *key, const char *val) -{ - const AVOption *o = NULL; - int ret; - - ret = av_opt_set(f, key, val, AV_OPT_SEARCH_CHILDREN); - if (ret >= 0) - return 0; - - if (ret == AVERROR_OPTION_NOT_FOUND && key[0] == '/') - o = av_opt_find(f, key + 1, NULL, 0, AV_OPT_SEARCH_CHILDREN); - if (!o) - goto err_apply; - - // key is a valid option name prefixed with '/' - // interpret value as a path from which to load the actual option value - key++; - - if (o->type == AV_OPT_TYPE_BINARY) { - uint8_t *data; - int len; - - ret = read_binary(val, &data, &len); - if (ret < 0) - goto err_load; - - ret = av_opt_set_bin(f, key, data, len, AV_OPT_SEARCH_CHILDREN); - av_freep(&data); - } else { - char *data = file_read(val); - if (!data) { - ret = AVERROR(EIO); - goto err_load; - } - - ret = av_opt_set(f, key, data, AV_OPT_SEARCH_CHILDREN); - av_freep(&data); - } - if (ret < 0) - goto err_apply; - - return 0; - -err_apply: - av_log(NULL, AV_LOG_ERROR, - "Error applying option '%s' to filter '%s': %s\n", - key, f->filter->name, av_err2str(ret)); - return ret; -err_load: - av_log(NULL, AV_LOG_ERROR, - "Error loading value for option '%s' from file '%s'\n", - key, val); - return ret; -} - -static int graph_opts_apply(AVFilterGraphSegment *seg) -{ - for (size_t i = 0; i < seg->nb_chains; i++) { - AVFilterChain *ch = seg->chains[i]; - - for (size_t j = 0; j < ch->nb_filters; j++) { - AVFilterParams *p = ch->filters[j]; - const AVDictionaryEntry *e = NULL; - - av_assert0(p->filter); - - while ((e = av_dict_iterate(p->opts, e))) { - int ret = filter_opt_apply(p->filter, e->key, e->value); - if (ret < 0) - return ret; - } - - av_dict_free(&p->opts); - } - } - - return 0; -} - -static int graph_parse(AVFilterGraph *graph, const char *desc, - AVFilterInOut **inputs, AVFilterInOut **outputs, - AVBufferRef *hw_device) -{ - AVFilterGraphSegment *seg; - int ret; - - *inputs = NULL; - *outputs = NULL; - - ret = avfilter_graph_segment_parse(graph, desc, 0, &seg); - if (ret < 0) - return ret; - - ret = avfilter_graph_segment_create_filters(seg, 0); - if (ret < 0) - goto fail; - - if (hw_device) { - for (int i = 0; i < graph->nb_filters; i++) { - AVFilterContext *f = graph->filters[i]; - - if (!(f->filter->flags & AVFILTER_FLAG_HWDEVICE)) - continue; - f->hw_device_ctx = av_buffer_ref(hw_device); - if (!f->hw_device_ctx) { - ret = AVERROR(ENOMEM); - goto fail; - } - } - } - - ret = graph_opts_apply(seg); - if (ret < 0) - goto fail; - - ret = avfilter_graph_segment_apply(seg, 0, inputs, outputs); - -fail: - avfilter_graph_segment_free(&seg); - return ret; -} - int init_complex_filtergraph(FilterGraph *fg) { FilterGraphPriv *fgp = fgp_from_fg(fg);