Video解码出来需要使用DirectFB进行Blending,由于解出来的frame已经分配了buffer,所以想直接使用frame的buffer就可以创建surface,这样可以减少一次buffer的操作。在DFBSurfaceDescription的flags的属性中有一个feature为DSDESC_PREALLOCATED正好可以实现这个功能。我首先把解码完成的frame直接保存到一个文件中,frame的格式为YV12,只要DirectFB支持的格式都可以例如很多hardware解出来的为NV12,在测试代码中把相应的数据读出来map到内存中,最后attach到一个surface上,下面是具体的实现。
================================code begin=========================================
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <directfb.h>
static IDirectFB *dfb = NULL;
static IDirectFBSurface *primary = NULL;
static int screen_width, screen_height;
static int img_width = 720;
static int img_height= 480;
#define DFBCHECK(x...) \
{ \
DFBResult err = x; \
if (err != DFB_OK) \
{ \
fprintf( stderr, "%s<%d>:\n\t", __FILE__, __LINE__ );\
DirectFBErrorFatal( #x, err); \
} \
}
int main (int argc, char **argv){
DFBSurfaceDescription dsc;
DFBCHECK (DirectFBInit (&argc, &argv));
DFBCHECK (DirectFBCreate (&dfb));
DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_FULLSCREEN));
dsc.flags = DSDESC_CAPS;
dsc.caps = DSCAPS_PRIMARY |DSCAPS_FLIPPING;
DFBCHECK (dfb->CreateSurface( dfb, &dsc, &primary ));
DFBCHECK (primary->GetSize( primary, &screen_width,&screen_height ));
//fill screen with green
DFBCHECK (primary->SetColor(primary,0,255,0,255));
DFBCHECK(primary->FillRectangle(primary,0,0,screen_width,screen_height));
DFBCHECK (primary->Flip(primary, NULL, 0));
sleep(2);
//load data from file
intfd;
struct stat stat;
char * data;
fd= open( "dump01.yuv", O_RDONLY );
if(fd < 0) {
perror( "open" );
return 0;
}
if(fstat( fd, &stat ) < 0) {
perror( "fstat" );
close( fd );
return 0;
}
//map the data to memory
data = mmap( NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0 );
if(data == MAP_FAILED) {
perror( "mmap" );
close( fd );
return 0;
}
//Create a surface with your frame data
IDirectFBSurface *frm_surface = NULL;
DFBSurfaceDescription frm_dsc;
DFBRectangle clipRect = {0,0,img_width,img_height};
DFBRegion flipRegion = {0,0,img_width,img_height};
frm_dsc.flags =DSDESC_CAPS|DSDESC_PREALLOCATED|DSDESC_PIXELFORMAT|DSDESC_WIDTH|DSDESC_HEIGHT;
frm_dsc.caps =DSCAPS_SYSTEMONLY;//DSCAPS_NONE;
frm_dsc.width = img_width; //image width
frm_dsc.height = img_height; //image height
frm_dsc.pixelformat = DSPF_YV12; //video pixel format
frm_dsc.preallocated[0].data = data; //attach frame data
frm_dsc.preallocated[0].pitch = 2048; //stride in your data
frm_dsc.preallocated[1].data = NULL;
frm_dsc.preallocated[1].pitch = 0;
DFBCHECK (dfb->CreateSurface( dfb, &frm_dsc, &frm_surface ));
//draw to primary
DFBCHECK (primary->SetBlittingFlags( primary, DSBLIT_NOFX ));
DFBCHECK (primary->Blit(primary, frm_surface, &clipRect, 0, 0 ));
DFBCHECK (primary->Flip(primary, &flipRegion, 0));
//wait a moment
sleep(2);
//free something
frm_surface->Release(frm_surface);
primary->Release( primary );
dfb->Release( dfb );
close(fd);
return 23;
}
================================code end=========================================
另外还有一个问题Ubuntu中如何enable DirectFB,在网上查找了一些资料,一般都是说更改menu.lst文件,但是在我的系统中没有找到相应的文件,后来在找到另外一个方法就是在相关用户的目录下创建.directfbrc文件,解决了运行的问题,具体如下:
Log in into your gnome or kde or whatevergraphical environment you use. Open up a terminal in there and type:
nano ~/.directfbrc
What we’re going to do now is change a fewdirectfb settings to run it under X11. (see man directfbrc for more settings)
Just plain copy and paste the followingsettings in that file:
mode=1024×768
pixelformat=RGB32
system=x11
You can change the resolution to yourliking if you want.
Now type (still in that same console that’srunning inside your graphical environment):
df_window & // runs it in thebackground
df_cpuload &