Tag Archives: FFmpeg

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

This method will build FFmpeg 3.2.2 for Synology DSM 6.0 with the shared libraries linked with relative paths, required for Serviio DLNA media server, using a Ubuntu/Xubuntu Desktop 14.04 virtual machine. The same method probably works with many other Linux distributions. The target CPU architectures are ARMv5, ARMv7 hard float ABI, ARM hard float ABI with NEON, Intel i686, Intel i686 Evansport, Intel x86-64, 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, libbz2, liblzma, libpng16, librt, libgmp, libgnutls, libhogweed, libnettle, libfreetype, libfontconfig, 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.7.1 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. Synology took a very long time (over a year) to partly comply with the GNU Public License and release this source code, despite numerous support requests, forum posts, and reports to the GPL Violations team. Their first DSM 6.0 beta was released in October 2015, and the DSM 6.0 sources were only published in late November 2016, but these remain incomplete since the kernel sources are not included.

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="https://sourceforge.net/projects/dsgpl/files/DSM%206.0.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
wget "https://sourceforge.net/projects/dsgpl/files/toolkit/DSM6.0/ds.6281-6.0.dev.txz"
export DEV_DL="ds.6281-6.0.dev.txz"
export DEV_DL_ROOT="libc"
export CROSS_PREFIX=arm-marvell-linux-gnueabi
export TOOLCHAIN=/usr/local/${CROSS_PREFIX}
export TARGET=arm-marvell-linux-gnueabi
export MARCH="-march=armv5te -mtune=marvell-f -mtune=xscale"
#-----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 --disable-opencl"
#-----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-libvorbis --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-libvorbis --enable-gpl --enable-libx264 --enable-gnutls --enable-nonfree --enable-libfdk_aac --pkg-config=pkg-config --extra-version=compiled_by_patters_for_Serviio"
#-----these next two packages are needed to build libshine
sudo apt-get install automake
sudo apt-get install libtool
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
#-----since DSM 6.0 hard float ABI is used
wget "${DL_PATH}/Marvell%20Armada%20370%20Linux%203.2.40/armada370-gcc493_glibc220_hard-GPL.txz"
tar xvJf armada370-gcc493_glibc220_hard-GPL.txz
wget "https://sourceforge.net/projects/dsgpl/files/toolkit/DSM6.0/ds.armada370-6.0.dev.txz"
export DEV_DL="ds.armada370-6.0.dev.txz"
export DEV_DL_ROOT="sysroot"
export CROSS_PREFIX=arm-unknown-linux-gnueabi
export TARGET=arm-unknown-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"
#-----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 --disable-opencl"
#-----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-libvorbis --enable-gpl --enable-libx264 --enable-gnutls --pkg-config=pkg-config --extra-version=compiled_by_patters_for_Serviio"




#-----Marvell Armada 375, Armada 385, and Mindspeed Comcerto 2000 CPU are based on dual ARM Cortex-A9 cores with NEON vector unit
#-----http://www.marvell.com/embedded-processors/armada-300/assets/ARMADA_375_SoC-01_product_brief.pdf
#-----http://www.marvell.com/embedded-processors/armada-38x/assets/A38x-Functional-Spec-PU0A.pdf
#-----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
#-----Since DSM 6.0 Armada 375 finally has hard float ABI and therefore gains NEON support
wget "${DL_PATH}/Marvell%20Armada%20375%20Linux%203.2.40/armada375-gcc493_glibc220_hard-GPL.txz"
tar xvJf armada375-gcc493_glibc220_hard-GPL.txz
#-----Marvell gave all the ARMv7 toolchains the same name so rename to allow concurrent installations
mv arm-unknown-linux-gnueabi/ arm-cortexa9-linux-gnueabi/
wget "https://sourceforge.net/projects/dsgpl/files/toolkit/DSM6.0/ds.armada375-6.0.dev.txz"
export DEV_DL="ds.armada375-6.0.dev.txz"
export DEV_DL_ROOT="sysroot"
export CROSS_PREFIX=arm-unknown-linux-gnueabi
export TARGET=arm-unknown-linux-gnueabi
export TOOLCHAIN=/usr/local/arm-cortexa9-linux-gnueabi
#-----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"
#-----libx264:
export X264_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --enable-shared --enable-pic --enable-strip --disable-opencl"
#-----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-libvorbis --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-gcc493_glibc220_hard_qoriq-GPL.txz"
tar xvJf qoriq-gcc493_glibc220_hard_qoriq-GPL.txz
wget "https://sourceforge.net/projects/dsgpl/files/toolkit/DSM6.0/ds.qoriq-6.0.dev.txz"
export DEV_DL="ds.qoriq-6.0.dev.txz"
export DEV_DL_ROOT="sysroot"
export CROSS_PREFIX=powerpc-e500v2-linux-gnuspe
export TOOLCHAIN=/usr/local/${CROSS_PREFIX}
export TARGET=powerpc-e500v2-linux-gnuspe
export MARCH="-mcpu=8548 -mhard-float -mfloat-gprs=double"
#-----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 --disable-opencl"
#-----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-libvorbis --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
#-----libx264 requires yasm 1.20
sudo apt-get install yasm
wget "${DL_PATH}/Intel%20x86%20Linux%203.2.40%20%28Evansport%29/evansport-gcc493_glibc220_linaro_i686-GPL.txz"
tar xvJf evansport-gcc493_glibc220_linaro_i686-GPL.txz
#-----Both Intel i686 toolchains the same name so rename to allow concurrent installations
mv i686-pc-linux-gnu evansport-pc-linux-gnu
wget "https://sourceforge.net/projects/dsgpl/files/toolkit/DSM6.0/ds.evansport-6.0.dev.txz"
export DEV_DL="ds.evansport-6.0.dev.txz"
export DEV_DL_ROOT="sys-root"
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 X264_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${TARGET} --cross-prefix=${TOOLCHAIN}/bin/${CROSS_PREFIX}- --enable-shared --enable-pic --enable-strip --disable-opencl"
#-----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-libvorbis --enable-libx264 --enable-libh264_smd --enable-smd --enable-gpl --enable-gnutls --pkg-config=pkg-config --extra-version=SMD_enabled-compiled_by_patters_for_Serviio"
export FF_CONFIG_I686="./configure --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-libvorbis --enable-libx264 --enable-gpl --enable-gnutls --pkg-config=pkg-config --extra-version=compiled_by_patters_for_Serviio"
#-----http://trac.ffmpeg.org/ticket/1794
#-----first ffmpeg compilation error run "make V=1" then add " -lismd_core -lismd_viddec -ljson-c" to the command line
#-----second ffmpeg compilation error run "make V=1" then add " -ljson-c" to the command line




#-----With the exception of Evansport (i686), Intel CPUs used in Synology products are all 64bit and SSSE3 capable
#-----Since DSM 6.0 x86_64 toolchain is used
#-----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.10.77%20%28Pineview%29/x64-gcc493_glibc220_linaro_x86_64-GPL.txz"
tar xvJf x64-gcc493_glibc220_linaro_x86_64-GPL.txz
wget "https://sourceforge.net/projects/dsgpl/files/toolkit/DSM6.0/ds.cedarview-6.0.dev.txz"
export DEV_DL="ds.cedarview-6.0.dev.txz"
export DEV_DL_ROOT="sys-root"
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-libvorbis --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"


#-----set up all our dependent libraries from the Synology dev environment
mkdir ${CROSS_PREFIX}-dev
cd ${CROSS_PREFIX}-dev
tar xfJv ../${DEV_DL}

mkdir $TOOLCHAIN/lib/pkgconfig/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/expat.h $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/expat_external.h $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libexpat.* $TOOLCHAIN/lib/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/pkgconfig/expat.pc $TOOLCHAIN/lib/pkgconfig/
sed -i "s|^prefix=.*$|prefix=${TOOLCHAIN}|" $TOOLCHAIN/lib/pkgconfig/expat.pc

cp -R usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/fontconfig/ $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libfontconfig.* $TOOLCHAIN/lib/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/pkgconfig/fontconfig.pc $TOOLCHAIN/lib/pkgconfig/
sed -i "s|^prefix=.*$|prefix=${TOOLCHAIN}|" $TOOLCHAIN/lib/pkgconfig/fontconfig.pc

cp -R usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/freetype2/ $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libfreetype.* $TOOLCHAIN/lib/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/pkgconfig/freetype2.pc $TOOLCHAIN/lib/pkgconfig/
sed -i "s|^prefix=.*$|prefix=${TOOLCHAIN}|" $TOOLCHAIN/lib/pkgconfig/freetype2.pc
sed -i "s|^exec_prefix=.*$|exec_prefix=${TOOLCHAIN}|" $TOOLCHAIN/lib/pkgconfig/freetype2.pc
sed -i "s|^libdir=.*$|libdir=${TOOLCHAIN}/lib|" $TOOLCHAIN/lib/pkgconfig/freetype2.pc
sed -i "s|^includedir=.*$|includedir=${TOOLCHAIN}/include/freetype2|" $TOOLCHAIN/lib/pkgconfig/freetype2.pc

cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/gmp.h $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libgmp.* $TOOLCHAIN/lib/

cp -R usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/gnutls/ $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libgnutls.* $TOOLCHAIN/lib/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/pkgconfig/gnutls.pc $TOOLCHAIN/lib/pkgconfig/
sed -i "s|^prefix=.*$|prefix=${TOOLCHAIN}|" $TOOLCHAIN/lib/pkgconfig/gnutls.pc

cp -R usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/lame/ $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libmp3lame.* $TOOLCHAIN/lib/

cp -R usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/nettle/ $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libnettle.* $TOOLCHAIN/lib/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libhogweed.* $TOOLCHAIN/lib/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/pkgconfig/nettle.pc $TOOLCHAIN/lib/pkgconfig/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/pkgconfig/hogweed.pc $TOOLCHAIN/lib/pkgconfig/
sed -i "s|^prefix=.*$|prefix=${TOOLCHAIN}|" $TOOLCHAIN/lib/pkgconfig/nettle.pc
sed -i "s|^prefix=.*$|prefix=${TOOLCHAIN}|" $TOOLCHAIN/lib/pkgconfig/hogweed.pc

cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/png.h $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/pngconf.h $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/pnglibconf.h $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libpng.* $TOOLCHAIN/lib/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/pkgconfig/libpng.pc $TOOLCHAIN/lib/pkgconfig/
sed -i "s|^prefix=.*$|prefix=${TOOLCHAIN}|" $TOOLCHAIN/lib/pkgconfig/libpng.pc

cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/zlib.h $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/zconf.h $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libz.* $TOOLCHAIN/lib/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/pkgconfig/zlib.pc $TOOLCHAIN/lib/pkgconfig/
sed -i "s|^prefix=.*$|prefix=${TOOLCHAIN}|" $TOOLCHAIN/lib/pkgconfig/zlib.pc

cp -R usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/json-c/ $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libjson-c.* $TOOLCHAIN/lib/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/pkgconfig/json-c.pc $TOOLCHAIN/lib/pkgconfig/
sed -i "s|^prefix=.*$|prefix=${TOOLCHAIN}|" $TOOLCHAIN/lib/pkgconfig/json-c.pc

#-----libbz2 and libxml-2.0 are dependencies of fontconfig
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/bzlib.h $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libbz2.* $TOOLCHAIN/lib/

cp -R usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/libxml2/ $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libxml2.* $TOOLCHAIN/lib/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/pkgconfig/libxml-2.0.pc $TOOLCHAIN/lib/pkgconfig/
sed -i "s|^prefix=.*$|prefix=${TOOLCHAIN}|" $TOOLCHAIN/lib/pkgconfig/libxml-2.0.pc

#-----liblzma is a dependency of libass
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/lzma.h $TOOLCHAIN/include/
cp -R usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/lzma/ $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/liblzma.* $TOOLCHAIN/lib/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/pkgconfig/liblzma.pc $TOOLCHAIN/lib/pkgconfig/

#-----libpng16 is a dependency of freetype2
cp -R usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/libpng16/ $TOOLCHAIN/include/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/libpng16.* $TOOLCHAIN/lib/
cp usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/pkgconfig/libpng16.pc $TOOLCHAIN/lib/pkgconfig/

#-----End of syno devkit extraction
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 ..

#-----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
./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.13.4/libass-0.13.4.tar.xz
tar xvJf libass-0.13.4.tar.xz
cd libass-0.13.4
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
wget https://download.videolan.org/x264/snapshots/last_stable_x264.tar.bz2
tar xvjf last_stable_x264.tar.bz2
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/evansport-pc-linux-gnu" ] && export AS=yasm
[ "${TOOLCHAIN}" == "/usr/local/i686-pc-linux-gnu" ] && export AS=yasm
[ "${TOOLCHAIN}" == "/usr/local/x86_64-pc-linux-gnu" ] && export AS=yasm
$X264_CONFIG
#-----back out assembler changes
AS=${TOOLCHAIN}/bin/${CROSS_PREFIX}-as
make
make install
cd ..

#-----libx265 shared lib
#wget https://bitbucket.org/multicoreware/x265/downloads/x265_2.1.tar.gz
#tar xvzf x265_2.1.tar.gz
#cd x265_2.1

#-----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
sed -i "s/^hardcode_into_libs=yes/hardcode_into_libs=no/" libtool
make
make install
cd ..

#-----libogg shared lib
wget http://downloads.xiph.org/releases/ogg/libogg-1.3.2.tar.xz
tar xvJf libogg-1.3.2.tar.xz
cd libogg-1.3.2
./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static
sed -i "s/^hardcode_into_libs=yes/hardcode_into_libs=no/" libtool
make
make install
cd ..

#-----libvorbis shared lib
wget http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.5.tar.xz
tar xvJf libvorbis-1.3.5.tar.xz
cd libvorbis-1.3.5
./configure --prefix=${TOOLCHAIN} --host=${TARGET} --build=x86_64-linux-gnu --enable-shared --disable-static
sed -i "s/^hardcode_into_libs=yes/hardcode_into_libs=no/" libtool
make
make install
cd ..

#-----Evansport only - don't run these two lines until right before compiling FFmpeg since some of the includes will break other stuff
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && cp -R ${CROSS_PREFIX}-dev/usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/include/intelce-utilities $TOOLCHAIN/include
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && cp -R ${CROSS_PREFIX}-dev/usr/local/$TARGET/$TARGET/${DEV_DL_ROOT}/usr/lib/intelce-utilities $TOOLCHAIN/lib

#-----FFmpeg (Evansport uses a separate Synology-modified source bundle)
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || wget https://www.ffmpeg.org/releases/ffmpeg-3.2.2.tar.xz
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || tar xvJf ffmpeg-3.2.2.tar.xz
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] || cd ffmpeg-3.2.2
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && wget https://sourceforge.net/projects/dsgpl/files/Synology%20NAS%20GPL%20Source/8451branch/evansport-source/ffmpeg-2.7.x.txz
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && tar xvJf ffmpeg-2.7.x.txz
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && cd ffmpeg-2.7.x

#-----PowerPC-specific fix originally provided by Synology Support in Oct 2012, adapted after code re-org by ffmpeg
[ "${CROSS_PREFIX}" == "powerpc-e500v2-linux-gnuspe" ] && wget http://dl.dropboxusercontent.com/u/1188556/ffmpeg-syno-ppc.patch
[ "${CROSS_PREFIX}" == "powerpc-e500v2-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_EVANSPORT_SMD" synoconfig.h
#-----Evansport ffmpeg will by default skip DTS audio tracks for transcoding and will refuse to encode AC3
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && wget https://dl.dropboxusercontent.com/u/1188556/ffmpeg-2.7.1-syno-dts-skip.patch
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && patch --verbose -p1 < ffmpeg-2.7.1-syno-dts-skip.patch

#-----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}"
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && rm -rf ${TOOLCHAIN}/include/intelce-utilities
[ "${TOOLCHAIN}" == "/usr/local/evansport-pc-linux-gnu" ] && rm -rf ${TOOLCHAIN}/lib/intelce-utilities 

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

#-----evansport 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}/bin/ffmpeg .
cp ${TOOLCHAIN}/bin/fc-cache .
cp ${TOOLCHAIN}/lib/libass.so.5 .
cp ${TOOLCHAIN}/lib/libfribidi.so.0 .
cp ${TOOLCHAIN}/lib/libogg.so.0 .
cp ${TOOLCHAIN}/lib/librtmp.so.1 .
cp ${TOOLCHAIN}/lib/libspeex.so.1 .
cp ${TOOLCHAIN}/lib/libvorbis.so.0 .
cp ${TOOLCHAIN}/lib/libvorbisenc.so.2 .
cp ${TOOLCHAIN}/lib/libx264.so.148 .


#-----FFmpeg 3.2.2
#-----fix up rpath settings
sudo chrpath -r '$ORIGIN/../lib:$ORIGIN' ${TOOLCHAIN}/bin/ffmpeg
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavcodec.so.57
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavdevice.so.57
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavfilter.so.6
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavformat.so.57
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libavutil.so.55
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libpostproc.so.54
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libswresample.so.2
sudo chrpath -r '$ORIGIN' ${TOOLCHAIN}/lib/libswscale.so.4
cp ${TOOLCHAIN}/lib/libavcodec.so.57 .
cp ${TOOLCHAIN}/lib/libavdevice.so.57 .
cp ${TOOLCHAIN}/lib/libavfilter.so.6 .
cp ${TOOLCHAIN}/lib/libavformat.so.57 .
cp ${TOOLCHAIN}/lib/libavutil.so.55 .
cp ${TOOLCHAIN}/lib/libpostproc.so.54 .
cp ${TOOLCHAIN}/lib/libswresample.so.2 .
cp ${TOOLCHAIN}/lib/libswscale.so.4 .
cp ${TOOLCHAIN}/bin/ffmpeg .
cp ${TOOLCHAIN}/bin/fc-cache .
cp ${TOOLCHAIN}/lib/libass.so.5 .
cp ${TOOLCHAIN}/lib/libfribidi.so.0 .
cp ${TOOLCHAIN}/lib/libogg.so.0 .
cp ${TOOLCHAIN}/lib/librtmp.so.1 .
cp ${TOOLCHAIN}/lib/libspeex.so.1 .
cp ${TOOLCHAIN}/lib/libvorbis.so.0 .
cp ${TOOLCHAIN}/lib/libvorbisenc.so.2 .
cp ${TOOLCHAIN}/lib/libx264.so.148 .
[ ${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).

DS214> ldd /var/packages/Serviio/target/bin/ffmpeg
	linux-gate.so.1 (0xffffe000)
	libavdevice.so.57 => /volume1/@appstore/Serviio/bin/../lib/libavdevice.so.57 (0xb7708000)
	libavfilter.so.6 => /volume1/@appstore/Serviio/bin/../lib/libavfilter.so.6 (0xb74fd000)
	libavformat.so.57 => /volume1/@appstore/Serviio/bin/../lib/libavformat.so.57 (0xb72bd000)
	libavcodec.so.57 => /volume1/@appstore/Serviio/bin/../lib/libavcodec.so.57 (0xb5ee8000)
	libpostproc.so.54 => /volume1/@appstore/Serviio/bin/../lib/libpostproc.so.54 (0xb5ec1000)
	libswresample.so.2 => /volume1/@appstore/Serviio/bin/../lib/libswresample.so.2 (0xb5ea2000)
	libswscale.so.4 => /volume1/@appstore/Serviio/bin/../lib/libswscale.so.4 (0xb5e11000)
	libavutil.so.55 => /volume1/@appstore/Serviio/bin/../lib/libavutil.so.55 (0xb5d8b000)
	libm.so.6 => /lib/libm.so.6 (0xb5d42000)
	libpthread.so.0 => /lib/libpthread.so.0 (0xb5d25000)
	libc.so.6 => /lib/libc.so.6 (0xb5b77000)
	libass.so.5 => /volume1/@appstore/Serviio/bin/../lib/libass.so.5 (0xb5b33000)
	librtmp.so.1 => /volume1/@appstore/Serviio/bin/../lib/librtmp.so.1 (0xb5b14000)
	libz.so.1 => /lib/libz.so.1 (0xb5afb000)
	libgnutls.so.28 => /lib/libgnutls.so.28 (0xb59f0000)
	libbz2.so.1.0 => /lib/libbz2.so.1.0 (0xb59df000)
	libdl.so.2 => /lib/libdl.so.2 (0xb59da000)
	libx264.so.148 => /volume1/@appstore/Serviio/bin/../lib/libx264.so.148 (0xb583c000)
	libvorbisenc.so.2 => /volume1/@appstore/Serviio/bin/../lib/libvorbisenc.so.2 (0xb57aa000)
	libvorbis.so.0 => /volume1/@appstore/Serviio/bin/../lib/libvorbis.so.0 (0xb5770000)
	libspeex.so.1 => /volume1/@appstore/Serviio/bin/../lib/libspeex.so.1 (0xb5747000)
	libmp3lame.so.0 => /lib/libmp3lame.so.0 (0xb56cf000)
	liblzma.so.5 => /lib/liblzma.so.5 (0xb56a3000)
	/lib/ld-linux.so.2 (0xb7718000)
	libfribidi.so.0 => /volume1/@appstore/Serviio/bin/../lib/libfribidi.so.0 (0xb5688000)
	libfontconfig.so.1 => /lib/libfontconfig.so.1 (0xb5645000)
	libfreetype.so.6 => /lib/libfreetype.so.6 (0xb5586000)
	libhogweed.so.2 => /lib/libhogweed.so.2 (0xb5555000)
	libnettle.so.4 => /lib/libnettle.so.4 (0xb5521000)
	libgmp.so.10 => /lib/libgmp.so.10 (0xb54ac000)
	libogg.so.0 => /volume1/@appstore/Serviio/bin/../lib/libogg.so.0 (0xb54a2000)
	libxml2.so.2 => /lib/libxml2.so.2 (0xb5321000)
	libpng16.so.16 => /lib/libpng16.so.16 (0xb52e4000)
DS214>
 

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.56 => /volume1/@appstore/Serviio/bin/../lib/libavdevice.so.56 (0xb77c0000)
	libavfilter.so.5 => /volume1/@appstore/Serviio/bin/../lib/libavfilter.so.5 (0xb7686000)
	libavformat.so.56 => /volume1/@appstore/Serviio/bin/../lib/libavformat.so.56 (0xb748d000)
	libavcodec.so.56 => /volume1/@appstore/Serviio/bin/../lib/libavcodec.so.56 (0xb630e000)
	libpostproc.so.53 => /volume1/@appstore/Serviio/bin/../lib/libpostproc.so.53 (0xb62e7000)
	libswresample.so.1 => /volume1/@appstore/Serviio/bin/../lib/libswresample.so.1 (0xb62cb000)
	libswscale.so.3 => /volume1/@appstore/Serviio/bin/../lib/libswscale.so.3 (0xb624a000)
	libavutil.so.54 => /volume1/@appstore/Serviio/bin/../lib/libavutil.so.54 (0xb61d4000)
	libffmpeg_plugin.so => /lib/libffmpeg_plugin.so (0xb61be000)
	libm.so.6 => /lib/libm.so.6 (0xb6175000)
	libismd_core.so => /lib/libismd_core.so (0xb6168000)
	libismd_viddec.so => /lib/libismd_viddec.so (0xb6160000)
	libjson-c.so.2 => /lib/libjson-c.so.2 (0xb6153000)
	libpthread.so.0 => /lib/libpthread.so.0 (0xb6137000)
	libc.so.6 => /lib/libc.so.6 (0xb5f88000)
	libass.so.5 => /volume1/@appstore/Serviio/bin/../lib/libass.so.5 (0xb5f44000)
	librtmp.so.1 => /volume1/@appstore/Serviio/bin/../lib/librtmp.so.1 (0xb5f25000)
	libz.so.1 => /lib/libz.so.1 (0xb5f0c000)
	libgnutls.so.28 => /lib/libgnutls.so.28 (0xb5e02000)
	libbz2.so.1.0 => /lib/libbz2.so.1.0 (0xb5df0000)
	libx264.so.148 => /volume1/@appstore/Serviio/bin/../lib/libx264.so.148 (0xb5c52000)
	libvorbisenc.so.2 => /volume1/@appstore/Serviio/bin/../lib/libvorbisenc.so.2 (0xb5bc0000)
	libvorbis.so.0 => /volume1/@appstore/Serviio/bin/../lib/libvorbis.so.0 (0xb5b87000)
	libspeex.so.1 => /volume1/@appstore/Serviio/bin/../lib/libspeex.so.1 (0xb5b5e000)
	libmp3lame.so.0 => /lib/libmp3lame.so.0 (0xb5ae5000)
	liblzma.so.5 => /lib/liblzma.so.5 (0xb5ab9000)
	libdl.so.2 => /lib/libdl.so.2 (0xb5ab4000)
	libxml2.so.2 => /lib/libxml2.so.2 (0xb5933000)
	libismd_demux.so => /lib/libismd_demux.so (0xb5928000)
	libismd_vidrend.so => /lib/libismd_vidrend.so (0xb591f000)
	libismd_clock.so => /lib/libismd_clock.so (0xb591d000)
	libismd_audio.so => /lib/libismd_audio.so (0xb590e000)
	libismd_videnc.so => /lib/libismd_videnc.so (0xb590a000)
	libismd_vidpproc.so => /lib/libismd_vidpproc.so (0xb5903000)
	libismdmessage.so => /lib/libismdmessage.so (0xb58ff000)
	libsven.so => /lib/libsven.so (0xb57b9000)
	libpal.so => /lib/libpal.so (0xb57b7000)
	libosal.so => /lib/libosal.so (0xb57ae000)
	libplatform_config.so => /lib/libplatform_config.so (0xb57ab000)
	libsystem_utils.so => /lib/libsystem_utils.so (0xb57a8000)
	libismd_clock_recovery.so => /lib/libismd_clock_recovery.so (0xb57a4000)
	/lib/ld-linux.so.2 (0xb77d0000)
	libfribidi.so.0 => /volume1/@appstore/Serviio/bin/../lib/libfribidi.so.0 (0xb5789000)
	libfontconfig.so.1 => /lib/libfontconfig.so.1 (0xb5747000)
	libfreetype.so.6 => /lib/libfreetype.so.6 (0xb5688000)
	libhogweed.so.2 => /lib/libhogweed.so.2 (0xb5657000)
	libnettle.so.4 => /lib/libnettle.so.4 (0xb5623000)
	libgmp.so.10 => /lib/libgmp.so.10 (0xb55ad000)
	libogg.so.0 => /volume1/@appstore/Serviio/bin/../lib/libogg.so.0 (0xb55a4000)
	libpng16.so.16 => /lib/libpng16.so.16 (0xb5567000)
DS214Play> 
 
 
Advertisements

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> 

Compiling FFmpeg with libRTMP and libmp3lame for Intel, ARM and QorIQ PowerPC CPUs

Intel cross-compile for Synology NAS on Ubuntu Desktop 12.04 64bit (VirtualBox VM running on a Macbook Air):

#-----set up Synology toolchain
cd ~/Downloads
PART1="http://sourceforge.net/projects/dsgpl/files/DSM%204.0%20Tool%20Chains/"
PART2="Intel%20x86%20Linux%202.6.32%20%28Pineview%29/gcc420_glibc236_x64-GPL.tgz"
wget "${PART1}${PART2}"
tar xvzf gcc420_glibc236_x64-GPL.tgz
sudo mv x86_64-linux-gnu /usr/local
export PATH="/usr/local/x86_64-linux-gnu/bin:${PATH}"

#-----libz static lib
wget http://zlib.net/zlib-1.2.7.tar.gz
tar xvzf zlib-1.2.7.tar.gz
cd zlib-1.2.7
./configure --prefix=/usr/local/x86_64-linux-gnu --static
make libz.a
cp libz.a /usr/local/x86_64-linux-gnu/lib
cp *.h /usr/local/x86_64-linux-gnu/include/
cd ..

#-----libbz2 static lib
#-----seem to need 32bit libraries to build bzip2
#-----http://maketecheasier.com/run-32-bit-apps-in-64-bit-linux/2009/08/10
sudo apt-get install ia32-libs
wget http://bzip.org/1.0.6/bzip2-1.0.6.tar.gz
tar xvfz bzip2-1.0.6.tar.gz
cd bzip2-1.0.6
sed -i 's/^CC=gcc/CC=x86_64-linux-gnu-gcc/g' Makefile
sed -i 's/^AR=ar rc/AR=x86_64-linux-gnu-ar rc/g' Makefile
sed -i 's/^RANLIB=ranlib/RANLIB=x86_64-linux-gnu-ranlib/g' Makefile
make
make install PREFIX=/usr/local/x86_64-linux-gnu
cd ..

#-----libmp3lame static lib
sudo apt-get install nasm
wget http://sourceforge.net/projects/lame/files/lame/3.99/lame-3.99.5.tar.gz
tar xvzf lame-3.99.5.tar.gz
cd lame-3.99.5
./configure --prefix=/usr/local/x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --build=x86_64-linux-gnu --enable-static --disable-shared --disable-decoder --enable-nasm
make
make install
cd..

#-----libssl & libcrypto static libs
wget http://www.openssl.org/source/openssl-0.9.8v.tar.gz
tar xvzf openssl-0.9.8v.tar.gz
cd openssl-0.9.8v
./config --prefix=/usr/local/x86_64-linux-gnu no-shared
sed -i 's/^CC= gcc/CC= x86_64-linux-gnu-gcc/g' Makefile
sed -i 's/^AR= ar /AR= x86_64-linux-gnu-ar /g' Makefile
sed -i 's/^ARD=ar /ARD=x86_64-linux-gnu-ar /g' Makefile
sed -i 's/^RANLIB= \/usr\/bin\/ranlib/RANLIB=x86_64-linux-gnu-ranlib/g' Makefile
sed -i 's/^MAKEDEPPROG= gcc/MAKEDEPPROG= x86_64-linux-gnu-gcc /g' Makefile
make
make install
cd ..

#-----librtmp 2.4 static lib
wget http://download.serviio.org/opensource/rtmpdump-c58cfb3e9208c6e6bc1aa18f1b1d650d799084e5.tar.gz
tar xvfz rtmpdump-c58cfb3e9208c6e6bc1aa18f1b1d650d799084e5.tar.gz
cd rtmpdump
#-----move all static libs to a separate folder to force compiler to use them
#-----http://www.gossamer-threads.com/lists/apache/dev/265052
mkdir /tmp/lib
cp /usr/local/x86_64-linux-gnu/lib/*.a /tmp/lib
#-----fix Makefile (won't compile without libdl linked)
#-----http://forum.luahub.com/index.php?topic=2390.0
sed -i.bak -e '/^LIB_OPENSSL\=/s/lcrypto/lcrypto \-ldl/' Makefile
make CROSS_COMPILE=x86_64-linux-gnu- SYS=posix prefix=/usr/local/x86_64-linux-gnu INC=-I/usr/local/x86_64-linux-gnu XLDFLAGS=-L/tmp/lib SHARED=
make install prefix=/usr/local/x86_64-linux-gnu SHARED=
cd ..

#-----gather all static libs again ready for FFmpeg compile
cp /usr/local/x86_64-linux-gnu/lib/*.a /tmp/lib
#-----remove unsupported URL line from pkgconfig/librtmp.pc
#-----pkg-config --exists --print-errors librtmp
sed -i -e '/^URL/d' /usr/local/x86_64-linux-gnu/lib/pkgconfig/librtmp.pc
export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:/usr/local/x86_64-linux-gnu/lib/pkgconfig"

#-----FFmpeg 0.11.1
wget http://download.serviio.org/opensource/ffmpeg-N-41860-g6fd0b55.tar.gz
tar xvzf ffmpeg-N-41860-g6fd0b55.tar.gz
cd ffmpeg
echo N-41860-g6fd0b55 > RELEASE
#-----Intel CPU-specific options
#-----pkg-config needs to be defined because with cross-prefix it assumes x86_64-linux-gnu-pkg-config which doesn't exist, and then librtmp won't be detected
sudo apt-get install yasm
./configure --arch=x86_64 --enable-ssse3 --cross-prefix=x86_64-linux-gnu- --target-os=linux --prefix=/usr/local/x86_64-linux-gnu --extra-cflags='-I/usr/local/x86_64-linux-gnu/include' --extra-ldflags='-L/tmp/lib' --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-pthreads --enable-libmp3lame --enable-librtmp --pkg-config=pkg-config --extra-version=Serviio
make
./ffmpeg
 

ARM cross-compile for Synology NAS on Ubuntu Desktop 12.04 64bit (VirtualBox VM running on a Macbook Air):

#-----set up Synology toolchain
cd ~/Downloads
PART1="http://sourceforge.net/projects/dsgpl/files/DSM%204.1%20Tool%20Chains/"
PART2="Marvell%2088F628x%20Linux%202.6.32/gcc421_glibc25_88f6281-GPL.tgz"
wget "${PART1}${PART2}"
tar xvzf gcc421_glibc25_88f6281-GPL.tgz
sudo mv arm-none-linux-gnueabi /usr/local
export PATH=/usr/local/arm-none-linux-gnueabi/bin:$PATH
export AR=arm-none-linux-gnueabi-ar
export CC=arm-none-linux-gnueabi-gcc
export CXX=arm-none-linux-gnueabi-g++
export LD=arm-none-linux-gnueabi-ld
export RANLIB=arm-none-linux-gnueabi-ranlib
export CFLAGS="-I/usr/local/arm-none-linux-gnueabi/include"
export LDFLAGS="-L/usr/local/arm-none-linux-gnueabi/lib"

#-----libz static lib
wget http://zlib.net/zlib-1.2.7.tar.gz
tar xvzf zlib-1.2.7.tar.gz
cd zlib-1.2.7
./configure --prefix=/usr/local/arm-none-linux-gnueabi --static
make libz.a
cp libz.a /usr/local/arm-none-linux-gnueabi/lib
cp *.h /usr/local/arm-none-linux-gnueabi/include/
cd ..

#-----libbz2 static lib
wget http://bzip.org/1.0.6/bzip2-1.0.6.tar.gz
tar xvfz bzip2-1.0.6.tar.gz
cd bzip2-1.0.6
sed -i 's/^CC=gcc/CC=arm-none-linux-gnueabi-gcc/g' Makefile
sed -i 's/^AR=ar/AR=arm-none-linux-gnueabi-ar/g' Makefile
sed -i 's/^RANLIB=ranlib/RANLIB=arm-none-linux-gnueabi-ranlib/g' Makefile
#remove the tests - we can't run the native binaries
sed -i 's/^\(all: libbz2\.a bzip2 bzip2recover\) test/\1/' Makefile
make
make install PREFIX=/usr/local/arm-none-linux-gnueabi
cd ..

#-----libmp3lame static lib
wget http://sourceforge.net/projects/lame/files/lame/3.99/lame-3.99.5.tar.gz
tar xvzf lame-3.99.5.tar.gz
cd lame-3.99.5
./configure --prefix=/usr/local/arm-none-linux-gnueabi --host=arm-none-linux-gnueabi --build=x86_64-linux-gnu --enable-static --disable-shared --disable-decoder
make
make install
cd ..

#-----libssl & libcrypto static libs
wget http://www.openssl.org/source/openssl-0.9.8v.tar.gz
tar xvzf openssl-0.9.8v.tar.gz
cd openssl-0.9.8v
#Some kind of strange issue where cross compilation parameters are ignored
#unless this fix is used http://marc.waeckerlin.org/computer/blog/openssl_fuer_windows_mingw_unter_linux_crosscomilieren
sed -i 's/\(die \"target already defined - \$target (offending arg\)/#\1/' Configure
./config --prefix=/usr/local/arm-none-linux-gnueabi no-shared linux-generic32
make
make install
cd ..

#-----librtmp 2.4 static lib
wget http://download.serviio.org/opensource/rtmpdump-c58cfb3e9208c6e6bc1aa18f1b1d650d799084e5.tar.gz
tar xvfz rtmpdump-c58cfb3e9208c6e6bc1aa18f1b1d650d799084e5.tar.gz
cd rtmpdump
#-----move all static libs to a separate folder to force compiler to use them
#-----http://www.gossamer-threads.com/lists/apache/dev/265052
mkdir /tmp/lib
cp /usr/local/arm-none-linux-gnueabi/lib/*.a /tmp/lib
#-----fix Makefile (won't compile without libdl linked)
#-----http://forum.luahub.com/index.php?topic=2390.0
sed -i.bak -e '/^LIB_OPENSSL\=/s/lcrypto/lcrypto \-ldl/' Makefile
make CROSS_COMPILE=arm-none-linux-gnueabi- SYS=posix prefix=/usr/local/arm-none-linux-gnueabi INC=-I/usr/local/arm-none-linux-gnueabi XLDFLAGS=-L/tmp/lib SHARED=
make install prefix=/usr/local/arm-none-linux-gnueabi SHARED=
cd ..

#-----gather all static libs again ready for FFmpeg compile
cp /usr/local/arm-none-linux-gnueabi/lib/*.a /tmp/lib
#-----remove unsupported URL line from pkgconfig/librtmp.pc
#-----pkg-config --exists --print-errors librtmp
sed -i -e '/^URL/d' /usr/local/arm-none-linux-gnueabi/lib/pkgconfig/librtmp.pc
export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:/usr/local/arm-none-linux-gnueabi/lib/pkgconfig"

#-----FFmpeg
wget http://download.serviio.org/opensource/ffmpeg-N-42368-gbf53863.tar.gz
tar xvzf ffmpeg-N-42368-gbf53863.tar.gz
cd ffmpeg
#-----fixed point maths modification for mpeg audio encoder
sed -i "s/^#define USE_FLOATS//" libavcodec/mpegaudioenc.c
#-----Marvell Kirkwood mv6282 CPU is based on the ARMv5TE core which has DSP and thumb instruction support
#-----http://www.arm.com/products/processors/technologies/dsp-simd.php
#-----http://www.marvell.com/embedded-processors/kirkwood/assets/88f6282-3_pb.pdf
#-----ARMv5TE CPU-specific options (based on inspecting 'configure' source https://github.com/FFmpeg/FFmpeg/blob/master/configure)
#-----pkg-config needs to be defined because with cross-prefix it assumes arm-none-linux-gnueabi-pkg-config which doesn't exist, and then librtmp won't be detected
#-----zmbv encoder refuses to cross compile here so it's disabled
./configure --arch=arm --cpu=armv5te --cross-prefix=arm-none-linux-gnueabi- --target-os=linux --prefix=/usr/local/arm-none-linux-gnueabi --extra-cflags='-I/usr/local/arm-none-linux-gnueabi/include' --extra-ldflags='-L/tmp/lib' --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-pthreads --enable-libmp3lame --enable-librtmp --disable-encoder=zmbv --pkg-config=pkg-config --extra-version=Serviio
make

./ffmpeg

Freescale QorIQ P1022 PowerPC cross-compile for Synology NAS on Ubuntu Desktop 12.04 64bit (VirtualBox VM running on a Macbook Air):

#-----set up Synology toolchain
cd ~/Downloads
PART1="http://sourceforge.net/projects/dsgpl/files/DSM%204.1%20Tool%20Chains/"
PART2="PowerPC%20QorIQ%20Linux%202.6.32/gcc4374_eglibc2874_qoriq-GPL.tgz"
wget "${PART1}${PART2}"
tar xvzf gcc4374_eglibc2874_qoriq-GPL.tgz
sudo mv powerpc-none-linux-gnuspe /usr/local
export PATH=/usr/local/powerpc-none-linux-gnuspe/bin:$PATH
export AR=powerpc-none-linux-gnuspe-ar
export CC=powerpc-none-linux-gnuspe-gcc
export CXX=powerpc-none-linux-gnuspe-g++
export LD=powerpc-none-linux-gnuspe-ld
export RANLIB=powerpc-none-linux-gnuspe-ranlib
export CFLAGS="-I/usr/local/powerpc-none-linux-gnuspe/include"
export LDFLAGS="-L/usr/local/powerpc-none-linux-gnuspe/lib"

#-----libz static lib
wget http://zlib.net/zlib-1.2.7.tar.gz
tar xvzf zlib-1.2.7.tar.gz
cd zlib-1.2.7
./configure --prefix=/usr/local/powerpc-none-linux-gnuspe --static
make libz.a
cp libz.a /usr/local/powerpc-none-linux-gnuspe/lib
cp *.h /usr/local/powerpc-none-linux-gnuspe/include/
cd ..

#-----libbz2 static lib
wget http://bzip.org/1.0.6/bzip2-1.0.6.tar.gz
tar xvfz bzip2-1.0.6.tar.gz
cd bzip2-1.0.6
sed -i 's/^CC=gcc/CC=powerpc-none-linux-gnuspe-gcc/g' Makefile
sed -i 's/^AR=ar/AR=powerpc-none-linux-gnuspe-ar/g' Makefile
sed -i 's/^RANLIB=ranlib/RANLIB=powerpc-none-linux-gnuspe-ranlib/g' Makefile
#remove the tests - we can't run the native binaries
sed -i 's/^\(all: libbz2\.a bzip2 bzip2recover\) test/\1/' Makefile
make
make install PREFIX=/usr/local/powerpc-none-linux-gnuspe
cd ..

#-----libmp3lame static lib
wget http://sourceforge.net/projects/lame/files/lame/3.99/lame-3.99.5.tar.gz
tar xvzf lame-3.99.5.tar.gz
cd lame-3.99.5
./configure --prefix=/usr/local/powerpc-none-linux-gnuspe --host=powerpc-none-linux-gnuspe --build=x86_64-linux-gnu --enable-static --disable-shared --disable-decoder
make
make install
cd..

#-----libssl & libcrypto static libs
wget http://www.openssl.org/source/openssl-0.9.8v.tar.gz
tar xvzf openssl-0.9.8v.tar.gz
cd openssl-0.9.8v
#Some kind of strange issue where cross compilation parameters are ignored
#unless this fix is used http://marc.waeckerlin.org/computer/blog/openssl_fuer_windows_mingw_unter_linux_crosscomilieren
sed -i 's/\(die \"target already defined - \$target (offending arg\)/#\1/' Configure
./config --prefix=/usr/local/powerpc-none-linux-gnuspe no-shared linux-ppc
make
make install
cd ..

#-----librtmp 2.4 static lib
wget http://download.serviio.org/opensource/rtmpdump-c58cfb3e9208c6e6bc1aa18f1b1d650d799084e5.tar.gz
tar xvfz rtmpdump-c58cfb3e9208c6e6bc1aa18f1b1d650d799084e5.tar.gz
cd rtmpdump
#-----move all static libs to a separate folder to force compiler to use them
#-----http://www.gossamer-threads.com/lists/apache/dev/265052
mkdir /tmp/lib
cp /usr/local/powerpc-none-linux-gnuspe/lib/*.a /tmp/lib
#-----fix Makefile (won't compile without libdl linked)
#-----http://forum.luahub.com/index.php?topic=2390.0
sed -i.bak -e '/^LIB_OPENSSL\=/s/lcrypto/lcrypto \-ldl/' Makefile
make CROSS_COMPILE=powerpc-none-linux-gnuspe- SYS=posix prefix=/usr/local/powerpc-none-linux-gnuspe INC=-I/usr/local/powerpc-none-linux-gnuspe XLDFLAGS=-L/tmp/lib SHARED=
make install prefix=/usr/local/powerpc-none-linux-gnuspe SHARED=
cd ..

#-----gather all static libs again ready for FFmpeg compile
cp /usr/local/powerpc-none-linux-gnuspe/lib/*.a /tmp/lib
#-----remove unsupported URL line from pkgconfig/librtmp.pc
#-----pkg-config --exists --print-errors librtmp
sed -i -e '/^URL/d' /usr/local/powerpc-none-linux-gnuspe/lib/pkgconfig/librtmp.pc
export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:/usr/local/powerpc-none-linux-gnuspe/lib/pkgconfig"

#-----FFmpeg
wget http://download.serviio.org/opensource/ffmpeg-N-42368-gbf53863.tar.gz
tar xvzf ffmpeg-N-42368-gbf53863.tar.gz
cd ffmpeg
#-----QorIQ P1022 CPU is based on the PowerPC e500v2 core which has Signal Processing Engine which is not a classic FPU design
#-----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
#-----PowerPC e500v2 CPU-specific options (based on inspecting source https://github.com/FFmpeg/FFmpeg/blob/master/configure)
#-----pkg-config needs to be defined because with cross-prefix it assumes powerpc-none-linux-gnuspe-pkg-config which doesn't exist, and then librtmp won't be detected
./configure --arch=ppc --cpu=e500v2 --cross-prefix=powerpc-none-linux-gnuspe- --target-os=linux --prefix=/usr/local/powerpc-none-linux-gnuspe --extra-cflags='-I/usr/local/powerpc-none-linux-gnuspe/include' --extra-ldflags='-L/tmp/lib' --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-pthreads --enable-libmp3lame --enable-librtmp --pkg-config=pkg-config --extra-version=Serviio
make
./ffmpeg

Cross-compiling FFmpeg with librtmp for Intel CPU Synology NAS

I used this method to compile the FFmpeg binary for inclusion in my Serviio package, because I don’t have a NAS with an Intel CPU. Several people who tried to help were getting strange errors while trying to compile on their NAS units.

To begin, install 64bit Ubuntu Linux (I used a VM). As a test I first successfully cross-compiled ARM binaries using the same method but using the ARM Synology toolchain, since I was able to test the results. Once I got it working I did the following:

#-----set up Synology toolchain
cd ~/Downloads
wget http://sourceforge.net/projects/dsgpl/files/DSM%203.1%20Tool%20Chains/Intel%20x86%20Linux%202.6.32/gcc420_glibc236_pineview.tgz
tar xvfz gcc420_glibc236_pineview.tgz
sudo mv i686-linux-gnu /usr/local
sudo mv x86_64-linux-gnu /usr/local
#-----I think the Synology toolchain is anticipating being run on i686-linux-gnu, so we need 32bit libraries to even run the binaries
#-----http://maketecheasier.com/run-32-bit-apps-in-64-bit-linux/2009/08/10
sudo apt-get install ia32-libs
export PATH="/usr/local/x86_64-linux-gnu/bin:${PATH}"

#-----libz static lib
wget http://zlib.net/zlib-1.2.5.tar.gz
tar xvfz zlib-1.2.5.tar.gz
cd zlib-1.2.5
#-----http://www.crosscompile.org/static/pages/ZLib.html
#-----http://tinc-vpn.org/examples/cross-compiling-64-bit-windows-binary/
./configure --prefix=/usr/local/x86_64-linux-gnu --static
sed -i 's/^CC=gcc/CC=x86_64-linux-gnu-gcc/g' Makefile
sed -i 's/^LDSHARED=gcc/LDSHARED=x86_64-linux-gnu-gcc/g' Makefile
sed -i 's/^CPP=gcc -E/CPP=x86_64-linux-gnu-gcc -E/g' Makefile
sed -i 's/^AR=ar rc/AR=x86_64-linux-gnu-ar rc/g' Makefile
sed -i 's/^RANLIB=ranlib/RANLIB=x86_64-linux-gnu-ranlib/g' Makefile
make libz.a
cp libz.a /usr/local/x86_64-linux-gnu/lib
cp *.h /usr/local/x86_64-linux-gnu/include/
cd ..

#-----libbz2 static lib
wget http://bzip.org/1.0.6/bzip2-1.0.6.tar.gz
tar xvfz bzip2-1.0.6.tar.gz
cd bzip2-1.0.6
sed -i 's/^CC=gcc/CC=x86_64-linux-gnu-gcc/g' Makefile
sed -i 's/^AR=ar rc/AR=x86_64-linux-gnu-ar rc/g' Makefile
sed -i 's/^RANLIB=ranlib/RANLIB=x86_64-linux-gnu-ranlib/g' Makefile
make
make install PREFIX=/usr/local/x86_64-linux-gnu
cd ..

#-----libmp3lame static lib
wget http://sourceforge.net/projects/lame/files/lame/3.98.4/lame-3.98.4.tar.gz
tar xvfz lame-3.98.4.tar.gz
cd lame-3.98.4
./configure --prefix=/usr/local/x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --build=x86_64-linux-gnu --enable-static --disable-shared --disable-decoder --enable-nasm
make
make install

#-----libssl & libcrypto static libs
ipkg install openssl-dev
wget http://www.openssl.org/source/openssl-0.9.8p.tar.gz
tar xvfz openssl-0.9.8p.tar.gz
cd openssl-0.9.8p
./config --prefix=/usr/local/x86_64-linux-gnu no-shared
sed -i 's/^CC= gcc/CC= x86_64-linux-gnu-gcc/g' Makefile
sed -i 's/^AR= ar /AR= x86_64-linux-gnu-ar /g' Makefile
sed -i 's/^ARD=ar /ARD=x86_64-linux-gnu-ar /g' Makefile
sed -i 's/^RANLIB= \/usr\/bin\/ranlib/RANLIB=x86_64-linux-gnu-ranlib/g' Makefile
sed -i 's/^MAKEDEPPROG= gcc/MAKEDEPPROG= x86_64-linux-gnu-gcc /g' Makefile
make
make install
cd ..

#-----librtmp 2.4 static lib
wget http://download.serviio.org/opensource/rtmpdump-c58cfb3e9208c6e6bc1aa18f1b1d650d799084e5.tar.gz
tar xvfz rtmpdump-c58cfb3e9208c6e6bc1aa18f1b1d650d799084e5.tar.gz
cd rtmpdump
#-----move all static libs to a separate folder to force compiler to use them
#-----http://www.gossamer-threads.com/lists/apache/dev/265052
mkdir /tmp/lib
cp /usr/local/x86_64-linux-gnu/lib/*.a /tmp/lib
#-----fix Makefile (won't compile without libdl linked)
#-----http://forum.luahub.com/index.php?topic=2390.0
sed -i.bak -e '/^LIB_OPENSSL\=/s/lcrypto/lcrypto \-ldl/' Makefile
make CROSS_COMPILE=x86_64-linux-gnu- SYS=posix prefix=/usr/local/x86_64-linux-gnu INC=-I/usr/local/x86_64-linux-gnu XLDFLAGS=-L/tmp/lib SHARED=
make install prefix=/usr/local/x86_64-linux-gnu SHARED=
cd ..
#-----gather all static libs again ready for FFmpeg compile
cp /usr/local/x86_64-linux-gnu/lib/*.a /tmp/lib
#-----remove unsupported URL line from pkgconfig/librtmp.pc
#-----pkg-config --exists --print-errors librtmp
sed -i -e '/^URL/d' /usr/local/x86_64-linux-gnu/lib/pkgconfig/librtmp.pc
export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:/usr/local/x86_64-linux-gnu/lib/pkgconfig"

#-----FFmpeg 0.8.2 (slightly newer than the one at Serviio.org)
wget http://dl.dropbox.com/u/1188556/ffmpeg-HEAD-05a2673.tar.gz
tar xvfz ffmpeg-HEAD-05a2673.tar.gz
cd ffmpeg-HEAD-05a2673
#-----Intel CPU-specific options
#-----pkg-config needs to be defined because with cross-prefix it assumes x86_64-linux-gnu-pkg-config which doesn't exist, and then librtmp won't be detected
sudo apt-get install yasm
./configure --arch=x86_64 --enable-ssse3 --cross-prefix=x86_64-linux-gnu- --target-os=linux --prefix=/usr/local/x86_64-linux-gnu
--extra-cflags='-I/usr/local/x86_64-linux-gnu/include' --extra-ldflags='-L/tmp/lib' --enable-static --disable-shared --disable-ffplay
--disable-ffserver --enable-pthreads --enable-libmp3lame --enable-librtmp --pkg-config=pkg-config --extra-version=Serviio
make
make install
 

Serviio 0.6 DLNA server on Synology NAS

Serviio-Synology

Update – I have released a Synology package for Serviio 0.6

 

Serviio is an excellent free Java DLNA media server by Petr Nejedly which focuses on minimizing the amount of unnecessary media transcoding, and maximizing the use of renderer devices’ supported features. Version 0.6 adds support for streaming content from online RSS feeds. Since the installation process has changed a lot, I decided to create a new post rather than edit the old one. The guide is accurate for Synology DSM 3.2 beta, and the one tricky section with wget-ssl also applies for DSM 3.1. Older DSM versions may vary.

In the Synology DSM go to Control Panel > Terminal > enable SSH.

Read this Synology wiki document about modifying your NAS carefully and install the bootstrap for your model. If you have previously been messing around with your unit and want to set it back to defaults, you can run the bootstrap again. It will prompt you to delete a couple of folders and reboot, whereupon you can start afresh.

Download the PuTTY SSH client if you’re using Windows – other operating systems will already allow you to SSH from the terminal. Give the session a name, set the remote character set to UTF-8 as shown and save it before you connect (to save time in future). This will ensure that all characters display properly. The Mac OS SSH client defaults to UTF-8.
PuTTY remote character set configuration

Connect to your NAS’s IP address using SSH. Use the root account (same password as admin). For Mac OS for instance, use ssh root@x.x.x.x. I suggest enabling a more descriptive shell prompt which should reduce the chance of accidentally being in the wrong directory:

sed -i -r 's/(^PS1=.*$)/#\1\n\1/' ~/.profile
sed -i -e 's/^PS1=.*$/PS1=\"\\w\\\$ \"/g' ~/.profile
source ~/.profile
 

sed (stream editor) is a powerful tool which uses regular expressions. The first command opens the file ~./profile searches for the line beginning with PS1= and duplicates it, commenting out the first copy (so the change can be undone). Then second command sets the value PS1=”\w\$ “ which changes the prompt to be the current directory followed by dollar sign and space characters.

To install the development tools. Type:

ipkg update
ipkg install optware-devel
 

It will halt and complain that package wget-ssl clashes with wget. Continue with:

cp /opt/bin/wget /opt/bin/wget-old
ipkg remove wget
cp /opt/bin/wget-old /opt/bin/wget
ipkg install libidn
ipkg install optware-devel
 

This time it will finish successfully.

Next we need to install Lame MP3 encoder, providing libmp3lame which will be compiled into FFmpeg, and the Nano text editor (much easier to use than vi), and fix up some other issues (thanks to Nicolas Jolet for these):

ipkg install lame
ipkg install nano
#-----coreutils ls has no colour output by default
mv /opt/bin/ls /opt/bin/ls.bak
ln -sf /bin/ls /opt/bin/ls
#-----coreutils uptime is broken
mv /opt/bin/uptime /opt/bin/uptime.bak
ln -sf /usr/bin/uptime /opt/bin/uptime
 

Download Java SE for Embedded 7 from Oracle, selecting the Linux build for the appropriate CPU. The ARM v5 version is required for the Marvell Kirkwood CPU Synology Products. Note that there is a PowerPC e500v2 version – the CPU core in Synology products which use the Freescale mpc85x3). Unfortunately for PowerPC Synology owners, this depends on a higher version of glibc than the Synology DSM provides for this architecture. Until JamVM supports Java 1.6, or Synology update to glibc 2.4 you won’t be able to follow this guide on PowerPC models. This situation may have changed since DSM 3.2 beta was released.

You will need to sign up to receive the Java download link by email. It’s free to use for non-commercial evaluation use. Use your computer to save it into the top level shared folder of your NAS, which will probably be /volume1/public on the NAS filesystem. Then:

cd /volume1/public
mv ejre-7-fcs-b147-linux-arm-sflt-headless-27_jun_2011.tar.gz /volume1/@tmp
cd /volume1/@tmp
tar xvzf ejre-7-fcs-b147-linux-arm-sflt-headless-27_jun_2011.tar.gz
mv ejre1.7.0 /opt/local/java
 

Synology’s Linux build has no localization support built in, though it does use UTF-8 character encoding for the filesystem. That’s no problem for storage, however the Java VM inherits the locale setting of the host OS. Since this is undefined, Serviio and all other Java software will default to US-ASCII which is a big problem if you have filenames with non-US characters. The solution is to obtain the missing files to add locale support from the Synology toolchain, which is distributed under the GPL. Many thanks to IWarez at the Subsonic forum for this fix, though it took me a good while to realise the required files are indeed included in the ARM toolchain:

#-----for ARM CPU
cd /volume1/@tmp
wget http://sourceforge.net/projects/dsgpl/files/DSM%203.1%20Tool%20Chains/Marvell%2088F628x%20Linux%202.6.32/gcc421_glibc25_88f628x.tgz
tar xvfz gcc421_glibc25_88f628x.tgz
cd arm-none-linux-gnueabi/arm-none-linux-gnueabi/libc/usr/bin
cp locale /opt/bin
cp localedef /opt/bin
cp -R arm-none-linux-gnueabi/arm-none-linux-gnueabi/libc/usr/share/i18n /usr/share
#-----keep another copy safe in case DSM is reinstalled later
cp -R arm-none-linux-gnueabi/arm-none-linux-gnueabi/libc/usr/share/i18n /opt/share
mkdir /usr/lib/locale
localedef -c -f UTF-8 -i en_US en_US.utf8

#-----for Intel CPU
cd /volume1/@tmp
wget http://sourceforge.net/projects/dsgpl/files/DSM%203.1%20Tool%20Chains/Intel%20x86%20Linux%202.6.32/gcc420_glibc236_pineview.tgz
tar xvfz gcc420_glibc236_pineview.tgz
cd i686-linux-gnu/i686-linux-gnu/bin
cp locale /opt/bin
cp localedef /opt/bin
cp -R i686-linux-gnu/i686-linux-gnu/share/i18n /usr/share
#-----keep another copy safe in case DSM is reinstalled later
cp -R i686-linux-gnu/i686-linux-gnu/share/i18n /opt/share
mkdir /usr/lib/locale
localedef -c -f UTF-8 -i en_US en_US.utf8

 

Now use nano to edit some configuration files (Ctrl-o saves, and Ctrl-x exits).
First edit the profile for all bash shell users:

nano /opt/etc/profile
 

Make the changes shown in bold:

#
# Bash initialization script
#

PS1=”[\u@\h \W]$ ”
PATH=/opt/sbin:/opt/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/local/java/bin
LD_LIBRARY_PATH=/opt/lib:${LD_LIBRARY_PATH}
JAVA_HOME=/opt/local/java
LANG=en_US.utf8

export PS1 PATH LD_LIBRARY_PATH JAVA_HOME LANG

 

Save and exit. Next edit the profile for all ash shell users (root):

nano /etc/profile
 

Add the changes shown in bold:

#/etc/profile: system-wide .profile file for ash.
PATH=”$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/syno/bin:/usr/syno/sbin:/usr/local/bin:/usr/local/sbin
PATH=”$PATH:/opt/local/java/bin”
JAVA_HOME=/opt/local/java
LANG=en_US.utf8
export JAVA_HOME LANG

umask 022

 

Save and exit. Now install Serviio 0.6:

cd /volume1/@tmp
wget http://download.serviio.org/releases/serviio-0.6-linux.tar.gz
tar xvzf serviio-0.6-linux.tar.gz
mv serviio-0.6 /opt/local/serviio
 

Next, compile librtmp which FFmpeg will use to retrieve Adobe Flash streaming video, the libssl static libraries (which librtmp depends on), libz and libbz2 static libraries for FFmpeg.

#-----libz static lib (ipkg only provides shared)
wget http://zlib.net/zlib-1.2.5.tar.gz
tar xvfz zlib-1.2.5.tar.gz
cd zlib-1.2.5
./configure --prefix=/opt --static
make
make install
 

At this point ou will see the error “cp: missing destination file operand after `/opt/lib'” because the libz.so shared library wasn’t compiled and the install script tries to copy it nonetheless. libz.a which we need was built ok, so ignore and continue.

cd ..
#-----libbz2 static lib (ipkg only provides shared)
wget http://bzip.org/1.0.6/bzip2-1.0.6.tar.gz
tar xvfz bzip2-1.0.6.tar.gz
cd bzip2-1.0.6
make
make install PREFIX=/opt
cd ..

#-----libssl & libcrypto static libs (ipkg only provides shared)
ipkg install openssl-dev
wget http://www.openssl.org/source/openssl-0.9.8p.tar.gz
tar xvfz openssl-0.9.8p.tar.gz
cd openssl-0.9.8p
./config --prefix=/opt no-shared
make
cp libssl.a /opt/lib
cp libcrypto.a /opt/lib
#-----librtmp won't compile without these pkgconfig definitions
cp libssl.pc /opt/lib/pkgconfig
cp libcrypto.pc /opt/lib/pkgconfig
cd ..

#-----librtmp depends on libpthreads but the optware copy seems to be broken
#-----http://forum.synology.com/enu/viewtopic.php?f=90&t=30132
mkdir /opt/arm-none-linux-gnueabi/lib_disabled
mv /opt/arm-none-linux-gnueabi/lib/libpthread* /opt/arm-none-linux-gnueabi/lib_disabled
cp /lib/libpthread.so.0 /opt/arm-none-linux-gnueabi/lib/
cd /opt/arm-none-linux-gnueabi/lib/
ln -s libpthread.so.0 libpthread.so
ln -s libpthread.so.0 libpthread-2.5.so
cd /volume1/@tmp
wget http://download.serviio.org/opensource/rtmpdump-c58cfb3e9208c6e6bc1aa18f1b1d650d799084e5.tar.gz
tar xvfz rtmpdump-c58cfb3e9208c6e6bc1aa18f1b1d650d799084e5.tar.gz
cd rtmpdump
#-----move all static libs to a separate folder to force compiler to use them
#-----http://www.gossamer-threads.com/lists/apache/dev/265052
mkdir /volume1/@tmp/lib
cp /opt/lib/*.a /volume1/@tmp/lib
#-----fix Makefile (won't compile without libdl linked)
#-----http://forum.luahub.com/index.php?topic=2390.0
sed -i.bak -e '/^LIB_OPENSSL\=/s/lcrypto/lcrypto \-ldl/' Makefile
make SYS=posix prefix=/opt INC=-I/opt/include XLDFLAGS=-L/volume1/@tmp/lib SHARED=
make install prefix=/opt SHARED=
cd ..

#-----gather all static libs again ready for FFmpeg compile
cp /opt/lib/*.a /volume1/@tmp/lib

#-----remove unsupported URL line from /opt/lib/pkgconfig/librtmp.pc
#-----pkg-config --exists --print-errors librtmp
sed -i -e '/^URL/d' /opt/lib/pkgconfig/librtmp.pc

#-----FFmpeg 0.8.2 (slightly newer than the one at Serviio.org)
cd /volume1/@tmp
wget http://dl.dropbox.com/u/1188556/ffmpeg-HEAD-05a2673.tar.gz
tar xvfz ffmpeg-HEAD-05a2673.tar.gz
cd ffmpeg-HEAD-05a2673

#-----for ARM CPU
./configure --arch=arm --enable-armv5te --prefix=/opt --extra-cflags='-I/opt/include' --extra-ldflags='-L/volume1/@tmp/lib' --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-pthreads --enable-libmp3lame --enable-librtmp --extra-version=Serviio

#-----for Intel CPU
ipkg install yasm
./configure --arch=x86_64 --enable-ssse3 --prefix=/opt --extra-cflags='-I/opt/include' --extra-ldflags='-L/volume1/@tmp/lib' --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-pthreads --enable-libmp3lame --enable-librtmp --extra-version=Serviio

#-----for PowerPC CPU
./configure --arch=powerpc --disable-altivec --prefix=/opt --extra-cflags='-I/opt/include' --extra-ldflags='-L/volume1/@tmp/lib' --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-pthreads --enable-libmp3lame --enable-librtmp --extra-version=Serviio

make
make install
 

Notice that the ./configure command is line wrapped – it’s all one command. The make command takes approximately 25 minutes and will show many warnings during compilation, but this is expected.

Try running ffmpeg and check the compile time to make sure the newly compiled one is running. You should see this but with your compilation date and time:

ffmpeg version 0.8.2.git-05a2673-Serviio, Copyright (c) 2000-2011 the FFmpeg developers
built on Aug 22 2011 09:57:40 with gcc 4.2.3
configuration: –arch=arm –enable-armv5te –prefix=/opt –extra-cflags=-I/opt/include –extra-ldflags=’-L/volume1/@tmp/lib’ –enable-static –disable-shared –disable-ffplay –disable-ffserver –enable-pthreads –enable-libmp3lame –enable-librtmp –extra-version=Serviio
libavutil 51. 13. 0 / 51. 13. 0
libavcodec 53. 11. 0 / 53. 11. 0
libavformat 53. 9. 0 / 53. 9. 0
libavdevice 53. 3. 0 / 53. 3. 0
libavfilter 2. 34. 1 / 2. 34. 1
libswscale 2. 0. 0 / 2. 0. 0
Hyper fast Audio and Video encoder
usage: ffmpeg [options] [[infile options] -i infile]… {[outfile options] outfile}…

Use -h to get full help or, even better, run ‘man ffmpeg’

In the DSM User Control Panel create a new user called serviio and set a password. Give that user access to the paths that contain the media you want to serve. Click the User Home button and enable the User Home Service. Go back to your SSH session and type:

nano /etc/passwd
 

Be very careful editing this file. A wrong move here could trash your system. Notice that the serviio user has a shell of /sbin/nologin. Change this to /bin/sh like the admin user has. Nano may try to line wrap this line as you type if you added an long account description. If it does, delete the carriage return before the line break and pull it back onto one line. Save and exit.

Now we’ll create the Serviio daemon start and stop script:

nano /volume1/@tmp/S99serviio.sh
 

Paste in the following text (mouseover and use the view source button to copy):

#!/bin/sh

User=serviio

case "$1" in

stop)
        echo "Stop Serviio..."
        su -l $User -c "/opt/local/serviio/bin/serviio.sh -stop" > /dev/null 2>&1 &
        ;;

start)
        # start Serviio in background mode
        su -l $User -c "/opt/local/serviio/bin/serviio.sh" > /dev/null 2>&1 &
        echo "Start Serviio..."
        ;;

restart)
        $0 stop
        sleep 1
        $0 start
        ;;
*)
        echo "usage: $0 { start | stop | restart}" >&2
        exit 1
        ;;

esac
 

Now make it executable and set the serviio user to be the owner of the Serviio folder (so it can create the media database, and log files):

chmod +x /volume1/@tmp/S99serviio.sh
chown -R serviio /opt/local/serviio
 

Test the script manually by running:

/volume1/@tmp/S99serviio.sh start
ps
 

The running process list should show the serviio user running the Serviio launcher shell script and the JVM like so:

 5132 root     16988 S    /usr/syno/sbin/nmbd -D
 5134 admin    34804 S    postgres: admin photo [local] idle
 5187 root     21080 S    /usr/syno/sbin/smbd -D
 5189 root     21080 S    /usr/syno/sbin/smbd -D
 5205 root      7216 S    /usr/syno/sbin/cnid_metad -l log_error
 5207 root     13808 S    /usr/syno/sbin/afpd -g guest -c 256 -n DS111 AFPServ
 5253 root      9208 S N  /usr/syno/sbin/synomkflvd
 5317 root      4112 S    /usr/syno/sbin/sshd
 5332 root      6932 S    /usr/syno/apache/bin/httpd -f /usr/syno/apache/conf/
 5344 root      7068 S    /usr/syno/apache/bin/httpd -f /usr/syno/apache/conf/
 5345 root      7068 S    /usr/syno/apache/bin/httpd -f /usr/syno/apache/conf/
 5369 root      6928 S    /usr/syno/apache/bin/httpd
 5383 nobody    6928 S    /usr/syno/apache/bin/httpd
 5384 nobody    6928 S    /usr/syno/apache/bin/httpd
 5385 nobody    6928 S    /usr/syno/apache/bin/httpd
 5436 root      2408 S    avahi-daemon: running [DS111.local]
 5460 root     11928 S    sshd: root@pts/0
 5466 root      5452 S    -ash
 5582 root         0 SW   [flush-8:0]
 5602 serviio   2988 S    -sh -c /opt/local/serviio/bin/serviio.sh
 5605 serviio   2988 S    /bin/sh /opt/local/serviio/bin/serviio.sh
 5610 serviio   498m S    /opt/local/java/bin/java -Xmx384M -Djava.net.preferI
 5623 root      5452 R    ps
 

Stop the daemon with:

/volume1/@tmp/S99serviio.sh stop
 

Check the web UI or the process list again and make sure it did indeed stop. If it’s all ok, we need to move the daemon launcher script so it starts automatically on boot (it will survive a DSM upgrade):

mv /volume1/@tmp/S99serviio.sh /opt/etc/init.d
 

Shutdown the NAS and restart, checking that Serviio starts by itself.

From now on you can start and stop Serviio manually using this same script (say if you were experimenting with changes to profiles.xml for instance):

/opt/etc/init.d/S99serviio.sh stop
/opt/etc/init.d/S99serviio.sh start
 

Remote console

AcidumIrae’s PHP Web UI is only for Serviio up to version 0.5.2 at present, and at the time of writing the Java Restful Web UI by kairoh does not yet integrate with Serviio 0.6. The only option for now is to use the proper Serviio Console from another computer. Since 0.6 there is no longer a requirement to change anything at the server end, so you just need to pass the parameter -Dserviio.remoteHost=x.x.x.x to the Serviio Console to indicate the IP of your Serviio server. This is covered in the Serviio FAQ. There’s quite a lag for it to start up (at least on Windows), but eventually you see the familiar icon.

 

Serviio settings

Navigate to the Transcoding tab. Set the transcoded files location to /volume1/@tmp. Failure to do this will result in temporary files being written to /tmp which will fill up the partition it’s on the moment you remux a 4GB movie, which would prevent you from logging into the NAS. If your Synology has an Intel CPU set the number of transcoding threads to 2. The dual cores should take advantage of FFmpeg’s pthreads support for a decent performance boost.

I recommend de-selecting Generate thumbnails for local videos in the Metadata tab. Note that you have to click Save on each tab or any change will not take effect. As you’ll see if you have a DLNA renderer that supports thumbnails, Serviio retrieves good ones from the online databases it checks so they’re not really needed. Often FFmpeg will get stuck trying to generate a thumbnail for a video and will lock the CPU at 100% for long periods of time. This issue was raised in this Serviio forum thread.

You can use the Library tab to add the media folders you want to share. Use Add Path not Add Local (we’re using a remote console remember) and express the paths in Linux syntax, e.g. /volume1/public/videos. Be sure that the serviio user has been granted read privileges over the folders you add (User Control Panel in DSM).

 

Performance

The Synology seems perfectly able to transcode DTS audio in a hi-def Matroska file down to 2 channel AC3 in MPEG-TS while copying the H.264 stream. The CPU use leaps up to 100% but I guess that’s because it’s running ahead transcoding down to the end of the file (and is CPU-bound).

If I play something that’s only remuxing the container and copying both audio and video streams then the CPU stays at around 40% (because it’s I/O-bound) then 5 minutes into a film it falls away to pretty much idle – I guess it has finished remuxing to the temporary file.

Memory use even while running Serviio is around 20% at idle, 30% during a remux with audio transcode, though I have noticed that with a larger library this creeps up to around 70%. I have a 2011 product so it has 256MB of RAM. This seems to indicate that the value line of products (with the j suffix) like the DS211j should run Serviio on their 128MB. They have a 1.2GHz CPU though versus 1.6GHz on mine (and the DS110j is only 800MHz), so it would need testing by someone.

All in all it would seem that the Synology products are very capable Serviio appliances!

 

Uninstalling

Log in as root and stop Serviio, then in the DSM User Control Panel delete the user called serviio. Undo the changes that you made to /opt/etc/profile and /etc/profile (the LANG, JAVA_HOME and java path modifications marked in bold earlier in the guide).

Finally, re-download the bootstrap for your model of NAS and run it again. It will tell you to delete a few folders and restart. This will completely trash all optware ipkg packages (i.e. everything in /opt) and undo everything else you did in this guide without affecting your data partitions. If you had any other ipkg packages installed since installing Serviio, these would also be lost.

Batch script for recursive FFmpeg transcoding

I recently had to shrink around 50GB of MP3 audio recordings that were sitting in a nested folder structure on a web server. Having experimented to find more appropriate LAME encoder settings for spoken word content I needed to transcode the files whilst keeping the existing ID3 tags intact. FFmpeg can do this nicely using libmp3lame, whereas LAME by itself cannot. Armed with my own compile of FFmpeg, I created a drag & drop batch script to recursively work through a folder structure transcoding MP3 and WAV files and writing out the resulting MP3 files in the same folder structure with an amended top level folder name. It will accept multiple files or folders being dragged and dropped. You could adapt this script to whatever task you’re using FFmpeg for.

::MP3 transcoding to more sensible default quality settings for spoken word
::32kHz mono VBR @ approx. 64Kbps
::
::pcloadletter.co.uk

@echo off
setlocal ENABLEDELAYEDEXPANSION
::parse multiple command lines (so multiple targets can be dragged and dropped at once)
:commandlineloop
if "%~1"=="" goto :continue
call :mainloop %1
shift
goto :commandlineloop
:continue
echo.
pause
goto :eof

::main loop we run for each command line arg of the script
:mainloop
set folderpath=
if "%~1"=="" (
  echo Drag and drop files or folders onto this script.
  goto :eof
)
set folderpath=%~1
echo "%1" | find /I ".mp3" && (
  goto :fileonly
)
echo "%1" | find /I ".wav" && (
  goto :fileonly
)

::folders
echo.
echo.
echo Processing folder %1
echo ________________________________________________________________________________
echo.

::we need to find the last folder level in the folderpath
::batch scripting is horrible so we need to use a hacky way to get the last token
::(from http://stackoverflow.com/questions/5473840/last-token-in-batch-variable)
set temp_string=%~1
set count=0

::iterate parsing the tokens and trimming the string until it's empty, while counting how many loops
:loopcounter
for /F "tokens=1* delims=\" %%a in ( "%temp_string%" ) do (
  set /A count+=1
  set temp_string=%%b
  goto loopcounter
)
for /F "tokens=%count% delims=\" %%i in ( "%~1" ) do set folder=%%i

::append the top level folder name with "-optimized" so we create a new folder tree
for /R "%folderpath%" %%i in (*.mp3 *.wav) do (
  set sourcepath=%%~di%%~pi
  set destpath=!sourcepath:%folder%=%folder%-optimized!
  md "!destpath!"
  ffmpeg -i "%%~fi" -acodec libmp3lame -aq 8 -ar 32000 -ac 1 "!destpath!%%~ni.mp3"
)
goto :eof

::individual files
:fileonly
for %%i in ("%folderpath%") do (
  ffmpeg -i "%folderpath%" -acodec libmp3lame -aq 8 -ar 32000 -ac 1 "%%~di%%~pi%%~ni-optimized.mp3"
)
 

There are several neat little tricks here. Multiple folders can be dragged onto the script because it uses SHIFT to work through each command line argument. The next hurdle is to get the last part of the folder name(s) being dragged. Though this would be simple in any Unix-like shell, but to do this in batch without relying on any additional tools proved to be quite tricky. Though tokens can be parsed by FOR, finding the last one (which we need) requires us to count how many tokens there are. Only then can the last one be selected. The folder name string substitution is done by the SET command (also used in my file renaming script). Delayed variable expansion means that the variables between the the exclamation marks are evaluated once per loop rather than the default of once per script execution (more info here). I hadn’t realised until today that you can create a folder structure several layers deep with a single MD command. This avoids having to iterate through all subfolders – we can use FOR’s /R switch to handle the recursion in a single line. For more information on some of the variables containing tildes like %%~pi and %%~ni, try running FOR /?. The script also first runs the FFmpeg subroutine with ECHO in front of the commands so you can double-check the syntax before proceeding.

There are of course much more efficient ways of compressing spoken word content than MP3 these days – AAC-HEv2 for instance, but that will rule out all but the latest audio playback devices.
The source MP3 recordings were in 44.1kHz mono @ 128Kbps. This was definitely overkill for speech. Just by opting for 64Kbps I could halve that. However I couldn’t drop the sample rate below 32kHz, as this is the lowest legal limit of MPEG-1 layer III. This info is tricky to find but the LAME encoder reveals it in its extended help:

MPEG-1   layer III sample frequencies (kHz):  32  48  44.1
bitrates (kbps): 32 40 48 56 64 80 96 112 128 160 192 224 256 320
MPEG-2   layer III sample frequencies (kHz):  16  24  22.05
bitrates (kbps):  8 16 24 32 40 48 56 64 80 96 112 128 144 160
MPEG-2.5 layer III sample frequencies (kHz):   8  12  11.025
bitrates (kbps):  8 16 24 32 40 48 56 64

 

I think it’s safe to assume that most MP3 players can handle variable bit rate. As far as I can remember only the first generation ones couldnt from early last decade – the sort of ones which only had around 64MB of storage. I don’t think excluding players this old is much of a concern.

Playing around with VBR quality settings in LAME we can see that with -V 9 we get a small file (12.9MB becomes 3.7MB) however it’s actually an MPEG-2 layer III file which as you can see above supports lower sample rates. I’m not certain of the wider compatibility of this sub-type of MP3 file, and besides it does sound considerably worse than the lowest MPEG-1 layer III settings which is –V 8 (12.9MB becomes 5.2MB). This proved to be the best compromise between size and quality.

Compiling x64/x86 FFmpeg on 64bit Windows with libfaac and libmp3lame

Once I had compiled FFmpeg for 32bit Windows, I discovered that it’s probably ten times more difficult to find information about doing the same with free tools on 64bit editions of Windows. A perfect topic for PCLOADLETTER then!

For building FFmpeg we must use the build environment MinGW-w64 which is a separate version of MinGW. The complication is that even when compiling natively you need to use configuration options as if you’re cross compiling (for host type x86_64-w64-mingw32). It’s not strictly necessary with all packages, but some will fail to build without these parameters. As a result you have to search around trying to find all the necessary configure commands for each package, and they’re not always identical. It’s a slow and frustrating process. What’s even more confusing, is that some builds of MinGW-w64 are targetted at 32bit, some 64bit, and some both. What is more, I had to try three different ones before I found one that could compile LAME without errors (though that could be LAME’s fault).

Most people will want a toolchain with the flexibility to create both x64 and x86 binaries, so that is what I shall describe in this guide.

On the MinGW-w64 downloads site browse to the Multilib Toolchains (Targetting Win32 and Win64) section, and download the latest megasoft78 binary build prefixed with mingw-w64-bin_x86_64-mingw. Extract the contents of this archive to the root of your C: drive (which at time of writing will create a folder named mingw64_4.5.2_multilib).

There is no installer – it’s not as automated as the 32bit distribution of MinGW. I spent a long time trying to compile LAME with the official MSYS build and eventually gave up, chosing instead to use a working one made by a third party. Download MSYS_MinGW_GCC_460_x86-x64_Full.7z from xhmikosr.1f0.de. Extract that archive into C:\mingw64_4.5.2_multilib so you have a subfolder in there named MSYS.

Update – I now realise that this archive also includes the whole GCC toolchain as well, but by then I’d already written the guide :)

Download the latest DirectX SDK. Install it, but only select the following component:
DirectX SDK installation options

This document provides useful background information to the uninitiated. Crucially it explains that when you compile with a particular host type defined, most configure scripts will look for a compiler whose filename is prefixed with that host type. So gcc.exe might be present in the toolchain distro as x86_64-w64-mingw32-gcc.exe. The toolchain I just recommended you download does not contain prefixes, but we shall need them since FFmpeg’s configure script expects them. On Windows Vista or later (which should cover most 64bit Windows systems) we can use mklink.exe to create symbolic links. We’ll also copy some missing DirectX headers into the toolchain and configure MSYS.

Start a Command Prompt as Administrator:

cd \mingw64_4.5.2_multilib\bin\
for %i in (*.exe) do mklink x86_64-w64-mingw32-%i %i
copy /y "%DXSDK_DIR%\Include\*.*" C:\mingw64_4.5.2_multilib\x86_64-w64-mingw32\include\
cd \mingw64_4.5.2_multilib\msys\postinstall
pi
 

This will launch the post-install script which will configure a filesystem mount for /mingw. When asked, enter your mingw installation path as c:/mingw64_4.5.2_multilib

Once that’s complete, launch the MSYS shell from your Administrator command prompt:

C:\mingw64_4.5.2_multilib\MSYS\msys.bat
 

Download the source .tar.gz files of:

Copy those downloaded files to C:\mingw64_4.5.2_multilib\msys\home\administrator (since you’re running in the Administrator user context). In the MSYS shell this is your home directory (cd ~).

In the MSYS shell, run:

tar xvfz faac-1.28.tar.gz
tar xvfz lame-3.98.4.tar.gz
tar xvfz ffmpeg-HEAD-6fd00e9.tar.gz
 

For a 64bit compile of FFmpeg with libfaac and libmp3lame:

cd ~/faac-1.28
./configure --prefix=/usr/local/x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --enable-static --disable-shared --with-mp4v2=no
make clean && make
make install
cd ..
cd lame-3.98.4
./configure --prefix=/usr/local/x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --enable-static --disable-shared --disable-decoder --enable-nasm
make clean && make
make install
cd ..
cd ffmpeg-HEAD-6fd00e9
CPPFLAGS="$CPPFLAGS -I/usr/local/x86_64-w64-mingw32/include" ./configure --extra-ldflags='-L/usr/local/x86_64-w64-mingw32/lib' --prefix=/usr/local/x86_64-w64-mingw32 --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-memalign-hack --enable-libmp3lame --enable-nonfree --enable-libfaac --arch=x86_64 --enable-runtime-cpudetect --enable-w32threads --cross-prefix=x86_64-w64-mingw32- --target-os=mingw32
make clean && make
make install
 

The compiled ffmpeg.exe will be in C:\mingw64_4.5.2_multilib\MSYS\local\x86_64-w64-mingw32\bin.

In summary what’s happening is we’re compiling FAAC without MP4v2 support (compilation halts if that’s enabled), and we’re making sure the binaries are stored in /usr/local/x86_64-w64-mingw32. Likewise for LAME. FFmpeg needs to be told where to find these new libraries (and headers too). We’re also installing it to /usr/local/x86_64-w64-mingw32, so as to keep x64 and x86 binaries separated.

 

For a 32bit compile of FFmpeg with libfaac and libmp3lame:

cd ~/faac-1.28
CFLAGS="-m32" CXXFLAGS="-m32" ./configure --prefix=/usr/local/i686-pc-mingw32 --host=x86_64-w64-mingw32 --enable-static --disable-shared --with-mp4v2=no
make clean && make
make install
cd ..
cd lame-3.98.4
CFLAGS="-m32" CXXFLAGS="-m32" ./configure --prefix=/usr/local/i686-pc-mingw32 --host=x86_64-w64-mingw32 --enable-static --disable-shared --disable-decoder --enable-nasm
make clean && make
make install
cd ..
cd ffmpeg-HEAD-6fd00e9
CPPFLAGS="$CPPFLAGS -I/usr/local/i686-pc-mingw32/include" ./configure --extra-cflags=-m32 --extra-ldflags='-m32 -L/usr/local/i686-pc-mingw32/lib' --prefix=/usr/local/i686-pc-mingw32 --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-memalign-hack --enable-libmp3lame --enable-nonfree --enable-libfaac --arch=x86_32 --enable-runtime-cpudetect --enable-w32threads --cross-prefix=x86_64-w64-mingw32- --target-os=mingw32
make clean && make
make install
 

The compiled ffmpeg.exe will be in C:\mingw64_4.5.2_multilib\MSYS\local\i686-pc-mingw32\bin.

This is pretty much the same as before, but CFLAGS=”-m32″ and CXXFLAGS=”-m32″ force the 64bit-native C and C++ compilers to produce 32bit binaries. I found that useful option at the bottom of this FFmpeg wiki page. As usual, FFmpeg has its own way of specifying most of these settings (except CPPFLAGS). It is also instructed to use 32bit libraries via –extra-ldflags=’-m32′.

 

Footnote

Until I gave up and used the MSYS distro from xhmikosr.1f0.de, LAME persistently failed to compile with the error undefined reference to `init_xrpow_core_sse’. I tried a newer version of NASM than 2.09.08, replacing nasm.exe with yasm.exe, using LAME 3.98.2 instead of 3.98.4, disabling NASM in the configure, using the Unix makefile, all to no avail. Apart from a problem someone had compiling a Mac universal binary (fixed by using compiler options I could not use with MinGW), the only other link I could find about this is here, and that’s also unsolved. Even taking the nasm.exe (which I notice is 32bit) from the working MSYS bundle and trying it with the SourceForge ‘official’ MSYS bundle, I cannot get LAME to compile. I had no such problem when using the normal MinGW on my 32bit PC from my previous post on this subject, despite compiling my own nasm.exe. If you have any insight into why this might be, please leave a comment!