3/31/2010

03-31-10 - Video Annoyances

Oo lord working with video is annoying.

I noticed over at Media Xiph.org they have some sample videos in Y4M 444. 444 means it has full res chroma. I have previously tested against x264 using some Y4M 420 sequences like "parkrun", but the problem with that is that it has pre-killed chroma, so it actually is biased against me because I don't kill chroma in the same way they do, so I'm sort of taking a chroma killing penalty twice. What I want is full res color data so that x264 and I can both kill chroma in our own ways and then compare to the original.

So I get the full res 444 Y4M data. Then the problems begin. Most Windows video tools won't real Y4M because it's not packaged in an AVI with a codec for DirectShow and all that. But the linuxy tools that are starting to dominate do read Y4M. *BUT* my favorite tools, x264 and mplayer/mencoder both don't read Y4M 444, they only read 420. Now the linuxy thing to do would be to pipe the video through y4mscaler, but then I'm killing the chroma. That's fine to do the x264 compress, but I need to get back to RGB full res for my compress.

So now FFMPEG does read Y4M 444. But for some fucking reason the ffmpeg on my machine refuses to show any command line help. All the things I'm supposed to be able to do to make it tell me what codecs it has and so on don't work. Yay. So I get to randomly search the web and try things in the dark until it works.


ffmpeg -i t:\park_joy_444_720p.y4m -vcodec rawvideo -pix_fmt bgr24 r:\park_joy_444_720p_rawvideo.avi

So we have raw video out, yay! That's awfully big so we want to compress it with something lossless. The only lossless codec that I have found which really works in all players and supports plain RGB right is Lagarith. (other people have had success with HuffYUV but I have trouble making it work with RGB and it randomly crashes on me sometimes).

BTW if you want 420 subsampled colorspace YUV, x264 is a great option for lossless video, and it's easy, just compress with -q0. In fact this is a good way to convert a 420 Y4M or YUV file into an MP4 which can then be loaded by Windows video tools. HOWEVER you may need to specify low profile and no bframes, and even then some Windows video tools will still have problems with x264 output. Also - Y4M is a raw YUV file with a header. A .YUV file has no header and you have to tell it the size. The easiest way is to name the file "blah_widthxheight.yuv" and then give it to x264, which will parse the file name for width & height.

Unfortunately we cannot go straight to Lagarith in ffmpeg because FFMPEG is some linuxy thing that uses hard-coded "lib" system rather than using the Windows pluggable codec thing. So even though I have Lagarith on my machine and all the Windowsy video products can encode to it, ffmpeg can't. (I guess on Linux ffmpeg actually loads libs using the purported magic Linux lib system, but on Windows they are hard-compiled into FFMPEG; that is advantageous in that it means ffmpeg actually fucking works, unlike the apps that rely on DirectShow codecs to be set up right which is a fragile disaster, but it's disadvantageous in that you rely on the whims of ffmpeg builders to put in the right codecs). So anyway to transcode I have to use VirtualDub. Vdub is a pretty nice app for simple AVI transcoding, it's basically just an interface to the DirectShow filters.

(BTW I guess I could do this directly in ffmpeg by going throught AVISynth since there is an ffmpeg-avisynth connection and then avisynth can get you to anything in DirectShow, but lord help me if I have to get into that snake pit).

I set up my config for transcoding in the VirtualDub GUI and then I save the settings out to a "VCF" file and then I can run it from the command line like this :


c:\progs\virtualdub>vdub /s r:\vdub_lagarith.vcf /p r:\park_joy_444_720p_rawvideo.avi r:\park_joy_444_720p_lagarith.avi /r

Okay, so now we have the lagarith RGB video. That is all I need to be an input to my coder, but to compress with x264 we need to go back through some hoops. The most reliable way I've found is to use MPlayer to turn that into Y4M :


mplayer -benchmark -ao null -vo yuv4mpeg:file=park_joy_444_720p_lagarith.y4m park_joy_444_720p_lagarith.avi

And then finally we can run x264 on the Y4M :


x264_2pass park_joy_444_720p_lagarith.y4m park_joy_444_720p_x264.mp4 --bitrate 10500 --preset slow

x264_2pass.bat :
set x264args=%3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 %17 %18 %19 %20 %21 %22 %23 %24 %25 %26 %27 %28 %29
x264 -o %2 %1 -p 1 -I 9999 %x264args%
x264 -o %2 %1 -p 3 -I 9999 %x264args%
REM x264 -o %2 %1 -p 3 -I 9999 %x264args%

(note I specifically do not want to start from the original Y4M and just use y4mscaler or something to get to x264, I want to start from the same RGB lagarith video that my coder will start with, since that's the most unbiased source type; eg. neither of us code in RGB and neither of us are tuned for RGB, so it's not biased one way or the other).

Yay ! Oh, and BTW x264 seems to often severely miss it's bitrate, usually over. That bitrate 10500 is my attempt to make it hit 12500. Depending on the video you'll have to look at the output size and fiddle with that to make it hit the right size.

One annoying niggle is that somebody along the way seems to fuck up framerate a bit. On park_joy , which is at 50 fps, it seems to be perfect. However on the 29.97 fps videos (30000/1001), somebody is doing the math wrong and getting off sync, so on long videos it will have a frame slip, so that if you compare the original to the final output, you'll find a frame where they get out of sync by one frame and you have to step ahead in the source to get them back in perfect sync. I haven't tracked down who the culprit is or how to fix it, so I just live with manually stepping a bit to find sync when comparing. I also haven't found an app that can just change the time code on a video without touching the frame data, that is take a 29.97 fps video and make it claim to be 30 fps, but show the exact same frames, eg. change duration but keep the frame count the same.

1 comment:

ryg said...

Yeah, AVISynth works. It's a good way of getting stuff into the libavcodec-based toolchain, but most of the actual filters suck hard.

All of this video stuff is just horribly broken in so many different ways...

old rants