My solution up to now was to play the videos using Haali Media Splitter for the .MP4 container and Xvid for decoding. That resolved all the problems for me, but if I sent a file to someone else, they could still end up viewing the video at 320x240. Now I've finally figured out what is wrong with the files themselves.
I started out by compiling mp4v2 in Cygwin. This resulted in some errors, but just re-running make was enough to get the executables compiled. Then I used "mp4file --dump" to examine the contents of the MP4 container. It showed a 320x240 size in two places: the tkhd header for the video track and the stsd atom. QuickTime 7.6.5 uses the tkhd size, and Mplayer 1.0rc1-3.4.2 uses the stsd size. Changing both sizes to 640x480 should make the video always play at 640x480.
After seeing 320x240 at two places in the file and not seeing 640x480, I was left wondering what was the actual resolution of the video. It seems to be 640x480 based on several pieces of supporting evidence:
- The videos are clearer when decoded at 640x480 than when decoded at 320x240 and scaled up.
- Even when decoding at 320x240, Mplayer allocates a 640 wide YUV buffer with 320x240 chroma (which should be at half resolution).
- If I extract the video stream using mp4creator, Mplayer plays the resulting MPEG4 ES stream at 640x480. This is even true if extracting from an unaltered .MP4 file which plays at 320x240.
000000F0: 01 02This is the output of "fc /b". The first four are lines are tkhd and last four are stsd. Note that the patch is simply changing obvious big endian values.
000000F1: 40 80
000000F4: 00 01
000000F5: F0 E0
000001B9: 01 02
000001BA: 40 80
000001BB: 00 01
000001BC: F0 E0
Now the only problem was how to automatically change these values. I thought I would be able to find a utility which takes "fc /b" or "cmp -l" output, verifies the original bytes and applies the changes. However, I didn't find any simple utilities so I decided to create my own. For fun, I created a sed script which transforms "fc /b" output into a C program which performs the patch. You can download it and the resulting Windows executable.