[FFmpeg-cvslog] Merge commit '3c53627ac17fc6bdea5029be57da1e03b32d265d'

Derek Buitenhuis git at videolan.org
Mon Apr 11 15:57:01 CEST 2016


ffmpeg | branch: master | Derek Buitenhuis <derek.buitenhuis at gmail.com> | Mon Apr 11 14:56:27 2016 +0100| [d30cf57a7b2097b565db02ecfffbdc9c16423d0e] | committer: Derek Buitenhuis

Merge commit '3c53627ac17fc6bdea5029be57da1e03b32d265d'

* commit '3c53627ac17fc6bdea5029be57da1e03b32d265d':
  qsvdec: store the sync point in heap memory

Merged-by: Derek Buitenhuis <derek.buitenhuis at gmail.com>

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

 libavcodec/qsvdec.c |   34 ++++++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
index 9125700..c17606d 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -142,7 +142,7 @@ static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q, AVPacket *avpkt
      */
     if (!q->async_fifo) {
         q->async_fifo = av_fifo_alloc((1 + 16) *
-                                      (sizeof(mfxSyncPoint) + sizeof(QSVFrame*)));
+                                      (sizeof(mfxSyncPoint*) + sizeof(QSVFrame*)));
         if (!q->async_fifo)
             return AVERROR(ENOMEM);
     }
@@ -297,6 +297,16 @@ static void close_decoder(QSVContext *q)
     if (q->session)
         MFXVideoDECODE_Close(q->session);
 
+    while (q->async_fifo && av_fifo_size(q->async_fifo)) {
+        QSVFrame *out_frame;
+        mfxSyncPoint *sync;
+
+        av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
+        av_fifo_generic_read(q->async_fifo, &sync,      sizeof(sync),      NULL);
+
+        av_freep(&sync);
+    }
+
     cur = q->work_frames;
     while (cur) {
         q->work_frames = cur->next;
@@ -316,7 +326,7 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
     QSVFrame *out_frame;
     mfxFrameSurface1 *insurf;
     mfxFrameSurface1 *outsurf;
-    mfxSyncPoint sync;
+    mfxSyncPoint *sync;
     mfxBitstream bs = { { { 0 } } };
     int ret;
     int n_out_frames;
@@ -349,13 +359,19 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
         bs.TimeStamp  = avpkt->pts;
     }
 
+    sync = av_mallocz(sizeof(*sync));
+    if (!sync) {
+        av_freep(&sync);
+        return AVERROR(ENOMEM);
+    }
+
     while (1) {
         ret = get_surface(avctx, q, &insurf);
         if (ret < 0)
             return ret;
         do {
             ret = MFXVideoDECODE_DecodeFrameAsync(q->session, flush ? NULL : &bs,
-                                                  insurf, &outsurf, &sync);
+                                                  insurf, &outsurf, sync);
             if (ret != MFX_WRN_DEVICE_BUSY)
                 break;
             av_usleep(500);
@@ -369,10 +385,11 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
             continue;
         }
 
-        if (sync) {
+        if (*sync) {
             QSVFrame *out_frame = find_frame(q, outsurf);
 
             if (!out_frame) {
+                av_freep(&sync);
                 av_log(avctx, AV_LOG_ERROR,
                        "The returned surface does not correspond to any frame\n");
                 return AVERROR_BUG;
@@ -383,6 +400,8 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
             av_fifo_generic_write(q->async_fifo, &sync,      sizeof(sync),      NULL);
 
             continue;
+        } else {
+            av_freep(&sync);
         }
         if (MFX_ERR_MORE_SURFACE != ret && ret < 0)
             break;
@@ -390,7 +409,7 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
 
     /* make sure we do not enter an infinite loop if the SDK
      * did not consume any data and did not return anything */
-    if (!sync && !bs.DataOffset && !flush) {
+    if (!*sync && !bs.DataOffset && !flush) {
         av_log(avctx, AV_LOG_WARNING, "A decode call did not consume any data\n");
         bs.DataOffset = avpkt->size;
     }
@@ -404,6 +423,7 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
     }
 
     if (MFX_ERR_MORE_DATA!=ret && ret < 0) {
+        av_freep(&sync);
         av_log(avctx, AV_LOG_ERROR, "Error %d during QSV decoding.\n", ret);
         return ff_qsv_error(ret);
     }
@@ -417,9 +437,11 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
         out_frame->queued = 0;
 
         do {
-            ret = MFXVideoCORE_SyncOperation(q->session, sync, 1000);
+            ret = MFXVideoCORE_SyncOperation(q->session, *sync, 1000);
         } while (ret == MFX_WRN_IN_EXECUTION);
 
+        av_freep(&sync);
+
         src_frame = out_frame->frame;
 
         ret = av_frame_ref(frame, src_frame);


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

diff --cc libavcodec/qsvdec.c
index 9125700,1d59e72..c17606d
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@@ -129,37 -116,6 +129,37 @@@ static int qsv_decode_init(AVCodecConte
          return ff_qsv_error(ret);
      }
  
 +    avctx->profile      = param.mfx.CodecProfile;
 +    avctx->level        = param.mfx.CodecLevel;
 +    avctx->coded_width  = param.mfx.FrameInfo.Width;
 +    avctx->coded_height = param.mfx.FrameInfo.Height;
 +    avctx->width        = param.mfx.FrameInfo.CropW - param.mfx.FrameInfo.CropX;
 +    avctx->height       = param.mfx.FrameInfo.CropH - param.mfx.FrameInfo.CropY;
 +
 +    /* maximum decoder latency should be not exceed max DPB size for h.264 and
 +       HEVC which is 16 for both cases.
 +       So weare  pre-allocating fifo big enough for 17 elements:
 +     */
 +    if (!q->async_fifo) {
 +        q->async_fifo = av_fifo_alloc((1 + 16) *
-                                       (sizeof(mfxSyncPoint) + sizeof(QSVFrame*)));
++                                      (sizeof(mfxSyncPoint*) + sizeof(QSVFrame*)));
 +        if (!q->async_fifo)
 +            return AVERROR(ENOMEM);
 +    }
 +
 +    if (!q->input_fifo) {
 +        q->input_fifo = av_fifo_alloc(1024*16);
 +        if (!q->input_fifo)
 +            return AVERROR(ENOMEM);
 +    }
 +
 +    if (!q->pkt_fifo) {
 +        q->pkt_fifo = av_fifo_alloc( sizeof(AVPacket) * (1 + 16) );
 +        if (!q->pkt_fifo)
 +            return AVERROR(ENOMEM);
 +    }
 +    q->engine_ready = 1;
 +
      return 0;
  }
  
@@@ -255,161 -211,77 +255,181 @@@ static QSVFrame *find_frame(QSVContext 
      return NULL;
  }
  
 -static int qsv_decode(AVCodecContext *avctx, QSVContext *q,
 -                      AVFrame *frame, int *got_frame,
 -                      AVPacket *avpkt)
 +/*  This function uses for 'smart' releasing of consumed data
 +    from the input bitstream fifo.
 +    Since the input fifo mapped to mfxBitstream which does not understand
 +    a wrapping of data over fifo end, we should also to relocate a possible
 +    data rest to fifo begin. If rest of data is absent then we just reset fifo's
 +    pointers to initial positions.
 +    NOTE the case when fifo does contain unconsumed data is rare and typical
 +    amount of such data is 1..4 bytes.
 +*/
 +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;
 +}
 +
 +
 +static void close_decoder(QSVContext *q)
 +{
 +    QSVFrame *cur;
 +
 +    if (q->session)
 +        MFXVideoDECODE_Close(q->session);
 +
++    while (q->async_fifo && av_fifo_size(q->async_fifo)) {
++        QSVFrame *out_frame;
++        mfxSyncPoint *sync;
++
++        av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
++        av_fifo_generic_read(q->async_fifo, &sync,      sizeof(sync),      NULL);
++
++        av_freep(&sync);
++    }
++
 +    cur = q->work_frames;
 +    while (cur) {
 +        q->work_frames = cur->next;
 +        av_frame_free(&cur->frame);
 +        av_freep(&cur);
 +        cur = q->work_frames;
 +    }
 +
 +    q->engine_ready   = 0;
 +    q->reinit_pending = 0;
 +}
 +
 +static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
 +                  AVFrame *frame, int *got_frame,
 +                  AVPacket *avpkt)
  {
      QSVFrame *out_frame;
      mfxFrameSurface1 *insurf;
      mfxFrameSurface1 *outsurf;
-     mfxSyncPoint sync;
+     mfxSyncPoint *sync;
      mfxBitstream bs = { { { 0 } } };
      int ret;
 +    int n_out_frames;
 +    int buffered = 0;
 +    int flush    = !avpkt->size || q->reinit_pending;
  
 -    if (avpkt->size) {
 -        bs.Data       = avpkt->data;
 -        bs.DataLength = avpkt->size;
 +    if (!q->engine_ready) {
 +        ret = qsv_decode_init(avctx, q, avpkt);
 +        if (ret)
 +            return ret;
 +    }
 +
 +    if (!flush) {
 +        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;
 +        }
          bs.MaxLength  = bs.DataLength;
          bs.TimeStamp  = avpkt->pts;
      }
  
+     sync = av_mallocz(sizeof(*sync));
+     if (!sync) {
+         av_freep(&sync);
+         return AVERROR(ENOMEM);
+     }
+ 
 -    do {
 +    while (1) {
          ret = get_surface(avctx, q, &insurf);
          if (ret < 0)
              return ret;
 +        do {
 +            ret = MFXVideoDECODE_DecodeFrameAsync(q->session, flush ? NULL : &bs,
-                                                   insurf, &outsurf, &sync);
++                                                  insurf, &outsurf, sync);
 +            if (ret != MFX_WRN_DEVICE_BUSY)
 +                break;
 +            av_usleep(500);
 +        } while (1);
 +
 +        if (MFX_WRN_VIDEO_PARAM_CHANGED==ret) {
 +            /* TODO: handle here minor sequence header changing */
 +        } else if (MFX_ERR_INCOMPATIBLE_VIDEO_PARAM==ret) {
 +            av_fifo_reset(q->input_fifo);
 +            flush = q->reinit_pending = 1;
 +            continue;
 +        }
  
-         if (sync) {
 -        ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
 -                                              insurf, &outsurf, sync);
 -        if (ret == MFX_WRN_DEVICE_BUSY)
 -            av_usleep(1);
++        if (*sync) {
 +            QSVFrame *out_frame = find_frame(q, outsurf);
  
 -    } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE);
 +            if (!out_frame) {
++                av_freep(&sync);
 +                av_log(avctx, AV_LOG_ERROR,
 +                       "The returned surface does not correspond to any frame\n");
 +                return AVERROR_BUG;
 +            }
  
 -    if (ret != MFX_ERR_NONE &&
 -        ret != MFX_ERR_MORE_DATA &&
 -        ret != MFX_WRN_VIDEO_PARAM_CHANGED &&
 -        ret != MFX_ERR_MORE_SURFACE) {
 -        av_log(avctx, AV_LOG_ERROR, "Error during QSV decoding.\n");
 -        av_freep(&sync);
 -        return ff_qsv_error(ret);
 +            out_frame->queued = 1;
 +            av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
 +            av_fifo_generic_write(q->async_fifo, &sync,      sizeof(sync),      NULL);
 +
 +            continue;
++        } else {
++            av_freep(&sync);
 +        }
 +        if (MFX_ERR_MORE_SURFACE != ret && ret < 0)
 +            break;
      }
  
      /* make sure we do not enter an infinite loop if the SDK
       * did not consume any data and did not return anything */
-     if (!sync && !bs.DataOffset && !flush) {
 -    if (!*sync && !bs.DataOffset) {
++    if (!*sync && !bs.DataOffset && !flush) {
          av_log(avctx, AV_LOG_WARNING, "A decode call did not consume any data\n");
          bs.DataOffset = avpkt->size;
      }
  
 -    if (*sync) {
 -        QSVFrame *out_frame = find_frame(q, outsurf);
 -
 -        if (!out_frame) {
 -            av_log(avctx, AV_LOG_ERROR,
 -                   "The returned surface does not correspond to any frame\n");
 -            av_freep(&sync);
 -            return AVERROR_BUG;
 -        }
 +    if (buffered) {
 +        qsv_fifo_relocate(q->input_fifo, bs.DataOffset);
 +    } else if (bs.DataOffset!=avpkt->size) {
 +        /* some data of packet was not consumed. store it to local buffer */
 +        av_fifo_generic_write(q->input_fifo, avpkt->data+bs.DataOffset,
 +                              avpkt->size - bs.DataOffset, NULL);
 +    }
  
 -        out_frame->queued = 1;
 -        av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
 -        av_fifo_generic_write(q->async_fifo, &sync,      sizeof(sync),      NULL);
 -    } else {
 +    if (MFX_ERR_MORE_DATA!=ret && ret < 0) {
+         av_freep(&sync);
 +        av_log(avctx, AV_LOG_ERROR, "Error %d during QSV decoding.\n", ret);
 +        return ff_qsv_error(ret);
      }
 +    n_out_frames = av_fifo_size(q->async_fifo) / (sizeof(out_frame)+sizeof(sync));
  
 -    if (!av_fifo_space(q->async_fifo) ||
 -        (!avpkt->size && av_fifo_size(q->async_fifo))) {
 +    if (n_out_frames > q->async_depth || (flush && n_out_frames) ) {
          AVFrame *src_frame;
  
          av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);



More information about the ffmpeg-cvslog mailing list