MattMcManis / Axiom

An FFmpeg GUI for Windows
https://axiomui.github.io
GNU General Public License v3.0
1.49k stars 116 forks source link

Setting HW Accel to "nvenc" when using x265 does not set the encoder to "hevc_nvenc" as expected #41

Open Henri-J-Norden opened 4 years ago

Henri-J-Norden commented 4 years ago

Hi! I noticed that with nvenc on x264 I got an encoding framerate >100fps, while with x265 the performance was an abysmal ~15 fps.

The issue: on x264 with HW Accel set to nvenc, the program properly sets the encoder to h264_nvenc, while on x265 the encoder is always set to libx265. I verified this by manually changing the encoder in the generated script to hevc_nvenc and this resulted in good encoding performance similar to x264 with nvenc enabled. Hopefully this is an easy fix.

I am using version 1.7.9.1-Alpha.

Best regards, Henri

MattMcManis commented 4 years ago

Thanks for finding this bug, it was a typo in the code, causing it to skip x265.

I've released an update.

Press the arrow button in Axiom to update through PowerShell, or download from here
https://github.com/MattMcManis/Axiom/releases

Update

VA1DER commented 4 years ago

There is still a bug. The "fix" sets the encoder as "x265_nvenc", but for x265 the codec should be set to "hevc_nvenc".

MattMcManis commented 4 years ago

@VA1DER

I see, the HWAccel section had a some other problems with it. I've released an update.

cuvid x264 is -c:v h264_cuvid x265 is -c:v hevc_cuvid

nvenc x264 is -c:v h264_nvenc x265 is -c:v hevc_nvenc

cuvid+nvenc x264 is -hwaccel cuvid -c:v h264_nvenc x265 is -hwaccel cuvid -c:v hevc_nvenc

VA1DER commented 4 years ago

There is still an issue with cuvid and cuvid+nvenc. Neither produce proper command lines for me.

Cuvid is a decode-only acceleration, so -c:v hevc_cuvid has to appear before the input file. The output codec should be just the non-accelerated libx265, for example.

Cuvid+NVENC - is this even a legal usage? I can't get it to work with any command line in my FFMPEG.

MattMcManis commented 4 years ago

I'll fix cuvid, and might remove cuvid+nvenc, and add these new options https://github.com/MattMcManis/Axiom/issues/42#issue-615176173 I'll release an update soon.

MattMcManis commented 4 years ago

@VA1DER

Does this look correct?

dxva2 (decode)

ffmpeg -hwaccel dxva2 -i input.mpg -c:v libx264 output.mp4

cuda (decode)

ffmpeg -hwaccel cuda -i input.mpg -c:v libx264 output.mp4

cuvid (decode)

ffmpeg -hwaccel cuvid -c:v h264_cuvid -i input.mpg output.mp4

or

ffmpeg -hwaccel cuvid -i input.mpg -c:v libx264 output.mp4

nvenc (transcode)

ffmpeg -i input.mpg -c:v h264_nvenc output.mp4

nvenc+cuda (transcode)

ffmpeg -hwaccel cuda -hwaccel_output_format cuda -i input.mpg -c:v h264_nvenc output.mp4

qsv (transcode)

ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -i input.mpg -c:v h264_qsv output.mp4

Resources:
https://trac.ffmpeg.org/wiki/HWAccelIntro
https://trac.ffmpeg.org/wiki/Hardware/QuickSync

MattMcManis commented 4 years ago

@VA1DER

I redid a lot of the code for HW Accel. I released the update for you to test.

CUVID still might not work properly, I don't have the custom compiled ffmpeg to test it.

Intel QSV hevc_qsv gives loading plugin error, but h264_qsv works.

VA1DER commented 4 years ago

@MattMcManis

The Zeranoe ffmpeg builds (I use the static ones) have all the hardware support built in.

CUVID Decode: Omit the "-hwaccel cuvid". With CUVID you just need to know the input codec and to speciffy the correct cuvid decoder on the command line.
ffmpeg -c:v h264_cuvid -i input.mp4 -c:v (outputcodec) output.mp4

It's kind of dumb, actually. In fact the whole hardware accel command line system in ffmpeg is dumb in that different types of acceleration use completely different command line paradigms. dxva2 is correct. nvenc is correct. qsv is correct.

I was mistaken about cuvid+nvenc not being legal. It works. In fact, I can make a command line that works for all the decode-only hardware accelerations and also works with nvenc encoding acceleration:

cuvid+nvenc ffmpeg -c:v h264_cuvid -i input.mkv -c:v hevc_nvenc output.mp4

dxva2+nvenc ffmpeg -hwaccel dxva2 -i input.mkv -c:v hevc_nvenc output.mp4

I cannot figure out a way to get qsv and nvenc to work together.

I would suggest if you want to support decode-only accel that you split up the decode hardware accel and the encode hardware accel into two settings. There might have to be some glue logic to forbid combinations that don't work.

VA1DER commented 4 years ago

@MattMcManis

For what it's worth, I put in an enhancement ticket with ffmpeg to clean up their command line:

https://trac.ffmpeg.org/ticket/8666#ticket

I don't hold out much hope, but we'll see.

MattMcManis commented 4 years ago

@VA1DER

When trying to use NVENC, I get the error Cannot load nvEncodeAPI64.dll. Maybe my graphics card does not have the driver that supports it.

I might remove CUVID, since there is no easy way for the user to know the input codec.


How does this look for splitting HW Accel options into 2 parts?
Or I could have 1 menu with individual and all combinations.

Decode

Transcode

Combinations

MattMcManis commented 4 years ago

@VA1DER

I've released an update with some new options:

These changes could introduce new bugs, you will have to test it out and let me know how it works. Certain HW Accel options may need the required Intel/Nvidia/AMD hardware. Some HW Accel Transcode codecs are only available for x264/x265.

https://github.com/MattMcManis/Axiom/releases

See a related issue here https://github.com/MattMcManis/Axiom/issues/42#issue-615176173

MarcoRavich commented 3 years ago

Just found this interesting insight @ StackExchange:

Notes on encoding with the QSV encoders: Typically, you will need to initialize a hardware device that will be used by both the encoder(s) in use and filtering, as shown in the example below:

ffmpeg -y -loglevel debug -init_hw_device qsv=hw -filter_hw_device hw -hwaccel qsv -hwaccel_output_format qsv \
-i simpsons.mp4 -vf 'format=qsv,hwupload=extra_hw_frames=64'  \
-c:v hevc_qsv \
-bf 3 -b:v 3.75M -maxrate:v 3.75M -bufsize:v 0.5M -r:v 30 -c:a copy -f mp4 trolled.mp4

See how the hardware device for use with MFX sessions has been initialized (-init_hw_device qsv=hw) and mapped as available to filters such as hwupload (-filter_hw_device hw).

Recommended for further reading: The Advanced Video options section on FFmpeg wiki.

The example above demonstrates the use of the hevc_qsv encoders with some private options passed to it, for reference.

Another example, showing the use of the h264_qsv encoder:

ffmpeg -y -loglevel debug -init_hw_device qsv=hw -filter_hw_device hw -hwaccel qsv -hwaccel_output_format qsv \
-i simpsons.mp4 -vf 'format=qsv,hwupload=extra_hw_frames=64'  \
-c:v h264_qsv \
-bf 3 -b:v 15M -maxrate:v 15M -bufsize:v 2M -r:v 30 -c:a copy -f mp4 trolled.mp4

Take note that both examples above will use the constant bitrate control (CBR) method in MFX, as shown in the console log: [hevc_qsv @ 0x55faf21eedc0] Using the constant bitrate (CBR) ratecontrol method

Rate control, similar to how the VAAPI implementation governs it, is driven by the parameters -b:v (target video bitrate) and the -maxrate:v (maximum video bitrate) passed to the encoder. If they are equal, CBR (constant bitrate control) is used. If maxrate is greater than target bitrate, then VBR, and in effect, look-ahead based control (if so desired) are enabled.

Observe how we call up the hwupload filter, chained with the format=qsv filter to ensure that the MFX runtime receives a supported pixel format. Failure to pass this video filter chain will result in initialization failure, with output similar to this:

[h264_qsv @ 0x560e1bda7280] Selected ratecontrol mode is unsupported
[h264_qsv @ 0x560e1bda7280] Low power mode is unsupported
[h264_qsv @ 0x560e1bda7280] Current frame rate is unsupported
[h264_qsv @ 0x560e1bda7280] Current picture structure is unsupported
[h264_qsv @ 0x560e1bda7280] Current resolution is unsupported
[h264_qsv @ 0x560e1bda7280] Current pixel format is unsupported
[h264_qsv @ 0x560e1bda7280] some encoding parameters are not supported by the QSV runtime. Please double check the input parameters.
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height

The error message may seem ambiguous at first, but it stems primarily from mapping invalid options to the underlying MFX library, such as an unsupported pixel format.

The extra argument extra_hw_frames=64 passed to hwupload has to do with the MFX runtime requiring a fixed frame pool size to be pre-allocated. Use a number suitable to your requirements. Generally, you'll need a larger number (64, or thereabouts) if using features such as look-ahead (LA-ICQ).

Hope that helps/inspires !