tirsdag 17. februar 2009

H.264 at 1080p with NVIDIA's VDPAU on Linux

NVIDIA released support for their Video Decode and Presentation API for Unix with version 180.06 of their video and OpenGL driver for Xorg. They have also released patches to MPlayer so we can actually use it. I have tried getting it to work on my Gentoo GNU/Linux x86_64, but with the earliest drivers I got a green video window followed by a Xorg freeze with my graphics card. I had to SSH into the computer and kill MPlayer and Xorg. One of the versions even froze the kernel up completely. Version 180.27 actually didn't freeze my computer, put instead of the decoded video I got a random mosaic of colors.

With version 180.29 it did function properly with my XFX GeForce 280 GTX XXX graphics card. It's working great, and I can play H.264 1080p video with MPlayer using only 3% of a single CPU core!

To get VDPAU working you need, as I mentioned, a recent driver and at least version 180.06. Also you need a patched MPlayer, witch you can obtain the sources for here. Get the header files under "include" as well, and unpack the tarball and run the script checkout-patch-build.sh to retrieve MPlayer sources, patches and compile it all. As it is now (version 3482714), the VDPAU patches need additional patching to be able to play H.264 video above level 4.1:


--- libvo/vo_vdpau.c.orig 2009-02-17 15:03:25.936006847 +0100
+++ libvo/vo_vdpau.c 2009-02-17 18:43:43.995005259 +0100
@@ -90,7 +90,7 @@
/* Numbers of video and ouput Surfaces */
#define NUM_OUTPUT_SURFACES 3
#define NUM_VIDEO_SURFACES_MPEG2 3 // (1 frame being decoded, 2 reference)
-#define NUM_VIDEO_SURFACES_H264 17 // (1 frame being decoded, up to 16 references)
+#define NUM_VIDEO_SURFACES_H264 18 // (1 frame being decoded, 16 reference frames, plus b_frames and b_pyramid)
#define NUM_VIDEO_SURFACES_VC1 3 // (same as MPEG-2)
#define NUM_VIDEO_SURFACES_NON_ACCEL_YUV 1 // surfaces for YV12 etc.
#define NUM_VIDEO_SURFACES_NON_ACCEL_RGB 0 // surfaces for RGB or YUV4:4:4
@@ -701,10 +701,7 @@
uint32_t round_width = (vid_width + 15) & ~15;
uint32_t round_height = (vid_height + 15) & ~15;
uint32_t surf_size = (round_width * round_height * 3) / 2;
- max_references = (12 * 1024 * 1024) / surf_size;
- if (max_references > 16) {
- max_references = 16;
- }
+ max_references = 16; // Support for H.264 Level 5.1
}
break;
default:

Ingen kommentarer: