[FFmpeg-devel,2/2] lavf/qsvvpp: allocate continuous memory across Y and UV

Submitted by Linjie Fu on March 15, 2019, 4:36 p.m.

Details

Message ID 20190315163600.29075-1-linjie.fu@intel.com
State New
Headers show

Commit Message

Linjie Fu March 15, 2019, 4:36 p.m.
Mediasdk calls CMRT to copy from video to system memory and requires
memory to be continuously allocated across Y and UV.

Add a new path to allocate continuous memory when using system out

Fix the segmentation fault when enabling QSV mirror through video
memory -> system memory. [#1223 in MediaSDK]

Signed-off-by: Linjie Fu <linjie.fu@intel.com>
---
 libavfilter/qsvvpp.c | 34 +++++++++++++++++++++++++++++-----
 1 file changed, 29 insertions(+), 5 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c
index 06efdf5089..0edd10044a 100644
--- a/libavfilter/qsvvpp.c
+++ b/libavfilter/qsvvpp.c
@@ -27,6 +27,7 @@ 
 #include "libavutil/hwcontext_qsv.h"
 #include "libavutil/time.h"
 #include "libavutil/pixdesc.h"
+#include "libavutil/imgutils.h"
 
 #include "internal.h"
 #include "qsvvpp.h"
@@ -51,6 +52,7 @@  struct QSVVPPContext {
     enum AVPixelFormat  out_sw_format;   /* Real output format */
     mfxVideoParam       vpp_param;
     mfxFrameInfo       *frame_infos;     /* frame info for each input */
+    AVBufferPool       *pool;
 
     /* members related to the input/output surface */
     int                 in_mem_mode;
@@ -375,10 +377,26 @@  static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink)
         out_frame->surface = (mfxFrameSurface1 *)out_frame->frame->data[3];
     } else {
         /* Get a frame with aligned dimensions.
-         * Libmfx need system memory being 128x64 aligned */
-        out_frame->frame = ff_get_video_buffer(outlink,
-                                               FFALIGN(outlink->w, 128),
-                                               FFALIGN(outlink->h, 64));
+         * Libmfx need system memory being 128x64 aligned
+         * and continuously allocated across Y and UV */
+        out_frame->frame = av_frame_alloc();
+        if (!out_frame->frame) {
+            return NULL;
+        }
+
+        out_frame->frame->linesize[0] = FFALIGN(outlink->w, 128);
+        out_frame->frame->linesize[1] = out_frame->frame->linesize[0];
+        out_frame->frame->buf[0]      = av_buffer_pool_get(s->pool);
+        out_frame->frame->format      = outlink->format;
+
+        if (!out_frame->frame->buf[0])
+            return NULL;
+
+        out_frame->frame->data[0] = out_frame->frame->buf[0]->data;
+        out_frame->frame->data[1] = out_frame->frame->data[0] +
+                                    out_frame->frame->linesize[0] *
+                                    FFALIGN(outlink->h, 64);
+
         if (!out_frame->frame)
             return NULL;
 
@@ -483,8 +501,13 @@  static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
 
         av_buffer_unref(&outlink->hw_frames_ctx);
         outlink->hw_frames_ctx = out_frames_ref;
-    } else
+    } else {
         s->out_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
+        s->pool = av_buffer_pool_init(av_image_get_buffer_size(outlink->format,
+                                                        FFALIGN(outlink->w, 128),
+                                                        FFALIGN(outlink->h, 64), 1),
+                                        av_buffer_allocz);
+    }
 
     /* extract the properties of the "master" session given to us */
     ret = MFXQueryIMPL(device_hwctx->session, &impl);
@@ -674,6 +697,7 @@  int ff_qsvvpp_free(QSVVPPContext **vpp)
     /* release all the resources */
     clear_frame_list(&s->in_frame_list);
     clear_frame_list(&s->out_frame_list);
+    av_buffer_pool_uninit(&s->pool);
     av_freep(&s->surface_ptrs_in);
     av_freep(&s->surface_ptrs_out);
     av_freep(&s->ext_buffers);