Page head image

The perils of creating an MP4 stream

(2 comments)

This is a rant, sort of... I was trying to crate MP4 files with H.264 video and AAC audio codecs (as this is the only thing Apple Quicktime Player is going to play.)

And I actually succeeded. However, it turned out to be as complicated as I feared. First of all, I don't run Windows and I don't have Apple iLive. This means I have to resort to command line tools running on Linux. Next, the machine is an AMD64 box, running in 64-bit mode. Since it is an unbearable PITA to build the required tools yourself for x86_64, I chose to take the packages from Packman.

The ffmpeg package even has dependencies to faac and x264 -- alas,
it cannot create either format. Great. But I still have the command line tools for x264 and faac, so
lets DEMUX the streams first. Hmm, better do that in two steps, one for the audio, the other for
the video:


ffmpeg -i dvd/chapter01.vob work/chapter01.wav -map 0.1:0
ffmpeg -i dvd/chapter01.vob -croptop 88 -cropbottom 88 -s 512x280 -deinterlace -y work/chapter01.yuv -map 0.0:0

Now encode the audio and the video and MUX it. Hmm, x264 is not linked against GPAC, so it can MUX it right away. Okay, we'll take ffmpeg,
as it claims to be able to decode everything and write MPEG4 containers:


faac work/chapter01.wav -o work/chapter01.m4a
x264 -o work/chapter01.h264 work/chapter01.yuv
ffmpeg -i work/chapter01.h264 -r 25 -i work/chapter01.m4a -acodec aac -f mp4 mp4/chapter01.mp4

Woops, ffmpeg can't handle the AAC codec, even though -formats claims to do so. Okay, so just
copy that:


ffmpeg -i work/chapter01.h264 -r 25 -i work/chapter01.m4a -acodec copy -f mp4 mp4/chapter01.mp4

Yay, MPlayer plays it. However, Apple QT doesn't. It complains
about a broken stream format. As it turns out, Apple QT requires MP4 AAC, and faac by default creates MPEG2 AAC streams. Well, Apple QT plays the standalone AAC file fine, just not in an MP4 container together with a video stream. Okay, let's re-encode the audio stream and try again:


faac -w work/chapter01.wav -o work/chapter01.m4a
ffmpeg -i work/chapter01.h264 -r 25 -i work/chapter01.m4a -acodec copy -f mp4 mp4/chapter01.mp4

That's better, Apple QT plays the stream. Albeit, without sound. No wonder:


$ mp4creator -list mp4/02-act1-scene2-the_opera_house.mp4
Track Type Info
1 video MPEG-4 Unknown Profile(0), 377.000 secs, 0 kbps, 520x256 @ 25.000000 fps
2 audio MPEG-4 AAC LC, 0.000 secs, 0 kbps, 48000 Hz
$

FFmpeg does not write the stream duration of the audio stream to the MP4 track header. Great idea.
And while mp4creator happily multiplexes the MPEG2 AAC format (which Apple QT does not play, remember?), it throws lots of error messages and crashes with a segmentation fault when fed with an MP4 AAC stream.

So, what now? x264 mentioned GPAC. It contains a multiplexer, but you have to compile it from source. After a lot of plumbing (disabling the wxWindow based GUI tools, adding -fPIC, adding -L/usr/X11R6/lib64, disabling some other C++ based GUI with type cast error on 64-bit-platforms. Hello?! Anyone home? We have 2006 and you folks still write tools that don't compile on 64-bit platforms?!) and concerns regarding tons of warning about assignments between signed and unsigned integers I even got it compiled.

And indeed, despite the source code being in a rather rotten state, it actually multiplexes the two streams:


MP4Box -add work/chapter01.h264 mp4/chapter01.mp4
MP4Box -add work/chapter01.m4a mp4/chapter01.mp4

But wait a second, the sound is early by half a second, probably due to a problem with the VOB
file (or is it supposed to be that way?) But that's just a minor problem, and the complete conversion looks like this:


ffmpeg -i dvd/chapter01.vob -ss 00:00:00.5 work/chapter01.wav -map 0.1:0
ffmpeg -i dvd/chapter01.vob -croptop 88 -cropbottom 88 -s 512x280 -deinterlace -y work/chapter01.yuv -map 0.0:0
faac -w work/chapter01.wav -o work/chapter01.m4a
x264 -o work/chapter01.h264 work/chapter01.yuv
MP4Box -add work/chapter01.h264 mp4/chapter01.mp4
MP4Box -add work/chapter01.m4a mp4/chapter01.mp4

Voila, it plays on Apple QT Player 7, recent versions of vlc and recent CVS versions of MPlayer.

Ideally, if ffmpeg would have been configured correctly on build time, the whole process propably could be reduced to a one-line call to ffmpeg. But building anything multimedia related yourself is already painful on i386, on x86_64 it is a royal pain in the arse.

Comments

cheetah-spotty.livejournal.com 17 years, 11 months ago

A good starting point for mp4-related stuff on linux is:

http://mpeg4ip.sourceforge.net/

(And yes, it's tricky. Getting F8K-TV running was a nightmare. And you didn't even have to deal with the darwin streaming server, oh lucky one!)

Link | Reply

woelfisch.livejournal.com 17 years, 11 months ago

Yes, mpeg4ip is the tool chain where mp4creator comes from. Thanks for the link, I forgot to mention it above.

Nevermind that the package from Packman is missing the mp4encode script -- I'm pretty sure the script also calls mp4creator to MUX the streams, which crashes with MPEG4 profile AAC files, at least on x86-64. Fortunately, the analysis tools work quite nicely and help a lot hunting down problems with streams.

And after playing around with streaming a bit I can definately say that I don't want to open that can of worms...

Link | Reply

New Comment

required

required (not published)

optional