Skip to content

Enable AMF Decoder, HWContext AMF, vpp_amf filter#6475

Open
Hotactioncop wants to merge 1 commit intoHandBrake:masterfrom
Hotactioncop:Enable_AMF_decode
Open

Enable AMF Decoder, HWContext AMF, vpp_amf filter#6475
Hotactioncop wants to merge 1 commit intoHandBrake:masterfrom
Hotactioncop:Enable_AMF_decode

Conversation

@Hotactioncop
Copy link
Contributor

Adds hwcontext_amf, enabling a shared AMF context for encoders,
decoders, and AMF-based filters, without copy to the host memory.

Benefits:

  • Optimizations for direct video memory access from CPU
  • Significant performance boost in full AMF pipelines with filters
  • Integration of GPU filters like VPP, Super Resolution, and
    Compression Artefact Removal(in future plans)
  • VCN power management control for decoders.
  • Ability to specify which VCN instance to use for decoding
    (like for encoder)
  • AMD will soon introduce full AMF API for multimedia accelerator MA35D
    • With AMF API, integration will be much easier:
      GPU and the accelerator will have the same API
    • including encoder, decoder, scaler, color converter

Tested on:

  • Windows 10+ (via MinGW)
  • Ubuntu Linux

@galad87
Copy link
Contributor

galad87 commented Dec 10, 2024

I have a feeling it would be better to wait until the patches are integrated into FFmpeg, and after #6446 is merged.

@stickz
Copy link
Contributor

stickz commented Dec 21, 2024

Thanks so much for this! I'm running the AMF decoder with SVT-AV1 on my AMD Ryzen 9 9950x. It works great! I just had to update my bios and disable PBO to fix the BSOD problem.

@Hotactioncop
Copy link
Contributor Author

Asking for patch review.
What changed since last PR:
Updated to latest HandBrake master.
Updated contriib/ffmpeg patches to latest HWcontext, which is implemented into FFmpeg master.
Implemented GUI checkbox to enable AMF decoder on Linux.
Fixed crashes on Linux for copy_plane when default bytewidth larger than the source frame linesize.

Copy link
Contributor

@galad87 galad87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a bunch of random comments, didn't test this yet. But it would be better to replicate what NVenc/NVdec are doing (even if it was an hit and run and no one is keeping it working), instead of QSV.

job->qsv.decode = !!(title->video_decode_support &
HB_DECODE_SUPPORT_QSV);
#endif
memset(&job->amf, 0, sizeof(job->amf));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hb_job_t is already zeroed on creation, this shouldn't be needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this will be applied in the upcoming fix commit.

hb_dict_set(settings, "format", hb_value_string(av_get_pix_fmt_name(pv->job->input_pix_fmt)));
hb_avfilter_append_dict(filters, "scale_cuda", settings);
}
else if ((pv->frame->hw_frames_ctx && pv->job && pv->job->hw_pix_fmt == AV_PIX_FMT_AMF_SURFACE) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A rotate filter is needed in this function too, if not all those video recorded on phones with a rotation metadata will fail to encode properly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, AMF Hardware filters do not support rotation.
I will add an extra condition if (pv->title->rotation == HB_ROTATION_0) in the upcoming fix commit.

// HWAccel falled back to the software decoder
av_frame_ref(pv->frame, pv->hw_frame);
av_frame_unref(pv->hw_frame);
if (ret < 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Contributor Author

@Hotactioncop Hotactioncop Mar 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accidentally removed, will be returned in the next fix commit.

} while (ret >= 0);
if(send_packet)
{
av_usleep(100);// wait 0.1 ms before resubmitting
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't add random usleep around.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A sleep is required if the submit input is full, to prevent unnecessary CPU usage.

if(name != NULL)
{
pv->codec = avcodec_find_decoder_by_name(name);
if(pv->job) // no need to copy output for preview
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel this is not a good way, what if we start to use hw filters for previews in the future?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A reasonable remark. Will be removed in the next fix commit.

}
}
#endif
#if HB_PROJECT_FEATURE_VCE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other hardware encoders check if the hwaccel falled back to software decoder, wouldn't that work for amfdec too?

// AMF-specific settings
struct
{
int num_sw_filters;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to store these numbers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to store this variable because it is used to check whether software filters are present.
If this variable is not 0, it means that software filters are present, and the pipeline can't be fully hardware-accelerated. However, since HandBrake is designed for maximum compatibility, we use int instead of bool.

{
return job->hw_pix_fmt == AV_PIX_FMT_AMF_SURFACE;
}
hb_buffer_t * hb_vce_copy_avframe_to_video_buffer(hb_job_t *job, AVFrame *frame, AVRational time_base)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this function needed? Looks the same as hb_avframe_to_video_buffer

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hw frame to sw frame conversion happens before, so there shouldn't be any need to check for sw_filters or whatever.

if(w->hw_device_ctx)
{
pv->codec = avcodec_find_decoder_by_name(pv->qsv.codec_name);
const char* name = hb_vce_decode_get_codec_name(w->codec_param);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would't be better to use the hwaccel framework like nvdec and videotoolboxdec? Don't try to copy the QSV implementation, because it was added before hwaccel, and it's doing custom things that hopefully will go away soon.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The HWContext and AMF decoder is not hardware accelerated, it is an offload decoder.
Implementation of HWaccel AMF in hw_configs for default codecs was blocked by ffmpeg maintainers:
https://patchwork.ffmpeg.org/project/ffmpeg/patch/20240214015515.1027-2-ovchinnikov.dmitrii@gmail.com/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue with standalone hw decoders is that they are missing features, and are never in sync with the built-in parsers and hwaccel decoders. For example HDR dynamic metadata are ignored, and others metadata too. It's a pain because you never know what works and what doesn't.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That ultimately leads to a bad user experience when features that should be transparent and just work, don't.

@Geoknysis
Copy link

Geoknysis commented Feb 28, 2025

There may be a bug that requires fixing before the feature is fully functional. Per the below, the output is sub-optimal and the work speed is slower. Below each image is the respective activity log for the encode. I also noticed that with the amfdecode option selected, when selecting the constant framerate video option, HandBrake crashes.

I used the official h265 1080p preset for each. I compiled HandBrake with https://github.com/Hotactioncop/HandBrake/tree/Enable_AMF_decode source.

official_h265_vcn_1080p_amfdecode
Activity.log (official_h265_vcn_1080p_amfdecode).txt

official_h265_vcn_1080p_no_amfdecode
Activity.log (official_h265_vcn_1080p_no_amfdecode).txt

@Hotactioncop
Copy link
Contributor Author

There may be a bug that requires fixing before the feature is fully functional. Per the below, the output is sub-optimal and the work speed is slower. Below each image is the respective activity log for the encode. I also noticed that with the amfdecode option selected, when selecting the constant framerate video option, HandBrake crashes.

I used the official h265 1080p preset for each. I compiled HandBrake with https://github.com/Hotactioncop/HandBrake/tree/Enable_AMF_decode source.

Thank you for testing this PR!
I noticed that you are seeing different frames compared to my results.
To help me investigate and reproduce the issue, could you please provide the following details?

Input video file (or a short sample that reproduces the issue).
Your software setup, including:

  • Linnux version
  • GPU model
  • Driver version
  • Any specific build configuration or flags used
  • Your HandBrake settings, especially the encoding parameters you used.

With my setup and a prepared video file matching the characteristics in your log file, I haven't encountered any errors.
Having your exact input and environment details will help me debug this properly.
Thanks!

@galad87 galad87 removed this from the 1.10.0 milestone Jun 11, 2025
@Mine181
Copy link

Mine181 commented Aug 25, 2025

any update on this merge request?

@Hotactioncop
Copy link
Contributor Author

Thanks for following up!
The patch didn’t fit anymore after recent HandBrake updates, so It is rewritten to match the new code.
It is currently under testing, and I will update the PR shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

6 participants