[FFmpeg-cvslog] Merge commit '33d18982fa03feb061c8f744a4f0a9175c1f63ab'

Derek Buitenhuis git at videolan.org
Sun Apr 17 19:48:56 CEST 2016


ffmpeg | branch: master | Derek Buitenhuis <derek.buitenhuis at gmail.com> | Sun Apr 17 18:47:25 2016 +0100| [af9cac1be1750ecc0e12c6788a3aeed1f1a778be] | committer: Derek Buitenhuis

Merge commit '33d18982fa03feb061c8f744a4f0a9175c1f63ab'

* commit '33d18982fa03feb061c8f744a4f0a9175c1f63ab':
  lavc: add a new bitstream filtering API

Conversions-by: Hendrik Leppkes <h.leppkes at gmail.com>
Conversions-by: Derek Buitenguis <derek.buitenhuis at gmail.com>
Merged-by: Derek Buitenhuis <derek.buitenhuis at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=af9cac1be1750ecc0e12c6788a3aeed1f1a778be
---

 configure                              |    2 +-
 doc/APIchanges                         |    4 +
 libavcodec/Makefile                    |    2 +
 libavcodec/aac_adtstoasc_bsf.c         |  100 +++++++++-----
 libavcodec/allcodecs.c                 |   25 ----
 libavcodec/avcodec.h                   |  197 +++++++++++++++++++++++++++-
 libavcodec/bitstream_filter.c          |  155 ++++++++++++++++------
 libavcodec/bitstream_filters.c         |  137 ++++++++++++++++++++
 libavcodec/bsf.c                       |  219 +++++++++++++++++++++++++++++++
 libavcodec/bsf.h                       |   33 +++++
 libavcodec/chomp_bsf.c                 |   24 ++--
 libavcodec/dca_core_bsf.c              |   36 +++---
 libavcodec/dump_extradata_bsf.c        |   93 +++++++++----
 libavcodec/h264_mp4toannexb_bsf.c      |  222 ++++++++++++++++----------------
 libavcodec/hevc_mp4toannexb_bsf.c      |  151 ++++++++++------------
 libavcodec/imx_dump_header_bsf.c       |   62 +++++----
 libavcodec/mjpeg2jpeg_bsf.c            |   75 +++++++----
 libavcodec/mjpega_dump_header_bsf.c    |  105 ++++++++-------
 libavcodec/movsub_bsf.c                |   86 +++++++++----
 libavcodec/mp3_header_decompress_bsf.c |   73 +++++++----
 libavcodec/mpeg4_unpack_bframes_bsf.c  |  131 +++++++++----------
 libavcodec/noise_bsf.c                 |   70 +++++++---
 libavcodec/remove_extradata_bsf.c      |  109 ++++++++++++----
 libavcodec/version.h                   |    7 +-
 libavcodec/vp9_superframe_bsf.c        |  120 +++++++++--------
 libavformat/mux.c                      |    6 +
 26 files changed, 1591 insertions(+), 653 deletions(-)

diff --git a/configure b/configure
index f981a4e..993f352 100755
--- a/configure
+++ b/configure
@@ -3204,7 +3204,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)
@@ -3218,6 +3217,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/doc/APIchanges b/doc/APIchanges
index 33bd02e..8a14e77 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,6 +15,10 @@ libavutil:     2015-08-28
 
 API changes, most recent first:
 
+2016-xx-xx - xxxxxxx - lavc 57.15.0 - avcodec.h
+  Add a new bitstream filtering API working with AVPackets.
+  Deprecate the old bistream filtering API.
+
 2016-xx-xx - xxxxxxx - lavfi 6.42.0 - avfilter.h
   Add AVFilterContext.hw_device_ctx.
 
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index ec41446..6a2450e 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -26,6 +26,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/aac_adtstoasc_bsf.c b/libavcodec/aac_adtstoasc_bsf.c
index 9c117c6..48889fc 100644
--- a/libavcodec/aac_adtstoasc_bsf.c
+++ b/libavcodec/aac_adtstoasc_bsf.c
@@ -21,6 +21,7 @@
 
 #include "avcodec.h"
 #include "aacadtsdec.h"
+#include "bsf.h"
 #include "put_bits.h"
 #include "get_bits.h"
 #include "mpeg4audio.h"
@@ -34,68 +35,75 @@ typedef struct AACBSFContext {
  * This filter creates an MPEG-4 AudioSpecificConfig from an MPEG-2/4
  * ADTS header and removes the ADTS header.
  */
-static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc,
-                                AVCodecContext *avctx, const char *args,
-                                uint8_t  **poutbuf, int *poutbuf_size,
-                                const uint8_t *buf, int      buf_size,
-                                int keyframe)
+static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out)
 {
+    AACBSFContext *ctx = bsfc->priv_data;
+
     GetBitContext gb;
     PutBitContext pb;
     AACADTSHeaderInfo hdr;
+    AVPacket *in;
+    int ret;
 
-    AACBSFContext *ctx = bsfc->priv_data;
+    ret = ff_bsf_get_packet(bsfc, &in);
+    if (ret < 0)
+        return ret;
 
-    init_get_bits(&gb, buf, AAC_ADTS_HEADER_SIZE*8);
+    if (in->size < AAC_ADTS_HEADER_SIZE)
+        goto packet_too_small;
 
-    *poutbuf = (uint8_t*) buf;
-    *poutbuf_size = buf_size;
+    init_get_bits(&gb, in->data, AAC_ADTS_HEADER_SIZE * 8);
 
-    if (avctx->extradata)
-        if (show_bits(&gb, 12) != 0xfff)
-            return 0;
+    if (bsfc->par_in->extradata && show_bits(&gb, 12) != 0xfff)
+        goto finish;
 
     if (avpriv_aac_parse_header(&gb, &hdr) < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Error parsing ADTS frame header!\n");
-        return AVERROR_INVALIDDATA;
+        av_log(bsfc, AV_LOG_ERROR, "Error parsing ADTS frame header!\n");
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
     }
 
     if (!hdr.crc_absent && hdr.num_aac_frames > 1) {
-        avpriv_report_missing_feature(avctx,
+        avpriv_report_missing_feature(bsfc,
                                       "Multiple RDBs per frame with CRC");
-        return AVERROR_PATCHWELCOME;
+        ret = AVERROR_PATCHWELCOME;
+        goto fail;
     }
 
-    buf      += AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent;
-    buf_size -= AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent;
+    in->size -= AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
+    if (in->size <= 0)
+        goto packet_too_small;
+    in->data += AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
 
     if (!ctx->first_frame_done) {
         int            pce_size = 0;
         uint8_t        pce_data[MAX_PCE_SIZE];
+        uint8_t       *extradata;
+
         if (!hdr.chan_config) {
-            init_get_bits(&gb, buf, buf_size * 8);
+            init_get_bits(&gb, in->data, in->size * 8);
             if (get_bits(&gb, 3) != 5) {
-                avpriv_report_missing_feature(avctx,
+                avpriv_report_missing_feature(bsfc,
                                               "PCE-based channel configuration "
                                               "without PCE as first syntax "
                                               "element");
-                return AVERROR_PATCHWELCOME;
+                ret = AVERROR_PATCHWELCOME;
+                goto fail;
             }
             init_put_bits(&pb, pce_data, MAX_PCE_SIZE);
             pce_size = avpriv_copy_pce_data(&pb, &gb)/8;
             flush_put_bits(&pb);
-            buf_size -= get_bits_count(&gb)/8;
-            buf      += get_bits_count(&gb)/8;
+            in->size -= get_bits_count(&gb)/8;
+            in->data += get_bits_count(&gb)/8;
         }
-        av_free(avctx->extradata);
-        avctx->extradata_size = 2 + pce_size;
-        avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
-        if (!avctx->extradata) {
-            avctx->extradata_size = 0;
-            return AVERROR(ENOMEM);
+
+        extradata = av_mallocz(2 + pce_size + AV_INPUT_BUFFER_PADDING_SIZE);
+        if (!extradata) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
         }
 
-        init_put_bits(&pb, avctx->extradata, avctx->extradata_size);
+        init_put_bits(&pb, extradata, 2 + pce_size);
         put_bits(&pb, 5, hdr.object_type);
         put_bits(&pb, 4, hdr.sampling_index);
         put_bits(&pb, 4, hdr.chan_config);
@@ -104,20 +112,44 @@ static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc,
         put_bits(&pb, 1, 0); //is not extension
         flush_put_bits(&pb);
         if (pce_size) {
-            memcpy(avctx->extradata + 2, pce_data, pce_size);
+            memcpy(extradata + 2, pce_data, pce_size);
         }
 
+        bsfc->par_out->extradata = extradata;
+        bsfc->par_out->extradata_size = 2 + pce_size;
         ctx->first_frame_done = 1;
     }
 
-    *poutbuf = (uint8_t*) buf;
-    *poutbuf_size = buf_size;
+finish:
+    av_packet_move_ref(out, in);
+    av_packet_free(&in);
 
     return 0;
+
+packet_too_small:
+    av_log(bsfc, AV_LOG_ERROR, "Input packet too small\n");
+    ret = AVERROR_INVALIDDATA;
+fail:
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_aac_adtstoasc_bsf = {
+static int aac_adtstoasc_init(AVBSFContext *ctx)
+{
+    av_freep(&ctx->par_out->extradata);
+    ctx->par_out->extradata_size = 0;
+
+    return 0;
+}
+
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_AAC, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_aac_adtstoasc_bsf = {
     .name           = "aac_adtstoasc",
     .priv_data_size = sizeof(AACBSFContext),
+    .init           = aac_adtstoasc_init,
     .filter         = aac_adtstoasc_filter,
+    .codec_ids      = codec_ids,
 };
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 3214e35..f88c0ff 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -58,13 +58,6 @@
             av_register_codec_parser(&ff_##x##_parser);                 \
     }
 
-#define REGISTER_BSF(X, x)                                              \
-    {                                                                   \
-        extern AVBitStreamFilter ff_##x##_bsf;                          \
-        if (CONFIG_##X##_BSF)                                           \
-            av_register_bitstream_filter(&ff_##x##_bsf);                \
-    }
-
 void avcodec_register_all(void)
 {
     static int initialized;
@@ -667,22 +660,4 @@ void avcodec_register_all(void)
     REGISTER_PARSER(VP3,                vp3);
     REGISTER_PARSER(VP8,                vp8);
     REGISTER_PARSER(VP9,                vp9);
-
-    /* bitstream filters */
-    REGISTER_BSF(AAC_ADTSTOASC,         aac_adtstoasc);
-    REGISTER_BSF(CHOMP,                 chomp);
-    REGISTER_BSF(DUMP_EXTRADATA,        dump_extradata);
-    REGISTER_BSF(DCA_CORE,              dca_core);
-    REGISTER_BSF(H264_MP4TOANNEXB,      h264_mp4toannexb);
-    REGISTER_BSF(HEVC_MP4TOANNEXB,      hevc_mp4toannexb);
-    REGISTER_BSF(IMX_DUMP_HEADER,       imx_dump_header);
-    REGISTER_BSF(MJPEG2JPEG,            mjpeg2jpeg);
-    REGISTER_BSF(MJPEGA_DUMP_HEADER,    mjpega_dump_header);
-    REGISTER_BSF(MP3_HEADER_DECOMPRESS, mp3_header_decompress);
-    REGISTER_BSF(MPEG4_UNPACK_BFRAMES,  mpeg4_unpack_bframes);
-    REGISTER_BSF(MOV2TEXTSUB,           mov2textsub);
-    REGISTER_BSF(NOISE,                 noise);
-    REGISTER_BSF(REMOVE_EXTRADATA,      remove_extradata);
-    REGISTER_BSF(TEXT2MOVSUB,           text2movsub);
-    REGISTER_BSF(VP9_SUPERFRAME,        vp9_superframe);
 }
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 784b1c1..9a8a0f0 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -5386,7 +5386,7 @@ 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;
@@ -5398,19 +5398,102 @@ typedef struct AVBitStreamFilterContext {
      */
     char *args;
 } 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
 /**
  * Register a bitstream filter.
  *
@@ -5420,6 +5503,7 @@ typedef struct AVBitStreamFilter {
  *
  * @see avcodec_register_all()
  */
+attribute_deprecated
 void av_register_bitstream_filter(AVBitStreamFilter *bsf);
 
 /**
@@ -5432,6 +5516,7 @@ void av_register_bitstream_filter(AVBitStreamFilter *bsf);
  * @return a bitstream filter context if a matching filter was found
  * and successfully initialized, NULL otherwise
  */
+attribute_deprecated
 AVBitStreamFilterContext *av_bitstream_filter_init(const char *name);
 
 /**
@@ -5463,6 +5548,7 @@ AVBitStreamFilterContext *av_bitstream_filter_init(const char *name);
  * its starting address). A special case is if *poutbuf was set to NULL and
  * *poutbuf_size was set to 0, which indicates the packet should be dropped.
  */
+attribute_deprecated
 int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
                                AVCodecContext *avctx, const char *args,
                                uint8_t **poutbuf, int *poutbuf_size,
@@ -5474,6 +5560,7 @@ int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
  * @param bsf the bitstream filter context created with
  * av_bitstream_filter_init(), can be NULL
  */
+attribute_deprecated
 void av_bitstream_filter_close(AVBitStreamFilterContext *bsf);
 
 /**
@@ -5484,7 +5571,103 @@ void av_bitstream_filter_close(AVBitStreamFilterContext *bsf);
  * This function can be used to iterate over all registered bitstream
  * filters.
  */
+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_filter.c b/libavcodec/bitstream_filter.c
index fb690b6..d9bafbe 100644
--- a/libavcodec/bitstream_filter.c
+++ b/libavcodec/bitstream_filter.c
@@ -22,59 +22,75 @@
 
 #include "avcodec.h"
 #include "libavutil/atomic.h"
+#include "libavutil/internal.h"
 #include "libavutil/mem.h"
 
-static AVBitStreamFilter *first_bitstream_filter = NULL;
+#if FF_API_OLD_BSF
+FF_DISABLE_DEPRECATION_WARNINGS
 
 AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f)
 {
-    if (f)
-        return f->next;
-    else
-        return first_bitstream_filter;
+    const AVBitStreamFilter *filter = NULL;
+    void *opaque = NULL;
+
+    while (filter != f)
+        filter = av_bsf_next(&opaque);
+
+    return av_bsf_next(&opaque);
 }
 
 void av_register_bitstream_filter(AVBitStreamFilter *bsf)
 {
-    do {
-        bsf->next = first_bitstream_filter;
-    } while(bsf->next != avpriv_atomic_ptr_cas((void * volatile *)&first_bitstream_filter, bsf->next, bsf));
 }
 
+typedef struct BSFCompatContext {
+    AVBSFContext *ctx;
+    int extradata_updated;
+} BSFCompatContext;
+
 AVBitStreamFilterContext *av_bitstream_filter_init(const char *name)
 {
-    AVBitStreamFilter *bsf = NULL;
-
-    while (bsf = av_bitstream_filter_next(bsf)) {
-        if (!strcmp(name, bsf->name)) {
-            AVBitStreamFilterContext *bsfc =
-                av_mallocz(sizeof(AVBitStreamFilterContext));
-            if (!bsfc)
-                return NULL;
-            bsfc->filter    = bsf;
-            bsfc->priv_data = NULL;
-            if (bsf->priv_data_size) {
-                bsfc->priv_data = av_mallocz(bsf->priv_data_size);
-                if (!bsfc->priv_data) {
-                    av_freep(&bsfc);
-                    return NULL;
-                }
-            }
-            return bsfc;
-        }
-    }
+    AVBitStreamFilterContext *ctx = NULL;
+    BSFCompatContext         *priv = NULL;
+    const AVBitStreamFilter *bsf;
+
+    bsf = av_bsf_get_by_name(name);
+    if (!bsf)
+        return NULL;
+
+    ctx = av_mallocz(sizeof(*ctx));
+    if (!ctx)
+        return NULL;
+
+    priv = av_mallocz(sizeof(*priv));
+    if (!priv)
+        goto fail;
+
+
+    ctx->filter    = bsf;
+    ctx->priv_data = priv;
+
+    return ctx;
+
+fail:
+    if (priv)
+        av_bsf_free(&priv->ctx);
+    av_freep(&priv);
+    av_freep(&ctx);
     return NULL;
 }
 
 void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc)
 {
+    BSFCompatContext *priv;
+
     if (!bsfc)
         return;
-    if (bsfc->filter->close)
-        bsfc->filter->close(bsfc);
+
+    priv = bsfc->priv_data;
+
+    av_bsf_free(&priv->ctx);
     av_freep(&bsfc->priv_data);
-    av_freep(&bsfc->args);
-    av_parser_close(bsfc->parser);
     av_free(bsfc);
 }
 
@@ -83,8 +99,75 @@ int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
                                uint8_t **poutbuf, int *poutbuf_size,
                                const uint8_t *buf, int buf_size, int keyframe)
 {
-    *poutbuf      = (uint8_t *)buf;
-    *poutbuf_size = buf_size;
-    return bsfc->filter->filter(bsfc, avctx, args ? args : bsfc->args,
-                                poutbuf, poutbuf_size, buf, buf_size, keyframe);
+    BSFCompatContext *priv = bsfc->priv_data;
+    AVPacket pkt = { 0 };
+    int ret;
+
+    if (!priv->ctx) {
+        ret = av_bsf_alloc(bsfc->filter, &priv->ctx);
+        if (ret < 0)
+            return ret;
+
+        ret = avcodec_parameters_from_context(priv->ctx->par_in, avctx);
+        if (ret < 0)
+            return ret;
+
+        priv->ctx->time_base_in = avctx->time_base;
+
+        ret = av_bsf_init(priv->ctx);
+        if (ret < 0)
+            return ret;
+    }
+
+    pkt.data = buf;
+    pkt.size = buf_size;
+
+    ret = av_bsf_send_packet(priv->ctx, &pkt);
+    if (ret < 0)
+        return ret;
+
+    *poutbuf      = NULL;
+    *poutbuf_size = 0;
+
+    ret = av_bsf_receive_packet(priv->ctx, &pkt);
+    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+        return 0;
+    else if (ret < 0)
+        return ret;
+
+    *poutbuf = av_malloc(pkt.size + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!*poutbuf) {
+        av_packet_unref(&pkt);
+        return AVERROR(ENOMEM);
+    }
+
+    *poutbuf_size = pkt.size;
+    memcpy(*poutbuf, pkt.data, pkt.size);
+
+    av_packet_unref(&pkt);
+
+    /* drain all the remaining packets we cannot return */
+    while (ret >= 0) {
+        ret = av_bsf_receive_packet(priv->ctx, &pkt);
+        av_packet_unref(&pkt);
+    }
+
+    if (!priv->extradata_updated) {
+        /* update extradata in avctx from the output codec parameters */
+        if (priv->ctx->par_out->extradata_size && (!args || !strstr(args, "private_spspps_buf"))) {
+            av_freep(&avctx->extradata);
+            avctx->extradata_size = 0;
+            avctx->extradata = av_mallocz(priv->ctx->par_out->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+            if (!avctx->extradata)
+                return AVERROR(ENOMEM);
+            memcpy(avctx->extradata, priv->ctx->par_out->extradata, priv->ctx->par_out->extradata_size);
+            avctx->extradata_size = priv->ctx->par_out->extradata_size;
+        }
+
+        priv->extradata_updated = 1;
+    }
+
+    return 1;
 }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c
new file mode 100644
index 0000000..51f3cd9
--- /dev/null
+++ b/libavcodec/bitstream_filters.c
@@ -0,0 +1,137 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; 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"
+
+extern const AVBitStreamFilter ff_aac_adtstoasc_bsf;
+extern const AVBitStreamFilter ff_chomp_bsf;
+extern const AVBitStreamFilter ff_dump_extradata_bsf;
+extern const AVBitStreamFilter ff_dca_core_bsf;
+extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf;
+extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf;
+extern const AVBitStreamFilter ff_imx_dump_header_bsf;
+extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf;
+extern const AVBitStreamFilter ff_mjpega_dump_header_bsf;
+extern const AVBitStreamFilter ff_mp3_header_decompress_bsf;
+extern const AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf;
+extern const AVBitStreamFilter ff_mov2textsub_bsf;
+extern const AVBitStreamFilter ff_noise_bsf;
+extern const AVBitStreamFilter ff_remove_extradata_bsf;
+extern const AVBitStreamFilter ff_text2movsub_bsf;
+extern const AVBitStreamFilter ff_vp9_superframe_bsf;
+
+static const AVBitStreamFilter *bitstream_filters[] = {
+#if CONFIG_AAC_ADTSTOASC_BSF
+    &ff_aac_adtstoasc_bsf,
+#endif
+#if CONFIG_CHOMP_BSF
+    &ff_chomp_bsf,
+#endif
+#if CONFIG_DUMP_EXTRADATA_BSF
+    &ff_dump_extradata_bsf,
+#endif
+#if CONFIG_DCA_CORE_BSF
+    &ff_dca_core_bsf,
+#endif
+#if CONFIG_H264_MP4TOANNEXB_BSF
+    &ff_h264_mp4toannexb_bsf,
+#endif
+#if CONFIG_HEVC_MP4TOANNEXB_BSF
+    &ff_hevc_mp4toannexb_bsf,
+#endif
+#if CONFIG_IMX_DUMP_HEADER_BSF
+    &ff_imx_dump_header_bsf,
+#endif
+#if CONFIG_MJPEG2JPEG_BSF
+    &ff_mjpeg2jpeg_bsf,
+#endif
+#if CONFIG_MJPEGA_DUMP_HEADER_BSF
+    &ff_mjpega_dump_header_bsf,
+#endif
+#if CONFIG_MP3_HEADER_DECOMPRESS_BSF
+    &ff_mp3_header_decompress_bsf,
+#endif
+#if CONFIG_MPEG4_UNPACK_BFRAMES_BSF
+    &ff_mpeg4_unpack_bframes_bsf,
+#endif
+#if CONFIG_MOV2TEXTSUB_BSF
+    &ff_mov2textsub_bsf,
+#endif
+#if CONFIG_NOISE_BSF
+    &ff_noise_bsf,
+#endif
+#if CONFIG_REMOVE_EXTRADATA_BSF
+    &ff_remove_extradata_bsf,
+#endif
+#if CONFIG_TEXT2MOVSUB_BSF
+    &ff_text2movsub_bsf,
+#endif
+#if CONFIG_VP9_SUPERFRAME_BSF
+    &ff_vp9_superframe_bsf,
+#endif
+    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..88b7f29
--- /dev/null
+++ b/libavcodec/bsf.c
@@ -0,0 +1,219 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; 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..0ca64a7
--- /dev/null
+++ b/libavcodec/bsf.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; 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/chomp_bsf.c b/libavcodec/chomp_bsf.c
index 2b93fa9..cc94380 100644
--- a/libavcodec/chomp_bsf.c
+++ b/libavcodec/chomp_bsf.c
@@ -20,19 +20,23 @@
  */
 
 #include "avcodec.h"
+#include "bsf.h"
 #include "internal.h"
 
-static int chomp_filter(AVBitStreamFilterContext *bsfc,
-                        AVCodecContext *avctx, const char *args,
-                        uint8_t  **poutbuf, int *poutbuf_size,
-                        const uint8_t *buf, int      buf_size,
-                        int keyframe)
+static int chomp_filter(AVBSFContext *ctx, AVPacket *out)
 {
-    while (buf_size > 0 && !buf[buf_size-1])
-        buf_size--;
+    AVPacket *in;
+    int ret;
 
-    *poutbuf = (uint8_t*) buf;
-    *poutbuf_size = buf_size;
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    while (in->size > 0 && !in->data[in->size - 1])
+        in->size--;
+
+    av_packet_move_ref(out, in);
+    av_packet_free(&in);
 
     return 0;
 }
@@ -40,7 +44,7 @@ static int chomp_filter(AVBitStreamFilterContext *bsfc,
 /**
  * This filter removes a string of NULL bytes from the end of a packet.
  */
-AVBitStreamFilter ff_chomp_bsf = {
+const AVBitStreamFilter ff_chomp_bsf = {
     .name   = "chomp",
     .filter = chomp_filter,
 };
diff --git a/libavcodec/dca_core_bsf.c b/libavcodec/dca_core_bsf.c
index 7d37236..9edc0cf 100644
--- a/libavcodec/dca_core_bsf.c
+++ b/libavcodec/dca_core_bsf.c
@@ -19,21 +19,23 @@
  */
 
 #include "avcodec.h"
+#include "bsf.h"
 #include "bytestream.h"
 #include "dca_syncwords.h"
 #include "libavutil/mem.h"
 
-static int dca_core(AVBitStreamFilterContext *bsfc,
-                    AVCodecContext *avctx, const char *args,
-                    uint8_t **poutbuf, int *poutbuf_size,
-                    const uint8_t *buf, int buf_size,
-                    int keyframe)
+static int dca_core_filter(AVBSFContext *ctx, AVPacket *out)
 {
+    AVPacket *in;
     GetByteContext gb;
     uint32_t syncword;
-    int core_size = 0;
+    int core_size = 0, ret;
 
-    bytestream2_init(&gb, buf, buf_size);
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    bytestream2_init(&gb, in->data, in->size);
     syncword = bytestream2_get_be32(&gb);
     bytestream2_skip(&gb, 1);
 
@@ -43,18 +45,22 @@ static int dca_core(AVBitStreamFilterContext *bsfc,
         break;
     }
 
-    *poutbuf = (uint8_t *)buf;
+    av_packet_move_ref(out, in);
+    av_packet_free(&in);
 
-    if (core_size > 0 && core_size <= buf_size) {
-        *poutbuf_size = core_size;
-    } else {
-        *poutbuf_size = buf_size;
+    if (core_size > 0 && core_size <= out->size) {
+        out->size = core_size;
     }
 
     return 0;
 }
 
-AVBitStreamFilter ff_dca_core_bsf = {
-    .name   = "dca_core",
-    .filter = dca_core,
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_DTS, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_dca_core_bsf = {
+    .name      = "dca_core",
+    .filter    = dca_core_filter,
+    .codec_ids = codec_ids,
 };
diff --git a/libavcodec/dump_extradata_bsf.c b/libavcodec/dump_extradata_bsf.c
index 08c4227..1f91e21 100644
--- a/libavcodec/dump_extradata_bsf.c
+++ b/libavcodec/dump_extradata_bsf.c
@@ -21,34 +21,81 @@
 #include <string.h>
 
 #include "avcodec.h"
+#include "bsf.h"
+
+#include "libavutil/log.h"
 #include "libavutil/mem.h"
+#include "libavutil/opt.h"
+
+enum DumpFreq {
+    DUMP_FREQ_KEYFRAME,
+    DUMP_FREQ_ALL,
+};
+
+typedef struct DumpExtradataContext {
+    const AVClass *class;
+    int freq;
+} DumpExtradataContext;
+
+static int dump_extradata(AVBSFContext *ctx, AVPacket *out)
+{
+    DumpExtradataContext *s = ctx->priv_data;
+    AVPacket *in;
+    int ret = 0;
+
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    if (ctx->par_in->extradata &&
+        (s->freq == DUMP_FREQ_ALL ||
+         (s->freq == DUMP_FREQ_KEYFRAME && in->flags & AV_PKT_FLAG_KEY))) {
+        if (in->size >= INT_MAX - ctx->par_in->extradata_size) {
+            ret = AVERROR(ERANGE);
+            goto fail;
+        }
 
+        ret = av_new_packet(out, in->size + ctx->par_in->extradata_size);
+        if (ret < 0)
+            goto fail;
 
-static int dump_extradata(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                     uint8_t **poutbuf, int *poutbuf_size,
-                     const uint8_t *buf, int buf_size, int keyframe){
-    int cmd= args ? *args : 0;
-    /* cast to avoid warning about discarding qualifiers */
-    if(avctx->extradata){
-        if(  (keyframe && (avctx->flags2 & AV_CODEC_FLAG2_LOCAL_HEADER) && cmd == 'a')
-           ||(keyframe && (cmd=='k' || !cmd))
-           ||(cmd=='e')
-            /*||(? && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_BEGIN)*/){
-            int size= buf_size + avctx->extradata_size;
-            *poutbuf_size= size;
-            *poutbuf= av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!*poutbuf)
-                return AVERROR(ENOMEM);
-
-            memcpy(*poutbuf, avctx->extradata, avctx->extradata_size);
-            memcpy((*poutbuf) + avctx->extradata_size, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
-            return 1;
+        ret = av_packet_copy_props(out, in);
+        if (ret < 0) {
+            av_packet_unref(out);
+            goto fail;
         }
+
+        memcpy(out->data, ctx->par_in->extradata, ctx->par_in->extradata_size);
+        memcpy(out->data + ctx->par_in->extradata_size, in->data, in->size);
+    } else {
+        av_packet_move_ref(out, in);
     }
-    return 0;
+
+fail:
+    av_packet_free(&in);
+
+    return ret;
 }
 
-AVBitStreamFilter ff_dump_extradata_bsf={
-    .name   = "dump_extra",
-    .filter = dump_extradata,
+#define OFFSET(x) offsetof(DumpExtradataContext, x)
+static const AVOption options[] = {
+    { "freq", "When do dump extradata", OFFSET(freq), AV_OPT_TYPE_INT,
+        { .i64 = DUMP_FREQ_KEYFRAME }, DUMP_FREQ_KEYFRAME, DUMP_FREQ_ALL, 0, "freq" },
+        { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_KEYFRAME }, .unit = "freq" },
+        { "all",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_ALL      }, .unit = "freq" },
+    { NULL },
+};
+
+static const AVClass dump_extradata_class = {
+    .class_name = "dump_extradata bsf",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_MAJOR,
+};
+
+const AVBitStreamFilter ff_dump_extradata_bsf = {
+    .name           = "dump_extra",
+    .priv_data_size = sizeof(DumpExtradataContext),
+    .priv_class     = &dump_extradata_class,
+    .filter         = dump_extradata,
 };
diff --git a/libavcodec/h264_mp4toannexb_bsf.c b/libavcodec/h264_mp4toannexb_bsf.c
index 2d447f7..828bf18 100644
--- a/libavcodec/h264_mp4toannexb_bsf.c
+++ b/libavcodec/h264_mp4toannexb_bsf.c
@@ -23,7 +23,9 @@
 
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mem.h"
+
 #include "avcodec.h"
+#include "bsf.h"
 
 typedef struct H264BSFContext {
     int32_t  sps_offset;
@@ -33,66 +35,53 @@ typedef struct H264BSFContext {
     uint8_t  idr_sps_seen;
     uint8_t  idr_pps_seen;
     int      extradata_parsed;
-
-    /* When private_spspps is zero then spspps_buf points to global extradata
-       and bsf does replace a global extradata to own-allocated version (default
-       behaviour).
-       When private_spspps is non-zero the bsf uses a private version of spspps buf.
-       This mode necessary when bsf uses in decoder, else bsf has issues after
-       decoder re-initialization. Use the "private_spspps_buf" argument to
-       activate this mode.
-     */
-    int      private_spspps;
-    uint8_t *spspps_buf;
-    uint32_t spspps_size;
 } H264BSFContext;
 
-static int alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size,
+static int alloc_and_copy(AVPacket *out,
                           const uint8_t *sps_pps, uint32_t sps_pps_size,
                           const uint8_t *in, uint32_t in_size)
 {
-    uint32_t offset         = *poutbuf_size;
+    uint32_t offset         = out->size;
     uint8_t nal_header_size = offset ? 3 : 4;
     int err;
 
-    *poutbuf_size += sps_pps_size + in_size + nal_header_size;
-    if ((err = av_reallocp(poutbuf,
-                           *poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
-        *poutbuf_size = 0;
+    err = av_grow_packet(out, sps_pps_size + in_size + nal_header_size);
+    if (err < 0)
         return err;
-    }
+
     if (sps_pps)
-        memcpy(*poutbuf + offset, sps_pps, sps_pps_size);
-    memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size);
+        memcpy(out->data + offset, sps_pps, sps_pps_size);
+    memcpy(out->data + sps_pps_size + nal_header_size + offset, in, in_size);
     if (!offset) {
-        AV_WB32(*poutbuf + sps_pps_size, 1);
+        AV_WB32(out->data + sps_pps_size, 1);
     } else {
-        (*poutbuf + offset + sps_pps_size)[0] =
-        (*poutbuf + offset + sps_pps_size)[1] = 0;
-        (*poutbuf + offset + sps_pps_size)[2] = 1;
+        (out->data + offset + sps_pps_size)[0] =
+        (out->data + offset + sps_pps_size)[1] = 0;
+        (out->data + offset + sps_pps_size)[2] = 1;
     }
 
     return 0;
 }
 
-static int h264_extradata_to_annexb(H264BSFContext *ctx, AVCodecContext *avctx, const int padding)
+static int h264_extradata_to_annexb(AVBSFContext *ctx, const int padding)
 {
+    H264BSFContext *s = ctx->priv_data;
     uint16_t unit_size;
     uint64_t total_size                 = 0;
     uint8_t *out                        = NULL, unit_nb, sps_done = 0,
              sps_seen                   = 0, pps_seen = 0;
-    const uint8_t *extradata            = avctx->extradata + 4;
+    const uint8_t *extradata            = ctx->par_in->extradata + 4;
     static const uint8_t nalu_header[4] = { 0, 0, 0, 1 };
     int length_size = (*extradata++ & 0x3) + 1; // retrieve length coded size
 
-    ctx->sps_offset = ctx->pps_offset = -1;
+    s->sps_offset = s->pps_offset = -1;
 
     /* retrieve sps and pps unit(s) */
     unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */
     if (!unit_nb) {
         goto pps;
     } else {
-        ctx->sps_offset = 0;
+        s->sps_offset = 0;
         sps_seen = 1;
     }
 
@@ -102,13 +91,13 @@ static int h264_extradata_to_annexb(H264BSFContext *ctx, AVCodecContext *avctx,
         unit_size   = AV_RB16(extradata);
         total_size += unit_size + 4;
         if (total_size > INT_MAX - padding) {
-            av_log(avctx, AV_LOG_ERROR,
+            av_log(ctx, AV_LOG_ERROR,
                    "Too big extradata size, corrupted stream or invalid MP4/AVCC bitstream\n");
             av_free(out);
             return AVERROR(EINVAL);
         }
-        if (extradata + 2 + unit_size > avctx->extradata + avctx->extradata_size) {
-            av_log(avctx, AV_LOG_ERROR, "Packet header is not contained in global extradata, "
+        if (extradata + 2 + unit_size > ctx->par_in->extradata + ctx->par_in->extradata_size) {
+            av_log(ctx, AV_LOG_ERROR, "Packet header is not contained in global extradata, "
                    "corrupted stream or invalid MP4/AVCC bitstream\n");
             av_free(out);
             return AVERROR(EINVAL);
@@ -122,7 +111,7 @@ pps:
         if (!unit_nb && !sps_done++) {
             unit_nb = *extradata++; /* number of pps unit(s) */
             if (unit_nb) {
-                ctx->pps_offset = total_size;
+                s->pps_offset = total_size;
                 pps_seen = 1;
             }
         }
@@ -132,93 +121,100 @@ pps:
         memset(out + total_size, 0, padding);
 
     if (!sps_seen)
-        av_log(avctx, AV_LOG_WARNING,
+        av_log(ctx, AV_LOG_WARNING,
                "Warning: SPS NALU missing or invalid. "
                "The resulting stream may not play.\n");
 
     if (!pps_seen)
-        av_log(avctx, AV_LOG_WARNING,
+        av_log(ctx, AV_LOG_WARNING,
                "Warning: PPS NALU missing or invalid. "
                "The resulting stream may not play.\n");
 
-    if (!ctx->private_spspps) {
-        av_free(avctx->extradata);
-        avctx->extradata      = out;
-        avctx->extradata_size = total_size;
-    }
-    ctx->spspps_buf  = out;
-    ctx->spspps_size = total_size;
+    av_freep(&ctx->par_out->extradata);
+    ctx->par_out->extradata      = out;
+    ctx->par_out->extradata_size = total_size;
 
     return length_size;
 }
 
-static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
-                                   AVCodecContext *avctx, const char *args,
-                                   uint8_t **poutbuf, int *poutbuf_size,
-                                   const uint8_t *buf, int buf_size,
-                                   int keyframe)
+static int h264_mp4toannexb_init(AVBSFContext *ctx)
 {
-    H264BSFContext *ctx = bsfc->priv_data;
-    int i;
+    H264BSFContext *s = ctx->priv_data;
+    int ret;
+
+    /* retrieve sps and pps NAL units from extradata */
+    if (ctx->par_in->extradata_size >= 6) {
+        ret = h264_extradata_to_annexb(ctx, AV_INPUT_BUFFER_PADDING_SIZE);
+        if (ret < 0)
+            return ret;
+
+        s->length_size      = ret;
+        s->new_idr          = 1;
+        s->idr_sps_seen     = 0;
+        s->idr_pps_seen     = 0;
+        s->extradata_parsed = 1;
+    }
+
+    return 0;
+}
+
+static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
+{
+    H264BSFContext *s = ctx->priv_data;
+
+    AVPacket *in;
     uint8_t unit_type;
     int32_t nal_size;
     uint32_t cumul_size    = 0;
-    const uint8_t *buf_end = buf + buf_size;
-    int ret = 0;
+    const uint8_t *buf;
+    const uint8_t *buf_end;
+    int            buf_size;
+    int ret = 0, i;
+
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
 
     /* nothing to filter */
-    if (!avctx->extradata || avctx->extradata_size < 6) {
-        *poutbuf      = (uint8_t *)buf;
-        *poutbuf_size = buf_size;
+    if (!s->extradata_parsed) {
+        av_packet_move_ref(out, in);
+        av_packet_free(&in);
         return 0;
     }
 
-    /* retrieve sps and pps NAL units from extradata */
-    if (!ctx->extradata_parsed) {
-        if (args && strstr(args, "private_spspps_buf"))
-            ctx->private_spspps = 1;
+    buf      = in->data;
+    buf_size = in->size;
+    buf_end  = in->data + in->size;
 
-        ret = h264_extradata_to_annexb(ctx, avctx, AV_INPUT_BUFFER_PADDING_SIZE);
-        if (ret < 0)
-            return ret;
-        ctx->length_size      = ret;
-        ctx->new_idr          = 1;
-        ctx->idr_sps_seen     = 0;
-        ctx->idr_pps_seen     = 0;
-        ctx->extradata_parsed = 1;
-    }
-
-    *poutbuf_size = 0;
-    *poutbuf      = NULL;
     do {
         ret= AVERROR(EINVAL);
-        if (buf + ctx->length_size > buf_end)
+        if (buf + s->length_size > buf_end)
             goto fail;
 
-        for (nal_size = 0, i = 0; i<ctx->length_size; i++)
+        for (nal_size = 0, i = 0; i<s->length_size; i++)
             nal_size = (nal_size << 8) | buf[i];
 
-        buf      += ctx->length_size;
+        buf += s->length_size;
         unit_type = *buf & 0x1f;
 
         if (nal_size > buf_end - buf || nal_size < 0)
             goto fail;
 
         if (unit_type == 7)
-            ctx->idr_sps_seen = ctx->new_idr = 1;
+            s->idr_sps_seen = s->new_idr = 1;
         else if (unit_type == 8) {
-            ctx->idr_pps_seen = ctx->new_idr = 1;
+            s->idr_pps_seen = s->new_idr = 1;
             /* if SPS has not been seen yet, prepend the AVCC one to PPS */
-            if (!ctx->idr_sps_seen) {
-                if (ctx->sps_offset == -1)
-                    av_log(avctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n");
+            if (!s->idr_sps_seen) {
+                if (s->sps_offset == -1)
+                    av_log(ctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n");
                 else {
-                    if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
-                                         ctx->spspps_buf + ctx->sps_offset,
-                                         ctx->pps_offset != -1 ? ctx->pps_offset : ctx->spspps_size - ctx->sps_offset,
+                    if ((ret = alloc_and_copy(out,
+                                         ctx->par_out->extradata + s->sps_offset,
+                                         s->pps_offset != -1 ? s->pps_offset : ctx->par_out->extradata_size - s->sps_offset,
                                          buf, nal_size)) < 0)
                         goto fail;
-                    ctx->idr_sps_seen = 1;
+                    s->idr_sps_seen = 1;
                     goto next_nal;
                 }
             }
@@ -227,61 +223,61 @@ static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
         /* if this is a new IDR picture following an IDR picture, reset the idr flag.
          * Just check first_mb_in_slice to be 0 as this is the simplest solution.
          * This could be checking idr_pic_id instead, but would complexify the parsing. */
-        if (!ctx->new_idr && unit_type == 5 && (buf[1] & 0x80))
-            ctx->new_idr = 1;
+        if (!s->new_idr && unit_type == 5 && (buf[1] & 0x80))
+            s->new_idr = 1;
 
         /* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */
-        if (ctx->new_idr && unit_type == 5 && !ctx->idr_sps_seen && !ctx->idr_pps_seen) {
-            if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
-                               ctx->spspps_buf, ctx->spspps_size,
+        if (s->new_idr && unit_type == 5 && !s->idr_sps_seen && !s->idr_pps_seen) {
+            if ((ret=alloc_and_copy(out,
+                               ctx->par_out->extradata, ctx->par_out->extradata_size,
                                buf, nal_size)) < 0)
                 goto fail;
-            ctx->new_idr = 0;
+            s->new_idr = 0;
         /* if only SPS has been seen, also insert PPS */
-        } else if (ctx->new_idr && unit_type == 5 && ctx->idr_sps_seen && !ctx->idr_pps_seen) {
-            if (ctx->pps_offset == -1) {
-                av_log(avctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n");
-                if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
-                                     NULL, 0, buf, nal_size)) < 0)
+        } else if (s->new_idr && unit_type == 5 && s->idr_sps_seen && !s->idr_pps_seen) {
+            if (s->pps_offset == -1) {
+                av_log(ctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n");
+                if ((ret = alloc_and_copy(out, NULL, 0, buf, nal_size)) < 0)
                     goto fail;
-            } else if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
-                                        ctx->spspps_buf + ctx->pps_offset, ctx->spspps_size - ctx->pps_offset,
+            } else if ((ret = alloc_and_copy(out,
+                                        ctx->par_out->extradata + s->pps_offset, ctx->par_out->extradata_size - s->pps_offset,
                                         buf, nal_size)) < 0)
                 goto fail;
         } else {
-            if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
-                               NULL, 0, buf, nal_size)) < 0)
+            if ((ret=alloc_and_copy(out, NULL, 0, buf, nal_size)) < 0)
                 goto fail;
-            if (!ctx->new_idr && unit_type == 1) {
-                ctx->new_idr = 1;
-                ctx->idr_sps_seen = 0;
-                ctx->idr_pps_seen = 0;
+            if (!s->new_idr && unit_type == 1) {
+                s->new_idr = 1;
+                s->idr_sps_seen = 0;
+                s->idr_pps_seen = 0;
             }
         }
 
 next_nal:
         buf        += nal_size;
-        cumul_size += nal_size + ctx->length_size;
+        cumul_size += nal_size + s->length_size;
     } while (cumul_size < buf_size);
 
-    return 1;
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
 
 fail:
-    av_freep(poutbuf);
-    *poutbuf_size = 0;
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+
     return ret;
 }
 
-static void h264_mp4toannexb_filter_close(AVBitStreamFilterContext *bsfc)
-{
-    H264BSFContext *ctx = bsfc->priv_data;
-    if (ctx->private_spspps)
-        av_freep(&ctx->spspps_buf);
-}
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_H264, AV_CODEC_ID_NONE,
+};
 
-AVBitStreamFilter ff_h264_mp4toannexb_bsf = {
+const AVBitStreamFilter ff_h264_mp4toannexb_bsf = {
     .name           = "h264_mp4toannexb",
     .priv_data_size = sizeof(H264BSFContext),
+    .init           = h264_mp4toannexb_init,
     .filter         = h264_mp4toannexb_filter,
-    .close          = h264_mp4toannexb_filter_close,
+    .codec_ids      = codec_ids,
 };
diff --git a/libavcodec/hevc_mp4toannexb_bsf.c b/libavcodec/hevc_mp4toannexb_bsf.c
index d6feb99..5cc642b 100644
--- a/libavcodec/hevc_mp4toannexb_bsf.c
+++ b/libavcodec/hevc_mp4toannexb_bsf.c
@@ -25,6 +25,7 @@
 #include "libavutil/mem.h"
 
 #include "avcodec.h"
+#include "bsf.h"
 #include "bytestream.h"
 #include "hevc.h"
 
@@ -33,23 +34,9 @@
 typedef struct HEVCBSFContext {
     uint8_t  length_size;
     int      extradata_parsed;
-
-    int logged_nonmp4_warning;
-
-    /* When private_spspps is zero then spspps_buf points to global extradata
-       and bsf does replace a global extradata to own-allocated version (default
-       behaviour).
-       When private_spspps is non-zero the bsf uses a private version of spspps buf.
-       This mode necessary when bsf uses in decoder, else bsf has issues after
-       decoder re-initialization. Use the "private_spspps_buf" argument to
-       activate this mode.
-     */
-    int      private_spspps;
-    uint8_t *spspps_buf;
-    uint32_t spspps_size;
 } HEVCBSFContext;
 
-static int hevc_extradata_to_annexb(HEVCBSFContext* ctx, AVCodecContext *avctx)
+static int hevc_extradata_to_annexb(AVBSFContext *ctx)
 {
     GetByteContext gb;
     int length_size, num_arrays, i, j;
@@ -58,7 +45,7 @@ static int hevc_extradata_to_annexb(HEVCBSFContext* ctx, AVCodecContext *avctx)
     uint8_t *new_extradata = NULL;
     size_t   new_extradata_size = 0;
 
-    bytestream2_init(&gb, avctx->extradata, avctx->extradata_size);
+    bytestream2_init(&gb, ctx->par_in->extradata, ctx->par_in->extradata_size);
 
     bytestream2_skip(&gb, 21);
     length_size = (bytestream2_get_byte(&gb) & 3) + 1;
@@ -70,7 +57,7 @@ static int hevc_extradata_to_annexb(HEVCBSFContext* ctx, AVCodecContext *avctx)
 
         if (!(type == NAL_VPS || type == NAL_SPS || type == NAL_PPS ||
               type == NAL_SEI_PREFIX || type == NAL_SEI_SUFFIX)) {
-            av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n",
+            av_log(ctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n",
                    type);
             ret = AVERROR_INVALIDDATA;
             goto fail;
@@ -94,16 +81,12 @@ static int hevc_extradata_to_annexb(HEVCBSFContext* ctx, AVCodecContext *avctx)
         }
     }
 
-    if (!ctx->private_spspps) {
-        av_freep(&avctx->extradata);
-        avctx->extradata      = new_extradata;
-        avctx->extradata_size = new_extradata_size;
-    }
-    ctx->spspps_buf  = new_extradata;
-    ctx->spspps_size = new_extradata_size;
+    av_freep(&ctx->par_out->extradata);
+    ctx->par_out->extradata      = new_extradata;
+    ctx->par_out->extradata_size = new_extradata_size;
 
     if (!new_extradata_size)
-        av_log(avctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
+        av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
 
     return length_size;
 fail:
@@ -111,54 +94,54 @@ fail:
     return ret;
 }
 
-static int hevc_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
-                                   AVCodecContext *avctx, const char *args,
-                                   uint8_t **poutbuf, int *poutbuf_size,
-                                   const uint8_t *buf, int buf_size,
-                                   int keyframe)
+static int hevc_mp4toannexb_init(AVBSFContext *ctx)
+{
+    HEVCBSFContext *s = ctx->priv_data;
+    int ret;
+
+    if (ctx->par_in->extradata_size < MIN_HEVCC_LENGTH ||
+        AV_RB24(ctx->par_in->extradata) == 1           ||
+        AV_RB32(ctx->par_in->extradata) == 1) {
+        av_log(ctx, AV_LOG_VERBOSE,
+               "The input looks like it is Annex B already\n");
+    } else {
+        ret = hevc_extradata_to_annexb(ctx);
+        if (ret < 0)
+            return ret;
+        s->length_size      = ret;
+        s->extradata_parsed = 1;
+    }
+
+    return 0;
+}
+
+static int hevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
 {
-    HEVCBSFContext *ctx = bsfc->priv_data;
+    HEVCBSFContext *s = ctx->priv_data;
+    AVPacket *in;
     GetByteContext gb;
 
-    uint8_t *out = NULL;
-    size_t   out_size = 0;
     int got_irap = 0;
     int i, ret = 0;
 
-    if (!ctx->extradata_parsed) {
-        if (avctx->extradata_size < MIN_HEVCC_LENGTH ||
-            AV_RB24(avctx->extradata) == 1           ||
-            AV_RB32(avctx->extradata) == 1) {
-            if (!ctx->logged_nonmp4_warning) {
-                av_log(avctx, AV_LOG_VERBOSE,
-                       "The input looks like it is Annex B already\n");
-                ctx->logged_nonmp4_warning = 1;
-            }
-            *poutbuf      = (uint8_t *)buf;
-            *poutbuf_size = buf_size;
-            return 0;
-        }
-        if (args && strstr(args, "private_spspps_buf"))
-            ctx->private_spspps = 1;
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
 
-        ret = hevc_extradata_to_annexb(ctx, avctx);
-        if (ret < 0)
-            return ret;
-        ctx->length_size      = ret;
-        ctx->extradata_parsed = 1;
+    if (!s->extradata_parsed) {
+        av_packet_move_ref(out, in);
+        av_packet_free(&in);
+        return 0;
     }
 
-    *poutbuf_size = 0;
-    *poutbuf      = NULL;
-
-    bytestream2_init(&gb, buf, buf_size);
+    bytestream2_init(&gb, in->data, in->size);
 
     while (bytestream2_get_bytes_left(&gb)) {
         uint32_t nalu_size = 0;
         int      nalu_type;
-        int is_irap, add_extradata, extra_size;
+        int is_irap, add_extradata, extra_size, prev_size;
 
-        for (i = 0; i < ctx->length_size; i++)
+        for (i = 0; i < s->length_size; i++)
             nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb);
 
         nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f;
@@ -166,47 +149,47 @@ static int hevc_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
         /* prepend extradata to IRAP frames */
         is_irap       = nalu_type >= 16 && nalu_type <= 23;
         add_extradata = is_irap && !got_irap;
-        extra_size    = add_extradata * ctx->spspps_size;
+        extra_size    = add_extradata * ctx->par_out->extradata_size;
         got_irap     |= is_irap;
 
-        if (SIZE_MAX - out_size < 4             ||
-            SIZE_MAX - out_size - 4 < nalu_size ||
-            SIZE_MAX - out_size - 4 - nalu_size < extra_size) {
+        if (SIZE_MAX - nalu_size < 4 ||
+            SIZE_MAX - 4 - nalu_size < extra_size) {
             ret = AVERROR_INVALIDDATA;
             goto fail;
         }
 
-        ret = av_reallocp(&out, out_size + 4 + nalu_size + extra_size);
+        prev_size = out->size;
+
+        ret = av_grow_packet(out, 4 + nalu_size + extra_size);
         if (ret < 0)
             goto fail;
 
         if (add_extradata)
-            memcpy(out + out_size, ctx->spspps_buf, extra_size);
-        AV_WB32(out + out_size + extra_size, 1);
-        bytestream2_get_buffer(&gb, out + out_size + 4 + extra_size, nalu_size);
-        out_size += 4 + nalu_size + extra_size;
+            memcpy(out->data + prev_size, ctx->par_out->extradata, extra_size);
+        AV_WB32(out->data + prev_size + extra_size, 1);
+        bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size, nalu_size);
     }
 
-    *poutbuf      = out;
-    *poutbuf_size = out_size;
-
-    return 1;
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
 
 fail:
-    av_freep(&out);
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+
     return ret;
 }
 
-static void hevc_mp4toannexb_close(AVBitStreamFilterContext *bsfc)
-{
-    HEVCBSFContext *ctx = bsfc->priv_data;
-    if (ctx->private_spspps)
-        av_freep(&ctx->spspps_buf);
-}
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_HEVC, AV_CODEC_ID_NONE,
+};
 
-AVBitStreamFilter ff_hevc_mp4toannexb_bsf = {
-    "hevc_mp4toannexb",
-    sizeof(HEVCBSFContext),
-    hevc_mp4toannexb_filter,
-    hevc_mp4toannexb_close,
+const AVBitStreamFilter ff_hevc_mp4toannexb_bsf = {
+    .name           = "hevc_mp4toannexb",
+    .priv_data_size = sizeof(HEVCBSFContext),
+    .init           = hevc_mp4toannexb_init,
+    .filter         = hevc_mp4toannexb_filter,
+    .codec_ids      = codec_ids,
 };
diff --git a/libavcodec/imx_dump_header_bsf.c b/libavcodec/imx_dump_header_bsf.c
index 3a69e98..9a9de05 100644
--- a/libavcodec/imx_dump_header_bsf.c
+++ b/libavcodec/imx_dump_header_bsf.c
@@ -26,35 +26,51 @@
  */
 
 #include "avcodec.h"
+#include "bsf.h"
 #include "bytestream.h"
 
 
-static int imx_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                           uint8_t **poutbuf, int *poutbuf_size,
-                           const uint8_t *buf, int buf_size, int keyframe)
+static int imx_dump_header(AVBSFContext *ctx, AVPacket *out)
 {
     /* MXF essence element key */
     static const uint8_t imx_header[16] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x05,0x01,0x01,0x00 };
-    uint8_t *poutbufp;
-
-    if (avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO) {
-        av_log(avctx, AV_LOG_ERROR, "imx bitstream filter only applies to mpeg2video codec\n");
-        return 0;
-    }
-
-    *poutbuf = av_malloc(buf_size + 20 + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!*poutbuf)
-        return AVERROR(ENOMEM);
-    poutbufp = *poutbuf;
-    bytestream_put_buffer(&poutbufp, imx_header, 16);
-    bytestream_put_byte(&poutbufp, 0x83); /* KLV BER long form */
-    bytestream_put_be24(&poutbufp, buf_size);
-    bytestream_put_buffer(&poutbufp, buf, buf_size);
-    *poutbuf_size = poutbufp - *poutbuf;
-    return 1;
+
+    AVPacket *in;
+    int ret = 0;
+    uint8_t *out_buf;
+
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    ret = av_new_packet(out, in->size + 20);
+    if (ret < 0)
+        goto fail;
+
+    out_buf = out->data;
+
+    bytestream_put_buffer(&out_buf, imx_header, 16);
+    bytestream_put_byte(&out_buf, 0x83); /* KLV BER long form */
+    bytestream_put_be24(&out_buf, in->size);
+    bytestream_put_buffer(&out_buf, in->data, in->size);
+
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
+
+fail:
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_imx_dump_header_bsf = {
-    .name   = "imxdump",
-    .filter = imx_dump_header,
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_imx_dump_header_bsf = {
+    .name      = "imxdump",
+    .filter    = imx_dump_header,
+    .codec_ids = codec_ids,
 };
diff --git a/libavcodec/mjpeg2jpeg_bsf.c b/libavcodec/mjpeg2jpeg_bsf.c
index 92dc3ca..2d4cee2 100644
--- a/libavcodec/mjpeg2jpeg_bsf.c
+++ b/libavcodec/mjpeg2jpeg_bsf.c
@@ -31,6 +31,7 @@
 #include "libavutil/intreadwrite.h"
 
 #include "avcodec.h"
+#include "bsf.h"
 #include "jpegtables.h"
 #include "mjpeg.h"
 
@@ -77,46 +78,64 @@ static uint8_t *append_dht_segment(uint8_t *buf)
     return buf;
 }
 
-static int mjpeg2jpeg_filter(AVBitStreamFilterContext *bsfc,
-                             AVCodecContext *avctx, const char *args,
-                             uint8_t **poutbuf, int *poutbuf_size,
-                             const uint8_t *buf, int buf_size,
-                             int keyframe)
+static int mjpeg2jpeg_filter(AVBSFContext *ctx, AVPacket *out)
 {
+    AVPacket *in;
+    int ret = 0;
     int input_skip, output_size;
-    uint8_t *output, *out;
+    uint8_t *output;
 
-    if (buf_size < 12) {
-        av_log(avctx, AV_LOG_ERROR, "input is truncated\n");
-        return AVERROR_INVALIDDATA;
+    ret = ff_bsf_get_packet(ctx, &in);
+
+    if (in->size < 12) {
+        av_log(ctx, AV_LOG_ERROR, "input is truncated\n");
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
     }
-    if (AV_RB16(buf) != 0xffd8) {
-        av_log(avctx, AV_LOG_ERROR, "input is not MJPEG\n");
-        return AVERROR_INVALIDDATA;
+    if (AV_RB16(in->data) != 0xffd8) {
+        av_log(ctx, AV_LOG_ERROR, "input is not MJPEG\n");
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
     }
-    if (buf[2] == 0xff && buf[3] == APP0) {
-        input_skip = (buf[4] << 8) + buf[5] + 4;
+    if (in->data[2] == 0xff && in->data[3] == APP0) {
+        input_skip = (in->data[4] << 8) + in->data[5] + 4;
     } else {
         input_skip = 2;
     }
-    if (buf_size < input_skip) {
-        av_log(avctx, AV_LOG_ERROR, "input is truncated\n");
-        return AVERROR_INVALIDDATA;
+    if (in->size < input_skip) {
+        av_log(ctx, AV_LOG_ERROR, "input is truncated\n");
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
     }
-    output_size = buf_size - input_skip +
+    output_size = in->size - input_skip +
                   sizeof(jpeg_header) + dht_segment_size;
-    output = out = av_malloc(output_size);
-    if (!output)
-        return AVERROR(ENOMEM);
-    out = append(out, jpeg_header, sizeof(jpeg_header));
-    out = append_dht_segment(out);
-    out = append(out, buf + input_skip, buf_size - input_skip);
-    *poutbuf = output;
-    *poutbuf_size = output_size;
-    return 1;
+    ret = av_new_packet(out, output_size);
+    if (ret < 0)
+        goto fail;
+
+    output = out->data;
+
+    output = append(output, jpeg_header, sizeof(jpeg_header));
+    output = append_dht_segment(output);
+    output = append(output, in->data + input_skip, in->size - input_skip);
+
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
+
+fail:
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_mjpeg2jpeg_bsf = {
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_MJPEG, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_mjpeg2jpeg_bsf = {
     .name           = "mjpeg2jpeg",
     .filter         = mjpeg2jpeg_filter,
+    .codec_ids      = codec_ids,
 };
diff --git a/libavcodec/mjpega_dump_header_bsf.c b/libavcodec/mjpega_dump_header_bsf.c
index d6d41e6..ca5fb3a 100644
--- a/libavcodec/mjpega_dump_header_bsf.c
+++ b/libavcodec/mjpega_dump_header_bsf.c
@@ -26,70 +26,83 @@
  */
 
 #include "avcodec.h"
+#include "bsf.h"
 #include "bytestream.h"
 #include "mjpeg.h"
 
 
-static int mjpega_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                              uint8_t **poutbuf, int *poutbuf_size,
-                              const uint8_t *buf, int buf_size, int keyframe)
+static int mjpega_dump_header(AVBSFContext *ctx, AVPacket *out)
 {
-    uint8_t *poutbufp;
+    AVPacket *in;
+    uint8_t *out_buf;
     unsigned dqt = 0, dht = 0, sof0 = 0;
-    int i;
+    int ret = 0, i;
 
-    if (avctx->codec_id != AV_CODEC_ID_MJPEG) {
-        av_log(avctx, AV_LOG_ERROR, "mjpega bitstream filter only applies to mjpeg codec\n");
-        return 0;
-    }
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    ret = av_new_packet(out, in->size + 44);
+    if (ret < 0)
+        goto fail;
+
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
 
-    *poutbuf_size = 0;
-    *poutbuf = av_malloc(buf_size + 44 + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!*poutbuf)
-        return AVERROR(ENOMEM);
-    poutbufp = *poutbuf;
-    bytestream_put_byte(&poutbufp, 0xff);
-    bytestream_put_byte(&poutbufp, SOI);
-    bytestream_put_byte(&poutbufp, 0xff);
-    bytestream_put_byte(&poutbufp, APP1);
-    bytestream_put_be16(&poutbufp, 42); /* size */
-    bytestream_put_be32(&poutbufp, 0);
-    bytestream_put_buffer(&poutbufp, "mjpg", 4);
-    bytestream_put_be32(&poutbufp, buf_size + 44); /* field size */
-    bytestream_put_be32(&poutbufp, buf_size + 44); /* pad field size */
-    bytestream_put_be32(&poutbufp, 0);             /* next ptr */
+    out_buf = out->data;
+    bytestream_put_byte(&out_buf, 0xff);
+    bytestream_put_byte(&out_buf, SOI);
+    bytestream_put_byte(&out_buf, 0xff);
+    bytestream_put_byte(&out_buf, APP1);
+    bytestream_put_be16(&out_buf, 42); /* size */
+    bytestream_put_be32(&out_buf, 0);
+    bytestream_put_buffer(&out_buf, "mjpg", 4);
+    bytestream_put_be32(&out_buf, in->size + 44); /* field size */
+    bytestream_put_be32(&out_buf, in->size + 44); /* pad field size */
+    bytestream_put_be32(&out_buf, 0);             /* next ptr */
 
-    for (i = 0; i < buf_size - 1; i++) {
-        if (buf[i] == 0xff) {
-            switch (buf[i + 1]) {
+    for (i = 0; i < in->size - 1; i++) {
+        if (in->data[i] == 0xff) {
+            switch (in->data[i + 1]) {
             case DQT:  dqt  = i + 46; break;
             case DHT:  dht  = i + 46; break;
             case SOF0: sof0 = i + 46; break;
             case SOS:
-                bytestream_put_be32(&poutbufp, dqt); /* quant off */
-                bytestream_put_be32(&poutbufp, dht); /* huff off */
-                bytestream_put_be32(&poutbufp, sof0); /* image off */
-                bytestream_put_be32(&poutbufp, i + 46); /* scan off */
-                bytestream_put_be32(&poutbufp, i + 46 + AV_RB16(buf + i + 2)); /* data off */
-                bytestream_put_buffer(&poutbufp, buf + 2, buf_size - 2); /* skip already written SOI */
-                *poutbuf_size = poutbufp - *poutbuf;
-                return 1;
+                bytestream_put_be32(&out_buf, dqt); /* quant off */
+                bytestream_put_be32(&out_buf, dht); /* huff off */
+                bytestream_put_be32(&out_buf, sof0); /* image off */
+                bytestream_put_be32(&out_buf, i + 46); /* scan off */
+                bytestream_put_be32(&out_buf, i + 46 + AV_RB16(in->data + i + 2)); /* data off */
+                bytestream_put_buffer(&out_buf, in->data + 2, in->size - 2); /* skip already written SOI */
+
+                out->size = out_buf - out->data;
+                av_packet_free(&in);
+                return 0;
             case APP1:
-                if (i + 8 < buf_size && AV_RL32(buf + i + 8) == AV_RL32("mjpg")) {
-                    av_log(avctx, AV_LOG_ERROR, "bitstream already formatted\n");
-                    memcpy(*poutbuf, buf, buf_size);
-                    *poutbuf_size = buf_size;
-                    return 1;
+                if (i + 8 < in->size && AV_RL32(in->data + i + 8) == AV_RL32("mjpg")) {
+                    av_log(ctx, AV_LOG_ERROR, "bitstream already formatted\n");
+                    av_packet_unref(out);
+                    av_packet_move_ref(out, in);
+                    av_packet_free(&in);
+                    return 0;
                 }
             }
         }
     }
-    av_freep(poutbuf);
-    av_log(avctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n");
-    return 0;
+    av_log(ctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n");
+fail:
+    av_packet_unref(out);
+    av_packet_free(&in);
+    return AVERROR_INVALIDDATA;
 }
 
-AVBitStreamFilter ff_mjpega_dump_header_bsf = {
-    .name   = "mjpegadump",
-    .filter = mjpega_dump_header,
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_MJPEG, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_mjpega_dump_header_bsf = {
+    .name      = "mjpegadump",
+    .filter    = mjpega_dump_header,
+    .codec_ids = codec_ids,
 };
diff --git a/libavcodec/movsub_bsf.c b/libavcodec/movsub_bsf.c
index 8ee7a3a..3cb1183 100644
--- a/libavcodec/movsub_bsf.c
+++ b/libavcodec/movsub_bsf.c
@@ -21,39 +21,79 @@
 #include "libavutil/common.h"
 #include "libavutil/intreadwrite.h"
 #include "avcodec.h"
+#include "bsf.h"
 
+static int text2movsub(AVBSFContext *ctx, AVPacket *out)
+{
+    AVPacket *in;
+    int ret = 0;
 
-static int text2movsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                     uint8_t **poutbuf, int *poutbuf_size,
-                     const uint8_t *buf, int buf_size, int keyframe){
-    if (buf_size > 0xffff) return 0;
-    *poutbuf_size = buf_size + 2;
-    *poutbuf = av_malloc(*poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!*poutbuf)
-        return AVERROR(ENOMEM);
-    AV_WB16(*poutbuf, buf_size);
-    memcpy(*poutbuf + 2, buf, buf_size);
-    return 1;
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    if (in->size > 0xffff) {
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
+    }
+
+    ret = av_new_packet(out, in->size + 2);
+    if (ret < 0) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
+
+    AV_WB16(out->data, in->size);
+    memcpy(out->data + 2, in->data, in->size);
+
+fail:
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_text2movsub_bsf={
+const AVBitStreamFilter ff_text2movsub_bsf = {
     .name   = "text2movsub",
     .filter = text2movsub,
 };
 
-static int mov2textsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                     uint8_t **poutbuf, int *poutbuf_size,
-                     const uint8_t *buf, int buf_size, int keyframe){
-    if (buf_size < 2) return 0;
-    *poutbuf_size = FFMIN(buf_size - 2, AV_RB16(buf));
-    *poutbuf = av_malloc(*poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!*poutbuf)
-        return AVERROR(ENOMEM);
-    memcpy(*poutbuf, buf + 2, *poutbuf_size);
-    return 1;
+static int mov2textsub(AVBSFContext *ctx, AVPacket *out)
+{
+    AVPacket *in;
+    int ret = 0;
+
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    if (in->size < 2) {
+       ret = AVERROR_INVALIDDATA;
+       goto fail;
+    }
+
+    ret = av_new_packet(out, FFMIN(in->size - 2, AV_RB16(in->data)));
+    if (ret < 0)
+        goto fail;
+
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
+
+    memcpy(out->data, in->data + 2, out->size);
+
+fail:
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_mov2textsub_bsf={
+const AVBitStreamFilter ff_mov2textsub_bsf = {
     .name   = "mov2textsub",
     .filter = mov2textsub,
 };
diff --git a/libavcodec/mp3_header_decompress_bsf.c b/libavcodec/mp3_header_decompress_bsf.c
index 95c0b5b..22c1ef0 100644
--- a/libavcodec/mp3_header_decompress_bsf.c
+++ b/libavcodec/mp3_header_decompress_bsf.c
@@ -21,32 +21,43 @@
 #include "libavutil/common.h"
 #include "libavutil/intreadwrite.h"
 #include "avcodec.h"
+#include "bsf.h"
 #include "mpegaudiodecheader.h"
 #include "mpegaudiodata.h"
 
 
-static int mp3_header_decompress(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                     uint8_t **poutbuf, int *poutbuf_size,
-                     const uint8_t *buf, int buf_size, int keyframe){
+static int mp3_header_decompress(AVBSFContext *ctx, AVPacket *out)
+{
+    AVPacket *in;
     uint32_t header;
-    int sample_rate= avctx->sample_rate;
+    int sample_rate= ctx->par_in->sample_rate;
     int sample_rate_index=0;
-    int lsf, mpeg25, bitrate_index, frame_size;
+    int lsf, mpeg25, bitrate_index, frame_size, ret;
+    uint8_t *buf;
+    int buf_size;
+
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    buf      = in->data;
+    buf_size = in->size;
 
     header = AV_RB32(buf);
     if(ff_mpa_check_header(header) >= 0){
-        *poutbuf= (uint8_t *) buf;
-        *poutbuf_size= buf_size;
+        av_packet_move_ref(out, in);
+        av_packet_free(&in);
 
         return 0;
     }
 
-    if(avctx->extradata_size != 15 || strcmp(avctx->extradata, "FFCMP3 0.0")){
-        av_log(avctx, AV_LOG_ERROR, "Extradata invalid %d\n", avctx->extradata_size);
-        return -1;
+    if(ctx->par_in->extradata_size != 15 || strcmp(ctx->par_in->extradata, "FFCMP3 0.0")){
+        av_log(ctx, AV_LOG_ERROR, "Extradata invalid %d\n", ctx->par_in->extradata_size);
+        ret = AVERROR(EINVAL);
+        goto fail;
     }
 
-    header= AV_RB32(avctx->extradata+11) & MP3_MASK;
+    header= AV_RB32(ctx->par_in->extradata+11) & MP3_MASK;
 
     lsf     = sample_rate < (24000+32000)/2;
     mpeg25  = sample_rate < (12000+16000)/2;
@@ -62,20 +73,27 @@ static int mp3_header_decompress(AVBitStreamFilterContext *bsfc, AVCodecContext
             break;
     }
     if(bitrate_index == 30){
-        av_log(avctx, AV_LOG_ERROR, "Could not find bitrate_index.\n");
-        return -1;
+        av_log(ctx, AV_LOG_ERROR, "Could not find bitrate_index.\n");
+        ret = AVERROR(EINVAL);
+        goto fail;
     }
 
     header |= (bitrate_index&1)<<9;
     header |= (bitrate_index>>1)<<12;
     header |= (frame_size == buf_size + 4)<<16; //FIXME actually set a correct crc instead of 0
 
-    *poutbuf_size= frame_size;
-    *poutbuf= av_malloc(frame_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    memcpy(*poutbuf + frame_size - buf_size, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
+    ret = av_new_packet(out, frame_size);
+    if (ret < 0)
+        goto fail;
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0) {
+        av_packet_free(&out);
+        goto fail;
+    }
+    memcpy(out->data + frame_size - buf_size, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
 
-    if(avctx->channels==2){
-        uint8_t *p= *poutbuf + frame_size - buf_size;
+    if(ctx->par_in->channels==2){
+        uint8_t *p= out->data + frame_size - buf_size;
         if(lsf){
             FFSWAP(int, p[1], p[2]);
             header |= (p[1] & 0xC0)>>2;
@@ -86,12 +104,21 @@ static int mp3_header_decompress(AVBitStreamFilterContext *bsfc, AVCodecContext
         }
     }
 
-    AV_WB32(*poutbuf, header);
+    AV_WB32(out->data, header);
 
-    return 1;
+    ret = 0;
+
+fail:
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_mp3_header_decompress_bsf={
-    .name   = "mp3decomp",
-    .filter = mp3_header_decompress,
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_MP3, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_mp3_header_decompress_bsf = {
+    .name      = "mp3decomp",
+    .filter    = mp3_header_decompress,
+    .codec_ids = codec_ids,
 };
diff --git a/libavcodec/mpeg4_unpack_bframes_bsf.c b/libavcodec/mpeg4_unpack_bframes_bsf.c
index df49d3f..0615621 100644
--- a/libavcodec/mpeg4_unpack_bframes_bsf.c
+++ b/libavcodec/mpeg4_unpack_bframes_bsf.c
@@ -20,12 +20,12 @@
  */
 
 #include "avcodec.h"
+#include "bsf.h"
 #include "mpeg4video.h"
 
 typedef struct UnpackBFramesBSFContext {
     uint8_t *b_frame_buf;
     int      b_frame_buf_size;
-    int      updated_extradata;
 } UnpackBFramesBSFContext;
 
 /* search next start code */
@@ -83,112 +83,109 @@ static uint8_t *create_new_buffer(const uint8_t *src, int size) {
     return dst;
 }
 
-static int mpeg4_unpack_bframes_filter(AVBitStreamFilterContext *bsfc,
-                                       AVCodecContext *avctx, const char *args,
-                                       uint8_t  **poutbuf, int *poutbuf_size,
-                                       const uint8_t *buf, int      buf_size,
-                                       int keyframe)
+static int mpeg4_unpack_bframes_filter(AVBSFContext *ctx, AVPacket *out)
 {
-    UnpackBFramesBSFContext *ctx = bsfc->priv_data;
+    UnpackBFramesBSFContext *s = ctx->priv_data;
     int pos_p = -1, nb_vop = 0, pos_vop2 = -1, ret = 0;
+    AVPacket *in;
 
-    if (avctx->codec_id != AV_CODEC_ID_MPEG4) {
-        av_log(avctx, AV_LOG_ERROR,
-               "The mpeg4_unpack_bframes bitstream filter is only useful for mpeg4.\n");
-        return AVERROR(EINVAL);
-    }
-
-    if (!ctx->updated_extradata && avctx->extradata) {
-        int pos_p_ext = -1;
-        scan_buffer(avctx->extradata, avctx->extradata_size, &pos_p_ext, NULL, NULL);
-        if (pos_p_ext >= 0) {
-            av_log(avctx, AV_LOG_DEBUG,
-                   "Updating DivX userdata (remove trailing 'p') in extradata.\n");
-            avctx->extradata[pos_p_ext] = '\0';
-        }
-        ctx->updated_extradata = 1;
-    }
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
 
-    scan_buffer(buf, buf_size, &pos_p, &nb_vop, &pos_vop2);
-    av_log(avctx, AV_LOG_DEBUG, "Found %d VOP startcode(s) in this packet.\n", nb_vop);
+    scan_buffer(in->data, in->size, &pos_p, &nb_vop, &pos_vop2);
+    av_log(ctx, AV_LOG_DEBUG, "Found %d VOP startcode(s) in this packet.\n", nb_vop);
 
     if (pos_vop2 >= 0) {
-        if (ctx->b_frame_buf) {
-            av_log(avctx, AV_LOG_WARNING,
+        if (s->b_frame_buf) {
+            av_log(ctx, AV_LOG_WARNING,
                    "Missing one N-VOP packet, discarding one B-frame.\n");
-            av_freep(&ctx->b_frame_buf);
-            ctx->b_frame_buf_size = 0;
+            av_freep(&s->b_frame_buf);
+            s->b_frame_buf_size = 0;
         }
         /* store the packed B-frame in the BSFContext */
-        ctx->b_frame_buf_size = buf_size - pos_vop2;
-        ctx->b_frame_buf      = create_new_buffer(buf + pos_vop2, ctx->b_frame_buf_size);
-        if (!ctx->b_frame_buf) {
-            ctx->b_frame_buf_size = 0;
+        s->b_frame_buf_size = in->size - pos_vop2;
+        s->b_frame_buf      = create_new_buffer(in->data + pos_vop2, s->b_frame_buf_size);
+        if (!s->b_frame_buf) {
+            s->b_frame_buf_size = 0;
+            av_packet_free(&in);
             return AVERROR(ENOMEM);
         }
     }
 
     if (nb_vop > 2) {
-        av_log(avctx, AV_LOG_WARNING,
+        av_log(ctx, AV_LOG_WARNING,
        "Found %d VOP headers in one packet, only unpacking one.\n", nb_vop);
     }
 
-    if (nb_vop == 1 && ctx->b_frame_buf) {
+    if (nb_vop == 1 && s->b_frame_buf) {
         /* use frame from BSFContext */
-        *poutbuf      = ctx->b_frame_buf;
-        *poutbuf_size = ctx->b_frame_buf_size;
-        /* the output buffer is distinct from the input buffer */
-        ret = 1;
-        if (buf_size <= MAX_NVOP_SIZE) {
+        av_packet_from_data(out, s->b_frame_buf, s->b_frame_buf_size);
+        if (in->size <= MAX_NVOP_SIZE) {
             /* N-VOP */
-            av_log(avctx, AV_LOG_DEBUG, "Skipping N-VOP.\n");
-            ctx->b_frame_buf      = NULL;
-            ctx->b_frame_buf_size = 0;
+            av_log(ctx, AV_LOG_DEBUG, "Skipping N-VOP.\n");
+            s->b_frame_buf      = NULL;
+            s->b_frame_buf_size = 0;
         } else {
             /* copy packet into BSFContext */
-            ctx->b_frame_buf_size = buf_size;
-            ctx->b_frame_buf      = create_new_buffer(buf , buf_size);
-            if (!ctx->b_frame_buf) {
-                ctx->b_frame_buf_size = 0;
-                av_freep(poutbuf);
-                *poutbuf_size = 0;
+            s->b_frame_buf_size = in->size;
+            s->b_frame_buf      = create_new_buffer(in->data, in->size);
+            if (!s->b_frame_buf) {
+                s->b_frame_buf_size = 0;
+                av_packet_unref(out);
+                av_packet_free(&in);
                 return AVERROR(ENOMEM);
             }
         }
     } else if (nb_vop >= 2) {
         /* use first frame of the packet */
-        *poutbuf      = (uint8_t *) buf;
-        *poutbuf_size = pos_vop2;
+        av_packet_move_ref(out, in);
+        out->size = pos_vop2;
     } else if (pos_p >= 0) {
-        av_log(avctx, AV_LOG_DEBUG, "Updating DivX userdata (remove trailing 'p').\n");
-        *poutbuf_size = buf_size;
-        *poutbuf      = create_new_buffer(buf, buf_size);
-        if (!*poutbuf) {
-            *poutbuf_size = 0;
-            return AVERROR(ENOMEM);
-        }
+        av_log(ctx, AV_LOG_DEBUG, "Updating DivX userdata (remove trailing 'p').\n");
+        av_packet_move_ref(out, in);
         /* remove 'p' (packed) from the end of the (DivX) userdata string */
-        (*poutbuf)[pos_p] = '\0';
-        /* the output buffer is distinct from the input buffer */
-        ret = 1;
+        out->data[pos_p] = '\0';
     } else {
         /* copy packet */
-        *poutbuf      = (uint8_t *) buf;
-        *poutbuf_size = buf_size;
+        av_packet_move_ref(out, in);
+    }
+
+    av_packet_free(&in);
+
+    return 0;
+}
+
+static int mpeg4_unpack_bframes_init(AVBSFContext *ctx)
+{
+    if (ctx->par_in->extradata) {
+        int pos_p_ext = -1;
+        scan_buffer(ctx->par_in->extradata, ctx->par_in->extradata_size, &pos_p_ext, NULL, NULL);
+        if (pos_p_ext >= 0) {
+            av_log(ctx, AV_LOG_DEBUG,
+                   "Updating DivX userdata (remove trailing 'p') in extradata.\n");
+            ctx->par_out->extradata[pos_p_ext] = '\0';
+        }
     }
 
-    return ret;
+    return 0;
 }
 
-static void mpeg4_unpack_bframes_close(AVBitStreamFilterContext *bsfc)
+static void mpeg4_unpack_bframes_close(AVBSFContext *bsfc)
 {
     UnpackBFramesBSFContext *ctx = bsfc->priv_data;
     av_freep(&ctx->b_frame_buf);
 }
 
-AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf = {
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_MPEG4, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf = {
     .name           = "mpeg4_unpack_bframes",
     .priv_data_size = sizeof(UnpackBFramesBSFContext),
+    .init           = mpeg4_unpack_bframes_init,
     .filter         = mpeg4_unpack_bframes_filter,
-    .close          = mpeg4_unpack_bframes_close
+    .close          = mpeg4_unpack_bframes_close,
+    .codec_ids      = codec_ids,
 };
diff --git a/libavcodec/noise_bsf.c b/libavcodec/noise_bsf.c
index 556ad5c..9b4f4e4 100644
--- a/libavcodec/noise_bsf.c
+++ b/libavcodec/noise_bsf.c
@@ -22,34 +22,70 @@
 #include <string.h>
 
 #include "avcodec.h"
+#include "bsf.h"
+
+#include "libavutil/log.h"
 #include "libavutil/mem.h"
+#include "libavutil/opt.h"
 
+typedef struct NoiseContext {
+    const AVClass *class;
+    int amount;
+    unsigned int state;
+} NoiseContext;
 
-static int noise(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                     uint8_t **poutbuf, int *poutbuf_size,
-                     const uint8_t *buf, int buf_size, int keyframe){
-    unsigned int *state= bsfc->priv_data;
-    int amount= args ? atoi(args) : (*state % 10001+1);
-    int i;
+static int noise(AVBSFContext *ctx, AVPacket *out)
+{
+    NoiseContext *s = ctx->priv_data;
+    AVPacket *in;
+    int amount = s->amount > 0 ? s->amount : (s->state % 10001 + 1);
+    int i, ret = 0;
 
-    if(amount <= 0)
+    if (amount <= 0)
         return AVERROR(EINVAL);
 
-    *poutbuf= av_malloc(buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!*poutbuf)
-        return AVERROR(ENOMEM);
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    ret = av_new_packet(out, in->size);
+    if (ret < 0)
+        goto fail;
+
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
+
+    memcpy(out->data, in->data, in->size);
 
-    memcpy(*poutbuf, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    for(i=0; i<buf_size; i++){
-        (*state) += (*poutbuf)[i] + 1;
-        if(*state % amount == 0)
-            (*poutbuf)[i] = *state;
+    for (i = 0; i < out->size; i++) {
+        s->state += out->data[i] + 1;
+        if (s->state % amount == 0)
+            out->data[i] = s->state;
     }
-    return 1;
+fail:
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_noise_bsf={
+#define OFFSET(x) offsetof(NoiseContext, x)
+static const AVOption options[] = {
+    { "amount", NULL, OFFSET(amount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX },
+    { NULL },
+};
+
+static const AVClass noise_class = {
+    .class_name = "noise",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+const AVBitStreamFilter ff_noise_bsf = {
     .name           = "noise",
     .priv_data_size = sizeof(int),
+    .priv_class     = &noise_class,
     .filter         = noise,
 };
diff --git a/libavcodec/remove_extradata_bsf.c b/libavcodec/remove_extradata_bsf.c
index 6bb3576..c183567 100644
--- a/libavcodec/remove_extradata_bsf.c
+++ b/libavcodec/remove_extradata_bsf.c
@@ -18,38 +18,99 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libavutil/log.h"
+#include "libavutil/opt.h"
+
 #include "avcodec.h"
+#include "bsf.h"
 
+enum RemoveFreq {
+    REMOVE_FREQ_KEYFRAME,
+    REMOVE_FREQ_ALL,
+};
 
-static int remove_extradata(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                     uint8_t **poutbuf, int *poutbuf_size,
-                     const uint8_t *buf, int buf_size, int keyframe){
-    int cmd= args ? *args : 0;
-    AVCodecParserContext *s;
+typedef struct RemoveExtradataContext {
+    const AVClass *class;
+    int freq;
 
-    if(!bsfc->parser){
-        bsfc->parser= av_parser_init(avctx->codec_id);
-    }
-    s= bsfc->parser;
-
-    if(s && s->parser->split){
-        if(  (((avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ||
-               (avctx->flags2 & AV_CODEC_FLAG2_LOCAL_HEADER)) && cmd == 'a')
-           ||(!keyframe && cmd=='k')
-           ||(cmd=='e' || !cmd)
-          ){
-            int i= s->parser->split(avctx, buf, buf_size);
-            buf += i;
-            buf_size -= i;
+    AVCodecParserContext *parser;
+    AVCodecContext *avctx;
+} RemoveExtradataContext;
+
+static int remove_extradata(AVBSFContext *ctx, AVPacket *out)
+{
+    RemoveExtradataContext *s = ctx->priv_data;
+
+    AVPacket *in;
+    int ret;
+
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    if (s->parser && s->parser->parser->split) {
+        if (s->freq == REMOVE_FREQ_ALL ||
+            (s->freq == REMOVE_FREQ_KEYFRAME && in->flags & AV_PKT_FLAG_KEY)) {
+            int i = s->parser->parser->split(s->avctx, in->data, in->size);
+            in->data += i;
+            in->size -= i;
         }
     }
-    *poutbuf= (uint8_t *) buf;
-    *poutbuf_size= buf_size;
+
+    av_packet_move_ref(out, in);
+    av_packet_free(&in);
 
     return 0;
 }
 
-AVBitStreamFilter ff_remove_extradata_bsf={
-    .name   = "remove_extra",
-    .filter = remove_extradata,
+static int remove_extradata_init(AVBSFContext *ctx)
+{
+    RemoveExtradataContext *s = ctx->priv_data;
+    int ret;
+
+    s->parser = av_parser_init(ctx->par_in->codec_id);
+
+    if (s->parser) {
+        s->avctx = avcodec_alloc_context3(NULL);
+        if (!s->avctx)
+            return AVERROR(ENOMEM);
+
+        ret = avcodec_parameters_to_context(s->avctx, ctx->par_in);
+        if (ret < 0)
+            return ret;
+    }
+
+    return 0;
+}
+
+static void remove_extradata_close(AVBSFContext *ctx)
+{
+    RemoveExtradataContext *s = ctx->priv_data;
+
+    avcodec_free_context(&s->avctx);
+    av_parser_close(s->parser);
+}
+
+#define OFFSET(x) offsetof(RemoveExtradataContext, x)
+static const AVOption options[] = {
+    { "freq", NULL, OFFSET(freq), AV_OPT_TYPE_INT, { .i64 = REMOVE_FREQ_KEYFRAME }, REMOVE_FREQ_KEYFRAME, REMOVE_FREQ_ALL, 0, "freq" },
+        { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_KEYFRAME }, .unit = "freq" },
+        { "all",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_ALL      }, .unit = "freq" },
+    { NULL },
+};
+
+static const AVClass remove_extradata_class = {
+    .class_name = "remove_extradata",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+const AVBitStreamFilter ff_remove_extradata_bsf = {
+    .name           = "remove_extra",
+    .priv_data_size = sizeof(RemoveExtradataContext),
+    .priv_class     = &remove_extradata_class,
+    .init           = remove_extradata_init,
+    .close          = remove_extradata_close,
+    .filter         = remove_extradata,
 };
diff --git a/libavcodec/version.h b/libavcodec/version.h
index c24f0fc..b8ef9c5 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -28,8 +28,8 @@
 #include "libavutil/version.h"
 
 #define LIBAVCODEC_VERSION_MAJOR  57
-#define LIBAVCODEC_VERSION_MINOR  34
-#define LIBAVCODEC_VERSION_MICRO 102
+#define LIBAVCODEC_VERSION_MINOR  35
+#define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \
@@ -214,5 +214,8 @@
 #ifndef FF_API_ASS_TIMING
 #define FF_API_ASS_TIMING       (LIBAVCODEC_VERSION_MAJOR < 59)
 #endif
+#ifndef FF_API_OLD_BSF
+#define FF_API_OLD_BSF          (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
 
 #endif /* AVCODEC_VERSION_H */
diff --git a/libavcodec/vp9_superframe_bsf.c b/libavcodec/vp9_superframe_bsf.c
index d4a61ee..b686adb 100644
--- a/libavcodec/vp9_superframe_bsf.c
+++ b/libavcodec/vp9_superframe_bsf.c
@@ -21,6 +21,7 @@
 
 #include "libavutil/avassert.h"
 #include "avcodec.h"
+#include "bsf.h"
 #include "get_bits.h"
 
 #define MAX_CACHE 8
@@ -50,20 +51,20 @@ static void stats(const struct CachedBuf *in, int n_in,
     *_sum = sum;
 }
 
-static int merge_superframe(const struct CachedBuf *in, int n_in,
-                            uint8_t **poutbuf, int *poutbuf_size)
+static int merge_superframe(const struct CachedBuf *in, int n_in, AVPacket *out)
 {
     unsigned max, sum, mag, marker, n, sz;
     uint8_t *ptr;
+    int res;
 
     stats(in, n_in, &max, &sum);
     mag = av_log2(max) >> 3;
     marker = 0xC0 + (mag << 3) + (n_in - 1);
-    sz = *poutbuf_size = sum + 2 + (mag + 1) * n_in;
-    ptr = *poutbuf = av_malloc(sz);
-    if (!ptr)
-        return AVERROR(ENOMEM);
-
+    sz = sum + 2 + (mag + 1) * n_in;
+    res = av_new_packet(out, sz);
+    if (res < 0)
+        return res;
+    ptr = out->data;
     for (n = 0; n < n_in; n++) {
         memcpy(ptr, in[n].data, in[n].size);
         ptr += in[n].size;
@@ -92,31 +93,32 @@ static int merge_superframe(const struct CachedBuf *in, int n_in,
         break;
     }
     *ptr++ = marker;
-    av_assert0(ptr == &(*poutbuf)[*poutbuf_size]);
+    av_assert0(ptr == &out->data[out->size]);
 
     return 0;
 }
 
-static int vp9_superframe_filter(AVBitStreamFilterContext *bsfc,
-                                 AVCodecContext *avctx, const char *args,
-                                 uint8_t  **poutbuf, int *poutbuf_size,
-                                 const uint8_t *buf, int      buf_size,
-                                 int keyframe)
+static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out)
 {
     GetBitContext gb;
-    VP9BSFContext *ctx = bsfc->priv_data;
+    VP9BSFContext *s = ctx->priv_data;
+    AVPacket *in;
     int res, invisible, profile, marker, uses_superframe_syntax = 0, n;
 
-    marker = buf[buf_size - 1];
+    res = ff_bsf_get_packet(ctx, &in);
+    if (res < 0)
+        return res;
+
+    marker = in->data[in->size - 1];
     if ((marker & 0xe0) == 0xc0) {
         int nbytes = 1 + ((marker >> 3) & 0x3);
         int n_frames = 1 + (marker & 0x7), idx_sz = 2 + n_frames * nbytes;
 
-        uses_superframe_syntax = buf_size >= idx_sz && buf[buf_size - idx_sz] == marker;
+        uses_superframe_syntax = in->size >= idx_sz && in->data[in->size - idx_sz] == marker;
     }
 
-    if ((res = init_get_bits8(&gb, buf, buf_size)) < 0)
-        return res;
+    if ((res = init_get_bits8(&gb, in->data, in->size)) < 0)
+        goto done;
 
     get_bits(&gb, 2); // frame marker
     profile  = get_bits1(&gb);
@@ -130,60 +132,74 @@ static int vp9_superframe_filter(AVBitStreamFilterContext *bsfc,
         invisible = !get_bits1(&gb);
     }
 
-    if (uses_superframe_syntax && ctx->n_cache > 0) {
-        av_log(avctx, AV_LOG_ERROR,
+    if (uses_superframe_syntax && s->n_cache > 0) {
+        av_log(ctx, AV_LOG_ERROR,
                "Mixing of superframe syntax and naked VP9 frames not supported");
-        return AVERROR_INVALIDDATA;
-    } else if ((!invisible || uses_superframe_syntax) && !ctx->n_cache) {
+        res = AVERROR_INVALIDDATA;
+        goto done;
+    } else if ((!invisible || uses_superframe_syntax) && !s->n_cache) {
         // passthrough
-        *poutbuf = (uint8_t *) buf;
-        *poutbuf_size = buf_size;
-        return 0;
-    } else if (ctx->n_cache + 1 >= MAX_CACHE) {
-        av_log(avctx, AV_LOG_ERROR,
+        av_packet_move_ref(out, in);
+        goto done;
+    } else if (s->n_cache + 1 >= MAX_CACHE) {
+        av_log(ctx, AV_LOG_ERROR,
                "Too many invisible frames");
-        return AVERROR_INVALIDDATA;
+        res = AVERROR_INVALIDDATA;
+        goto done;
     }
 
-    ctx->cache[ctx->n_cache].size = buf_size;
+    s->cache[s->n_cache].size = in->size;
     if (invisible && !uses_superframe_syntax) {
-        ctx->cache[ctx->n_cache].data = av_malloc(buf_size);
-        if (!ctx->cache[ctx->n_cache].data)
-            return AVERROR(ENOMEM);
-        memcpy(ctx->cache[ctx->n_cache++].data, buf, buf_size);
-        *poutbuf = NULL;
-        *poutbuf_size = 0;
-        return 0;
+        s->cache[s->n_cache].data = av_malloc(in->size);
+        if (!s->cache[s->n_cache].data) {
+            res = AVERROR(ENOMEM);
+            goto done;
+        }
+        memcpy(s->cache[s->n_cache++].data, in->data, in->size);
+        res = AVERROR(EAGAIN);
+        goto done;
     }
-    av_assert0(ctx->n_cache > 0);
+    av_assert0(s->n_cache > 0);
 
-    ctx->cache[ctx->n_cache].data = (uint8_t *) buf;
+    s->cache[s->n_cache].data = in->data;
 
     // build superframe
-    if ((res = merge_superframe(ctx->cache, ctx->n_cache + 1,
-                                poutbuf, poutbuf_size)) < 0)
-        return res;
-
-    for (n = 0; n < ctx->n_cache; n++)
-        av_freep(&ctx->cache[n].data);
-    ctx->n_cache = 0;
-
-    return 0;
+    if ((res = merge_superframe(s->cache, s->n_cache + 1, out)) < 0)
+        goto done;
+
+    for (n = 0; n < s->n_cache; n++)
+        av_freep(&s->cache[n].data);
+    s->n_cache = 0;
+
+    res = av_packet_copy_props(out, in);
+    if (res < 0)
+        goto done;
+
+done:
+    if (res < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+    return res;
 }
 
-static void vp9_superframe_close(AVBitStreamFilterContext *bsfc)
+static void vp9_superframe_close(AVBSFContext *ctx)
 {
-    VP9BSFContext *ctx = bsfc->priv_data;
+    VP9BSFContext *s = ctx->priv_data;
     int n;
 
     // free cached data
-    for (n = 0; n < ctx->n_cache; n++)
-        av_freep(&ctx->cache[n].data);
+    for (n = 0; n < s->n_cache; n++)
+        av_freep(&s->cache[n].data);
 }
 
-AVBitStreamFilter ff_vp9_superframe_bsf = {
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_VP9, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_vp9_superframe_bsf = {
     .name           = "vp9_superframe",
     .priv_data_size = sizeof(VP9BSFContext),
     .filter         = vp9_superframe_filter,
     .close          = vp9_superframe_close,
+    .codec_ids      = codec_ids,
 };
diff --git a/libavformat/mux.c b/libavformat/mux.c
index 33301f1..6239fd1 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -309,6 +309,12 @@ FF_DISABLE_DEPRECATION_WARNINGS
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
+        /* update internal context from codecpar, old bsf api needs this
+         * FIXME: remove when autobsf uses new bsf API */
+        ret = avcodec_parameters_to_context(st->internal->avctx, st->codecpar);
+        if (ret < 0)
+            goto fail;
+
         if (!st->time_base.num) {
             /* fall back on the default timebase values */
             if (par->codec_type == AVMEDIA_TYPE_AUDIO && par->sample_rate)


======================================================================

diff --cc doc/APIchanges
index 33bd02e,c50faa6..8a14e77
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@@ -15,117 -13,67 +15,121 @@@ libavutil:     2015-08-2
  
  API changes, most recent first:
  
+ 2016-xx-xx - xxxxxxx - lavc 57.15.0 - avcodec.h
+   Add a new bitstream filtering API working with AVPackets.
+   Deprecate the old bistream filtering API.
+ 
 -2016-xx-xx - xxxxxxx - lavfi 6.3.0 - avfilter.h
 +2016-xx-xx - xxxxxxx - lavfi 6.42.0 - avfilter.h
    Add AVFilterContext.hw_device_ctx.
  
 -2016-xx-xx - xxxxxxx - lavu 55.9.0 - hwcontext_vaapi.h
 +2016-xx-xx - xxxxxxx - lavu 55.22.0 - hwcontext_vaapi.h
    Add new installed header with VAAPI-specific hwcontext definitions.
  
 -2016-xx-xx - xxxxxxx - lavu 55.8.0 - pixfmt.h
 -  Deprecate all AV_PIX_FMT_VAAPI_* formats.
 -  Replaced by AV_PIX_FMT_VAAPI.
 -
 -2016-xx-xx - xxxxxxx - lavu 55.7.0 - hwcontext.h
 +2016-xx-xx - xxxxxxx - lavu 55.21.0 - hwcontext.h
    Add AVHWFramesConstraints and associated API.
  
 -2016-02-23 - 9200514 - lavf 57.5.0 - avformat.h
 +2016-04-11 - xxxxxxx - lavf 57.33.0 - avformat.h
    Add AVStream.codecpar, deprecate AVStream.codec.
  
 -2016-xx-xx - lavc 57.14.0 - avcodec.h
 -  998e1b8 - Add AVCodecParameters and its related API.
 -  a806834 - Add av_get_audio_frame_duration2().
 +2016-04-02 - xxxxxxx - lavu 55.20.100 - base64.h
 +  Add AV_BASE64_DECODE_SIZE(x) macro.
 +
 +2016-xx-xx - lavc 57.33.0 - avcodec.h
 +  xxxxxxx - Add AVCodecParameters and its related API.
 +  xxxxxxx - Add av_get_audio_frame_duration2().
 +
 +2016-03-11 - xxxxxxx - lavf/lavc 57.28.101
 +  Add requirement to bitstream filtering API that returned packets with
 +  size == 0 and side_data_elems == 0 are to be skipped by the caller.
 +
 +2016-XX-XX - xxxxxxx - lavf 57.28.100
 +  Add protocol blacklisting API
 +
 +2016-02-28 - xxxxxxx - lavc 57.27.101
 +  Validate AVFrame returned by get_buffer2 to have required
 +  planes not NULL and unused planes set to NULL as crashes
 +  and buffer overflow are possible with certain streams if
 +  that is not the case.
 +
 +2016-xx-xx - xxxxxxx - lavc 57.27.100 - avcodec.h
 +  "flags2" decoding option now allows the flag "ass_ro_flush_noop" preventing
 +  the reset of the ASS ReadOrder field on flush. This affects the content of
 +  AVSubtitles.rects[N]->ass when "sub_text_format" is set to "ass" (see
 +  previous entry).
 +
 +2016-xx-xx - xxxxxxx - lavc 57.26.100 - avcodec.h
 +  Add a "sub_text_format" subtitles decoding option allowing the values "ass"
 +  (recommended) and "ass_with_timings" (not recommended, deprecated, default).
 +  The default value for this option will change to "ass" at the next major
 +  libavcodec version bump.
 +
 +  The current default is "ass_with_timings" for compatibility. This means that
 +  all subtitles text decoders currently still output ASS with timings printed
 +  as strings in the AVSubtitles.rects[N]->ass fields.
 +
 +  Setting "sub_text_format" to "ass" allows a better timing accuracy (ASS
 +  timing is limited to a 1/100 time base, so this is relevant for any subtitles
 +  format needing a bigger one), ease timing adjustments, and prevents the need
 +  of removing the timing from the decoded string yourself. This form is also
 +  known as "the Matroska form". The timing information (start time, duration)
 +  can be found in the AVSubtitles fields.
 +
 +2016-xx-xx - lavc 57.25.0 - avcodec.h
 +  Add AVCodecContext.hw_frames_ctx.
  
 -2016-02-22 - ec4c483 - lavf 57.4.0 - avformat.h
 -  Add AVFormatContext.protocol_whitelist and protocol_blacklist.
 -  Add 'protocol_whitelist' and 'protocol_blacklist' private options for
 -  avio_open2().
 +2016-xx-xx - lavfi 6.36.0 - avfilter.h
 +  xxxxxxx avfilter.h - Add AVFilterLink.hw_frames_ctx.
 +  xxxxxxx buffersrc.h - Add AVBufferSrcParameters and functions for handling it.
  
 -2016-02-14 - 7b3214d0 - lavc 57.13.0 - avcodec.h
 -  Add AVCodecContext.hw_frames_ctx.
 +2016-02-xx - xxxxxxx - lavc 57.25.100
 +  Add AV_PKT_DATA_MPEGTS_STREAM_ID for exporting the MPEGTS stream ID.
  
 -2016-02-14 - lavfi 6.2.0 - avfilter.h
 -  b3dd30d avfilter.h - Add AVFilterLink.hw_frames_ctx.
 -          buffersrc.h - Add AVBufferSrcParameters and functions for handling it.
 +2016-xx-xx - lavu 55.18.100
 +  xxxxxxx audio_fifo.h - Add av_audio_fifo_peek_at().
  
 -2016-02-14 - lavu 55.6.0
 -  721a4ef buffer.h - Add av_buffer_pool_init2().
 -  89923e4 hwcontext.h - Add a new installed header hwcontext.h with a new API
 +2016-xx-xx - lavu 55.18.0
 +  xxxxxxx buffer.h - Add av_buffer_pool_init2().
 +  xxxxxxx hwcontext.h - Add a new installed header hwcontext.h with a new API
                          for handling hwaccel frames.
 -  ad884d1 hwcontext_cuda.h - Add a new installed header hwcontext_cuda.h with
 +  xxxxxxx hwcontext_cuda.h - Add a new installed header hwcontext_cuda.h with
                               CUDA-specific hwcontext definitions.
 -  a001ce3 hwcontext_vdpau.h - Add a new installed header hwcontext_vdpau.h with
 +  xxxxxxx hwcontext_vdpau.h - Add a new installed header hwcontext_vdpau.h with
                                VDPAU-specific hwcontext definitions.
 -  7bc780c pixfmt.h - Add AV_PIX_FMT_CUDA.
 +  xxxxxxx pixfmt.h - Add AV_PIX_FMT_CUDA.
  
 -2016-01-24 - 9f61abc - lavf 57.3.0 - avformat.h
 +-------- 8< --------- FFmpeg 3.0 was cut here -------- 8< ---------
 +
 +2016-02-10 - bc9a596 / 9f61abc - lavf 57.25.100 / 57.3.0 - avformat.h
    Add AVFormatContext.opaque, io_open and io_close, allowing custom IO
 -  for muxers and demuxers that open additional files.
  
 -2015-12-12 - 2c68113 - lavc 57.12.0 - avcodec.h
 +2016-02-01 - 1dba837 - lavf 57.24.100 - avformat.h, avio.h
 +  Add protocol_whitelist to AVFormatContext, AVIOContext
 +
 +2016-01-31 - 66e9d2f - lavu 55.17.100 - frame.h
 +  Add AV_FRAME_DATA_GOP_TIMECODE for exporting MPEG1/2 GOP timecodes.
 +
 +2016-01-01 - 5e8b053 / 2c68113 - lavc 57.21.100 / 57.12.0 - avcodec.h
    Add AVCodecDescriptor.profiles and avcodec_profile_name().
  
 -2015-12-06 - lavc 57.11.0 - avcodec.h dirac.h
 -  31c51f7 - Add av_packet_add_side_data().
 -  84adab3 - Add AVCodecContext.coded_side_data.
 -  f0b769c - Add AVCPBProperties API.
 -  e02de9d - Add a new public header dirac.h containing
 +2015-12-28 - 1f9139b - lavf 57.21.100 - avformat.h
 +  Add automatic bitstream filtering; add av_apply_bitstream_filters()
 +
 +2015-12-22 - 39a09e9 - lavfi 6.21.101 - avfilter.h
 +  Deprecate avfilter_link_set_closed().
 +  Applications are not supposed to mess with links,
 +  they should close the sinks.
 +
 +2015-12-17 - lavc 57.18.100 / 57.11.0 - avcodec.h dirac.h
 +  xxxxxxx - Add av_packet_add_side_data().
 +  xxxxxxx - Add AVCodecContext.coded_side_data.
 +  xxxxxxx - Add AVCPBProperties API.
 +  xxxxxxx - Add a new public header dirac.h containing
              av_dirac_parse_sequence_header()
  
 -2015-11-20 - 462a54e - lavc 57.9.1 - avcodec.h
 +2015-12-11 - 676a93f - lavf 57.20.100 - avformat.h
 +  Add av_program_add_stream_index()
 +
 +2015-11-29 - 93fb4a4 - lavc 57.16.101 - avcodec.h
    Deprecate rtp_callback without replacement, i.e. it won't be possible to
    get image slices before the full frame is encoded any more. The libavformat
    rtpenc muxer can still be used for RFC-2190 packetization.
diff --cc libavcodec/aac_adtstoasc_bsf.c
index 9c117c6,9168e2b..48889fc
--- a/libavcodec/aac_adtstoasc_bsf.c
+++ b/libavcodec/aac_adtstoasc_bsf.c
@@@ -84,18 -93,18 +93,17 @@@ static int aac_adtstoasc_filter(AVBSFCo
              init_put_bits(&pb, pce_data, MAX_PCE_SIZE);
              pce_size = avpriv_copy_pce_data(&pb, &gb)/8;
              flush_put_bits(&pb);
-             buf_size -= get_bits_count(&gb)/8;
-             buf      += get_bits_count(&gb)/8;
+             in->size -= get_bits_count(&gb)/8;
+             in->data += get_bits_count(&gb)/8;
          }
-         av_free(avctx->extradata);
-         avctx->extradata_size = 2 + pce_size;
-         avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
-         if (!avctx->extradata) {
-             avctx->extradata_size = 0;
-             return AVERROR(ENOMEM);
+ 
 -        extradata = av_packet_new_side_data(in, AV_PKT_DATA_NEW_EXTRADATA,
 -                                            2 + pce_size);
++        extradata = av_mallocz(2 + pce_size + AV_INPUT_BUFFER_PADDING_SIZE);
+         if (!extradata) {
+             ret = AVERROR(ENOMEM);
+             goto fail;
          }
  
-         init_put_bits(&pb, avctx->extradata, avctx->extradata_size);
+         init_put_bits(&pb, extradata, 2 + pce_size);
          put_bits(&pb, 5, hdr.object_type);
          put_bits(&pb, 4, hdr.sampling_index);
          put_bits(&pb, 4, hdr.chan_config);
@@@ -104,9 -113,9 +112,11 @@@
          put_bits(&pb, 1, 0); //is not extension
          flush_put_bits(&pb);
          if (pce_size) {
-             memcpy(avctx->extradata + 2, pce_data, pce_size);
+             memcpy(extradata + 2, pce_data, pce_size);
          }
  
++        bsfc->par_out->extradata = extradata;
++        bsfc->par_out->extradata_size = 2 + pce_size;
          ctx->first_frame_done = 1;
      }
  
diff --cc libavcodec/allcodecs.c
index 3214e35,f0b57d5..f88c0ff
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@@ -666,23 -529,4 +659,5 @@@ void avcodec_register_all(void
      REGISTER_PARSER(VORBIS,             vorbis);
      REGISTER_PARSER(VP3,                vp3);
      REGISTER_PARSER(VP8,                vp8);
 +    REGISTER_PARSER(VP9,                vp9);
- 
-     /* bitstream filters */
-     REGISTER_BSF(AAC_ADTSTOASC,         aac_adtstoasc);
-     REGISTER_BSF(CHOMP,                 chomp);
-     REGISTER_BSF(DUMP_EXTRADATA,        dump_extradata);
-     REGISTER_BSF(DCA_CORE,              dca_core);
-     REGISTER_BSF(H264_MP4TOANNEXB,      h264_mp4toannexb);
-     REGISTER_BSF(HEVC_MP4TOANNEXB,      hevc_mp4toannexb);
-     REGISTER_BSF(IMX_DUMP_HEADER,       imx_dump_header);
-     REGISTER_BSF(MJPEG2JPEG,            mjpeg2jpeg);
-     REGISTER_BSF(MJPEGA_DUMP_HEADER,    mjpega_dump_header);
-     REGISTER_BSF(MP3_HEADER_DECOMPRESS, mp3_header_decompress);
-     REGISTER_BSF(MPEG4_UNPACK_BFRAMES,  mpeg4_unpack_bframes);
-     REGISTER_BSF(MOV2TEXTSUB,           mov2textsub);
-     REGISTER_BSF(NOISE,                 noise);
-     REGISTER_BSF(REMOVE_EXTRADATA,      remove_extradata);
-     REGISTER_BSF(TEXT2MOVSUB,           text2movsub);
-     REGISTER_BSF(VP9_SUPERFRAME,        vp9_superframe);
  }
diff --cc libavcodec/avcodec.h
index 784b1c1,0ff31a0..9a8a0f0
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@@ -5392,99 -4698,215 +5392,282 @@@ typedef struct AVBitStreamFilterContex
      struct AVBitStreamFilter *filter;
      AVCodecParserContext *parser;
      struct AVBitStreamFilterContext *next;
 +    /**
 +     * Internal default arguments, used if NULL is passed to av_bitstream_filter_filter().
 +     * Not for access by library users.
 +     */
 +    char *args;
  } 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).
 + * Register a bitstream filter.
 + *
 + * The filter will be accessible to the application code through
 + * av_bitstream_filter_next() or can be directly initialized with
 + * av_bitstream_filter_init().
 + *
 + * @see avcodec_register_all()
   */
+ attribute_deprecated
  void av_register_bitstream_filter(AVBitStreamFilter *bsf);
 +
 +/**
 + * Create and initialize a bitstream filter context given a bitstream
 + * filter name.
 + *
 + * The returned context must be freed with av_bitstream_filter_close().
 + *
 + * @param name    the name of the bitstream filter
 + * @return a bitstream filter context if a matching filter was found
 + * and successfully initialized, NULL otherwise
 + */
+ attribute_deprecated
  AVBitStreamFilterContext *av_bitstream_filter_init(const char *name);
 +
 +/**
 + * Filter bitstream.
 + *
 + * This function filters the buffer buf with size buf_size, and places the
 + * filtered buffer in the buffer pointed to by poutbuf.
 + *
 + * The output buffer must be freed by the caller.
 + *
 + * @param bsfc            bitstream filter context created by av_bitstream_filter_init()
 + * @param avctx           AVCodecContext accessed by the filter, may be NULL.
 + *                        If specified, this must point to the encoder context of the
 + *                        output stream the packet is sent to.
 + * @param args            arguments which specify the filter configuration, may be NULL
 + * @param poutbuf         pointer which is updated to point to the filtered buffer
 + * @param poutbuf_size    pointer which is updated to the filtered buffer size in bytes
 + * @param buf             buffer containing the data to filter
 + * @param buf_size        size in bytes of buf
 + * @param keyframe        set to non-zero if the buffer to filter corresponds to a key-frame packet data
 + * @return >= 0 in case of success, or a negative error code in case of failure
 + *
 + * If the return value is positive, an output buffer is allocated and
 + * is available in *poutbuf, and is distinct from the input buffer.
 + *
 + * If the return value is 0, the output buffer is not allocated and
 + * should be considered identical to the input buffer, or in case
 + * *poutbuf was set it points to the input buffer (not necessarily to
 + * its starting address). A special case is if *poutbuf was set to NULL and
 + * *poutbuf_size was set to 0, which indicates the packet should be dropped.
 + */
+ 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);
 +
 +/**
 + * Release bitstream filter context.
 + *
 + * @param bsf the bitstream filter context created with
 + * av_bitstream_filter_init(), can be NULL
 + */
+ attribute_deprecated
  void av_bitstream_filter_close(AVBitStreamFilterContext *bsf);
 +
 +/**
 + * If f is NULL, return the first registered bitstream filter,
 + * if f is non-NULL, return the next registered bitstream filter
 + * after f, or NULL if f is the last one.
 + *
 + * This function can be used to iterate over all registered bitstream
 + * filters.
 + */
+ 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 --cc libavcodec/bitstream_filter.c
index fb690b6,ab608a9..d9bafbe
--- a/libavcodec/bitstream_filter.c
+++ b/libavcodec/bitstream_filter.c
@@@ -21,10 -21,12 +21,12 @@@
  #include <string.h>
  
  #include "avcodec.h"
 -
 +#include "libavutil/atomic.h"
+ #include "libavutil/internal.h"
  #include "libavutil/mem.h"
  
- static AVBitStreamFilter *first_bitstream_filter = NULL;
+ #if FF_API_OLD_BSF
+ FF_DISABLE_DEPRECATION_WARNINGS
  
  AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f)
  {
@@@ -36,45 -41,50 +41,56 @@@
  
  void av_register_bitstream_filter(AVBitStreamFilter *bsf)
  {
-     do {
-         bsf->next = first_bitstream_filter;
-     } while(bsf->next != avpriv_atomic_ptr_cas((void * volatile *)&first_bitstream_filter, bsf->next, bsf));
  }
  
+ typedef struct BSFCompatContext {
+     AVBSFContext *ctx;
++    int extradata_updated;
+ } BSFCompatContext;
+ 
  AVBitStreamFilterContext *av_bitstream_filter_init(const char *name)
  {
-     AVBitStreamFilter *bsf = NULL;
- 
-     while (bsf = av_bitstream_filter_next(bsf)) {
-         if (!strcmp(name, bsf->name)) {
-             AVBitStreamFilterContext *bsfc =
-                 av_mallocz(sizeof(AVBitStreamFilterContext));
-             if (!bsfc)
-                 return NULL;
-             bsfc->filter    = bsf;
-             bsfc->priv_data = NULL;
-             if (bsf->priv_data_size) {
-                 bsfc->priv_data = av_mallocz(bsf->priv_data_size);
-                 if (!bsfc->priv_data) {
-                     av_freep(&bsfc);
-                     return NULL;
-                 }
-             }
-             return bsfc;
-         }
-     }
+     AVBitStreamFilterContext *ctx = NULL;
+     BSFCompatContext         *priv = NULL;
+     const AVBitStreamFilter *bsf;
+ 
+     bsf = av_bsf_get_by_name(name);
+     if (!bsf)
+         return NULL;
+ 
+     ctx = av_mallocz(sizeof(*ctx));
+     if (!ctx)
+         return NULL;
+ 
+     priv = av_mallocz(sizeof(*priv));
+     if (!priv)
+         goto fail;
+ 
+ 
+     ctx->filter    = bsf;
+     ctx->priv_data = priv;
+ 
+     return ctx;
+ 
+ fail:
+     if (priv)
+         av_bsf_free(&priv->ctx);
+     av_freep(&priv);
+     av_freep(&ctx);
      return NULL;
  }
  
  void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc)
  {
 -    BSFCompatContext *priv = bsfc->priv_data;
++    BSFCompatContext *priv;
++
 +    if (!bsfc)
 +        return;
-     if (bsfc->filter->close)
-         bsfc->filter->close(bsfc);
++
++    priv = bsfc->priv_data;
+ 
+     av_bsf_free(&priv->ctx);
      av_freep(&bsfc->priv_data);
-     av_freep(&bsfc->args);
-     av_parser_close(bsfc->parser);
      av_free(bsfc);
  }
  
@@@ -83,8 -93,71 +99,75 @@@ int av_bitstream_filter_filter(AVBitStr
                                 uint8_t **poutbuf, int *poutbuf_size,
                                 const uint8_t *buf, int buf_size, int keyframe)
  {
-     *poutbuf      = (uint8_t *)buf;
-     *poutbuf_size = buf_size;
-     return bsfc->filter->filter(bsfc, avctx, args ? args : bsfc->args,
-                                 poutbuf, poutbuf_size, buf, buf_size, keyframe);
+     BSFCompatContext *priv = bsfc->priv_data;
+     AVPacket pkt = { 0 };
+     int ret;
+ 
+     if (!priv->ctx) {
+         ret = av_bsf_alloc(bsfc->filter, &priv->ctx);
+         if (ret < 0)
+             return ret;
+ 
+         ret = avcodec_parameters_from_context(priv->ctx->par_in, avctx);
+         if (ret < 0)
+             return ret;
+ 
+         priv->ctx->time_base_in = avctx->time_base;
+ 
+         ret = av_bsf_init(priv->ctx);
+         if (ret < 0)
+             return ret;
 -
 -        if (priv->ctx->par_out->extradata_size) {
 -            av_freep(&avctx->extradata);
 -            avctx->extradata_size = 0;
 -            avctx->extradata = av_mallocz(priv->ctx->par_out->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
 -            if (!avctx->extradata)
 -                return AVERROR(ENOMEM);
 -            memcpy(avctx->extradata, priv->ctx->par_out->extradata,
 -                   priv->ctx->par_out->extradata_size);
 -            avctx->extradata_size = priv->ctx->par_out->extradata_size;
 -        }
+     }
+ 
+     pkt.data = buf;
+     pkt.size = buf_size;
+ 
+     ret = av_bsf_send_packet(priv->ctx, &pkt);
+     if (ret < 0)
+         return ret;
+ 
+     *poutbuf      = NULL;
+     *poutbuf_size = 0;
+ 
+     ret = av_bsf_receive_packet(priv->ctx, &pkt);
+     if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+         return 0;
+     else if (ret < 0)
+         return ret;
+ 
+     *poutbuf = av_malloc(pkt.size + AV_INPUT_BUFFER_PADDING_SIZE);
+     if (!*poutbuf) {
+         av_packet_unref(&pkt);
+         return AVERROR(ENOMEM);
+     }
+ 
+     *poutbuf_size = pkt.size;
+     memcpy(*poutbuf, pkt.data, pkt.size);
+ 
+     av_packet_unref(&pkt);
+ 
+     /* drain all the remaining packets we cannot return */
+     while (ret >= 0) {
+         ret = av_bsf_receive_packet(priv->ctx, &pkt);
+         av_packet_unref(&pkt);
+     }
+ 
++    if (!priv->extradata_updated) {
++        /* update extradata in avctx from the output codec parameters */
++        if (priv->ctx->par_out->extradata_size && (!args || !strstr(args, "private_spspps_buf"))) {
++            av_freep(&avctx->extradata);
++            avctx->extradata_size = 0;
++            avctx->extradata = av_mallocz(priv->ctx->par_out->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
++            if (!avctx->extradata)
++                return AVERROR(ENOMEM);
++            memcpy(avctx->extradata, priv->ctx->par_out->extradata, priv->ctx->par_out->extradata_size);
++            avctx->extradata_size = priv->ctx->par_out->extradata_size;
++        }
++
++        priv->extradata_updated = 1;
++    }
++
+     return 1;
  }
+ FF_ENABLE_DEPRECATION_WARNINGS
+ #endif
diff --cc libavcodec/bitstream_filters.c
index 0000000,897e1f8..51f3cd9
mode 000000,100644..100644
--- a/libavcodec/bitstream_filters.c
+++ b/libavcodec/bitstream_filters.c
@@@ -1,0 -1,121 +1,137 @@@
+ /*
 - * This file is part of Libav.
++ * This file is part of FFmpeg.
+  *
 - * Libav is free software; you can redistribute it and/or
++ * FFmpeg 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,
++ * FFmpeg 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
++ * License along with FFmpeg; 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"
+ 
+ extern const AVBitStreamFilter ff_aac_adtstoasc_bsf;
+ extern const AVBitStreamFilter ff_chomp_bsf;
+ extern const AVBitStreamFilter ff_dump_extradata_bsf;
++extern const AVBitStreamFilter ff_dca_core_bsf;
+ extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf;
+ extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf;
+ extern const AVBitStreamFilter ff_imx_dump_header_bsf;
+ extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf;
+ extern const AVBitStreamFilter ff_mjpega_dump_header_bsf;
++extern const AVBitStreamFilter ff_mp3_header_decompress_bsf;
++extern const AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf;
+ extern const AVBitStreamFilter ff_mov2textsub_bsf;
 -extern const AVBitStreamFilter ff_text2movsub_bsf;
+ extern const AVBitStreamFilter ff_noise_bsf;
+ extern const AVBitStreamFilter ff_remove_extradata_bsf;
++extern const AVBitStreamFilter ff_text2movsub_bsf;
++extern const AVBitStreamFilter ff_vp9_superframe_bsf;
+ 
+ static const AVBitStreamFilter *bitstream_filters[] = {
+ #if CONFIG_AAC_ADTSTOASC_BSF
+     &ff_aac_adtstoasc_bsf,
+ #endif
+ #if CONFIG_CHOMP_BSF
+     &ff_chomp_bsf,
+ #endif
+ #if CONFIG_DUMP_EXTRADATA_BSF
+     &ff_dump_extradata_bsf,
+ #endif
++#if CONFIG_DCA_CORE_BSF
++    &ff_dca_core_bsf,
++#endif
+ #if CONFIG_H264_MP4TOANNEXB_BSF
+     &ff_h264_mp4toannexb_bsf,
+ #endif
+ #if CONFIG_HEVC_MP4TOANNEXB_BSF
+     &ff_hevc_mp4toannexb_bsf,
+ #endif
+ #if CONFIG_IMX_DUMP_HEADER_BSF
+     &ff_imx_dump_header_bsf,
+ #endif
+ #if CONFIG_MJPEG2JPEG_BSF
+     &ff_mjpeg2jpeg_bsf,
+ #endif
+ #if CONFIG_MJPEGA_DUMP_HEADER_BSF
 -    &ff_mjpeg2jpeg_bsf,
++    &ff_mjpega_dump_header_bsf,
++#endif
++#if CONFIG_MP3_HEADER_DECOMPRESS_BSF
++    &ff_mp3_header_decompress_bsf,
++#endif
++#if CONFIG_MPEG4_UNPACK_BFRAMES_BSF
++    &ff_mpeg4_unpack_bframes_bsf,
+ #endif
+ #if CONFIG_MOV2TEXTSUB_BSF
+     &ff_mov2textsub_bsf,
+ #endif
 -#if CONFIG_TEXT2MOVSUB_BSF
 -    &ff_text2movsub_bsf,
 -#endif
+ #if CONFIG_NOISE_BSF
+     &ff_noise_bsf,
+ #endif
+ #if CONFIG_REMOVE_EXTRADATA_BSF
+     &ff_remove_extradata_bsf,
+ #endif
++#if CONFIG_TEXT2MOVSUB_BSF
++    &ff_text2movsub_bsf,
++#endif
++#if CONFIG_VP9_SUPERFRAME_BSF
++    &ff_vp9_superframe_bsf,
++#endif
+     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 --cc libavcodec/bsf.c
index 0000000,284c7c8..88b7f29
mode 000000,100644..100644
--- a/libavcodec/bsf.c
+++ b/libavcodec/bsf.c
@@@ -1,0 -1,219 +1,219 @@@
+ /*
 - * This file is part of Libav.
++ * This file is part of FFmpeg.
+  *
 - * Libav is free software; you can redistribute it and/or
++ * FFmpeg 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,
++ * FFmpeg 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
++ * License along with FFmpeg; 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 --cc libavcodec/bsf.h
index 0000000,9e05f0b..0ca64a7
mode 000000,100644..100644
--- a/libavcodec/bsf.h
+++ b/libavcodec/bsf.h
@@@ -1,0 -1,33 +1,33 @@@
+ /*
 - * This file is part of Libav.
++ * This file is part of FFmpeg.
+  *
 - * Libav is free software; you can redistribute it and/or
++ * FFmpeg 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,
++ * FFmpeg 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
++ * License along with FFmpeg; 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 --cc libavcodec/dca_core_bsf.c
index 7d37236,0000000..9edc0cf
mode 100644,000000..100644
--- a/libavcodec/dca_core_bsf.c
+++ b/libavcodec/dca_core_bsf.c
@@@ -1,60 -1,0 +1,66 @@@
 +/*
 + * Copyright (c) 2016 Paul B Mahol
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg 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.
 + *
 + * FFmpeg 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 FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "avcodec.h"
++#include "bsf.h"
 +#include "bytestream.h"
 +#include "dca_syncwords.h"
 +#include "libavutil/mem.h"
 +
- static int dca_core(AVBitStreamFilterContext *bsfc,
-                     AVCodecContext *avctx, const char *args,
-                     uint8_t **poutbuf, int *poutbuf_size,
-                     const uint8_t *buf, int buf_size,
-                     int keyframe)
++static int dca_core_filter(AVBSFContext *ctx, AVPacket *out)
 +{
++    AVPacket *in;
 +    GetByteContext gb;
 +    uint32_t syncword;
-     int core_size = 0;
++    int core_size = 0, ret;
 +
-     bytestream2_init(&gb, buf, buf_size);
++    ret = ff_bsf_get_packet(ctx, &in);
++    if (ret < 0)
++        return ret;
++
++    bytestream2_init(&gb, in->data, in->size);
 +    syncword = bytestream2_get_be32(&gb);
 +    bytestream2_skip(&gb, 1);
 +
 +    switch (syncword) {
 +    case DCA_SYNCWORD_CORE_BE:
 +        core_size = ((bytestream2_get_be24(&gb) >> 4) & 0x3fff) + 1;
 +        break;
 +    }
 +
-     *poutbuf = (uint8_t *)buf;
++    av_packet_move_ref(out, in);
++    av_packet_free(&in);
 +
-     if (core_size > 0 && core_size <= buf_size) {
-         *poutbuf_size = core_size;
-     } else {
-         *poutbuf_size = buf_size;
++    if (core_size > 0 && core_size <= out->size) {
++        out->size = core_size;
 +    }
 +
 +    return 0;
 +}
 +
- AVBitStreamFilter ff_dca_core_bsf = {
-     .name   = "dca_core",
-     .filter = dca_core,
++static const enum AVCodecID codec_ids[] = {
++    AV_CODEC_ID_DTS, AV_CODEC_ID_NONE,
++};
++
++const AVBitStreamFilter ff_dca_core_bsf = {
++    .name      = "dca_core",
++    .filter    = dca_core_filter,
++    .codec_ids = codec_ids,
 +};
diff --cc libavcodec/h264_mp4toannexb_bsf.c
index 2d447f7,c1e2a28..828bf18
--- a/libavcodec/h264_mp4toannexb_bsf.c
+++ b/libavcodec/h264_mp4toannexb_bsf.c
@@@ -23,31 -23,17 +23,21 @@@
  
  #include "libavutil/intreadwrite.h"
  #include "libavutil/mem.h"
+ 
  #include "avcodec.h"
+ #include "bsf.h"
  
  typedef struct H264BSFContext {
 +    int32_t  sps_offset;
 +    int32_t  pps_offset;
      uint8_t  length_size;
 -    uint8_t  first_idr;
 +    uint8_t  new_idr;
 +    uint8_t  idr_sps_seen;
 +    uint8_t  idr_pps_seen;
      int      extradata_parsed;
- 
-     /* When private_spspps is zero then spspps_buf points to global extradata
-        and bsf does replace a global extradata to own-allocated version (default
-        behaviour).
-        When private_spspps is non-zero the bsf uses a private version of spspps buf.
-        This mode necessary when bsf uses in decoder, else bsf has issues after
-        decoder re-initialization. Use the "private_spspps_buf" argument to
-        activate this mode.
-      */
-     int      private_spspps;
-     uint8_t *spspps_buf;
-     uint32_t spspps_size;
  } H264BSFContext;
  
- static int alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size,
+ static int alloc_and_copy(AVPacket *out,
                            const uint8_t *sps_pps, uint32_t sps_pps_size,
                            const uint8_t *in, uint32_t in_size)
  {
@@@ -75,8 -59,8 +63,9 @@@
      return 0;
  }
  
- static int h264_extradata_to_annexb(H264BSFContext *ctx, AVCodecContext *avctx, const int padding)
+ static int h264_extradata_to_annexb(AVBSFContext *ctx, const int padding)
  {
++    H264BSFContext *s = ctx->priv_data;
      uint16_t unit_size;
      uint64_t total_size                 = 0;
      uint8_t *out                        = NULL, unit_nb, sps_done = 0,
@@@ -85,14 -69,18 +74,14 @@@
      static const uint8_t nalu_header[4] = { 0, 0, 0, 1 };
      int length_size = (*extradata++ & 0x3) + 1; // retrieve length coded size
  
-     ctx->sps_offset = ctx->pps_offset = -1;
 -    if (length_size == 3)
 -        return AVERROR(EINVAL);
++    s->sps_offset = s->pps_offset = -1;
  
      /* retrieve sps and pps unit(s) */
      unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */
      if (!unit_nb) {
 -        unit_nb = *extradata++; /* number of pps unit(s) */
 -        sps_done++;
 -
 -        if (unit_nb)
 -            pps_seen = 1;
 +        goto pps;
      } else {
-         ctx->sps_offset = 0;
++        s->sps_offset = 0;
          sps_seen = 1;
      }
  
@@@ -101,15 -89,9 +90,15 @@@
  
          unit_size   = AV_RB16(extradata);
          total_size += unit_size + 4;
 -        if (total_size > INT_MAX - padding ||
 -            extradata + 2 + unit_size > ctx->par_in->extradata +
 -            ctx->par_in->extradata_size) {
 +        if (total_size > INT_MAX - padding) {
-             av_log(avctx, AV_LOG_ERROR,
++            av_log(ctx, AV_LOG_ERROR,
 +                   "Too big extradata size, corrupted stream or invalid MP4/AVCC bitstream\n");
 +            av_free(out);
 +            return AVERROR(EINVAL);
 +        }
-         if (extradata + 2 + unit_size > avctx->extradata + avctx->extradata_size) {
-             av_log(avctx, AV_LOG_ERROR, "Packet header is not contained in global extradata, "
++        if (extradata + 2 + unit_size > ctx->par_in->extradata + ctx->par_in->extradata_size) {
++            av_log(ctx, AV_LOG_ERROR, "Packet header is not contained in global extradata, "
 +                   "corrupted stream or invalid MP4/AVCC bitstream\n");
              av_free(out);
              return AVERROR(EINVAL);
          }
@@@ -118,21 -100,19 +107,21 @@@
          memcpy(out + total_size - unit_size - 4, nalu_header, 4);
          memcpy(out + total_size - unit_size, extradata + 2, unit_size);
          extradata += 2 + unit_size;
 -
 +pps:
          if (!unit_nb && !sps_done++) {
              unit_nb = *extradata++; /* number of pps unit(s) */
 -            if (unit_nb)
 +            if (unit_nb) {
-                 ctx->pps_offset = total_size;
++                s->pps_offset = total_size;
                  pps_seen = 1;
 +            }
          }
      }
  
      if (out)
 -        memset(out + total_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
 +        memset(out + total_size, 0, padding);
  
      if (!sps_seen)
-         av_log(avctx, AV_LOG_WARNING,
+         av_log(ctx, AV_LOG_WARNING,
                 "Warning: SPS NALU missing or invalid. "
                 "The resulting stream may not play.\n");
  
@@@ -152,123 -128,98 +137,136 @@@
      return length_size;
  }
  
- static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
-                                    AVCodecContext *avctx, const char *args,
-                                    uint8_t **poutbuf, int *poutbuf_size,
-                                    const uint8_t *buf, int buf_size,
-                                    int keyframe)
+ static int h264_mp4toannexb_init(AVBSFContext *ctx)
  {
-     H264BSFContext *ctx = bsfc->priv_data;
-     int i;
+     H264BSFContext *s = ctx->priv_data;
+     int ret;
+ 
+     /* retrieve sps and pps NAL units from extradata */
+     if (ctx->par_in->extradata_size >= 6) {
+         ret = h264_extradata_to_annexb(ctx, AV_INPUT_BUFFER_PADDING_SIZE);
+         if (ret < 0)
+             return ret;
+ 
+         s->length_size      = ret;
 -        s->first_idr        = 1;
++        s->new_idr          = 1;
++        s->idr_sps_seen     = 0;
++        s->idr_pps_seen     = 0;
+         s->extradata_parsed = 1;
+     }
+ 
+     return 0;
+ }
+ 
+ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
+ {
+     H264BSFContext *s = ctx->priv_data;
+ 
+     AVPacket *in;
      uint8_t unit_type;
      int32_t nal_size;
      uint32_t cumul_size    = 0;
-     const uint8_t *buf_end = buf + buf_size;
-     int ret = 0;
+     const uint8_t *buf;
+     const uint8_t *buf_end;
+     int            buf_size;
 -    int ret = 0;
++    int ret = 0, i;
+ 
+     ret = ff_bsf_get_packet(ctx, &in);
+     if (ret < 0)
+         return ret;
  
      /* nothing to filter */
-     if (!avctx->extradata || avctx->extradata_size < 6) {
-         *poutbuf      = (uint8_t *)buf;
-         *poutbuf_size = buf_size;
+     if (!s->extradata_parsed) {
+         av_packet_move_ref(out, in);
+         av_packet_free(&in);
          return 0;
      }
  
-     /* retrieve sps and pps NAL units from extradata */
-     if (!ctx->extradata_parsed) {
-         if (args && strstr(args, "private_spspps_buf"))
-             ctx->private_spspps = 1;
+     buf      = in->data;
+     buf_size = in->size;
+     buf_end  = in->data + in->size;
  
-         ret = h264_extradata_to_annexb(ctx, avctx, AV_INPUT_BUFFER_PADDING_SIZE);
-         if (ret < 0)
-             return ret;
-         ctx->length_size      = ret;
-         ctx->new_idr          = 1;
-         ctx->idr_sps_seen     = 0;
-         ctx->idr_pps_seen     = 0;
-         ctx->extradata_parsed = 1;
-     }
- 
-     *poutbuf_size = 0;
-     *poutbuf      = NULL;
      do {
 +        ret= AVERROR(EINVAL);
-         if (buf + ctx->length_size > buf_end)
+         if (buf + s->length_size > buf_end)
              goto fail;
  
-         for (nal_size = 0, i = 0; i<ctx->length_size; i++)
 -        if (s->length_size == 1) {
 -            nal_size = buf[0];
 -        } else if (s->length_size == 2) {
 -            nal_size = AV_RB16(buf);
 -        } else
 -            nal_size = AV_RB32(buf);
++        for (nal_size = 0, i = 0; i<s->length_size; i++)
 +            nal_size = (nal_size << 8) | buf[i];
  
-         buf      += ctx->length_size;
+         buf += s->length_size;
          unit_type = *buf & 0x1f;
  
 -        if (buf + nal_size > buf_end || nal_size < 0)
 +        if (nal_size > buf_end - buf || nal_size < 0)
              goto fail;
  
 -        /* prepend only to the first type 5 NAL unit of an IDR picture */
 -        if (s->first_idr && unit_type == 5) {
 -            if (alloc_and_copy(out,
 +        if (unit_type == 7)
-             ctx->idr_sps_seen = ctx->new_idr = 1;
++            s->idr_sps_seen = s->new_idr = 1;
 +        else if (unit_type == 8) {
-             ctx->idr_pps_seen = ctx->new_idr = 1;
++            s->idr_pps_seen = s->new_idr = 1;
 +            /* if SPS has not been seen yet, prepend the AVCC one to PPS */
-             if (!ctx->idr_sps_seen) {
-                 if (ctx->sps_offset == -1)
-                     av_log(avctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n");
++            if (!s->idr_sps_seen) {
++                if (s->sps_offset == -1)
++                    av_log(ctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n");
 +                else {
-                     if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
-                                          ctx->spspps_buf + ctx->sps_offset,
-                                          ctx->pps_offset != -1 ? ctx->pps_offset : ctx->spspps_size - ctx->sps_offset,
++                    if ((ret = alloc_and_copy(out,
++                                         ctx->par_out->extradata + s->sps_offset,
++                                         s->pps_offset != -1 ? s->pps_offset : ctx->par_out->extradata_size - s->sps_offset,
 +                                         buf, nal_size)) < 0)
 +                        goto fail;
-                     ctx->idr_sps_seen = 1;
++                    s->idr_sps_seen = 1;
 +                    goto next_nal;
 +                }
 +            }
 +        }
 +
 +        /* if this is a new IDR picture following an IDR picture, reset the idr flag.
 +         * Just check first_mb_in_slice to be 0 as this is the simplest solution.
 +         * This could be checking idr_pic_id instead, but would complexify the parsing. */
-         if (!ctx->new_idr && unit_type == 5 && (buf[1] & 0x80))
-             ctx->new_idr = 1;
++        if (!s->new_idr && unit_type == 5 && (buf[1] & 0x80))
++            s->new_idr = 1;
 +
 +        /* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */
-         if (ctx->new_idr && unit_type == 5 && !ctx->idr_sps_seen && !ctx->idr_pps_seen) {
-             if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
-                                ctx->spspps_buf, ctx->spspps_size,
++        if (s->new_idr && unit_type == 5 && !s->idr_sps_seen && !s->idr_pps_seen) {
++            if ((ret=alloc_and_copy(out,
+                                ctx->par_out->extradata, ctx->par_out->extradata_size,
 -                               buf, nal_size) < 0)
 +                               buf, nal_size)) < 0)
 +                goto fail;
-             ctx->new_idr = 0;
++            s->new_idr = 0;
 +        /* if only SPS has been seen, also insert PPS */
-         } else if (ctx->new_idr && unit_type == 5 && ctx->idr_sps_seen && !ctx->idr_pps_seen) {
-             if (ctx->pps_offset == -1) {
-                 av_log(avctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n");
-                 if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
-                                      NULL, 0, buf, nal_size)) < 0)
++        } else if (s->new_idr && unit_type == 5 && s->idr_sps_seen && !s->idr_pps_seen) {
++            if (s->pps_offset == -1) {
++                av_log(ctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n");
++                if ((ret = alloc_and_copy(out, NULL, 0, buf, nal_size)) < 0)
 +                    goto fail;
-             } else if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
-                                         ctx->spspps_buf + ctx->pps_offset, ctx->spspps_size - ctx->pps_offset,
++            } else if ((ret = alloc_and_copy(out,
++                                        ctx->par_out->extradata + s->pps_offset, ctx->par_out->extradata_size - s->pps_offset,
 +                                        buf, nal_size)) < 0)
                  goto fail;
 -            s->first_idr = 0;
          } else {
-             if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
-                                NULL, 0, buf, nal_size)) < 0)
 -            if (alloc_and_copy(out,
 -                               NULL, 0, buf, nal_size) < 0)
++            if ((ret=alloc_and_copy(out, NULL, 0, buf, nal_size)) < 0)
                  goto fail;
-             if (!ctx->new_idr && unit_type == 1) {
-                 ctx->new_idr = 1;
-                 ctx->idr_sps_seen = 0;
-                 ctx->idr_pps_seen = 0;
 -            if (!s->first_idr && unit_type == 1)
 -                s->first_idr = 1;
++            if (!s->new_idr && unit_type == 1) {
++                s->new_idr = 1;
++                s->idr_sps_seen = 0;
++                s->idr_pps_seen = 0;
 +            }
          }
  
 +next_nal:
          buf        += nal_size;
-         cumul_size += nal_size + ctx->length_size;
+         cumul_size += nal_size + s->length_size;
      } while (cumul_size < buf_size);
  
-     return 1;
+     ret = av_packet_copy_props(out, in);
+     if (ret < 0)
+         goto fail;
  
  fail:
-     av_freep(poutbuf);
-     *poutbuf_size = 0;
+     if (ret < 0)
+         av_packet_unref(out);
+     av_packet_free(&in);
+ 
      return ret;
  }
  
diff --cc libavcodec/hevc_mp4toannexb_bsf.c
index d6feb99,8d7ac58..5cc642b
--- a/libavcodec/hevc_mp4toannexb_bsf.c
+++ b/libavcodec/hevc_mp4toannexb_bsf.c
@@@ -56,9 -43,9 +43,9 @@@ static int hevc_extradata_to_annexb(AVB
      int ret = 0;
  
      uint8_t *new_extradata = NULL;
 -    size_t   new_extradata_size = 0;;
 +    size_t   new_extradata_size = 0;
  
-     bytestream2_init(&gb, avctx->extradata, avctx->extradata_size);
+     bytestream2_init(&gb, ctx->par_in->extradata, ctx->par_in->extradata_size);
  
      bytestream2_skip(&gb, 21);
      length_size = (bytestream2_get_byte(&gb) & 3) + 1;
diff --cc libavcodec/mjpeg2jpeg_bsf.c
index 92dc3ca,eec3469..2d4cee2
--- a/libavcodec/mjpeg2jpeg_bsf.c
+++ b/libavcodec/mjpeg2jpeg_bsf.c
@@@ -28,11 -28,10 +28,12 @@@
  
  #include "libavutil/error.h"
  #include "libavutil/mem.h"
 +#include "libavutil/intreadwrite.h"
  
  #include "avcodec.h"
+ #include "bsf.h"
  #include "jpegtables.h"
 +#include "mjpeg.h"
  
  static const uint8_t jpeg_header[] = {
      0xff, 0xd8,                     // SOI
@@@ -77,46 -76,56 +78,64 @@@ static uint8_t *append_dht_segment(uint
      return buf;
  }
  
- static int mjpeg2jpeg_filter(AVBitStreamFilterContext *bsfc,
-                              AVCodecContext *avctx, const char *args,
-                              uint8_t **poutbuf, int *poutbuf_size,
-                              const uint8_t *buf, int buf_size,
-                              int keyframe)
+ static int mjpeg2jpeg_filter(AVBSFContext *ctx, AVPacket *out)
  {
+     AVPacket *in;
+     int ret = 0;
      int input_skip, output_size;
-     uint8_t *output, *out;
+     uint8_t *output;
  
-     if (buf_size < 12) {
-         av_log(avctx, AV_LOG_ERROR, "input is truncated\n");
-         return AVERROR_INVALIDDATA;
+     ret = ff_bsf_get_packet(ctx, &in);
+ 
+     if (in->size < 12) {
+         av_log(ctx, AV_LOG_ERROR, "input is truncated\n");
+         ret = AVERROR_INVALIDDATA;
+         goto fail;
      }
-     if (AV_RB16(buf) != 0xffd8) {
-         av_log(avctx, AV_LOG_ERROR, "input is not MJPEG\n");
-         return AVERROR_INVALIDDATA;
 -    if (memcmp("AVI1", in->data + 6, 4)) {
 -        av_log(ctx, AV_LOG_ERROR, "input is not MJPEG/AVI1\n");
++    if (AV_RB16(in->data) != 0xffd8) {
++        av_log(ctx, AV_LOG_ERROR, "input is not MJPEG\n");
+         ret = AVERROR_INVALIDDATA;
+         goto fail;
      }
-     if (buf[2] == 0xff && buf[3] == APP0) {
-         input_skip = (buf[4] << 8) + buf[5] + 4;
 -
 -    input_skip = (in->data[4] << 8) + in->data[5] + 4;
++    if (in->data[2] == 0xff && in->data[3] == APP0) {
++        input_skip = (in->data[4] << 8) + in->data[5] + 4;
 +    } else {
 +        input_skip = 2;
 +    }
-     if (buf_size < input_skip) {
-         av_log(avctx, AV_LOG_ERROR, "input is truncated\n");
-         return AVERROR_INVALIDDATA;
+     if (in->size < input_skip) {
+         av_log(ctx, AV_LOG_ERROR, "input is truncated\n");
+         ret = AVERROR_INVALIDDATA;
+         goto fail;
      }
-     output_size = buf_size - input_skip +
+     output_size = in->size - input_skip +
                    sizeof(jpeg_header) + dht_segment_size;
-     output = out = av_malloc(output_size);
-     if (!output)
-         return AVERROR(ENOMEM);
-     out = append(out, jpeg_header, sizeof(jpeg_header));
-     out = append_dht_segment(out);
-     out = append(out, buf + input_skip, buf_size - input_skip);
-     *poutbuf = output;
-     *poutbuf_size = output_size;
-     return 1;
+     ret = av_new_packet(out, output_size);
+     if (ret < 0)
+         goto fail;
+ 
+     output = out->data;
+ 
+     output = append(output, jpeg_header, sizeof(jpeg_header));
+     output = append_dht_segment(output);
+     output = append(output, in->data + input_skip, in->size - input_skip);
+ 
+     ret = av_packet_copy_props(out, in);
+     if (ret < 0)
+         goto fail;
+ 
+ fail:
+     if (ret < 0)
+         av_packet_unref(out);
+     av_packet_free(&in);
+     return ret;
  }
  
- AVBitStreamFilter ff_mjpeg2jpeg_bsf = {
++static const enum AVCodecID codec_ids[] = {
++    AV_CODEC_ID_MJPEG, AV_CODEC_ID_NONE,
++};
++
+ const AVBitStreamFilter ff_mjpeg2jpeg_bsf = {
      .name           = "mjpeg2jpeg",
      .filter         = mjpeg2jpeg_filter,
++    .codec_ids      = codec_ids,
  };
diff --cc libavcodec/mp3_header_decompress_bsf.c
index 95c0b5b,0000000..22c1ef0
mode 100644,000000..100644
--- a/libavcodec/mp3_header_decompress_bsf.c
+++ b/libavcodec/mp3_header_decompress_bsf.c
@@@ -1,97 -1,0 +1,124 @@@
 +/*
 + * copyright (c) 2006 Michael Niedermayer <michaelni at gmx.at>
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg 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.
 + *
 + * FFmpeg 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 FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "libavutil/common.h"
 +#include "libavutil/intreadwrite.h"
 +#include "avcodec.h"
++#include "bsf.h"
 +#include "mpegaudiodecheader.h"
 +#include "mpegaudiodata.h"
 +
 +
- static int mp3_header_decompress(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                      uint8_t **poutbuf, int *poutbuf_size,
-                      const uint8_t *buf, int buf_size, int keyframe){
++static int mp3_header_decompress(AVBSFContext *ctx, AVPacket *out)
++{
++    AVPacket *in;
 +    uint32_t header;
-     int sample_rate= avctx->sample_rate;
++    int sample_rate= ctx->par_in->sample_rate;
 +    int sample_rate_index=0;
-     int lsf, mpeg25, bitrate_index, frame_size;
++    int lsf, mpeg25, bitrate_index, frame_size, ret;
++    uint8_t *buf;
++    int buf_size;
++
++    ret = ff_bsf_get_packet(ctx, &in);
++    if (ret < 0)
++        return ret;
++
++    buf      = in->data;
++    buf_size = in->size;
 +
 +    header = AV_RB32(buf);
 +    if(ff_mpa_check_header(header) >= 0){
-         *poutbuf= (uint8_t *) buf;
-         *poutbuf_size= buf_size;
++        av_packet_move_ref(out, in);
++        av_packet_free(&in);
 +
 +        return 0;
 +    }
 +
-     if(avctx->extradata_size != 15 || strcmp(avctx->extradata, "FFCMP3 0.0")){
-         av_log(avctx, AV_LOG_ERROR, "Extradata invalid %d\n", avctx->extradata_size);
-         return -1;
++    if(ctx->par_in->extradata_size != 15 || strcmp(ctx->par_in->extradata, "FFCMP3 0.0")){
++        av_log(ctx, AV_LOG_ERROR, "Extradata invalid %d\n", ctx->par_in->extradata_size);
++        ret = AVERROR(EINVAL);
++        goto fail;
 +    }
 +
-     header= AV_RB32(avctx->extradata+11) & MP3_MASK;
++    header= AV_RB32(ctx->par_in->extradata+11) & MP3_MASK;
 +
 +    lsf     = sample_rate < (24000+32000)/2;
 +    mpeg25  = sample_rate < (12000+16000)/2;
 +    sample_rate_index= (header>>10)&3;
 +    sample_rate= avpriv_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); //in case sample rate is a little off
 +
 +    for(bitrate_index=2; bitrate_index<30; bitrate_index++){
 +        frame_size = avpriv_mpa_bitrate_tab[lsf][2][bitrate_index>>1];
 +        frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index&1);
 +        if(frame_size == buf_size + 4)
 +            break;
 +        if(frame_size == buf_size + 6)
 +            break;
 +    }
 +    if(bitrate_index == 30){
-         av_log(avctx, AV_LOG_ERROR, "Could not find bitrate_index.\n");
-         return -1;
++        av_log(ctx, AV_LOG_ERROR, "Could not find bitrate_index.\n");
++        ret = AVERROR(EINVAL);
++        goto fail;
 +    }
 +
 +    header |= (bitrate_index&1)<<9;
 +    header |= (bitrate_index>>1)<<12;
 +    header |= (frame_size == buf_size + 4)<<16; //FIXME actually set a correct crc instead of 0
 +
-     *poutbuf_size= frame_size;
-     *poutbuf= av_malloc(frame_size + AV_INPUT_BUFFER_PADDING_SIZE);
-     memcpy(*poutbuf + frame_size - buf_size, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
++    ret = av_new_packet(out, frame_size);
++    if (ret < 0)
++        goto fail;
++    ret = av_packet_copy_props(out, in);
++    if (ret < 0) {
++        av_packet_free(&out);
++        goto fail;
++    }
++    memcpy(out->data + frame_size - buf_size, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
 +
-     if(avctx->channels==2){
-         uint8_t *p= *poutbuf + frame_size - buf_size;
++    if(ctx->par_in->channels==2){
++        uint8_t *p= out->data + frame_size - buf_size;
 +        if(lsf){
 +            FFSWAP(int, p[1], p[2]);
 +            header |= (p[1] & 0xC0)>>2;
 +            p[1] &= 0x3F;
 +        }else{
 +            header |= p[1] & 0x30;
 +            p[1] &= 0xCF;
 +        }
 +    }
 +
-     AV_WB32(*poutbuf, header);
++    AV_WB32(out->data, header);
 +
-     return 1;
++    ret = 0;
++
++fail:
++    av_packet_free(&in);
++    return ret;
 +}
 +
- AVBitStreamFilter ff_mp3_header_decompress_bsf={
-     .name   = "mp3decomp",
-     .filter = mp3_header_decompress,
++static const enum AVCodecID codec_ids[] = {
++    AV_CODEC_ID_MP3, AV_CODEC_ID_NONE,
++};
++
++const AVBitStreamFilter ff_mp3_header_decompress_bsf = {
++    .name      = "mp3decomp",
++    .filter    = mp3_header_decompress,
++    .codec_ids = codec_ids,
 +};
diff --cc libavcodec/mpeg4_unpack_bframes_bsf.c
index df49d3f,0000000..0615621
mode 100644,000000..100644
--- a/libavcodec/mpeg4_unpack_bframes_bsf.c
+++ b/libavcodec/mpeg4_unpack_bframes_bsf.c
@@@ -1,194 -1,0 +1,191 @@@
 +/*
 + * Bitstream filter for unpacking DivX-style packed B-frames in MPEG-4 (divx_packed)
 + * Copyright (c) 2015 Andreas Cadhalpun <Andreas.Cadhalpun at googlemail.com>
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg 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.
 + *
 + * FFmpeg 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 FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "avcodec.h"
++#include "bsf.h"
 +#include "mpeg4video.h"
 +
 +typedef struct UnpackBFramesBSFContext {
 +    uint8_t *b_frame_buf;
 +    int      b_frame_buf_size;
-     int      updated_extradata;
 +} UnpackBFramesBSFContext;
 +
 +/* search next start code */
 +static unsigned int find_startcode(const uint8_t *buf, int buf_size, int *pos)
 +{
 +    unsigned int startcode = 0xFF;
 +
 +    for (; *pos < buf_size;) {
 +        startcode = ((startcode << 8) | buf[*pos]) & 0xFFFFFFFF;
 +        *pos +=1;
 +        if ((startcode & 0xFFFFFF00) != 0x100)
 +            continue;  /* no startcode */
 +        return startcode;
 +    }
 +
 +    return 0;
 +}
 +
 +/* determine the position of the packed marker in the userdata,
 + * the number of VOPs and the position of the second VOP */
 +static void scan_buffer(const uint8_t *buf, int buf_size,
 +                        int *pos_p, int *nb_vop, int *pos_vop2) {
 +    unsigned int startcode;
 +    int pos, i;
 +
 +    for (pos = 0; pos < buf_size;) {
 +        startcode = find_startcode(buf, buf_size, &pos);
 +
 +        if (startcode == USER_DATA_STARTCODE && pos_p) {
 +            /* check if the (DivX) userdata string ends with 'p' (packed) */
 +            for (i = 0; i < 255 && pos + i + 1 < buf_size; i++) {
 +                if (buf[pos + i] == 'p' && buf[pos + i + 1] == '\0') {
 +                    *pos_p = pos + i;
 +                    break;
 +                }
 +            }
 +        } else if (startcode == VOP_STARTCODE && nb_vop) {
 +            *nb_vop += 1;
 +            if (*nb_vop == 2 && pos_vop2) {
 +                *pos_vop2 = pos - 4; /* subtract 4 bytes startcode */
 +            }
 +        }
 +    }
 +}
 +
 +/* allocate new buffer and copy size bytes from src */
 +static uint8_t *create_new_buffer(const uint8_t *src, int size) {
 +    uint8_t *dst = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
 +
 +    if (dst) {
 +        memcpy(dst, src, size);
 +        memset(dst + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
 +    }
 +
 +    return dst;
 +}
 +
- static int mpeg4_unpack_bframes_filter(AVBitStreamFilterContext *bsfc,
-                                        AVCodecContext *avctx, const char *args,
-                                        uint8_t  **poutbuf, int *poutbuf_size,
-                                        const uint8_t *buf, int      buf_size,
-                                        int keyframe)
++static int mpeg4_unpack_bframes_filter(AVBSFContext *ctx, AVPacket *out)
 +{
-     UnpackBFramesBSFContext *ctx = bsfc->priv_data;
++    UnpackBFramesBSFContext *s = ctx->priv_data;
 +    int pos_p = -1, nb_vop = 0, pos_vop2 = -1, ret = 0;
++    AVPacket *in;
 +
-     if (avctx->codec_id != AV_CODEC_ID_MPEG4) {
-         av_log(avctx, AV_LOG_ERROR,
-                "The mpeg4_unpack_bframes bitstream filter is only useful for mpeg4.\n");
-         return AVERROR(EINVAL);
-     }
- 
-     if (!ctx->updated_extradata && avctx->extradata) {
-         int pos_p_ext = -1;
-         scan_buffer(avctx->extradata, avctx->extradata_size, &pos_p_ext, NULL, NULL);
-         if (pos_p_ext >= 0) {
-             av_log(avctx, AV_LOG_DEBUG,
-                    "Updating DivX userdata (remove trailing 'p') in extradata.\n");
-             avctx->extradata[pos_p_ext] = '\0';
-         }
-         ctx->updated_extradata = 1;
-     }
++    ret = ff_bsf_get_packet(ctx, &in);
++    if (ret < 0)
++        return ret;
 +
-     scan_buffer(buf, buf_size, &pos_p, &nb_vop, &pos_vop2);
-     av_log(avctx, AV_LOG_DEBUG, "Found %d VOP startcode(s) in this packet.\n", nb_vop);
++    scan_buffer(in->data, in->size, &pos_p, &nb_vop, &pos_vop2);
++    av_log(ctx, AV_LOG_DEBUG, "Found %d VOP startcode(s) in this packet.\n", nb_vop);
 +
 +    if (pos_vop2 >= 0) {
-         if (ctx->b_frame_buf) {
-             av_log(avctx, AV_LOG_WARNING,
++        if (s->b_frame_buf) {
++            av_log(ctx, AV_LOG_WARNING,
 +                   "Missing one N-VOP packet, discarding one B-frame.\n");
-             av_freep(&ctx->b_frame_buf);
-             ctx->b_frame_buf_size = 0;
++            av_freep(&s->b_frame_buf);
++            s->b_frame_buf_size = 0;
 +        }
 +        /* store the packed B-frame in the BSFContext */
-         ctx->b_frame_buf_size = buf_size - pos_vop2;
-         ctx->b_frame_buf      = create_new_buffer(buf + pos_vop2, ctx->b_frame_buf_size);
-         if (!ctx->b_frame_buf) {
-             ctx->b_frame_buf_size = 0;
++        s->b_frame_buf_size = in->size - pos_vop2;
++        s->b_frame_buf      = create_new_buffer(in->data + pos_vop2, s->b_frame_buf_size);
++        if (!s->b_frame_buf) {
++            s->b_frame_buf_size = 0;
++            av_packet_free(&in);
 +            return AVERROR(ENOMEM);
 +        }
 +    }
 +
 +    if (nb_vop > 2) {
-         av_log(avctx, AV_LOG_WARNING,
++        av_log(ctx, AV_LOG_WARNING,
 +       "Found %d VOP headers in one packet, only unpacking one.\n", nb_vop);
 +    }
 +
-     if (nb_vop == 1 && ctx->b_frame_buf) {
++    if (nb_vop == 1 && s->b_frame_buf) {
 +        /* use frame from BSFContext */
-         *poutbuf      = ctx->b_frame_buf;
-         *poutbuf_size = ctx->b_frame_buf_size;
-         /* the output buffer is distinct from the input buffer */
-         ret = 1;
-         if (buf_size <= MAX_NVOP_SIZE) {
++        av_packet_from_data(out, s->b_frame_buf, s->b_frame_buf_size);
++        if (in->size <= MAX_NVOP_SIZE) {
 +            /* N-VOP */
-             av_log(avctx, AV_LOG_DEBUG, "Skipping N-VOP.\n");
-             ctx->b_frame_buf      = NULL;
-             ctx->b_frame_buf_size = 0;
++            av_log(ctx, AV_LOG_DEBUG, "Skipping N-VOP.\n");
++            s->b_frame_buf      = NULL;
++            s->b_frame_buf_size = 0;
 +        } else {
 +            /* copy packet into BSFContext */
-             ctx->b_frame_buf_size = buf_size;
-             ctx->b_frame_buf      = create_new_buffer(buf , buf_size);
-             if (!ctx->b_frame_buf) {
-                 ctx->b_frame_buf_size = 0;
-                 av_freep(poutbuf);
-                 *poutbuf_size = 0;
++            s->b_frame_buf_size = in->size;
++            s->b_frame_buf      = create_new_buffer(in->data, in->size);
++            if (!s->b_frame_buf) {
++                s->b_frame_buf_size = 0;
++                av_packet_unref(out);
++                av_packet_free(&in);
 +                return AVERROR(ENOMEM);
 +            }
 +        }
 +    } else if (nb_vop >= 2) {
 +        /* use first frame of the packet */
-         *poutbuf      = (uint8_t *) buf;
-         *poutbuf_size = pos_vop2;
++        av_packet_move_ref(out, in);
++        out->size = pos_vop2;
 +    } else if (pos_p >= 0) {
-         av_log(avctx, AV_LOG_DEBUG, "Updating DivX userdata (remove trailing 'p').\n");
-         *poutbuf_size = buf_size;
-         *poutbuf      = create_new_buffer(buf, buf_size);
-         if (!*poutbuf) {
-             *poutbuf_size = 0;
-             return AVERROR(ENOMEM);
-         }
++        av_log(ctx, AV_LOG_DEBUG, "Updating DivX userdata (remove trailing 'p').\n");
++        av_packet_move_ref(out, in);
 +        /* remove 'p' (packed) from the end of the (DivX) userdata string */
-         (*poutbuf)[pos_p] = '\0';
-         /* the output buffer is distinct from the input buffer */
-         ret = 1;
++        out->data[pos_p] = '\0';
 +    } else {
 +        /* copy packet */
-         *poutbuf      = (uint8_t *) buf;
-         *poutbuf_size = buf_size;
++        av_packet_move_ref(out, in);
++    }
++
++    av_packet_free(&in);
++
++    return 0;
++}
++
++static int mpeg4_unpack_bframes_init(AVBSFContext *ctx)
++{
++    if (ctx->par_in->extradata) {
++        int pos_p_ext = -1;
++        scan_buffer(ctx->par_in->extradata, ctx->par_in->extradata_size, &pos_p_ext, NULL, NULL);
++        if (pos_p_ext >= 0) {
++            av_log(ctx, AV_LOG_DEBUG,
++                   "Updating DivX userdata (remove trailing 'p') in extradata.\n");
++            ctx->par_out->extradata[pos_p_ext] = '\0';
++        }
 +    }
 +
-     return ret;
++    return 0;
 +}
 +
- static void mpeg4_unpack_bframes_close(AVBitStreamFilterContext *bsfc)
++static void mpeg4_unpack_bframes_close(AVBSFContext *bsfc)
 +{
 +    UnpackBFramesBSFContext *ctx = bsfc->priv_data;
 +    av_freep(&ctx->b_frame_buf);
 +}
 +
- AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf = {
++static const enum AVCodecID codec_ids[] = {
++    AV_CODEC_ID_MPEG4, AV_CODEC_ID_NONE,
++};
++
++const AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf = {
 +    .name           = "mpeg4_unpack_bframes",
 +    .priv_data_size = sizeof(UnpackBFramesBSFContext),
++    .init           = mpeg4_unpack_bframes_init,
 +    .filter         = mpeg4_unpack_bframes_filter,
-     .close          = mpeg4_unpack_bframes_close
++    .close          = mpeg4_unpack_bframes_close,
++    .codec_ids      = codec_ids,
 +};
diff --cc libavcodec/noise_bsf.c
index 556ad5c,3b41dbf..9b4f4e4
--- a/libavcodec/noise_bsf.c
+++ b/libavcodec/noise_bsf.c
@@@ -22,34 -22,67 +22,70 @@@
  #include <string.h>
  
  #include "avcodec.h"
+ #include "bsf.h"
+ 
+ #include "libavutil/log.h"
  #include "libavutil/mem.h"
+ #include "libavutil/opt.h"
  
+ typedef struct NoiseContext {
+     const AVClass *class;
+     int amount;
+     unsigned int state;
+ } NoiseContext;
  
- static int noise(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                      uint8_t **poutbuf, int *poutbuf_size,
-                      const uint8_t *buf, int buf_size, int keyframe){
-     unsigned int *state= bsfc->priv_data;
-     int amount= args ? atoi(args) : (*state % 10001+1);
-     int i;
+ static int noise(AVBSFContext *ctx, AVPacket *out)
+ {
+     NoiseContext *s = ctx->priv_data;
+     AVPacket *in;
+     int amount = s->amount > 0 ? s->amount : (s->state % 10001 + 1);
+     int i, ret = 0;
  
-     if(amount <= 0)
++    if (amount <= 0)
 +        return AVERROR(EINVAL);
 +
-     *poutbuf= av_malloc(buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
-     if (!*poutbuf)
-         return AVERROR(ENOMEM);
+     ret = ff_bsf_get_packet(ctx, &in);
+     if (ret < 0)
+         return ret;
+ 
+     ret = av_new_packet(out, in->size);
+     if (ret < 0)
+         goto fail;
+ 
+     ret = av_packet_copy_props(out, in);
+     if (ret < 0)
+         goto fail;
+ 
+     memcpy(out->data, in->data, in->size);
  
-     memcpy(*poutbuf, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
-     for(i=0; i<buf_size; i++){
-         (*state) += (*poutbuf)[i] + 1;
-         if(*state % amount == 0)
-             (*poutbuf)[i] = *state;
+     for (i = 0; i < out->size; i++) {
+         s->state += out->data[i] + 1;
+         if (s->state % amount == 0)
+             out->data[i] = s->state;
      }
-     return 1;
+ fail:
+     if (ret < 0)
+         av_packet_unref(out);
+     av_packet_free(&in);
+     return ret;
  }
  
- AVBitStreamFilter ff_noise_bsf={
+ #define OFFSET(x) offsetof(NoiseContext, x)
+ static const AVOption options[] = {
+     { "amount", NULL, OFFSET(amount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX },
+     { NULL },
+ };
+ 
+ static const AVClass noise_class = {
+     .class_name = "noise",
+     .item_name  = av_default_item_name,
+     .option     = options,
+     .version    = LIBAVUTIL_VERSION_INT,
+ };
+ 
+ const AVBitStreamFilter ff_noise_bsf = {
      .name           = "noise",
      .priv_data_size = sizeof(int),
+     .priv_class     = &noise_class,
      .filter         = noise,
  };
diff --cc libavcodec/version.h
index c24f0fc,d5045fb..b8ef9c5
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@@ -27,9 -27,9 +27,9 @@@
  
  #include "libavutil/version.h"
  
 -#define LIBAVCODEC_VERSION_MAJOR 57
 -#define LIBAVCODEC_VERSION_MINOR 15
 -#define LIBAVCODEC_VERSION_MICRO  0
 +#define LIBAVCODEC_VERSION_MAJOR  57
- #define LIBAVCODEC_VERSION_MINOR  34
- #define LIBAVCODEC_VERSION_MICRO 102
++#define LIBAVCODEC_VERSION_MINOR  35
++#define LIBAVCODEC_VERSION_MICRO 100
  
  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                 LIBAVCODEC_VERSION_MINOR, \
@@@ -211,8 -194,11 +211,11 @@@
  #ifndef FF_API_PRIVATE_OPT
  #define FF_API_PRIVATE_OPT      (LIBAVCODEC_VERSION_MAJOR < 59)
  #endif
 +#ifndef FF_API_ASS_TIMING
 +#define FF_API_ASS_TIMING       (LIBAVCODEC_VERSION_MAJOR < 59)
 +#endif
+ #ifndef FF_API_OLD_BSF
+ #define FF_API_OLD_BSF          (LIBAVCODEC_VERSION_MAJOR < 59)
+ #endif
  
  #endif /* AVCODEC_VERSION_H */
diff --cc libavcodec/vp9_superframe_bsf.c
index d4a61ee,0000000..b686adb
mode 100644,000000..100644
--- a/libavcodec/vp9_superframe_bsf.c
+++ b/libavcodec/vp9_superframe_bsf.c
@@@ -1,189 -1,0 +1,205 @@@
 +/*
 + * Vp9 invisible (alt-ref) frame to superframe merge bitstream filter
 + * Copyright (c) 2016 Ronald S. Bultje <rsbultje at gmail.com>
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg 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.
 + *
 + * FFmpeg 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 FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "libavutil/avassert.h"
 +#include "avcodec.h"
++#include "bsf.h"
 +#include "get_bits.h"
 +
 +#define MAX_CACHE 8
 +typedef struct VP9BSFContext {
 +    int n_cache;
 +    struct CachedBuf {
 +        uint8_t *data;
 +        int size;
 +    } cache[MAX_CACHE];
 +} VP9BSFContext;
 +
 +static void stats(const struct CachedBuf *in, int n_in,
 +                  unsigned *_max, unsigned *_sum)
 +{
 +    int n;
 +    unsigned max = 0, sum = 0;
 +
 +    for (n = 0; n < n_in; n++) {
 +        unsigned sz = in[n].size;
 +
 +        if (sz > max)
 +            max = sz;
 +        sum += sz;
 +    }
 +
 +    *_max = max;
 +    *_sum = sum;
 +}
 +
- static int merge_superframe(const struct CachedBuf *in, int n_in,
-                             uint8_t **poutbuf, int *poutbuf_size)
++static int merge_superframe(const struct CachedBuf *in, int n_in, AVPacket *out)
 +{
 +    unsigned max, sum, mag, marker, n, sz;
 +    uint8_t *ptr;
++    int res;
 +
 +    stats(in, n_in, &max, &sum);
 +    mag = av_log2(max) >> 3;
 +    marker = 0xC0 + (mag << 3) + (n_in - 1);
-     sz = *poutbuf_size = sum + 2 + (mag + 1) * n_in;
-     ptr = *poutbuf = av_malloc(sz);
-     if (!ptr)
-         return AVERROR(ENOMEM);
- 
++    sz = sum + 2 + (mag + 1) * n_in;
++    res = av_new_packet(out, sz);
++    if (res < 0)
++        return res;
++    ptr = out->data;
 +    for (n = 0; n < n_in; n++) {
 +        memcpy(ptr, in[n].data, in[n].size);
 +        ptr += in[n].size;
 +    }
 +
 +#define wloop(mag, wr) \
 +    for (n = 0; n < n_in; n++) { \
 +        wr; \
 +        ptr += mag + 1; \
 +    }
 +
 +    // write superframe with marker 110[mag:2][nframes:3]
 +    *ptr++ = marker;
 +    switch (mag) {
 +    case 0:
 +        wloop(mag, *ptr = in[n].size);
 +        break;
 +    case 1:
 +        wloop(mag, AV_WL16(ptr, in[n].size));
 +        break;
 +    case 2:
 +        wloop(mag, AV_WL24(ptr, in[n].size));
 +        break;
 +    case 3:
 +        wloop(mag, AV_WL32(ptr, in[n].size));
 +        break;
 +    }
 +    *ptr++ = marker;
-     av_assert0(ptr == &(*poutbuf)[*poutbuf_size]);
++    av_assert0(ptr == &out->data[out->size]);
 +
 +    return 0;
 +}
 +
- static int vp9_superframe_filter(AVBitStreamFilterContext *bsfc,
-                                  AVCodecContext *avctx, const char *args,
-                                  uint8_t  **poutbuf, int *poutbuf_size,
-                                  const uint8_t *buf, int      buf_size,
-                                  int keyframe)
++static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out)
 +{
 +    GetBitContext gb;
-     VP9BSFContext *ctx = bsfc->priv_data;
++    VP9BSFContext *s = ctx->priv_data;
++    AVPacket *in;
 +    int res, invisible, profile, marker, uses_superframe_syntax = 0, n;
 +
-     marker = buf[buf_size - 1];
++    res = ff_bsf_get_packet(ctx, &in);
++    if (res < 0)
++        return res;
++
++    marker = in->data[in->size - 1];
 +    if ((marker & 0xe0) == 0xc0) {
 +        int nbytes = 1 + ((marker >> 3) & 0x3);
 +        int n_frames = 1 + (marker & 0x7), idx_sz = 2 + n_frames * nbytes;
 +
-         uses_superframe_syntax = buf_size >= idx_sz && buf[buf_size - idx_sz] == marker;
++        uses_superframe_syntax = in->size >= idx_sz && in->data[in->size - idx_sz] == marker;
 +    }
 +
-     if ((res = init_get_bits8(&gb, buf, buf_size)) < 0)
-         return res;
++    if ((res = init_get_bits8(&gb, in->data, in->size)) < 0)
++        goto done;
 +
 +    get_bits(&gb, 2); // frame marker
 +    profile  = get_bits1(&gb);
 +    profile |= get_bits1(&gb) << 1;
 +    if (profile == 3) profile += get_bits1(&gb);
 +
 +    if (get_bits1(&gb)) {
 +        invisible = 0;
 +    } else {
 +        get_bits1(&gb); // keyframe
 +        invisible = !get_bits1(&gb);
 +    }
 +
-     if (uses_superframe_syntax && ctx->n_cache > 0) {
-         av_log(avctx, AV_LOG_ERROR,
++    if (uses_superframe_syntax && s->n_cache > 0) {
++        av_log(ctx, AV_LOG_ERROR,
 +               "Mixing of superframe syntax and naked VP9 frames not supported");
-         return AVERROR_INVALIDDATA;
-     } else if ((!invisible || uses_superframe_syntax) && !ctx->n_cache) {
++        res = AVERROR_INVALIDDATA;
++        goto done;
++    } else if ((!invisible || uses_superframe_syntax) && !s->n_cache) {
 +        // passthrough
-         *poutbuf = (uint8_t *) buf;
-         *poutbuf_size = buf_size;
-         return 0;
-     } else if (ctx->n_cache + 1 >= MAX_CACHE) {
-         av_log(avctx, AV_LOG_ERROR,
++        av_packet_move_ref(out, in);
++        goto done;
++    } else if (s->n_cache + 1 >= MAX_CACHE) {
++        av_log(ctx, AV_LOG_ERROR,
 +               "Too many invisible frames");
-         return AVERROR_INVALIDDATA;
++        res = AVERROR_INVALIDDATA;
++        goto done;
 +    }
 +
-     ctx->cache[ctx->n_cache].size = buf_size;
++    s->cache[s->n_cache].size = in->size;
 +    if (invisible && !uses_superframe_syntax) {
-         ctx->cache[ctx->n_cache].data = av_malloc(buf_size);
-         if (!ctx->cache[ctx->n_cache].data)
-             return AVERROR(ENOMEM);
-         memcpy(ctx->cache[ctx->n_cache++].data, buf, buf_size);
-         *poutbuf = NULL;
-         *poutbuf_size = 0;
-         return 0;
++        s->cache[s->n_cache].data = av_malloc(in->size);
++        if (!s->cache[s->n_cache].data) {
++            res = AVERROR(ENOMEM);
++            goto done;
++        }
++        memcpy(s->cache[s->n_cache++].data, in->data, in->size);
++        res = AVERROR(EAGAIN);
++        goto done;
 +    }
-     av_assert0(ctx->n_cache > 0);
++    av_assert0(s->n_cache > 0);
 +
-     ctx->cache[ctx->n_cache].data = (uint8_t *) buf;
++    s->cache[s->n_cache].data = in->data;
 +
 +    // build superframe
-     if ((res = merge_superframe(ctx->cache, ctx->n_cache + 1,
-                                 poutbuf, poutbuf_size)) < 0)
-         return res;
- 
-     for (n = 0; n < ctx->n_cache; n++)
-         av_freep(&ctx->cache[n].data);
-     ctx->n_cache = 0;
- 
-     return 0;
++    if ((res = merge_superframe(s->cache, s->n_cache + 1, out)) < 0)
++        goto done;
++
++    for (n = 0; n < s->n_cache; n++)
++        av_freep(&s->cache[n].data);
++    s->n_cache = 0;
++
++    res = av_packet_copy_props(out, in);
++    if (res < 0)
++        goto done;
++
++done:
++    if (res < 0)
++        av_packet_unref(out);
++    av_packet_free(&in);
++    return res;
 +}
 +
- static void vp9_superframe_close(AVBitStreamFilterContext *bsfc)
++static void vp9_superframe_close(AVBSFContext *ctx)
 +{
-     VP9BSFContext *ctx = bsfc->priv_data;
++    VP9BSFContext *s = ctx->priv_data;
 +    int n;
 +
 +    // free cached data
-     for (n = 0; n < ctx->n_cache; n++)
-         av_freep(&ctx->cache[n].data);
++    for (n = 0; n < s->n_cache; n++)
++        av_freep(&s->cache[n].data);
 +}
 +
- AVBitStreamFilter ff_vp9_superframe_bsf = {
++static const enum AVCodecID codec_ids[] = {
++    AV_CODEC_ID_VP9, AV_CODEC_ID_NONE,
++};
++
++const AVBitStreamFilter ff_vp9_superframe_bsf = {
 +    .name           = "vp9_superframe",
 +    .priv_data_size = sizeof(VP9BSFContext),
 +    .filter         = vp9_superframe_filter,
 +    .close          = vp9_superframe_close,
++    .codec_ids      = codec_ids,
 +};
diff --cc libavformat/mux.c
index 33301f1,76662ee..6239fd1
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@@ -309,6 -143,6 +309,12 @@@ FF_DISABLE_DEPRECATION_WARNING
  FF_ENABLE_DEPRECATION_WARNINGS
  #endif
  
++        /* update internal context from codecpar, old bsf api needs this
++         * FIXME: remove when autobsf uses new bsf API */
++        ret = avcodec_parameters_to_context(st->internal->avctx, st->codecpar);
++        if (ret < 0)
++            goto fail;
++
          if (!st->time_base.num) {
              /* fall back on the default timebase values */
              if (par->codec_type == AVMEDIA_TYPE_AUDIO && par->sample_rate)




More information about the ffmpeg-cvslog mailing list