[FFmpeg-devel] [PATCH v2] avcodec/bsf: restructure the internal implementation of the bistream filter API
James Almer
jamrial at gmail.com
Sun Apr 19 19:48:43 EEST 2020
On 4/19/2020 11:34 AM, James Almer wrote:
> Process input data as soon as it's fed to av_bsf_send_packet(), instead of
> storing a single packet and expecting the user to call av_bsf_receive_packet()
> in order to trigger the decoding process before they are allowed to feed more
> data.
This is no longer the case in v2, sorry for the confusion.
av_bsf_send_packet() will trigger filtering only when called more than
one time in a row (When it can't consume the new packet without trying
to filter the previous one first), to keep behavior for existing API
users intact.
>
> This puts the bsf API more in line with the decoupled decode API, without
> breaking existing using it.
>
> Signed-off-by: James Almer <jamrial at gmail.com>
> ---
> Now without creating a new reference for the input packet, and behaving the
> exact same as before for current users that were following the doxy right down
> to the letter.
>
> Also didn't rename buffer_pkt to reduce the size of the diff and easily find
> the actual changes and additions.
>
> libavcodec/avcodec.h | 6 +-----
> libavcodec/bsf.c | 42 +++++++++++++++++++++++++++++++-----------
> 2 files changed, 32 insertions(+), 16 deletions(-)
>
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index b79b025e53..af2a1b0e90 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -4735,10 +4735,6 @@ 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.
> * If pkt is empty (i.e. NULL, or pkt->data is NULL and pkt->side_data_elems zero),
> @@ -4770,7 +4766,7 @@ int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt);
> * 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
> + * a packet with av_bsf_send_packet(), this function may need 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.
> diff --git a/libavcodec/bsf.c b/libavcodec/bsf.c
> index b9fc771a88..c79a8ebbdf 100644
> --- a/libavcodec/bsf.c
> +++ b/libavcodec/bsf.c
> @@ -30,6 +30,7 @@
>
> struct AVBSFInternal {
> AVPacket *buffer_pkt;
> + AVPacket *out_pkt;
> int eof;
> };
>
> @@ -46,8 +47,10 @@ void av_bsf_free(AVBSFContext **pctx)
> if (ctx->filter->priv_class && ctx->priv_data)
> av_opt_free(ctx->priv_data);
>
> - if (ctx->internal)
> + if (ctx->internal) {
> av_packet_free(&ctx->internal->buffer_pkt);
> + av_packet_free(&ctx->internal->out_pkt);
> + }
> av_freep(&ctx->internal);
> av_freep(&ctx->priv_data);
>
> @@ -112,7 +115,8 @@ int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx)
> ctx->internal = bsfi;
>
> bsfi->buffer_pkt = av_packet_alloc();
> - if (!bsfi->buffer_pkt) {
> + bsfi->out_pkt = av_packet_alloc();
> + if (!bsfi->buffer_pkt || !bsfi->out_pkt) {
> ret = AVERROR(ENOMEM);
> goto fail;
> }
> @@ -185,6 +189,7 @@ void av_bsf_flush(AVBSFContext *ctx)
> bsfi->eof = 0;
>
> av_packet_unref(bsfi->buffer_pkt);
> + av_packet_unref(bsfi->out_pkt);
>
> if (ctx->filter->flush)
> ctx->filter->flush(ctx);
> @@ -205,10 +210,21 @@ int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt)
> return AVERROR(EINVAL);
> }
>
> + if (!bsfi->buffer_pkt->data &&
> + !bsfi->buffer_pkt->side_data_elems)
> + goto end;
> +
> + if (!bsfi->out_pkt->data && !bsfi->out_pkt->side_data_elems) {
> + ret = ctx->filter->filter(ctx, bsfi->out_pkt);
> + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
> + return ret;
> + }
> +
> if (bsfi->buffer_pkt->data ||
> bsfi->buffer_pkt->side_data_elems)
> return AVERROR(EAGAIN);
>
> +end:
> ret = av_packet_make_refcounted(pkt);
> if (ret < 0)
> return ret;
> @@ -219,7 +235,17 @@ int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt)
>
> int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt)
> {
> - return ctx->filter->filter(ctx, pkt);
> + AVBSFInternal *bsfi = ctx->internal;
> + int ret;
> +
> + if (!bsfi->out_pkt->data && !bsfi->out_pkt->side_data_elems) {
> + ret = ctx->filter->filter(ctx, bsfi->out_pkt);
> + if (ret < 0)
> + return ret;
> + }
> + av_packet_move_ref(pkt, bsfi->out_pkt);
> +
> + return 0;
> }
>
> int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt)
> @@ -227,12 +253,9 @@ int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt)
> AVBSFInternal *bsfi = ctx->internal;
> AVPacket *tmp_pkt;
>
> - if (bsfi->eof)
> - return AVERROR_EOF;
> -
> if (!bsfi->buffer_pkt->data &&
> !bsfi->buffer_pkt->side_data_elems)
> - return AVERROR(EAGAIN);
> + return bsfi->eof ? AVERROR_EOF : AVERROR(EAGAIN);
>
> tmp_pkt = av_packet_alloc();
> if (!tmp_pkt)
> @@ -248,12 +271,9 @@ int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt)
> {
> AVBSFInternal *bsfi = ctx->internal;
>
> - if (bsfi->eof)
> - return AVERROR_EOF;
> -
> if (!bsfi->buffer_pkt->data &&
> !bsfi->buffer_pkt->side_data_elems)
> - return AVERROR(EAGAIN);
> + return bsfi->eof ? AVERROR_EOF : AVERROR(EAGAIN);
>
> av_packet_move_ref(pkt, bsfi->buffer_pkt);
>
>
More information about the ffmpeg-devel
mailing list