FFmpeg, AppleTV and conversions

Last year, a few months before ending up in the hospital, I bought a LCD TV and an AppleTV device, to watch my animes before sleeping, in my bedroom, relaxing down. After the hospital I ended up not watching much anime anyway, but before that I noticed one nasty thing: my LCD TV “eats” away around 16-20 pixel around the borders with the result that the subtitles for the japanese anime were unreadable. Which was very nasty in my opinion.

After AppleTV Take 2 software was released I also didn’t have much time to play with it to modify it again to install extra codecs, nor I had time to watch much anime, even though I bought a PlayStation 3 to relax. Now, I also considered the idea of selling away the AppleTV, getting a bigger harddrive for the PlayStation 3 and live with that. But since I have already spent enough time in the hospital, having mobile access to my anime is still a feature I’d like to keep, and since I can easily make AppleTV and iPod use the same video files, while PS3 and PSP (which I don’t own, my sister does though) would require different copies, I finally decided to keep it.

I have already tried converting video files but FFmpeg failed, while VisualDub let me do some of the conversions; unfortunately I never had the time to finish the conversion before I ended up in the hospital again. Geez, you really have some trouble when you can count eras based on when you ended up in the hospital. Anyway, since now I got a new box, I decided to try doing the conversion once again with FFmpeg, with all the improvements that arrived up to now.

Before trying that, though, I wanted to be able to do one thing: try to remove data duplication between my workstation (Yamato) and the laptop (Intrepid). My easy way out of this is to make sure that they use the same partition for music and video, which is what they share. Linux and OSX can share mainly two filesystems: FAT32 (nasty) and HFS+. The problem is that HFS+, Apple’s filesystem, can have multiple variants: it may or may not be case-sensitive, and it might be journaled. Linux cannot write to journaled HFS+, and I dislike case insensitivity, so I set up a HFS+ case-sensitive non-journaled partition beside the Time Machine partition on the external hard drive, and connect the drive to Yamato.

Moving the music and video files off Yamato’s drives also helped me to reduce the amount of data I have on the internal drives, which in turn should reduce at least a little the stress on them until I can get a new setup. And Linux HFS+ support is not that bad after all, once you disable journaling. The problem is that I wanted to make sure I could use the same disk both connected to Yamato with network attached, and directly connected to Intrepid. A tried way to do this was to export the partitions via iSCSI, but that would have given exclusive access to the partition to the laptop, and thus caused me once again not to be able to share the data.

The other solution was to export the filesystem via NFS when connected to Yamato, which is what I tried, unfortunately, as I’ve written before, Linux does not support NFS export of HFS+ partitions; or at least it doesn’t right now. I love Free Software just for this reason: if a feature does not exist, I make it up; now I just have to hope that it gets applied upstream in a decent timeframe.

Now that the filesystem problem is mostly behind me (mostly because I still see some failures; I don’t know exactly what they relates to yet), I wanted to make sure I could get a way to convert my content with FFmpeg directly; Yamato is an 8-core system so it should be faster than the laptop to do the work. So I got the latest FFmpeg version out of FFmpeg, and tried.

So the first issue is getting the right container format, while ISO Media, QuickTime, iPod video files, and so on are all based on more or less the same idea, to the point that xine can easily use a single demuxer for all of them, as well as libavformat, there are some tricky issues with having those files working on QuickTime, iTunes and AppleTV. Luckily, FFmpeg has an ipod preset that does the job, mostly, which is very good. The problem is the “mostly”: these formats are based upon elements called atoms, atoms can have versions; the common version 0 that is supported by Apple’s software has 32-bit values for timescales, offsets and stuff like that; alternatively there exist a version 1 that uses 64-bit values instead; xine supports both, but Apple’s software does not. The intersting bit here is that FFmpeg produces version 1 atoms whenever the time scale does not fit as it is in the 32-bit values, without warning even when asking for the iPod container format. The trick here is to force a timescale conversion; most of the content I got is encoded with approximately 29.97 fps, but using a timescale in AVI files that does not fit into version 0 atoms; changing the timescale to basically the same through -r 29.97 fixes the problem for me.

Now, time to get correct video and audio codecs. If you have ever tried to do this you know you have to use H.264 for video and AAC for audio; I used 800kbit/s for video and 128kbit/s for audio; just make sure you pass the parameters before the output filename, otherwise they won’t be picked up. To make sure to enable the proper features for the x264 encoder, I used the presets that are in FFmpeg’s repository; I chosen to skip the -max version since that was giving me less than one frame per second, which was very very bad, I used -hq instead, which gave me good enough results. The problem is the default version enables 8×8 DCT and B-Pyramids, which QuickTime does not properly support. Files encoded with these two features enabled were synced properly to the AppleTV but crashed it down once played. Not so nice. To fix this, just replace the + symbol with a - in front of the two features dct8x8 and bpyramids. Problem solved, and the files play.

For some reason, FFmpeg’s MS-Mpeg4 decoder dies when enabling more than 8 threads, and with so many threads, only about four cores get used on Yamato; I’m not sure why the limit is imposed by the video decoder, since I would expect at least a thread to be able to handle audio, but anyway, since that’s the deal, I decided to convert two files at a time, and to do that, well we have GNU make don’t we?

I wrote this Makefile:

VPATH = $(ORIG)

SRCS = $(notdir $(wildcard $(ORIG)/*.avi $(ORIG)/*.mp4))
all: $(patsubst %.mp4,%.m4v,$(patsubst %.avi,%.m4v,$(SRCS)))

%.m4v: $(filter %.avi,$(SRCS)) $(filter %.mp4,$(SRCS))
    ffmpeg -threads 8 -i lt; -vpre libx264-appletv-hq.ffpreset -b 800k -ab 128k -acodec libfaac -padcolor 000000 -padtop 16 -padbottom 16 -padleft 16 -padright 16 -r 29.97 -f ipod "$@"

As you can see, I’m padding 16 pixels around the video for the subtitles to appear on my TV, thanks to FFmpeg, doing the padding is very quick and does not degrade quality.

I just run make -f ~/makefle.convert -j2 ORIG=/directory and there it goes, the conversion is running, and it’ll be done in… a few hours.

2 thoughts on “FFmpeg, AppleTV and conversions

  1. I got this working ok building the nightly ffmpeg from source, and found that I had to have libfaac shared library built and installed, and libx264 shared library built and installed, and then ffmpeg had to be built with enable-libfaac and enable-libx264 and enable-gpl.(Since I had an older kernel, I had to disable-muxer=v4l and disable-muxer=v4l2 and disable-demuxer=.. for both as well, to avoid compile errors).(Since I didn’t have a recent enough yasm, I had to tell libx264 not build without asm).Finally it isn’t obvious from the above but you have to copy libx264-hq.ffpreset to libx264-appletv-hq.ffpreset and modify the two flags as mentioned.At that point everything works.Without libx264 enabled, ffmpeg doesn’t give a very sane error message such as “you didn’t enable libx264!”, instead it complains about 0x0000 being an invalid output codec.I don’t think my above notes apply to a distro that includes a fully functioning and recent copy of ffmpeg and libx264 and lifaac ..

    Like

  2. I know this is an 8-month+ post and you probably won’t see my comment, but I wanted to thank you for this post. I had been struggling for a few days trying to convert my video library for my new Apple TV. Between ffmpeg crashes and Invalid Atoms messages I was getting close to giving up and returning the Apple TV, but your explanations of what’s causing the atoms issues fixed my last issue, and now everything is up and running!So, thanks you ;)

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s