[FFmpeg-devel] [PATCH 02/12] lavf: update auto-bsf to new BSF API

Hendrik Leppkes h.leppkes at gmail.com
Wed Apr 20 09:34:59 CEST 2016


On Wed, Apr 20, 2016 at 9:10 AM, Rodger Combs <rodger.combs at gmail.com> wrote:
> ---
>  libavformat/internal.h |  5 +++--
>  libavformat/mux.c      | 32 +++++++++++++++++++++++++--
>  libavformat/segment.c  |  6 +++--
>  libavformat/utils.c    | 59 +++++++++++++++++++++++++++++++++++++++++---------
>  4 files changed, 86 insertions(+), 16 deletions(-)
>
> diff --git a/libavformat/internal.h b/libavformat/internal.h
> index 40ba089..52f9eb6 100644
> --- a/libavformat/internal.h
> +++ b/libavformat/internal.h
> @@ -134,11 +134,12 @@ struct AVStreamInternal {
>      int reorder;
>
>      /**
> -     * bitstream filter to run on stream
> +     * bitstream filters to run on stream
>       * - encoding: Set by muxer using ff_stream_add_bitstream_filter
>       * - decoding: unused
>       */
> -    AVBitStreamFilterContext *bsfc;
> +    AVBSFContext **bsfcs;
> +    int nb_bsfcs;
>
>      /**
>       * Whether or not check_bitstream should still be run on each packet
> diff --git a/libavformat/mux.c b/libavformat/mux.c
> index 6239fd1..c8e3b74 100644
> --- a/libavformat/mux.c
> +++ b/libavformat/mux.c
> @@ -1042,7 +1042,7 @@ static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, in
>
>  int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
>  {
> -    int ret, flush = 0;
> +    int ret, flush = 0, i;
>
>      ret = prepare_input_packet(s, pkt);
>      if (ret < 0)
> @@ -1060,7 +1060,35 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
>              }
>          }
>
> -        av_apply_bitstream_filters(st->internal->avctx, pkt, st->internal->bsfc);
> +        for (i = 0; i < st->internal->nb_bsfcs; i++) {
> +            AVBSFContext* ctx = st->internal->bsfcs[i];
> +            if (i > 0) {
> +                AVBSFContext* prev_ctx = st->internal->bsfcs[i - 1];
> +                if (prev_ctx->par_out->extradata_size != ctx->par_in->extradata_size) {
> +                    if ((ret = avcodec_parameters_copy(ctx->par_in, prev_ctx->par_out)) < 0)
> +                        goto fail;
> +                }
> +            }
> +            if ((ret = av_bsf_send_packet(ctx, pkt)) < 0) {
> +                av_log(ctx, AV_LOG_ERROR,
> +                       "Failed to send packet to filter %s for stream %d",
> +                       ctx->filter->name, pkt->stream_index);
> +                goto fail;
> +            }
> +            if ((ret = av_bsf_receive_packet(ctx, pkt)) < 0) {
> +                av_log(ctx, AV_LOG_ERROR,
> +                       "Failed to send packet to filter %s for stream %d",
> +                       ctx->filter->name, pkt->stream_index);
> +                goto fail;
> +            }

You should probably silently accept EAGAIN and EOF and not print big
errors about that.
The vp9 bsf for example will often return EAGAIN.

> +            if (i == st->internal->nb_bsfcs - 1) {
> +                if (ctx->par_out->extradata_size != st->codecpar->extradata_size) {
> +                    if ((ret = avcodec_parameters_copy(st->codecpar, ctx->par_out)) < 0)
> +                        goto fail;
> +                }
> +            }
> +        }
> +
>          if (pkt->size == 0 && pkt->side_data_elems == 0)
>              return 0;
>          if (!st->codecpar->extradata && st->internal->avctx->extradata) {

You can strip this code away here. empty packets will not be returned
(it'll say EAGAIN instead), and the extradata is updated in codecpar,
not internal avctx, so that following block can also go.

> diff --git a/libavformat/segment.c b/libavformat/segment.c
> index df6f4b5..4c6c6d4 100644
> --- a/libavformat/segment.c
> +++ b/libavformat/segment.c
> @@ -966,8 +966,10 @@ static int seg_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
>          if (ret == 1) {
>              AVStream *st = s->streams[pkt->stream_index];
>              AVStream *ost = oc->streams[pkt->stream_index];
> -            st->internal->bsfc = ost->internal->bsfc;
> -            ost->internal->bsfc = NULL;
> +            st->internal->bsfcs = ost->internal->bsfcs;
> +            st->internal->nb_bsfcs = ost->internal->nb_bsfcs;
> +            ost->internal->bsfcs = NULL;
> +            ost->internal->nb_bsfcs = 0;
>          }
>          return ret;
>      }
> diff --git a/libavformat/utils.c b/libavformat/utils.c
> index b43cfb1..9515496 100644
> --- a/libavformat/utils.c
> +++ b/libavformat/utils.c
> @@ -3938,6 +3938,10 @@ static void free_stream(AVStream **pst)
>
>      if (st->internal) {
>          avcodec_free_context(&st->internal->avctx);
> +        for (i = 0; i < st->internal->nb_bsfcs; i++) {
> +            av_bsf_free(&st->internal->bsfcs[i]);
> +            av_freep(&st->internal->bsfcs);
> +        }
>      }
>      av_freep(&st->internal);
>
> @@ -4962,23 +4966,58 @@ uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type,
>
>  int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *args)
>  {
> -    AVBitStreamFilterContext *bsfc = NULL;
> -    AVBitStreamFilterContext **dest = &st->internal->bsfc;
> -    while (*dest && (*dest)->next)
> -        dest = &(*dest)->next;
> +    int ret;
> +    const AVBitStreamFilter *bsf;
> +    AVBSFContext *bsfc;
> +    AVCodecParameters *in_par;
>
> -    if (!(bsfc = av_bitstream_filter_init(name))) {
> +    if (!(bsf = av_bsf_get_by_name(name))) {
>          av_log(NULL, AV_LOG_ERROR, "Unknown bitstream filter '%s'\n", name);
> -        return AVERROR(EINVAL);
> +        return AVERROR_BSF_NOT_FOUND;
>      }
> -    if (args && !(bsfc->args = av_strdup(args))) {
> -        av_bitstream_filter_close(bsfc);
> -        return AVERROR(ENOMEM);
> +
> +    if ((ret = av_bsf_alloc(bsf, &bsfc)) < 0)
> +        return ret;
> +
> +    if (st->internal->nb_bsfcs) {
> +        in_par = st->internal->bsfcs[st->internal->nb_bsfcs - 1]->par_out;
> +        bsfc->time_base_in = st->internal->bsfcs[st->internal->nb_bsfcs - 1]->time_base_out;
> +    } else {
> +        in_par = st->codecpar;
> +        bsfc->time_base_in = st->time_base;
> +    }
> +
> +    if ((ret = avcodec_parameters_copy(bsfc->par_in, in_par)) < 0) {
> +        av_bsf_free(&bsfc);
> +        return ret;
> +    }
> +
> +    if (args && bsfc->filter->priv_class) {
> +        const AVOption *opt = av_opt_next(bsfc->priv_data, NULL);
> +        const char * shorthand[2] = {NULL};
> +
> +        if (opt)
> +            shorthand[0] = opt->name;
> +
> +        if ((ret = av_opt_set_from_string(bsfc->priv_data, args, shorthand, "=", ":")) < 0) {
> +            av_bsf_free(&bsfc);
> +            return ret;
> +        }
> +    }
> +
> +    if ((ret = av_bsf_init(bsfc)) < 0) {
> +        av_bsf_free(&bsfc);
> +        return ret;
> +    }
> +
> +    if ((ret = av_dynarray_add_nofree(&st->internal->bsfcs, &st->internal->nb_bsfcs, bsfc))) {
> +        av_bsf_free(&bsfc);
> +        return ret;
>      }
> +
>      av_log(NULL, AV_LOG_VERBOSE,
>             "Automatically inserted bitstream filter '%s'; args='%s'\n",
>             name, args ? args : "");
> -    *dest = bsfc;
>      return 1;
>  }
>
> --
> 2.7.3
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


More information about the ffmpeg-devel mailing list