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

Possible bug with av_frame_get_buffer() when trying to get audio frame buffer #315

Open
Error-String-Expected-Got-Nil opened this issue Jan 18, 2025 · 2 comments

Comments

@Error-String-Expected-Got-Nil
Copy link

Error-String-Expected-Got-Nil commented Jan 18, 2025

Using FFmpeg version 7.1, though I did test with 7.0 and it persisted there as well.

Image

The upper half of this snippet always fails with the EINVAL error return code, despite the fact that the frame has the nb_samples, ch_layout, and sample_format fields set, which should be all that is required to allocate the buffers according to the documentation.. I have looked over the libav source code and manually tried the checks that can return EINVAL, and this setup shouldn't be tripping them as far as I can tell. The video frame buffer get is there as a sanity check and it works exactly as expected.

Addendum: I finally managed to make a C project to test this, and have confirmed that it works fine in raw C. This code should be equivalent to the C# code:

Image

This correctly returns 0 and allocates the buffers, whereas the C# code has the previously described error.

@zgabi
Copy link
Contributor

zgabi commented Jan 18, 2025

I got 0:

Image

I'm using ffmpeg 7.0.1, from gyan.dev:
ffmpeg-7.0.1-full_build-shared.7z

After upgrade to 7.1 it still works. So probaby you are using a "wrong" ffmpeg version. From where did you download id?

@Error-String-Expected-Got-Nil
Copy link
Author

Error-String-Expected-Got-Nil commented Jan 19, 2025

After MUCH investigation I figured out what the problem was.

In my use-case, I am running a 32-bit process (I'm making a video encoder I intend to build into a mod for a Unity game, which is 32 bit). The AVFrame struct in C/direct libav has 4 fields of type size_t, which is an unsigned integer type who's size is system/platform-dependent, as it has a size of 8 bytes in 64 bit, and 4 bytes on 32 bit.

The AVFrame struct in FFmpeg.AutoGen, however, just uses ulongs for these fields. Thus, when accessing the fields of the AVFrame in C#, there is a serious misalignment of their locations in memory, making writes and reads to certain fields go to the wrong locations. None of the affected fields are relevant for video frames (as only fields sequentially below the size_t fields are affected), but they are relevant for audio frames.

I made my own version of the AVFrame struct in C# using uints instead of ulongs for these fields, and with some pointer casts, it proceeded to work exactly as expected.

I'm not sure if there's a good library-side solution for this, I don't think there's a way to make the type of some field depend on whether the process is 32 or 64 bit. But at least the issue is clear now.

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

2 participants