On Sat, 23 Dec 2017 13:27:53 +0000 Josh de Kock <j...@itanimul.li> wrote:
> From 1d84641556eea563b82b17a6ffe54226e0e31c4e Mon Sep 17 00:00:00 2001 > From: Josh de Kock <j...@itanimul.li> > Date: Fri, 22 Dec 2017 22:17:00 +0000 > Subject: [PATCH] lavc: add new API for iterating codecs and codec parsers > > Also replace linked list with an array. > --- I generally agree with this patch. > configure | 14 +- > libavcodec/allcodecs.c | 1472 > ++++++++++++++++++++++++++++-------------------- > libavcodec/avcodec.h | 25 + > libavcodec/parser.c | 86 ++- > libavcodec/utils.c | 105 ---- > 5 files changed, 962 insertions(+), 740 deletions(-) > > diff --git a/configure b/configure > index d09eec4..681fe10 100755 > --- a/configure > +++ b/configure > @@ -3517,9 +3517,6 @@ find_things(){ > sed -n "s/^[^#]*$pattern.*([^,]*, *\([^,]*\)\(,.*\)*).*/\1_$thing/p" > "$file" > } > > -ENCODER_LIST=$(find_things encoder ENC libavcodec/allcodecs.c) > -DECODER_LIST=$(find_things decoder DEC libavcodec/allcodecs.c) > -PARSER_LIST=$(find_things parser PARSER libavcodec/allcodecs.c) > MUXER_LIST=$(find_things muxer _MUX libavformat/allformats.c) > DEMUXER_LIST=$(find_things demuxer DEMUX libavformat/allformats.c) > OUTDEV_LIST=$(find_things outdev OUTDEV libavdevice/alldevices.c) > @@ -3533,6 +3530,13 @@ find_things_extern(){ > sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" > "$file" > } > > +ENCODER_LIST=$(find_things_extern encoder AVCodec libavcodec/allcodecs.c) > +DECODER_LIST=$(find_things_extern decoder AVCodec libavcodec/allcodecs.c) > +CODEC_LIST=" > + $ENCODER_LIST > + $DECODER_LIST > +" > +PARSER_LIST=$(find_things_extern parser AVCodecParser libavcodec/parser.c) > BSF_LIST=$(find_things_extern bsf AVBitStreamFilter > libavcodec/bitstream_filters.c) > HWACCEL_LIST=$(find_things_extern hwaccel AVHWAccel libavcodec/hwaccels.h) > PROTOCOL_LIST=$(find_things_extern protocol URLProtocol > libavformat/protocols.c) > @@ -7020,6 +7024,10 @@ print_enabled_components(){ > cp_if_changed $TMPH $file > } > > +print_enabled_components libavcodec/codec_list.c AVCodec codec_list > $CODEC_LIST > +#print_enabled_components libavcodec/encoder_list.c AVCodec encoder_list > $ENCODER_LIST > +#print_enabled_components libavcodec/decoder_list.c AVCodec decoder_list > $DECODER_LIST Commented leftover crap? > +print_enabled_components libavcodec/parser_list.c AVCodecParser parser_list > $PARSER_LIST > print_enabled_components libavcodec/bsf_list.c AVBitStreamFilter > bitstream_filters $BSF_LIST > print_enabled_components libavformat/protocol_list.c URLProtocol > url_protocols $PROTOCOL_LIST > > diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c > index ed1e7ab..cea2bf3 100644 > --- a/libavcodec/allcodecs.c > +++ b/libavcodec/allcodecs.c > @@ -29,641 +29,865 @@ > #include "avcodec.h" > #include "version.h" > > -#define REGISTER_ENCODER(X, x) \ > - { \ > - extern AVCodec ff_##x##_encoder; \ > - if (CONFIG_##X##_ENCODER) \ > - avcodec_register(&ff_##x##_encoder); \ > +extern AVCodec ff_a64multi_encoder; > [...] > > +#include "codec_list.c" > + > +#if CONFIG_ME_CMP > +#include "me_cmp.h" > +pthread_once_t ff_me_cmp_static_init = PTHREAD_ONCE_INIT; > +#endif > + > +pthread_once_t av_codec_next_init = PTHREAD_ONCE_INIT; > + > +const AVCodec *av_codec_iterate(void **opaque) > +{ > + uintptr_t i = (uintptr_t)*opaque; > + const AVCodec *c = codec_list[i]; > + > + if (c) > + *opaque = (void*)(i + 1); > + > + return c; > +} > + > +static void av_codec_init_next(void) > +{ > + AVCodec *prev = NULL, *p; > + void *i = 0; > + while ((p = (AVCodec*)av_codec_iterate(&i))) { > + if (prev) > + prev->next = p; > + prev = p; > } > + prev->next = NULL; > +} > > -#define REGISTER_DECODER(X, x) \ > - { \ > - extern AVCodec ff_##x##_decoder; \ > - if (CONFIG_##X##_DECODER) \ > - avcodec_register(&ff_##x##_decoder); \ > +av_cold void avcodec_register(AVCodec *codec) > +{ This function, together with av_codec_next(), should be deprecated. Just adding attribute_deprecated isn't enough. You also need to add that FF_API_ ifdeffery soup (unfortunately). > +#if CONFIG_ME_CMP > + pthread_once(&ff_me_cmp_static_init, ff_me_cmp_init_static); > +#endif > + > + pthread_once(&av_codec_next_init, av_codec_init_next); > + > + if (codec->init_static_data) > + codec->init_static_data(codec); > +} As I stated below, this stuff should go away. The me_cmp thing can probably be (very carefully) be moved to codecs which need it. The init_static_data thing will have to stay for a while, because wrappers like libx264 modify a public field of AVCodec in it. > + > +AVCodec *av_codec_next(const AVCodec *c) > +{ > + pthread_once(&av_codec_next_init, av_codec_init_next); > + > + if (c) > + return c->next; > + else > + return (AVCodec*)codec_list[0]; > +} > + > +static enum AVCodecID remap_deprecated_codec_id(enum AVCodecID id) > +{ > + switch(id){ > + //This is for future deprecatec codec ids, its empty since > + //last major bump but will fill up again over time, please don't > remove it > + default : return id; > } > +} > + > +static AVCodec *find_codec(enum AVCodecID id, int (*x)(const AVCodec *)) > +{ > + const AVCodec *p, *experimental = NULL; > + void *i = 0; > > -#define REGISTER_ENCDEC(X, x) REGISTER_ENCODER(X, x); REGISTER_DECODER(X, x) > + id = remap_deprecated_codec_id(id); > > -#define REGISTER_PARSER(X, x) \ > - { \ > - extern AVCodecParser ff_##x##_parser; \ > - if (CONFIG_##X##_PARSER) \ > - av_register_codec_parser(&ff_##x##_parser); \ > + while ((p = av_codec_iterate(&i))) { > + if (!x(p)) > + continue; > + if (p->id == id) { > + if (p->capabilities & AV_CODEC_CAP_EXPERIMENTAL && > !experimental) { > + experimental = p; > + } else > + return (AVCodec*)p; > + } > } > > -static void register_all(void) > + return (AVCodec*)experimental; > +} > + > +AVCodec *avcodec_find_encoder(enum AVCodecID id) > { > - /* video codecs */ > - REGISTER_ENCODER(A64MULTI, a64multi); > [...] > + return find_codec(id, av_codec_is_encoder); > +} > + > +AVCodec *avcodec_find_decoder(enum AVCodecID id) > +{ > + return find_codec(id, av_codec_is_decoder); > +} > + > +static AVCodec *find_codec_by_name(const char *name, int (*x)(const AVCodec > *)) > +{ > + void *i = 0; > + const AVCodec *p; > + > + if (!name) > + return NULL; > + > + while ((p = av_codec_iterate(&i))) { > + if (!x(p)) > + continue; > + if (strcmp(name, p->name) == 0) > + return (AVCodec*)p; > + } > + > + return NULL; > +} > + > +AVCodec *avcodec_find_encoder_by_name(const char *name) > +{ > + return find_codec_by_name(name, av_codec_is_encoder); > +} > + > +AVCodec *avcodec_find_decoder_by_name(const char *name) > +{ > + return find_codec_by_name(name, av_codec_is_decoder); > } > > void avcodec_register_all(void) > { > - static AVOnce control = AV_ONCE_INIT; > + const AVCodec *codec; > + void *i = 0; > > - ff_thread_once(&control, register_all); > +#if CONFIG_ME_CMP > + pthread_once(&ff_me_cmp_static_init, ff_me_cmp_init_static); > +#endif > + > + pthread_once(&av_codec_next_init, av_codec_init_next); > + > + while ((codec = av_codec_iterate(&i))) { > + if (codec->init_static_data) > + codec->init_static_data((AVCodec*)codec); > + } > } I think this function should be deprecated, and not be required to be called. This requires init_static_data and the me_cmp thing to be moved somewhere else. Also, init_static_data should somehow be synchronized too. > diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h > index ce089b7..2300974 100644 > --- a/libavcodec/avcodec.h > +++ b/libavcodec/avcodec.h > @@ -3979,10 +3979,22 @@ typedef struct AVCodecParameters { > } AVCodecParameters; > > /** > + * Iterate over all registered codecs. > + * > + * @param opaque a pointer where libavcodec will store the iteration state. > Must > + * point to NULL to start the iteration. > + * > + * @return the next registered codec or NULL when the iteration is > + * finished > + */ > +const AVCodec *av_codec_iterate(void **opaque); > + > +/** > * If c is NULL, returns the first registered codec, > * if c is non-NULL, returns the next registered codec after c, > * or NULL if c is the last one. > */ > +attribute_deprecated > AVCodec *av_codec_next(const AVCodec *c); > > /** > @@ -5120,8 +5132,21 @@ typedef struct AVCodecParser { > struct AVCodecParser *next; > } AVCodecParser; > > +/** > + * Iterate over all registered codec parsers. > + * > + * @param opaque a pointer where libavcodec will store the iteration state. > Must > + * point to NULL to start the iteration. > + * > + * @return the next registered codec parser or NULL when the iteration is > + * finished > + */ > +const AVCodecParser *av_parser_iterate(void **opaque); Such additions need doc/APIchanges entries. Deprecations receive an entry in that file too. > + > +attribute_deprecated > AVCodecParser *av_parser_next(const AVCodecParser *c); > > +attribute_deprecated > void av_register_codec_parser(AVCodecParser *parser); > AVCodecParserContext *av_parser_init(int codec_id); > > diff --git a/libavcodec/parser.c b/libavcodec/parser.c > index 670680e..4e4c22d 100644 > --- a/libavcodec/parser.c > +++ b/libavcodec/parser.c > @@ -32,33 +32,103 @@ > #include "internal.h" > #include "parser.h" > > -static AVCodecParser *av_first_parser = NULL; > +#include "pthread.h" > + > +/* Parsers */ > +extern AVCodecParser ff_aac_parser; > +extern AVCodecParser ff_aac_latm_parser; > +extern AVCodecParser ff_ac3_parser; > +extern AVCodecParser ff_adx_parser; > +extern AVCodecParser ff_bmp_parser; > +extern AVCodecParser ff_cavsvideo_parser; > +extern AVCodecParser ff_cook_parser; > +extern AVCodecParser ff_dca_parser; > +extern AVCodecParser ff_dirac_parser; > +extern AVCodecParser ff_dnxhd_parser; > +extern AVCodecParser ff_dpx_parser; > +extern AVCodecParser ff_dvaudio_parser; > +extern AVCodecParser ff_dvbsub_parser; > +extern AVCodecParser ff_dvdsub_parser; > +extern AVCodecParser ff_dvd_nav_parser; > +extern AVCodecParser ff_flac_parser; > +extern AVCodecParser ff_g729_parser; > +extern AVCodecParser ff_gsm_parser; > +extern AVCodecParser ff_h261_parser; > +extern AVCodecParser ff_h263_parser; > +extern AVCodecParser ff_h264_parser; > +extern AVCodecParser ff_hevc_parser; > +extern AVCodecParser ff_mjpeg_parser; > +extern AVCodecParser ff_mlp_parser; > +extern AVCodecParser ff_mpeg4video_parser; > +extern AVCodecParser ff_mpegaudio_parser; > +extern AVCodecParser ff_mpegvideo_parser; > +extern AVCodecParser ff_opus_parser; > +extern AVCodecParser ff_png_parser; > +extern AVCodecParser ff_pnm_parser; > +extern AVCodecParser ff_rv30_parser; > +extern AVCodecParser ff_rv40_parser; > +extern AVCodecParser ff_sipr_parser; > +extern AVCodecParser ff_tak_parser; > +extern AVCodecParser ff_vc1_parser; > +extern AVCodecParser ff_vorbis_parser; > +extern AVCodecParser ff_vp3_parser; > +extern AVCodecParser ff_vp8_parser; > +extern AVCodecParser ff_vp9_parser; > +extern AVCodecParser ff_xma_parser; > + > +#include "parser_list.c" > + > +pthread_once_t av_parser_next_init = PTHREAD_ONCE_INIT; > + > +static void av_parser_init_next(void) > +{ > + AVCodecParser *prev = NULL, *p; > + int i = 0; > + while ((p = (AVCodecParser*)parser_list[i++])) { > + if (prev) > + prev->next = p; > + prev = p; > + } > + prev->next = NULL; > +} > > AVCodecParser *av_parser_next(const AVCodecParser *p) > { > + pthread_once(&av_parser_next_init, av_parser_init_next); > + > if (p) > return p->next; > else > - return av_first_parser; > + return (AVCodecParser*)parser_list[0]; > +} > + > +const AVCodecParser *av_parser_iterate(void **opaque) > +{ > + uintptr_t i = (uintptr_t)*opaque; > + const AVCodecParser *p = parser_list[i]; > + > + if (p) > + *opaque = (void*)(i + 1); > + > + return p; > } > > void av_register_codec_parser(AVCodecParser *parser) > { > - do { > - parser->next = av_first_parser; > - } while (parser->next != avpriv_atomic_ptr_cas((void * volatile > *)&av_first_parser, parser->next, parser)); > + pthread_once(&av_parser_next_init, av_parser_init_next); > } > > AVCodecParserContext *av_parser_init(int codec_id) > { > AVCodecParserContext *s = NULL; > - AVCodecParser *parser; > + const AVCodecParser *parser; > + void *i = 0; > int ret; > > if (codec_id == AV_CODEC_ID_NONE) > return NULL; > > - for (parser = av_first_parser; parser; parser = parser->next) { > + while ((parser = av_parser_iterate(&i))) { > if (parser->codec_ids[0] == codec_id || > parser->codec_ids[1] == codec_id || > parser->codec_ids[2] == codec_id || > @@ -72,7 +142,7 @@ found: > s = av_mallocz(sizeof(AVCodecParserContext)); > if (!s) > goto err_out; > - s->parser = parser; > + s->parser = (AVCodecParser*)parser; > s->priv_data = av_mallocz(parser->priv_data_size); > if (!s->priv_data) > goto err_out; > diff --git a/libavcodec/utils.c b/libavcodec/utils.c > index 873f39f..ff1422e 100644 > --- a/libavcodec/utils.c > +++ b/libavcodec/utils.c > @@ -47,7 +47,6 @@ > #include "decode.h" > #include "hwaccel.h" > #include "libavutil/opt.h" > -#include "me_cmp.h" > #include "mpegvideo.h" > #include "thread.h" > #include "frame_thread_encoder.h" > @@ -144,30 +143,6 @@ void av_fast_padded_mallocz(void *ptr, unsigned int > *size, size_t min_size) > memset(*p, 0, min_size + AV_INPUT_BUFFER_PADDING_SIZE); > } > > -/* encoder management */ > -static AVCodec *first_avcodec = NULL; > -static AVCodec **last_avcodec = &first_avcodec; > - > -AVCodec *av_codec_next(const AVCodec *c) > -{ > - if (c) > - return c->next; > - else > - return first_avcodec; > -} > - > -static av_cold void avcodec_init(void) > -{ > - static int initialized = 0; > - > - if (initialized != 0) > - return; > - initialized = 1; > - > - if (CONFIG_ME_CMP) > - ff_me_cmp_init_static(); > -} > - > int av_codec_is_encoder(const AVCodec *codec) > { > return codec && (codec->encode_sub || codec->encode2 > ||codec->send_frame); > @@ -178,21 +153,6 @@ int av_codec_is_decoder(const AVCodec *codec) > return codec && (codec->decode || codec->receive_frame); > } > > -av_cold void avcodec_register(AVCodec *codec) > -{ > - AVCodec **p; > - avcodec_init(); > - p = last_avcodec; > - codec->next = NULL; > - > - while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, codec)) > - p = &(*p)->next; > - last_avcodec = &codec->next; > - > - if (codec->init_static_data) > - codec->init_static_data(codec); > -} > - > int ff_set_dimensions(AVCodecContext *s, int width, int height) > { > int ret = av_image_check_size2(width, height, s->max_pixels, > AV_PIX_FMT_NONE, 0, s); > @@ -1202,71 +1162,6 @@ FF_ENABLE_DEPRECATION_WARNINGS > return 0; > } > > -static enum AVCodecID remap_deprecated_codec_id(enum AVCodecID id) > -{ > - switch(id){ > - //This is for future deprecatec codec ids, its empty since > - //last major bump but will fill up again over time, please don't > remove it > - default : return id; > - } > -} > - > -static AVCodec *find_encdec(enum AVCodecID id, int encoder) > -{ > - AVCodec *p, *experimental = NULL; > - p = first_avcodec; > - id= remap_deprecated_codec_id(id); > - while (p) { > - if ((encoder ? av_codec_is_encoder(p) : av_codec_is_decoder(p)) && > - p->id == id) { > - if (p->capabilities & AV_CODEC_CAP_EXPERIMENTAL && > !experimental) { > - experimental = p; > - } else > - return p; > - } > - p = p->next; > - } > - return experimental; > -} > - > -AVCodec *avcodec_find_encoder(enum AVCodecID id) > -{ > - return find_encdec(id, 1); > -} > - > -AVCodec *avcodec_find_encoder_by_name(const char *name) > -{ > - AVCodec *p; > - if (!name) > - return NULL; > - p = first_avcodec; > - while (p) { > - if (av_codec_is_encoder(p) && strcmp(name, p->name) == 0) > - return p; > - p = p->next; > - } > - return NULL; > -} > - > -AVCodec *avcodec_find_decoder(enum AVCodecID id) > -{ > - return find_encdec(id, 0); > -} > - > -AVCodec *avcodec_find_decoder_by_name(const char *name) > -{ > - AVCodec *p; > - if (!name) > - return NULL; > - p = first_avcodec; > - while (p) { > - if (av_codec_is_decoder(p) && strcmp(name, p->name) == 0) > - return p; > - p = p->next; > - } > - return NULL; > -} > - > const char *avcodec_get_name(enum AVCodecID id) > { > const AVCodecDescriptor *cd; I think it'd be slightly more readable if you did the move in a separate patch before this one, but I'm not insisting on it. _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel