Tag Archives: FFmpeg

Compiling FFmpeg for Windows with libfaac and libmp3lame

Having realised how simple it is to compile stuff on my Synology NAS I decided to finally get something built on Windows using free tools. It’s not really much different, but I had to do a lot of searching to finally gather all the necessary configure parameters.

First we need to set up the build environment. MinGW stands for ‘Minimalist GNU for Windows’. Download the MinGW-get installer, which will install everything you’ll need including MSYS which is a Unix shell complete with all the essential binaries. Run the MinGW-get installer and select Download latest repository catalogs.
In the options add the C++ compiler (needed for FAAC) and select MSYS Basic System and MinGW Developer Toolkit.

Now download the source .tar.gz files of:

Launch MinGW Shell from the Start Menu.
Copy those downloaded files to C:\MinGW\msys\1.0\home\yourusername
For each one run:

tar xvfz packagename.tar.gz
 

Then in order, cd into each extracted directory and…

For NASM and yasm:

./configure
make
make install
 

For FAAC (we need to disable the mp4v2 option to avoid a nasty compiler error – took me a long time to discover):

./bootstrap CC='gcc -mno-cygwin'
./configure --prefix=/mingw --exec-prefix=/mingw --enable-static --disable-shared --with-mp4v2=no
make
make install
 

For LAME:

./configure --prefix=/mingw --exec-prefix=/mingw --enable-static --disable-shared --disable-decoder --enable-nasm
make
make install
 

For FFmpeg:

./configure --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-memalign-hack --enable-libmp3lame --enable-nonfree --enable-libfaac --arch=x86 --enable-runtime-cpudetect --enable-w32threads
make
make install
 

The compiled ffmpeg.exe will be in C:\MinGW\msys\1.0\local\bin

Update – I tried to set this up on my work PC which runs 64 bit Windows 7 and I discovered that it’s a world of pain, so I’ll have to amend this post once I solve it.

Advertisements

Serviio 0.5.2 DLNA server on Synology NAS

last updated 24/08/2011 – fixed typos in locale section
Serviio-Synology

This guide is now redundant – 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. Some of the more main-stream servers like Windows Media Player just brute-force everything to MPEG2 video and MP3 audio, which degrades quality and wastes power. Though some servers like Mezzmo are better and will play Matroska files, even they tend to transcode all audio to AC-3 regardless of source type. As a Java app Serviio will run on anything that has a JVM, and the media tool it relies on is the open source and therefore highly portable FFmpeg. All these design priorities make Serviio an ideal choice to run on a NAS device since, when paired with a renderer with good format support like a Sony Bluray Player, the NAS will barely ever be transcoding.

I was about to buy a new large external hard disk, but once I realised that Serviio could probably run on a NAS I started looking at one of these instead. Synology seemed to offer a lot of value and seemed to have the sort of user-community enjoyed by my old Linksys NSLU2, which I promptly sold on eBay for almost what I had paid for it in 2007. I considered the value DS110j model but I decided to go for the more expensive DS111 on the basis that the double CPU speed and RAM would probably be a wise move.

This guide outlines how to get Serviio 0.5.2 running on the Marvell Kirkwood ARM CPUs found in most of the 2011 product line-up, but Synology devices also exist with Freescale PowerPC and Intel Atom processors. The key problem is finding a Java virtual machine, but FFmpeg also needs compiling from source. This is because although there is an FFmpeg binary bundled with DSM 3.0, it’s too old and lacks support for features critical to Serviio. This guide could be used for other CPU architectures, but the compilation options for FFmpeg need adapting.

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.

Download the PuTTY SSH client.

Connect to your NAS’s IP address using SSH. Use the root account (same password as admin). I suggest that you perform the mod at the bottom of this post to enable colour directory listings and a more descriptive shell prompt which should reduce the chance of accidentally being in the wrong directory.

We need to install the development tools. Type:

ipkg install optware-devel
 

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

ipkg remove wget
cp /usr/syno/bin/wget /opt/bin
ipkg install wget-ssl
ipkg update
ipkg upgrade
ipkg install optware-devel
 

This time it will finish successfully.

Update – It seems that there is a serious problem with running ipkg on a clean install of DSM 3.1. This guide was written before it was released, and though I have since upgraded my Synology I haven’t encountered that issue, but there have been many comments about it. User mayk on the Synology forum seems to have the solution here. Use the extra wget verbosity switch to find out the exact package URL for the following two packages, then manually download them with wget and install:

cd /volume1/@tmp
ipkg install -verbose_wget libidn
wget url1
ipkg install -verbose_wget wget-ssl
wget url2
ipkg install filename1
ipkg install filename2
 

Next we need to install Lame MP3 encoder, providing libmp3lame which FFmpeg will be compiled to depend on, and the Nano text editor (much easier to use than vi):

ipkg install lame
ipkg install nano
 

JamVM is a JVM that gets mentioned a lot in connection with NAS systems, but it’s only Java 1.5, and Serviio needs version 1.6. Download the Java SE Embedded Runtime from Oracle, selecting the ARM v5 Linux version (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 may have changed since DSM 3.1 was released.

You will need to sign up to receive the download link by email. It’s free to use for non-commercial self-educational 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-1_6_0_21-fcs-b09-linux-arm-sflt-eabi-headless-27_sep_2010.tar.gz /volume1/@tmp
cd /volume1/@tmp
tar xvzf ejre-1_6_0_21-fcs-b09-linux-arm-sflt-eabi-headless-27_sep_2010.tar.gz
mkdir /opt/java
mv ejre1.6.0_21 /opt/java
 

Synology’s Linux build has no localisation 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:

#-----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/java/ejre1.6.0_21/bin
LD_LIBRARY_PATH=/opt/lib:${LD_LIBRARY_PATH}
JAVA_HOME=/opt/java/ejre1.6.0_21
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
 

At the last line make the changes in bold:

PATH=/opt/java/ejre1.6.0_21/bin:/opt/bin:/opt/sbin:$PATH
JAVA_HOME=/opt/java/ejre1.6.0_21
LANG=en_US.utf8
export JAVA_HOME LANG

 

Save and exit. Now install the Serviio application:

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

In the DSM Control Panel got to Web Services > Web Applications tab > Enable Web Station.
Install AcidumIrae’s PHP web UI for Serviio. You will need to have enabled Web Station for the directory /volume1/web to exist.

wget http://labs.softjourn.com/attachments/download/67/serviio-0.5.2.1b.zip
unzip serviio-0.5.2.1b.zip
mv serviio-0.5.2 /volume1/web/serviio
 

You should already be able to browse to http://your_NAS_IP/serviio and see the user interface, though it will complain with a big red X that Serviio is not running.

FFmpeg depends on the libbz2 and zlib libraries, and although both are installed along with the optware-devel package, FFmpeg will only look for them in /lib rather than in their actual location in /opt/lib. Copies of the existing symbolic links will be fine:

cp /opt/lib/libbz2.so.1.0 /lib
cp /opt/lib/libz.so.1 /lib
 

Compile the patched version 26303 of FFmpeg from the Serviio download page. Running cat /proc/cpuinfo it is clear that the DS111 is an ARM 5TE platform so I enabled those specific optimizations:

cd /volume1/@tmp
wget http://download.serviio.org/opensource/ffmpeg-26303.tar.gz
tar xvzf ffmpeg-26303.tar.gz
cd ffmpeg
./configure --arch=arm --enable-armv5te --prefix=/opt --extra-cflags='-I/opt/include' --extra-ldflags='-L/opt/lib' --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-libmp3lame
make
 

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

Update – Thanks to bakman for pointing out that for Intel Atom CPUs you will need to install the assembler YASM and also use the following ./configure parameters:

ipkg install yasm
./configure --arch=x86_64 --enable-ssse3 --prefix=/opt --extra-cflags='-I/opt/include' --extra-ldflags='-L/opt/lib' --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-libmp3lame
 

Another Update – Thanks to gregorio for parameters for Freescale PowerPC processors:

./configure --arch=powerpc --disable-altivec --prefix=/opt --extra-cflags='-I/opt/include' --extra-ldflags='-L/opt/lib' --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-libmp3lame
 

When the compile is done, install it.

make install
 

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 UNKNOWN, Copyright (c) 2000-2011 the FFmpeg developers
built on Feb 6 2011 01:14:38 with gcc 4.2.3
configuration: –arch=arm –enable-armv5te –prefix=/opt –extra-cflags=-I/opt/include –extra-ldflags=-L/opt/lib –enable-static –disable-shared –disable-ffplay –disable-ffserver –enable-libmp3lame
libavutil 50.36. 0 / 50.36. 0
libavcore 0.16. 0 / 0.16. 0
libavcodec 52.108. 0 / 52.108. 0
libavformat 52.92. 0 / 52.92. 0
libavdevice 52. 2. 3 / 52. 2. 3
libavfilter 1.72. 0 / 1.72. 0
libswscale 0.12. 0 / 0.12. 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’

If you see the text below then something is wrong – this is the version included with DSM 3.0:

FFmpeg version SVN-r20167-snapshot, Copyright (c) 2000-2009 Fabrice Bellard, et al.

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 icon in the top right to copy):

#!/bin/sh

User=serviio

case "$1" in

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

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

        #check libs FFmpeg depends on (in case DSM was upgraded)
        if [ ! -f /lib/libbz2.so.1.0 ]; then
                cp /opt/lib/libbz2.so.1.0 /lib
        fi
        if [ ! -f /lib/libz.so.1 ]; then
                cp /opt/lib/libz.so.1 /lib
        fi
        ;;

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/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:

 2542 root      9080 S N  /usr/syno/sbin/synomkflvd
 2589 root      3908 S    /usr/syno/sbin/sshd
 2591 root      5376 S    /usr/syno/apache/bin/httpd -f /usr/syno/apache/conf/
 2599 root      5944 S    /usr/syno/apache/bin/httpd -f /usr/syno/apache/conf/
 2600 root      5936 S    /usr/syno/apache/bin/httpd -f /usr/syno/apache/conf/
 2628 root     58920 S    /usr/syno/apache/bin/httpd
 2687 nobody   58920 S    /usr/syno/apache/bin/httpd
 2688 nobody   58920 S    /usr/syno/apache/bin/httpd
 2689 nobody   59500 S    /usr/syno/apache/bin/httpd
 2695 root     11560 S    /usr/syno/sbin/mDNSResponder -f /tmp/mDNSResponder.c
 2703 root      5568 S    /usr/syno/apache/bin/httpd -f /usr/syno/apache/conf/
 2949 root      5568 S    /usr/syno/apache/bin/httpd -f /usr/syno/apache/conf/
 3025 root      5568 S    /usr/syno/apache/bin/httpd -f /usr/syno/apache/conf/
 3087 root      8664 S N  /bin/ntfs-3g -o uid=1024,gid=100 /dev/sdk1 /volumeUS
 3518 root      8852 S    /usr/syno/sbin/cnid_metad
 3524 root     15132 S    /usr/syno/sbin/afpd -c 256 -g guest -n SynologyDS111
 3566 nobody   58920 S    /usr/syno/apache/bin/httpd
 7747 root      6660 S    sshd: root@pts/0
 7826 root      5404 S    -ash
13567 serviio   2940 S    -sh -c /opt/serviio/bin/serviio.sh
13570 serviio   2940 S    /bin/sh /opt/serviio/bin/serviio.sh
13575 serviio   501m S    /opt/java/ejre1.6.0_21/bin/java -Xmx384M -Djava.net.
13917 root      5404 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:

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

Shutdown the NAS and restart.

Update – previously I had used the directory /usr/syno/etc/rc.d, but this is destroyed when the DSM software is updated. /usr/local/etc/rc.d is the official Synology location for 3rd party daemon init scripts but I found that it doesn’t work, so I used /opt/etc/init.d instead which also survives a DSM upgrade. I just tested this by upgrading to DSM 3.1-1605 and Serviio remained intact. I only had to copy the sym links for the libraries FFmpeg needs (“cp /opt/lib/libbz2.so.1.0 /lib” and “cp /opt/lib/libz.so.1 /lib”).

 

Web UI integration with the Synology DSM

I read the official Synology notes for 3rd party developers and decided to make some icons. The result is pretty neat:

Open an SSH session:

cd /usr/syno/synoman/webman/3rdparty
wget http://dl.dropbox.com/u/1188556/blog/serviio_syno_DSM.zip
unzip serviio_syno_DSM.zip
rm serviio_syno_DSM.zip
nano serviio/config
 

The file loaded into nano will look like this, and you need to edit the IP address to match the IP of your Synology (either put your syno on a static IP, or set a reservation in your broadband router’s DHCP server options).

{
 ".url": {
    "org.serviio.serviio": {
      "type": "legacy",
      "allUsers": true,
      "title": "Serviio",
      "desc": "DLNA Media Server",
      "icon": "images/icon_{0}.png",
      "url": "http://192.168.1.202/serviio/index.php"
    }
  }
}
 

I can’t find a way to avoid manually specifying the IP address like this – relative paths can’t be used because the Synology runs two different webservers: the DSM one on port 5000 without PHP, and the PHP-enabled Web Station one on port 80.

Log out of DSM and log back in. You will see the Serviio icon in the pull down menu in the top left, which you can drag to the desktop if you prefer:

 

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.

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. Note that the Add Local… button will fail because the web service user does not have access to the root of the filesystem (probably a good thing security-wise). Use Add Path… instead and express the paths as I have done in the first screenshot above. Be sure that the serviio user has been granted read privileges over the folders you add (User Control Panel in DSM).

Update – If you really want to use the Ajax file browser UI, then go to DSM Control Panel > Web Services > PHP Settings tab > open_basedir and append /volume1: to the start of that list. Then on the Web Applications tab, disable Web Station, Ok, enable Web Station. Go back to your SSH session and run:

nano /volume1/web/serviio/afb/config.php
 

Change the value of $path from / to /volume1/public (or the top level shared folder where your media resides). You’ll notice however that when you use Add local button in the Serviio Library tab it’s very buggy. It will only list a maximum of 5 child folders from each node.

 

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 delete a couple of libraries which had been copied to /lib:

/opt/etc/init.d/S99serviio.sh stop
rm /lib/libbz2.so.1.0
rm /lib/libz.so.1
 

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 JAVA_HOME and java path modifications marked in bold earlier in the guide).

To remove the web UI, in DSM go to Web Services > Web Applications tab > Disable Web Station. Then:

rm -r /volume1/web/serviio
rm -r /usr/syno/synoman/webman/3rdparty/serviio
 

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.