[FFmpeg-devel] [RFC] FFmpeg Execution Graph Visualization
softworkz .
softworkz at hotmail.com
Sat Apr 12 04:25:32 EEST 2025
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces at ffmpeg.org> On Behalf Of
> Nicolas George
> Sent: Freitag, 11. April 2025 19:09
> To: FFmpeg development discussions and patches <ffmpeg-devel at ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [RFC] FFmpeg Execution Graph Visualization
>
> Michael Niedermayer (HE12025-03-29):
> > can you repost the AVWriter patches ?
>
> Sure, but I need to find the latest branch, and it is proving a cause of
> procrastination for me. In the meantime, let me explain anew the
> principles behind it, after a few years I might be able to express them
> better.
>
> (I hope it means you are considering re-asserting your authority to
> approve it on principle pending review of the code. I will not invest
> more coding into it unless I know nobody has the authority to put it to
> waste with “it does not belong”.)
>
>
> 1. Why we need it
>
> We use a lot of text for small things. As a command-line tool, we use
> text to communicate with users. Even as a library, when GUIs do not have
> the proper widget they will use text, and we need to provide the
> necessary support functions.
>
> We should have a rule that for every type we add, we must have a
> corresponding to-text API function. Furthermore, these functions should
> all have the same type (up to the type of the opaque pointer), so that
> we can store them in a structure that describes the type along with
> other information (from string, ref/unref, etc.).
>
> We also need text for inter-process communication, like exporting
> statistics from filters.
>
> Some of these to-text conversions happen once per frame. That means they
> should happen without dynamic allocation. Quite complex code is
> warranted to prevent dynamic allocations once per frame: see the frame
> and buffer pools too. But some of these to-text conversion have an
> unbounded output. That means the API needs to be able to handle long
> output.
>
> BPrint meets the criteria: BPrint is as fast as a buffer on the stack
> but can handle strings of arbitrary length.
>
> Unfortunately, BPrint is ugly. The name is ugly, and more importantly,
> it is inflexible, it works only with flat buffers in memory.
>
>
> 2. How AVWriter does it
>
> AVWriter is an attempt — successful, in my opinion — at keeping what is
> good in BPrint and fixing what is ugly, in particular by giving it
> features similar to AVIO.
>
> The design principle is the same as AVIO: a structure with callbacks
> that perform the low-level operations.
>
> The difference with AVIO is that effort were made to keep the structures
> small and allocatable by the caller.
>
> Also, the back-end is allowed to provide only a few methods: printf-like
> or write-like or get_buffer-like, and the framework will make sure to
> use one that is available. That means quite a bit of code to handle
> doing a printf() on a back-end that only has get_buffer, but it is code
> isolated within a single file and with ample FATE coverage.
>
> One of the tricks I used to avoid dynamic allocations is to store the
> structure of methods and the structure with an instance as a structure
> with two pointer elements passed by value.
>
> Another trick I used to avoid dynamic allocations is to store the size
> of a structure in it. That way, if a caller is compiled with an old
> version of the library, it stores a smaller size than the current one,
> and the new version of the library can test and avoid accessing the new
> fields. That lets the caller allocate the structure while keeping the
> ability to add fields to the structure.
>
> Apart from that, is is rather straightforward. The default AVWriter is a
> simple wrapper around BPrint, but there are also quite a few other
> built-in ones: wrapper around stdio and av_log (without storing the
> whole string), wrapper around a fixed-size buffer. AVwriter can also act
> as a filter: get an AVWriter, you can create a new one that will encode
> to base64 or HTML entities on the fly.
>
>
> 3. Where it will go
>
> The trick passing a struct of methods and the object as a structure with
> two members passed by value is meant to become a very light-weight
> object system. Thus if ctx is a pointer to a structure of type T, we can
> define serialize_t as a structure with functions and consider
> { serialize_t, ctx } as an object of the class “serializable”. But we
> can also make it an object of the class “refcounted” by pairing it with
> another structure.
>
> The object system, including casts from one class to another, can be
> de-centralized, new classes ca be defined anywhere in the code without a
> central registry. That will be useful to enhance several parts of our
> code:
>
> - Side data would not need to be added in libavutil. A pair of
> demuxer-muxer in libavformat can define a new type of side data by
> defining the methods to handle it.
>
> - Filters with unusual parsing needs can define a new type of option and
> plug it into the standard options parsing system. It is extremely
> useful if the needs of the filter are too specific to add a type in
> libavutil but too far from something existing to be able to use it
> conveniently.
>
> - Pluging new types into the options system will automatically fix our
> “escaping hell” issue where users sometimes need 42 levels of \ in
> front of a : to achieve their goals.
>
> - We can implement a full-featured av_printf() function that serializes
> on the fly:
>
> av_printf(out, "Stream %d at %d Hz, %@ with layout %@\n",
> st->id, st->sample_rate,
> avany_sample_fmt(st->sample_fmt),
> avany_layout(st->channel_layout));
>
> With this, it becomes possible to implement new features that rely a lot
> on text. That includes:
>
> - Better error reporting. Instead the error message going to the log,
> where nobody will see it if it is a GUI, instead of the application
> having to install a log handler, with the responsibility to assemble
> lines together and filter out unrelated messages that just happened to
> arrive at the same time, the error message is stored in the relevant
> context and can be retrieved cleanly later.
>
> - Built-in comprehensive documentation. You can do
> av_get_documentation(ctx, …) and get explanations on how to use it.
> Depending on the flags given, the returned documentation can be terse
> and suitable for a tooltip or comprehensive including hyperlinks and
> reference for the syntax of the options.
>
> - Serialization of high-level data structures into various standard
> formats: JSON, XML, etc., precisely what started this thread. That
> allows to factor the writers in ffprobe and that gives us means to
> exfiltrate statistics from filters.
>
>
> 4. Why it must be in FFmpeg
>
> I acknowledge that nothing I described is even remotely specific to
> FFmpeg. I could be arguing for AVWriter, a light-weight object system,
> built-in documentation, etc., in a project that does something entirely
> else.
>
> That means in principle all this could go into a separate library, and
> some people have argued for it. In principle it could, but in practice
> it does not make sense for multiple reasons, but the main reason is
> this:
>
> As a matter of principle, we do not demand that users install
> third-parties libraries in order to build FFmpeg. We rely on system
> libraries, and we can rely on external libraries for optional features,
> even very important ones (x264…), but if something is needed to run
> FFmpeg at all then it must be in our own code base so that building from
> sources will just work. Strings and error reporting cannot be optional,
> they must be in FFmpeg.
>
>
> I will come back later with the code as it was last time.
>
> Regards,
>
> --
> Nicolas George
> _______________________________________________
HI Nicolas,
> - Serialization of high-level data structures into various standard
> formats: JSON, XML, etc., precisely what started this thread. That
> allows to factor the writers in ffprobe and that gives us means to
> exfiltrate statistics from filters.
just FYI - there aren't any writers in FFprobe anymore. Formatting and output are separate things now.
I had asked you about the AVWriter code - even before Michael did - out of interest, for checking out how much the implementation might benefit from AVWriter because I can remind just some fragments about it.
I don't even remember the "object system" aspect - which I find even more interesting, yet the presentation is a bit confusing. I believe that treating them as two separate things would make it a better and easier sell.
I'm still not sure about the relation between AVWriter and "object-system". Is it that AVWriter is implemented according to that "object-system" proposal, i.e. being like all "objects" are supposed to be implemented in the future?
Or is AVWriter just using the same technique in a similar way but for a different purpose?
I notice how much frustration this subject appears to have caused for you, but you should not project that frustration on the wrong targets.
Like I said before - I don't want to cut you off from the work in the area of text formatting and writing and you are welcome to collaborate - if you want that.
Weirdly enough, I like many of the examples you are giving above. I can say that because I'm not cultivating my own frustrations. If you'd only manage to pretend being a friendly person, that should already suffice to make some good progress. Seriously.
Best,
sw
More information about the ffmpeg-devel
mailing list