lisamelton / other_video_transcoding

Other tools to transcode videos.
MIT License
543 stars 24 forks source link

Add option to override VAAPI device. #133

Open mpmc opened 2 years ago

mpmc commented 2 years ago

Thanks for creating this project, I have two renderers (amd and intel) but only the intel device can be used, however the wrong device is chosen. On my system it's renderD129 rather than renderD128

vainfo --display drm --device /dev/dri/renderD129
libva info: VA-API version 1.13.0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_13
libva error: /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so init failed
libva info: va_openDriver() returns 1
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva info: Found init function __vaDriverInit_1_8
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.13 (libva 2.12.0)
vainfo: Driver version: Intel i965 driver for Intel(R) Haswell Desktop - 2.4.1
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Simple            : VAEntrypointEncSlice
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline: VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointEncSlice
      VAProfileH264High               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointEncSlice
      VAProfileH264MultiviewHigh      : VAEntrypointVLD
      VAProfileH264MultiviewHigh      : VAEntrypointEncSlice
      VAProfileH264StereoHigh         : VAEntrypointVLD
      VAProfileH264StereoHigh         : VAEntrypointEncSlice
      VAProfileVC1Simple              : VAEntrypointVLD
      VAProfileVC1Main                : VAEntrypointVLD
      VAProfileVC1Advanced            : VAEntrypointVLD
      VAProfileNone                   : VAEntrypointVideoProc
      VAProfileJPEGBaseline           : VAEntrypointVLD

Please could you add the option to change the render device for VAAPI?

Thanks :)

lisamelton commented 2 years ago

@mpmc Thanks for using my software! And sorry you ran into this problem. But I think you might be the first VAAPI user with two devices? Not sure. I'll talk to the HiveMind™ to see if anyone else has hit this. In the meantime, I'll start working on an option specify the device path. I assume having to specify the whole path is better, albeit nerdier?

mpmc commented 2 years ago

@mpmc Thanks for using my software! And sorry you ran into this problem. But I think you might be the first VAAPI user with two devices? Not sure. I'll talk to the HiveMind™ to see if anyone else has hit this. In the meantime, I'll start working on an option specify the device path. I assume having to specify the whole path is better, albeit nerdier?

No need to apologise, it's not your fault and it isn't a bug! I'm sure I'm not the only one with such a setup though :) My motherboard just allows the secondary integrated intel gpu to run alongside the amd pcie gpu. As for paths I think ffmpeg requires it?

lisamelton commented 2 years ago

@mpmc Ah, so you have one of those beefy AMD CPUs then with an on-board encoder. Nice!

Yeah, I know ffmpeg requires the full path but I could be clever or something and just ask for the device name and then prepend /dev/dri/ to save you the typing. :)

mpmc commented 2 years ago

@donmelton ha, i wish, it's just an old intel G3320 CPU and an amd 7700 graphics card!

lisamelton commented 2 years ago

@mpmc Well, at least your GPU is decent. :)

skj-dev commented 2 years ago

@mpmc

If Docker is an option, you might want to try explicitly mapping only the Intel device into a container context so ffmpeg only has one to choose from. I'm assuming you also have a /dev/dri/card0 => AMD, and /dev/dri/card1 => Intel in this example.

I'm assuming your input files are in a sub directory from your working directory (e.g. /path/to/dir/sources, and you're running the following command from the /path/to/dir directory). If not, then you'll just need to adjust the bind mounting options to line up with how your hierarchy is laid out.

docker run --rm --device /dev/dri/renderD129:/dev/dri/renderD129 --device /dev/dri/card1:/dev/dri/card1 -v $(pwd):$(pwd) -w $(pwd) ghcr.io/ttys0/other-transcode:qsv-latest sources/file.mkv

lisamelton commented 2 years ago

@ttyS0 Thanks once again for your container (and other) expertise, sir! 👍

@mpmc If that works for you, do you still need the option?

mpmc commented 2 years ago

@ttyS0 Thanks for the tip, :) but I'm going to be honest, I really do not like running things in docker, especially if I can avoid it.

@donmelton you do not need to add the option if you don't want to, it is after all a request and nothing more! But I would be grateful if you could when you have the time. :)

lisamelton commented 2 years ago

@mpmc No problem. I was just checking. :) I'll still plan on adding the option then.

mpmc commented 2 years ago

Oh, before I forget (and in case it's somehow useful), here's what I was using to get vaapi encoding via ffmpeg going before I found your repo :)

ffmpeg \
        -hwaccel vaapi \
        -hwaccel_device /dev/dri/renderD129 \
        -hwaccel_output_format vaapi \
        -nostdin \
        -probesize 10000000 \
        -playlist "${playlist}" \
        -angle 0 \
        -i "bluray:${input}" \
        -rc_mode:v 3 \
        -b:v 4000k \
        -profile:v 77 \
        -level 40 \
        -map 0:v \
        -c:v h264_vaapi \
        -map 0:a:0 \
        -c:a:0 copy \
        -map 0:a:1? \
        -map 0:a:2? \
        -c:a:1 aac \
        -c:a:2 aac \
        -b:a:1 160k \
        -b:a:2 160k \
        -c:s:0 copy \
        -map 0:s:0? \
        "${title}-${playlist}-`date`.mkv" 2>&1 | tee "${title}-${playlist}-`date`.log"

This command works as far as using vaapi but isn't as fine tuned as your script.

lisamelton commented 2 years ago

@mpmc Interesting. Thanks! 👍

lisamelton commented 2 years ago

@mpmc OK, I've just checked in a new option to implement this. Here's how I describe it in the --help full output:

    --vaapi-device PATH
                    set device path (default: /dev/dri/renderD128)

Please download a copy of other-transcode from GitHub and try it out.

mpmc commented 2 years ago

@mpmc OK, I've just checked in a new option to implement this. Here's how I describe it in the --help full output:

    --vaapi-device PATH
                    set device path (default: /dev/dri/renderD128)

Please download a copy of other-transcode from GitHub and try it out.

It works. Thank you :)

[graph 0 input from stream 0:0 @ 0x5579572b6700] w:1920 h:1080 pixfmt:vaapi_vld tb:1/1000 fr:24000/1001 sar:1/1
[h264_vaapi @ 0x557956f82180] Using input frames context (format vaapi_vld) with h264_vaapi encoder.
[h264_vaapi @ 0x557956f82180] Input surface format is nv12.
[h264_vaapi @ 0x557956f82180] Using VAAPI profile VAProfileH264High (7).
[h264_vaapi @ 0x557956f82180] Using VAAPI entrypoint VAEntrypointEncSlice (6).
[h264_vaapi @ 0x557956f82180] Using VAAPI render target format YUV420 (0x1).
[h264_vaapi @ 0x557956f82180] RC mode: VBR.
[h264_vaapi @ 0x557956f82180] RC target: 50% of 12000000 bps over 500 ms.
[h264_vaapi @ 0x557956f82180] RC buffer: 6000000 bits, initial fullness 4500000 bits.
[h264_vaapi @ 0x557956f82180] RC framerate: 24000/1001 (23.98 fps).
[h264_vaapi @ 0x557956f82180] Using intra, P- and B-frames (supported references: 1 / 1).
[h264_vaapi @ 0x557956f82180] All wanted packed headers available (wanted 0xd, found 0x1f).
[h264_vaapi @ 0x557956f82180] Using level 4.
lisamelton commented 2 years ago

@mpmc Thanks for testing! And you are very welcome. I'll probably release this in a few weeks because I'm working on other changes. I'll let you know here when version 0.11.0 is out.

mpmc commented 2 years ago

@mpmc Thanks for testing! And you are very welcome. I'll probably release this in a few weeks because I'm working on other changes. I'll let you know here when version 0.11.0 is out.

Sadly whilst it does work, it results in blocking on fast moving scenes. I suspect vaapi is just not up to the job.

wintervaler commented 2 years ago

My suspicion is that, rather than the blockiness being a result of VAAPI implementation, it's the underlying hardware — Intel encoders improved rapidly generation over generation until about 6th (Skylake) or 7th (Kaby Lake) generations, at which point quality largely leveled off (at what most would agree to be an above-average level, even using VAAPI to access the encoders). Your CPU looks like it is from the Haswell days, meaning you're dealing with a fairly early incarnation of the QuickSync encoder on the iGPU, which is showing its age these days both in terms of quality and codec support.

lisamelton commented 2 years ago

Since the code is in I'm going to close this for now. Thanks for testing!

skj-dev commented 2 years ago

Just adding a bit of nitpick.

Specifying the --vaapi-device is throwing the encode into VAAPI mode (notice the h264_vaapi in the logs), and not using QSV mode. My guess is that has a lot to do with the poor quality, since VAAPI is not great by itself. It's also true, as @wintervaler pointed out, that Haswell generation iGPU is not going to be great from a QSV point of view. However, if this were a newer generation of iGPU, the difference would be more stark, since the QSV output could be better, but not if h264_vaapi is being used. The QSV option would need to be -qsv_device for ffmpeg, since it doesn't use the VAAPI device setting.

lisamelton commented 2 years ago

@ttyS0 OK, re-opening the issue. I'm still unclear on how to fix this. Can you give me a sample ffmpeg command line that would work for @wintervaler? Since I'm inclined to just back this new option out.

skj-dev commented 2 years ago

I don't have a multi GPU system to test on, but my interpretation based on https://trac.ffmpeg.org/wiki/Hardware/QuickSync (at the bottom) means something like this would be needed to specify a non-default render device for QSV:

ffmpeg -loglevel error -stats -qsv_device /dev/dri/renderD129 -i /path/to/file.mkv -map 0:0 -c:v h264_qsv -b:v 6000k -look_ahead:v 1 -color_primaries:v bt709 -color_trc:v bt709 -colorspace:v bt709 -metadata:s:v title\= -disposition:v default -map 0:1 -c:a:0 ac3 -metadata:s:a:0 title\= -disposition:a:0 default -sn -metadata:g title\= -default_mode passthrough file.mkv

The headache is QSV is kinda sorta an overlay onto VAAPI. So, VAAPI is needed for QSV, but QSV doesn't use VAAPI options. At least that's how I'm reading it. Honestly, the whole thing is a confusing mess. That's why I suggested the Docker approach, since if only a single device is mapped in, ffmpeg will only see the one, and shouldn't care what its actual name is.

lisamelton commented 2 years ago

@ttyS0 Woof. Yeah, the Docker approach is the way to go here.

@mpmc I'm sorry, but I'm going to back out this option because, obviously, it doesn't really solve your problem and deliver a quality transcode.