jump to navigation

Some notes about video playback on Linux June 4, 2007

Posted by TSAI HONG-BIN in Linux.
trackback

In addition to original maintenance projects, my responsibility here at the new office increases. The most challenging one is “Video Renderer”, plus, on Linux. As long as I can remember, none of the classes I took in under-grad. and grad. school relates to multimedia. Computer Graphics? no, Data Compression? no. The only thing I know about multimedia, is DRM. No, not “Direct Rendering Management,” but “Digital Right Management.”

Fortunately, we have MPlayer on Linux. MPlayer is a powerful, open source media player. It supports various audio/video codecs and offers various ways of rendering to fulfill compatibility over different platforms and operating systems. Please visit http://www.mplayerhq.hu/ for further information.

So, let’s dig into the video rendering part of MPlayer. By running


#mplayer -vo help

You can see a list of available video rendering “techniques,” say, X11, Xv, OpenGL, FrameBuffer…etc. Without a thorough understanding, I picked Xv (XVideo) to help me do my job. There are some reasons urged me to make this decision, and the most important one is, I found a sample…here, http://bellet.info/XVideo/testxv.c, my implementation is a revision from that. Secondly, XVideo basically relies on X11 system, so, unlike directfb, it has loose dependency on vga driver. One more thing, Xv is an extension from X11 that mainly deals with video plackback. To me, that implies fewer APIs that I have to go through.

Before we start to look into the codes, I feel like to explain the “color spaces” that we use to reproduce image/video on screen. As you may already know, all the colors that Human Visual System recognizes can be composed from three primary colors, Red, Green, Blue. By being straightforward, images and videos can thus be reproduced on screen by mixing these three color signals electronically. And yes, it is how we define colors, by drawing RGB respectively in one pixel and users will perceive a mixed color, in the past. As technology evolves, a new color space called YUV, YCrCb, YPrPb, YIQ … either of above refers to an identical system (let’s use YCrCb), was introduced. The YCrCb system defines instead of each original color but the color difference. “Y” signal stands for Luminance and “CrCb” signal stands for chrominance. Since human eyes are more sensitive to Luminance than Chrominance, there is less CrCb signal that we need to carry to reproduce images in even quality. You may see some remarks like “4:2:2” or “4:2:0”, “4:1:1” on DVD case, they all indicate to the sampling methods. For example, “4:2:0” means that if the original image has four pixels, we sample four Y signals and two Cr (Cb in turn) signals. By applying YCrCb instead of RGB system, we save bandwidth that transmits the visual signals. In other words, with same bandwidth, we can transmit more data that may help reproduce images in a better quality.

MPlayer supports most color spaces as well, and therefore a great portion of it’s video rendering source code deals with such switch-cases. For example, If a video stream is recorded in RGB, the video renderer either converts the stream into other color spaces, or it has to draw it on screen in RGB fashion. For test only, this is not my concern.

Finally, let’s go to the source directly.

required include libraries: (weird, wordpress doesn’t allow me to put arrows…)

#include stdio.h
#include stdlib.h
#include unistd.h
#include time.h
#include string.h
#include sys/ipc.h
#include sys/shm.h
#include X11/Xlib.h
#include X11/Xatom.h
#include X11/Xmd.h
#include X11/Xutil.h
#include X11/extensions/Xvlib.h
#include X11/extensions/Xv.h
#include X11/extensions/XShm.h

libX11 draws window on the X11 system, libXv do the X-Video work. We use shared memory so shm.h is needed. X-Video works this way:

1. search for available XvPortID and do some initialization.
2. XvShmCreateImage allocates a space from shared memory and attaches it with XvImage object via shmat()
3. Read raw data from super process, ex, file I/O, and use memcpy to copy data from input buffer.
4. call XvShmPutImage to render the data on screen.

FILE* fp;
int size = xv_yuv_image->data_size;
char buf[size/8];
char buf_frame[size];
int buf_read = 0;
char* sFilename = argv[1];
fp = fopen (sFilename, “rb”);

if(!fp){
printf(“file open error!\n”);
exit(-1);
}

memset(buf_frame, ”, sizeof(buf_frame));
memset(buf, ”, sizeof(buf));

while (1) {

buf_read += fread(buf, 1, sizeof(buf), fp);
if(buf_read data, buf_frame, sizeof(buf_frame)) ;

XGetGeometry (dpy, window, &_dw, &_d, &_d, &_w, &_h, &_d, &_d);
XvShmPutImage ( dpy,
xv_port,
window,
gc,
xv_yuv_image,
0,
0,
xv_yuv_image->width,
xv_yuv_image->height,
0,
0,
_w,
_h,
True);

memset(buf_frame, ”, sizeof(buf_frame));
usleep(33333);
}

memset(buf, ”, sizeof(buf));

buf_read = 0;
}

The while loop above iteratingly reads from buffer and call XvShmPutImage to render the video content till EOF. Note that I use a usleep() to control the rendering frequency so it roughly plays like a normal video: 30fps.

Advertisements

Comments»

No comments yet — be the first.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: