(Solution) FFMPEG under AMD64

I have been playing around with building Panda3d 1.5.2 with FFMPEG enabled under Debian SID AMD64 and some how managed to get it working.

So here’s the errors/steps and my solutions, take everything with a tablespoon of salt, I’m a newbie and I pieced it together mostly from Google.

[color=darkred][size=84]/usr/bin/ld: built/lib/libavutil.a(mem.o): relocation R_X86_64_32 against `a local symbol’ can not be used when making a shared object; recompile with -fPIC
built/lib/libavutil.a: could not read symbols: Bad value[/size]

Apparently this version of FFMPEG needs to be recompiled with -fPIC, now I didn’t have this problem before since I was using the latest SID packages from Debian-Multimedia, but I felt I might as well address it for anyone who doesn’t.

[color=indigo]su (enter root password)
cd /tmp
apt-get build-dep ffmpeg
apt-get source ffmpeg
cd ffmpeg*/

nano Makefile
add -fPIC to the end of CFLAGS and LDFLAGS.
(CTRL+O to save, CTRL+X to quit)

[color=indigo]dpkg-buildpackage
cd …
dpkg -i libavcodec-dev*.deb libavformat-dev*.deb libavutil-dev*.deb

Since APT happily upgrades these packages losing the changes you made, you need to temporarily put them on hold. I use wajig for sheer ease, which is available through apt-get like usual.

[color=indigo]wajig hold libavcodec-dev libavformat-dev libavutil-dev
In the future you’ll need, wajig list-hold, wajig unhold

[color=darkred][size=84]g++ -o built/bin/apply_patch -Lbuilt/lib -L/usr/X11R6/lib built/tmp/apply_patch_apply_patch.o -lpanda -lpandaexpress -lp3dtool -lp3dtoolconfig -lp3pystub -lz -lssl -lpthread -ldl
built/lib/libpanda.so: undefined reference to av_close_input_file(AVFormatContext*)' built/lib/libpanda.so: undefined reference toregister_protocol(URLProtocol*)’
built/lib/libpanda.so: undefined reference to avcodec_open(AVCodecContext*, AVCodec*)' built/lib/libpanda.so: undefined reference toav_register_all()’
built/lib/libpanda.so: undefined reference to avpicture_fill(AVPicture*, unsigned char*, int, int, int)' built/lib/libpanda.so: undefined reference toav_open_input_file(AVFormatContext**, char const*, AVInputFormat*, int, AVFormatParameters*)’
built/lib/libpanda.so: undefined reference to avcodec_decode_video(AVCodecContext*, AVFrame*, int*, unsigned char const*, int)' built/lib/libpanda.so: undefined reference toavcodec_alloc_frame()’
built/lib/libpanda.so: undefined reference to dump_format(AVFormatContext*, int, char const*, int)' built/lib/libpanda.so: undefined reference toavcodec_close(AVCodecContext*)’
built/lib/libpanda.so: undefined reference to avcodec_find_decoder(CodecID)' built/lib/libpanda.so: undefined reference toavcodec_decode_audio(AVCodecContext*, short*, int*, unsigned char const*, int)’
built/lib/libpanda.so: undefined reference to avpicture_get_size(int, int, int)' built/lib/libpanda.so: undefined reference toav_seek_frame(AVFormatContext*, int, long, int)’
built/lib/libpanda.so: undefined reference to av_free(void*)' built/lib/libpanda.so: undefined reference toav_find_stream_info(AVFormatContext*)’
built/lib/libpanda.so: undefined reference to img_convert(AVPicture*, int, AVPicture const*, int, int, int)' built/lib/libpanda.so: undefined reference toav_read_frame(AVFormatContext*, AVPacket*)’
collect2: ld returned 1 exit status[/size]

It turns out some while back FFMPEG removed their internal support for C++ and switched to pure C, I ended up having to edit these files:

panda/src/grutil/ffmpegTexture.h
panda/src/movies/ffmpegAudioCursor.cxx
panda/src/movies/ffmpegVideoCursor.cxx
panda/src/movies/config_movies.cxx

And surrounding any instances of #include “avcodec.h” and “avformat.h” with extern “C” { }, like so:

[color=darkblue]extern “C” {
#include “avcodec.h”
#include “avformat.h”
}

[color=darkred][size=84]g++ -o built/bin/apply_patch -Lbuilt/lib -L/usr/X11R6/lib built/tmp/apply_patch_apply_patch.o -lpanda -lpandaexpress -lp3dtool -lp3dtoolconfig -lp3pystub -lz -lssl -lpthread -ldl
built/lib/libpanda.so: undefined reference to vorbis_analysis' built/lib/libpanda.so: undefined reference tovorbis_info_clear’
built/lib/libpanda.so: undefined reference to gsm_destroy' built/lib/libpanda.so: undefined reference totheora_info_clear’
built/lib/libpanda.so: undefined reference to NeAACDecGetCurrentConfiguration' built/lib/libpanda.so: undefined reference totheora_encode_YUVin’
built/lib/libpanda.so: undefined reference to a52_init' built/lib/libpanda.so: undefined reference tovorbis_encode_setup_init’
built/lib/libpanda.so: undefined reference to a52_free' built/lib/libpanda.so: undefined reference tovorbis_block_init’
built/lib/libpanda.so: undefined reference to vorbis_bitrate_flushpacket' built/lib/libpanda.so: undefined reference totheora_encode_header’
built/lib/libpanda.so: undefined reference to vorbis_comment_clear' built/lib/libpanda.so: undefined reference tovorbis_analysis_wrote’
built/lib/libpanda.so: undefined reference to theora_info_init' built/lib/libpanda.so: undefined reference toa52_block’
built/lib/libpanda.so: undefined reference to vorbis_dsp_clear' built/lib/libpanda.so: undefined reference totheora_encode_packetout’
built/lib/libpanda.so: undefined reference to vorbis_analysis_blockout' built/lib/libpanda.so: undefined reference totheora_encode_tables’
built/lib/libpanda.so: undefined reference to gsm_create' built/lib/libpanda.so: undefined reference tovorbis_comment_add_tag’
built/lib/libpanda.so: undefined reference to NeAACDecOpen' built/lib/libpanda.so: undefined reference totheora_encode_comment’
built/lib/libpanda.so: undefined reference to vorbis_encode_setup_vbr' built/lib/libpanda.so: undefined reference toa52_syncinfo’
built/lib/libpanda.so: undefined reference to a52_frame' built/lib/libpanda.so: undefined reference tovorbis_info_init’
built/lib/libpanda.so: undefined reference to gsm_option' built/lib/libpanda.so: undefined reference tovorbis_encode_ctl’
built/lib/libpanda.so: undefined reference to vorbis_analysis_init' built/lib/libpanda.so: undefined reference totheora_clear’
built/lib/libpanda.so: undefined reference to gsm_decode' built/lib/libpanda.so: undefined reference toNeAACDecClose’
built/lib/libpanda.so: undefined reference to vorbis_block_clear' built/lib/libpanda.so: undefined reference tovorbis_comment_init’
built/lib/libpanda.so: undefined reference to NeAACDecGetErrorMessage' built/lib/libpanda.so: undefined reference totheora_comment_clear’
built/lib/libpanda.so: undefined reference to NeAACDecSetConfiguration' built/lib/libpanda.so: undefined reference tovorbis_encode_setup_managed’
built/lib/libpanda.so: undefined reference to NeAACDecDecode' built/lib/libpanda.so: undefined reference toa52_samples’
built/lib/libpanda.so: undefined reference to theora_comment_init' built/lib/libpanda.so: undefined reference togsm_encode’
built/lib/libpanda.so: undefined reference to vorbis_analysis_headerout' built/lib/libpanda.so: undefined reference tovorbis_bitrate_addblock’
built/lib/libpanda.so: undefined reference to vorbis_analysis_buffer' built/lib/libpanda.so: undefined reference toNeAACDecInit2’
built/lib/libpanda.so: undefined reference to theora_encode_init' built/lib/libpanda.so: undefined reference toNeAACDecInit’
collect2: ld returned 1 exit status[/size]

Simple enough, ffmpeg needs the libraries that it has enabled, so just adding this to makepanda.py at line 1829 pushes it forward.

[color=darkblue]TargetAdd(‘libpanda.dll’, input=‘libvorbis.dll’)
TargetAdd(‘libpanda.dll’, input=‘libvorbisenc.dll’)
TargetAdd(‘libpanda.dll’, input=‘libtheora.dll’)
TargetAdd(‘libpanda.dll’, input=‘liba52.dll’)
TargetAdd(‘libpanda.dll’, input=‘libgsm.dll’)
TargetAdd(‘libpanda.dll’, input=‘libfaad.dll’)

Hope that helps!

P.S. Here’s the relevant part from my symlinks.sh in case it saves someone some time.

#!/bin/sh

mkdir -pv linux-libs-x64
cd linux-libs-x64

if [ "$1" == "ffmpeg" ]
then
	mkdir ffmpeg
	mkdir ffmpeg/include
	mkdir ffmpeg/lib

	cd ffmpeg

	cd include
	cp -s /usr/include/ffmpeg/*	./
	ln -s /usr/include/ffmpeg	ffmpeg
	cd ..

	cd lib
	ln -s /usr/lib/libavcodec.a libavcodec.a
	ln -s /usr/lib/libavformat.a libavformat.a
	ln -s /usr/lib/libavutil.a libavutil.a
	cd ..
fi

Just run from the thirdparty directory as “./symlinks.sh ffmpeg”

thanks for the info!