Closed MrEMU closed 3 years ago
those checks are there because whenever ffmpeg changes their headers, the translated headers in our project should be changed accordingly, too. Just blindly ignoring those changes will eventually result in very hard to track + analyze bugs.
In theory the version check in configure should be enough because ffmpeg nowadays follows strict rules to raise the version numbers in specific ways when ABI compatibility is broken. In practice there is a single old code line in USDX that accesses a private structure element that regularly moves around.
In FFmpeg 4.0 on x86-64 AVCodec::flush is at offset 216. In 4.3 it is at 208. If you have a fix for #259, we can think about relaxing the version requirement.
As a workaround for Arch Linux users downgrade to ffmpeg 2:4.2.3-2
and put to IgnorePkg
.
Yeah I will use that workaround for now. Thanks for all your quick replies.
on: Debian testing bullseye
same issue: "Linked version of libavutil is not yet supported!"
I'm working on it.
Any advances on this?
Facing the same issue on a fresh install of Ubuntu 21.04 Here are the version details of the ffmpeg libraries that are pre-installed on that OS:
ffmpeg version 4.3.2-0+deb11u1ubuntu1 Copyright (c) 2000-2021 the FFmpeg developers built with gcc 10 (Ubuntu 10.2.1-20ubuntu1) configuration: --prefix=/usr --extra-version=0+deb11u1ubuntu1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-pocketsphinx --enable-libmfx --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared libavutil 56. 51.100 / 56. 51.100 libavcodec 58. 91.100 / 58. 91.100 libavformat 58. 45.100 / 58. 45.100 libavdevice 58. 10.100 / 58. 10.100 libavfilter 7. 85.100 / 7. 85.100 libavresample 4. 0. 0 / 4. 0. 0 libswscale 5. 7.100 / 5. 7.100 libswresample 3. 7.100 / 3. 7.100 libpostproc 55. 7.100 / 55. 7.100
Comparing the 4.2 branch of ffmpeg with the 4.3 branch, folder libavutil:
No other changes took place.
Comparing the 4.3 branch of ffmpeg with the 4.4 branch, folder libavutil:
No other changes took place.
I know I promised to take care of that and I have already converted most of the 4.3 headers, but I am not yet done.
We can't use the 4.0 units because we access the flush
member of AVCodec
, which is not part of the public API. This element has moved. There are also a few bugs in the old units. Some of them have been caused by incorrect porting of the preprocessor ifs. I will finish the work if nobody beats me to it.
In August I wrote a script to compare the offset and size of structure members as well as the values of constants between the ffmpeg units configured in USDX and the C headers. I don't remember how complete it is, but it lists three mismatches on x86-64 Linux when comparing the 4.0 units to the 4.3 headers. It checks only the structure elements and constants I found in USDX. For structures allocated by pascal code also the size and alignment are checked. checkffabi.sh.txt
And I once wrote a C++ application to create a minimal unit. It is ugly and IIRC had problems to force Free Pascal to use the correct structure alignment. Also there is ambiguity how to convert pointer arguments (keep as pointer or pass with var
or out
).
typedump.cpp.txt
Maybe I am mistaking, but I thought that USDX is compatible with ffmpeg 4.2 (not 4.0) ? Is that not the case ?
It is. The flush
element did not move between 4.0 and 4.2, so the 4.0 units can be used for 4.2.
Unless the ffmpeg people make a mistake, libraries with matching major version number are compatible except for things like flush which are not part of the public API.
ffmpeg |
libavutil | libavformat | libavcodec | libswscale | libswresample |
---|---|---|---|---|---|
3.4.x | 55.78.100 | 57.83.100 | 57.107.100 | 4.8.100 | 2.9.100 |
4.0.x | 56.14.100 | 58.12.100 | 58.18.100 | 5.1.100 | 3.1.100 |
4.1.x | 56.22.100 | 58.20.100 | 58.35.100 | 5.3.100 | 3.3.100 |
4.2.x | 56.31.100 | 58.29.100 | 58.54.100 | 5.5.100 | 3.5.100 |
4.3.x | 56.51.100 | 58.45.100 | 58.91.100 | 5.7.100 | 3.7.100 |
4.4 | 56.70.100 | 58.76.100 | 58.134.100 | 5.9.100 | 3.9.100 |
We could use the same units for all ffmpeg versions where libavutil is version 56.x, libavformat is version 58.x, libavcodec is version 58.x, libswscale is version 5.x, and libswresample is version 3.x if we didn't access flush
and didn't want to use features added after 4.0.
mmm. Strange.
See ./src/lib/ffmpeg-4.0/avio.pas
The element "must-flush" has been removed from the structure in ffmpeg in Nov 2017 but was not removed in the pascal headers. Wonder how this is working.
=> Maybe that explains the difference in offset you have seen (216 vs 208) ?
Yes, that's one of the errors made when support for 4.0 was added in 2018.
=> Maybe that explains the difference in offset you have seen (216 vs 208) ?
No, the reason is FFmpeg/FFmpeg@1f4cf92cfbd3accbae582ac63126ed5570ddfd37 (removes init_thread_copy
).
The superfluous must_flush
on x86-64 just messes up the offset of eof_reached
and the following two elements write_flag
and max_packet_size
(not used by USDX) because of the 4 bytes padding added by the compiler to align checksum
. On 32 bit platforms all elements after must_flush
have a wrong offset.
Note that init_thread_copy
and flush
are below the comment
/*****************************************************************
* No fields below this line are part of the public API. They
* may not be used outside of libavcodec and can be changed and
* removed at will.
* New public fields should be added right above.
*****************************************************************
*/
I wonder if using GDB (maybe https://www.gdbgui.com/) to browse the structures and offsets in the original ffmpeg libs and the USDX equivalents would not be the fastest way to uncover any discrepancy ? Or maybe pahole (https://manpages.debian.org/unstable/dwarves/pahole.1.en.html) is even better ?
Which gdb command do you have in mind? info types
does not print the contents of structures.
On Linux there is a tool called pahole, but it crashes on the ultrastardx binary.
I am thinking of this gdb command (requires gdb 8.1+ I believe):
ptype /o struct <structname>
or alternatively use the gdbgui
ptype has problems with function pointers inside structures. It prints them as single byte value followed by a 7 byte hole.
C (FFmpeg 4.3):
(gdb) ptype /o AVCodec
type = struct AVCodec {
/* 0 | 8 */ const char *name;
/* 8 | 8 */ const char *long_name;
/* 16 | 4 */ enum AVMediaType type;
/* 20 | 4 */ enum AVCodecID id;
/* 24 | 4 */ int capabilities;
/* XXX 4-byte hole */
/* 32 | 8 */ const AVRational *supported_framerates;
/* 40 | 8 */ const enum AVPixelFormat *pix_fmts;
/* 48 | 8 */ const int *supported_samplerates;
/* 56 | 8 */ const enum AVSampleFormat *sample_fmts;
/* 64 | 8 */ const uint64_t *channel_layouts;
/* 72 | 1 */ uint8_t max_lowres;
/* XXX 7-byte hole */
/* 80 | 8 */ const AVClass *priv_class;
/* 88 | 8 */ const AVProfile *profiles;
/* 96 | 8 */ const char *wrapper_name;
/* 104 | 4 */ int priv_data_size;
/* XXX 4-byte hole */
/* 112 | 8 */ struct AVCodec *next;
/* 120 | 8 */ int (*update_thread_context)(struct AVCodecContext *, const struct AVCodecContext *);
/* 128 | 8 */ const AVCodecDefault *defaults;
/* 136 | 8 */ void (*init_static_data)(struct AVCodec *);
/* 144 | 8 */ int (*init)(struct AVCodecContext *);
/* 152 | 8 */ int (*encode_sub)(struct AVCodecContext *, uint8_t *, int, const struct AVSubtitle *);
/* 160 | 8 */ int (*encode2)(struct AVCodecContext *, struct AVPacket *, const struct AVFrame *, int *);
/* 168 | 8 */ int (*decode)(struct AVCodecContext *, void *, int *, struct AVPacket *);
/* 176 | 8 */ int (*close)(struct AVCodecContext *);
/* 184 | 8 */ int (*send_frame)(struct AVCodecContext *, const struct AVFrame *);
/* 192 | 8 */ int (*receive_packet)(struct AVCodecContext *, struct AVPacket *);
/* 200 | 8 */ int (*receive_frame)(struct AVCodecContext *, struct AVFrame *);
/* 208 | 8 */ void (*flush)(struct AVCodecContext *);
/* 216 | 4 */ int caps_internal;
/* XXX 4-byte hole */
/* 224 | 8 */ const char *bsfs;
/* 232 | 8 */ const struct AVCodecHWConfigInternal **hw_configs;
/* 240 | 8 */ const uint32_t *codec_tags;
/* total size (bytes): 248 */
}
Pascal (FFmpeg 4.0):
(gdb) ptype /o TAVCodec
type = struct TAVCODEC {
/* 0 | 8 */ PChar name;
/* 8 | 8 */ PChar long_name;
/* 16 | 4 */ TAVMediaType type_;
/* 20 | 4 */ TAVCodecID id;
/* 24 | 4 */ LongInt capabilities;
/* XXX 4-byte hole */
/* 32 | 8 */ PAVRational supported_framerates;
/* 40 | 8 */ PAVPixelFormat pix_fmts;
/* 48 | 8 */ pcint supported_samplerates;
/* 56 | 8 */ PAVSampleFormatArray sample_fmts;
/* 64 | 8 */ pcuint64 channel_layouts;
/* 72 | 1 */ Byte max_lowres;
/* XXX 7-byte hole */
/* 80 | 8 */ PAVClass priv_class;
/* 88 | 8 */ PAVProfile profiles;
/* 96 | 8 */ PChar wrapper_name;
/* 104 | 4 */ LongInt priv_data_size;
/* XXX 4-byte hole */
/* 112 | 8 */ PAVCodec next;
/* 120 | 1 */ pcint init_thread_copy(PAVCodecContext);
/* XXX 7-byte hole */
/* 128 | 1 */ LongInt update_thread_context(PAVCodecContext, PAVCodecContext);
/* XXX 7-byte hole */
/* 136 | 8 */ Pointer defaults;
/* 144 | 1 */ void init_static_data(PAVCodec);
/* XXX 7-byte hole */
/* 152 | 1 */ LongInt init(PAVCodecContext);
/* XXX 7-byte hole */
/* 160 | 1 */ LongInt encode_sub(PAVCodecContext, PByteArray, LongInt, PAVSubtitle);
/* XXX 7-byte hole */
/* 168 | 1 */ LongInt encode2(PAVCodecContext, PAVPacket, PAVFrame, pcint);
/* XXX 7-byte hole */
/* 176 | 1 */ LongInt decode(PAVCodecContext, Pointer, LongInt, PAVPacket);
/* XXX 7-byte hole */
/* 184 | 1 */ LongInt close(PAVCodecContext);
/* XXX 7-byte hole */
/* 192 | 1 */ LongInt send_frame(PAVCodecContext, PAVFrame);
/* XXX 7-byte hole */
/* 200 | 1 */ LongInt receive_packet(PAVCodecContext, PAVPacket);
/* XXX 7-byte hole */
/* 208 | 1 */ LongInt receive_frame(PAVCodecContext, PAVFrame);
/* XXX 7-byte hole */
/* 216 | 1 */ void flush(PAVCodecContext);
/* XXX 7-byte hole */
--Type <RET> for more, q to quit, c to continue without paging--
/* 224 | 4 */ LongInt caps_internal;
/* XXX 4-byte hole */
/* 232 | 8 */ PChar bsfs;
/* 240 | 8 */ PPointer hw_configs;
/* total size (bytes): 248 */
}
That looks already very good to validate the total size and alignment of each offset! One can see that for this example, the problem starts at offset 120.
We need more people who test #583 to get the fix merged.
Arch Linux users can build the test version like this:
wget -qO- https://aur.archlinux.org/cgit/aur.git/snapshot/ultrastardx-git.tar.gz | tar xvzf -
cd ultrastardx-git
sed -i '/source=/s/USDX\.git/&#branch=ffmpeg-4.3-4.4/' PKGBUILD
makepkg -fi
All looking good here with this patch. Arch Linux, x86_64
When i recently updated my Arch Linux, i couldn't compile the recent USDX repo. When checking the errors I noticed, that the checks for the ffmpeg libraries max versions failed. I've been wondering why there where such strict checks and when i removed them like in my forked branch everything worked just fine. Checked also with multiple micros. Why are these checks there? Should i open a PR to remove them?
Actual behaviour
Compiling fails with error messages like:
USDX/src/lib/ffmpeg-4.0/avutil.pas(81,4) Error: User defined: Linked version of libavutil is not yet supported!
Expected behaviour
Compiles without error
Steps to reproduce
Details
Provide some additional information: