[FFmpeg-devel] [PATCH 2.e/3] libavformat/protocols.c: avio_enum_protocols(): Create a macro for generating different loops
Michael Witten
mfwitten at gmail.com
Wed Aug 11 22:00:16 EEST 2021
The function 'avio_enum_protocols()' iterates through the list of
protocols, looking for a protocol that has a certain non-zero
pointer-to-function; the exact pointer-to-function to use depends
on the the argument passed through the parameter 'output'.
* Before this commit, the parameter 'output' was being checked
on every iteration, despite the fact that its value does not
change.
* This commit explicitly separates out the different cases into
their own loops (i.e., their own functions), so that 'output'
need not be tested on each iteration.
* To aid maintenance, these separate functions are the expansion
of a single macro that provides a generic implementation:
AVIO_ENUM_PROTOCOLS(METHOD)
One of the benefits of using a macro is that it does not depend
on a compiler being able to optimize the code. Before deciding
to use a macro for this purpose, it was attempted to write a
generic version in terms of pure C code that also would not
rely on magical optimizations; this involved type conversions
on pointer arithmetic around 'offsetof()', but it turns out that
Standard C (not to be confused with Actual C) has no reliable way
to recover the value of a pointer-to-function from an object,
so that avenue was ultimately abandoned for the sake of pure
pedantry.
---
libavformat/protocols.c | 37 +++++++++++++++++++++++++++----------
1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/libavformat/protocols.c b/libavformat/protocols.c
index 9ce98968fa..4cb8ae0b63 100644
--- a/libavformat/protocols.c
+++ b/libavformat/protocols.c
@@ -91,18 +91,35 @@ const AVClass *ff_urlcontext_child_class_iterate(void **iter)
return ret;
}
-const char *avio_enum_protocols(void **const opaque, const int output)
+#define AVIO_ENUM_PROTOCOLS(METHOD) \
+ typedef const URLProtocol *const *Iterator; \
+ for(Iterator p = *opaque ? (Iterator)(*opaque) + 1 : url_protocols; *p; ++p) { \
+ if ((*p)->METHOD) { \
+ *opaque = (void *)p; \
+ return (*p)->name; \
+ } \
+ } \
+ *opaque = NULL; \
+ return NULL;
+
+static inline
+const char *avio_enum_protocols_for_output(void **const opaque)
{
- typedef const URLProtocol *const *Iterator;
- for(Iterator p = *opaque ? (Iterator)(*opaque) + 1 : url_protocols; *p; ++p) {
- if ((output && (*p)->url_write) || (!output && (*p)->url_read)) {
- *opaque = (void *)p;
- return (*p)->name;
- }
- }
+ AVIO_ENUM_PROTOCOLS(url_write);
+}
- *opaque = NULL;
- return NULL;
+static inline
+const char *avio_enum_protocols_for_input(void **const opaque)
+{
+ AVIO_ENUM_PROTOCOLS(url_read);
+}
+
+const char *avio_enum_protocols(void **const opaque, const int output)
+{
+ if (output)
+ return avio_enum_protocols_for_output(opaque);
+ else
+ return avio_enum_protocols_for_input(opaque);
}
const AVClass *avio_protocol_get_class(const char *name)
--
2.22.0
More information about the ffmpeg-devel
mailing list