[FFmpeg-devel] [PATCH] restoring binary compatibility with ffmpeg 0.5

Reinhard Tartler siretart
Sun Jun 6 17:03:40 CEST 2010


Hi,

I'm sorry for not noticing earlier, but during upgrade tests, I noticed
that there are some functions that went missing in libavformat.so.52
since ffmpeg 0.5. In total, they are:

void ff_av_destruct_packet_nofree(AVPacket *pkt);
void ff_av_destruct_packet(AVPacket *pkt);
int ff_av_new_packet(AVPacket *pkt, int size);
int ff_av_dup_packet(AVPacket *pkt);
void ff_av_free_packet(AVPacket *pkt);
void ff_av_init_packet(AVPacket *pkt);

They all were moved quite some time ago from libavformat to libavcodec.
The API has not been broken, as avcodec is a dependency for avformat.
Still, this is a serious problem if we want to retain binary
compatibility. As a testcase, I'm using the ubuntu ffplay binary (ffmpeg
0.5) with a LD_LIBRARY_PATH, in which ffmpeg 0.6 libraries have been
installed to playback a VP8 file in a WEBM container. Using this setup,
ffplay aborts with:

>> ffplay /tmp/elephant-dream.webm
FFplay version SVN-r0.5.1-4:0.5.1-1ubuntu1, Copyright (c) 2003-2009 Fabrice Bellard, et al.
  configuration: --extra-version=4:0.5.1-1ubuntu1 --prefix=/usr --enable-avfilter --enable-avfilter-lavf --enable-vdpau --enable-bzlib --enable-libgsm --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libvorbis --enable-pthreads --enable-zlib --disable-stripping --disable-vhook --enable-runtime-cpudetect --enable-gpl --enable-postproc --enable-swscale --enable-x11grab --enable-libdc1394 --enable-shared --disable-static
  libavutil     49.15. 0 / 49.15. 0
  libavcodec    52.20. 1 / 52.72. 2
  libavformat   52.31. 0 / 52.64. 2
  libavdevice   52. 1. 0 / 52. 2. 0
  libavfilter    0. 4. 0 /  0. 4. 0
  libswscale     0. 7. 1 /  0.11. 0
  libpostproc   51. 2. 0 / 51. 2. 0
  built on Mar  4 2010 12:35:30, gcc: 4.4.3
ffplay: relocation error: ffplay: symbol av_init_packet, version LIBAVFORMAT_52 not defined in file libavformat.so.52 with link time reference

The message is exactly right; the mentioned symbols have been removed
from libavformat.so.52.

The safest fix in this situation would be of course to bump major.
However, I've spent now some time to restore binary compatibility by
adding trampoline functions and .symver directives. With the attached
patch, I get the following:

>> ffplay /tmp/elephant-dream.webm
FFplay version SVN-r0.5.1-4:0.5.1-1ubuntu1, Copyright (c) 2003-2009 Fabrice Bellard, et al.
  configuration: --extra-version=4:0.5.1-1ubuntu1 --prefix=/usr --enable-avfilter --enable-avfilter-lavf --enable-vdpau --enable-bzlib --enable-libgsm --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libvorbis --enable-pthreads --enable-zlib --disable-stripping --disable-vhook --enable-runtime-cpudetect --enable-gpl --enable-postproc --enable-swscale --enable-x11grab --enable-libdc1394 --enable-shared --disable-static
  libavutil     49.15. 0 / 49.15. 0
  libavcodec    52.20. 1 / 52.72. 2
  libavformat   52.31. 0 / 52.64. 2
  libavdevice   52. 1. 0 / 52. 2. 0
  libavfilter    0. 4. 0 /  0. 4. 0
  libswscale     0. 7. 1 /  0.11. 0
  libpostproc   51. 2. 0 / 51. 2. 0
  built on Mar  4 2010 12:35:30, gcc: 4.4.3
diverting av_*_packet function calls to libavcodec. Recompile to improve performance
[libvpx @ 0x9f60b10]v0.9.0
[matroska @ 0x9f2fce0]Estimating duration from bitrate, this may be inaccurate
[libvpx @ 0x9f60b10]v0.9.0

and the video plays back just fine.

I'd really like to have this for ffmpeg 0.6. Is the attached patch
acceptable for trunk?

Index: configure
===================================================================
--- configure	(revision 23498)
+++ configure	(working copy)
@@ -1086,6 +1086,7 @@
     struct_sockaddr_in6
     struct_sockaddr_sa_len
     struct_sockaddr_storage
+    symbol_versioning
     sys_mman_h
     sys_resource_h
     sys_select_h
@@ -2733,7 +2734,7 @@
 
 echo "X{};" > $TMPV
 test_ldflags -Wl,--version-script,$TMPV &&
-    append SHFLAGS '-Wl,--version-script,\$(SUBDIR)lib\$(NAME).ver'
+    append SHFLAGS '-Wl,--version-script,\$(SUBDIR)lib\$(NAME).ver' && enable symbol_versioning
 
 if enabled small; then
     add_cflags $size_cflags
Index: libavformat/utils.c
===================================================================
--- libavformat/utils.c	(revision 23498)
+++ libavformat/utils.c	(working copy)
@@ -29,6 +29,9 @@
 #include <time.h>
 #include <strings.h>
 #include <stdarg.h>
+#if HAVE_SYMBOL_VERSIONING && LIBAVFORMAT_VERSION_MAJOR < 53
+#include <dlfcn.h>
+#endif
 #if CONFIG_NETWORK
 #include "network.h"
 #endif
@@ -41,6 +44,10 @@
  * various utility functions for use within FFmpeg
  */
 
+#if HAVE_SYMBOL_VERSIONING && LIBAVFORMAT_VERSION_MAJOR < 53
+static void *avformat_handle;
+#endif
+
 unsigned avformat_version(void)
 {
     return LIBAVFORMAT_VERSION_INT;
@@ -282,9 +289,75 @@
     return NULL;
 }
 
-/* memory handling */
+#if HAVE_SYMBOL_VERSIONING && LIBAVFORMAT_VERSION_MAJOR < 53
+/* compatibility trampolines for packet functions */
 
+void ff_av_destruct_packet_nofree(AVPacket *pkt);
+void ff_av_destruct_packet_nofree(AVPacket *pkt)
+{
+    void (*fn)(AVPacket *pkt) = dlsym(avformat_handle, "av_destruct_packet_nofree");
+    if (!fn)
+        av_log(NULL, AV_LOG_FATAL, "Failed to locate symbol: av_destruct_nofree\n");
+    (*fn)(pkt);
+}
+__asm__(".symver ff_av_destruct_packet_nofree,av_destruct_packet_nofree at LIBAVFORMAT_52");
 
+void ff_av_destruct_packet(AVPacket *pkt);
+void ff_av_destruct_packet(AVPacket *pkt)
+{
+    void (*fn)(AVPacket *pkt) = dlsym(avformat_handle, "av_destruct_packet");
+    if (!fn)
+        av_log(NULL, AV_LOG_FATAL, "Failed to locate symbol: av_destruct_packet\n");
+    (*fn)(pkt);
+}
+__asm__(".symver ff_av_destruct_packet,av_destruct_packet at LIBAVFORMAT_52");
+
+int ff_av_new_packet(AVPacket *pkt, int size);
+int ff_av_new_packet(AVPacket *pkt, int size)
+{
+    int (*fn)(AVPacket *pkt, int size) = dlsym(avformat_handle, "av_new_packet");
+    if (!fn)
+        av_log(NULL, AV_LOG_FATAL, "Failed to locate symbol: av_new_packet\n");
+    return (*fn)(pkt, size);
+}
+__asm__(".symver ff_av_new_packet,av_new_packet at LIBAVFORMAT_52");
+
+int ff_av_dup_packet(AVPacket *pkt);
+int ff_av_dup_packet(AVPacket *pkt)
+{
+    int (*fn)(AVPacket *pkt) = dlsym(avformat_handle, "av_dup_packet");
+    if (!fn)
+        av_log(NULL, AV_LOG_FATAL, "Failed to locate symbol: av_dup_packet\n");
+    return (*fn)(pkt);
+}
+__asm__(".symver ff_av_dup_packet,av_dup_packet at LIBAVFORMAT_52");
+
+void ff_av_free_packet(AVPacket *pkt);
+void ff_av_free_packet(AVPacket *pkt)
+{
+    void (*fn)(AVPacket *pkt) = dlsym(avformat_handle, "av_free_packet");
+    if (!fn)
+        av_log(NULL, AV_LOG_FATAL, "Failed to locate symbol: av_free_packet\n");
+    (*fn)(pkt);
+}
+__asm__(".symver ff_av_free_packet,av_free_packet at LIBAVFORMAT_52");
+
+void ff_av_init_packet(AVPacket *pkt);
+void ff_av_init_packet(AVPacket *pkt)
+{
+    void (*fn)(AVPacket *pkt);
+    av_log(NULL, AV_LOG_WARNING, "diverting av_*_packet function calls to libavcodec. Recompile to improve performance\n");
+    avformat_handle=dlopen("libavcodec.so.52", RTLD_LAZY);
+    if(!avformat_handle)
+        av_log(NULL, AV_LOG_FATAL, "Could not open libavcodec.so.52\n");
+    fn = dlsym(avformat_handle, "av_init_packet");
+    if (!fn)
+        av_log(NULL, AV_LOG_FATAL, "Failed to locate symbol: av_init_packet\n");
+    (*fn)(pkt);
+}
+__asm__(".symver ff_av_init_packet,av_init_packet at LIBAVFORMAT_52");
+#endif
+
 int av_get_packet(ByteIOContext *s, AVPacket *pkt, int size)
 {
     int ret= av_new_packet(pkt, size);



-- 
Gruesse/greetings,
Reinhard Tartler, KeyID 945348A4




More information about the ffmpeg-devel mailing list