Update – I discovered that the cross-compiled ARM build of FFmpeg cannot encode AC3 audio without severe artifacts. After a very long time spent recompiling with different options, trying static builds etc. I finally found that the Synology cross toolchain (GCC 4.2.1) appears to cause the problem. Compiling natively on a bootstrapped ARM Synology system with GCC 4.2.3 produces a working binary. However, I had to spend a long time re-working the method, particularly since you can’t run automake to build libshine on the Synology due to a dependency on a threaded version of Perl, which is missing from the Optware repo, and in turn is very tricky to compile. I have appended the ARM shared build guide to the end of this post.
This method will build FFmpeg with portable shared libraries (linked with relative paths) using a Ubuntu Desktop 12 VM. 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, libz, 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.
Although the unmodified source code will compile successfully for QorIQ CPUs, the FFmpeg binary will core dump when running any command on a video file. I contacted Synology Support for help with this issue. Their developers mentioned that they had needed to make numerous patches to the source of the version they used for DSM, and they guessed that the following one in particular was likely to be needed. This produced a working binary.
--- ffmpeg/libavcodec/ppc/dsputil_ppc.c 2012-02-17 18:20:07.000000000 +0000
+++ ffmpeg-patched/libavcodec/ppc/dsputil_ppc.c 2012-10-18 22:15:50.740992688 +0100
@@ -116,7 +116,11 @@
/* below the constraint "b" seems to mean "Address base register"
in gcc-3.3 / RS/6000 speaks. seems to avoid using r0, so.... */
+ #if 1
+ __asm__ volatile("dcbz %0, %1" : : "r" (fakedata_middle), "r" (zero));
+ #else
__asm__ volatile("dcbzl %0, %1" : : "b" (fakedata_middle), "r" (zero));
+ #endif
for (i = 0; i < 1024 ; i ++) {
if (fakedata[i] == (char)0)
Here is a patch to add libshine as an additional encoder to FFmpeg 1.1.1 which is particularly useful on ARM CPUs which lack an FPU (shine is an integer maths encoder).
diff -rupN ffmpeg-1.1.1/configure ffmpeg-1.1.1-shine/configure
--- ffmpeg-1.1.1/configure 2013-01-20 01:06:39.000000000 +0000
+++ ffmpeg-1.1.1-shine/configure 2013-02-05 13:46:30.000000000 +0000
@@ -214,6 +214,7 @@ External library support:
--enable-libpulse enable Pulseaudio input via libpulse [no]
--enable-librtmp enable RTMP[E] support via librtmp [no]
--enable-libschroedinger enable Dirac de/encoding via libschroedinger [no]
+ --enable-libshine enable fixed-point MP3 encoding via libshine [no]
--enable-libsoxr enable Include libsoxr resampling [no]
--enable-libspeex enable Speex de/encoding via libspeex [no]
--enable-libstagefright-h264 enable H.264 decoding via libstagefright [no]
@@ -1174,6 +1175,7 @@ CONFIG_LIST="
libpulse
librtmp
libschroedinger
+ libshine
libsoxr
libspeex
libstagefright_h264
@@ -1843,6 +1845,7 @@ libopus_decoder_deps="libopus"
libopus_encoder_deps="libopus"
libschroedinger_decoder_deps="libschroedinger"
libschroedinger_encoder_deps="libschroedinger"
+libshine_encoder_deps="libshine"
libspeex_decoder_deps="libspeex"
libspeex_encoder_deps="libspeex"
libstagefright_h264_decoder_deps="libstagefright_h264"
@@ -3843,6 +3846,7 @@ enabled libopus && require_pkg_config
enabled libpulse && require_pkg_config libpulse-simple pulse/simple.h pa_simple_new
enabled librtmp && require_pkg_config librtmp librtmp/rtmp.h RTMP_Socket
enabled libschroedinger && require_pkg_config schroedinger-1.0 schroedinger/schro.h schro_init
+enabled libshine && require_pkg_config shine shine/layer3.h L3_encode_frame
enabled libsoxr && require libsoxr soxr.h soxr_create -lsoxr
enabled libspeex && require libspeex speex/speex.h speex_decoder_init -lspeex
enabled libstagefright_h264 && require_cpp libstagefright_h264 "binder/ProcessState.h media/stagefright/MetaData.h
@@ -4264,6 +4268,7 @@ echo "libopus enabled ${libopu
echo "libpulse enabled ${libpulse-no}"
echo "librtmp enabled ${librtmp-no}"
echo "libschroedinger enabled ${libschroedinger-no}"
+echo "libshine enabled ${libshine-no}"
echo "libsoxr enabled ${libsoxr-no}"
echo "libspeex enabled ${libspeex-no}"
echo "libstagefright-h264 enabled ${libstagefright_h264-no}"
diff -rupN ffmpeg-1.1.1/libavcodec/allcodecs.c ffmpeg-1.1.1-shine/libavcodec/allcodecs.c
--- ffmpeg-1.1.1/libavcodec/allcodecs.c 2013-01-06 21:53:29.000000000 +0000
+++ ffmpeg-1.1.1-shine/libavcodec/allcodecs.c 2013-02-05 13:48:04.000000000 +0000
@@ -469,6 +469,7 @@ void avcodec_register_all(void)
REGISTER_ENCDEC (LIBGSM, libgsm);
REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms);
REGISTER_ENCDEC (LIBILBC, libilbc);
+ REGISTER_ENCODER(LIBSHINE, libshine);
REGISTER_ENCODER(LIBMP3LAME, libmp3lame);
REGISTER_ENCDEC (LIBOPENCORE_AMRNB, libopencore_amrnb);
REGISTER_DECODER(LIBOPENCORE_AMRWB, libopencore_amrwb);
diff -rupN ffmpeg-1.1.1/libavcodec/libshine.c ffmpeg-1.1.1-shine/libavcodec/libshine.c
--- ffmpeg-1.1.1/libavcodec/libshine.c 1970-01-01 00:00:00.000000000 +0000
+++ ffmpeg-1.1.1-shine/libavcodec/libshine.c 2013-02-05 13:49:39.000000000 +0000
@@ -0,0 +1,149 @@
+/*
+ * Interface to libshine for mp3 encoding
+ * Copyright (c) 2012 Paul B Mahol
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <shine/layer3.h>
+
+#include "libavutil/intreadwrite.h"
+#include "audio_frame_queue.h"
+#include "avcodec.h"
+#include "internal.h"
+#include "mpegaudio.h"
+#include "mpegaudiodecheader.h"
+
+#define BUFFER_SIZE (4096 * 20)
+
+typedef struct SHINEContext {
+ shine_config_t config;
+ shine_t shine;
+ uint8_t buffer[BUFFER_SIZE];
+ int buffer_index;
+ AudioFrameQueue afq;
+} SHINEContext;
+
+static av_cold int shine_encode_init(AVCodecContext *avctx)
+{
+ SHINEContext *s = avctx->priv_data;
+
+ if (avctx->channels <= 0 || avctx->channels > 2){
+ av_log(avctx, AV_LOG_ERROR, "only mono or stereo is supportedn");
+ return AVERROR(EINVAL);
+ }
+
+ L3_set_config_mpeg_defaults(&s->config.mpeg);
+ if (avctx->bit_rate)
+ s->config.mpeg.bitr = avctx->bit_rate / 1000;
+ if (L3_find_bitrate_index(s->config.mpeg.bitr) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "invalid bitraten");
+ return AVERROR(EINVAL);
+ }
+ s->config.mpeg.mode = avctx->channels == 2 ? STEREO : MONO;
+ s->config.wave.samplerate = avctx->sample_rate;
+ s->config.wave.channels = avctx->channels == 2 ? PCM_STEREO : PCM_MONO;
+ s->shine = L3_initialise(&s->config);
+ if (!s->shine)
+ return AVERROR(ENOMEM);
+ avctx->frame_size = samp_per_frame;
+ ff_af_queue_init(avctx, &s->afq);
+ return 0;
+}
+
+static int shine_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
+{
+ SHINEContext *s = avctx->priv_data;
+ MPADecodeHeader hdr;
+ unsigned char *data;
+ long written;
+ int ret, len;
+
+ if (frame)
+ data = L3_encode_frame(s->shine, frame->data[0], &written);
+ else
+ data = L3_flush(s->shine, &written);
+ if (written < 0)
+ return -1;
+ if (written > 0) {
+ if (s->buffer_index + written > BUFFER_SIZE) {
+ av_log(avctx, AV_LOG_ERROR, "internal buffer too smalln");
+ return AVERROR_BUG;
+ }
+ memcpy(s->buffer + s->buffer_index, data, written);
+ s->buffer_index += written;
+ }
+ if (frame) {
+ if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
+ return ret;
+ }
+
+ if (s->buffer_index < 4 || !s->afq.frame_count)
+ return 0;
+ if (avpriv_mpegaudio_decode_header(&hdr, AV_RB32(s->buffer))) {
+ av_log(avctx, AV_LOG_ERROR, "free format output not supportedn");
+ return -1;
+ }
+
+ len = hdr.frame_size;
+ if (len <= s->buffer_index) {
+ if ((ret = ff_alloc_packet2(avctx, avpkt, len)))
+ return ret;
+ memcpy(avpkt->data, s->buffer, len);
+ s->buffer_index -= len;
+ memmove(s->buffer, s->buffer + len, s->buffer_index);
+
+ ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
+ &avpkt->duration);
+
+ avpkt->size = len;
+ *got_packet_ptr = 1;
+ }
+ return 0;
+}
+
+static av_cold int shine_encode_close(AVCodecContext *avctx)
+{
+ SHINEContext *s = avctx->priv_data;
+
+ ff_af_queue_close(&s->afq);
+ L3_close(s->shine);
+ return 0;
+}
+
+static const int libshine_sample_rates[] = {
+ 44100, 48000, 32000, 0
+};
+
+AVCodec ff_libshine_encoder = {
+ .name = "libshine",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .id = CODEC_ID_MP3,
+ .priv_data_size = sizeof(SHINEContext),
+ .init = shine_encode_init,
+ .encode2 = shine_encode_frame,
+ .close = shine_encode_close,
+ .capabilities = CODEC_CAP_DELAY,
+ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16P,
+ AV_SAMPLE_FMT_NONE },
+ .supported_samplerates = libshine_sample_rates,
+ .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
+ AV_CH_LAYOUT_STEREO,
+ 0 },
+ .long_name = NULL_IF_CONFIG_SMALL("libshine MP3 (MPEG audio layer 3)"),
+};
diff -rupN ffmpeg-1.1.1/libavcodec/Makefile ffmpeg-1.1.1-shine/libavcodec/Makefile
--- ffmpeg-1.1.1/libavcodec/Makefile 2013-01-06 21:53:29.000000000 +0000
+++ ffmpeg-1.1.1-shine/libavcodec/Makefile 2013-02-05 13:49:09.000000000 +0000
@@ -685,6 +685,7 @@ OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER)
libschroedinger.o
OBJS-$(CONFIG_LIBSCHROEDINGER_ENCODER) += libschroedingerenc.o
libschroedinger.o
+OBJS-$(CONFIG_LIBSHINE_ENCODER) += libshine.o
OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o
OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o audio_frame_queue.o
OBJS-$(CONFIG_LIBSTAGEFRIGHT_H264_DECODER)+= libstagefright.o
#-----set up Synology toolchain
cd ~/Downloads
export DL_PATH="http://sourceforge.net/projects/dsgpl/files/DSM%204.1%20Tool%20Chains"
#----------------------------------------------------
#-----NOW PASTE ONE OF THE FOLLOWING THREE BLOCKS TO THE TERMINAL, DEPENDING ON YOUR TARGET CPU TYPE
#-----Marvell Kirkwood mv6281/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
wget "${DL_PATH}/Marvell%2088F628x%20Linux%202.6.32/gcc421_glibc25_88f6281-GPL.tgz"
tar xvzf gcc421_glibc25_88f6281-GPL.tgz
export CROSS_PREFIX=arm-none-linux-gnueabi
export TOOLCHAIN=/usr/local/${CROSS_PREFIX}
export MARCH=-march=armv5te
export LAME_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${CROSS_PREFIX} --build=x86_64-linux-gnu --enable-shared --disable-static --disable-decoder"
export SSL_CONFIG="./Configure.syno --prefix=${TOOLCHAIN} threads shared linux-elf-armle"
#-----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
#-----zbmv decoder won't cross compile for some reason so it is disabled: https://ffmpeg.org/trac/ffmpeg/ticket/1794
#-----something changed in FFmpeg 1.1.1's 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-vfp --disable-neon --disable-debug --enable-pthreads --enable-libshine --enable-librtmp --enable-libass --disable-encoder=zmbv --pkg-config=pkg-config --extra-version=compiled_by_patters_for_Serviio"
#-----sudo apt-get automake
#-----sudo apt-get libtool
wget https://github.com/savonet/shine/zipball/master
unzip master
cd savonet-shine-*
./bootstrap
cd ..
#-----Intel CPUs used in Synology products are all 64bit and SSSE3 capable but existing DSM libs are 32bit, so use the i686 toolchain rather than x86_64
wget "${DL_PATH}/Intel%20x86%20Linux%203.2.11%20%28Pineview%29/gcc421_glibc236_x86-GPL.tgz"
tar xvzf gcc421_glibc236_x86-GPL.tgz
export CROSS_PREFIX=i686-linux-gnu
export TOOLCHAIN=/usr/local/${CROSS_PREFIX}
export LAME_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${CROSS_PREFIX} --build=x86_64-linux-gnu --enable-shared --disable-static --disable-decoder --enable-nasm"
export SSL_CONFIG="./Configure.syno --prefix=${TOOLCHAIN} threads shared linux-generic32"
#-----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-ssse3 --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 --pkg-config=pkg-config --extra-version=compiled_by_patters_for_Serviio"
sudo apt-get install yasm
#-----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
wget "${DL_PATH}/PowerPC%20QorIQ%20Linux%202.6.32/gcc4374_eglibc2874_qoriq-GPL.tgz"
tar xvzf gcc4374_eglibc2874_qoriq-GPL.tgz
export CROSS_PREFIX=powerpc-none-linux-gnuspe
export TOOLCHAIN=/usr/local/${CROSS_PREFIX}
export MARCH="-mcpu=8548 -mhard-float -mfloat-gprs=double"
export LAME_CONFIG="./configure --prefix=${TOOLCHAIN} --host=${CROSS_PREFIX} --build=x86_64-linux-gnu --enable-shared --disable-static --disable-decoder"
export SSL_CONFIG="./Configure.syno --prefix=${TOOLCHAIN} threads shared linux-ppc"
#-----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 --pkg-config=pkg-config --extra-version=compiled_by_patters_for_Serviio"
#----------------------------------------------------
#-----script continues
sudo mv ${CROSS_PREFIX} /usr/local
export AR=${TOOLCHAIN}/bin/${CROSS_PREFIX}-ar
export CC=${TOOLCHAIN}/bin/${CROSS_PREFIX}-gcc
export CXX=${TOOLCHAIN}/bin/${CROSS_PREFIX}-g++
export LD=${TOOLCHAIN}/bin/${CROSS_PREFIX}-ld
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 sources for certain libraries
wget http://dl.dropbox.com/u/1188556/DSM-source.tgz
tar xvzf DSM-source.tgz
cd DSM-source
#-----libz shared lib (toolchain only has static lib)
cd zlib-1.2
./configure --prefix=${TOOLCHAIN}
make
make install
cd ..
#-----lame shared lib
cd lame-398
$LAME_CONFIG
make
make install
cd ..
#-----shine shared lib for ARM
[ "${CROSS_PREFIX}" == "arm-none-linux-gnueabi" ] && mv ../savonet-shine-* .
[ "${CROSS_PREFIX}" == "arm-none-linux-gnueabi" ] && cd savonet-shine-*
[ "${CROSS_PREFIX}" == "arm-none-linux-gnueabi" ] && ./configure --prefix=${TOOLCHAIN} --host=${CROSS_PREFIX} --build=x86_64-linux-gnu --enable-shared --disable-static
[ "${CROSS_PREFIX}" == "arm-none-linux-gnueabi" ] && make
[ "${CROSS_PREFIX}" == "arm-none-linux-gnueabi" ] && make install
[ "${CROSS_PREFIX}" == "arm-none-linux-gnueabi" ] && cd ..
#-----openssl shared lib (Synology seem to have tweaked the source for each CPU)
cd openssl-1.0.x-${CROSS_PREFIX}
$SSL_CONFIG
make
make install
cd ..
#-----expat shared lib
cd expat-2.x
./configure --prefix=${TOOLCHAIN} --host=${CROSS_PREFIX} --build=x86_64-linux-gnu --enable-shared --disable-static
make
make install
cd ..
#-----freetype shared lib
cd freetype-2.3.7
./configure --prefix=${TOOLCHAIN} --host=${CROSS_PREFIX} --build=x86_64-linux-gnu --enable-shared --disable-static
make
make install
cd ..
#-----finished building DSM-bundled libs
cd ..
#-----fribidi shared lib
wget http://fribidi.org/download/fribidi-0.19.5.tar.bz2
tar xvjf fribidi-0.19.5.tar.bz2
cd fribidi-0.19.5
#-----patch fribidi source since it won't compile - some sort of page size function is no longer available
#-----error on ARM and Intel: fribidi-run.c:70: error: 'PAGE_SIZE' undeclared (first use in this function)
#-----error on QorIQ: include/asm/kdump.h:41: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void'
#-----clues found here:
#-----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
sed -i "s|include <asm/page.h>|include <unistd.h>n# define PAGE_SIZE sysconf(_SC_PAGESIZE)|" lib/common.h
./configure --prefix=${TOOLCHAIN} --host=${CROSS_PREFIX} --build=x86_64-linux-gnu --enable-shared --disable-static
make
make install
cd ..
#-----fontconfig shared lib
wget http://freedesktop.org/software/fontconfig/release/fontconfig-2.10.91.tar.gz
tar xvzf fontconfig-2.10.91.tar.gz
cd fontconfig-2.10.91
LDFLAGS=-Wl,-rpath=\'\$\$ORIGIN\' ./configure --prefix=${TOOLCHAIN} --host=${CROSS_PREFIX} --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 http://libass.googlecode.com/files/libass-0.10.1.tar.gz
tar xvzf libass-0.10.1.tar.gz
cd libass-0.10.1
LDFLAGS=-Wl,-rpath=\'\$\$ORIGIN\' ./configure --prefix=${TOOLCHAIN} --host=${CROSS_PREFIX} --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 ..
#-----librtmp shared lib
wget http://download.serviio.org/opensource/rtmpdump.tar.gz
tar xvfz rtmpdump.tar.gz
cd rtmpdump
make CROSS_COMPILE=${TOOLCHAIN}/bin/${CROSS_PREFIX}- SYS=posix prefix=${TOOLCHAIN} INC=-I${TOOLCHAIN}/include
make install prefix=${TOOLCHAIN}
cd ..
#-----FFmpeg
wget http://www.ffmpeg.org/releases/ffmpeg-1.1.1.tar.gz
tar xvzf ffmpeg-1.1.1.tar.gz
cd ffmpeg-1.1.1
#-----patch in libshine support for ARM builds
[ "${CROSS_PREFIX}" == "arm-none-linux-gnueabi" ] && wget http://dl.dropbox.com/u/1188556/ffmpeg-1.1.1-shine.patch
[ "${CROSS_PREFIX}" == "arm-none-linux-gnueabi" ] && patch --verbose -p1 < ffmpeg-1.1.1-shine.patch
#-----fetch latest wrapper source code from richardpl's FFmpeg fork
[ "${CROSS_PREFIX}" == "arm-none-linux-gnueabi" ] && wget --no-check-certificate https://raw.github.com/richardpl/FFmpeg/shine/libavcodec/libshine.c -O libavcodec/libshine.c
#-----ARM-specific fixed point maths modification for mpeg audio encoder
[ "${CROSS_PREFIX}" == "arm-none-linux-gnueabi" ] && sed -i "s/^#define USE_FLOATS//" libavcodec/mpegaudioenc.c
#-----QorIQ-specific fix provided by Synology Support
[ "${CROSS_PREFIX}" == "powerpc-none-linux-gnuspe" ] && wget http://dl.dropbox.com/u/1188556/ffmpeg-synology-qoriq.patch
[ "${CROSS_PREFIX}" == "powerpc-none-linux-gnuspe" ] && patch --verbose -p1 < ffmpeg-synology-qoriq.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
LDFLAGS=-Wl,-rpath=\'\$\$ORIGIN/../lib:\$\$ORIGIN\' ${FF_CONFIG}
#-----external libs (librtmp, libass) don't seem to link correctly as shared libs
#-----on QorIQ and Intel toolchains without this fix (check with objdump -x)
[ "${CROSS_PREFIX}" == "arm-none-linux-gnueabi" ] || sed -r -i 's%(^LDFLAGS.*)\$\(LDFLAGS\)%\1-Wl,-rpath=z888z\$\$ORIGIN/../libz888z%' common.mak; sed -i "s/z888z/'/g" common.mak
make
make install
cd ..
mkdir native-${CROSS_PREFIX}
cd native-${CROSS_PREFIX}
cp ${TOOLCHAIN}/bin/ffmpeg .
cp ${TOOLCHAIN}/lib/libass.so.4 .
cp ${TOOLCHAIN}/lib/libavcodec.so.54 .
cp ${TOOLCHAIN}/lib/libavdevice.so.54 .
cp ${TOOLCHAIN}/lib/libavfilter.so.3 .
cp ${TOOLCHAIN}/lib/libavformat.so.54 .
cp ${TOOLCHAIN}/lib/libavutil.so.52 .
cp ${TOOLCHAIN}/lib/libfontconfig.so.1 .
cp ${TOOLCHAIN}/lib/libfribidi.so.0 .
cp ${TOOLCHAIN}/lib/librtmp.so.0 .
cp ${TOOLCHAIN}/lib/libswresample.so.0 .
cp ${TOOLCHAIN}/lib/libswscale.so.2 .
[ "${CROSS_PREFIX}" == "arm-none-linux-gnueabi" ] && cp ${TOOLCHAIN}/lib/libshine.so.1 .
sudo chown root:root *
cd ..
mkdir oldDSM
cd oldDSM
cp ${TOOLCHAIN}/lib/libz.so.1 .
cp ${TOOLCHAIN}/lib/libcrypto.so.1.0.0 .
cp ${TOOLCHAIN}/lib/libssl.so.1.0.0 .
cp ${TOOLCHAIN}/lib/libmp3lame.so.0 .
cp ${TOOLCHAIN}/lib/libfreetype.so.6 .
cp ${TOOLCHAIN}/lib/libexpat.so.1 .
sudo chown root:root *
cd ..
Native compile for ARM systems
Here is the method to natively compile FFmpeg with libshine and libass, with shared libraries rather than static. It transpires that the cross compiled build has a broken AC3 encoder which produces crackling and muffled audio streams. The guide assumes a bootstrapped NAS with the optware-devel tools installed. See my much earlier blog post for details of how to set that up, since there are some pitfalls. I haven’t run through and tested the whole sequence – I have assembled this from hundreds of lines of notes I made while working – but I’m publishing it here to help others, and to refer to in future when I need to build newer FFmpeg revisions for future Serviio releases.
#-----on a bootstrapped system that's since had its DSM upgraded the path has been reset
#export PATH=/opt/bin:/opt/sbin:$PATH
#-----fetch headers for zlib, OpenSSL, LAME, freetype2, and expat libraries obtained by compiling the DSM 4.1 included versions from source, plus ncurses headers from Synology ARM cross toolchain
cd /tmp
mkdir include
cd include
wget http://dl.dropbox.com/u/1188556/synology-armv5te-headers.tgz
tar xvzf synology-armv5te-headers.tgz
#-----this archive also contains pkgconfig definitions for DSM's existing versions of libcrypto, libssl and freetype2, edited to fit requirements
#-----this will allow librtmp to link to DSM's existing OpenSSL libraries, and libass to link to DSM's bundled freetype2 and expat libraries
cp *.pc /opt/lib/pkgconfig
cd /volume1/@tmp
#-----fetch savonet-shine source which has already had the bootstrap script run on a Linux system with automake
#-----on the Linux system you would need to run:
#sudo apt-get automake
#sudo apt-get libtool
#wget https://github.com/savonet/shine/zipball/master
#unzip master
#cd savonet-shine-*
#./bootstrap
#cd ..
#-----but here's one I made earlier:
wget http://dl.dropbox.com/u/1188556/savonet-shine-43c74e7.tgz
tar xvzf savonet-shine-43c74e7.tgz
cd savonet-shine-43c74e7
./configure --prefix=/opt --enable-shared --disable-static
make
#-----don't worry about the repeated message #warning NO MULT FILE FOR ARCHITECTURE - USING GENERIC MATH
#-----the include for mult_sarm_gcc.h (optimized ARM maths in assembler) is commented out in src/lib/types.h
#-----the comment mentions that fixing this is on the to-do list, so it can't be helped
make install
cd ..
#-----fetch libRTMP source
wget http://download.serviio.org/opensource/rtmpdump.tar.gz
tar xvfz rtmpdump.tar.gz
cd rtmpdump
#-----the following options will force it to use the existing OpenSSL libs thanks to the imported headers
make SYS=posix prefix=/opt INC=-I/tmp/include XLDFLAGS=-L/lib
make install prefix=/opt
cp -R /opt/include/librtmp /tmp/include
#-----remove unsupported URL line from pkgconfig/librtmp.pc
#-----pkg-config --exists --print-errors librtmp
sed -i -e '/^URL/d' /opt/lib/pkgconfig/librtmp.pc
cd ..
#-----fetch fribidi source
wget http://fribidi.org/download/fribidi-0.19.5.tar.bz2
tar xvjf fribidi-0.19.5.tar.bz2
cd fribidi-0.19.5
#-----patch fribidi source since it won't compile on ARM
#-----fribidi-run.c:70: error: 'PAGE_SIZE' undeclared (first use in this function)
#-----clues found here:
#-----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
sed -i "s|include <asm/page.h>|include <unistd.h>\n# define PAGE_SIZE sysconf(_SC_PAGESIZE)|" lib/common.h
./configure --prefix=/opt --enable-shared --disable-static
make
make install
cd ..
#-----fetch fontconfig source
wget http://freedesktop.org/software/fontconfig/release/fontconfig-2.10.91.tar.gz
tar xvzf fontconfig-2.10.91.tar.gz
cd fontconfig-2.10.91
LDFLAGS=-Wl,-rpath='$$ORIGIN' ./configure --prefix=/opt --enable-shared --disable-static
#-----correct some non-standard library linking behaviour
sed -i "s/^hardcode_into_libs=yes/hardcode_into_libs=no/" libtool
sed -i "s|^sys_lib_search_path_spec="/opt/lib/gcc/arm-none-linux-gnueabi/4.2.3 /opt/arm-none-linux-gnueabi/lib /opt/lib /lib /usr/lib"|sys_lib_search_path_spec="/lib /usr/lib /opt/lib/gcc/arm-none-linux-gnueabi/4.2.3 /opt/arm-none-linux-gnueabi/lib /opt/lib"|" libtool
make
make install
cd ..
#-----fetch libass source
wget http://libass.googlecode.com/files/libass-0.10.1.tar.gz
tar xvzf libass-0.10.1.tar.gz
cd libass-0.10.1
export CFLAGS=-I/tmp/include
LDFLAGS=-Wl,-rpath='$$ORIGIN' ./configure --prefix=/opt --enable-shared --disable-static
#-----correct some non-standard library linking behaviour
sed -i "s/^hardcode_into_libs=yes/hardcode_into_libs=no/" libtool
sed -i "s|^sys_lib_search_path_spec="/opt/lib/gcc/arm-none-linux-gnueabi/4.2.3 /opt/arm-none-linux-gnueabi/lib /opt/lib /lib /usr/lib"|sys_lib_search_path_spec="/lib /usr/lib /opt/lib/gcc/arm-none-linux-gnueabi/4.2.3 /opt/arm-none-linux-gnueabi/lib /opt/lib"|" libtool
make
make install
cd ..
#-----fetch exact FFmpeg source version that Serviio requires
wget http://www.ffmpeg.org/releases/ffmpeg-1.1.1.tar.gz
tar xvzf ffmpeg-1.1.1.tar.gz
cd ffmpeg-1.1.1
#-----libshine patch by richardpl posted in FFmpeg ticket which I raised, applied to ffmpeg-1.1.1 by hand, then diffed to make patch file
#-----https://ffmpeg.org/trac/ffmpeg/ticket/1457
wget http://dl.dropbox.com/u/1188556/ffmpeg-1.1.1-shine.patch
patch -p1 --verbose < ffmpeg-1.1.1-shine.patch
#-----fetch latest wrapper source code from richardpl's FFmpeg fork
wget --no-check-certificate https://raw.github.com/richardpl/FFmpeg/shine/libavcodec/libshine.c -O libavcodec/libshine.c
#-----ARM-specific fixed point maths modification for mpeg audio encoder, mentioned in same ticket
sed -i "s/^#define USE_FLOATS//" libavcodec/mpegaudioenc.c
#-----FFmpeg configure parameters for native compile with shared libraries
#-----something changed in FFmpeg 1.1.1's 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 --prefix=/opt --extra-cflags=-I/tmp/include --enable-shared --disable-static --enable-pic --disable-ffplay --disable-ffserver --disable-vfp --disable-neon --disable-debug --enable-pthreads --enable-libshine --enable-librtmp --enable-libass --extra-version=compiled_by_patters_for_Serviio"
#-----set library linker to use relative library search path (../lib:.)
#-----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
LDFLAGS=-Wl,-rpath='$$ORIGIN/../lib:$$ORIGIN' ${FF_CONFIG}
make
make install
mkdir /volume1/@tmp/binaries
cd /volume1/@tmp/binaries
mkdir bin
mkdir lib
cp /opt/bin/ffmpeg bin
cp /opt/lib/libass.so.4 lib
cp /opt/lib/libavcodec.so.54 lib
cp /opt/lib/libavdevice.so.54 lib
cp /opt/lib/libavfilter.so.3 lib
cp /opt/lib/libavformat.so.54 lib
cp /opt/lib/libavutil.so.52 lib
cp /opt/lib/libfontconfig.so.1 lib
cp /opt/lib/libfribidi.so.0 lib
cp /opt/lib/librtmp.so.0 lib
cp /opt/lib/libshine.so.1 lib
cp /opt/lib/libswresample.so.0 lib
cp /opt/lib/libswscale.so.2 lib
tar -cvf ffmpeg-syno-armv5tel.tar *
gzip ffmpeg-syno-armv5tel.tar
mv ffmpeg-syno-armv5tel.tar.gz ffmpeg-syno-armv5tel.tgz
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).
~$ ldd /volume1/@appstore/Serviio/bin/ffmpeg
libavdevice.so.54 => /volume1/@appstore/Serviio/bin/../lib/libavdevice.so.54 (0x40026000)
libavfilter.so.3 => /volume1/@appstore/Serviio/bin/../lib/libavfilter.so.3 (0x40038000)
libavformat.so.54 => /volume1/@appstore/Serviio/bin/../lib/libavformat.so.54 (0x40095000)
libavcodec.so.54 => /volume1/@appstore/Serviio/bin/../lib/libavcodec.so.54 (0x401db000)
libswresample.so.0 => /volume1/@appstore/Serviio/bin/../lib/libswresample.so.0 (0x40f36000)
libswscale.so.2 => /volume1/@appstore/Serviio/bin/../lib/libswscale.so.2 (0x40f50000)
libavutil.so.52 => /volume1/@appstore/Serviio/bin/../lib/libavutil.so.52 (0x40f90000)
libm.so.6 => /lib/libm.so.6 (0x40fcc000)
libpthread.so.0 => /lib/libpthread.so.0 (0x4107b000)
libc.so.6 => /lib/libc.so.6 (0x4109b000)
librt.so.1 => /lib/librt.so.1 (0x411ca000)
libass.so.4 => /volume1/@appstore/Serviio/bin/../lib/libass.so.4 (0x411d9000)
librtmp.so.0 => /volume1/@appstore/Serviio/bin/../lib/librtmp.so.0 (0x4120b000)
libz.so.1 => /lib/libz.so.1 (0x4122a000)
libshine.so.1 => /volume1/@appstore/Serviio/bin/../lib/libshine.so.1 (0x41247000)
/lib/ld-linux.so.3 (0x40000000)
libfreetype.so.6 => /lib/libfreetype.so.6 (0x41259000)
libfribidi.so.0 => /volume1/@appstore/Serviio/bin/../lib/libfribidi.so.0 (0x41318000)
libfontconfig.so.1 => /volume1/@appstore/Serviio/bin/../lib/libfontconfig.so.1 (0x41337000)
libssl.so.1.0.0 => /lib/libssl.so.1.0.0 (0x41386000)
libcrypto.so.1.0.0 => /lib/libcrypto.so.1.0.0 (0x413d2000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x4156d000)
libexpat.so.1 => /lib/libexpat.so.1 (0x41581000)
libdl.so.2 => /lib/libdl.so.2 (0x415a8000)

keep up the great work on serviio, i hope you get something going for the PPC cpu for synology soon. are synology assiting you? i hope they are!
Not yet. I have raised a support request, so we shall see…
What’s ur ticket number ill send one to them emphasizing your ticket lol
They suggested a patch which seems to have done the trick. Serviio package to follow once it’s been tested…
Can someone post an already compiled version of ffmpeg with this shine lib?
Sorry. The version for ARM
Hi, I’d like to setup some kind of automatic (via cron job) reencoding of dreambox .ts-files (dvb-c) for later watching on the iPad. On OSX I use the following command “ffmpeg -i input.ts -vcodec libx264 -vprofile high -preset faster -b:v 2000k -vf scale=-1:720 -maxrate 10M -bufsize 10M -threads 0 -acodec libvo_aacenc -ab 196k output.mp4″ which gives good results.
I have an DS412+ with Atom. I know it will take maybe days for one movie to reencode, but I would not care, if it would run in background.
Do you think that is possible on DS412+? Unfortunately I don’t have the skills for x-compiling something and setting the right compiler flags, etc. – I tried, but I now know my limits :)
Could you upload a compiled current version of ffmpeg with all the codecs (especially X264) the osx version of the ffmpeg.org site has?
This would be GREAT !!! :)
+1
Great, this worked for me. I built under xubuntu 12.10 and built for the DS211j. I can successfully transcode my FLAC collection to mp3 to take on the go with my android.
Hello, I don’t have any Linux experience but I need tom compile ffmpeg to support video streaming on my Intel Synology NAS.
I followed this note under a Ubuntu 12 VM (using Oracle VM).
The process seems to work correctly but I don’t have any ffmpeg file created.
Is there something missing to compile it ?
I’m sorry, this might seems stupid for Linux geek… ;o(
Everything seem just fine ’til the end…
(I run it with sudo then as root)…
root@ubuntu:~/Downloads/DSM-source/ffmpeg# export CFLAGS=”-I${TOOLCHAIN}/include”
root@ubuntu:~/Downloads/DSM-source/ffmpeg# make
Makefile:2: config.mak: No such file or directory
Makefile:47: /common.mak: No such file or directory
Makefile:89: /libavutil/Makefile: No such file or directory
Makefile:89: /library.mak: No such file or directory
Makefile:169: /doc/Makefile: No such file or directory
Makefile:170: /tests/Makefile: No such file or directory
make: *** No rule to make target `/tests/Makefile’. Stop.
root@ubuntu:~/Downloads/DSM-source/ffmpeg# make install
Makefile:2: config.mak: No such file or directory
Makefile:47: /common.mak: No such file or directory
Makefile:89: /libavutil/Makefile: No such file or directory
Makefile:89: /library.mak: No such file or directory
Makefile:169: /doc/Makefile: No such file or directory
Makefile:170: /tests/Makefile: No such file or directory
make: *** No rule to make target `/tests/Makefile’. Stop.
root@ubuntu:~/Downloads/DSM-source/ffmpeg#
Any way to fix that or find how to ?
Thanks in advance for your help.
I tried many times, many different ways but I’ve been unable to compile an INTEL version.
I created a VM (VirtualBOX) with Ubuntu 12.10, 10.04 (64bits AND 32bits) and never been able to pass the librtmp & ffmpeg compilation.
I searched on Internet and already spend to much hours ;o(
If anyone could share an “how to”, this will be just fantastic !
This way anyone could compile…
If not, do anybody will be nice enough to share an INTEL version ?
PS It will be used for Subsonic and video support ;o)
It’s Christmas after all !!!
Pingback: Serviio 1.1 package for Synology NAS « PC LOAD LETTER
Article below gives good info to build ffmpeg for ARM with fixed-point encoders: http://bernaerts.dyndns.org/dns325/249-dns325-ffp7-ffmpeg-sox-x264-lame-shineenc-fdkaac-twolame-opus
Thanks !!!!
But I need x86-64 :o(
I will give a look anyway.
What I like about all this Serviio and Synology business is WHAT DOES IT ALL MEAN????
I have a Synology NAS, I have a Samsung Smart TV – I want the F**ker to play Xvid, .MKV – I heard Serviio would help me achieve this. But I’ll be f**ked if I can follow your instructions / find the links to where the files reside.
I admit I might be a bit dyslexic and have the attention of a gnat, but two hours in I haven’t a f**king clue why I can’t get things working. I need you to provide pictures, step by step instruction, links to files, instructions on where to save them, instruction of which ones to download first and install first, if I need to extract them, where to extract them, how to get the Synology NAS to act upon the information. No abriviation, no block paragraph’s. Even a youtube video would be helpful.
Or if you think I need to direct my frustrations at Synology please let me know.
I’m afraid I don’t have time to record YouTube videos for you. The intended audience for my posts is a reasonably technical one. If you are only interested in running Serviio, this particular post is not for you – it’s intended to show other technically-minded people how I compiled FFmpeg so as to help other aspiring Linux hobbyists. For running Serviio on Synology you want this post:
http://pcloadletter.co.uk/2012/01/25/serviio-syno-package/
Hello Patters,
there is a missed characted ‘\’ in Native compile for ARM systems line 60. correct line is:
sed -i “s|include |include \n# define PAGE_SIZE sysconf(_SC_PAGESIZE)|” lib/common.h
Thanks, post corrected. It’s entirely possible there are some more errors in there. When I last updated it I had an issue in the WordPress editor and had to revert to a draft, whereupon WordPress helpfully mangled the syntax of the whole thing by HTML encoding the entire post. It made a real mess, and the only way back was the run the post back through a free online HTML decoder – but I guess it wasn’t perfect.
@patters: is it possible for you to add libx264 support ?
(including on your serviio package since I do use it on my NAS) ?
Juste a small note, I would like to use the following recommended transcode command for Apple (HFS) : “ffmpeg -ss %o -t %d -i %s -async 1 -b %bk -s %wx%h -ar 44100 -ac 2 -v 0 -f mpegts -vcodec libx264 -preset superfast -acodec libmp3lame -threads 0 -”
The licence seems to prohibit this – see point 18 here:
http://www.ffmpeg.org/legal.html
I’ll wait and see how Zip works this out for the next version of Serviio. I gather that iOS device support is likely, which will require this.