diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index 53403ef9fc..780bc3c4ec 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -89,10 +89,14 @@ static const struct {
 } qsv_iopatterns[] = {
     {MFX_IOPATTERN_IN_VIDEO_MEMORY,     "input is video memory surface"         },
     {MFX_IOPATTERN_IN_SYSTEM_MEMORY,    "input is system memory surface"        },
+#if QSV_HAVE_OPAQUE
     {MFX_IOPATTERN_IN_OPAQUE_MEMORY,    "input is opaque memory surface"        },
+#endif
     {MFX_IOPATTERN_OUT_VIDEO_MEMORY,    "output is video memory surface"        },
     {MFX_IOPATTERN_OUT_SYSTEM_MEMORY,   "output is system memory surface"       },
+#if QSV_HAVE_OPAQUE
     {MFX_IOPATTERN_OUT_OPAQUE_MEMORY,   "output is opaque memory surface"       },
+#endif
 };
 
 int ff_qsv_print_iopattern(void *log_ctx, int mfx_iopattern,
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index 04ae0d6f34..c156b08d07 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -61,6 +61,8 @@ typedef struct AVQSVContext {
      * required by the encoder and the user-provided value nb_opaque_surfaces.
      * The array of the opaque surfaces will be exported to the caller through
      * the opaque_surfaces field.
+     *
+     * The caller must set this field to zero for oneVPL (MFX_VERSION >= 2.0)
      */
     int opaque_alloc;
 
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index 659417ded8..ff50b41de8 100644
--- a/libavcodec/qsv_internal.h
+++ b/libavcodec/qsv_internal.h
@@ -61,6 +61,7 @@
     (MFX_VERSION.Major == (MAJOR) && MFX_VERSION.Minor >= (MINOR)))
 
 #define QSV_ONEVPL       QSV_VERSION_ATLEAST(2, 0)
+#define QSV_HAVE_OPAQUE  !QSV_ONEVPL
 
 typedef struct QSVMid {
     AVBufferRef *hw_frames_ref;
diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
index 1cadb846f5..9395a1fd9a 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -171,7 +171,11 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses
 
         ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session,
                                          &q->frames_ctx, q->load_plugins,
+#if QSV_HAVE_OPAQUE
                                          q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY,
+#else
+                                         0,
+#endif
                                          q->gpu_copy);
         if (ret < 0) {
             av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
@@ -282,10 +286,15 @@ static int qsv_decode_preinit(AVCodecContext *avctx, QSVContext *q, enum AVPixel
         AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
 
         if (!iopattern) {
+#if QSV_HAVE_OPAQUE
             if (frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)
                 iopattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
             else if (frames_hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
                 iopattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY;
+#else
+            if (frames_hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
+                iopattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY;
+#endif
         }
     }
 
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index 57e95a2aa1..1b467cf2cd 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -1029,6 +1029,7 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
     return 0;
 }
 
+#if QSV_HAVE_OPAQUE
 static int qsv_init_opaque_alloc(AVCodecContext *avctx, QSVEncContext *q)
 {
     AVQSVContext *qsv = avctx->hwaccel_context;
@@ -1065,6 +1066,7 @@ static int qsv_init_opaque_alloc(AVCodecContext *avctx, QSVEncContext *q)
 
     return 0;
 }
+#endif
 
 static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q)
 {
@@ -1080,7 +1082,11 @@ static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q)
 
         ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session,
                                          &q->frames_ctx, q->load_plugins,
+#if QSV_HAVE_OPAQUE
                                          q->param.IOPattern == MFX_IOPATTERN_IN_OPAQUE_MEMORY,
+#else
+                                         0,
+#endif
                                          MFX_GPUCOPY_OFF);
         if (ret < 0) {
             av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
@@ -1142,11 +1148,17 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
         AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
 
         if (!iopattern) {
+#if QSV_HAVE_OPAQUE
             if (frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)
                 iopattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY;
             else if (frames_hwctx->frame_type &
                      (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET))
                 iopattern = MFX_IOPATTERN_IN_VIDEO_MEMORY;
+#else
+            if (frames_hwctx->frame_type &
+                (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET))
+                iopattern = MFX_IOPATTERN_IN_VIDEO_MEMORY;
+#endif
         }
     }
 
@@ -1220,9 +1232,16 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
                                   "Error querying (IOSurf) the encoding parameters");
 
     if (opaque_alloc) {
+#if QSV_HAVE_OPAQUE
         ret = qsv_init_opaque_alloc(avctx, q);
         if (ret < 0)
             return ret;
+#else
+        av_log(avctx, AV_LOG_ERROR, "User is requesting to allocate OPAQUE surface, "
+               "however libmfx %d.%d doesn't support OPAQUE memory.\n",
+               q->ver.Major, q->ver.Minor);
+        return AVERROR_UNKNOWN;
+#endif
     }
 
     ret = MFXVideoENCODE_Init(q->session, &q->param);
@@ -1665,8 +1684,10 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
     av_fifo_free(q->async_fifo);
     q->async_fifo = NULL;
 
+#if QSV_HAVE_OPAQUE
     av_freep(&q->opaque_surfaces);
     av_buffer_unref(&q->opaque_alloc_buf);
+#endif
 
     av_freep(&q->extparam);
 
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index 93af4d1198..320ad6db2b 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -135,9 +135,11 @@ typedef struct QSVEncContext {
     mfxExtVP9Param  extvp9param;
 #endif
 
+#if QSV_HAVE_OPAQUE
     mfxExtOpaqueSurfaceAlloc opaque_alloc;
     mfxFrameSurface1       **opaque_surfaces;
     AVBufferRef             *opaque_alloc_buf;
+#endif
 
     mfxExtVideoSignalInfo extvsi;
 
diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c
index 0f7f76b971..bd3a50c070 100644
--- a/libavfilter/qsvvpp.c
+++ b/libavfilter/qsvvpp.c
@@ -34,7 +34,9 @@
 
 #define IS_VIDEO_MEMORY(mode)  (mode & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | \
                                         MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET))
+#if QSV_HAVE_OPAQUE
 #define IS_OPAQUE_MEMORY(mode) (mode & MFX_MEMTYPE_OPAQUE_FRAME)
+#endif
 #define IS_SYSTEM_MEMORY(mode) (mode & MFX_MEMTYPE_SYSTEM_MEMORY)
 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
 
@@ -48,10 +50,14 @@ static const struct {
 } qsv_iopatterns[] = {
     {MFX_IOPATTERN_IN_VIDEO_MEMORY,     "input is video memory surface"         },
     {MFX_IOPATTERN_IN_SYSTEM_MEMORY,    "input is system memory surface"        },
+#if QSV_HAVE_OPAQUE
     {MFX_IOPATTERN_IN_OPAQUE_MEMORY,    "input is opaque memory surface"        },
+#endif
     {MFX_IOPATTERN_OUT_VIDEO_MEMORY,    "output is video memory surface"        },
     {MFX_IOPATTERN_OUT_SYSTEM_MEMORY,   "output is system memory surface"       },
+#if QSV_HAVE_OPAQUE
     {MFX_IOPATTERN_OUT_OPAQUE_MEMORY,   "output is opaque memory surface"       },
+#endif
 };
 
 int ff_qsvvpp_print_iopattern(void *log_ctx, int mfx_iopattern,
@@ -531,9 +537,13 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
         if (!out_frames_ref)
             return AVERROR(ENOMEM);
 
+#if QSV_HAVE_OPAQUE
         s->out_mem_mode = IS_OPAQUE_MEMORY(s->in_mem_mode) ?
                           MFX_MEMTYPE_OPAQUE_FRAME :
                           MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
+#else
+        s->out_mem_mode = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
+#endif
 
         out_frames_ctx   = (AVHWFramesContext *)out_frames_ref->data;
         out_frames_hwctx = out_frames_ctx->hwctx;
@@ -619,6 +629,7 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
             return AVERROR_UNKNOWN;
     }
 
+#if QSV_HAVE_OPAQUE
     if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) {
         s->opaque_alloc.In.Surfaces   = s->surface_ptrs_in;
         s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs_in;
@@ -630,7 +641,9 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
 
         s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
         s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);
-    } else if (IS_VIDEO_MEMORY(s->in_mem_mode) || IS_VIDEO_MEMORY(s->out_mem_mode)) {
+    } else
+#endif
+    if (IS_VIDEO_MEMORY(s->in_mem_mode) || IS_VIDEO_MEMORY(s->out_mem_mode)) {
         mfxFrameAllocator frame_allocator = {
             .pthis  = s,
             .Alloc  = frame_alloc,
@@ -712,6 +725,7 @@ int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *p
         goto failed;
     }
 
+#if QSV_HAVE_OPAQUE
     if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) {
         s->nb_ext_buffers = param->num_ext_buf + 1;
         s->ext_buffers = av_mallocz_array(s->nb_ext_buffers, sizeof(*s->ext_buffers));
@@ -729,6 +743,10 @@ int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *p
         s->vpp_param.NumExtParam = param->num_ext_buf;
         s->vpp_param.ExtParam    = param->ext_buf;
     }
+#else
+    s->vpp_param.NumExtParam = param->num_ext_buf;
+    s->vpp_param.ExtParam    = param->ext_buf;
+#endif
 
     s->got_frame = 0;
 
@@ -746,15 +764,19 @@ int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *p
         s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_SYSTEM_MEMORY;
     else if (IS_VIDEO_MEMORY(s->in_mem_mode))
         s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_VIDEO_MEMORY;
+#if QSV_HAVE_OPAQUE
     else if (IS_OPAQUE_MEMORY(s->in_mem_mode))
         s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_OPAQUE_MEMORY;
+#endif
 
     if (IS_SYSTEM_MEMORY(s->out_mem_mode))
         s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
     else if (IS_VIDEO_MEMORY(s->out_mem_mode))
         s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_VIDEO_MEMORY;
+#if QSV_HAVE_OPAQUE
     else if (IS_OPAQUE_MEMORY(s->out_mem_mode))
         s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
+#endif
 
     /* Print input memory mode */
     ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0x0F, "VPP");
@@ -793,7 +815,9 @@ int ff_qsvvpp_free(QSVVPPContext **vpp)
     clear_frame_list(&s->out_frame_list);
     av_freep(&s->surface_ptrs_in);
     av_freep(&s->surface_ptrs_out);
+#if QSV_HAVE_OPAQUE
     av_freep(&s->ext_buffers);
+#endif
     av_freep(&s->frame_infos);
     av_fifo_free(s->async_fifo);
     av_freep(vpp);
diff --git a/libavfilter/qsvvpp.h b/libavfilter/qsvvpp.h
index 46e90c1d2c..67c351f297 100644
--- a/libavfilter/qsvvpp.h
+++ b/libavfilter/qsvvpp.h
@@ -41,6 +41,7 @@
     (MFX_VERSION.Major == (MAJOR) && MFX_VERSION.Minor >= (MINOR)))
 
 #define QSV_ONEVPL       QSV_VERSION_ATLEAST(2, 0)
+#define QSV_HAVE_OPAQUE  !QSV_ONEVPL
 
 typedef struct QSVFrame {
     AVFrame          *frame;
@@ -66,10 +67,12 @@ typedef struct QSVVPPContext {
     mfxFrameSurface1  **surface_ptrs_in;
     mfxFrameSurface1  **surface_ptrs_out;
 
+#if QSV_HAVE_OPAQUE
     /** MFXVPP extern parameters */
     mfxExtOpaqueSurfaceAlloc opaque_alloc;
     mfxExtBuffer      **ext_buffers;
     int                 nb_ext_buffers;
+#endif
 
     int got_frame;
     int async_depth;
diff --git a/libavfilter/vf_deinterlace_qsv.c b/libavfilter/vf_deinterlace_qsv.c
index d9332fb90e..84b3ec5a7c 100644
--- a/libavfilter/vf_deinterlace_qsv.c
+++ b/libavfilter/vf_deinterlace_qsv.c
@@ -62,7 +62,9 @@ typedef struct QSVDeintContext {
     mfxFrameSurface1 **surface_ptrs;
     int             nb_surface_ptrs;
 
+#if QSV_HAVE_OPAQUE
     mfxExtOpaqueSurfaceAlloc opaque_alloc;
+#endif
     mfxExtVPPDeinterlacing   deint_conf;
     mfxExtBuffer            *ext_buffers[2];
     int                      num_ext_buffers;
@@ -163,9 +165,7 @@ static int init_out_session(AVFilterContext *ctx)
     AVHWFramesContext    *hw_frames_ctx = (AVHWFramesContext*)s->hw_frames_ctx->data;
     AVQSVFramesContext *hw_frames_hwctx = hw_frames_ctx->hwctx;
     AVQSVDeviceContext    *device_hwctx = hw_frames_ctx->device_ctx->hwctx;
-
-    int opaque = !!(hw_frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
-
+    int opaque = 0;
     mfxHDL handle = NULL;
     mfxHandleType handle_type;
     mfxVersion ver;
@@ -174,6 +174,9 @@ static int init_out_session(AVFilterContext *ctx)
     mfxStatus err;
     int i;
 
+#if QSV_HAVE_OPAQUE
+    opaque = !!(hw_frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
+#endif
     /* extract the properties of the "master" session given to us */
     err = MFXQueryIMPL(device_hwctx->session, &impl);
     if (err == MFX_ERR_NONE)
@@ -232,28 +235,7 @@ static int init_out_session(AVFilterContext *ctx)
 
     s->ext_buffers[s->num_ext_buffers++] = (mfxExtBuffer *)&s->deint_conf;
 
-    if (opaque) {
-        s->surface_ptrs = av_mallocz_array(hw_frames_hwctx->nb_surfaces,
-                                           sizeof(*s->surface_ptrs));
-        if (!s->surface_ptrs)
-            return AVERROR(ENOMEM);
-        for (i = 0; i < hw_frames_hwctx->nb_surfaces; i++)
-            s->surface_ptrs[i] = hw_frames_hwctx->surfaces + i;
-        s->nb_surface_ptrs = hw_frames_hwctx->nb_surfaces;
-
-        s->opaque_alloc.In.Surfaces   = s->surface_ptrs;
-        s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs;
-        s->opaque_alloc.In.Type       = hw_frames_hwctx->frame_type;
-
-        s->opaque_alloc.Out = s->opaque_alloc.In;
-
-        s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
-        s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);
-
-        s->ext_buffers[s->num_ext_buffers++] = (mfxExtBuffer *)&s->opaque_alloc;
-
-        par.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY | MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
-    } else {
+    if (!opaque) {
         mfxFrameAllocator frame_allocator = {
             .pthis  = ctx,
             .Alloc  = frame_alloc,
@@ -277,6 +259,30 @@ static int init_out_session(AVFilterContext *ctx)
 
         par.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY;
     }
+#if QSV_HAVE_OPAQUE
+    else {
+        s->surface_ptrs = av_mallocz_array(hw_frames_hwctx->nb_surfaces,
+                                           sizeof(*s->surface_ptrs));
+        if (!s->surface_ptrs)
+            return AVERROR(ENOMEM);
+        for (i = 0; i < hw_frames_hwctx->nb_surfaces; i++)
+            s->surface_ptrs[i] = hw_frames_hwctx->surfaces + i;
+        s->nb_surface_ptrs = hw_frames_hwctx->nb_surfaces;
+
+        s->opaque_alloc.In.Surfaces   = s->surface_ptrs;
+        s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs;
+        s->opaque_alloc.In.Type       = hw_frames_hwctx->frame_type;
+
+        s->opaque_alloc.Out = s->opaque_alloc.In;
+
+        s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
+        s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);
+
+        s->ext_buffers[s->num_ext_buffers++] = (mfxExtBuffer *)&s->opaque_alloc;
+
+        par.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY | MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
+    }
+#endif
 
     par.ExtParam    = s->ext_buffers;
     par.NumExtParam = s->num_ext_buffers;
diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c
index fa8ba1f670..bbdca3660f 100644
--- a/libavfilter/vf_scale_qsv.c
+++ b/libavfilter/vf_scale_qsv.c
@@ -90,7 +90,9 @@ typedef struct QSVScaleContext {
     mfxFrameSurface1 **surface_ptrs_out;
     int             nb_surface_ptrs_out;
 
+#if QSV_HAVE_OPAQUE
     mfxExtOpaqueSurfaceAlloc opaque_alloc;
+#endif
 
 #if QSV_HAVE_SCALING_CONFIG
     mfxExtVPPScaling         scale_conf;
@@ -280,7 +282,7 @@ static int init_out_session(AVFilterContext *ctx)
     AVQSVFramesContext *out_frames_hwctx = out_frames_ctx->hwctx;
     AVQSVDeviceContext     *device_hwctx = in_frames_ctx->device_ctx->hwctx;
 
-    int opaque = !!(in_frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
+    int opaque = 0;
 
     mfxHDL handle = NULL;
     mfxHandleType handle_type;
@@ -290,6 +292,9 @@ static int init_out_session(AVFilterContext *ctx)
     mfxStatus err;
     int i;
 
+#if QSV_HAVE_OPAQUE
+    opaque = !!(in_frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
+#endif
     s->num_ext_buf = 0;
 
     /* extract the properties of the "master" session given to us */
@@ -342,38 +347,7 @@ static int init_out_session(AVFilterContext *ctx)
 
     memset(&par, 0, sizeof(par));
 
-    if (opaque) {
-        s->surface_ptrs_in = av_mallocz_array(in_frames_hwctx->nb_surfaces,
-                                              sizeof(*s->surface_ptrs_in));
-        if (!s->surface_ptrs_in)
-            return AVERROR(ENOMEM);
-        for (i = 0; i < in_frames_hwctx->nb_surfaces; i++)
-            s->surface_ptrs_in[i] = in_frames_hwctx->surfaces + i;
-        s->nb_surface_ptrs_in = in_frames_hwctx->nb_surfaces;
-
-        s->surface_ptrs_out = av_mallocz_array(out_frames_hwctx->nb_surfaces,
-                                               sizeof(*s->surface_ptrs_out));
-        if (!s->surface_ptrs_out)
-            return AVERROR(ENOMEM);
-        for (i = 0; i < out_frames_hwctx->nb_surfaces; i++)
-            s->surface_ptrs_out[i] = out_frames_hwctx->surfaces + i;
-        s->nb_surface_ptrs_out = out_frames_hwctx->nb_surfaces;
-
-        s->opaque_alloc.In.Surfaces   = s->surface_ptrs_in;
-        s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs_in;
-        s->opaque_alloc.In.Type       = in_frames_hwctx->frame_type;
-
-        s->opaque_alloc.Out.Surfaces   = s->surface_ptrs_out;
-        s->opaque_alloc.Out.NumSurface = s->nb_surface_ptrs_out;
-        s->opaque_alloc.Out.Type       = out_frames_hwctx->frame_type;
-
-        s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
-        s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);
-
-        s->ext_buffers[s->num_ext_buf++] = (mfxExtBuffer*)&s->opaque_alloc;
-
-        par.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY | MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
-    } else {
+    if (!opaque) {
         mfxFrameAllocator frame_allocator = {
             .pthis  = ctx,
             .Alloc  = frame_alloc,
@@ -405,6 +379,40 @@ static int init_out_session(AVFilterContext *ctx)
 
         par.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY;
     }
+#if QSV_HAVE_OPAQUE
+    else {
+        s->surface_ptrs_in = av_mallocz_array(in_frames_hwctx->nb_surfaces,
+                                              sizeof(*s->surface_ptrs_in));
+        if (!s->surface_ptrs_in)
+            return AVERROR(ENOMEM);
+        for (i = 0; i < in_frames_hwctx->nb_surfaces; i++)
+            s->surface_ptrs_in[i] = in_frames_hwctx->surfaces + i;
+        s->nb_surface_ptrs_in = in_frames_hwctx->nb_surfaces;
+
+        s->surface_ptrs_out = av_mallocz_array(out_frames_hwctx->nb_surfaces,
+                                               sizeof(*s->surface_ptrs_out));
+        if (!s->surface_ptrs_out)
+            return AVERROR(ENOMEM);
+        for (i = 0; i < out_frames_hwctx->nb_surfaces; i++)
+            s->surface_ptrs_out[i] = out_frames_hwctx->surfaces + i;
+        s->nb_surface_ptrs_out = out_frames_hwctx->nb_surfaces;
+
+        s->opaque_alloc.In.Surfaces   = s->surface_ptrs_in;
+        s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs_in;
+        s->opaque_alloc.In.Type       = in_frames_hwctx->frame_type;
+
+        s->opaque_alloc.Out.Surfaces   = s->surface_ptrs_out;
+        s->opaque_alloc.Out.NumSurface = s->nb_surface_ptrs_out;
+        s->opaque_alloc.Out.Type       = out_frames_hwctx->frame_type;
+
+        s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
+        s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);
+
+        s->ext_buffers[s->num_ext_buf++] = (mfxExtBuffer*)&s->opaque_alloc;
+
+        par.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY | MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
+    }
+#endif
 
 #if QSV_HAVE_SCALING_CONFIG
     memset(&s->scale_conf, 0, sizeof(mfxExtVPPScaling));
diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index fcfcd315cc..fd6703cd38 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -53,6 +53,8 @@
      MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
 
 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
+#define QSV_ONEVPL       QSV_VERSION_ATLEAST(2, 0)
+#define QSV_HAVE_OPAQUE  !QSV_ONEVPL
 
 typedef struct QSVDevicePriv {
     AVBufferRef *child_device_ctx;
@@ -85,11 +87,13 @@ typedef struct QSVFramesContext {
 
     // used in the frame allocator for non-opaque surfaces
     mfxMemId *mem_ids;
+#if QSV_HAVE_OPAQUE
     // used in the opaque alloc request for opaque surfaces
     mfxFrameSurface1 **surface_ptrs;
 
     mfxExtOpaqueSurfaceAlloc opaque_alloc;
     mfxExtBuffer *ext_buffers[1];
+#endif
 } QSVFramesContext;
 
 static const struct {
@@ -217,7 +221,9 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx)
 #endif
 
     av_freep(&s->mem_ids);
+#if QSV_HAVE_OPAQUE
     av_freep(&s->surface_ptrs);
+#endif
     av_freep(&s->surfaces_internal);
     av_freep(&s->handle_pairs_internal);
     av_buffer_unref(&s->child_frames_ref);
@@ -453,11 +459,17 @@ static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc)
             return ret;
     }
 
+#if QSV_HAVE_OPAQUE
     if (!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)) {
         ret = qsv_init_child_ctx(ctx);
         if (ret < 0)
             return ret;
     }
+#else
+    ret = qsv_init_child_ctx(ctx);
+    if (ret < 0)
+        return ret;
+#endif
 
     ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(mfxFrameSurface1),
                                                         ctx, qsv_pool_alloc, NULL);
@@ -528,10 +540,9 @@ static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
 static int qsv_init_internal_session(AVHWFramesContext *ctx,
                                      mfxSession *session, int upload)
 {
-    QSVFramesContext              *s = ctx->internal->priv;
     AVQSVFramesContext *frames_hwctx = ctx->hwctx;
     QSVDeviceContext   *device_priv  = ctx->device_ctx->internal->priv;
-    int opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
+    int opaque = 0;
 
     mfxFrameAllocator frame_allocator = {
         .pthis  = ctx,
@@ -545,6 +556,11 @@ static int qsv_init_internal_session(AVHWFramesContext *ctx,
     mfxVideoParam par;
     mfxStatus err;
 
+#if QSV_HAVE_OPAQUE
+    QSVFramesContext              *s = ctx->internal->priv;
+    opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
+#endif
+
     err = MFXInit(device_priv->impl, &device_priv->ver, session);
     if (err != MFX_ERR_NONE) {
         av_log(ctx, AV_LOG_ERROR, "Error initializing an internal session\n");
@@ -566,15 +582,18 @@ static int qsv_init_internal_session(AVHWFramesContext *ctx,
 
     memset(&par, 0, sizeof(par));
 
-    if (opaque) {
+    if (!opaque) {
+        par.IOPattern = upload ? MFX_IOPATTERN_OUT_VIDEO_MEMORY :
+                                 MFX_IOPATTERN_IN_VIDEO_MEMORY;
+    }
+#if QSV_HAVE_OPAQUE
+    else {
         par.ExtParam    = s->ext_buffers;
         par.NumExtParam = FF_ARRAY_ELEMS(s->ext_buffers);
         par.IOPattern   = upload ? MFX_IOPATTERN_OUT_OPAQUE_MEMORY :
                                    MFX_IOPATTERN_IN_OPAQUE_MEMORY;
-    } else {
-        par.IOPattern = upload ? MFX_IOPATTERN_OUT_VIDEO_MEMORY :
-                                 MFX_IOPATTERN_IN_VIDEO_MEMORY;
     }
+#endif
 
     par.IOPattern |= upload ? MFX_IOPATTERN_IN_SYSTEM_MEMORY :
                               MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
@@ -606,11 +625,15 @@ static int qsv_frames_init(AVHWFramesContext *ctx)
     QSVFramesContext              *s = ctx->internal->priv;
     AVQSVFramesContext *frames_hwctx = ctx->hwctx;
 
-    int opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
+    int opaque = 0;
 
     uint32_t fourcc;
     int i, ret;
 
+#if QSV_HAVE_OPAQUE
+    opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
+#endif
+
     fourcc = qsv_fourcc_from_pix_fmt(ctx->sw_format);
     if (!fourcc) {
         av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format\n");
@@ -625,7 +648,16 @@ static int qsv_frames_init(AVHWFramesContext *ctx)
         }
     }
 
-    if (opaque) {
+    if (!opaque) {
+        s->mem_ids = av_mallocz_array(frames_hwctx->nb_surfaces, sizeof(*s->mem_ids));
+        if (!s->mem_ids)
+            return AVERROR(ENOMEM);
+
+        for (i = 0; i < frames_hwctx->nb_surfaces; i++)
+            s->mem_ids[i] = frames_hwctx->surfaces[i].Data.MemId;
+    }
+#if QSV_HAVE_OPAQUE
+    else {
         s->surface_ptrs = av_mallocz_array(frames_hwctx->nb_surfaces,
                                            sizeof(*s->surface_ptrs));
         if (!s->surface_ptrs)
@@ -644,14 +676,8 @@ static int qsv_frames_init(AVHWFramesContext *ctx)
         s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);
 
         s->ext_buffers[0] = (mfxExtBuffer*)&s->opaque_alloc;
-    } else {
-        s->mem_ids = av_mallocz_array(frames_hwctx->nb_surfaces, sizeof(*s->mem_ids));
-        if (!s->mem_ids)
-            return AVERROR(ENOMEM);
-
-        for (i = 0; i < frames_hwctx->nb_surfaces; i++)
-            s->mem_ids[i] = frames_hwctx->surfaces[i].Data.MemId;
     }
+#endif
 
     s->session_download = NULL;
     s->session_upload   = NULL;
