diff mbox series

[FFmpeg-devel,5/8] lavc/nvenc: Add hardware config metadata

Message ID 20200413153321.5956-5-sw@jkqxz.net
State Accepted
Headers show
Series [FFmpeg-devel,1/8] lavc: Rename hwaccel.h to hwconfig.h | expand

Checks

Context Check Description
andriy/default pending
andriy/make success Make finished
andriy/make_fate success Make fate finished

Commit Message

Mark Thompson April 13, 2020, 3:33 p.m. UTC
NOT TESTED.
---
Needs someone with suitable hardware to try it.

With this and the relevant ffmpeg patches, existing stuff should continue to work and you should also be able to choose between multiple devices for a standalone encoder with things like:

ffmpeg -init_hw_device cuda:2 ... -c:v nvenc ...
ffmpeg -init_hw_device d3d11:2 ... -c:v nvenc ...


 libavcodec/nvenc.c      | 11 +++++++++++
 libavcodec/nvenc.h      |  1 +
 libavcodec/nvenc_h264.c |  1 +
 libavcodec/nvenc_hevc.c |  1 +
 4 files changed, 14 insertions(+)

Comments

Dennis Mungai April 13, 2020, 4:48 p.m. UTC | #1
On Mon, 13 Apr 2020 at 18:34, Mark Thompson <sw@jkqxz.net> wrote:

> NOT TESTED.
> ---
> Needs someone with suitable hardware to try it.
>
> With this and the relevant ffmpeg patches, existing stuff should continue
> to work and you should also be able to choose between multiple devices for
> a standalone encoder with things like:
>
> ffmpeg -init_hw_device cuda:2 ... -c:v nvenc ...
> ffmpeg -init_hw_device d3d11:2 ... -c:v nvenc ...
>
>
>  libavcodec/nvenc.c      | 11 +++++++++++
>  libavcodec/nvenc.h      |  1 +
>  libavcodec/nvenc_h264.c |  1 +
>  libavcodec/nvenc_hevc.c |  1 +
>  4 files changed, 14 insertions(+)
>
> diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
> index 9a96bf2bba..b0cd8874ee 100644
> --- a/libavcodec/nvenc.c
> +++ b/libavcodec/nvenc.c
> @@ -30,6 +30,7 @@
>  #include "libavutil/avassert.h"
>  #include "libavutil/mem.h"
>  #include "libavutil/pixdesc.h"
> +#include "hwconfig.h"
>  #include "internal.h"
>
>  #define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, dl_fn->cuda_dl, x)
> @@ -55,6 +56,16 @@ const enum AVPixelFormat ff_nvenc_pix_fmts[] = {
>      AV_PIX_FMT_NONE
>  };
>
> +const AVCodecHWConfigInternal *ff_nvenc_hw_configs[] = {
> +    HW_CONFIG_ENCODER_FRAMES(CUDA,  CUDA),
> +    HW_CONFIG_ENCODER_DEVICE(NONE,  CUDA),
> +#if CONFIG_D3D11VA
> +    HW_CONFIG_ENCODER_FRAMES(D3D11, D3D11),
> +    HW_CONFIG_ENCODER_DEVICE(NONE,  D3D11),
> +#endif
> +    NULL,
> +};
> +
>  #define IS_10BIT(pix_fmt)  (pix_fmt == AV_PIX_FMT_P010    || \
>                              pix_fmt == AV_PIX_FMT_P016    || \
>                              pix_fmt == AV_PIX_FMT_YUV444P16)
> diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
> index c44c81e675..c80332d914 100644
> --- a/libavcodec/nvenc.h
> +++ b/libavcodec/nvenc.h
> @@ -217,5 +217,6 @@ int ff_nvenc_encode_frame(AVCodecContext *avctx,
> AVPacket *pkt,
>  void ff_nvenc_encode_flush(AVCodecContext *avctx);
>
>  extern const enum AVPixelFormat ff_nvenc_pix_fmts[];
> +extern const AVCodecHWConfigInternal *ff_nvenc_hw_configs[];
>
>  #endif /* AVCODEC_NVENC_H */
> diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c
> index 479155fe15..6d82422308 100644
> --- a/libavcodec/nvenc_h264.c
> +++ b/libavcodec/nvenc_h264.c
> @@ -248,4 +248,5 @@ AVCodec ff_h264_nvenc_encoder = {
>      .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
>      .pix_fmts       = ff_nvenc_pix_fmts,
>      .wrapper_name   = "nvenc",
> +    .hw_configs     = ff_nvenc_hw_configs,
>  };
> diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
> index 7c9b3848f1..58d5265977 100644
> --- a/libavcodec/nvenc_hevc.c
> +++ b/libavcodec/nvenc_hevc.c
> @@ -206,4 +206,5 @@ AVCodec ff_hevc_nvenc_encoder = {
>      .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE,
>      .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
>      .wrapper_name   = "nvenc",
> +    .hw_configs     = ff_nvenc_hw_configs,
>  };
> --
> 2.25.1
>
>
>
What type of hardware is considered "suitable"? Systems with multiple
NVENC-capable GPUs?
Also, provide a sample command line extending on the examples above that
you'd like tested and I'll report back with results.

Regards,

Dennis.
Mark Thompson April 26, 2020, 6:02 p.m. UTC | #2
On 13/04/2020 17:48, Dennis Mungai wrote:
> On Mon, 13 Apr 2020 at 18:34, Mark Thompson <sw@jkqxz.net> wrote:
> 
>> NOT TESTED.
>> ---
>> Needs someone with suitable hardware to try it.
>>
>> With this and the relevant ffmpeg patches, existing stuff should continue
>> to work and you should also be able to choose between multiple devices for
>> a standalone encoder with things like:
>>
>> ffmpeg -init_hw_device cuda:2 ... -c:v nvenc ...
>> ffmpeg -init_hw_device d3d11:2 ... -c:v nvenc ...
>>
>>
>>  libavcodec/nvenc.c      | 11 +++++++++++
>>  libavcodec/nvenc.h      |  1 +
>>  libavcodec/nvenc_h264.c |  1 +
>>  libavcodec/nvenc_hevc.c |  1 +
>>  4 files changed, 14 insertions(+)
>>
>> diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
>> index 9a96bf2bba..b0cd8874ee 100644
>> --- a/libavcodec/nvenc.c
>> +++ b/libavcodec/nvenc.c
>> @@ -30,6 +30,7 @@
>>  #include "libavutil/avassert.h"
>>  #include "libavutil/mem.h"
>>  #include "libavutil/pixdesc.h"
>> +#include "hwconfig.h"
>>  #include "internal.h"
>>
>>  #define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, dl_fn->cuda_dl, x)
>> @@ -55,6 +56,16 @@ const enum AVPixelFormat ff_nvenc_pix_fmts[] = {
>>      AV_PIX_FMT_NONE
>>  };
>>
>> +const AVCodecHWConfigInternal *ff_nvenc_hw_configs[] = {
>> +    HW_CONFIG_ENCODER_FRAMES(CUDA,  CUDA),
>> +    HW_CONFIG_ENCODER_DEVICE(NONE,  CUDA),
>> +#if CONFIG_D3D11VA
>> +    HW_CONFIG_ENCODER_FRAMES(D3D11, D3D11),
>> +    HW_CONFIG_ENCODER_DEVICE(NONE,  D3D11),
>> +#endif
>> +    NULL,
>> +};
>> +
>>  #define IS_10BIT(pix_fmt)  (pix_fmt == AV_PIX_FMT_P010    || \
>>                              pix_fmt == AV_PIX_FMT_P016    || \
>>                              pix_fmt == AV_PIX_FMT_YUV444P16)
>> diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
>> index c44c81e675..c80332d914 100644
>> --- a/libavcodec/nvenc.h
>> +++ b/libavcodec/nvenc.h
>> @@ -217,5 +217,6 @@ int ff_nvenc_encode_frame(AVCodecContext *avctx,
>> AVPacket *pkt,
>>  void ff_nvenc_encode_flush(AVCodecContext *avctx);
>>
>>  extern const enum AVPixelFormat ff_nvenc_pix_fmts[];
>> +extern const AVCodecHWConfigInternal *ff_nvenc_hw_configs[];
>>
>>  #endif /* AVCODEC_NVENC_H */
>> diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c
>> index 479155fe15..6d82422308 100644
>> --- a/libavcodec/nvenc_h264.c
>> +++ b/libavcodec/nvenc_h264.c
>> @@ -248,4 +248,5 @@ AVCodec ff_h264_nvenc_encoder = {
>>      .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
>>      .pix_fmts       = ff_nvenc_pix_fmts,
>>      .wrapper_name   = "nvenc",
>> +    .hw_configs     = ff_nvenc_hw_configs,
>>  };
>> diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
>> index 7c9b3848f1..58d5265977 100644
>> --- a/libavcodec/nvenc_hevc.c
>> +++ b/libavcodec/nvenc_hevc.c
>> @@ -206,4 +206,5 @@ AVCodec ff_hevc_nvenc_encoder = {
>>      .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE,
>>      .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
>>      .wrapper_name   = "nvenc",
>> +    .hw_configs     = ff_nvenc_hw_configs,
>>  };
>> --
>> 2.25.1
>>
>>
>>
> What type of hardware is considered "suitable"? Systems with multiple
> NVENC-capable GPUs?

Something supporting CUDA, NVENC and D3D11.

> Also, provide a sample command line extending on the examples above that
> you'd like tested and I'll report back with results.

Create CUDA and D3D11 devices and make sure that they get passed to an NVENC encoder.  Since NVENC chooses a device itself if not given one, I think you would need to stop it in a debugger to make sure that the right thing happened.

Thanks,

- Mark
Timo Rothenpieler April 27, 2020, 8:35 p.m. UTC | #3
On 13.04.2020 17:33, Mark Thompson wrote:
> NOT TESTED.
> 

Fails to build:

> In file included from libavcodec/nvenc_hevc.c:24:
> libavcodec/nvenc.h:220:14: error: unknown type name ‘AVCodecHWConfigInternal’
>   220 | extern const AVCodecHWConfigInternal *ff_nvenc_hw_configs[];
>       |              ^~~~~~~~~~~~~~~~~~~~~~~
> libavcodec/nvenc_hevc.c:211:23: warning: initialization of ‘const struct AVCodecHWConfigInternal **’ from incompatible pointer type ‘const int **’ [-Wincompatible-pointer-types]
>   211 |     .hw_configs     = ff_nvenc_hw_configs,
>       |                       ^~~~~~~~~~~~~~~~~~~
> libavcodec/nvenc_hevc.c:211:23: note: (near initialization for ‘ff_hevc_nvenc_encoder.hw_configs’)
> In file included from libavcodec/nvenc.c:24:
> libavcodec/nvenc.h:220:14: error: unknown type name ‘AVCodecHWConfigInternal’
>   220 | extern const AVCodecHWConfigInternal *ff_nvenc_hw_configs[];
>       |              ^~~~~~~~~~~~~~~~~~~~~~~
> libavcodec/nvenc.c:59:32: error: conflicting types for ‘ff_nvenc_hw_configs’
>    59 | const AVCodecHWConfigInternal *ff_nvenc_hw_configs[] = {
>       |                                ^~~~~~~~~~~~~~~~~~~
> In file included from libavcodec/nvenc.c:24:
> libavcodec/nvenc.h:220:39: note: previous declaration of ‘ff_nvenc_hw_configs’ was here
>   220 | extern const AVCodecHWConfigInternal *ff_nvenc_hw_configs[];
>       |                                       ^~~~~~~~~~~~~~~~~~~
> CC      libavcodec/parsers.o
> In file included from libavcodec/nvenc.c:33:
> libavcodec/hwconfig.h:91:28: error: ‘AV_HWDEVICE_TYPE_D3D11’ undeclared here (not in a function); did you mean ‘AV_HWDEVICE_TYPE_D3D11VA’?
>    91 |             .device_type = AV_HWDEVICE_TYPE_ ## device_type_, \
>       |                            ^~~~~~~~~~~~~~~~~
> libavcodec/hwconfig.h:91:28: note: in definition of macro ‘HW_CONFIG_ENCODER’
>    91 |             .device_type = AV_HWDEVICE_TYPE_ ## device_type_, \
>       |                            ^~~~~~~~~~~~~~~~~
> libavcodec/nvenc.c:63:5: note: in expansion of macro ‘HW_CONFIG_ENCODER_FRAMES’
>    63 |     HW_CONFIG_ENCODER_FRAMES(D3D11, D3D11),
>       |     ^~~~~~~~~~~~~~~~~~~~~~~~
> make: *** [ffbuild/common.mak:59: libavcodec/nvenc_hevc.o] Error 1
> make: *** Waiting for unfinished jobs....
> In file included from libavcodec/nvenc_h264.c:24:
> libavcodec/nvenc.h:220:14: error: unknown type name ‘AVCodecHWConfigInternal’
>   220 | extern const AVCodecHWConfigInternal *ff_nvenc_hw_configs[];
>       |              ^~~~~~~~~~~~~~~~~~~~~~~
> libavcodec/nvenc_h264.c:256:23: warning: initialization of ‘const struct AVCodecHWConfigInternal **’ from incompatible pointer type ‘const int **’ [-Wincompatible-pointer-types]
>   256 |     .hw_configs     = ff_nvenc_hw_configs,
>       |                       ^~~~~~~~~~~~~~~~~~~
> libavcodec/nvenc_h264.c:256:23: note: (near initialization for ‘ff_h264_nvenc_encoder.hw_configs’)
> make: *** [ffbuild/common.mak:59: libavcodec/nvenc_h264.o] Error 1
> make: *** [ffbuild/common.mak:59: libavcodec/nvenc.o] Error 1
Timo Rothenpieler April 27, 2020, 9:11 p.m. UTC | #4
fixed version applied
diff mbox series

Patch

diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index 9a96bf2bba..b0cd8874ee 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -30,6 +30,7 @@ 
 #include "libavutil/avassert.h"
 #include "libavutil/mem.h"
 #include "libavutil/pixdesc.h"
+#include "hwconfig.h"
 #include "internal.h"
 
 #define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, dl_fn->cuda_dl, x)
@@ -55,6 +56,16 @@  const enum AVPixelFormat ff_nvenc_pix_fmts[] = {
     AV_PIX_FMT_NONE
 };
 
+const AVCodecHWConfigInternal *ff_nvenc_hw_configs[] = {
+    HW_CONFIG_ENCODER_FRAMES(CUDA,  CUDA),
+    HW_CONFIG_ENCODER_DEVICE(NONE,  CUDA),
+#if CONFIG_D3D11VA
+    HW_CONFIG_ENCODER_FRAMES(D3D11, D3D11),
+    HW_CONFIG_ENCODER_DEVICE(NONE,  D3D11),
+#endif
+    NULL,
+};
+
 #define IS_10BIT(pix_fmt)  (pix_fmt == AV_PIX_FMT_P010    || \
                             pix_fmt == AV_PIX_FMT_P016    || \
                             pix_fmt == AV_PIX_FMT_YUV444P16)
diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
index c44c81e675..c80332d914 100644
--- a/libavcodec/nvenc.h
+++ b/libavcodec/nvenc.h
@@ -217,5 +217,6 @@  int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 void ff_nvenc_encode_flush(AVCodecContext *avctx);
 
 extern const enum AVPixelFormat ff_nvenc_pix_fmts[];
+extern const AVCodecHWConfigInternal *ff_nvenc_hw_configs[];
 
 #endif /* AVCODEC_NVENC_H */
diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c
index 479155fe15..6d82422308 100644
--- a/libavcodec/nvenc_h264.c
+++ b/libavcodec/nvenc_h264.c
@@ -248,4 +248,5 @@  AVCodec ff_h264_nvenc_encoder = {
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
     .pix_fmts       = ff_nvenc_pix_fmts,
     .wrapper_name   = "nvenc",
+    .hw_configs     = ff_nvenc_hw_configs,
 };
diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
index 7c9b3848f1..58d5265977 100644
--- a/libavcodec/nvenc_hevc.c
+++ b/libavcodec/nvenc_hevc.c
@@ -206,4 +206,5 @@  AVCodec ff_hevc_nvenc_encoder = {
     .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
     .wrapper_name   = "nvenc",
+    .hw_configs     = ff_nvenc_hw_configs,
 };