Cross-compiling FFmpeg for Serviio with shared libraries on Synology NAS (for 7 CPU architectures)

This method will build FFmpeg 2.7.1 with the shared libraries (linked with relative paths) required for Serviio DLNA media server, using a Ubuntu/Xubuntu Desktop 14.04 virtual machine, however the same method probably works with many other Linux distributions. The target CPU architectures are ARMv5, ARMv7, ARM hard float ABI with NEON, Intel i686, Intel x64, and PowerPC e500v2.

The >10MB size of the static executable is kind of getting out of hand especially on embedded systems with very limited RAM. Using shared libs means many concurrent instances of FFmpeg can use broadly the same memory footprint, and package distribution binaries can be smaller – our target systems already have libmp3lame, libm, libz, librt, libgmp, libssl, libcrypto, libfreetype, libexpat, and libpthread which add up to several megabytes. I’m also guessing that the OS will decide when to unload them from RAM which could help when FFmpeg is being launched repeatedly in a short period of time (e.g. during library scanning).

The notes below also detail how to compile the Synology fork of FFmpeg 2.0.2 with Intel Evansport SMD (Streaming Media Drivers) hardware transcoding support. This source is itself based upon a fork by Intel which seems to form part of the Evansport SDK. It was not straightforward to compile, and now that I have released Serviio for Synology with hardware transcoding support I’m sharing my method in the hope it can help others. This older FFmpeg needs a patch to fix a long standing bug with DTS audio remuxing (reported by me) where the stream ID was incorrectly set:

--- ffmpeg-2.2.1/libavformat/mpegts.h
+++ ffmpeg-2.2.1-ticket1398/libavformat/mpegts.h
@@ -57,7 +57,8 @@
 #define STREAM_TYPE_VIDEO_DIRAC     0xd1
 
 #define STREAM_TYPE_AUDIO_AC3       0x81
-#define STREAM_TYPE_AUDIO_DTS       0x8a
+#define STREAM_TYPE_AUDIO_DTS       0x82
+#define STREAM_TYPE_AUDIO_TRUEHD    0x83
 
 typedef struct MpegTSContext MpegTSContext;
 
--- ffmpeg-2.2.1/libavformat/mpegtsenc.c
+++ ffmpeg-2.2.1-ticket1398/libavformat/mpegtsenc.c
@@ -311,6 +311,12 @@
         case AV_CODEC_ID_AC3:
             stream_type = STREAM_TYPE_AUDIO_AC3;
             break;
+        case AV_CODEC_ID_DTS:
+            stream_type = STREAM_TYPE_AUDIO_DTS;
+            break;
+        case AV_CODEC_ID_TRUEHD:
+            stream_type = STREAM_TYPE_AUDIO_TRUEHD;
+            break;
         default:
             stream_type = STREAM_TYPE_PRIVATE_DATA;
             break;

Although the unmodified FFmpeg source code will compile successfully for PowerPC CPUs, the FFmpeg binary will core dump when running any command on a video file. I contacted Synology Support for help with this issue back in October 2012 and was given a patch to use at that time which changes the use of a CPU register in the DSP assembly code. The FFmpeg source code has changed a bit recently meaning the patch was no longer valid, but I was able to discover the appropriate location in the code and create a new working patch (code was moved from dsputil_ppc.c to blockdsp.c):

diff -rupN ffmpeg/libavcodec/ppc/blockdsp.c ffmpeg-patched/libavcodec/ppc/blockdsp.c
--- ffmpeg/libavcodec/ppc/blockdsp.c	2015-06-19 21:44:40.000000000 +0100
+++ ffmpeg-patched/libavcodec/ppc/blockdsp.c	2015-07-11 04:06:27.326911100 +0100
@@ -115,8 +115,9 @@ static long check_dcbzl_effect(void)
     memset(fakedata, 0xFF, 1024);
 
     /* Below the constraint "b" seems to mean "address base register"
-     * in gcc-3.3 / RS/6000 speaks. Seems to avoid using r0, so.... */
-    __asm__ volatile ("dcbzl %0, %1" :: "b" (fakedata_middle), "r" (zero));
+     * in gcc-3.3 / RS/6000 speaks. Seems to avoid using r0, so.... 
+    __asm__ volatile ("dcbzl %0, %1" :: "b" (fakedata_middle), "r" (zero)); */
+    __asm__ volatile ("dcbz %0, %1" :: "r" (fakedata_middle), "r" (zero));
 
     for (i = 0; i < 1024; i++)
         if (fakedata[i] == (char) 0)
 
#-----set up Synology toolchain
cd ~/Downloads
#export DL_PATH="http://sourceforge.net/projects/dsgpl/files/DSM%205.0%20Tool%20Chains"
#export DL_PATH="http://sourceforge.net/projects/dsgpl/files/DSM%20Beta%205.2%20Tool%20Chains"
export DL_PATH="http://sourceforge.net/projects/dsgpl/files/DSM%205.2%20Tool%20Chains"
#-----add 32bit binary compatibility to Ubuntu 14.04 LTS (Syno toolchains are 32bit)
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
sudo apt-get install git
sudo apt-get install chrpath
#----------------------------------------------------
#-----NOW PASTE ONE OF THE FOLLOWING SIX BLOCKS TO THE TERMINAL, DEPENDING ON YOUR TARGET CPU TYPE
#-----Marvell Kirkwood mv6281/mv6282 (ARMv5te)
#-----Marvell Armada 370/375/XP (ARMv7l FPU)
#-----Mindspeed Comcerto 2000/Marvell Armada 375 (ARM Cortex-A9 NEON)
#-----Freescale PowerQUICC III MPC8533E/QorIQ P1022 (PPC e500v2 FPU)
#-----Intel Atom/Bromolow/Cedarview (i686 SSSE3)
#-----Intel Evansport (i686 SSSE3 various HW decoders, HW H.264 encoder)




#-----Marvell Kirkwood mv6281/mv6282 CPU is based on the ARMv5TE core which has DSP and Thumb instruction support
#-----However using Thumb on ARMv5 results in worse performance
#-----http://www.arm.com/products/processors/technologies/dsp-simd.php
#-----http://www.marvell.com/embedded-processors/kirkwood/assets/88f6282-3_pb.pdf
wget "${DL_PATH}/Marvell%2088F628x%20Linux%202.6.32/6281-gcc464_glibc215_88f6281-GPL.txz"
tar xvJf 6281-gcc464_glibc215_88f6281-GPL.txz
#-----Marvell gave the ARMv5 and ARMv7 toolchains the same name so rename to allow concurrent installations
mv arm-marvell-linux-gnueabi/ arm-none-linux-gnueabi/
#-----these next two packages are needed to build libshine
sudo apt-get install automake
sudo apt-get install libtool
export CROSS_PREFIX=arm-marvell-linux-gnueabi
export TOOLCHAIN=/usr/local/arm-none-linux-gnueabi
export TARGET=arm-marvell-linux-gnueabi
export MARCH="-march=armv5te -mtune=marvell-f -mtune=xscale"
export LAME_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static --disable-decoder"
#-----libx264:
#-----http://forum.doom9.org/showthread.php?t=160584
#-----https://mailman.videolan.org/pipermail/x264-devel/2010-December/008093.html
#-----x264 builds with NEON by default because x264 is so slow without NEON (and on any non-NEON chip) as to be useless.
#-----You can of course compile with --disable-asm on such chips, but we don't do it by default because
#-----we don't feel it's necessary to actively support chips on which x264 would be basically useless
export X264_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --enable-shared --disable-asm --enable-pic --enable-strip"
#-----FFmpeg:
#-----ARMv5TE CPU-specific options (based on inspecting 'configure' script https://github.com/FFmpeg/FFmpeg/blob/master/configure)
#-----pkg-config needs to be defined because with cross-prefix it assumes ${CROSS_PREFIX}-pkg-config which doesn't exist, and then librtmp won't be detected
#-----something changed in the FFmpeg configure script and now vfp and neon optimizations have to be explicitly disabled for ARMv5TE, which doesn't have those features in any case
export FF_CONFIG="./configure --arch=arm --cpu=armv5te --enable-cross-compile --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --target-os=linux --prefix=${TOOLCHAIN} --enable-shared --disable-static --enable-pic --disable-ffplay --disable-ffserver --disable-neon --disable-vfp --disable-armv6 --disable-armv6t2 --disable-debug --enable-pthreads --enable-libshine --enable-librtmp --enable-libass --enable-libspeex --enable-gpl --enable-libx264 --enable-gnutls --pkg-config=pkg-config --extra-version=compiled_by_patters_for_Serviio"
#export FF_CONFIG="./configure --arch=arm --cpu=armv5te --enable-cross-compile --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --target-os=linux --prefix=${TOOLCHAIN} --enable-shared --disable-static --enable-pic --disable-ffplay --disable-ffserver --disable-neon --disable-vfp --disable-armv6 --disable-armv6t2 --disable-debug --enable-pthreads --enable-libshine --enable-librtmp --enable-libass --enable-libspeex --enable-gpl --enable-libx264 --enable-gnutls --enable-nonfree --enable-libfdk_aac --pkg-config=pkg-config --extra-version=compiled_by_patters_for_Serviio"
wget https://github.com/savonet/shine/zipball/master
unzip master
cd toots-shine-*
./bootstrap
cd ..
#-----fetch libfdk-aac fixed point math AAC encoder, binaries linked to it cannot be redistributed under GPL
#-----so it is excluded from the FFmpeg binary I built for the Serviio package
wget http://sourceforge.net/projects/opencore-amr/files/fdk-aac/fdk-aac-0.1.4.tar.gz
tar xvzf fdk-aac-0.1.4.tar.gz
cd fdk-aac-0.1.4
./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static
make
make install
cd ..
 



#-----Marvell Armada 370/XP CPU is based on a dual issue ARMv7 core with Thumb-2, VFPv3-16, but no NEON vector unit
#-----http://www.marvell.com/embedded-processors/armada-300/assets/Marvell_ARMADA_370_SoC.pdf
#-----http://www.arm.com/products/processors/technologies/vector-floating-point.php
#-----Marvell Armada 375 CPU is based on dual ARM Cortex-A9 cores with NEON vector unit, but there is no Synology toolchain with NEON support
#-----Synology seems to have used this toolchain to build DSM for the Armada 375
#-----http://www.marvell.com/embedded-processors/armada-300/assets/ARMADA_375_SoC-01_product_brief.pdf
wget "${DL_PATH}/Marvell%20Armada%20370%20Linux%203.2.40/armada370-gcc464_glibc215_hard_armada-GPL.txz"
tar xvJf armada370-gcc464_glibc215_hard_armada-GPL.txz
export CROSS_PREFIX=arm-marvell-linux-gnueabi
export TARGET=arm-marvell-linux-gnueabi
export TOOLCHAIN=/usr/local/${CROSS_PREFIX}
#-----Tune for Marvell PJ4 dual issue core (two instructions per clock)
#-----Thumb-2 can be used on ARMv6 or newer with no performance drop
export MARCH="-march=armv7-a -mcpu=marvell-pj4 -mtune=marvell-pj4 -mhard-float -mfpu=vfpv3-d16 -mthumb"
export LAME_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static --disable-decoder"
#-----libx264:
#-----http://forum.doom9.org/showthread.php?t=160584
#-----https://mailman.videolan.org/pipermail/x264-devel/2010-December/008093.html
#-----x264 builds with NEON by default because x264 is so slow without NEON (and on any non-NEON chip) as to be useless.
#-----You can of course compile with --disable-asm on such chips, but we don't do it by default because
#-----we don't feel it's necessary to actively support chips on which x264 would be basically useless
#-----http://lists.busybox.net/pipermail/buildroot/2014-October/107797.html
export X264_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --enable-shared --disable-asm --enable-pic --enable-strip"
#-----FFmpeg:
#-----ARMv7 CPU-specific options (based on inspecting 'configure' script https://github.com/FFmpeg/FFmpeg/blob/master/configure)
#-----pkg-config needs to be defined because with cross-prefix it assumes ${CROSS_PREFIX}-pkg-config which doesn't exist, and then librtmp won't be detected
export FF_CONFIG="./configure --arch=arm --cpu=armv7-a --enable-thumb --enable-cross-compile --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --target-os=linux --prefix=${TOOLCHAIN} --enable-shared --disable-static --enable-pic --disable-ffplay --disable-ffserver --disable-neon --disable-debug --enable-pthreads --enable-libmp3lame --enable-librtmp --enable-libass --enable-libspeex --enable-gpl --enable-libx264 --enable-gnutls --pkg-config=pkg-config --extra-version=compiled_by_patters_for_Serviio"




#-----Mindspeed Comcerto 2000 CPU is based on dual ARM Cortex-A9 cores with NEON vector unit
#-----http://www.mindspeed.com/products/cpe-processors/comcertoreg-2000
#-----http://www.arm.com/products/processors/cortex-a/cortex-a9.php
#-----http://www.arm.com/products/processors/technologies/neon.php
#-----Armada 375 toolchain uses glibc 2.15, Comcerto 2000 uses glibc 2.17 
wget "${DL_PATH}/Mindspeed%20Comcerto%202000%20Linux%203.2.40/comcerto2k-gcc464_glibc217_neon_comcerto-GPL.txz"
tar xvJf comcerto2k-gcc464_glibc217_neon_comcerto-GPL.txz
export CROSS_PREFIX=arm-cortexa9-linux-gnueabi
export TARGET=arm-cortexa9-linux-gnueabi
export TOOLCHAIN=/usr/local/${CROSS_PREFIX}
#-----it seems that in general neon should be used as the fpu when present unless there's a specific reason not to use it
export MARCH="-march=armv7-a -mcpu=cortex-a9 -mfpu=neon -mhard-float -mthumb"
export LAME_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static --disable-decoder"
#-----libx264:
export X264_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --enable-shared --enable-pic --enable-strip"
#-----FFmpeg:
#-----ARMv7 CPU-specific options (based on inspecting 'configure' script https://github.com/FFmpeg/FFmpeg/blob/master/configure)
#-----pkg-config needs to be defined because with cross-prefix it assumes ${CROSS_PREFIX}-pkg-config which doesn't exist, and then librtmp won't be detected
export FF_CONFIG="./configure --arch=arm --cpu=cortex-a9 --enable-thumb --enable-cross-compile --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --target-os=linux --prefix=${TOOLCHAIN} --enable-shared --disable-static --enable-pic --disable-ffplay --disable-ffserver --disable-debug --enable-pthreads --enable-libmp3lame --enable-librtmp --enable-libass --enable-libspeex --enable-gpl --enable-libx264 --enable-gnutls --pkg-config=pkg-config --extra-version=compiled_by_patters_for_Serviio"




#-----Freescale PowerQUICC III MPC8533E/QorIQ P1022 CPUs use the PowerPC e500v2 core with Signal Processing Engine (SPE) which is not a classic FPU design, but have no AltiVec vector unit 
#-----Some QorIQ models have e500mc cores with true FPUs but these are not used in 2013 series Synology NAS
#-----http://en.wikipedia.org/wiki/QorIQ
#-----http://cache.freescale.com/files/32bit/doc/fact_sheet/QP1022FS.pdf?fpsp=1
wget "${DL_PATH}/PowerPC%20QorIQ%20Linux%202.6.32/qoriq-gcc4374_eglibc2874_qoriq-GPL.txz"
tar xvJf qoriq-gcc4374_eglibc2874_qoriq-GPL.txz
export CROSS_PREFIX=powerpc-none-linux-gnuspe
export TOOLCHAIN=/usr/local/${CROSS_PREFIX}
export TARGET=powerpc-none-linux-gnuspe
export MARCH="-mcpu=8548 -mhard-float -mfloat-gprs=double"
export LAME_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static --disable-decoder"
#-----asm disabled since QorIQ has no AltiVec
export X264_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --enable-shared --disable-asm --enable-pic --enable-strip"
#-----FFmpeg:#-----PowerPC e500v2 CPU-specific options (based on inspecting 'configure' script https://github.com/FFmpeg/FFmpeg/blob/master/configure)
#-----pkg-config needs to be defined because with cross-prefix it assumes ${CROSS_PREFIX}-pkg-config which doesn't exist, and then librtmp won't be detected
export FF_CONFIG="./configure --arch=ppc --cpu=e500v2 --enable-cross-compile --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --target-os=linux --prefix=${TOOLCHAIN} --enable-shared --disable-static --enable-pic --disable-ffplay --disable-ffserver --disable-debug --enable-pthreads --enable-libmp3lame --enable-librtmp --enable-libass --enable-libspeex --enable-gpl --enable-libx264 --enable-gnutls --pkg-config=pkg-config --extra-version=compiled_by_patters_for_Serviio"




#-----With the exception of Evansport (i686), Intel CPUs used in Synology products are all 64bit and SSSE3 capable but existing DSM libs are 32bit at time of writing (DSM 4.1), so use the i686 toolchain rather than x86_64
#-----libx264 requires yasm 1.20
sudo apt-get install yasm
#-----unlike the others this toolchain has an external dependency on libz
sudo apt-get install libz1:i386
wget "${DL_PATH}/Intel%20x86%20Linux%203.2.40%20%28Pineview%29/x64-gcc463_glibc213_i686_patched-GPL.txz"
tar xvJf x64-gcc463_glibc213_i686_patched-GPL.txz
export CROSS_PREFIX=i686-pc-linux-gnu
export TARGET=i686-pc-linux-gnu
export TOOLCHAIN=/usr/local/${CROSS_PREFIX}
#-----We don't really care how lame is built since ffmpeg will use the version in DSM.
#-----The DSM version is built without asm optimizations but these only make a 5% difference, and have been known to introduce instability
export LAME_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static --disable-decoder"
export X264_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --enable-shared --enable-pic --enable-strip"
#-----FFmpeg:
#-----Intel CPU-specific options (based on inspecting 'configure' script https://github.com/FFmpeg/FFmpeg/blob/master/configure)
#-----pkg-config needs to be defined because with cross-prefix it assumes ${CROSS_PREFIX}-pkg-config which doesn't exist, and then librtmp won't be detected
export FF_CONFIG="./configure --arch=x86 --enable-cross-compile --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --target-os=linux --prefix=${TOOLCHAIN} --enable-shared --disable-static --enable-pic --disable-ffplay --disable-ffserver --disable-debug --enable-pthreads --enable-libmp3lame --enable-librtmp --enable-libass --enable-libspeex --enable-gpl --enable-libx264 --enable-gnutls --pkg-config=pkg-config --extra-version=compiled_by_patters_for_Serviio"




#-----Intel Evansport with support for hardware decoding of VC-1, H.264, MPEG-4, MPEG2, AAC and hardware encoding of H.264
#-----http://www.anandtech.com/show/8020/synology-ds214play-intel-evansport-almost-done-right/9
#-----http://ukdl.synology.com/download/spk/VideoStation/1.3-0547/
#-----libx264 requires yasm 1.20
sudo apt-get install yasm
wget "${DL_PATH}/Intel%20x86%20Linux%203.2.40%20%28Evansport%29/evansport-gcc463_glibc213_i686_patched-GPL.txz"
tar xvJf evansport-gcc463_glibc213_i686_patched-GPL.txz
#-----Both Intel toolchains the same name so rename to allow concurrent installations
mv i686-pc-linux-gnu evansport-pc-linux-gnu
#-----Synology headers and libs for the Intel Streaming Media Driver support
wget http://sourceforge.net/projects/dsgpl/files/Synology%20NAS%20GPL%20Source/5565branch/evansport-chroot.txz
mkdir evansport-chroot
cd evansport-chroot
tar xvJf ../evansport-chroot.txz
sudo cp -R lib/intelce-utilities/ ../evansport-pc-linux-gnu/lib
sudo cp -R include/intelce-utilities/ ../evansport-pc-linux-gnu/include
cd ..
#end of Intel SMD section
export CROSS_PREFIX=i686-pc-linux-gnu
export TARGET=i686-pc-linux-gnu
export MARCH="-march=atom"
export TOOLCHAIN=/usr/local/evansport-pc-linux-gnu
export LAME_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static --disable-decoder"
export X264_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --enable-shared --enable-pic --enable-strip"
#-----FFmpeg:
#-----Intel CPU-specific options (based on inspecting 'configure' script https://github.com/FFmpeg/FFmpeg/blob/master/configure)
#-----pkg-config needs to be defined because with cross-prefix it assumes ${CROSS_PREFIX}-pkg-config which doesn't exist, and then librtmp won't be detected
export FF_CONFIG="./configure.syno --arch=x86 --cpu=atom --enable-cross-compile --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --target-os=linux --prefix=${TOOLCHAIN} --enable-shared --disable-static --enable-pic --disable-ffplay --disable-ffserver --disable-debug --enable-pthreads --enable-libmp3lame --enable-librtmp --enable-libass --enable-libspeex --enable-libx264 --enable-libh264_smd --enable-smd --enable-gpl --enable-gnutls --pkg-config=pkg-config --extra-version=SMD_enabled_with_DTS_remux_fix-compiled_by_patters_for_Serviio"
#-----implicit function declaration issue for libavcodec/ismd_ffmpeg_audio_util.o, libavcodec/libx264.o, ffmpeg.o
#-----http://stackoverflow.com/questions/11561261/cc1-warnings-being-treated-as-errors
#-----http://stackoverflow.com/questions/13986301/is-gcc-doing-implicit-function-declarations-incorrectly-in-c99-mode
#-----how to workaround an error using make V=1 (re-issue gcc command, removing -Werror=implicit-function-declaration from command line)
#-----http://trac.ffmpeg.org/ticket/1794
#-----ffmpeg_g and ffprobe_g libavcodec/libavcodec.so: undefined reference to `json_object_array_length' used by (libavcodec/syno_trans_loading.c)
#-----add -ljson-c to the linker parameters




#-----Intel Core-i3 CPUs are 64bit and SSSE3 and seem to have their DSM built using x86_64
#-----libx264 requires yasm 1.20
sudo apt-get install yasm
wget "${DL_PATH}/Intel%20x86%20Linux%203.2.40%20%28Pineview%29/x64-gcc473_glibc217_x86_64-GPL.txz"
tar xvJf x64-gcc473_glibc217_x86_64-GPL.txz
export CROSS_PREFIX=x86_64-pc-linux-gnu
export TARGET=x86_64-pc-linux-gnu
export TOOLCHAIN=/usr/local/${CROSS_PREFIX}
#-----We don't really care how lame is built since ffmpeg will use the version in DSM.
#-----The DSM version is built without asm optimizations but these only make a 5% difference, and have been known to introduce instability
export LAME_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static --disable-decoder"
export X264_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --enable-shared --enable-pic --enable-strip"
#-----FFmpeg:
#-----Intel CPU-specific options (based on inspecting 'configure' script https://github.com/FFmpeg/FFmpeg/blob/master/configure)
#-----pkg-config needs to be defined because with cross-prefix it assumes ${CROSS_PREFIX}-pkg-config which doesn't exist, and then librtmp won't be detected
export FF_CONFIG="./configure --arch=x86 --enable-cross-compile --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --target-os=linux --prefix=${TOOLCHAIN} --enable-shared --disable-static --enable-pic --disable-ffplay --disable-ffserver --disable-debug --enable-pthreads --enable-libmp3lame --enable-librtmp --enable-libass --enable-libspeex --enable-gpl --enable-libx264 --enable-gnutls --pkg-config=pkg-config --extra-version=compiled_by_patters_for_Serviio"





#----------------------------------------------------
#-----script continues
sudo mv `echo $TOOLCHAIN | sed -r "s%^.*/(.*$)%\1%"` /usr/local
#-----some of the toolchains have bad permissions
sudo chmod -R 0755 ${TOOLCHAIN}
export PATH=${TOOLCHAIN}/bin:$PATH
export AR=${TOOLCHAIN}/bin/${CROSS_PREFIX}-ar
export AS=${TOOLCHAIN}/bin/${CROSS_PREFIX}-as
export CC=${TOOLCHAIN}/bin/${CROSS_PREFIX}-gcc
export CXX=${TOOLCHAIN}/bin/${CROSS_PREFIX}-g++
export LD=${TOOLCHAIN}/bin/${CROSS_PREFIX}-ld
export LDSHARED="${TOOLCHAIN}/bin/${CROSS_PREFIX}-gcc -shared "
export RANLIB=${TOOLCHAIN}/bin/${CROSS_PREFIX}-ranlib
export CFLAGS="-I${TOOLCHAIN}/include -O3 ${MARCH}"
export LDFLAGS="-L${TOOLCHAIN}/lib"
export PKG_CONFIG_PATH="${TOOLCHAIN}/lib/pkgconfig"


#-----fetch Synology's DSM 5565 sources for certain libraries we want to link against
wget https://dl.dropboxusercontent.com/u/1188556/DSM5565-src.tar.xz
tar xvJf DSM5565-src.tar.xz

#-----libz shared lib (toolchain only has static lib)
cd zlib-1.x
./configure --prefix=${TOOLCHAIN}
#-----owing to a bug in the configure script, libz cross compiles without a SONAME (check it with objdump -x)
#-----http://forums.gentoo.org/viewtopic-p-7156392.html
sed -i "s/\(^LDSHARED=.*$\)/\1 -Wl,-soname,libz.so.1,--version-script,zlib.map/" Makefile
make
make install
cd ..

#-----LAME shared lib
cd lame-398
$LAME_CONFIG
make
make install
cd ..

#-----expat shared lib
cd expat-2.x
./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static
make
make install
cd ..

#-----freetype shared lib
cd freetype-2.x
#-----disable external zlib library since it appears Synology compiled DSM-included libfreetype binary this way
#-----failure to do this results in a hang during fc-cache generation - this took a significant effort to determine
./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --with-zlib=no --enable-shared --disable-static
make
make install
cd ..

#-----shine shared lib for ARMv5 only (no FPU)
[ "${TOOLCHAIN}" == "/usr/local/arm-none-linux-gnueabi" ] && cd toots-shine-*
[ "${TOOLCHAIN}" == "/usr/local/arm-none-linux-gnueabi" ] && ./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static
[ "${TOOLCHAIN}" == "/usr/local/arm-none-linux-gnueabi" ] && make
[ "${TOOLCHAIN}" == "/usr/local/arm-none-linux-gnueabi" ] && make install
[ "${TOOLCHAIN}" == "/usr/local/arm-none-linux-gnueabi" ] && cd ..

#-----misc shared libs for Intel Evansport FFmpeg build only
#-----use libx264 version from Synology sources since the Evansport ffmpeg may have specific dependencies on this version
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && cd x264
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && $X264_CONFIG
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && make
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && make install
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && cd ..
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && cd libxml2-2.x
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && ./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static --without-python
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && make
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && make install
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && cd ..
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && cd json-c-0.x
#-----undefined reference to `rpl_malloc' when linking ffmpeg
#-----http://rickfoosusa.blogspot.co.uk/2011/11/howto-fix-undefined-reference-to.html 
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && ac_cv_func_malloc_0_nonnull=yes ac_cv_func_realloc_0_nonnull=yes ./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu  --enable-shared --disable-static
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && make
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && make install
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && cd ..

#-----fribidi shared lib
wget http://fribidi.org/download/fribidi-0.19.6.tar.bz2
tar xvjf fribidi-0.19.6.tar.bz2
cd fribidi-0.19.6
#-----patch fribidi source since it won't compile - some sort of page size function is no longer available
#-----error on Intel: fribidi-run.c:70: error: 'PAGE_SIZE' undeclared (first use in this function)
#-----http://armbedded.eu/node/56
#-----http://lists.debian.org/debian-glibc/2006/10/msg00169.html
#-----http://my.safaribooksonline.com/book/operating-systems-and-server-administration/linux/0596009585/advanced-file-i-o/mapping_files_into_memory
[ "${CROSS_PREFIX}" == "i686-pc-linux-gnu" ] && sed -i "s|include <asm/page.h>|include <unistd.h>\n#   define PAGE_SIZE sysconf(_SC_PAGESIZE)|" lib/common.h
./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static
make
make install
cd ..

#-----fontconfig shared lib
wget http://www.freedesktop.org/software/fontconfig/release/fontconfig-2.11.1.tar.gz
tar xvzf fontconfig-2.11.1.tar.gz
cd fontconfig-2.11.1
LDFLAGS=-Wl,-L${TOOLCHAIN}/lib,-rpath,\'\$\$ORIGIN/../lib:\$\$ORIGIN\' ./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static
#-----correct some non-standard library linking behaviour
sed -i "s/^hardcode_into_libs=yes/hardcode_into_libs=no/" libtool
make
make install
cd ..

#-----libass shared lib
wget https://github.com/libass/libass/releases/download/0.12.1/libass-0.12.1.tar.xz
tar xvJf libass-0.12.1.tar.xz
cd libass-0.12.1
LDFLAGS=-Wl,-L${TOOLCHAIN}/lib,-rpath,\'\$\$ORIGIN\' ./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static
#-----correct some non-standard library linking behaviour
sed -i "s/^hardcode_into_libs=yes/hardcode_into_libs=no/" libtool
make
make install
cd ..
#-----Although libass would link correctly to older FFmpeg versions, this mod is now necessary:
#-----http://ffmpeg.org/pipermail/ffmpeg-user/2012-November/010906.html
#-----no longer needed, note here in case of regression in future versions 
#sed -i -r "s/(^Libs: .*$)/\1 -lfontconfig -lfribidi -lfreetype -lexpat/" $TOOLCHAIN/lib/pkgconfig/libass.pc

#-----libx264 shared lib
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || wget ftp://ftp.videolan.org/pub/x264/snapshots/last_x264.tar.bz2
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || tar xvjf last_x264.tar.bz2
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || cd x264-snapshot-*
#-----NEON ASM needs to be built by GCC assembler not AS
[ "${TOOLCHAIN}" == "/usr/local/arm-cortexa9-linux-gnueabi" ] && export AS=${TOOLCHAIN}/bin/${CROSS_PREFIX}-gcc
#-----intel ASM needs to be built by yasm assembler
[ "${TOOLCHAIN}" == "/usr/local/i686-pc-linux-gnu" ] && export AS=yasm
[ "${TOOLCHAIN}" == "/usr/local/x86_64-pc-linux-gnu" ] && export AS=yasm
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || $X264_CONFIG
#-----back out assembler changes
[ "${TOOLCHAIN}" == "/usr/local/arm-cortexa9-linux-gnueabi" ] && export AS=${TOOLCHAIN}/bin/${CROSS_PREFIX}-as
[ "${TOOLCHAIN}" == "/usr/local/i686-pc-linux-gnu" ] && export AS=${TOOLCHAIN}/bin/${CROSS_PREFIX}-as
[ "${TOOLCHAIN}" == "/usr/local/x86_64-pc-linux-gnu" ] && export AS=${TOOLCHAIN}/bin/${CROSS_PREFIX}-as
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || make
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || make install
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || cd ..

#-----GMP shared lib
wget https://gmplib.org/download/gmp/gmp-6.0.0a.tar.xz
tar -xJf gmp-6.0.0a.tar.xz
cd gmp-6.0.0
#-----disable ARM Thumb - GMP doesn't compile in Thumb mode even using this patch
#-----https://gmplib.org/list-archives/gmp-discuss/2014-March/005537.html
export MARCH=`echo $MARCH | sed -e "s/ -mthumb//"`
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || export CFLAGS="-I${TOOLCHAIN}/include -O3 ${MARCH}"
[ "${TOOLCHAIN}" == "/usr/local/powerpc-none-linux-gnuspe" ] && mv ${TOOLCHAIN}/bin/flex ${TOOLCHAIN}/bin/flex.old
./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static
make
make install
#-----re-enable thumb-2 mode where applicable
[ "${TOOLCHAIN}" == "/usr/local/arm-cortexa9-linux-gnueabi" ] && export MARCH="${MARCH} -mthumb" 
[ "${TOOLCHAIN}" == "/usr/local/arm-marvell-linux-gnueabi" ] && export MARCH="${MARCH} -mthumb"
[ "${TOOLCHAIN}" == "/usr/local/armv7-marvell-linux-gnueabi-hard" ] && export MARCH="${MARCH} -mthumb"
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || export CFLAGS="-I${TOOLCHAIN}/include -O3 ${MARCH}" 
cd ..

#-----nettle shared lib
#-----version compatibility issues with gnutls: https://crux.nu/bugs/?do=details&task_id=1023
wget https://ftp.gnu.org/gnu/nettle/nettle-2.7.1.tar.gz
tar xvzf nettle-2.7.1.tar.gz
cd nettle-2.7.1
LDFLAGS=-Wl,-L${TOOLCHAIN}/lib,-rpath,\'\$\$ORIGIN\' ./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static --disable-openssl
make
make install
#-----this will fail to complete but it's not important: *** No rule to make target `../libnettle.a', needed by `sexp-conv'. Stop.
cd ..

#-----gnutls shared lib
wget ftp://ftp.gnutls.org/gcrypt/gnutls/v3.3/gnutls-3.3.14.tar.xz
tar -xJf gnutls-3.3.14.tar.xz 
cd gnutls-3.3.14
#-----use DSM's existing root CA certs bundle
LDFLAGS=-Wl,-L${TOOLCHAIN}/lib,-rpath,\'\$\$ORIGIN\' ./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --with-default-trust-store-file=/etc/ssl/certs/ca-certificates.crt --enable-threads=posix --disable-doc --enable-shared --disable-static
#-----correct some non-standard library linking behaviour
sed -i "s/^hardcode_into_libs=yes/hardcode_into_libs=no/" libtool
make
make install
sed -i -r "s/(^Libs: .*$)/\1 -lnettle -lhogweed -lgmp/" $TOOLCHAIN/lib/pkgconfig/gnutls.pc
cd ..

#-----librtmp shared lib
git clone git://git.ffmpeg.org/rtmpdump
cd rtmpdump
make CROSS_COMPILE=${TOOLCHAIN}/bin/${CROSS_PREFIX}- SYS=posix prefix=${TOOLCHAIN} CRYPTO=GNUTLS INC=-I${TOOLCHAIN}/include XLDFLAGS=-Wl,-L${TOOLCHAIN}/lib,-rpath,\'\$\$ORIGIN\'
#------librtmp.pc will have the wrong lib dependencies defined unless GNUTLS is specified again here
make install prefix=${TOOLCHAIN} CRYPTO=GNUTLS
cd ..

#-----libspeex shared lib
wget http://downloads.xiph.org/releases/speex/speex-1.2rc2.tar.gz
tar xvzf speex-1.2rc2.tar.gz
cd speex-1.2rc2
./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static
make
make install
cd ..

#-----FFmpeg (Evansport uses a separate Synology-modified source bundle)
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || wget https://www.ffmpeg.org/releases/ffmpeg-2.7.1.tar.gz
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || tar xvzf ffmpeg-2.7.1.tar.gz
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || cd ffmpeg-2.7.1
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && wget https://dl.dropboxusercontent.com/u/1188556/DSM5565-ffmpeg-2.0.x-src.tar.xz
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && tar xvJf DSM5565-ffmpeg-2.0.x-src.tar.xz
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && cd ffmpeg-2.0.x

#-----Apply DTS audio remux fix for hardware players (incorrect stream ID was set in older versions of FFmpeg)
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && wget http://dl.dropboxusercontent.com/u/1188556/ffmpeg-ticket1398.patch
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && patch --verbose -p1 < ffmpeg-ticket1398.patch

#-----PowerPC-specific fix originally provided by Synology Support in Oct 2012, adapted after code re-org by ffmpeg
[ "${CROSS_PREFIX}" == "powerpc-none-linux-gnuspe" ] && wget http://dl.dropboxusercontent.com/u/1188556/ffmpeg-syno-ppc.patch
[ "${CROSS_PREFIX}" == "powerpc-none-linux-gnuspe" ] && patch --verbose -p1 < ffmpeg-syno-ppc.patch

#-----Evansport SMD driver scheduler uses inline asm which breaks compilation without -fasm
#-----http://stackoverflow.com/questions/18574943/gcc-inline-assembler-implicit-function-declaration-on-powerpc-arch
#-----http://ffmpeg.org/pipermail/ffmpeg-devel/2008-October/056533.html
#-----http://www.tldp.org/HOWTO/Assembly-HOWTO/gcc.html
#-----we also need to add the intelce-utlities locations of the SMD libraries
#-----libx264 will fail to compile with this added to include path, so only add it just before compiling ffmpeg
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] \
  && export CFLAGS="${CFLAGS} -fasm -I${TOOLCHAIN}/include/json-c -I${TOOLCHAIN}/include/intelce-utilities -I${TOOLCHAIN}/include/intelce-utilities/linux_user"

#-----Evansport SMD functionality is disabled by default
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && sed -i "1i#define SYNO_ENABLE_SMD" synoconfig.h
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && sed -i "1i#define SYNO_EVANSPORT" synoconfig.h

#-----set library linker to use relative library search path (../lib and .)
#-----tricky shell escaping of $ORIGIN is required http://itee.uq.edu.au/~daniel/using_origin/
#-----http://stackoverflow.com/questions/6562403/i-dont-understand-wl-rpath-wl
#-----however although FFmpeg gets a correct rpath, the downstream libraries get a value of "RIGIN/../lib:RIGIN"
#-----owing to some additional variable substitution happening - easier to build with XORIGIN and use chrpath later
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] \
  || LDFLAGS=-Wl,-L${TOOLCHAIN}/lib,-rpath,XORIGIN/../lib:XORIGIN,-rpath-link,${TOOLCHAIN}/lib ${FF_CONFIG} \
  && LDFLAGS=-Wl,-L${TOOLCHAIN}/lib,-L${TOOLCHAIN}/lib/intelce-utilities,-rpath,XORIGIN/../lib:XORIGIN,-rpath-link,${TOOLCHAIN}/lib,-rpath-link,${TOOLCHAIN}/lib/intelce-utilities ${FF_CONFIG}

#-----external libs (librtmp, libass) don't seem to link to ffmpeg (check ffmpeg binary with objdump -x)
#-----this is in fact normal because LDFLAGS as defined in config.mak contains '--as-needed'
#-----https://wiki.gentoo.org/wiki/Project:Quality_Assurance/As-needed
#-----e.g. FFmpeg does not contain any symbols from librtmp, but libavformat does
#-----use ldd on the target system and the full dependency chain will be shown
make
make install

#-----remove intelce-utilities from include path
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && export CFLAGS="-I${TOOLCHAIN}/include -O3 ${MARCH}"

mkdir native-${CROSS_PREFIX}
cd native-${CROSS_PREFIX}

#-----evansport FFmpeg 2.0.2
#-----fix up rpath settings
sudo chrpath -r '$ORIGIN/../lib:$ORIGIN' ${TOOLCHAIN}/bin/ffmpeg
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavcodec.so.55
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavdevice.so.55
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavfilter.so.3
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavformat.so.55
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavutil.so.52
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libpostproc.so.52
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libswresample.so.0
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libswscale.so.2
cp ${TOOLCHAIN}/lib/libavcodec.so.55 .
cp ${TOOLCHAIN}/lib/libavdevice.so.55 .
cp ${TOOLCHAIN}/lib/libavfilter.so.3 .
cp ${TOOLCHAIN}/lib/libavformat.so.55 .
cp ${TOOLCHAIN}/lib/libavutil.so.52 .
cp ${TOOLCHAIN}/lib/libpostproc.so.52 .
cp ${TOOLCHAIN}/lib/libswresample.so.0 .
cp ${TOOLCHAIN}/lib/libswscale.so.2 .
cp ${TOOLCHAIN}/lib/libx264.so.119 .

#-----FFmpeg 2.7.1
#-----fix up rpath settings
sudo chrpath -r '$ORIGIN/../lib:$ORIGIN' ${TOOLCHAIN}/bin/ffmpeg
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavcodec.so.56
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavdevice.so.56
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavfilter.so.5
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavformat.so.56
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavutil.so.54
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libpostproc.so.53
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libswresample.so.1
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libswscale.so.3
cp ${TOOLCHAIN}/lib/libavcodec.so.56 .
cp ${TOOLCHAIN}/lib/libavdevice.so.56 .
cp ${TOOLCHAIN}/lib/libavfilter.so.5 .
cp ${TOOLCHAIN}/lib/libavformat.so.56 .
cp ${TOOLCHAIN}/lib/libavutil.so.54 .
cp ${TOOLCHAIN}/lib/libpostproc.so.53 .
cp ${TOOLCHAIN}/lib/libswresample.so.1 .
cp ${TOOLCHAIN}/lib/libswscale.so.3 .
cp ${TOOLCHAIN}/lib/libx264.so.146 .

cp ${TOOLCHAIN}/bin/ffmpeg .
cp ${TOOLCHAIN}/bin/fc-cache .
cp ${TOOLCHAIN}/lib/libass.so.5 .
cp ${TOOLCHAIN}/lib/libfontconfig.so.1 .
cp ${TOOLCHAIN}/lib/libfribidi.so.0 .
cp ${TOOLCHAIN}/lib/libnettle.so.4 .
cp ${TOOLCHAIN}/lib/libhogweed.so.2 .
cp ${TOOLCHAIN}/lib/libgnutls.so.28 .
cp ${TOOLCHAIN}/lib/librtmp.so.1 .
cp ${TOOLCHAIN}/lib/libspeex.so.1 .
[ ${TOOLCHAIN} == "/usr/local/arm-none-linux-gnueabi" ] && cp ${TOOLCHAIN}/lib/libshine.so.3 .
#cp ${TOOLCHAIN}/lib/libfdk-aac.so.1 .
sudo chmod +x *
sudo chown root:root *
XZ_OPT=-9 tar -cvJf ffmpeg-${CROSS_PREFIX}.tar.xz *
 

Here’s how the library dependencies look. There are no links to any libraries in /opt, and DSM-bundled libraries in /lib are linked to where possible. All the other new libraries are kept within the Serviio lib folder (../lib relative to the ffmpeg binary).

DS111> ldd /var/packages/Serviio/target/bin/ffmpeg
	libavdevice.so.56 => /volume1/@appstore/Serviio/bin/../lib/libavdevice.so.56 (0x40031000)
	libavfilter.so.5 => /volume1/@appstore/Serviio/bin/../lib/libavfilter.so.5 (0x4004f000)
	libavformat.so.56 => /volume1/@appstore/Serviio/bin/../lib/libavformat.so.56 (0x40174000)
	libavcodec.so.56 => /volume1/@appstore/Serviio/bin/../lib/libavcodec.so.56 (0x40321000)
	libpostproc.so.53 => /volume1/@appstore/Serviio/bin/../lib/libpostproc.so.53 (0x4138d000)
	libswresample.so.1 => /volume1/@appstore/Serviio/bin/../lib/libswresample.so.1 (0x413ad000)
	libswscale.so.3 => /volume1/@appstore/Serviio/bin/../lib/libswscale.so.3 (0x413d1000)
	libavutil.so.54 => /volume1/@appstore/Serviio/bin/../lib/libavutil.so.54 (0x41449000)
	libm.so.6 => /lib/libm.so.6 (0x414c2000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x4156b000)
	libpthread.so.0 => /lib/libpthread.so.0 (0x41587000)
	libc.so.6 => /lib/libc.so.6 (0x415b0000)
	libass.so.5 => /volume1/@appstore/Serviio/bin/../lib/libass.so.5 (0x416f3000)
	librtmp.so.1 => /volume1/@appstore/Serviio/bin/../lib/librtmp.so.1 (0x41726000)
	libz.so.1 => /lib/libz.so.1 (0x4174e000)
	libgnutls.so.28 => /volume1/@appstore/Serviio/bin/../lib/libgnutls.so.28 (0x41772000)
	libx264.so.146 => /volume1/@appstore/Serviio/bin/../lib/libx264.so.146 (0x4187a000)
	libspeex.so.1 => /volume1/@appstore/Serviio/bin/../lib/libspeex.so.1 (0x419ea000)
	libshine.so.3 => /volume1/@appstore/Serviio/bin/../lib/libshine.so.3 (0x41a14000)
	librt.so.1 => /lib/librt.so.1 (0x41a2e000)
	/lib/ld-linux.so.3 (0x40000000)
	libfribidi.so.0 => /volume1/@appstore/Serviio/bin/../lib/libfribidi.so.0 (0x41a45000)
	libfontconfig.so.1 => /volume1/@appstore/Serviio/bin/../lib/libfontconfig.so.1 (0x41a6c000)
	libexpat.so.1 => /lib/libexpat.so.1 (0x41ab9000)
	libfreetype.so.6 => /lib/libfreetype.so.6 (0x41adb000)
	libhogweed.so.2 => /volume1/@appstore/Serviio/bin/../lib/libhogweed.so.2 (0x41b7e000)
	libnettle.so.4 => /volume1/@appstore/Serviio/bin/../lib/libnettle.so.4 (0x41bb5000)
	libgmp.so.10 => /lib/libgmp.so.10 (0x41bfc000)
	libbz2.so.1.0 => /lib/libbz2.so.1.0 (0x41c6b000)
	libpng16.so.16 => /lib/libpng16.so.16 (0x41c7c000)
DS111>
 

Here’s how the even more complex Evansport build with hardware transcoding support looks:

DS214Play> ldd /var/packages/Serviio/target/bin/ffmpeg
	linux-gate.so.1 =>  (0xffffe000)
	libavdevice.so.55 => /volume1/@appstore/Serviio/bin/../lib/libavdevice.so.55 (0xb775c000)
	libavfilter.so.3 => /volume1/@appstore/Serviio/bin/../lib/libavfilter.so.3 (0xb767d000)
	libavformat.so.55 => /volume1/@appstore/Serviio/bin/../lib/libavformat.so.55 (0xb74fd000)
	libavcodec.so.55 => /volume1/@appstore/Serviio/bin/../lib/libavcodec.so.55 (0xb677b000)
	libpostproc.so.52 => /volume1/@appstore/Serviio/bin/../lib/libpostproc.so.52 (0xb674b000)
	libswresample.so.0 => /volume1/@appstore/Serviio/bin/../lib/libswresample.so.0 (0xb6733000)
	libswscale.so.2 => /volume1/@appstore/Serviio/bin/../lib/libswscale.so.2 (0xb66c9000)
	libavutil.so.52 => /volume1/@appstore/Serviio/bin/../lib/libavutil.so.52 (0xb6687000)
	libffmpeg_plugin.so => /lib/libffmpeg_plugin.so (0xb6672000)
	libm.so.6 => /lib/libm.so.6 (0xb6648000)
	libjson-c.so.2 => /lib/libjson-c.so.2 (0xb663d000)
	libpthread.so.0 => /lib/libpthread.so.0 (0xb6622000)
	libc.so.6 => /lib/libc.so.6 (0xb64aa000)
	libismd_core.so => /lib/libismd_core.so (0xb649d000)
	libismd_viddec.so => /lib/libismd_viddec.so (0xb6494000)
	librt.so.1 => /lib/librt.so.1 (0xb648b000)
	libass.so.5 => /volume1/@appstore/Serviio/bin/../lib/libass.so.5 (0xb645f000)
	librtmp.so.1 => /volume1/@appstore/Serviio/bin/../lib/librtmp.so.1 (0xb6443000)
	libz.so.1 => /lib/libz.so.1 (0xb642d000)
	libgnutls.so.28 => /volume1/@appstore/Serviio/bin/../lib/libgnutls.so.28 (0xb6306000)
	libx264.so.119 => /volume1/@appstore/Serviio/bin/../lib/libx264.so.119 (0xb61b3000)
	libspeex.so.1 => /volume1/@appstore/Serviio/bin/../lib/libspeex.so.1 (0xb6193000)
	libmp3lame.so.0 => /lib/libmp3lame.so.0 (0xb6121000)
	libdl.so.2 => /lib/libdl.so.2 (0xb611c000)
	libxml2.so.2 => /lib/libxml2.so.2 (0xb5fc5000)
	libismd_demux.so => /lib/libismd_demux.so (0xb5fba000)
	libismd_vidrend.so => /lib/libismd_vidrend.so (0xb5fb2000)
	libismd_clock.so => /lib/libismd_clock.so (0xb5fb0000)
	libismd_audio.so => /lib/libismd_audio.so (0xb5fa1000)
	libismd_videnc.so => /lib/libismd_videnc.so (0xb5f9d000)
	libismd_vidpproc.so => /lib/libismd_vidpproc.so (0xb5f96000)
	libismdmessage.so => /lib/libismdmessage.so (0xb5f93000)
	libsven.so => /lib/libsven.so (0xb5e53000)
	libpal.so => /lib/libpal.so (0xb5e51000)
	libosal.so => /lib/libosal.so (0xb5e49000)
	libplatform_config.so => /lib/libplatform_config.so (0xb5e46000)
	libsystem_utils.so => /lib/libsystem_utils.so (0xb5e43000)
	libismd_clock_recovery.so => /lib/libismd_clock_recovery.so (0xb5e40000)
	/lib/ld-linux.so.2 (0xb7768000)
	libfribidi.so.0 => /volume1/@appstore/Serviio/bin/../lib/libfribidi.so.0 (0xb5e27000)
	libfontconfig.so.1 => /volume1/@appstore/Serviio/bin/../lib/libfontconfig.so.1 (0xb5de4000)
	libexpat.so.1 => /lib/libexpat.so.1 (0xb5dbc000)
	libfreetype.so.6 => /lib/libfreetype.so.6 (0xb5d08000)
	libhogweed.so.2 => /volume1/@appstore/Serviio/bin/../lib/libhogweed.so.2 (0xb5cdb000)
	libnettle.so.4 => /volume1/@appstore/Serviio/bin/../lib/libnettle.so.4 (0xb5ca3000)
	libgmp.so.10 => /lib/libgmp.so.10 (0xb5c33000)
	liblzma.so.5 => /lib/liblzma.so.5 (0xb5c0d000)
	libbz2.so.1.0 => /lib/libbz2.so.1.0 (0xb5bfc000)
	libpng16.so.16 => /lib/libpng16.so.16 (0xb5bc4000)
DS214Play> 

30 thoughts on “Cross-compiling FFmpeg for Serviio with shared libraries on Synology NAS (for 7 CPU architectures)

  1. michael

    keep up the great work on serviio, i hope you get something going for the PPC cpu for synology soon. are synology assiting you? i hope they are!

    Reply
  2. Steven

    Hi, I’d like to setup some kind of automatic (via cron job) reencoding of dreambox .ts-files (dvb-c) for later watching on the iPad. On OSX I use the following command “ffmpeg -i input.ts -vcodec libx264 -vprofile high -preset faster -b:v 2000k -vf scale=-1:720 -maxrate 10M -bufsize 10M -threads 0 -acodec libvo_aacenc -ab 196k output.mp4” which gives good results.

    I have an DS412+ with Atom. I know it will take maybe days for one movie to reencode, but I would not care, if it would run in background.

    Do you think that is possible on DS412+? Unfortunately I don’t have the skills for x-compiling something and setting the right compiler flags, etc. – I tried, but I now know my limits :)

    Could you upload a compiled current version of ffmpeg with all the codecs (especially X264) the osx version of the ffmpeg.org site has?

    This would be GREAT !!! :)

    Reply
  3. EJ

    Great, this worked for me. I built under xubuntu 12.10 and built for the DS211j. I can successfully transcode my FLAC collection to mp3 to take on the go with my android.

    Reply
  4. MoBO

    Hello, I don’t have any Linux experience but I need tom compile ffmpeg to support video streaming on my Intel Synology NAS.
    I followed this note under a Ubuntu 12 VM (using Oracle VM).
    The process seems to work correctly but I don’t have any ffmpeg file created.

    Is there something missing to compile it ?

    I’m sorry, this might seems stupid for Linux geek… ;o(

    Reply
    1. MoBO

      Everything seem just fine ’til the end…
      (I run it with sudo then as root)…

      root@ubuntu:~/Downloads/DSM-source/ffmpeg# export CFLAGS=”-I${TOOLCHAIN}/include”
      root@ubuntu:~/Downloads/DSM-source/ffmpeg# make
      Makefile:2: config.mak: No such file or directory
      Makefile:47: /common.mak: No such file or directory
      Makefile:89: /libavutil/Makefile: No such file or directory
      Makefile:89: /library.mak: No such file or directory
      Makefile:169: /doc/Makefile: No such file or directory
      Makefile:170: /tests/Makefile: No such file or directory
      make: *** No rule to make target `/tests/Makefile’. Stop.
      root@ubuntu:~/Downloads/DSM-source/ffmpeg# make install
      Makefile:2: config.mak: No such file or directory
      Makefile:47: /common.mak: No such file or directory
      Makefile:89: /libavutil/Makefile: No such file or directory
      Makefile:89: /library.mak: No such file or directory
      Makefile:169: /doc/Makefile: No such file or directory
      Makefile:170: /tests/Makefile: No such file or directory
      make: *** No rule to make target `/tests/Makefile’. Stop.
      root@ubuntu:~/Downloads/DSM-source/ffmpeg#

      Any way to fix that or find how to ?

      Thanks in advance for your help.

      Reply
  5. MoBO

    I tried many times, many different ways but I’ve been unable to compile an INTEL version.
    I created a VM (VirtualBOX) with Ubuntu 12.10, 10.04 (64bits AND 32bits) and never been able to pass the librtmp & ffmpeg compilation.

    I searched on Internet and already spend to much hours ;o(
    If anyone could share an “how to”, this will be just fantastic !
    This way anyone could compile…

    If not, do anybody will be nice enough to share an INTEL version ?
    PS It will be used for Subsonic and video support ;o)

    It’s Christmas after all !!!

    Reply
  6. Pingback: Serviio 1.1 package for Synology NAS « PC LOAD LETTER

  7. Hanz

    What I like about all this Serviio and Synology business is WHAT DOES IT ALL MEAN????

    I have a Synology NAS, I have a Samsung Smart TV – I want the F**ker to play Xvid, .MKV – I heard Serviio would help me achieve this. But I’ll be f**ked if I can follow your instructions / find the links to where the files reside.

    I admit I might be a bit dyslexic and have the attention of a gnat, but two hours in I haven’t a f**king clue why I can’t get things working. I need you to provide pictures, step by step instruction, links to files, instructions on where to save them, instruction of which ones to download first and install first, if I need to extract them, where to extract them, how to get the Synology NAS to act upon the information. No abriviation, no block paragraph’s. Even a youtube video would be helpful.

    Or if you think I need to direct my frustrations at Synology please let me know.

    Reply
    1. patters Post author

      I’m afraid I don’t have time to record YouTube videos for you. The intended audience for my posts is a reasonably technical one. If you are only interested in running Serviio, this particular post is not for you – it’s intended to show other technically-minded people how I compiled FFmpeg so as to help other aspiring Linux hobbyists. For running Serviio on Synology you want this post:

      Serviio 2.0 package for Synology NAS

      Reply
  8. Piotr

    Hello Patters,
    there is a missed characted ‘\’ in Native compile for ARM systems line 60. correct line is:
    sed -i “s|include |include \n# define PAGE_SIZE sysconf(_SC_PAGESIZE)|” lib/common.h

    Reply
    1. patters Post author

      Thanks, post corrected. It’s entirely possible there are some more errors in there. When I last updated it I had an issue in the WordPress editor and had to revert to a draft, whereupon WordPress helpfully mangled the syntax of the whole thing by HTML encoding the entire post. It made a real mess, and the only way back was the run the post back through a free online HTML decoder – but I guess it wasn’t perfect.

      Reply
  9. shadock

    @patters: is it possible for you to add libx264 support ?

    (including on your serviio package since I do use it on my NAS) ?

    Reply
    1. shadock

      Juste a small note, I would like to use the following recommended transcode command for Apple (HFS) : “ffmpeg -ss %o -t %d -i %s -async 1 -b %bk -s %wx%h -ar 44100 -ac 2 -v 0 -f mpegts -vcodec libx264 -preset superfast -acodec libmp3lame -threads 0 -“

      Reply
    1. coolraoul

      Oups, sorry didn’t noticed at first sight that you were cross compiling

      Please ignore my comment

      Reply
    2. patters Post author

      I didn’t – all the stuff I have made has been by using the cross-compiling toolchain in a Linux VM on my MacBook.

      Reply
  10. Forgetful Orange (@ForgotMyOrange)

    FYI much appreciate this.
    I might be able to do without it, but I couldn’t get this sed command working under #—–fetch libass source

    dsm@/volume1/downloads/libass-0.10.1> sed -i “s|^sys_lib_search_path_spec=”/opt/lib/gcc/arm-none-linux-gnueabi/4.2.3 /opt/a
    rm-none-linux-gnueabi/lib /opt/lib /lib /usr/lib”|sys_lib_search_path_spec=”/lib /usr/lib /opt/lib/gcc/arm-none-linux-gnueabi/4.2.3
    /opt/arm-none-linux-gnueabi/lib /opt/lib”|” libtool
    sed: unmatched ‘|’

    Reply
  11. JoergGaBo

    Hi,
    thanks a lot for this one… I think it might be quite helpful even for other compiling projects. Currently I try to cross-compile ReadyMedia (aka miniDLNA) for the Synology DiskStation DS213+ under DS4.3. However I can’t seem to get it working right. I managed once to compile the minidlnad deamon, starting it on the diskstation returned in some dump.

    Might somebody be interested in helping out with the ReadyMedia compilation?

    thanks & cu
    jgb

    Reply
  12. rl

    Hi,

    great work here!
    I tried to natively compile on my DS213+ (qoriq), but I got stuck in ffmpeg. Please find config.log part here:
    —-
    BEGIN /tmp/ffconf.LahXDFlS.c
    1 int main(void){ return 0; }
    END /tmp/ffconf.LahXDFlS.c
    gcc -I/tmp/include -I/tmp/include -march=armv5te -c -o /tmp/ffconf.aoPWBhTS.o /tmp/ffconf.LahXDFlS.c
    cc1: error: invalid option `arch=armv5te’
    C compiler test failed.
    —-
    Any hints?

    rgds, rl

    Reply
  13. George

    What is the latest serviio version that can be installed on zyxel nsa310s. Could someone tell me…someone who tested?

    Reply

Leave a comment