Deprecate the current bitstream filtering API.
---
configure | 2 +-
libavcodec/Makefile | 2 +
libavcodec/avcodec.h | 194 ++++++++++++++++++++++++++++++++--
libavcodec/bitstream_filters.c | 72 +++++++++++++
libavcodec/bsf.c | 230 +++++++++++++++++++++++++++++++++++++++++
libavcodec/bsf.h | 33 ++++++
libavcodec/version.h | 3 +
7 files changed, 527 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..9143992 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -4692,35 +4692,213 @@ 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;
+
+/**
+ * The bitstream filter state.
+ *
+ * This struct should be allocated with av_bsf_alloc() and freed with
+ * av_bsf_free().
+ */
+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;
+ /**
+ * 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.
+ *
+ * @return 0 on success, a negative AVERROR code on failure
+ */
+int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx);
+
+/**
+ * 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.
+ * This parameter may be NULL, which signals the end of the stream (i.e. no
more
+ * packets will be sent). That will cause the filter to output any packets it
+ * may have buffered internally.
+ *
+ * @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.
+ * This parameter should be "clean" (i.e. freshly allocated
+ * with av_packet_alloc() or unreffed with av_packet_unref())
+ * when this function is called. If this function returns
+ * successfully, the contents of pkt will be completely
+ * overwritten by the returned data. On failure, pkt is not
+ * touched.
+ *
+ * @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
sending
+ * a packet with av_bsf_send_packet(), this function needs to be called
+ * repeatedly until it stops returning 0. It is also possible for a filter to
+ * output fewer packets than were sent to it, so this function may return
+ * AVERROR(EAGAIN) immediately after a successful av_bsf_send_packet() call.
+ */
+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);
+
+/**
+ * Get the AVClass for AVBSFContext. It can be used in combination with
+ * AV_OPT_SEARCH_FAKE_OBJ for examining options.
+ *
+ * @see av_opt_find().
+ */
+const AVClass *av_bsf_get_class(void);
/* memory */
diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c
new file mode 100644
index 0000000..28d028d
--- /dev/null
+++ b/libavcodec/bitstream_filters.c
@@ -0,0 +1,72 @@
+/*
+ * 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 "libavutil/log.h"
+
+#include "avcodec.h"
+#include "bsf.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;
+}
+
+const AVClass *ff_bsf_child_class_next(const AVClass *prev)
+{
+ int i;
+
+ /* find the protocol that corresponds to prev */
+ for (i = 0; prev && bitstream_filters[i]; i++) {
+ if (bitstream_filters[i]->priv_class == prev) {
+ i++;
+ break;
+ }
+ }
+
+ /* find next protocol with priv options */
+ for (; bitstream_filters[i]; i++)
+ if (bitstream_filters[i]->priv_class)
+ return bitstream_filters[i]->priv_class;
+ return NULL;
+}
diff --git a/libavcodec/bsf.c b/libavcodec/bsf.c
new file mode 100644
index 0000000..5e625e6
--- /dev/null
+++ b/libavcodec/bsf.c
@@ -0,0 +1,230 @@
+/*
+ * 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 void *bsf_child_next(void *obj, void *prev)
+{
+ AVBSFContext *ctx = obj;
+ if (!prev && ctx->filter->priv_class)
+ return ctx->priv_data;
+ return NULL;
+}
+
+static const AVClass bsf_class = {
+ .class_name = "AVBSFContext",
+ .item_name = av_default_item_name,
+ .version = LIBAVUTIL_VERSION_INT,
+ .child_next = bsf_child_next,
+ .child_class_next = ff_bsf_child_class_next,
+};
+
+const AVClass *av_bsf_get_class(void)
+{
+ return &bsf_class;
+}
+
+int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx)
+{
+ AVBSFContext *ctx;
+ int ret;
+
+ ctx = av_mallocz(sizeof(*ctx));
+ if (!ctx)
+ return AVERROR(ENOMEM);
+
+ ctx->av_class = &bsf_class;
+ ctx->filter = filter;
+
+ 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, i;
+
+ /* check that the codec is supported */
+ if (ctx->filter->codec_ids) {
+ for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++)
+ if (ctx->par_in->codec_id == ctx->filter->codec_ids[i])
+ break;
+ if (ctx->filter->codec_ids[i] == AV_CODEC_ID_NONE) {
+ const AVCodecDescriptor *desc =
avcodec_descriptor_get(ctx->par_in->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", ctx->par_in->codec_id,
ctx->filter->name);
+ for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++) {
+ desc = avcodec_descriptor_get(ctx->filter->codec_ids[i]);
+ av_log(ctx, AV_LOG_ERROR, "%s (%d) ",
+ desc ? desc->name : "unknown",
ctx->filter->codec_ids[i]);
+ }
+ av_log(ctx, AV_LOG_ERROR, "\n");
+ return AVERROR(EINVAL);
+ }
+ }
+
+ /* 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..9e05f0b
--- /dev/null
+++ b/libavcodec/bsf.h
@@ -0,0 +1,33 @@
+/*
+ * 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);
+
+const AVClass *ff_bsf_child_class_next(const AVClass *prev);
+
+#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 */
--
2.0.0
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel