Getting the Best Results From MPlayer and Mixed Telecined & Progressive Video

This post is years in the making.  Not that I’ve spent the entirety of those years working on this problem, or even the entirety of my spare time.  This is just one of those things that I’ve relentlessly banged my head up against until I couldn’t take anymore, only to have it nag me somewhere down the line and pick it back up again.

For the longest time, I could not for the life of me process video that was mixed telecine and progressive without having the resulting video end up longer than the original.  The immediate problem is that A/V sync starts out fine but then drifts to whatever the time difference is between the two videos.  I eventually discovered soundstretch, which can adjust tempo (play time) without affecting pitch, but then that introduces the problem of calculating the time difference as a percentage (and the rounding errors involved in that), re-coding an already-lossy audio stream, and the time it can take to process one-to-two hours of uncompressed WAV data.

While I did have most of that down, it was just too much time.

The biggest stumbling block is this little quip from How to Deal With Telecine and Interlacing Within NTSC DVDs:

filmdint will deinterlace individual fields that it cannot match, however, whereas pullup will simply drop them. Also, the two filters have separate detection code, and filmdint may tend to match fields a bit less often.

I interpreted this (I think rightfully so) as meaning that filmdint would add even more frames than pullup.

To be fair, there’s also this quip in the same paragraph:

[F]eel free to experiment with fine-tuning the filters’ options if you encounter problems with either one (see the man page for details). For most well-mastered input video, however, both filters work quite well, so either one is a safe choice to start with.

So, for the longest time I avoided filmdint and stuck to solving the problems I was presented with by pullup.

Just recently I started dabbling with lossless codecs. The fun started with AVIDemux and FFV1, but the extreme bloat that lossless video gives you bumps you up against the 4GB boundary of the original AVI container spec, which seems like the only container that AVIDemux will let you dump FFV1 into. I knew x264 had a lossless option, and has also come up with preset and tune parameters as shortcuts for a group of x264 encoding options, but AVIDemux doesn’t do a very good job of presenting this information to you nor does it seem to remember settings between projects.

I then came across this x264 Lossless discussion, which gave me the options I needed:

–qp 0 –preset ultrafast –tune animation

Then I stumbled up this x264 Encoding Guide with this little gem:

mplayer -nosound -benchmark -vo yuv4mpeg:file=>(x264 --demuxer y4m --crf 20 --threads auto --output output.264 - 2>x264.log) star-wars.mkv

This was not hard at all to adapt to what I wanted to do (with a little help from this x264 Settings wiki page):

mplayer -nosound -benchmark -vf pullup,softskip -vo yuv4mpeg:file=>(x264 --demuxer y4m --fps 24000/1001 --input-res 720x480 --sar 8/9 --qp 0 --preset ultrafast --tune animation --threads auto --output output.264 - 2>x264.log) dvd://4

For some reason, even though the x264 stream itself does have the proper frame rate information, MPlayer doesn’t use it. (MPlayer probably expects it to be specified inside the container only, and x264 is pretty damn-near a raw stream.) The same site, however, makes mention of a simple utility for Linux to mux streams into an MP4 container.

MP4Box -tmp ~/tmp -fps 23.976 -add output.264

Of course, same old same old.

I did some digging and found this gem on the Best Tool for Inverse Telecining and Deinterlacing discussion on the Arch Linux forums:

mkfifo /tmp/videopipe.y4m
mkfifo /tmp/videopipe2

x264 /tmp/videopipe.y4m --crf 0 --preset ultrafast --threads auto -o output-264.mkv & mencoder dvd://1 -dvd-device /dev/sr0 -nosub -vf pullup,softskip,format=i420,scale=720:480 -ofps 24000/1001 -nosound -ovc raw -of rawvideo -really-quiet -o - | mplayer - -rawvideo w=720:h=480:fps=24000/1001:format=i420 -demuxer rawvideo -aspect 4:3 -benchmark -vo yuv4mpeg:file=/tmp/videopipe.y4m -really-quiet 2>/dev/null

The poster incorrectly asserts “mplayer…DOESN’T have the ability to change framerate…” so then he insists on using mencoder which he claims “does technically have the format=i420, it’s broken so you can’t pipe from mencoder to x264 directly.” If the complete lack of attention isn’t apparent, note that /tmp/videopipe2 is never used and the output destination is named with the mkv instead of one of the standard 264, h264, x264, or avc extensions.

It’s pure Linux command line masturbation induced by incorrect perception. MPlayer doesn’t change framerate, but its filters sure can…which renders any discussion about MEncoder mute.

As a last resort, I opted to test out softpulldown to see just how badly damaged the video was.

mplayer -nosound -benchmark -vf softpulldown -vo yuv4mpeg:file=>(x264 --interlaced --demuxer y4m --fps 30000/1001 --input-res 720x480 --sar 8/9 --qp 0 --preset ultrafast --tune animation --threads auto --output output.264 - 2>x264.log) dvd://4

LO AND BEHOLD! THE COPY WAS THE SAME LENGTH AS THE ORIGINAL!

OK, so it’s not that big of a deal, really. If everything was mastered correctly, telecining the progressive parts so that the entire video is telecined should do that. Of course, if it was mastered correctly then I wouldn’t be in this situation to begin with, would I? To wit, there is dot-crawl in the original video and damaged frames (one frame missing an entire field followed by one or two full frames with damaged chroma) in the completely-telecine copy.

Well, I had my video length correct, but the interlacing was unacceptable. I tried decombing the completely-telecined copy and then decimating it, but the video ended up horribly jerky during pans. I wanted to try the combo of decombing and doubling frame rate, but I couldn’t get it to work.

Out of desperation, I tried filmdint.

mplayer -nosound -benchmark -vf filmdint -vo yuv4mpeg:file=>(x264 --interlaced --demuxer y4m --fps 24000/1001 --input-res 720x480 --sar 8/9 --qp 0 --preset ultrafast --tune animation --threads auto --output output.264 - 2>x264.log) output.mp4

LO AND BEHOLD! THE COPY’S LENGTH WAS STILL INTACT!

I then tried to apply directly to the output from the DVD.

mplayer -nosound -benchmark -vf filmdint -vo yuv4mpeg:file=>(x264 --interlaced --demuxer y4m --fps 24000/1001 --input-res 720x480 --sar 8/9 --qp 0 --preset ultrafast --tune animation --threads auto --output output.264 - 2>x264.log) dvd://4

BINGO!