[FFmpeg-devel] [PATCH 3/4] libavcodec/qsvdec.c: The ff_qsv_decode() now guarantees the consumption of whole packet.

Michael Niedermayer michael at niedermayer.cc
Thu Jul 23 17:29:13 CEST 2015


On Thu, Jul 23, 2015 at 12:46:47PM +0300, Ivan Uskov wrote:
> Hello All ,
> 
> There is updated version of patch which should be applied without conflicts.
> Also here couple wrong places have been corrected into ff_qsv_decode().
> 
> Tuesday, July 21, 2015, 4:08:47 PM, you wrote:
> 
> IU> Hello all,
> 
> IU> Actual implementation of ff_qsv_decode() is not reliable, it may
> IU> return without consumption of 1..3 last bytes of packet which
> IU> initiates infinitive loop. New implementation guarantees that packet
> IU> will consumed, now internal fifo uses to join unconsumed previous packet
> IU> tail with new packet.
> IU> Please review.
> IU>   
> 
> 
> 
> 
> -- 
> Best regards,
>  Ivan                            mailto:ivan.uskov at nablet.com

>  qsvdec.c |  130 +++++++++++++++++++++++++++++++++++++++++++++++----------------
>  qsvdec.h |    1 
>  2 files changed, 100 insertions(+), 31 deletions(-)
> eb551cc0e8ef21a3557cebb850b5a15ce385e30e  0002-libavcodec-qsvdec.c-The-ff_qsv_decode-now-guarantees.patch
> From 1b1d3cae1910eb1a4dcea3ddee31a1b2a42292f5 Mon Sep 17 00:00:00 2001
> From: Ivan Uskov <ivan.uskov at nablet.com>
> Date: Tue, 21 Jul 2015 08:31:14 -0400
> Subject: [PATCH 2/2] libavcodec/qsvdec.c: The ff_qsv_decode() now guarantees
>  the consumption of whole packet.
> 
> ---
>  libavcodec/qsvdec.c | 130 +++++++++++++++++++++++++++++++++++++++-------------
>  libavcodec/qsvdec.h |   1 +
>  2 files changed, 100 insertions(+), 31 deletions(-)
> 
> diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
> index 4e7a0ac..b81781b 100644
> --- a/libavcodec/qsvdec.c
> +++ b/libavcodec/qsvdec.c
> @@ -126,6 +126,10 @@ int ff_qsv_decode_init(AVCodecContext *avctx, QSVContext *q, AVPacket *avpkt)
>      if (!q->async_fifo)
>          return AVERROR(ENOMEM);
>  
> +    q->input_fifo = av_fifo_alloc(1024*16);
> +    if (!q->input_fifo)
> +        return AVERROR(ENOMEM);
> +
>      q->engine_ready = 1;
>  
>      return 0;
> @@ -223,6 +227,31 @@ static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf)
>      return NULL;
>  }
>  
> +static void qsv_fifo_relocate(AVFifoBuffer *f, int bytes_to_free)
> +{
> +    int data_size;
> +    int data_rest = 0;
> +
> +    av_fifo_drain(f, bytes_to_free);
> +
> +    data_size = av_fifo_size(f);
> +    if (data_size > 0) {
> +        if (f->buffer!=f->rptr) {
> +            if ( (f->end - f->rptr) < data_size) {
> +                data_rest = data_size - (f->end - f->rptr);
> +                data_size-=data_rest;
> +                memmove(f->buffer+data_size, f->buffer, data_rest);
> +            }
> +            memmove(f->buffer, f->rptr, data_size);
> +            data_size+= data_rest;
> +        }
> +    }
> +    f->rptr = f->buffer;
> +    f->wptr = f->buffer + data_size;
> +    f->wndx = data_size;
> +    f->rndx = 0;
> +}
> +
>  int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
>                    AVFrame *frame, int *got_frame,
>                    AVPacket *avpkt)

> @@ -233,55 +262,91 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
>      mfxSyncPoint sync;
>      mfxBitstream bs = { { { 0 } } };
>      int ret;
> +    int n_out_frames;
> +    int buffered = 0;
>  
>      if (!q->engine_ready) {
>          ret = ff_qsv_decode_init(avctx, q, avpkt);
>          if (ret)
>              return ret;
>      }
> -    if (avpkt->size) {
> -        bs.Data       = avpkt->data;
> -        bs.DataLength = avpkt->size;
> +
> +    if (avpkt->size ) {
> +        if (av_fifo_size(q->input_fifo)) {
> +            /* we have got rest of previous packet into buffer */
> +            if (av_fifo_space(q->input_fifo) < avpkt->size) {
> +                ret = av_fifo_grow(q->input_fifo, avpkt->size);
> +                if (ret < 0)
> +                    return ret;
> +            }
> +            av_fifo_generic_write(q->input_fifo, avpkt->data, avpkt->size, NULL);
> +            bs.Data       = q->input_fifo->rptr;
> +            bs.DataLength = av_fifo_size(q->input_fifo);
> +            buffered = 1;
> +        } else {
> +            bs.Data       = avpkt->data;
> +            bs.DataLength = avpkt->size;
> +        }

Does this mean that each packet will be memcpy-ed ?
this would slow things down

also, is there a performance difference between AVParser and using
the external parser ?


>          bs.MaxLength  = bs.DataLength;
>          bs.TimeStamp  = avpkt->pts;
>      }
>  
> -    do {
> +    while (1) {
>          ret = get_surface(avctx, q, &insurf);
>          if (ret < 0)
>              return ret;
> +        do {
> +            ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
> +                                                  insurf, &outsurf, &sync);
> +            if (ret != MFX_WRN_DEVICE_BUSY)
> +                break;
> -        ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
> -                                              insurf, &outsurf, &sync);
> -        if (ret == MFX_WRN_DEVICE_BUSY)

> -            av_usleep(1);
> +            av_usleep(500);

looks like a unrelated change,
should be in a seperate patch with explanation

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Opposition brings concord. Out of discord comes the fairest harmony.
-- Heraclitus
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20150723/20ba701e/attachment.sig>


More information about the ffmpeg-devel mailing list