Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means
@ 2024-04-18 15:06 Andrew Sayers
  2024-04-18 15:06 ` [FFmpeg-devel] [PATCH 2/3] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
                   ` (4 more replies)
  0 siblings, 5 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-04-18 15:06 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Based largely on the explanation by Stefano Sabatini:
https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325854.html
---
 doc/jargon.md | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)
 create mode 100644 doc/jargon.md

diff --git a/doc/jargon.md b/doc/jargon.md
new file mode 100644
index 0000000000..3b78ffb61f
--- /dev/null
+++ b/doc/jargon.md
@@ -0,0 +1,96 @@
+# 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 elsewhere.
+
+Consider a trivial program to print uppercase text:
+
+```c
+/*
+ * Contextual information about where to print a series of messages
+ */
+struct UpperCasePrinterContext {
+    FILE* out;
+};
+
+/*
+ * Extra information about messages to print.
+ * This could be used multiple times in a single context,
+ * or reused several times across multiple contexts.
+ */
+struct PrintInfo {
+    char* str;
+};
+
+void print(
+    struct UpperCasePrinterContext * ctx,
+    struct PrintInfo * info
+) {
+    for ( char* c = info->str; *c; ++c ) {
+        char C = toupper(*c);
+        fwrite( &C, 1, 1, ctx->out );
+    }
+}
+
+int main()
+{
+    struct PrintInfo hello, world;
+    struct UpperCasePrinterContext ctx;
+
+    hello.str = "hello, ";
+    world.str = "world!\n";
+
+    ctx.out = stdout;
+
+    print( &ctx, &hello );
+    print( &ctx, &world );
+
+    return 0;
+}
+```
+
+The `UpperCasePrinterContext` object contains the information that's about
+the context of the current job (i.e. printing things to standard output).
+Information with a lifetime different than that of the context is moved
+to the `PrintInfo` object.
+
+FFmpeg's main context structures all happen to face some common problems:
+
+- querying, setting and getting options
+- handling "private" internal context, including options for
+  a particular instance of the generic context
+- configuring log message verbosity and content
+
+FFmpeg gradually converged on the AVClass struct to store this information,
+then converged on the @ref avoptions "AVOptions" system to manipulate it,
+so modern code often uses the terms "context", "AVClass context structure"
+and "AVOptions-enabled struct" interchangeably.  But it is occasionally
+necessary to distinguish between them - for example, AVMediaCodecContext
+is a context that does not use AVClass.
+
+To understand how this all works, consider some requirements for the
+`libx264` encoder:
+
+- it has to support common encoder options like "bitrate"
+- it has to support encoder-specific options like "profile"
+- 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 to
+users 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 you get
+and set those values, and provides readable feedback about errors.  Although
+X264Context can be set by users, it is not part of the public interface,
+so new releases can modify it without affecting the API version.
+
+FFmpeg itself uses context structures to handle FFmpeg-specific problems,
+but the design pattern, as well as the AVClass and @ref avoptions "AVOptions"
+implementations, are general solutions you can use for any purpose.
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH 2/3] lavu: Clarify relationship between AVClass, AVOption and context
  2024-04-18 15:06 [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means Andrew Sayers
@ 2024-04-18 15:06 ` Andrew Sayers
  2024-04-18 15:06 ` [FFmpeg-devel] [PATCH 3/3] all: Link to "context" from all contexts with documentation Andrew Sayers
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-04-18 15:06 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

---
 libavutil/log.h | 11 ++++++++---
 libavutil/opt.h |  7 ++++---
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/libavutil/log.h b/libavutil/log.h
index ab7ceabe22..b5c739dab1 100644
--- a/libavutil/log.h
+++ b/libavutil/log.h
@@ -59,9 +59,14 @@ typedef enum {
 struct AVOptionRanges;
 
 /**
- * Describe the class of an AVClass context structure. That is an
- * arbitrary struct of which the first field is a pointer to an
- * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.).
+ * Metadata about an arbitrary data structure
+ *
+ * A @ref context "context struct" whose first member is a pointer
+ * to an AVClass object is called an "AVClass context structure"
+ * (e.g. AVCodecContext, AVFormatContext etc.).
+ *
+ * AVClass is often combined with @ref avoptions "AVOptions" to create
+ * "AVOptions-enabled structs" that can be easily configured by users.
  */
 typedef struct AVClass {
     /**
diff --git a/libavutil/opt.h b/libavutil/opt.h
index e6013662f6..b817d15554 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -39,9 +39,10 @@
  * @defgroup avoptions AVOptions
  * @ingroup lavu_data
  * @{
- * AVOptions provide a generic system to declare options on arbitrary structs
- * ("objects"). An option can have a help text, a type and a range of possible
- * values. Options may then be enumerated, read and written to.
+ * Builds on AVClass, adding a generic system to declare options.
+ *
+ * An option can have a help text, a type and a range of possible values.
+ * Options may then be enumerated, read and written to.
  *
  * There are two modes of access to members of AVOption and its child structs.
  * One is called 'native access', and refers to access from the code that
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH 3/3] all: Link to "context" from all contexts with documentation
  2024-04-18 15:06 [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means Andrew Sayers
  2024-04-18 15:06 ` [FFmpeg-devel] [PATCH 2/3] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
@ 2024-04-18 15:06 ` Andrew Sayers
  2024-04-20  7:25 ` [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means Stefano Sabatini
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-04-18 15:06 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Some headings needed to be rewritten to accomodate the text,
(hopefully) without changing the meaning.
---
 libavcodec/aacdec.h              |  2 +-
 libavcodec/aacenc.h              |  2 +-
 libavcodec/ac3enc.h              |  2 +-
 libavcodec/amfenc.h              |  2 +-
 libavcodec/atrac.h               |  2 +-
 libavcodec/avcodec.h             |  3 ++-
 libavcodec/bsf.h                 |  2 +-
 libavcodec/d3d11va.h             |  3 +--
 libavcodec/mediacodec.h          |  2 +-
 libavcodec/qsv.h                 |  6 ++++--
 libavcodec/sbr.h                 |  2 +-
 libavcodec/vdpau.h               |  3 ++-
 libavcodec/videotoolbox.h        |  5 +++--
 libavfilter/avfilter.h           |  2 +-
 libavformat/avformat.h           |  3 ++-
 libavformat/avio.h               |  3 ++-
 libavutil/hwcontext.h            | 21 ++++++++++++---------
 libavutil/hwcontext_cuda.h       |  2 +-
 libavutil/hwcontext_d3d11va.h    |  4 ++--
 libavutil/hwcontext_d3d12va.h    |  6 +++---
 libavutil/hwcontext_drm.h        |  2 +-
 libavutil/hwcontext_dxva2.h      |  4 ++--
 libavutil/hwcontext_mediacodec.h |  2 +-
 libavutil/hwcontext_opencl.h     |  4 ++--
 libavutil/hwcontext_qsv.h        |  4 ++--
 libavutil/hwcontext_vaapi.h      |  6 +++---
 libavutil/hwcontext_vdpau.h      |  2 +-
 libavutil/hwcontext_vulkan.h     |  4 ++--
 28 files changed, 57 insertions(+), 48 deletions(-)

diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 1b245f9258..3a5317cd54 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -181,7 +181,7 @@ typedef struct DynamicRangeControl {
 } DynamicRangeControl;
 
 /**
- * main AAC decoding context
+ * main AAC decoding @ref context "context"
  */
 typedef struct AACDecContext {
     const struct AVClass  *class;
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index 8899f90ac7..c91f99bc6c 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -193,7 +193,7 @@ typedef struct AACPCEInfo {
 } AACPCEInfo;
 
 /**
- * AAC encoder context
+ * AAC encoder @ref context "context"
  */
 typedef struct AACEncContext {
     AVClass *av_class;
diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
index 227744d27f..68d8736f7a 100644
--- a/libavcodec/ac3enc.h
+++ b/libavcodec/ac3enc.h
@@ -151,7 +151,7 @@ typedef struct AC3Block {
 } AC3Block;
 
 /**
- * AC-3 encoder private context.
+ * AC-3 encoder private @ref context "context"
  */
 typedef struct AC3EncodeContext {
     AVClass *av_class;                      ///< AVClass used for AVOption
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
index 2dbd378ef8..71138e7f76 100644
--- a/libavcodec/amfenc.h
+++ b/libavcodec/amfenc.h
@@ -43,7 +43,7 @@ typedef struct AmfTraceWriter {
 } AmfTraceWriter;
 
 /**
-* AMF encoder context
+* AMF encoder @ref context "context"
 */
 
 typedef struct AmfContext {
diff --git a/libavcodec/atrac.h b/libavcodec/atrac.h
index 05208bbee6..acdd0a741a 100644
--- a/libavcodec/atrac.h
+++ b/libavcodec/atrac.h
@@ -39,7 +39,7 @@ typedef struct AtracGainInfo {
 } AtracGainInfo;
 
 /**
- *  Gain compensation context structure.
+ *  Gain compensation @ref context "context"
  */
 typedef struct AtracGCContext {
     float   gain_tab1[16];  ///< gain compensation level table
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 968009a192..a1f1430dde 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -430,7 +430,8 @@ typedef struct RcOverride{
 #define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0)
 
 /**
- * main external API structure.
+ * @ref context "Context" for an encode or decode session
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
index a09c69f242..23c3cc87e4 100644
--- a/libavcodec/bsf.h
+++ b/libavcodec/bsf.h
@@ -56,7 +56,7 @@
  */
 
 /**
- * The bitstream filter state.
+ * Bitstream filter @ref context "context"
  *
  * This struct must be allocated with av_bsf_alloc() and freed with
  * av_bsf_free().
diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
index 27f40e5519..087c99f161 100644
--- a/libavcodec/d3d11va.h
+++ b/libavcodec/d3d11va.h
@@ -46,8 +46,7 @@
  */
 
 /**
- * This structure is used to provides the necessary configurations and data
- * to the Direct3D11 FFmpeg HWAccel implementation.
+ * @ref context "Context" for the Direct3D11 FFmpeg HWAccel implementation
  *
  * The application must make it available as AVCodecContext.hwaccel_context.
  *
diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
index 4e9b56a618..d983e7ff1a 100644
--- a/libavcodec/mediacodec.h
+++ b/libavcodec/mediacodec.h
@@ -26,7 +26,7 @@
 #include "libavcodec/avcodec.h"
 
 /**
- * This structure holds a reference to a android/view/Surface object that will
+ * @ref context "Context" for the android/view/Surface object that will
  * be used as output by the decoder.
  *
  */
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index c156b08d07..e75351ae27 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -26,8 +26,10 @@
 #include "libavutil/buffer.h"
 
 /**
- * This struct is used for communicating QSV parameters between libavcodec and
- * the caller. It is managed by the caller and must be assigned to
+ * @ref context "Context" for communicating QSV parameters between libavcodec
+ * and the caller.
+ *
+ * It is managed by the caller and must be assigned to
  * AVCodecContext.hwaccel_context.
  * - decoding: hwaccel_context must be set on return from the get_format()
  *             callback
diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
index fe3a39603a..65f7a6da8f 100644
--- a/libavcodec/sbr.h
+++ b/libavcodec/sbr.h
@@ -116,7 +116,7 @@ typedef struct SBRData {
 typedef struct SpectralBandReplication SpectralBandReplication;
 
 /**
- * aacsbr functions pointers
+ * aacsbr functions pointer @ref context "context"
  */
 typedef struct AACSBRContext {
     int (*sbr_lf_gen)(SpectralBandReplication *sbr,
diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
index 8021c25761..a9ff8b5f47 100644
--- a/libavcodec/vdpau.h
+++ b/libavcodec/vdpau.h
@@ -64,8 +64,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
                                const VdpBitstreamBuffer *);
 
 /**
- * This structure is used to share data between the libavcodec library and
+ * @ref context "Context" to share data between the libavcodec library and
  * the client video application.
+ *
  * This structure will be allocated and stored in AVCodecContext.hwaccel_context
  * by av_vdpau_bind_context(). Members can be set by the user once
  * during initialization or through each AVCodecContext.get_buffer()
diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
index d68d76e400..ece008157c 100644
--- a/libavcodec/videotoolbox.h
+++ b/libavcodec/videotoolbox.h
@@ -49,8 +49,9 @@
 #include "libavutil/attributes.h"
 
 /**
- * This struct holds all the information that needs to be passed
- * between the caller and libavcodec for initializing Videotoolbox decoding.
+ * @ref context "Context" for information passed between the caller and libavcodec
+ * for initializing Videotoolbox decoding.
+ *
  * Its size is not a part of the public ABI, it must be allocated with
  * av_videotoolbox_alloc_context() and freed with av_free().
  */
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index a34e61f23c..41bdc30d89 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -403,7 +403,7 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
  */
 #define AVFILTER_THREAD_SLICE (1 << 0)
 
-/** An instance of a filter */
+/** @ref context "Context" for a filter */
 struct AVFilterContext {
     const AVClass *av_class;        ///< needed for av_log() and filters common options
 
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 8afdcd9fd0..6bb08a0b0c 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1241,7 +1241,8 @@ enum AVDurationEstimationMethod {
 };
 
 /**
- * Format I/O context.
+ * Format I/O @ref context "context"
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavformat/avio.h b/libavformat/avio.h
index ebf611187d..e18d542377 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -146,7 +146,8 @@ enum AVIODataMarkerType {
 };
 
 /**
- * Bytestream IO Context.
+ * Bytestream I/O @ref context "context"
+ *
  * New public fields can be added with minor version bumps.
  * Removal, reordering and changes to existing public fields require
  * a major version bump.
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index bac30debae..f94f44906c 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -41,12 +41,13 @@ enum AVHWDeviceType {
 };
 
 /**
- * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
- * i.e. state that is not tied to a concrete processing configuration.
- * E.g., in an API that supports hardware-accelerated encoding and decoding,
- * this struct will (if possible) wrap the state that is common to both encoding
- * and decoding and from which specific instances of encoders or decoders can be
- * derived.
+ * @ref context "Context" for (hardware/vendor-specific) "high-level" state.
+ *
+ * "High-level state" is anything that is not tied to a concrete processing
+ * configuration. E.g., in an API that supports hardware-accelerated encoding
+ * and decoding, this struct will (if possible) wrap the state that is common
+ * to both encoding and decoding and from which specific instances of encoders
+ * or decoders can be derived.
  *
  * This struct is reference-counted with the AVBuffer mechanism. The
  * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
@@ -103,9 +104,11 @@ typedef struct AVHWDeviceContext {
 } AVHWDeviceContext;
 
 /**
- * This struct describes a set or pool of "hardware" frames (i.e. those with
- * data not located in normal system memory). All the frames in the pool are
- * assumed to be allocated in the same way and interchangeable.
+ * @ref context "context" for a pool of "hardware" frames (those with
+ * data not located in normal system memory)
+ *
+ * All the frames in the pool are assumed to be allocated in the same way and
+ * interchangeable.
  *
  * This struct is reference-counted with the AVBuffer mechanism and tied to a
  * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
index cbad434fea..befa978cf9 100644
--- a/libavutil/hwcontext_cuda.h
+++ b/libavutil/hwcontext_cuda.h
@@ -37,7 +37,7 @@
 typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVCUDADeviceContext {
     CUcontext cuda_ctx;
diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
index 77d2d72f1b..eac7d6062a 100644
--- a/libavutil/hwcontext_d3d11va.h
+++ b/libavutil/hwcontext_d3d11va.h
@@ -40,7 +40,7 @@
 #include <stdint.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVD3D11VADeviceContext {
     /**
@@ -126,7 +126,7 @@ typedef struct AVD3D11FrameDescriptor {
 } AVD3D11FrameDescriptor;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVD3D11VAFramesContext {
     /**
diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
index ff06e6f2ef..d170f74b4d 100644
--- a/libavutil/hwcontext_d3d12va.h
+++ b/libavutil/hwcontext_d3d12va.h
@@ -37,7 +37,7 @@
 #include <d3d12video.h>
 
 /**
- * @brief This struct is allocated as AVHWDeviceContext.hwctx
+ * @brief This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  *
  */
 typedef struct AVD3D12VADeviceContext {
@@ -78,7 +78,7 @@ typedef struct AVD3D12VADeviceContext {
 } AVD3D12VADeviceContext;
 
 /**
- * @brief This struct is used to sync d3d12 execution
+ * @brief This @ref context "context" is used to sync d3d12 execution
  *
  */
 typedef struct AVD3D12VASyncContext {
@@ -120,7 +120,7 @@ typedef struct AVD3D12VAFrame {
 } AVD3D12VAFrame;
 
 /**
- * @brief This struct is allocated as AVHWFramesContext.hwctx
+ * @brief This @ref context "context" is allocated as AVHWFramesContext.hwctx
  *
  */
 typedef struct AVD3D12VAFramesContext {
diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
index 42709f215e..b7b1bad171 100644
--- a/libavutil/hwcontext_drm.h
+++ b/libavutil/hwcontext_drm.h
@@ -152,7 +152,7 @@ typedef struct AVDRMFrameDescriptor {
 /**
  * DRM device.
  *
- * Allocated as AVHWDeviceContext.hwctx.
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx.
  */
 typedef struct AVDRMDeviceContext {
     /**
diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
index e1b79bc0de..b77b7293ab 100644
--- a/libavutil/hwcontext_dxva2.h
+++ b/libavutil/hwcontext_dxva2.h
@@ -34,14 +34,14 @@
 #include <dxva2api.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVDXVA2DeviceContext {
     IDirect3DDeviceManager9 *devmgr;
 } AVDXVA2DeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVDXVA2FramesContext {
     /**
diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
index fc0263cabc..39381b56c5 100644
--- a/libavutil/hwcontext_mediacodec.h
+++ b/libavutil/hwcontext_mediacodec.h
@@ -22,7 +22,7 @@
 /**
  * MediaCodec details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVMediaCodecDeviceContext {
     /**
diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
index ef54486c95..fc5b1bb24f 100644
--- a/libavutil/hwcontext_opencl.h
+++ b/libavutil/hwcontext_opencl.h
@@ -58,7 +58,7 @@ typedef struct AVOpenCLFrameDescriptor {
 /**
  * OpenCL device details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVOpenCLDeviceContext {
     /**
@@ -84,7 +84,7 @@ typedef struct AVOpenCLDeviceContext {
 /**
  * OpenCL-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * This @ref context "context" is allocated as AVHWFramesContext.hwctx.
  */
 typedef struct AVOpenCLFramesContext {
     /**
diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
index e2dba8ad83..c7cc88627b 100644
--- a/libavutil/hwcontext_qsv.h
+++ b/libavutil/hwcontext_qsv.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVQSVDeviceContext {
     mfxSession session;
@@ -48,7 +48,7 @@ typedef struct AVQSVDeviceContext {
 } AVQSVDeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVQSVFramesContext {
     mfxFrameSurface1 *surfaces;
diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
index 0b2e071cb3..e1940a5fe0 100644
--- a/libavutil/hwcontext_vaapi.h
+++ b/libavutil/hwcontext_vaapi.h
@@ -63,7 +63,7 @@ enum {
 /**
  * VAAPI connection details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVVAAPIDeviceContext {
     /**
@@ -83,7 +83,7 @@ typedef struct AVVAAPIDeviceContext {
 /**
  * VAAPI-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * This @ref context "context" is allocated as AVHWFramesContext.hwctx.
  */
 typedef struct AVVAAPIFramesContext {
     /**
@@ -105,7 +105,7 @@ typedef struct AVVAAPIFramesContext {
 /**
  * VAAPI hardware pipeline configuration details.
  *
- * Allocated with av_hwdevice_hwconfig_alloc().
+ * This struct is allocated with av_hwdevice_hwconfig_alloc().
  */
 typedef struct AVVAAPIHWConfig {
     /**
diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
index 1b7ea1e443..b26f7f171e 100644
--- a/libavutil/hwcontext_vdpau.h
+++ b/libavutil/hwcontext_vdpau.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVVDPAUDeviceContext {
     VdpDevice          device;
diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
index cbbd2390c1..d6897a96fa 100644
--- a/libavutil/hwcontext_vulkan.h
+++ b/libavutil/hwcontext_vulkan.h
@@ -39,7 +39,7 @@ typedef struct AVVkFrame AVVkFrame;
  */
 
 /**
- * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
+ * Main Vulkan @ref context "context", allocated as AVHWDeviceContext.hwctx.
  * All of these can be set before init to change what the context uses
  */
 typedef struct AVVulkanDeviceContext {
@@ -172,7 +172,7 @@ typedef enum AVVkFrameFlags {
 } AVVkFrameFlags;
 
 /**
- * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
+ * This @ref context "context" is allocated as AVHWFramesContext.hwctx, used to set pool-specific options
  */
 typedef struct AVVulkanFramesContext {
     /**
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means
  2024-04-18 15:06 [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means Andrew Sayers
  2024-04-18 15:06 ` [FFmpeg-devel] [PATCH 2/3] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
  2024-04-18 15:06 ` [FFmpeg-devel] [PATCH 3/3] all: Link to "context" from all contexts with documentation Andrew Sayers
@ 2024-04-20  7:25 ` Stefano Sabatini
  2024-04-20 12:18   ` Andrew Sayers
  2024-04-20 12:19   ` [FFmpeg-devel] [PATCH v2 " Andrew Sayers
  2024-05-15 15:54 ` [FFmpeg-devel] [PATCH v4 0/4] Explain what "context" means Andrew Sayers
  2024-06-04 14:47 ` [FFmpeg-devel] [PATCH v6 0/4] doc: Explain what "context" means Andrew Sayers
  4 siblings, 2 replies; 84+ messages in thread
From: Stefano Sabatini @ 2024-04-20  7:25 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andrew Sayers

On date Thursday 2024-04-18 16:06:12 +0100, Andrew Sayers wrote:
> Based largely on the explanation by Stefano Sabatini:
> https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325854.html
> ---
>  doc/jargon.md | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 96 insertions(+)
>  create mode 100644 doc/jargon.md
> 
> diff --git a/doc/jargon.md b/doc/jargon.md
> new file mode 100644
> index 0000000000..3b78ffb61f

> --- /dev/null
> +++ b/doc/jargon.md

We currently have a single .md file in doc (for historical reason we
still stick to texinfo). Also how is this integrated into doxygen?


> @@ -0,0 +1,96 @@
> +# 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 elsewhere.
> +
> +Consider a trivial program to print uppercase text:
> +
> +```c

> +/*
> + * Contextual information about where to print a series of messages
> + */

Style:
/**
 * Contextual information about where to print a series of messages
 */

> +struct UpperCasePrinterContext {
> +    FILE* out;

here and below, use:
VAR *out;

for overall consistency with the project style.

> +};
> +
> +/*
> + * Extra information about messages to print.
> + * This could be used multiple times in a single context,
> + * or reused several times across multiple contexts.
> + */
> +struct PrintInfo {
> +    char* str;
> +};
> +
> +void print(
> +    struct UpperCasePrinterContext * ctx,
> +    struct PrintInfo * info
> +) {
> +    for ( char* c = info->str; *c; ++c ) {
> +        char C = toupper(*c);
> +        fwrite( &C, 1, 1, ctx->out );
> +    }
> +}
> +

> +int main()
> +{
> +    struct PrintInfo hello, world;
> +    struct UpperCasePrinterContext ctx;
> +
> +    hello.str = "hello, ";
> +    world.str = "world!\n";
> +
> +    ctx.out = stdout;
> +
> +    print( &ctx, &hello );
> +    print( &ctx, &world );
> +
> +    return 0;
> +}

I'm not sure this is a fitting example. Usually the context is a
public structure and the internal context (which corresponds to the
PrintInfo struct) is private to the implementation. In this case the
API user is not interested at all at its implmentation.

You can think the context provides the "object"/instance where some
operations are done - this is alike in object oriented programming,
where the context corresponds to the self, so that you create/allocate
the object, initialize it, and invoke operations on the object.

So using this analogy, the example would be:

struct UpperCasePrinterContext {...};

// this corresponds to a "method" defined on the context/object
void uppercase_printer_print(UpperCasePrinterContext *ctx, const char *str);

Or maybe you want to define the property in the context itself, so you
do:
uppercase_ctx.str = "foobar";

then you have:
void uppercase_printer_print(UpperCasePrinterContext *ctx);

On a typical FFmpeg context you typically do (see
doc/examples/encode.c example):
    // create the context
    c = avcodec_alloc_context3(codec);

    // set parameters, either in the context or by using the av_opt API
    c->bit_rate = 400000;
    c->width = 352;
    c->height = 288;
    c->time_base = (AVRational){1, 25};
    c->framerate = (AVRational){25, 1};
    // ...

    // invoke the methods defined in the context
    ret = avcodec_send_frame(enc_ctx, frame);
    if (ret < 0) {
        fprintf(stderr, "Error sending a frame for encoding\n");
        exit(1);
    }

    while (ret >= 0) {
        ret = avcodec_receive_packet(enc_ctx, pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error during encoding\n");
            exit(1);
        }
        ...
        av_packet_unref(pkt);
    }

[...]

Note also that "context" in the FFmpeg jargon is not very specific
because it might be different depending on the implementation, for
example it might not have an av_opt_* interface (for example
libavutil/hash.h).

> +```
> +

> +The `UpperCasePrinterContext` object contains the information that's about
> +the context of the current job (i.e. printing things to standard output).

I find this confusing, it is essentially saying that the context (the
"object") is the context of the current job.

> +Information with a lifetime different than that of the context is moved
> +to the `PrintInfo` object.
> +

> +FFmpeg's main context structures all happen to face some common problems:
> +
> +- querying, setting and getting options
> +- handling "private" internal context, including options for
> +  a particular instance of the generic context
> +- configuring log message verbosity and content
> +

> +FFmpeg gradually converged on the AVClass struct to store this information,
> +then converged on the @ref avoptions "AVOptions" system to manipulate it,
> +so modern code often uses the terms "context", "AVClass context structure"
> +and "AVOptions-enabled struct" interchangeably.  But it is occasionally
> +necessary to distinguish between them - for example, AVMediaCodecContext
> +is a context that does not use AVClass.
> +
> +To understand how this all works, consider some requirements for the
> +`libx264` encoder:
> +
> +- it has to support common encoder options like "bitrate"
> +- it has to support encoder-specific options like "profile"
> +- 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 to
> +users 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 you get

> +and set those values, and provides readable feedback about errors.

> Although X264Context can be set by users,

Can it? The X264Context is defined within the implementation, so it is
not exposed to the user, the only way to set it is through the private
options to be set through the AVCodecContext options through the
av_opt API - in other words you cannot set the context directly as you
do with the "generic" options defined in the AVCodecContext.

> it is not part of the public interface, so new releases can modify
> it without affecting the API version.

[...]
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means
  2024-04-20  7:25 ` [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means Stefano Sabatini
@ 2024-04-20 12:18   ` Andrew Sayers
  2024-04-20 16:13     ` Stefano Sabatini
  2024-04-20 12:19   ` [FFmpeg-devel] [PATCH v2 " Andrew Sayers
  1 sibling, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-04-20 12:18 UTC (permalink / raw)
  To: ffmpeg-devel

On 20/04/2024 08:25, Stefano Sabatini wrote:
> On date Thursday 2024-04-18 16:06:12 +0100, Andrew Sayers wrote:
>> Based largely on the explanation by Stefano Sabatini:
>> https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325854.html
>> ---
>>   doc/jargon.md | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 96 insertions(+)
>>   create mode 100644 doc/jargon.md
>>
>> diff --git a/doc/jargon.md b/doc/jargon.md
>> new file mode 100644
>> index 0000000000..3b78ffb61f
>> --- /dev/null
>> +++ b/doc/jargon.md
> We currently have a single .md file in doc (for historical reason we
> still stick to texinfo). Also how is this integrated into doxygen?

Doxygen automatically renders all /*.md and /doc/*.md files to pages at [1]
which is the only place I'd know to look for this sort of thing. it seems
like texinfo is more for man pages etc., which would be hard to link from
doxygen?  By the way, a file called "jargon" seemed like a better idea than
e.g. a "design_patterns" file or a section in AVClass.  I've rewritten the
document completely based on your feedback - same markdown file for now,
but happy to move/reformat.

The points below should be addressed by the new patch, so I'll let that
speak for itself.  But there's a general issue that's worth mentioning...

Technically, it sounds like a more accurate description would be "Context
is an FFmpeg convention that has become fairly rigorous over the years".
But IMHO readers would uncharitably read that as "Context is some weird
FFmpeg thing they're stuck with because they picked a pre-OOP language".
Arguing "Context is a design pattern that groups objects by lifespan"
emphasises the lessons a newbie can take from FFmpeg and use elsewhere,
so they get more value from the time they spent reading the document.
I've tried to write the document to start with the more useful argument,
then gradually ease in to the more accurate one.

Note: I previously sent this from the wrong e-mail address - apologies for
spam if the other one makes it past moderation.

[1] https://ffmpeg.org/doxygen/trunk/pages.html

>
>> @@ -0,0 +1,96 @@
>> +# 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 elsewhere.
>> +
>> +Consider a trivial program to print uppercase text:
>> +
>> +```c
>> +/*
>> + * Contextual information about where to print a series of messages
>> + */
> Style:
> /**
>   * Contextual information about where to print a series of messages
>   */
>
>> +struct UpperCasePrinterContext {
>> +    FILE* out;
> here and below, use:
> VAR *out;
>
> for overall consistency with the project style.
>
>> +};
>> +
>> +/*
>> + * Extra information about messages to print.
>> + * This could be used multiple times in a single context,
>> + * or reused several times across multiple contexts.
>> + */
>> +struct PrintInfo {
>> +    char* str;
>> +};
>> +
>> +void print(
>> +    struct UpperCasePrinterContext * ctx,
>> +    struct PrintInfo * info
>> +) {
>> +    for ( char* c = info->str; *c; ++c ) {
>> +        char C = toupper(*c);
>> +        fwrite( &C, 1, 1, ctx->out );
>> +    }
>> +}
>> +
>> +int main()
>> +{
>> +    struct PrintInfo hello, world;
>> +    struct UpperCasePrinterContext ctx;
>> +
>> +    hello.str = "hello, ";
>> +    world.str = "world!\n";
>> +
>> +    ctx.out = stdout;
>> +
>> +    print( &ctx, &hello );
>> +    print( &ctx, &world );
>> +
>> +    return 0;
>> +}
> I'm not sure this is a fitting example. Usually the context is a
> public structure and the internal context (which corresponds to the
> PrintInfo struct) is private to the implementation. In this case the
> API user is not interested at all at its implmentation.
>
> You can think the context provides the "object"/instance where some
> operations are done - this is alike in object oriented programming,
> where the context corresponds to the self, so that you create/allocate
> the object, initialize it, and invoke operations on the object.
>
> So using this analogy, the example would be:
>
> struct UpperCasePrinterContext {...};
>
> // this corresponds to a "method" defined on the context/object
> void uppercase_printer_print(UpperCasePrinterContext *ctx, const char *str);
>
> Or maybe you want to define the property in the context itself, so you
> do:
> uppercase_ctx.str = "foobar";
>
> then you have:
> void uppercase_printer_print(UpperCasePrinterContext *ctx);
>
> On a typical FFmpeg context you typically do (see
> doc/examples/encode.c example):
>      // create the context
>      c = avcodec_alloc_context3(codec);
>
>      // set parameters, either in the context or by using the av_opt API
>      c->bit_rate = 400000;
>      c->width = 352;
>      c->height = 288;
>      c->time_base = (AVRational){1, 25};
>      c->framerate = (AVRational){25, 1};
>      // ...
>
>      // invoke the methods defined in the context
>      ret = avcodec_send_frame(enc_ctx, frame);
>      if (ret < 0) {
>          fprintf(stderr, "Error sending a frame for encoding\n");
>          exit(1);
>      }
>
>      while (ret >= 0) {
>          ret = avcodec_receive_packet(enc_ctx, pkt);
>          if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
>              return;
>          else if (ret < 0) {
>              fprintf(stderr, "Error during encoding\n");
>              exit(1);
>          }
>          ...
>          av_packet_unref(pkt);
>      }
>
> [...]
>
> Note also that "context" in the FFmpeg jargon is not very specific
> because it might be different depending on the implementation, for
> example it might not have an av_opt_* interface (for example
> libavutil/hash.h).
>
>> +```
>> +
>> +The `UpperCasePrinterContext` object contains the information that's about
>> +the context of the current job (i.e. printing things to standard output).
> I find this confusing, it is essentially saying that the context (the
> "object") is the context of the current job.
>
>> +Information with a lifetime different than that of the context is moved
>> +to the `PrintInfo` object.
>> +
>> +FFmpeg's main context structures all happen to face some common problems:
>> +
>> +- querying, setting and getting options
>> +- handling "private" internal context, including options for
>> +  a particular instance of the generic context
>> +- configuring log message verbosity and content
>> +
>> +FFmpeg gradually converged on the AVClass struct to store this information,
>> +then converged on the @ref avoptions "AVOptions" system to manipulate it,
>> +so modern code often uses the terms "context", "AVClass context structure"
>> +and "AVOptions-enabled struct" interchangeably.  But it is occasionally
>> +necessary to distinguish between them - for example, AVMediaCodecContext
>> +is a context that does not use AVClass.
>> +
>> +To understand how this all works, consider some requirements for the
>> +`libx264` encoder:
>> +
>> +- it has to support common encoder options like "bitrate"
>> +- it has to support encoder-specific options like "profile"
>> +- 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 to
>> +users 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 you get
>> +and set those values, and provides readable feedback about errors.
>> Although X264Context can be set by users,
> Can it? The X264Context is defined within the implementation, so it is
> not exposed to the user, the only way to set it is through the private
> options to be set through the AVCodecContext options through the
> av_opt API - in other words you cannot set the context directly as you
> do with the "generic" options defined in the AVCodecContext.
>
>> it is not part of the public interface, so new releases can modify
>> it without affecting the API version.
> [...]
> _______________________________________________
> 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".
>
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v2 1/3] doc: Explain what "context" means
  2024-04-20  7:25 ` [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means Stefano Sabatini
  2024-04-20 12:18   ` Andrew Sayers
@ 2024-04-20 12:19   ` Andrew Sayers
  2024-04-20 12:19     ` [FFmpeg-devel] [PATCH v2 2/3] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
                       ` (2 more replies)
  1 sibling, 3 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-04-20 12:19 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v2 2/3] lavu: Clarify relationship between AVClass, AVOption and context
  2024-04-20 12:19   ` [FFmpeg-devel] [PATCH v2 " Andrew Sayers
@ 2024-04-20 12:19     ` Andrew Sayers
  2024-04-20 12:19     ` [FFmpeg-devel] [PATCH v2 3/3] all: Link to "context" from all contexts with documentation Andrew Sayers
  2024-04-20 16:48     ` [FFmpeg-devel] [PATCH v2 1/3] doc: Explain what "context" means Stefano Sabatini
  2 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-04-20 12:19 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

---
 libavutil/log.h | 11 ++++++++---
 libavutil/opt.h |  7 ++++---
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/libavutil/log.h b/libavutil/log.h
index ab7ceabe22..b5c739dab1 100644
--- a/libavutil/log.h
+++ b/libavutil/log.h
@@ -59,9 +59,14 @@ typedef enum {
 struct AVOptionRanges;
 
 /**
- * Describe the class of an AVClass context structure. That is an
- * arbitrary struct of which the first field is a pointer to an
- * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.).
+ * Metadata about an arbitrary data structure
+ *
+ * A @ref context "context struct" whose first member is a pointer
+ * to an AVClass object is called an "AVClass context structure"
+ * (e.g. AVCodecContext, AVFormatContext etc.).
+ *
+ * AVClass is often combined with @ref avoptions "AVOptions" to create
+ * "AVOptions-enabled structs" that can be easily configured by users.
  */
 typedef struct AVClass {
     /**
diff --git a/libavutil/opt.h b/libavutil/opt.h
index e6013662f6..b817d15554 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -39,9 +39,10 @@
  * @defgroup avoptions AVOptions
  * @ingroup lavu_data
  * @{
- * AVOptions provide a generic system to declare options on arbitrary structs
- * ("objects"). An option can have a help text, a type and a range of possible
- * values. Options may then be enumerated, read and written to.
+ * Builds on AVClass, adding a generic system to declare options.
+ *
+ * An option can have a help text, a type and a range of possible values.
+ * Options may then be enumerated, read and written to.
  *
  * There are two modes of access to members of AVOption and its child structs.
  * One is called 'native access', and refers to access from the code that
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v2 3/3] all: Link to "context" from all contexts with documentation
  2024-04-20 12:19   ` [FFmpeg-devel] [PATCH v2 " Andrew Sayers
  2024-04-20 12:19     ` [FFmpeg-devel] [PATCH v2 2/3] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
@ 2024-04-20 12:19     ` Andrew Sayers
  2024-04-20 16:48     ` [FFmpeg-devel] [PATCH v2 1/3] doc: Explain what "context" means Stefano Sabatini
  2 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-04-20 12:19 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Some headings needed to be rewritten to accomodate the text,
(hopefully) without changing the meaning.
---
 libavcodec/aacdec.h              |  2 +-
 libavcodec/aacenc.h              |  2 +-
 libavcodec/ac3enc.h              |  2 +-
 libavcodec/amfenc.h              |  2 +-
 libavcodec/atrac.h               |  2 +-
 libavcodec/avcodec.h             |  3 ++-
 libavcodec/bsf.h                 |  2 +-
 libavcodec/d3d11va.h             |  3 +--
 libavcodec/mediacodec.h          |  2 +-
 libavcodec/qsv.h                 |  6 ++++--
 libavcodec/sbr.h                 |  2 +-
 libavcodec/vdpau.h               |  3 ++-
 libavcodec/videotoolbox.h        |  5 +++--
 libavfilter/avfilter.h           |  2 +-
 libavformat/avformat.h           |  3 ++-
 libavformat/avio.h               |  3 ++-
 libavutil/hwcontext.h            | 21 ++++++++++++---------
 libavutil/hwcontext_cuda.h       |  2 +-
 libavutil/hwcontext_d3d11va.h    |  4 ++--
 libavutil/hwcontext_d3d12va.h    |  6 +++---
 libavutil/hwcontext_drm.h        |  2 +-
 libavutil/hwcontext_dxva2.h      |  4 ++--
 libavutil/hwcontext_mediacodec.h |  2 +-
 libavutil/hwcontext_opencl.h     |  4 ++--
 libavutil/hwcontext_qsv.h        |  4 ++--
 libavutil/hwcontext_vaapi.h      |  6 +++---
 libavutil/hwcontext_vdpau.h      |  2 +-
 libavutil/hwcontext_vulkan.h     |  4 ++--
 28 files changed, 57 insertions(+), 48 deletions(-)

diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 1b245f9258..3a5317cd54 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -181,7 +181,7 @@ typedef struct DynamicRangeControl {
 } DynamicRangeControl;
 
 /**
- * main AAC decoding context
+ * main AAC decoding @ref context "context"
  */
 typedef struct AACDecContext {
     const struct AVClass  *class;
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index 8899f90ac7..c91f99bc6c 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -193,7 +193,7 @@ typedef struct AACPCEInfo {
 } AACPCEInfo;
 
 /**
- * AAC encoder context
+ * AAC encoder @ref context "context"
  */
 typedef struct AACEncContext {
     AVClass *av_class;
diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
index 30812617cc..4b6b3c222b 100644
--- a/libavcodec/ac3enc.h
+++ b/libavcodec/ac3enc.h
@@ -152,7 +152,7 @@ typedef struct AC3Block {
 } AC3Block;
 
 /**
- * AC-3 encoder private context.
+ * AC-3 encoder private @ref context "context"
  */
 typedef struct AC3EncodeContext {
     AVClass *av_class;                      ///< AVClass used for AVOption
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
index 2dbd378ef8..71138e7f76 100644
--- a/libavcodec/amfenc.h
+++ b/libavcodec/amfenc.h
@@ -43,7 +43,7 @@ typedef struct AmfTraceWriter {
 } AmfTraceWriter;
 
 /**
-* AMF encoder context
+* AMF encoder @ref context "context"
 */
 
 typedef struct AmfContext {
diff --git a/libavcodec/atrac.h b/libavcodec/atrac.h
index 05208bbee6..acdd0a741a 100644
--- a/libavcodec/atrac.h
+++ b/libavcodec/atrac.h
@@ -39,7 +39,7 @@ typedef struct AtracGainInfo {
 } AtracGainInfo;
 
 /**
- *  Gain compensation context structure.
+ *  Gain compensation @ref context "context"
  */
 typedef struct AtracGCContext {
     float   gain_tab1[16];  ///< gain compensation level table
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 968009a192..a1f1430dde 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -430,7 +430,8 @@ typedef struct RcOverride{
 #define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0)
 
 /**
- * main external API structure.
+ * @ref context "Context" for an encode or decode session
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
index a09c69f242..23c3cc87e4 100644
--- a/libavcodec/bsf.h
+++ b/libavcodec/bsf.h
@@ -56,7 +56,7 @@
  */
 
 /**
- * The bitstream filter state.
+ * Bitstream filter @ref context "context"
  *
  * This struct must be allocated with av_bsf_alloc() and freed with
  * av_bsf_free().
diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
index 27f40e5519..087c99f161 100644
--- a/libavcodec/d3d11va.h
+++ b/libavcodec/d3d11va.h
@@ -46,8 +46,7 @@
  */
 
 /**
- * This structure is used to provides the necessary configurations and data
- * to the Direct3D11 FFmpeg HWAccel implementation.
+ * @ref context "Context" for the Direct3D11 FFmpeg HWAccel implementation
  *
  * The application must make it available as AVCodecContext.hwaccel_context.
  *
diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
index 4e9b56a618..d983e7ff1a 100644
--- a/libavcodec/mediacodec.h
+++ b/libavcodec/mediacodec.h
@@ -26,7 +26,7 @@
 #include "libavcodec/avcodec.h"
 
 /**
- * This structure holds a reference to a android/view/Surface object that will
+ * @ref context "Context" for the android/view/Surface object that will
  * be used as output by the decoder.
  *
  */
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index c156b08d07..e75351ae27 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -26,8 +26,10 @@
 #include "libavutil/buffer.h"
 
 /**
- * This struct is used for communicating QSV parameters between libavcodec and
- * the caller. It is managed by the caller and must be assigned to
+ * @ref context "Context" for communicating QSV parameters between libavcodec
+ * and the caller.
+ *
+ * It is managed by the caller and must be assigned to
  * AVCodecContext.hwaccel_context.
  * - decoding: hwaccel_context must be set on return from the get_format()
  *             callback
diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
index fe3a39603a..65f7a6da8f 100644
--- a/libavcodec/sbr.h
+++ b/libavcodec/sbr.h
@@ -116,7 +116,7 @@ typedef struct SBRData {
 typedef struct SpectralBandReplication SpectralBandReplication;
 
 /**
- * aacsbr functions pointers
+ * aacsbr functions pointer @ref context "context"
  */
 typedef struct AACSBRContext {
     int (*sbr_lf_gen)(SpectralBandReplication *sbr,
diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
index 8021c25761..a9ff8b5f47 100644
--- a/libavcodec/vdpau.h
+++ b/libavcodec/vdpau.h
@@ -64,8 +64,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
                                const VdpBitstreamBuffer *);
 
 /**
- * This structure is used to share data between the libavcodec library and
+ * @ref context "Context" to share data between the libavcodec library and
  * the client video application.
+ *
  * This structure will be allocated and stored in AVCodecContext.hwaccel_context
  * by av_vdpau_bind_context(). Members can be set by the user once
  * during initialization or through each AVCodecContext.get_buffer()
diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
index d68d76e400..ece008157c 100644
--- a/libavcodec/videotoolbox.h
+++ b/libavcodec/videotoolbox.h
@@ -49,8 +49,9 @@
 #include "libavutil/attributes.h"
 
 /**
- * This struct holds all the information that needs to be passed
- * between the caller and libavcodec for initializing Videotoolbox decoding.
+ * @ref context "Context" for information passed between the caller and libavcodec
+ * for initializing Videotoolbox decoding.
+ *
  * Its size is not a part of the public ABI, it must be allocated with
  * av_videotoolbox_alloc_context() and freed with av_free().
  */
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index a34e61f23c..41bdc30d89 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -403,7 +403,7 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
  */
 #define AVFILTER_THREAD_SLICE (1 << 0)
 
-/** An instance of a filter */
+/** @ref context "Context" for a filter */
 struct AVFilterContext {
     const AVClass *av_class;        ///< needed for av_log() and filters common options
 
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 8afdcd9fd0..6bb08a0b0c 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1241,7 +1241,8 @@ enum AVDurationEstimationMethod {
 };
 
 /**
- * Format I/O context.
+ * Format I/O @ref context "context"
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavformat/avio.h b/libavformat/avio.h
index ebf611187d..e18d542377 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -146,7 +146,8 @@ enum AVIODataMarkerType {
 };
 
 /**
- * Bytestream IO Context.
+ * Bytestream I/O @ref context "context"
+ *
  * New public fields can be added with minor version bumps.
  * Removal, reordering and changes to existing public fields require
  * a major version bump.
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index bac30debae..f94f44906c 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -41,12 +41,13 @@ enum AVHWDeviceType {
 };
 
 /**
- * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
- * i.e. state that is not tied to a concrete processing configuration.
- * E.g., in an API that supports hardware-accelerated encoding and decoding,
- * this struct will (if possible) wrap the state that is common to both encoding
- * and decoding and from which specific instances of encoders or decoders can be
- * derived.
+ * @ref context "Context" for (hardware/vendor-specific) "high-level" state.
+ *
+ * "High-level state" is anything that is not tied to a concrete processing
+ * configuration. E.g., in an API that supports hardware-accelerated encoding
+ * and decoding, this struct will (if possible) wrap the state that is common
+ * to both encoding and decoding and from which specific instances of encoders
+ * or decoders can be derived.
  *
  * This struct is reference-counted with the AVBuffer mechanism. The
  * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
@@ -103,9 +104,11 @@ typedef struct AVHWDeviceContext {
 } AVHWDeviceContext;
 
 /**
- * This struct describes a set or pool of "hardware" frames (i.e. those with
- * data not located in normal system memory). All the frames in the pool are
- * assumed to be allocated in the same way and interchangeable.
+ * @ref context "context" for a pool of "hardware" frames (those with
+ * data not located in normal system memory)
+ *
+ * All the frames in the pool are assumed to be allocated in the same way and
+ * interchangeable.
  *
  * This struct is reference-counted with the AVBuffer mechanism and tied to a
  * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
index cbad434fea..befa978cf9 100644
--- a/libavutil/hwcontext_cuda.h
+++ b/libavutil/hwcontext_cuda.h
@@ -37,7 +37,7 @@
 typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVCUDADeviceContext {
     CUcontext cuda_ctx;
diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
index 77d2d72f1b..eac7d6062a 100644
--- a/libavutil/hwcontext_d3d11va.h
+++ b/libavutil/hwcontext_d3d11va.h
@@ -40,7 +40,7 @@
 #include <stdint.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVD3D11VADeviceContext {
     /**
@@ -126,7 +126,7 @@ typedef struct AVD3D11FrameDescriptor {
 } AVD3D11FrameDescriptor;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVD3D11VAFramesContext {
     /**
diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
index ff06e6f2ef..d170f74b4d 100644
--- a/libavutil/hwcontext_d3d12va.h
+++ b/libavutil/hwcontext_d3d12va.h
@@ -37,7 +37,7 @@
 #include <d3d12video.h>
 
 /**
- * @brief This struct is allocated as AVHWDeviceContext.hwctx
+ * @brief This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  *
  */
 typedef struct AVD3D12VADeviceContext {
@@ -78,7 +78,7 @@ typedef struct AVD3D12VADeviceContext {
 } AVD3D12VADeviceContext;
 
 /**
- * @brief This struct is used to sync d3d12 execution
+ * @brief This @ref context "context" is used to sync d3d12 execution
  *
  */
 typedef struct AVD3D12VASyncContext {
@@ -120,7 +120,7 @@ typedef struct AVD3D12VAFrame {
 } AVD3D12VAFrame;
 
 /**
- * @brief This struct is allocated as AVHWFramesContext.hwctx
+ * @brief This @ref context "context" is allocated as AVHWFramesContext.hwctx
  *
  */
 typedef struct AVD3D12VAFramesContext {
diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
index 42709f215e..b7b1bad171 100644
--- a/libavutil/hwcontext_drm.h
+++ b/libavutil/hwcontext_drm.h
@@ -152,7 +152,7 @@ typedef struct AVDRMFrameDescriptor {
 /**
  * DRM device.
  *
- * Allocated as AVHWDeviceContext.hwctx.
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx.
  */
 typedef struct AVDRMDeviceContext {
     /**
diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
index e1b79bc0de..b77b7293ab 100644
--- a/libavutil/hwcontext_dxva2.h
+++ b/libavutil/hwcontext_dxva2.h
@@ -34,14 +34,14 @@
 #include <dxva2api.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVDXVA2DeviceContext {
     IDirect3DDeviceManager9 *devmgr;
 } AVDXVA2DeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVDXVA2FramesContext {
     /**
diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
index fc0263cabc..39381b56c5 100644
--- a/libavutil/hwcontext_mediacodec.h
+++ b/libavutil/hwcontext_mediacodec.h
@@ -22,7 +22,7 @@
 /**
  * MediaCodec details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVMediaCodecDeviceContext {
     /**
diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
index ef54486c95..fc5b1bb24f 100644
--- a/libavutil/hwcontext_opencl.h
+++ b/libavutil/hwcontext_opencl.h
@@ -58,7 +58,7 @@ typedef struct AVOpenCLFrameDescriptor {
 /**
  * OpenCL device details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVOpenCLDeviceContext {
     /**
@@ -84,7 +84,7 @@ typedef struct AVOpenCLDeviceContext {
 /**
  * OpenCL-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * This @ref context "context" is allocated as AVHWFramesContext.hwctx.
  */
 typedef struct AVOpenCLFramesContext {
     /**
diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
index e2dba8ad83..c7cc88627b 100644
--- a/libavutil/hwcontext_qsv.h
+++ b/libavutil/hwcontext_qsv.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVQSVDeviceContext {
     mfxSession session;
@@ -48,7 +48,7 @@ typedef struct AVQSVDeviceContext {
 } AVQSVDeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVQSVFramesContext {
     mfxFrameSurface1 *surfaces;
diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
index 0b2e071cb3..e1940a5fe0 100644
--- a/libavutil/hwcontext_vaapi.h
+++ b/libavutil/hwcontext_vaapi.h
@@ -63,7 +63,7 @@ enum {
 /**
  * VAAPI connection details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVVAAPIDeviceContext {
     /**
@@ -83,7 +83,7 @@ typedef struct AVVAAPIDeviceContext {
 /**
  * VAAPI-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * This @ref context "context" is allocated as AVHWFramesContext.hwctx.
  */
 typedef struct AVVAAPIFramesContext {
     /**
@@ -105,7 +105,7 @@ typedef struct AVVAAPIFramesContext {
 /**
  * VAAPI hardware pipeline configuration details.
  *
- * Allocated with av_hwdevice_hwconfig_alloc().
+ * This struct is allocated with av_hwdevice_hwconfig_alloc().
  */
 typedef struct AVVAAPIHWConfig {
     /**
diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
index 1b7ea1e443..b26f7f171e 100644
--- a/libavutil/hwcontext_vdpau.h
+++ b/libavutil/hwcontext_vdpau.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVVDPAUDeviceContext {
     VdpDevice          device;
diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
index cbbd2390c1..d6897a96fa 100644
--- a/libavutil/hwcontext_vulkan.h
+++ b/libavutil/hwcontext_vulkan.h
@@ -39,7 +39,7 @@ typedef struct AVVkFrame AVVkFrame;
  */
 
 /**
- * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
+ * Main Vulkan @ref context "context", allocated as AVHWDeviceContext.hwctx.
  * All of these can be set before init to change what the context uses
  */
 typedef struct AVVulkanDeviceContext {
@@ -172,7 +172,7 @@ typedef enum AVVkFrameFlags {
 } AVVkFrameFlags;
 
 /**
- * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
+ * This @ref context "context" is allocated as AVHWFramesContext.hwctx, used to set pool-specific options
  */
 typedef struct AVVulkanFramesContext {
     /**
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means
  2024-04-20 12:18   ` Andrew Sayers
@ 2024-04-20 16:13     ` Stefano Sabatini
  0 siblings, 0 replies; 84+ messages in thread
From: Stefano Sabatini @ 2024-04-20 16:13 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On date Saturday 2024-04-20 13:18:29 +0100, Andrew Sayers wrote:
> On 20/04/2024 08:25, Stefano Sabatini wrote:
> > On date Thursday 2024-04-18 16:06:12 +0100, Andrew Sayers wrote:
> > > Based largely on the explanation by Stefano Sabatini:
> > > https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325854.html
> > > ---
> > >   doc/jargon.md | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++
> > >   1 file changed, 96 insertions(+)
> > >   create mode 100644 doc/jargon.md
> > > 
> > > diff --git a/doc/jargon.md b/doc/jargon.md
> > > new file mode 100644
> > > index 0000000000..3b78ffb61f
> > > --- /dev/null
> > > +++ b/doc/jargon.md
> > We currently have a single .md file in doc (for historical reason we
> > still stick to texinfo). Also how is this integrated into doxygen?
> 

> Doxygen automatically renders all /*.md and /doc/*.md files to pages at [1]
> which is the only place I'd know to look for this sort of thing. it seems
> like texinfo is more for man pages etc., which would be hard to link from
> doxygen?  By the way, a file called "jargon" seemed like a better idea than
> e.g. a "design_patterns" file or a section in AVClass.  I've rewritten the
> document completely based on your feedback - same markdown file for now,
> but happy to move/reformat.

If this is the case, probably we should move the files to a dedicated
directory (doxygen?) to avoid to mix too many things in the same
bundle (can be done as a separated patch though since we might think
about what we really want to include in the doxygen docs).

> The points below should be addressed by the new patch, so I'll let that
> speak for itself.  But there's a general issue that's worth mentioning...
> 

> Technically, it sounds like a more accurate description would be "Context
> is an FFmpeg convention that has become fairly rigorous over the years".
> But IMHO readers would uncharitably read that as "Context is some weird
> FFmpeg thing they're stuck with because they picked a pre-OOP language".
> Arguing "Context is a design pattern that groups objects by lifespan"
> emphasises the lessons a newbie can take from FFmpeg and use elsewhere,
> so they get more value from the time they spent reading the document.
> I've tried to write the document to start with the more useful argument,
> then gradually ease in to the more accurate one.

But, I don't think this is really something very rigourous, because it
is used in different "contexts" with sligthly different features
(e.g. you can have a structure named "context" but without an AVClass
or options).

And it's not really about lifespan, and not really specific for
FFmpeg, in C programming this is used to provide a "context" for
several "methods" operating on a given struct - so basically a light
implementation of an object-oriented-based API.

[...]
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2 1/3] doc: Explain what "context" means
  2024-04-20 12:19   ` [FFmpeg-devel] [PATCH v2 " Andrew Sayers
  2024-04-20 12:19     ` [FFmpeg-devel] [PATCH v2 2/3] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
  2024-04-20 12:19     ` [FFmpeg-devel] [PATCH v2 3/3] all: Link to "context" from all contexts with documentation Andrew Sayers
@ 2024-04-20 16:48     ` Stefano Sabatini
  2024-04-20 22:17       ` Andrew Sayers
  2 siblings, 1 reply; 84+ messages in thread
From: Stefano Sabatini @ 2024-04-20 16:48 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andrew Sayers

On date Saturday 2024-04-20 13:19:41 +0100, Andrew Sayers wrote:
> 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.

I'd skip the mention of a design pattern since this is about the
jargon.

So a simplified variant would be:

A "context" is a a structure used to store information
(e.g. configuration and/or internal state) for a series of operations
working on the same data.

> +
> +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`.

I still find this overly complex, I would rather use a typical example
of AVCodecContext for encoding or decoding or something even simpler
(for example md5.h).

About the internal "private" context, this is mostly relevant for
FFmpeg development, and not really useful for API users (basically
they don't even need to know about the private data).

For example all they need to know is that for AVCodecContext generic
options they can set the fields in the context itself, or use
AVOptions, but they can only use AVOptions for "private" options.

We are not still enforcing the use of AVOption to set all options,
although we might want in the future.

> +
> +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.
> +

I like this section, looks useful to explain the internals.

> +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.

But again, I'm confused by this since it's confusing two levels:
internal API development and API usage. When you write "may want to
use" it seems to refer to the former, but the user should not really
care about this (unless he wants to know how the internal
implementation works).

In fact, while one user might want to use the FFmpeg API as a generic
development toolkit (and therefore create its own custom API with
AVClass and AVOptions) I don't think this is really very common.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2 1/3] doc: Explain what "context" means
  2024-04-20 16:48     ` [FFmpeg-devel] [PATCH v2 1/3] doc: Explain what "context" means Stefano Sabatini
@ 2024-04-20 22:17       ` Andrew Sayers
  2024-04-22  8:02         ` Stefano Sabatini
  0 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-04-20 22:17 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Sat, Apr 20, 2024 at 06:48:32PM +0200, Stefano Sabatini wrote:
> On date Saturday 2024-04-20 13:19:41 +0100, Andrew Sayers wrote:
> > 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.
> 
> I'd skip the mention of a design pattern since this is about the
> jargon.
> 
> So a simplified variant would be:
> 
> A "context" is a a structure used to store information
> (e.g. configuration and/or internal state) for a series of operations
> working on the same data.

I think there's a pattern to the problems I'm having in this thread -
*anchoring effects*.

If you ask someone "is 5 a big number?" then "is 5 thousand a big number?",
they'll probably say "yes" to the second question.  But if you ask them
"is 5 billian a big number?" then "is 5 thousand a big number?", they'll
probably say "no".  In each case, their concept of "bigness" has been
anchored by the first question you asked.

When I originally tried to learn FFmpeg back in the day, I got nowhere with my
default OOP mindset.  It wasn't until I thought to read the examples with a
procedural mindset that it started making any sense, and I think that has
*anchored* my mental model of FFmpeg to a mindset that made it hard to think
deeply about its object-oriented bits.

Yesterday I would have agreed this was just one piece of jargon that needed
pinning down.  But if other people have similarly mis-anchored themselves,
this question might need to be a bit easier for them to find.

> 
> > +
> > +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`.
> 
> I still find this overly complex, I would rather use a typical example
> of AVCodecContext for encoding or decoding or something even simpler
> (for example md5.h).
> 
> About the internal "private" context, this is mostly relevant for
> FFmpeg development, and not really useful for API users (basically
> they don't even need to know about the private data).
> 
> For example all they need to know is that for AVCodecContext generic
> options they can set the fields in the context itself, or use
> AVOptions, but they can only use AVOptions for "private" options.
> 
> We are not still enforcing the use of AVOption to set all options,
> although we might want in the future.

I think you're saying that "context structure" is synonymous with "context",
and is FFmpeg's term for a common style of C structure; but that other projects
might use a different word, or write that style of struct without naming it at
all?  If so, I'd argue it's important to give people a non-FFmpeg-specific
*anchor*, but that we should expand the later FFmpeg-specific example, so they
have an idea of how it's used around here.

A quick grep of the source suggests that "private context" is an accepted
synonym for "internal context".  And it sounds like it fulfils the same purpose
as C++ "private" access.  If both statements are true, then yes it doesn't need
to go in the example, and the whole topic can be cut down to a line like "the
main context is for public members, the private context is for private members".
Sound good?

If we have public and private members, and then AVOption members are a third
thing, the document should probably address the natural assumption that they're
equivalent to C++ "protected" members (i.e. not fully private to the class, but
not fully open to the public).  How about "It might help to think of
AVOption-accessible public members as having 'protected' access, in that you
should access them through the AVOptions API unless you know what you're
doing.  This rule isn't always followed in practice, especially in older code"?

> 
> > +
> > +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.
> > +
> 
> I like this section, looks useful to explain the internals.
> 
> > +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.
> 
> But again, I'm confused by this since it's confusing two levels:
> internal API development and API usage. When you write "may want to
> use" it seems to refer to the former, but the user should not really
> care about this (unless he wants to know how the internal
> implementation works).
> 
> In fact, while one user might want to use the FFmpeg API as a generic
> development toolkit (and therefore create its own custom API with
> AVClass and AVOptions) I don't think this is really very common.

I think this is another anchoring problem on my part.  The AVOptions docs[1]
describe how to add AVOptions in accessible language that made me think it was
aimed at ordinary programmers who happen to use FFmpeg.  Would it be better for
the line below "Implementing AVOptions" on that page to say something like:

 This section describes how to add AVOptions capabilities to a struct.
+It is intended for developers of new FFmpeg libraries, but use outside of FFmpeg
+is also possible.

If so, I'll make a separate patch for that and rewrite the document to match.

	- Andrew Sayers

[1] https://ffmpeg.org/doxygen/trunk/group__avoptions.html#details
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2 1/3] doc: Explain what "context" means
  2024-04-20 22:17       ` Andrew Sayers
@ 2024-04-22  8:02         ` Stefano Sabatini
  2024-04-22 15:56           ` [FFmpeg-devel] [PATCH v3 0/3] all: Link to "context" from all contexts with documentation Andrew Sayers
  0 siblings, 1 reply; 84+ messages in thread
From: Stefano Sabatini @ 2024-04-22  8:02 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On date Saturday 2024-04-20 23:17:57 +0100, Andrew Sayers wrote:
> On Sat, Apr 20, 2024 at 06:48:32PM +0200, Stefano Sabatini wrote:
> > On date Saturday 2024-04-20 13:19:41 +0100, Andrew Sayers wrote:
> > > 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.
> > 
> > I'd skip the mention of a design pattern since this is about the
> > jargon.
> > 
> > So a simplified variant would be:
> > 
> > A "context" is a a structure used to store information
> > (e.g. configuration and/or internal state) for a series of operations
> > working on the same data.
> 
> I think there's a pattern to the problems I'm having in this thread -
> *anchoring effects*.
> 
> If you ask someone "is 5 a big number?" then "is 5 thousand a big number?",
> they'll probably say "yes" to the second question.  But if you ask them
> "is 5 billian a big number?" then "is 5 thousand a big number?", they'll
> probably say "no".  In each case, their concept of "bigness" has been
> anchored by the first question you asked.
> 
> When I originally tried to learn FFmpeg back in the day, I got nowhere with my
> default OOP mindset.  It wasn't until I thought to read the examples with a
> procedural mindset that it started making any sense, and I think that has
> *anchored* my mental model of FFmpeg to a mindset that made it hard to think
> deeply about its object-oriented bits.
> 
> Yesterday I would have agreed this was just one piece of jargon that needed
> pinning down.  But if other people have similarly mis-anchored themselves,
> this question might need to be a bit easier for them to find.
> 
[...]
> > About the internal "private" context, this is mostly relevant for
> > FFmpeg development, and not really useful for API users (basically
> > they don't even need to know about the private data).
> > 
> > For example all they need to know is that for AVCodecContext generic
> > options they can set the fields in the context itself, or use
> > AVOptions, but they can only use AVOptions for "private" options.
> > 
> > We are not still enforcing the use of AVOption to set all options,
> > although we might want in the future.
> 

> I think you're saying that "context structure" is synonymous with "context",
> and is FFmpeg's term for a common style of C structure; but that other projects
> might use a different word, or write that style of struct without naming it at
> all?

Correct, althought this style is pretty common in plain C and there
are some commonly used conventions (e.g. the first parameter of the
related functions is usually the "context") but there is no common
jargon.

Examples:
https://github.com/freeswitch/sofia-sip/blob/master/libsofia-sip-ua/nua/nua_client.h
https://github.com/GNOME/glib/blob/main/gio/gsettings.h
https://code.videolan.org/videolan/x264/-/blob/master/x264.h?ref_type=heads

The meaning of "context" in FFmpeg maps pretty well on the meaning of
the English term (provides the context for a given operation needing
to work on the same data and with a changing state).

> If so, I'd argue it's important to give people a non-FFmpeg-specific
> *anchor*, but that we should expand the later FFmpeg-specific example, so they
> have an idea of how it's used around here.
> 

> A quick grep of the source suggests that "private context" is an accepted
> synonym for "internal context".  And it sounds like it fulfils the same purpose
> as C++ "private" access.  If both statements are true, then yes it doesn't need
> to go in the example, and the whole topic can be cut down to a line like "the
> main context is for public members, the private context is for private members".
> Sound good?

The "internal context" was added to specify options which are not
already covered in the "generic" options. Initially the options were
only specified in the "global" public context, as fields in the
generic structure (e.g. AVCodecContext for encoding/decoding).

One of the problems was that we needed to query the options - for
example so that you can print all the options with ffmpeg -help
encoder=libx264, so AVOptions were added to query those fields through
some form of rudimetary "introspection" (the AVOptions API implies
that there is a struct containing the offsets of the fields, together
with other metadata - a description, a type, and other data to perform
validation).

Later as more codecs/formats were added, there was the need to support
options only specified for specific elements. Such options were stored
in a private context.

In summary:
> the main context is for public members, the private context is for private members

This is correct with the clarification that members correspond to the
options the user can set/get on the affected component (encoder,
decoder, muxers, demuxers, filters etc) using the AVOptions API.

> 
> If we have public and private members, and then AVOption members are a third
> thing, the document should probably address the natural assumption that they're
> equivalent to C++ "protected" members (i.e. not fully private to the class, but
> not fully open to the public).  How about "It might help to think of
> AVOption-accessible public members as having 'protected' access, in that you
> should access them through the AVOptions API unless you know what you're
> doing.  This rule isn't always followed in practice, especially in older code"?

On the other hand, I'm worried to adopt the OOP terminology, as this
might convey the wrong impression that there is a complete OOP
internal implementation or that there is a perfect mapping with OOP
concepts. Also a pure C programmer might not be familiar with the OOP
terminology, and this might be confusing to her.

For example, the main reason for private options was not really to
make them protected, but rather to make it possible to set
component-specific (aka private) options. For setting generic options,
it's still pretty common to set the fields directly, although this has
several disadvantages (no validation is performed, and this is not
robust to API changes - e.g. in case the field is moved in the
structure).

Private options fields direct access is technically not possible
(i.e. you cannot set an option for the x264 encoder by directly
accessing the private x264 context, since this is an opaque field), so
this is not even a concern.

[...]
> > > +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.
> > 
> > But again, I'm confused by this since it's confusing two levels:
> > internal API development and API usage. When you write "may want to
> > use" it seems to refer to the former, but the user should not really
> > care about this (unless he wants to know how the internal
> > implementation works).
> > 
> > In fact, while one user might want to use the FFmpeg API as a generic
> > development toolkit (and therefore create its own custom API with
> > AVClass and AVOptions) I don't think this is really very common.
> 

> I think this is another anchoring problem on my part.  The AVOptions docs[1]
> describe how to add AVOptions in accessible language that made me think it was
> aimed at ordinary programmers who happen to use FFmpeg.  Would it be better for
> the line below "Implementing AVOptions" on that page to say something like:
> 
>  This section describes how to add AVOptions capabilities to a struct.

> +It is intended for developers of new FFmpeg libraries, but use outside of FFmpeg
> +is also possible.

Yes, but I'd say instead:

It is intended for developers of FFmpeg/internal FFmpeg development,
...

(since usually FFmpeg is extended by adding new API - e.g. new headers
or new functions - not necessarily libraries).

> 
> If so, I'll make a separate patch for that and rewrite the document to match.

Thanks.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v3 0/3] all: Link to "context" from all contexts with documentation
  2024-04-22  8:02         ` Stefano Sabatini
@ 2024-04-22 15:56           ` Andrew Sayers
  2024-04-22 15:56             ` [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means Andrew Sayers
                               ` (2 more replies)
  0 siblings, 3 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-04-22 15:56 UTC (permalink / raw)
  To: ffmpeg-devel

I've updated the link in patch 1 to point to this thread instead of your
original post.

I've heavily rewritten "jargon.md" and renamed it to "context.md", reflecting
how it's more important than I previously realised.  I think it's safe to leave
it in markdown format in doc/ now - it shouldn't open the floodgates to more
files, and that seems like a safe enough bridge to cross when we come to it.

The links in patches 2 and 3 have been updated to point to the new file, but
are otherwise unchanged.

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means
  2024-04-22 15:56           ` [FFmpeg-devel] [PATCH v3 0/3] all: Link to "context" from all contexts with documentation Andrew Sayers
@ 2024-04-22 15:56             ` Andrew Sayers
  2024-04-22 17:05               ` Stefano Sabatini
  2024-04-22 15:56             ` [FFmpeg-devel] [PATCH v3 2/3] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
  2024-04-22 15:56             ` [FFmpeg-devel] [PATCH v3 3/3] all: Link to "context" from all contexts with documentation Andrew Sayers
  2 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-04-22 15:56 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Derived from detailed explanations kindly provided by Stefano Sabatini:
https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
---
 doc/context.md | 276 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 276 insertions(+)
 create mode 100644 doc/context.md

diff --git a/doc/context.md b/doc/context.md
new file mode 100644
index 0000000000..73caacf54f
--- /dev/null
+++ b/doc/context.md
@@ -0,0 +1,276 @@
+# Context-oriented programming
+
+Like many C projects, FFmpeg has adopted the subset of object-oriented techniques
+that help solve its problems.  Object-like structures are called "contexts",
+and this document provides a general introduction to how they work.
+
+Object-oriented programming usually focusses on *access* as a primary concern.
+For example, members of an object are visibly designated "private", "constant"
+etc. to control how they are accessed.  *Reflection* is a secondary concern,
+where it is provided at all.  For example, C++ has no built-in way to get a
+string containing the name of a variable.
+
+Reflection is extremely important for FFmpeg, because user-facing options are
+implemented by reflecting state at runtime.  Limiting access is a secondary
+concern, mainly important for ensuring implementation details can change
+between versions.
+
+An object-oriented programmer learning FFmpeg should be careful not to fixate on
+FFmpeg's access control features, nor to overlook its reflection capabilities.
+Both are present, but have been given the level of focus appropriate for the task.
+
+## Example: modify text then print it
+
+The example below shows a context structure that receives input strings,
+modifies them in some context-dependant way, then prints them to a specified
+filehandle.
+
+```c
+/**
+ * Type information, accessible at runtime.
+ *
+ * Useful when configuring objects.
+ */
+enum ModifyThenPrintDialect {
+    MODIFY_THEN_PRINT_PLAIN_TEXT = 0,
+    MODIFY_THEN_PRINT_REGEX      = 1,
+    MODIFY_THEN_PRINT_REGEX_PCRE = 2
+};
+
+/**
+ * User-facing information about types
+ *
+ * Useful for describing contexts to the user.
+ */
+static const char* ModifyThenPrintDialectName[] = {
+    "plain text",
+    "regular expression",
+    "Perl-compatible regular expression"
+};
+
+/**
+ * Context for functions that modify strings before printing them
+ */
+struct ModifyThenPrintContext {
+
+    /**
+     * Information about the type of this particular instance
+     *
+     * Object-oriented programs would probably represent this example
+     * as a sub-class, but some instance-specific functionality
+     * behaves more like a mixin.
+     */
+    enum ModifyThenPrintDialect dialect;
+
+    /**
+     * Internal context
+     *
+     * Object-oriented programs would put private members in here,
+     * but could also use it to store a virtual function table
+     * or other "invisible" information.
+     */
+    void* priv_data;
+
+    /**
+     * User-configurable options
+     *
+     * Best set through an API, but can be set directly if necessary
+     *
+     * Data from users needs to be validated before it's set, and the API
+     * might e.g. want to update some internal buffer when these change.
+     * Setting this directly is always less robust than using an API,
+     * but might be worthwhile if you're willing to spend the time checking
+     * for edge cases, and don't mind your code misbehaving if future
+     * versions change the API but not the structure.
+     *
+     * Object-oriented programs would likely make these protected members,
+     * initialised in a constructor and accessed with getters and setters.
+     * Making them user-configurable would be left to the programmer.
+     */
+    char *replace_this;
+    char *with_this;
+
+    /**
+     * Programmer-configurable variable
+     *
+     * Object-oriented programs would represent this as a public member.
+     */
+    FILE *out;
+
+};
+
+/**
+ * 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.
+ *
+ * Object-oriented programs would likely represent this as an
+ * allocator function and a constructor.
+ */
+int ModifyThenPrintContext_alloc_context(struct ModifyThenPrintContext **ctx,
+                                         enum ModifyThenPrintDialect dialect,
+                                         FILE *out);
+
+/**
+ * Uninitialize and deallocate a ModifyThenPrintContext
+ *
+ * This does any work required by the internal context (e.g. deallocating
+ * `priv_data`), then deallocates the main context itself.
+ *
+ * Object-oriented programs would likely represent this as a
+ * destructor and a deallocator.
+ */
+int ModifyThenPrintContext_free(struct ModifyThenPrintContext *ctx);
+
+/**
+ * Configure a ModifyThenPrintContext
+ *
+ * This checks the arguments are valid in the context's dialect,
+ * then updates the options as necessary
+ *
+ * Object-oriented programs would likely represent this as a
+ * collection of setter functions.
+ */
+int ModifyThenPrintContext_configure(struct ModifyThenPrintContext *ctx,
+                                     char* replace_this,
+                                     char* with_this);
+
+/**
+ * Print the contents of a ModifyThenPrintContext to a filehandle
+ *
+ * Provides human-readable information about keys and values.
+ *
+ * Object-oriented programs would likely represent this with some kind of
+ * `serialise` operation.
+ */
+int ModifyThenPrintContext_dump(struct ModifyThenPrintContext **ctx,
+                                FILE *dump_fh);
+
+/**
+ * Print a single message
+ *
+ * Object-oriented programs would likely represent this with a member function.
+ */
+int ModifyThenPrintContext_print(struct ModifyThenPrintContext *ctx,
+                                 char *msg);
+
+/**
+ * How this context might be used in practice
+ */
+int print_hello_world()
+{
+
+    int ret = 0;
+
+    struct ModifyThenPrintContext *ctx;
+
+    if ( ModifyThenPrintContext_alloc_context( &ctx, MODIFY_THEN_PRINT_REGEX, stdout ) < 0 ) {
+        ret = -1;
+        goto EXIT_WITHOUT_CLEANUP;
+    }
+
+    if ( ModifyThenPrintContext_configure(ctx, "Hi|Hullo", "Hello") < 0 ) {
+        ret = -1;
+        goto FINISH;
+    }
+
+    if ( ModifyThenPrintContext_print( ctx, "Hi, world!\n" ) < 0 ) {
+        ret = -1;
+        goto FINISH;
+    }
+
+    if ( ModifyThenPrintContext_print( ctx, "Hullo, world!\n" ) < 0 ) {
+        ret = -1;
+        goto FINISH;
+    }
+
+    FINISH:
+    if ( ModifyThenPrintContext_free( ctx ) ) {
+        ret = -1;
+        goto EXIT_WITHOUT_CLEANUP;
+    }
+
+    EXIT_WITHOUT_CLEANUP:
+    return ret;
+
+}
+```
+
+## FFmpeg context structures
+
+The example above is a generic example of a context structure and its
+associated functions.  Some FFmpeg contexts are no more complex than
+that example, just as some objects are just key/value stores with some
+functions attached.  But here are some examples to show the variety of
+contexts available in FFmpeg.
+
+AVHashContext presents a generic API for hashing data.  @ref hash.h
+"Its associated functions" show how to create, use and destroy a hash.
+The exact algorithm is specified by passing a string to av_hash_alloc(),
+and the list of strings can be retrieved from av_hash_names().
+Algorithm-specific internal context is stored in AVHashContext::ctx.
+
+AVCodecContext is a complex member representing data about an encoding or
+decoding session.  @ref avcodec.h "Its associated functions" provide an
+abstract interface to encode and decode data.  Like most widely-used contexts,
+its first member is an AVClass pointer containing instance-specific information.
+That means it's an *AVClass context structure* (discussed in more detail below).
+
+X264Context contains the internal context for an AVCodecContext that uses
+the x264 library.  @ref libx264.c "Its associated functions" provide a concrete
+implementation for interacting with libx264.  This class is not directly
+accessible through FFmpeg's public interface, so unlike AVCodecContext it can
+change significantly between releases.
+
+## Reflection with AVClass and AVOptions
+
+An *AVClass context structure* is a context whose first member is an AVClass
+that reflects its contents.  An *@ref avoptions "AVOptions"-enabled struct*
+is a structure which reflects its contents using the @ref avoptions "AVOptions"
+API.  These terms have become synonymous in modern usage, but you might notice
+some distinction when looking at code written after AVClass was developed but
+before @ref avoptions "AVOptions" was added.
+
+At first glance, an object-oriented programmer might be tempted to look at AVClass
+as a base class that contexts inherit from.  But unlike a base class, an AVClass
+doesn't imply any theoretical relationship between objects, and contexts of the
+same type will often have different AVClass values.  It's even theoretically possible
+for a single AVClass to be shared between contexts of different types.  A better
+analogy would be to [C++ concepts](https://en.wikipedia.org/wiki/Concepts_(C%2B%2B))
+or [Java interfaces](https://en.wikipedia.org/wiki/Interface_(Java)).
+
+To understand how AVClass and @ref avoptions "AVOptions" work,
+consider the requirements for a `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 to users about unsupported options
+
+Common encoder options like "bitrate" need to be stored in AVCodecContext itself
+to avoid duplicating code, while encoder-specific options like "profile" have to
+be stored in the X264Context instance stored in AVCodecContext::priv_data.
+But both need to be presented to users (along with help text, default values etc.)
+in a way that makes it easy to build user interfaces to get and set those options.
+
+A context's AVClass member contains a list of AVOption objects, describing
+the user-configurable members of the class.  It also contains functions to
+iterate through a tree of AVClass objects representing internal context either
+for the current object or for any class that could potentially exist in the
+current version of FFmpeg.
+
+The @ref avoptions "AVOptions" API accepts any AVClass context structure,
+looks through its AVOption data, and uses that to examine, introspect, and modify
+the structure.  Because the API doesn't contain any type-specific information,
+it can be used to create a general user interface that adapts automatically
+when e.g. a new version of FFmpeg adds a new configuration option.
+
+## Summary
+
+FFmpeg uses "contexts" in ways that are often resemble object-oriented programming.
+But it focuses less on encapsulation within arbitrarily complex systems,
+and more on providing reflectivity to make pleasant user interfaces.
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v3 2/3] lavu: Clarify relationship between AVClass, AVOption and context
  2024-04-22 15:56           ` [FFmpeg-devel] [PATCH v3 0/3] all: Link to "context" from all contexts with documentation Andrew Sayers
  2024-04-22 15:56             ` [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means Andrew Sayers
@ 2024-04-22 15:56             ` Andrew Sayers
  2024-04-22 15:56             ` [FFmpeg-devel] [PATCH v3 3/3] all: Link to "context" from all contexts with documentation Andrew Sayers
  2 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-04-22 15:56 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

---
 libavutil/log.h | 11 ++++++++---
 libavutil/opt.h |  7 ++++---
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/libavutil/log.h b/libavutil/log.h
index ab7ceabe22..cfbf416679 100644
--- a/libavutil/log.h
+++ b/libavutil/log.h
@@ -59,9 +59,14 @@ typedef enum {
 struct AVOptionRanges;
 
 /**
- * Describe the class of an AVClass context structure. That is an
- * arbitrary struct of which the first field is a pointer to an
- * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.).
+ * Metadata about an arbitrary data structure
+ *
+ * A @ref md_doc_2context "context struct" whose first member is a pointer
+ * to an AVClass object is called an "AVClass context structure"
+ * (e.g. AVCodecContext, AVFormatContext etc.).
+ *
+ * AVClass is often combined with @ref avoptions "AVOptions" to create
+ * "AVOptions-enabled structs" that can be easily configured by users.
  */
 typedef struct AVClass {
     /**
diff --git a/libavutil/opt.h b/libavutil/opt.h
index e6013662f6..b817d15554 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -39,9 +39,10 @@
  * @defgroup avoptions AVOptions
  * @ingroup lavu_data
  * @{
- * AVOptions provide a generic system to declare options on arbitrary structs
- * ("objects"). An option can have a help text, a type and a range of possible
- * values. Options may then be enumerated, read and written to.
+ * Builds on AVClass, adding a generic system to declare options.
+ *
+ * An option can have a help text, a type and a range of possible values.
+ * Options may then be enumerated, read and written to.
  *
  * There are two modes of access to members of AVOption and its child structs.
  * One is called 'native access', and refers to access from the code that
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v3 3/3] all: Link to "context" from all contexts with documentation
  2024-04-22 15:56           ` [FFmpeg-devel] [PATCH v3 0/3] all: Link to "context" from all contexts with documentation Andrew Sayers
  2024-04-22 15:56             ` [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means Andrew Sayers
  2024-04-22 15:56             ` [FFmpeg-devel] [PATCH v3 2/3] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
@ 2024-04-22 15:56             ` Andrew Sayers
  2 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-04-22 15:56 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Some headings needed to be rewritten to accomodate the text,
(hopefully) without changing the meaning.
---
 libavcodec/aacdec.h              |  2 +-
 libavcodec/aacenc.h              |  2 +-
 libavcodec/ac3enc.h              |  2 +-
 libavcodec/amfenc.h              |  2 +-
 libavcodec/atrac.h               |  2 +-
 libavcodec/avcodec.h             |  3 ++-
 libavcodec/bsf.h                 |  2 +-
 libavcodec/d3d11va.h             |  3 +--
 libavcodec/mediacodec.h          |  2 +-
 libavcodec/qsv.h                 |  6 ++++--
 libavcodec/sbr.h                 |  2 +-
 libavcodec/vdpau.h               |  3 ++-
 libavcodec/videotoolbox.h        |  5 +++--
 libavfilter/avfilter.h           |  2 +-
 libavformat/avformat.h           |  3 ++-
 libavformat/avio.h               |  3 ++-
 libavutil/hwcontext.h            | 21 ++++++++++++---------
 libavutil/hwcontext_cuda.h       |  2 +-
 libavutil/hwcontext_d3d11va.h    |  4 ++--
 libavutil/hwcontext_d3d12va.h    |  6 +++---
 libavutil/hwcontext_drm.h        |  2 +-
 libavutil/hwcontext_dxva2.h      |  4 ++--
 libavutil/hwcontext_mediacodec.h |  2 +-
 libavutil/hwcontext_opencl.h     |  4 ++--
 libavutil/hwcontext_qsv.h        |  4 ++--
 libavutil/hwcontext_vaapi.h      |  6 +++---
 libavutil/hwcontext_vdpau.h      |  2 +-
 libavutil/hwcontext_vulkan.h     |  4 ++--
 28 files changed, 57 insertions(+), 48 deletions(-)

diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 1b245f9258..715886ae07 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -181,7 +181,7 @@ typedef struct DynamicRangeControl {
 } DynamicRangeControl;
 
 /**
- * main AAC decoding context
+ * main AAC decoding @ref md_doc_2context "context"
  */
 typedef struct AACDecContext {
     const struct AVClass  *class;
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index 8899f90ac7..755f0495a2 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -193,7 +193,7 @@ typedef struct AACPCEInfo {
 } AACPCEInfo;
 
 /**
- * AAC encoder context
+ * AAC encoder @ref md_doc_2context "context"
  */
 typedef struct AACEncContext {
     AVClass *av_class;
diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
index 30812617cc..c725007077 100644
--- a/libavcodec/ac3enc.h
+++ b/libavcodec/ac3enc.h
@@ -152,7 +152,7 @@ typedef struct AC3Block {
 } AC3Block;
 
 /**
- * AC-3 encoder private context.
+ * AC-3 encoder private @ref md_doc_2context "context"
  */
 typedef struct AC3EncodeContext {
     AVClass *av_class;                      ///< AVClass used for AVOption
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
index 2dbd378ef8..f142ede63a 100644
--- a/libavcodec/amfenc.h
+++ b/libavcodec/amfenc.h
@@ -43,7 +43,7 @@ typedef struct AmfTraceWriter {
 } AmfTraceWriter;
 
 /**
-* AMF encoder context
+* AMF encoder @ref md_doc_2context "context"
 */
 
 typedef struct AmfContext {
diff --git a/libavcodec/atrac.h b/libavcodec/atrac.h
index 05208bbee6..1527e376a9 100644
--- a/libavcodec/atrac.h
+++ b/libavcodec/atrac.h
@@ -39,7 +39,7 @@ typedef struct AtracGainInfo {
 } AtracGainInfo;
 
 /**
- *  Gain compensation context structure.
+ *  Gain compensation @ref md_doc_2context "context"
  */
 typedef struct AtracGCContext {
     float   gain_tab1[16];  ///< gain compensation level table
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 968009a192..9180fedca7 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -430,7 +430,8 @@ typedef struct RcOverride{
 #define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0)
 
 /**
- * main external API structure.
+ * @ref md_doc_2context "Context" for an encode or decode session
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
index a09c69f242..bf79afa7cc 100644
--- a/libavcodec/bsf.h
+++ b/libavcodec/bsf.h
@@ -56,7 +56,7 @@
  */
 
 /**
- * The bitstream filter state.
+ * Bitstream filter @ref md_doc_2context "context"
  *
  * This struct must be allocated with av_bsf_alloc() and freed with
  * av_bsf_free().
diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
index 27f40e5519..ec0c472ab9 100644
--- a/libavcodec/d3d11va.h
+++ b/libavcodec/d3d11va.h
@@ -46,8 +46,7 @@
  */
 
 /**
- * This structure is used to provides the necessary configurations and data
- * to the Direct3D11 FFmpeg HWAccel implementation.
+ * @ref md_doc_2context "Context" for the Direct3D11 FFmpeg HWAccel implementation
  *
  * The application must make it available as AVCodecContext.hwaccel_context.
  *
diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
index 4e9b56a618..9967a7cfb3 100644
--- a/libavcodec/mediacodec.h
+++ b/libavcodec/mediacodec.h
@@ -26,7 +26,7 @@
 #include "libavcodec/avcodec.h"
 
 /**
- * This structure holds a reference to a android/view/Surface object that will
+ * @ref md_doc_2context "Context" for the android/view/Surface object that will
  * be used as output by the decoder.
  *
  */
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index c156b08d07..8b8160a4b1 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -26,8 +26,10 @@
 #include "libavutil/buffer.h"
 
 /**
- * This struct is used for communicating QSV parameters between libavcodec and
- * the caller. It is managed by the caller and must be assigned to
+ * @ref md_doc_2context "Context" for communicating QSV parameters between libavcodec
+ * and the caller.
+ *
+ * It is managed by the caller and must be assigned to
  * AVCodecContext.hwaccel_context.
  * - decoding: hwaccel_context must be set on return from the get_format()
  *             callback
diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
index fe3a39603a..98ad9024a9 100644
--- a/libavcodec/sbr.h
+++ b/libavcodec/sbr.h
@@ -116,7 +116,7 @@ typedef struct SBRData {
 typedef struct SpectralBandReplication SpectralBandReplication;
 
 /**
- * aacsbr functions pointers
+ * aacsbr functions pointer @ref md_doc_2context "context"
  */
 typedef struct AACSBRContext {
     int (*sbr_lf_gen)(SpectralBandReplication *sbr,
diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
index 8021c25761..227b85727d 100644
--- a/libavcodec/vdpau.h
+++ b/libavcodec/vdpau.h
@@ -64,8 +64,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
                                const VdpBitstreamBuffer *);
 
 /**
- * This structure is used to share data between the libavcodec library and
+ * @ref md_doc_2context "Context" to share data between the libavcodec library and
  * the client video application.
+ *
  * This structure will be allocated and stored in AVCodecContext.hwaccel_context
  * by av_vdpau_bind_context(). Members can be set by the user once
  * during initialization or through each AVCodecContext.get_buffer()
diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
index d68d76e400..f15e79f325 100644
--- a/libavcodec/videotoolbox.h
+++ b/libavcodec/videotoolbox.h
@@ -49,8 +49,9 @@
 #include "libavutil/attributes.h"
 
 /**
- * This struct holds all the information that needs to be passed
- * between the caller and libavcodec for initializing Videotoolbox decoding.
+ * @ref md_doc_2context "Context" for information passed between the caller and libavcodec
+ * for initializing Videotoolbox decoding.
+ *
  * Its size is not a part of the public ABI, it must be allocated with
  * av_videotoolbox_alloc_context() and freed with av_free().
  */
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index a34e61f23c..54b5f9dc43 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -403,7 +403,7 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
  */
 #define AVFILTER_THREAD_SLICE (1 << 0)
 
-/** An instance of a filter */
+/** @ref md_doc_2context "Context" for a filter */
 struct AVFilterContext {
     const AVClass *av_class;        ///< needed for av_log() and filters common options
 
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 8afdcd9fd0..28243c06c4 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1241,7 +1241,8 @@ enum AVDurationEstimationMethod {
 };
 
 /**
- * Format I/O context.
+ * Format I/O @ref md_doc_2context "context"
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavformat/avio.h b/libavformat/avio.h
index ebf611187d..b525c93194 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -146,7 +146,8 @@ enum AVIODataMarkerType {
 };
 
 /**
- * Bytestream IO Context.
+ * Bytestream I/O @ref md_doc_2context "context"
+ *
  * New public fields can be added with minor version bumps.
  * Removal, reordering and changes to existing public fields require
  * a major version bump.
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index bac30debae..60064cf08b 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -41,12 +41,13 @@ enum AVHWDeviceType {
 };
 
 /**
- * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
- * i.e. state that is not tied to a concrete processing configuration.
- * E.g., in an API that supports hardware-accelerated encoding and decoding,
- * this struct will (if possible) wrap the state that is common to both encoding
- * and decoding and from which specific instances of encoders or decoders can be
- * derived.
+ * @ref md_doc_2context "Context" for (hardware/vendor-specific) "high-level" state.
+ *
+ * "High-level state" is anything that is not tied to a concrete processing
+ * configuration. E.g., in an API that supports hardware-accelerated encoding
+ * and decoding, this struct will (if possible) wrap the state that is common
+ * to both encoding and decoding and from which specific instances of encoders
+ * or decoders can be derived.
  *
  * This struct is reference-counted with the AVBuffer mechanism. The
  * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
@@ -103,9 +104,11 @@ typedef struct AVHWDeviceContext {
 } AVHWDeviceContext;
 
 /**
- * This struct describes a set or pool of "hardware" frames (i.e. those with
- * data not located in normal system memory). All the frames in the pool are
- * assumed to be allocated in the same way and interchangeable.
+ * @ref md_doc_2context "context" for a pool of "hardware" frames (those with
+ * data not located in normal system memory)
+ *
+ * All the frames in the pool are assumed to be allocated in the same way and
+ * interchangeable.
  *
  * This struct is reference-counted with the AVBuffer mechanism and tied to a
  * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
index cbad434fea..e259892688 100644
--- a/libavutil/hwcontext_cuda.h
+++ b/libavutil/hwcontext_cuda.h
@@ -37,7 +37,7 @@
 typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVCUDADeviceContext {
     CUcontext cuda_ctx;
diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
index 77d2d72f1b..101d1cb6f8 100644
--- a/libavutil/hwcontext_d3d11va.h
+++ b/libavutil/hwcontext_d3d11va.h
@@ -40,7 +40,7 @@
 #include <stdint.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVD3D11VADeviceContext {
     /**
@@ -126,7 +126,7 @@ typedef struct AVD3D11FrameDescriptor {
 } AVD3D11FrameDescriptor;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVD3D11VAFramesContext {
     /**
diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
index ff06e6f2ef..c623914c2b 100644
--- a/libavutil/hwcontext_d3d12va.h
+++ b/libavutil/hwcontext_d3d12va.h
@@ -37,7 +37,7 @@
 #include <d3d12video.h>
 
 /**
- * @brief This struct is allocated as AVHWDeviceContext.hwctx
+ * @brief This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  *
  */
 typedef struct AVD3D12VADeviceContext {
@@ -78,7 +78,7 @@ typedef struct AVD3D12VADeviceContext {
 } AVD3D12VADeviceContext;
 
 /**
- * @brief This struct is used to sync d3d12 execution
+ * @brief This @ref md_doc_2context "context" is used to sync d3d12 execution
  *
  */
 typedef struct AVD3D12VASyncContext {
@@ -120,7 +120,7 @@ typedef struct AVD3D12VAFrame {
 } AVD3D12VAFrame;
 
 /**
- * @brief This struct is allocated as AVHWFramesContext.hwctx
+ * @brief This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
  *
  */
 typedef struct AVD3D12VAFramesContext {
diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
index 42709f215e..8329e69966 100644
--- a/libavutil/hwcontext_drm.h
+++ b/libavutil/hwcontext_drm.h
@@ -152,7 +152,7 @@ typedef struct AVDRMFrameDescriptor {
 /**
  * DRM device.
  *
- * Allocated as AVHWDeviceContext.hwctx.
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx.
  */
 typedef struct AVDRMDeviceContext {
     /**
diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
index e1b79bc0de..c679c16af0 100644
--- a/libavutil/hwcontext_dxva2.h
+++ b/libavutil/hwcontext_dxva2.h
@@ -34,14 +34,14 @@
 #include <dxva2api.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVDXVA2DeviceContext {
     IDirect3DDeviceManager9 *devmgr;
 } AVDXVA2DeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVDXVA2FramesContext {
     /**
diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
index fc0263cabc..e81193247b 100644
--- a/libavutil/hwcontext_mediacodec.h
+++ b/libavutil/hwcontext_mediacodec.h
@@ -22,7 +22,7 @@
 /**
  * MediaCodec details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVMediaCodecDeviceContext {
     /**
diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
index ef54486c95..7abd97db2b 100644
--- a/libavutil/hwcontext_opencl.h
+++ b/libavutil/hwcontext_opencl.h
@@ -58,7 +58,7 @@ typedef struct AVOpenCLFrameDescriptor {
 /**
  * OpenCL device details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVOpenCLDeviceContext {
     /**
@@ -84,7 +84,7 @@ typedef struct AVOpenCLDeviceContext {
 /**
  * OpenCL-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
  */
 typedef struct AVOpenCLFramesContext {
     /**
diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
index e2dba8ad83..b63ebddaef 100644
--- a/libavutil/hwcontext_qsv.h
+++ b/libavutil/hwcontext_qsv.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVQSVDeviceContext {
     mfxSession session;
@@ -48,7 +48,7 @@ typedef struct AVQSVDeviceContext {
 } AVQSVDeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVQSVFramesContext {
     mfxFrameSurface1 *surfaces;
diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
index 0b2e071cb3..4a897eb851 100644
--- a/libavutil/hwcontext_vaapi.h
+++ b/libavutil/hwcontext_vaapi.h
@@ -63,7 +63,7 @@ enum {
 /**
  * VAAPI connection details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVVAAPIDeviceContext {
     /**
@@ -83,7 +83,7 @@ typedef struct AVVAAPIDeviceContext {
 /**
  * VAAPI-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
  */
 typedef struct AVVAAPIFramesContext {
     /**
@@ -105,7 +105,7 @@ typedef struct AVVAAPIFramesContext {
 /**
  * VAAPI hardware pipeline configuration details.
  *
- * Allocated with av_hwdevice_hwconfig_alloc().
+ * This struct is allocated with av_hwdevice_hwconfig_alloc().
  */
 typedef struct AVVAAPIHWConfig {
     /**
diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
index 1b7ea1e443..e305caa595 100644
--- a/libavutil/hwcontext_vdpau.h
+++ b/libavutil/hwcontext_vdpau.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVVDPAUDeviceContext {
     VdpDevice          device;
diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
index cbbd2390c1..1869870032 100644
--- a/libavutil/hwcontext_vulkan.h
+++ b/libavutil/hwcontext_vulkan.h
@@ -39,7 +39,7 @@ typedef struct AVVkFrame AVVkFrame;
  */
 
 /**
- * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
+ * Main Vulkan @ref md_doc_2context "context", allocated as AVHWDeviceContext.hwctx.
  * All of these can be set before init to change what the context uses
  */
 typedef struct AVVulkanDeviceContext {
@@ -172,7 +172,7 @@ typedef enum AVVkFrameFlags {
 } AVVkFrameFlags;
 
 /**
- * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx, used to set pool-specific options
  */
 typedef struct AVVulkanFramesContext {
     /**
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means
  2024-04-22 15:56             ` [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means Andrew Sayers
@ 2024-04-22 17:05               ` Stefano Sabatini
  2024-04-29  9:10                 ` Andrew Sayers
  2024-04-29  9:24                 ` [FFmpeg-devel] [PATCH v4 1/4] " Andrew Sayers
  0 siblings, 2 replies; 84+ messages in thread
From: Stefano Sabatini @ 2024-04-22 17:05 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andrew Sayers

On date Monday 2024-04-22 16:56:48 +0100, Andrew Sayers wrote:
> Derived from detailed explanations kindly provided by Stefano Sabatini:
> https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
> ---
>  doc/context.md | 276 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 276 insertions(+)
>  create mode 100644 doc/context.md
> 
> diff --git a/doc/context.md b/doc/context.md
> new file mode 100644
> index 0000000000..73caacf54f
> --- /dev/null
> +++ b/doc/context.md
> @@ -0,0 +1,276 @@
> +# Context-oriented programming
> +
> +Like many C projects, FFmpeg has adopted the subset of object-oriented techniques
> +that help solve its problems.  Object-like structures are called "contexts",
> +and this document provides a general introduction to how they work.
> +
> +Object-oriented programming usually focusses on *access* as a primary concern.
> +For example, members of an object are visibly designated "private", "constant"
> +etc. to control how they are accessed.  *Reflection* is a secondary concern,
> +where it is provided at all.  For example, C++ has no built-in way to get a
> +string containing the name of a variable.
> +
> +Reflection is extremely important for FFmpeg, because user-facing options are
> +implemented by reflecting state at runtime. Limiting access is a secondary
> +concern, mainly important for ensuring implementation details can change
> +between versions.
> +
> +An object-oriented programmer learning FFmpeg should be careful not to fixate on
> +FFmpeg's access control features, nor to overlook its reflection capabilities.
> +Both are present, but have been given the level of focus appropriate for the task.
> +
> +## Example: modify text then print it
> +
> +The example below shows a context structure that receives input strings,
> +modifies them in some context-dependant way, then prints them to a specified
> +filehandle.
> +
> +```c
> +/**
> + * Type information, accessible at runtime.
> + *
> + * Useful when configuring objects.
> + */
> +enum ModifyThenPrintDialect {
> +    MODIFY_THEN_PRINT_PLAIN_TEXT = 0,
> +    MODIFY_THEN_PRINT_REGEX      = 1,
> +    MODIFY_THEN_PRINT_REGEX_PCRE = 2
> +};
> +
> +/**
> + * User-facing information about types
> + *
> + * Useful for describing contexts to the user.
> + */
> +static const char* ModifyThenPrintDialectName[] = {
> +    "plain text",
> +    "regular expression",
> +    "Perl-compatible regular expression"
> +};
> +
> +/**
> + * Context for functions that modify strings before printing them
> + */
> +struct ModifyThenPrintContext {
> +
> +    /**
> +     * Information about the type of this particular instance
> +     *
> +     * Object-oriented programs would probably represent this example
> +     * as a sub-class, but some instance-specific functionality
> +     * behaves more like a mixin.
> +     */
> +    enum ModifyThenPrintDialect dialect;
> +
> +    /**
> +     * Internal context
> +     *
> +     * Object-oriented programs would put private members in here,
> +     * but could also use it to store a virtual function table
> +     * or other "invisible" information.
> +     */

> +    void* priv_data;

style:
type *name;

here and below


> +
> +    /**
> +     * User-configurable options
> +     *
> +     * Best set through an API, but can be set directly if necessary
> +     *
> +     * Data from users needs to be validated before it's set, and the API
> +     * might e.g. want to update some internal buffer when these change.
> +     * Setting this directly is always less robust than using an API,
> +     * but might be worthwhile if you're willing to spend the time checking
> +     * for edge cases, and don't mind your code misbehaving if future
> +     * versions change the API but not the structure.
> +     *
> +     * Object-oriented programs would likely make these protected members,
> +     * initialised in a constructor and accessed with getters and setters.
> +     * Making them user-configurable would be left to the programmer.
> +     */
> +    char *replace_this;
> +    char *with_this;
> +
> +    /**
> +     * Programmer-configurable variable
> +     *
> +     * Object-oriented programs would represent this as a public member.
> +     */
> +    FILE *out;
> +
> +};
> +
> +/**
> + * 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.
> + *
> + * Object-oriented programs would likely represent this as an
> + * allocator function and a constructor.
> + */
> +int ModifyThenPrintContext_alloc_context(struct ModifyThenPrintContext **ctx,
> +                                         enum ModifyThenPrintDialect dialect,
> +                                         FILE *out);
> +
> +/**
> + * Uninitialize and deallocate a ModifyThenPrintContext
> + *
> + * This does any work required by the internal context (e.g. deallocating
> + * `priv_data`), then deallocates the main context itself.
> + *
> + * Object-oriented programs would likely represent this as a
> + * destructor and a deallocator.
> + */
> +int ModifyThenPrintContext_free(struct ModifyThenPrintContext *ctx);
> +
> +/**
> + * Configure a ModifyThenPrintContext
> + *
> + * This checks the arguments are valid in the context's dialect,
> + * then updates the options as necessary
> + *
> + * Object-oriented programs would likely represent this as a
> + * collection of setter functions.
> + */
> +int ModifyThenPrintContext_configure(struct ModifyThenPrintContext *ctx,
> +                                     char* replace_this,
> +                                     char* with_this);
> +
> +/**
> + * Print the contents of a ModifyThenPrintContext to a filehandle
> + *
> + * Provides human-readable information about keys and values.
> + *
> + * Object-oriented programs would likely represent this with some kind of
> + * `serialise` operation.
> + */
> +int ModifyThenPrintContext_dump(struct ModifyThenPrintContext **ctx,
> +                                FILE *dump_fh);
> +
> +/**
> + * Print a single message
> + *
> + * Object-oriented programs would likely represent this with a member function.
> + */
> +int ModifyThenPrintContext_print(struct ModifyThenPrintContext *ctx,
> +                                 char *msg);
> +
> +/**
> + * How this context might be used in practice
> + */
> +int print_hello_world()
> +{
> +
> +    int ret = 0;
> +
> +    struct ModifyThenPrintContext *ctx;
> +
> +    if ( ModifyThenPrintContext_alloc_context( &ctx, MODIFY_THEN_PRINT_REGEX, stdout ) < 0 ) {
> +        ret = -1;
> +        goto EXIT_WITHOUT_CLEANUP;
> +    }
> +
> +    if ( ModifyThenPrintContext_configure(ctx, "Hi|Hullo", "Hello") < 0 ) {
> +        ret = -1;
> +        goto FINISH;
> +    }
> +
> +    if ( ModifyThenPrintContext_print( ctx, "Hi, world!\n" ) < 0 ) {
> +        ret = -1;
> +        goto FINISH;
> +    }
> +
> +    if ( ModifyThenPrintContext_print( ctx, "Hullo, world!\n" ) < 0 ) {
> +        ret = -1;
> +        goto FINISH;
> +    }
> +
> +    FINISH:
> +    if ( ModifyThenPrintContext_free( ctx ) ) {
> +        ret = -1;
> +        goto EXIT_WITHOUT_CLEANUP;
> +    }
> +
> +    EXIT_WITHOUT_CLEANUP:
> +    return ret;
> +
> +}
> +```

I don't have a strong opinion, but I'd probably focus on providing a
typical example of a common API (check doc/examples). Also I see here
there is a strong focus on OOP, this might be counter-productive in
case the reader is not familiar with OOP terminology.

OTOH the content might be useful for readers coming from an OOP
background and terminology. I wonder if this content might be isolated
in a dedicated section, so that non-OOP readers can simply skip it.

But this is not a strong objection, and can be possibly reworked in a
later step.

> +
> +## FFmpeg context structures
> +
> +The example above is a generic example of a context structure and its
> +associated functions.  Some FFmpeg contexts are no more complex than
> +that example, just as some objects are just key/value stores with some
> +functions attached.  But here are some examples to show the variety of
> +contexts available in FFmpeg.
> +
> +AVHashContext presents a generic API for hashing data.  @ref hash.h
> +"Its associated functions" show how to create, use and destroy a hash.
> +The exact algorithm is specified by passing a string to av_hash_alloc(),
> +and the list of strings can be retrieved from av_hash_names().
> +Algorithm-specific internal context is stored in AVHashContext::ctx.
> +
> +AVCodecContext is a complex member representing data about an encoding or
> +decoding session.  @ref avcodec.h "Its associated functions" provide an
> +abstract interface to encode and decode data.  Like most widely-used contexts,
> +its first member is an AVClass pointer containing instance-specific information.
> +That means it's an *AVClass context structure* (discussed in more detail below).
> +
> +X264Context contains the internal context for an AVCodecContext that uses
> +the x264 library.  @ref libx264.c "Its associated functions" provide a concrete

> +implementation for interacting with libx264.  This class is not directly
> +accessible through FFmpeg's public interface, so unlike AVCodecContext it can
> +change significantly between releases.

Note: still, we are not supposed to break compatibilty, for example by
changing the private option names, or this will break both scripts
using the ff* tools and applications using the libav* libraries, since
they refer to those option names. In other words, the options names
provide the public API to interact with a specific codec.

> +## Reflection with AVClass and AVOptions
> +
> +An *AVClass context structure* is a context whose first member is an AVClass
> +that reflects its contents.  An *@ref avoptions "AVOptions"-enabled struct*
> +is a structure which reflects its contents using the @ref avoptions "AVOptions"
> +API.

"reflects its contents" is a bit too strong, we want only to be able
to set and query options on such structures. In some cases the
AVOptions API is abused also to get "properties" from the structures
(see for example the "location" option in libavformation/http.c). But
the whole content in general is not available through AVOptions, only
a specific subset which is supposed to configure the structure.

> These terms have become synonymous in modern usage, but you might notice
> +some distinction when looking at code written after AVClass was developed but
> +before @ref avoptions "AVOptions" was added.
> +
> +At first glance, an object-oriented programmer might be tempted to look at AVClass
> +as a base class that contexts inherit from.  But unlike a base class, an AVClass
> +doesn't imply any theoretical relationship between objects, and contexts of the
> +same type will often have different AVClass values.  It's even theoretically possible
> +for a single AVClass to be shared between contexts of different types.  A better
> +analogy would be to [C++ concepts](https://en.wikipedia.org/wiki/Concepts_(C%2B%2B))
> +or [Java interfaces](https://en.wikipedia.org/wiki/Interface_(Java)).
> +
> +To understand how AVClass and @ref avoptions "AVOptions" work,
> +consider the requirements for a `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

but this will be a compatiblity break for most applications and
scripts (you will notice in this case because people will complain
aloud about the breakage), so we need to be careful when changing
options following the usual deprecation dance

> +- it has to provide useful feedback to users about unsupported options
> +
> +Common encoder options like "bitrate" need to be stored in AVCodecContext itself
> +to avoid duplicating code, while encoder-specific options like "profile" have to
> +be stored in the X264Context instance stored in AVCodecContext::priv_data.

> +But both need to be presented to users (along with help text, default values etc.)
> +in a way that makes it easy to build user interfaces to get and set those options.

nit: s/easy/possible/

> +
> +A context's AVClass member contains a list of AVOption objects, describing
> +the user-configurable members of the class.  It also contains functions to
> +iterate through a tree of AVClass objects representing internal context either
> +for the current object or for any class that could potentially exist in the
> +current version of FFmpeg.
> +
> +The @ref avoptions "AVOptions" API accepts any AVClass context structure,
> +looks through its AVOption data, and uses that to examine, introspect, and modify
> +the structure.  Because the API doesn't contain any type-specific information,
> +it can be used to create a general user interface that adapts automatically
> +when e.g. a new version of FFmpeg adds a new configuration option.
> +
> +## Summary
> +

> +FFmpeg uses "contexts" in ways that are often resemble object-oriented programming.
> +But it focuses less on encapsulation within arbitrarily complex systems,
> +and more on providing reflectivity to make pleasant user interfaces.

nit++: s/pleasant//, here the point is to make them possible, we don't
know if they are pleasant :-)

[...]

Note: I'll be probably offline for one week or so.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means
  2024-04-22 17:05               ` Stefano Sabatini
@ 2024-04-29  9:10                 ` Andrew Sayers
  2024-05-02 10:03                   ` Andrew Sayers
  2024-05-05  7:29                   ` Stefano Sabatini
  2024-04-29  9:24                 ` [FFmpeg-devel] [PATCH v4 1/4] " Andrew Sayers
  1 sibling, 2 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-04-29  9:10 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Mon, Apr 22, 2024 at 07:05:12PM +0200, Stefano Sabatini wrote:
> On date Monday 2024-04-22 16:56:48 +0100, Andrew Sayers wrote:
> > Derived from detailed explanations kindly provided by Stefano Sabatini:
> > https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
> > ---
> >  doc/context.md | 276 +++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 276 insertions(+)
> >  create mode 100644 doc/context.md
> > 
> > diff --git a/doc/context.md b/doc/context.md
> > new file mode 100644
> > index 0000000000..73caacf54f
> > --- /dev/null
> > +++ b/doc/context.md
> > @@ -0,0 +1,276 @@
> > +# Context-oriented programming
> > +
> > +Like many C projects, FFmpeg has adopted the subset of object-oriented techniques
> > +that help solve its problems.  Object-like structures are called "contexts",
> > +and this document provides a general introduction to how they work.
> > +
> > +Object-oriented programming usually focusses on *access* as a primary concern.
> > +For example, members of an object are visibly designated "private", "constant"
> > +etc. to control how they are accessed.  *Reflection* is a secondary concern,
> > +where it is provided at all.  For example, C++ has no built-in way to get a
> > +string containing the name of a variable.
> > +
> > +Reflection is extremely important for FFmpeg, because user-facing options are
> > +implemented by reflecting state at runtime. Limiting access is a secondary
> > +concern, mainly important for ensuring implementation details can change
> > +between versions.
> > +
> > +An object-oriented programmer learning FFmpeg should be careful not to fixate on
> > +FFmpeg's access control features, nor to overlook its reflection capabilities.
> > +Both are present, but have been given the level of focus appropriate for the task.
> > +
> > +## Example: modify text then print it
> > +
> > +The example below shows a context structure that receives input strings,
> > +modifies them in some context-dependant way, then prints them to a specified
> > +filehandle.
> > +
> > +```c
> > +/**
> > + * Type information, accessible at runtime.
> > + *
> > + * Useful when configuring objects.
> > + */
> > +enum ModifyThenPrintDialect {
> > +    MODIFY_THEN_PRINT_PLAIN_TEXT = 0,
> > +    MODIFY_THEN_PRINT_REGEX      = 1,
> > +    MODIFY_THEN_PRINT_REGEX_PCRE = 2
> > +};
> > +
> > +/**
> > + * User-facing information about types
> > + *
> > + * Useful for describing contexts to the user.
> > + */
> > +static const char* ModifyThenPrintDialectName[] = {
> > +    "plain text",
> > +    "regular expression",
> > +    "Perl-compatible regular expression"
> > +};
> > +
> > +/**
> > + * Context for functions that modify strings before printing them
> > + */
> > +struct ModifyThenPrintContext {
> > +
> > +    /**
> > +     * Information about the type of this particular instance
> > +     *
> > +     * Object-oriented programs would probably represent this example
> > +     * as a sub-class, but some instance-specific functionality
> > +     * behaves more like a mixin.
> > +     */
> > +    enum ModifyThenPrintDialect dialect;
> > +
> > +    /**
> > +     * Internal context
> > +     *
> > +     * Object-oriented programs would put private members in here,
> > +     * but could also use it to store a virtual function table
> > +     * or other "invisible" information.
> > +     */
> 
> > +    void* priv_data;
> 
> style:
> type *name;
> 
> here and below
> 
> 
> > +
> > +    /**
> > +     * User-configurable options
> > +     *
> > +     * Best set through an API, but can be set directly if necessary
> > +     *
> > +     * Data from users needs to be validated before it's set, and the API
> > +     * might e.g. want to update some internal buffer when these change.
> > +     * Setting this directly is always less robust than using an API,
> > +     * but might be worthwhile if you're willing to spend the time checking
> > +     * for edge cases, and don't mind your code misbehaving if future
> > +     * versions change the API but not the structure.
> > +     *
> > +     * Object-oriented programs would likely make these protected members,
> > +     * initialised in a constructor and accessed with getters and setters.
> > +     * Making them user-configurable would be left to the programmer.
> > +     */
> > +    char *replace_this;
> > +    char *with_this;
> > +
> > +    /**
> > +     * Programmer-configurable variable
> > +     *
> > +     * Object-oriented programs would represent this as a public member.
> > +     */
> > +    FILE *out;
> > +
> > +};
> > +
> > +/**
> > + * 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.
> > + *
> > + * Object-oriented programs would likely represent this as an
> > + * allocator function and a constructor.
> > + */
> > +int ModifyThenPrintContext_alloc_context(struct ModifyThenPrintContext **ctx,
> > +                                         enum ModifyThenPrintDialect dialect,
> > +                                         FILE *out);
> > +
> > +/**
> > + * Uninitialize and deallocate a ModifyThenPrintContext
> > + *
> > + * This does any work required by the internal context (e.g. deallocating
> > + * `priv_data`), then deallocates the main context itself.
> > + *
> > + * Object-oriented programs would likely represent this as a
> > + * destructor and a deallocator.
> > + */
> > +int ModifyThenPrintContext_free(struct ModifyThenPrintContext *ctx);
> > +
> > +/**
> > + * Configure a ModifyThenPrintContext
> > + *
> > + * This checks the arguments are valid in the context's dialect,
> > + * then updates the options as necessary
> > + *
> > + * Object-oriented programs would likely represent this as a
> > + * collection of setter functions.
> > + */
> > +int ModifyThenPrintContext_configure(struct ModifyThenPrintContext *ctx,
> > +                                     char* replace_this,
> > +                                     char* with_this);
> > +
> > +/**
> > + * Print the contents of a ModifyThenPrintContext to a filehandle
> > + *
> > + * Provides human-readable information about keys and values.
> > + *
> > + * Object-oriented programs would likely represent this with some kind of
> > + * `serialise` operation.
> > + */
> > +int ModifyThenPrintContext_dump(struct ModifyThenPrintContext **ctx,
> > +                                FILE *dump_fh);
> > +
> > +/**
> > + * Print a single message
> > + *
> > + * Object-oriented programs would likely represent this with a member function.
> > + */
> > +int ModifyThenPrintContext_print(struct ModifyThenPrintContext *ctx,
> > +                                 char *msg);
> > +
> > +/**
> > + * How this context might be used in practice
> > + */
> > +int print_hello_world()
> > +{
> > +
> > +    int ret = 0;
> > +
> > +    struct ModifyThenPrintContext *ctx;
> > +
> > +    if ( ModifyThenPrintContext_alloc_context( &ctx, MODIFY_THEN_PRINT_REGEX, stdout ) < 0 ) {
> > +        ret = -1;
> > +        goto EXIT_WITHOUT_CLEANUP;
> > +    }
> > +
> > +    if ( ModifyThenPrintContext_configure(ctx, "Hi|Hullo", "Hello") < 0 ) {
> > +        ret = -1;
> > +        goto FINISH;
> > +    }
> > +
> > +    if ( ModifyThenPrintContext_print( ctx, "Hi, world!\n" ) < 0 ) {
> > +        ret = -1;
> > +        goto FINISH;
> > +    }
> > +
> > +    if ( ModifyThenPrintContext_print( ctx, "Hullo, world!\n" ) < 0 ) {
> > +        ret = -1;
> > +        goto FINISH;
> > +    }
> > +
> > +    FINISH:
> > +    if ( ModifyThenPrintContext_free( ctx ) ) {
> > +        ret = -1;
> > +        goto EXIT_WITHOUT_CLEANUP;
> > +    }
> > +
> > +    EXIT_WITHOUT_CLEANUP:
> > +    return ret;
> > +
> > +}
> > +```
> 
> I don't have a strong opinion, but I'd probably focus on providing a
> typical example of a common API (check doc/examples). Also I see here
> there is a strong focus on OOP, this might be counter-productive in
> case the reader is not familiar with OOP terminology.
> 
> OTOH the content might be useful for readers coming from an OOP
> background and terminology. I wonder if this content might be isolated
> in a dedicated section, so that non-OOP readers can simply skip it.
> 
> But this is not a strong objection, and can be possibly reworked in a
> later step.
> 

This is really a document for FFmpeg newbies, so we need to assume as
little prior knowledge as possible.  After a few days to think it
over, I think we should avoid assuming...

Knowledge of object-oriented programming.  For example, this should be
useful to a research mathematician with a project that involves codec
algorithms.  So the next draft should feel less like "FFmpeg for OOP
devs" and more like "FFmpeg for newbies (with some optional OOP
background reading)".

Knowing that programming doesn't *have* to be object-oriented.
OOP has become so ubiquitous nowadays, there are plenty of programmers
who will insist everything is OOP if you just speak loudly and slowly.
This is a harder problem in some ways, because someone who doesn't
understand can always re-read until they do, while someone who jumps
to the wrong conclusion will just keep reading and try to make things
fit their assumption (e.g. my earlier messages in this thread!).
So the "how it differs from OOP" stuff needs to stay fairly prominent.

Knowing anything about FFmpeg (or multimedia in general).  I like the
idea of tweaking `doc/examples` to better introduce FFmpeg
fundamentals, but explaining "context" is a steep enough learning
curve on its own - introducing concepts like "stream" and "codec" at
the same time seems like too much.

> > +
> > +## FFmpeg context structures
> > +
> > +The example above is a generic example of a context structure and its
> > +associated functions.  Some FFmpeg contexts are no more complex than
> > +that example, just as some objects are just key/value stores with some
> > +functions attached.  But here are some examples to show the variety of
> > +contexts available in FFmpeg.
> > +
> > +AVHashContext presents a generic API for hashing data.  @ref hash.h
> > +"Its associated functions" show how to create, use and destroy a hash.
> > +The exact algorithm is specified by passing a string to av_hash_alloc(),
> > +and the list of strings can be retrieved from av_hash_names().
> > +Algorithm-specific internal context is stored in AVHashContext::ctx.
> > +
> > +AVCodecContext is a complex member representing data about an encoding or
> > +decoding session.  @ref avcodec.h "Its associated functions" provide an
> > +abstract interface to encode and decode data.  Like most widely-used contexts,
> > +its first member is an AVClass pointer containing instance-specific information.
> > +That means it's an *AVClass context structure* (discussed in more detail below).
> > +
> > +X264Context contains the internal context for an AVCodecContext that uses
> > +the x264 library.  @ref libx264.c "Its associated functions" provide a concrete
> 
> > +implementation for interacting with libx264.  This class is not directly
> > +accessible through FFmpeg's public interface, so unlike AVCodecContext it can
> > +change significantly between releases.
> 
> Note: still, we are not supposed to break compatibilty, for example by
> changing the private option names, or this will break both scripts
> using the ff* tools and applications using the libav* libraries, since
> they refer to those option names. In other words, the options names
> provide the public API to interact with a specific codec.
> 
> > +## Reflection with AVClass and AVOptions
> > +
> > +An *AVClass context structure* is a context whose first member is an AVClass
> > +that reflects its contents.  An *@ref avoptions "AVOptions"-enabled struct*
> > +is a structure which reflects its contents using the @ref avoptions "AVOptions"
> > +API.
> 
> "reflects its contents" is a bit too strong, we want only to be able
> to set and query options on such structures. In some cases the
> AVOptions API is abused also to get "properties" from the structures
> (see for example the "location" option in libavformation/http.c). But
> the whole content in general is not available through AVOptions, only
> a specific subset which is supposed to configure the structure.
> 
> > These terms have become synonymous in modern usage, but you might notice
> > +some distinction when looking at code written after AVClass was developed but
> > +before @ref avoptions "AVOptions" was added.
> > +
> > +At first glance, an object-oriented programmer might be tempted to look at AVClass
> > +as a base class that contexts inherit from.  But unlike a base class, an AVClass
> > +doesn't imply any theoretical relationship between objects, and contexts of the
> > +same type will often have different AVClass values.  It's even theoretically possible
> > +for a single AVClass to be shared between contexts of different types.  A better
> > +analogy would be to [C++ concepts](https://en.wikipedia.org/wiki/Concepts_(C%2B%2B))
> > +or [Java interfaces](https://en.wikipedia.org/wiki/Interface_(Java)).
> > +
> > +To understand how AVClass and @ref avoptions "AVOptions" work,
> > +consider the requirements for a `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
> 
> but this will be a compatiblity break for most applications and
> scripts (you will notice in this case because people will complain
> aloud about the breakage), so we need to be careful when changing
> options following the usual deprecation dance
> 
> > +- it has to provide useful feedback to users about unsupported options
> > +
> > +Common encoder options like "bitrate" need to be stored in AVCodecContext itself
> > +to avoid duplicating code, while encoder-specific options like "profile" have to
> > +be stored in the X264Context instance stored in AVCodecContext::priv_data.
> 
> > +But both need to be presented to users (along with help text, default values etc.)
> > +in a way that makes it easy to build user interfaces to get and set those options.
> 
> nit: s/easy/possible/
> 
> > +
> > +A context's AVClass member contains a list of AVOption objects, describing
> > +the user-configurable members of the class.  It also contains functions to
> > +iterate through a tree of AVClass objects representing internal context either
> > +for the current object or for any class that could potentially exist in the
> > +current version of FFmpeg.
> > +
> > +The @ref avoptions "AVOptions" API accepts any AVClass context structure,
> > +looks through its AVOption data, and uses that to examine, introspect, and modify
> > +the structure.  Because the API doesn't contain any type-specific information,
> > +it can be used to create a general user interface that adapts automatically
> > +when e.g. a new version of FFmpeg adds a new configuration option.
> > +
> > +## Summary
> > +
> 
> > +FFmpeg uses "contexts" in ways that are often resemble object-oriented programming.
> > +But it focuses less on encapsulation within arbitrarily complex systems,
> > +and more on providing reflectivity to make pleasant user interfaces.
> 
> nit++: s/pleasant//, here the point is to make them possible, we don't
> know if they are pleasant :-)

Comments above should be reflected in a patch I'll send after writing this.
The patch also adds more links from the code, because I noticed doxygen was
replacing all "Context for foo" comments with links to some private struct
that happened to be called "Context".

I've also gone through the code looking for edge cases we haven't covered.
Here are some questions trying to prompt an "oh yeah I forgot to mention
that"-type answer.  Anything where the answer is more like "that should
probably be rewritten to be clearer", let me know and I'll avoid confusing
newbies with it.

av_ambient_viewing_environment_create_side_data() takes an AVFrame as its
first argument, and returns a new AVAmbientViewingEnvironment.  What is the
context object for that function - AVFrame or AVAmbientViewingEnvironment?

av_register_bitstream_filter() (deprecated 4.0, removed 5.0) took an
`AVBitStreamFilter *` as its first argument, but I don't think you'd say
the argument provided "context" for the function.  So would I be right in
saying `AVBitStreamFilter *` is not a context, despite looking like one?

av_buffersink_*() all take a `const AVFilterContext *` argument.
What does the difference between av_buffersink prefix and AVFilter type mean?

av_channel_description_bprint() takes a `struct AVBPrint *` as its first
argument, then `enum AVChannel`.  Is the context AVBPrint, AVChannel,
or both?  Does it make sense for a function to have two contexts?

Related to the previous question, does `av_cmp_q()` count as a function
with two contexts?  Or no contexts?

Finally, a general question - functions of the form "avfoo" seem like they
are more consistent than "av_foo".  Does the underscore mean anything?
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-04-22 17:05               ` Stefano Sabatini
  2024-04-29  9:10                 ` Andrew Sayers
@ 2024-04-29  9:24                 ` Andrew Sayers
  2024-04-29  9:24                   ` [FFmpeg-devel] [PATCH v4 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
                                     ` (3 more replies)
  1 sibling, 4 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-04-29  9:24 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Derived from detailed explanations kindly provided by Stefano Sabatini:
https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
---
 doc/context.md | 308 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 308 insertions(+)
 create mode 100644 doc/context.md

diff --git a/doc/context.md b/doc/context.md
new file mode 100644
index 0000000000..73297f53aa
--- /dev/null
+++ b/doc/context.md
@@ -0,0 +1,308 @@
+# Introduction to contexts
+
+Like many C projects, FFmpeg has adopted the subset of
+[object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming)
+techniques that help solve its problems.  Object-like structures are called "contexts",
+and this document provides a general introduction to how they work.
+
+Object-oriented programming tends to focus on
+[access](https://en.wikipedia.org/wiki/Access_modifiers) as a primary concern.
+For example, members of a class are often designated "private" to indicate
+they are only accessible to code that's part of the class.  Less focus is put on
+[reflection](https://en.wikipedia.org/wiki/Reflection_(computer_programming)),
+where it is provided at all.  For example, C++ has no built-in way to serialize
+the state of an arbitrary object.
+
+Reflection is extremely important for FFmpeg, because user-facing
+options are implemented by reflecting the state of contexts.  Limiting
+access is a secondary concern, mainly important for ensuring
+implementation details can change between versions.
+
+Knowledge of object-oriented programming concepts can help when learning FFmpeg,
+but it's important not to fixate on FFmpeg's access control features,
+nor to overlook its reflection capabilities.  This document compares
+FFmpeg and OOP techniques where relevant, but does not require an understanding
+of object-oriented programming.
+
+## Example: modify text then print it
+
+The example below shows a context structure that receives input strings,
+modifies them in some context-dependant way, then prints them to a specified
+filehandle.
+
+```c
+/**
+ * Type information, accessible at runtime.
+ *
+ * Useful when configuring objects.
+ */
+enum ModifyThenPrintDialect {
+    MODIFY_THEN_PRINT_DIALECT_PLAIN_TEXT = 0,
+    MODIFY_THEN_PRINT_DIALECT_REGEX      = 1,
+    MODIFY_THEN_PRINT_DIALECT_REGEX_PCRE = 2
+};
+
+/**
+ * User-facing information about types
+ *
+ * Useful for describing contexts to the user.
+ */
+static const char *ModifyThenPrintDialectName[] = {
+    "plain text",
+    "regular expression",
+    "Perl-compatible regular expression"
+};
+
+/**
+ * Context for functions that modify strings before printing them
+ */
+struct ModifyThenPrintContext {
+
+    /**
+     * Information about the type of this particular instance
+     *
+     * Object-oriented programs would probably replace this with "sub-classes",
+     * where each class extends the base class to implement one dialect.
+     * But information about a type can also work more like "mixins",
+     * where several pieces of unrelated functionality are blended together
+     * to create an interface for a specific purpose.
+     */
+    enum ModifyThenPrintDialect dialect;
+
+    /**
+     * Internal context
+     *
+     * Contains anything that isn't part of the public interface.
+     * The most obvious OOP analogy is to "private" members that are only
+     * accessible to code that's part of the class.  But it could also contain
+     * information about "virtual functions" - functions that every sub-class
+     * guarantees to implement, but in their own class-specific way.
+     */
+    void *priv_data;
+
+    /**
+     * User-configurable options
+     *
+     * Best set through an API, but can be set directly if necessary
+     *
+     * Data from users needs to be validated before it's set, and the API
+     * might e.g. want to update some internal buffer for performance reasons.
+     * Setting these directly is always less robust than using an API,
+     * but might be worthwhile if you're willing to spend the time checking
+     * for edge cases, and don't mind your code misbehaving if future
+     * versions change the API but not the structure.
+     *
+     * Object-oriented programs would likely make these "protected" members,
+     * initialised in a constructor and accessed with getters and setters.
+     * That means code *related* to this class can access them directly,
+     * while unrelated code accesses them indirectly by calling functions.
+     *
+     * But the "protected access" analogy is quite limited. In particular,
+     * protected members don't have any special reflective properties,
+     * whereas FFmpeg options are usually configurable by end users.
+     */
+    char *replace_this;
+    char *with_this;
+
+    /**
+     * Programmer-configurable variable
+     *
+     * Object-oriented programs would represent this as a public member.
+     */
+    FILE *out;
+
+};
+
+/**
+ * Allocate and initialize a ModifyThenPrintContext
+ *
+ * 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.
+ *
+ * Object-oriented programs would likely implement this with "allocator"
+ * and "constructor" functions, (i.e. separate functions that reserve memory
+ * for an object and set its initial values).
+ */
+int ModifyThenPrintContext_alloc_context(struct ModifyThenPrintContext **ctx,
+                                         enum ModifyThenPrintDialect dialect,
+                                         FILE *out);
+
+/**
+ * Uninitialize and deallocate a ModifyThenPrintContext
+ *
+ * Does any work required by the internal context (e.g. deallocating
+ * `priv_data`), then deallocates the main context itself.
+ *
+ * Object-oriented programs would likely implement this with
+ * destructor and deallocator functions (i.e. separate functions
+ * that do the opposite of the allocator and constructor above).
+ */
+int ModifyThenPrintContext_free(struct ModifyThenPrintContext *ctx);
+
+/**
+ * Configure a ModifyThenPrintContext
+ *
+ * Checks that the arguments are valid in the context's dialect,
+ * then updates the options as necessary
+ *
+ * Object-oriented programs would likely represent this as a
+ * pair of "setter" functions (functions whose only job is to
+ * validate and update a value).
+ */
+int ModifyThenPrintContext_configure(struct ModifyThenPrintContext *ctx,
+                                     char *replace_this,
+                                     char *with_this);
+
+/**
+ * Print a single message
+ *
+ * Object-oriented programs would likely represent this with an ordinary
+ * member function (a function called like `context->function(...)`
+ * instead of `function( context, ... )`).
+ */
+int ModifyThenPrintContext_print(struct ModifyThenPrintContext *ctx,
+                                 char *msg);
+
+/**
+ * Print the contents of a ModifyThenPrintContext to a filehandle
+ *
+ * Provides human-readable information about keys and values.
+ *
+ * Object-oriented programs would likely represent this with some kind of
+ * `serialize` function (a function that iterates through all members,
+ * printing each one's name and contents to the file).  These can be member
+ * functions, but in practice many languages implement it some other way -
+ * an example of the lack of focus on reflection in object-oriented languages.
+ */
+int ModifyThenPrintContext_dump(struct ModifyThenPrintContext **ctx,
+                                FILE *dump_fh);
+
+/**
+ * How this context might be used in practice
+ */
+int print_hello_world()
+{
+
+    int ret = 0;
+
+    struct ModifyThenPrintContext *ctx;
+
+    if ( ModifyThenPrintContext_alloc_context( &ctx, MODIFY_THEN_PRINT_DIALECT_REGEX, stdout ) < 0 ) {
+        ret = -1;
+        goto EXIT_WITHOUT_CLEANUP;
+    }
+
+    if ( ModifyThenPrintContext_configure(ctx, "Hi|Hullo", "Hello") < 0 ) {
+        ret = -1;
+        goto FINISH;
+    }
+
+    if ( ModifyThenPrintContext_print( ctx, "Hi, world!\n" ) < 0 ) {
+        ret = -1;
+        goto FINISH;
+    }
+
+    if ( ModifyThenPrintContext_print( ctx, "Hullo, world!\n" ) < 0 ) {
+        ret = -1;
+        goto FINISH;
+    }
+
+    FINISH:
+    if ( ModifyThenPrintContext_free( ctx ) ) {
+        ret = -1;
+        goto EXIT_WITHOUT_CLEANUP;
+    }
+
+    EXIT_WITHOUT_CLEANUP:
+    return ret;
+
+}
+```
+
+## FFmpeg context structures
+
+The example above shows a generic context structure and its associated
+functions.  Some FFmpeg contexts are no more complex than that example,
+just as some objects are just key/value stores with some functions attached.
+But here are some examples to show the variety of contexts available in FFmpeg.
+
+AVHashContext presents a generic API for hashing data.  @ref hash.h
+"Its associated functions" show how to create, use and destroy a hash.
+The exact algorithm is specified by passing a string to av_hash_alloc(),
+and the list of strings can be retrieved from av_hash_names().
+Algorithm-specific internal context is stored in AVHashContext::ctx.
+
+AVCodecContext is a complex context representing data about an encoding or
+decoding session.  @ref avcodec.h "Its associated functions" provide an
+abstract interface to encode and decode data.  Like most widely-used contexts,
+its first member is an AVClass pointer containing instance-specific information.
+That means it's an *AVClass context structure* (discussed below).
+
+X264Context contains the internal context for an AVCodecContext that uses
+the x264 library.  @ref libx264.c "Its associated functions" provide a concrete
+implementation for interacting with libx264.  This class is not directly
+accessible through FFmpeg's public interface, so it's easier to change
+X264Context than to change AVCodecContext between releases.
+
+## Reflection with AVClass and AVOptions
+
+AVClass is a struct containing general information about a context.
+It's a generic version of `ModifyThenPrintDialect` in the example.
+An *AVClass context structure* is a context whose first member
+is an AVClass that reflects the context's interface.
+
+AVOption is a struct containing information about a member of a context,
+or of an internal context.  `replace_this` and `with_this` in the example
+would echa have an associated AVOption value stored in the context's AVClass.
+An *@ref avoptions "AVOptions"-enabled struct* is a structure which reflects
+its contents using the @ref avoptions "AVOptions" API.
+
+The terms *AVClass context structure* and *@ref avoptions "AVOptions"-enabled
+struct* have become synonymous in modern usage, although you might notice some
+distinction when looking at code written after AVClass was developed but
+before @ref avoptions "AVOptions" was added.
+
+Even though the name "AVClass" implies an analogy to an object-oriented
+base [class](https://en.wikipedia.org/wiki/Class_(computer_programming)), they
+behave more like [C++ concepts](https://en.wikipedia.org/wiki/Concepts_(C%2B%2B))
+or [Java interfaces](https://en.wikipedia.org/wiki/Interface_(Java)).  Unlike a
+base class, an AVClass doesn't imply any theoretical relationship between objects,
+and contexts of the same type will often have different AVClass values.  It's even
+theoretically possible for a single AVClass to be shared between contexts of
+different types.
+
+To understand how AVClass and @ref avoptions "AVOptions" work,
+consider the requirements for a `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 must not expose implementation details (e.g. its encoding buffer)
+  - otherwise, trivial improvements would force an increase of the major API version
+- it has to provide useful feedback to users about unsupported options
+
+Common encoder options like "bitrate" need to be stored in AVCodecContext itself
+to avoid duplicating code, while encoder-specific options like "profile" have to
+be stored in the X264Context instance stored in AVCodecContext::priv_data.
+But both need to be presented to users (along with help text, default values etc.)
+in a way that makes it practical to build user interfaces to get and set those options.
+
+A context's AVClass contains a list of AVOption members, describing the
+user-configurable options in the class.  It also contains a tree of further AVClass
+members that represent internal context either for the current object or for any
+object of the same type that could potentially exist in the current version of FFmpeg.
+
+The @ref avoptions "AVOptions" API accepts any AVClass context structure,
+looks through its AVOption data, and uses that to examine, introspect, and modify
+the structure.  Because the API doesn't contain any type-specific information,
+it can be used to create a general user interface that adapts automatically
+when e.g. a new version of FFmpeg adds a new configuration option.
+
+## Summary
+
+FFmpeg uses "contexts" in ways that often resemble object-oriented programming.
+But it focuses less on encapsulation within arbitrarily complex systems,
+and more on providing reflectivity to make good user interfaces.
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v4 2/4] lavu: Clarify relationship between AVClass, AVOption and context
  2024-04-29  9:24                 ` [FFmpeg-devel] [PATCH v4 1/4] " Andrew Sayers
@ 2024-04-29  9:24                   ` Andrew Sayers
  2024-04-29  9:24                   ` [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation Andrew Sayers
                                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-04-29  9:24 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

---
 libavutil/log.h | 11 ++++++++---
 libavutil/opt.h |  7 ++++---
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/libavutil/log.h b/libavutil/log.h
index ab7ceabe22..cfbf416679 100644
--- a/libavutil/log.h
+++ b/libavutil/log.h
@@ -59,9 +59,14 @@ typedef enum {
 struct AVOptionRanges;
 
 /**
- * Describe the class of an AVClass context structure. That is an
- * arbitrary struct of which the first field is a pointer to an
- * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.).
+ * Metadata about an arbitrary data structure
+ *
+ * A @ref md_doc_2context "context struct" whose first member is a pointer
+ * to an AVClass object is called an "AVClass context structure"
+ * (e.g. AVCodecContext, AVFormatContext etc.).
+ *
+ * AVClass is often combined with @ref avoptions "AVOptions" to create
+ * "AVOptions-enabled structs" that can be easily configured by users.
  */
 typedef struct AVClass {
     /**
diff --git a/libavutil/opt.h b/libavutil/opt.h
index 855e363091..82ac933a2a 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -39,9 +39,10 @@
  * @defgroup avoptions AVOptions
  * @ingroup lavu_data
  * @{
- * AVOptions provide a generic system to declare options on arbitrary structs
- * ("objects"). An option can have a help text, a type and a range of possible
- * values. Options may then be enumerated, read and written to.
+ * Builds on AVClass, adding a generic system to declare options.
+ *
+ * An option can have a help text, a type and a range of possible values.
+ * Options may then be enumerated, read and written to.
  *
  * There are two modes of access to members of AVOption and its child structs.
  * One is called 'native access', and refers to access from the code that
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation
  2024-04-29  9:24                 ` [FFmpeg-devel] [PATCH v4 1/4] " Andrew Sayers
  2024-04-29  9:24                   ` [FFmpeg-devel] [PATCH v4 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
@ 2024-04-29  9:24                   ` Andrew Sayers
  2024-05-02 11:01                     ` Lynne
  2024-04-29  9:24                   ` [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes Andrew Sayers
  2024-05-05  8:31                   ` [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means Andreas Rheinhardt
  3 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-04-29  9:24 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Some headings needed to be rewritten to accomodate the text,
(hopefully) without changing the meaning.
---
 libavcodec/aac/aacdec.h            |  2 +-
 libavcodec/aacenc.h                |  2 +-
 libavcodec/ac3enc.h                |  2 +-
 libavcodec/amfenc.h                |  2 +-
 libavcodec/atrac.h                 |  2 +-
 libavcodec/avcodec.h               |  3 ++-
 libavcodec/bsf.h                   |  2 +-
 libavcodec/cbs.h                   |  2 +-
 libavcodec/d3d11va.h               |  3 +--
 libavcodec/h264dsp.h               |  2 +-
 libavcodec/h264pred.h              |  2 +-
 libavcodec/mediacodec.h            |  2 +-
 libavcodec/mpegaudiodec_template.c |  2 +-
 libavcodec/pthread_frame.c         |  4 ++--
 libavcodec/qsv.h                   |  6 ++++--
 libavcodec/sbr.h                   |  2 +-
 libavcodec/smacker.c               |  2 +-
 libavcodec/vdpau.h                 |  3 ++-
 libavcodec/videotoolbox.h          |  5 +++--
 libavfilter/avfilter.h             |  2 +-
 libavformat/avformat.h             |  3 ++-
 libavformat/avio.h                 |  3 ++-
 libavutil/audio_fifo.h             |  2 +-
 libavutil/hwcontext.h              | 21 ++++++++++++---------
 libavutil/hwcontext_cuda.h         |  2 +-
 libavutil/hwcontext_d3d11va.h      |  4 ++--
 libavutil/hwcontext_d3d12va.h      |  6 +++---
 libavutil/hwcontext_drm.h          |  2 +-
 libavutil/hwcontext_dxva2.h        |  4 ++--
 libavutil/hwcontext_mediacodec.h   |  2 +-
 libavutil/hwcontext_opencl.h       |  4 ++--
 libavutil/hwcontext_qsv.h          |  4 ++--
 libavutil/hwcontext_vaapi.h        |  6 +++---
 libavutil/hwcontext_vdpau.h        |  2 +-
 libavutil/hwcontext_vulkan.h       |  4 ++--
 libavutil/lfg.h                    |  2 +-
 36 files changed, 66 insertions(+), 57 deletions(-)

diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
index 4cf764e2e9..71d61813f4 100644
--- a/libavcodec/aac/aacdec.h
+++ b/libavcodec/aac/aacdec.h
@@ -248,7 +248,7 @@ typedef struct AACDecDSP {
 } AACDecDSP;
 
 /**
- * main AAC decoding context
+ * main AAC decoding @ref md_doc_2context "context"
  */
 struct AACDecContext {
     const struct AVClass  *class;
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index d07960620e..1a645f4719 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -207,7 +207,7 @@ typedef struct AACPCEInfo {
 } AACPCEInfo;
 
 /**
- * AAC encoder context
+ * AAC encoder @ref md_doc_2context "context"
  */
 typedef struct AACEncContext {
     AVClass *av_class;
diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
index 30812617cc..c725007077 100644
--- a/libavcodec/ac3enc.h
+++ b/libavcodec/ac3enc.h
@@ -152,7 +152,7 @@ typedef struct AC3Block {
 } AC3Block;
 
 /**
- * AC-3 encoder private context.
+ * AC-3 encoder private @ref md_doc_2context "context"
  */
 typedef struct AC3EncodeContext {
     AVClass *av_class;                      ///< AVClass used for AVOption
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
index 2dbd378ef8..f142ede63a 100644
--- a/libavcodec/amfenc.h
+++ b/libavcodec/amfenc.h
@@ -43,7 +43,7 @@ typedef struct AmfTraceWriter {
 } AmfTraceWriter;
 
 /**
-* AMF encoder context
+* AMF encoder @ref md_doc_2context "context"
 */
 
 typedef struct AmfContext {
diff --git a/libavcodec/atrac.h b/libavcodec/atrac.h
index 05208bbee6..1527e376a9 100644
--- a/libavcodec/atrac.h
+++ b/libavcodec/atrac.h
@@ -39,7 +39,7 @@ typedef struct AtracGainInfo {
 } AtracGainInfo;
 
 /**
- *  Gain compensation context structure.
+ *  Gain compensation @ref md_doc_2context "context"
  */
 typedef struct AtracGCContext {
     float   gain_tab1[16];  ///< gain compensation level table
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 968009a192..9180fedca7 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -430,7 +430,8 @@ typedef struct RcOverride{
 #define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0)
 
 /**
- * main external API structure.
+ * @ref md_doc_2context "Context" for an encode or decode session
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
index a09c69f242..bf79afa7cc 100644
--- a/libavcodec/bsf.h
+++ b/libavcodec/bsf.h
@@ -56,7 +56,7 @@
  */
 
 /**
- * The bitstream filter state.
+ * Bitstream filter @ref md_doc_2context "context"
  *
  * This struct must be allocated with av_bsf_alloc() and freed with
  * av_bsf_free().
diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
index d479b1ac2d..0ff64d2fef 100644
--- a/libavcodec/cbs.h
+++ b/libavcodec/cbs.h
@@ -214,7 +214,7 @@ typedef void (*CBSTraceWriteCallback)(void *trace_context,
                                       int64_t value);
 
 /**
- * Context structure for coded bitstream operations.
+ * @ref md_doc_2context "Context" structure for coded bitstream operations.
  */
 typedef struct CodedBitstreamContext {
     /**
diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
index 27f40e5519..ec0c472ab9 100644
--- a/libavcodec/d3d11va.h
+++ b/libavcodec/d3d11va.h
@@ -46,8 +46,7 @@
  */
 
 /**
- * This structure is used to provides the necessary configurations and data
- * to the Direct3D11 FFmpeg HWAccel implementation.
+ * @ref md_doc_2context "Context" for the Direct3D11 FFmpeg HWAccel implementation
  *
  * The application must make it available as AVCodecContext.hwaccel_context.
  *
diff --git a/libavcodec/h264dsp.h b/libavcodec/h264dsp.h
index e0880c4d88..27256c5605 100644
--- a/libavcodec/h264dsp.h
+++ b/libavcodec/h264dsp.h
@@ -37,7 +37,7 @@ typedef void (*h264_biweight_func)(uint8_t *dst, uint8_t *src,
                                    int weightd, int weights, int offset);
 
 /**
- * Context for storing H.264 DSP functions
+ * @ref md_doc_2context "Context" for storing H.264 DSP functions
  */
 typedef struct H264DSPContext {
     /* weighted MC */
diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h
index cb008548fc..2b076f8846 100644
--- a/libavcodec/h264pred.h
+++ b/libavcodec/h264pred.h
@@ -89,7 +89,7 @@
 #define PART_NOT_AVAILABLE -2
 
 /**
- * Context for storing H.264 prediction functions
+ * @ref md_doc_2context "Context" for storing H.264 prediction functions
  */
 typedef struct H264PredContext {
     void(*pred4x4[9 + 3 + 3])(uint8_t *src, const uint8_t *topright,
diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
index 4e9b56a618..9967a7cfb3 100644
--- a/libavcodec/mediacodec.h
+++ b/libavcodec/mediacodec.h
@@ -26,7 +26,7 @@
 #include "libavcodec/avcodec.h"
 
 /**
- * This structure holds a reference to a android/view/Surface object that will
+ * @ref md_doc_2context "Context" for the android/view/Surface object that will
  * be used as output by the decoder.
  *
  */
diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c
index c73b1e0054..15d63215d1 100644
--- a/libavcodec/mpegaudiodec_template.c
+++ b/libavcodec/mpegaudiodec_template.c
@@ -1691,7 +1691,7 @@ static int decode_frame_adu(AVCodecContext *avctx, AVFrame *frame,
 #if CONFIG_MP3ON4_DECODER || CONFIG_MP3ON4FLOAT_DECODER
 
 /**
- * Context for MP3On4 decoder
+ * @ref md_doc_2context "Context" for MP3On4 decoder
  */
 typedef struct MP3On4DecodeContext {
     int frames;                     ///< number of mp3 frames per block (number of mp3 decoder instances)
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 67f09c1f48..74f05eedcf 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -71,7 +71,7 @@ typedef struct ThreadFrameProgress {
 } ThreadFrameProgress;
 
 /**
- * Context used by codec threads and stored in their AVCodecInternal thread_ctx.
+ * @ref md_doc_2context "Context" used by codec threads and stored in their AVCodecInternal thread_ctx.
  */
 typedef struct PerThreadContext {
     struct FrameThreadContext *parent;
@@ -111,7 +111,7 @@ typedef struct PerThreadContext {
 } PerThreadContext;
 
 /**
- * Context stored in the client AVCodecInternal thread_ctx.
+ * @ref md_doc_2context "Context" stored in the client AVCodecInternal thread_ctx.
  */
 typedef struct FrameThreadContext {
     PerThreadContext *threads;     ///< The contexts for each thread.
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index c156b08d07..8b8160a4b1 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -26,8 +26,10 @@
 #include "libavutil/buffer.h"
 
 /**
- * This struct is used for communicating QSV parameters between libavcodec and
- * the caller. It is managed by the caller and must be assigned to
+ * @ref md_doc_2context "Context" for communicating QSV parameters between libavcodec
+ * and the caller.
+ *
+ * It is managed by the caller and must be assigned to
  * AVCodecContext.hwaccel_context.
  * - decoding: hwaccel_context must be set on return from the get_format()
  *             callback
diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
index fe3a39603a..98ad9024a9 100644
--- a/libavcodec/sbr.h
+++ b/libavcodec/sbr.h
@@ -116,7 +116,7 @@ typedef struct SBRData {
 typedef struct SpectralBandReplication SpectralBandReplication;
 
 /**
- * aacsbr functions pointers
+ * aacsbr functions pointer @ref md_doc_2context "context"
  */
 typedef struct AACSBRContext {
     int (*sbr_lf_gen)(SpectralBandReplication *sbr,
diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c
index 8f198d6957..1ca39a74a0 100644
--- a/libavcodec/smacker.c
+++ b/libavcodec/smacker.c
@@ -68,7 +68,7 @@ typedef struct HuffEntry {
 } HuffEntry;
 
 /**
- * Context used for code reconstructing
+ * @ref md_doc_2context "Context" used for code reconstructing
  */
 typedef struct HuffContext {
     int current;
diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
index 8021c25761..227b85727d 100644
--- a/libavcodec/vdpau.h
+++ b/libavcodec/vdpau.h
@@ -64,8 +64,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
                                const VdpBitstreamBuffer *);
 
 /**
- * This structure is used to share data between the libavcodec library and
+ * @ref md_doc_2context "Context" to share data between the libavcodec library and
  * the client video application.
+ *
  * This structure will be allocated and stored in AVCodecContext.hwaccel_context
  * by av_vdpau_bind_context(). Members can be set by the user once
  * during initialization or through each AVCodecContext.get_buffer()
diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
index d68d76e400..f15e79f325 100644
--- a/libavcodec/videotoolbox.h
+++ b/libavcodec/videotoolbox.h
@@ -49,8 +49,9 @@
 #include "libavutil/attributes.h"
 
 /**
- * This struct holds all the information that needs to be passed
- * between the caller and libavcodec for initializing Videotoolbox decoding.
+ * @ref md_doc_2context "Context" for information passed between the caller and libavcodec
+ * for initializing Videotoolbox decoding.
+ *
  * Its size is not a part of the public ABI, it must be allocated with
  * av_videotoolbox_alloc_context() and freed with av_free().
  */
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index a34e61f23c..54b5f9dc43 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -403,7 +403,7 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
  */
 #define AVFILTER_THREAD_SLICE (1 << 0)
 
-/** An instance of a filter */
+/** @ref md_doc_2context "Context" for a filter */
 struct AVFilterContext {
     const AVClass *av_class;        ///< needed for av_log() and filters common options
 
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 8afdcd9fd0..28243c06c4 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1241,7 +1241,8 @@ enum AVDurationEstimationMethod {
 };
 
 /**
- * Format I/O context.
+ * Format I/O @ref md_doc_2context "context"
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavformat/avio.h b/libavformat/avio.h
index ebf611187d..b525c93194 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -146,7 +146,8 @@ enum AVIODataMarkerType {
 };
 
 /**
- * Bytestream IO Context.
+ * Bytestream I/O @ref md_doc_2context "context"
+ *
  * New public fields can be added with minor version bumps.
  * Removal, reordering and changes to existing public fields require
  * a major version bump.
diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h
index fa5f59a2be..de29715462 100644
--- a/libavutil/audio_fifo.h
+++ b/libavutil/audio_fifo.h
@@ -39,7 +39,7 @@
  */
 
 /**
- * Context for an Audio FIFO Buffer.
+ * @ref md_doc_2context "Context" for an Audio FIFO Buffer.
  *
  * - Operates at the sample level rather than the byte level.
  * - Supports multiple channels with either planar or packed sample format.
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index bac30debae..60064cf08b 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -41,12 +41,13 @@ enum AVHWDeviceType {
 };
 
 /**
- * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
- * i.e. state that is not tied to a concrete processing configuration.
- * E.g., in an API that supports hardware-accelerated encoding and decoding,
- * this struct will (if possible) wrap the state that is common to both encoding
- * and decoding and from which specific instances of encoders or decoders can be
- * derived.
+ * @ref md_doc_2context "Context" for (hardware/vendor-specific) "high-level" state.
+ *
+ * "High-level state" is anything that is not tied to a concrete processing
+ * configuration. E.g., in an API that supports hardware-accelerated encoding
+ * and decoding, this struct will (if possible) wrap the state that is common
+ * to both encoding and decoding and from which specific instances of encoders
+ * or decoders can be derived.
  *
  * This struct is reference-counted with the AVBuffer mechanism. The
  * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
@@ -103,9 +104,11 @@ typedef struct AVHWDeviceContext {
 } AVHWDeviceContext;
 
 /**
- * This struct describes a set or pool of "hardware" frames (i.e. those with
- * data not located in normal system memory). All the frames in the pool are
- * assumed to be allocated in the same way and interchangeable.
+ * @ref md_doc_2context "context" for a pool of "hardware" frames (those with
+ * data not located in normal system memory)
+ *
+ * All the frames in the pool are assumed to be allocated in the same way and
+ * interchangeable.
  *
  * This struct is reference-counted with the AVBuffer mechanism and tied to a
  * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
index cbad434fea..e259892688 100644
--- a/libavutil/hwcontext_cuda.h
+++ b/libavutil/hwcontext_cuda.h
@@ -37,7 +37,7 @@
 typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVCUDADeviceContext {
     CUcontext cuda_ctx;
diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
index 77d2d72f1b..101d1cb6f8 100644
--- a/libavutil/hwcontext_d3d11va.h
+++ b/libavutil/hwcontext_d3d11va.h
@@ -40,7 +40,7 @@
 #include <stdint.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVD3D11VADeviceContext {
     /**
@@ -126,7 +126,7 @@ typedef struct AVD3D11FrameDescriptor {
 } AVD3D11FrameDescriptor;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVD3D11VAFramesContext {
     /**
diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
index ff06e6f2ef..c623914c2b 100644
--- a/libavutil/hwcontext_d3d12va.h
+++ b/libavutil/hwcontext_d3d12va.h
@@ -37,7 +37,7 @@
 #include <d3d12video.h>
 
 /**
- * @brief This struct is allocated as AVHWDeviceContext.hwctx
+ * @brief This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  *
  */
 typedef struct AVD3D12VADeviceContext {
@@ -78,7 +78,7 @@ typedef struct AVD3D12VADeviceContext {
 } AVD3D12VADeviceContext;
 
 /**
- * @brief This struct is used to sync d3d12 execution
+ * @brief This @ref md_doc_2context "context" is used to sync d3d12 execution
  *
  */
 typedef struct AVD3D12VASyncContext {
@@ -120,7 +120,7 @@ typedef struct AVD3D12VAFrame {
 } AVD3D12VAFrame;
 
 /**
- * @brief This struct is allocated as AVHWFramesContext.hwctx
+ * @brief This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
  *
  */
 typedef struct AVD3D12VAFramesContext {
diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
index 42709f215e..8329e69966 100644
--- a/libavutil/hwcontext_drm.h
+++ b/libavutil/hwcontext_drm.h
@@ -152,7 +152,7 @@ typedef struct AVDRMFrameDescriptor {
 /**
  * DRM device.
  *
- * Allocated as AVHWDeviceContext.hwctx.
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx.
  */
 typedef struct AVDRMDeviceContext {
     /**
diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
index e1b79bc0de..c679c16af0 100644
--- a/libavutil/hwcontext_dxva2.h
+++ b/libavutil/hwcontext_dxva2.h
@@ -34,14 +34,14 @@
 #include <dxva2api.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVDXVA2DeviceContext {
     IDirect3DDeviceManager9 *devmgr;
 } AVDXVA2DeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVDXVA2FramesContext {
     /**
diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
index fc0263cabc..e81193247b 100644
--- a/libavutil/hwcontext_mediacodec.h
+++ b/libavutil/hwcontext_mediacodec.h
@@ -22,7 +22,7 @@
 /**
  * MediaCodec details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVMediaCodecDeviceContext {
     /**
diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
index ef54486c95..7abd97db2b 100644
--- a/libavutil/hwcontext_opencl.h
+++ b/libavutil/hwcontext_opencl.h
@@ -58,7 +58,7 @@ typedef struct AVOpenCLFrameDescriptor {
 /**
  * OpenCL device details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVOpenCLDeviceContext {
     /**
@@ -84,7 +84,7 @@ typedef struct AVOpenCLDeviceContext {
 /**
  * OpenCL-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
  */
 typedef struct AVOpenCLFramesContext {
     /**
diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
index e2dba8ad83..b63ebddaef 100644
--- a/libavutil/hwcontext_qsv.h
+++ b/libavutil/hwcontext_qsv.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVQSVDeviceContext {
     mfxSession session;
@@ -48,7 +48,7 @@ typedef struct AVQSVDeviceContext {
 } AVQSVDeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVQSVFramesContext {
     mfxFrameSurface1 *surfaces;
diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
index 0b2e071cb3..4a897eb851 100644
--- a/libavutil/hwcontext_vaapi.h
+++ b/libavutil/hwcontext_vaapi.h
@@ -63,7 +63,7 @@ enum {
 /**
  * VAAPI connection details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVVAAPIDeviceContext {
     /**
@@ -83,7 +83,7 @@ typedef struct AVVAAPIDeviceContext {
 /**
  * VAAPI-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
  */
 typedef struct AVVAAPIFramesContext {
     /**
@@ -105,7 +105,7 @@ typedef struct AVVAAPIFramesContext {
 /**
  * VAAPI hardware pipeline configuration details.
  *
- * Allocated with av_hwdevice_hwconfig_alloc().
+ * This struct is allocated with av_hwdevice_hwconfig_alloc().
  */
 typedef struct AVVAAPIHWConfig {
     /**
diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
index 1b7ea1e443..e305caa595 100644
--- a/libavutil/hwcontext_vdpau.h
+++ b/libavutil/hwcontext_vdpau.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVVDPAUDeviceContext {
     VdpDevice          device;
diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
index cbbd2390c1..1869870032 100644
--- a/libavutil/hwcontext_vulkan.h
+++ b/libavutil/hwcontext_vulkan.h
@@ -39,7 +39,7 @@ typedef struct AVVkFrame AVVkFrame;
  */
 
 /**
- * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
+ * Main Vulkan @ref md_doc_2context "context", allocated as AVHWDeviceContext.hwctx.
  * All of these can be set before init to change what the context uses
  */
 typedef struct AVVulkanDeviceContext {
@@ -172,7 +172,7 @@ typedef enum AVVkFrameFlags {
 } AVVkFrameFlags;
 
 /**
- * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx, used to set pool-specific options
  */
 typedef struct AVVulkanFramesContext {
     /**
diff --git a/libavutil/lfg.h b/libavutil/lfg.h
index e75a986f12..7f4ff5b62f 100644
--- a/libavutil/lfg.h
+++ b/libavutil/lfg.h
@@ -25,7 +25,7 @@
 #include <stdint.h>
 
 /**
- * Context structure for the Lagged Fibonacci PRNG.
+ * @ref md_doc_2context "Context" structure for the Lagged Fibonacci PRNG.
  * The exact layout, types and content of this struct may change and should
  * not be accessed directly. Only its `sizeof()` is guaranteed to stay the same
  * to allow easy instanciation.
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes
  2024-04-29  9:24                 ` [FFmpeg-devel] [PATCH v4 1/4] " Andrew Sayers
  2024-04-29  9:24                   ` [FFmpeg-devel] [PATCH v4 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
  2024-04-29  9:24                   ` [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation Andrew Sayers
@ 2024-04-29  9:24                   ` Andrew Sayers
  2024-05-05  8:31                   ` [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means Andreas Rheinhardt
  3 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-04-29  9:24 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Doxygen thinks any text like "Context for foo" is a link to a struct called "Context".
Add a description and a better link, to avoid confusing readers.
---
 libavformat/async.c | 3 +++
 libavformat/cache.c | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/libavformat/async.c b/libavformat/async.c
index e096b0bc6f..3c28d418ae 100644
--- a/libavformat/async.c
+++ b/libavformat/async.c
@@ -53,6 +53,9 @@ typedef struct RingBuffer
     int           read_pos;
 } RingBuffer;
 
+/**
+ * @brief @ref md_doc_2context "Context" for testing async
+ */
 typedef struct Context {
     AVClass        *class;
     URLContext     *inner;
diff --git a/libavformat/cache.c b/libavformat/cache.c
index 5f78adba9d..3cc0edec82 100644
--- a/libavformat/cache.c
+++ b/libavformat/cache.c
@@ -52,6 +52,9 @@ typedef struct CacheEntry {
     int size;
 } CacheEntry;
 
+/**
+ * @brief @ref md_doc_2context "Context" for a cache
+ */
 typedef struct Context {
     AVClass *class;
     int fd;
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means
  2024-04-29  9:10                 ` Andrew Sayers
@ 2024-05-02 10:03                   ` Andrew Sayers
  2024-05-05  7:29                   ` Stefano Sabatini
  1 sibling, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-02 10:03 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Mon, Apr 29, 2024 at 10:10:35AM +0100, Andrew Sayers wrote:
> 
> I've also gone through the code looking for edge cases we haven't covered.
> Here are some questions trying to prompt an "oh yeah I forgot to mention
> that"-type answer.  Anything where the answer is more like "that should
> probably be rewritten to be clearer", let me know and I'll avoid confusing
> newbies with it.
> 
> av_ambient_viewing_environment_create_side_data() takes an AVFrame as its
> first argument, and returns a new AVAmbientViewingEnvironment.  What is the
> context object for that function - AVFrame or AVAmbientViewingEnvironment?
> 
> av_register_bitstream_filter() (deprecated 4.0, removed 5.0) took an
> `AVBitStreamFilter *` as its first argument, but I don't think you'd say
> the argument provided "context" for the function.  So would I be right in
> saying `AVBitStreamFilter *` is not a context, despite looking like one?
> 
> av_buffersink_*() all take a `const AVFilterContext *` argument.
> What does the difference between av_buffersink prefix and AVFilter type mean?
> 
> av_channel_description_bprint() takes a `struct AVBPrint *` as its first
> argument, then `enum AVChannel`.  Is the context AVBPrint, AVChannel,
> or both?  Does it make sense for a function to have two contexts?
> 
> Related to the previous question, does `av_cmp_q()` count as a function
> with two contexts?  Or no contexts?
> 
> Finally, a general question - functions of the form "avfoo" seem like they
> are more consistent than "av_foo".  Does the underscore mean anything?

One extra question I hadn't thought to ask before - when, if at all, would an
ordinary user be expected to access the contents of AVClass directly?  Or
AVOption for that matter?  For example, it's not clear to me how people are
supposed to use AVClass.category - is this an important use case we haven't
covered?  Either way, happy to propose an AVClass patch to make it clearer.

It's my turn to be off for a few days, so will pick up any responses next week.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation
  2024-04-29  9:24                   ` [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation Andrew Sayers
@ 2024-05-02 11:01                     ` Lynne
  2024-05-02 11:14                       ` Andrew Sayers
  2024-05-02 13:00                       ` Zhao Zhili
  0 siblings, 2 replies; 84+ messages in thread
From: Lynne @ 2024-05-02 11:01 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Apr 29, 2024, 11:24 by ffmpeg-devel@pileofstuff.org:

> Some headings needed to be rewritten to accomodate the text,
> (hopefully) without changing the meaning.
> ---
>  libavcodec/aac/aacdec.h            |  2 +-
>  libavcodec/aacenc.h                |  2 +-
>  libavcodec/ac3enc.h                |  2 +-
>  libavcodec/amfenc.h                |  2 +-
>  libavcodec/atrac.h                 |  2 +-
>  libavcodec/avcodec.h               |  3 ++-
>  libavcodec/bsf.h                   |  2 +-
>  libavcodec/cbs.h                   |  2 +-
>  libavcodec/d3d11va.h               |  3 +--
>  libavcodec/h264dsp.h               |  2 +-
>  libavcodec/h264pred.h              |  2 +-
>  libavcodec/mediacodec.h            |  2 +-
>  libavcodec/mpegaudiodec_template.c |  2 +-
>  libavcodec/pthread_frame.c         |  4 ++--
>  libavcodec/qsv.h                   |  6 ++++--
>  libavcodec/sbr.h                   |  2 +-
>  libavcodec/smacker.c               |  2 +-
>  libavcodec/vdpau.h                 |  3 ++-
>  libavcodec/videotoolbox.h          |  5 +++--
>  libavfilter/avfilter.h             |  2 +-
>  libavformat/avformat.h             |  3 ++-
>  libavformat/avio.h                 |  3 ++-
>  libavutil/audio_fifo.h             |  2 +-
>  libavutil/hwcontext.h              | 21 ++++++++++++---------
>  libavutil/hwcontext_cuda.h         |  2 +-
>  libavutil/hwcontext_d3d11va.h      |  4 ++--
>  libavutil/hwcontext_d3d12va.h      |  6 +++---
>  libavutil/hwcontext_drm.h          |  2 +-
>  libavutil/hwcontext_dxva2.h        |  4 ++--
>  libavutil/hwcontext_mediacodec.h   |  2 +-
>  libavutil/hwcontext_opencl.h       |  4 ++--
>  libavutil/hwcontext_qsv.h          |  4 ++--
>  libavutil/hwcontext_vaapi.h        |  6 +++---
>  libavutil/hwcontext_vdpau.h        |  2 +-
>  libavutil/hwcontext_vulkan.h       |  4 ++--
>  libavutil/lfg.h                    |  2 +-
>  36 files changed, 66 insertions(+), 57 deletions(-)
>
> diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
> index 4cf764e2e9..71d61813f4 100644
> --- a/libavcodec/aac/aacdec.h
> +++ b/libavcodec/aac/aacdec.h
> @@ -248,7 +248,7 @@ typedef struct AACDecDSP {
>  } AACDecDSP;
>  
>  /**
> - * main AAC decoding context
> + * main AAC decoding @ref md_doc_2context "context"
>  */
>  struct AACDecContext {
>  const struct AVClass  *class;
> diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
> index d07960620e..1a645f4719 100644
> --- a/libavcodec/aacenc.h
> +++ b/libavcodec/aacenc.h
> @@ -207,7 +207,7 @@ typedef struct AACPCEInfo {
>  } AACPCEInfo;
>  
>  /**
> - * AAC encoder context
> + * AAC encoder @ref md_doc_2context "context"
>  */
>  typedef struct AACEncContext {
>  AVClass *av_class;
> diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
> index 30812617cc..c725007077 100644
> --- a/libavcodec/ac3enc.h
> +++ b/libavcodec/ac3enc.h
> @@ -152,7 +152,7 @@ typedef struct AC3Block {
>  } AC3Block;
>  
>  /**
> - * AC-3 encoder private context.
> + * AC-3 encoder private @ref md_doc_2context "context"
>  */
>  typedef struct AC3EncodeContext {
>  AVClass *av_class;                      ///< AVClass used for AVOption
> diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
> index 2dbd378ef8..f142ede63a 100644
> --- a/libavcodec/amfenc.h
> +++ b/libavcodec/amfenc.h
> @@ -43,7 +43,7 @@ typedef struct AmfTraceWriter {
>  } AmfTraceWriter;
>  
>  /**
> -* AMF encoder context
> +* AMF encoder @ref md_doc_2context "context"
>  */
>  
>  typedef struct AmfContext {
> diff --git a/libavcodec/atrac.h b/libavcodec/atrac.h
> index 05208bbee6..1527e376a9 100644
> --- a/libavcodec/atrac.h
> +++ b/libavcodec/atrac.h
> @@ -39,7 +39,7 @@ typedef struct AtracGainInfo {
>  } AtracGainInfo;
>  
>  /**
> - *  Gain compensation context structure.
> + *  Gain compensation @ref md_doc_2context "context"
>  */
>  typedef struct AtracGCContext {
>  float   gain_tab1[16];  ///< gain compensation level table
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 968009a192..9180fedca7 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -430,7 +430,8 @@ typedef struct RcOverride{
>  #define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0)
>  
>  /**
> - * main external API structure.
> + * @ref md_doc_2context "Context" for an encode or decode session
> + *
>  * New fields can be added to the end with minor version bumps.
>  * Removal, reordering and changes to existing fields require a major
>  * version bump.
> diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
> index a09c69f242..bf79afa7cc 100644
> --- a/libavcodec/bsf.h
> +++ b/libavcodec/bsf.h
> @@ -56,7 +56,7 @@
>  */
>  
>  /**
> - * The bitstream filter state.
> + * Bitstream filter @ref md_doc_2context "context"
>  *
>  * This struct must be allocated with av_bsf_alloc() and freed with
>  * av_bsf_free().
> diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
> index d479b1ac2d..0ff64d2fef 100644
> --- a/libavcodec/cbs.h
> +++ b/libavcodec/cbs.h
> @@ -214,7 +214,7 @@ typedef void (*CBSTraceWriteCallback)(void *trace_context,
>  int64_t value);
>  
>  /**
> - * Context structure for coded bitstream operations.
> + * @ref md_doc_2context "Context" structure for coded bitstream operations.
>  */
>  typedef struct CodedBitstreamContext {
>  /**
> diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
> index 27f40e5519..ec0c472ab9 100644
> --- a/libavcodec/d3d11va.h
> +++ b/libavcodec/d3d11va.h
> @@ -46,8 +46,7 @@
>  */
>  
>  /**
> - * This structure is used to provides the necessary configurations and data
> - * to the Direct3D11 FFmpeg HWAccel implementation.
> + * @ref md_doc_2context "Context" for the Direct3D11 FFmpeg HWAccel implementation
>  *
>  * The application must make it available as AVCodecContext.hwaccel_context.
>  *
> diff --git a/libavcodec/h264dsp.h b/libavcodec/h264dsp.h
> index e0880c4d88..27256c5605 100644
> --- a/libavcodec/h264dsp.h
> +++ b/libavcodec/h264dsp.h
> @@ -37,7 +37,7 @@ typedef void (*h264_biweight_func)(uint8_t *dst, uint8_t *src,
>  int weightd, int weights, int offset);
>  
>  /**
> - * Context for storing H.264 DSP functions
> + * @ref md_doc_2context "Context" for storing H.264 DSP functions
>  */
>  typedef struct H264DSPContext {
>  /* weighted MC */
> diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h
> index cb008548fc..2b076f8846 100644
> --- a/libavcodec/h264pred.h
> +++ b/libavcodec/h264pred.h
> @@ -89,7 +89,7 @@
>  #define PART_NOT_AVAILABLE -2
>  
>  /**
> - * Context for storing H.264 prediction functions
> + * @ref md_doc_2context "Context" for storing H.264 prediction functions
>  */
>  typedef struct H264PredContext {
>  void(*pred4x4[9 + 3 + 3])(uint8_t *src, const uint8_t *topright,
> diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
> index 4e9b56a618..9967a7cfb3 100644
> --- a/libavcodec/mediacodec.h
> +++ b/libavcodec/mediacodec.h
> @@ -26,7 +26,7 @@
>  #include "libavcodec/avcodec.h"
>  
>  /**
> - * This structure holds a reference to a android/view/Surface object that will
> + * @ref md_doc_2context "Context" for the android/view/Surface object that will
>  * be used as output by the decoder.
>  *
>  */
> diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c
> index c73b1e0054..15d63215d1 100644
> --- a/libavcodec/mpegaudiodec_template.c
> +++ b/libavcodec/mpegaudiodec_template.c
> @@ -1691,7 +1691,7 @@ static int decode_frame_adu(AVCodecContext *avctx, AVFrame *frame,
>  #if CONFIG_MP3ON4_DECODER || CONFIG_MP3ON4FLOAT_DECODER
>  
>  /**
> - * Context for MP3On4 decoder
> + * @ref md_doc_2context "Context" for MP3On4 decoder
>  */
>  typedef struct MP3On4DecodeContext {
>  int frames;                     ///< number of mp3 frames per block (number of mp3 decoder instances)
> diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
> index 67f09c1f48..74f05eedcf 100644
> --- a/libavcodec/pthread_frame.c
> +++ b/libavcodec/pthread_frame.c
> @@ -71,7 +71,7 @@ typedef struct ThreadFrameProgress {
>  } ThreadFrameProgress;
>  
>  /**
> - * Context used by codec threads and stored in their AVCodecInternal thread_ctx.
> + * @ref md_doc_2context "Context" used by codec threads and stored in their AVCodecInternal thread_ctx.
>  */
>  typedef struct PerThreadContext {
>  struct FrameThreadContext *parent;
> @@ -111,7 +111,7 @@ typedef struct PerThreadContext {
>  } PerThreadContext;
>  
>  /**
> - * Context stored in the client AVCodecInternal thread_ctx.
> + * @ref md_doc_2context "Context" stored in the client AVCodecInternal thread_ctx.
>  */
>  typedef struct FrameThreadContext {
>  PerThreadContext *threads;     ///< The contexts for each thread.
> diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
> index c156b08d07..8b8160a4b1 100644
> --- a/libavcodec/qsv.h
> +++ b/libavcodec/qsv.h
> @@ -26,8 +26,10 @@
>  #include "libavutil/buffer.h"
>  
>  /**
> - * This struct is used for communicating QSV parameters between libavcodec and
> - * the caller. It is managed by the caller and must be assigned to
> + * @ref md_doc_2context "Context" for communicating QSV parameters between libavcodec
> + * and the caller.
> + *
> + * It is managed by the caller and must be assigned to
>  * AVCodecContext.hwaccel_context.
>  * - decoding: hwaccel_context must be set on return from the get_format()
>  *             callback
> diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
> index fe3a39603a..98ad9024a9 100644
> --- a/libavcodec/sbr.h
> +++ b/libavcodec/sbr.h
> @@ -116,7 +116,7 @@ typedef struct SBRData {
>  typedef struct SpectralBandReplication SpectralBandReplication;
>  
>  /**
> - * aacsbr functions pointers
> + * aacsbr functions pointer @ref md_doc_2context "context"
>  */
>  typedef struct AACSBRContext {
>  int (*sbr_lf_gen)(SpectralBandReplication *sbr,
> diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c
> index 8f198d6957..1ca39a74a0 100644
> --- a/libavcodec/smacker.c
> +++ b/libavcodec/smacker.c
> @@ -68,7 +68,7 @@ typedef struct HuffEntry {
>  } HuffEntry;
>  
>  /**
> - * Context used for code reconstructing
> + * @ref md_doc_2context "Context" used for code reconstructing
>  */
>  typedef struct HuffContext {
>  int current;
> diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
> index 8021c25761..227b85727d 100644
> --- a/libavcodec/vdpau.h
> +++ b/libavcodec/vdpau.h
> @@ -64,8 +64,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
>  const VdpBitstreamBuffer *);
>  
>  /**
> - * This structure is used to share data between the libavcodec library and
> + * @ref md_doc_2context "Context" to share data between the libavcodec library and
>  * the client video application.
> + *
>  * This structure will be allocated and stored in AVCodecContext.hwaccel_context
>  * by av_vdpau_bind_context(). Members can be set by the user once
>  * during initialization or through each AVCodecContext.get_buffer()
> diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
> index d68d76e400..f15e79f325 100644
> --- a/libavcodec/videotoolbox.h
> +++ b/libavcodec/videotoolbox.h
> @@ -49,8 +49,9 @@
>  #include "libavutil/attributes.h"
>  
>  /**
> - * This struct holds all the information that needs to be passed
> - * between the caller and libavcodec for initializing Videotoolbox decoding.
> + * @ref md_doc_2context "Context" for information passed between the caller and libavcodec
> + * for initializing Videotoolbox decoding.
> + *
>  * Its size is not a part of the public ABI, it must be allocated with
>  * av_videotoolbox_alloc_context() and freed with av_free().
>  */
> diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
> index a34e61f23c..54b5f9dc43 100644
> --- a/libavfilter/avfilter.h
> +++ b/libavfilter/avfilter.h
> @@ -403,7 +403,7 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
>  */
>  #define AVFILTER_THREAD_SLICE (1 << 0)
>  
> -/** An instance of a filter */
> +/** @ref md_doc_2context "Context" for a filter */
>  struct AVFilterContext {
>  const AVClass *av_class;        ///< needed for av_log() and filters common options
>  
> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> index 8afdcd9fd0..28243c06c4 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -1241,7 +1241,8 @@ enum AVDurationEstimationMethod {
>  };
>  
>  /**
> - * Format I/O context.
> + * Format I/O @ref md_doc_2context "context"
> + *
>  * New fields can be added to the end with minor version bumps.
>  * Removal, reordering and changes to existing fields require a major
>  * version bump.
> diff --git a/libavformat/avio.h b/libavformat/avio.h
> index ebf611187d..b525c93194 100644
> --- a/libavformat/avio.h
> +++ b/libavformat/avio.h
> @@ -146,7 +146,8 @@ enum AVIODataMarkerType {
>  };
>  
>  /**
> - * Bytestream IO Context.
> + * Bytestream I/O @ref md_doc_2context "context"
> + *
>  * New public fields can be added with minor version bumps.
>  * Removal, reordering and changes to existing public fields require
>  * a major version bump.
> diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h
> index fa5f59a2be..de29715462 100644
> --- a/libavutil/audio_fifo.h
> +++ b/libavutil/audio_fifo.h
> @@ -39,7 +39,7 @@
>  */
>  
>  /**
> - * Context for an Audio FIFO Buffer.
> + * @ref md_doc_2context "Context" for an Audio FIFO Buffer.
>  *
>  * - Operates at the sample level rather than the byte level.
>  * - Supports multiple channels with either planar or packed sample format.
> diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
> index bac30debae..60064cf08b 100644
> --- a/libavutil/hwcontext.h
> +++ b/libavutil/hwcontext.h
> @@ -41,12 +41,13 @@ enum AVHWDeviceType {
>  };
>  
>  /**
> - * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
> - * i.e. state that is not tied to a concrete processing configuration.
> - * E.g., in an API that supports hardware-accelerated encoding and decoding,
> - * this struct will (if possible) wrap the state that is common to both encoding
> - * and decoding and from which specific instances of encoders or decoders can be
> - * derived.
> + * @ref md_doc_2context "Context" for (hardware/vendor-specific) "high-level" state.
> + *
> + * "High-level state" is anything that is not tied to a concrete processing
> + * configuration. E.g., in an API that supports hardware-accelerated encoding
> + * and decoding, this struct will (if possible) wrap the state that is common
> + * to both encoding and decoding and from which specific instances of encoders
> + * or decoders can be derived.
>  *
>  * This struct is reference-counted with the AVBuffer mechanism. The
>  * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
> @@ -103,9 +104,11 @@ typedef struct AVHWDeviceContext {
>  } AVHWDeviceContext;
>  
>  /**
> - * This struct describes a set or pool of "hardware" frames (i.e. those with
> - * data not located in normal system memory). All the frames in the pool are
> - * assumed to be allocated in the same way and interchangeable.
> + * @ref md_doc_2context "context" for a pool of "hardware" frames (those with
> + * data not located in normal system memory)
> + *
> + * All the frames in the pool are assumed to be allocated in the same way and
> + * interchangeable.
>  *
>  * This struct is reference-counted with the AVBuffer mechanism and tied to a
>  * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
> diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
> index cbad434fea..e259892688 100644
> --- a/libavutil/hwcontext_cuda.h
> +++ b/libavutil/hwcontext_cuda.h
> @@ -37,7 +37,7 @@
>  typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
>  
>  /**
> - * This struct is allocated as AVHWDeviceContext.hwctx
> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>  */
>  typedef struct AVCUDADeviceContext {
>  CUcontext cuda_ctx;
> diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
> index 77d2d72f1b..101d1cb6f8 100644
> --- a/libavutil/hwcontext_d3d11va.h
> +++ b/libavutil/hwcontext_d3d11va.h
> @@ -40,7 +40,7 @@
>  #include <stdint.h>
>  
>  /**
> - * This struct is allocated as AVHWDeviceContext.hwctx
> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>  */
>  typedef struct AVD3D11VADeviceContext {
>  /**
> @@ -126,7 +126,7 @@ typedef struct AVD3D11FrameDescriptor {
>  } AVD3D11FrameDescriptor;
>  
>  /**
> - * This struct is allocated as AVHWFramesContext.hwctx
> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
>  */
>  typedef struct AVD3D11VAFramesContext {
>  /**
> diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
> index ff06e6f2ef..c623914c2b 100644
> --- a/libavutil/hwcontext_d3d12va.h
> +++ b/libavutil/hwcontext_d3d12va.h
> @@ -37,7 +37,7 @@
>  #include <d3d12video.h>
>  
>  /**
> - * @brief This struct is allocated as AVHWDeviceContext.hwctx
> + * @brief This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>  *
>  */
>  typedef struct AVD3D12VADeviceContext {
> @@ -78,7 +78,7 @@ typedef struct AVD3D12VADeviceContext {
>  } AVD3D12VADeviceContext;
>  
>  /**
> - * @brief This struct is used to sync d3d12 execution
> + * @brief This @ref md_doc_2context "context" is used to sync d3d12 execution
>  *
>  */
>  typedef struct AVD3D12VASyncContext {
> @@ -120,7 +120,7 @@ typedef struct AVD3D12VAFrame {
>  } AVD3D12VAFrame;
>  
>  /**
> - * @brief This struct is allocated as AVHWFramesContext.hwctx
> + * @brief This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
>  *
>  */
>  typedef struct AVD3D12VAFramesContext {
> diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
> index 42709f215e..8329e69966 100644
> --- a/libavutil/hwcontext_drm.h
> +++ b/libavutil/hwcontext_drm.h
> @@ -152,7 +152,7 @@ typedef struct AVDRMFrameDescriptor {
>  /**
>  * DRM device.
>  *
> - * Allocated as AVHWDeviceContext.hwctx.
> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx.
>  */
>  typedef struct AVDRMDeviceContext {
>  /**
> diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
> index e1b79bc0de..c679c16af0 100644
> --- a/libavutil/hwcontext_dxva2.h
> +++ b/libavutil/hwcontext_dxva2.h
> @@ -34,14 +34,14 @@
>  #include <dxva2api.h>
>  
>  /**
> - * This struct is allocated as AVHWDeviceContext.hwctx
> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>  */
>  typedef struct AVDXVA2DeviceContext {
>  IDirect3DDeviceManager9 *devmgr;
>  } AVDXVA2DeviceContext;
>  
>  /**
> - * This struct is allocated as AVHWFramesContext.hwctx
> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
>  */
>  typedef struct AVDXVA2FramesContext {
>  /**
> diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
> index fc0263cabc..e81193247b 100644
> --- a/libavutil/hwcontext_mediacodec.h
> +++ b/libavutil/hwcontext_mediacodec.h
> @@ -22,7 +22,7 @@
>  /**
>  * MediaCodec details.
>  *
> - * Allocated as AVHWDeviceContext.hwctx
> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>  */
>  typedef struct AVMediaCodecDeviceContext {
>  /**
> diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
> index ef54486c95..7abd97db2b 100644
> --- a/libavutil/hwcontext_opencl.h
> +++ b/libavutil/hwcontext_opencl.h
> @@ -58,7 +58,7 @@ typedef struct AVOpenCLFrameDescriptor {
>  /**
>  * OpenCL device details.
>  *
> - * Allocated as AVHWDeviceContext.hwctx
> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>  */
>  typedef struct AVOpenCLDeviceContext {
>  /**
> @@ -84,7 +84,7 @@ typedef struct AVOpenCLDeviceContext {
>  /**
>  * OpenCL-specific data associated with a frame pool.
>  *
> - * Allocated as AVHWFramesContext.hwctx.
> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
>  */
>  typedef struct AVOpenCLFramesContext {
>  /**
> diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
> index e2dba8ad83..b63ebddaef 100644
> --- a/libavutil/hwcontext_qsv.h
> +++ b/libavutil/hwcontext_qsv.h
> @@ -30,7 +30,7 @@
>  */
>  
>  /**
> - * This struct is allocated as AVHWDeviceContext.hwctx
> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>  */
>  typedef struct AVQSVDeviceContext {
>  mfxSession session;
> @@ -48,7 +48,7 @@ typedef struct AVQSVDeviceContext {
>  } AVQSVDeviceContext;
>  
>  /**
> - * This struct is allocated as AVHWFramesContext.hwctx
> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
>  */
>  typedef struct AVQSVFramesContext {
>  mfxFrameSurface1 *surfaces;
> diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
> index 0b2e071cb3..4a897eb851 100644
> --- a/libavutil/hwcontext_vaapi.h
> +++ b/libavutil/hwcontext_vaapi.h
> @@ -63,7 +63,7 @@ enum {
>  /**
>  * VAAPI connection details.
>  *
> - * Allocated as AVHWDeviceContext.hwctx
> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>  */
>  typedef struct AVVAAPIDeviceContext {
>  /**
> @@ -83,7 +83,7 @@ typedef struct AVVAAPIDeviceContext {
>  /**
>  * VAAPI-specific data associated with a frame pool.
>  *
> - * Allocated as AVHWFramesContext.hwctx.
> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
>  */
>  typedef struct AVVAAPIFramesContext {
>  /**
> @@ -105,7 +105,7 @@ typedef struct AVVAAPIFramesContext {
>  /**
>  * VAAPI hardware pipeline configuration details.
>  *
> - * Allocated with av_hwdevice_hwconfig_alloc().
> + * This struct is allocated with av_hwdevice_hwconfig_alloc().
>  */
>  typedef struct AVVAAPIHWConfig {
>  /**
> diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
> index 1b7ea1e443..e305caa595 100644
> --- a/libavutil/hwcontext_vdpau.h
> +++ b/libavutil/hwcontext_vdpau.h
> @@ -30,7 +30,7 @@
>  */
>  
>  /**
> - * This struct is allocated as AVHWDeviceContext.hwctx
> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>  */
>  typedef struct AVVDPAUDeviceContext {
>  VdpDevice          device;
> diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
> index cbbd2390c1..1869870032 100644
> --- a/libavutil/hwcontext_vulkan.h
> +++ b/libavutil/hwcontext_vulkan.h
> @@ -39,7 +39,7 @@ typedef struct AVVkFrame AVVkFrame;
>  */
>  
>  /**
> - * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
> + * Main Vulkan @ref md_doc_2context "context", allocated as AVHWDeviceContext.hwctx.
>  * All of these can be set before init to change what the context uses
>  */
>  typedef struct AVVulkanDeviceContext {
> @@ -172,7 +172,7 @@ typedef enum AVVkFrameFlags {
>  } AVVkFrameFlags;
>  
>  /**
> - * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx, used to set pool-specific options
>  */
>  typedef struct AVVulkanFramesContext {
>  /**
> diff --git a/libavutil/lfg.h b/libavutil/lfg.h
> index e75a986f12..7f4ff5b62f 100644
> --- a/libavutil/lfg.h
> +++ b/libavutil/lfg.h
> @@ -25,7 +25,7 @@
>  #include <stdint.h>
>  
>  /**
> - * Context structure for the Lagged Fibonacci PRNG.
> + * @ref md_doc_2context "Context" structure for the Lagged Fibonacci PRNG.
>  * The exact layout, types and content of this struct may change and should
>  * not be accessed directly. Only its `sizeof()` is guaranteed to stay the same
>  * to allow easy instanciation.
>

Could you at least not put "context" in quotation marks?
To be honest, I'm not sure this makes documentation any better.
A context is an essential term we use in our codebase that's pretty
universal. Explaining again and again at every mention is annoying.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation
  2024-05-02 11:01                     ` Lynne
@ 2024-05-02 11:14                       ` Andrew Sayers
  2024-05-02 13:00                       ` Zhao Zhili
  1 sibling, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-02 11:14 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Thu, May 02, 2024 at 01:01:43PM +0200, Lynne wrote:
> Apr 29, 2024, 11:24 by ffmpeg-devel@pileofstuff.org:
> 
> > Some headings needed to be rewritten to accomodate the text,
> > (hopefully) without changing the meaning.
> > ---
> >  libavcodec/aac/aacdec.h            |  2 +-
> >  libavcodec/aacenc.h                |  2 +-
> >  libavcodec/ac3enc.h                |  2 +-
> >  libavcodec/amfenc.h                |  2 +-
> >  libavcodec/atrac.h                 |  2 +-
> >  libavcodec/avcodec.h               |  3 ++-
> >  libavcodec/bsf.h                   |  2 +-
> >  libavcodec/cbs.h                   |  2 +-
> >  libavcodec/d3d11va.h               |  3 +--
> >  libavcodec/h264dsp.h               |  2 +-
> >  libavcodec/h264pred.h              |  2 +-
> >  libavcodec/mediacodec.h            |  2 +-
> >  libavcodec/mpegaudiodec_template.c |  2 +-
> >  libavcodec/pthread_frame.c         |  4 ++--
> >  libavcodec/qsv.h                   |  6 ++++--
> >  libavcodec/sbr.h                   |  2 +-
> >  libavcodec/smacker.c               |  2 +-
> >  libavcodec/vdpau.h                 |  3 ++-
> >  libavcodec/videotoolbox.h          |  5 +++--
> >  libavfilter/avfilter.h             |  2 +-
> >  libavformat/avformat.h             |  3 ++-
> >  libavformat/avio.h                 |  3 ++-
> >  libavutil/audio_fifo.h             |  2 +-
> >  libavutil/hwcontext.h              | 21 ++++++++++++---------
> >  libavutil/hwcontext_cuda.h         |  2 +-
> >  libavutil/hwcontext_d3d11va.h      |  4 ++--
> >  libavutil/hwcontext_d3d12va.h      |  6 +++---
> >  libavutil/hwcontext_drm.h          |  2 +-
> >  libavutil/hwcontext_dxva2.h        |  4 ++--
> >  libavutil/hwcontext_mediacodec.h   |  2 +-
> >  libavutil/hwcontext_opencl.h       |  4 ++--
> >  libavutil/hwcontext_qsv.h          |  4 ++--
> >  libavutil/hwcontext_vaapi.h        |  6 +++---
> >  libavutil/hwcontext_vdpau.h        |  2 +-
> >  libavutil/hwcontext_vulkan.h       |  4 ++--
> >  libavutil/lfg.h                    |  2 +-
> >  36 files changed, 66 insertions(+), 57 deletions(-)
> >
> > diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
> > index 4cf764e2e9..71d61813f4 100644
> > --- a/libavcodec/aac/aacdec.h
> > +++ b/libavcodec/aac/aacdec.h
> > @@ -248,7 +248,7 @@ typedef struct AACDecDSP {
> >  } AACDecDSP;
> >  
> >  /**
> > - * main AAC decoding context
> > + * main AAC decoding @ref md_doc_2context "context"
> >  */
> >  struct AACDecContext {
> >  const struct AVClass  *class;
> > diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
> > index d07960620e..1a645f4719 100644
> > --- a/libavcodec/aacenc.h
> > +++ b/libavcodec/aacenc.h
> > @@ -207,7 +207,7 @@ typedef struct AACPCEInfo {
> >  } AACPCEInfo;
> >  
> >  /**
> > - * AAC encoder context
> > + * AAC encoder @ref md_doc_2context "context"
> >  */
> >  typedef struct AACEncContext {
> >  AVClass *av_class;
> > diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
> > index 30812617cc..c725007077 100644
> > --- a/libavcodec/ac3enc.h
> > +++ b/libavcodec/ac3enc.h
> > @@ -152,7 +152,7 @@ typedef struct AC3Block {
> >  } AC3Block;
> >  
> >  /**
> > - * AC-3 encoder private context.
> > + * AC-3 encoder private @ref md_doc_2context "context"
> >  */
> >  typedef struct AC3EncodeContext {
> >  AVClass *av_class;                      ///< AVClass used for AVOption
> > diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
> > index 2dbd378ef8..f142ede63a 100644
> > --- a/libavcodec/amfenc.h
> > +++ b/libavcodec/amfenc.h
> > @@ -43,7 +43,7 @@ typedef struct AmfTraceWriter {
> >  } AmfTraceWriter;
> >  
> >  /**
> > -* AMF encoder context
> > +* AMF encoder @ref md_doc_2context "context"
> >  */
> >  
> >  typedef struct AmfContext {
> > diff --git a/libavcodec/atrac.h b/libavcodec/atrac.h
> > index 05208bbee6..1527e376a9 100644
> > --- a/libavcodec/atrac.h
> > +++ b/libavcodec/atrac.h
> > @@ -39,7 +39,7 @@ typedef struct AtracGainInfo {
> >  } AtracGainInfo;
> >  
> >  /**
> > - *  Gain compensation context structure.
> > + *  Gain compensation @ref md_doc_2context "context"
> >  */
> >  typedef struct AtracGCContext {
> >  float   gain_tab1[16];  ///< gain compensation level table
> > diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> > index 968009a192..9180fedca7 100644
> > --- a/libavcodec/avcodec.h
> > +++ b/libavcodec/avcodec.h
> > @@ -430,7 +430,8 @@ typedef struct RcOverride{
> >  #define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0)
> >  
> >  /**
> > - * main external API structure.
> > + * @ref md_doc_2context "Context" for an encode or decode session
> > + *
> >  * New fields can be added to the end with minor version bumps.
> >  * Removal, reordering and changes to existing fields require a major
> >  * version bump.
> > diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
> > index a09c69f242..bf79afa7cc 100644
> > --- a/libavcodec/bsf.h
> > +++ b/libavcodec/bsf.h
> > @@ -56,7 +56,7 @@
> >  */
> >  
> >  /**
> > - * The bitstream filter state.
> > + * Bitstream filter @ref md_doc_2context "context"
> >  *
> >  * This struct must be allocated with av_bsf_alloc() and freed with
> >  * av_bsf_free().
> > diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
> > index d479b1ac2d..0ff64d2fef 100644
> > --- a/libavcodec/cbs.h
> > +++ b/libavcodec/cbs.h
> > @@ -214,7 +214,7 @@ typedef void (*CBSTraceWriteCallback)(void *trace_context,
> >  int64_t value);
> >  
> >  /**
> > - * Context structure for coded bitstream operations.
> > + * @ref md_doc_2context "Context" structure for coded bitstream operations.
> >  */
> >  typedef struct CodedBitstreamContext {
> >  /**
> > diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
> > index 27f40e5519..ec0c472ab9 100644
> > --- a/libavcodec/d3d11va.h
> > +++ b/libavcodec/d3d11va.h
> > @@ -46,8 +46,7 @@
> >  */
> >  
> >  /**
> > - * This structure is used to provides the necessary configurations and data
> > - * to the Direct3D11 FFmpeg HWAccel implementation.
> > + * @ref md_doc_2context "Context" for the Direct3D11 FFmpeg HWAccel implementation
> >  *
> >  * The application must make it available as AVCodecContext.hwaccel_context.
> >  *
> > diff --git a/libavcodec/h264dsp.h b/libavcodec/h264dsp.h
> > index e0880c4d88..27256c5605 100644
> > --- a/libavcodec/h264dsp.h
> > +++ b/libavcodec/h264dsp.h
> > @@ -37,7 +37,7 @@ typedef void (*h264_biweight_func)(uint8_t *dst, uint8_t *src,
> >  int weightd, int weights, int offset);
> >  
> >  /**
> > - * Context for storing H.264 DSP functions
> > + * @ref md_doc_2context "Context" for storing H.264 DSP functions
> >  */
> >  typedef struct H264DSPContext {
> >  /* weighted MC */
> > diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h
> > index cb008548fc..2b076f8846 100644
> > --- a/libavcodec/h264pred.h
> > +++ b/libavcodec/h264pred.h
> > @@ -89,7 +89,7 @@
> >  #define PART_NOT_AVAILABLE -2
> >  
> >  /**
> > - * Context for storing H.264 prediction functions
> > + * @ref md_doc_2context "Context" for storing H.264 prediction functions
> >  */
> >  typedef struct H264PredContext {
> >  void(*pred4x4[9 + 3 + 3])(uint8_t *src, const uint8_t *topright,
> > diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
> > index 4e9b56a618..9967a7cfb3 100644
> > --- a/libavcodec/mediacodec.h
> > +++ b/libavcodec/mediacodec.h
> > @@ -26,7 +26,7 @@
> >  #include "libavcodec/avcodec.h"
> >  
> >  /**
> > - * This structure holds a reference to a android/view/Surface object that will
> > + * @ref md_doc_2context "Context" for the android/view/Surface object that will
> >  * be used as output by the decoder.
> >  *
> >  */
> > diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c
> > index c73b1e0054..15d63215d1 100644
> > --- a/libavcodec/mpegaudiodec_template.c
> > +++ b/libavcodec/mpegaudiodec_template.c
> > @@ -1691,7 +1691,7 @@ static int decode_frame_adu(AVCodecContext *avctx, AVFrame *frame,
> >  #if CONFIG_MP3ON4_DECODER || CONFIG_MP3ON4FLOAT_DECODER
> >  
> >  /**
> > - * Context for MP3On4 decoder
> > + * @ref md_doc_2context "Context" for MP3On4 decoder
> >  */
> >  typedef struct MP3On4DecodeContext {
> >  int frames;                     ///< number of mp3 frames per block (number of mp3 decoder instances)
> > diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
> > index 67f09c1f48..74f05eedcf 100644
> > --- a/libavcodec/pthread_frame.c
> > +++ b/libavcodec/pthread_frame.c
> > @@ -71,7 +71,7 @@ typedef struct ThreadFrameProgress {
> >  } ThreadFrameProgress;
> >  
> >  /**
> > - * Context used by codec threads and stored in their AVCodecInternal thread_ctx.
> > + * @ref md_doc_2context "Context" used by codec threads and stored in their AVCodecInternal thread_ctx.
> >  */
> >  typedef struct PerThreadContext {
> >  struct FrameThreadContext *parent;
> > @@ -111,7 +111,7 @@ typedef struct PerThreadContext {
> >  } PerThreadContext;
> >  
> >  /**
> > - * Context stored in the client AVCodecInternal thread_ctx.
> > + * @ref md_doc_2context "Context" stored in the client AVCodecInternal thread_ctx.
> >  */
> >  typedef struct FrameThreadContext {
> >  PerThreadContext *threads;     ///< The contexts for each thread.
> > diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
> > index c156b08d07..8b8160a4b1 100644
> > --- a/libavcodec/qsv.h
> > +++ b/libavcodec/qsv.h
> > @@ -26,8 +26,10 @@
> >  #include "libavutil/buffer.h"
> >  
> >  /**
> > - * This struct is used for communicating QSV parameters between libavcodec and
> > - * the caller. It is managed by the caller and must be assigned to
> > + * @ref md_doc_2context "Context" for communicating QSV parameters between libavcodec
> > + * and the caller.
> > + *
> > + * It is managed by the caller and must be assigned to
> >  * AVCodecContext.hwaccel_context.
> >  * - decoding: hwaccel_context must be set on return from the get_format()
> >  *             callback
> > diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
> > index fe3a39603a..98ad9024a9 100644
> > --- a/libavcodec/sbr.h
> > +++ b/libavcodec/sbr.h
> > @@ -116,7 +116,7 @@ typedef struct SBRData {
> >  typedef struct SpectralBandReplication SpectralBandReplication;
> >  
> >  /**
> > - * aacsbr functions pointers
> > + * aacsbr functions pointer @ref md_doc_2context "context"
> >  */
> >  typedef struct AACSBRContext {
> >  int (*sbr_lf_gen)(SpectralBandReplication *sbr,
> > diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c
> > index 8f198d6957..1ca39a74a0 100644
> > --- a/libavcodec/smacker.c
> > +++ b/libavcodec/smacker.c
> > @@ -68,7 +68,7 @@ typedef struct HuffEntry {
> >  } HuffEntry;
> >  
> >  /**
> > - * Context used for code reconstructing
> > + * @ref md_doc_2context "Context" used for code reconstructing
> >  */
> >  typedef struct HuffContext {
> >  int current;
> > diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
> > index 8021c25761..227b85727d 100644
> > --- a/libavcodec/vdpau.h
> > +++ b/libavcodec/vdpau.h
> > @@ -64,8 +64,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
> >  const VdpBitstreamBuffer *);
> >  
> >  /**
> > - * This structure is used to share data between the libavcodec library and
> > + * @ref md_doc_2context "Context" to share data between the libavcodec library and
> >  * the client video application.
> > + *
> >  * This structure will be allocated and stored in AVCodecContext.hwaccel_context
> >  * by av_vdpau_bind_context(). Members can be set by the user once
> >  * during initialization or through each AVCodecContext.get_buffer()
> > diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
> > index d68d76e400..f15e79f325 100644
> > --- a/libavcodec/videotoolbox.h
> > +++ b/libavcodec/videotoolbox.h
> > @@ -49,8 +49,9 @@
> >  #include "libavutil/attributes.h"
> >  
> >  /**
> > - * This struct holds all the information that needs to be passed
> > - * between the caller and libavcodec for initializing Videotoolbox decoding.
> > + * @ref md_doc_2context "Context" for information passed between the caller and libavcodec
> > + * for initializing Videotoolbox decoding.
> > + *
> >  * Its size is not a part of the public ABI, it must be allocated with
> >  * av_videotoolbox_alloc_context() and freed with av_free().
> >  */
> > diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
> > index a34e61f23c..54b5f9dc43 100644
> > --- a/libavfilter/avfilter.h
> > +++ b/libavfilter/avfilter.h
> > @@ -403,7 +403,7 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
> >  */
> >  #define AVFILTER_THREAD_SLICE (1 << 0)
> >  
> > -/** An instance of a filter */
> > +/** @ref md_doc_2context "Context" for a filter */
> >  struct AVFilterContext {
> >  const AVClass *av_class;        ///< needed for av_log() and filters common options
> >  
> > diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> > index 8afdcd9fd0..28243c06c4 100644
> > --- a/libavformat/avformat.h
> > +++ b/libavformat/avformat.h
> > @@ -1241,7 +1241,8 @@ enum AVDurationEstimationMethod {
> >  };
> >  
> >  /**
> > - * Format I/O context.
> > + * Format I/O @ref md_doc_2context "context"
> > + *
> >  * New fields can be added to the end with minor version bumps.
> >  * Removal, reordering and changes to existing fields require a major
> >  * version bump.
> > diff --git a/libavformat/avio.h b/libavformat/avio.h
> > index ebf611187d..b525c93194 100644
> > --- a/libavformat/avio.h
> > +++ b/libavformat/avio.h
> > @@ -146,7 +146,8 @@ enum AVIODataMarkerType {
> >  };
> >  
> >  /**
> > - * Bytestream IO Context.
> > + * Bytestream I/O @ref md_doc_2context "context"
> > + *
> >  * New public fields can be added with minor version bumps.
> >  * Removal, reordering and changes to existing public fields require
> >  * a major version bump.
> > diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h
> > index fa5f59a2be..de29715462 100644
> > --- a/libavutil/audio_fifo.h
> > +++ b/libavutil/audio_fifo.h
> > @@ -39,7 +39,7 @@
> >  */
> >  
> >  /**
> > - * Context for an Audio FIFO Buffer.
> > + * @ref md_doc_2context "Context" for an Audio FIFO Buffer.
> >  *
> >  * - Operates at the sample level rather than the byte level.
> >  * - Supports multiple channels with either planar or packed sample format.
> > diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
> > index bac30debae..60064cf08b 100644
> > --- a/libavutil/hwcontext.h
> > +++ b/libavutil/hwcontext.h
> > @@ -41,12 +41,13 @@ enum AVHWDeviceType {
> >  };
> >  
> >  /**
> > - * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
> > - * i.e. state that is not tied to a concrete processing configuration.
> > - * E.g., in an API that supports hardware-accelerated encoding and decoding,
> > - * this struct will (if possible) wrap the state that is common to both encoding
> > - * and decoding and from which specific instances of encoders or decoders can be
> > - * derived.
> > + * @ref md_doc_2context "Context" for (hardware/vendor-specific) "high-level" state.
> > + *
> > + * "High-level state" is anything that is not tied to a concrete processing
> > + * configuration. E.g., in an API that supports hardware-accelerated encoding
> > + * and decoding, this struct will (if possible) wrap the state that is common
> > + * to both encoding and decoding and from which specific instances of encoders
> > + * or decoders can be derived.
> >  *
> >  * This struct is reference-counted with the AVBuffer mechanism. The
> >  * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
> > @@ -103,9 +104,11 @@ typedef struct AVHWDeviceContext {
> >  } AVHWDeviceContext;
> >  
> >  /**
> > - * This struct describes a set or pool of "hardware" frames (i.e. those with
> > - * data not located in normal system memory). All the frames in the pool are
> > - * assumed to be allocated in the same way and interchangeable.
> > + * @ref md_doc_2context "context" for a pool of "hardware" frames (those with
> > + * data not located in normal system memory)
> > + *
> > + * All the frames in the pool are assumed to be allocated in the same way and
> > + * interchangeable.
> >  *
> >  * This struct is reference-counted with the AVBuffer mechanism and tied to a
> >  * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
> > diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
> > index cbad434fea..e259892688 100644
> > --- a/libavutil/hwcontext_cuda.h
> > +++ b/libavutil/hwcontext_cuda.h
> > @@ -37,7 +37,7 @@
> >  typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
> >  
> >  /**
> > - * This struct is allocated as AVHWDeviceContext.hwctx
> > + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >  */
> >  typedef struct AVCUDADeviceContext {
> >  CUcontext cuda_ctx;
> > diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
> > index 77d2d72f1b..101d1cb6f8 100644
> > --- a/libavutil/hwcontext_d3d11va.h
> > +++ b/libavutil/hwcontext_d3d11va.h
> > @@ -40,7 +40,7 @@
> >  #include <stdint.h>
> >  
> >  /**
> > - * This struct is allocated as AVHWDeviceContext.hwctx
> > + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >  */
> >  typedef struct AVD3D11VADeviceContext {
> >  /**
> > @@ -126,7 +126,7 @@ typedef struct AVD3D11FrameDescriptor {
> >  } AVD3D11FrameDescriptor;
> >  
> >  /**
> > - * This struct is allocated as AVHWFramesContext.hwctx
> > + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
> >  */
> >  typedef struct AVD3D11VAFramesContext {
> >  /**
> > diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
> > index ff06e6f2ef..c623914c2b 100644
> > --- a/libavutil/hwcontext_d3d12va.h
> > +++ b/libavutil/hwcontext_d3d12va.h
> > @@ -37,7 +37,7 @@
> >  #include <d3d12video.h>
> >  
> >  /**
> > - * @brief This struct is allocated as AVHWDeviceContext.hwctx
> > + * @brief This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >  *
> >  */
> >  typedef struct AVD3D12VADeviceContext {
> > @@ -78,7 +78,7 @@ typedef struct AVD3D12VADeviceContext {
> >  } AVD3D12VADeviceContext;
> >  
> >  /**
> > - * @brief This struct is used to sync d3d12 execution
> > + * @brief This @ref md_doc_2context "context" is used to sync d3d12 execution
> >  *
> >  */
> >  typedef struct AVD3D12VASyncContext {
> > @@ -120,7 +120,7 @@ typedef struct AVD3D12VAFrame {
> >  } AVD3D12VAFrame;
> >  
> >  /**
> > - * @brief This struct is allocated as AVHWFramesContext.hwctx
> > + * @brief This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
> >  *
> >  */
> >  typedef struct AVD3D12VAFramesContext {
> > diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
> > index 42709f215e..8329e69966 100644
> > --- a/libavutil/hwcontext_drm.h
> > +++ b/libavutil/hwcontext_drm.h
> > @@ -152,7 +152,7 @@ typedef struct AVDRMFrameDescriptor {
> >  /**
> >  * DRM device.
> >  *
> > - * Allocated as AVHWDeviceContext.hwctx.
> > + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx.
> >  */
> >  typedef struct AVDRMDeviceContext {
> >  /**
> > diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
> > index e1b79bc0de..c679c16af0 100644
> > --- a/libavutil/hwcontext_dxva2.h
> > +++ b/libavutil/hwcontext_dxva2.h
> > @@ -34,14 +34,14 @@
> >  #include <dxva2api.h>
> >  
> >  /**
> > - * This struct is allocated as AVHWDeviceContext.hwctx
> > + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >  */
> >  typedef struct AVDXVA2DeviceContext {
> >  IDirect3DDeviceManager9 *devmgr;
> >  } AVDXVA2DeviceContext;
> >  
> >  /**
> > - * This struct is allocated as AVHWFramesContext.hwctx
> > + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
> >  */
> >  typedef struct AVDXVA2FramesContext {
> >  /**
> > diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
> > index fc0263cabc..e81193247b 100644
> > --- a/libavutil/hwcontext_mediacodec.h
> > +++ b/libavutil/hwcontext_mediacodec.h
> > @@ -22,7 +22,7 @@
> >  /**
> >  * MediaCodec details.
> >  *
> > - * Allocated as AVHWDeviceContext.hwctx
> > + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >  */
> >  typedef struct AVMediaCodecDeviceContext {
> >  /**
> > diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
> > index ef54486c95..7abd97db2b 100644
> > --- a/libavutil/hwcontext_opencl.h
> > +++ b/libavutil/hwcontext_opencl.h
> > @@ -58,7 +58,7 @@ typedef struct AVOpenCLFrameDescriptor {
> >  /**
> >  * OpenCL device details.
> >  *
> > - * Allocated as AVHWDeviceContext.hwctx
> > + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >  */
> >  typedef struct AVOpenCLDeviceContext {
> >  /**
> > @@ -84,7 +84,7 @@ typedef struct AVOpenCLDeviceContext {
> >  /**
> >  * OpenCL-specific data associated with a frame pool.
> >  *
> > - * Allocated as AVHWFramesContext.hwctx.
> > + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
> >  */
> >  typedef struct AVOpenCLFramesContext {
> >  /**
> > diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
> > index e2dba8ad83..b63ebddaef 100644
> > --- a/libavutil/hwcontext_qsv.h
> > +++ b/libavutil/hwcontext_qsv.h
> > @@ -30,7 +30,7 @@
> >  */
> >  
> >  /**
> > - * This struct is allocated as AVHWDeviceContext.hwctx
> > + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >  */
> >  typedef struct AVQSVDeviceContext {
> >  mfxSession session;
> > @@ -48,7 +48,7 @@ typedef struct AVQSVDeviceContext {
> >  } AVQSVDeviceContext;
> >  
> >  /**
> > - * This struct is allocated as AVHWFramesContext.hwctx
> > + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
> >  */
> >  typedef struct AVQSVFramesContext {
> >  mfxFrameSurface1 *surfaces;
> > diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
> > index 0b2e071cb3..4a897eb851 100644
> > --- a/libavutil/hwcontext_vaapi.h
> > +++ b/libavutil/hwcontext_vaapi.h
> > @@ -63,7 +63,7 @@ enum {
> >  /**
> >  * VAAPI connection details.
> >  *
> > - * Allocated as AVHWDeviceContext.hwctx
> > + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >  */
> >  typedef struct AVVAAPIDeviceContext {
> >  /**
> > @@ -83,7 +83,7 @@ typedef struct AVVAAPIDeviceContext {
> >  /**
> >  * VAAPI-specific data associated with a frame pool.
> >  *
> > - * Allocated as AVHWFramesContext.hwctx.
> > + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
> >  */
> >  typedef struct AVVAAPIFramesContext {
> >  /**
> > @@ -105,7 +105,7 @@ typedef struct AVVAAPIFramesContext {
> >  /**
> >  * VAAPI hardware pipeline configuration details.
> >  *
> > - * Allocated with av_hwdevice_hwconfig_alloc().
> > + * This struct is allocated with av_hwdevice_hwconfig_alloc().
> >  */
> >  typedef struct AVVAAPIHWConfig {
> >  /**
> > diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
> > index 1b7ea1e443..e305caa595 100644
> > --- a/libavutil/hwcontext_vdpau.h
> > +++ b/libavutil/hwcontext_vdpau.h
> > @@ -30,7 +30,7 @@
> >  */
> >  
> >  /**
> > - * This struct is allocated as AVHWDeviceContext.hwctx
> > + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >  */
> >  typedef struct AVVDPAUDeviceContext {
> >  VdpDevice          device;
> > diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
> > index cbbd2390c1..1869870032 100644
> > --- a/libavutil/hwcontext_vulkan.h
> > +++ b/libavutil/hwcontext_vulkan.h
> > @@ -39,7 +39,7 @@ typedef struct AVVkFrame AVVkFrame;
> >  */
> >  
> >  /**
> > - * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
> > + * Main Vulkan @ref md_doc_2context "context", allocated as AVHWDeviceContext.hwctx.
> >  * All of these can be set before init to change what the context uses
> >  */
> >  typedef struct AVVulkanDeviceContext {
> > @@ -172,7 +172,7 @@ typedef enum AVVkFrameFlags {
> >  } AVVkFrameFlags;
> >  
> >  /**
> > - * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
> > + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx, used to set pool-specific options
> >  */
> >  typedef struct AVVulkanFramesContext {
> >  /**
> > diff --git a/libavutil/lfg.h b/libavutil/lfg.h
> > index e75a986f12..7f4ff5b62f 100644
> > --- a/libavutil/lfg.h
> > +++ b/libavutil/lfg.h
> > @@ -25,7 +25,7 @@
> >  #include <stdint.h>
> >  
> >  /**
> > - * Context structure for the Lagged Fibonacci PRNG.
> > + * @ref md_doc_2context "Context" structure for the Lagged Fibonacci PRNG.
> >  * The exact layout, types and content of this struct may change and should
> >  * not be accessed directly. Only its `sizeof()` is guaranteed to stay the same
> >  * to allow easy instanciation.
> >
> 
> Could you at least not put "context" in quotation marks?
> To be honest, I'm not sure this makes documentation any better.
> A context is an essential term we use in our codebase that's pretty
> universal. Explaining again and again at every mention is annoying.

I'll check when I get back, but sadly the documentation implies quotation marks
are mandatory[0].  FWIW, it's rendered without quotes in the final documentation.

I don't really follow the second part - surely if it's essential for readers to
understand, and it's not common enough outside of FFmpeg that they can be
assumed to already know it, there need to be links everywhere in order for the
documentation to be any use to new readers?

[0] https://www.doxygen.nl/manual/commands.html#cmdref
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation
  2024-05-02 11:01                     ` Lynne
  2024-05-02 11:14                       ` Andrew Sayers
@ 2024-05-02 13:00                       ` Zhao Zhili
  2024-05-02 13:27                         ` Andrew Sayers
  1 sibling, 1 reply; 84+ messages in thread
From: Zhao Zhili @ 2024-05-02 13:00 UTC (permalink / raw)
  To: FFmpeg development discussions and patches



> On May 2, 2024, at 19:01, Lynne <dev@lynne.ee> wrote:
> 
> Apr 29, 2024, 11:24 by ffmpeg-devel@pileofstuff.org:
> 
>> Some headings needed to be rewritten to accomodate the text,
>> (hopefully) without changing the meaning.
>> ---
>> libavcodec/aac/aacdec.h            |  2 +-
>> libavcodec/aacenc.h                |  2 +-
>> libavcodec/ac3enc.h                |  2 +-
>> libavcodec/amfenc.h                |  2 +-
>> libavcodec/atrac.h                 |  2 +-
>> libavcodec/avcodec.h               |  3 ++-
>> libavcodec/bsf.h                   |  2 +-
>> libavcodec/cbs.h                   |  2 +-
>> libavcodec/d3d11va.h               |  3 +--
>> libavcodec/h264dsp.h               |  2 +-
>> libavcodec/h264pred.h              |  2 +-
>> libavcodec/mediacodec.h            |  2 +-
>> libavcodec/mpegaudiodec_template.c |  2 +-
>> libavcodec/pthread_frame.c         |  4 ++--
>> libavcodec/qsv.h                   |  6 ++++--
>> libavcodec/sbr.h                   |  2 +-
>> libavcodec/smacker.c               |  2 +-
>> libavcodec/vdpau.h                 |  3 ++-
>> libavcodec/videotoolbox.h          |  5 +++--
>> libavfilter/avfilter.h             |  2 +-
>> libavformat/avformat.h             |  3 ++-
>> libavformat/avio.h                 |  3 ++-
>> libavutil/audio_fifo.h             |  2 +-
>> libavutil/hwcontext.h              | 21 ++++++++++++---------
>> libavutil/hwcontext_cuda.h         |  2 +-
>> libavutil/hwcontext_d3d11va.h      |  4 ++--
>> libavutil/hwcontext_d3d12va.h      |  6 +++---
>> libavutil/hwcontext_drm.h          |  2 +-
>> libavutil/hwcontext_dxva2.h        |  4 ++--
>> libavutil/hwcontext_mediacodec.h   |  2 +-
>> libavutil/hwcontext_opencl.h       |  4 ++--
>> libavutil/hwcontext_qsv.h          |  4 ++--
>> libavutil/hwcontext_vaapi.h        |  6 +++---
>> libavutil/hwcontext_vdpau.h        |  2 +-
>> libavutil/hwcontext_vulkan.h       |  4 ++--
>> libavutil/lfg.h                    |  2 +-
>> 36 files changed, 66 insertions(+), 57 deletions(-)
>> 
>> diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
>> index 4cf764e2e9..71d61813f4 100644
>> --- a/libavcodec/aac/aacdec.h
>> +++ b/libavcodec/aac/aacdec.h
>> @@ -248,7 +248,7 @@ typedef struct AACDecDSP {
>> } AACDecDSP;
>> 
>> /**
>> - * main AAC decoding context
>> + * main AAC decoding @ref md_doc_2context "context"
>> */
>> struct AACDecContext {
>> const struct AVClass  *class;
>> diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
>> index d07960620e..1a645f4719 100644
>> --- a/libavcodec/aacenc.h
>> +++ b/libavcodec/aacenc.h
>> @@ -207,7 +207,7 @@ typedef struct AACPCEInfo {
>> } AACPCEInfo;
>> 
>> /**
>> - * AAC encoder context
>> + * AAC encoder @ref md_doc_2context "context"
>> */
>> typedef struct AACEncContext {
>> AVClass *av_class;
>> diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
>> index 30812617cc..c725007077 100644
>> --- a/libavcodec/ac3enc.h
>> +++ b/libavcodec/ac3enc.h
>> @@ -152,7 +152,7 @@ typedef struct AC3Block {
>> } AC3Block;
>> 
>> /**
>> - * AC-3 encoder private context.
>> + * AC-3 encoder private @ref md_doc_2context "context"
>> */
>> typedef struct AC3EncodeContext {
>> AVClass *av_class;                      ///< AVClass used for AVOption
>> diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
>> index 2dbd378ef8..f142ede63a 100644
>> --- a/libavcodec/amfenc.h
>> +++ b/libavcodec/amfenc.h
>> @@ -43,7 +43,7 @@ typedef struct AmfTraceWriter {
>> } AmfTraceWriter;
>> 
>> /**
>> -* AMF encoder context
>> +* AMF encoder @ref md_doc_2context "context"
>> */
>> 
>> typedef struct AmfContext {
>> diff --git a/libavcodec/atrac.h b/libavcodec/atrac.h
>> index 05208bbee6..1527e376a9 100644
>> --- a/libavcodec/atrac.h
>> +++ b/libavcodec/atrac.h
>> @@ -39,7 +39,7 @@ typedef struct AtracGainInfo {
>> } AtracGainInfo;
>> 
>> /**
>> - *  Gain compensation context structure.
>> + *  Gain compensation @ref md_doc_2context "context"
>> */
>> typedef struct AtracGCContext {
>> float   gain_tab1[16];  ///< gain compensation level table
>> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
>> index 968009a192..9180fedca7 100644
>> --- a/libavcodec/avcodec.h
>> +++ b/libavcodec/avcodec.h
>> @@ -430,7 +430,8 @@ typedef struct RcOverride{
>> #define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0)
>> 
>> /**
>> - * main external API structure.
>> + * @ref md_doc_2context "Context" for an encode or decode session
>> + *
>> * New fields can be added to the end with minor version bumps.
>> * Removal, reordering and changes to existing fields require a major
>> * version bump.
>> diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
>> index a09c69f242..bf79afa7cc 100644
>> --- a/libavcodec/bsf.h
>> +++ b/libavcodec/bsf.h
>> @@ -56,7 +56,7 @@
>> */
>> 
>> /**
>> - * The bitstream filter state.
>> + * Bitstream filter @ref md_doc_2context "context"
>> *
>> * This struct must be allocated with av_bsf_alloc() and freed with
>> * av_bsf_free().
>> diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
>> index d479b1ac2d..0ff64d2fef 100644
>> --- a/libavcodec/cbs.h
>> +++ b/libavcodec/cbs.h
>> @@ -214,7 +214,7 @@ typedef void (*CBSTraceWriteCallback)(void *trace_context,
>> int64_t value);
>> 
>> /**
>> - * Context structure for coded bitstream operations.
>> + * @ref md_doc_2context "Context" structure for coded bitstream operations.
>> */
>> typedef struct CodedBitstreamContext {
>> /**
>> diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
>> index 27f40e5519..ec0c472ab9 100644
>> --- a/libavcodec/d3d11va.h
>> +++ b/libavcodec/d3d11va.h
>> @@ -46,8 +46,7 @@
>> */
>> 
>> /**
>> - * This structure is used to provides the necessary configurations and data
>> - * to the Direct3D11 FFmpeg HWAccel implementation.
>> + * @ref md_doc_2context "Context" for the Direct3D11 FFmpeg HWAccel implementation
>> *
>> * The application must make it available as AVCodecContext.hwaccel_context.
>> *
>> diff --git a/libavcodec/h264dsp.h b/libavcodec/h264dsp.h
>> index e0880c4d88..27256c5605 100644
>> --- a/libavcodec/h264dsp.h
>> +++ b/libavcodec/h264dsp.h
>> @@ -37,7 +37,7 @@ typedef void (*h264_biweight_func)(uint8_t *dst, uint8_t *src,
>> int weightd, int weights, int offset);
>> 
>> /**
>> - * Context for storing H.264 DSP functions
>> + * @ref md_doc_2context "Context" for storing H.264 DSP functions
>> */
>> typedef struct H264DSPContext {
>> /* weighted MC */
>> diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h
>> index cb008548fc..2b076f8846 100644
>> --- a/libavcodec/h264pred.h
>> +++ b/libavcodec/h264pred.h
>> @@ -89,7 +89,7 @@
>> #define PART_NOT_AVAILABLE -2
>> 
>> /**
>> - * Context for storing H.264 prediction functions
>> + * @ref md_doc_2context "Context" for storing H.264 prediction functions
>> */
>> typedef struct H264PredContext {
>> void(*pred4x4[9 + 3 + 3])(uint8_t *src, const uint8_t *topright,
>> diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
>> index 4e9b56a618..9967a7cfb3 100644
>> --- a/libavcodec/mediacodec.h
>> +++ b/libavcodec/mediacodec.h
>> @@ -26,7 +26,7 @@
>> #include "libavcodec/avcodec.h"
>> 
>> /**
>> - * This structure holds a reference to a android/view/Surface object that will
>> + * @ref md_doc_2context "Context" for the android/view/Surface object that will
>> * be used as output by the decoder.
>> *
>> */
>> diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c
>> index c73b1e0054..15d63215d1 100644
>> --- a/libavcodec/mpegaudiodec_template.c
>> +++ b/libavcodec/mpegaudiodec_template.c
>> @@ -1691,7 +1691,7 @@ static int decode_frame_adu(AVCodecContext *avctx, AVFrame *frame,
>> #if CONFIG_MP3ON4_DECODER || CONFIG_MP3ON4FLOAT_DECODER
>> 
>> /**
>> - * Context for MP3On4 decoder
>> + * @ref md_doc_2context "Context" for MP3On4 decoder
>> */
>> typedef struct MP3On4DecodeContext {
>> int frames;                     ///< number of mp3 frames per block (number of mp3 decoder instances)
>> diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
>> index 67f09c1f48..74f05eedcf 100644
>> --- a/libavcodec/pthread_frame.c
>> +++ b/libavcodec/pthread_frame.c
>> @@ -71,7 +71,7 @@ typedef struct ThreadFrameProgress {
>> } ThreadFrameProgress;
>> 
>> /**
>> - * Context used by codec threads and stored in their AVCodecInternal thread_ctx.
>> + * @ref md_doc_2context "Context" used by codec threads and stored in their AVCodecInternal thread_ctx.
>> */
>> typedef struct PerThreadContext {
>> struct FrameThreadContext *parent;
>> @@ -111,7 +111,7 @@ typedef struct PerThreadContext {
>> } PerThreadContext;
>> 
>> /**
>> - * Context stored in the client AVCodecInternal thread_ctx.
>> + * @ref md_doc_2context "Context" stored in the client AVCodecInternal thread_ctx.
>> */
>> typedef struct FrameThreadContext {
>> PerThreadContext *threads;     ///< The contexts for each thread.
>> diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
>> index c156b08d07..8b8160a4b1 100644
>> --- a/libavcodec/qsv.h
>> +++ b/libavcodec/qsv.h
>> @@ -26,8 +26,10 @@
>> #include "libavutil/buffer.h"
>> 
>> /**
>> - * This struct is used for communicating QSV parameters between libavcodec and
>> - * the caller. It is managed by the caller and must be assigned to
>> + * @ref md_doc_2context "Context" for communicating QSV parameters between libavcodec
>> + * and the caller.
>> + *
>> + * It is managed by the caller and must be assigned to
>> * AVCodecContext.hwaccel_context.
>> * - decoding: hwaccel_context must be set on return from the get_format()
>> *             callback
>> diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
>> index fe3a39603a..98ad9024a9 100644
>> --- a/libavcodec/sbr.h
>> +++ b/libavcodec/sbr.h
>> @@ -116,7 +116,7 @@ typedef struct SBRData {
>> typedef struct SpectralBandReplication SpectralBandReplication;
>> 
>> /**
>> - * aacsbr functions pointers
>> + * aacsbr functions pointer @ref md_doc_2context "context"
>> */
>> typedef struct AACSBRContext {
>> int (*sbr_lf_gen)(SpectralBandReplication *sbr,
>> diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c
>> index 8f198d6957..1ca39a74a0 100644
>> --- a/libavcodec/smacker.c
>> +++ b/libavcodec/smacker.c
>> @@ -68,7 +68,7 @@ typedef struct HuffEntry {
>> } HuffEntry;
>> 
>> /**
>> - * Context used for code reconstructing
>> + * @ref md_doc_2context "Context" used for code reconstructing
>> */
>> typedef struct HuffContext {
>> int current;
>> diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
>> index 8021c25761..227b85727d 100644
>> --- a/libavcodec/vdpau.h
>> +++ b/libavcodec/vdpau.h
>> @@ -64,8 +64,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
>> const VdpBitstreamBuffer *);
>> 
>> /**
>> - * This structure is used to share data between the libavcodec library and
>> + * @ref md_doc_2context "Context" to share data between the libavcodec library and
>> * the client video application.
>> + *
>> * This structure will be allocated and stored in AVCodecContext.hwaccel_context
>> * by av_vdpau_bind_context(). Members can be set by the user once
>> * during initialization or through each AVCodecContext.get_buffer()
>> diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
>> index d68d76e400..f15e79f325 100644
>> --- a/libavcodec/videotoolbox.h
>> +++ b/libavcodec/videotoolbox.h
>> @@ -49,8 +49,9 @@
>> #include "libavutil/attributes.h"
>> 
>> /**
>> - * This struct holds all the information that needs to be passed
>> - * between the caller and libavcodec for initializing Videotoolbox decoding.
>> + * @ref md_doc_2context "Context" for information passed between the caller and libavcodec
>> + * for initializing Videotoolbox decoding.
>> + *
>> * Its size is not a part of the public ABI, it must be allocated with
>> * av_videotoolbox_alloc_context() and freed with av_free().
>> */
>> diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
>> index a34e61f23c..54b5f9dc43 100644
>> --- a/libavfilter/avfilter.h
>> +++ b/libavfilter/avfilter.h
>> @@ -403,7 +403,7 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
>> */
>> #define AVFILTER_THREAD_SLICE (1 << 0)
>> 
>> -/** An instance of a filter */
>> +/** @ref md_doc_2context "Context" for a filter */
>> struct AVFilterContext {
>> const AVClass *av_class;        ///< needed for av_log() and filters common options
>> 
>> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
>> index 8afdcd9fd0..28243c06c4 100644
>> --- a/libavformat/avformat.h
>> +++ b/libavformat/avformat.h
>> @@ -1241,7 +1241,8 @@ enum AVDurationEstimationMethod {
>> };
>> 
>> /**
>> - * Format I/O context.
>> + * Format I/O @ref md_doc_2context "context"
>> + *
>> * New fields can be added to the end with minor version bumps.
>> * Removal, reordering and changes to existing fields require a major
>> * version bump.
>> diff --git a/libavformat/avio.h b/libavformat/avio.h
>> index ebf611187d..b525c93194 100644
>> --- a/libavformat/avio.h
>> +++ b/libavformat/avio.h
>> @@ -146,7 +146,8 @@ enum AVIODataMarkerType {
>> };
>> 
>> /**
>> - * Bytestream IO Context.
>> + * Bytestream I/O @ref md_doc_2context "context"
>> + *
>> * New public fields can be added with minor version bumps.
>> * Removal, reordering and changes to existing public fields require
>> * a major version bump.
>> diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h
>> index fa5f59a2be..de29715462 100644
>> --- a/libavutil/audio_fifo.h
>> +++ b/libavutil/audio_fifo.h
>> @@ -39,7 +39,7 @@
>> */
>> 
>> /**
>> - * Context for an Audio FIFO Buffer.
>> + * @ref md_doc_2context "Context" for an Audio FIFO Buffer.
>> *
>> * - Operates at the sample level rather than the byte level.
>> * - Supports multiple channels with either planar or packed sample format.
>> diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
>> index bac30debae..60064cf08b 100644
>> --- a/libavutil/hwcontext.h
>> +++ b/libavutil/hwcontext.h
>> @@ -41,12 +41,13 @@ enum AVHWDeviceType {
>> };
>> 
>> /**
>> - * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
>> - * i.e. state that is not tied to a concrete processing configuration.
>> - * E.g., in an API that supports hardware-accelerated encoding and decoding,
>> - * this struct will (if possible) wrap the state that is common to both encoding
>> - * and decoding and from which specific instances of encoders or decoders can be
>> - * derived.
>> + * @ref md_doc_2context "Context" for (hardware/vendor-specific) "high-level" state.
>> + *
>> + * "High-level state" is anything that is not tied to a concrete processing
>> + * configuration. E.g., in an API that supports hardware-accelerated encoding
>> + * and decoding, this struct will (if possible) wrap the state that is common
>> + * to both encoding and decoding and from which specific instances of encoders
>> + * or decoders can be derived.
>> *
>> * This struct is reference-counted with the AVBuffer mechanism. The
>> * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
>> @@ -103,9 +104,11 @@ typedef struct AVHWDeviceContext {
>> } AVHWDeviceContext;
>> 
>> /**
>> - * This struct describes a set or pool of "hardware" frames (i.e. those with
>> - * data not located in normal system memory). All the frames in the pool are
>> - * assumed to be allocated in the same way and interchangeable.
>> + * @ref md_doc_2context "context" for a pool of "hardware" frames (those with
>> + * data not located in normal system memory)
>> + *
>> + * All the frames in the pool are assumed to be allocated in the same way and
>> + * interchangeable.
>> *
>> * This struct is reference-counted with the AVBuffer mechanism and tied to a
>> * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
>> diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
>> index cbad434fea..e259892688 100644
>> --- a/libavutil/hwcontext_cuda.h
>> +++ b/libavutil/hwcontext_cuda.h
>> @@ -37,7 +37,7 @@
>> typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
>> 
>> /**
>> - * This struct is allocated as AVHWDeviceContext.hwctx
>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>> */
>> typedef struct AVCUDADeviceContext {
>> CUcontext cuda_ctx;
>> diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
>> index 77d2d72f1b..101d1cb6f8 100644
>> --- a/libavutil/hwcontext_d3d11va.h
>> +++ b/libavutil/hwcontext_d3d11va.h
>> @@ -40,7 +40,7 @@
>> #include <stdint.h>
>> 
>> /**
>> - * This struct is allocated as AVHWDeviceContext.hwctx
>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>> */
>> typedef struct AVD3D11VADeviceContext {
>> /**
>> @@ -126,7 +126,7 @@ typedef struct AVD3D11FrameDescriptor {
>> } AVD3D11FrameDescriptor;
>> 
>> /**
>> - * This struct is allocated as AVHWFramesContext.hwctx
>> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
>> */
>> typedef struct AVD3D11VAFramesContext {
>> /**
>> diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
>> index ff06e6f2ef..c623914c2b 100644
>> --- a/libavutil/hwcontext_d3d12va.h
>> +++ b/libavutil/hwcontext_d3d12va.h
>> @@ -37,7 +37,7 @@
>> #include <d3d12video.h>
>> 
>> /**
>> - * @brief This struct is allocated as AVHWDeviceContext.hwctx
>> + * @brief This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>> *
>> */
>> typedef struct AVD3D12VADeviceContext {
>> @@ -78,7 +78,7 @@ typedef struct AVD3D12VADeviceContext {
>> } AVD3D12VADeviceContext;
>> 
>> /**
>> - * @brief This struct is used to sync d3d12 execution
>> + * @brief This @ref md_doc_2context "context" is used to sync d3d12 execution
>> *
>> */
>> typedef struct AVD3D12VASyncContext {
>> @@ -120,7 +120,7 @@ typedef struct AVD3D12VAFrame {
>> } AVD3D12VAFrame;
>> 
>> /**
>> - * @brief This struct is allocated as AVHWFramesContext.hwctx
>> + * @brief This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
>> *
>> */
>> typedef struct AVD3D12VAFramesContext {
>> diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
>> index 42709f215e..8329e69966 100644
>> --- a/libavutil/hwcontext_drm.h
>> +++ b/libavutil/hwcontext_drm.h
>> @@ -152,7 +152,7 @@ typedef struct AVDRMFrameDescriptor {
>> /**
>> * DRM device.
>> *
>> - * Allocated as AVHWDeviceContext.hwctx.
>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx.
>> */
>> typedef struct AVDRMDeviceContext {
>> /**
>> diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
>> index e1b79bc0de..c679c16af0 100644
>> --- a/libavutil/hwcontext_dxva2.h
>> +++ b/libavutil/hwcontext_dxva2.h
>> @@ -34,14 +34,14 @@
>> #include <dxva2api.h>
>> 
>> /**
>> - * This struct is allocated as AVHWDeviceContext.hwctx
>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>> */
>> typedef struct AVDXVA2DeviceContext {
>> IDirect3DDeviceManager9 *devmgr;
>> } AVDXVA2DeviceContext;
>> 
>> /**
>> - * This struct is allocated as AVHWFramesContext.hwctx
>> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
>> */
>> typedef struct AVDXVA2FramesContext {
>> /**
>> diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
>> index fc0263cabc..e81193247b 100644
>> --- a/libavutil/hwcontext_mediacodec.h
>> +++ b/libavutil/hwcontext_mediacodec.h
>> @@ -22,7 +22,7 @@
>> /**
>> * MediaCodec details.
>> *
>> - * Allocated as AVHWDeviceContext.hwctx
>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>> */
>> typedef struct AVMediaCodecDeviceContext {
>> /**
>> diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
>> index ef54486c95..7abd97db2b 100644
>> --- a/libavutil/hwcontext_opencl.h
>> +++ b/libavutil/hwcontext_opencl.h
>> @@ -58,7 +58,7 @@ typedef struct AVOpenCLFrameDescriptor {
>> /**
>> * OpenCL device details.
>> *
>> - * Allocated as AVHWDeviceContext.hwctx
>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>> */
>> typedef struct AVOpenCLDeviceContext {
>> /**
>> @@ -84,7 +84,7 @@ typedef struct AVOpenCLDeviceContext {
>> /**
>> * OpenCL-specific data associated with a frame pool.
>> *
>> - * Allocated as AVHWFramesContext.hwctx.
>> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
>> */
>> typedef struct AVOpenCLFramesContext {
>> /**
>> diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
>> index e2dba8ad83..b63ebddaef 100644
>> --- a/libavutil/hwcontext_qsv.h
>> +++ b/libavutil/hwcontext_qsv.h
>> @@ -30,7 +30,7 @@
>> */
>> 
>> /**
>> - * This struct is allocated as AVHWDeviceContext.hwctx
>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>> */
>> typedef struct AVQSVDeviceContext {
>> mfxSession session;
>> @@ -48,7 +48,7 @@ typedef struct AVQSVDeviceContext {
>> } AVQSVDeviceContext;
>> 
>> /**
>> - * This struct is allocated as AVHWFramesContext.hwctx
>> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
>> */
>> typedef struct AVQSVFramesContext {
>> mfxFrameSurface1 *surfaces;
>> diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
>> index 0b2e071cb3..4a897eb851 100644
>> --- a/libavutil/hwcontext_vaapi.h
>> +++ b/libavutil/hwcontext_vaapi.h
>> @@ -63,7 +63,7 @@ enum {
>> /**
>> * VAAPI connection details.
>> *
>> - * Allocated as AVHWDeviceContext.hwctx
>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>> */
>> typedef struct AVVAAPIDeviceContext {
>> /**
>> @@ -83,7 +83,7 @@ typedef struct AVVAAPIDeviceContext {
>> /**
>> * VAAPI-specific data associated with a frame pool.
>> *
>> - * Allocated as AVHWFramesContext.hwctx.
>> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
>> */
>> typedef struct AVVAAPIFramesContext {
>> /**
>> @@ -105,7 +105,7 @@ typedef struct AVVAAPIFramesContext {
>> /**
>> * VAAPI hardware pipeline configuration details.
>> *
>> - * Allocated with av_hwdevice_hwconfig_alloc().
>> + * This struct is allocated with av_hwdevice_hwconfig_alloc().
>> */
>> typedef struct AVVAAPIHWConfig {
>> /**
>> diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
>> index 1b7ea1e443..e305caa595 100644
>> --- a/libavutil/hwcontext_vdpau.h
>> +++ b/libavutil/hwcontext_vdpau.h
>> @@ -30,7 +30,7 @@
>> */
>> 
>> /**
>> - * This struct is allocated as AVHWDeviceContext.hwctx
>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>> */
>> typedef struct AVVDPAUDeviceContext {
>> VdpDevice          device;
>> diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
>> index cbbd2390c1..1869870032 100644
>> --- a/libavutil/hwcontext_vulkan.h
>> +++ b/libavutil/hwcontext_vulkan.h
>> @@ -39,7 +39,7 @@ typedef struct AVVkFrame AVVkFrame;
>> */
>> 
>> /**
>> - * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
>> + * Main Vulkan @ref md_doc_2context "context", allocated as AVHWDeviceContext.hwctx.
>> * All of these can be set before init to change what the context uses
>> */
>> typedef struct AVVulkanDeviceContext {
>> @@ -172,7 +172,7 @@ typedef enum AVVkFrameFlags {
>> } AVVkFrameFlags;
>> 
>> /**
>> - * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
>> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx, used to set pool-specific options
>> */
>> typedef struct AVVulkanFramesContext {
>> /**
>> diff --git a/libavutil/lfg.h b/libavutil/lfg.h
>> index e75a986f12..7f4ff5b62f 100644
>> --- a/libavutil/lfg.h
>> +++ b/libavutil/lfg.h
>> @@ -25,7 +25,7 @@
>> #include <stdint.h>
>> 
>> /**
>> - * Context structure for the Lagged Fibonacci PRNG.
>> + * @ref md_doc_2context "Context" structure for the Lagged Fibonacci PRNG.
>> * The exact layout, types and content of this struct may change and should
>> * not be accessed directly. Only its `sizeof()` is guaranteed to stay the same
>> * to allow easy instanciation.
>> 
> 
> Could you at least not put "context" in quotation marks?
> To be honest, I'm not sure this makes documentation any better.
> A context is an essential term we use in our codebase that's pretty
> universal. Explaining again and again at every mention is annoying.

+1. I don’t think “context" is specific to FFmpeg, it’s like common naming conventions.

> _______________________________________________
> 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".

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation
  2024-05-02 13:00                       ` Zhao Zhili
@ 2024-05-02 13:27                         ` Andrew Sayers
  2024-05-02 13:39                           ` Zhao Zhili
  0 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-05-02 13:27 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Thu, May 02, 2024 at 09:00:42PM +0800, Zhao Zhili wrote:
> 
> 
> > On May 2, 2024, at 19:01, Lynne <dev@lynne.ee> wrote:
> > 
> > Apr 29, 2024, 11:24 by ffmpeg-devel@pileofstuff.org:
> > 
> >> Some headings needed to be rewritten to accomodate the text,
> >> (hopefully) without changing the meaning.
> >> ---
> >> libavcodec/aac/aacdec.h            |  2 +-
> >> libavcodec/aacenc.h                |  2 +-
> >> libavcodec/ac3enc.h                |  2 +-
> >> libavcodec/amfenc.h                |  2 +-
> >> libavcodec/atrac.h                 |  2 +-
> >> libavcodec/avcodec.h               |  3 ++-
> >> libavcodec/bsf.h                   |  2 +-
> >> libavcodec/cbs.h                   |  2 +-
> >> libavcodec/d3d11va.h               |  3 +--
> >> libavcodec/h264dsp.h               |  2 +-
> >> libavcodec/h264pred.h              |  2 +-
> >> libavcodec/mediacodec.h            |  2 +-
> >> libavcodec/mpegaudiodec_template.c |  2 +-
> >> libavcodec/pthread_frame.c         |  4 ++--
> >> libavcodec/qsv.h                   |  6 ++++--
> >> libavcodec/sbr.h                   |  2 +-
> >> libavcodec/smacker.c               |  2 +-
> >> libavcodec/vdpau.h                 |  3 ++-
> >> libavcodec/videotoolbox.h          |  5 +++--
> >> libavfilter/avfilter.h             |  2 +-
> >> libavformat/avformat.h             |  3 ++-
> >> libavformat/avio.h                 |  3 ++-
> >> libavutil/audio_fifo.h             |  2 +-
> >> libavutil/hwcontext.h              | 21 ++++++++++++---------
> >> libavutil/hwcontext_cuda.h         |  2 +-
> >> libavutil/hwcontext_d3d11va.h      |  4 ++--
> >> libavutil/hwcontext_d3d12va.h      |  6 +++---
> >> libavutil/hwcontext_drm.h          |  2 +-
> >> libavutil/hwcontext_dxva2.h        |  4 ++--
> >> libavutil/hwcontext_mediacodec.h   |  2 +-
> >> libavutil/hwcontext_opencl.h       |  4 ++--
> >> libavutil/hwcontext_qsv.h          |  4 ++--
> >> libavutil/hwcontext_vaapi.h        |  6 +++---
> >> libavutil/hwcontext_vdpau.h        |  2 +-
> >> libavutil/hwcontext_vulkan.h       |  4 ++--
> >> libavutil/lfg.h                    |  2 +-
> >> 36 files changed, 66 insertions(+), 57 deletions(-)
> >> 
> >> diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
> >> index 4cf764e2e9..71d61813f4 100644
> >> --- a/libavcodec/aac/aacdec.h
> >> +++ b/libavcodec/aac/aacdec.h
> >> @@ -248,7 +248,7 @@ typedef struct AACDecDSP {
> >> } AACDecDSP;
> >> 
> >> /**
> >> - * main AAC decoding context
> >> + * main AAC decoding @ref md_doc_2context "context"
> >> */
> >> struct AACDecContext {
> >> const struct AVClass  *class;
> >> diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
> >> index d07960620e..1a645f4719 100644
> >> --- a/libavcodec/aacenc.h
> >> +++ b/libavcodec/aacenc.h
> >> @@ -207,7 +207,7 @@ typedef struct AACPCEInfo {
> >> } AACPCEInfo;
> >> 
> >> /**
> >> - * AAC encoder context
> >> + * AAC encoder @ref md_doc_2context "context"
> >> */
> >> typedef struct AACEncContext {
> >> AVClass *av_class;
> >> diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
> >> index 30812617cc..c725007077 100644
> >> --- a/libavcodec/ac3enc.h
> >> +++ b/libavcodec/ac3enc.h
> >> @@ -152,7 +152,7 @@ typedef struct AC3Block {
> >> } AC3Block;
> >> 
> >> /**
> >> - * AC-3 encoder private context.
> >> + * AC-3 encoder private @ref md_doc_2context "context"
> >> */
> >> typedef struct AC3EncodeContext {
> >> AVClass *av_class;                      ///< AVClass used for AVOption
> >> diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
> >> index 2dbd378ef8..f142ede63a 100644
> >> --- a/libavcodec/amfenc.h
> >> +++ b/libavcodec/amfenc.h
> >> @@ -43,7 +43,7 @@ typedef struct AmfTraceWriter {
> >> } AmfTraceWriter;
> >> 
> >> /**
> >> -* AMF encoder context
> >> +* AMF encoder @ref md_doc_2context "context"
> >> */
> >> 
> >> typedef struct AmfContext {
> >> diff --git a/libavcodec/atrac.h b/libavcodec/atrac.h
> >> index 05208bbee6..1527e376a9 100644
> >> --- a/libavcodec/atrac.h
> >> +++ b/libavcodec/atrac.h
> >> @@ -39,7 +39,7 @@ typedef struct AtracGainInfo {
> >> } AtracGainInfo;
> >> 
> >> /**
> >> - *  Gain compensation context structure.
> >> + *  Gain compensation @ref md_doc_2context "context"
> >> */
> >> typedef struct AtracGCContext {
> >> float   gain_tab1[16];  ///< gain compensation level table
> >> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> >> index 968009a192..9180fedca7 100644
> >> --- a/libavcodec/avcodec.h
> >> +++ b/libavcodec/avcodec.h
> >> @@ -430,7 +430,8 @@ typedef struct RcOverride{
> >> #define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0)
> >> 
> >> /**
> >> - * main external API structure.
> >> + * @ref md_doc_2context "Context" for an encode or decode session
> >> + *
> >> * New fields can be added to the end with minor version bumps.
> >> * Removal, reordering and changes to existing fields require a major
> >> * version bump.
> >> diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
> >> index a09c69f242..bf79afa7cc 100644
> >> --- a/libavcodec/bsf.h
> >> +++ b/libavcodec/bsf.h
> >> @@ -56,7 +56,7 @@
> >> */
> >> 
> >> /**
> >> - * The bitstream filter state.
> >> + * Bitstream filter @ref md_doc_2context "context"
> >> *
> >> * This struct must be allocated with av_bsf_alloc() and freed with
> >> * av_bsf_free().
> >> diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
> >> index d479b1ac2d..0ff64d2fef 100644
> >> --- a/libavcodec/cbs.h
> >> +++ b/libavcodec/cbs.h
> >> @@ -214,7 +214,7 @@ typedef void (*CBSTraceWriteCallback)(void *trace_context,
> >> int64_t value);
> >> 
> >> /**
> >> - * Context structure for coded bitstream operations.
> >> + * @ref md_doc_2context "Context" structure for coded bitstream operations.
> >> */
> >> typedef struct CodedBitstreamContext {
> >> /**
> >> diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
> >> index 27f40e5519..ec0c472ab9 100644
> >> --- a/libavcodec/d3d11va.h
> >> +++ b/libavcodec/d3d11va.h
> >> @@ -46,8 +46,7 @@
> >> */
> >> 
> >> /**
> >> - * This structure is used to provides the necessary configurations and data
> >> - * to the Direct3D11 FFmpeg HWAccel implementation.
> >> + * @ref md_doc_2context "Context" for the Direct3D11 FFmpeg HWAccel implementation
> >> *
> >> * The application must make it available as AVCodecContext.hwaccel_context.
> >> *
> >> diff --git a/libavcodec/h264dsp.h b/libavcodec/h264dsp.h
> >> index e0880c4d88..27256c5605 100644
> >> --- a/libavcodec/h264dsp.h
> >> +++ b/libavcodec/h264dsp.h
> >> @@ -37,7 +37,7 @@ typedef void (*h264_biweight_func)(uint8_t *dst, uint8_t *src,
> >> int weightd, int weights, int offset);
> >> 
> >> /**
> >> - * Context for storing H.264 DSP functions
> >> + * @ref md_doc_2context "Context" for storing H.264 DSP functions
> >> */
> >> typedef struct H264DSPContext {
> >> /* weighted MC */
> >> diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h
> >> index cb008548fc..2b076f8846 100644
> >> --- a/libavcodec/h264pred.h
> >> +++ b/libavcodec/h264pred.h
> >> @@ -89,7 +89,7 @@
> >> #define PART_NOT_AVAILABLE -2
> >> 
> >> /**
> >> - * Context for storing H.264 prediction functions
> >> + * @ref md_doc_2context "Context" for storing H.264 prediction functions
> >> */
> >> typedef struct H264PredContext {
> >> void(*pred4x4[9 + 3 + 3])(uint8_t *src, const uint8_t *topright,
> >> diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
> >> index 4e9b56a618..9967a7cfb3 100644
> >> --- a/libavcodec/mediacodec.h
> >> +++ b/libavcodec/mediacodec.h
> >> @@ -26,7 +26,7 @@
> >> #include "libavcodec/avcodec.h"
> >> 
> >> /**
> >> - * This structure holds a reference to a android/view/Surface object that will
> >> + * @ref md_doc_2context "Context" for the android/view/Surface object that will
> >> * be used as output by the decoder.
> >> *
> >> */
> >> diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c
> >> index c73b1e0054..15d63215d1 100644
> >> --- a/libavcodec/mpegaudiodec_template.c
> >> +++ b/libavcodec/mpegaudiodec_template.c
> >> @@ -1691,7 +1691,7 @@ static int decode_frame_adu(AVCodecContext *avctx, AVFrame *frame,
> >> #if CONFIG_MP3ON4_DECODER || CONFIG_MP3ON4FLOAT_DECODER
> >> 
> >> /**
> >> - * Context for MP3On4 decoder
> >> + * @ref md_doc_2context "Context" for MP3On4 decoder
> >> */
> >> typedef struct MP3On4DecodeContext {
> >> int frames;                     ///< number of mp3 frames per block (number of mp3 decoder instances)
> >> diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
> >> index 67f09c1f48..74f05eedcf 100644
> >> --- a/libavcodec/pthread_frame.c
> >> +++ b/libavcodec/pthread_frame.c
> >> @@ -71,7 +71,7 @@ typedef struct ThreadFrameProgress {
> >> } ThreadFrameProgress;
> >> 
> >> /**
> >> - * Context used by codec threads and stored in their AVCodecInternal thread_ctx.
> >> + * @ref md_doc_2context "Context" used by codec threads and stored in their AVCodecInternal thread_ctx.
> >> */
> >> typedef struct PerThreadContext {
> >> struct FrameThreadContext *parent;
> >> @@ -111,7 +111,7 @@ typedef struct PerThreadContext {
> >> } PerThreadContext;
> >> 
> >> /**
> >> - * Context stored in the client AVCodecInternal thread_ctx.
> >> + * @ref md_doc_2context "Context" stored in the client AVCodecInternal thread_ctx.
> >> */
> >> typedef struct FrameThreadContext {
> >> PerThreadContext *threads;     ///< The contexts for each thread.
> >> diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
> >> index c156b08d07..8b8160a4b1 100644
> >> --- a/libavcodec/qsv.h
> >> +++ b/libavcodec/qsv.h
> >> @@ -26,8 +26,10 @@
> >> #include "libavutil/buffer.h"
> >> 
> >> /**
> >> - * This struct is used for communicating QSV parameters between libavcodec and
> >> - * the caller. It is managed by the caller and must be assigned to
> >> + * @ref md_doc_2context "Context" for communicating QSV parameters between libavcodec
> >> + * and the caller.
> >> + *
> >> + * It is managed by the caller and must be assigned to
> >> * AVCodecContext.hwaccel_context.
> >> * - decoding: hwaccel_context must be set on return from the get_format()
> >> *             callback
> >> diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
> >> index fe3a39603a..98ad9024a9 100644
> >> --- a/libavcodec/sbr.h
> >> +++ b/libavcodec/sbr.h
> >> @@ -116,7 +116,7 @@ typedef struct SBRData {
> >> typedef struct SpectralBandReplication SpectralBandReplication;
> >> 
> >> /**
> >> - * aacsbr functions pointers
> >> + * aacsbr functions pointer @ref md_doc_2context "context"
> >> */
> >> typedef struct AACSBRContext {
> >> int (*sbr_lf_gen)(SpectralBandReplication *sbr,
> >> diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c
> >> index 8f198d6957..1ca39a74a0 100644
> >> --- a/libavcodec/smacker.c
> >> +++ b/libavcodec/smacker.c
> >> @@ -68,7 +68,7 @@ typedef struct HuffEntry {
> >> } HuffEntry;
> >> 
> >> /**
> >> - * Context used for code reconstructing
> >> + * @ref md_doc_2context "Context" used for code reconstructing
> >> */
> >> typedef struct HuffContext {
> >> int current;
> >> diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
> >> index 8021c25761..227b85727d 100644
> >> --- a/libavcodec/vdpau.h
> >> +++ b/libavcodec/vdpau.h
> >> @@ -64,8 +64,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
> >> const VdpBitstreamBuffer *);
> >> 
> >> /**
> >> - * This structure is used to share data between the libavcodec library and
> >> + * @ref md_doc_2context "Context" to share data between the libavcodec library and
> >> * the client video application.
> >> + *
> >> * This structure will be allocated and stored in AVCodecContext.hwaccel_context
> >> * by av_vdpau_bind_context(). Members can be set by the user once
> >> * during initialization or through each AVCodecContext.get_buffer()
> >> diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
> >> index d68d76e400..f15e79f325 100644
> >> --- a/libavcodec/videotoolbox.h
> >> +++ b/libavcodec/videotoolbox.h
> >> @@ -49,8 +49,9 @@
> >> #include "libavutil/attributes.h"
> >> 
> >> /**
> >> - * This struct holds all the information that needs to be passed
> >> - * between the caller and libavcodec for initializing Videotoolbox decoding.
> >> + * @ref md_doc_2context "Context" for information passed between the caller and libavcodec
> >> + * for initializing Videotoolbox decoding.
> >> + *
> >> * Its size is not a part of the public ABI, it must be allocated with
> >> * av_videotoolbox_alloc_context() and freed with av_free().
> >> */
> >> diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
> >> index a34e61f23c..54b5f9dc43 100644
> >> --- a/libavfilter/avfilter.h
> >> +++ b/libavfilter/avfilter.h
> >> @@ -403,7 +403,7 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
> >> */
> >> #define AVFILTER_THREAD_SLICE (1 << 0)
> >> 
> >> -/** An instance of a filter */
> >> +/** @ref md_doc_2context "Context" for a filter */
> >> struct AVFilterContext {
> >> const AVClass *av_class;        ///< needed for av_log() and filters common options
> >> 
> >> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> >> index 8afdcd9fd0..28243c06c4 100644
> >> --- a/libavformat/avformat.h
> >> +++ b/libavformat/avformat.h
> >> @@ -1241,7 +1241,8 @@ enum AVDurationEstimationMethod {
> >> };
> >> 
> >> /**
> >> - * Format I/O context.
> >> + * Format I/O @ref md_doc_2context "context"
> >> + *
> >> * New fields can be added to the end with minor version bumps.
> >> * Removal, reordering and changes to existing fields require a major
> >> * version bump.
> >> diff --git a/libavformat/avio.h b/libavformat/avio.h
> >> index ebf611187d..b525c93194 100644
> >> --- a/libavformat/avio.h
> >> +++ b/libavformat/avio.h
> >> @@ -146,7 +146,8 @@ enum AVIODataMarkerType {
> >> };
> >> 
> >> /**
> >> - * Bytestream IO Context.
> >> + * Bytestream I/O @ref md_doc_2context "context"
> >> + *
> >> * New public fields can be added with minor version bumps.
> >> * Removal, reordering and changes to existing public fields require
> >> * a major version bump.
> >> diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h
> >> index fa5f59a2be..de29715462 100644
> >> --- a/libavutil/audio_fifo.h
> >> +++ b/libavutil/audio_fifo.h
> >> @@ -39,7 +39,7 @@
> >> */
> >> 
> >> /**
> >> - * Context for an Audio FIFO Buffer.
> >> + * @ref md_doc_2context "Context" for an Audio FIFO Buffer.
> >> *
> >> * - Operates at the sample level rather than the byte level.
> >> * - Supports multiple channels with either planar or packed sample format.
> >> diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
> >> index bac30debae..60064cf08b 100644
> >> --- a/libavutil/hwcontext.h
> >> +++ b/libavutil/hwcontext.h
> >> @@ -41,12 +41,13 @@ enum AVHWDeviceType {
> >> };
> >> 
> >> /**
> >> - * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
> >> - * i.e. state that is not tied to a concrete processing configuration.
> >> - * E.g., in an API that supports hardware-accelerated encoding and decoding,
> >> - * this struct will (if possible) wrap the state that is common to both encoding
> >> - * and decoding and from which specific instances of encoders or decoders can be
> >> - * derived.
> >> + * @ref md_doc_2context "Context" for (hardware/vendor-specific) "high-level" state.
> >> + *
> >> + * "High-level state" is anything that is not tied to a concrete processing
> >> + * configuration. E.g., in an API that supports hardware-accelerated encoding
> >> + * and decoding, this struct will (if possible) wrap the state that is common
> >> + * to both encoding and decoding and from which specific instances of encoders
> >> + * or decoders can be derived.
> >> *
> >> * This struct is reference-counted with the AVBuffer mechanism. The
> >> * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
> >> @@ -103,9 +104,11 @@ typedef struct AVHWDeviceContext {
> >> } AVHWDeviceContext;
> >> 
> >> /**
> >> - * This struct describes a set or pool of "hardware" frames (i.e. those with
> >> - * data not located in normal system memory). All the frames in the pool are
> >> - * assumed to be allocated in the same way and interchangeable.
> >> + * @ref md_doc_2context "context" for a pool of "hardware" frames (those with
> >> + * data not located in normal system memory)
> >> + *
> >> + * All the frames in the pool are assumed to be allocated in the same way and
> >> + * interchangeable.
> >> *
> >> * This struct is reference-counted with the AVBuffer mechanism and tied to a
> >> * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
> >> diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
> >> index cbad434fea..e259892688 100644
> >> --- a/libavutil/hwcontext_cuda.h
> >> +++ b/libavutil/hwcontext_cuda.h
> >> @@ -37,7 +37,7 @@
> >> typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
> >> 
> >> /**
> >> - * This struct is allocated as AVHWDeviceContext.hwctx
> >> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >> */
> >> typedef struct AVCUDADeviceContext {
> >> CUcontext cuda_ctx;
> >> diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
> >> index 77d2d72f1b..101d1cb6f8 100644
> >> --- a/libavutil/hwcontext_d3d11va.h
> >> +++ b/libavutil/hwcontext_d3d11va.h
> >> @@ -40,7 +40,7 @@
> >> #include <stdint.h>
> >> 
> >> /**
> >> - * This struct is allocated as AVHWDeviceContext.hwctx
> >> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >> */
> >> typedef struct AVD3D11VADeviceContext {
> >> /**
> >> @@ -126,7 +126,7 @@ typedef struct AVD3D11FrameDescriptor {
> >> } AVD3D11FrameDescriptor;
> >> 
> >> /**
> >> - * This struct is allocated as AVHWFramesContext.hwctx
> >> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
> >> */
> >> typedef struct AVD3D11VAFramesContext {
> >> /**
> >> diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
> >> index ff06e6f2ef..c623914c2b 100644
> >> --- a/libavutil/hwcontext_d3d12va.h
> >> +++ b/libavutil/hwcontext_d3d12va.h
> >> @@ -37,7 +37,7 @@
> >> #include <d3d12video.h>
> >> 
> >> /**
> >> - * @brief This struct is allocated as AVHWDeviceContext.hwctx
> >> + * @brief This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >> *
> >> */
> >> typedef struct AVD3D12VADeviceContext {
> >> @@ -78,7 +78,7 @@ typedef struct AVD3D12VADeviceContext {
> >> } AVD3D12VADeviceContext;
> >> 
> >> /**
> >> - * @brief This struct is used to sync d3d12 execution
> >> + * @brief This @ref md_doc_2context "context" is used to sync d3d12 execution
> >> *
> >> */
> >> typedef struct AVD3D12VASyncContext {
> >> @@ -120,7 +120,7 @@ typedef struct AVD3D12VAFrame {
> >> } AVD3D12VAFrame;
> >> 
> >> /**
> >> - * @brief This struct is allocated as AVHWFramesContext.hwctx
> >> + * @brief This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
> >> *
> >> */
> >> typedef struct AVD3D12VAFramesContext {
> >> diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
> >> index 42709f215e..8329e69966 100644
> >> --- a/libavutil/hwcontext_drm.h
> >> +++ b/libavutil/hwcontext_drm.h
> >> @@ -152,7 +152,7 @@ typedef struct AVDRMFrameDescriptor {
> >> /**
> >> * DRM device.
> >> *
> >> - * Allocated as AVHWDeviceContext.hwctx.
> >> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx.
> >> */
> >> typedef struct AVDRMDeviceContext {
> >> /**
> >> diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
> >> index e1b79bc0de..c679c16af0 100644
> >> --- a/libavutil/hwcontext_dxva2.h
> >> +++ b/libavutil/hwcontext_dxva2.h
> >> @@ -34,14 +34,14 @@
> >> #include <dxva2api.h>
> >> 
> >> /**
> >> - * This struct is allocated as AVHWDeviceContext.hwctx
> >> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >> */
> >> typedef struct AVDXVA2DeviceContext {
> >> IDirect3DDeviceManager9 *devmgr;
> >> } AVDXVA2DeviceContext;
> >> 
> >> /**
> >> - * This struct is allocated as AVHWFramesContext.hwctx
> >> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
> >> */
> >> typedef struct AVDXVA2FramesContext {
> >> /**
> >> diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
> >> index fc0263cabc..e81193247b 100644
> >> --- a/libavutil/hwcontext_mediacodec.h
> >> +++ b/libavutil/hwcontext_mediacodec.h
> >> @@ -22,7 +22,7 @@
> >> /**
> >> * MediaCodec details.
> >> *
> >> - * Allocated as AVHWDeviceContext.hwctx
> >> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >> */
> >> typedef struct AVMediaCodecDeviceContext {
> >> /**
> >> diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
> >> index ef54486c95..7abd97db2b 100644
> >> --- a/libavutil/hwcontext_opencl.h
> >> +++ b/libavutil/hwcontext_opencl.h
> >> @@ -58,7 +58,7 @@ typedef struct AVOpenCLFrameDescriptor {
> >> /**
> >> * OpenCL device details.
> >> *
> >> - * Allocated as AVHWDeviceContext.hwctx
> >> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >> */
> >> typedef struct AVOpenCLDeviceContext {
> >> /**
> >> @@ -84,7 +84,7 @@ typedef struct AVOpenCLDeviceContext {
> >> /**
> >> * OpenCL-specific data associated with a frame pool.
> >> *
> >> - * Allocated as AVHWFramesContext.hwctx.
> >> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
> >> */
> >> typedef struct AVOpenCLFramesContext {
> >> /**
> >> diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
> >> index e2dba8ad83..b63ebddaef 100644
> >> --- a/libavutil/hwcontext_qsv.h
> >> +++ b/libavutil/hwcontext_qsv.h
> >> @@ -30,7 +30,7 @@
> >> */
> >> 
> >> /**
> >> - * This struct is allocated as AVHWDeviceContext.hwctx
> >> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >> */
> >> typedef struct AVQSVDeviceContext {
> >> mfxSession session;
> >> @@ -48,7 +48,7 @@ typedef struct AVQSVDeviceContext {
> >> } AVQSVDeviceContext;
> >> 
> >> /**
> >> - * This struct is allocated as AVHWFramesContext.hwctx
> >> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
> >> */
> >> typedef struct AVQSVFramesContext {
> >> mfxFrameSurface1 *surfaces;
> >> diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
> >> index 0b2e071cb3..4a897eb851 100644
> >> --- a/libavutil/hwcontext_vaapi.h
> >> +++ b/libavutil/hwcontext_vaapi.h
> >> @@ -63,7 +63,7 @@ enum {
> >> /**
> >> * VAAPI connection details.
> >> *
> >> - * Allocated as AVHWDeviceContext.hwctx
> >> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >> */
> >> typedef struct AVVAAPIDeviceContext {
> >> /**
> >> @@ -83,7 +83,7 @@ typedef struct AVVAAPIDeviceContext {
> >> /**
> >> * VAAPI-specific data associated with a frame pool.
> >> *
> >> - * Allocated as AVHWFramesContext.hwctx.
> >> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
> >> */
> >> typedef struct AVVAAPIFramesContext {
> >> /**
> >> @@ -105,7 +105,7 @@ typedef struct AVVAAPIFramesContext {
> >> /**
> >> * VAAPI hardware pipeline configuration details.
> >> *
> >> - * Allocated with av_hwdevice_hwconfig_alloc().
> >> + * This struct is allocated with av_hwdevice_hwconfig_alloc().
> >> */
> >> typedef struct AVVAAPIHWConfig {
> >> /**
> >> diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
> >> index 1b7ea1e443..e305caa595 100644
> >> --- a/libavutil/hwcontext_vdpau.h
> >> +++ b/libavutil/hwcontext_vdpau.h
> >> @@ -30,7 +30,7 @@
> >> */
> >> 
> >> /**
> >> - * This struct is allocated as AVHWDeviceContext.hwctx
> >> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
> >> */
> >> typedef struct AVVDPAUDeviceContext {
> >> VdpDevice          device;
> >> diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
> >> index cbbd2390c1..1869870032 100644
> >> --- a/libavutil/hwcontext_vulkan.h
> >> +++ b/libavutil/hwcontext_vulkan.h
> >> @@ -39,7 +39,7 @@ typedef struct AVVkFrame AVVkFrame;
> >> */
> >> 
> >> /**
> >> - * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
> >> + * Main Vulkan @ref md_doc_2context "context", allocated as AVHWDeviceContext.hwctx.
> >> * All of these can be set before init to change what the context uses
> >> */
> >> typedef struct AVVulkanDeviceContext {
> >> @@ -172,7 +172,7 @@ typedef enum AVVkFrameFlags {
> >> } AVVkFrameFlags;
> >> 
> >> /**
> >> - * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
> >> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx, used to set pool-specific options
> >> */
> >> typedef struct AVVulkanFramesContext {
> >> /**
> >> diff --git a/libavutil/lfg.h b/libavutil/lfg.h
> >> index e75a986f12..7f4ff5b62f 100644
> >> --- a/libavutil/lfg.h
> >> +++ b/libavutil/lfg.h
> >> @@ -25,7 +25,7 @@
> >> #include <stdint.h>
> >> 
> >> /**
> >> - * Context structure for the Lagged Fibonacci PRNG.
> >> + * @ref md_doc_2context "Context" structure for the Lagged Fibonacci PRNG.
> >> * The exact layout, types and content of this struct may change and should
> >> * not be accessed directly. Only its `sizeof()` is guaranteed to stay the same
> >> * to allow easy instanciation.
> >> 
> > 
> > Could you at least not put "context" in quotation marks?
> > To be honest, I'm not sure this makes documentation any better.
> > A context is an essential term we use in our codebase that's pretty
> > universal. Explaining again and again at every mention is annoying.
> 
> +1. I don’t think “context" is specific to FFmpeg, it’s like common naming conventions.

Ooh, I don't suppose you've got some examples?  I know some other C
projects use similar concepts, but a compatible use of the word
"context" would really help explain things to newbies.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation
  2024-05-02 13:27                         ` Andrew Sayers
@ 2024-05-02 13:39                           ` Zhao Zhili
  0 siblings, 0 replies; 84+ messages in thread
From: Zhao Zhili @ 2024-05-02 13:39 UTC (permalink / raw)
  To: FFmpeg development discussions and patches



> On May 2, 2024, at 21:27, Andrew Sayers <ffmpeg-devel@pileofstuff.org> wrote:
> 
> On Thu, May 02, 2024 at 09:00:42PM +0800, Zhao Zhili wrote:
>> 
>> 
>>> On May 2, 2024, at 19:01, Lynne <dev@lynne.ee> wrote:
>>> 
>>> Apr 29, 2024, 11:24 by ffmpeg-devel@pileofstuff.org:
>>> 
>>>> Some headings needed to be rewritten to accomodate the text,
>>>> (hopefully) without changing the meaning.
>>>> ---
>>>> libavcodec/aac/aacdec.h            |  2 +-
>>>> libavcodec/aacenc.h                |  2 +-
>>>> libavcodec/ac3enc.h                |  2 +-
>>>> libavcodec/amfenc.h                |  2 +-
>>>> libavcodec/atrac.h                 |  2 +-
>>>> libavcodec/avcodec.h               |  3 ++-
>>>> libavcodec/bsf.h                   |  2 +-
>>>> libavcodec/cbs.h                   |  2 +-
>>>> libavcodec/d3d11va.h               |  3 +--
>>>> libavcodec/h264dsp.h               |  2 +-
>>>> libavcodec/h264pred.h              |  2 +-
>>>> libavcodec/mediacodec.h            |  2 +-
>>>> libavcodec/mpegaudiodec_template.c |  2 +-
>>>> libavcodec/pthread_frame.c         |  4 ++--
>>>> libavcodec/qsv.h                   |  6 ++++--
>>>> libavcodec/sbr.h                   |  2 +-
>>>> libavcodec/smacker.c               |  2 +-
>>>> libavcodec/vdpau.h                 |  3 ++-
>>>> libavcodec/videotoolbox.h          |  5 +++--
>>>> libavfilter/avfilter.h             |  2 +-
>>>> libavformat/avformat.h             |  3 ++-
>>>> libavformat/avio.h                 |  3 ++-
>>>> libavutil/audio_fifo.h             |  2 +-
>>>> libavutil/hwcontext.h              | 21 ++++++++++++---------
>>>> libavutil/hwcontext_cuda.h         |  2 +-
>>>> libavutil/hwcontext_d3d11va.h      |  4 ++--
>>>> libavutil/hwcontext_d3d12va.h      |  6 +++---
>>>> libavutil/hwcontext_drm.h          |  2 +-
>>>> libavutil/hwcontext_dxva2.h        |  4 ++--
>>>> libavutil/hwcontext_mediacodec.h   |  2 +-
>>>> libavutil/hwcontext_opencl.h       |  4 ++--
>>>> libavutil/hwcontext_qsv.h          |  4 ++--
>>>> libavutil/hwcontext_vaapi.h        |  6 +++---
>>>> libavutil/hwcontext_vdpau.h        |  2 +-
>>>> libavutil/hwcontext_vulkan.h       |  4 ++--
>>>> libavutil/lfg.h                    |  2 +-
>>>> 36 files changed, 66 insertions(+), 57 deletions(-)
>>>> 
>>>> diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
>>>> index 4cf764e2e9..71d61813f4 100644
>>>> --- a/libavcodec/aac/aacdec.h
>>>> +++ b/libavcodec/aac/aacdec.h
>>>> @@ -248,7 +248,7 @@ typedef struct AACDecDSP {
>>>> } AACDecDSP;
>>>> 
>>>> /**
>>>> - * main AAC decoding context
>>>> + * main AAC decoding @ref md_doc_2context "context"
>>>> */
>>>> struct AACDecContext {
>>>> const struct AVClass  *class;
>>>> diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
>>>> index d07960620e..1a645f4719 100644
>>>> --- a/libavcodec/aacenc.h
>>>> +++ b/libavcodec/aacenc.h
>>>> @@ -207,7 +207,7 @@ typedef struct AACPCEInfo {
>>>> } AACPCEInfo;
>>>> 
>>>> /**
>>>> - * AAC encoder context
>>>> + * AAC encoder @ref md_doc_2context "context"
>>>> */
>>>> typedef struct AACEncContext {
>>>> AVClass *av_class;
>>>> diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
>>>> index 30812617cc..c725007077 100644
>>>> --- a/libavcodec/ac3enc.h
>>>> +++ b/libavcodec/ac3enc.h
>>>> @@ -152,7 +152,7 @@ typedef struct AC3Block {
>>>> } AC3Block;
>>>> 
>>>> /**
>>>> - * AC-3 encoder private context.
>>>> + * AC-3 encoder private @ref md_doc_2context "context"
>>>> */
>>>> typedef struct AC3EncodeContext {
>>>> AVClass *av_class;                      ///< AVClass used for AVOption
>>>> diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
>>>> index 2dbd378ef8..f142ede63a 100644
>>>> --- a/libavcodec/amfenc.h
>>>> +++ b/libavcodec/amfenc.h
>>>> @@ -43,7 +43,7 @@ typedef struct AmfTraceWriter {
>>>> } AmfTraceWriter;
>>>> 
>>>> /**
>>>> -* AMF encoder context
>>>> +* AMF encoder @ref md_doc_2context "context"
>>>> */
>>>> 
>>>> typedef struct AmfContext {
>>>> diff --git a/libavcodec/atrac.h b/libavcodec/atrac.h
>>>> index 05208bbee6..1527e376a9 100644
>>>> --- a/libavcodec/atrac.h
>>>> +++ b/libavcodec/atrac.h
>>>> @@ -39,7 +39,7 @@ typedef struct AtracGainInfo {
>>>> } AtracGainInfo;
>>>> 
>>>> /**
>>>> - *  Gain compensation context structure.
>>>> + *  Gain compensation @ref md_doc_2context "context"
>>>> */
>>>> typedef struct AtracGCContext {
>>>> float   gain_tab1[16];  ///< gain compensation level table
>>>> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
>>>> index 968009a192..9180fedca7 100644
>>>> --- a/libavcodec/avcodec.h
>>>> +++ b/libavcodec/avcodec.h
>>>> @@ -430,7 +430,8 @@ typedef struct RcOverride{
>>>> #define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0)
>>>> 
>>>> /**
>>>> - * main external API structure.
>>>> + * @ref md_doc_2context "Context" for an encode or decode session
>>>> + *
>>>> * New fields can be added to the end with minor version bumps.
>>>> * Removal, reordering and changes to existing fields require a major
>>>> * version bump.
>>>> diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
>>>> index a09c69f242..bf79afa7cc 100644
>>>> --- a/libavcodec/bsf.h
>>>> +++ b/libavcodec/bsf.h
>>>> @@ -56,7 +56,7 @@
>>>> */
>>>> 
>>>> /**
>>>> - * The bitstream filter state.
>>>> + * Bitstream filter @ref md_doc_2context "context"
>>>> *
>>>> * This struct must be allocated with av_bsf_alloc() and freed with
>>>> * av_bsf_free().
>>>> diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
>>>> index d479b1ac2d..0ff64d2fef 100644
>>>> --- a/libavcodec/cbs.h
>>>> +++ b/libavcodec/cbs.h
>>>> @@ -214,7 +214,7 @@ typedef void (*CBSTraceWriteCallback)(void *trace_context,
>>>> int64_t value);
>>>> 
>>>> /**
>>>> - * Context structure for coded bitstream operations.
>>>> + * @ref md_doc_2context "Context" structure for coded bitstream operations.
>>>> */
>>>> typedef struct CodedBitstreamContext {
>>>> /**
>>>> diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
>>>> index 27f40e5519..ec0c472ab9 100644
>>>> --- a/libavcodec/d3d11va.h
>>>> +++ b/libavcodec/d3d11va.h
>>>> @@ -46,8 +46,7 @@
>>>> */
>>>> 
>>>> /**
>>>> - * This structure is used to provides the necessary configurations and data
>>>> - * to the Direct3D11 FFmpeg HWAccel implementation.
>>>> + * @ref md_doc_2context "Context" for the Direct3D11 FFmpeg HWAccel implementation
>>>> *
>>>> * The application must make it available as AVCodecContext.hwaccel_context.
>>>> *
>>>> diff --git a/libavcodec/h264dsp.h b/libavcodec/h264dsp.h
>>>> index e0880c4d88..27256c5605 100644
>>>> --- a/libavcodec/h264dsp.h
>>>> +++ b/libavcodec/h264dsp.h
>>>> @@ -37,7 +37,7 @@ typedef void (*h264_biweight_func)(uint8_t *dst, uint8_t *src,
>>>> int weightd, int weights, int offset);
>>>> 
>>>> /**
>>>> - * Context for storing H.264 DSP functions
>>>> + * @ref md_doc_2context "Context" for storing H.264 DSP functions
>>>> */
>>>> typedef struct H264DSPContext {
>>>> /* weighted MC */
>>>> diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h
>>>> index cb008548fc..2b076f8846 100644
>>>> --- a/libavcodec/h264pred.h
>>>> +++ b/libavcodec/h264pred.h
>>>> @@ -89,7 +89,7 @@
>>>> #define PART_NOT_AVAILABLE -2
>>>> 
>>>> /**
>>>> - * Context for storing H.264 prediction functions
>>>> + * @ref md_doc_2context "Context" for storing H.264 prediction functions
>>>> */
>>>> typedef struct H264PredContext {
>>>> void(*pred4x4[9 + 3 + 3])(uint8_t *src, const uint8_t *topright,
>>>> diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
>>>> index 4e9b56a618..9967a7cfb3 100644
>>>> --- a/libavcodec/mediacodec.h
>>>> +++ b/libavcodec/mediacodec.h
>>>> @@ -26,7 +26,7 @@
>>>> #include "libavcodec/avcodec.h"
>>>> 
>>>> /**
>>>> - * This structure holds a reference to a android/view/Surface object that will
>>>> + * @ref md_doc_2context "Context" for the android/view/Surface object that will
>>>> * be used as output by the decoder.
>>>> *
>>>> */
>>>> diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c
>>>> index c73b1e0054..15d63215d1 100644
>>>> --- a/libavcodec/mpegaudiodec_template.c
>>>> +++ b/libavcodec/mpegaudiodec_template.c
>>>> @@ -1691,7 +1691,7 @@ static int decode_frame_adu(AVCodecContext *avctx, AVFrame *frame,
>>>> #if CONFIG_MP3ON4_DECODER || CONFIG_MP3ON4FLOAT_DECODER
>>>> 
>>>> /**
>>>> - * Context for MP3On4 decoder
>>>> + * @ref md_doc_2context "Context" for MP3On4 decoder
>>>> */
>>>> typedef struct MP3On4DecodeContext {
>>>> int frames;                     ///< number of mp3 frames per block (number of mp3 decoder instances)
>>>> diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
>>>> index 67f09c1f48..74f05eedcf 100644
>>>> --- a/libavcodec/pthread_frame.c
>>>> +++ b/libavcodec/pthread_frame.c
>>>> @@ -71,7 +71,7 @@ typedef struct ThreadFrameProgress {
>>>> } ThreadFrameProgress;
>>>> 
>>>> /**
>>>> - * Context used by codec threads and stored in their AVCodecInternal thread_ctx.
>>>> + * @ref md_doc_2context "Context" used by codec threads and stored in their AVCodecInternal thread_ctx.
>>>> */
>>>> typedef struct PerThreadContext {
>>>> struct FrameThreadContext *parent;
>>>> @@ -111,7 +111,7 @@ typedef struct PerThreadContext {
>>>> } PerThreadContext;
>>>> 
>>>> /**
>>>> - * Context stored in the client AVCodecInternal thread_ctx.
>>>> + * @ref md_doc_2context "Context" stored in the client AVCodecInternal thread_ctx.
>>>> */
>>>> typedef struct FrameThreadContext {
>>>> PerThreadContext *threads;     ///< The contexts for each thread.
>>>> diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
>>>> index c156b08d07..8b8160a4b1 100644
>>>> --- a/libavcodec/qsv.h
>>>> +++ b/libavcodec/qsv.h
>>>> @@ -26,8 +26,10 @@
>>>> #include "libavutil/buffer.h"
>>>> 
>>>> /**
>>>> - * This struct is used for communicating QSV parameters between libavcodec and
>>>> - * the caller. It is managed by the caller and must be assigned to
>>>> + * @ref md_doc_2context "Context" for communicating QSV parameters between libavcodec
>>>> + * and the caller.
>>>> + *
>>>> + * It is managed by the caller and must be assigned to
>>>> * AVCodecContext.hwaccel_context.
>>>> * - decoding: hwaccel_context must be set on return from the get_format()
>>>> *             callback
>>>> diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
>>>> index fe3a39603a..98ad9024a9 100644
>>>> --- a/libavcodec/sbr.h
>>>> +++ b/libavcodec/sbr.h
>>>> @@ -116,7 +116,7 @@ typedef struct SBRData {
>>>> typedef struct SpectralBandReplication SpectralBandReplication;
>>>> 
>>>> /**
>>>> - * aacsbr functions pointers
>>>> + * aacsbr functions pointer @ref md_doc_2context "context"
>>>> */
>>>> typedef struct AACSBRContext {
>>>> int (*sbr_lf_gen)(SpectralBandReplication *sbr,
>>>> diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c
>>>> index 8f198d6957..1ca39a74a0 100644
>>>> --- a/libavcodec/smacker.c
>>>> +++ b/libavcodec/smacker.c
>>>> @@ -68,7 +68,7 @@ typedef struct HuffEntry {
>>>> } HuffEntry;
>>>> 
>>>> /**
>>>> - * Context used for code reconstructing
>>>> + * @ref md_doc_2context "Context" used for code reconstructing
>>>> */
>>>> typedef struct HuffContext {
>>>> int current;
>>>> diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
>>>> index 8021c25761..227b85727d 100644
>>>> --- a/libavcodec/vdpau.h
>>>> +++ b/libavcodec/vdpau.h
>>>> @@ -64,8 +64,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
>>>> const VdpBitstreamBuffer *);
>>>> 
>>>> /**
>>>> - * This structure is used to share data between the libavcodec library and
>>>> + * @ref md_doc_2context "Context" to share data between the libavcodec library and
>>>> * the client video application.
>>>> + *
>>>> * This structure will be allocated and stored in AVCodecContext.hwaccel_context
>>>> * by av_vdpau_bind_context(). Members can be set by the user once
>>>> * during initialization or through each AVCodecContext.get_buffer()
>>>> diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
>>>> index d68d76e400..f15e79f325 100644
>>>> --- a/libavcodec/videotoolbox.h
>>>> +++ b/libavcodec/videotoolbox.h
>>>> @@ -49,8 +49,9 @@
>>>> #include "libavutil/attributes.h"
>>>> 
>>>> /**
>>>> - * This struct holds all the information that needs to be passed
>>>> - * between the caller and libavcodec for initializing Videotoolbox decoding.
>>>> + * @ref md_doc_2context "Context" for information passed between the caller and libavcodec
>>>> + * for initializing Videotoolbox decoding.
>>>> + *
>>>> * Its size is not a part of the public ABI, it must be allocated with
>>>> * av_videotoolbox_alloc_context() and freed with av_free().
>>>> */
>>>> diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
>>>> index a34e61f23c..54b5f9dc43 100644
>>>> --- a/libavfilter/avfilter.h
>>>> +++ b/libavfilter/avfilter.h
>>>> @@ -403,7 +403,7 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
>>>> */
>>>> #define AVFILTER_THREAD_SLICE (1 << 0)
>>>> 
>>>> -/** An instance of a filter */
>>>> +/** @ref md_doc_2context "Context" for a filter */
>>>> struct AVFilterContext {
>>>> const AVClass *av_class;        ///< needed for av_log() and filters common options
>>>> 
>>>> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
>>>> index 8afdcd9fd0..28243c06c4 100644
>>>> --- a/libavformat/avformat.h
>>>> +++ b/libavformat/avformat.h
>>>> @@ -1241,7 +1241,8 @@ enum AVDurationEstimationMethod {
>>>> };
>>>> 
>>>> /**
>>>> - * Format I/O context.
>>>> + * Format I/O @ref md_doc_2context "context"
>>>> + *
>>>> * New fields can be added to the end with minor version bumps.
>>>> * Removal, reordering and changes to existing fields require a major
>>>> * version bump.
>>>> diff --git a/libavformat/avio.h b/libavformat/avio.h
>>>> index ebf611187d..b525c93194 100644
>>>> --- a/libavformat/avio.h
>>>> +++ b/libavformat/avio.h
>>>> @@ -146,7 +146,8 @@ enum AVIODataMarkerType {
>>>> };
>>>> 
>>>> /**
>>>> - * Bytestream IO Context.
>>>> + * Bytestream I/O @ref md_doc_2context "context"
>>>> + *
>>>> * New public fields can be added with minor version bumps.
>>>> * Removal, reordering and changes to existing public fields require
>>>> * a major version bump.
>>>> diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h
>>>> index fa5f59a2be..de29715462 100644
>>>> --- a/libavutil/audio_fifo.h
>>>> +++ b/libavutil/audio_fifo.h
>>>> @@ -39,7 +39,7 @@
>>>> */
>>>> 
>>>> /**
>>>> - * Context for an Audio FIFO Buffer.
>>>> + * @ref md_doc_2context "Context" for an Audio FIFO Buffer.
>>>> *
>>>> * - Operates at the sample level rather than the byte level.
>>>> * - Supports multiple channels with either planar or packed sample format.
>>>> diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
>>>> index bac30debae..60064cf08b 100644
>>>> --- a/libavutil/hwcontext.h
>>>> +++ b/libavutil/hwcontext.h
>>>> @@ -41,12 +41,13 @@ enum AVHWDeviceType {
>>>> };
>>>> 
>>>> /**
>>>> - * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
>>>> - * i.e. state that is not tied to a concrete processing configuration.
>>>> - * E.g., in an API that supports hardware-accelerated encoding and decoding,
>>>> - * this struct will (if possible) wrap the state that is common to both encoding
>>>> - * and decoding and from which specific instances of encoders or decoders can be
>>>> - * derived.
>>>> + * @ref md_doc_2context "Context" for (hardware/vendor-specific) "high-level" state.
>>>> + *
>>>> + * "High-level state" is anything that is not tied to a concrete processing
>>>> + * configuration. E.g., in an API that supports hardware-accelerated encoding
>>>> + * and decoding, this struct will (if possible) wrap the state that is common
>>>> + * to both encoding and decoding and from which specific instances of encoders
>>>> + * or decoders can be derived.
>>>> *
>>>> * This struct is reference-counted with the AVBuffer mechanism. The
>>>> * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
>>>> @@ -103,9 +104,11 @@ typedef struct AVHWDeviceContext {
>>>> } AVHWDeviceContext;
>>>> 
>>>> /**
>>>> - * This struct describes a set or pool of "hardware" frames (i.e. those with
>>>> - * data not located in normal system memory). All the frames in the pool are
>>>> - * assumed to be allocated in the same way and interchangeable.
>>>> + * @ref md_doc_2context "context" for a pool of "hardware" frames (those with
>>>> + * data not located in normal system memory)
>>>> + *
>>>> + * All the frames in the pool are assumed to be allocated in the same way and
>>>> + * interchangeable.
>>>> *
>>>> * This struct is reference-counted with the AVBuffer mechanism and tied to a
>>>> * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
>>>> diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
>>>> index cbad434fea..e259892688 100644
>>>> --- a/libavutil/hwcontext_cuda.h
>>>> +++ b/libavutil/hwcontext_cuda.h
>>>> @@ -37,7 +37,7 @@
>>>> typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
>>>> 
>>>> /**
>>>> - * This struct is allocated as AVHWDeviceContext.hwctx
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>>>> */
>>>> typedef struct AVCUDADeviceContext {
>>>> CUcontext cuda_ctx;
>>>> diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
>>>> index 77d2d72f1b..101d1cb6f8 100644
>>>> --- a/libavutil/hwcontext_d3d11va.h
>>>> +++ b/libavutil/hwcontext_d3d11va.h
>>>> @@ -40,7 +40,7 @@
>>>> #include <stdint.h>
>>>> 
>>>> /**
>>>> - * This struct is allocated as AVHWDeviceContext.hwctx
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>>>> */
>>>> typedef struct AVD3D11VADeviceContext {
>>>> /**
>>>> @@ -126,7 +126,7 @@ typedef struct AVD3D11FrameDescriptor {
>>>> } AVD3D11FrameDescriptor;
>>>> 
>>>> /**
>>>> - * This struct is allocated as AVHWFramesContext.hwctx
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
>>>> */
>>>> typedef struct AVD3D11VAFramesContext {
>>>> /**
>>>> diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
>>>> index ff06e6f2ef..c623914c2b 100644
>>>> --- a/libavutil/hwcontext_d3d12va.h
>>>> +++ b/libavutil/hwcontext_d3d12va.h
>>>> @@ -37,7 +37,7 @@
>>>> #include <d3d12video.h>
>>>> 
>>>> /**
>>>> - * @brief This struct is allocated as AVHWDeviceContext.hwctx
>>>> + * @brief This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>>>> *
>>>> */
>>>> typedef struct AVD3D12VADeviceContext {
>>>> @@ -78,7 +78,7 @@ typedef struct AVD3D12VADeviceContext {
>>>> } AVD3D12VADeviceContext;
>>>> 
>>>> /**
>>>> - * @brief This struct is used to sync d3d12 execution
>>>> + * @brief This @ref md_doc_2context "context" is used to sync d3d12 execution
>>>> *
>>>> */
>>>> typedef struct AVD3D12VASyncContext {
>>>> @@ -120,7 +120,7 @@ typedef struct AVD3D12VAFrame {
>>>> } AVD3D12VAFrame;
>>>> 
>>>> /**
>>>> - * @brief This struct is allocated as AVHWFramesContext.hwctx
>>>> + * @brief This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
>>>> *
>>>> */
>>>> typedef struct AVD3D12VAFramesContext {
>>>> diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
>>>> index 42709f215e..8329e69966 100644
>>>> --- a/libavutil/hwcontext_drm.h
>>>> +++ b/libavutil/hwcontext_drm.h
>>>> @@ -152,7 +152,7 @@ typedef struct AVDRMFrameDescriptor {
>>>> /**
>>>> * DRM device.
>>>> *
>>>> - * Allocated as AVHWDeviceContext.hwctx.
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx.
>>>> */
>>>> typedef struct AVDRMDeviceContext {
>>>> /**
>>>> diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
>>>> index e1b79bc0de..c679c16af0 100644
>>>> --- a/libavutil/hwcontext_dxva2.h
>>>> +++ b/libavutil/hwcontext_dxva2.h
>>>> @@ -34,14 +34,14 @@
>>>> #include <dxva2api.h>
>>>> 
>>>> /**
>>>> - * This struct is allocated as AVHWDeviceContext.hwctx
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>>>> */
>>>> typedef struct AVDXVA2DeviceContext {
>>>> IDirect3DDeviceManager9 *devmgr;
>>>> } AVDXVA2DeviceContext;
>>>> 
>>>> /**
>>>> - * This struct is allocated as AVHWFramesContext.hwctx
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
>>>> */
>>>> typedef struct AVDXVA2FramesContext {
>>>> /**
>>>> diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
>>>> index fc0263cabc..e81193247b 100644
>>>> --- a/libavutil/hwcontext_mediacodec.h
>>>> +++ b/libavutil/hwcontext_mediacodec.h
>>>> @@ -22,7 +22,7 @@
>>>> /**
>>>> * MediaCodec details.
>>>> *
>>>> - * Allocated as AVHWDeviceContext.hwctx
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>>>> */
>>>> typedef struct AVMediaCodecDeviceContext {
>>>> /**
>>>> diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
>>>> index ef54486c95..7abd97db2b 100644
>>>> --- a/libavutil/hwcontext_opencl.h
>>>> +++ b/libavutil/hwcontext_opencl.h
>>>> @@ -58,7 +58,7 @@ typedef struct AVOpenCLFrameDescriptor {
>>>> /**
>>>> * OpenCL device details.
>>>> *
>>>> - * Allocated as AVHWDeviceContext.hwctx
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>>>> */
>>>> typedef struct AVOpenCLDeviceContext {
>>>> /**
>>>> @@ -84,7 +84,7 @@ typedef struct AVOpenCLDeviceContext {
>>>> /**
>>>> * OpenCL-specific data associated with a frame pool.
>>>> *
>>>> - * Allocated as AVHWFramesContext.hwctx.
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
>>>> */
>>>> typedef struct AVOpenCLFramesContext {
>>>> /**
>>>> diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
>>>> index e2dba8ad83..b63ebddaef 100644
>>>> --- a/libavutil/hwcontext_qsv.h
>>>> +++ b/libavutil/hwcontext_qsv.h
>>>> @@ -30,7 +30,7 @@
>>>> */
>>>> 
>>>> /**
>>>> - * This struct is allocated as AVHWDeviceContext.hwctx
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>>>> */
>>>> typedef struct AVQSVDeviceContext {
>>>> mfxSession session;
>>>> @@ -48,7 +48,7 @@ typedef struct AVQSVDeviceContext {
>>>> } AVQSVDeviceContext;
>>>> 
>>>> /**
>>>> - * This struct is allocated as AVHWFramesContext.hwctx
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
>>>> */
>>>> typedef struct AVQSVFramesContext {
>>>> mfxFrameSurface1 *surfaces;
>>>> diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
>>>> index 0b2e071cb3..4a897eb851 100644
>>>> --- a/libavutil/hwcontext_vaapi.h
>>>> +++ b/libavutil/hwcontext_vaapi.h
>>>> @@ -63,7 +63,7 @@ enum {
>>>> /**
>>>> * VAAPI connection details.
>>>> *
>>>> - * Allocated as AVHWDeviceContext.hwctx
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>>>> */
>>>> typedef struct AVVAAPIDeviceContext {
>>>> /**
>>>> @@ -83,7 +83,7 @@ typedef struct AVVAAPIDeviceContext {
>>>> /**
>>>> * VAAPI-specific data associated with a frame pool.
>>>> *
>>>> - * Allocated as AVHWFramesContext.hwctx.
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
>>>> */
>>>> typedef struct AVVAAPIFramesContext {
>>>> /**
>>>> @@ -105,7 +105,7 @@ typedef struct AVVAAPIFramesContext {
>>>> /**
>>>> * VAAPI hardware pipeline configuration details.
>>>> *
>>>> - * Allocated with av_hwdevice_hwconfig_alloc().
>>>> + * This struct is allocated with av_hwdevice_hwconfig_alloc().
>>>> */
>>>> typedef struct AVVAAPIHWConfig {
>>>> /**
>>>> diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
>>>> index 1b7ea1e443..e305caa595 100644
>>>> --- a/libavutil/hwcontext_vdpau.h
>>>> +++ b/libavutil/hwcontext_vdpau.h
>>>> @@ -30,7 +30,7 @@
>>>> */
>>>> 
>>>> /**
>>>> - * This struct is allocated as AVHWDeviceContext.hwctx
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
>>>> */
>>>> typedef struct AVVDPAUDeviceContext {
>>>> VdpDevice          device;
>>>> diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
>>>> index cbbd2390c1..1869870032 100644
>>>> --- a/libavutil/hwcontext_vulkan.h
>>>> +++ b/libavutil/hwcontext_vulkan.h
>>>> @@ -39,7 +39,7 @@ typedef struct AVVkFrame AVVkFrame;
>>>> */
>>>> 
>>>> /**
>>>> - * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
>>>> + * Main Vulkan @ref md_doc_2context "context", allocated as AVHWDeviceContext.hwctx.
>>>> * All of these can be set before init to change what the context uses
>>>> */
>>>> typedef struct AVVulkanDeviceContext {
>>>> @@ -172,7 +172,7 @@ typedef enum AVVkFrameFlags {
>>>> } AVVkFrameFlags;
>>>> 
>>>> /**
>>>> - * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
>>>> + * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx, used to set pool-specific options
>>>> */
>>>> typedef struct AVVulkanFramesContext {
>>>> /**
>>>> diff --git a/libavutil/lfg.h b/libavutil/lfg.h
>>>> index e75a986f12..7f4ff5b62f 100644
>>>> --- a/libavutil/lfg.h
>>>> +++ b/libavutil/lfg.h
>>>> @@ -25,7 +25,7 @@
>>>> #include <stdint.h>
>>>> 
>>>> /**
>>>> - * Context structure for the Lagged Fibonacci PRNG.
>>>> + * @ref md_doc_2context "Context" structure for the Lagged Fibonacci PRNG.
>>>> * The exact layout, types and content of this struct may change and should
>>>> * not be accessed directly. Only its `sizeof()` is guaranteed to stay the same
>>>> * to allow easy instanciation.
>>>> 
>>> 
>>> Could you at least not put "context" in quotation marks?
>>> To be honest, I'm not sure this makes documentation any better.
>>> A context is an essential term we use in our codebase that's pretty
>>> universal. Explaining again and again at every mention is annoying.
>> 
>> +1. I don’t think “context" is specific to FFmpeg, it’s like common naming conventions.
> 
> Ooh, I don't suppose you've got some examples?

Curl, libxml2, libevent.

>  I know some other C
> projects use similar concepts, but a compatible use of the word
> "context" would really help explain things to newbies.
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org <mailto:ffmpeg-devel@ffmpeg.org>
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org <mailto:ffmpeg-devel-request@ffmpeg.org> with subject "unsubscribe".

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means
  2024-04-29  9:10                 ` Andrew Sayers
  2024-05-02 10:03                   ` Andrew Sayers
@ 2024-05-05  7:29                   ` Stefano Sabatini
  2024-05-05 21:04                     ` Andrew Sayers
  1 sibling, 1 reply; 84+ messages in thread
From: Stefano Sabatini @ 2024-05-05  7:29 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On date Monday 2024-04-29 10:10:35 +0100, Andrew Sayers wrote:
> On Mon, Apr 22, 2024 at 07:05:12PM +0200, Stefano Sabatini wrote:
[...]
> > I don't have a strong opinion, but I'd probably focus on providing a
> > typical example of a common API (check doc/examples). Also I see here
> > there is a strong focus on OOP, this might be counter-productive in
> > case the reader is not familiar with OOP terminology.
> > 
> > OTOH the content might be useful for readers coming from an OOP
> > background and terminology. I wonder if this content might be isolated
> > in a dedicated section, so that non-OOP readers can simply skip it.
> > 
> > But this is not a strong objection, and can be possibly reworked in a
> > later step.
> > 
> 
> This is really a document for FFmpeg newbies, so we need to assume as
> little prior knowledge as possible.  After a few days to think it
> over, I think we should avoid assuming...
> 
> Knowledge of object-oriented programming.  For example, this should be
> useful to a research mathematician with a project that involves codec
> algorithms.  So the next draft should feel less like "FFmpeg for OOP
> devs" and more like "FFmpeg for newbies (with some optional OOP
> background reading)".
> 
> Knowing that programming doesn't *have* to be object-oriented.
> OOP has become so ubiquitous nowadays, there are plenty of programmers
> who will insist everything is OOP if you just speak loudly and slowly.
> This is a harder problem in some ways, because someone who doesn't
> understand can always re-read until they do, while someone who jumps
> to the wrong conclusion will just keep reading and try to make things
> fit their assumption (e.g. my earlier messages in this thread!).
> So the "how it differs from OOP" stuff needs to stay fairly prominent.
> 

> Knowing anything about FFmpeg (or multimedia in general).  I like the
> idea of tweaking `doc/examples` to better introduce FFmpeg
> fundamentals, but explaining "context" is a steep enough learning
> curve on its own - introducing concepts like "stream" and "codec" at
> the same time seems like too much.

But even if you show the API that does not mean you need to explain
it entirely, you only need to highligth the structural relationships:

    // create an instance context, whatever it is
    c = avcodec_alloc_context3(codec);
    if (!c) {
        fprintf(stderr, "Could not allocate video codec context\n");
        exit(1);
    }

    // set context parametres directly
    c->bit_rate = 400000;
    /* resolution must be a multiple of two */
    c->width = 352;
    c->height = 288;
    /* frames per second */
    c->time_base = (AVRational){1, 25};
    c->framerate = (AVRational){25, 1};

    // use av_opt API to set the options?
    ...

    // open the codec context provided a codec
    ret = avcodec_open2(c, codec, NULL);
    if (ret < 0) {
        fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
        exit(1);
    }

You might even replace avcodec_ with fooblargh_ and get the same
effect, with the addition that with avcodec_ you are already
familiarizing the user with the concrete API rather than with an
hypotetical one.

[...]

> I've also gone through the code looking for edge cases we haven't covered.
> Here are some questions trying to prompt an "oh yeah I forgot to mention
> that"-type answer.  Anything where the answer is more like "that should
> probably be rewritten to be clearer", let me know and I'll avoid confusing
> newbies with it.
> 

> av_ambient_viewing_environment_create_side_data() takes an AVFrame as its
> first argument, and returns a new AVAmbientViewingEnvironment.  What is the
> context object for that function - AVFrame or AVAmbientViewingEnvironment?

But this should be clear from the doxy:

/**
 * Allocate and add an AVAmbientViewingEnvironment structure to an existing
 * AVFrame as side data.
 *
 * @return the newly allocated struct, or NULL on failure
 */
AVAmbientViewingEnvironment *av_ambient_viewing_environment_create_side_data(AVFrame *frame);

Also, you are assuming that all the function should have a
context. That's not the case, as you don't always need to keep track
of a "context" when performing operations.

> 
> av_register_bitstream_filter() (deprecated 4.0, removed 5.0) took an
> `AVBitStreamFilter *` as its first argument, but I don't think you'd say
> the argument provided "context" for the function.  So would I be right in
> saying `AVBitStreamFilter *` is not a context, despite looking like one?

This was finally dropped so this is even missing. But again, it seems
you are assuming that all the functions should take a context, which
is not the case. In that case you had:
av_register_bistream_filter(filter)

which was registering the filter in the program global state.
 
> av_buffersink_*() all take a `const AVFilterContext *` argument.
> What does the difference between av_buffersink prefix and AVFilter type mean?

None, probabily it should have been named avfilter_buffersink since
this is a libavfilter API, seel below.

> av_channel_description_bprint() takes a `struct AVBPrint *` as its first
> argument, then `enum AVChannel`.  Is the context AVBPrint, AVChannel,
> or both?  Does it make sense for a function to have two contexts?

Again, this should be clear from the doxy:
/**
 * Get a human readable string describing a given channel.
 *
 * @param buf pre-allocated buffer where to put the generated string
 * @param buf_size size in bytes of the buffer.
 * @param channel the AVChannel whose description to get
 * @return amount of bytes needed to hold the output string, or a negative AVERROR
 *         on failure. If the returned value is bigger than buf_size, then the
 *         string was truncated.
 */
int av_channel_description(char *buf, size_t buf_size, enum AVChannel channel);

/**
 * bprint variant of av_channel_description().
 *
 * @note the string will be appended to the bprint buffer.
 */
void av_channel_description_bprint(struct AVBPrint *bp, enum AVChannel channel_id);

> Related to the previous question, does `av_cmp_q()` count as a function
> with two contexts?  Or no contexts?

And again, it looks like you are overgeneralizing and require that all
the functions take a context. In general, the C language is procedural
and so is the FFmpeg API. The fact that we are assuming some
constructs which might mimic or resemble OOP does not mean that all
the API was designed in that way.

> 
> Finally, a general question - functions of the form "avfoo" seem like they
> are more consistent than "av_foo".  Does the underscore mean anything?

This is due to the fact that despite the effort, implementing a
consistent API is difficult, also due to different
reviewers/contributors picking different conventions.

In some case we prefer av_ (most of libavutil) for the generic API,
while libavcodec/libavformat/libavfilter tend to use avLIB_, but there
might be exceptions.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-04-29  9:24                 ` [FFmpeg-devel] [PATCH v4 1/4] " Andrew Sayers
                                     ` (2 preceding siblings ...)
  2024-04-29  9:24                   ` [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes Andrew Sayers
@ 2024-05-05  8:31                   ` Andreas Rheinhardt
  2024-05-05 10:34                     ` Andrew Sayers
  3 siblings, 1 reply; 84+ messages in thread
From: Andreas Rheinhardt @ 2024-05-05  8:31 UTC (permalink / raw)
  To: ffmpeg-devel

Andrew Sayers:
> Derived from detailed explanations kindly provided by Stefano Sabatini:
> https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
> ---
>  doc/context.md | 308 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 308 insertions(+)
>  create mode 100644 doc/context.md
> 

Who is the intended audience of this file? (Aspiring) internal
developers or external API users?

- Andreas

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-05-05  8:31                   ` [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means Andreas Rheinhardt
@ 2024-05-05 10:34                     ` Andrew Sayers
  0 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-05 10:34 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Sun, May 05, 2024 at 10:31:18AM +0200, Andreas Rheinhardt wrote:
> Andrew Sayers:
> > Derived from detailed explanations kindly provided by Stefano Sabatini:
> > https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
> > ---
> >  doc/context.md | 308 +++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 308 insertions(+)
> >  create mode 100644 doc/context.md
> > 
> 
> Who is the intended audience of this file? (Aspiring) internal
> developers or external API users?

External API users.  This needs to say e.g. "ignore anything called
`internal` or `priv_data`", whereas a document for new internal devs
would say which one to prefer in new code.  That would be very
useful, but well beyond my current abilities.

(I'm still travelling so have low mental and typing bandwidth, but am
thinking through other responses and should have time to respond in
the coming days)
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means
  2024-05-05  7:29                   ` Stefano Sabatini
@ 2024-05-05 21:04                     ` Andrew Sayers
  2024-05-22 10:37                       ` Stefano Sabatini
  0 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-05-05 21:04 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

I'm still travelling, so the following thoughts might be a bit
half-formed.  But I wanted to get some feedback before sitting down
for a proper think.

On Sun, May 05, 2024 at 09:29:10AM +0200, Stefano Sabatini wrote:
> On date Monday 2024-04-29 10:10:35 +0100, Andrew Sayers wrote:
> > On Mon, Apr 22, 2024 at 07:05:12PM +0200, Stefano Sabatini wrote:
> [...]
> > > I don't have a strong opinion, but I'd probably focus on providing a
> > > typical example of a common API (check doc/examples). Also I see here
> > > there is a strong focus on OOP, this might be counter-productive in
> > > case the reader is not familiar with OOP terminology.
> > > 
> > > OTOH the content might be useful for readers coming from an OOP
> > > background and terminology. I wonder if this content might be isolated
> > > in a dedicated section, so that non-OOP readers can simply skip it.
> > > 
> > > But this is not a strong objection, and can be possibly reworked in a
> > > later step.
> > > 
> > 
> > This is really a document for FFmpeg newbies, so we need to assume as
> > little prior knowledge as possible.  After a few days to think it
> > over, I think we should avoid assuming...
> > 
> > Knowledge of object-oriented programming.  For example, this should be
> > useful to a research mathematician with a project that involves codec
> > algorithms.  So the next draft should feel less like "FFmpeg for OOP
> > devs" and more like "FFmpeg for newbies (with some optional OOP
> > background reading)".
> > 
> > Knowing that programming doesn't *have* to be object-oriented.
> > OOP has become so ubiquitous nowadays, there are plenty of programmers
> > who will insist everything is OOP if you just speak loudly and slowly.
> > This is a harder problem in some ways, because someone who doesn't
> > understand can always re-read until they do, while someone who jumps
> > to the wrong conclusion will just keep reading and try to make things
> > fit their assumption (e.g. my earlier messages in this thread!).
> > So the "how it differs from OOP" stuff needs to stay fairly prominent.
> > 
> 
> > Knowing anything about FFmpeg (or multimedia in general).  I like the
> > idea of tweaking `doc/examples` to better introduce FFmpeg
> > fundamentals, but explaining "context" is a steep enough learning
> > curve on its own - introducing concepts like "stream" and "codec" at
> > the same time seems like too much.
> 
> But even if you show the API that does not mean you need to explain
> it entirely, you only need to highligth the structural relationships:
> 
>     // create an instance context, whatever it is
>     c = avcodec_alloc_context3(codec);
>     if (!c) {
>         fprintf(stderr, "Could not allocate video codec context\n");
>         exit(1);
>     }
> 
>     // set context parametres directly
>     c->bit_rate = 400000;
>     /* resolution must be a multiple of two */
>     c->width = 352;
>     c->height = 288;
>     /* frames per second */
>     c->time_base = (AVRational){1, 25};
>     c->framerate = (AVRational){25, 1};
> 
>     // use av_opt API to set the options?
>     ...
> 
>     // open the codec context provided a codec
>     ret = avcodec_open2(c, codec, NULL);
>     if (ret < 0) {
>         fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
>         exit(1);
>     }
> 
> You might even replace avcodec_ with fooblargh_ and get the same
> effect, with the addition that with avcodec_ you are already
> familiarizing the user with the concrete API rather than with an
> hypotetical one.
> 
> [...]
> 
> > I've also gone through the code looking for edge cases we haven't covered.
> > Here are some questions trying to prompt an "oh yeah I forgot to mention
> > that"-type answer.  Anything where the answer is more like "that should
> > probably be rewritten to be clearer", let me know and I'll avoid confusing
> > newbies with it.
> > 
> 
> > av_ambient_viewing_environment_create_side_data() takes an AVFrame as its
> > first argument, and returns a new AVAmbientViewingEnvironment.  What is the
> > context object for that function - AVFrame or AVAmbientViewingEnvironment?
> 
> But this should be clear from the doxy:
> 
> /**
>  * Allocate and add an AVAmbientViewingEnvironment structure to an existing
>  * AVFrame as side data.
>  *
>  * @return the newly allocated struct, or NULL on failure
>  */
> AVAmbientViewingEnvironment *av_ambient_viewing_environment_create_side_data(AVFrame *frame);

I'm afraid it's not clear, at least to me.  I think you're saying the
AVFrame is the context because a "create" function can't have a
context any more than a C++ "new" can be called as a member.  But the
function's prefix points to the other conclusion, and neither signal
is clear enough on its own.

My current thinking is to propose separate patches renaming arguments
to `ctx` whenever I find functions I can't parse.  That's not as good
as a simple rule like "the first argument is always the context", but
better than adding a paragraph or two about how to read the docs.

> Also, you are assuming that all the function should have a
> context. That's not the case, as you don't always need to keep track
> of a "context" when performing operations.

It sounds like there's a subtle distinction to be made here: when a
struct is named "FooContext" or a variable is named `ctx`, the writer
has signalled that "context" is the (only) correct interpretation.
OTOH, when something acts like a context but isn't explicitly
labelled as such, it may or may not have been intended as a context,
and treating it as one may or may not be helpful - it's more "if it
helps" than an objective fact.  That means reasonable people can
disagree about edge cases - for example, it's genuinely unclear
whether av_register_bitstream_filter()'s argument is a context, and
TBH if I weren't writing this doc I would just avoid thinking about
av_ambient_viewing_environment_create_side_data() altogether.

> 
> > 
> > av_register_bitstream_filter() (deprecated 4.0, removed 5.0) took an
> > `AVBitStreamFilter *` as its first argument, but I don't think you'd say
> > the argument provided "context" for the function.  So would I be right in
> > saying `AVBitStreamFilter *` is not a context, despite looking like one?
> 
> This was finally dropped so this is even missing. But again, it seems
> you are assuming that all the functions should take a context, which
> is not the case. In that case you had:
> av_register_bistream_filter(filter)
> 
> which was registering the filter in the program global state.
>  
> > av_buffersink_*() all take a `const AVFilterContext *` argument.
> > What does the difference between av_buffersink prefix and AVFilter type mean?
> 
> None, probabily it should have been named avfilter_buffersink since
> this is a libavfilter API, seel below.
> 
> > av_channel_description_bprint() takes a `struct AVBPrint *` as its first
> > argument, then `enum AVChannel`.  Is the context AVBPrint, AVChannel,
> > or both?  Does it make sense for a function to have two contexts?
> 
> Again, this should be clear from the doxy:
> /**
>  * Get a human readable string describing a given channel.
>  *
>  * @param buf pre-allocated buffer where to put the generated string
>  * @param buf_size size in bytes of the buffer.
>  * @param channel the AVChannel whose description to get
>  * @return amount of bytes needed to hold the output string, or a negative AVERROR
>  *         on failure. If the returned value is bigger than buf_size, then the
>  *         string was truncated.
>  */
> int av_channel_description(char *buf, size_t buf_size, enum AVChannel channel);
> 
> /**
>  * bprint variant of av_channel_description().
>  *
>  * @note the string will be appended to the bprint buffer.
>  */
> void av_channel_description_bprint(struct AVBPrint *bp, enum AVChannel channel_id);

I think you're saying that I should look at which word appears more
often in the doxy ("channel") rather than which word appears first in
the argument list ("buf")?  As above, the solution might be to rename
the variable in a separate patch rather than teach people another
special case.

> 
> > Related to the previous question, does `av_cmp_q()` count as a function
> > with two contexts?  Or no contexts?
> 
> And again, it looks like you are overgeneralizing and require that all
> the functions take a context. In general, the C language is procedural
> and so is the FFmpeg API. The fact that we are assuming some
> constructs which might mimic or resemble OOP does not mean that all
> the API was designed in that way.
> 
> > 
> > Finally, a general question - functions of the form "avfoo" seem like they
> > are more consistent than "av_foo".  Does the underscore mean anything?
> 
> This is due to the fact that despite the effort, implementing a
> consistent API is difficult, also due to different
> reviewers/contributors picking different conventions.
> 
> In some case we prefer av_ (most of libavutil) for the generic API,
> while libavcodec/libavformat/libavfilter tend to use avLIB_, but there
> might be exceptions.

Given all of the above (and Zhao Zhili's useful examples), I think
the document might be better like:

Section 1: context is a good way to think about some code constructs.
If you've ever used a callback function with an arbitrary callback
argument, you've used a context.  <quick example of a hypothetical
callback function with a context variable>.

Section 2: some projects explicitly use "context" as a metaphor.
<comparison of curl and FFmpeg's md5 contexts>.  This should be
understood as a broad metaphor that different people use to mean
slightly different things.

Section 3: FFmpeg has developed various conventions around contexts.
<discussion of a non-AVClass example that follows most patterns but
breaks some others>.

Section 4: user-facing contexts use AVClass+AVOptions.  This is a
common and highly visible special case, but not the inevitable
endpoint of all contexts.  <discussion of an AVClass-enabled object>.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v4 0/4] Explain what "context" means
  2024-04-18 15:06 [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means Andrew Sayers
                   ` (2 preceding siblings ...)
  2024-04-20  7:25 ` [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means Stefano Sabatini
@ 2024-05-15 15:54 ` Andrew Sayers
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 1/4] doc: " Andrew Sayers
                     ` (3 more replies)
  2024-06-04 14:47 ` [FFmpeg-devel] [PATCH v6 0/4] doc: Explain what "context" means Andrew Sayers
  4 siblings, 4 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-15 15:54 UTC (permalink / raw)
  To: ffmpeg-devel

This version strongly implies AVClass is only used alongside AVOption.
I'm not sure when or if e.g. AVClass::category would be used by an external
API developer, but happy to change the text if anyone has a use case.

I accept the argument that the previous version was linked more widely
than it was useful, but instead of reducing links I've tried to widen
its usefulness.  The new version discusses how e.g. FFmpeg contexts differ
from curl, which could be useful to developers coming from other projects.
And it goes into more detail about e.g. context lifetime, which could
be useful for even an intermediate developer.

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-05-15 15:54 ` [FFmpeg-devel] [PATCH v4 0/4] Explain what "context" means Andrew Sayers
@ 2024-05-15 15:54   ` Andrew Sayers
  2024-05-22  9:31     ` Stefano Sabatini
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-05-15 15:54 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Derived from detailed explanations kindly provided by Stefano Sabatini:
https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
---
 doc/context.md | 394 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 394 insertions(+)
 create mode 100644 doc/context.md

diff --git a/doc/context.md b/doc/context.md
new file mode 100644
index 0000000000..fb85b3f366
--- /dev/null
+++ b/doc/context.md
@@ -0,0 +1,394 @@
+# Introduction to contexts
+
+&ldquo;%Context&rdquo; is a name for a widely-used programming idiom.
+This document explains the general idiom and the conventions FFmpeg has built around it.
+
+This document uses object-oriented analogies to help readers familiar with
+[object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming)
+learn about contexts.  But contexts can also be used outside of OOP,
+and even in situations where OOP isn't helpful.  So these analogies
+should only be used as a first step towards understanding contexts.
+
+## &ldquo;Context&rdquo; as a way to think about code
+
+A context is any data structure that is passed to several functions
+(or several instances of the same function) that all operate on the same entity.
+For example, [object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming)
+languages usually provide member functions with a `this` or `self` value:
+
+```c
+class my_cxx_class {
+  void my_member_function() {
+    // the implicit object parameter provides context for the member function:
+    std::cout << this;
+  }
+};
+```
+
+Contexts are a fundamental building block of OOP, but can also be used in procedural code.
+For example, most callback functions can be understood to use contexts:
+
+```c
+struct MyStruct {
+  int counter;
+};
+
+void my_callback( void *my_var_ ) {
+  // my_var provides context for the callback function:
+  struct MyStruct *my_var = (struct MyStruct *)my_var_;
+  printf("Called %d time(s)", ++my_var->counter);
+}
+
+void init() {
+  struct MyStruct my_var;
+  my_var.counter = 0;
+  register_callback( my_callback, &my_var );
+}
+```
+
+In the broadest sense, &ldquo;context&rdquo; is just a way to think about code.
+You can even use it to think about code written by people who have never
+heard the term, or who would disagree with you about what it means.
+
+## &ldquo;Context&rdquo; as a tool of communication
+
+&ldquo;%Context&ldquo; can just be a word to understand code in your own head,
+but it can also be a term you use to explain your interfaces.
+Here is a version of the callback example that makes the context explicit:
+
+```c
+struct CallbackContext {
+  int counter;
+};
+
+void my_callback( void *ctx_ ) {
+  // ctx provides context for the callback function:
+  struct CallbackContext *ctx = (struct CallbackContext *)ctx_;
+  printf("Called %d time(s)", ++ctx->counter);
+}
+
+void init() {
+  struct CallbackContext ctx;
+  ctx.counter = 0;
+  register_callback( my_callback, &ctx );
+}
+```
+
+The difference here is subtle, but important.  If a piece of code
+*appears compatible with contexts*, then you are *allowed to think
+that way*, but if a piece of code *explicitly states it uses
+contexts*, then you are *required to follow that approach*.
+
+For example, imagine someone modified `MyStruct` in the earlier example
+to count several unrelated events across the whole program.  That would mean
+it contained information about multiple entities, so was not a context.
+But nobody ever *said* it was a context, so that isn't necessarily wrong.
+However, proposing the same change to the `CallbackContext` in the later example
+would violate a guarantee, and should be pointed out in a code review.
+
+@warning Guaranteeing to use contexts does not mean guaranteeing to use
+object-oriented programming.  For example, FFmpeg creates its contexts
+procedurally instead of with constructors.
+
+## Contexts in the real world
+
+To understand how contexts are used in the real world, it might be
+useful to compare [curl's MD5 hash context](https://github.com/curl/curl/blob/bbeeccdea8507ff50efca70a0b33d28aef720267/lib/curl_md5.h#L48)
+with @ref AVMD5 "FFmpeg's equivalent context".
+
+The [MD5 algorithm](https://en.wikipedia.org/wiki/MD5) produces
+a fixed-length digest from arbitrary-length data.  It does this by calculating
+the digest for a prefix of the data, then loading the next part and adding it
+to the previous digest, and so on.  Projects that use MD5 generally use some
+kind of context, so comparing them can reveal differences between projects.
+
+```c
+// Curl's MD5 context looks like this:
+struct MD5_context {
+  const struct MD5_params *md5_hash;    /* Hash function definition */
+  void                  *md5_hashctx;   /* Hash function context */
+};
+
+// FFmpeg's MD5 context looks like this:
+typedef struct AVMD5 {
+    uint64_t len;
+    uint8_t  block[64];
+    uint32_t ABCD[4];
+} AVMD5;
+```
+
+Curl's struct name ends with `_context`, guaranteeing contexts are the correct
+interpretation.  FFmpeg's struct does not explicitly say it's a context, but
+@ref libavutil/md5.c "its functions do" so we can reasonably assume
+it's the intended interpretation.
+
+Curl's struct uses `void *md5_hashctx` to avoid guaranteeing
+implementation details in the public interface, whereas FFmpeg makes
+everything accessible.  This kind of data hiding is an advanced context-oriented
+convention, and is discussed below.  Using it in this case has strengths and
+weaknesses.  On one hand, it means changing the layout in a future version
+of curl won't break downstream programs that used that data.  On the other hand,
+the MD5 algorithm has been stable for 30 years, so it's arguably more important
+to let people dig in when debugging their own code.
+
+Curl's struct is declared as `struct <type> { ... }`, whereas FFmpeg uses
+`typedef struct <type> { ... } <type>`.  These conventions are used with both
+context and non-context structs, so don't say anything about contexts as such.
+Specifically, FFmpeg's convention is a workaround for an issue with C grammar:
+
+```c
+void my_function( ... ) {
+  int                my_var;        // good
+  MD5_context        my_curl_ctx;   // error: C needs you to explicitly say "struct"
+  struct MD5_context my_curl_ctx;   // good: added "struct"
+  AVMD5              my_ffmpeg_ctx; // good: typedef's avoid the need for "struct"
+}
+```
+
+Both MD5 implementations are long-tested, widely-used examples of contexts
+in the real world.  They show how contexts can solve the same problem
+in different ways.
+
+## FFmpeg's advanced context-oriented conventions
+
+Projects that make heavy use of contexts tend to develop conventions
+to make them more useful.  This section discusses conventions used in FFmpeg,
+some of which are used in other projects, others are unique to this project.
+
+### Naming: &ldquo;Context&rdquo; and &ldquo;ctx&rdquo;
+
+```c
+// Context struct names usually end with `Context`:
+struct AVSomeContext {
+  ...
+};
+
+// Functions are usually named after their context,
+// context parameters usually come first and are often called `ctx`:
+void av_some_function( AVSomeContext *ctx, ... );
+```
+
+If an FFmpeg struct is intended for use as a context, its name usually
+makes that clear.  Exceptions to this rule include AVMD5 (discussed above),
+which is only identified as a context by the functions that call it.
+
+If a function is associated with a context, its name usually
+begins with some variant of the context name (e.g. av_md5_alloc()
+or avcodec_alloc_context3()).  Exceptions to this rule include
+@ref avformat.h "AVFormatContext's functions", many of which
+begin with just `av_`.
+
+If a function has a context parameter, it usually comes first and its name
+often contains `ctx`.  Exceptions include av_bsf_alloc(), which puts the
+context argument second to emphasise it's an out variable.
+
+### Data hiding: private contexts
+
+```c
+// Context structs often hide private context:
+struct AVSomeContext {
+  void *priv_data; // sometimes just called "internal"
+};
+```
+
+Contexts usually present a public interface, so changing a context's members
+forces everyone that uses the library to at least recompile their program,
+if not rewrite it to remain compatible.  Hiding information in a private context
+ensures it can be modified without affecting downstream software.
+
+Object-oriented programmers may be tempted to compare private contexts to
+*private class members*.  That's often accurate, but for example it can also
+be used like a *virtual function table* - a list of functions that are
+guaranteed to exist, but may be implemented differently for different
+sub-classes.  When thinking about private contexts, remember that FFmpeg
+isn't *large enough* to need some common OOP techniques, even though it's
+solving a problem that's *complex enough* to benefit from some rarer techniques.
+
+### Manage lifetime: allocate, initialize and free
+
+```c
+void my_function( ... ) {
+
+    // Context structs are allocated then initialized with associated functions:
+
+    AVSomeContext *ctx = av_some_context_alloc( ... );
+
+    // ... configure ctx ...
+
+    av_some_context_init( ctx, ... );
+
+    // ... use ctx ...
+
+    // Context structs are freed with associated functions:
+
+    av_some_context_free( ctx );
+
+}
+```
+
+FFmpeg contexts go through the following stages of life:
+
+1. allocation (often a function that ends with `_alloc`)
+   * a range of memory is allocated for use by the structure
+   * memory is allocated on boundaries that improve caching
+   * memory is reset to zeroes, some internal structures may be initialized
+2. configuration (implemented by setting values directly on the object)
+   * no function for this - calling code populates the structure directly
+   * memory is populated with useful values
+   * simple contexts can skip this stage
+3. initialization (often a function that ends with `_init`)
+   * setup actions are performed based on the configuration (e.g. opening files)
+5. normal usage
+   * most functions are called in this stage
+   * documentation implies some members are now read-only (or not used at all)
+   * some contexts allow re-initialization
+6. closing (often a function that ends with `_close()`)
+   * teardown actions are performed (e.g. closing files)
+7. deallocation (often a function that ends with `_free()`)
+   * memory is returned to the pool of available memory
+
+This can mislead object-oriented programmers, who expect something more like:
+
+1. allocation (usually a `new` keyword)
+   * a range of memory is allocated for use by the structure
+   * memory *may* be reset (e.g. for security reasons)
+2. initialization (usually a constructor)
+   * memory is populated with useful values
+   * related setup actions are performed based on arguments (e.g. opening files)
+3. normal usage
+   * most functions are called in this stage
+   * compiler enforces that some members are read-only (or private)
+   * no going back to the previous stage
+4. finalization (usually a destructor)
+   * teardown actions are performed (e.g. closing files)
+5. deallocation (usually a `delete` keyword)
+   * memory is returned to the pool of available memory
+
+FFmpeg's allocation stage is broadly similar to OOP, but can do some higher-level
+operations.  For example, AVOptions-enabled structs (discussed below) contain an
+AVClass member that is set during allocation.
+
+FFmpeg's "configuration" and "initialization" stages combine to resemble OOP's
+"initialization" stage.  This can mislead object-oriented developers,
+who are used to doing both at once.  This means FFmpeg contexts don't have
+a direct equivalent of OOP constructors, as they would be doing
+two jobs in one function.
+
+FFmpeg's three-stage creation process is useful for complicated structures.
+For example, AVCodecContext contains many members that *can* be set before
+initialization, but in practice most programs set few if any of them.
+Implementing this with a constructor would involve a function with a list
+of arguments that was extremely long and changed whenever the struct was
+updated.  For contexts that don't need the extra flexibility, FFmpeg usually
+provides a combined allocator and initializer function.  For historical reasons,
+suffixes like `_alloc`, `_init`, `_alloc_context` and even `_open` can indicate
+the function does any combination of allocation and initialization.
+
+FFmpeg's "closing" stage is broadly similar to OOP's "finalization" stage,
+but some contexts allow re-initialization after finalization.  For example,
+SwrContext lets you call swr_close() then swr_init() to reuse a context.
+
+FFmpeg's "deallocation" stage is broadly similar to OOP, but can perform some
+higher-level functions (similar to the allocation stage).
+
+Very few contexts need the flexibility of separate "closing" and
+"deallocation" stages, so these are usually combined into a single function.
+Closing functions usually end with "_close", while deallocation
+functions usually end with "_free".
+
+### Reflection: AVOptions-enabled structs
+
+Object-oriented programming puts more focus on data hiding than FFmpeg needs,
+but it also puts less focus on
+[reflection](https://en.wikipedia.org/wiki/Reflection_(computer_programming)).
+
+To understand FFmpeg's reflection requirements, run `ffmpeg -h full` on the
+command-line, then ask yourself how you would implement all those options
+with the C standard [`getopt` function](https://en.wikipedia.org/wiki/Getopt).
+You can also ask the same question for any other programming languages you know.
+[Python's argparse module](https://docs.python.org/3/library/argparse.html)
+is a good example - its approach works well with far more complex programs
+than `getopt`, but would you like to maintain an argparse implementation
+with 15,000 options and growing?
+
+Most solutions assume you can just put all options in a single block,
+which is unworkable at FFmpeg's scale.  Instead, we split configuration
+across many *AVOptions-enabled structs*, which use the @ref avoptions
+"AVOptions API" to reflect information about their user-configurable members,
+including members in private contexts.
+
+An *AVOptions-enabled struct* is a struct that contains an AVClass element as
+its first member, and uses that element to provide access to instances of
+AVOption, each of which provides information about a single option.
+The AVClass can also include more @ref AVClass "AVClasses" for private contexts,
+making it possible to set options through the API that aren't
+accessible directly.
+
+AVOptions-accessible members of a context should be accessed through the
+AVOptions API whenever possible, even if they're not hidden away in a private
+context.  That ensures values are validated as they're set, and means you won't
+have to do as much work if a future version of FFmpeg changes the layout.
+
+AVClass was created very early in FFmpeg's history, long before AVOptions.
+Its name suggests some kind of relationship to an OOP
+base [class](https://en.wikipedia.org/wiki/Class_(computer_programming)),
+but the name has become less accurate as FFmpeg evolved, to the point where
+AVClass and AVOption are largely synonymous in modern usage.  The difference
+might still matter if you need to support old versions of FFmpeg,
+where you might find *AVClass context structures* (contain an AVClass element
+as their first member) that are not *AVOptions-enabled* (don't use that element
+to provide access to instances of AVOption).
+
+Object-oriented programmers may be tempted to compare @ref avoptions "AVOptions"
+to OOP getters and setters.  There is some overlap in functionality, but OOP
+getters and setters are usually specific to a single member and don't provide
+metadata about the member; whereas AVOptions has a single API that covers
+every option, and provides help text etc. as well.
+
+Object-oriented programmers may be tempted to compare AVOptions-accessible
+members of a public context to protected members of a class.  Both provide
+global access through an API, and unrestricted access for trusted friends.
+But this is just a happy accident, not a guarantee.
+
+## Final example: context for a codec
+
+AVCodecContext is an AVOptions-enabled struct that contains information
+about encoding or decoding one stream of data (e.g. the video in a movie).
+It's a good example of many of the issues above.
+
+The name "AVCodecContext" tells us this is a context.  Many of
+@ref libavcodec/avcodec.h "its functions" start with an `avctx` parameter,
+indicating this object provides context for that function.
+
+AVCodecContext::internal contains the private context.  For example,
+codec-specific information might be stored here.
+
+AVCodecContext is allocated with avcodec_alloc_context3(), initialized with
+avcodec_open2(), and freed with avcodec_free_context().  Most of its members
+are configured with the @ref avoptions "AVOptions API", but for example you
+can set AVCodecContext::opaque or AVCodecContext::draw_horiz_band() if your
+program happens to need them.
+
+AVCodecContext provides an abstract interface to many different *codecs*.
+Options supported by many codecs (e.g. "bitrate") are kept in AVCodecContext
+and reflected as AVOptions.  Options that are specific to one codec are
+stored in the internal context, and reflected from there.
+
+To support a specific codec, AVCodecContext's private context is set to
+an encoder-specific data type.  For example, the video codec
+[H.264](https://en.wikipedia.org/wiki/Advanced_Video_Coding) is supported via
+[the x264 library](https://www.videolan.org/developers/x264.html), and
+implemented in X264Context.  Although included in the documentation, X264Context
+is not part of the public API.  Whereas there are strict rules about
+changing AVCodecContext, a version of FFmpeg could modify X264Context or
+replace it with another type altogether.  An adverse legal ruling or security
+problem could even force us to switch to a completely different library
+without a major version bump.
+
+The design of AVCodecContext provides several important guarantees:
+
+- lets you use the same interface for any codec
+- supports common encoder options like "bitrate" without duplicating code
+- supports encoder-specific options like "profile" without bulking out the public interface
+- reflects both types of options to users, with help text and detection of missing options
+- hides implementation details (e.g. its encoding buffer)
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v4 2/4] lavu: Clarify relationship between AVClass, AVOption and context
  2024-05-15 15:54 ` [FFmpeg-devel] [PATCH v4 0/4] Explain what "context" means Andrew Sayers
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 1/4] doc: " Andrew Sayers
@ 2024-05-15 15:54   ` Andrew Sayers
  2024-05-22 10:04     ` Stefano Sabatini
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation Andrew Sayers
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes Andrew Sayers
  3 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-05-15 15:54 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

---
 libavutil/log.h | 11 ++++++++---
 libavutil/opt.h |  7 ++++---
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/libavutil/log.h b/libavutil/log.h
index ab7ceabe22..cfbf416679 100644
--- a/libavutil/log.h
+++ b/libavutil/log.h
@@ -59,9 +59,14 @@ typedef enum {
 struct AVOptionRanges;
 
 /**
- * Describe the class of an AVClass context structure. That is an
- * arbitrary struct of which the first field is a pointer to an
- * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.).
+ * Metadata about an arbitrary data structure
+ *
+ * A @ref md_doc_2context "context struct" whose first member is a pointer
+ * to an AVClass object is called an "AVClass context structure"
+ * (e.g. AVCodecContext, AVFormatContext etc.).
+ *
+ * AVClass is often combined with @ref avoptions "AVOptions" to create
+ * "AVOptions-enabled structs" that can be easily configured by users.
  */
 typedef struct AVClass {
     /**
diff --git a/libavutil/opt.h b/libavutil/opt.h
index 07e27a9208..e314e134c2 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -39,9 +39,10 @@
  * @defgroup avoptions AVOptions
  * @ingroup lavu_data
  * @{
- * AVOptions provide a generic system to declare options on arbitrary structs
- * ("objects"). An option can have a help text, a type and a range of possible
- * values. Options may then be enumerated, read and written to.
+ * Builds on AVClass, adding a generic system to declare options.
+ *
+ * An option can have a help text, a type and a range of possible values.
+ * Options may then be enumerated, read and written to.
  *
  * There are two modes of access to members of AVOption and its child structs.
  * One is called 'native access', and refers to access from the code that
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation
  2024-05-15 15:54 ` [FFmpeg-devel] [PATCH v4 0/4] Explain what "context" means Andrew Sayers
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 1/4] doc: " Andrew Sayers
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
@ 2024-05-15 15:54   ` Andrew Sayers
  2024-05-15 16:46     ` Lynne via ffmpeg-devel
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes Andrew Sayers
  3 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-05-15 15:54 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Some headings needed to be rewritten to accomodate the text,
(hopefully) without changing the meaning.
---
 libavcodec/aac/aacdec.h            |  2 +-
 libavcodec/aacenc.h                |  2 +-
 libavcodec/ac3enc.h                |  2 +-
 libavcodec/amfenc.h                |  2 +-
 libavcodec/atrac.h                 |  2 +-
 libavcodec/avcodec.h               |  3 ++-
 libavcodec/bsf.h                   |  2 +-
 libavcodec/cbs.h                   |  2 +-
 libavcodec/d3d11va.h               |  3 +--
 libavcodec/h264dsp.h               |  2 +-
 libavcodec/h264pred.h              |  2 +-
 libavcodec/mediacodec.h            |  2 +-
 libavcodec/mpegaudiodec_template.c |  2 +-
 libavcodec/pthread_frame.c         |  4 ++--
 libavcodec/qsv.h                   |  6 ++++--
 libavcodec/sbr.h                   |  2 +-
 libavcodec/smacker.c               |  2 +-
 libavcodec/vdpau.h                 |  3 ++-
 libavcodec/videotoolbox.h          |  5 +++--
 libavfilter/avfilter.h             |  2 +-
 libavformat/avformat.h             |  3 ++-
 libavformat/avio.h                 |  3 ++-
 libavutil/audio_fifo.h             |  2 +-
 libavutil/hwcontext.h              | 21 ++++++++++++---------
 libavutil/hwcontext_cuda.h         |  2 +-
 libavutil/hwcontext_d3d11va.h      |  4 ++--
 libavutil/hwcontext_d3d12va.h      |  6 +++---
 libavutil/hwcontext_drm.h          |  2 +-
 libavutil/hwcontext_dxva2.h        |  4 ++--
 libavutil/hwcontext_mediacodec.h   |  2 +-
 libavutil/hwcontext_opencl.h       |  4 ++--
 libavutil/hwcontext_qsv.h          |  4 ++--
 libavutil/hwcontext_vaapi.h        |  6 +++---
 libavutil/hwcontext_vdpau.h        |  2 +-
 libavutil/hwcontext_vulkan.h       |  4 ++--
 libavutil/lfg.h                    |  2 +-
 36 files changed, 66 insertions(+), 57 deletions(-)

diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
index eed53c6c96..1d991a3c63 100644
--- a/libavcodec/aac/aacdec.h
+++ b/libavcodec/aac/aacdec.h
@@ -253,7 +253,7 @@ typedef struct AACDecDSP {
 } AACDecDSP;
 
 /**
- * main AAC decoding context
+ * main AAC decoding @ref md_doc_2context "context"
  */
 struct AACDecContext {
     const struct AVClass  *class;
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index d07960620e..1a645f4719 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -207,7 +207,7 @@ typedef struct AACPCEInfo {
 } AACPCEInfo;
 
 /**
- * AAC encoder context
+ * AAC encoder @ref md_doc_2context "context"
  */
 typedef struct AACEncContext {
     AVClass *av_class;
diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
index 30812617cc..c725007077 100644
--- a/libavcodec/ac3enc.h
+++ b/libavcodec/ac3enc.h
@@ -152,7 +152,7 @@ typedef struct AC3Block {
 } AC3Block;
 
 /**
- * AC-3 encoder private context.
+ * AC-3 encoder private @ref md_doc_2context "context"
  */
 typedef struct AC3EncodeContext {
     AVClass *av_class;                      ///< AVClass used for AVOption
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
index 2dbd378ef8..f142ede63a 100644
--- a/libavcodec/amfenc.h
+++ b/libavcodec/amfenc.h
@@ -43,7 +43,7 @@ typedef struct AmfTraceWriter {
 } AmfTraceWriter;
 
 /**
-* AMF encoder context
+* AMF encoder @ref md_doc_2context "context"
 */
 
 typedef struct AmfContext {
diff --git a/libavcodec/atrac.h b/libavcodec/atrac.h
index 05208bbee6..1527e376a9 100644
--- a/libavcodec/atrac.h
+++ b/libavcodec/atrac.h
@@ -39,7 +39,7 @@ typedef struct AtracGainInfo {
 } AtracGainInfo;
 
 /**
- *  Gain compensation context structure.
+ *  Gain compensation @ref md_doc_2context "context"
  */
 typedef struct AtracGCContext {
     float   gain_tab1[16];  ///< gain compensation level table
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 2da63c87ea..4f7a5aa80d 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -430,7 +430,8 @@ typedef struct RcOverride{
 #define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0)
 
 /**
- * main external API structure.
+ * @ref md_doc_2context "Context" for an encode or decode session
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
index a09c69f242..bf79afa7cc 100644
--- a/libavcodec/bsf.h
+++ b/libavcodec/bsf.h
@@ -56,7 +56,7 @@
  */
 
 /**
- * The bitstream filter state.
+ * Bitstream filter @ref md_doc_2context "context"
  *
  * This struct must be allocated with av_bsf_alloc() and freed with
  * av_bsf_free().
diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
index d479b1ac2d..0ff64d2fef 100644
--- a/libavcodec/cbs.h
+++ b/libavcodec/cbs.h
@@ -214,7 +214,7 @@ typedef void (*CBSTraceWriteCallback)(void *trace_context,
                                       int64_t value);
 
 /**
- * Context structure for coded bitstream operations.
+ * @ref md_doc_2context "Context" structure for coded bitstream operations.
  */
 typedef struct CodedBitstreamContext {
     /**
diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
index 27f40e5519..ec0c472ab9 100644
--- a/libavcodec/d3d11va.h
+++ b/libavcodec/d3d11va.h
@@ -46,8 +46,7 @@
  */
 
 /**
- * This structure is used to provides the necessary configurations and data
- * to the Direct3D11 FFmpeg HWAccel implementation.
+ * @ref md_doc_2context "Context" for the Direct3D11 FFmpeg HWAccel implementation
  *
  * The application must make it available as AVCodecContext.hwaccel_context.
  *
diff --git a/libavcodec/h264dsp.h b/libavcodec/h264dsp.h
index e0880c4d88..27256c5605 100644
--- a/libavcodec/h264dsp.h
+++ b/libavcodec/h264dsp.h
@@ -37,7 +37,7 @@ typedef void (*h264_biweight_func)(uint8_t *dst, uint8_t *src,
                                    int weightd, int weights, int offset);
 
 /**
- * Context for storing H.264 DSP functions
+ * @ref md_doc_2context "Context" for storing H.264 DSP functions
  */
 typedef struct H264DSPContext {
     /* weighted MC */
diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h
index cb008548fc..2b076f8846 100644
--- a/libavcodec/h264pred.h
+++ b/libavcodec/h264pred.h
@@ -89,7 +89,7 @@
 #define PART_NOT_AVAILABLE -2
 
 /**
- * Context for storing H.264 prediction functions
+ * @ref md_doc_2context "Context" for storing H.264 prediction functions
  */
 typedef struct H264PredContext {
     void(*pred4x4[9 + 3 + 3])(uint8_t *src, const uint8_t *topright,
diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
index 4e9b56a618..9967a7cfb3 100644
--- a/libavcodec/mediacodec.h
+++ b/libavcodec/mediacodec.h
@@ -26,7 +26,7 @@
 #include "libavcodec/avcodec.h"
 
 /**
- * This structure holds a reference to a android/view/Surface object that will
+ * @ref md_doc_2context "Context" for the android/view/Surface object that will
  * be used as output by the decoder.
  *
  */
diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c
index c73b1e0054..15d63215d1 100644
--- a/libavcodec/mpegaudiodec_template.c
+++ b/libavcodec/mpegaudiodec_template.c
@@ -1691,7 +1691,7 @@ static int decode_frame_adu(AVCodecContext *avctx, AVFrame *frame,
 #if CONFIG_MP3ON4_DECODER || CONFIG_MP3ON4FLOAT_DECODER
 
 /**
- * Context for MP3On4 decoder
+ * @ref md_doc_2context "Context" for MP3On4 decoder
  */
 typedef struct MP3On4DecodeContext {
     int frames;                     ///< number of mp3 frames per block (number of mp3 decoder instances)
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 67f09c1f48..74f05eedcf 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -71,7 +71,7 @@ typedef struct ThreadFrameProgress {
 } ThreadFrameProgress;
 
 /**
- * Context used by codec threads and stored in their AVCodecInternal thread_ctx.
+ * @ref md_doc_2context "Context" used by codec threads and stored in their AVCodecInternal thread_ctx.
  */
 typedef struct PerThreadContext {
     struct FrameThreadContext *parent;
@@ -111,7 +111,7 @@ typedef struct PerThreadContext {
 } PerThreadContext;
 
 /**
- * Context stored in the client AVCodecInternal thread_ctx.
+ * @ref md_doc_2context "Context" stored in the client AVCodecInternal thread_ctx.
  */
 typedef struct FrameThreadContext {
     PerThreadContext *threads;     ///< The contexts for each thread.
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index c156b08d07..8b8160a4b1 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -26,8 +26,10 @@
 #include "libavutil/buffer.h"
 
 /**
- * This struct is used for communicating QSV parameters between libavcodec and
- * the caller. It is managed by the caller and must be assigned to
+ * @ref md_doc_2context "Context" for communicating QSV parameters between libavcodec
+ * and the caller.
+ *
+ * It is managed by the caller and must be assigned to
  * AVCodecContext.hwaccel_context.
  * - decoding: hwaccel_context must be set on return from the get_format()
  *             callback
diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
index fe3a39603a..98ad9024a9 100644
--- a/libavcodec/sbr.h
+++ b/libavcodec/sbr.h
@@ -116,7 +116,7 @@ typedef struct SBRData {
 typedef struct SpectralBandReplication SpectralBandReplication;
 
 /**
- * aacsbr functions pointers
+ * aacsbr functions pointer @ref md_doc_2context "context"
  */
 typedef struct AACSBRContext {
     int (*sbr_lf_gen)(SpectralBandReplication *sbr,
diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c
index 8f198d6957..1ca39a74a0 100644
--- a/libavcodec/smacker.c
+++ b/libavcodec/smacker.c
@@ -68,7 +68,7 @@ typedef struct HuffEntry {
 } HuffEntry;
 
 /**
- * Context used for code reconstructing
+ * @ref md_doc_2context "Context" used for code reconstructing
  */
 typedef struct HuffContext {
     int current;
diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
index 8021c25761..227b85727d 100644
--- a/libavcodec/vdpau.h
+++ b/libavcodec/vdpau.h
@@ -64,8 +64,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
                                const VdpBitstreamBuffer *);
 
 /**
- * This structure is used to share data between the libavcodec library and
+ * @ref md_doc_2context "Context" to share data between the libavcodec library and
  * the client video application.
+ *
  * This structure will be allocated and stored in AVCodecContext.hwaccel_context
  * by av_vdpau_bind_context(). Members can be set by the user once
  * during initialization or through each AVCodecContext.get_buffer()
diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
index d68d76e400..f15e79f325 100644
--- a/libavcodec/videotoolbox.h
+++ b/libavcodec/videotoolbox.h
@@ -49,8 +49,9 @@
 #include "libavutil/attributes.h"
 
 /**
- * This struct holds all the information that needs to be passed
- * between the caller and libavcodec for initializing Videotoolbox decoding.
+ * @ref md_doc_2context "Context" for information passed between the caller and libavcodec
+ * for initializing Videotoolbox decoding.
+ *
  * Its size is not a part of the public ABI, it must be allocated with
  * av_videotoolbox_alloc_context() and freed with av_free().
  */
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index a34e61f23c..54b5f9dc43 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -403,7 +403,7 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
  */
 #define AVFILTER_THREAD_SLICE (1 << 0)
 
-/** An instance of a filter */
+/** @ref md_doc_2context "Context" for a filter */
 struct AVFilterContext {
     const AVClass *av_class;        ///< needed for av_log() and filters common options
 
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 8afdcd9fd0..28243c06c4 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1241,7 +1241,8 @@ enum AVDurationEstimationMethod {
 };
 
 /**
- * Format I/O context.
+ * Format I/O @ref md_doc_2context "context"
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavformat/avio.h b/libavformat/avio.h
index ebf611187d..b525c93194 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -146,7 +146,8 @@ enum AVIODataMarkerType {
 };
 
 /**
- * Bytestream IO Context.
+ * Bytestream I/O @ref md_doc_2context "context"
+ *
  * New public fields can be added with minor version bumps.
  * Removal, reordering and changes to existing public fields require
  * a major version bump.
diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h
index fa5f59a2be..de29715462 100644
--- a/libavutil/audio_fifo.h
+++ b/libavutil/audio_fifo.h
@@ -39,7 +39,7 @@
  */
 
 /**
- * Context for an Audio FIFO Buffer.
+ * @ref md_doc_2context "Context" for an Audio FIFO Buffer.
  *
  * - Operates at the sample level rather than the byte level.
  * - Supports multiple channels with either planar or packed sample format.
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index bac30debae..60064cf08b 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -41,12 +41,13 @@ enum AVHWDeviceType {
 };
 
 /**
- * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
- * i.e. state that is not tied to a concrete processing configuration.
- * E.g., in an API that supports hardware-accelerated encoding and decoding,
- * this struct will (if possible) wrap the state that is common to both encoding
- * and decoding and from which specific instances of encoders or decoders can be
- * derived.
+ * @ref md_doc_2context "Context" for (hardware/vendor-specific) "high-level" state.
+ *
+ * "High-level state" is anything that is not tied to a concrete processing
+ * configuration. E.g., in an API that supports hardware-accelerated encoding
+ * and decoding, this struct will (if possible) wrap the state that is common
+ * to both encoding and decoding and from which specific instances of encoders
+ * or decoders can be derived.
  *
  * This struct is reference-counted with the AVBuffer mechanism. The
  * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
@@ -103,9 +104,11 @@ typedef struct AVHWDeviceContext {
 } AVHWDeviceContext;
 
 /**
- * This struct describes a set or pool of "hardware" frames (i.e. those with
- * data not located in normal system memory). All the frames in the pool are
- * assumed to be allocated in the same way and interchangeable.
+ * @ref md_doc_2context "context" for a pool of "hardware" frames (those with
+ * data not located in normal system memory)
+ *
+ * All the frames in the pool are assumed to be allocated in the same way and
+ * interchangeable.
  *
  * This struct is reference-counted with the AVBuffer mechanism and tied to a
  * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
index cbad434fea..e259892688 100644
--- a/libavutil/hwcontext_cuda.h
+++ b/libavutil/hwcontext_cuda.h
@@ -37,7 +37,7 @@
 typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVCUDADeviceContext {
     CUcontext cuda_ctx;
diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
index 77d2d72f1b..101d1cb6f8 100644
--- a/libavutil/hwcontext_d3d11va.h
+++ b/libavutil/hwcontext_d3d11va.h
@@ -40,7 +40,7 @@
 #include <stdint.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVD3D11VADeviceContext {
     /**
@@ -126,7 +126,7 @@ typedef struct AVD3D11FrameDescriptor {
 } AVD3D11FrameDescriptor;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVD3D11VAFramesContext {
     /**
diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
index ff06e6f2ef..c623914c2b 100644
--- a/libavutil/hwcontext_d3d12va.h
+++ b/libavutil/hwcontext_d3d12va.h
@@ -37,7 +37,7 @@
 #include <d3d12video.h>
 
 /**
- * @brief This struct is allocated as AVHWDeviceContext.hwctx
+ * @brief This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  *
  */
 typedef struct AVD3D12VADeviceContext {
@@ -78,7 +78,7 @@ typedef struct AVD3D12VADeviceContext {
 } AVD3D12VADeviceContext;
 
 /**
- * @brief This struct is used to sync d3d12 execution
+ * @brief This @ref md_doc_2context "context" is used to sync d3d12 execution
  *
  */
 typedef struct AVD3D12VASyncContext {
@@ -120,7 +120,7 @@ typedef struct AVD3D12VAFrame {
 } AVD3D12VAFrame;
 
 /**
- * @brief This struct is allocated as AVHWFramesContext.hwctx
+ * @brief This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
  *
  */
 typedef struct AVD3D12VAFramesContext {
diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
index 42709f215e..8329e69966 100644
--- a/libavutil/hwcontext_drm.h
+++ b/libavutil/hwcontext_drm.h
@@ -152,7 +152,7 @@ typedef struct AVDRMFrameDescriptor {
 /**
  * DRM device.
  *
- * Allocated as AVHWDeviceContext.hwctx.
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx.
  */
 typedef struct AVDRMDeviceContext {
     /**
diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
index e1b79bc0de..c679c16af0 100644
--- a/libavutil/hwcontext_dxva2.h
+++ b/libavutil/hwcontext_dxva2.h
@@ -34,14 +34,14 @@
 #include <dxva2api.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVDXVA2DeviceContext {
     IDirect3DDeviceManager9 *devmgr;
 } AVDXVA2DeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVDXVA2FramesContext {
     /**
diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
index fc0263cabc..e81193247b 100644
--- a/libavutil/hwcontext_mediacodec.h
+++ b/libavutil/hwcontext_mediacodec.h
@@ -22,7 +22,7 @@
 /**
  * MediaCodec details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVMediaCodecDeviceContext {
     /**
diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
index ef54486c95..7abd97db2b 100644
--- a/libavutil/hwcontext_opencl.h
+++ b/libavutil/hwcontext_opencl.h
@@ -58,7 +58,7 @@ typedef struct AVOpenCLFrameDescriptor {
 /**
  * OpenCL device details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVOpenCLDeviceContext {
     /**
@@ -84,7 +84,7 @@ typedef struct AVOpenCLDeviceContext {
 /**
  * OpenCL-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
  */
 typedef struct AVOpenCLFramesContext {
     /**
diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
index e2dba8ad83..b63ebddaef 100644
--- a/libavutil/hwcontext_qsv.h
+++ b/libavutil/hwcontext_qsv.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVQSVDeviceContext {
     mfxSession session;
@@ -48,7 +48,7 @@ typedef struct AVQSVDeviceContext {
 } AVQSVDeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx
  */
 typedef struct AVQSVFramesContext {
     mfxFrameSurface1 *surfaces;
diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
index 0b2e071cb3..4a897eb851 100644
--- a/libavutil/hwcontext_vaapi.h
+++ b/libavutil/hwcontext_vaapi.h
@@ -63,7 +63,7 @@ enum {
 /**
  * VAAPI connection details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVVAAPIDeviceContext {
     /**
@@ -83,7 +83,7 @@ typedef struct AVVAAPIDeviceContext {
 /**
  * VAAPI-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx.
  */
 typedef struct AVVAAPIFramesContext {
     /**
@@ -105,7 +105,7 @@ typedef struct AVVAAPIFramesContext {
 /**
  * VAAPI hardware pipeline configuration details.
  *
- * Allocated with av_hwdevice_hwconfig_alloc().
+ * This struct is allocated with av_hwdevice_hwconfig_alloc().
  */
 typedef struct AVVAAPIHWConfig {
     /**
diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
index 1b7ea1e443..e305caa595 100644
--- a/libavutil/hwcontext_vdpau.h
+++ b/libavutil/hwcontext_vdpau.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * This @ref md_doc_2context "context" is allocated as AVHWDeviceContext.hwctx
  */
 typedef struct AVVDPAUDeviceContext {
     VdpDevice          device;
diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
index cbbd2390c1..1869870032 100644
--- a/libavutil/hwcontext_vulkan.h
+++ b/libavutil/hwcontext_vulkan.h
@@ -39,7 +39,7 @@ typedef struct AVVkFrame AVVkFrame;
  */
 
 /**
- * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
+ * Main Vulkan @ref md_doc_2context "context", allocated as AVHWDeviceContext.hwctx.
  * All of these can be set before init to change what the context uses
  */
 typedef struct AVVulkanDeviceContext {
@@ -172,7 +172,7 @@ typedef enum AVVkFrameFlags {
 } AVVkFrameFlags;
 
 /**
- * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
+ * This @ref md_doc_2context "context" is allocated as AVHWFramesContext.hwctx, used to set pool-specific options
  */
 typedef struct AVVulkanFramesContext {
     /**
diff --git a/libavutil/lfg.h b/libavutil/lfg.h
index e75a986f12..7f4ff5b62f 100644
--- a/libavutil/lfg.h
+++ b/libavutil/lfg.h
@@ -25,7 +25,7 @@
 #include <stdint.h>
 
 /**
- * Context structure for the Lagged Fibonacci PRNG.
+ * @ref md_doc_2context "Context" structure for the Lagged Fibonacci PRNG.
  * The exact layout, types and content of this struct may change and should
  * not be accessed directly. Only its `sizeof()` is guaranteed to stay the same
  * to allow easy instanciation.
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes
  2024-05-15 15:54 ` [FFmpeg-devel] [PATCH v4 0/4] Explain what "context" means Andrew Sayers
                     ` (2 preceding siblings ...)
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation Andrew Sayers
@ 2024-05-15 15:54   ` Andrew Sayers
  2024-05-22 10:08     ` Stefano Sabatini
  2024-05-22 15:24     ` Andreas Rheinhardt
  3 siblings, 2 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-15 15:54 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Doxygen thinks any text like "Context for foo" is a link to a struct called "Context".
Add a description and a better link, to avoid confusing readers.
---
 libavformat/async.c | 3 +++
 libavformat/cache.c | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/libavformat/async.c b/libavformat/async.c
index e096b0bc6f..3c28d418ae 100644
--- a/libavformat/async.c
+++ b/libavformat/async.c
@@ -53,6 +53,9 @@ typedef struct RingBuffer
     int           read_pos;
 } RingBuffer;
 
+/**
+ * @brief @ref md_doc_2context "Context" for testing async
+ */
 typedef struct Context {
     AVClass        *class;
     URLContext     *inner;
diff --git a/libavformat/cache.c b/libavformat/cache.c
index 5f78adba9d..3cc0edec82 100644
--- a/libavformat/cache.c
+++ b/libavformat/cache.c
@@ -52,6 +52,9 @@ typedef struct CacheEntry {
     int size;
 } CacheEntry;
 
+/**
+ * @brief @ref md_doc_2context "Context" for a cache
+ */
 typedef struct Context {
     AVClass *class;
     int fd;
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation Andrew Sayers
@ 2024-05-15 16:46     ` Lynne via ffmpeg-devel
  2024-05-16 11:25       ` Andrew Sayers
  0 siblings, 1 reply; 84+ messages in thread
From: Lynne via ffmpeg-devel @ 2024-05-15 16:46 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Lynne


[-- Attachment #1.1.1.1: Type: text/plain, Size: 2139 bytes --]

On 15/05/2024 17:54, Andrew Sayers wrote:
> Some headings needed to be rewritten to accomodate the text,
> (hopefully) without changing the meaning.
> ---
>   libavcodec/aac/aacdec.h            |  2 +-
>   libavcodec/aacenc.h                |  2 +-
>   libavcodec/ac3enc.h                |  2 +-
>   libavcodec/amfenc.h                |  2 +-
>   libavcodec/atrac.h                 |  2 +-
>   libavcodec/avcodec.h               |  3 ++-
>   libavcodec/bsf.h                   |  2 +-
>   libavcodec/cbs.h                   |  2 +-
>   libavcodec/d3d11va.h               |  3 +--
>   libavcodec/h264dsp.h               |  2 +-
>   libavcodec/h264pred.h              |  2 +-
>   libavcodec/mediacodec.h            |  2 +-
>   libavcodec/mpegaudiodec_template.c |  2 +-
>   libavcodec/pthread_frame.c         |  4 ++--
>   libavcodec/qsv.h                   |  6 ++++--
>   libavcodec/sbr.h                   |  2 +-
>   libavcodec/smacker.c               |  2 +-
>   libavcodec/vdpau.h                 |  3 ++-
>   libavcodec/videotoolbox.h          |  5 +++--
>   libavfilter/avfilter.h             |  2 +-
>   libavformat/avformat.h             |  3 ++-
>   libavformat/avio.h                 |  3 ++-
>   libavutil/audio_fifo.h             |  2 +-
>   libavutil/hwcontext.h              | 21 ++++++++++++---------
>   libavutil/hwcontext_cuda.h         |  2 +-
>   libavutil/hwcontext_d3d11va.h      |  4 ++--
>   libavutil/hwcontext_d3d12va.h      |  6 +++---
>   libavutil/hwcontext_drm.h          |  2 +-
>   libavutil/hwcontext_dxva2.h        |  4 ++--
>   libavutil/hwcontext_mediacodec.h   |  2 +-
>   libavutil/hwcontext_opencl.h       |  4 ++--
>   libavutil/hwcontext_qsv.h          |  4 ++--
>   libavutil/hwcontext_vaapi.h        |  6 +++---
>   libavutil/hwcontext_vdpau.h        |  2 +-
>   libavutil/hwcontext_vulkan.h       |  4 ++--
>   libavutil/lfg.h                    |  2 +-
>   36 files changed, 66 insertions(+), 57 deletions(-)

I still don't like this part. There's no reason to link this everywhere 
when no one will be bothered to. The document alone is enough IMO.

[-- Attachment #1.1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 637 bytes --]

[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 236 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation
  2024-05-15 16:46     ` Lynne via ffmpeg-devel
@ 2024-05-16 11:25       ` Andrew Sayers
  0 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-16 11:25 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Wed, May 15, 2024 at 06:46:19PM +0200, Lynne via ffmpeg-devel wrote:
> On 15/05/2024 17:54, Andrew Sayers wrote:
> > Some headings needed to be rewritten to accomodate the text,
> > (hopefully) without changing the meaning.
> > ---
> >   libavcodec/aac/aacdec.h            |  2 +-
> >   libavcodec/aacenc.h                |  2 +-
> >   libavcodec/ac3enc.h                |  2 +-
> >   libavcodec/amfenc.h                |  2 +-
> >   libavcodec/atrac.h                 |  2 +-
> >   libavcodec/avcodec.h               |  3 ++-
> >   libavcodec/bsf.h                   |  2 +-
> >   libavcodec/cbs.h                   |  2 +-
> >   libavcodec/d3d11va.h               |  3 +--
> >   libavcodec/h264dsp.h               |  2 +-
> >   libavcodec/h264pred.h              |  2 +-
> >   libavcodec/mediacodec.h            |  2 +-
> >   libavcodec/mpegaudiodec_template.c |  2 +-
> >   libavcodec/pthread_frame.c         |  4 ++--
> >   libavcodec/qsv.h                   |  6 ++++--
> >   libavcodec/sbr.h                   |  2 +-
> >   libavcodec/smacker.c               |  2 +-
> >   libavcodec/vdpau.h                 |  3 ++-
> >   libavcodec/videotoolbox.h          |  5 +++--
> >   libavfilter/avfilter.h             |  2 +-
> >   libavformat/avformat.h             |  3 ++-
> >   libavformat/avio.h                 |  3 ++-
> >   libavutil/audio_fifo.h             |  2 +-
> >   libavutil/hwcontext.h              | 21 ++++++++++++---------
> >   libavutil/hwcontext_cuda.h         |  2 +-
> >   libavutil/hwcontext_d3d11va.h      |  4 ++--
> >   libavutil/hwcontext_d3d12va.h      |  6 +++---
> >   libavutil/hwcontext_drm.h          |  2 +-
> >   libavutil/hwcontext_dxva2.h        |  4 ++--
> >   libavutil/hwcontext_mediacodec.h   |  2 +-
> >   libavutil/hwcontext_opencl.h       |  4 ++--
> >   libavutil/hwcontext_qsv.h          |  4 ++--
> >   libavutil/hwcontext_vaapi.h        |  6 +++---
> >   libavutil/hwcontext_vdpau.h        |  2 +-
> >   libavutil/hwcontext_vulkan.h       |  4 ++--
> >   libavutil/lfg.h                    |  2 +-
> >   36 files changed, 66 insertions(+), 57 deletions(-)
> 
> I still don't like this part. There's no reason to link this everywhere when
> no one will be bothered to. The document alone is enough IMO.

Readers who don't already know the word "context" need a sign that it's a word
they need to pay attention to.  For example, I come from an OOP background
where the word "object" is used so widely, it simply never comes up.

In fact, I'm probably not the only person who followed the link to AVClass
instead, which just makes FFmpeg look like a failed attempt at OOP if you don't
know about contexts.

Linking widely lets an attentive reader see this *before* they get the wrong
end of the stick, and gives an overwhelmed newbie enough hints that this is a
word they need to pay attention to.

To underline the previous point - an attentive reader could probably make do
with e.g. just links from AVClass and a handful of the most popular contexts.
But newbies are often inefficient learners who need many reminders before
they stop paying attention to random things.  So linking as widely as possible
makes the project more accessible to people with less experience.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 1/4] doc: " Andrew Sayers
@ 2024-05-22  9:31     ` Stefano Sabatini
  2024-05-22 16:07       ` Andrew Sayers
  2024-05-23 20:00       ` [FFmpeg-devel] [PATCH v5 0/4] " Andrew Sayers
  0 siblings, 2 replies; 84+ messages in thread
From: Stefano Sabatini @ 2024-05-22  9:31 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andrew Sayers

Sorry for the slow reply.

On date Wednesday 2024-05-15 16:54:19 +0100, Andrew Sayers wrote:
> Derived from detailed explanations kindly provided by Stefano Sabatini:
> https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
> ---
>  doc/context.md | 394 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 394 insertions(+)
>  create mode 100644 doc/context.md
> 
> diff --git a/doc/context.md b/doc/context.md
> new file mode 100644
> index 0000000000..fb85b3f366
> --- /dev/null
> +++ b/doc/context.md
> @@ -0,0 +1,394 @@
> +# Introduction to contexts
> +
> +&ldquo;%Context&rdquo;

Is this style of quoting needed? Especially I'd avoid special markup
to simplify unredendered text reading (which is the point of markdown
afterall).

> is a name for a widely-used programming idiom.

> +This document explains the general idiom and the conventions FFmpeg has built around it.
> +
> +This document uses object-oriented analogies to help readers familiar with
> +[object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming)
> +learn about contexts.  But contexts can also be used outside of OOP,
> +and even in situations where OOP isn't helpful.  So these analogies
> +should only be used as a first step towards understanding contexts.
> +
> +## &ldquo;Context&rdquo; as a way to think about code
> +
> +A context is any data structure that is passed to several functions
> +(or several instances of the same function) that all operate on the same entity.
> +For example, [object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming)
> +languages usually provide member functions with a `this` or `self` value:
> +

> +```c
> +class my_cxx_class {
> +  void my_member_function() {
> +    // the implicit object parameter provides context for the member function:
> +    std::cout << this;
> +  }
> +};
> +```

I'm not convinced this is really useful: if you know C++ this is
redundant, if you don't this is confusing and don't add much information.

> +
> +Contexts are a fundamental building block of OOP, but can also be used in procedural code.

I'd drop this line, and drop the anchor on OOP at the same time since
it's adding no much information.

> +For example, most callback functions can be understood to use contexts:

> +
> +```c
> +struct MyStruct {
> +  int counter;
> +};
> +
> +void my_callback( void *my_var_ ) {
> +  // my_var provides context for the callback function:
> +  struct MyStruct *my_var = (struct MyStruct *)my_var_;
> +  printf("Called %d time(s)", ++my_var->counter);
> +}
> +
> +void init() {
> +  struct MyStruct my_var;
> +  my_var.counter = 0;
> +  register_callback( my_callback, &my_var );

style: fun(my_callback, ...) (so spaces around parentheses) here and
below

> +}
> +```
> +
> +In the broadest sense, &ldquo;context&rdquo; is just a way to think about code.
> +You can even use it to think about code written by people who have never
> +heard the term, or who would disagree with you about what it means.
> +
> +## &ldquo;Context&rdquo; as a tool of communication
> +
> +&ldquo;%Context&ldquo; can just be a word to understand code in your own head,
> +but it can also be a term you use to explain your interfaces.
> +Here is a version of the callback example that makes the context explicit:
> +
> +```c
> +struct CallbackContext {
> +  int counter;
> +};
> +
> +void my_callback( void *ctx_ ) {
> +  // ctx provides context for the callback function:
> +  struct CallbackContext *ctx = (struct CallbackContext *)ctx_;
> +  printf("Called %d time(s)", ++ctx->counter);
> +}
> +
> +void init() {
> +  struct CallbackContext ctx;
> +  ctx.counter = 0;
> +  register_callback( my_callback, &ctx );
> +}
> +```
> +
> +The difference here is subtle, but important.  If a piece of code
> +*appears compatible with contexts*, then you are *allowed to think
> +that way*, but if a piece of code *explicitly states it uses
> +contexts*, then you are *required to follow that approach*.
> +

> +For example, imagine someone modified `MyStruct` in the earlier example
> +to count several unrelated events across the whole program.  That would mean
> +it contained information about multiple entities, so was not a context.
> +But nobody ever *said* it was a context, so that isn't necessarily wrong.
> +However, proposing the same change to the `CallbackContext` in the later example
> +would violate a guarantee, and should be pointed out in a code review.
> +

I'm not very convinced by the callback example. The use of contexts in
the FFmpeg API is very much simpler, it is used to keep track of
configuration and state (that is they track the "object" where to
operate on), so the callback example here is a bit misleading.

Callbacks are used in the internals to implement different elements
(codecs, protocols, filters, etc...) implementing a common API, but in
this case the relation with "contexts" is less straightforward.

> +@warning Guaranteeing to use contexts does not mean guaranteeing to use
> +object-oriented programming.  For example, FFmpeg creates its contexts
> +procedurally instead of with constructors.

I'm afraid this is more confusing than helpful, since the FFmpeg API
is not OOP. I'd drop this sentence.

> +
> +## Contexts in the real world
> +
> +To understand how contexts are used in the real world, it might be
> +useful to compare [curl's MD5 hash context](https://github.com/curl/curl/blob/bbeeccdea8507ff50efca70a0b33d28aef720267/lib/curl_md5.h#L48)
> +with @ref AVMD5 "FFmpeg's equivalent context".
> +

> +The [MD5 algorithm](https://en.wikipedia.org/wiki/MD5) produces
> +a fixed-length digest from arbitrary-length data.  It does this by calculating
> +the digest for a prefix of the data, then loading the next part and adding it
> +to the previous digest, and so on.  Projects that use MD5 generally use some
> +kind of context, so comparing them can reveal differences between projects.
> +
> +```c
> +// Curl's MD5 context looks like this:
> +struct MD5_context {
> +  const struct MD5_params *md5_hash;    /* Hash function definition */
> +  void                  *md5_hashctx;   /* Hash function context */
> +};
> +
> +// FFmpeg's MD5 context looks like this:
> +typedef struct AVMD5 {
> +    uint64_t len;
> +    uint8_t  block[64];
> +    uint32_t ABCD[4];
> +} AVMD5;
> +```
> +
> +Curl's struct name ends with `_context`, guaranteeing contexts are the correct
> +interpretation.  FFmpeg's struct does not explicitly say it's a context, but
> +@ref libavutil/md5.c "its functions do" so we can reasonably assume
> +it's the intended interpretation.
> +
> +Curl's struct uses `void *md5_hashctx` to avoid guaranteeing
> +implementation details in the public interface, whereas FFmpeg makes
> +everything accessible.  This kind of data hiding is an advanced context-oriented
> +convention, and is discussed below.  Using it in this case has strengths and
> +weaknesses.  On one hand, it means changing the layout in a future version
> +of curl won't break downstream programs that used that data.  On the other hand,
> +the MD5 algorithm has been stable for 30 years, so it's arguably more important
> +to let people dig in when debugging their own code.
> +
> +Curl's struct is declared as `struct <type> { ... }`, whereas FFmpeg uses
> +`typedef struct <type> { ... } <type>`.  These conventions are used with both
> +context and non-context structs, so don't say anything about contexts as such.
> +Specifically, FFmpeg's convention is a workaround for an issue with C grammar:
> +
> +```c
> +void my_function( ... ) {
> +  int                my_var;        // good
> +  MD5_context        my_curl_ctx;   // error: C needs you to explicitly say "struct"
> +  struct MD5_context my_curl_ctx;   // good: added "struct"
> +  AVMD5              my_ffmpeg_ctx; // good: typedef's avoid the need for "struct"
> +}
> +```
> +
> +Both MD5 implementations are long-tested, widely-used examples of contexts
> +in the real world.  They show how contexts can solve the same problem
> +in different ways.

I'm concerned that this is adding more information than really
needed. Especially comparing with internals of curl means that now the
docs needs to be kept in synch also with the curl's API, meaning that
it will be outdated very soon. I'd rather drop the curl comparison
altogether.

> +
> +## FFmpeg's advanced context-oriented conventions
> +
> +Projects that make heavy use of contexts tend to develop conventions
> +to make them more useful.  This section discusses conventions used in FFmpeg,
> +some of which are used in other projects, others are unique to this project.
> +
> +### Naming: &ldquo;Context&rdquo; and &ldquo;ctx&rdquo;
> +
> +```c
> +// Context struct names usually end with `Context`:
> +struct AVSomeContext {
> +  ...
> +};
> +
> +// Functions are usually named after their context,
> +// context parameters usually come first and are often called `ctx`:
> +void av_some_function( AVSomeContext *ctx, ... );
> +```
> +
> +If an FFmpeg struct is intended for use as a context, its name usually
> +makes that clear.  Exceptions to this rule include AVMD5 (discussed above),
> +which is only identified as a context by the functions that call it.
> +
> +If a function is associated with a context, its name usually
> +begins with some variant of the context name (e.g. av_md5_alloc()
> +or avcodec_alloc_context3()).  Exceptions to this rule include
> +@ref avformat.h "AVFormatContext's functions", many of which
> +begin with just `av_`.
> +
> +If a function has a context parameter, it usually comes first and its name
> +often contains `ctx`.  Exceptions include av_bsf_alloc(), which puts the
> +context argument second to emphasise it's an out variable.
> +
> +### Data hiding: private contexts
> +
> +```c
> +// Context structs often hide private context:
> +struct AVSomeContext {
> +  void *priv_data; // sometimes just called "internal"
> +};
> +```
> +
> +Contexts usually present a public interface, so changing a context's members
> +forces everyone that uses the library to at least recompile their program,
> +if not rewrite it to remain compatible.  Hiding information in a private context
> +ensures it can be modified without affecting downstream software.
> +
> +Object-oriented programmers may be tempted to compare private contexts to
> +*private class members*.  That's often accurate, but for example it can also
> +be used like a *virtual function table* - a list of functions that are
> +guaranteed to exist, but may be implemented differently for different
> +sub-classes.  When thinking about private contexts, remember that FFmpeg
> +isn't *large enough* to need some common OOP techniques, even though it's
> +solving a problem that's *complex enough* to benefit from some rarer techniques.
> +
> +### Manage lifetime: allocate, initialize and free
> +
> +```c
> +void my_function( ... ) {
> +
> +    // Context structs are allocated then initialized with associated functions:
> +
> +    AVSomeContext *ctx = av_some_context_alloc( ... );
> +
> +    // ... configure ctx ...
> +
> +    av_some_context_init( ctx, ... );
> +
> +    // ... use ctx ...
> +
> +    // Context structs are freed with associated functions:
> +
> +    av_some_context_free( ctx );
> +
> +}
> +```
> +
> +FFmpeg contexts go through the following stages of life:
> +
> +1. allocation (often a function that ends with `_alloc`)
> +   * a range of memory is allocated for use by the structure
> +   * memory is allocated on boundaries that improve caching
> +   * memory is reset to zeroes, some internal structures may be initialized
> +2. configuration (implemented by setting values directly on the object)
> +   * no function for this - calling code populates the structure directly
> +   * memory is populated with useful values
> +   * simple contexts can skip this stage
> +3. initialization (often a function that ends with `_init`)
> +   * setup actions are performed based on the configuration (e.g. opening files)
> +5. normal usage
> +   * most functions are called in this stage
> +   * documentation implies some members are now read-only (or not used at all)
> +   * some contexts allow re-initialization
> +6. closing (often a function that ends with `_close()`)
> +   * teardown actions are performed (e.g. closing files)
> +7. deallocation (often a function that ends with `_free()`)
> +   * memory is returned to the pool of available memory
> +
> +This can mislead object-oriented programmers, who expect something more like:
> +
> +1. allocation (usually a `new` keyword)
> +   * a range of memory is allocated for use by the structure
> +   * memory *may* be reset (e.g. for security reasons)
> +2. initialization (usually a constructor)
> +   * memory is populated with useful values
> +   * related setup actions are performed based on arguments (e.g. opening files)
> +3. normal usage
> +   * most functions are called in this stage
> +   * compiler enforces that some members are read-only (or private)
> +   * no going back to the previous stage
> +4. finalization (usually a destructor)
> +   * teardown actions are performed (e.g. closing files)
> +5. deallocation (usually a `delete` keyword)
> +   * memory is returned to the pool of available memory
> +
> +FFmpeg's allocation stage is broadly similar to OOP, but can do some higher-level
> +operations.  For example, AVOptions-enabled structs (discussed below) contain an
> +AVClass member that is set during allocation.
> +
> +FFmpeg's "configuration" and "initialization" stages combine to resemble OOP's
> +"initialization" stage.  This can mislead object-oriented developers,
> +who are used to doing both at once.  This means FFmpeg contexts don't have
> +a direct equivalent of OOP constructors, as they would be doing
> +two jobs in one function.
> +
> +FFmpeg's three-stage creation process is useful for complicated structures.
> +For example, AVCodecContext contains many members that *can* be set before
> +initialization, but in practice most programs set few if any of them.
> +Implementing this with a constructor would involve a function with a list
> +of arguments that was extremely long and changed whenever the struct was
> +updated.  For contexts that don't need the extra flexibility, FFmpeg usually
> +provides a combined allocator and initializer function.  For historical reasons,
> +suffixes like `_alloc`, `_init`, `_alloc_context` and even `_open` can indicate
> +the function does any combination of allocation and initialization.
> +
> +FFmpeg's "closing" stage is broadly similar to OOP's "finalization" stage,
> +but some contexts allow re-initialization after finalization.  For example,
> +SwrContext lets you call swr_close() then swr_init() to reuse a context.
> +
> +FFmpeg's "deallocation" stage is broadly similar to OOP, but can perform some
> +higher-level functions (similar to the allocation stage).
> +
> +Very few contexts need the flexibility of separate "closing" and
> +"deallocation" stages, so these are usually combined into a single function.
> +Closing functions usually end with "_close", while deallocation
> +functions usually end with "_free".
> +
> +### Reflection: AVOptions-enabled structs
> +
> +Object-oriented programming puts more focus on data hiding than FFmpeg needs,
> +but it also puts less focus on
> +[reflection](https://en.wikipedia.org/wiki/Reflection_(computer_programming)).
> +
> +To understand FFmpeg's reflection requirements, run `ffmpeg -h full` on the
> +command-line, then ask yourself how you would implement all those options
> +with the C standard [`getopt` function](https://en.wikipedia.org/wiki/Getopt).
> +You can also ask the same question for any other programming languages you know.
> +[Python's argparse module](https://docs.python.org/3/library/argparse.html)
> +is a good example - its approach works well with far more complex programs
> +than `getopt`, but would you like to maintain an argparse implementation
> +with 15,000 options and growing?
> +
> +Most solutions assume you can just put all options in a single block,
> +which is unworkable at FFmpeg's scale.  Instead, we split configuration
> +across many *AVOptions-enabled structs*, which use the @ref avoptions
> +"AVOptions API" to reflect information about their user-configurable members,
> +including members in private contexts.
> +
> +An *AVOptions-enabled struct* is a struct that contains an AVClass element as
> +its first member, and uses that element to provide access to instances of
> +AVOption, each of which provides information about a single option.
> +The AVClass can also include more @ref AVClass "AVClasses" for private contexts,
> +making it possible to set options through the API that aren't
> +accessible directly.
> +
> +AVOptions-accessible members of a context should be accessed through the
> +AVOptions API whenever possible, even if they're not hidden away in a private
> +context.  That ensures values are validated as they're set, and means you won't
> +have to do as much work if a future version of FFmpeg changes the layout.
> +
> +AVClass was created very early in FFmpeg's history, long before AVOptions.
> +Its name suggests some kind of relationship to an OOP
> +base [class](https://en.wikipedia.org/wiki/Class_(computer_programming)),
> +but the name has become less accurate as FFmpeg evolved, to the point where
> +AVClass and AVOption are largely synonymous in modern usage.  The difference
> +might still matter if you need to support old versions of FFmpeg,
> +where you might find *AVClass context structures* (contain an AVClass element
> +as their first member) that are not *AVOptions-enabled* (don't use that element
> +to provide access to instances of AVOption).
> +
> +Object-oriented programmers may be tempted to compare @ref avoptions "AVOptions"
> +to OOP getters and setters.  There is some overlap in functionality, but OOP
> +getters and setters are usually specific to a single member and don't provide
> +metadata about the member; whereas AVOptions has a single API that covers
> +every option, and provides help text etc. as well.
> +
> +Object-oriented programmers may be tempted to compare AVOptions-accessible
> +members of a public context to protected members of a class.  Both provide
> +global access through an API, and unrestricted access for trusted friends.
> +But this is just a happy accident, not a guarantee.

This part looks fine, although there is too much OOP jargon for my
taste: this would make reading for programmers not familiar with OOP
harder than needed since she will miss many references.

> +
> +## Final example: context for a codec
> +
> +AVCodecContext is an AVOptions-enabled struct that contains information
> +about encoding or decoding one stream of data (e.g. the video in a movie).
> +It's a good example of many of the issues above.
> +
> +The name "AVCodecContext" tells us this is a context.  Many of
> +@ref libavcodec/avcodec.h "its functions" start with an `avctx` parameter,
> +indicating this object provides context for that function.
> +
> +AVCodecContext::internal contains the private context.  For example,
> +codec-specific information might be stored here.
> +
> +AVCodecContext is allocated with avcodec_alloc_context3(), initialized with
> +avcodec_open2(), and freed with avcodec_free_context().  Most of its members
> +are configured with the @ref avoptions "AVOptions API", but for example you
> +can set AVCodecContext::opaque or AVCodecContext::draw_horiz_band() if your
> +program happens to need them.
> +
> +AVCodecContext provides an abstract interface to many different *codecs*.
> +Options supported by many codecs (e.g. "bitrate") are kept in AVCodecContext
> +and reflected as AVOptions.  Options that are specific to one codec are
> +stored in the internal context, and reflected from there.
> +
> +To support a specific codec, AVCodecContext's private context is set to
> +an encoder-specific data type.  For example, the video codec
> +[H.264](https://en.wikipedia.org/wiki/Advanced_Video_Coding) is supported via
> +[the x264 library](https://www.videolan.org/developers/x264.html), and
> +implemented in X264Context.

> Although included in the documentation, X264Context is not part of the public API.

Why included in the doc? That is a private struct and therefore should
not be included in the doxy.

> +[...] Whereas there are strict rules about
> +changing AVCodecContext, a version of FFmpeg could modify X264Context or
> +replace it with another type altogether.  An adverse legal ruling or security
> +problem could even force us to switch to a completely different library
> +without a major version bump.
> +
> +The design of AVCodecContext provides several important guarantees:
> +
> +- lets you use the same interface for any codec
> +- supports common encoder options like "bitrate" without duplicating code
> +- supports encoder-specific options like "profile" without bulking out the public interface
> +- reflects both types of options to users, with help text and detection of missing options
> +- hides implementation details (e.g. its encoding buffer)
> -- 
> 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".
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 2/4] lavu: Clarify relationship between AVClass, AVOption and context
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
@ 2024-05-22 10:04     ` Stefano Sabatini
  0 siblings, 0 replies; 84+ messages in thread
From: Stefano Sabatini @ 2024-05-22 10:04 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andrew Sayers

On date Wednesday 2024-05-15 16:54:20 +0100, Andrew Sayers wrote:
> ---
>  libavutil/log.h | 11 ++++++++---
>  libavutil/opt.h |  7 ++++---
>  2 files changed, 12 insertions(+), 6 deletions(-)
> 
> diff --git a/libavutil/log.h b/libavutil/log.h
> index ab7ceabe22..cfbf416679 100644
> --- a/libavutil/log.h
> +++ b/libavutil/log.h
> @@ -59,9 +59,14 @@ typedef enum {
>  struct AVOptionRanges;
>  
>  /**
> - * Describe the class of an AVClass context structure. That is an
> - * arbitrary struct of which the first field is a pointer to an
> - * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.).

> + * Metadata about an arbitrary data structure

The previous definition was circular, while this one is lacking
information (for example it is neglecting the logging facilities
provided by AVClass).

My take:
Provide access to generic logging and introspection facilities, used to
describe a class of structs.

An AVClass should be defined as the first element of the struct using
the AVClass facilities, so that functions operating on the AVClass
will work by providing the pointer to the structure.

Note: we might move the AVClass definition to its own file class.h.

> + *
> + * A @ref md_doc_2context "context struct" whose first member is a pointer
> + * to an AVClass object is called an "AVClass context structure"
> + * (e.g. AVCodecContext, AVFormatContext etc.).
> + *
> + * AVClass is often combined with @ref avoptions "AVOptions" to create
> + * "AVOptions-enabled structs" that can be easily configured by users.
>   */

>  typedef struct AVClass {
>      /**
> diff --git a/libavutil/opt.h b/libavutil/opt.h
> index 07e27a9208..e314e134c2 100644
> --- a/libavutil/opt.h
> +++ b/libavutil/opt.h
> @@ -39,9 +39,10 @@
>   * @defgroup avoptions AVOptions
>   * @ingroup lavu_data
>   * @{

> - * AVOptions provide a generic system to declare options on arbitrary structs
> - * ("objects").

This should be kept. In addition you can mention that it requires the
first element of the struct to be an AVClass (which is already
mentioned later in the text).

> An option can have a help text, a type and a range of possible
> - * values. Options may then be enumerated, read and written to.

> + * Builds on AVClass, adding a generic system to declare options.

> + *
> + * An option can have a help text, a type and a range of possible values.
> + * Options may then be enumerated, read and written to.
>   *
>   * There are two modes of access to members of AVOption and its child structs.
>   * One is called 'native access', and refers to access from the code that

[...]
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes Andrew Sayers
@ 2024-05-22 10:08     ` Stefano Sabatini
  2024-05-22 14:47       ` Andrew Sayers
  2024-05-22 15:24     ` Andreas Rheinhardt
  1 sibling, 1 reply; 84+ messages in thread
From: Stefano Sabatini @ 2024-05-22 10:08 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andrew Sayers

On date Wednesday 2024-05-15 16:54:22 +0100, Andrew Sayers wrote:
> Doxygen thinks any text like "Context for foo" is a link to a struct called "Context".
> Add a description and a better link, to avoid confusing readers.
> ---
>  libavformat/async.c | 3 +++
>  libavformat/cache.c | 3 +++
>  2 files changed, 6 insertions(+)
> 
> diff --git a/libavformat/async.c b/libavformat/async.c
> index e096b0bc6f..3c28d418ae 100644
> --- a/libavformat/async.c
> +++ b/libavformat/async.c
> @@ -53,6 +53,9 @@ typedef struct RingBuffer
>      int           read_pos;
>  } RingBuffer;
>  
> +/**
> + * @brief @ref md_doc_2context "Context" for testing async
> + */
>  typedef struct Context {
>      AVClass        *class;
>      URLContext     *inner;
> diff --git a/libavformat/cache.c b/libavformat/cache.c
> index 5f78adba9d..3cc0edec82 100644
> --- a/libavformat/cache.c
> +++ b/libavformat/cache.c
> @@ -52,6 +52,9 @@ typedef struct CacheEntry {
>      int size;
>  } CacheEntry;
>  
> +/**
> + * @brief @ref md_doc_2context "Context" for a cache
> + */
>  typedef struct Context {
>      AVClass *class;
>      int fd;

Not sure, these are private structs and we enforce no use of internal
markup for those, and we can assume internals developers are already
acquainted with contexts and such so this is probably adding no value.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means
  2024-05-05 21:04                     ` Andrew Sayers
@ 2024-05-22 10:37                       ` Stefano Sabatini
  2024-05-22 12:47                         ` Andrew Sayers
  0 siblings, 1 reply; 84+ messages in thread
From: Stefano Sabatini @ 2024-05-22 10:37 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On date Sunday 2024-05-05 22:04:36 +0100, Andrew Sayers wrote:
> I'm still travelling, so the following thoughts might be a bit
> half-formed.  But I wanted to get some feedback before sitting down
> for a proper think.
[...]
> > > I've also gone through the code looking for edge cases we haven't covered.
> > > Here are some questions trying to prompt an "oh yeah I forgot to mention
> > > that"-type answer.  Anything where the answer is more like "that should
> > > probably be rewritten to be clearer", let me know and I'll avoid confusing
> > > newbies with it.
> > > 
> > 
> > > av_ambient_viewing_environment_create_side_data() takes an AVFrame as its
> > > first argument, and returns a new AVAmbientViewingEnvironment.  What is the
> > > context object for that function - AVFrame or AVAmbientViewingEnvironment?
> > 
> > But this should be clear from the doxy:
> > 
> > /**
> >  * Allocate and add an AVAmbientViewingEnvironment structure to an existing
> >  * AVFrame as side data.
> >  *
> >  * @return the newly allocated struct, or NULL on failure
> >  */
> > AVAmbientViewingEnvironment *av_ambient_viewing_environment_create_side_data(AVFrame *frame);
> 
> I'm afraid it's not clear, at least to me.  I think you're saying the
> AVFrame is the context because a "create" function can't have a
> context any more than a C++ "new" can be called as a member.  But the
> function's prefix points to the other conclusion, and neither signal
> is clear enough on its own.

No, what I'm saying is that in some cases you don't need to think in
terms of contexts, in this case there is no context at all, the
function takes a frame and modify it, and returns the ambient
environment to be used by the following functions. This should be very
clear by reading the doxy. There is no rule dictating the first param
of each FFmpeg function should be a "context".

> 
> My current thinking is to propose separate patches renaming arguments
> to `ctx` whenever I find functions I can't parse.  That's not as good
> as a simple rule like "the first argument is always the context", but
> better than adding a paragraph or two about how to read the docs.

There cannot be such rule, because it would be false in many cases.

> > Also, you are assuming that all the function should have a
> > context. That's not the case, as you don't always need to keep track
> > of a "context" when performing operations.
> 
[...]
> > > av_channel_description_bprint() takes a `struct AVBPrint *` as its first
> > > argument, then `enum AVChannel`.  Is the context AVBPrint, AVChannel,
> > > or both?  Does it make sense for a function to have two contexts?
> > 
> > Again, this should be clear from the doxy:
> > /**
> >  * Get a human readable string describing a given channel.
> >  *
> >  * @param buf pre-allocated buffer where to put the generated string
> >  * @param buf_size size in bytes of the buffer.
> >  * @param channel the AVChannel whose description to get
> >  * @return amount of bytes needed to hold the output string, or a negative AVERROR
> >  *         on failure. If the returned value is bigger than buf_size, then the
> >  *         string was truncated.
> >  */
> > int av_channel_description(char *buf, size_t buf_size, enum AVChannel channel);
> > 
> > /**
> >  * bprint variant of av_channel_description().
> >  *
> >  * @note the string will be appended to the bprint buffer.
> >  */
> > void av_channel_description_bprint(struct AVBPrint *bp, enum AVChannel channel_id);
> 

> I think you're saying that I should look at which word appears more
> often in the doxy ("channel") rather than which word appears first in
> the argument list ("buf")?  As above, the solution might be to rename
> the variable in a separate patch rather than teach people another
> special case.

This is more about the semantics described in English language by the
doxy (which is normative). Again, thinking in terms of "contexts" is
misleading in this case.

In this case you have two functions, av_channel_description writing a
string to a buffer with fixed size, the second modifying an "AVBPrint"
struct, which is a high-level buffer providing more flexibility (and
"bprint" is used as a verb in the doxy, which might be misleading).

Note that both signatures are mimicing the standard C library
convention:
memcpy(dst, dst_size, src)

which in turn is a mnemonics for:
dst = src

meaning that we are copying data from src to dst.

You might think that in fact you are operating on a context (the dst
buffer or the AVBPrint struct), but you don't need to introduce the
concept of context for these simple functions.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means
  2024-05-22 10:37                       ` Stefano Sabatini
@ 2024-05-22 12:47                         ` Andrew Sayers
  2024-05-25  9:00                           ` Stefano Sabatini
  0 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-05-22 12:47 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Wed, May 22, 2024 at 12:37:37PM +0200, Stefano Sabatini wrote:
> On date Sunday 2024-05-05 22:04:36 +0100, Andrew Sayers wrote:
> > I'm still travelling, so the following thoughts might be a bit
> > half-formed.  But I wanted to get some feedback before sitting down
> > for a proper think.
> [...]
> > > > I've also gone through the code looking for edge cases we haven't covered.
> > > > Here are some questions trying to prompt an "oh yeah I forgot to mention
> > > > that"-type answer.  Anything where the answer is more like "that should
> > > > probably be rewritten to be clearer", let me know and I'll avoid confusing
> > > > newbies with it.
> > > > 
> > > 
> > > > av_ambient_viewing_environment_create_side_data() takes an AVFrame as its
> > > > first argument, and returns a new AVAmbientViewingEnvironment.  What is the
> > > > context object for that function - AVFrame or AVAmbientViewingEnvironment?
> > > 
> > > But this should be clear from the doxy:
> > > 
> > > /**
> > >  * Allocate and add an AVAmbientViewingEnvironment structure to an existing
> > >  * AVFrame as side data.
> > >  *
> > >  * @return the newly allocated struct, or NULL on failure
> > >  */
> > > AVAmbientViewingEnvironment *av_ambient_viewing_environment_create_side_data(AVFrame *frame);
> > 
> > I'm afraid it's not clear, at least to me.  I think you're saying the
> > AVFrame is the context because a "create" function can't have a
> > context any more than a C++ "new" can be called as a member.  But the
> > function's prefix points to the other conclusion, and neither signal
> > is clear enough on its own.
> 
> No, what I'm saying is that in some cases you don't need to think in
> terms of contexts, in this case there is no context at all, the
> function takes a frame and modify it, and returns the ambient
> environment to be used by the following functions. This should be very
> clear by reading the doxy. There is no rule dictating the first param
> of each FFmpeg function should be a "context".

I'm still writing up a reply to your longer feedback, but on this topic...

This function is in the "av_ambient_viewing_environment" namespace, and returns
an object that is clearly used as a context for other functions.  So saying
"stop thinking about contexts" just leaves a negative space and a bad thing
to fill it with (confusion in my case).

I've found it useful to think about "receiving" vs. "producing" a context:

* avcodec_alloc_context3() produces a context, but does not receive one
* sws_init_context() receives a context, but does not produce one
* av_ambient_viewing_environment_create_side_data() receives one context,
  and produces another

How about if the document mostly talks about functions as having contexts,
then follows it up with something like:

    There are some edge cases where this doesn't work.  <examples>.
    If you find contexts a useful metaphor in these cases, you might
    prefer to think about them as "receiving" and "producing" contexts.

... or something similar that acknowledges contexts are unnecessary here,
but provides a solution for people that want to use them anyway.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes
  2024-05-22 10:08     ` Stefano Sabatini
@ 2024-05-22 14:47       ` Andrew Sayers
  0 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-22 14:47 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Wed, May 22, 2024 at 12:08:29PM +0200, Stefano Sabatini wrote:
> On date Wednesday 2024-05-15 16:54:22 +0100, Andrew Sayers wrote:
> > Doxygen thinks any text like "Context for foo" is a link to a struct called "Context".
> > Add a description and a better link, to avoid confusing readers.
> > ---
> >  libavformat/async.c | 3 +++
> >  libavformat/cache.c | 3 +++
> >  2 files changed, 6 insertions(+)
> > 
> > diff --git a/libavformat/async.c b/libavformat/async.c
> > index e096b0bc6f..3c28d418ae 100644
> > --- a/libavformat/async.c
> > +++ b/libavformat/async.c
> > @@ -53,6 +53,9 @@ typedef struct RingBuffer
> >      int           read_pos;
> >  } RingBuffer;
> >  
> > +/**
> > + * @brief @ref md_doc_2context "Context" for testing async
> > + */
> >  typedef struct Context {
> >      AVClass        *class;
> >      URLContext     *inner;
> > diff --git a/libavformat/cache.c b/libavformat/cache.c
> > index 5f78adba9d..3cc0edec82 100644
> > --- a/libavformat/cache.c
> > +++ b/libavformat/cache.c
> > @@ -52,6 +52,9 @@ typedef struct CacheEntry {
> >      int size;
> >  } CacheEntry;
> >  
> > +/**
> > + * @brief @ref md_doc_2context "Context" for a cache
> > + */
> >  typedef struct Context {
> >      AVClass *class;
> >      int fd;
> 
> Not sure, these are private structs and we enforce no use of internal
> markup for those, and we can assume internals developers are already
> acquainted with contexts and such so this is probably adding no value.

Ah, yeah the use case isn't obvious if you haven't tripped over it...

Imagine you're a new user trying to learn FFmpeg, and you find yourself at
https://ffmpeg.org/doxygen/trunk/structAVAudioFifo.html - the first word
appears to be a link for this "context" thing you've been hearing about[1],
so you drop what you're doing to investigate.  It links you to a struct that
looks promisingly general, but eventually turns out to be some random internal
struct with a misleading name.  Now you've wasted a bunch of time and forgotten
what you were doing.

The other patch fixes the examples I've found in the code, but doxygen links
all instances of the word "Context" to this struct, confusing newbies.  This
patch ensures that when future developers say "Context" in a comment, the page
doxygen links them to will point them in the right direction.

I had previously assumed it was a deliberate decision to include private files
in the documentation, so I didn't look that carefully into workarounds that
would break links to these private structures.  But you've implied elsewhere
that's not the case, so is it worth looking into solutions that made "Context"
link to the context document, at the cost of making it impossible to link to
these private structs at all?

[1] to be clear, this is the current behaviour of the page on the live site
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes
  2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes Andrew Sayers
  2024-05-22 10:08     ` Stefano Sabatini
@ 2024-05-22 15:24     ` Andreas Rheinhardt
  2024-05-22 16:54       ` Andrew Sayers
  1 sibling, 1 reply; 84+ messages in thread
From: Andreas Rheinhardt @ 2024-05-22 15:24 UTC (permalink / raw)
  To: ffmpeg-devel

Andrew Sayers:
> Doxygen thinks any text like "Context for foo" is a link to a struct called "Context".
> Add a description and a better link, to avoid confusing readers.
> ---
>  libavformat/async.c | 3 +++
>  libavformat/cache.c | 3 +++
>  2 files changed, 6 insertions(+)
> 
> diff --git a/libavformat/async.c b/libavformat/async.c
> index e096b0bc6f..3c28d418ae 100644
> --- a/libavformat/async.c
> +++ b/libavformat/async.c
> @@ -53,6 +53,9 @@ typedef struct RingBuffer
>      int           read_pos;
>  } RingBuffer;
>  
> +/**
> + * @brief @ref md_doc_2context "Context" for testing async
> + */
>  typedef struct Context {
>      AVClass        *class;
>      URLContext     *inner;
> diff --git a/libavformat/cache.c b/libavformat/cache.c
> index 5f78adba9d..3cc0edec82 100644
> --- a/libavformat/cache.c
> +++ b/libavformat/cache.c
> @@ -52,6 +52,9 @@ typedef struct CacheEntry {
>      int size;
>  } CacheEntry;
>  
> +/**
> + * @brief @ref md_doc_2context "Context" for a cache
> + */
>  typedef struct Context {
>      AVClass *class;
>      int fd;

These structures should be renamed instead of adding these comments
(which are pointless for internal developers). I just sent a patch for that.
Thanks for pointing out the issue.

- Andreas

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-05-22  9:31     ` Stefano Sabatini
@ 2024-05-22 16:07       ` Andrew Sayers
  2024-05-25  9:49         ` Stefano Sabatini
  2024-05-23 20:00       ` [FFmpeg-devel] [PATCH v5 0/4] " Andrew Sayers
  1 sibling, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-05-22 16:07 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Wed, May 22, 2024 at 11:31:52AM +0200, Stefano Sabatini wrote:
> Sorry for the slow reply.

Welcome back :)

I've gathered some critiques of my own over the past week, which I'll pepper
throughout the reply.  Starting with...

The document assumes (or is at least designed to be secure against) readers
starting at the top and reading through to the bottom.  I found doxygen's
@tableofcontents command while writing this e-mail, which I will definitely
use in the next version, and which might provoke a rewrite aimed at people
jumping around the document looking for answers to specific questions.

> 
> On date Wednesday 2024-05-15 16:54:19 +0100, Andrew Sayers wrote:
> > Derived from detailed explanations kindly provided by Stefano Sabatini:
> > https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
> > ---
> >  doc/context.md | 394 +++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 394 insertions(+)
> >  create mode 100644 doc/context.md
> > 
> > diff --git a/doc/context.md b/doc/context.md
> > new file mode 100644
> > index 0000000000..fb85b3f366
> > --- /dev/null
> > +++ b/doc/context.md
> > @@ -0,0 +1,394 @@
> > +# Introduction to contexts
> > +
> > +&ldquo;%Context&rdquo;
> 
> Is this style of quoting needed? Especially I'd avoid special markup
> to simplify unredendered text reading (which is the point of markdown
> afterall).

Short answer: I'll change it in the next patch and see what happens.

Long answer: HTML quotes are ugly for everyone, UTF-8 is great until someone
turns up complaining we broke their Latin-1 workflow.  I've always preferred
ASCII-only representations for that reason, but happy to try the other way
and see if anyone still cares.

> 
> > is a name for a widely-used programming idiom.
> 
> > +This document explains the general idiom and the conventions FFmpeg has built around it.
> > +
> > +This document uses object-oriented analogies to help readers familiar with
> > +[object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming)
> > +learn about contexts.  But contexts can also be used outside of OOP,
> > +and even in situations where OOP isn't helpful.  So these analogies
> > +should only be used as a first step towards understanding contexts.
> > +
> > +## &ldquo;Context&rdquo; as a way to think about code
> > +
> > +A context is any data structure that is passed to several functions
> > +(or several instances of the same function) that all operate on the same entity.
> > +For example, [object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming)
> > +languages usually provide member functions with a `this` or `self` value:
> > +
> 
> > +```c
> > +class my_cxx_class {
> > +  void my_member_function() {
> > +    // the implicit object parameter provides context for the member function:
> > +    std::cout << this;
> > +  }
> > +};
> > +```
> 
> I'm not convinced this is really useful: if you know C++ this is
> redundant, if you don't this is confusing and don't add much information.

The example is there to break up a wall of text (syntax-highlighted in the
rendered output), and to let the reader know that this is going to be one of
those documents that alternates between text and code, so they're ready for the
more substantive examples later on.  I take the point about C++ though -
would this Python example be more readable?

    class MyClass:
        def my_func(self):
            # If a Python function is part of a class,
            # its first parameter must be an instance of that class

> 
> > +
> > +Contexts are a fundamental building block of OOP, but can also be used in procedural code.
> 
> I'd drop this line, and drop the anchor on OOP at the same time since
> it's adding no much information.

Fundamentally, this document addresses two audiences:

1. people coming from a non-OOP background, who want to learn contexts
   from first principles, and at best see OOP stuff as background information

2. people coming from an OOP background.  There's no polite way to say this -
   their incentive is to write FFmpeg off as a failed attempt at OOP, so they
   don't have to learn a new way of working that's just different enough to
   make them feel dumb

I think a good way to evaluate the document might be to read it through twice,
stopping after each paragraph to ask two unfair questions...

1. what has this told me about FFmpeg itself, as opposed to some other thing
   you wish I cared about?

2. couldn't you have just done this the standard OOP way?

The earlier paragraph acknowledged that contexts resemble OOP (telling the OOP
audience we get it), then this paragraph adds "but they're not the same"
(telling the OOP audience we disagree).  To be more useful to non-OOP folk,
how about:

    Contexts can be a fundamental building block of OOP, but can also be used in
    procedural projects like FFmpeg.

> 
> > +For example, most callback functions can be understood to use contexts:
> 
> > +
> > +```c
> > +struct MyStruct {
> > +  int counter;
> > +};
> > +
> > +void my_callback( void *my_var_ ) {
> > +  // my_var provides context for the callback function:
> > +  struct MyStruct *my_var = (struct MyStruct *)my_var_;
> > +  printf("Called %d time(s)", ++my_var->counter);
> > +}
> > +
> > +void init() {
> > +  struct MyStruct my_var;
> > +  my_var.counter = 0;
> > +  register_callback( my_callback, &my_var );
> 
> style: fun(my_callback, ...) (so spaces around parentheses) here and
> below

🫡

... no wait I just said Unicode is bad ...

I mean, will do.

> 
> > +}
> > +```
> > +
> > +In the broadest sense, &ldquo;context&rdquo; is just a way to think about code.
> > +You can even use it to think about code written by people who have never
> > +heard the term, or who would disagree with you about what it means.
> > +
> > +## &ldquo;Context&rdquo; as a tool of communication
> > +
> > +&ldquo;%Context&ldquo; can just be a word to understand code in your own head,
> > +but it can also be a term you use to explain your interfaces.
> > +Here is a version of the callback example that makes the context explicit:
> > +
> > +```c
> > +struct CallbackContext {
> > +  int counter;
> > +};
> > +
> > +void my_callback( void *ctx_ ) {
> > +  // ctx provides context for the callback function:
> > +  struct CallbackContext *ctx = (struct CallbackContext *)ctx_;
> > +  printf("Called %d time(s)", ++ctx->counter);
> > +}
> > +
> > +void init() {
> > +  struct CallbackContext ctx;
> > +  ctx.counter = 0;
> > +  register_callback( my_callback, &ctx );
> > +}
> > +```
> > +
> > +The difference here is subtle, but important.  If a piece of code
> > +*appears compatible with contexts*, then you are *allowed to think
> > +that way*, but if a piece of code *explicitly states it uses
> > +contexts*, then you are *required to follow that approach*.
> > +
> 
> > +For example, imagine someone modified `MyStruct` in the earlier example
> > +to count several unrelated events across the whole program.  That would mean
> > +it contained information about multiple entities, so was not a context.
> > +But nobody ever *said* it was a context, so that isn't necessarily wrong.
> > +However, proposing the same change to the `CallbackContext` in the later example
> > +would violate a guarantee, and should be pointed out in a code review.
> > +
> 
> I'm not very convinced by the callback example. The use of contexts in
> the FFmpeg API is very much simpler, it is used to keep track of
> configuration and state (that is they track the "object" where to
> operate on), so the callback example here is a bit misleading.
> 
> Callbacks are used in the internals to implement different elements
> (codecs, protocols, filters, etc...) implementing a common API, but in
> this case the relation with "contexts" is less straightforward.

I go back and forth on this one, but your point made me think about it
in a new way...

AVIOContext::read_packet is a callback function, and a reader who has just
learnt about contexts would naturally assume we intend its first argument
to be interpreted as a context.  Given that new readers are likely to learn
avio_alloc_context() around the same time as reading this document,
it's important we give them the tools to understand that function.

How about changing the topmost callback example to read data from a FILE*
(without mentioning AVIOContext), then emphasising how you can think of it
as a context despite not following FFmpeg's rules, then finally mentioning
how you could pass the callback to avio_alloc_context() if you wanted?

> 
> > +@warning Guaranteeing to use contexts does not mean guaranteeing to use
> > +object-oriented programming.  For example, FFmpeg creates its contexts
> > +procedurally instead of with constructors.
> 
> I'm afraid this is more confusing than helpful, since the FFmpeg API
> is not OOP. I'd drop this sentence.

My concern is that if an OOP reader asks "couldn't you have just done this
the standard OOP way?", they will be tempted to answer "oh, so you *used to*
fail at OOP but nowadays you promise to do it right", and not bother reading
any further.  So there needs to be something eye-catching here, but yes this
paragraph needs to be more useful to non-OOP readers.

This will probably need to be rewritten based on the callback discussion,
so I'll think about ways to change this at the same time.

> 
> > +
> > +## Contexts in the real world
> > +
> > +To understand how contexts are used in the real world, it might be
> > +useful to compare [curl's MD5 hash context](https://github.com/curl/curl/blob/bbeeccdea8507ff50efca70a0b33d28aef720267/lib/curl_md5.h#L48)
> > +with @ref AVMD5 "FFmpeg's equivalent context".
> > +
> 
> > +The [MD5 algorithm](https://en.wikipedia.org/wiki/MD5) produces
> > +a fixed-length digest from arbitrary-length data.  It does this by calculating
> > +the digest for a prefix of the data, then loading the next part and adding it
> > +to the previous digest, and so on.  Projects that use MD5 generally use some
> > +kind of context, so comparing them can reveal differences between projects.
> > +
> > +```c
> > +// Curl's MD5 context looks like this:
> > +struct MD5_context {
> > +  const struct MD5_params *md5_hash;    /* Hash function definition */
> > +  void                  *md5_hashctx;   /* Hash function context */
> > +};
> > +
> > +// FFmpeg's MD5 context looks like this:
> > +typedef struct AVMD5 {
> > +    uint64_t len;
> > +    uint8_t  block[64];
> > +    uint32_t ABCD[4];
> > +} AVMD5;
> > +```
> > +
> > +Curl's struct name ends with `_context`, guaranteeing contexts are the correct
> > +interpretation.  FFmpeg's struct does not explicitly say it's a context, but
> > +@ref libavutil/md5.c "its functions do" so we can reasonably assume
> > +it's the intended interpretation.
> > +
> > +Curl's struct uses `void *md5_hashctx` to avoid guaranteeing
> > +implementation details in the public interface, whereas FFmpeg makes
> > +everything accessible.  This kind of data hiding is an advanced context-oriented
> > +convention, and is discussed below.  Using it in this case has strengths and
> > +weaknesses.  On one hand, it means changing the layout in a future version
> > +of curl won't break downstream programs that used that data.  On the other hand,
> > +the MD5 algorithm has been stable for 30 years, so it's arguably more important
> > +to let people dig in when debugging their own code.
> > +
> > +Curl's struct is declared as `struct <type> { ... }`, whereas FFmpeg uses
> > +`typedef struct <type> { ... } <type>`.  These conventions are used with both
> > +context and non-context structs, so don't say anything about contexts as such.
> > +Specifically, FFmpeg's convention is a workaround for an issue with C grammar:
> > +
> > +```c
> > +void my_function( ... ) {
> > +  int                my_var;        // good
> > +  MD5_context        my_curl_ctx;   // error: C needs you to explicitly say "struct"
> > +  struct MD5_context my_curl_ctx;   // good: added "struct"
> > +  AVMD5              my_ffmpeg_ctx; // good: typedef's avoid the need for "struct"
> > +}
> > +```
> > +
> > +Both MD5 implementations are long-tested, widely-used examples of contexts
> > +in the real world.  They show how contexts can solve the same problem
> > +in different ways.
> 
> I'm concerned that this is adding more information than really
> needed. Especially comparing with internals of curl means that now the
> docs needs to be kept in synch also with the curl's API, meaning that
> it will be outdated very soon. I'd rather drop the curl comparison
> altogether.

The value of this section depends on the reader...

This tells a non-OOP reader that FFmpeg didn't invent contexts, and reasonable
people can disagree about what they mean.  So when we get into the ambiguous
cases later on, they have a better idea about which things are just how
contexts work, and which are specifically how FFmpeg uses them.

This tells an OOP reader that it's not "OOP standard, FFmpeg non-standard",
it's that FFmpeg is using a C standard that's not used in OOP languages.

Curl's `MD5_context` was last modified in 2020 (interestingly, to get rid of
the `typedef struct` trick).  It's a slow-moving target, but you're right it's
not a static one.

I'd argue the above means this should be *somewhere* in the document, but not
necessarily here in the middle.  I'll see if it works better as a paragraph
here and an appendix or something at the bottom.

> > +
> > +## FFmpeg's advanced context-oriented conventions
> > +
> > +Projects that make heavy use of contexts tend to develop conventions
> > +to make them more useful.  This section discusses conventions used in FFmpeg,
> > +some of which are used in other projects, others are unique to this project.
> > +
> > +### Naming: &ldquo;Context&rdquo; and &ldquo;ctx&rdquo;
> > +
> > +```c
> > +// Context struct names usually end with `Context`:
> > +struct AVSomeContext {
> > +  ...
> > +};
> > +
> > +// Functions are usually named after their context,
> > +// context parameters usually come first and are often called `ctx`:
> > +void av_some_function( AVSomeContext *ctx, ... );
> > +```
> > +
> > +If an FFmpeg struct is intended for use as a context, its name usually
> > +makes that clear.  Exceptions to this rule include AVMD5 (discussed above),
> > +which is only identified as a context by the functions that call it.
> > +
> > +If a function is associated with a context, its name usually
> > +begins with some variant of the context name (e.g. av_md5_alloc()
> > +or avcodec_alloc_context3()).  Exceptions to this rule include
> > +@ref avformat.h "AVFormatContext's functions", many of which
> > +begin with just `av_`.
> > +
> > +If a function has a context parameter, it usually comes first and its name
> > +often contains `ctx`.  Exceptions include av_bsf_alloc(), which puts the
> > +context argument second to emphasise it's an out variable.
> > +
> > +### Data hiding: private contexts
> > +
> > +```c
> > +// Context structs often hide private context:
> > +struct AVSomeContext {
> > +  void *priv_data; // sometimes just called "internal"
> > +};
> > +```
> > +
> > +Contexts usually present a public interface, so changing a context's members
> > +forces everyone that uses the library to at least recompile their program,
> > +if not rewrite it to remain compatible.  Hiding information in a private context
> > +ensures it can be modified without affecting downstream software.
> > +
> > +Object-oriented programmers may be tempted to compare private contexts to
> > +*private class members*.  That's often accurate, but for example it can also
> > +be used like a *virtual function table* - a list of functions that are
> > +guaranteed to exist, but may be implemented differently for different
> > +sub-classes.  When thinking about private contexts, remember that FFmpeg
> > +isn't *large enough* to need some common OOP techniques, even though it's
> > +solving a problem that's *complex enough* to benefit from some rarer techniques.
> > +
> > +### Manage lifetime: allocate, initialize and free
> > +
> > +```c
> > +void my_function( ... ) {
> > +
> > +    // Context structs are allocated then initialized with associated functions:
> > +
> > +    AVSomeContext *ctx = av_some_context_alloc( ... );
> > +
> > +    // ... configure ctx ...
> > +
> > +    av_some_context_init( ctx, ... );
> > +
> > +    // ... use ctx ...
> > +
> > +    // Context structs are freed with associated functions:
> > +
> > +    av_some_context_free( ctx );
> > +
> > +}
> > +```
> > +
> > +FFmpeg contexts go through the following stages of life:
> > +
> > +1. allocation (often a function that ends with `_alloc`)
> > +   * a range of memory is allocated for use by the structure
> > +   * memory is allocated on boundaries that improve caching
> > +   * memory is reset to zeroes, some internal structures may be initialized
> > +2. configuration (implemented by setting values directly on the object)
> > +   * no function for this - calling code populates the structure directly
> > +   * memory is populated with useful values
> > +   * simple contexts can skip this stage
> > +3. initialization (often a function that ends with `_init`)
> > +   * setup actions are performed based on the configuration (e.g. opening files)
> > +5. normal usage
> > +   * most functions are called in this stage
> > +   * documentation implies some members are now read-only (or not used at all)
> > +   * some contexts allow re-initialization
> > +6. closing (often a function that ends with `_close()`)
> > +   * teardown actions are performed (e.g. closing files)
> > +7. deallocation (often a function that ends with `_free()`)
> > +   * memory is returned to the pool of available memory
> > +
> > +This can mislead object-oriented programmers, who expect something more like:
> > +
> > +1. allocation (usually a `new` keyword)
> > +   * a range of memory is allocated for use by the structure
> > +   * memory *may* be reset (e.g. for security reasons)
> > +2. initialization (usually a constructor)
> > +   * memory is populated with useful values
> > +   * related setup actions are performed based on arguments (e.g. opening files)
> > +3. normal usage
> > +   * most functions are called in this stage
> > +   * compiler enforces that some members are read-only (or private)
> > +   * no going back to the previous stage
> > +4. finalization (usually a destructor)
> > +   * teardown actions are performed (e.g. closing files)
> > +5. deallocation (usually a `delete` keyword)
> > +   * memory is returned to the pool of available memory
> > +
> > +FFmpeg's allocation stage is broadly similar to OOP, but can do some higher-level
> > +operations.  For example, AVOptions-enabled structs (discussed below) contain an
> > +AVClass member that is set during allocation.
> > +
> > +FFmpeg's "configuration" and "initialization" stages combine to resemble OOP's
> > +"initialization" stage.  This can mislead object-oriented developers,
> > +who are used to doing both at once.  This means FFmpeg contexts don't have
> > +a direct equivalent of OOP constructors, as they would be doing
> > +two jobs in one function.
> > +
> > +FFmpeg's three-stage creation process is useful for complicated structures.
> > +For example, AVCodecContext contains many members that *can* be set before
> > +initialization, but in practice most programs set few if any of them.
> > +Implementing this with a constructor would involve a function with a list
> > +of arguments that was extremely long and changed whenever the struct was
> > +updated.  For contexts that don't need the extra flexibility, FFmpeg usually
> > +provides a combined allocator and initializer function.  For historical reasons,
> > +suffixes like `_alloc`, `_init`, `_alloc_context` and even `_open` can indicate
> > +the function does any combination of allocation and initialization.
> > +
> > +FFmpeg's "closing" stage is broadly similar to OOP's "finalization" stage,
> > +but some contexts allow re-initialization after finalization.  For example,
> > +SwrContext lets you call swr_close() then swr_init() to reuse a context.
> > +
> > +FFmpeg's "deallocation" stage is broadly similar to OOP, but can perform some
> > +higher-level functions (similar to the allocation stage).
> > +
> > +Very few contexts need the flexibility of separate "closing" and
> > +"deallocation" stages, so these are usually combined into a single function.
> > +Closing functions usually end with "_close", while deallocation
> > +functions usually end with "_free".

Some changes I'm planning to make in the next rewrite...

* some functions happen to end with "_finalize()" (e.g. av_bsf_list_finalize()),
  but it's just a coincidence that they share a name with the OOP stage

* I think that e.g. av_mediacodec_default_free() needs to be called immediately
  before (or after?) closing the associated context, which would make it a
  separate "deconfiguration" stage according to the logic above.

> > +
> > +### Reflection: AVOptions-enabled structs
> > +
> > +Object-oriented programming puts more focus on data hiding than FFmpeg needs,
> > +but it also puts less focus on
> > +[reflection](https://en.wikipedia.org/wiki/Reflection_(computer_programming)).
> > +
> > +To understand FFmpeg's reflection requirements, run `ffmpeg -h full` on the
> > +command-line, then ask yourself how you would implement all those options
> > +with the C standard [`getopt` function](https://en.wikipedia.org/wiki/Getopt).
> > +You can also ask the same question for any other programming languages you know.
> > +[Python's argparse module](https://docs.python.org/3/library/argparse.html)
> > +is a good example - its approach works well with far more complex programs
> > +than `getopt`, but would you like to maintain an argparse implementation
> > +with 15,000 options and growing?
> > +
> > +Most solutions assume you can just put all options in a single block,
> > +which is unworkable at FFmpeg's scale.  Instead, we split configuration
> > +across many *AVOptions-enabled structs*, which use the @ref avoptions
> > +"AVOptions API" to reflect information about their user-configurable members,
> > +including members in private contexts.
> > +
> > +An *AVOptions-enabled struct* is a struct that contains an AVClass element as
> > +its first member, and uses that element to provide access to instances of
> > +AVOption, each of which provides information about a single option.
> > +The AVClass can also include more @ref AVClass "AVClasses" for private contexts,
> > +making it possible to set options through the API that aren't
> > +accessible directly.
> > +
> > +AVOptions-accessible members of a context should be accessed through the
> > +AVOptions API whenever possible, even if they're not hidden away in a private
> > +context.  That ensures values are validated as they're set, and means you won't
> > +have to do as much work if a future version of FFmpeg changes the layout.
> > +
> > +AVClass was created very early in FFmpeg's history, long before AVOptions.
> > +Its name suggests some kind of relationship to an OOP
> > +base [class](https://en.wikipedia.org/wiki/Class_(computer_programming)),
> > +but the name has become less accurate as FFmpeg evolved, to the point where
> > +AVClass and AVOption are largely synonymous in modern usage.  The difference
> > +might still matter if you need to support old versions of FFmpeg,
> > +where you might find *AVClass context structures* (contain an AVClass element
> > +as their first member) that are not *AVOptions-enabled* (don't use that element
> > +to provide access to instances of AVOption).

One more note I'm planning for the next rewrite...

* as you've mentioned elsewhere, AVClass is involved in formatting log messages,
  so if you e.g. make your own logging framework, it might help to think about
  AVClass context structures as distinct from from AVOptions-enabled structs

> > +Object-oriented programmers may be tempted to compare @ref avoptions "AVOptions"
> > +to OOP getters and setters.  There is some overlap in functionality, but OOP
> > +getters and setters are usually specific to a single member and don't provide
> > +metadata about the member; whereas AVOptions has a single API that covers
> > +every option, and provides help text etc. as well.
> > +
> > +Object-oriented programmers may be tempted to compare AVOptions-accessible
> > +members of a public context to protected members of a class.  Both provide
> > +global access through an API, and unrestricted access for trusted friends.
> > +But this is just a happy accident, not a guarantee.
> 
> This part looks fine, although there is too much OOP jargon for my
> taste: this would make reading for programmers not familiar with OOP
> harder than needed since she will miss many references.
> 
> > +
> > +## Final example: context for a codec
> > +
> > +AVCodecContext is an AVOptions-enabled struct that contains information
> > +about encoding or decoding one stream of data (e.g. the video in a movie).
> > +It's a good example of many of the issues above.
> > +
> > +The name "AVCodecContext" tells us this is a context.  Many of
> > +@ref libavcodec/avcodec.h "its functions" start with an `avctx` parameter,
> > +indicating this object provides context for that function.
> > +
> > +AVCodecContext::internal contains the private context.  For example,
> > +codec-specific information might be stored here.
> > +
> > +AVCodecContext is allocated with avcodec_alloc_context3(), initialized with
> > +avcodec_open2(), and freed with avcodec_free_context().  Most of its members
> > +are configured with the @ref avoptions "AVOptions API", but for example you
> > +can set AVCodecContext::opaque or AVCodecContext::draw_horiz_band() if your
> > +program happens to need them.
> > +
> > +AVCodecContext provides an abstract interface to many different *codecs*.
> > +Options supported by many codecs (e.g. "bitrate") are kept in AVCodecContext
> > +and reflected as AVOptions.  Options that are specific to one codec are
> > +stored in the internal context, and reflected from there.
> > +
> > +To support a specific codec, AVCodecContext's private context is set to
> > +an encoder-specific data type.  For example, the video codec
> > +[H.264](https://en.wikipedia.org/wiki/Advanced_Video_Coding) is supported via
> > +[the x264 library](https://www.videolan.org/developers/x264.html), and
> > +implemented in X264Context.
> 
> > Although included in the documentation, X264Context is not part of the public API.
> 
> Why included in the doc? That is a private struct and therefore should
> not be included in the doxy.

Doxygen doesn't provide an obvious mechanism to include only the public API.
Changing that would be at best a big job, and it isn't obvious where to even
start until/unless e.g. [1] gets merged in.  It seems like a better plan
to put the warning in and take it out if and when the site gets updated.

[1] https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/326031.html
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes
  2024-05-22 15:24     ` Andreas Rheinhardt
@ 2024-05-22 16:54       ` Andrew Sayers
  0 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-22 16:54 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Wed, May 22, 2024 at 05:24:36PM +0200, Andreas Rheinhardt wrote:
> These structures should be renamed instead of adding these comments
> (which are pointless for internal developers). I just sent a patch for that.
> Thanks for pointing out the issue.

Oh, great!  So the next version of this patchset will skip this patch,
and will reduce links like this:

> + * @brief @ref md_doc_2context "Context" for a cache

down to:

> + * @brief @ref Context for a cache

I don't see a way of removing the "@ref" without doing something nasty,
like making a fake "Context" struct and shoving the documentation in there.

Also, if someone does something strange like this:

> + * @brief @ref Context "structure" (actually an enum)

doxygen won't render it the way the author expects.  I don't expect that to
happen much in the real world though.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v5 0/4] Explain what "context" means
  2024-05-22  9:31     ` Stefano Sabatini
  2024-05-22 16:07       ` Andrew Sayers
@ 2024-05-23 20:00       ` Andrew Sayers
  2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 1/4] doc: " Andrew Sayers
                           ` (4 more replies)
  1 sibling, 5 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-23 20:00 UTC (permalink / raw)
  To: ffmpeg-devel

NOTE: this patchset depends on [1], and should not be applied before that.

I think it's important to guide readers between parts of FFmpeg, because
learning how the pieces of the puzzle fit together is a big part of the
newbie experience.  So this patchset replaces the "@ref Context for foo"
statements in public structs with "@see" blocks, giving us a hook we can
hang more links on in future.

That said, there's a rule against internal links from private structs,
so I've removed the @ref's from them.  By the way, is this rule written
somewhere?  If not, where would be a good place to write it?
And either way, it would be good to link to this as part of [2].

Previous patches had to change the language for many structs, but "@see" blocks
avoid the need to include those changes in this patchset.  Rather than waste
that work, I've temporarily moved those changes to the final patch in this set.
My feelings about that last patch aren't strong, but I guess I'll propose them
in a separate thread unless anyone wants them here or chucked altogether.


I've rewritten AVOptions and AVClass based on feedback.  The new version
reflects a hypothetical that's been going round my head all week...

Imagine you wanted to write a system that nudged people to try new codecs.
It might say e.g. "you seem to be using H.264, would you like to try H.265?"
Implementing that would probably involve a struct like:

struct AVOldNew {
  AVClass* old;
  AVClass* new;
};

That's a struct that begins with an AVClass*, but is clearly not an AVClass
context structure.  So the new version defines "AVClass context structure" and
"AVOptions-enabled struct" in terms of the way the structs are used instead of
their layout, which should be more useful and accurate to current practice,
while remaining compatible(ish) with the way the words are used in conversation.


I mentioned hwaccels in a previous message.  From another look around the code,
I think these are supposed to be completely invisible to an external API dev.
If not, please point me in the direction of any documentation I missed.

[1] https://ffmpeg.org/pipermail/ffmpeg-devel/2024-May/327958.html
[2] https://ffmpeg.org/pipermail/ffmpeg-devel/2024-May/327624.html


_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v5 1/4] doc: Explain what "context" means
  2024-05-23 20:00       ` [FFmpeg-devel] [PATCH v5 0/4] " Andrew Sayers
@ 2024-05-23 20:00         ` Andrew Sayers
  2024-05-25 11:00           ` Stefano Sabatini
  2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
                           ` (3 subsequent siblings)
  4 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-05-23 20:00 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Derived from explanations kindly provided by Stefano Sabatini and others:
https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
---
 doc/context.md | 439 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 439 insertions(+)
 create mode 100644 doc/context.md

diff --git a/doc/context.md b/doc/context.md
new file mode 100644
index 0000000000..21469a6e58
--- /dev/null
+++ b/doc/context.md
@@ -0,0 +1,439 @@
+@page Context Introduction to contexts
+
+@tableofcontents
+
+“Context” is a name for a widely-used programming idiom.
+This document explains the general idiom and some conventions used by FFmpeg.
+
+This document uses object-oriented analogies for readers familiar with
+[object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming).
+But contexts can also be used outside of OOP, and even in situations where OOP
+isn't helpful.  So these analogies should only be used as a rough guide.
+
+@section Context_general “Context” as a general concept
+
+Many projects use some kind of “context” idiom.  You can safely skip this
+section if you have used contexts in another project.  You might also prefer to
+read @ref Context_comparison before continuing with the rest of the document.
+
+@subsection Context_think “Context” as a way to think about code
+
+A context is any data structure that is passed to several functions
+(or several instances of the same function) that all operate on the same entity.
+For example, [object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming)
+languages usually provide member functions with a `this` or `self` value:
+
+```python
+# Python methods (functions within classes) must start with an object argument,
+# which does a similar job to a context:
+class MyClass:
+    def my_func(self):
+        ...
+```
+
+Contexts can also be used in C-style procedural code.  If you have ever written
+a callback function, you have probably used a context:
+
+```c
+struct FileReader {
+    FILE* file;
+};
+
+int my_callback(void *my_var_, uint8_t* buf, int buf_size) {
+
+    // my_var provides context for the callback function:
+    struct FileReader *my_var = (struct FileReader *)my_var_;
+
+    return read(my_var->file, sizeof(*buf), buf_size);
+}
+
+void init() {
+
+    struct FileReader my_var;
+    my_var->file = fopen("my-file", "rb");
+
+    register_callback(my_callback, &my_var);
+
+    ...
+
+    fclose( my_var->file );
+
+}
+```
+
+In the broadest sense, a context is just a way to think about some code.
+You can even use it to think about code written by people who have never
+heard the term, or who would disagree with you about what it means.
+But when FFmpeg developers say “context”, they're usually talking about
+a more specific set of conventions.
+
+@subsection Context_communication “Context” as a tool of communication
+
+“Context“ can just be a word to understand code in your own head,
+but it can also be a term you use to explain your interfaces.
+Here is a version of the callback example that makes the context explicit:
+
+```c
+struct FileReaderContext {
+    FILE *file;
+};
+
+int my_callback(void *ctx_, uint8_t *buf, int buf_size) {
+
+    // ctx provides context for the callback function:
+    struct FileReaderContext *ctx = (struct FileReaderContext *)ctx_;
+
+    return read(ctx->file, sizeof(*buf), buf_size);
+}
+
+void init() {
+
+    struct FileReader ctx;
+    ctx->file = fopen("my-file", "rb");
+
+    register_callback(my_callback, &ctx);
+
+    ...
+
+    fclose( ctx->file );
+
+}
+```
+
+The difference here is subtle, but important.  If a piece of code
+*appears compatible with contexts*, then you are *allowed to think
+that way*, but if a piece of code *explicitly states it uses
+contexts*, then you are *required to follow that approach*.
+
+For example, take a look at avio_alloc_context().
+The function name and return value both state it uses contexts,
+so failing to follow that approach is a bug you can report.
+But its arguments are a set of callbacks that merely appear compatible with
+contexts, so it's fine to write a `read_packet` function that just reads
+from standard input.
+
+When a programmer says their code is "a context", they're guaranteeing
+to follow a set of conventions enforced by their community - for example,
+the FFmpeg community enforces that contexts have separate allocation,
+configuration, and initialization steps.  That's different from saying
+their code is "an object", which normally guarantees to follow conventions
+enforced by their programming language (e.g. using a constructor function).
+
+@section Context_ffmpeg FFmpeg contexts
+
+This section discusses specific context-related conventions used in FFmpeg.
+Some of these are used in other projects, others are unique to this project.
+
+@subsection Context_naming Naming: “Context” and “ctx”
+
+```c
+// Context struct names usually end with `Context`:
+struct AVSomeContext {
+  ...
+};
+
+// Functions are usually named after their context,
+// context parameters usually come first and are often called `ctx`:
+void av_some_function(AVSomeContext *ctx, ...);
+```
+
+If an FFmpeg struct is intended for use as a context, its name usually
+makes that clear.  Exceptions to this rule include AVMD5, which is only
+identified as a context by @ref libavutil/md5.c "the functions that call it".
+
+If a function is associated with a context, its name usually
+begins with some variant of the context name (e.g. av_md5_alloc()
+or avcodec_alloc_context3()).  Exceptions to this rule include
+@ref avformat.h "AVFormatContext's functions", many of which
+begin with just `av_`.
+
+If a function has a context parameter, it usually comes first and its name
+often contains `ctx`.  Exceptions include av_bsf_alloc(), which puts the
+context argument second to emphasise it's an out variable.
+
+Some functions fit awkwardly within FFmpeg's context idiom.  For example,
+av_ambient_viewing_environment_create_side_data() creates an
+AVAmbientViewingEnvironment context, then adds it to the side-data of an
+AVFrame context.  If you find contexts a useful metaphor in these cases,
+you might prefer to think of these functions as "receiving" and "producing"
+contexts.
+
+@subsection Context_data_hiding Data hiding: private contexts
+
+```c
+// Context structs often hide private context:
+struct AVSomeContext {
+  void *priv_data; // sometimes just called "internal"
+};
+```
+
+Contexts present a public interface, so changing a context's members forces
+everyone that uses the library to at least recompile their program,
+if not rewrite it to remain compatible.  Many contexts reduce this problem
+by including a private context with a type that is not exposed in the public
+interface.  Hiding information this way ensures it can be modified without
+affecting downstream software.
+
+Private contexts often store variables users aren't supposed to see
+(similar to an OOP private block), but can also store information shared between
+some but not all instances of a context (e.g. codec-specific functionality),
+and @ref Context_avoptions "AVOptions-enabled structs" can include options
+that are accessible through the @ref avoptions "AVOptions API".
+Object-oriented programmers thinking about private contexts should remember
+that FFmpeg isn't *large enough* to need some common object-oriented techniques,
+even though it's solving a problem *complex enough* to benefit from
+some rarer techniques.
+
+@subsection Context_lifetime Manage lifetime: allocate, initialize and free
+
+```c
+void my_function( ... ) {
+
+    // Context structs are allocated then initialized with associated functions:
+
+    AVSomeContext *ctx = av_some_context_alloc(...);
+
+    // ... configure ctx ...
+
+    av_some_context_init(ctx, ...);
+
+    // ... use ctx ...
+
+    // Context structs are freed with associated functions:
+
+    av_some_context_close(ctx);
+    av_some_context_free(ctx);
+
+}
+```
+
+FFmpeg contexts go through the following stages of life:
+
+1. allocation (often a function that ends with `_alloc`)
+   * a range of memory is allocated for use by the structure
+   * memory is allocated on boundaries that improve caching
+   * memory is reset to zeroes, some internal structures may be initialized
+2. configuration (implemented by setting values directly on the context)
+   * no function for this - calling code populates the structure directly
+   * memory is populated with useful values
+   * simple contexts can skip this stage
+3. initialization (often a function that ends with `_init`)
+   * setup actions are performed based on the configuration (e.g. opening files)
+5. normal usage
+   * most functions are called in this stage
+   * documentation implies some members are now read-only (or not used at all)
+   * some contexts allow re-initialization
+6. closing (often a function that ends with `_close()`)
+   * teardown actions are performed (e.g. closing files)
+7. deallocation (often a function that ends with `_free()`)
+   * memory is returned to the pool of available memory
+
+This can mislead object-oriented programmers, who expect something more like:
+
+1. allocation (usually a `new` keyword)
+   * a range of memory is allocated for use by the structure
+   * memory *may* be reset (e.g. for security reasons)
+2. initialization (usually a constructor)
+   * memory is populated with useful values
+   * related setup actions are performed based on arguments (e.g. opening files)
+3. normal usage
+   * most functions are called in this stage
+   * compiler enforces that some members are read-only (or private)
+   * no going back to the previous stage
+4. finalization (usually a destructor)
+   * teardown actions are performed (e.g. closing files)
+5. deallocation (usually a `delete` keyword)
+   * memory is returned to the pool of available memory
+
+FFmpeg's allocation stage is broadly similar to the OOP stage of the same name.
+Both set aside some memory for use by a new entity, but FFmpeg's stage can also
+do some higher-level operations.  For example, @ref Context_avoptions
+"AVOptions-enabled structs" set their AVClass member during allocation.
+
+FFmpeg's configuration stage involves setting any variables you want to before
+you start using the context.  Complicated FFmpeg structures like AVCodecContext
+tend to have many members you *could* set, but in practice most programs set
+few if any of them.  The freeform configuration stage works better than bundling
+these into the initilization stage, which would lead to functions with
+impractically many parameters, and would mean each new option was an
+incompatible change to the API.
+
+FFmpeg's initialization stage involves calling a function that sets the context
+up based on your configuration.
+
+FFmpeg's first three stages do the same job as OOP's first two stages.
+This can mislead object-oriented developers, who expect to do less work in the
+allocation stage, and more work in the initialization stage.  To simplify this,
+most FFmpeg contexts provide a combined allocator and initializer function.
+For historical reasons, suffixes like `_alloc`, `_init`, `_alloc_context` and
+even `_open` can indicate the function does any combination of allocation and
+initialization.
+
+FFmpeg's "closing" stage is broadly similar to OOP's "finalization" stage,
+but some contexts allow re-initialization after finalization.  For example,
+SwrContext lets you call swr_close() then swr_init() to reuse a context.
+Be aware that some FFmpeg functions happen to use the word "finalize" in a way
+that has nothing to do with the OOP stage (e.g. av_bsf_list_finalize()).
+
+FFmpeg's "deallocation" stage is broadly similar to OOP, but can perform some
+higher-level functions (similar to the allocation stage).
+
+Closing functions usually end with "_close", while deallocation
+functions usually end with "_free".  Very few contexts need the flexibility of
+separate "closing" and "deallocation" stages, so many "_free" functions
+implicitly close the context first.
+
+@subsection Context_avoptions Reflection: AVOptions-enabled structs
+
+Object-oriented programming puts more focus on data hiding than FFmpeg needs,
+but it also puts less focus on
+[reflection](https://en.wikipedia.org/wiki/Reflection_(computer_programming)).
+
+To understand FFmpeg's reflection requirements, run `ffmpeg -h full` on the
+command-line, then ask yourself how you would implement all those options
+with the C standard [`getopt` function](https://en.wikipedia.org/wiki/Getopt).
+You can also ask the same question for any other programming languages you know.
+[Python's argparse module](https://docs.python.org/3/library/argparse.html)
+is a good example - its approach works well with far more complex programs
+than `getopt`, but would you like to maintain an argparse implementation
+with 15,000 options and growing?
+
+Most solutions assume you can just put all options in a single block,
+which is unworkable at FFmpeg's scale.  Instead, we split configuration
+across many *AVOptions-enabled structs*, which use the @ref avoptions
+"AVOptions API" to reflect information about their user-configurable members,
+including members in private contexts.
+
+AVOptions-accessible members of a context should be accessed through the
+@ref avoptions "AVOptions API" whenever possible, even if they're not hidden
+in a private context.  That ensures values are validated as they're set, and
+means you won't have to do as much work if a future version of FFmpeg changes
+the allowed values.  This is broadly similar to the way object-oriented programs
+recommend getters and setters over direct access.
+
+Object-oriented programmers may be tempted to compare AVOptions-accessible
+members of a public context to protected members of a class.  Both provide
+global access through an API, and unrestricted access for trusted friends.
+But this is just a happy accident, not a guarantee.
+
+@subsection Context_logging Logging: AVClass context structures
+
+FFmpeg's @ref lavu_log "logging facility" needs to be simple to use,
+but flexible enough to let people debug problems.  And much like reflection,
+it needs to work the same across a wide variety of unrelated structs.
+
+FFmpeg structs that support the logging framework are called *@ref AVClass
+context structures*.  The name @ref AVClass was chosen early in FFmpeg's
+development, but in practice it only came to store information about
+logging, and about introspection.
+
+@section Context_further Further information about contexts
+
+So far, this document has provided a theoretical guide to FFmpeg contexts.
+This final section provides some alternative approaches to the topic,
+which may help round out your understanding.
+
+@subsection Context_example Learning by example: context for a codec
+
+It can help to learn contexts by doing a deep dive into a specific struct.
+This section will discuss AVCodecContext - an AVOptions-enabled struct
+that contains information about encoding or decoding one stream of data
+(e.g. the video in a movie).
+
+The name "AVCodecContext" tells us this is a context.  Many of
+@ref libavcodec/avcodec.h "its functions" start with an `avctx` parameter,
+indicating this parameter provides context for that function.
+
+AVCodecContext::internal contains the private context.  For example,
+codec-specific information might be stored here.
+
+AVCodecContext is allocated with avcodec_alloc_context3(), initialized with
+avcodec_open2(), and freed with avcodec_free_context().  Most of its members
+are configured with the @ref avoptions "AVOptions API", but for example you
+can set AVCodecContext::opaque or AVCodecContext::draw_horiz_band() if your
+program happens to need them.
+
+AVCodecContext provides an abstract interface to many different *codecs*.
+Options supported by many codecs (e.g. "bitrate") are kept in AVCodecContext
+and reflected as AVOptions.  Options that are specific to one codec are
+stored in the private context, and reflected from there.
+
+AVCodecContext::av_class contains logging metadata to ensure all codec-related
+error messages look the same, plus implementation details about options.
+
+To support a specific codec, AVCodecContext's private context is set to
+an encoder-specific data type.  For example, the video codec
+[H.264](https://en.wikipedia.org/wiki/Advanced_Video_Coding) is supported via
+[the x264 library](https://www.videolan.org/developers/x264.html), and
+implemented in X264Context.  Although included in the documentation, X264Context
+is not part of the public API.  That means FFmpeg's @ref ffmpeg_versioning
+"strict rules about changing public structs" aren't as important here, so a
+version of FFmpeg could modify X264Context or replace it with another type
+altogether.  An adverse legal ruling or security problem could even force us to
+switch to a completely different library without a major version bump.
+
+The design of AVCodecContext provides several important guarantees:
+
+- lets you use the same interface for any codec
+- supports common encoder options like "bitrate" without duplicating code
+- supports encoder-specific options like "profile" without bulking out the public interface
+- reflects both types of options to users, with help text and detection of missing options
+- provides uniform logging output
+- hides implementation details (e.g. its encoding buffer)
+
+@subsection Context_comparison Learning by comparison: FFmpeg vs. Curl contexts
+
+It can help to learn contexts by comparing how different projects tackle
+similar problems.  This section will compare @ref AVMD5 "FFmpeg's MD5 context"
+with [curl 8.8.0's equivalent](https://github.com/curl/curl/blob/curl-8_8_0/lib/md5.c#L48).
+
+The [MD5 algorithm](https://en.wikipedia.org/wiki/MD5) produces
+a fixed-length digest from arbitrary-length data.  It does this by calculating
+the digest for a prefix of the data, then loading the next part and adding it
+to the previous digest, and so on.
+
+```c
+// FFmpeg's MD5 context looks like this:
+typedef struct AVMD5 {
+    uint64_t len;
+    uint8_t  block[64];
+    uint32_t ABCD[4];
+} AVMD5;
+
+// Curl 8.8.0's MD5 context looks like this:
+struct MD5_context {
+  const struct MD5_params *md5_hash;    /* Hash function definition */
+  void                  *md5_hashctx;   /* Hash function context */
+};
+```
+
+Curl's struct name ends with `_context`, guaranteeing contexts are the correct
+interpretation.  FFmpeg's struct does not explicitly say it's a context, but
+@ref libavutil/md5.c "its functions do" so we can reasonably assume
+it's the intended interpretation.
+
+Curl's struct uses `void *md5_hashctx` to avoid guaranteeing
+implementation details in the public interface, whereas FFmpeg makes
+everything accessible.  This disagreement about data hiding is a good example
+of how contexts can be used differently.  Hiding the data means changing the
+layout in a future version of curl won't break downstream programs that used
+that data.  But the MD5 algorithm has been stable for 30 years, and making the
+data public makes it easier for people to follow a bug in their own code.
+
+Curl's struct is declared as `struct <type> { ... }`, whereas FFmpeg uses
+`typedef struct <type> { ... } <type>`.  These conventions are used with both
+context and non-context structs, so don't say anything about contexts as such.
+Specifically, FFmpeg's convention is a workaround for an issue with C grammar:
+
+```c
+void my_function( ... ) {
+  int                my_var;        // good
+  MD5_context        my_curl_ctx;   // error: C needs you to explicitly say "struct"
+  struct MD5_context my_curl_ctx;   // good: added "struct"
+  AVMD5              my_ffmpeg_ctx; // good: typedef's avoid the need for "struct"
+}
+```
+
+Both MD5 implementations are long-tested, widely-used examples of contexts
+in the real world.  They show how contexts can solve the same problem
+in different ways.
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v5 2/4] lavu: Clarify relationship between AVClass, AVOption and context
  2024-05-23 20:00       ` [FFmpeg-devel] [PATCH v5 0/4] " Andrew Sayers
  2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 1/4] doc: " Andrew Sayers
@ 2024-05-23 20:00         ` Andrew Sayers
  2024-05-25  9:57           ` Stefano Sabatini
  2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 3/4] all: Link to "context" from all public contexts with documentation Andrew Sayers
                           ` (2 subsequent siblings)
  4 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-05-23 20:00 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

---
 libavutil/log.h | 16 +++++++++++++---
 libavutil/opt.h | 17 ++++++++++++++---
 2 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/libavutil/log.h b/libavutil/log.h
index ab7ceabe22..d599ab506e 100644
--- a/libavutil/log.h
+++ b/libavutil/log.h
@@ -59,9 +59,19 @@ typedef enum {
 struct AVOptionRanges;
 
 /**
- * Describe the class of an AVClass context structure. That is an
- * arbitrary struct of which the first field is a pointer to an
- * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.).
+ * Generic Logging and introspection facilities
+ *
+ * Logging and introspection functions expect to be passed structs
+ * whose first member is a pointer-to-@ref AVClass.
+ *
+ * Structs that only use the logging facilities are often referred to as
+ * "AVClass context structures", while those that use introspection facilities
+ * are called "AVOptions-enabled structs".
+ *
+ * @see
+ * * @ref lavu_log
+ * * @ref avoptions
+ * * @ref Context
  */
 typedef struct AVClass {
     /**
diff --git a/libavutil/opt.h b/libavutil/opt.h
index 07e27a9208..b14c120e36 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -39,9 +39,16 @@
  * @defgroup avoptions AVOptions
  * @ingroup lavu_data
  * @{
- * AVOptions provide a generic system to declare options on arbitrary structs
- * ("objects"). An option can have a help text, a type and a range of possible
- * values. Options may then be enumerated, read and written to.
+ *
+ * Generic introspection facilities for AVClass context structures
+ *
+ * Provides a generic system to declare and manage options on any struct
+ * whose first member is a pointer-to-@ref AVClass.  Structs with private
+ * contexts can use that AVClass to return further @ref AVClass "AVClass"es
+ * that enable introspection of the private structs.
+ *
+ * Each option can have a help text, a type and a range of possible values.
+ * Options may be enumerated, read and written to.
  *
  * There are two modes of access to members of AVOption and its child structs.
  * One is called 'native access', and refers to access from the code that
@@ -53,6 +60,10 @@
  * question is allowed to access the field. This allows us to extend the
  * semantics of those fields without breaking API compatibility.
  *
+ * @see
+ * * @ref lavu_log
+ * * @ref Context
+ *
  * @section avoptions_scope Scope of AVOptions
  *
  * AVOptions is designed to support any set of multimedia configuration options
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v5 3/4] all: Link to "context" from all public contexts with documentation
  2024-05-23 20:00       ` [FFmpeg-devel] [PATCH v5 0/4] " Andrew Sayers
  2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 1/4] doc: " Andrew Sayers
  2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
@ 2024-05-23 20:00         ` Andrew Sayers
  2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 4/4] all: Rewrite documentation for contexts Andrew Sayers
  2024-05-24  1:50         ` [FFmpeg-devel] [PATCH v5 0/4] Explain what "context" means Michael Niedermayer
  4 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-23 20:00 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

The goal of putting these links in "@see" blocks is to provide hooks
for future developers to add links to other useful parts of the codebase.
---
 libavcodec/avcodec.h             | 3 +++
 libavcodec/bsf.h                 | 3 +++
 libavcodec/d3d11va.h             | 3 +++
 libavcodec/mediacodec.h          | 2 ++
 libavcodec/qsv.h                 | 3 +++
 libavcodec/vdpau.h               | 3 +++
 libavcodec/videotoolbox.h        | 3 +++
 libavfilter/avfilter.h           | 7 ++++++-
 libavformat/avformat.h           | 3 +++
 libavformat/avio.h               | 3 +++
 libavutil/audio_fifo.h           | 3 +++
 libavutil/hwcontext.h            | 6 ++++++
 libavutil/hwcontext_cuda.h       | 3 +++
 libavutil/hwcontext_d3d11va.h    | 6 ++++++
 libavutil/hwcontext_d3d12va.h    | 6 ++++++
 libavutil/hwcontext_drm.h        | 3 +++
 libavutil/hwcontext_dxva2.h      | 6 ++++++
 libavutil/hwcontext_mediacodec.h | 3 +++
 libavutil/hwcontext_opencl.h     | 6 ++++++
 libavutil/hwcontext_qsv.h        | 6 ++++++
 libavutil/hwcontext_vaapi.h      | 6 ++++++
 libavutil/hwcontext_vdpau.h      | 3 +++
 libavutil/hwcontext_vulkan.h     | 6 ++++++
 libavutil/lfg.h                  | 3 +++
 24 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 2da63c87ea..abc00ab394 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -441,6 +441,9 @@ typedef struct RcOverride{
  * The AVOption/command line parameter names differ in some cases from the C
  * structure field names for historic reasons or brevity.
  * sizeof(AVCodecContext) must not be used outside libav*.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVCodecContext {
     /**
diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
index a09c69f242..ee5fdd48d2 100644
--- a/libavcodec/bsf.h
+++ b/libavcodec/bsf.h
@@ -64,6 +64,9 @@
  * The fields in the struct will only be changed (by the caller or by the
  * filter) as described in their documentation, and are to be considered
  * immutable otherwise.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVBSFContext {
     /**
diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
index 27f40e5519..686974b083 100644
--- a/libavcodec/d3d11va.h
+++ b/libavcodec/d3d11va.h
@@ -52,6 +52,9 @@
  * The application must make it available as AVCodecContext.hwaccel_context.
  *
  * Use av_d3d11va_alloc_context() exclusively to allocate an AVD3D11VAContext.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVD3D11VAContext {
     /**
diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
index 4e9b56a618..43f049a609 100644
--- a/libavcodec/mediacodec.h
+++ b/libavcodec/mediacodec.h
@@ -29,6 +29,8 @@
  * This structure holds a reference to a android/view/Surface object that will
  * be used as output by the decoder.
  *
+ * @see
+ * - @ref Context
  */
 typedef struct AVMediaCodecContext {
 
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index c156b08d07..8ab93af6b6 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -32,6 +32,9 @@
  * - decoding: hwaccel_context must be set on return from the get_format()
  *             callback
  * - encoding: hwaccel_context must be set before avcodec_open2()
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVQSVContext {
     /**
diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
index 8021c25761..934c96b88c 100644
--- a/libavcodec/vdpau.h
+++ b/libavcodec/vdpau.h
@@ -74,6 +74,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
  *
  * The size of this structure is not a part of the public ABI and must not
  * be used outside of libavcodec.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVDPAUContext {
     /**
diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
index d68d76e400..81d90d63b6 100644
--- a/libavcodec/videotoolbox.h
+++ b/libavcodec/videotoolbox.h
@@ -53,6 +53,9 @@
  * between the caller and libavcodec for initializing Videotoolbox decoding.
  * Its size is not a part of the public ABI, it must be allocated with
  * av_videotoolbox_alloc_context() and freed with av_free().
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVideotoolboxContext {
     /**
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index a34e61f23c..25ccd80433 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -403,7 +403,12 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
  */
 #define AVFILTER_THREAD_SLICE (1 << 0)
 
-/** An instance of a filter */
+/**
+ * An instance of a filter
+ *
+ * @see
+ * - @ref Context
+ */
 struct AVFilterContext {
     const AVClass *av_class;        ///< needed for av_log() and filters common options
 
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 8afdcd9fd0..18f20f0bb0 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1253,6 +1253,9 @@ enum AVDurationEstimationMethod {
  * can be found in libavformat/options_table.h.
  * The AVOption/command line parameter names differ in some cases from the C
  * structure field names for historic reasons or brevity.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVFormatContext {
     /**
diff --git a/libavformat/avio.h b/libavformat/avio.h
index ebf611187d..d68f912a2f 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -156,6 +156,9 @@ enum AVIODataMarkerType {
  *       directly, they should only be set by the client application
  *       when implementing custom I/O. Normally these are set to the
  *       function pointers specified in avio_alloc_context()
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVIOContext {
     /**
diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h
index fa5f59a2be..6fdb114af8 100644
--- a/libavutil/audio_fifo.h
+++ b/libavutil/audio_fifo.h
@@ -44,6 +44,9 @@
  * - Operates at the sample level rather than the byte level.
  * - Supports multiple channels with either planar or packed sample format.
  * - Automatic reallocation when writing to a full buffer.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVAudioFifo AVAudioFifo;
 
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index bac30debae..6bbb96fcd6 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -56,6 +56,9 @@ enum AVHWDeviceType {
  * references are released, the AVHWDeviceContext itself will be freed,
  * optionally invoking a user-specified callback for uninitializing the hardware
  * state.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVHWDeviceContext {
     /**
@@ -111,6 +114,9 @@ typedef struct AVHWDeviceContext {
  * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
  * yields a reference, whose data field points to the actual AVHWFramesContext
  * struct.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVHWFramesContext {
     /**
diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
index cbad434fea..0db5a69f0a 100644
--- a/libavutil/hwcontext_cuda.h
+++ b/libavutil/hwcontext_cuda.h
@@ -38,6 +38,9 @@ typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
 
 /**
  * This struct is allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVCUDADeviceContext {
     CUcontext cuda_ctx;
diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
index 77d2d72f1b..5b7763e73f 100644
--- a/libavutil/hwcontext_d3d11va.h
+++ b/libavutil/hwcontext_d3d11va.h
@@ -41,6 +41,9 @@
 
 /**
  * This struct is allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVD3D11VADeviceContext {
     /**
@@ -127,6 +130,9 @@ typedef struct AVD3D11FrameDescriptor {
 
 /**
  * This struct is allocated as AVHWFramesContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVD3D11VAFramesContext {
     /**
diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
index ff06e6f2ef..63281aa835 100644
--- a/libavutil/hwcontext_d3d12va.h
+++ b/libavutil/hwcontext_d3d12va.h
@@ -39,6 +39,8 @@
 /**
  * @brief This struct is allocated as AVHWDeviceContext.hwctx
  *
+ * @see
+ * - @ref Context
  */
 typedef struct AVD3D12VADeviceContext {
     /**
@@ -80,6 +82,8 @@ typedef struct AVD3D12VADeviceContext {
 /**
  * @brief This struct is used to sync d3d12 execution
  *
+ * @see
+ * - @ref Context
  */
 typedef struct AVD3D12VASyncContext {
     /**
@@ -122,6 +126,8 @@ typedef struct AVD3D12VAFrame {
 /**
  * @brief This struct is allocated as AVHWFramesContext.hwctx
  *
+ * @see
+ * - @ref Context
  */
 typedef struct AVD3D12VAFramesContext {
     /**
diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
index 42709f215e..eb0b6e734a 100644
--- a/libavutil/hwcontext_drm.h
+++ b/libavutil/hwcontext_drm.h
@@ -153,6 +153,9 @@ typedef struct AVDRMFrameDescriptor {
  * DRM device.
  *
  * Allocated as AVHWDeviceContext.hwctx.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVDRMDeviceContext {
     /**
diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
index e1b79bc0de..3accd8d070 100644
--- a/libavutil/hwcontext_dxva2.h
+++ b/libavutil/hwcontext_dxva2.h
@@ -35,6 +35,9 @@
 
 /**
  * This struct is allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVDXVA2DeviceContext {
     IDirect3DDeviceManager9 *devmgr;
@@ -42,6 +45,9 @@ typedef struct AVDXVA2DeviceContext {
 
 /**
  * This struct is allocated as AVHWFramesContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVDXVA2FramesContext {
     /**
diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
index fc0263cabc..77d7d4e3a5 100644
--- a/libavutil/hwcontext_mediacodec.h
+++ b/libavutil/hwcontext_mediacodec.h
@@ -23,6 +23,9 @@
  * MediaCodec details.
  *
  * Allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVMediaCodecDeviceContext {
     /**
diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
index ef54486c95..4c184484c9 100644
--- a/libavutil/hwcontext_opencl.h
+++ b/libavutil/hwcontext_opencl.h
@@ -59,6 +59,9 @@ typedef struct AVOpenCLFrameDescriptor {
  * OpenCL device details.
  *
  * Allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVOpenCLDeviceContext {
     /**
@@ -85,6 +88,9 @@ typedef struct AVOpenCLDeviceContext {
  * OpenCL-specific data associated with a frame pool.
  *
  * Allocated as AVHWFramesContext.hwctx.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVOpenCLFramesContext {
     /**
diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
index 35530e4e93..b4a84c9893 100644
--- a/libavutil/hwcontext_qsv.h
+++ b/libavutil/hwcontext_qsv.h
@@ -31,6 +31,9 @@
 
 /**
  * This struct is allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVQSVDeviceContext {
     mfxSession session;
@@ -49,6 +52,9 @@ typedef struct AVQSVDeviceContext {
 
 /**
  * This struct is allocated as AVHWFramesContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVQSVFramesContext {
     /**
diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
index 0b2e071cb3..02399ff7dc 100644
--- a/libavutil/hwcontext_vaapi.h
+++ b/libavutil/hwcontext_vaapi.h
@@ -64,6 +64,9 @@ enum {
  * VAAPI connection details.
  *
  * Allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVAAPIDeviceContext {
     /**
@@ -84,6 +87,9 @@ typedef struct AVVAAPIDeviceContext {
  * VAAPI-specific data associated with a frame pool.
  *
  * Allocated as AVHWFramesContext.hwctx.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVAAPIFramesContext {
     /**
diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
index 1b7ea1e443..051af42dfc 100644
--- a/libavutil/hwcontext_vdpau.h
+++ b/libavutil/hwcontext_vdpau.h
@@ -31,6 +31,9 @@
 
 /**
  * This struct is allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVDPAUDeviceContext {
     VdpDevice          device;
diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
index cbbd2390c1..6dfe4badfe 100644
--- a/libavutil/hwcontext_vulkan.h
+++ b/libavutil/hwcontext_vulkan.h
@@ -41,6 +41,9 @@ typedef struct AVVkFrame AVVkFrame;
 /**
  * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
  * All of these can be set before init to change what the context uses
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVulkanDeviceContext {
     /**
@@ -173,6 +176,9 @@ typedef enum AVVkFrameFlags {
 
 /**
  * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVulkanFramesContext {
     /**
diff --git a/libavutil/lfg.h b/libavutil/lfg.h
index e75a986f12..4e420b0e16 100644
--- a/libavutil/lfg.h
+++ b/libavutil/lfg.h
@@ -29,6 +29,9 @@
  * The exact layout, types and content of this struct may change and should
  * not be accessed directly. Only its `sizeof()` is guaranteed to stay the same
  * to allow easy instanciation.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVLFG {
     unsigned int state[64];
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v5 4/4] all: Rewrite documentation for contexts
  2024-05-23 20:00       ` [FFmpeg-devel] [PATCH v5 0/4] " Andrew Sayers
                           ` (2 preceding siblings ...)
  2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 3/4] all: Link to "context" from all public contexts with documentation Andrew Sayers
@ 2024-05-23 20:00         ` Andrew Sayers
  2024-05-24  1:50         ` [FFmpeg-devel] [PATCH v5 0/4] Explain what "context" means Michael Niedermayer
  4 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-23 20:00 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Make their documentation more readable and similar to each other,
(hopefully) without changing the meaning.
---
 libavcodec/aac/aacdec.h          |  2 +-
 libavcodec/aacenc.h              |  2 +-
 libavcodec/ac3enc.h              |  2 +-
 libavcodec/amfenc.h              |  2 +-
 libavcodec/atrac.h               |  2 +-
 libavcodec/avcodec.h             |  3 ++-
 libavcodec/bsf.h                 |  2 +-
 libavcodec/cbs.h                 |  2 +-
 libavcodec/d3d11va.h             |  3 +--
 libavcodec/mediacodec.h          |  4 ++--
 libavcodec/pthread_frame.c       |  4 ++--
 libavcodec/qsv.h                 |  6 ++++--
 libavcodec/sbr.h                 |  2 +-
 libavcodec/vdpau.h               |  5 +++--
 libavcodec/videotoolbox.h        |  5 +++--
 libavfilter/avfilter.h           |  2 +-
 libavformat/avformat.h           |  3 ++-
 libavformat/avio.h               |  3 ++-
 libavutil/audio_fifo.h           |  2 +-
 libavutil/hwcontext.h            | 21 ++++++++++++---------
 libavutil/hwcontext_cuda.h       |  2 +-
 libavutil/hwcontext_d3d11va.h    |  4 ++--
 libavutil/hwcontext_d3d12va.h    |  6 +++---
 libavutil/hwcontext_drm.h        |  2 +-
 libavutil/hwcontext_dxva2.h      |  4 ++--
 libavutil/hwcontext_mediacodec.h |  2 +-
 libavutil/hwcontext_opencl.h     |  4 ++--
 libavutil/hwcontext_qsv.h        |  4 ++--
 libavutil/hwcontext_vaapi.h      |  4 ++--
 libavutil/hwcontext_vdpau.h      |  2 +-
 libavutil/hwcontext_vulkan.h     |  5 +++--
 libavutil/lfg.h                  |  3 ++-
 32 files changed, 65 insertions(+), 54 deletions(-)

diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
index eed53c6c96..87a834797d 100644
--- a/libavcodec/aac/aacdec.h
+++ b/libavcodec/aac/aacdec.h
@@ -253,7 +253,7 @@ typedef struct AACDecDSP {
 } AACDecDSP;
 
 /**
- * main AAC decoding context
+ * Context for decoding AAC
  */
 struct AACDecContext {
     const struct AVClass  *class;
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index d07960620e..3e710c7fac 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -207,7 +207,7 @@ typedef struct AACPCEInfo {
 } AACPCEInfo;
 
 /**
- * AAC encoder context
+ * Context for encoding AAC
  */
 typedef struct AACEncContext {
     AVClass *av_class;
diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
index 5e98ad188b..e5abe0a856 100644
--- a/libavcodec/ac3enc.h
+++ b/libavcodec/ac3enc.h
@@ -153,7 +153,7 @@ typedef struct AC3Block {
 struct PutBitContext;
 
 /**
- * AC-3 encoder private context.
+ * Private context for encoding AC-3
  */
 typedef struct AC3EncodeContext {
     AVClass *av_class;                      ///< AVClass used for AVOption
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
index 2dbd378ef8..184897beeb 100644
--- a/libavcodec/amfenc.h
+++ b/libavcodec/amfenc.h
@@ -43,7 +43,7 @@ typedef struct AmfTraceWriter {
 } AmfTraceWriter;
 
 /**
-* AMF encoder context
+* Context for encoding AMF
 */
 
 typedef struct AmfContext {
diff --git a/libavcodec/atrac.h b/libavcodec/atrac.h
index 05208bbee6..e760f0384d 100644
--- a/libavcodec/atrac.h
+++ b/libavcodec/atrac.h
@@ -39,7 +39,7 @@ typedef struct AtracGainInfo {
 } AtracGainInfo;
 
 /**
- *  Gain compensation context structure.
+ *  Context for gain compensation
  */
 typedef struct AtracGCContext {
     float   gain_tab1[16];  ///< gain compensation level table
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index abc00ab394..2fed4757ed 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -430,7 +430,8 @@ typedef struct RcOverride{
 #define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0)
 
 /**
- * main external API structure.
+ * Context for an encode or decode session
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
index ee5fdd48d2..fadcfc5d47 100644
--- a/libavcodec/bsf.h
+++ b/libavcodec/bsf.h
@@ -56,7 +56,7 @@
  */
 
 /**
- * The bitstream filter state.
+ * Context for bitstream filtering
  *
  * This struct must be allocated with av_bsf_alloc() and freed with
  * av_bsf_free().
diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
index d479b1ac2d..c074dd11ec 100644
--- a/libavcodec/cbs.h
+++ b/libavcodec/cbs.h
@@ -214,7 +214,7 @@ typedef void (*CBSTraceWriteCallback)(void *trace_context,
                                       int64_t value);
 
 /**
- * Context structure for coded bitstream operations.
+ * Context for coded bitstream operations
  */
 typedef struct CodedBitstreamContext {
     /**
diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
index 686974b083..5ffee2b3be 100644
--- a/libavcodec/d3d11va.h
+++ b/libavcodec/d3d11va.h
@@ -46,8 +46,7 @@
  */
 
 /**
- * This structure is used to provides the necessary configurations and data
- * to the Direct3D11 FFmpeg HWAccel implementation.
+ * Context for the Direct3D11 FFmpeg HWAccel implementation
  *
  * The application must make it available as AVCodecContext.hwaccel_context.
  *
diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
index 43f049a609..49af9513b0 100644
--- a/libavcodec/mediacodec.h
+++ b/libavcodec/mediacodec.h
@@ -26,8 +26,8 @@
 #include "libavcodec/avcodec.h"
 
 /**
- * This structure holds a reference to a android/view/Surface object that will
- * be used as output by the decoder.
+ * Context for the android/view/Surface object that will
+ * be used as output by the decoder
  *
  * @see
  * - @ref Context
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 982e4a64c5..c462159022 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -69,7 +69,7 @@ typedef struct ThreadFrameProgress {
 } ThreadFrameProgress;
 
 /**
- * Context used by codec threads and stored in their AVCodecInternal thread_ctx.
+ * Context used by codec threads and allocated as AVCodecInternal.thread_ctx
  */
 typedef struct PerThreadContext {
     struct FrameThreadContext *parent;
@@ -113,7 +113,7 @@ typedef struct PerThreadContext {
 } PerThreadContext;
 
 /**
- * Context stored in the client AVCodecInternal thread_ctx.
+ * Context allocated as AVCodecInternal.thread_ctx
  */
 typedef struct FrameThreadContext {
     PerThreadContext *threads;     ///< The contexts for each thread.
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index 8ab93af6b6..9d36197fbf 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -26,8 +26,10 @@
 #include "libavutil/buffer.h"
 
 /**
- * This struct is used for communicating QSV parameters between libavcodec and
- * the caller. It is managed by the caller and must be assigned to
+ * Context for communicating QSV parameters between libavcodec
+ * and the caller.
+ *
+ * It is managed by the caller and must be assigned to
  * AVCodecContext.hwaccel_context.
  * - decoding: hwaccel_context must be set on return from the get_format()
  *             callback
diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
index fe3a39603a..ea0760776c 100644
--- a/libavcodec/sbr.h
+++ b/libavcodec/sbr.h
@@ -116,7 +116,7 @@ typedef struct SBRData {
 typedef struct SpectralBandReplication SpectralBandReplication;
 
 /**
- * aacsbr functions pointers
+ * Context for aacsbr functions
  */
 typedef struct AACSBRContext {
     int (*sbr_lf_gen)(SpectralBandReplication *sbr,
diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
index 934c96b88c..e20f37ef2a 100644
--- a/libavcodec/vdpau.h
+++ b/libavcodec/vdpau.h
@@ -64,8 +64,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
                                const VdpBitstreamBuffer *);
 
 /**
- * This structure is used to share data between the libavcodec library and
- * the client video application.
+ * Context to share data between the libavcodec library and
+ * the client video application
+ *
  * This structure will be allocated and stored in AVCodecContext.hwaccel_context
  * by av_vdpau_bind_context(). Members can be set by the user once
  * during initialization or through each AVCodecContext.get_buffer()
diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
index 81d90d63b6..dfc5c1a5a5 100644
--- a/libavcodec/videotoolbox.h
+++ b/libavcodec/videotoolbox.h
@@ -49,8 +49,9 @@
 #include "libavutil/attributes.h"
 
 /**
- * This struct holds all the information that needs to be passed
- * between the caller and libavcodec for initializing Videotoolbox decoding.
+ * Context for information passed between the caller and libavcodec
+ * for initializing Videotoolbox decoding
+ *
  * Its size is not a part of the public ABI, it must be allocated with
  * av_videotoolbox_alloc_context() and freed with av_free().
  *
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 25ccd80433..15aaba6ea2 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -404,7 +404,7 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
 #define AVFILTER_THREAD_SLICE (1 << 0)
 
 /**
- * An instance of a filter
+ * Context for a filter
  *
  * @see
  * - @ref Context
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 18f20f0bb0..d8abab56d8 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1241,7 +1241,8 @@ enum AVDurationEstimationMethod {
 };
 
 /**
- * Format I/O context.
+ * Context for format I/O
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavformat/avio.h b/libavformat/avio.h
index d68f912a2f..bf017f1338 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -146,7 +146,8 @@ enum AVIODataMarkerType {
 };
 
 /**
- * Bytestream IO Context.
+ * Context for bytestream I/O
+ *
  * New public fields can be added with minor version bumps.
  * Removal, reordering and changes to existing public fields require
  * a major version bump.
diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h
index 6fdb114af8..ab56ef69f5 100644
--- a/libavutil/audio_fifo.h
+++ b/libavutil/audio_fifo.h
@@ -39,7 +39,7 @@
  */
 
 /**
- * Context for an Audio FIFO Buffer.
+ * Context for an Audio FIFO Buffer
  *
  * - Operates at the sample level rather than the byte level.
  * - Supports multiple channels with either planar or packed sample format.
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index 6bbb96fcd6..18d25a644c 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -41,12 +41,13 @@ enum AVHWDeviceType {
 };
 
 /**
- * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
- * i.e. state that is not tied to a concrete processing configuration.
- * E.g., in an API that supports hardware-accelerated encoding and decoding,
- * this struct will (if possible) wrap the state that is common to both encoding
- * and decoding and from which specific instances of encoders or decoders can be
- * derived.
+ * Context for (hardware/vendor-specific) "high-level" state
+ *
+ * "High-level state" is anything that is not tied to a concrete processing
+ * configuration. E.g., in an API that supports hardware-accelerated encoding
+ * and decoding, this struct will (if possible) wrap the state that is common
+ * to both encoding and decoding and from which specific instances of encoders
+ * or decoders can be derived.
  *
  * This struct is reference-counted with the AVBuffer mechanism. The
  * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
@@ -106,9 +107,11 @@ typedef struct AVHWDeviceContext {
 } AVHWDeviceContext;
 
 /**
- * This struct describes a set or pool of "hardware" frames (i.e. those with
- * data not located in normal system memory). All the frames in the pool are
- * assumed to be allocated in the same way and interchangeable.
+ * Context for a pool of "hardware" frames (those with data not located
+ * in normal system memory)
+ *
+ * All the frames in the pool are assumed to be allocated in the same way and
+ * interchangeable.
  *
  * This struct is reference-counted with the AVBuffer mechanism and tied to a
  * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
index 0db5a69f0a..bb380d5450 100644
--- a/libavutil/hwcontext_cuda.h
+++ b/libavutil/hwcontext_cuda.h
@@ -37,7 +37,7 @@
 typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
index 5b7763e73f..ce07f84450 100644
--- a/libavutil/hwcontext_d3d11va.h
+++ b/libavutil/hwcontext_d3d11va.h
@@ -40,7 +40,7 @@
 #include <stdint.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
@@ -129,7 +129,7 @@ typedef struct AVD3D11FrameDescriptor {
 } AVD3D11FrameDescriptor;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * Context allocated as AVHWFramesContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
index 63281aa835..f741fc00e8 100644
--- a/libavutil/hwcontext_d3d12va.h
+++ b/libavutil/hwcontext_d3d12va.h
@@ -37,7 +37,7 @@
 #include <d3d12video.h>
 
 /**
- * @brief This struct is allocated as AVHWDeviceContext.hwctx
+ * @brief Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
@@ -80,7 +80,7 @@ typedef struct AVD3D12VADeviceContext {
 } AVD3D12VADeviceContext;
 
 /**
- * @brief This struct is used to sync d3d12 execution
+ * @brief Context for syncing d3d12 execution
  *
  * @see
  * - @ref Context
@@ -124,7 +124,7 @@ typedef struct AVD3D12VAFrame {
 } AVD3D12VAFrame;
 
 /**
- * @brief This struct is allocated as AVHWFramesContext.hwctx
+ * @brief Context allocated as AVHWFramesContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
index eb0b6e734a..f8aa75c5cf 100644
--- a/libavutil/hwcontext_drm.h
+++ b/libavutil/hwcontext_drm.h
@@ -152,7 +152,7 @@ typedef struct AVDRMFrameDescriptor {
 /**
  * DRM device.
  *
- * Allocated as AVHWDeviceContext.hwctx.
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
index 3accd8d070..a2320ea18a 100644
--- a/libavutil/hwcontext_dxva2.h
+++ b/libavutil/hwcontext_dxva2.h
@@ -34,7 +34,7 @@
 #include <dxva2api.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
@@ -44,7 +44,7 @@ typedef struct AVDXVA2DeviceContext {
 } AVDXVA2DeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * Context allocated as AVHWFramesContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
index 77d7d4e3a5..ada61fa61e 100644
--- a/libavutil/hwcontext_mediacodec.h
+++ b/libavutil/hwcontext_mediacodec.h
@@ -22,7 +22,7 @@
 /**
  * MediaCodec details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
index 4c184484c9..0c3ef04fc6 100644
--- a/libavutil/hwcontext_opencl.h
+++ b/libavutil/hwcontext_opencl.h
@@ -58,7 +58,7 @@ typedef struct AVOpenCLFrameDescriptor {
 /**
  * OpenCL device details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
@@ -87,7 +87,7 @@ typedef struct AVOpenCLDeviceContext {
 /**
  * OpenCL-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * Context allocated as AVHWFramesContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
index b4a84c9893..afdddbce0e 100644
--- a/libavutil/hwcontext_qsv.h
+++ b/libavutil/hwcontext_qsv.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
@@ -51,7 +51,7 @@ typedef struct AVQSVDeviceContext {
 } AVQSVDeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * Context allocated as AVHWFramesContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
index 02399ff7dc..a6c1b25415 100644
--- a/libavutil/hwcontext_vaapi.h
+++ b/libavutil/hwcontext_vaapi.h
@@ -63,7 +63,7 @@ enum {
 /**
  * VAAPI connection details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
@@ -86,7 +86,7 @@ typedef struct AVVAAPIDeviceContext {
 /**
  * VAAPI-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * Context allocated as AVHWFramesContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
index 051af42dfc..a2e6fcf5ba 100644
--- a/libavutil/hwcontext_vdpau.h
+++ b/libavutil/hwcontext_vdpau.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
index 6dfe4badfe..3766546100 100644
--- a/libavutil/hwcontext_vulkan.h
+++ b/libavutil/hwcontext_vulkan.h
@@ -39,7 +39,8 @@ typedef struct AVVkFrame AVVkFrame;
  */
 
 /**
- * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
+ * Context for Vulkan, allocated as AVHWDeviceContext.hwctx
+ *
  * All of these can be set before init to change what the context uses
  *
  * @see
@@ -175,7 +176,7 @@ typedef enum AVVkFrameFlags {
 } AVVkFrameFlags;
 
 /**
- * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
+ * Context allocated as AVHWFramesContext.hwctx, used to set pool-specific options
  *
  * @see
  * - @ref Context
diff --git a/libavutil/lfg.h b/libavutil/lfg.h
index 4e420b0e16..4ee7834fe4 100644
--- a/libavutil/lfg.h
+++ b/libavutil/lfg.h
@@ -25,7 +25,8 @@
 #include <stdint.h>
 
 /**
- * Context structure for the Lagged Fibonacci PRNG.
+ * Context structure for the Lagged Fibonacci PRNG
+ *
  * The exact layout, types and content of this struct may change and should
  * not be accessed directly. Only its `sizeof()` is guaranteed to stay the same
  * to allow easy instanciation.
-- 
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v5 0/4] Explain what "context" means
  2024-05-23 20:00       ` [FFmpeg-devel] [PATCH v5 0/4] " Andrew Sayers
                           ` (3 preceding siblings ...)
  2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 4/4] all: Rewrite documentation for contexts Andrew Sayers
@ 2024-05-24  1:50         ` Michael Niedermayer
  2024-05-24  9:43           ` Andrew Sayers
  4 siblings, 1 reply; 84+ messages in thread
From: Michael Niedermayer @ 2024-05-24  1:50 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 2153 bytes --]

On Thu, May 23, 2024 at 09:00:39PM +0100, Andrew Sayers wrote:
> NOTE: this patchset depends on [1], and should not be applied before that.
> 
> I think it's important to guide readers between parts of FFmpeg, because
> learning how the pieces of the puzzle fit together is a big part of the
> newbie experience.  So this patchset replaces the "@ref Context for foo"
> statements in public structs with "@see" blocks, giving us a hook we can
> hang more links on in future.
> 
> That said, there's a rule against internal links from private structs,
> so I've removed the @ref's from them.  By the way, is this rule written
> somewhere?  If not, where would be a good place to write it?
> And either way, it would be good to link to this as part of [2].
> 
> Previous patches had to change the language for many structs, but "@see" blocks
> avoid the need to include those changes in this patchset.  Rather than waste
> that work, I've temporarily moved those changes to the final patch in this set.
> My feelings about that last patch aren't strong, but I guess I'll propose them
> in a separate thread unless anyone wants them here or chucked altogether.
> 
> 
> I've rewritten AVOptions and AVClass based on feedback.  The new version
> reflects a hypothetical that's been going round my head all week...
> 
> Imagine you wanted to write a system that nudged people to try new codecs.
> It might say e.g. "you seem to be using H.264, would you like to try H.265?"
> Implementing that would probably involve a struct like:
> 
> struct AVOldNew {
>   AVClass* old;
>   AVClass* new;
> };

AVClass would describe the internal decoder structures. This would not be
correct at all in this example.
Thats like handing a man 2 CAD documents about 2 engines of 2 cars

If you wanted to suggest to get a tesla instead of a ford. One would have to
describe the 2 cars and their differences
thats 2 AVCodecDescriptor maybe

thx

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

It is a danger to trust the dream we wish for rather than
the science we have, -- Dr. Kenneth Brown

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v5 0/4] Explain what "context" means
  2024-05-24  1:50         ` [FFmpeg-devel] [PATCH v5 0/4] Explain what "context" means Michael Niedermayer
@ 2024-05-24  9:43           ` Andrew Sayers
  0 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-24  9:43 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Fri, May 24, 2024 at 03:50:52AM +0200, Michael Niedermayer wrote:
> On Thu, May 23, 2024 at 09:00:39PM +0100, Andrew Sayers wrote:
<snip>
> > Imagine you wanted to write a system that nudged people to try new codecs.
> > It might say e.g. "you seem to be using H.264, would you like to try H.265?"
> > Implementing that would probably involve a struct like:
> > 
> > struct AVOldNew {
> >   AVClass* old;
> >   AVClass* new;
> > };
> 
> AVClass would describe the internal decoder structures. This would not be
> correct at all in this example.
> Thats like handing a man 2 CAD documents about 2 engines of 2 cars
> 
> If you wanted to suggest to get a tesla instead of a ford. One would have to
> describe the 2 cars and their differences
> thats 2 AVCodecDescriptor maybe

Hmm, yes fair point.  A better example might be a simple linked list:

struct AVClassList {
    AVClass* cur;
    AVClassList* next;
};

Again, that clearly is a struct that begins with AVClass*, but clearly isn't an
AVClass context structure.

I realise it's a bit of an academic distinction, but IMHO these hypotheticals
suggest it's more accurate to define the term "AVClass context structure"
in terms of usage rather than layout.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means
  2024-05-22 12:47                         ` Andrew Sayers
@ 2024-05-25  9:00                           ` Stefano Sabatini
  0 siblings, 0 replies; 84+ messages in thread
From: Stefano Sabatini @ 2024-05-25  9:00 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On date Wednesday 2024-05-22 13:47:36 +0100, Andrew Sayers wrote:
> On Wed, May 22, 2024 at 12:37:37PM +0200, Stefano Sabatini wrote:
> > On date Sunday 2024-05-05 22:04:36 +0100, Andrew Sayers wrote:
> > > I'm still travelling, so the following thoughts might be a bit
> > > half-formed.  But I wanted to get some feedback before sitting down
> > > for a proper think.
> > [...]
> > > > > I've also gone through the code looking for edge cases we haven't covered.
> > > > > Here are some questions trying to prompt an "oh yeah I forgot to mention
> > > > > that"-type answer.  Anything where the answer is more like "that should
> > > > > probably be rewritten to be clearer", let me know and I'll avoid confusing
> > > > > newbies with it.
> > > > > 
> > > > 
> > > > > av_ambient_viewing_environment_create_side_data() takes an AVFrame as its
> > > > > first argument, and returns a new AVAmbientViewingEnvironment.  What is the
> > > > > context object for that function - AVFrame or AVAmbientViewingEnvironment?
> > > > 
> > > > But this should be clear from the doxy:
> > > > 
> > > > /**
> > > >  * Allocate and add an AVAmbientViewingEnvironment structure to an existing
> > > >  * AVFrame as side data.
> > > >  *
> > > >  * @return the newly allocated struct, or NULL on failure
> > > >  */
> > > > AVAmbientViewingEnvironment *av_ambient_viewing_environment_create_side_data(AVFrame *frame);
> > > 
> > > I'm afraid it's not clear, at least to me.  I think you're saying the
> > > AVFrame is the context because a "create" function can't have a
> > > context any more than a C++ "new" can be called as a member.  But the
> > > function's prefix points to the other conclusion, and neither signal
> > > is clear enough on its own.
> > 
> > No, what I'm saying is that in some cases you don't need to think in
> > terms of contexts, in this case there is no context at all, the
> > function takes a frame and modify it, and returns the ambient
> > environment to be used by the following functions. This should be very
> > clear by reading the doxy. There is no rule dictating the first param
> > of each FFmpeg function should be a "context".
> 
> I'm still writing up a reply to your longer feedback, but on this topic...
> 

> This function is in the "av_ambient_viewing_environment" namespace, and returns
> an object that is clearly used as a context for other functions.  So saying
> "stop thinking about contexts" just leaves a negative space and a bad thing
> to fill it with (confusion in my case).

>av_ambient_viewing_environment_create_side_data() takes an AVFrame as its
>first argument, and returns a new AVAmbientViewingEnvironment.  What is the
>context object for that function - AVFrame or AVAmbientViewingEnvironment?

av_ambient_viewing_environment_ defines the namespace. In this case we
are not using the av_frame_ API since we want to have all the ambient
API defined in a single place.

Alternatively we might have extended the av_frame API (e.g. 
av_frame_create_ambient_viewing_environment_side_data()), but we
wanted to avoid to reference the ambient API in the minimal frame API,
so this approach makes perfect sense to me and I cannot see major
inconsistencies.

You can think about it in terms of a static or class constructor
function, where AVFrame is simply an argument of the contructor.

What is the approach that you would have expected in this case?
 
> I've found it useful to think about "receiving" vs. "producing" a context:
> 
> * avcodec_alloc_context3() produces a context, but does not receive one
> * sws_init_context() receives a context, but does not produce one
> * av_ambient_viewing_environment_create_side_data() receives one context,
>   and produces another
> 
> How about if the document mostly talks about functions as having contexts,
> then follows it up with something like:
> 
>     There are some edge cases where this doesn't work.  <examples>.
>     If you find contexts a useful metaphor in these cases, you might
>     prefer to think about them as "receiving" and "producing" contexts.
> 
> ... or something similar that acknowledges contexts are unnecessary here,
> but provides a solution for people that want to use them anyway.

I see, but I still see an excessive use of the context concept in
place of the simpler and more natural use of parameters (in this case
AVFrame is simply the input element), and this scheme is pretty common
in C APIs (note that ambient is a simple structure, no need to use
AVClass or options for this simple struct), so I see no need to tag
this as an edge case.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-05-22 16:07       ` Andrew Sayers
@ 2024-05-25  9:49         ` Stefano Sabatini
  2024-05-26 12:06           ` Andrew Sayers
  0 siblings, 1 reply; 84+ messages in thread
From: Stefano Sabatini @ 2024-05-25  9:49 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On date Wednesday 2024-05-22 17:07:51 +0100, Andrew Sayers wrote:
[...]
> > > diff --git a/doc/context.md b/doc/context.md
> > > new file mode 100644
> > > index 0000000000..fb85b3f366
> > > --- /dev/null
> > > +++ b/doc/context.md
> > > @@ -0,0 +1,394 @@
> > > +# Introduction to contexts
> > > +
> > > +&ldquo;%Context&rdquo;
> > 
> > Is this style of quoting needed? Especially I'd avoid special markup
> > to simplify unredendered text reading (which is the point of markdown
> > afterall).
> 
> Short answer: I'll change it in the next patch and see what happens.
> 
> Long answer: HTML quotes are ugly for everyone, UTF-8 is great until someone
> turns up complaining we broke their Latin-1 workflow.  I've always preferred
> ASCII-only representations for that reason, but happy to try the other way
> and see if anyone still cares.

I think it's safe to assume UTF-8 as the default nowadays, and every
other encoding broken in same way. Latin-1 is assumed probably only by
a minor group of FFmpeg users.
 
> > 
> > > is a name for a widely-used programming idiom.
> > 
> > > +This document explains the general idiom and the conventions FFmpeg has built around it.
> > > +
> > > +This document uses object-oriented analogies to help readers familiar with
> > > +[object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming)
> > > +learn about contexts.  But contexts can also be used outside of OOP,
> > > +and even in situations where OOP isn't helpful.  So these analogies
> > > +should only be used as a first step towards understanding contexts.
> > > +
> > > +## &ldquo;Context&rdquo; as a way to think about code
> > > +
> > > +A context is any data structure that is passed to several functions
> > > +(or several instances of the same function) that all operate on the same entity.
> > > +For example, [object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming)
> > > +languages usually provide member functions with a `this` or `self` value:
> > > +
> > 
> > > +```c
> > > +class my_cxx_class {
> > > +  void my_member_function() {
> > > +    // the implicit object parameter provides context for the member function:
> > > +    std::cout << this;
> > > +  }
> > > +};
> > > +```
> > 
> > I'm not convinced this is really useful: if you know C++ this is
> > redundant, if you don't this is confusing and don't add much information.
> 
> The example is there to break up a wall of text (syntax-highlighted in the
> rendered output), and to let the reader know that this is going to be one of
> those documents that alternates between text and code, so they're ready for the
> more substantive examples later on.  I take the point about C++ though -
> would this Python example be more readable?
> 
>     class MyClass:
>         def my_func(self):
>             # If a Python function is part of a class,
>             # its first parameter must be an instance of that class
> 

But again, this is redundnat if you know Python, otherwise is not very
helpful if you don't. In this case probably it's good just to keep the
mention to self/this, without a specific example.

> > 
> > > +
> > > +Contexts are a fundamental building block of OOP, but can also be used in procedural code.
> > 
> > I'd drop this line, and drop the anchor on OOP at the same time since
> > it's adding no much information.
> 
> Fundamentally, this document addresses two audiences:
> 
> 1. people coming from a non-OOP background, who want to learn contexts
>    from first principles, and at best see OOP stuff as background information
> 
> 2. people coming from an OOP background.  There's no polite way to say this -
>    their incentive is to write FFmpeg off as a failed attempt at OOP, so they
>    don't have to learn a new way of working that's just different enough to
>    make them feel dumb
> 
> I think a good way to evaluate the document might be to read it through twice,
> stopping after each paragraph to ask two unfair questions...
> 
> 1. what has this told me about FFmpeg itself, as opposed to some other thing
>    you wish I cared about?
> 
> 2. couldn't you have just done this the standard OOP way?
> 
> The earlier paragraph acknowledged that contexts resemble OOP (telling the OOP
> audience we get it), then this paragraph adds "but they're not the same"
> (telling the OOP audience we disagree).  To be more useful to non-OOP folk,
> how about:
> 

>     Contexts can be a fundamental building block of OOP, but can also be used in
>     procedural projects like FFmpeg.

What perplexes me is that "context" is not part of the standard OOP
jargon, so this is probably adding more to the confusion. I think the
target here is to clarify what context is meant for in FFmpeg, and
this can be simply defined without any reference to OOP:

|A context is a structure used to contain data (allocated memory,
|configuration, and/or state) for operations working on the same
|entity.

As such a context is just a glorified struct referecenced by a set of
functions operating on them, with the convention (common in most C
APIs) that this is the first argument of these functions.

Then we have AVClass+log+options as a trick to define common
functionality for the most complex "contexts".

This is also why I'm concerned with the idea of explainig this with a
strong focus on OOP: the effect is that the reader not familiar with
OOP is convinced that she needs to be familiar with OOP to understand
it (which is not the case). That's also why I'm in favor of having a
comparison with OOP in a dedicated section: this might help the
OOP-minded reader, and might be skipped by the other ones.

[...]
> > I'm not very convinced by the callback example. The use of contexts in
> > the FFmpeg API is very much simpler, it is used to keep track of
> > configuration and state (that is they track the "object" where to
> > operate on), so the callback example here is a bit misleading.
> > 
> > Callbacks are used in the internals to implement different elements
> > (codecs, protocols, filters, etc...) implementing a common API, but in
> > this case the relation with "contexts" is less straightforward.
> 
> I go back and forth on this one, but your point made me think about it
> in a new way...
> 

> AVIOContext::read_packet is a callback function, and a reader who has just
> learnt about contexts would naturally assume we intend its first argument
> to be interpreted as a context.  Given that new readers are likely to learn
> avio_alloc_context() around the same time as reading this document,
> it's important we give them the tools to understand that function.
> 
> How about changing the topmost callback example to read data from a FILE*
> (without mentioning AVIOContext), then emphasising how you can think of it
> as a context despite not following FFmpeg's rules, then finally mentioning
> how you could pass the callback to avio_alloc_context() if you wanted?

Let's discuss this in the context of the new patch.

> > > +@warning Guaranteeing to use contexts does not mean guaranteeing to use
> > > +object-oriented programming.  For example, FFmpeg creates its contexts
> > > +procedurally instead of with constructors.
> > 
> > I'm afraid this is more confusing than helpful, since the FFmpeg API
> > is not OOP. I'd drop this sentence.
> 
> My concern is that if an OOP reader asks "couldn't you have just done this
> the standard OOP way?", they will be tempted to answer "oh, so you *used to*
> fail at OOP but nowadays you promise to do it right", and not bother reading
> any further.  So there needs to be something eye-catching here, but yes this
> paragraph needs to be more useful to non-OOP readers.

If you write:
> FFmpeg creates its contexts procedurally instead of with constructors.

then I don't know what this means, since there are no explicit
"contructors" in plain C as they are not part of the language
(although you can mimic constructors using special conventions, but
this is something built on top of the language).

>[...]
> This will probably need to be rewritten based on the callback discussion,
> so I'll think about ways to change this at the same time.
> > > +Curl's struct is declared as `struct <type> { ... }`, whereas FFmpeg uses
> > > +`typedef struct <type> { ... } <type>`.  These conventions are used with both
> > > +context and non-context structs, so don't say anything about contexts as such.
> > > +Specifically, FFmpeg's convention is a workaround for an issue with C grammar:
> > > +
> > > +```c
> > > +void my_function( ... ) {
> > > +  int                my_var;        // good
> > > +  MD5_context        my_curl_ctx;   // error: C needs you to explicitly say "struct"
> > > +  struct MD5_context my_curl_ctx;   // good: added "struct"
> > > +  AVMD5              my_ffmpeg_ctx; // good: typedef's avoid the need for "struct"
> > > +}
> > > +```
> > > +
> > > +Both MD5 implementations are long-tested, widely-used examples of contexts
> > > +in the real world.  They show how contexts can solve the same problem
> > > +in different ways.
> > 
> > I'm concerned that this is adding more information than really
> > needed. Especially comparing with internals of curl means that now the
> > docs needs to be kept in synch also with the curl's API, meaning that
> > it will be outdated very soon. I'd rather drop the curl comparison
> > altogether.
> 
> The value of this section depends on the reader...
> 
> This tells a non-OOP reader that FFmpeg didn't invent contexts, and reasonable
> people can disagree about what they mean.  So when we get into the ambiguous
> cases later on, they have a better idea about which things are just how
> contexts work, and which are specifically how FFmpeg uses them.
> 
> This tells an OOP reader that it's not "OOP standard, FFmpeg non-standard",
> it's that FFmpeg is using a C standard that's not used in OOP languages.
> 
> Curl's `MD5_context` was last modified in 2020 (interestingly, to get rid of
> the `typedef struct` trick).  It's a slow-moving target, but you're right it's
> not a static one.
> 
> I'd argue the above means this should be *somewhere* in the document, but not
> necessarily here in the middle.  I'll see if it works better as a paragraph
> here and an appendix or something at the bottom.

Yes, moving to a less prominent section might help, since we want to
avoid the long-wall-of-text effect with information not impacting the
basic understanding.

[...]
> > > +To support a specific codec, AVCodecContext's private context is set to
> > > +an encoder-specific data type.  For example, the video codec
> > > +[H.264](https://en.wikipedia.org/wiki/Advanced_Video_Coding) is supported via
> > > +[the x264 library](https://www.videolan.org/developers/x264.html), and
> > > +implemented in X264Context.
> > 
> > > Although included in the documentation, X264Context is not part of the public API.
> > 
> > Why included in the doc? That is a private struct and therefore should
> > not be included in the doxy.
> 

> Doxygen doesn't provide an obvious mechanism to include only the public API.
> Changing that would be at best a big job, and it isn't obvious where to even
> start until/unless e.g. [1] gets merged in.  It seems like a better plan
> to put the warning in and take it out if and when the site gets updated.

I think it's fine to keep as is, this is somehow a doxygen glitch, but
at the same time might help with internal development (in this case
you want to know the internal structures).
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v5 2/4] lavu: Clarify relationship between AVClass, AVOption and context
  2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
@ 2024-05-25  9:57           ` Stefano Sabatini
  0 siblings, 0 replies; 84+ messages in thread
From: Stefano Sabatini @ 2024-05-25  9:57 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andrew Sayers

On date Thursday 2024-05-23 21:00:41 +0100, Andrew Sayers wrote:
> ---
>  libavutil/log.h | 16 +++++++++++++---
>  libavutil/opt.h | 17 ++++++++++++++---
>  2 files changed, 27 insertions(+), 6 deletions(-)
> 
> diff --git a/libavutil/log.h b/libavutil/log.h
> index ab7ceabe22..d599ab506e 100644
> --- a/libavutil/log.h
> +++ b/libavutil/log.h
> @@ -59,9 +59,19 @@ typedef enum {
>  struct AVOptionRanges;
>  
>  /**
> - * Describe the class of an AVClass context structure. That is an
> - * arbitrary struct of which the first field is a pointer to an
> - * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.).
> + * Generic Logging and introspection facilities

Looks mostly good to me but now I wonder if we are really confusing
introspection with AVOptions (AVOptions adopt introspection but it's
mostly about AVOptions themselves).

So maybe we should replace "introspection" with something more
concrete, such as:

Generic logging and options facilities

> + *
> + * Logging and introspection functions expect to be passed structs
> + * whose first member is a pointer-to-@ref AVClass.
> + *
> + * Structs that only use the logging facilities are often referred to as
> + * "AVClass context structures", while those that use introspection facilities
> + * are called "AVOptions-enabled structs".
> + *
> + * @see
> + * * @ref lavu_log
> + * * @ref avoptions
> + * * @ref Context
>   */
>  typedef struct AVClass {
>      /**
> diff --git a/libavutil/opt.h b/libavutil/opt.h
> index 07e27a9208..b14c120e36 100644
> --- a/libavutil/opt.h
> +++ b/libavutil/opt.h
> @@ -39,9 +39,16 @@
>   * @defgroup avoptions AVOptions
>   * @ingroup lavu_data
>   * @{
> - * AVOptions provide a generic system to declare options on arbitrary structs
> - * ("objects"). An option can have a help text, a type and a range of possible
> - * values. Options may then be enumerated, read and written to.

> + *
> + * Generic introspection facilities for AVClass context structures

ditto, more concrete with:
Generic options facilities ...

[...]
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v5 1/4] doc: Explain what "context" means
  2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 1/4] doc: " Andrew Sayers
@ 2024-05-25 11:00           ` Stefano Sabatini
  0 siblings, 0 replies; 84+ messages in thread
From: Stefano Sabatini @ 2024-05-25 11:00 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andrew Sayers

On date Thursday 2024-05-23 21:00:40 +0100, Andrew Sayers wrote:
> Derived from explanations kindly provided by Stefano Sabatini and others:
> https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
> ---
>  doc/context.md | 439 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 439 insertions(+)
>  create mode 100644 doc/context.md
> 
> diff --git a/doc/context.md b/doc/context.md
> new file mode 100644
> index 0000000000..21469a6e58
> --- /dev/null
> +++ b/doc/context.md
> @@ -0,0 +1,439 @@
> +@page Context Introduction to contexts
> +
> +@tableofcontents
> +

> +“Context” is a name for a widely-used programming idiom.

nit++: better to use simple "" quoting to help people with simple
ascii keyboard layouts.

nit++: "Context" is a name employed for a widely-used programming idiom.

since "context" is not the idiom itself.

> +This document explains the general idiom and some conventions used by FFmpeg.
> +
> +This document uses object-oriented analogies for readers familiar with
> +[object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming).
> +But contexts can also be used outside of OOP, and even in situations where OOP
> +isn't helpful.  So these analogies should only be used as a rough guide.
> +
> +@section Context_general “Context” as a general concept
> +
> +Many projects use some kind of “context” idiom.  You can safely skip this
> +section if you have used contexts in another project.  You might also prefer to
> +read @ref Context_comparison before continuing with the rest of the document.
> +
> +@subsection Context_think “Context” as a way to think about code
> +
> +A context is any data structure that is passed to several functions
> +(or several instances of the same function) that all operate on the same entity.
> +For example, [object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming)
> +languages usually provide member functions with a `this` or `self` value:
> +

> +```python
> +# Python methods (functions within classes) must start with an object argument,
> +# which does a similar job to a context:
> +class MyClass:
> +    def my_func(self):
> +        ...
> +```

nit: as noted, I'd skip this example altogether

> +Contexts can also be used in C-style procedural code.  If you have ever written
> +a callback function, you have probably used a context:
> +
> +```c
> +struct FileReader {
> +    FILE* file;
> +};
> +
> +int my_callback(void *my_var_, uint8_t* buf, int buf_size) {
> +
> +    // my_var provides context for the callback function:
> +    struct FileReader *my_var = (struct FileReader *)my_var_;
> +
> +    return read(my_var->file, sizeof(*buf), buf_size);
> +}
> +
> +void init() {
> +
> +    struct FileReader my_var;
> +    my_var->file = fopen("my-file", "rb");
> +
> +    register_callback(my_callback, &my_var);
> +
> +    ...
> +
> +    fclose( my_var->file );
> +
> +}
> +```

Not convinced this is a good example, especially given that a struct
with a single field might be used directly so this looks a bit like
obfuscation.

Rather than this, maybe something as:

struct AVBikeShedContext {
    uint8_t color_r;
    uint8_t color_g;
    uint8_t color_b;
    char *color;
    int (* set_default_color)(const char *color);
}

AVBikeShedContext *av_bikeshed_context_alloc();
int                av_bikeshed_context_set_color(AVBikeShedContext *bikeshed, const char *color);
const char        *av_bikeshed_context_get_color(AVBikeShedContext *bikeshed);
void               av_bikeshed_context_get_rgb_color(AVBikeShedContext *bikeshed, uint8_t *color_r, uint8_t *color_g, uint8_t *color_b);

Then you can use:
int set_bikeshed_pink_color(AVBikeShedContext *bikeshed, const char *color) {
    return av_bikeshed_context_set_color(bikeshed, "pink");
}

bikeshed->set_default_color = set_bikeshed_pink_color;

to provide a callback example

> +In the broadest sense, a context is just a way to think about some code.
> +You can even use it to think about code written by people who have never
> +heard the term, or who would disagree with you about what it means.
> +But when FFmpeg developers say “context”, they're usually talking about
> +a more specific set of conventions.
> +
> +@subsection Context_communication “Context” as a tool of communication
> +
> +“Context“ can just be a word to understand code in your own head,
> +but it can also be a term you use to explain your interfaces.
> +Here is a version of the callback example that makes the context explicit:
> +
> +```c
> +struct FileReaderContext {
> +    FILE *file;
> +};
> +
> +int my_callback(void *ctx_, uint8_t *buf, int buf_size) {
> +
> +    // ctx provides context for the callback function:
> +    struct FileReaderContext *ctx = (struct FileReaderContext *)ctx_;
> +
> +    return read(ctx->file, sizeof(*buf), buf_size);
> +}
> +
> +void init() {
> +
> +    struct FileReader ctx;

> +    ctx->file = fopen("my-file", "rb");

this should be ctx.file

> +
> +    register_callback(my_callback, &ctx);

I don't understand what's this for

> +
> +    ...
> +
> +    fclose( ctx->file );
> +
> +}
> +```
> +
> +The difference here is subtle, but important.  If a piece of code
> +*appears compatible with contexts*, then you are *allowed to think
> +that way*, but if a piece of code *explicitly states it uses
> +contexts*, then you are *required to follow that approach*.
> +
> +For example, take a look at avio_alloc_context().
> +The function name and return value both state it uses contexts,

> +so failing to follow that approach is a bug you can report.

"failing to follow that approach" is meant at the API level?

> +But its arguments are a set of callbacks that merely appear compatible with
> +contexts, so it's fine to write a `read_packet` function that just reads
> +from standard input.
> +
> +When a programmer says their code is "a context", they're guaranteeing
> +to follow a set of conventions enforced by their community - for example,
> +the FFmpeg community enforces that contexts have separate allocation,
> +configuration, and initialization steps.  That's different from saying
> +their code is "an object", which normally guarantees to follow conventions
> +enforced by their programming language (e.g. using a constructor function).
> +
> +@section Context_ffmpeg FFmpeg contexts
> +
> +This section discusses specific context-related conventions used in FFmpeg.
> +Some of these are used in other projects, others are unique to this project.
> +
> +@subsection Context_naming Naming: “Context” and “ctx”
> +
> +```c
> +// Context struct names usually end with `Context`:
> +struct AVSomeContext {
> +  ...
> +};
> +
> +// Functions are usually named after their context,
> +// context parameters usually come first and are often called `ctx`:
> +void av_some_function(AVSomeContext *ctx, ...);
> +```
> +
> +If an FFmpeg struct is intended for use as a context, its name usually
> +makes that clear.  Exceptions to this rule include AVMD5, which is only
> +identified as a context by @ref libavutil/md5.c "the functions that call it".
> +
> +If a function is associated with a context, its name usually
> +begins with some variant of the context name (e.g. av_md5_alloc()
> +or avcodec_alloc_context3()).  Exceptions to this rule include
> +@ref avformat.h "AVFormatContext's functions", many of which
> +begin with just `av_`.
> +
> +If a function has a context parameter, it usually comes first and its name
> +often contains `ctx`.  Exceptions include av_bsf_alloc(), which puts the
> +context argument second to emphasise it's an out variable.
> +

> +Some functions fit awkwardly within FFmpeg's context idiom.  For example,
> +av_ambient_viewing_environment_create_side_data() creates an
> +AVAmbientViewingEnvironment context, then adds it to the side-data of an
> +AVFrame context.

To go back to this unfitting example, can you state what would be
fitting in this case?

> If you find contexts a useful metaphor in these cases,
> +you might prefer to think of these functions as "receiving" and "producing"
> +contexts.
> +
> +@subsection Context_data_hiding Data hiding: private contexts
> +
> +```c
> +// Context structs often hide private context:
> +struct AVSomeContext {
> +  void *priv_data; // sometimes just called "internal"
> +};
> +```
> +
> +Contexts present a public interface, so changing a context's members forces
> +everyone that uses the library to at least recompile their program,
> +if not rewrite it to remain compatible.  Many contexts reduce this problem
> +by including a private context with a type that is not exposed in the public
> +interface.  Hiding information this way ensures it can be modified without
> +affecting downstream software.
> +
> +Private contexts often store variables users aren't supposed to see
> +(similar to an OOP private block), but can also store information shared between
> +some but not all instances of a context (e.g. codec-specific functionality),
> +and @ref Context_avoptions "AVOptions-enabled structs" can include options
> +that are accessible through the @ref avoptions "AVOptions API".
> +Object-oriented programmers thinking about private contexts should remember
> +that FFmpeg isn't *large enough* to need some common object-oriented techniques,
> +even though it's solving a problem *complex enough* to benefit from
> +some rarer techniques.
> +
> +@subsection Context_lifetime Manage lifetime: allocate, initialize and free
> +
> +```c
> +void my_function( ... ) {
> +
> +    // Context structs are allocated then initialized with associated functions:
> +
> +    AVSomeContext *ctx = av_some_context_alloc(...);
> +
> +    // ... configure ctx ...
> +
> +    av_some_context_init(ctx, ...);
> +
> +    // ... use ctx ...
> +
> +    // Context structs are freed with associated functions:
> +
> +    av_some_context_close(ctx);
> +    av_some_context_free(ctx);
> +
> +}
> +```
> +
> +FFmpeg contexts go through the following stages of life:
> +
> +1. allocation (often a function that ends with `_alloc`)
> +   * a range of memory is allocated for use by the structure
> +   * memory is allocated on boundaries that improve caching
> +   * memory is reset to zeroes, some internal structures may be initialized
> +2. configuration (implemented by setting values directly on the context)
> +   * no function for this - calling code populates the structure directly
> +   * memory is populated with useful values
> +   * simple contexts can skip this stage
> +3. initialization (often a function that ends with `_init`)
> +   * setup actions are performed based on the configuration (e.g. opening files)
> +5. normal usage
> +   * most functions are called in this stage
> +   * documentation implies some members are now read-only (or not used at all)
> +   * some contexts allow re-initialization
> +6. closing (often a function that ends with `_close()`)
> +   * teardown actions are performed (e.g. closing files)
> +7. deallocation (often a function that ends with `_free()`)
> +   * memory is returned to the pool of available memory
> +
> +This can mislead object-oriented programmers, who expect something more like:
> +
> +1. allocation (usually a `new` keyword)
> +   * a range of memory is allocated for use by the structure
> +   * memory *may* be reset (e.g. for security reasons)
> +2. initialization (usually a constructor)
> +   * memory is populated with useful values
> +   * related setup actions are performed based on arguments (e.g. opening files)
> +3. normal usage
> +   * most functions are called in this stage
> +   * compiler enforces that some members are read-only (or private)
> +   * no going back to the previous stage
> +4. finalization (usually a destructor)
> +   * teardown actions are performed (e.g. closing files)
> +5. deallocation (usually a `delete` keyword)
> +   * memory is returned to the pool of available memory
> +
> +FFmpeg's allocation stage is broadly similar to the OOP stage of the same name.
> +Both set aside some memory for use by a new entity, but FFmpeg's stage can also
> +do some higher-level operations.  For example, @ref Context_avoptions
> +"AVOptions-enabled structs" set their AVClass member during allocation.
> +
> +FFmpeg's configuration stage involves setting any variables you want to before
> +you start using the context.  Complicated FFmpeg structures like AVCodecContext
> +tend to have many members you *could* set, but in practice most programs set
> +few if any of them.  The freeform configuration stage works better than bundling
> +these into the initilization stage, which would lead to functions with
> +impractically many parameters, and would mean each new option was an
> +incompatible change to the API.
> +
> +FFmpeg's initialization stage involves calling a function that sets the context
> +up based on your configuration.
> +
> +FFmpeg's first three stages do the same job as OOP's first two stages.
> +This can mislead object-oriented developers, who expect to do less work in the
> +allocation stage, and more work in the initialization stage.  To simplify this,
> +most FFmpeg contexts provide a combined allocator and initializer function.
> +For historical reasons, suffixes like `_alloc`, `_init`, `_alloc_context` and
> +even `_open` can indicate the function does any combination of allocation and
> +initialization.
> +
> +FFmpeg's "closing" stage is broadly similar to OOP's "finalization" stage,
> +but some contexts allow re-initialization after finalization.  For example,
> +SwrContext lets you call swr_close() then swr_init() to reuse a context.
> +Be aware that some FFmpeg functions happen to use the word "finalize" in a way
> +that has nothing to do with the OOP stage (e.g. av_bsf_list_finalize()).
> +
> +FFmpeg's "deallocation" stage is broadly similar to OOP, but can perform some
> +higher-level functions (similar to the allocation stage).
> +
> +Closing functions usually end with "_close", while deallocation
> +functions usually end with "_free".  Very few contexts need the flexibility of
> +separate "closing" and "deallocation" stages, so many "_free" functions
> +implicitly close the context first.
> +

> +@subsection Context_avoptions Reflection: AVOptions-enabled structs

To clarify this, we should not treat reflection and AVOptions as
synonyms.

Clearly the AVOptions system enables the options introspection (you
can query the specified options, and get the default values or the set
values and help etc.) but it's not only about introspection, but also
about setting the values using a high-level API.

> +
> +Object-oriented programming puts more focus on data hiding than FFmpeg needs,
> +but it also puts less focus on
> +[reflection](https://en.wikipedia.org/wiki/Reflection_(computer_programming)).
> +

> +To understand FFmpeg's reflection requirements, run `ffmpeg -h full` on the
> +command-line, then ask yourself how you would implement all those options
> +with the C standard [`getopt` function](https://en.wikipedia.org/wiki/Getopt).
> +You can also ask the same question for any other programming languages you know.
> +[Python's argparse module](https://docs.python.org/3/library/argparse.html)
> +is a good example - its approach works well with far more complex programs
> +than `getopt`, but would you like to maintain an argparse implementation
> +with 15,000 options and growing?

To clarify this: the approach in this case is to use the introspection
API to expose the options programmatically, even if in fact one might
use getopt to build the CLI (or another toolkit to build a GUI).

In the case of ffmpeg, getopt cannot be used since the options are
positional (depending on the place it might take encoder/format/url
options). For a simpler CLI (e.g. an hash API wrapper) it might work.

> +
> +Most solutions assume you can just put all options in a single block,
> +which is unworkable at FFmpeg's scale.  Instead, we split configuration
> +across many *AVOptions-enabled structs*, which use the @ref avoptions
> +"AVOptions API" to reflect information about their user-configurable members,
> +including members in private contexts.
> +
> +AVOptions-accessible members of a context should be accessed through the
> +@ref avoptions "AVOptions API" whenever possible, even if they're not hidden
> +in a private context.  That ensures values are validated as they're set, and
> +means you won't have to do as much work if a future version of FFmpeg changes
> +the allowed values.  This is broadly similar to the way object-oriented programs
> +recommend getters and setters over direct access.
> +
> +Object-oriented programmers may be tempted to compare AVOptions-accessible
> +members of a public context to protected members of a class.  Both provide
> +global access through an API, and unrestricted access for trusted friends.
> +But this is just a happy accident, not a guarantee.
> +
> +@subsection Context_logging Logging: AVClass context structures
> +
> +FFmpeg's @ref lavu_log "logging facility" needs to be simple to use,
> +but flexible enough to let people debug problems.  And much like reflection,
> +it needs to work the same across a wide variety of unrelated structs.
> +

> +FFmpeg structs that support the logging framework are called *@ref AVClass
> +context structures*.  The name @ref AVClass was chosen early in FFmpeg's
> +development, but in practice it only came to store information about
> +logging, and about introspection.

nit: introspection => options

To further clarify this, I think AVClass was chosen because the idea
is to support a "class" of structures. You define logging and options
in a single place for all the encoders, decoders, filters etc (check
for example libavfilter/avfilter.c::avfilter_class).

> +
> +@section Context_further Further information about contexts
> +
> +So far, this document has provided a theoretical guide to FFmpeg contexts.
> +This final section provides some alternative approaches to the topic,
> +which may help round out your understanding.
> +
> +@subsection Context_example Learning by example: context for a codec
> +
> +It can help to learn contexts by doing a deep dive into a specific struct.
> +This section will discuss AVCodecContext - an AVOptions-enabled struct
> +that contains information about encoding or decoding one stream of data
> +(e.g. the video in a movie).
> +
> +The name "AVCodecContext" tells us this is a context.  Many of
> +@ref libavcodec/avcodec.h "its functions" start with an `avctx` parameter,
> +indicating this parameter provides context for that function.
> +
> +AVCodecContext::internal contains the private context.  For example,
> +codec-specific information might be stored here.
> +
> +AVCodecContext is allocated with avcodec_alloc_context3(), initialized with
> +avcodec_open2(), and freed with avcodec_free_context().  Most of its members
> +are configured with the @ref avoptions "AVOptions API", but for example you
> +can set AVCodecContext::opaque or AVCodecContext::draw_horiz_band() if your
> +program happens to need them.
> +
> +AVCodecContext provides an abstract interface to many different *codecs*.
> +Options supported by many codecs (e.g. "bitrate") are kept in AVCodecContext
> +and reflected as AVOptions.  Options that are specific to one codec are
> +stored in the private context, and reflected from there.
> +
> +AVCodecContext::av_class contains logging metadata to ensure all codec-related
> +error messages look the same, plus implementation details about options.
> +
> +To support a specific codec, AVCodecContext's private context is set to
> +an encoder-specific data type.  For example, the video codec
> +[H.264](https://en.wikipedia.org/wiki/Advanced_Video_Coding) is supported via
> +[the x264 library](https://www.videolan.org/developers/x264.html), and
> +implemented in X264Context.  Although included in the documentation, X264Context
> +is not part of the public API.  That means FFmpeg's @ref ffmpeg_versioning
> +"strict rules about changing public structs" aren't as important here, so a
> +version of FFmpeg could modify X264Context or replace it with another type
> +altogether.  An adverse legal ruling or security problem could even force us to
> +switch to a completely different library without a major version bump.
> +
> +The design of AVCodecContext provides several important guarantees:
> +
> +- lets you use the same interface for any codec
> +- supports common encoder options like "bitrate" without duplicating code
> +- supports encoder-specific options like "profile" without bulking out the public interface
> +- reflects both types of options to users, with help text and detection of missing options
> +- provides uniform logging output
> +- hides implementation details (e.g. its encoding buffer)
> +
> +@subsection Context_comparison Learning by comparison: FFmpeg vs. Curl contexts
> +
> +It can help to learn contexts by comparing how different projects tackle
> +similar problems.  This section will compare @ref AVMD5 "FFmpeg's MD5 context"
> +with [curl 8.8.0's equivalent](https://github.com/curl/curl/blob/curl-8_8_0/lib/md5.c#L48).
> +
> +The [MD5 algorithm](https://en.wikipedia.org/wiki/MD5) produces
> +a fixed-length digest from arbitrary-length data.  It does this by calculating
> +the digest for a prefix of the data, then loading the next part and adding it
> +to the previous digest, and so on.
> +
> +```c
> +// FFmpeg's MD5 context looks like this:
> +typedef struct AVMD5 {
> +    uint64_t len;
> +    uint8_t  block[64];
> +    uint32_t ABCD[4];
> +} AVMD5;
> +
> +// Curl 8.8.0's MD5 context looks like this:
> +struct MD5_context {
> +  const struct MD5_params *md5_hash;    /* Hash function definition */
> +  void                  *md5_hashctx;   /* Hash function context */
> +};
> +```
> +
> +Curl's struct name ends with `_context`, guaranteeing contexts are the correct
> +interpretation.  FFmpeg's struct does not explicitly say it's a context, but
> +@ref libavutil/md5.c "its functions do" so we can reasonably assume
> +it's the intended interpretation.
> +
> +Curl's struct uses `void *md5_hashctx` to avoid guaranteeing
> +implementation details in the public interface, whereas FFmpeg makes
> +everything accessible.  This disagreement about data hiding is a good example
> +of how contexts can be used differently.  Hiding the data means changing the
> +layout in a future version of curl won't break downstream programs that used
> +that data.  But the MD5 algorithm has been stable for 30 years, and making the
> +data public makes it easier for people to follow a bug in their own code.
> +
> +Curl's struct is declared as `struct <type> { ... }`, whereas FFmpeg uses
> +`typedef struct <type> { ... } <type>`.  These conventions are used with both
> +context and non-context structs, so don't say anything about contexts as such.
> +Specifically, FFmpeg's convention is a workaround for an issue with C grammar:
> +
> +```c
> +void my_function( ... ) {
> +  int                my_var;        // good
> +  MD5_context        my_curl_ctx;   // error: C needs you to explicitly say "struct"
> +  struct MD5_context my_curl_ctx;   // good: added "struct"
> +  AVMD5              my_ffmpeg_ctx; // good: typedef's avoid the need for "struct"
> +}
> +```
> +

> +Both MD5 implementations are long-tested, widely-used examples of contexts
> +in the real world.  They show how contexts can solve the same problem
> +in different ways.

I'm fine with keeping this section at the end of the document.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-05-25  9:49         ` Stefano Sabatini
@ 2024-05-26 12:06           ` Andrew Sayers
  2024-05-28 17:24             ` Stefano Sabatini
  0 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-05-26 12:06 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

It feels like we've got through most of the mid-level "how FFmpeg works" stuff,
and now we're left with language choices (e.g "options" vs. "introspection")
and philosophical discussions (e.g. the relationship between contexts and OOP).
It's probably best to philosophise first, then come back to language.

This message has been sent as a reply to one specific message, but is actually
springboarding off messages from two sub-threads.  Hopefully that will keep
the big questions contained in one place.

On Sat, May 25, 2024 at 11:49:48AM +0200, Stefano Sabatini wrote:
> What perplexes me is that "context" is not part of the standard OOP
> jargon, so this is probably adding more to the confusion.

This actually speaks to a more fundamental issue about how we learn.
To be clear, everything I'm about to describe applies every human that ever
lived, but starting with this message makes it easier to explain
(for reasons that will hopefully become obvious).

When you ask why "context" is not part of OOP jargon, one could equally ask
why "object" isn't part of FFmpeg jargon.  The document hints at some arguments:
their lifetime stages are different, their rules are enforced at the
language vs. community level, OOP encourages homogenous interfaces while FFmpeg
embraces unique interfaces that precisely suit each use case, and so on.
But the honest answer is much simpler - humans are lazy, and we want the things
we learn today to resemble the things we learnt yesterday.

Put another way - if we had infinite time every day, we could probably write an
object-oriented interface to FFmpeg.  But our time is sadly finite so we stick
with the thing that's proven to work.  Similarly, if our readers had infinite
free time every day, they could probably learn a completely new approach to
programming.  But their time is finite, so they stick to what they know.

That means people reading this document aren't just passively soaking up
information, they're looking for shortcuts that fit their assumptions.
And as anyone that's ever seen a political discussion can tell you,
humans are *really good* at finding shortcuts that fit their assumptions.
For example, when an OOP developer sees the words "alloc" and "init",
they will assume these map precisely to OOP allocators and initializers.  One
reason for the long section about context lifetimes is because it needs to
meet them where they are, then walk them step-by-step to a better place.

Aside: if FFmpeg had a blog, I could turn this discussion into a great post
called something like "reflections on object- vs. context-oriented development".
But the project's voice is more objective than that, so this document is limited
to discussing the subset of issues that relate specifically to the FFmpeg API.


On Sat, May 25, 2024 at 01:00:14PM +0200, Stefano Sabatini wrote:
> > +Some functions fit awkwardly within FFmpeg's context idiom.  For example,
> > +av_ambient_viewing_environment_create_side_data() creates an
> > +AVAmbientViewingEnvironment context, then adds it to the side-data of an
> > +AVFrame context.
> 
> To go back to this unfitting example, can you state what would be
> fitting in this case?

"Awkwardly" probably isn't the right word to use, but that's a language choice
we can come back to.

The problem with FFmpeg's interface isn't that any one part is illogical,
it's that different parts of the interface follow incompatible logic.

It's hard to give specific examples, because any given learner's journey looks
like a random walk through the API, and you can always say "well nobody else
would have that problem".  But if everyone has a different problem, that means
everyone has *a* problem, even though there's no localised code fix.

For sake of argument, let's imagine a user who was a world-leading expert in
Microsoft QBasic in the eighties, then fell into a forty-year coma and woke up
in front of the FFmpeg documentation.  In other words, a highly adept
programmer with zero knowledge of programming conventions more recent than
"a function is a special type of subroutine for returning a value".
Their journey might look like...

1. there's this thing called "context", and some functions "have" contexts
2. sws_init_context() says "Initialize the swscaler context sws_context",
   and `sws_context` is a `SwsContext *`, so I think it has a SwsContext context
3. sws_alloc_context() says "Allocate an empty SwsContext",
   and it returns a `SwsContext *`, so I think it has the same context
   as sws_init_context()
4. avio_alloc_context() and avio_open2() are both variations on this theme,
   so I should look for creative ways to interpret things as "having" contexts
5. av_alloc_format_context() puts the type in the middle of the function name,
   so I should only treat prefixes as a weak signal
6. av_ambient_viewing_environment_create_side_data() allocates like an alloc,
   so I think the return value is the context; but it also operates on AVFrame
   in a way that affects related functions, so I think the arg is the context.
   Its prefix is too a weak a signal to be a tiebreaker, so I'll just guess
   one of them at random and wait until something goes wrong

In the above case, the interface rewarded the developer for looking harder and
harder for ways to call something a context, to the point where saying "neither"
becomes inconceivable (or at best an admission of defeat).

There's no way to avoid that sort of inconsistency in a project like FFmpeg,
and explaining the logic behind each choice would involve an order of magnitude
more documentation.  So the only practical choice is to present a sort of
conceptual buffet - "here are several ways to think about the problem, choose
whatever suits your tastes".
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-05-26 12:06           ` Andrew Sayers
@ 2024-05-28 17:24             ` Stefano Sabatini
  2024-05-29 10:10               ` Andrew Sayers
  2024-05-29 10:50               ` Andrew Sayers
  0 siblings, 2 replies; 84+ messages in thread
From: Stefano Sabatini @ 2024-05-28 17:24 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On date Sunday 2024-05-26 13:06:52 +0100, Andrew Sayers wrote:
> It feels like we've got through most of the mid-level "how FFmpeg works" stuff,
> and now we're left with language choices (e.g "options" vs. "introspection")
> and philosophical discussions (e.g. the relationship between contexts and OOP).
> It's probably best to philosophise first, then come back to language.
> 
> This message has been sent as a reply to one specific message, but is actually
> springboarding off messages from two sub-threads.  Hopefully that will keep
> the big questions contained in one place.
> 
> On Sat, May 25, 2024 at 11:49:48AM +0200, Stefano Sabatini wrote:
> > What perplexes me is that "context" is not part of the standard OOP
> > jargon, so this is probably adding more to the confusion.
> 

> This actually speaks to a more fundamental issue about how we learn.
> To be clear, everything I'm about to describe applies every human that ever
> lived, but starting with this message makes it easier to explain
> (for reasons that will hopefully become obvious).
> 

> When you ask why "context" is not part of OOP jargon, one could equally ask
> why "object" isn't part of FFmpeg jargon.  The document hints at some arguments:
> their lifetime stages are different, their rules are enforced at the
> language vs. community level, OOP encourages homogenous interfaces while FFmpeg
> embraces unique interfaces that precisely suit each use case, and so on.
> But the honest answer is much simpler - humans are lazy, and we want the things
> we learn today to resemble the things we learnt yesterday.
> 
> Put another way - if we had infinite time every day, we could probably write an
> object-oriented interface to FFmpeg.  But our time is sadly finite so we stick
> with the thing that's proven to work.  Similarly, if our readers had infinite
> free time every day, they could probably learn a completely new approach to
> programming.  But their time is finite, so they stick to what they know.
> 
> That means people reading this document aren't just passively soaking up
> information, they're looking for shortcuts that fit their assumptions.
> And as anyone that's ever seen a political discussion can tell you,
> humans are *really good* at finding shortcuts that fit their assumptions.
> For example, when an OOP developer sees the words "alloc" and "init",
> they will assume these map precisely to OOP allocators and initializers.  One
> reason for the long section about context lifetimes is because it needs to
> meet them where they are, then walk them step-by-step to a better place.

I think we start with different assumptions: you assume that most of
the readers are familiar with OOP jargon, and that they will leverage
the OOP jargon to understand the FFmpeg API. I think this is
misleading: historically what defined FFmpeg is its minimalistic
approach, in this case we don't want the user, familiar with C, to be
familiar with OOP in order to use and understand the FFmpeg API, as
this is simply not necessary as FFmpeg is plain C language.

In fact, if this might help with some users, this will probably
confuse all the others. Even more, if we adopt the FFmpeg jargon to
OOP (using "context") we are adding more confusion, as now the OOP
reader will have to adopt the FFmpeg jargon applied to OOP.

My advice is to move all the content to OOP to a dedicated section, or
to make the references to OOP jargon as less as possible, to not get
in the way with the non-OOP reader.

> Aside: if FFmpeg had a blog, I could turn this discussion into a great post
> called something like "reflections on object- vs. context-oriented development".
> But the project's voice is more objective than that, so this document is limited
> to discussing the subset of issues that relate specifically to the FFmpeg API.

One option would be the wiki:
http://trac.ffmpeg.org/

but probably a personal blog entry would be better, given that this
would not be reference material but more as an article (since the API
and its own philosophy is a moving target).

> 
> On Sat, May 25, 2024 at 01:00:14PM +0200, Stefano Sabatini wrote:
> > > +Some functions fit awkwardly within FFmpeg's context idiom.  For example,
> > > +av_ambient_viewing_environment_create_side_data() creates an
> > > +AVAmbientViewingEnvironment context, then adds it to the side-data of an
> > > +AVFrame context.
> > 
> > To go back to this unfitting example, can you state what would be
> > fitting in this case?
> 
> "Awkwardly" probably isn't the right word to use, but that's a language choice
> we can come back to.
> 
> The problem with FFmpeg's interface isn't that any one part is illogical,
> it's that different parts of the interface follow incompatible logic.
> 
> It's hard to give specific examples, because any given learner's journey looks
> like a random walk through the API, and you can always say "well nobody else
> would have that problem".  But if everyone has a different problem, that means
> everyone has *a* problem, even though there's no localised code fix.

Fine, but can you propose the signature of the functions that you
would consider optimal in this case?

One option I suggested is to move the function to frame.h, but this
would have other implications (that's why keeping as is looks to me
like a reasonable tradeoff - you can consider it as a sort of static
class method if you like).

> 
> For sake of argument, let's imagine a user who was a world-leading expert in
> Microsoft QBasic in the eighties, then fell into a forty-year coma and woke up
> in front of the FFmpeg documentation.  In other words, a highly adept
> programmer with zero knowledge of programming conventions more recent than
> "a function is a special type of subroutine for returning a value".
> Their journey might look like...
> 
> 1. there's this thing called "context", and some functions "have" contexts
> 2. sws_init_context() says "Initialize the swscaler context sws_context",
>    and `sws_context` is a `SwsContext *`, so I think it has a SwsContext context
> 3. sws_alloc_context() says "Allocate an empty SwsContext",
>    and it returns a `SwsContext *`, so I think it has the same context
>    as sws_init_context()
> 4. avio_alloc_context() and avio_open2() are both variations on this theme,
>    so I should look for creative ways to interpret things as "having" contexts
> 5. av_alloc_format_context() puts the type in the middle of the function name,
>    so I should only treat prefixes as a weak signal

> 6. av_ambient_viewing_environment_create_side_data() allocates like an alloc,
>    so I think the return value is the context; but it also operates on AVFrame
>    in a way that affects related functions, so I think the arg is the context.
>    Its prefix is too a weak a signal to be a tiebreaker, so I'll just guess
>    one of them at random and wait until something goes wrong

I see, but the "exception" should be apparent from the doc.

Also you might think at it like:
AVAmbientViewingEnvironment.create_side_data(AVFrame *frame)

that is as a static class method creating the object starting from a
frame component.

[...]

Anyway resuming, I'm mostly fine with your latest patch, but for the
nits and the specific points I raised. Also I'd tend to loose the
references to OOP jargon for the reasons I explained.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-05-28 17:24             ` Stefano Sabatini
@ 2024-05-29 10:10               ` Andrew Sayers
  2024-05-29 10:50               ` Andrew Sayers
  1 sibling, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-29 10:10 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Tue, May 28, 2024 at 07:24:55PM +0200, Stefano Sabatini wrote:
> 
> I think we start with different assumptions: you assume that most of
> the readers are familiar with OOP jargon, and that they will leverage
> the OOP jargon to understand the FFmpeg API. I think this is

Not exactly.  I'm saying the document has two equally valid use cases:

1. non-OOP developers, who need us to add new information to their brains
2. OOP developers, who need us to replace existing information in their brains

So it's not a matter of "leveraging OOP" jargon so much as "calling out
OOP assumptions".  For example, I originally assumed AVClass was to FFmpeg
as the Object struct[1] is to GObject, and struggled to take anything onboard
until that been explicitly debunked.  You may even be able to see that
opinion gradually eroding in each rewrite of the context document.

But actually, two groups is probably over-simplifying.  Another group would be
people coming from other C projects, who have incompatible ideas about contexts
that would never occur to us.  Or Fortran developers, who (according to the
first link on Google[2]) can be expected to understand modules but not objects.

> misleading: historically what defined FFmpeg is its minimalistic
> approach, in this case we don't want the user, familiar with C, to be
> familiar with OOP in order to use and understand the FFmpeg API, as
> this is simply not necessary as FFmpeg is plain C language.
> 
> In fact, if this might help with some users, this will probably
> confuse all the others. Even more, if we adopt the FFmpeg jargon to
> OOP (using "context") we are adding more confusion, as now the OOP
> reader will have to adopt the FFmpeg jargon applied to OOP.
> 
> My advice is to move all the content to OOP to a dedicated section, or
> to make the references to OOP jargon as less as possible, to not get
> in the way with the non-OOP reader.

Earlier versions of the document probably drew too strong an analogy with OOP,
but I suspect the problem may be simpler in the latest draft.  The majority of
OOP references explain how things are different to OOP - it might be possible
to make these more readable, but they can't be moved or removed, because
replacing information involves calling out the old information first.  Only the
first few OOP references draw the analogy in the positive, aiming to show OOP
devs how this is similar but different.

Given the OOP vs. non-OOP distinction is too simplistic, the solution might be
to start the document with a collection of code samples - a generic C function,
a Python object, a JavaScript event listener, and an FFmpeg sample.  That would
show how "context" is a name for a broad concept you've probably used before,
without singling out OOP.  It would also reinforce the idea of the document as
a buffet of concepts - don't like the OOP example?  Never mind, here are some
procedural ones for you to enjoy.

> 
> > Aside: if FFmpeg had a blog, I could turn this discussion into a great post
> > called something like "reflections on object- vs. context-oriented development".
> > But the project's voice is more objective than that, so this document is limited
> > to discussing the subset of issues that relate specifically to the FFmpeg API.
> 
> One option would be the wiki:
> http://trac.ffmpeg.org/
> 
> but probably a personal blog entry would be better, given that this
> would not be reference material but more as an article (since the API
> and its own philosophy is a moving target).
> 
> > 
> > On Sat, May 25, 2024 at 01:00:14PM +0200, Stefano Sabatini wrote:
> > > > +Some functions fit awkwardly within FFmpeg's context idiom.  For example,
> > > > +av_ambient_viewing_environment_create_side_data() creates an
> > > > +AVAmbientViewingEnvironment context, then adds it to the side-data of an
> > > > +AVFrame context.
> > > 
> > > To go back to this unfitting example, can you state what would be
> > > fitting in this case?
> > 
> > "Awkwardly" probably isn't the right word to use, but that's a language choice
> > we can come back to.
> > 
> > The problem with FFmpeg's interface isn't that any one part is illogical,
> > it's that different parts of the interface follow incompatible logic.
> > 
> > It's hard to give specific examples, because any given learner's journey looks
> > like a random walk through the API, and you can always say "well nobody else
> > would have that problem".  But if everyone has a different problem, that means
> > everyone has *a* problem, even though there's no localised code fix.
> 
> Fine, but can you propose the signature of the functions that you
> would consider optimal in this case?

I think we largely agree on this, but since you ask -

The code solution would be to pick a rule and rewrite the entire codebase to
fit that rule.  I don't have a strong opinion about what the rule is, but one
example might be "the first context parameter to a function must be that
function's context", which I guess would mean renaming this to something like
"av_frame_create_ambient_viewing_environment_side_data()".  That would be a
huge amount of work to implement, and even more work to maintain, so yes it's
fine to just document it and move on.

> One option I suggested is to move the function to frame.h, but this
> would have other implications (that's why keeping as is looks to me
> like a reasonable tradeoff - you can consider it as a sort of static
> class method if you like).

That's fine for this example, but interesting in other ways.

I'm increasingly reading the API in terms of what signals different parts of it
emit.  For example, if a function ends with "_alloc", that signals it's probably
an allocator, but av_max_alloc() doesn't allocate `max`es, so that signal's
information value is less than 1.  I think you're saying the location of a
function is an important signal - what sort of things does it tell you?

[...]

[1] https://docs.gtk.org/gobject/class.Object.html
[2] https://fortranwiki.org/fortran/show/Object-oriented+programming
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-05-28 17:24             ` Stefano Sabatini
  2024-05-29 10:10               ` Andrew Sayers
@ 2024-05-29 10:50               ` Andrew Sayers
  2024-05-29 11:06                 ` Paul B Mahol
  2024-05-29 16:06                 ` Stefano Sabatini
  1 sibling, 2 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-29 10:50 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Posting this separately, as these are practical "how does FFmpeg work" issues
vaguely inspired by recent discussions.


*How do namespaces work in FFmpeg?*

We've talked a bit about function namespaces recently.  One reason I've
suggested they're a weak signal is because they aren't really addressed in the
documentation.  How about adding something like this to the context doc:

    Most FFmpeg functions are grouped into namespaces, usually indicated by
    prefixes (e.g. `av_format_*`) but sometimes indicated by infixes
    (e.g. av_alloc_format_context()).  Namespaces group functions by *topic*,
    which doesn't always correlate with *context*.  For example, `av_find_*`
    functions search for information across various contexts.


*Should external API devs treat Sw{r,s}Context as AVClass context structures?*

This is probably an uninteresting edge case, but just to be sure...

The website says Sw{r,s}Context start with AVClass[1], they have _get_class
functions, are shown in `ffmpeg -h full`, and I haven't found anything that says
to treat them differently to e.g. AVCodecContext.  So I'm pretty sure these
are AVClass context structures, at least as far as internal devs are concerned.

But their definitions are only in the private interface, so the layout is just
an implementation detail that can change without even a major version bump.
AVFrame used to have a _get_class function despite never having an actual
AVClass member, so that's not a signal to external API devs.  And `URLContext`
appears in `ffmpeg -h full` despite having being made private long ago,
so that's not much of a signal either.

My guess is that the above should be addressed with a patch like:

+/**
+ * @brief Context for SWResampler
+ *
+ * @note The public ABI only guarantees this is an AVOptions-enabled struct.
+ * Its size and other members are not a part of the public ABI.
+ *
+ * @see
+ * - @ref Context
+ */
 struct SwrContext {

Let me know if the above is on the right track.  If so, I'll queue up a patch
for after the context document is done.


*Are AVOptions just command-line options?*

I have trouble with statements like "AVOptions is a framework for options",
both because it's circular and because the term "option" is too broad to be
meaningful.

I've previously pushed the word "reflection" on the assumption that options
can be used anywhere variables are used.  For example, imagine a decoder that
could be reconfigured on-the-fly to reduce CPU usage at the cost of displaying
blurier images.  That can't be part of the public interface because it's
codec-specific, but I could imagine updating some kind of "output_quality"
AVOption as a user slides a slider up and down.

But the CLI tools are largely non-interactive, so have I just misunderstood?

How about saying "AVOptions is a framework for command-line options"?

[1] https://ffmpeg.org/doxygen/trunk/structSwrContext.html
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-05-29 10:50               ` Andrew Sayers
@ 2024-05-29 11:06                 ` Paul B Mahol
  2024-05-29 14:18                   ` Andrew Sayers
  2024-05-29 16:06                 ` Stefano Sabatini
  1 sibling, 1 reply; 84+ messages in thread
From: Paul B Mahol @ 2024-05-29 11:06 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Wed, May 29, 2024 at 12:50 PM Andrew Sayers <ffmpeg-devel@pileofstuff.org>
wrote:

> Posting this separately, as these are practical "how does FFmpeg work"
> issues
> vaguely inspired by recent discussions.
>
>
> *How do namespaces work in FFmpeg?*
>
> We've talked a bit about function namespaces recently.  One reason I've
> suggested they're a weak signal is because they aren't really addressed in
> the
> documentation.  How about adding something like this to the context doc:
>
>     Most FFmpeg functions are grouped into namespaces, usually indicated by
>     prefixes (e.g. `av_format_*`) but sometimes indicated by infixes
>     (e.g. av_alloc_format_context()).  Namespaces group functions by
> *topic*,
>     which doesn't always correlate with *context*.  For example,
> `av_find_*`
>     functions search for information across various contexts.
>
>
> *Should external API devs treat Sw{r,s}Context as AVClass context
> structures?*
>
> This is probably an uninteresting edge case, but just to be sure...
>
> The website says Sw{r,s}Context start with AVClass[1], they have _get_class
> functions, are shown in `ffmpeg -h full`, and I haven't found anything
> that says
> to treat them differently to e.g. AVCodecContext.  So I'm pretty sure these
> are AVClass context structures, at least as far as internal devs are
> concerned.
>
> But their definitions are only in the private interface, so the layout is
> just
> an implementation detail that can change without even a major version bump.
> AVFrame used to have a _get_class function despite never having an actual
> AVClass member, so that's not a signal to external API devs.  And
> `URLContext`
> appears in `ffmpeg -h full` despite having being made private long ago,
> so that's not much of a signal either.
>
> My guess is that the above should be addressed with a patch like:
>
> +/**
> + * @brief Context for SWResampler
> + *
> + * @note The public ABI only guarantees this is an AVOptions-enabled
> struct.
> + * Its size and other members are not a part of the public ABI.
> + *
> + * @see
> + * - @ref Context
> + */
>  struct SwrContext {
>
> Let me know if the above is on the right track.  If so, I'll queue up a
> patch
> for after the context document is done.
>
>
> *Are AVOptions just command-line options?*
>
> I have trouble with statements like "AVOptions is a framework for options",
> both because it's circular and because the term "option" is too broad to be
> meaningful.
>
> I've previously pushed the word "reflection" on the assumption that options
> can be used anywhere variables are used.  For example, imagine a decoder
> that
> could be reconfigured on-the-fly to reduce CPU usage at the cost of
> displaying
> blurier images.  That can't be part of the public interface because it's
> codec-specific, but I could imagine updating some kind of "output_quality"
> AVOption as a user slides a slider up and down.
>
> But the CLI tools are largely non-interactive, so have I just
> misunderstood?
>
> How about saying "AVOptions is a framework for command-line options"?
>

ffmpeg is cli tool

libavfilter is library

AVOptions is certainly and primarily not framework for command-line options.


>
> [1] https://ffmpeg.org/doxygen/trunk/structSwrContext.html
> _______________________________________________
> 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".
>
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-05-29 11:06                 ` Paul B Mahol
@ 2024-05-29 14:18                   ` Andrew Sayers
  0 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-05-29 14:18 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Wed, May 29, 2024 at 01:06:30PM +0200, Paul B Mahol wrote:
> On Wed, May 29, 2024 at 12:50 PM Andrew Sayers <ffmpeg-devel@pileofstuff.org>
> wrote:
> 
[...]
> > *Are AVOptions just command-line options?*
> >
> > I have trouble with statements like "AVOptions is a framework for options",
> > both because it's circular and because the term "option" is too broad to be
> > meaningful.
> >
> > I've previously pushed the word "reflection" on the assumption that options
> > can be used anywhere variables are used.  For example, imagine a decoder
> > that
> > could be reconfigured on-the-fly to reduce CPU usage at the cost of
> > displaying
> > blurier images.  That can't be part of the public interface because it's
> > codec-specific, but I could imagine updating some kind of "output_quality"
> > AVOption as a user slides a slider up and down.
> >
> > But the CLI tools are largely non-interactive, so have I just
> > misunderstood?
> >
> > How about saying "AVOptions is a framework for command-line options"?
> >
> 
> ffmpeg is cli tool
> 
> libavfilter is library
> 
> AVOptions is certainly and primarily not framework for command-line options.

"Command-line option" might be the wrong word, but I've just checked
write_number() in libavutil/opt.c, and it seems to do non-atomic updates
without locking anything.  That suggests I was indeed wrong to think it could
be used on-the-fly - maybe "initial configuration options" would be a better
term?  Possibly with a warning somewhere about how AVOptions is not reentrant?
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means
  2024-05-29 10:50               ` Andrew Sayers
  2024-05-29 11:06                 ` Paul B Mahol
@ 2024-05-29 16:06                 ` Stefano Sabatini
  1 sibling, 0 replies; 84+ messages in thread
From: Stefano Sabatini @ 2024-05-29 16:06 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On date Wednesday 2024-05-29 11:50:40 +0100, Andrew Sayers wrote:
> Posting this separately, as these are practical "how does FFmpeg work" issues
> vaguely inspired by recent discussions.
> 
> 
> *How do namespaces work in FFmpeg?*
> 
> We've talked a bit about function namespaces recently.  One reason I've
> suggested they're a weak signal is because they aren't really addressed in the
> documentation.  How about adding something like this to the context doc:
> 
>     Most FFmpeg functions are grouped into namespaces, usually indicated by
>     prefixes (e.g. `av_format_*`) but sometimes indicated by infixes
>     (e.g. av_alloc_format_context()).  Namespaces group functions by *topic*,
>     which doesn't always correlate with *context*.  For example, `av_find_*`
>     functions search for information across various contexts.
> 
> 
> *Should external API devs treat Sw{r,s}Context as AVClass context structures?*
> 
> This is probably an uninteresting edge case, but just to be sure...
> 

> The website says Sw{r,s}Context start with AVClass[1], they have _get_class
> functions, are shown in `ffmpeg -h full`, and I haven't found anything that says
> to treat them differently to e.g. AVCodecContext.  So I'm pretty sure these
> are AVClass context structures, at least as far as internal devs are concerned.

It impacts the user as this changes the API. I guess when AVClass was
removed from AVFrame that was done with a major bump to advertise an
API break.

> But their definitions are only in the private interface, so the layout is just
> an implementation detail that can change without even a major version bump.
> AVFrame used to have a _get_class function despite never having an actual
> AVClass member, so that's not a signal to external API devs.  And `URLContext`
> appears in `ffmpeg -h full` despite having being made private long ago,
> so that's not much of a signal either.
> 
> My guess is that the above should be addressed with a patch like:
> 
> +/**
> + * @brief Context for SWResampler
> + *

> + * @note The public ABI only guarantees this is an AVOptions-enabled struct.
> + * Its size and other members are not a part of the public ABI.

This looks redundant to me, this is true for all the opaque structus,
and we don't want to repeat this again and again (this is a feature of
the C language, not of the API itself).

> + *
> + * @see
> + * - @ref Context
> + */
>  struct SwrContext {
> 
> Let me know if the above is on the right track.  If so, I'll queue up a patch
> for after the context document is done.

Better to treat this as a separate patch anyway.
 
> *Are AVOptions just command-line options?*

No, in fact this is not about comman-line options at all.

> 
> I have trouble with statements like "AVOptions is a framework for options",
> both because it's circular and because the term "option" is too broad to be
> meaningful.

AVOptions (or better the av_opt API) is a system to set
fields/properties/options on an enabled struct. This is a high level
API since it allows multiple options setting, validation, setting
from a dictionary etc., and enables to abstract the struct field name
(since the option names might be different from the field name).

> 
> I've previously pushed the word "reflection" on the assumption that options
> can be used anywhere variables are used.  For example, imagine a decoder that
> could be reconfigured on-the-fly to reduce CPU usage at the cost of displaying
> blurier images.  That can't be part of the public interface because it's
> codec-specific, but I could imagine updating some kind of "output_quality"
> AVOption as a user slides a slider up and down.
> 
> But the CLI tools are largely non-interactive, so have I just misunderstood?
> 
> How about saying "AVOptions is a framework for command-line options"?

It is not about CLI options, although you can use introspection to get
the supported options and build an interface to set them.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v6 0/4] doc: Explain what "context" means
  2024-04-18 15:06 [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means Andrew Sayers
                   ` (3 preceding siblings ...)
  2024-05-15 15:54 ` [FFmpeg-devel] [PATCH v4 0/4] Explain what "context" means Andrew Sayers
@ 2024-06-04 14:47 ` Andrew Sayers
  2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 1/4] " Andrew Sayers
                     ` (3 more replies)
  4 siblings, 4 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-06-04 14:47 UTC (permalink / raw)
  To: ffmpeg-devel

I'm making a list of little documentation patches to submit as a set once this
patchset is done.  I've put Sw{r,s}Context on the list, and will think about
their relationship to other opaque AVOptions-enabled structs as part of that.
I don't see anything in that discussion that affects this patchset,
so let's park that discussion for now.

One thing we haven't talked about before, but is worth stating explicitly -
smart people tend to conflate "I can't think of anything complex about X"
with "there are no complex things about X", so this document needs to sell
people on the complexity of each problem before laying out the solution.
The AVOptions section is a particularly good example, tackling the implicit
question "can't you just use `getopt`?" first then moving on to describe how
it solves that problem.  Some parts of the document function as responses to 
questions an FFmpeg developer would never think to ask, because why would you 
even think to compare AVOptions with getopt?

This version emphasises how AVOptions should only be set during configuration.
It avoids the words "reflection" and "introspection" altogether, because IMHO
they imply an API that can be used in any stage of a struct's lifetime.

Aside: this is the latest in a series of issues where it initially seemed like
I was adding unnecessary terminology in places where it was confusing,
but turned out to be a symptom of a fundamental misunderstanding on my part.
If there's any such language remaining in this version, we should probably
look for those misunderstandings first and worry about language second.

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v6 1/4] doc: Explain what "context" means
  2024-06-04 14:47 ` [FFmpeg-devel] [PATCH v6 0/4] doc: Explain what "context" means Andrew Sayers
@ 2024-06-04 14:47   ` Andrew Sayers
  2024-06-05  8:15     ` Anton Khirnov
  2024-06-12 20:52     ` Stefano Sabatini
  2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
                     ` (2 subsequent siblings)
  3 siblings, 2 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-06-04 14:47 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Derived from explanations kindly provided by Stefano Sabatini and others:
https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
---
 doc/context.md | 430 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 430 insertions(+)
 create mode 100644 doc/context.md

diff --git a/doc/context.md b/doc/context.md
new file mode 100644
index 0000000000..bd8cb58696
--- /dev/null
+++ b/doc/context.md
@@ -0,0 +1,430 @@
+@page Context Introduction to contexts
+
+@tableofcontents
+
+FFmpeg uses the term “context” to refer to an idiom
+you have probably used before:
+
+```c
+// C structs often share context between functions:
+
+FILE *my_file; // my_file stores information about a filehandle
+
+printf(my_file, "hello "); // my_file provides context to this function,
+printf(my_file, "world!"); // and also to this function
+```
+
+```python
+# Python classes provide context for the methods they contain:
+
+class MyClass:
+    def print(self,message):
+        if self.prev_message != message:
+            self.prev_message = message
+            print(message)
+```
+
+<!-- marked "c" because Doxygen doesn't support JS highlighting: -->
+```c
+// Many JavaScript callbacks accept an optional context argument:
+
+const my_object = {};
+
+my_array.forEach(function_1, my_object);
+my_array.forEach(function_2, my_object);
+```
+
+Be careful comparing FFmpeg contexts to things you're already familiar with -
+FFmpeg may sometimes happen to reuse words you recognise, but mean something
+completely different.  For example, the AVClass struct has nothing to do with
+[object-oriented classes](https://en.wikipedia.org/wiki/Class_(computer_programming)).
+
+If you've used contexts in other C projects, you may want to read
+@ref Context_comparison before the rest of the document.
+
+@section Context_general “Context” as a general concept
+
+@par
+A context is any data structure used by several functions
+(or several instances of the same function) that all operate on the same entity.
+
+In the broadest sense, “context” is just a way to think about code.
+You can even use it to think about code written by people who have never
+heard the term, or who would disagree with you about what it means.
+Consider the following snippet:
+
+```c
+struct DualWriter {
+    int fd1, fd2;
+};
+
+ssize_t write_to_two_files(
+    struct DualWriter *my_writer,
+    uint8_t *buf,
+    int buf_size
+) {
+
+    ssize_t bytes_written_1 = write(my_writer->fd1, buf, buf_size);
+    ssize_t bytes_written_2 = write(my_writer->fd2, buf, buf_size);
+
+    if ( bytes_written_1 != bytes_written_2 ) {
+        // ... handle this edge case ...
+    }
+
+    return bytes_written_1;
+
+}
+
+int main() {
+
+    struct DualWriter my_writer;
+    my_writer.fd1 = open("file1", 0644, "wb");
+    my_writer.fd2 = open("file2", 0644, "wb");
+
+    write_to_two_files(&my_writer, "hello ", sizeof("hello "));
+    write_to_two_files(&my_writer, "world!", sizeof("world!"));
+
+    close( my_writer.fd1 );
+    close( my_writer.fd2 );
+
+}
+```
+
+The term “context” doesn't appear anywhere in the snippet.  But `DualWriter`
+is passed to several instances of `write_to_two_files()` that operate on
+the same entity, so it fits the definition of a context.
+
+When reading code that isn't explicitly described in terms of contexts,
+remember that your interpretation may differ from other people's.
+For example, FFmpeg's avio_alloc_context() accepts a set of callback functions
+and an `opaque` argument - even though this function guarantees to *return*
+a context, it does not require `opaque` to *provide* context for the callback
+functions.  So you could choose to pass a struct like `DualWriter` as the
+`opaque` argument, or you could pass callbacks that use `stdin` and `stdout`
+and just pass a `NULL` argument for `opaque`.
+
+When reading code that *is* explicitly described in terms of contexts,
+remember that the term's meaning is guaranteed by *the project's community*,
+not *the language it's written in*.  That means guarantees may be more flexible
+and change more over time.  For example, programming languages that use
+[encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))
+will simply refuse to compile code that violates its rules about access,
+while communities can put up with special cases if they improve code quality.
+
+The next section will discuss what specific conventions FFmpeg developers mean
+when they describe parts of their code as using “contexts”.
+
+@section Context_ffmpeg FFmpeg contexts
+
+This section discusses specific context-related conventions used in FFmpeg.
+Some of these are used in other projects, others are unique to this project.
+
+@subsection Context_indicating Indicating context: “Context”, “ctx” etc.
+
+```c
+// Context struct names usually end with `Context`:
+struct AVSomeContext {
+  ...
+};
+
+// Functions are usually named after their context,
+// context parameters usually come first and are often called `ctx`:
+void av_some_function(AVSomeContext *ctx, ...);
+```
+
+FFmpeg struct names usually signal whether they are contexts (e.g. AVBSFContext
+or AVCodecContext).  Exceptions to this rule include AVMD5, which is only
+identified as a context by @ref libavutil/md5.c "the functions that call it".
+
+Function names usually signal the context they're associated with (e.g.
+av_md5_alloc() or avcodec_alloc_context3()).  Exceptions to this rule include
+@ref avformat.h "AVFormatContext's functions", many of which begin with
+just `av_`.
+
+Functions usually signal their context parameter by putting it first and
+naming it some variant of `ctx`.  Exceptions include av_bsf_alloc(), which puts
+its context argument second to emphasise it's an out variable.
+
+Some functions fit awkwardly within FFmpeg's context idiom, so they send mixed
+signals.  For example, av_ambient_viewing_environment_create_side_data() creates
+an AVAmbientViewingEnvironment context, then adds it to the side-data of an
+AVFrame context.  So its name hints at one context, its parameter hints at
+another, and its documentation is silent on the issue.  You might prefer to
+think of such functions as not having a context, or as “receiving” one context
+and “producing” another.
+
+@subsection Context_data_hiding Data hiding: private contexts
+
+```c
+// Context structs often hide private context:
+struct AVSomeContext {
+  void *priv_data; // sometimes just called "internal"
+};
+```
+
+Contexts present a public interface, so changing a context's members forces
+everyone that uses the library to at least recompile their program,
+if not rewrite it to remain compatible.  Many contexts reduce this problem
+by including a private context with a type that is not exposed in the public
+interface.  Hiding information this way ensures it can be modified without
+affecting downstream software.
+
+Private contexts often store variables users aren't supposed to see
+(similar to an [OOP](https://en.wikipedia.org/wiki/Object-oriented_programming)
+private block), but can be used for more than just access control.  They can
+also store information shared between some but not all instances of a context
+(e.g. codec-specific functionality), and @ref Context_avoptions
+"AVOptions-enabled structs" can provide user configuration options through
+the @ref avoptions "AVOptions API".
+
+@subsection Context_lifetime Manage lifetime: creation, use, destruction
+
+```c
+void my_function(...) {
+
+    // Context structs are allocated then initialized with associated functions:
+
+    AVSomeContext *ctx = av_some_context_alloc(...);
+
+    // ... configure ctx ...
+
+    av_some_context_init(ctx, ...);
+
+    // ... use ctx ...
+
+    // Context structs are closed then freed with associated functions:
+
+    av_some_context_close(ctx);
+    av_some_context_free(ctx);
+
+}
+```
+
+FFmpeg contexts go through the following stages of life:
+
+1. allocation (often a function that ends with `_alloc`)
+   * a range of memory is allocated for use by the structure
+   * memory is allocated on boundaries that improve caching
+   * memory is reset to zeroes, some internal structures may be initialized
+2. configuration (implemented by setting values directly on the context)
+   * no function for this - calling code populates the structure directly
+   * memory is populated with useful values
+   * simple contexts can skip this stage
+3. initialization (often a function that ends with `_init`)
+   * setup actions are performed based on the configuration (e.g. opening files)
+5. normal usage
+   * most functions are called in this stage
+   * documentation implies some members are now read-only (or not used at all)
+   * some contexts allow re-initialization
+6. closing (often a function that ends with `_close()`)
+   * teardown actions are performed (e.g. closing files)
+7. deallocation (often a function that ends with `_free()`)
+   * memory is returned to the pool of available memory
+
+This can mislead object-oriented programmers, who expect something more like:
+
+1. allocation (usually a `new` keyword)
+   * a range of memory is allocated for use by the structure
+   * memory *may* be reset (e.g. for security reasons)
+2. initialization (usually a constructor)
+   * memory is populated with useful values
+   * related setup actions are performed based on arguments (e.g. opening files)
+3. normal usage
+   * most functions are called in this stage
+   * compiler enforces that some members are read-only (or private)
+   * no going back to the previous stage
+4. finalization (usually a destructor)
+   * teardown actions are performed (e.g. closing files)
+5. deallocation (usually a `delete` keyword)
+   * memory is returned to the pool of available memory
+
+The remainder of this section discusses FFmpeg's differences from OOP, to help
+object-oriented programmers avoid misconceptions.  You can safely skip this
+section if you aren't familiar with the OOP lifetime described above.
+
+FFmpeg's allocation stage is broadly similar to the OOP stage of the same name.
+Both set aside some memory for use by a new entity, but FFmpeg's stage can also
+do some higher-level operations.  For example, @ref Context_avoptions
+"AVOptions-enabled structs" set their AVClass member during allocation.
+
+FFmpeg's configuration stage involves setting any variables you want before
+you start using the context.  Complicated FFmpeg structures like AVCodecContext
+tend to have many members you *could* set, but in practice most programs set
+few if any of them.  The freeform configuration stage works better than bundling
+these into the initialization stage, which would lead to functions with
+impractically many parameters, and would mean each new option was an
+incompatible change to the API.  One way to understand the problem is to read
+@ref Context_avoptions "the AVOptions section below" and think how a constructor
+would handle those options.
+
+FFmpeg's initialization stage involves calling a function that sets the context
+up based on your configuration.
+
+FFmpeg's first three stages do the same job as OOP's first two stages.
+This can mislead object-oriented developers, who expect to do less work in the
+allocation stage, and more work in the initialization stage.  To simplify this,
+most FFmpeg contexts provide a combined allocator and initializer function.
+For historical reasons, suffixes like `_alloc`, `_init`, `_alloc_context` and
+even `_open` can indicate the function does any combination of allocation and
+initialization.
+
+FFmpeg's "closing" stage is broadly similar to OOP's "finalization" stage,
+but some contexts allow re-initialization after finalization.  For example,
+SwrContext lets you call swr_close() then swr_init() to reuse a context.
+Be aware that some FFmpeg functions happen to use the word "finalize" in a way
+that has nothing to do with the OOP stage (e.g. av_bsf_list_finalize()).
+
+FFmpeg's "deallocation" stage is broadly similar to OOP, but can perform some
+higher-level functions (similar to the allocation stage).
+
+Closing functions usually end with "_close", while deallocation
+functions usually end with "_free".  Very few contexts need the flexibility of
+separate "closing" and "deallocation" stages, so many "_free" functions
+implicitly close the context first.
+
+@subsection Context_avoptions Configuration options: AVOptions-enabled structs
+
+The @ref avoptions "AVOptions API" is a framework to configure user-facing
+options, e.g. on the command-line or in GUI configuration forms.
+
+To understand FFmpeg's configuration requirements, run `ffmpeg -h full` on the
+command-line, then ask yourself how you would implement all those options
+with the C standard [`getopt` function](https://en.wikipedia.org/wiki/Getopt).
+You can also ask the same question for other approaches - for example, how would
+you maintain a GUI with 15,000+ configuration options?
+
+Most solutions assume you can just put all options in a single code block,
+which is unworkable at FFmpeg's scale.  Instead, we split configuration
+across many *AVOptions-enabled structs*, which use the @ref avoptions
+"AVOptions API" to inspect and configure options, including in private contexts.
+
+AVOptions-accessible members of a context should be accessed through the
+@ref avoptions "AVOptions API" whenever possible, even if they're not hidden
+in a private context.  That ensures values are validated as they're set, and
+means you won't have to do as much work if a future version of FFmpeg changes
+the allowed values.
+
+Although not strictly required, it is best to only modify options during
+the configuration stage.  Initialized structs may be accessed by internal
+FFmpeg threads, and modifying them can cause weird intermittent bugs.
+
+@subsection Context_logging Logging: AVClass context structures
+
+FFmpeg's @ref lavu_log "logging facility" needs to be simple to use,
+but flexible enough to let people debug problems.  And much like options,
+it needs to work the same across a wide variety of unrelated structs.
+
+FFmpeg structs that support the logging framework are called *@ref AVClass
+context structures*.  The name @ref AVClass was chosen early in FFmpeg's
+development, but in practice it only came to store information about
+logging, and about options.
+
+@section Context_further Further information about contexts
+
+So far, this document has provided a theoretical guide to FFmpeg contexts.
+This final section provides some alternative approaches to the topic,
+which may help round out your understanding.
+
+@subsection Context_example Learning by example: context for a codec
+
+It can help to learn contexts by doing a deep dive into a specific struct.
+This section will discuss AVCodecContext - an AVOptions-enabled struct
+that contains information about encoding or decoding one stream of data
+(e.g. the video in a movie).
+
+The name "AVCodecContext" tells us this is a context.  Many of
+@ref libavcodec/avcodec.h "its functions" start with an `avctx` parameter,
+indicating this parameter provides context for that function.
+
+AVCodecContext::internal contains the private context.  For example,
+codec-specific information might be stored here.
+
+AVCodecContext is allocated with avcodec_alloc_context3(), initialized with
+avcodec_open2(), and freed with avcodec_free_context().  Most of its members
+are configured with the @ref avoptions "AVOptions API", but for example you
+can set AVCodecContext::draw_horiz_band() if your program happens to need it.
+
+AVCodecContext provides an abstract interface to many different *codecs*.
+Options supported by many codecs (e.g. "bitrate") are kept in AVCodecContext
+and exposed with AVOptions.  Options that are specific to one codec are
+stored in the private context, and also exposed with AVOptions.
+
+AVCodecContext::av_class contains logging metadata to ensure all codec-related
+error messages look the same, plus implementation details about options.
+
+To support a specific codec, AVCodecContext's private context is set to
+an encoder-specific data type.  For example, the video codec
+[H.264](https://en.wikipedia.org/wiki/Advanced_Video_Coding) is supported via
+[the x264 library](https://www.videolan.org/developers/x264.html), and
+implemented in X264Context.  Although included in the documentation, X264Context
+is not part of the public API.  That means FFmpeg's @ref ffmpeg_versioning
+"strict rules about changing public structs" aren't as important here, so a
+version of FFmpeg could modify X264Context or replace it with another type
+altogether.  An adverse legal ruling or security problem could even force us to
+switch to a completely different library without a major version bump.
+
+The design of AVCodecContext provides several important guarantees:
+
+- lets you use the same interface for any codec
+- supports common encoder options like "bitrate" without duplicating code
+- supports encoder-specific options like "profile" without bulking out the public interface
+- exposes both types of options to users, with help text and detection of missing options
+- provides uniform logging output
+- hides implementation details (e.g. its encoding buffer)
+
+@subsection Context_comparison Learning by comparison: FFmpeg vs. Curl contexts
+
+It can help to learn contexts by comparing how different projects tackle
+similar problems.  This section will compare @ref AVMD5 "FFmpeg's MD5 context"
+with [curl 8.8.0's equivalent](https://github.com/curl/curl/blob/curl-8_8_0/lib/md5.c#L48).
+
+The [MD5 algorithm](https://en.wikipedia.org/wiki/MD5) produces
+a fixed-length digest from arbitrary-length data.  It does this by calculating
+the digest for a prefix of the data, then loading the next part and adding it
+to the previous digest, and so on.
+
+```c
+// FFmpeg's MD5 context looks like this:
+typedef struct AVMD5 {
+    uint64_t len;
+    uint8_t  block[64];
+    uint32_t ABCD[4];
+} AVMD5;
+
+// Curl 8.8.0's MD5 context looks like this:
+struct MD5_context {
+  const struct MD5_params *md5_hash;    /* Hash function definition */
+  void                  *md5_hashctx;   /* Hash function context */
+};
+```
+
+Curl's struct name ends with `_context`, guaranteeing contexts are the correct
+interpretation.  FFmpeg's struct does not explicitly say it's a context, but
+@ref libavutil/md5.c "its functions do" so we can reasonably assume
+it's the intended interpretation.
+
+Curl's struct uses `void *md5_hashctx` to avoid guaranteeing
+implementation details in the public interface, whereas FFmpeg makes
+everything accessible.  This disagreement about data hiding is a good example
+of how contexts can be used differently.  Hiding the data means changing the
+layout in a future version of curl won't break downstream programs that used
+that data.  But the MD5 algorithm has been stable for 30 years, and making the
+data public makes it easier for people to follow a bug in their own code.
+
+Curl's struct is declared as `struct <type> { ... }`, whereas FFmpeg uses
+`typedef struct <type> { ... } <type>`.  These conventions are used with both
+context and non-context structs, so don't say anything about contexts as such.
+Specifically, FFmpeg's convention is a workaround for an issue with C grammar:
+
+```c
+void my_function(...) {
+  int                my_var;        // good
+  MD5_context        my_curl_ctx;   // error: C needs you to explicitly say "struct"
+  struct MD5_context my_curl_ctx;   // good: added "struct"
+  AVMD5              my_ffmpeg_ctx; // good: typedef's avoid the need for "struct"
+}
+```
+
+Both MD5 implementations are long-tested, widely-used examples of contexts
+in the real world.  They show how contexts can solve the same problem
+in different ways.
-- 
2.45.1

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v6 2/4] lavu: Clarify relationship between AVClass, AVOption and context
  2024-06-04 14:47 ` [FFmpeg-devel] [PATCH v6 0/4] doc: Explain what "context" means Andrew Sayers
  2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 1/4] " Andrew Sayers
@ 2024-06-04 14:47   ` Andrew Sayers
  2024-06-05 10:34     ` Stefano Sabatini
  2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 3/4] all: Link to "context" from all public contexts with documentation Andrew Sayers
  2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 4/4] all: Rewrite documentation for contexts Andrew Sayers
  3 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-06-04 14:47 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

---
 libavutil/log.h | 16 +++++++++++++---
 libavutil/opt.h | 26 +++++++++++++++++++++-----
 2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/libavutil/log.h b/libavutil/log.h
index ab7ceabe22..88b35897c6 100644
--- a/libavutil/log.h
+++ b/libavutil/log.h
@@ -59,9 +59,19 @@ typedef enum {
 struct AVOptionRanges;
 
 /**
- * Describe the class of an AVClass context structure. That is an
- * arbitrary struct of which the first field is a pointer to an
- * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.).
+ * Generic Logging facilities and configuration options
+ *
+ * Logging and AVOptions functions expect to be passed structs
+ * whose first member is a pointer-to-@ref AVClass.
+ *
+ * Structs that only use logging facilities are often referred to as
+ * "AVClass context structures", while those that provide configuration
+ * options are called "AVOptions-enabled structs".
+ *
+ * @see
+ * * @ref lavu_log
+ * * @ref avoptions
+ * * @ref Context
  */
 typedef struct AVClass {
     /**
diff --git a/libavutil/opt.h b/libavutil/opt.h
index 07e27a9208..cdee8f7d28 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -39,9 +39,16 @@
  * @defgroup avoptions AVOptions
  * @ingroup lavu_data
  * @{
- * AVOptions provide a generic system to declare options on arbitrary structs
- * ("objects"). An option can have a help text, a type and a range of possible
- * values. Options may then be enumerated, read and written to.
+ *
+ * Inspection and configuration for AVClass context structures
+ *
+ * Provides a generic API to declare and manage options on any struct
+ * whose first member is a pointer-to-@ref AVClass.  Structs with private
+ * contexts can use that AVClass to return further @ref AVClass "AVClass"es
+ * that allow access to options in the private structs.
+ *
+ * Each option can have a help text, a type and a range of possible values.
+ * Options may be enumerated, read and written to.
  *
  * There are two modes of access to members of AVOption and its child structs.
  * One is called 'native access', and refers to access from the code that
@@ -53,11 +60,20 @@
  * question is allowed to access the field. This allows us to extend the
  * semantics of those fields without breaking API compatibility.
  *
+ * Note that AVOptions is not reentrant, and that many FFmpeg functions access
+ * options from separate threads.  Unless otherwise indicated, it is best to
+ * avoid modifying options once a struct has been initialized.
+ *
+ * @see
+ * * @ref lavu_log
+ * * @ref Context
+ *
  * @section avoptions_scope Scope of AVOptions
  *
  * AVOptions is designed to support any set of multimedia configuration options
- * that can be defined at compile-time.  Although it is mainly used to expose
- * FFmpeg options, you are welcome to adapt it to your own use case.
+ * that can be defined at compile-time and set at object creation time.  Although
+ * it is mainly used to expose FFmpeg options, you are welcome to adapt it
+ * to your own use case.
  *
  * No single approach can ever fully solve the problem of configuration,
  * but please submit a patch if you believe you have found a problem
-- 
2.45.1

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v6 3/4] all: Link to "context" from all public contexts with documentation
  2024-06-04 14:47 ` [FFmpeg-devel] [PATCH v6 0/4] doc: Explain what "context" means Andrew Sayers
  2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 1/4] " Andrew Sayers
  2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
@ 2024-06-04 14:47   ` Andrew Sayers
  2024-06-05  8:12     ` Anton Khirnov
  2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 4/4] all: Rewrite documentation for contexts Andrew Sayers
  3 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-06-04 14:47 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

The goal of putting these links in "@see" blocks is to provide hooks
for future developers to add links to other useful parts of the codebase.
---
 libavcodec/avcodec.h             | 3 +++
 libavcodec/bsf.h                 | 3 +++
 libavcodec/d3d11va.h             | 3 +++
 libavcodec/mediacodec.h          | 2 ++
 libavcodec/qsv.h                 | 3 +++
 libavcodec/vdpau.h               | 3 +++
 libavcodec/videotoolbox.h        | 3 +++
 libavfilter/avfilter.h           | 7 ++++++-
 libavformat/avformat.h           | 3 +++
 libavformat/avio.h               | 3 +++
 libavutil/audio_fifo.h           | 3 +++
 libavutil/hwcontext.h            | 6 ++++++
 libavutil/hwcontext_cuda.h       | 3 +++
 libavutil/hwcontext_d3d11va.h    | 6 ++++++
 libavutil/hwcontext_d3d12va.h    | 6 ++++++
 libavutil/hwcontext_drm.h        | 3 +++
 libavutil/hwcontext_dxva2.h      | 6 ++++++
 libavutil/hwcontext_mediacodec.h | 3 +++
 libavutil/hwcontext_opencl.h     | 6 ++++++
 libavutil/hwcontext_qsv.h        | 6 ++++++
 libavutil/hwcontext_vaapi.h      | 6 ++++++
 libavutil/hwcontext_vdpau.h      | 3 +++
 libavutil/hwcontext_vulkan.h     | 6 ++++++
 libavutil/lfg.h                  | 3 +++
 24 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 2da63c87ea..abc00ab394 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -441,6 +441,9 @@ typedef struct RcOverride{
  * The AVOption/command line parameter names differ in some cases from the C
  * structure field names for historic reasons or brevity.
  * sizeof(AVCodecContext) must not be used outside libav*.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVCodecContext {
     /**
diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
index a09c69f242..ee5fdd48d2 100644
--- a/libavcodec/bsf.h
+++ b/libavcodec/bsf.h
@@ -64,6 +64,9 @@
  * The fields in the struct will only be changed (by the caller or by the
  * filter) as described in their documentation, and are to be considered
  * immutable otherwise.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVBSFContext {
     /**
diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
index 27f40e5519..686974b083 100644
--- a/libavcodec/d3d11va.h
+++ b/libavcodec/d3d11va.h
@@ -52,6 +52,9 @@
  * The application must make it available as AVCodecContext.hwaccel_context.
  *
  * Use av_d3d11va_alloc_context() exclusively to allocate an AVD3D11VAContext.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVD3D11VAContext {
     /**
diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
index 4e9b56a618..43f049a609 100644
--- a/libavcodec/mediacodec.h
+++ b/libavcodec/mediacodec.h
@@ -29,6 +29,8 @@
  * This structure holds a reference to a android/view/Surface object that will
  * be used as output by the decoder.
  *
+ * @see
+ * - @ref Context
  */
 typedef struct AVMediaCodecContext {
 
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index c156b08d07..8ab93af6b6 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -32,6 +32,9 @@
  * - decoding: hwaccel_context must be set on return from the get_format()
  *             callback
  * - encoding: hwaccel_context must be set before avcodec_open2()
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVQSVContext {
     /**
diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
index 8021c25761..934c96b88c 100644
--- a/libavcodec/vdpau.h
+++ b/libavcodec/vdpau.h
@@ -74,6 +74,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
  *
  * The size of this structure is not a part of the public ABI and must not
  * be used outside of libavcodec.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVDPAUContext {
     /**
diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
index d68d76e400..81d90d63b6 100644
--- a/libavcodec/videotoolbox.h
+++ b/libavcodec/videotoolbox.h
@@ -53,6 +53,9 @@
  * between the caller and libavcodec for initializing Videotoolbox decoding.
  * Its size is not a part of the public ABI, it must be allocated with
  * av_videotoolbox_alloc_context() and freed with av_free().
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVideotoolboxContext {
     /**
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index a34e61f23c..25ccd80433 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -403,7 +403,12 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
  */
 #define AVFILTER_THREAD_SLICE (1 << 0)
 
-/** An instance of a filter */
+/**
+ * An instance of a filter
+ *
+ * @see
+ * - @ref Context
+ */
 struct AVFilterContext {
     const AVClass *av_class;        ///< needed for av_log() and filters common options
 
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 8afdcd9fd0..18f20f0bb0 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1253,6 +1253,9 @@ enum AVDurationEstimationMethod {
  * can be found in libavformat/options_table.h.
  * The AVOption/command line parameter names differ in some cases from the C
  * structure field names for historic reasons or brevity.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVFormatContext {
     /**
diff --git a/libavformat/avio.h b/libavformat/avio.h
index ebf611187d..d68f912a2f 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -156,6 +156,9 @@ enum AVIODataMarkerType {
  *       directly, they should only be set by the client application
  *       when implementing custom I/O. Normally these are set to the
  *       function pointers specified in avio_alloc_context()
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVIOContext {
     /**
diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h
index fa5f59a2be..6fdb114af8 100644
--- a/libavutil/audio_fifo.h
+++ b/libavutil/audio_fifo.h
@@ -44,6 +44,9 @@
  * - Operates at the sample level rather than the byte level.
  * - Supports multiple channels with either planar or packed sample format.
  * - Automatic reallocation when writing to a full buffer.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVAudioFifo AVAudioFifo;
 
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index bac30debae..6bbb96fcd6 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -56,6 +56,9 @@ enum AVHWDeviceType {
  * references are released, the AVHWDeviceContext itself will be freed,
  * optionally invoking a user-specified callback for uninitializing the hardware
  * state.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVHWDeviceContext {
     /**
@@ -111,6 +114,9 @@ typedef struct AVHWDeviceContext {
  * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
  * yields a reference, whose data field points to the actual AVHWFramesContext
  * struct.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVHWFramesContext {
     /**
diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
index cbad434fea..0db5a69f0a 100644
--- a/libavutil/hwcontext_cuda.h
+++ b/libavutil/hwcontext_cuda.h
@@ -38,6 +38,9 @@ typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
 
 /**
  * This struct is allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVCUDADeviceContext {
     CUcontext cuda_ctx;
diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
index 77d2d72f1b..5b7763e73f 100644
--- a/libavutil/hwcontext_d3d11va.h
+++ b/libavutil/hwcontext_d3d11va.h
@@ -41,6 +41,9 @@
 
 /**
  * This struct is allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVD3D11VADeviceContext {
     /**
@@ -127,6 +130,9 @@ typedef struct AVD3D11FrameDescriptor {
 
 /**
  * This struct is allocated as AVHWFramesContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVD3D11VAFramesContext {
     /**
diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
index ff06e6f2ef..63281aa835 100644
--- a/libavutil/hwcontext_d3d12va.h
+++ b/libavutil/hwcontext_d3d12va.h
@@ -39,6 +39,8 @@
 /**
  * @brief This struct is allocated as AVHWDeviceContext.hwctx
  *
+ * @see
+ * - @ref Context
  */
 typedef struct AVD3D12VADeviceContext {
     /**
@@ -80,6 +82,8 @@ typedef struct AVD3D12VADeviceContext {
 /**
  * @brief This struct is used to sync d3d12 execution
  *
+ * @see
+ * - @ref Context
  */
 typedef struct AVD3D12VASyncContext {
     /**
@@ -122,6 +126,8 @@ typedef struct AVD3D12VAFrame {
 /**
  * @brief This struct is allocated as AVHWFramesContext.hwctx
  *
+ * @see
+ * - @ref Context
  */
 typedef struct AVD3D12VAFramesContext {
     /**
diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
index 42709f215e..eb0b6e734a 100644
--- a/libavutil/hwcontext_drm.h
+++ b/libavutil/hwcontext_drm.h
@@ -153,6 +153,9 @@ typedef struct AVDRMFrameDescriptor {
  * DRM device.
  *
  * Allocated as AVHWDeviceContext.hwctx.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVDRMDeviceContext {
     /**
diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
index e1b79bc0de..3accd8d070 100644
--- a/libavutil/hwcontext_dxva2.h
+++ b/libavutil/hwcontext_dxva2.h
@@ -35,6 +35,9 @@
 
 /**
  * This struct is allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVDXVA2DeviceContext {
     IDirect3DDeviceManager9 *devmgr;
@@ -42,6 +45,9 @@ typedef struct AVDXVA2DeviceContext {
 
 /**
  * This struct is allocated as AVHWFramesContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVDXVA2FramesContext {
     /**
diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
index fc0263cabc..77d7d4e3a5 100644
--- a/libavutil/hwcontext_mediacodec.h
+++ b/libavutil/hwcontext_mediacodec.h
@@ -23,6 +23,9 @@
  * MediaCodec details.
  *
  * Allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVMediaCodecDeviceContext {
     /**
diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
index ef54486c95..4c184484c9 100644
--- a/libavutil/hwcontext_opencl.h
+++ b/libavutil/hwcontext_opencl.h
@@ -59,6 +59,9 @@ typedef struct AVOpenCLFrameDescriptor {
  * OpenCL device details.
  *
  * Allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVOpenCLDeviceContext {
     /**
@@ -85,6 +88,9 @@ typedef struct AVOpenCLDeviceContext {
  * OpenCL-specific data associated with a frame pool.
  *
  * Allocated as AVHWFramesContext.hwctx.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVOpenCLFramesContext {
     /**
diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
index 35530e4e93..b4a84c9893 100644
--- a/libavutil/hwcontext_qsv.h
+++ b/libavutil/hwcontext_qsv.h
@@ -31,6 +31,9 @@
 
 /**
  * This struct is allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVQSVDeviceContext {
     mfxSession session;
@@ -49,6 +52,9 @@ typedef struct AVQSVDeviceContext {
 
 /**
  * This struct is allocated as AVHWFramesContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVQSVFramesContext {
     /**
diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
index 0b2e071cb3..02399ff7dc 100644
--- a/libavutil/hwcontext_vaapi.h
+++ b/libavutil/hwcontext_vaapi.h
@@ -64,6 +64,9 @@ enum {
  * VAAPI connection details.
  *
  * Allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVAAPIDeviceContext {
     /**
@@ -84,6 +87,9 @@ typedef struct AVVAAPIDeviceContext {
  * VAAPI-specific data associated with a frame pool.
  *
  * Allocated as AVHWFramesContext.hwctx.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVAAPIFramesContext {
     /**
diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
index 1b7ea1e443..051af42dfc 100644
--- a/libavutil/hwcontext_vdpau.h
+++ b/libavutil/hwcontext_vdpau.h
@@ -31,6 +31,9 @@
 
 /**
  * This struct is allocated as AVHWDeviceContext.hwctx
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVDPAUDeviceContext {
     VdpDevice          device;
diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
index cbbd2390c1..6dfe4badfe 100644
--- a/libavutil/hwcontext_vulkan.h
+++ b/libavutil/hwcontext_vulkan.h
@@ -41,6 +41,9 @@ typedef struct AVVkFrame AVVkFrame;
 /**
  * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
  * All of these can be set before init to change what the context uses
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVulkanDeviceContext {
     /**
@@ -173,6 +176,9 @@ typedef enum AVVkFrameFlags {
 
 /**
  * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVVulkanFramesContext {
     /**
diff --git a/libavutil/lfg.h b/libavutil/lfg.h
index e75a986f12..4e420b0e16 100644
--- a/libavutil/lfg.h
+++ b/libavutil/lfg.h
@@ -29,6 +29,9 @@
  * The exact layout, types and content of this struct may change and should
  * not be accessed directly. Only its `sizeof()` is guaranteed to stay the same
  * to allow easy instanciation.
+ *
+ * @see
+ * - @ref Context
  */
 typedef struct AVLFG {
     unsigned int state[64];
-- 
2.45.1

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] [PATCH v6 4/4] all: Rewrite documentation for contexts
  2024-06-04 14:47 ` [FFmpeg-devel] [PATCH v6 0/4] doc: Explain what "context" means Andrew Sayers
                     ` (2 preceding siblings ...)
  2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 3/4] all: Link to "context" from all public contexts with documentation Andrew Sayers
@ 2024-06-04 14:47   ` Andrew Sayers
  3 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-06-04 14:47 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andrew Sayers

Make their documentation more readable and similar to each other,
(hopefully) without changing the meaning.
---
 libavcodec/aac/aacdec.h          |  2 +-
 libavcodec/aacenc.h              |  2 +-
 libavcodec/ac3enc.h              |  2 +-
 libavcodec/amfenc.h              |  2 +-
 libavcodec/atrac.h               |  2 +-
 libavcodec/avcodec.h             |  3 ++-
 libavcodec/bsf.h                 |  2 +-
 libavcodec/cbs.h                 |  2 +-
 libavcodec/d3d11va.h             |  3 +--
 libavcodec/mediacodec.h          |  4 ++--
 libavcodec/pthread_frame.c       |  4 ++--
 libavcodec/qsv.h                 |  6 ++++--
 libavcodec/sbr.h                 |  2 +-
 libavcodec/vdpau.h               |  5 +++--
 libavcodec/videotoolbox.h        |  5 +++--
 libavfilter/avfilter.h           |  2 +-
 libavformat/avformat.h           |  3 ++-
 libavformat/avio.h               |  3 ++-
 libavutil/audio_fifo.h           |  2 +-
 libavutil/hwcontext.h            | 21 ++++++++++++---------
 libavutil/hwcontext_cuda.h       |  2 +-
 libavutil/hwcontext_d3d11va.h    |  4 ++--
 libavutil/hwcontext_d3d12va.h    |  6 +++---
 libavutil/hwcontext_drm.h        |  2 +-
 libavutil/hwcontext_dxva2.h      |  4 ++--
 libavutil/hwcontext_mediacodec.h |  2 +-
 libavutil/hwcontext_opencl.h     |  4 ++--
 libavutil/hwcontext_qsv.h        |  4 ++--
 libavutil/hwcontext_vaapi.h      |  4 ++--
 libavutil/hwcontext_vdpau.h      |  2 +-
 libavutil/hwcontext_vulkan.h     |  5 +++--
 libavutil/lfg.h                  |  3 ++-
 32 files changed, 65 insertions(+), 54 deletions(-)

diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
index ee21a94007..f0d613afd9 100644
--- a/libavcodec/aac/aacdec.h
+++ b/libavcodec/aac/aacdec.h
@@ -441,7 +441,7 @@ typedef struct AACDecDSP {
 } AACDecDSP;
 
 /**
- * main AAC decoding context
+ * Context for decoding AAC
  */
 struct AACDecContext {
     const struct AVClass  *class;
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index d07960620e..3e710c7fac 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -207,7 +207,7 @@ typedef struct AACPCEInfo {
 } AACPCEInfo;
 
 /**
- * AAC encoder context
+ * Context for encoding AAC
  */
 typedef struct AACEncContext {
     AVClass *av_class;
diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
index 5e98ad188b..e5abe0a856 100644
--- a/libavcodec/ac3enc.h
+++ b/libavcodec/ac3enc.h
@@ -153,7 +153,7 @@ typedef struct AC3Block {
 struct PutBitContext;
 
 /**
- * AC-3 encoder private context.
+ * Private context for encoding AC-3
  */
 typedef struct AC3EncodeContext {
     AVClass *av_class;                      ///< AVClass used for AVOption
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
index 2dbd378ef8..184897beeb 100644
--- a/libavcodec/amfenc.h
+++ b/libavcodec/amfenc.h
@@ -43,7 +43,7 @@ typedef struct AmfTraceWriter {
 } AmfTraceWriter;
 
 /**
-* AMF encoder context
+* Context for encoding AMF
 */
 
 typedef struct AmfContext {
diff --git a/libavcodec/atrac.h b/libavcodec/atrac.h
index 05208bbee6..e760f0384d 100644
--- a/libavcodec/atrac.h
+++ b/libavcodec/atrac.h
@@ -39,7 +39,7 @@ typedef struct AtracGainInfo {
 } AtracGainInfo;
 
 /**
- *  Gain compensation context structure.
+ *  Context for gain compensation
  */
 typedef struct AtracGCContext {
     float   gain_tab1[16];  ///< gain compensation level table
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index abc00ab394..2fed4757ed 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -430,7 +430,8 @@ typedef struct RcOverride{
 #define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0)
 
 /**
- * main external API structure.
+ * Context for an encode or decode session
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
index ee5fdd48d2..fadcfc5d47 100644
--- a/libavcodec/bsf.h
+++ b/libavcodec/bsf.h
@@ -56,7 +56,7 @@
  */
 
 /**
- * The bitstream filter state.
+ * Context for bitstream filtering
  *
  * This struct must be allocated with av_bsf_alloc() and freed with
  * av_bsf_free().
diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
index d479b1ac2d..c074dd11ec 100644
--- a/libavcodec/cbs.h
+++ b/libavcodec/cbs.h
@@ -214,7 +214,7 @@ typedef void (*CBSTraceWriteCallback)(void *trace_context,
                                       int64_t value);
 
 /**
- * Context structure for coded bitstream operations.
+ * Context for coded bitstream operations
  */
 typedef struct CodedBitstreamContext {
     /**
diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
index 686974b083..5ffee2b3be 100644
--- a/libavcodec/d3d11va.h
+++ b/libavcodec/d3d11va.h
@@ -46,8 +46,7 @@
  */
 
 /**
- * This structure is used to provides the necessary configurations and data
- * to the Direct3D11 FFmpeg HWAccel implementation.
+ * Context for the Direct3D11 FFmpeg HWAccel implementation
  *
  * The application must make it available as AVCodecContext.hwaccel_context.
  *
diff --git a/libavcodec/mediacodec.h b/libavcodec/mediacodec.h
index 43f049a609..49af9513b0 100644
--- a/libavcodec/mediacodec.h
+++ b/libavcodec/mediacodec.h
@@ -26,8 +26,8 @@
 #include "libavcodec/avcodec.h"
 
 /**
- * This structure holds a reference to a android/view/Surface object that will
- * be used as output by the decoder.
+ * Context for the android/view/Surface object that will
+ * be used as output by the decoder
  *
  * @see
  * - @ref Context
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 982e4a64c5..c462159022 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -69,7 +69,7 @@ typedef struct ThreadFrameProgress {
 } ThreadFrameProgress;
 
 /**
- * Context used by codec threads and stored in their AVCodecInternal thread_ctx.
+ * Context used by codec threads and allocated as AVCodecInternal.thread_ctx
  */
 typedef struct PerThreadContext {
     struct FrameThreadContext *parent;
@@ -113,7 +113,7 @@ typedef struct PerThreadContext {
 } PerThreadContext;
 
 /**
- * Context stored in the client AVCodecInternal thread_ctx.
+ * Context allocated as AVCodecInternal.thread_ctx
  */
 typedef struct FrameThreadContext {
     PerThreadContext *threads;     ///< The contexts for each thread.
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index 8ab93af6b6..9d36197fbf 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -26,8 +26,10 @@
 #include "libavutil/buffer.h"
 
 /**
- * This struct is used for communicating QSV parameters between libavcodec and
- * the caller. It is managed by the caller and must be assigned to
+ * Context for communicating QSV parameters between libavcodec
+ * and the caller.
+ *
+ * It is managed by the caller and must be assigned to
  * AVCodecContext.hwaccel_context.
  * - decoding: hwaccel_context must be set on return from the get_format()
  *             callback
diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
index fe3a39603a..ea0760776c 100644
--- a/libavcodec/sbr.h
+++ b/libavcodec/sbr.h
@@ -116,7 +116,7 @@ typedef struct SBRData {
 typedef struct SpectralBandReplication SpectralBandReplication;
 
 /**
- * aacsbr functions pointers
+ * Context for aacsbr functions
  */
 typedef struct AACSBRContext {
     int (*sbr_lf_gen)(SpectralBandReplication *sbr,
diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
index 934c96b88c..e20f37ef2a 100644
--- a/libavcodec/vdpau.h
+++ b/libavcodec/vdpau.h
@@ -64,8 +64,9 @@ typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
                                const VdpBitstreamBuffer *);
 
 /**
- * This structure is used to share data between the libavcodec library and
- * the client video application.
+ * Context to share data between the libavcodec library and
+ * the client video application
+ *
  * This structure will be allocated and stored in AVCodecContext.hwaccel_context
  * by av_vdpau_bind_context(). Members can be set by the user once
  * during initialization or through each AVCodecContext.get_buffer()
diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h
index 81d90d63b6..dfc5c1a5a5 100644
--- a/libavcodec/videotoolbox.h
+++ b/libavcodec/videotoolbox.h
@@ -49,8 +49,9 @@
 #include "libavutil/attributes.h"
 
 /**
- * This struct holds all the information that needs to be passed
- * between the caller and libavcodec for initializing Videotoolbox decoding.
+ * Context for information passed between the caller and libavcodec
+ * for initializing Videotoolbox decoding
+ *
  * Its size is not a part of the public ABI, it must be allocated with
  * av_videotoolbox_alloc_context() and freed with av_free().
  *
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 25ccd80433..15aaba6ea2 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -404,7 +404,7 @@ unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);
 #define AVFILTER_THREAD_SLICE (1 << 0)
 
 /**
- * An instance of a filter
+ * Context for a filter
  *
  * @see
  * - @ref Context
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 18f20f0bb0..d8abab56d8 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1241,7 +1241,8 @@ enum AVDurationEstimationMethod {
 };
 
 /**
- * Format I/O context.
+ * Context for format I/O
+ *
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
  * version bump.
diff --git a/libavformat/avio.h b/libavformat/avio.h
index d68f912a2f..bf017f1338 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -146,7 +146,8 @@ enum AVIODataMarkerType {
 };
 
 /**
- * Bytestream IO Context.
+ * Context for bytestream I/O
+ *
  * New public fields can be added with minor version bumps.
  * Removal, reordering and changes to existing public fields require
  * a major version bump.
diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h
index 6fdb114af8..ab56ef69f5 100644
--- a/libavutil/audio_fifo.h
+++ b/libavutil/audio_fifo.h
@@ -39,7 +39,7 @@
  */
 
 /**
- * Context for an Audio FIFO Buffer.
+ * Context for an Audio FIFO Buffer
  *
  * - Operates at the sample level rather than the byte level.
  * - Supports multiple channels with either planar or packed sample format.
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index 6bbb96fcd6..18d25a644c 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -41,12 +41,13 @@ enum AVHWDeviceType {
 };
 
 /**
- * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
- * i.e. state that is not tied to a concrete processing configuration.
- * E.g., in an API that supports hardware-accelerated encoding and decoding,
- * this struct will (if possible) wrap the state that is common to both encoding
- * and decoding and from which specific instances of encoders or decoders can be
- * derived.
+ * Context for (hardware/vendor-specific) "high-level" state
+ *
+ * "High-level state" is anything that is not tied to a concrete processing
+ * configuration. E.g., in an API that supports hardware-accelerated encoding
+ * and decoding, this struct will (if possible) wrap the state that is common
+ * to both encoding and decoding and from which specific instances of encoders
+ * or decoders can be derived.
  *
  * This struct is reference-counted with the AVBuffer mechanism. The
  * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
@@ -106,9 +107,11 @@ typedef struct AVHWDeviceContext {
 } AVHWDeviceContext;
 
 /**
- * This struct describes a set or pool of "hardware" frames (i.e. those with
- * data not located in normal system memory). All the frames in the pool are
- * assumed to be allocated in the same way and interchangeable.
+ * Context for a pool of "hardware" frames (those with data not located
+ * in normal system memory)
+ *
+ * All the frames in the pool are assumed to be allocated in the same way and
+ * interchangeable.
  *
  * This struct is reference-counted with the AVBuffer mechanism and tied to a
  * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
index 0db5a69f0a..bb380d5450 100644
--- a/libavutil/hwcontext_cuda.h
+++ b/libavutil/hwcontext_cuda.h
@@ -37,7 +37,7 @@
 typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
index 5b7763e73f..ce07f84450 100644
--- a/libavutil/hwcontext_d3d11va.h
+++ b/libavutil/hwcontext_d3d11va.h
@@ -40,7 +40,7 @@
 #include <stdint.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
@@ -129,7 +129,7 @@ typedef struct AVD3D11FrameDescriptor {
 } AVD3D11FrameDescriptor;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * Context allocated as AVHWFramesContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
index 63281aa835..f741fc00e8 100644
--- a/libavutil/hwcontext_d3d12va.h
+++ b/libavutil/hwcontext_d3d12va.h
@@ -37,7 +37,7 @@
 #include <d3d12video.h>
 
 /**
- * @brief This struct is allocated as AVHWDeviceContext.hwctx
+ * @brief Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
@@ -80,7 +80,7 @@ typedef struct AVD3D12VADeviceContext {
 } AVD3D12VADeviceContext;
 
 /**
- * @brief This struct is used to sync d3d12 execution
+ * @brief Context for syncing d3d12 execution
  *
  * @see
  * - @ref Context
@@ -124,7 +124,7 @@ typedef struct AVD3D12VAFrame {
 } AVD3D12VAFrame;
 
 /**
- * @brief This struct is allocated as AVHWFramesContext.hwctx
+ * @brief Context allocated as AVHWFramesContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
index eb0b6e734a..f8aa75c5cf 100644
--- a/libavutil/hwcontext_drm.h
+++ b/libavutil/hwcontext_drm.h
@@ -152,7 +152,7 @@ typedef struct AVDRMFrameDescriptor {
 /**
  * DRM device.
  *
- * Allocated as AVHWDeviceContext.hwctx.
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
index 3accd8d070..a2320ea18a 100644
--- a/libavutil/hwcontext_dxva2.h
+++ b/libavutil/hwcontext_dxva2.h
@@ -34,7 +34,7 @@
 #include <dxva2api.h>
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
@@ -44,7 +44,7 @@ typedef struct AVDXVA2DeviceContext {
 } AVDXVA2DeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * Context allocated as AVHWFramesContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h
index 77d7d4e3a5..ada61fa61e 100644
--- a/libavutil/hwcontext_mediacodec.h
+++ b/libavutil/hwcontext_mediacodec.h
@@ -22,7 +22,7 @@
 /**
  * MediaCodec details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h
index 4c184484c9..0c3ef04fc6 100644
--- a/libavutil/hwcontext_opencl.h
+++ b/libavutil/hwcontext_opencl.h
@@ -58,7 +58,7 @@ typedef struct AVOpenCLFrameDescriptor {
 /**
  * OpenCL device details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
@@ -87,7 +87,7 @@ typedef struct AVOpenCLDeviceContext {
 /**
  * OpenCL-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * Context allocated as AVHWFramesContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
index b4a84c9893..afdddbce0e 100644
--- a/libavutil/hwcontext_qsv.h
+++ b/libavutil/hwcontext_qsv.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
@@ -51,7 +51,7 @@ typedef struct AVQSVDeviceContext {
 } AVQSVDeviceContext;
 
 /**
- * This struct is allocated as AVHWFramesContext.hwctx
+ * Context allocated as AVHWFramesContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
index 02399ff7dc..a6c1b25415 100644
--- a/libavutil/hwcontext_vaapi.h
+++ b/libavutil/hwcontext_vaapi.h
@@ -63,7 +63,7 @@ enum {
 /**
  * VAAPI connection details.
  *
- * Allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
@@ -86,7 +86,7 @@ typedef struct AVVAAPIDeviceContext {
 /**
  * VAAPI-specific data associated with a frame pool.
  *
- * Allocated as AVHWFramesContext.hwctx.
+ * Context allocated as AVHWFramesContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
index 051af42dfc..a2e6fcf5ba 100644
--- a/libavutil/hwcontext_vdpau.h
+++ b/libavutil/hwcontext_vdpau.h
@@ -30,7 +30,7 @@
  */
 
 /**
- * This struct is allocated as AVHWDeviceContext.hwctx
+ * Context allocated as AVHWDeviceContext.hwctx
  *
  * @see
  * - @ref Context
diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
index 6dfe4badfe..3766546100 100644
--- a/libavutil/hwcontext_vulkan.h
+++ b/libavutil/hwcontext_vulkan.h
@@ -39,7 +39,8 @@ typedef struct AVVkFrame AVVkFrame;
  */
 
 /**
- * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
+ * Context for Vulkan, allocated as AVHWDeviceContext.hwctx
+ *
  * All of these can be set before init to change what the context uses
  *
  * @see
@@ -175,7 +176,7 @@ typedef enum AVVkFrameFlags {
 } AVVkFrameFlags;
 
 /**
- * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
+ * Context allocated as AVHWFramesContext.hwctx, used to set pool-specific options
  *
  * @see
  * - @ref Context
diff --git a/libavutil/lfg.h b/libavutil/lfg.h
index 4e420b0e16..4ee7834fe4 100644
--- a/libavutil/lfg.h
+++ b/libavutil/lfg.h
@@ -25,7 +25,8 @@
 #include <stdint.h>
 
 /**
- * Context structure for the Lagged Fibonacci PRNG.
+ * Context structure for the Lagged Fibonacci PRNG
+ *
  * The exact layout, types and content of this struct may change and should
  * not be accessed directly. Only its `sizeof()` is guaranteed to stay the same
  * to allow easy instanciation.
-- 
2.45.1

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v6 3/4] all: Link to "context" from all public contexts with documentation
  2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 3/4] all: Link to "context" from all public contexts with documentation Andrew Sayers
@ 2024-06-05  8:12     ` Anton Khirnov
  2024-06-05 12:51       ` Andrew Sayers
  0 siblings, 1 reply; 84+ messages in thread
From: Anton Khirnov @ 2024-06-05  8:12 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andrew Sayers

Quoting Andrew Sayers (2024-06-04 16:47:23)
> The goal of putting these links in "@see" blocks is to provide hooks
> for future developers to add links to other useful parts of the codebase.
> ---
>  libavcodec/avcodec.h             | 3 +++
>  libavcodec/bsf.h                 | 3 +++
>  libavcodec/d3d11va.h             | 3 +++
>  libavcodec/mediacodec.h          | 2 ++
>  libavcodec/qsv.h                 | 3 +++
>  libavcodec/vdpau.h               | 3 +++
>  libavcodec/videotoolbox.h        | 3 +++
>  libavfilter/avfilter.h           | 7 ++++++-
>  libavformat/avformat.h           | 3 +++
>  libavformat/avio.h               | 3 +++
>  libavutil/audio_fifo.h           | 3 +++
>  libavutil/hwcontext.h            | 6 ++++++
>  libavutil/hwcontext_cuda.h       | 3 +++
>  libavutil/hwcontext_d3d11va.h    | 6 ++++++
>  libavutil/hwcontext_d3d12va.h    | 6 ++++++
>  libavutil/hwcontext_drm.h        | 3 +++
>  libavutil/hwcontext_dxva2.h      | 6 ++++++
>  libavutil/hwcontext_mediacodec.h | 3 +++
>  libavutil/hwcontext_opencl.h     | 6 ++++++
>  libavutil/hwcontext_qsv.h        | 6 ++++++
>  libavutil/hwcontext_vaapi.h      | 6 ++++++
>  libavutil/hwcontext_vdpau.h      | 3 +++
>  libavutil/hwcontext_vulkan.h     | 6 ++++++
>  libavutil/lfg.h                  | 3 +++
>  24 files changed, 98 insertions(+), 1 deletion(-)

IMO this is pointless churn.

-- 
Anton Khirnov
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v6 1/4] doc: Explain what "context" means
  2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 1/4] " Andrew Sayers
@ 2024-06-05  8:15     ` Anton Khirnov
  2024-06-12 20:52     ` Stefano Sabatini
  1 sibling, 0 replies; 84+ messages in thread
From: Anton Khirnov @ 2024-06-05  8:15 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andrew Sayers

Quoting Andrew Sayers (2024-06-04 16:47:21)
> Derived from explanations kindly provided by Stefano Sabatini and others:
> https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
> ---
>  doc/context.md | 430 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 430 insertions(+)
>  create mode 100644 doc/context.md

430 lines to say "context is a struct storing an object's state"?

-- 
Anton Khirnov
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v6 2/4] lavu: Clarify relationship between AVClass, AVOption and context
  2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
@ 2024-06-05 10:34     ` Stefano Sabatini
  2024-06-05 12:46       ` Andrew Sayers
  0 siblings, 1 reply; 84+ messages in thread
From: Stefano Sabatini @ 2024-06-05 10:34 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andrew Sayers

On date Tuesday 2024-06-04 15:47:22 +0100, Andrew Sayers wrote:
> ---
>  libavutil/log.h | 16 +++++++++++++---
>  libavutil/opt.h | 26 +++++++++++++++++++++-----
>  2 files changed, 34 insertions(+), 8 deletions(-)
> 
> diff --git a/libavutil/log.h b/libavutil/log.h
> index ab7ceabe22..88b35897c6 100644
> --- a/libavutil/log.h
> +++ b/libavutil/log.h
> @@ -59,9 +59,19 @@ typedef enum {
>  struct AVOptionRanges;
>  
>  /**
> - * Describe the class of an AVClass context structure. That is an
> - * arbitrary struct of which the first field is a pointer to an
> - * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.).

> + * Generic Logging facilities and configuration options

Generic logging and options handling facilities.

> + *
> + * Logging and AVOptions functions expect to be passed structs

Logging and options handling functions ...

> + * whose first member is a pointer-to-@ref AVClass.
> + *

> + * Structs that only use logging facilities are often referred to as
> + * "AVClass context structures", while those that provide configuration
> + * options are called "AVOptions-enabled structs".

A struct with an AVClass as its first member can be used for both
logging and options management, there is no difference between the
two. My take:
|Structs that use AVClass might be referred to as AVClass
|contexts/structures, those that in addition define options might be
|called AVOptions contexts/structures.

> + *
> + * @see
> + * * @ref lavu_log
> + * * @ref avoptions
> + * * @ref Context
>   */
>  typedef struct AVClass {
>      /**
> diff --git a/libavutil/opt.h b/libavutil/opt.h
> index 07e27a9208..cdee8f7d28 100644
> --- a/libavutil/opt.h
> +++ b/libavutil/opt.h
> @@ -39,9 +39,16 @@
>   * @defgroup avoptions AVOptions
>   * @ingroup lavu_data
>   * @{
> - * AVOptions provide a generic system to declare options on arbitrary structs
> - * ("objects"). An option can have a help text, a type and a range of possible
> - * values. Options may then be enumerated, read and written to.
> + *
> + * Inspection and configuration for AVClass context structures
> + *
> + * Provides a generic API to declare and manage options on any struct
> + * whose first member is a pointer-to-@ref AVClass.  Structs with private
> + * contexts can use that AVClass to return further @ref AVClass "AVClass"es
> + * that allow access to options in the private structs.
> + *
> + * Each option can have a help text, a type and a range of possible values.
> + * Options may be enumerated, read and written to.
>   *
>   * There are two modes of access to members of AVOption and its child structs.
>   * One is called 'native access', and refers to access from the code that
> @@ -53,11 +60,20 @@
>   * question is allowed to access the field. This allows us to extend the
>   * semantics of those fields without breaking API compatibility.
>   *

> + * Note that AVOptions is not reentrant, and that many FFmpeg functions access

... AVOptions access is not reeentrant ...

> + * options from separate threads.  Unless otherwise indicated, it is best to
> + * avoid modifying options once a struct has been initialized.

But this note is not relevant to the change, and should probably be
discussed separately

[...]
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v6 2/4] lavu: Clarify relationship between AVClass, AVOption and context
  2024-06-05 10:34     ` Stefano Sabatini
@ 2024-06-05 12:46       ` Andrew Sayers
  0 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-06-05 12:46 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Wed, Jun 05, 2024 at 12:34:48PM +0200, Stefano Sabatini wrote:
> On date Tuesday 2024-06-04 15:47:22 +0100, Andrew Sayers wrote:
<snip - language choices we can talk about in future>
> > + * Structs that only use logging facilities are often referred to as
> > + * "AVClass context structures", while those that provide configuration
> > + * options are called "AVOptions-enabled structs".
> 
> A struct with an AVClass as its first member can be used for both
> logging and options management, there is no difference between the
> two. My take:
> |Structs that use AVClass might be referred to as AVClass
> |contexts/structures, those that in addition define options might be
> |called AVOptions contexts/structures.

I think you were away when this came up, and anyway this thread is getting
quite unwieldy.  See [1] and [2] for the full version, but in short, defining
AVClass by layout leads to conclusions that are at best unintuitive.

<snip - AVOptions text>
> > + * Note that AVOptions is not reentrant, and that many FFmpeg functions access
> 
> ... AVOptions access is not reeentrant ...
> 
> > + * options from separate threads.  Unless otherwise indicated, it is best to
> > + * avoid modifying options once a struct has been initialized.
> 
> But this note is not relevant to the change, and should probably be
> discussed separately

Short version: I'll make a separate patch now, let's come back to this after

Long version...

If you assume options can be set at any time, they broadly resemble a reflection
mechanism.  If you assume they can only be set during the configuration stage,
they broadly resemble an OOP constructor.  The document needs to address the one
they resemble (even if just to say "this is why they're different"), and needs
to steer clear of any possible comparison with the one they don't resemble.
So it would be too risky to bump this to the upcoming omnibus patchset,
but it's fine to apply this *before* the context document.

[1] https://ffmpeg.org/pipermail/ffmpeg-devel/2024-May/328058.html
[2] https://ffmpeg.org/pipermail/ffmpeg-devel/2024-May/328087.html
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v6 3/4] all: Link to "context" from all public contexts with documentation
  2024-06-05  8:12     ` Anton Khirnov
@ 2024-06-05 12:51       ` Andrew Sayers
  0 siblings, 0 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-06-05 12:51 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Note: I somehow managed to send this message directly to Anton before - sorry
Anton for the message spam, please reply to this one if you want the list to
see it!

On Wed, Jun 05, 2024 at 10:12:47AM +0200, Anton Khirnov wrote:
> Quoting Andrew Sayers (2024-06-04 16:47:23)
> > The goal of putting these links in "@see" blocks is to provide hooks
> > for future developers to add links to other useful parts of the codebase.
> > ---
> >  libavcodec/avcodec.h             | 3 +++
> >  libavcodec/bsf.h                 | 3 +++
> >  libavcodec/d3d11va.h             | 3 +++
> >  libavcodec/mediacodec.h          | 2 ++
> >  libavcodec/qsv.h                 | 3 +++
> >  libavcodec/vdpau.h               | 3 +++
> >  libavcodec/videotoolbox.h        | 3 +++
> >  libavfilter/avfilter.h           | 7 ++++++-
> >  libavformat/avformat.h           | 3 +++
> >  libavformat/avio.h               | 3 +++
> >  libavutil/audio_fifo.h           | 3 +++
> >  libavutil/hwcontext.h            | 6 ++++++
> >  libavutil/hwcontext_cuda.h       | 3 +++
> >  libavutil/hwcontext_d3d11va.h    | 6 ++++++
> >  libavutil/hwcontext_d3d12va.h    | 6 ++++++
> >  libavutil/hwcontext_drm.h        | 3 +++
> >  libavutil/hwcontext_dxva2.h      | 6 ++++++
> >  libavutil/hwcontext_mediacodec.h | 3 +++
> >  libavutil/hwcontext_opencl.h     | 6 ++++++
> >  libavutil/hwcontext_qsv.h        | 6 ++++++
> >  libavutil/hwcontext_vaapi.h      | 6 ++++++
> >  libavutil/hwcontext_vdpau.h      | 3 +++
> >  libavutil/hwcontext_vulkan.h     | 6 ++++++
> >  libavutil/lfg.h                  | 3 +++
> >  24 files changed, 98 insertions(+), 1 deletion(-)
> 
> IMO this is pointless churn.

That's like saying caches are pointless bloat - it's not about correctness,
it's about performance.  Actually, I've been talking about "performance" a lot
round here, but not really explained what I mean...

Imagine a smart young developer who learned C at university and is now dipping
their toe in the world of actual C development.  They've come up with an idea
for a little app that's different enough from the examples to force themselves
not to just copy/paste example code.  It's simple enough that an experienced
developer like you would only need half a day for the whole project, so they
allow themselves a weekend to get it done.   "Performance" in this case means
"can they finish the project in their ~16 hour time budget?"

Assuming they're half as productive as you would be, 8 of their 16 hours go on
programming, leaving 8 hours to learn FFmpeg.

They've never written real-world C before, so they don't know what a context is.
And they only have a narrow understanding of OOP, so as soon as they see words
like "object" and "class", they assume you're referring to the precise version
of OOP their Java lecturer taught them about.  So the longer they spend poking
round looking for information, the more misconceptions they're going to develop.
Even if we assume they find the context document after one hour of searching,
they fully understand the document with no reading time, and only need one
extra hour to unlearn the misconceptions they developed, that's still cost
a quarter of their remaining time budget.

To an expert, these links are unnecessary verbiage pointing to a document
that explains things that are blindingly obvious.  But to a newbie, they're
an important optimisation that can make the difference between finishing
a project or having to give up on FFmpeg altogether.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v6 1/4] doc: Explain what "context" means
  2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 1/4] " Andrew Sayers
  2024-06-05  8:15     ` Anton Khirnov
@ 2024-06-12 20:52     ` Stefano Sabatini
  2024-06-13 14:20       ` Andrew Sayers
  1 sibling, 1 reply; 84+ messages in thread
From: Stefano Sabatini @ 2024-06-12 20:52 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andrew Sayers

On date Tuesday 2024-06-04 15:47:21 +0100, Andrew Sayers wrote:
> Derived from explanations kindly provided by Stefano Sabatini and others:
> https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
> ---
>  doc/context.md | 430 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 430 insertions(+)
>  create mode 100644 doc/context.md
> diff --git a/doc/context.md b/doc/context.md
> new file mode 100644
> index 0000000000..bd8cb58696
> --- /dev/null
> +++ b/doc/context.md
> @@ -0,0 +1,430 @@
> +@page Context Introduction to contexts
> +
> +@tableofcontents
> +
> +FFmpeg uses the term “context” to refer to an idiom
> +you have probably used before:
> +
> +```c
> +// C structs often share context between functions:
> +
> +FILE *my_file; // my_file stores information about a filehandle
> +
> +printf(my_file, "hello "); // my_file provides context to this function,
> +printf(my_file, "world!"); // and also to this function
> +```
> +
> +```python
> +# Python classes provide context for the methods they contain:
> +
> +class MyClass:
> +    def print(self,message):
> +        if self.prev_message != message:
> +            self.prev_message = message
> +            print(message)
> +```
> +
> +<!-- marked "c" because Doxygen doesn't support JS highlighting: -->
> +```c
> +// Many JavaScript callbacks accept an optional context argument:
> +
> +const my_object = {};
> +
> +my_array.forEach(function_1, my_object);
> +my_array.forEach(function_2, my_object);
> +```
> +
> +Be careful comparing FFmpeg contexts to things you're already familiar with -
> +FFmpeg may sometimes happen to reuse words you recognise, but mean something
> +completely different.  For example, the AVClass struct has nothing to do with
> +[object-oriented classes](https://en.wikipedia.org/wiki/Class_(computer_programming)).
> +
> +If you've used contexts in other C projects, you may want to read
> +@ref Context_comparison before the rest of the document.

My impression is that this is growing out of scope for a
reference. The doxy is a reference, therefore it should be clean and
terse, and we should avoid adding too much information, enough
information should be right enough. In fact, a reference is different
from a tutorial, and much different from a C tutorial. Also this is
not a treatise comparing different languages and frameworks, as this
would confuse beginners and would annoy experienced developers.

I propose to cut this patch to provide the minimal information you can
expect in a reference, but not more than that. Addition can be added
later, but I think we should try to avoid any unnecessary content, in
the spirit of keeping this a reference. More extensive discussions
might be done in a separate place (the wiki, a blog post etc.), but in
the spirit of a keeping this a reference they should not be put here.

> +
> +@section Context_general “Context” as a general concept
> +
> +@par
> +A context is any data structure used by several functions
> +(or several instances of the same function) that all operate on the same entity.
> +
> +In the broadest sense, “context” is just a way to think about code.

> +You can even use it to think about code written by people who have never
> +heard the term, or who would disagree with you about what it means.
> +Consider the following snippet:
> +
> +```c
> +struct DualWriter {
> +    int fd1, fd2;
> +};
> +
> +ssize_t write_to_two_files(
> +    struct DualWriter *my_writer,
> +    uint8_t *buf,
> +    int buf_size
> +) {
> +
> +    ssize_t bytes_written_1 = write(my_writer->fd1, buf, buf_size);
> +    ssize_t bytes_written_2 = write(my_writer->fd2, buf, buf_size);
> +
> +    if ( bytes_written_1 != bytes_written_2 ) {
> +        // ... handle this edge case ...
> +    }
> +
> +    return bytes_written_1;
> +
> +}
> +
> +int main() {
> +
> +    struct DualWriter my_writer;
> +    my_writer.fd1 = open("file1", 0644, "wb");
> +    my_writer.fd2 = open("file2", 0644, "wb");
> +
> +    write_to_two_files(&my_writer, "hello ", sizeof("hello "));
> +    write_to_two_files(&my_writer, "world!", sizeof("world!"));
> +
> +    close( my_writer.fd1 );
> +    close( my_writer.fd2 );
> +
> +}
> +```
> +
> +The term “context” doesn't appear anywhere in the snippet.  But `DualWriter`
> +is passed to several instances of `write_to_two_files()` that operate on
> +the same entity, so it fits the definition of a context.
> +
> +When reading code that isn't explicitly described in terms of contexts,
> +remember that your interpretation may differ from other people's.
> +For example, FFmpeg's avio_alloc_context() accepts a set of callback functions
> +and an `opaque` argument - even though this function guarantees to *return*
> +a context, it does not require `opaque` to *provide* context for the callback
> +functions.  So you could choose to pass a struct like `DualWriter` as the
> +`opaque` argument, or you could pass callbacks that use `stdin` and `stdout`
> +and just pass a `NULL` argument for `opaque`.

I'd skip all this part, as we assume the reader is already familiar
with C language and with data encapsulation through struct, if he is
not this is not the right place where to teach about C language
fundamentals.

> +
> +When reading code that *is* explicitly described in terms of contexts,
> +remember that the term's meaning is guaranteed by *the project's community*,
> +not *the language it's written in*.  That means guarantees may be more flexible
> +and change more over time.  For example, programming languages that use
> +[encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))
> +will simply refuse to compile code that violates its rules about access,
> +while communities can put up with special cases if they improve code quality.
> +

This looks a bit vague so I'd rather drop this.

> +The next section will discuss what specific conventions FFmpeg developers mean
> +when they describe parts of their code as using “contexts”.
> +
> +@section Context_ffmpeg FFmpeg contexts
> +
> +This section discusses specific context-related conventions used in FFmpeg.
> +Some of these are used in other projects, others are unique to this project.
> +
> +@subsection Context_indicating Indicating context: “Context”, “ctx” etc.
> +
> +```c
> +// Context struct names usually end with `Context`:
> +struct AVSomeContext {
> +  ...
> +};
> +
> +// Functions are usually named after their context,
> +// context parameters usually come first and are often called `ctx`:
> +void av_some_function(AVSomeContext *ctx, ...);
> +```
> +
> +FFmpeg struct names usually signal whether they are contexts (e.g. AVBSFContext
> +or AVCodecContext).  Exceptions to this rule include AVMD5, which is only
> +identified as a context by @ref libavutil/md5.c "the functions that call it".
> +
> +Function names usually signal the context they're associated with (e.g.
> +av_md5_alloc() or avcodec_alloc_context3()).  Exceptions to this rule include
> +@ref avformat.h "AVFormatContext's functions", many of which begin with
> +just `av_`.
> +
> +Functions usually signal their context parameter by putting it first and
> +naming it some variant of `ctx`.  Exceptions include av_bsf_alloc(), which puts
> +its context argument second to emphasise it's an out variable.
> +

> +Some functions fit awkwardly within FFmpeg's context idiom, so they send mixed
> +signals.  For example, av_ambient_viewing_environment_create_side_data() creates
> +an AVAmbientViewingEnvironment context, then adds it to the side-data of an
> +AVFrame context.  So its name hints at one context, its parameter hints at
> +another, and its documentation is silent on the issue.  You might prefer to
> +think of such functions as not having a context, or as “receiving” one context
> +and “producing” another.

I'd skip this paragraph. In fact, I think that API makes perfect
sense, OOP languages adopt such constructs all the time, for example
this could be a static module/class constructor. In other words, we
are not telling anywhere that all functions should take a "context" as
its first argument, and the documentation specify exactly how this
works, if you feel this is not clear or silent probably this is a sign
that that function documentation should be extended.

> +
> +@subsection Context_data_hiding Data hiding: private contexts
> +
> +```c
> +// Context structs often hide private context:
> +struct AVSomeContext {
> +  void *priv_data; // sometimes just called "internal"
> +};
> +```
> +
> +Contexts present a public interface, so changing a context's members forces
> +everyone that uses the library to at least recompile their program,
> +if not rewrite it to remain compatible.  Many contexts reduce this problem
> +by including a private context with a type that is not exposed in the public
> +interface.  Hiding information this way ensures it can be modified without
> +affecting downstream software.
> +
> +Private contexts often store variables users aren't supposed to see
> +(similar to an [OOP](https://en.wikipedia.org/wiki/Object-oriented_programming)
> +private block), but can be used for more than just access control.  They can
> +also store information shared between some but not all instances of a context
> +(e.g. codec-specific functionality), and @ref Context_avoptions
> +"AVOptions-enabled structs" can provide user configuration options through
> +the @ref avoptions "AVOptions API".

I'll skip this section as well: data hiding is a common C technique,
and AVOptions are already covered later in the document or in another
dedicated section.

> +@subsection Context_lifetime Manage lifetime: creation, use, destruction
> +
> +```c
> +void my_function(...) {
> +
> +    // Context structs are allocated then initialized with associated functions:
> +
> +    AVSomeContext *ctx = av_some_context_alloc(...);
> +
> +    // ... configure ctx ...
> +
> +    av_some_context_init(ctx, ...);
> +
> +    // ... use ctx ...
> +
> +    // Context structs are closed then freed with associated functions:
> +
> +    av_some_context_close(ctx);
> +    av_some_context_free(ctx);
> +
> +}
> +```
> +FFmpeg contexts go through the following stages of life:
> +
> +1. allocation (often a function that ends with `_alloc`)
> +   * a range of memory is allocated for use by the structure
> +   * memory is allocated on boundaries that improve caching
> +   * memory is reset to zeroes, some internal structures may be initialized
> +2. configuration (implemented by setting values directly on the context)
> +   * no function for this - calling code populates the structure directly
> +   * memory is populated with useful values
> +   * simple contexts can skip this stage
> +3. initialization (often a function that ends with `_init`)
> +   * setup actions are performed based on the configuration (e.g. opening files)
> +5. normal usage
> +   * most functions are called in this stage
> +   * documentation implies some members are now read-only (or not used at all)
> +   * some contexts allow re-initialization
> +6. closing (often a function that ends with `_close()`)
> +   * teardown actions are performed (e.g. closing files)
> +7. deallocation (often a function that ends with `_free()`)
> +   * memory is returned to the pool of available memory
> +
> +This can mislead object-oriented programmers, who expect something more like:
> +
> +1. allocation (usually a `new` keyword)
> +   * a range of memory is allocated for use by the structure
> +   * memory *may* be reset (e.g. for security reasons)
> +2. initialization (usually a constructor)
> +   * memory is populated with useful values
> +   * related setup actions are performed based on arguments (e.g. opening files)
> +3. normal usage
> +   * most functions are called in this stage
> +   * compiler enforces that some members are read-only (or private)
> +   * no going back to the previous stage
> +4. finalization (usually a destructor)
> +   * teardown actions are performed (e.g. closing files)
> +5. deallocation (usually a `delete` keyword)
> +   * memory is returned to the pool of available memory
> +
> +The remainder of this section discusses FFmpeg's differences from OOP, to help
> +object-oriented programmers avoid misconceptions.  You can safely skip this
> +section if you aren't familiar with the OOP lifetime described above.
> +
> +FFmpeg's allocation stage is broadly similar to the OOP stage of the same name.
> +Both set aside some memory for use by a new entity, but FFmpeg's stage can also
> +do some higher-level operations.  For example, @ref Context_avoptions
> +"AVOptions-enabled structs" set their AVClass member during allocation.
> +
> +FFmpeg's configuration stage involves setting any variables you want before
> +you start using the context.  Complicated FFmpeg structures like AVCodecContext
> +tend to have many members you *could* set, but in practice most programs set
> +few if any of them.  The freeform configuration stage works better than bundling
> +these into the initialization stage, which would lead to functions with
> +impractically many parameters, and would mean each new option was an
> +incompatible change to the API.  One way to understand the problem is to read
> +@ref Context_avoptions "the AVOptions section below" and think how a constructor
> +would handle those options.
> +
> +FFmpeg's initialization stage involves calling a function that sets the context
> +up based on your configuration.
> +
> +FFmpeg's first three stages do the same job as OOP's first two stages.
> +This can mislead object-oriented developers, who expect to do less work in the
> +allocation stage, and more work in the initialization stage.  To simplify this,
> +most FFmpeg contexts provide a combined allocator and initializer function.
> +For historical reasons, suffixes like `_alloc`, `_init`, `_alloc_context` and
> +even `_open` can indicate the function does any combination of allocation and
> +initialization.
> +
> +FFmpeg's "closing" stage is broadly similar to OOP's "finalization" stage,
> +but some contexts allow re-initialization after finalization.  For example,
> +SwrContext lets you call swr_close() then swr_init() to reuse a context.
> +Be aware that some FFmpeg functions happen to use the word "finalize" in a way
> +that has nothing to do with the OOP stage (e.g. av_bsf_list_finalize()).
> +
> +FFmpeg's "deallocation" stage is broadly similar to OOP, but can perform some
> +higher-level functions (similar to the allocation stage).
> +
> +Closing functions usually end with "_close", while deallocation
> +functions usually end with "_free".  Very few contexts need the flexibility of
> +separate "closing" and "deallocation" stages, so many "_free" functions
> +implicitly close the context first.

About this I have mixed feelings, but to me it sounds like a-posteriori
rationalization.

I don't think there is a general rule with the allocation/closing/free
rule for the various FFmpeg APIs, and giving the impression that this
is the case might be misleading. In practice the user needs to master
only a single API at a time (encodering/decoding, muxing/demuxing,
etc.)  each one with possibly slight differences in how the term
close/allocation/free are used. This is probably not optimal, but in
practice it works as the user do not really need to know all the
possible uses of the API (she will work through what she is interested
for the job at hand).

> +
> +@subsection Context_avoptions Configuration options: AVOptions-enabled structs
> +

> +The @ref avoptions "AVOptions API" is a framework to configure user-facing
> +options, e.g. on the command-line or in GUI configuration forms.

This looks wrong. AVOptions is not at all about CLI or GUI options, is
just some way to set/get fields (that is "options") defined in a
struct (a context) using a high level API including: setting multiple
options at once (through a textual encoding or a dictionary),
input/range validation, setting more fields based on a single option
(e.g. the size) etc.

Then you can query the options in a given struct and create
corresponding options in a UI, but this is not the point of AVOptions.

> +To understand FFmpeg's configuration requirements, run `ffmpeg -h full` on the
> +command-line, then ask yourself how you would implement all those options
> +with the C standard [`getopt` function](https://en.wikipedia.org/wiki/Getopt).
> +You can also ask the same question for other approaches - for example, how would
> +you maintain a GUI with 15,000+ configuration options?
> +
> +Most solutions assume you can just put all options in a single code block,
> +which is unworkable at FFmpeg's scale.  Instead, we split configuration
> +across many *AVOptions-enabled structs*, which use the @ref avoptions
> +"AVOptions API" to inspect and configure options, including in private contexts.
> +
> +AVOptions-accessible members of a context should be accessed through the
> +@ref avoptions "AVOptions API" whenever possible, even if they're not hidden
> +in a private context.  That ensures values are validated as they're set, and
> +means you won't have to do as much work if a future version of FFmpeg changes
> +the allowed values.
> +

> +Although not strictly required, it is best to only modify options during
> +the configuration stage.  Initialized structs may be accessed by internal
> +FFmpeg threads, and modifying them can cause weird intermittent bugs.
> +
> +@subsection Context_logging Logging: AVClass context structures
> +
> +FFmpeg's @ref lavu_log "logging facility" needs to be simple to use,
> +but flexible enough to let people debug problems.  And much like options,
> +it needs to work the same across a wide variety of unrelated structs.
> +
> +FFmpeg structs that support the logging framework are called *@ref AVClass
> +context structures*.  The name @ref AVClass was chosen early in FFmpeg's
> +development, but in practice it only came to store information about
> +logging, and about options.

OTOH hand AVOptions and logging should be discussed in the relevant
files, to avoid duplication.

> +
> +@section Context_further Further information about contexts
> +
> +So far, this document has provided a theoretical guide to FFmpeg contexts.
> +This final section provides some alternative approaches to the topic,
> +which may help round out your understanding.
> +
> +@subsection Context_example Learning by example: context for a codec
> +
> +It can help to learn contexts by doing a deep dive into a specific struct.
> +This section will discuss AVCodecContext - an AVOptions-enabled struct
> +that contains information about encoding or decoding one stream of data
> +(e.g. the video in a movie).
> +
> +The name "AVCodecContext" tells us this is a context.  Many of
> +@ref libavcodec/avcodec.h "its functions" start with an `avctx` parameter,
> +indicating this parameter provides context for that function.
> +
> +AVCodecContext::internal contains the private context.  For example,
> +codec-specific information might be stored here.
> +
> +AVCodecContext is allocated with avcodec_alloc_context3(), initialized with
> +avcodec_open2(), and freed with avcodec_free_context().  Most of its members
> +are configured with the @ref avoptions "AVOptions API", but for example you
> +can set AVCodecContext::draw_horiz_band() if your program happens to need it.
> +
> +AVCodecContext provides an abstract interface to many different *codecs*.
> +Options supported by many codecs (e.g. "bitrate") are kept in AVCodecContext
> +and exposed with AVOptions.  Options that are specific to one codec are
> +stored in the private context, and also exposed with AVOptions.
> +
> +AVCodecContext::av_class contains logging metadata to ensure all codec-related
> +error messages look the same, plus implementation details about options.
> +
> +To support a specific codec, AVCodecContext's private context is set to
> +an encoder-specific data type.  For example, the video codec
> +[H.264](https://en.wikipedia.org/wiki/Advanced_Video_Coding) is supported via
> +[the x264 library](https://www.videolan.org/developers/x264.html), and
> +implemented in X264Context.  Although included in the documentation, X264Context
> +is not part of the public API.  That means FFmpeg's @ref ffmpeg_versioning
> +"strict rules about changing public structs" aren't as important here, so a
> +version of FFmpeg could modify X264Context or replace it with another type
> +altogether.  An adverse legal ruling or security problem could even force us to
> +switch to a completely different library without a major version bump.
> +
> +The design of AVCodecContext provides several important guarantees:
> +
> +- lets you use the same interface for any codec
> +- supports common encoder options like "bitrate" without duplicating code
> +- supports encoder-specific options like "profile" without bulking out the public interface
> +- exposes both types of options to users, with help text and detection of missing options
> +- provides uniform logging output
> +- hides implementation details (e.g. its encoding buffer)
> +

> +@subsection Context_comparison Learning by comparison: FFmpeg vs. Curl contexts

About this, I'm still not really convinced that this should be part of
a reference, in the sense that it is adding more information than
really needed and it treats concepts related to the C language rather
than to the FFmpeg API itself.

[...]
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v6 1/4] doc: Explain what "context" means
  2024-06-12 20:52     ` Stefano Sabatini
@ 2024-06-13 14:20       ` Andrew Sayers
  2024-06-15  9:17         ` Stefano Sabatini
  0 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-06-13 14:20 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Wed, Jun 12, 2024 at 10:52:00PM +0200, Stefano Sabatini wrote:
> On date Tuesday 2024-06-04 15:47:21 +0100, Andrew Sayers wrote:
[...]
> My impression is that this is growing out of scope for a
> reference. The doxy is a reference, therefore it should be clean and
> terse, and we should avoid adding too much information, enough
> information should be right enough. In fact, a reference is different
> from a tutorial, and much different from a C tutorial. Also this is
> not a treatise comparing different languages and frameworks, as this
> would confuse beginners and would annoy experienced developers.
> 
> I propose to cut this patch to provide the minimal information you can
> expect in a reference, but not more than that. Addition can be added
> later, but I think we should try to avoid any unnecessary content, in
> the spirit of keeping this a reference. More extensive discussions
> might be done in a separate place (the wiki, a blog post etc.), but in
> the spirit of a keeping this a reference they should not be put here.

I would agree if we had a tradition of linking to the wiki or regular blog
posts, but even proposing internal links has generated pushback in this thread,
so that feels like making the perfect the enemy of the good.  Let's get this
committed, see how people react, then look for improvements.

In fact, once this is available in the trunk version of the website,
we should ask for feedback from the libav-user ML and #ffmpeg IRC channel.
Then we can expand/move/remove stuff based on feedback.

> 
> > +
> > +@section Context_general “Context” as a general concept
[...]
> I'd skip all this part, as we assume the reader is already familiar
> with C language and with data encapsulation through struct, if he is
> not this is not the right place where to teach about C language
> fundamentals.

I disagree, for a reason I've been looking for an excuse to mention :)

Let's assume 90% of people who use FFmpeg already know something in the doc.
You could say that part of the doc is useless to 90% of the audience.
Or you could say that 90% of FFmpeg users are not our audience.

Looking at it the second way means you need to spend more time on "routing" -
linking to the document in ways that (only) attract your target audience,
making a table of contents with headings that aid skip-readers, etc.
But once you've routed people around the bits they don't care about,
it's fine to have documentation that's only needed by a minority.

Also, less interesting but equally important - context is not a C language
fundamental, it's more like an emergent property of large C projects.  A
developer that came here without knowing e.g. what a struct is could read
any of the online tutorials that explain the concept better than we could.
I'd be happy to link to a good tutorial about contexts if we found one,
but we have to meet people where they are, and this is the best solution
I've been able to find.

> 
> > +
> > +When reading code that *is* explicitly described in terms of contexts,
> > +remember that the term's meaning is guaranteed by *the project's community*,
> > +not *the language it's written in*.  That means guarantees may be more flexible
> > +and change more over time.  For example, programming languages that use
> > +[encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))
> > +will simply refuse to compile code that violates its rules about access,
> > +while communities can put up with special cases if they improve code quality.
> > +
> 
> This looks a bit vague so I'd rather drop this.

This probably looks vague to you because you're part of the 90% of people this
paragraph isn't for.  All programming languages provide some guarantees, and
leave others up to the community to enforce (or not).  Over time, people stop
seeing the language guarantees at all, and assume the only alternative is
anarchy.  For example, if you got involved in a large JavaScript project,
you might be horrified to see almost all structs are the same type ("Object"),
and are implemented as dictionaries that are expected to have certain keys.
But in practice, this stuff gets enforced at the community level well enough.
Similarly, a JS programmer might be horrified to learn FFmpeg needs a whole
major version bump just to add a key to a struct.  This paragraph is there to
nudge people who have stopped seeing things we need them to look out for.

If you'd like to maintain an official FFmpeg blog, I'd be happy to expand the
paragraph above into a medium-sized post, then just link it from the doc.
But that post would be too subjective to be a wiki page - JavaScript is
evolving in a more strongly-typed direction, so it would only make sense to
future readers if they could say "oh yeah this was written in 2024, JS was
still like that back then".  This paragraph is an achievable compromise -
covers enough ground to give people a way to think about the code, short enough
for people who don't care to skip over, and objective enough to belong in
documentation.  We can always change it if we find a better solution.

[...]
> > +Some functions fit awkwardly within FFmpeg's context idiom, so they send mixed
> > +signals.  For example, av_ambient_viewing_environment_create_side_data() creates
> > +an AVAmbientViewingEnvironment context, then adds it to the side-data of an
> > +AVFrame context.  So its name hints at one context, its parameter hints at
> > +another, and its documentation is silent on the issue.  You might prefer to
> > +think of such functions as not having a context, or as “receiving” one context
> > +and “producing” another.
> 
> I'd skip this paragraph. In fact, I think that API makes perfect
> sense, OOP languages adopt such constructs all the time, for example
> this could be a static module/class constructor. In other words, we
> are not telling anywhere that all functions should take a "context" as
> its first argument, and the documentation specify exactly how this
> works, if you feel this is not clear or silent probably this is a sign
> that that function documentation should be extended.

That would be fine if it were just this function, but FFmpeg is littered
with special cases that don't quite fit.  Another example might be
swr_alloc_set_opts2(), which can take an SwrContext in a way that resembles
a context, or can take NULL and allocate a new SwrContext.  And yes,
we could document that edge case, and the next one, and the one after that.
But even if we documented every little special case that existed today,
there's no rule, so new bits of API will just reintroduce the problem again.

There's a deeper issue here - as an expert, when you don't know something,
your default assumption is that it's undefined, and could evolve in future.
When a newbie doesn't know something, their default assumption is that
everybody else knows and they're just stupid.  That assumption drives
newbies away from projects, so it's important to fill in as many blanks as
possible, even if it has to be with simple answers that they eventually
evolve beyond (and feel smart for doing so).

> > +@subsection Context_lifetime Manage lifetime: creation, use, destruction
[...]
> About this I have mixed feelings, but to me it sounds like a-posteriori
> rationalization.
> 
> I don't think there is a general rule with the allocation/closing/free
> rule for the various FFmpeg APIs, and giving the impression that this
> is the case might be misleading. In practice the user needs to master
> only a single API at a time (encodering/decoding, muxing/demuxing,
> etc.)  each one with possibly slight differences in how the term
> close/allocation/free are used. This is probably not optimal, but in
> practice it works as the user do not really need to know all the
> possible uses of the API (she will work through what she is interested
> for the job at hand).

Note: I'm assuming "this" means "this section", not "this paragraph".
Apologies if it was intended as a specific nitpick about closing functions.

TBH, a lot of this document is about inventing memorable rules of thumb.
The alternative is to say "FFmpeg devs can't agree on an answer, so they just
left you to memorise 3,000+ special cases".

Let's assume learning the whole of FFmpeg means understanding 3,000 tokens
(I'm not sure the exact count in 7.0, but it's about that number if you don't
include individual members of structs, arguments to functions etc.).  Let's
also assume it takes an average of ten minutes to learn each token (obviously
that varies - AV_LOG_PANIC will take less, AVCodecContext will take more).
That means you'd have to spend 8 hours a day every day for over two months
to learn FFmpeg.  Obviously there are usable subsets, but they mostly cut out
the simple things, so don't save nearly as much time as you'd think.  If you
want people to pick up FFmpeg, they need to learn a useful subset in about 8
hours, which requires a drastically simplified explanation.

(the above is closely related to an argument from a recent post[1],
but the numbers might help explain the scale of the challenge)

There may not be an explicit rule for context lifetimes, but I've looked at the
code carefully enough to have a nuanced opinion about the number of tokens,
and the edgiest case I've found so far is swr_alloc_set_opts2() (see above).
I'm open to counterexamples, but the model discussed in this section feels
pretty reliable.

> 
> > +
> > +@subsection Context_avoptions Configuration options: AVOptions-enabled structs
> > +
> 
> > +The @ref avoptions "AVOptions API" is a framework to configure user-facing
> > +options, e.g. on the command-line or in GUI configuration forms.
> 
> This looks wrong. AVOptions is not at all about CLI or GUI options, is
> just some way to set/get fields (that is "options") defined in a
> struct (a context) using a high level API including: setting multiple
> options at once (through a textual encoding or a dictionary),
> input/range validation, setting more fields based on a single option
> (e.g. the size) etc.
> 
> Then you can query the options in a given struct and create
> corresponding options in a UI, but this is not the point of AVOptions.

There's a problem here I haven't been communicating clearly enough.
I think that's because I've understated the problem in the past,
so I'll try overstating instead:

"Option" is a meaningless noise word.  A new developer might ask "is this like a
command-line option, or a CMake option?  Is it like those Python functions with
a million keyword arguments, or a config file with sensible defaults?".
Answering "it can be any of those if you need it to be" might help an advanced
user (not our audience), but is bewildering to a newbie who needs a rough guide
for how they're likely to use it.  The only solution that's useful to a newbie
is to provide a frame of reference, preferably in the form of something they
already know how to use.

Having said all that, yes this particular answer is wrong.  Could you apply [2]
so I can start thinking about what to replace it with?

[...]

[1] https://ffmpeg.org/pipermail/ffmpeg-devel/2024-June/328970.html
[2] https://ffmpeg.org/pipermail/ffmpeg-devel/2024-June/329068.html
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] [PATCH v6 1/4] doc: Explain what "context" means
  2024-06-13 14:20       ` Andrew Sayers
@ 2024-06-15  9:17         ` Stefano Sabatini
  2024-06-16 18:02           ` [FFmpeg-devel] Development process for explaining contexts (was Re: [PATCH v6 1/4] doc: Explain what "context" means) Andrew Sayers
  0 siblings, 1 reply; 84+ messages in thread
From: Stefano Sabatini @ 2024-06-15  9:17 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On date Thursday 2024-06-13 15:20:38 +0100, Andrew Sayers wrote:
> On Wed, Jun 12, 2024 at 10:52:00PM +0200, Stefano Sabatini wrote:
[...]
> > > +@section Context_general “Context” as a general concept
> [...]
> > I'd skip all this part, as we assume the reader is already familiar
> > with C language and with data encapsulation through struct, if he is
> > not this is not the right place where to teach about C language
> > fundamentals.
> 
> I disagree, for a reason I've been looking for an excuse to mention :)
> 

> Let's assume 90% of people who use FFmpeg already know something in the doc.
> You could say that part of the doc is useless to 90% of the audience.
> Or you could say that 90% of FFmpeg users are not our audience.
> 
> Looking at it the second way means you need to spend more time on "routing" -
> linking to the document in ways that (only) attract your target audience,
> making a table of contents with headings that aid skip-readers, etc.
> But once you've routed people around the bits they don't care about,
> it's fine to have documentation that's only needed by a minority.
> 

> Also, less interesting but equally important - context is not a C language
> fundamental, it's more like an emergent property of large C projects.  A
> developer that came here without knowing e.g. what a struct is could read
> any of the online tutorials that explain the concept better than we could.
> I'd be happy to link to a good tutorial about contexts if we found one,
> but we have to meet people where they are, and this is the best solution
> I've been able to find.

The context is just another way to call a struct used to keep an
entity state operated by several functions (that is in other words an
object and its methods), it's mostly about the specific jargon used by
FFmpeg (and used by other C projects as well). In addition to this we
provide some generic utilities (logging+avoptions) which can be used
through AVClass employment.

Giving a longer explanation is making this appear something more
complicated than actually is. My point is that providing more
information than actually needed provides the long-wall-of-text effect
(I need to read through all this to understand it - nah I'd rather
give-up), thus discouraging readers.

> 
> > 
> > > +
> > > +When reading code that *is* explicitly described in terms of contexts,
> > > +remember that the term's meaning is guaranteed by *the project's community*,
> > > +not *the language it's written in*.  That means guarantees may be more flexible
> > > +and change more over time.  For example, programming languages that use
> > > +[encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))
> > > +will simply refuse to compile code that violates its rules about access,
> > > +while communities can put up with special cases if they improve code quality.
> > > +
> > 
> > This looks a bit vague so I'd rather drop this.

I mean, if you read for the first time:
| [the context] term's meaning is guaranteed by *the project's
| community*, not the languaguage it's written for.
| That means guarantees may be more flexible and change more over time.

it's very hard to figure out what these guarantees are about, and this
might apply to every specific language and to every specific term,
that's why I consider this "vague".
 
[...]
> > > +Some functions fit awkwardly within FFmpeg's context idiom, so they send mixed
> > > +signals.  For example, av_ambient_viewing_environment_create_side_data() creates
> > > +an AVAmbientViewingEnvironment context, then adds it to the side-data of an
> > > +AVFrame context.  So its name hints at one context, its parameter hints at
> > > +another, and its documentation is silent on the issue.  You might prefer to
> > > +think of such functions as not having a context, or as “receiving” one context
> > > +and “producing” another.
> > 
> > I'd skip this paragraph. In fact, I think that API makes perfect
> > sense, OOP languages adopt such constructs all the time, for example
> > this could be a static module/class constructor. In other words, we
> > are not telling anywhere that all functions should take a "context" as
> > its first argument, and the documentation specify exactly how this
> > works, if you feel this is not clear or silent probably this is a sign
> > that that function documentation should be extended.
> 

> That would be fine if it were just this function, but FFmpeg is littered
> with special cases that don't quite fit.

I still fail to see the general rule for which this is creating a
special case. If this is a special case, what is this special case
for?

> Another example might be swr_alloc_set_opts2(), which can take an
> SwrContext in a way that resembles a context, or can take NULL and
> allocate a new SwrContext.  And yes, we could document that edge
> case, and the next one, and the one after that. But even if we
> documented every little special case that existed today, there's no
> rule, so new bits of API will just reintroduce the problem again.

In this specific case I'd say the API is not much ergonomic, and
probably it would have been better to keep operations (allow+set_opts)
separated, but then it is much a choice of the user (you can decide to
keep alloc and set_opts as different operations). On the other hand,
*it is already documented* so there is not much to add.

> There's a deeper issue here - as an expert, when you don't know something,
> your default assumption is that it's undefined, and could evolve in future.
> When a newbie doesn't know something, their default assumption is that
> everybody else knows and they're just stupid.  That assumption drives
> newbies away from projects, so it's important to fill in as many blanks as
> possible, even if it has to be with simple answers that they eventually
> evolve beyond (and feel smart for doing so).
> 
> > > +@subsection Context_lifetime Manage lifetime: creation, use, destruction
> [...]
> > About this I have mixed feelings, but to me it sounds like a-posteriori
> > rationalization.
> > 
> > I don't think there is a general rule with the allocation/closing/free
> > rule for the various FFmpeg APIs, and giving the impression that this
> > is the case might be misleading. In practice the user needs to master
> > only a single API at a time (encodering/decoding, muxing/demuxing,
> > etc.)  each one with possibly slight differences in how the term
> > close/allocation/free are used. This is probably not optimal, but in
> > practice it works as the user do not really need to know all the
> > possible uses of the API (she will work through what she is interested
> > for the job at hand).
> 
> Note: I'm assuming "this" means "this section", not "this paragraph".
> Apologies if it was intended as a specific nitpick about closing functions.
> 
> TBH, a lot of this document is about inventing memorable rules of thumb.

> The alternative is to say "FFmpeg devs can't agree on an answer, so they just
> left you to memorise 3,000+ special cases".

This is not what most people do. You don't have to read all the
manual, especially you don't have to memorize the complete API, but
only the relevant part for the task at hand. If you need to learn
about decoding, you would probably start with the decoding API
(libavcodec/avcodec.h - which is unfortunatly pretty much complex
because the problem is complex), and you can ignore pretty much
everything else. If you only need to work with hash methods, you only
need to learn about that API.

So in general, you only learn the smaller bits needed for the task at
hand. For example I never used the av_ambient_viewing_environment API,
and I will probably never will.

More realistically, people learn from examples, so that's why we
should improve doc/examples. doxy is mostly for providing a complete
reference in case you want to fine tune an already working piece of
code or you have problems understanding specific bits (how are
timestamps handled? When should I ref/unref a frame? How can I get the
name of a channel layout?).

Usually it is a mixed process (you read the API doc, or you read the
examples to get the general idea, and you interpolate between the
two).

> Let's assume learning the whole of FFmpeg means understanding 3,000 tokens
> (I'm not sure the exact count in 7.0, but it's about that number if you don't
> include individual members of structs, arguments to functions etc.).  Let's
> also assume it takes an average of ten minutes to learn each token (obviously
> that varies - AV_LOG_PANIC will take less, AVCodecContext will take more).
> That means you'd have to spend 8 hours a day every day for over two months
> to learn FFmpeg.

> Obviously there are usable subsets, but they mostly cut out the
> simple things, so don't save nearly as much time as you'd think.  If
> you want people to pick up FFmpeg, they need to learn a useful
> subset in about 8 hours, which requires a drastically simplified
> explanation.

I agree, I'm fine with giving a high level description of what we mean
by "context" - but probably one paragraph or two should be enough, but
adding too much information might get the exact opposite effect
(exposing more information than needed - assuming the reader is
familiar with the C language, which we should assume).

> (the above is closely related to an argument from a recent post[1],
> but the numbers might help explain the scale of the challenge)
> 
> There may not be an explicit rule for context lifetimes, but I've looked at the
> code carefully enough to have a nuanced opinion about the number of tokens,
> and the edgiest case I've found so far is swr_alloc_set_opts2() (see above).
> I'm open to counterexamples, but the model discussed in this section feels
> pretty reliable.

swr_alloc_set_opts() is an unfortunate case, probably it would be
better to fix the API to have a dedicated set_opts in place of
aggregating two operations - one of the issues being that the function
cannot distinguish the case of allocation failure (ENOMEM) from
invalid parameters (EINVAL).

That said, I would not mind keeping the general discussion, but
probably I'd cut the part about "finalize" to avoid the reference to
the C++ language, in general I'd avoid comparisons with C++ all around
the place.

> > > +
> > > +@subsection Context_avoptions Configuration options: AVOptions-enabled structs
> > > +
> > 
> > > +The @ref avoptions "AVOptions API" is a framework to configure user-facing
> > > +options, e.g. on the command-line or in GUI configuration forms.
> > 
> > This looks wrong. AVOptions is not at all about CLI or GUI options, is
> > just some way to set/get fields (that is "options") defined in a
> > struct (a context) using a high level API including: setting multiple
> > options at once (through a textual encoding or a dictionary),
> > input/range validation, setting more fields based on a single option
> > (e.g. the size) etc.
> > 
> > Then you can query the options in a given struct and create
> > corresponding options in a UI, but this is not the point of AVOptions.
> 
> There's a problem here I haven't been communicating clearly enough.
> I think that's because I've understated the problem in the past,
> so I'll try overstating instead:
> 
> "Option" is a meaningless noise word.  A new developer might ask "is this like a
> command-line option, or a CMake option?  Is it like those Python functions with
> a million keyword arguments, or a config file with sensible defaults?".
> Answering "it can be any of those if you need it to be" might help an advanced
> user (not our audience), but is bewildering to a newbie who needs a rough guide
> for how they're likely to use it.  The only solution that's useful to a newbie
> is to provide a frame of reference, preferably in the form of something they
> already know how to use.

This is the definition I gave:

[AVOptions system is] just some way to set/get fields (that is
"options") defined in a struct (a context) using a high level API
including: setting multiple options at once (through a textual
encoding or a dictionary), input/range validation, setting more fields
based on a single option (e.g. the size) etc.

"Setting options" on a struct/context with AVOptions means to set
_fields_ on the struct, following the very specific rules defined by
AVOptions.

So it's not like "it can be any of those if you need it to be", but it
has a very specific meaning.

> Having said all that, yes this particular answer is wrong.  Could
> you apply [2] so I can start thinking about what to replace it with?

I'll have a look at it.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [FFmpeg-devel] Development process for explaining contexts (was Re: [PATCH v6 1/4] doc: Explain what "context" means)
  2024-06-15  9:17         ` Stefano Sabatini
@ 2024-06-16 18:02           ` Andrew Sayers
  2024-06-16 21:20             ` Paul B Mahol
  2024-07-01 22:16             ` Stefano Sabatini
  0 siblings, 2 replies; 84+ messages in thread
From: Andrew Sayers @ 2024-06-16 18:02 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Meta note #1: I've replied in this thread but changed the subject line.
That's because it needs to stay focussed on solving this thread's problem,
but may be of more general interest.

Meta note #2: Stefano, I appreciate your feedback, but would rather wait
for [1] to get sorted out, then formulate my thoughts while writing a new
version.  That way I'll be more focussed on ways to improve things for readers.

This thread started with what I thought was a trivia question[1] -
what is a context?  It's short for "AVClass context structure", which is
synonymous with "AVOptions-enabled struct".  It turned out to be more complex
than that, so I wrote a little patch[3] explaining this piece of jargon.
But it turned out to be more complex again, and so on until we got a 430-line
document explaining things in voluminous detail.

Everyone agrees this isn't ideal, so here are some alternatives.
This may also inspire thoughts about FFmpeg development in general.

# Alternative: Just give up

The argument: We tried something, learnt a lot, but couldn't find a solution
we agreed on, so let's come back another day.

Obviously this is the easy way out, but essentially means leaving a critical
bug in the documentation (misleads the reader about a fundamental concept).
Even the most negative take on this document is that it's better than nothing,
so I think we can rule this one out.

# Err on the side of under-communicating

The argument: this document is on the right tracks, but explains too many things
the reader can already be assumed to know.

This argument is more complex than it appears.  To take some silly examples,
I'm not going to learn Mandarin just because FFmpeg users can't be assumed to
speak English.  But I am willing to use American spelling because it's what
more readers are used to.  This e-mail is plenty long enough already, so
I'll stick to some high-level points about this argument.

The main risk of cutting documentation is that if someone can't follow a single
step, they're lost and don't even know how to express their problem.  Imagine
teaching maths to children - you need to teach them what numbers are, then how
to add them together, then multiplication, then finally exponents.  But if you
say "we don't need to teach numbers because kids all watch Numberblocks now",
you'll cover the majority of kids who could have worked it out anyway, and
leave a minority who just give up and say "I guess I must be bad at maths".
I'd argue it's better to write more, then get feedback from actual newbies and
cut based on the evidence - we'll get it wrong either way, but at least this way
the newbies will know what they want us to cut.

Incidentally, there's a much stronger argument for *drafting* a long document,
even if it gets cut down before it's committed.  FFmpeg has lots of undocumented
nuances that experts just know and newbies don't know to ask, and this thread is
full of instances where writing more detail helped tease out a misunderstanding.
[1] is a great example - I had finally written enough detail to uncover my
assumption that all AVOptions could be set at any time, then that thread
taught me to look for a flag that tells you the options for which that's true.

If you assume I'm not the only person who has been subtly misled that way,
you could argue it's better to commit the long version.  That would give readers
more opportunities to confront their own wrong assumptions, instead of reading
something that assumed they knew one thing, but let them keep believing another.
The obvious counterargument is that we should...

# Spread the information across multiple documents

The argument: this document puts too much information in one place.  We should
instead focus on making small patches that put information people need to know
where they need to know it.

This is where things get more interesting to a general audience.

If you have repo commit access, you're probably imagining a workflow like:
write a bunch of little commits, send them out for review, then commit them
when people stop replying.  Your access is evidence that you basically know how
things work, and also lets you make plans confident in the knowledge that
anything you need committed will make it there in the end.

My workflow is nothing like that.  This thread has constantly reinforced that I
don't understand FFmpeg, so it's better for me not to have commit access.  But
that means I can only work on one patch at once, because I will probably learn
something that invalidates any other work I would have done.  It also means
a single patch not getting interest is enough to sink the project altogether.
I can put up with that when it's one big multi-faceted patch, because I can work
on one part while waiting for feedback on another part.  But my small patches
generally involve a few hours of work, a week of waiting, a ping begging for
attention, then often being rejected or ignored.  In the real world, the only
thing this approach will achieve is to burn me out.

It might be possible to revisit this idea *after* committing the document,
when we're fairly confident the answers are right and just need to tweak
the presentation based on feedback.  Or other people could write documentation
based on issues brought up in this thread, and I'll cut as appropriate.
But for now this is a non-starter.

# Write a blog post

The argument: doxygen and texinfo are good for documenting "timeless truths".
But we don't have anywhere to put transitory information like upgrade guides,
or subjective information like guidance about best practices.  This document
shoehorns information in here that really belongs somewhere like that.

This is basically true, but that doesn't solve anything.

I have neither a personal blog nor the desire to write one, and even if I wrote
an excellent guide to contexts as a general concept, nobody would actually find
the blog to read it.  So this idea would only work if we e.g. overhauled the
news area of the site[4] to look more like GIMP's news section[5].

If someone else would like to start a project like that, I can promise a good
series of posts to help get the ball rolling, and will be happy to trim down
the document as those posts go public.

# Write tutorials

The argument: this explains ideas from first principles that are better
explained by example.  This document shoehorns information in here that
really belongs somewhere like that.

This seems reasonable in principle, but as well as the "lots of small commits"
problem discussed above, FFmpeg is currently structured so nobody is actually
going to do that.

I've tried to learn FFmpeg many times over the years, and last year's attempt
involved trying to write a subtitles tutorial.  I didn't submit it to the ML
because I didn't understand the theory well enough, and was fairly sure I had
made some underlying error that made it all wrong.  Everyone who does understand
FFmpeg well enough to write a good subtitles tutorial seems to understand it
well enough to want a complete rewrite, but not care enough to get that done.
So subtitles end up falling between two stools - too ugly for newbies to learn,
not ugly enough for experts to fix.

If you want relatively new developers to have the confidence to write tutorials,
they need the theory to be well-documented first.

# Rewrite the API

The argument: instead of writing a bunch of words apologising for an interface,
just write a better interface.

In general, I'm a big believer in using documentation to drive API decisions.
But in FFmpeg's case, it wouldn't help to have a single developer trying to fix
a community-wide problem.

We've previously discussed swr_alloc_set_opts() (essentially two functions
sharing one symbol) and av_ambient_viewing_environment_create_side_data()
(receives a different context argument than its function name).
A better example of the community-wide issue might be av_new_packet()
(initializes but does not allocate, despite slightly confusing documentation)
vs. av_new_program() (allocates and initializes, but has no documentation).
Both of these could be documented better, and a developer who only needs to
learn one won't be bothered by the other.  But the real problem is that they
use the word "new" to mean fundamentally incompatible things, creating a trap
for anyone reviewing code that uses the "new" they haven't seen before.

Solving this problem wouldn't just involve rewriting a bunch of functions.
It would involve motivating the community to avoid writing that sort of API
in future, which would take all of us many years to achieve.

# Apply this, then iterate

The argument: OK fine, but dragging down other solutions doesn't help this one.
We should at least try to solve these problems.

This is the position I've currently landed up at.  I'm increasingly able to
justify the big picture decisions behind the document, and we're getting to
the point where detailed discussions are just putting opinions where evidence
should go.

I've talked in a previous e-mail about getting feedback from #ffmpeg and the
libav-user mailing list.  We've also talked about the value of making the
document useful to people familiar with other programming languages, so we
could try reaching out to people who write bindings in other languages.

This sort of iteration can be pretty quick, because we don't need to wait for
a major release.  We just need to have something on ffmpeg.org so people know
this is a "real" project.  As such, I think a "release early, release often"
approach is the best way forward.

[1] https://ffmpeg.org/pipermail/ffmpeg-devel/2024-June/329068.html
[2] https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325811.html
[3] https://ffmpeg.org/pipermail/ffmpeg-devel/2024-April/325903.html
[4] https://ffmpeg.org/index.html#news
[5] https://www.gimp.org/news/
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] Development process for explaining contexts (was Re: [PATCH v6 1/4] doc: Explain what "context" means)
  2024-06-16 18:02           ` [FFmpeg-devel] Development process for explaining contexts (was Re: [PATCH v6 1/4] doc: Explain what "context" means) Andrew Sayers
@ 2024-06-16 21:20             ` Paul B Mahol
  2024-07-01 22:16             ` Stefano Sabatini
  1 sibling, 0 replies; 84+ messages in thread
From: Paul B Mahol @ 2024-06-16 21:20 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Avoid filling some of bellow points:

https://erikbern.com/2023/12/13/simple-sabotage-for-software.html

Especially part of rewriting public or internal API just for rewrite.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] Development process for explaining contexts (was Re: [PATCH v6 1/4] doc: Explain what "context" means)
  2024-06-16 18:02           ` [FFmpeg-devel] Development process for explaining contexts (was Re: [PATCH v6 1/4] doc: Explain what "context" means) Andrew Sayers
  2024-06-16 21:20             ` Paul B Mahol
@ 2024-07-01 22:16             ` Stefano Sabatini
  2024-07-02  9:56               ` Andrew Sayers
  1 sibling, 1 reply; 84+ messages in thread
From: Stefano Sabatini @ 2024-07-01 22:16 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On date Sunday 2024-06-16 19:02:51 +0100, Andrew Sayers wrote:
> Meta note #1: I've replied in this thread but changed the subject line.
> That's because it needs to stay focussed on solving this thread's problem,
> but may be of more general interest.
> 
> Meta note #2: Stefano, I appreciate your feedback, but would rather wait
> for [1] to get sorted out, then formulate my thoughts while writing a new
> version.  That way I'll be more focussed on ways to improve things for readers.
> 
> This thread started with what I thought was a trivia question[1] -
> what is a context?  It's short for "AVClass context structure", which is
> synonymous with "AVOptions-enabled struct".  It turned out to be more complex
> than that, so I wrote a little patch[3] explaining this piece of jargon.
> But it turned out to be more complex again, and so on until we got a 430-line
> document explaining things in voluminous detail.
> 
> Everyone agrees this isn't ideal, so here are some alternatives.
> This may also inspire thoughts about FFmpeg development in general.
> 
> # Alternative: Just give up
> 
> The argument: We tried something, learnt a lot, but couldn't find a solution
> we agreed on, so let's come back another day.
> 
> Obviously this is the easy way out, but essentially means leaving a critical
> bug in the documentation (misleads the reader about a fundamental concept).
> Even the most negative take on this document is that it's better than nothing,
> so I think we can rule this one out.
> 
> # Err on the side of under-communicating
> 
> The argument: this document is on the right tracks, but explains too many things
> the reader can already be assumed to know.
> 
> This argument is more complex than it appears.  To take some silly examples,
> I'm not going to learn Mandarin just because FFmpeg users can't be assumed to
> speak English.  But I am willing to use American spelling because it's what
> more readers are used to.  This e-mail is plenty long enough already, so
> I'll stick to some high-level points about this argument.
> 
> The main risk of cutting documentation is that if someone can't follow a single
> step, they're lost and don't even know how to express their problem.  Imagine
> teaching maths to children - you need to teach them what numbers are, then how
> to add them together, then multiplication, then finally exponents.  But if you
> say "we don't need to teach numbers because kids all watch Numberblocks now",
> you'll cover the majority of kids who could have worked it out anyway, and
> leave a minority who just give up and say "I guess I must be bad at maths".
> I'd argue it's better to write more, then get feedback from actual newbies and
> cut based on the evidence - we'll get it wrong either way, but at least this way
> the newbies will know what they want us to cut.
> 
> Incidentally, there's a much stronger argument for *drafting* a long document,
> even if it gets cut down before it's committed.  FFmpeg has lots of undocumented
> nuances that experts just know and newbies don't know to ask, and this thread is
> full of instances where writing more detail helped tease out a misunderstanding.
> [1] is a great example - I had finally written enough detail to uncover my
> assumption that all AVOptions could be set at any time, then that thread
> taught me to look for a flag that tells you the options for which that's true.
> 
> If you assume I'm not the only person who has been subtly misled that way,
> you could argue it's better to commit the long version.  That would give readers
> more opportunities to confront their own wrong assumptions, instead of reading
> something that assumed they knew one thing, but let them keep believing another.
> The obvious counterargument is that we should...
> 
> # Spread the information across multiple documents
> 
> The argument: this document puts too much information in one place.  We should
> instead focus on making small patches that put information people need to know
> where they need to know it.
> 
> This is where things get more interesting to a general audience.
> 
> If you have repo commit access, you're probably imagining a workflow like:
> write a bunch of little commits, send them out for review, then commit them
> when people stop replying.  Your access is evidence that you basically know how
> things work, and also lets you make plans confident in the knowledge that
> anything you need committed will make it there in the end.
> 
> My workflow is nothing like that.  This thread has constantly reinforced that I
> don't understand FFmpeg, so it's better for me not to have commit access.  But
> that means I can only work on one patch at once, because I will probably learn
> something that invalidates any other work I would have done.  It also means
> a single patch not getting interest is enough to sink the project altogether.
> I can put up with that when it's one big multi-faceted patch, because I can work
> on one part while waiting for feedback on another part.  But my small patches
> generally involve a few hours of work, a week of waiting, a ping begging for
> attention, then often being rejected or ignored.  In the real world, the only
> thing this approach will achieve is to burn me out.
> 
> It might be possible to revisit this idea *after* committing the document,
> when we're fairly confident the answers are right and just need to tweak
> the presentation based on feedback.  Or other people could write documentation
> based on issues brought up in this thread, and I'll cut as appropriate.
> But for now this is a non-starter.
> 
> # Write a blog post
> 
> The argument: doxygen and texinfo are good for documenting "timeless truths".
> But we don't have anywhere to put transitory information like upgrade guides,
> or subjective information like guidance about best practices.  This document
> shoehorns information in here that really belongs somewhere like that.
> 
> This is basically true, but that doesn't solve anything.
> 
> I have neither a personal blog nor the desire to write one, and even if I wrote
> an excellent guide to contexts as a general concept, nobody would actually find
> the blog to read it.  So this idea would only work if we e.g. overhauled the
> news area of the site[4] to look more like GIMP's news section[5].
> 
> If someone else would like to start a project like that, I can promise a good
> series of posts to help get the ball rolling, and will be happy to trim down
> the document as those posts go public.
> 
[...]
> # Rewrite the API
> 
> The argument: instead of writing a bunch of words apologising for an interface,
> just write a better interface.
> 
> In general, I'm a big believer in using documentation to drive API decisions.
> But in FFmpeg's case, it wouldn't help to have a single developer trying to fix
> a community-wide problem.
> 

> We've previously discussed swr_alloc_set_opts() (essentially two functions
> sharing one symbol) and av_ambient_viewing_environment_create_side_data()
> (receives a different context argument than its function name).
> A better example of the community-wide issue might be av_new_packet()
> (initializes but does not allocate, despite slightly confusing documentation)
> vs. av_new_program() (allocates and initializes, but has no documentation).
> Both of these could be documented better, and a developer who only needs to

> learn one won't be bothered by the other.  But the real problem is that they
> use the word "new" to mean fundamentally incompatible things, creating a trap
> for anyone reviewing code that uses the "new" they haven't seen before.
> 
> Solving this problem wouldn't just involve rewriting a bunch of functions.
> It would involve motivating the community to avoid writing that sort of API
> in future, which would take all of us many years to achieve.

I see one of the differences about you and I perceive the API is that
I'm not assuming that every time you see "_new_" in a function there
will be a very exact behavior to be assumed in that function. This
would be nice in theory, but in practice you will see that different
APIs were written by different persons in different years and they
were approved by different reviewers.

I would happy enough if the documentation is correct when stating the
behavior of the function, but I don't pretend that since two functions
both contain the term "new" they can be described by the same notion
of "new". Also this is why we should not create an expectation of what
a function does if it contains "new".

This might work if there was a naming guideline the
contributors/reviewers must commit to, or if a function name is
enforced by the language (e.g. as in the case of C++). Since this is
not the case for FFmpeg, we should not set an expectation about
function terminology and behavior. Same is also true for contexts (we
don't have any "contract" stating that context functions should always
pick a "context" as first argument, and I noted several times even in
OOP languages there are constructs - e.g. static/class methods - which
works as constructors and therefore take no self as argument. In the
case of the C language there is no notion of class, so there is no way
to formally distinguish the two cases. I can come with a more concrete
example if this is not clear enough).

Finally, this does not mean that we should not try to make the FFmpeg
API more consistent (I tried for years), but that does not mean that
we should make a-priori assumptions about how the API behaves when you
read "context" or "new" in a function name - the documentation of the
function should clarify what it does - without resorting to a general
theory setting up too strict expectations which do not match reality.

There are a few examples which should be fixed (e.g. the ugly
swr_alloc_set_opts()) but I don't think we should really
mention/apologize for that in the documentation.

> 
> # Apply this, then iterate
> 
> The argument: OK fine, but dragging down other solutions doesn't help this one.
> We should at least try to solve these problems.
> 
> This is the position I've currently landed up at.  I'm increasingly able to
> justify the big picture decisions behind the document, and we're getting to
> the point where detailed discussions are just putting opinions where evidence
> should go.
> 
> I've talked in a previous e-mail about getting feedback from #ffmpeg and the
> libav-user mailing list.  We've also talked about the value of making the
> document useful to people familiar with other programming languages, so we
> could try reaching out to people who write bindings in other languages.
> 
> This sort of iteration can be pretty quick, because we don't need to wait for
> a major release.  We just need to have something on ffmpeg.org so people know
> this is a "real" project.  As such, I think a "release early, release often"
> approach is the best way forward.

[...]

Andrew, sorry again for the slow reply. Thinking about the whole
discussion, I reckon I probably gave some bad advice, and I totally
understand how this is feeling dragging and burning out, and I'm sorry
for that.

I'm still on the idea of erring on the side of under-communicating for
the reference documentation (with the idea that too much information
is just too much, and would scare people away and make it harder to
maintain the documentation, as now you have to check in many places
when changing/updating it, resulting in contradicting content).

So at the moment I'd be willing to publish an abridged version of your
latest patch, with the suggested cuts - I can make the edit myself if
you prefer like that. This way we can get the non controversial parts
committed, and we can work on the other parts where there is no still
agreement.

Also, I'd like to hear opinions from other developers, although my
impression - from the scattered feedback I read - is that other
developers have the same feeling as me.

In general, having different channels for different targets would be
ideal, e.g. for articles and tutorials. For this it would be ideal to
have a blog entry for the project org, to simplify contributions from
contributors who don't want to setup a blog just for that and to
collect resources in a single place. In practice we lack this so this
is not an option at the moment (and the wiki is not the ideal place
too).
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] Development process for explaining contexts (was Re: [PATCH v6 1/4] doc: Explain what "context" means)
  2024-07-01 22:16             ` Stefano Sabatini
@ 2024-07-02  9:56               ` Andrew Sayers
  2024-07-06 11:33                 ` Stefano Sabatini
  0 siblings, 1 reply; 84+ messages in thread
From: Andrew Sayers @ 2024-07-02  9:56 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Tue, Jul 02, 2024 at 12:16:21AM +0200, Stefano Sabatini wrote:
> On date Sunday 2024-06-16 19:02:51 +0100, Andrew Sayers wrote:
[...]
> 
> Andrew, sorry again for the slow reply. Thinking about the whole
> discussion, I reckon I probably gave some bad advice, and I totally
> understand how this is feeling dragging and burning out, and I'm sorry
> for that.
> 
> I'm still on the idea of erring on the side of under-communicating for
> the reference documentation (with the idea that too much information
> is just too much, and would scare people away and make it harder to
> maintain the documentation, as now you have to check in many places
> when changing/updating it, resulting in contradicting content).
> 
> So at the moment I'd be willing to publish an abridged version of your
> latest patch, with the suggested cuts - I can make the edit myself if
> you prefer like that. This way we can get the non controversial parts
> committed, and we can work on the other parts where there is no still
> agreement.
> 
> Also, I'd like to hear opinions from other developers, although my
> impression - from the scattered feedback I read - is that other
> developers have the same feeling as me.
> 
> In general, having different channels for different targets would be
> ideal, e.g. for articles and tutorials. For this it would be ideal to
> have a blog entry for the project org, to simplify contributions from
> contributors who don't want to setup a blog just for that and to
> collect resources in a single place. In practice we lack this so this
> is not an option at the moment (and the wiki is not the ideal place
> too).

No problem about the delay, although my thinking has moved on a little
(e.g. it turns out GIMP uses the word "context" in a completely different
way than we do[1]).  But rather than argue over today's minutia, here's
a big picture idea...

It sounds like your vision is for smaller, more disparate documentation;
and you're willing to spend some time writing that up.  How would you feel
about taking the AVClass/AVOptions bits from this document, and working them
in to the existing AVClass/AVOptions documentation?  That would require a level
of experience (and commit access) beyond what I can offer, after which we could
come back here and uncontroversially trim that stuff out of this document.

For inspiration, here are some uninformed questions a newbie might ask:

* (reading AVClass) does the struct name mean I have to learn OOP before I can
  use FFmpeg?
* (reading AVOptions) if the options API only works post-init for a subset of
  options, should I just ignore this API and set the variables directly
  whenever I like?

[1] https://developer.gimp.org/api/2.0/libgimp/libgimp-gimpcontext.html

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [FFmpeg-devel] Development process for explaining contexts (was Re: [PATCH v6 1/4] doc: Explain what "context" means)
  2024-07-02  9:56               ` Andrew Sayers
@ 2024-07-06 11:33                 ` Stefano Sabatini
  0 siblings, 0 replies; 84+ messages in thread
From: Stefano Sabatini @ 2024-07-06 11:33 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On date Tuesday 2024-07-02 10:56:34 +0100, Andrew Sayers wrote:
> On Tue, Jul 02, 2024 at 12:16:21AM +0200, Stefano Sabatini wrote:
> > On date Sunday 2024-06-16 19:02:51 +0100, Andrew Sayers wrote:
> [...]
> > 
> > Andrew, sorry again for the slow reply. Thinking about the whole
> > discussion, I reckon I probably gave some bad advice, and I totally
> > understand how this is feeling dragging and burning out, and I'm sorry
> > for that.
> > 
> > I'm still on the idea of erring on the side of under-communicating for
> > the reference documentation (with the idea that too much information
> > is just too much, and would scare people away and make it harder to
> > maintain the documentation, as now you have to check in many places
> > when changing/updating it, resulting in contradicting content).
> > 
> > So at the moment I'd be willing to publish an abridged version of your
> > latest patch, with the suggested cuts - I can make the edit myself if
> > you prefer like that. This way we can get the non controversial parts
> > committed, and we can work on the other parts where there is no still
> > agreement.
> > 
> > Also, I'd like to hear opinions from other developers, although my
> > impression - from the scattered feedback I read - is that other
> > developers have the same feeling as me.
> > 
> > In general, having different channels for different targets would be
> > ideal, e.g. for articles and tutorials. For this it would be ideal to
> > have a blog entry for the project org, to simplify contributions from
> > contributors who don't want to setup a blog just for that and to
> > collect resources in a single place. In practice we lack this so this
> > is not an option at the moment (and the wiki is not the ideal place
> > too).
> 
> No problem about the delay, although my thinking has moved on a little
> (e.g. it turns out GIMP uses the word "context" in a completely different
> way than we do[1]).  But rather than argue over today's minutia, here's
> a big picture idea...
> 
> It sounds like your vision is for smaller, more disparate documentation;
> and you're willing to spend some time writing that up.  How would you feel
> about taking the AVClass/AVOptions bits from this document, and working them
> in to the existing AVClass/AVOptions documentation?  That would require a level
> of experience (and commit access) beyond what I can offer, after which we could
> come back here and uncontroversially trim that stuff out of this document.
> 

> For inspiration, here are some uninformed questions a newbie might ask:
> 

> * (reading AVClass) does the struct name mean I have to learn OOP before I can
>   use FFmpeg?

The answer is definitively no, the point of AVClass is keeping the
"core" functionality for a class of contexts.

> * (reading AVOptions) if the options API only works post-init for a subset of
>   options, should I just ignore this API and set the variables directly
>   whenever I like?

Nothing prevents directly accessing a struct, but then yuo will miss
the following benefits:
* ABI/API compatibility in case of field renames in the context struct
* validation
* higher level setting functionality (e.g. to set options from
  a dictionary or from a string encoding multiple options)

I'll try to write something (and probably we should have a dedicated
class.h header to decouple it from the logging functionality).
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 84+ messages in thread

end of thread, other threads:[~2024-07-06 11:33 UTC | newest]

Thread overview: 84+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-18 15:06 [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means Andrew Sayers
2024-04-18 15:06 ` [FFmpeg-devel] [PATCH 2/3] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
2024-04-18 15:06 ` [FFmpeg-devel] [PATCH 3/3] all: Link to "context" from all contexts with documentation Andrew Sayers
2024-04-20  7:25 ` [FFmpeg-devel] [PATCH 1/3] doc: Explain what "context" means Stefano Sabatini
2024-04-20 12:18   ` Andrew Sayers
2024-04-20 16:13     ` Stefano Sabatini
2024-04-20 12:19   ` [FFmpeg-devel] [PATCH v2 " Andrew Sayers
2024-04-20 12:19     ` [FFmpeg-devel] [PATCH v2 2/3] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
2024-04-20 12:19     ` [FFmpeg-devel] [PATCH v2 3/3] all: Link to "context" from all contexts with documentation Andrew Sayers
2024-04-20 16:48     ` [FFmpeg-devel] [PATCH v2 1/3] doc: Explain what "context" means Stefano Sabatini
2024-04-20 22:17       ` Andrew Sayers
2024-04-22  8:02         ` Stefano Sabatini
2024-04-22 15:56           ` [FFmpeg-devel] [PATCH v3 0/3] all: Link to "context" from all contexts with documentation Andrew Sayers
2024-04-22 15:56             ` [FFmpeg-devel] [PATCH v3 1/3] doc: Explain what "context" means Andrew Sayers
2024-04-22 17:05               ` Stefano Sabatini
2024-04-29  9:10                 ` Andrew Sayers
2024-05-02 10:03                   ` Andrew Sayers
2024-05-05  7:29                   ` Stefano Sabatini
2024-05-05 21:04                     ` Andrew Sayers
2024-05-22 10:37                       ` Stefano Sabatini
2024-05-22 12:47                         ` Andrew Sayers
2024-05-25  9:00                           ` Stefano Sabatini
2024-04-29  9:24                 ` [FFmpeg-devel] [PATCH v4 1/4] " Andrew Sayers
2024-04-29  9:24                   ` [FFmpeg-devel] [PATCH v4 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
2024-04-29  9:24                   ` [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation Andrew Sayers
2024-05-02 11:01                     ` Lynne
2024-05-02 11:14                       ` Andrew Sayers
2024-05-02 13:00                       ` Zhao Zhili
2024-05-02 13:27                         ` Andrew Sayers
2024-05-02 13:39                           ` Zhao Zhili
2024-04-29  9:24                   ` [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes Andrew Sayers
2024-05-05  8:31                   ` [FFmpeg-devel] [PATCH v4 1/4] doc: Explain what "context" means Andreas Rheinhardt
2024-05-05 10:34                     ` Andrew Sayers
2024-04-22 15:56             ` [FFmpeg-devel] [PATCH v3 2/3] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
2024-04-22 15:56             ` [FFmpeg-devel] [PATCH v3 3/3] all: Link to "context" from all contexts with documentation Andrew Sayers
2024-05-15 15:54 ` [FFmpeg-devel] [PATCH v4 0/4] Explain what "context" means Andrew Sayers
2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 1/4] doc: " Andrew Sayers
2024-05-22  9:31     ` Stefano Sabatini
2024-05-22 16:07       ` Andrew Sayers
2024-05-25  9:49         ` Stefano Sabatini
2024-05-26 12:06           ` Andrew Sayers
2024-05-28 17:24             ` Stefano Sabatini
2024-05-29 10:10               ` Andrew Sayers
2024-05-29 10:50               ` Andrew Sayers
2024-05-29 11:06                 ` Paul B Mahol
2024-05-29 14:18                   ` Andrew Sayers
2024-05-29 16:06                 ` Stefano Sabatini
2024-05-23 20:00       ` [FFmpeg-devel] [PATCH v5 0/4] " Andrew Sayers
2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 1/4] doc: " Andrew Sayers
2024-05-25 11:00           ` Stefano Sabatini
2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
2024-05-25  9:57           ` Stefano Sabatini
2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 3/4] all: Link to "context" from all public contexts with documentation Andrew Sayers
2024-05-23 20:00         ` [FFmpeg-devel] [PATCH v5 4/4] all: Rewrite documentation for contexts Andrew Sayers
2024-05-24  1:50         ` [FFmpeg-devel] [PATCH v5 0/4] Explain what "context" means Michael Niedermayer
2024-05-24  9:43           ` Andrew Sayers
2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
2024-05-22 10:04     ` Stefano Sabatini
2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 3/4] all: Link to "context" from all contexts with documentation Andrew Sayers
2024-05-15 16:46     ` Lynne via ffmpeg-devel
2024-05-16 11:25       ` Andrew Sayers
2024-05-15 15:54   ` [FFmpeg-devel] [PATCH v4 4/4] lavf: Add documentation for private "Context" classes Andrew Sayers
2024-05-22 10:08     ` Stefano Sabatini
2024-05-22 14:47       ` Andrew Sayers
2024-05-22 15:24     ` Andreas Rheinhardt
2024-05-22 16:54       ` Andrew Sayers
2024-06-04 14:47 ` [FFmpeg-devel] [PATCH v6 0/4] doc: Explain what "context" means Andrew Sayers
2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 1/4] " Andrew Sayers
2024-06-05  8:15     ` Anton Khirnov
2024-06-12 20:52     ` Stefano Sabatini
2024-06-13 14:20       ` Andrew Sayers
2024-06-15  9:17         ` Stefano Sabatini
2024-06-16 18:02           ` [FFmpeg-devel] Development process for explaining contexts (was Re: [PATCH v6 1/4] doc: Explain what "context" means) Andrew Sayers
2024-06-16 21:20             ` Paul B Mahol
2024-07-01 22:16             ` Stefano Sabatini
2024-07-02  9:56               ` Andrew Sayers
2024-07-06 11:33                 ` Stefano Sabatini
2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 2/4] lavu: Clarify relationship between AVClass, AVOption and context Andrew Sayers
2024-06-05 10:34     ` Stefano Sabatini
2024-06-05 12:46       ` Andrew Sayers
2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 3/4] all: Link to "context" from all public contexts with documentation Andrew Sayers
2024-06-05  8:12     ` Anton Khirnov
2024-06-05 12:51       ` Andrew Sayers
2024-06-04 14:47   ` [FFmpeg-devel] [PATCH v6 4/4] all: Rewrite documentation for contexts Andrew Sayers

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git