On 25/02/16 16:05, Anton Khirnov wrote: > Deprecate the current bitstream filtering API. > --- > configure | 2 +- > libavcodec/Makefile | 2 + > libavcodec/avcodec.h | 178 +++++++++++++++++++++++++++++++-- > libavcodec/bitstream_filters.c | 51 ++++++++++ > libavcodec/bsf.c | 217 > +++++++++++++++++++++++++++++++++++++++++ > libavcodec/bsf.h | 31 ++++++ > libavcodec/version.h | 3 + > 7 files changed, 475 insertions(+), 9 deletions(-) > create mode 100644 libavcodec/bitstream_filters.c > create mode 100644 libavcodec/bsf.c > create mode 100644 libavcodec/bsf.h > > diff --git a/configure b/configure > index d8b8c07..0f59433 100755 > --- a/configure > +++ b/configure > @@ -2517,7 +2517,6 @@ ENCODER_LIST=$(find_things encoder ENC > libavcodec/allcodecs.c) > DECODER_LIST=$(find_things decoder DEC libavcodec/allcodecs.c) > HWACCEL_LIST=$(find_things hwaccel HWACCEL libavcodec/allcodecs.c) > PARSER_LIST=$(find_things parser PARSER libavcodec/allcodecs.c) > -BSF_LIST=$(find_things bsf BSF 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) > @@ -2531,6 +2530,7 @@ find_things_extern(){ > sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" > "$file" > } > > +BSF_LIST=$(find_things_extern bsf AVBitStreamFilter > libavcodec/bitstream_filters.c) > PROTOCOL_LIST=$(find_things_extern protocol URLProtocol > libavformat/protocols.c) > > ALL_COMPONENTS=" > diff --git a/libavcodec/Makefile b/libavcodec/Makefile > index 256dee3..ba1661d 100644 > --- a/libavcodec/Makefile > +++ b/libavcodec/Makefile > @@ -19,6 +19,8 @@ OBJS = allcodecs.o > \ > avpicture.o \ > bitstream.o \ > bitstream_filter.o \ > + bitstream_filters.o \ > + bsf.o \ > codec_desc.o \ > d3d11va.o \ > dirac.o \ > diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h > index 33de8ec..f6d474f 100644 > --- a/libavcodec/avcodec.h > +++ b/libavcodec/avcodec.h > @@ -4692,35 +4692,197 @@ int av_get_audio_frame_duration(AVCodecContext > *avctx, int frame_bytes); > */ > int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes); > > - > +#if FF_API_OLD_BSF > typedef struct AVBitStreamFilterContext { > void *priv_data; > struct AVBitStreamFilter *filter; > AVCodecParserContext *parser; > struct AVBitStreamFilterContext *next; > } AVBitStreamFilterContext; > +#endif > + > +typedef struct AVBSFInternal AVBSFInternal; > + > +typedef struct AVBSFContext { > + /** > + * A class for logging and AVOptions > + */ > + const AVClass *av_class; > + > + /** > + * The bitstream filter this context is an instance of. > + */ > + const struct AVBitStreamFilter *filter; > + > + /** > + * Opaque libavcodec internal data. Must not be touched by the caller in > any > + * way. > + */ > + AVBSFInternal *internal; > + > + /** > + * Opaque filter-specific private data. If filter->priv_class is > non-NULL, > + * this is an AVOptions-enabled struct. > + */ > + void *priv_data; > + > + /** > + * Codec id this bitstream filter was initialized for. > + * Set by libavcodec in av_bsf_alloc(). > + */ > + enum AVCodecID codec_id; > + > + /** > + * Parameters of the input stream. Set by the caller before > av_bsf_init(). > + */ > + AVCodecParameters *par_in; > + > + /** > + * Parameters of the output stream. Set by the filter in av_bsf_init(). > + */ > + AVCodecParameters *par_out; > > + /** > + * The timebase used for the timestamps of the input packets. Set by the > + * caller before av_bsf_init(). > + */ > + AVRational time_base_in; > + > + /** > + * The timebase used for the timestamps of the output packets. Set by the > + * filter in av_bsf_init(). > + */ > + AVRational time_base_out; > +} AVBSFContext; > > typedef struct AVBitStreamFilter { > const char *name; > + > + /** > + * A list of codec ids supported by the filter, terminated by > + * AV_CODEC_ID_NONE. > + * May be NULL, in that case the bitstream filter works with any codec > id. > + */ > + const enum AVCodecID *codec_ids; > + > + /** > + * A class for the private data, used to declare bitstream filter private > + * AVOptions. This field is NULL for bitstream filters that do not > declare > + * any options. > + * > + * If this field is non-NULL, the first member of the filter private data > + * must be a pointer to AVClass, which will be set by libavcodec generic > + * code to this class. > + */ > + const AVClass *priv_class; > + > + /***************************************************************** > + * No fields below this line are part of the public API. They > + * may not be used outside of libavcodec and can be changed and > + * removed at will. > + * New public fields should be added right above. > + ***************************************************************** > + */ > + > int priv_data_size; > - int (*filter)(AVBitStreamFilterContext *bsfc, > - AVCodecContext *avctx, const char *args, > - uint8_t **poutbuf, int *poutbuf_size, > - const uint8_t *buf, int buf_size, int keyframe); > - void (*close)(AVBitStreamFilterContext *bsfc); > - struct AVBitStreamFilter *next; > + int (*init)(AVBSFContext *ctx); > + int (*filter)(AVBSFContext *ctx, AVPacket *pkt); > + void (*close)(AVBSFContext *ctx); > } AVBitStreamFilter; > > +#if FF_API_OLD_BSF > +/** > + * @deprecated the old bitstream filtering API (using > AVBitStreamFilterContext) > + * is deprecated. Use the new bitstream filtering API (using AVBSFContext). > + */ > +attribute_deprecated > void av_register_bitstream_filter(AVBitStreamFilter *bsf); > +attribute_deprecated > AVBitStreamFilterContext *av_bitstream_filter_init(const char *name); > +attribute_deprecated > int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc, > AVCodecContext *avctx, const char *args, > uint8_t **poutbuf, int *poutbuf_size, > const uint8_t *buf, int buf_size, int > keyframe); > +attribute_deprecated > void av_bitstream_filter_close(AVBitStreamFilterContext *bsf); > - > +attribute_deprecated > AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f); > +#endif > + > +/** > + * @return a bitstream filter with the specified name or NULL if no such > + * bitstream filter exists. > + */ > +const AVBitStreamFilter *av_bsf_get_by_name(const char *name); > + > +/** > + * Iterate over all registered bitstream filters. > + * > + * @param opaque a pointer where libavcodec will store the iteration state. > Must > + * point to NULL to start the iteration. > + * > + * @return the next registered bitstream filter or NULL when the iteration is > + * finished > + */ > +const AVBitStreamFilter *av_bsf_next(void **opaque); > + > +/** > + * Allocate a context for a given bitstream filter. The caller must fill in > the > + * context parameters as described in the documentation and then call > + * av_bsf_init() before sending any data to the filter. > + * > + * @param filter the filter for which to allocate an instance. > + * @param ctx a pointer into which the pointer to the newly-allocated context > + * will be written. It must be freed with av_bsf_free() after the > + * filtering is done. > + * @param codec_id a codec id identifying the kind of data that will be sent > to > + * the filter. > + * > + * @return newly-allocated bitstream filter context or NULL on failure > + */ > +int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx, > + enum AVCodecID codec_id); > + > +/** > + * Prepare the filter for use, after all the parameters and options have been > + * set. > + */ > +int av_bsf_init(AVBSFContext *ctx); > + > +/** > + * Submit a packet for filtering. > + * > + * @param pkt the packet to filter. The bitstream filter will take ownership > of > + * the packet and reset the contents of pkt. pkt is not touched if an error > occurs. > + * > + * @return 0 on success, a negative AVERROR on error. > + */ > +int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt); > + > +/** > + * Retrieve a filtered packet. > + * > + * @param[out] pkt this struct will be filled with the contents of the > filtered > + * packet. It is owned by the caller and must be freed using > + * av_packet_unref() when it is no longer needed. > + * > + * @return 0 on success. AVERROR(EAGAIN) if more packets need to be sent to > the > + * filter (using av_bsf_send_packet()) to get more output. AVERROR_EOF if > there > + * will be no further output from the filter. Another negative AVERROR value > if > + * an error occurs. > + * > + * @note one input packet may result in several output packets, so after > adding > + * a packet with av_bsf_send_packet(), this function needs to be called > + * repeatedly until it stops returning 0. > + */ > +int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt); > + > +/** > + * Free a bitstream filter context and everything associated with it; write > NULL > + * into the supplied pointer. > + */ > +void av_bsf_free(AVBSFContext **ctx); > > /* memory */ > > diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c > new file mode 100644 > index 0000000..5e406d7 > --- /dev/null > +++ b/libavcodec/bitstream_filters.c > @@ -0,0 +1,51 @@ > +/* > + * This file is part of Libav. > + * > + * Libav is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * Libav is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with Libav; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + */ > + > +#include "config.h" > + > +#include "libavutil/common.h" > + > +#include "libavcodec/avcodec.h" > + > +static const AVBitStreamFilter *bitstream_filters[] = { > + NULL, > +}; > + > +const AVBitStreamFilter *av_bsf_next(void **opaque) > +{ > + uintptr_t i = (uintptr_t)*opaque; > + const AVBitStreamFilter *f = bitstream_filters[i]; > + > + if (f) > + *opaque = (void*)(i + 1); > + > + return f; > +} > + > +const AVBitStreamFilter *av_bsf_get_by_name(const char *name) > +{ > + int i; > + > + for (i = 0; bitstream_filters[i]; i++) { > + const AVBitStreamFilter *f = bitstream_filters[i]; > + if (!strcmp(f->name, name)) > + return f; > + } > + > + return NULL; > +} > diff --git a/libavcodec/bsf.c b/libavcodec/bsf.c > new file mode 100644 > index 0000000..ed4aef8 > --- /dev/null > +++ b/libavcodec/bsf.c > @@ -0,0 +1,217 @@ > +/* > + * This file is part of Libav. > + * > + * Libav is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * Libav is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with Libav; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + */ > + > +#include <string.h> > + > +#include "libavutil/fifo.h" > +#include "libavutil/log.h" > +#include "libavutil/mem.h" > +#include "libavutil/opt.h" > + > +#include "avcodec.h" > +#include "bsf.h" > + > +struct AVBSFInternal { > + AVFifoBuffer *fifo; > + int eof; > +}; > + > +void av_bsf_free(AVBSFContext **pctx) > +{ > + AVBSFContext *ctx; > + > + if (!pctx || !*pctx) > + return; > + ctx = *pctx; > + > + if (ctx->filter->close) > + ctx->filter->close(ctx); > + if (ctx->filter->priv_class && ctx->priv_data) > + av_opt_free(ctx->priv_data); > + > + av_opt_free(ctx); > + > + if (ctx->internal) { > + while (ctx->internal->fifo && av_fifo_size(ctx->internal->fifo)) { > + AVPacket *pkt; > + av_fifo_generic_read(ctx->internal->fifo, &pkt, sizeof(pkt), > NULL); > + av_packet_free(&pkt); > + } > + av_fifo_free(ctx->internal->fifo); > + } > + av_freep(&ctx->internal); > + av_freep(&ctx->priv_data); > + > + avcodec_parameters_free(&ctx->par_in); > + avcodec_parameters_free(&ctx->par_out); > + > + av_freep(pctx); > +} > + > +static const AVClass bsf_class = { > + .class_name = "AVBSFContext", > + .item_name = av_default_item_name, > + .version = LIBAVUTIL_VERSION_INT, > +}; > + > +int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx, > + enum AVCodecID codec_id) > +{ > + AVBSFContext *ctx; > + int i, ret; > + > + ctx = av_mallocz(sizeof(*ctx)); > + if (!ctx) > + return AVERROR(ENOMEM); > + > + ctx->av_class = &bsf_class; > + ctx->filter = filter; > + > + /* check that the codec is supported */ > + if (filter->codec_ids) { > + for (i = 0; filter->codec_ids[i] != AV_CODEC_ID_NONE; i++) > + if (codec_id == filter->codec_ids[i]) > + break; > + if (filter->codec_ids[i] == AV_CODEC_ID_NONE) { > + const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id); > + av_log(ctx, AV_LOG_ERROR, "Codec '%s' (%d) is not supported by > the " > + "bitstream filter '%s'. Supported codecs are: ", > + desc ? desc->name : "unknown", codec_id, filter->name); > + for (i = 0; filter->codec_ids[i] != AV_CODEC_ID_NONE; i++) { > + desc = avcodec_descriptor_get(filter->codec_ids[i]); > + av_log(ctx, AV_LOG_ERROR, "%s (%d) ", > + desc ? desc->name : "unknown", filter->codec_ids[i]); > + } > + av_log(ctx, AV_LOG_ERROR, "\n"); > + ret = AVERROR(EINVAL); > + goto fail; > + } > + } > + > + ctx->par_in = avcodec_parameters_alloc(); > + ctx->par_out = avcodec_parameters_alloc(); > + if (!ctx->par_in || !ctx->par_out) { > + ret = AVERROR(ENOMEM); > + goto fail; > + } > + > + ctx->internal = av_mallocz(sizeof(*ctx->internal)); > + if (!ctx->internal) { > + ret = AVERROR(ENOMEM); > + goto fail; > + } > + > + ctx->internal->fifo = av_fifo_alloc(8 * sizeof(AVPacket*)); > + if (!ctx->internal->fifo) { > + ret = AVERROR(ENOMEM); > + goto fail; > + } > + > + av_opt_set_defaults(ctx); > + > + /* allocate priv data and init private options */ > + if (filter->priv_data_size) { > + ctx->priv_data = av_mallocz(filter->priv_data_size); > + if (!ctx->priv_data) { > + ret = AVERROR(ENOMEM); > + goto fail; > + } > + if (filter->priv_class) { > + *(const AVClass **)ctx->priv_data = filter->priv_class; > + av_opt_set_defaults(ctx->priv_data); > + } > + } > + > + *pctx = ctx; > + return 0; > +fail: > + av_bsf_free(&ctx); > + return ret; > +} > + > +int av_bsf_init(AVBSFContext *ctx) > +{ > + int ret; > + > + /* initialize output parameters to be the same as input > + * init below might overwrite that */ > + ret = avcodec_parameters_copy(ctx->par_out, ctx->par_in); > + if (ret < 0) > + return ret; > + > + ctx->time_base_out = ctx->time_base_in; > + > + if (ctx->filter->init) { > + ret = ctx->filter->init(ctx); > + if (ret < 0) > + return ret; > + } > + > + return 0; > +} > + > +int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt) > +{ > + AVPacket *pkt_internal; > + > + if (!pkt || !pkt->data) { > + ctx->internal->eof = 1; > + return 0; > + } > + > + if (ctx->internal->eof) { > + av_log(ctx, AV_LOG_ERROR, "A non-NULL packet sent after an EOF.\n"); > + return AVERROR(EINVAL); > + } > + > + if (av_fifo_space(ctx->internal->fifo) < sizeof(pkt)) { > + int ret = av_fifo_realloc2(ctx->internal->fifo, > + av_fifo_size(ctx->internal->fifo) + 8 * > sizeof(pkt)); > + if (ret < 0) > + return ret; > + } > + > + pkt_internal = av_packet_alloc(); > + if (!pkt_internal) > + return AVERROR(ENOMEM); > + > + av_packet_move_ref(pkt_internal, pkt); > + av_fifo_generic_write(ctx->internal->fifo, &pkt_internal, > sizeof(pkt_internal), NULL); > + > + return 0; > +} > + > +int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt) > +{ > + return ctx->filter->filter(ctx, pkt); > +} > + > +int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt) > +{ > + AVBSFInternal *in = ctx->internal; > + > + if (in->eof) > + return AVERROR_EOF; > + > + if (av_fifo_size(in->fifo) < sizeof(*pkt)) > + return AVERROR(EAGAIN); > + > + av_fifo_generic_read(in->fifo, pkt, sizeof(*pkt), NULL); > + > + return 0; > +} > diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h > new file mode 100644 > index 0000000..cb18a05 > --- /dev/null > +++ b/libavcodec/bsf.h > @@ -0,0 +1,31 @@ > +/* > + * This file is part of Libav. > + * > + * Libav is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * Libav is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with Libav; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + */ > + > +#ifndef AVCODEC_BSF_H > +#define AVCODEC_BSF_H > + > +#include "avcodec.h" > + > +/** > + * Called by the biststream filters to get the next packet for filtering. > + * The filter is responsible for either freeing the packet or passing it to > the > + * caller. > + */ > +int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt); > + > +#endif /* AVCODEC_BSF_H */ > diff --git a/libavcodec/version.h b/libavcodec/version.h > index d247c09..59a0d40 100644 > --- a/libavcodec/version.h > +++ b/libavcodec/version.h > @@ -197,5 +197,8 @@ > #ifndef FF_API_PRIVATE_OPT > #define FF_API_PRIVATE_OPT (LIBAVCODEC_VERSION_MAJOR < 59) > #endif > +#ifndef FF_API_OLD_BSF > +#define FF_API_OLD_BSF (LIBAVCODEC_VERSION_MAJOR < 59) > +#endif > > #endif /* AVCODEC_VERSION_H */ >
Fine. _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel