Bluegrams / Vividl

Modern Windows GUI for youtube-dl/ yt-dlp
https://vividl.sourceforge.io
BSD 3-Clause "New" or "Revised" License
638 stars 54 forks source link

Add GPU acceleration option for AMD GPUs #44

Closed JosephM101 closed 1 year ago

JosephM101 commented 2 years ago

I was excited to see the new update for Vividl includes support for GPU acceleration. Unfortunately, it seems this only works with CUDA, which requires an NVIDIA GPU. There is no acceleration option for AMD GPUs, but FFmpeg has an option for it (-hwaccel amf). I'm hoping this can be implemented and added as an extra option or in a drop-down.

If I ever have the time, I can try experimenting with it myself, and contribute code if I figure something out.

alxnull commented 2 years ago

Hey @JosephM101, it's true that the current version only supports hardware acceleration with CUDA. I think it would make sense to include acceleration for AMD GPUs as well, however I'm unable to test this myself as I don't have an AMD GPU. In case you'd like to look into this issue yourself, I'd be glad to accept a PR. The current CUDA acceleration support is done by adding the required FFmpeg options in the download configuration class:

https://github.com/Bluegrams/Vividl/blob/ecd29c632bde587eb217b1e855a87755614a8e53/Vividl/Model/DownloadConfigurations.cs#L24-L31

Adding AMD GPU support should work equivalently.

JosephM101 commented 2 years ago

I went through the FFmpeg documentation and found arguments to enable AMD acceleration, and I played around with them a bit to figure out how to get it to work. I found that calling -hwaccel auto and -vcodec h264_amf yielded speedy results, with my laptop encoding a 1080p H.264 video at up to 3x the speed.

I set an additional parameter (-quality quality) since not passing this resulted in a fairly iffy output. It slowed down the encode a very slight bit, but the output was considerably better compared to not passing it, so I figured it was a worthy change.

Before the change: image

After the change: image

With the arguments combined, I ended up with a final command that looked similar to the following: ffmpeg -hwaccel auto -i "video_raw.mp4" -vcodec h264_amf -quality quality "video_amd.mp4"

Here's a code snippet I wrote based on the config code that you provided me and the arguments I found to work the best:

if (Settings.Default.FFmpegAmdAcceleration && download.GetExt() == "mp4")
{
    // Example command that enabled AMD acceleration:
    // ffmpeg -hwaccel auto -i "raw_video.mp4" -vcodec h264_amf -quality quality "amd_video.mp4"

    options = options ?? new OptionSet();
    // Use AMD-based H.264 encoder for MP4
    options.PostprocessorArgs = "ffmpeg:-vcodec h264_amf -quality quality";
    // Add another post-processor option for input file args
    options.AddCustomOption("--postprocessor-args", "ffmpeg_i1:-hwaccel auto");
}

I will do some more testing once I get the time, such as testing the above code snippet. I'm thinking about cloning the source code and making the additions/changes myself to see if the solution works. However, if it's possible for you to provide me with source code containing the necessary baseline changes (adding the settings/GUI options) so that all I have to do is mess with the OptionSet() arguments to see what works best, that would be great in terms of time and hassle on my end, although I completely understand if that kind of request is unreasonable.

I will follow-up with more findings once I get the chance to do some more testing. Thank you for reaching out to me!

alxnull commented 2 years ago

Hey @JosephM101, thanks for investigating this.

I'm thinking about cloning the source code and making the additions/changes myself to see if the solution works.

Would greatly appreciate this!

if it's possible for you to provide me with source code containing the necessary baseline changes (adding the settings/GUI options) so that all I have to do is mess with the OptionSet() arguments to see what works best

Sure, I made some initial changes for the integration in https://github.com/Bluegrams/Vividl/commit/67c373080cf19aa13ffd5edc84c7942b28184355. Most importantly, I changed the FFmpegCudaAcceleration boolean flag to an enum (HwAccelMode) to support more than two options. The settings change is already integrated into the UI. To build the modified version, checkout the branch https://github.com/Bluegrams/Vividl/tree/dev/hwaccel. To add your changes, please replicate this branch to your forked repository, modify it there, then open a pull request back to this repo once you have a working solution.

Let me know if anything is unclear!

JosephM101 commented 2 years ago

I have cloned the branch in GitHub desktop, but upon opening the solution in Visual Studio, the code is riddled with errors saying things can't be found.

image

I have tried restarting Visual Studio and rebuilding the NuGet package cache, but that has fixed nothing.

I'm using Visual Studio 2022 at the moment. I'm hoping you can tell me what version you use, and how you have set up your dev environment, so that I can replicate the environment in a VM.

EDIT: My apologies. I was completely overlooking the fact that my NuGet environment was set for a different dev environment. I reset the variables and it is now compiling. However, I do get the occasional error that stops building, but it works after cleaning & rebuilding the solution: image

JosephM101 commented 2 years ago

There appears to be an issue with the code you've provided. I went into Settings to attempt to change the encoder format, and noticed I was getting an error on conversion. The reason is that when changing what encoder is used, the change is not saved. Upon opening Settings, the drop-down selection is empty.

When opening the Settings window, this error appears in the output: System.Windows.Data Error: 40 : BindingExpression path error: 'HardwareAcceleration' property not found on 'object' ''Settings' ...

EDIT: I fixed the issue. It was just a typo in SettingsWindow.xml.

JosephM101 commented 2 years ago

I went the extra mile and added (experimental) Intel QSV support, as well as the option to enable it. I don't have any devices to test this on at the moment, but given that AMD AMF and Intel QSV are within the same ballpark as far as supported codecs, it should just work on Intel iGPUs about the same.

I have also made the pull request with both the AMD and QSV changes. Let me know if anything is unclear. I'm currently investigating an issue where running the same FFmpeg command from the terminal yields better performance than Vividl. Not sure if it's a threading thing.