Deprecate the current bitstream filtering API.
---
 configure                      |   2 +-
 libavcodec/Makefile            |   2 +
 libavcodec/avcodec.h           | 202 +++++++++++++++++++++++++++++++++++--
 libavcodec/bitstream_filters.c |  72 ++++++++++++++
 libavcodec/bsf.c               | 219 +++++++++++++++++++++++++++++++++++++++++
 libavcodec/bsf.h               |  33 +++++++
 libavcodec/version.h           |   3 +
 7 files changed, 524 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..0ff31a0 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -4692,35 +4692,221 @@ 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 must be allocated with av_bsf_alloc() and freed with
+ * av_bsf_free().
+ *
+ * The fields in the struct will only be changed (by the caller or by the
+ * filter) as described in their documentation, and are to be considered
+ * immutable otherwise.
+ */
+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.
+ *
+ * After sending each packet, the filter must be completely drained by calling
+ * av_bsf_receive_packet() repeatedly until it returns AVERROR(EAGAIN) or
+ * AVERROR_EOF.
+ *
+ * @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..4a546af
--- /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 filter that corresponds to prev */
+    for (i = 0; prev && bitstream_filters[i]; i++) {
+        if (bitstream_filters[i]->priv_class == prev) {
+            i++;
+            break;
+        }
+    }
+
+    /* find next filter 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..284c7c8
--- /dev/null
+++ b/libavcodec/bsf.c
@@ -0,0 +1,219 @@
+/*
+ * 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/log.h"
+#include "libavutil/mem.h"
+#include "libavutil/opt.h"
+
+#include "avcodec.h"
+#include "bsf.h"
+
+struct AVBSFInternal {
+    AVPacket *buffer_pkt;
+    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);
+
+    av_packet_free(&ctx->internal->buffer_pkt);
+    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->buffer_pkt = av_packet_alloc();
+    if (!ctx->internal->buffer_pkt) {
+        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)
+{
+    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 (ctx->internal->buffer_pkt->data ||
+        ctx->internal->buffer_pkt->side_data_elems)
+        return AVERROR(EAGAIN);
+
+    av_packet_move_ref(ctx->internal->buffer_pkt, pkt);
+
+    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;
+    AVPacket *tmp_pkt;
+
+    if (in->eof)
+        return AVERROR_EOF;
+
+    if (!ctx->internal->buffer_pkt->data &&
+        !ctx->internal->buffer_pkt->side_data_elems)
+        return AVERROR(EAGAIN);
+
+    tmp_pkt = av_packet_alloc();
+    if (!tmp_pkt)
+        return AVERROR(ENOMEM);
+
+    *pkt = ctx->internal->buffer_pkt;
+    ctx->internal->buffer_pkt = tmp_pkt;
+
+    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

Reply via email to