diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c
index dd52e4d366..97ef41e3fc 100644
--- a/libavformat/concatdec.c
+++ b/libavformat/concatdec.c
@@ -34,8 +34,7 @@ typedef enum ConcatMatchMode {
 } ConcatMatchMode;
 
 typedef struct ConcatStream {
-    AVBitStreamFilterContext *bsf;
-    AVCodecContext *avctx;
+    AVBSFContext *bsf;
     int out_stream_index;
 } ConcatStream;
 
@@ -196,7 +195,8 @@ static int detect_stream_specific(AVFormatContext *avf, int idx)
     ConcatContext *cat = avf->priv_data;
     AVStream *st = cat->avf->streams[idx];
     ConcatStream *cs = &cat->cur_file->streams[idx];
-    AVBitStreamFilterContext *bsf;
+    const AVBitStreamFilter *filter;
+    AVBSFContext *bsf;
     int ret;
 
     if (cat->auto_convert && st->codecpar->codec_id == AV_CODEC_ID_H264) {
@@ -206,29 +206,28 @@ static int detect_stream_specific(AVFormatContext *avf, int idx)
             return 0;
         av_log(cat->avf, AV_LOG_INFO,
                "Auto-inserting h264_mp4toannexb bitstream filter\n");
-        if (!(bsf = av_bitstream_filter_init("h264_mp4toannexb"))) {
+        filter = av_bsf_get_by_name("h264_mp4toannexb");
+        if (!filter) {
             av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb bitstream filter "
                    "required for H.264 streams\n");
             return AVERROR_BSF_NOT_FOUND;
         }
+        ret = av_bsf_alloc(filter, &bsf);
+        if (ret < 0)
+            return ret;
         cs->bsf = bsf;
 
-        cs->avctx = avcodec_alloc_context3(NULL);
-        if (!cs->avctx)
-            return AVERROR(ENOMEM);
-
-        /* This really should be part of the bsf work.
-           Note: input bitstream filtering will not work with bsf that
-           create extradata from the first packet. */
-        av_freep(&st->codecpar->extradata);
-        st->codecpar->extradata_size = 0;
+        ret = avcodec_parameters_copy(bsf->par_in, st->codecpar);
+        if (ret < 0)
+           return ret;
 
-        ret = avcodec_parameters_to_context(cs->avctx, st->codecpar);
-        if (ret < 0) {
-            avcodec_free_context(&cs->avctx);
+        ret = av_bsf_init(bsf);
+        if (ret < 0)
             return ret;
-        }
 
+        ret = avcodec_parameters_copy(st->codecpar, bsf->par_out);
+        if (ret < 0)
+            return ret;
     }
     return 0;
 }
@@ -370,10 +369,8 @@ static int concat_read_close(AVFormatContext *avf)
     for (i = 0; i < cat->nb_files; i++) {
         av_freep(&cat->files[i].url);
         for (j = 0; j < cat->files[i].nb_streams; j++) {
-            if (cat->files[i].streams[j].avctx)
-                avcodec_free_context(&cat->files[i].streams[j].avctx);
             if (cat->files[i].streams[j].bsf)
-                av_bitstream_filter_close(cat->files[i].streams[j].bsf);
+                av_bsf_free(&cat->files[i].streams[j].bsf);
         }
         av_freep(&cat->files[i].streams);
         av_dict_free(&cat->files[i].metadata);
@@ -524,56 +521,25 @@ static int open_next_file(AVFormatContext *avf)
 
 static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt)
 {
-    AVStream *st = avf->streams[cs->out_stream_index];
-    AVBitStreamFilterContext *bsf;
-    AVPacket pkt2;
     int ret;
 
     av_assert0(cs->out_stream_index >= 0);
-    for (bsf = cs->bsf; bsf; bsf = bsf->next) {
-        pkt2 = *pkt;
-
-        ret = av_bitstream_filter_filter(bsf, cs->avctx, NULL,
-                                         &pkt2.data, &pkt2.size,
-                                         pkt->data, pkt->size,
-                                         !!(pkt->flags & AV_PKT_FLAG_KEY));
+    if (cs->bsf) {
+        ret = av_bsf_send_packet(cs->bsf, pkt);
         if (ret < 0) {
+            av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb filter "
+                   "failed to send input packet\n");
             av_packet_unref(pkt);
             return ret;
         }
 
-        if (cs->avctx->extradata_size > st->codecpar->extradata_size) {
-            int eret;
-            if (st->codecpar->extradata)
-                av_freep(&st->codecpar->extradata);
-
-            eret = ff_alloc_extradata(st->codecpar, cs->avctx->extradata_size);
-            if (eret < 0) {
-                av_packet_unref(pkt);
-                return AVERROR(ENOMEM);
-            }
-            st->codecpar->extradata_size = cs->avctx->extradata_size;
-            memcpy(st->codecpar->extradata, cs->avctx->extradata, cs->avctx->extradata_size);
-        }
-
-        av_assert0(pkt2.buf);
-        if (ret == 0 && pkt2.data != pkt->data) {
-            if ((ret = av_copy_packet(&pkt2, pkt)) < 0) {
-                av_free(pkt2.data);
-                return ret;
-            }
-            ret = 1;
-        }
-        if (ret > 0) {
+        ret = av_bsf_receive_packet(cs->bsf, pkt);
+        if (ret < 0) {
+            av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb filter "
+                   "failed to receive output packet\n");
             av_packet_unref(pkt);
-            pkt2.buf = av_buffer_create(pkt2.data, pkt2.size,
-                                        av_buffer_default_free, NULL, 0);
-            if (!pkt2.buf) {
-                av_free(pkt2.data);
-                return AVERROR(ENOMEM);
-            }
+            return ret;
         }
-        *pkt = pkt2;
     }
     return 0;
 }
