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

Library version #3

Open
YorVeX opened this issue Jun 11, 2023 · 1 comment
Open

Library version #3

YorVeX opened this issue Jun 11, 2023 · 1 comment

Comments

@YorVeX
Copy link

YorVeX commented Jun 11, 2023

Currently this is only usable from C++. I think QOIR would get a boost in real-world adoption if this would additionally be made available to non C++ developers like me by offering a library version of it with a documented API.

Even more so if binary builds would be offered here too. A DLL for Windows would be the easy part, because that will be immediately compatible to the whole Windows world. And maybe for Linux at least one Ubuntu LTS version build could be a start to get some package maintainers for various distros interested.

I'd be the first to come up with a simple C# interface to get this into the .NET world. Outside of reading C++ code to understand libraries and tools I use I don't have a lot of C++ experience, but at least I already managed to get a DLL compiled with "__declspec(dllexport)" added to the qoir_encode and qoir_decode functions and could verify that these functions actually landed in the resulting DLL.

Part of this GH issue (if anyone decides they actually want to work on it) might be some extra work to make this API more friendly for other languages, e.g. use types that are less C++ specific, more generic and/or more explicit about endianness or whether they are 32 bit vs. 64 and so on. Will check myself now with the DLL I produced how hard or easy it is in the current form to fill the parameters these functions need.

@YorVeX
Copy link
Author

YorVeX commented Jun 15, 2023

My PoC code is working fine utilizing this from C# on Windows, haven't tried Linux yet. I am using this on video data so it has to do a lot of work at 60 frames per second. With my test setup and test video loops CPU usage goes roughly 5% down compared to QOI and compression rate is 5% better than for QOI - which is what the benchmarks here indicated and therefore why I wanted to test a QOIR implementation in the first place, so I am very pleased with the result.

I am wondering whether I should release this as a separate wrapper class in its current state though, as stated above the implementation from C# perspective is not ideal, though also not as bad as I was afraid of in the beginning. The option to specify contextual_malloc_func and contextual_free_func is essential, otherwise e.g. the result buffer couldn't be free'd after it was used. But other libraries solve this by either providing a free() function of their own or allow to hand over pre-allocated buffers in the first place (as is possible with the source and "scratch space" buffers already, but not with the result buffer), which can also help avoid unnecessary allocations by reusing a static buffer or at least buffers from a memory pool, something that becomes relevant when working with a high number of frames per second with a high resolution.

What I did so far is:

  • create a modified version of qoir.h with added __declspec(dllexport) prefixes for qoir_encode/qoir_decode as mentioned above and compile a DLL from it
  • create another modified version of qoir.h with only the parts outside of the QOIR_IMPLEMENTATION define
  • use ClangSharpPInvokeGenerator on this modified version to generate C# wrapper code for invoking the DLL
  • implement calls to the wrapper code that fills the structs, prepares buffers and invokes the qoir_encode/qoir_decode functions

This is mostly what C# calls "unsafe" code. It doesn't matter for me because my project already uses lots of that and has no option to avoid that anyway. But if one was to release a real standalone C# wrapper it should probably hide this layer and put another managed code layer on top of it working with Spans to keep performance high while making the code more safe from C# perspective. Before putting effort into this I personally would wish for some adjustments as mentioned here first. Or get a clear statement that this won't happen, at least it would be a better base for any decisions about that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant