NihAV: hardware-accelerated playback revisited

Recently I’ve made a mistake of upgrading one of my laptops to systemd 24.04. I can talk about various quality of life improvements there (like brightness control not working any longer so I have to evoke xrandr instead) but it’s so useless rant that it does not deserve to be written. What is worth talking about is hardware acceleration. Previously my player on that laptop had rather unreliable playback with VA-API decoding (i.e. it worked but some videos made it too laggy); now the situation has improved—it’s reliably unusable. Additionally it seems to consume only slightly less CPU than with software decoding. So I finally looked at the way to speed it up (spoiler alert: and failed).

Conceptually it’s simple: after you decode VA-API picture you need to obtain its internal parameters with vaExportSurfaceHandle(), create an EGL picture using eglCreateImage() (or eglCreateImageKHR()), blit it onto OpenGL texture with glEGLImageTargetTexture2DOES() and you’re done. It was not so simple in practice though.

Exporting descriptors is easy, I just modified my fork of VA-API wrapper to do that and it even seemed to produce correct output. The problems started with OpenGL integration. My player uses SDL2 so I spent a lot of time trying to make it work. First of all, it’s not clear how to obtain a proper OpenGL context for the calls, then there’s this problem of it being finicky and not liking multi-threaded execution. And of course you have to load all those functions mentioned above manually (because SDL2 offers only a small subset of all possible OpenGL functions—not surprising, considering how many of those are optionally supported extensions or missing in certain profiles).

Anyway, I threw away most of my player functionality, leaving just loading an input file, decoding it and trying to display only the first frame. It ended with a segfault.

It is probably because of (poorly documented) SDL2 wrapper doing, but it can’t provide a sane OpenGL context probably. So a call to eglGetCurrentDisplay() returns either NULL or a pointer that looks like a small negative value; the same happens with eglCreateImage() (fun thing that eglGetError() returns the same value, -424 if somebody is curious); at glEGLImageTargetTexture2DOES() call it finally segfaults.

At that point I actually tried searching for some alternative crates that would allow me to create an OpenGL window and call those functions—and found none fitting the purpose. They all are either provide rather limited OpenGL subset which is enough for drawing a triangle with shaders (and probably expect you to locate and load the library with the additional functions by yourself) or even simply provide OpenGL bindings, leaving even window creation to you.

In other words, not my kind of fun. I’ll simply disable hardware acceleration for all cases there until I find a better alternative.

P.S. Vulkan is not really an option either. My hardware is too old for ANV driver (and for HASVK driver too).

4 Responses to “NihAV: hardware-accelerated playback revisited”

  1. Paul says:

    Deprecate laptop. (How do you even use modern web if there is no at least 64 GB of RAM reserved just for browser usage)

    On more serious note, how is it going RE of that famous RAW camera format?

  2. Kostya says:

    Nah, my laptop has been serving me good for the last almost fifteen years (as my primary development machine among other things).

    And since I’m not a great fan of modern web and use web browser sparingly (i.e. launching it occasionally to see a couple of sites and closing it afterwards) and use ad-blocking, even 8 gigs of RAM is enough.

    As for that format – Ghidra has processed it but I could not as it employs the best anti-RE practices (C++, object requests and bloated binary even by C++ standards).

  3. Peter says:

    That’s not RED is it! Well at least there are symbols, unfortunately many thousands of them.

  4. Kostya says:

    No, it’s a Japanese codec – also with thousands of symbols (most of them do not have anything to do with video or compression but rather, say, XML parsing) and everything seems to be called via virtual interface, making static call tracking next to impossible.

Leave a Reply