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

Reinhard Tartler siretart
Mon Jun 7 07:52:11 CEST 2010

On Mo, Jun 07, 2010 at 01:44:30 (CEST), Michael Niedermayer wrote:

>> > we can duplicate the symbols and code in lavf under #if
>> I suspect that might cause a conflict during linking since the same
>> symbol would be provided by two libraries.  If it doesn't fail, the
>> version chosen is unpredictable.  We'd end up with apps linked against
>> a mix of sym at LIBAVFORMAT_XX and sym at LIBAVCODEC_XX which is obviously
>> not good.
> marking one as weak symbol might work.
> weak symbols are part of the ELF spec ... doesnt mean gnu tools support
> them of course ;)

I've (of course) tried that as well, but it doesn't work in this
case. The problem here is that you must not create symbol collisions in
the same compilation unit. Removing the symbols from libavcodec, even
conditionally, is not an option that we have. Using weak symbols, like
this version

/* compatibility trampolines for packet functions */

#define av_weak_alias(x)  __attribute__ (( weak, alias ("x") ))

void av_init_packet(AVPacket *pkt) av_weak_alias(av_init_packet);
void av_init_packet(AVPacket *pkt)
    av_log(NULL, AV_LOG_WARNING, "diverting av_*_packet function calls to libavcodec. Recompile to improve performance\n");

// and so on

causes this compiler error:
.../ffmpeg/libavformat/utils.c:326: error: redefinition of 'av_init_packet'
.../ffmpeg/libavformat/utils.c:325: note: previous definition of 'av_init_packet' was here

the point here is that defining multiple versions of the same symbol
(this is what we effectively need here) is generally not allowed in C.
It was also not part of the original sun symbol versioning
implementation, but a gnu extension that allows programmers to make
changes to the API and still retain binary compatibility. And even with
that extension, you still need to declare which version of the symbol is
to be used as default.  compare:

>> readelf -s -V /tmp/ffmpeg/lib/libavformat.so.52 | grep av_init_packet
   121: 00000000     0 FUNC    GLOBAL DEFAULT  UND av_init_packet at LIBAVCODEC_52 (4)
   470: 000a81b0    49 FUNC    GLOBAL DEFAULT   13 av_init_packet at LIBAVFORMAT_52
   516: 000a81b0    49 FUNC    GLOBAL DEFAULT   13 ff_av_init_packet@@LIBAVFORMAT_52

>> readelf -s -V /tmp/ffmpeg/lib/libavcodec.so.52 | grep av_init_packet
  1274: 000c0ca0    88 FUNC    GLOBAL DEFAULT   13 av_init_packet@@LIBAVCODEC_52

NB: 'av_init_packet@@LIBAVCODEC_52' vs. 'av_init_packet at LIBAVFORMAT_52'.
In this case, the symbol with '@@' is the default version. The gnu
implementation furthermore requires that there must be exactly one
default version for a symbol.  If this is not done, linked applications
might prefer the symbol from libavformat over libavcodec, and we really
really do not want this.

AFAIUI, these are our options now:

 - my proposed "half fix" (mans strongly objects to this)
 - bump major of libavformat

Ruled out options:

 - move symbols back to libavformat (would reintroduce lavc->lavf dependency)
 - using weak symbols (doesn't support duplicate symbols)

Any options that I've missed?

Reinhard Tartler, KeyID 945348A4

More information about the ffmpeg-devel mailing list