本文只關注FBDEV相關的內容,其它的或不提,或略過。
首先從Mplayer.c中的main函數開始,注意到
//================== Init VIDEO (codec & libvo) ==========================
current_module=”preinit_libvo”;
if( !(video_out=init_best_video_out(video_driver_list)) )
這將跳進Video_out.c
for(i=0;video_out_drivers[i];i++){
if(!video_driver->preinit(vo_subdevice))
如果你的FBDEV打開的話,即若有
#ifdef HAVE_FBDEV
&video_out_fbdev,
&video_out_fbdev2,
那麼 video_driver->preinit(vo_subdevice) 將跳進Vo_fbdev.c中執行preinit操作。
Preinit中進行了 fb_dev_fd = open(fb_dev_name, O_RDWR) 和一些ioctl對framebuffer設備的訊息進行讀取:
ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo),至此,FBDEV相關的pre初始化操作基本結束。。。。省略其他無關的訊息
進入
/*========================== PLAY VIDEO =============
這裡面最重要的一個操作就是解出一幀︰
//────── Decode a frame: ───────-
// get it!
current_module=”video_read_frame”;
具體如何解,暫時不提,但應關注一下結果:
in_size=video_read_frame(sh_video,&next_frame_time,&start,force_fps);
其中 video_read_frame 是 Video.c 中的函數,回傳得到了這一幀在暫存區的起始值start和長度in_size。
由於現下得到的本幀還只是未解碼的訊息,下一步就是要進行解碼操作:
// decode:
current_module=”decode_video”;
blit_frame=decode_video(sh_video,start,in_size,drop_frame);
執行時將跳進 Dec_video.c 中的 decode_video 函數。
mpi=mpvdec->decode(sh_video, start, in_size, drop_frame);
之後,得到了這一幀的原始的mp_image_t的圖像格式,基本上可以說是最終可用的數據了。
下一步就是如何將數據帶進Fb設備中了。
vf=sh_video->vfilter;
ret = vf->put_image(vf,mpi); // apply video filters and call the leaf vo/ve
這段實際上就是我們想要的。
原來的作者曾有一句註釋掉的,則更為清晰: //vo_draw_image(video_out,mpi);
意思則是說將mpi數據直接刷到已經初始化好的 video_out 去。
Vf_vo.c中實現了上述一段的主要功能︰
#define video_out ((vo_functions_t*)(vf->priv)) 定義了video_out實際為vo_functions_t類型。
而 vf->put_image(vf,mpi) 的呼叫,
video_out->draw_slice(mpi->planes,mpi->stride,mpi->w,mpi->h,mpi->x,mpi->y);
呼叫 draw_slice 函數的原型為在 Video_out.h 中的
/*
* 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)
*/
uint32_t (*draw_slice)(uint8_t *src[], int stride[], int w,int h, int x,int y);
也就是此時將調用Vo_fbdev.c中的
static uint32_t draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y)
{
uint8_t *d;
uint8_t *s;
d = center + (fb_line_len * y + x) * fb_pixel_size;
s = src[0];
while (h) {
memcpy(d, s, w * fb_pixel_size);
d += fb_line_len;
s += stride[0];
h ;
}
return 0;
}
從而完成從 mpi 到 framebuffer 的記憶體複製。
留言列表