全部博文(218)
分类: LINUX
2008-05-15 11:24:45
mplayer video_out driver
在很多应用中的图形输出数据是存放在一些指定的内存区域的,
比如说我现在实现的基于minigui图形中间件的mplayer播放器的,在播放前需要告诉mplayer当前播放窗口所在的内存地址和当前的屏幕像素深度,bpp,窗口大小等等一系列的信息,这就有必要给mplayer写个自己的video_out driver了.
和大多数驱动一样,mplayer也提供了一个驱动函数结构体,其结构体定义如下(在libvo/video_out.h文件中定义):
typedef struct vo_functions_s
{
/*
* Preinitializes driver (real INITIALIZATION)
* arg - currently it's vo_subdevice
* returns: zero on successful initialization, non-zero on error.
*/
int (*preinit)(const char *arg);
/*
* Initialize (means CONFIGURE) the display driver.
* params:
* width,height: image source size
* d_width,d_height: size of the requested window size, just a hint
* fullscreen: flag, 0=windowd 1=fullscreen, just a hint
* title: window title, if available
* format: fourcc of pixel format
* returns : zero on successful initialization, non-zero on error.
*/
int (*config)(uint32_t width, uint32_t height, uint32_t d_width,
uint32_t d_height, uint32_t fullscreen, char *title,
uint32_t format);
/*
* Control interface
*/
int (*control)(uint32_t request, void *data, ...);
/*
* Display a new RGB/BGR frame of the video to the screen.
* params:
* src[0] - pointer to the image
*/
int (*draw_frame)(uint8_t *src[]);
/*
* Draw a planar YUV slice to the buffer:
* params:
* src[3] = source image planes (Y,U,V)
* stride[3] = source image planes line widths (in bytes)
* w,h = width*height of area to be copied (in Y pixels)
* x,y = position at the destination image (in Y pixels)
*/
int (*draw_slice)(uint8_t *src[], int stride[], int w,int h, int x,int y);
/*
* Draws OSD to the screen buffer
*/
void (*draw_osd)(void);
/*
* Blit/Flip buffer to the screen. Must be called after each frame!
*/
void (*flip_page)(void);
/*
* This func is called after every frames to handle keyboard and
* other events. It's called in PAUSE mode too!
*/
void (*check_events)(void);
/*
* Closes driver. Should restore the original state of the system.
*/
void (*uninit)(void);
} vo_functions_t;
1:初始化驱动(preinit 函数和 uninit 函数):
当驱动初始化时将调用preinit ,退出时则调用uninit函数(注意:播放器在每播放一个媒体文件时都会初始化一次video驱动的).
在preinit函数里可以做我们一些初始化工作,比如指定存放音频的内存地址,当前设备支持的像素,窗口大小,和bpp(每像素点需要用多少bite存储)等工作。
而uninit 函数则可以做些收尾工作了....
2:告诉mplayer设备支持的图形显示格式
在mplayer调用完preinit 函数后, 它就要开始输出数据啦。 它在输出前会去查询下驱动支持的像素格式等一些大小,这时候它将调用驱动的control函数,并且传递 VOCTRL_QUERY_FORMAT参数, 这时候我们就应该把preinit函数中设置的参数告诉mplayer,然后mplayer就按设备支持的格式输出数据,
3:获取mplayer图形数据:
获取mplayer数据有很多种方法,这些方法可以根据设备来选择,这里我们只使用最简单的方法VOCTRL_DRAW_IMAGE。
同样还是在control函数函数中,当mplayer输出数据将会调用control函数并传递VOCTRL_DRAW_IMAGE参数和 mp_image_t指针,我们可以通过mp_image_t指针来获取图像数据的大小,存放的位置等必要信息,然后将这些存放在显示内存中显示出来...
int dx = mpi->w
int dy = mpi->h
uint8_t *buf = mpi->planes[0]
int stride = mpi->stride[0]
4:其它:
config函数:
mplayer将调用config函数来通知驱动,mplayer显示图形的原始大小,和播放的最佳大小,和影片标题等信息,这些信息只是给驱动提供参考值的.
还有其它draw_frame,draw_slice,draw_osd,flip_page等接口可以按需使用,充分利用mplayer提供的接口可以打造一个性能较优的video_out驱动的。
5:结尾
现在只是使用了简单的mplayer驱动的方法,其实还有很多点可以去优化的,比如说让mplayer直接将数据写到显示内存中,而不再先放入mp_image_t结构体中,充分利用其它的几个接口来提高驱动的性能。