X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Foptions.c;h=59e0389815678a00f287f6e3a3294f026ad951d2;hb=7b30dad3a696cc5423218ba0c11a48b6009a121b;hp=c188c23506a20b8a3c545f53b086b9d671bee891;hpb=ace96d2e693d804a0ed16aebc1b1027cfff2c527;p=ffmpeg diff --git a/libavformat/options.c b/libavformat/options.c index c188c23506a..59e03898156 100644 --- a/libavformat/options.c +++ b/libavformat/options.c @@ -21,6 +21,7 @@ #include "avio_internal.h" #include "internal.h" +#include "libavutil/avassert.h" #include "libavutil/internal.h" #include "libavutil/opt.h" @@ -53,33 +54,96 @@ static void *format_child_next(void *obj, void *prev) return NULL; } +#if FF_API_CHILD_CLASS_NEXT static const AVClass *format_child_class_next(const AVClass *prev) { - AVInputFormat *ifmt = NULL; - AVOutputFormat *ofmt = NULL; + const AVInputFormat *ifmt = NULL; + const AVOutputFormat *ofmt = NULL; + void *ifmt_iter = NULL, *ofmt_iter = NULL; if (!prev) return &ff_avio_class; - while ((ifmt = av_iformat_next(ifmt))) + while ((ifmt = av_demuxer_iterate(&ifmt_iter))) if (ifmt->priv_class == prev) break; - if (!ifmt) - while ((ofmt = av_oformat_next(ofmt))) + if (!ifmt) { + ifmt_iter = NULL; + while ((ofmt = av_muxer_iterate(&ofmt_iter))) if (ofmt->priv_class == prev) break; - if (!ofmt) - while (ifmt = av_iformat_next(ifmt)) + } + if (!ofmt) { + ofmt_iter = NULL; + while ((ifmt = av_demuxer_iterate(&ifmt_iter))) if (ifmt->priv_class) return ifmt->priv_class; + } - while (ofmt = av_oformat_next(ofmt)) + while ((ofmt = av_muxer_iterate(&ofmt_iter))) if (ofmt->priv_class) return ofmt->priv_class; return NULL; } +#endif + +enum { + CHILD_CLASS_ITER_AVIO = 0, + CHILD_CLASS_ITER_MUX, + CHILD_CLASS_ITER_DEMUX, + CHILD_CLASS_ITER_DONE, + +}; + +#define ITER_STATE_SHIFT 16 + +static const AVClass *format_child_class_iterate(void **iter) +{ + // we use the low 16 bits of iter as the value to be passed to + // av_(de)muxer_iterate() + void *val = (void*)(((uintptr_t)*iter) & ((1 << ITER_STATE_SHIFT) - 1)); + unsigned int state = ((uintptr_t)*iter) >> ITER_STATE_SHIFT; + const AVClass *ret = NULL; + + if (state == CHILD_CLASS_ITER_AVIO) { + ret = &ff_avio_class; + state++; + goto finish; + } + + if (state == CHILD_CLASS_ITER_MUX) { + const AVOutputFormat *ofmt; + + while ((ofmt = av_muxer_iterate(&val))) { + ret = ofmt->priv_class; + if (ret) + goto finish; + } + + val = NULL; + state++; + } + + if (state == CHILD_CLASS_ITER_DEMUX) { + const AVInputFormat *ifmt; + + while ((ifmt = av_demuxer_iterate(&val))) { + ret = ifmt->priv_class; + if (ret) + goto finish; + } + val = NULL; + state++; + } + +finish: + // make sure none av_(de)muxer_iterate does not set the high bits of val + av_assert0(!((uintptr_t)val >> ITER_STATE_SHIFT)); + *iter = (void*)((uintptr_t)val | (state << ITER_STATE_SHIFT)); + return ret; +} static AVClassCategory get_category(void *ptr) { @@ -94,7 +158,10 @@ static const AVClass av_format_context_class = { .option = avformat_options, .version = LIBAVUTIL_VERSION_INT, .child_next = format_child_next, +#if FF_API_CHILD_CLASS_NEXT .child_class_next = format_child_class_next, +#endif + .child_class_iterate = format_child_class_iterate, .category = AV_CLASS_CATEGORY_MUXER, .get_category = get_category, }; @@ -144,15 +211,17 @@ static void avformat_get_context_defaults(AVFormatContext *s) AVFormatContext *avformat_alloc_context(void) { AVFormatContext *ic; + AVFormatInternal *internal; ic = av_malloc(sizeof(AVFormatContext)); if (!ic) return ic; - avformat_get_context_defaults(ic); - ic->internal = av_mallocz(sizeof(*ic->internal)); - if (!ic->internal) { - avformat_free_context(ic); + internal = av_mallocz(sizeof(*internal)); + if (!internal) { + av_free(ic); return NULL; } + avformat_get_context_defaults(ic); + ic->internal = internal; ic->internal->offset = AV_NOPTS_VALUE; ic->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; ic->internal->shortest_end = AV_NOPTS_VALUE;