From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id D8E304982D for ; Sat, 20 Apr 2024 12:19:56 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 36D0B68D216; Sat, 20 Apr 2024 15:19:55 +0300 (EEST) Received: from b-painless.mh.aa.net.uk (unknown [81.187.30.52]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 557C568ABD7 for ; Sat, 20 Apr 2024 15:19:48 +0300 (EEST) Received: from 0.b.4.b.7.4.0.8.c.4.a.5.d.8.b.2.0.5.8.0.9.1.8.0.0.b.8.0.1.0.0.2.ip6.arpa ([2001:8b0:819:850:2b8d:5a4c:8047:b4b0] helo=andrews-2024-laptop.lan) by painless-b.tch.aa.net.uk with esmtp (Exim 4.96) (envelope-from ) id 1ry9h5-004Qdg-2L; Sat, 20 Apr 2024 13:19:47 +0100 From: Andrew Sayers To: ffmpeg-devel@ffmpeg.org Date: Sat, 20 Apr 2024 13:19:41 +0100 Message-ID: <20240420121943.201032-1-ffmpeg-devel@pileofstuff.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 1/3] doc: Explain what "context" means 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 Cc: Andrew Sayers Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: Based largely on the explanation by Stefano Sabatini: https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325854.html --- doc/jargon.md | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 doc/jargon.md diff --git a/doc/jargon.md b/doc/jargon.md new file mode 100644 index 0000000000..f967b5c8bc --- /dev/null +++ b/doc/jargon.md @@ -0,0 +1,169 @@ +# Jargon + +Terms used throughout the code that developers may need to know. + +@anchor context + +## Context + +A design pattern that stores the context (e.g. configuration) for a series +of operations in a "context" structure, and moves other information with +a longer or shorter lifetime elsewhere. + +Consider a code snippet to modify text then print it: + +```c +/** + * Contextual information about printing a series of messages + */ +struct ModifyThenPrintContext { + + /** + * Members of the context usually are usually part of its public API... + */ + FILE *out; + + /** + * ... but check the documentation just in case + */ + [[deprecated]] + int no_longer_part_of_the_public_api; + + /** + * The "internal context" is private to the context itself. + * + * Unlike the members above, the private context is not guaranteed + * and can change arbitrarily between versions. + */ + void* priv_data; +}; + +/** + * Long-lifetime information, reused by many contexts + */ +enum ModifyThenPrintDialect { + MODIFY_THEN_PRINT_PLAIN_TEXT, + MODIFY_THEN_PRINT_REGEX, + MODIFY_THEN_PRINT_REGEX_PCRE +}; + +/** + * Short-lifetime information, used repeatedly in a single context + */ +struct ModifyThenPrintMessage { + char *str; + char *replace_this; + char *with_this; +}; + +/** + * Allocate and initialize a ModifyThenPrintContext + * + * This creates a new pointer, then fills in some sensible defaults. + * + * We can reasonably assume this function will initialise `priv_data` + * with a dialect-specific object, but shouldn't make any assumptions + * about what that object is. + * + */ +int ModifyThenPrintContext_alloc_context(struct ModifyThenPrintContext **ctx, + FILE *out, + enum ModifyThenPrintDialect dialect); + +/** + * Uninitialize and deallocate a ModifyThenPrintContext + * + * This does any work required by the private context in `priv_data` + * (e.g. deallocating it), then deallocates the main context itself. + * + */ +int ModifyThenPrintContext_free(struct ModifyThenPrintContext *ctx); + +/** + * Print a single message + */ +int ModifyThenPrintContext_print(struct ModifyThenPrintContext *ctx, + struct ModifyThenPrintMessage *msg); + +int print_hello_world() +{ + + int ret = 0; + + struct ModifyThenPrintContext *ctx; + + struct ModifyThenPrintMessage hello_world; + + if ( ModifyThenPrintContext_alloc_context( &ctx, stdout, MODIFY_THEN_PRINT_REGEX ) < 0 ) { + ret = -1; + goto EXIT_WITHOUT_CLEANUP; + } + + hello_world.replace_this = "Hi|Hullo"; + hello_world.with_this = "Hello"; + + hello_world.str = "Hi, world!\n"; + if ( ModifyThenPrintContext_print( ctx, &hello_world ) < 0 ) { + ret = -1; + goto FINISH; + } + + hello_world.str = "Hullo, world!\n"; + if ( ModifyThenPrintContext_print( ctx, &hello_world ) < 0 ) { + ret = -1; + goto FINISH; + } + + FINISH: + if ( ModifyThenPrintContext_free( ctx ) ) { + ret = -1; + goto EXIT_WITHOUT_CLEANUP; + } + + EXIT_WITHOUT_CLEANUP: + return ret; + +} +``` + +In the example above, the `ModifyThenPrintContext` object contains information +that's needed for exactly the lifetime of the current job (i.e. how to modify +and where to print). Information with a longer or shorter lifetime is moved +to `ModifyThenPrintDialect` and `ModifyThenPrintMessage`. + +FFmpeg uses the context pattern to solve a variety of problems. But the most +common contexts (AVCodecContext, AVFormatContext etc.) tend to have a lot of +requirements in common: + +- need to query, set and get options + - including options whose implementation is not part of the public API +- need to configure log message verbosity and content + +FFmpeg gradually converged on the AVClass struct to store that information, +then converged on the @ref avoptions "AVOptions" system to manipulate it. +So the terms "context", "AVClass context structure" and "AVOptions-enabled +struct" are often used interchangeably when it's not important to emphasise +the difference. But for example, AVMediaCodecContext uses the context +pattern, but is not an AVClass context structure, so cannot be manipulated +with AVOptions. + +To understand AVClass context structures, consider the `libx264` encoder: + +- it has to support common encoder options like "bitrate" +- it has to support encoder-specific options like "profile" + - the exact options could change quickly if a legal ruling forces a change of backend +- it has to provide useful feedback about unsupported options + +Common encoder options like "bitrate" are stored in the AVCodecContext class, +while encoder-specific options like "profile" are stored in an X264Context +instance in AVCodecContext::priv_data. These options are then exposed through +a tree of AVOption objects, which include user-visible help text and +machine-readable information about the memory location to read/write +each option. Common @ref avoptions "AVOptions" functionality lets end users +get and set those values, and provides readable feedback about errors. But +even though they can be manipulated through an API, the X264Context class is +private and new releases can modify it without affecting the public interface. + +FFmpeg itself uses the context design pattern to solve many problems. +You can use this pattern anywhere it would be useful, and may want to use +AVClass and @ref avoptions "AVOptions" if they're relevant to your situation. -- 2.43.0 _______________________________________________ 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".