Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge branch hw-encoder-vaapi #3039

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

sgothel
Copy link
Contributor

@sgothel sgothel commented Jul 29, 2020

This is updating my work as described in #1083 (comment),
hence tackling issue 1083 #1083

I updates all my hw-encoder branches

  • hw-encoder-base
  • hw-encoder-nvenc
  • hw-encoder-vaapi
    and the fast-forward joint hw-encoder-joint.

Yes, there are still some issues, i.e. non-optimal integration into the build process,
e.g. gtk/configure.ac (see notes there)

There are also some vaapi and nvenc hardcoded parameters,
which I would love to see made variable via the encoder extra-options UI element

  • but I need some help to enable these.

Please see the commit log messages and I copy my original post here below.

++++

The usual TODO: I still have some hardcoded features in vaapi and nvenc,
which I like to have added to the extra-options field.
To enable this for the vaapi/nvenc codecs and have it stored in presets,
I need a little help from you.

Detailed description in the vaapi commit message,
working quite well on a AMD NAVI10 using my mesa-vaapi patch.

hw-encoder-base https://github.com/sgothel/HandBrake/tree/hw-encoder-base
1.1) hw-encoder-nvenc https://github.com/sgothel/HandBrake/tree/hw-encoder-nvenc
1.2) hw-encoder-vaapi https://github.com/sgothel/HandBrake/tree/hw-encoder-vaapi
hw-encoder-joint https://github.com/sgothel/HandBrake/tree/hw-encoder-joint

Notable, using vaapi with Handbrake (utilizing the hardcoded soft-frame -> NV12 -> VAAPI)
is faster than ffmpeg commandline: ~150 fps -> ~200 fps

I compared quality differences with x264 ~5Mbit/s and while I couldn't see
any visually really, PSNR and SSIM difference to orig were below 1%.

As usual, great job of all of you working on Handbrake!
I regularly use it, hence my sporadic contributions.
Will help with integration, if intended by your team.

@sr55 sr55 requested a review from jstebbins July 29, 2020 22:08
@sr55
Copy link
Contributor

sr55 commented Jul 30, 2020

I still have some hardcoded features in vaapi and nvenc, which I like to have added to the extra-options field.

How does a user know which encoder will be used?
I assume VAAPI will translate options to the relevant encoder?

Also, I've not checked if you've done this, but you need to make sure this is gated on the build system to be Linux/Unix only.

@sgothel
Copy link
Contributor Author

sgothel commented Jul 30, 2020

How does a user know which encoder will be used?
I assume VAAPI will translate options to the relevant encoder?

As stated in git commit log:

  • hb.c:
    - Adding global static 'vaapi_device_ctx0' default device

Currently hardwired to the 1st GPU, i.e. drm device.
Yes, would be nice to have this 'selectable' in the UI as well.

(plus some other custom options, like the mentioned 'b_depth=2' (b-frames) etc.

Yup, would need a pointer help, how to enable, combine those infos with UI.

Also, I've not checked if you've done this, but you need to make sure this is gated on the build system to be Linux/Unix only.

Yes, I only added vaapi for Linux so far, I might have made a mistake - hope not.
Touched build/config files:
gtk/configure.ac
gtk/src/makedeps.py
libhb/module.defs
make/configure.py
test/modules.defs

@sgothel
Copy link
Contributor Author

sgothel commented Jul 30, 2020

One question: How to access jobs->vcodec within Encode(..)?
I would like to refine the hw-frame selection.

@sgothel
Copy link
Contributor Author

sgothel commented Aug 1, 2020

How does a user know which encoder will be used?

(edited)

In more detail, the hardwired 1st GPU in hb.c:

+static const char * vaapi_device0 = NULL; // "/dev/dri/renderD128";
+static AVBufferRef *vaapi_device_ctx0 = NULL;

  • if( (err = av_hwdevice_ctx_create(&vaapi_device_ctx0, AV_HWDEVICE_TYPE_VAAPI,
  •    							      vaapi_device0, NULL, 0)) < 0 ) {
    

Again, yes, would be nice to have this also made an option.

So currently we use the first 'AV_HWDEVICE_TYPE_VAAPI' hmm.
Hence we might want to refine this indeed to avoid qsv collision etc?

@sgothel
Copy link
Contributor Author

sgothel commented Aug 1, 2020

So currently we use the first 'AV_HWDEVICE_TYPE_VAAPI' hmm.
Hence we might want to refine this indeed to avoid qsv collision etc?

https://ffmpeg.org/doxygen/trunk/hwcontext_8h.html#acf25724be4b066a51ad86aa9214b0d34

AV_HWDEVICE_TYPE_VAAPI does distinguish itself from AV_HWDEVICE_TYPE_QSV,
so that should not cause a collision.

av_hwdevice_ctx_create:
https://ffmpeg.org/doxygen/trunk/hwcontext_8c.html#a21fbd088225e4e25c4d9a01b3f5e8c51

vaapi_encode example: https://ffmpeg.org/doxygen/trunk/vaapi_encode_8c-example.html#a41

@sgothel
Copy link
Contributor Author

sgothel commented Aug 4, 2020

I have sync'ed my branches to HB master

Also removed mingw from VAAPI build, which failed naturally - see

commit 1a4ed1d

hw-encoder-vaapi: Build: Enable VAAPI only on linux and freebsd, i.e. this patch drops mingw.

@paulmenzel
Copy link

working quite well on a AMD NAVI10 using my mesa-vaapi patch.

Where is the Mesa patch and have you send it to the Mesa 3D project for review?

@paulmenzel paulmenzel mentioned this pull request Sep 2, 2020
@nyanmisaka
Copy link

Packed header haven't been well implemented in Mesa.

Only VA_ENC_PACKED_HEADER_SEQUENCE for hevc_vaapi is in this MR.
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4184/diffs

@sgothel
Copy link
Contributor Author

sgothel commented Sep 2, 2020

Packed header haven't been well implemented in Mesa.

Only VA_ENC_PACKED_HEADER_SEQUENCE for hevc_vaapi is in this MR.
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4184/diffs

My patch here sgothel/mesa@5e10db6
or https://jausoft.com/cgit/mesa.git/commit/?h=gallium_va_encpackedheader01&id=5e10db6f3f22a7d687ad7eeded3bbf0866978628

this is also included as a patch in the pull request.

When I compare both patches, I am afraid the proposed one
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4184/diffs#86a7f7cb2dad2e3298e5c8ef9e5a9bad8353f448_160_160
is not sufficient, as it would leave the value zero (VA_ENC_PACKED_HEADER_NONE) for non HEVC.

Also see https://trac.ffmpeg.org/ticket/8042
and its patch (also a hack): https://trac.ffmpeg.org/attachment/ticket/8042/mesa-report-packed-header-support.diff

No, I had no time yet to join the debate in the Mesa project itself, sorry.
All I can say is that my mentioned patch/hack and the ffmpeg patch/hack were able to produce
proper headers allowing the usage of MKV.

This b/c MKV is quite 'anal', i.e. complaints on wrong headers - which is a good thing.
MP4 or other containers do not complain - so working w/o this patch,
but losing the luxury of multi audio and subtitles streams.

@sgothel
Copy link
Contributor Author

sgothel commented Sep 2, 2020

working quite well on a AMD NAVI10 using my mesa-vaapi patch.

Where is the Mesa patch and have you send it to the Mesa 3D project for review?

see my reply below re my mesa communication, so no - not yet.

@sgothel
Copy link
Contributor Author

sgothel commented Oct 27, 2020

@jstebbins hope all is OK over there. Have you made a decision yet, merge w/ or w/o rework of this VAAPI stuff? Some feedback would be nice, hence bump :)

…tested w/ AMD NAVI10), untested: h265, vp8 and vp9

Tested using lates mesa master branch patched with
- contrib/mesa/A00-gallium_vaapi_encpackedheader01-commit-5e10db6.patch
to enable Matroska and correct packed header in general using ffmpeg.

Test hardware and configuration:
- Mesa Gallium driver 20.2.0-devel for AMD Radeon RX 5700 XT (NAVI10, DRM 3.37.0, 5.7.0-1-amd64, LLVM 9.0.1)

Codev h264_vaapi, avcodec_open options: rc_mode=CQP,qp=24,b_depth=2,profile=100,level=40 (profile high, level 4.0)
HD1080 source ~45min with 212fps
PSNR and SSIM difference to x264 below 1%,
having x264 using profile high, level 4.0, preset fast, rc 23.
Both using constant-quality w/ variable bitrate.

++++

If FEATURE vaapi is enable (autodetected),
the following libraries are linked: X11 va va-drm va-x11.

- hb.c:
  - Adding global static 'vaapi_device_ctx0' default device
    initialized via hb_avcodec_init() and released via hb_avcodec_free().
    The 'vaapi_device_ctx0' is used in vaa_common hb_avcodec_vaapi_set_hwframe_ctx(..).

  - hb_avcodec_vaapi_set_hwframe_ctx() attaches the new AVHWFramesContext
    to the AVCodecContext at initializing the encoder.
    This is the final sink for the vaapi hw-encoder
    and Encode(..) performs the frame conversion into it.

  - hb_avcodec_test_encoder(..) adds VAAPI branch,
    needs refinement

- encavcodec.c
  - adding VAAPI branches, enabling available, needs refinement.
    Currently profile and level are set to the user preferences,
    additionally 'b_depth=2' is being passed.

  - added hb_avcodec_test_encoder*(..) functions, currently only
    used to check vaapi-*codec*-availability.
    We used this codefragment regularly in an earlier HB version.

+++

Discussion:

Previous version of this patch of mine worked well on Intel hardware,
as described above - AMD NAVI10 also performs quite well.

VAAPI Workflow:
  - It uses hardware frames on the target device, which are being transported
    from the software device. The frame transport implicitly converts the pix_fmt.

  - AVCodecContext's pix_fmt uses AV_PIX_FMT_VAAPI

  - AVHWFramesContext: format uses AV_PIX_FMT_VAAPI and sw_format AV_PIX_FMT_NV12,
    the latter hinting on the actual hw-frame's target format.

  - AV_PIX_FMT_NV12 uses interleaved UV data, where AV_PIX_FMT_YUV420P uses
    seperated planes. Both use a separated Y plane upfront.
    Therefor both formats are not picture compatible, memory requirements are same.

  - Encode(..) allocates a hw_frame and the source frame is being transported
    to the hw-frame target using the pic_fmt conversion to NV12.

    Finally the hw_frame is being sent 'avcodec_send_frame' and the code-path re-aligns
    with non VAAPI.

Further fixes to do:
    Validate whether 'b_depth=2' (b-frames) works for all vaapi implementations,
    add custom extra-video-encoder field!
@rathann
Copy link

rathann commented Jan 25, 2023

Packed header haven't been well implemented in Mesa.
Only VA_ENC_PACKED_HEADER_SEQUENCE for hevc_vaapi is in this MR.
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4184/diffs

My patch here sgothel/mesa@5e10db6 or https://jausoft.com/cgit/mesa.git/commit/?h=gallium_va_encpackedheader01&id=5e10db6f3f22a7d687ad7eeded3bbf0866978628

this is also included as a patch in the pull request.

When I compare both patches, I am afraid the proposed one https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4184/diffs#86a7f7cb2dad2e3298e5c8ef9e5a9bad8353f448_160_160 is not sufficient, as it would leave the value zero (VA_ENC_PACKED_HEADER_NONE) for non HEVC.

Also see https://trac.ffmpeg.org/ticket/8042 and its patch (also a hack): https://trac.ffmpeg.org/attachment/ticket/8042/mesa-report-packed-header-support.diff

No, I had no time yet to join the debate in the Mesa project itself, sorry. All I can say is that my mentioned patch/hack and the ffmpeg patch/hack were able to produce proper headers allowing the usage of MKV.

The patch is not ready to be merged into mesa as-is, but perhaps reporting the issue as a bug and attaching the patch could help move forward there?

This b/c MKV is quite 'anal', i.e. complaints on wrong headers - which is a good thing.

Could you (or someone else) provide a way to reproduce the issue? I'm interested in having VAAPI encoding support so I could help drive this forward on Mesa side.

Current mesa code looks a bit different today, so the patch would need to be modified to do something like:

            if (u_reduce_video_profile(ProfileToPipe(profile)) == PIPE_VIDEO_FORMAT_MPEG4_AVC)
               value |=  VA_ENC_PACKED_HEADER_SEQUENCE | // SPS and PPS.
                    VA_ENC_PACKED_HEADER_SLICE    | // Slice headers.
                    VA_ENC_PACKED_HEADER_MISC;      // SEI.
            break;

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.

None yet

5 participants