diff mbox

[FFmpeg-devel,v2] libavcodec/amfenc: Vulkan initialization support for encoder.

Message ID 20190808183325.22116-1-ovchinnikov.dmitrii@gmail.com
State New
Headers show

Commit Message

OvchinnikovDmitrii Aug. 8, 2019, 6:33 p.m. UTC
Added linux support for amf encoder through vulkan.

To use h.264(AMD VCE) encoder on linux amdgru-pro version 19.20+ and amf-amdgpu-pro package(amdgru-pro contains, but does not install automatically) are required.
This driver can be installed using amdgpu-pro-install script in official amd driver archive.

Initialization of amf encoder occurs in this order:
1) trying to initialize through dx11(only windows)
2) trying to initialize through dx9(only windows)
3) trying to initialize through vulkan

Only Vulkan initialization available on linux.


---
 doc/general.texi    | 16 +++++++++++++---
 libavcodec/amfenc.c | 17 +++++++++++++++--
 2 files changed, 28 insertions(+), 5 deletions(-)

Comments

Timo Rothenpieler Aug. 9, 2019, 9:26 a.m. UTC | #1
On 08/08/2019 20:33, OvchinnikovDmitrii wrote:
> Added linux support for amf encoder through vulkan.
> 
> To use h.264(AMD VCE) encoder on linux amdgru-pro version 19.20+ and amf-amdgpu-pro package(amdgru-pro contains, but does not install automatically) are required.
> This driver can be installed using amdgpu-pro-install script in official amd driver archive.
> 
> Initialization of amf encoder occurs in this order:
> 1) trying to initialize through dx11(only windows)
> 2) trying to initialize through dx9(only windows)
> 3) trying to initialize through vulkan
> 
> Only Vulkan initialization available on linux.
> 

Is it possible to use Vulkan on Windows? For Interop with OpenCL and the 
like that could come very handy.
OvchinnikovDmitrii Aug. 12, 2019, 10:35 a.m. UTC | #2
Yes, it is possible, but it is required to implement separate patch with
selector dx9, dx11, vulkan. We could do it when this one is committed.
I will double check with opencl interop and will comeback.
Timo Rothenpieler Aug. 12, 2019, 11:23 a.m. UTC | #3
On 12/08/2019 12:35, Дмитрий Овчинников wrote:
> Yes, it is possible, but it is required to implement separate patch with
> selector dx9, dx11, vulkan. We could do it when this one is committed.
> I will double check with opencl interop and will comeback.

There is no standardized OpenCL/Vulkan Interop as of now, but there are 
working group for it and it's probably gonna happen sooner or later, so 
it'd be nice to be prepared.
Philip Langdale Aug. 27, 2019, 5:08 p.m. UTC | #4
On 2019-08-08 11:33, OvchinnikovDmitrii wrote:
> 
> diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
> index 384d8efc92..f66b95645e 100644
> --- a/libavcodec/amfenc.c
> +++ b/libavcodec/amfenc.c
> @@ -213,6 +213,7 @@ static int
> amf_init_from_dxva2_device(AVCodecContext *avctx, AVDXVA2DeviceContex
>  static int amf_init_context(AVCodecContext *avctx)
>  {
>      AmfContext *ctx = avctx->priv_data;
> +    AMFContext1 *context1 = NULL;
>      AMF_RESULT  res;
>      av_unused int ret;
> 
> @@ -311,8 +312,20 @@ static int amf_init_context(AVCodecContext *avctx)
>              if (res == AMF_OK) {
>                  av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation
> succeeded via D3D9.\n");
>              } else {
> -                av_log(avctx, AV_LOG_ERROR, "AMF initialisation
> failed via D3D9: error %d.\n", res);
> -                return AVERROR(ENOSYS);
> +                AMFGuid guid = IID_AMFContext1();
> +                res =
> ctx->context->pVtbl->QueryInterface(ctx->context, &guid,
> (void**)&context1);
> +                AMF_RETURN_IF_FALSE(ctx, res == AMF_OK,
> AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res);
> +
> +                res = context1->pVtbl->InitVulkan(context1, NULL);
> +                context1->pVtbl->Release(context1);
> +                if (res != AMF_OK) {
> +                    if (res == AMF_NOT_SUPPORTED)
> +                        av_log(avctx, AV_LOG_ERROR, "AMF via Vulkan
> is not supported on the given device.\n");
> +                    else
> +                        av_log(avctx, AV_LOG_ERROR, "AMF failed to
> initialise on the given Vulkan device: %d.\n", res);
> +                    return AVERROR(ENOSYS);
> +                }
> +                av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation
> succeeded via Vulkan.\n");
>              }
>          }
>      }

It's fully contained in the decoder, so it's fine, and strictly better
than before. However, keep in mind that if we ever follow through on
adding a Vulkan hwcontext, this would need to be handled in a different
way - but we'll deal with that when we get there.

I'll push it when I get a chance later today.

--phil
Philip Langdale Aug. 28, 2019, 1:34 a.m. UTC | #5
On Tue, 27 Aug 2019 10:08:43 -0700
Philip Langdale <philipl@overt.org> wrote:

> On 2019-08-08 11:33, OvchinnikovDmitrii wrote:
> > 
> > diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
> > index 384d8efc92..f66b95645e 100644
> > --- a/libavcodec/amfenc.c
> > +++ b/libavcodec/amfenc.c
> > @@ -213,6 +213,7 @@ static int
> > amf_init_from_dxva2_device(AVCodecContext *avctx,
> > AVDXVA2DeviceContex static int amf_init_context(AVCodecContext
> > *avctx) {
> >      AmfContext *ctx = avctx->priv_data;
> > +    AMFContext1 *context1 = NULL;
> >      AMF_RESULT  res;
> >      av_unused int ret;
> > 
> > @@ -311,8 +312,20 @@ static int amf_init_context(AVCodecContext
> > *avctx) if (res == AMF_OK) {
> >                  av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation
> > succeeded via D3D9.\n");
> >              } else {
> > -                av_log(avctx, AV_LOG_ERROR, "AMF initialisation
> > failed via D3D9: error %d.\n", res);
> > -                return AVERROR(ENOSYS);
> > +                AMFGuid guid = IID_AMFContext1();
> > +                res =
> > ctx->context->pVtbl->QueryInterface(ctx->context, &guid,
> > (void**)&context1);
> > +                AMF_RETURN_IF_FALSE(ctx, res == AMF_OK,
> > AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res);
> > +
> > +                res = context1->pVtbl->InitVulkan(context1, NULL);
> > +                context1->pVtbl->Release(context1);
> > +                if (res != AMF_OK) {
> > +                    if (res == AMF_NOT_SUPPORTED)
> > +                        av_log(avctx, AV_LOG_ERROR, "AMF via Vulkan
> > is not supported on the given device.\n");
> > +                    else
> > +                        av_log(avctx, AV_LOG_ERROR, "AMF failed to
> > initialise on the given Vulkan device: %d.\n", res);
> > +                    return AVERROR(ENOSYS);
> > +                }
> > +                av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation
> > succeeded via Vulkan.\n");
> >              }
> >          }
> >      }  
> 
> It's fully contained in the decoder, so it's fine, and strictly better
> than before. However, keep in mind that if we ever follow through on
> adding a Vulkan hwcontext, this would need to be handled in a
> different way - but we'll deal with that when we get there.
> 
> I'll push it when I get a chance later today.

Pushed with changelog and micro bump.

--phil
OvchinnikovDmitrii Aug. 28, 2019, 7:06 a.m. UTC | #6
> Pushed with changelog and micro bump.

Thanks for review/pushing! Waiting for Vulkan hwcontext to implement fully
hwaccelerated pipeline on linux.
-- 
С уважением, Овчинников Д.А.
diff mbox

Patch

diff --git a/doc/general.texi b/doc/general.texi
index 3c0c803449..056f88fba3 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -27,16 +27,26 @@  enable it.
 
 @section AMD AMF/VCE
 
-FFmpeg can use the AMD Advanced Media Framework library under Windows
-for accelerated H.264 and HEVC encoding on hardware with Video Coding Engine (VCE).
+FFmpeg can use the AMD Advanced Media Framework library 
+for accelerated H.264 and HEVC(only windows) encoding on hardware with Video Coding Engine (VCE).
 
-To enable support you must obtain the AMF framework header files from
+To enable support you must obtain the AMF framework header files(version 1.4.9+) from
 @url{https://github.com/GPUOpen-LibrariesAndSDKs/AMF.git}.
 
 Create an @code{AMF/} directory in the system include path.
 Copy the contents of @code{AMF/amf/public/include/} into that directory.
 Then configure FFmpeg with @code{--enable-amf}.
 
+Initialization of amf encoder occurs in this order:
+1) trying to initialize through dx11(only windows)
+2) trying to initialize through dx9(only windows)
+3) trying to initialize through vulkan
+
+To use h.264(AMD VCE) encoder on linux amdgru-pro version 19.20+ and amf-amdgpu-pro 
+package(amdgru-pro contains, but does not install automatically) are required.
+
+This driver can be installed using amdgpu-pro-install script in official amd driver archive.
+
 @section AviSynth
 
 FFmpeg can read AviSynth scripts as input. To enable support, pass
diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
index 384d8efc92..f66b95645e 100644
--- a/libavcodec/amfenc.c
+++ b/libavcodec/amfenc.c
@@ -213,6 +213,7 @@  static int amf_init_from_dxva2_device(AVCodecContext *avctx, AVDXVA2DeviceContex
 static int amf_init_context(AVCodecContext *avctx)
 {
     AmfContext *ctx = avctx->priv_data;
+    AMFContext1 *context1 = NULL;
     AMF_RESULT  res;
     av_unused int ret;
 
@@ -311,8 +312,20 @@  static int amf_init_context(AVCodecContext *avctx)
             if (res == AMF_OK) {
                 av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D9.\n");
             } else {
-                av_log(avctx, AV_LOG_ERROR, "AMF initialisation failed via D3D9: error %d.\n", res);
-                return AVERROR(ENOSYS);
+                AMFGuid guid = IID_AMFContext1();
+                res = ctx->context->pVtbl->QueryInterface(ctx->context, &guid, (void**)&context1);
+                AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res);
+
+                res = context1->pVtbl->InitVulkan(context1, NULL);
+                context1->pVtbl->Release(context1);
+                if (res != AMF_OK) {
+                    if (res == AMF_NOT_SUPPORTED)
+                        av_log(avctx, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device.\n");
+                    else
+                        av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on the given Vulkan device: %d.\n", res);
+                    return AVERROR(ENOSYS);
+                }
+                av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via Vulkan.\n");
             }
         }
     }