From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <ffmpeg-devel-bounces@ffmpeg.org>
Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100])
	by master.gitmailbox.com (Postfix) with ESMTPS id 4A85F4B505
	for <ffmpegdev@gitmailbox.com>; Wed, 26 Mar 2025 07:29:05 +0000 (UTC)
Received: from [127.0.1.1] (localhost [127.0.0.1])
	by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 2A3E0687B8C;
	Wed, 26 Mar 2025 09:29:01 +0200 (EET)
Received: from NAM11-CO1-obe.outbound.protection.outlook.com
 (mail-co1nam11olkn2094.outbound.protection.outlook.com [40.92.18.94])
 by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id EBA4E687B4E
 for <ffmpeg-devel@ffmpeg.org>; Wed, 26 Mar 2025 09:28:53 +0200 (EET)
ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;
 b=jVIusHeea/XMLTIyOWozVUkUauFwi3NiVh9iq+6ChF6e/BlcQlZDkuzxp1DWcue+MVcrYiQjWCavjI6DsOOR7SFp/ztxCQaajSSXs9AX4Gry3lDFKXw0oJM1bxFwuHDHOrwP6ZAX1aoGFgTLg8HRM0TY6IJDf3gU9cNIUq6sz25qimrPXN9WD7d16LwX6iUSuNf05r9BvsHwuPXUVF8IfKOw8vHu1mYas5ZTRaPW1TiNEosxDs59Aq9zPtVm4XAaFPfTaxrvbhFnWD/HHSQzsdjcAYBsYoVDSSH1bpgvKEPTiqqT0h0IoeXyiVmcGaUSzs9CcOczx5QBFJVhmxtPjQ==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; 
 s=arcselector10001;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
 bh=G8jyZAW4i7DgSNGQrxfF2RgVsPeyx6vmhbVGMQJspo0=;
 b=gfzVywU5yelcQpEJzMI9nm5m6lEFg9WhiYmW30h/eHls7gDxvJuvuqwcLcngJl5WdGJIyCQC94MgUjFV534hBppajRizeJp+p1kLba7OoCddcNzYfHhk/c6kvl/ACxSo2oAx/9S67yP1wZ6K/8WHKQBM3FxX6z+1KMbEw6n5G+PjrWgzghNpIEnvyTlyl7kfjbUaymWrgODVJaoTvJ7Qql6qqPBBBh8bagaqIl4RqlipAwsVOtl7x1ur+z+/y+0yXHoaHWK7A6WEKdXsYi/oqTT20cwbcFAECvdxniDKO/d73X8n665jCKCWxilGvX5PddcinMMPe+krJ2/Ay/lSJA==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none;
 dkim=none; arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hotmail.com;
 s=selector1;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=G8jyZAW4i7DgSNGQrxfF2RgVsPeyx6vmhbVGMQJspo0=;
 b=KsJmYEERzyAlPDkw0oo1LwcBfMR9fkb2v0d8WjS9IHg+d+tHXxr81Aw+GKjotwNY5Pnf6+wFaYS+CihiTtLkRDiLt5kvwnvgx8wmelBLJg2UvdHQwzsjSDmkdK8doeSOgFW+L2pl9YqV0lP3+/LEw+mz0ST2LoFGo78OSD0JbrEkt2qmW3rhuQwN+gJx4kvMRylHnYKG4sT4qiQI3Oyf6apTeYRO3FEHCuMqLs6wJXTRKrTOppCzdh3fbGr2OM78GuoFIicAPjyNoG4pjrIa7T3OmEE6eFEQ9zVXDBK/4qIwsKYNkmIAfd2yKAvIkTe+cExRRpLeIGhfC0aGlusXBw==
Received: from DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM (2603:10b6:8:b::20) by
 MN0P223MB1255.NAMP223.PROD.OUTLOOK.COM (2603:10b6:208:4bf::12) with Microsoft
 SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
 15.20.8534.43; Wed, 26 Mar 2025 07:28:50 +0000
Received: from DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM
 ([fe80::bf09:8e9:b07f:98a7]) by DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM
 ([fe80::bf09:8e9:b07f:98a7%7]) with mapi id 15.20.8534.043; Wed, 26 Mar 2025
 07:28:50 +0000
From: "softworkz ." <softworkz-at-hotmail.com@ffmpeg.org>
To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
Thread-Topic: [FFmpeg-devel] [PATCH] FFMPEG: add graph reconfig capability
Thread-Index: AQHbnXiTo7aivuMrDUCOJ23WUBAlQ7OE8gUQ
Date: Wed, 26 Mar 2025 07:28:50 +0000
Message-ID: <DM8P223MB0365C7C4D8966D4F27A8F77ABAA62@DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM>
References: <tencent_3D16BF6736523D0CF509D6BE945709048E07@qq.com>
In-Reply-To: <tencent_3D16BF6736523D0CF509D6BE945709048E07@qq.com>
Accept-Language: en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
x-ms-publictraffictype: Email
x-ms-traffictypediagnostic: DM8P223MB0365:EE_|MN0P223MB1255:EE_
x-ms-office365-filtering-correlation-id: 0448d739-98bd-4dcb-4486-08dd6c37da97
x-microsoft-antispam: BCL:0;
 ARA:14566002|15080799006|19110799003|7092599003|8060799006|461199028|8062599003|440099028|3412199025|12091999003|41001999003|102099032;
x-microsoft-antispam-message-info: =?iso-8859-1?Q?8aWJ6HANxdnX8qg+u3yYjco0IAd3CWfWzT+ahtJ8CR7/oM6jfCB9Zj7mAh?=
 =?iso-8859-1?Q?pjElQcpzRidZe4eh1RfU3uV2KJ9PIFoZSfPuHhlk9svSf7xM0MN2KH3PG/?=
 =?iso-8859-1?Q?RCnW2GIoHye5V4nE0qrAWYPGxBM6D512+4XaDQf/dgjsMewZBD47jmqqSz?=
 =?iso-8859-1?Q?MypYaQqJ8H8aNmYFTAoZnGTIDLeDqL760wsllF0uQClU81v7Ua3ICQXj7g?=
 =?iso-8859-1?Q?RGq9E0gW7qKBzNF8LcqNLGqAnMJ0/FGQOmTBk/a9wmtkKsmtYmxYlqRjvi?=
 =?iso-8859-1?Q?t08QJUUgb/pPJujUBr6cMwsOyinRNZWn9oWxCUsxgf+IS5EbCNbmP6nIsV?=
 =?iso-8859-1?Q?D70JY1gZaltYrqVTftJLPuhtw3oJbuVFn9Po7I8BwsZvHdifDPyq22oaaq?=
 =?iso-8859-1?Q?DvFEN0PjVh8E+PmV975ckHSPOuFuCG/BsGBDi9qzAsgW+MISKoFUs7nHrU?=
 =?iso-8859-1?Q?QN2S9k2QuVH/CjiLGHw9+T3oxtjiXweo1iU9FO6KFeiPcmTxdeDfi/Y6cj?=
 =?iso-8859-1?Q?xOn3lQjj2jP8FyzsAXCyvmkLjOQ5VVGzPU5jcYOz4XyM1Ye7wYMqMAGOtX?=
 =?iso-8859-1?Q?ayld56tb2hnBz0nkFQfLC81DExpEfI0GKxudVVlGbXFWOZ7Uh9Xm4qZGpE?=
 =?iso-8859-1?Q?OU7Ju4hoZ9C81pjSumlp+wuqwDhJvvYe/jzNUcuNn8GsBvvsfI+d+3l+7J?=
 =?iso-8859-1?Q?AP8h7NC9i05OVVHUUBPLLTuLpQeKlqrfc/MMB2jjwpknpN1jYrJHZsk7Xf?=
 =?iso-8859-1?Q?fxPbaRvchjkijmBQAW0DG53Um1m05mhjD9f+1n+uTzgLfQuWEOGajEOOfw?=
 =?iso-8859-1?Q?nndDKGp5+yVezCYqLwyix+liQ5e6guEgZ7lP+045oT093hjP5gKlaTz6/x?=
 =?iso-8859-1?Q?hrB9dxKEXRdLMvHGlaxkaQgBpGHh04taKZkCk8NN6ydMp0U1+kwvWsdUjQ?=
 =?iso-8859-1?Q?+dCc1zqlgNooPg7EH8VGGUMRsIL/eXi3oQa9ZJw/z+3FsNVLO9sPHNkljy?=
 =?iso-8859-1?Q?GiSSOgo/zXBENm/n7S8JsfpfYkAc1wqoApMQLzkPO7PDTo9qBrzZ6X+bhV?=
 =?iso-8859-1?Q?Gj2Wm3QjzW+aB6rkfSM4bZjFTDbo8g89VaklW7hRFcEULk1GakEI9uDGTl?=
 =?iso-8859-1?Q?d3//+MeB8QfCQ3cFrpE0p53FxvCz0PDSCJ25HgsPKvAqjq33mOpTNfZ40E?=
 =?iso-8859-1?Q?0t8H5DAtJu/IsLvd0rs4PWjUx01v17T3urU=3D?=
x-ms-exchange-antispam-messagedata-chunkcount: 1
x-ms-exchange-antispam-messagedata-0: =?iso-8859-1?Q?s/tSQ2m03/y80LZ03Um/urj7jwKkUX2Ddillegr/zdneG5Lb0QGzA7HtCe?=
 =?iso-8859-1?Q?O8mgPJhp1nBuilgcUWgmZ/8yxL9PkN22RjsUdXn/iK5W84ycq4fmkqB1aF?=
 =?iso-8859-1?Q?jbXOjcmp7QIScxhtgy1TCiqaPmahm0HpUc6A5TG0siF/uUupabixoIibt5?=
 =?iso-8859-1?Q?rhnhLXityZqYACgWHz6iYm18Rx/gLyTpn3OtgC8DJZT4+CuJ74nY8z5WVz?=
 =?iso-8859-1?Q?UiUFC7Ay1Zh9Hbqvh0Eef55bErj8j7RBF1vsgCXYFb2asa/ocTDwv+beYg?=
 =?iso-8859-1?Q?Yp4NiqVd9EjtBbeN4kn+n/GLhrCjN5Fmhffu92QZTiCcCCXEdsi7J2srXa?=
 =?iso-8859-1?Q?PE/s0XYAI4K8oTB0ywF/WI6R2eYr7jJrKyxFJVbmycl/Zw+4muhGwWVAh3?=
 =?iso-8859-1?Q?h+XZ07mAcz+AXtH5YQbQeB9ajmPzk7JTeDxqWVQn3bvSMHcZmN/yathFae?=
 =?iso-8859-1?Q?m8SyAGg9dfOJ1rVY37lb7U4UU77CEoxlpdy2o/zE5WjFcV1FZihClmKG8s?=
 =?iso-8859-1?Q?7rkuz5Bpv9bqHJuvBfguUVYVnsEZUhP+FU0Uia2qba4eQsWXGYPxDyGSxA?=
 =?iso-8859-1?Q?XFYWMX2bN8Vr/IwtiWhYQ+hshxamh4uaEW/WBrHLjr2I39VqoR7Lhg9uZA?=
 =?iso-8859-1?Q?8g3wtrjMeZyjBuWbHGvTVVLknzaat9JSUZgTX+oV9psXNJ9K2zMV9WlggP?=
 =?iso-8859-1?Q?dGByD1ey3UwKUhSslhxaflgbdhoc95SRDSn+dqcqi4uY+wrKwKUUjfDs6P?=
 =?iso-8859-1?Q?AR43+zzMCUTwTCmPhmA9itsCHsfnVh8cplXOP7DVuUo9iySqjqybdZ1vru?=
 =?iso-8859-1?Q?1EFC6jgmZaCsjqJwsyC6fqe8d4Z6cAjw66GIZQWpdw3BmL0/Ulb+wGSoHo?=
 =?iso-8859-1?Q?hjUPevxggRPOm7ZyHWYD3GMcVJ+UHFwrJ4NKe74eObaqk/U1zj3rJvsCH7?=
 =?iso-8859-1?Q?Wg8YJsXrxZhrw6AW/aQKZF47D84JyFaATj7s5tb+sIdS265vncVMWgpDtj?=
 =?iso-8859-1?Q?oDK4R6gzVOSqaVs+n5B3Z3oJ0/Ui61P7arOjRx78pKYIxzbhfYsPxDjMfy?=
 =?iso-8859-1?Q?IDFB14h8yUvtw4I04/mqTvxH1G0SDEgWiDN3t2HFZduwbOqxH2IYPiU6Pi?=
 =?iso-8859-1?Q?U0wQGXEhG2Z/aKCELu77Hva7YtS5FT/4GHjoljwZAtMWuWUwT8WIQ6Jxfr?=
 =?iso-8859-1?Q?HNptogo6N7y0f2rjjAXdXyQm73QC+06/QyQ7u5VhDBNce/j8PfRmm2omXL?=
 =?iso-8859-1?Q?9f6FbMg+YEgWbpPtKHJCRjr/QTufUFO3jwaDuo0Io=3D?=
MIME-Version: 1.0
X-OriginatorOrg: sct-15-20-4755-11-msonline-outlook-1ff67.templateTenant
X-MS-Exchange-CrossTenant-AuthAs: Internal
X-MS-Exchange-CrossTenant-AuthSource: DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM
X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000
X-MS-Exchange-CrossTenant-Network-Message-Id: 0448d739-98bd-4dcb-4486-08dd6c37da97
X-MS-Exchange-CrossTenant-originalarrivaltime: 26 Mar 2025 07:28:50.2798 (UTC)
X-MS-Exchange-CrossTenant-fromentityheader: Hosted
X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa
X-MS-Exchange-CrossTenant-rms-persistedconsumerorg: 00000000-0000-0000-0000-000000000000
X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN0P223MB1255
Subject: Re: [FFmpeg-devel] [PATCH] FFMPEG: add graph reconfig capability
X-BeenThere: ffmpeg-devel@ffmpeg.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: FFmpeg development discussions and patches <ffmpeg-devel.ffmpeg.org>
List-Unsubscribe: <https://ffmpeg.org/mailman/options/ffmpeg-devel>,
 <mailto:ffmpeg-devel-request@ffmpeg.org?subject=unsubscribe>
List-Archive: <https://ffmpeg.org/pipermail/ffmpeg-devel>
List-Post: <mailto:ffmpeg-devel@ffmpeg.org>
List-Help: <mailto:ffmpeg-devel-request@ffmpeg.org?subject=help>
List-Subscribe: <https://ffmpeg.org/mailman/listinfo/ffmpeg-devel>,
 <mailto:ffmpeg-devel-request@ffmpeg.org?subject=subscribe>
Reply-To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
Cc: "269032741@qq.com" <269032741@qq.com>
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Errors-To: ffmpeg-devel-bounces@ffmpeg.org
Sender: "ffmpeg-devel" <ffmpeg-devel-bounces@ffmpeg.org>
Archived-At: <https://master.gitmailbox.com/ffmpegdev/DM8P223MB0365C7C4D8966D4F27A8F77ABAA62@DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM/>
List-Archive: <https://master.gitmailbox.com/ffmpegdev/>
List-Post: <mailto:ffmpegdev@gitmailbox.com>



> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> yangyalei050 via ffmpeg-devel
> Sent: Dienstag, 25. M=E4rz 2025 12:25
> To: ffmpeg-devel@ffmpeg.org
> Cc: 269032741@qq.com
> Subject: [FFmpeg-devel] [PATCH] FFMPEG: add graph reconfig capability
> =

> From: yangyalei <269032741@qq.com>
> =

> 1. Support reuse the graph to play different audio.
> 2. Support config part of the graph.
> =

> Signed-off-by: yangyalei <269032741@qq.com>
> ---
>  libavfilter/avfilter.c      |   8 +-
>  libavfilter/avfiltergraph.c | 201 ++++++++++++++++++++++++++++++++----
>  2 files changed, 187 insertions(+), 22 deletions(-)
> =

> diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
> index e732556ffa..71396674fe 100644
> --- a/libavfilter/avfilter.c
> +++ b/libavfilter/avfilter.c
> @@ -345,7 +345,8 @@ int ff_filter_config_links(AVFilterContext *filter)
>          FilterLinkInternal *li =3D ff_link_internal(link);
>          FilterLinkInternal *li_in;
> =

> -        if (!link) continue;
> +        if (!link || !link->incfg.formats || !link->outcfg.formats)
> +            continue;
>          if (!link->src || !link->dst) {
>              av_log(filter, AV_LOG_ERROR,
>                     "Not all input and output are properly linked
> (%d).\n", i);
> @@ -359,6 +360,11 @@ int ff_filter_config_links(AVFilterContext *filter)
> =

>          switch (li->init_state) {
>          case AVLINK_INIT:
> +            /* for part graph re-negotiation.
> +             * For example: output-filter link has config_props,
> +             * but the input-filter still need config_props. */
> +            if ((ret =3D ff_filter_config_links(link->src)) < 0)
> +                return ret;
>              continue;
>          case AVLINK_STARTINIT:
>              av_log(filter, AV_LOG_INFO, "circular filter chain
> detected\n");
> diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
> index 5e93f93aab..8565fe6a24 100644
> --- a/libavfilter/avfiltergraph.c
> +++ b/libavfilter/avfiltergraph.c
> @@ -23,6 +23,7 @@
>  #include "config.h"
> =

>  #include <string.h>
> +#include <stdbool.h>
> =

>  #include "libavutil/avassert.h"
>  #include "libavutil/bprint.h"
> @@ -348,7 +349,7 @@ static int filter_query_formats(AVFilterContext
> *ctx)
> =

>      if (filter->formats_state =3D=3D FF_FILTER_FORMATS_QUERY_FUNC) {
>          if ((ret =3D filter->formats.query_func(ctx)) < 0) {
> -            if (ret !=3D AVERROR(EAGAIN))
> +            if (ret !=3D AVERROR(EAGAIN) && ret !=3D FFERROR_NOT_READY)
>                  av_log(ctx, AV_LOG_ERROR, "Query format failed for
> '%s': %s\n",
>                         ctx->name, av_err2str(ret));
>              return ret;
> @@ -390,7 +391,7 @@ static int filter_query_formats(AVFilterContext
> *ctx)
>          av_freep(&cfg_in_dyn);
>          av_freep(&cfg_out_dyn);
>          if (ret < 0) {
> -            if (ret !=3D AVERROR(EAGAIN))
> +            if (ret !=3D AVERROR(EAGAIN) && ret !=3D FFERROR_NOT_READY)
>                  av_log(ctx, AV_LOG_ERROR, "Query format failed for
> '%s': %s\n",
>                         ctx->name, av_err2str(ret));
>              return ret;
> @@ -438,6 +439,81 @@ static int formats_declared(AVFilterContext *f)
>      return 1;
>  }
> =

> +static void ff_avfilter_link_unref_formats(AVFilterLink *link)
> +{
> +    ff_formats_unref(&link->incfg.formats);
> +    ff_formats_unref(&link->outcfg.formats);
> +    ff_formats_unref(&link->incfg.samplerates);
> +    ff_formats_unref(&link->outcfg.samplerates);
> +    ff_channel_layouts_unref(&link->incfg.channel_layouts);
> +    ff_channel_layouts_unref(&link->outcfg.channel_layouts);

What about color_spaces and color_ranges?
Below you are removing the unref for those, but you don't add them here or =
elsewhere again.



> +}
> +
> +static bool formats_useless(AVFilterContext *f)
> +{
> +    bool in, out;
> +    int i;
> +
> +    if (!f->nb_inputs || !f->nb_outputs)
> +        return false;
> +
> +    in =3D out =3D true;
> +
> +    for (i =3D 0; i < f->nb_inputs; i++)
> +        if (f->inputs[i]->outcfg.formats) {
> +            in =3D false;
> +            break;
> +        }
> +
> +    for (i =3D 0; i < f->nb_outputs; i++)
> +        if (f->outputs[i]->incfg.formats) {
> +            out =3D false;
> +            break;
> +        }
> +
> +    return in ^ out;
> +}
> +
> +
> +static bool sanitize_formats(AVFilterGraph *graph)
> +{
> +    AVFilterContext *f;
> +    bool changed =3D false;
> +    unsigned i, j;
> +
> +    for (i =3D 0; i < graph->nb_filters; i++) {
> +        f =3D graph->filters[i];
> +
> +        for (j =3D 0; j < f->nb_inputs; j++) {
> +            if ((!f->inputs[j]->outcfg.formats && f->inputs[j]-
> >incfg.formats)
> +                 || (f->inputs[j]->outcfg.formats && !f->inputs[j]-
> >incfg.formats)) {
> +                ff_avfilter_link_unref_formats(f->inputs[j]);
> +                changed =3D true;
> +            }
> +        }
> +
> +        for (j =3D 0; j < f->nb_outputs; j++) {
> +            if ((!f->outputs[j]->incfg.formats && f->outputs[j]-
> >outcfg.formats)
> +                || (f->outputs[j]->incfg.formats && !f->outputs[j]-
> >outcfg.formats)) {
> +                ff_avfilter_link_unref_formats(f->outputs[j]);
> +                changed =3D true;
> +            }
> +        }
> +
> +        if (formats_useless(f)) {
> +            for (j =3D 0; j < f->nb_inputs; j++)
> +                ff_avfilter_link_unref_formats(f->inputs[j]);
> +
> +            for (j =3D 0; j < f->nb_outputs; j++)
> +                ff_avfilter_link_unref_formats(f->outputs[j]);
> +
> +            changed =3D true;
> +        }
> +    }
> +
> +    return changed;
> +}
> +
>  /**
>   * Perform one round of query_formats() and merging formats lists on
> the
>   * filter graph.
> @@ -462,7 +538,7 @@ static int query_formats(AVFilterGraph *graph, void
> *log_ctx)
>          if (formats_declared(f))
>              continue;
>          ret =3D filter_query_formats(f);
> -        if (ret < 0 && ret !=3D AVERROR(EAGAIN))
> +        if (ret < 0 && ret !=3D AVERROR(EAGAIN) && ret !=3D
> FFERROR_NOT_READY)
>              return ret;
>          /* note: EAGAIN could indicate a partial success, not counted
> yet */
>          count_queried +=3D ret >=3D 0;
> @@ -478,7 +554,7 @@ static int query_formats(AVFilterGraph *graph, void
> *log_ctx)
>              unsigned neg_step;
>              int convert_needed =3D 0;
> =

> -            if (!link)
> +            if (!link || !link->incfg.formats)
>                  continue;
> =

>              neg =3D ff_filter_get_negotiation(link);
> @@ -492,6 +568,7 @@ static int query_formats(AVFilterGraph *graph, void
> *log_ctx)
>                      break;
>                  }
>              }
> +
>              for (neg_step =3D 0; neg_step < neg->nb_mergers; neg_step++)
> {
>                  const AVFilterFormatsMerger *m =3D &neg-
> >mergers[neg_step];
>                  void *a =3D FF_FIELD_AT(void *, m->offset, link->incfg);
> @@ -789,17 +866,6 @@ static int pick_format(AVFilterLink *link,
> AVFilterLink *ref)
>              return ret;
>      }
> =

> -    ff_formats_unref(&link->incfg.formats);
> -    ff_formats_unref(&link->outcfg.formats);
> -    ff_formats_unref(&link->incfg.samplerates);
> -    ff_formats_unref(&link->outcfg.samplerates);
> -    ff_channel_layouts_unref(&link->incfg.channel_layouts);
> -    ff_channel_layouts_unref(&link->outcfg.channel_layouts);
> -    ff_formats_unref(&link->incfg.color_spaces);
> -    ff_formats_unref(&link->outcfg.color_spaces);
> -    ff_formats_unref(&link->incfg.color_ranges);
> -    ff_formats_unref(&link->outcfg.color_ranges);

The latter 4 are removed without replacement.


>      return 0;
>  }
> =

> @@ -818,6 +884,7 @@ do {
> \
>              list_type *fmts;
> \
> =

> \
>              if (link->type !=3D out_link->type ||
> \
> +                !out_link->incfg.list ||
> \
>                  out_link->incfg.list->nb =3D=3D 1)
> \
>                  continue;
> \
>              fmts =3D out_link->incfg.list;
> \
> @@ -925,6 +992,7 @@ static void
> swap_samplerates_on_filter(AVFilterContext *filter)
>          link =3D filter->inputs[i];
> =

>          if (link->type =3D=3D AVMEDIA_TYPE_AUDIO &&
> +            link->outcfg.samplerates &&
>              link->outcfg.samplerates->nb_formats=3D=3D 1)
>              break;
>      }
> @@ -938,6 +1006,7 @@ static void
> swap_samplerates_on_filter(AVFilterContext *filter)
>          int best_idx, best_diff =3D INT_MAX;
> =

>          if (outlink->type !=3D AVMEDIA_TYPE_AUDIO ||
> +            !outlink->incfg.samplerates ||
>              outlink->incfg.samplerates->nb_formats < 2)
>              continue;
> =

> @@ -1007,6 +1076,7 @@ static void
> swap_channel_layouts_on_filter(AVFilterContext *filter)
>          link =3D filter->inputs[i];
> =

>          if (link->type =3D=3D AVMEDIA_TYPE_AUDIO &&
> +            link->outcfg.channel_layouts &&
>              link->outcfg.channel_layouts->nb_channel_layouts =3D=3D 1)
>              break;
>      }
> @@ -1018,6 +1088,7 @@ static void
> swap_channel_layouts_on_filter(AVFilterContext *filter)
>          int best_idx =3D -1, best_score =3D INT_MIN, best_count_diff =3D
> INT_MAX;
> =

>          if (outlink->type !=3D AVMEDIA_TYPE_AUDIO ||
> +            !outlink->incfg.channel_layouts ||
>              outlink->incfg.channel_layouts->nb_channel_layouts < 2)
>              continue;
> =

> @@ -1110,6 +1181,7 @@ static void
> swap_sample_fmts_on_filter(AVFilterContext *filter)
>          link =3D filter->inputs[i];
> =

>          if (link->type =3D=3D AVMEDIA_TYPE_AUDIO &&
> +            link->outcfg.formats &&
>              link->outcfg.formats->nb_formats =3D=3D 1)
>              break;
>      }
> @@ -1124,6 +1196,7 @@ static void
> swap_sample_fmts_on_filter(AVFilterContext *filter)
>          int best_idx =3D -1, best_score =3D INT_MIN;
> =

>          if (outlink->type !=3D AVMEDIA_TYPE_AUDIO ||
> +            !outlink->incfg.formats ||
>              outlink->incfg.formats->nb_formats < 2)
>              continue;
> =

> @@ -1180,7 +1253,8 @@ static int pick_formats(AVFilterGraph *graph)
>              AVFilterContext *filter =3D graph->filters[i];
>              if (filter->nb_inputs){
>                  for (j =3D 0; j < filter->nb_inputs; j++){
> -                    if (filter->inputs[j]->incfg.formats && filter-
> >inputs[j]->incfg.formats->nb_formats =3D=3D 1) {
> +                    if (filter->inputs[j]->format < 0 &&
> +                        filter->inputs[j]->incfg.formats && filter-
> >inputs[j]->incfg.formats->nb_formats =3D=3D 1) {
>                          if ((ret =3D pick_format(filter->inputs[j],
> NULL)) < 0)
>                              return ret;
>                          change =3D 1;
> @@ -1189,7 +1263,8 @@ static int pick_formats(AVFilterGraph *graph)
>              }
>              if (filter->nb_outputs){
>                  for (j =3D 0; j < filter->nb_outputs; j++){
> -                    if (filter->outputs[j]->incfg.formats && filter-
> >outputs[j]->incfg.formats->nb_formats =3D=3D 1) {
> +                    if (filter->outputs[j]->format < 0 &&
> +                        filter->outputs[j]->incfg.formats && filter-
> >outputs[j]->incfg.formats->nb_formats =3D=3D 1) {
>                          if ((ret =3D pick_format(filter->outputs[j],
> NULL)) < 0)
>                              return ret;
>                          change =3D 1;
> @@ -1198,7 +1273,7 @@ static int pick_formats(AVFilterGraph *graph)
>              }
>              if (filter->nb_inputs && filter->nb_outputs && filter-
> >inputs[0]->format>=3D0) {
>                  for (j =3D 0; j < filter->nb_outputs; j++) {
> -                    if (filter->outputs[j]->format<0) {
> +                    if (filter->outputs[j]->format < 0 && filter-
> >outputs[j]->incfg.formats) {
>                          if ((ret =3D pick_format(filter->outputs[j],
> filter->inputs[0])) < 0)
>                              return ret;
>                          change =3D 1;
> @@ -1234,6 +1309,8 @@ static int graph_config_formats(AVFilterGraph
> *graph, void *log_ctx)
>      if (ret < 0)
>          return ret;
> =

> +    while (sanitize_formats(graph));
> +
>      /* Once everything is merged, it's possible that we'll still have
>       * multiple valid media format choices. We try to minimize the
> amount
>       * of format conversion inside filters */
> @@ -1292,12 +1369,94 @@ static int graph_config_pointers(AVFilterGraph
> *graph, void *log_ctx)
>      return 0;
>  }
> =

> +static void graph_clear_formats(AVFilterGraph *graph, void *log_ctx)
> +{
> +    int status_in, status_out;
> +    AVRational time_base;
> +    AVFilterContext *f;
> +    FilterLinkInternal *ilinki;
> +    FilterLinkInternal *olinki;
> +    int i, j;
> +
> +    for (i =3D graph->nb_filters - 1; i >=3D 0; i--) {
> +        f =3D graph->filters[i];
> +
> +        if (!strncmp(f->name, "auto_", strlen("auto_"))) {
> +            ilinki =3D ff_link_internal(f->inputs[0]);
> +            olinki =3D ff_link_internal(f->outputs[0]);
> +            if (ilinki->status_out || ilinki->status_in ||
> +                olinki->status_out || olinki->status_in) {
> +                AVFilterContext *src =3D f->inputs[0]->src;
> +                AVFilterContext *dst =3D f->outputs[0]->dst;
> +                unsigned srcpad =3D FF_OUTLINK_IDX(f->inputs[0]);
> +                unsigned dstpad =3D FF_INLINK_IDX(f->outputs[0]);
> +
> +                status_in  =3D ilinki->status_in;
> +                status_out =3D ilinki->status_out;
> +                time_base  =3D f->inputs[0]->time_base;
> +
> +                avfilter_free(f);
> +                avfilter_link(src, srcpad, dst, dstpad);
> +
> +                olinki->status_in  =3D status_in;
> +                olinki->status_out =3D status_out;
> +                dst->inputs[0]->time_base  =3D time_base;
> +
> +                ff_filter_set_ready(dst, 200);
> +                continue;
> +            }
> +        }
> +
> +        for (j =3D 0; j < f->nb_inputs; j++) {
> +            ilinki =3D ff_link_internal(f->inputs[j]);
> +            if (ilinki->status_out) {
> +                ff_formats_unref(&f->inputs[j]->outcfg.formats);
> +                ff_formats_unref(&f->inputs[j]->outcfg.samplerates);
> +                ff_channel_layouts_unref(&f->inputs[j]-
> >outcfg.channel_layouts);
> +
> +                if (ilinki->status_in) {
> +                    f->inputs[j]->format         =3D -1;
> +                    f->inputs[j]->sample_rate    =3D 0;
> +                    ilinki->init_state     =3D AVLINK_UNINIT;
> +                    f->inputs[j]->time_base.num  =3D 0;
> +                    f->inputs[j]->time_base.den  =3D 0;
> +                    av_channel_layout_uninit(&f->inputs[j]->ch_layout);
> +                }
> +            }
> +        }
> +
> +        for (j =3D 0; j < f->nb_outputs; j++) {
> +            olinki =3D ff_link_internal(f->outputs[j]);
> +            if (olinki->status_in) {
> +                ff_formats_unref(&f->outputs[j]->incfg.formats);
> +                ff_formats_unref(&f->outputs[j]->incfg.samplerates);
> +                ff_channel_layouts_unref(&f->outputs[j]-
> >incfg.channel_layouts);
> +
> +                if (olinki->status_out) {
> +                    f->outputs[j]->format         =3D -1;
> +                    f->outputs[j]->sample_rate    =3D 0;
> +                    olinki->init_state     =3D AVLINK_UNINIT;
> +                    f->outputs[j]->time_base.num  =3D 0;
> +                    f->outputs[j]->time_base.den  =3D 0;
> +                    av_channel_layout_uninit(&f->outputs[j]-
> >ch_layout);
> +                }

The code above is executed for audio and video filters but it seems to be h=
andling audio filters only.


> +            }
> +        }
> +    }
> +}
> +
>  int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
>  {
> -    int ret;
> +    AVClass *avc =3D log_ctx ? *(AVClass **)log_ctx : NULL;
> +    int ret, i;
> =

> -    if ((ret =3D graph_check_validity(graphctx, log_ctx)))
> -        return ret;

This is the only usage of graph_check_validity(), so you would need to remo=
ve that function as well, explaining why it is no longer needed.


> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> yangyalei via ffmpeg-devel
> Sent: Mittwoch, 26. M=E4rz 2025 04:10
> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> Cc: yangyalei <269032741@qq.com>
> Subject: Re: [FFmpeg-devel] [PATCH] FFMPEG: add graph reconfig
> capability
> (abuff_src@Music)(abuff_src@Ring)---amix---abuff_sink
> =

> =

> In the graph above, We support three playback scenarios at the same
> time:
> =

> =

> 1. Only abuff_src@Music needs to be played, and abuff_src@Ring has no
> data. abuff_src@Ring is ignored during negotiation, "abuff_src@Music --
> amix -- abuff_sink" link negotiation is successful, and playback can be
> performed;
> =

> =

> 2. Only abuff_src@Ring needs to be played, and abuff_src@Music has no
> data. abuff_src@Music is ignored during negotiation, "abuff_src@ring --
> &gt; amix --&gt; abuff_sink" link negotiation is successful, and
> playback can be performed;
> =

> =

> 3. Both abuff_src@Music and abuff_src@Ring need to be played, and all
> filters are negotiated successfully and mixed playback is performed.


Is this case about the ffmpeg CLI tool or are you using libavfilter directl=
y?

In the latter case: Why don't you just remove the source filter which has n=
o data, what's the purpose of keeping a filter without data flow in the gra=
ph?

Your patch enables a filter to remain in the graph without having any forma=
ts negotiated but is still connected to other filters. What's not quite cle=
ar to me: How can this work in your example with the amix filter?
If the amix filter has two connected inputs but one of those inputs does no=
t deliver any data, I would expect that the graph processing gets stuck at =
the amix filter input where it is waiting for data from the second input, i=
sn't that the case?

Thanks
sw





_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".