[mythtv] [directfb-dev] Improved MythTV DirectFB output

Kristof Pelckmans kristof.pelckmans at antwerpen.be
Wed Mar 31 18:11:22 EST 2004


Hello,

I improved the DirectFB output driver :
- added support for hardware blitting (if the videocard supports this)
- improved format handling : I420 -> YV12 and I420 -> I420 are now perfectly
supported. The output driver looks for a video layer that supports I420, when
it doesn't find it, it falls back to YV12 with software format conversion.
- improved I420->YV12 software conversion, supporting different pitches (this
was a bug, see http://www.gossamer-threads.com/perl/mailarc/gforum.cgi?
post=113868) - in fact, DirectFB should handle this conversion, but it is not
yet implemented :-(
- improved buffering : all buffers are now DirectFB surfaces with the
appropriate width, height and format - maybe this buffering should turn into a
real DirectFBVideoProvider some day...
- implemented aspect change, remind to set the FRAMEBUFFER environment variable
when your framebuffer device is different from /dev/fb0. I need to access the
framebuffer directly in order to determine the screen width and height.
Hopefully DirectFB will offer some method to do determine this...

Still to do :
- support for zoom
- support for osd : it would be nice to render the osd as a seperate surface
and let DirectFB combine them using alpha blending : you would get a nice
transparant osd display :-)
- look at those pause and scratch frames

Some questions :
- When I look at the format of the vbuffers that I receive, they seem to be
I420. However, I explicitely set vbuffers[i].codec = FMT_YV12 ? Can the input
format change ?
- Can someone take a look at the cleanup for my data struct ? I'm getting a
warning from DirectFB that a few bytes are not freed. (You can see this when
you compiled DirectFB with debug and tracing options) Don't worry : the video
buffers are properly closed !
- Is it necessary to have 31 buffers ? This was taken from the xv output...
- I think I read somewhere that there is a DirectFB port of QT Embedded, it
would be nice to run this for the ui stuff :-)

I include patches against the latest cvs versions.

Kind regards,

Kristof
-------------- next part --------------
15a16,21
> #include <linux/fb.h>
> #include <sys/ioctl.h>
> #include <fcntl.h>
> #include <unistd.h>
> 
> 
243a250,251
> 	int screen_width;
> 	int screen_height;
259c267
< 	ClearSurface();
---
> 	ClearSurface(data->surface);
303,306c311,331
<     VideoOutput::InitBuffers(kNumBuffers, true, kNeedFreeFrames,
<                              kPrebufferFrames, kKeepPrebuffer);
<     VideoOutput::Init(width, height, aspect, winid, winx, winy, winw, winh,
<                       embedid);
---
> 	//determine screen size
> 	char *fb_dev_name = NULL;
> 	int fb_dev_fd;
> 	struct fb_var_screeninfo fb_vinfo;
> 
> 	if (!fb_dev_name && !(fb_dev_name = getenv("FRAMEBUFFER")))
> 			fb_dev_name = strdup("/dev/fb0");
> 
> 	if ((fb_dev_fd = open(fb_dev_name, O_RDWR)) == -1) {
>         DirectFBError("Couldn't open framebuffer", ret);
> 	}
> 	if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo)) {
>         DirectFBError("Couldn't get screeninfo", ret);
> 	}
> 	close(fb_dev_fd);
> 	fb_dev_fd = -1;
> 			
> 
> 	data->screen_width = (int)fb_vinfo.xres;
> 	data->screen_height = (int)fb_vinfo.yres;
> 
315c340
<     
---
> 	
383,387d407
< 	ClearSurface();
< 
< 	//display output layer
<     DFBCHECK(data->layer->SetOpacity(data->layer, 0xff));
< 
388a409,410
>     VideoOutput::InitBuffers(kNumBuffers, true, kNeedFreeFrames,
>                              kPrebufferFrames, kKeepPrebuffer);
392c414
<     //desc.pixelformat = DSPF_YV12;
---
> 	//can this change ?
447a470,478
>     VideoOutput::Init(width, height, aspect, winid, winx, winy, data->screen_width, data->screen_height,
>                       embedid);
> 	
> 	VERBOSE(VB_GENERAL, QString("DirectFB output : screen size %1x%2").arg(data->screen_width).arg(data->screen_height));
> 	MoveResize();
> 
> 	//display output layer
>     DFBCHECK(data->layer->SetOpacity(data->layer, 0xff));
> 
452,453c483
< // clear the surface
< void VideoOutputDirectfb::ClearSurface()
---
> float VideoOutputDirectfb::GetDisplayAspect(void)
455,462c485
< 	if (data->surface)
< 	{
< 		for(int i=0; i<3; i++)
< 		{
< 			DFBCHECK(data->surface->Clear(data->surface, 0x00, 0x00, 0x00, 0xff));
< 			DFBCHECK(data->surface->Flip(data->surface, NULL, DSFLIP_ONSYNC));
< 		}
< 	}
---
> 	return (float)data->screen_width/(float)data->screen_height;
465d487
< 
555,556c577,601
<     //**FIXME - should do something here
<     cerr << "DrawUnusedRects()" << endl;
---
> /* DirectFB only draws what is needed :-)
> 	VERBOSE(VB_GENERAL, QString("drawUnusedRects : screen size %1x%2, proposed x : %3, y : %4, w : %5, h : %6")
> 								.arg(data->screen_width)
> 								.arg(data->screen_height)
> 								.arg(dispxoff)
> 								.arg(dispyoff)
> 								.arg(dispwoff)
> 								.arg(disphoff));
>     // Draw black in masked areas
>     if (dispxoff > dispx) // left
> 		DFBCHECK (data->surface->FillRectangle (data->surface, 
>                        dispx, dispy, dispxoff-dispx, disph));
>     if (dispxoff+dispwoff < dispx+dispw) // right
> 		DFBCHECK (data->surface->FillRectangle (data->surface, 
>                        dispxoff+dispwoff, dispy, 
>                        (dispx+dispw)-(dispxoff+dispwoff), disph));
>     if (dispyoff > dispy) // bottom
> 		DFBCHECK (data->surface->FillRectangle (data->surface, 
>                        dispx, dispy, dispw, dispyoff-dispy));
>     if (dispyoff+disphoff < dispy+disph) // top
> 		DFBCHECK (data->surface->FillRectangle (data->surface, 
>                        dispx, dispyoff+disphoff, 
>                        dispw, (dispy+disph)-(dispyoff+disphoff)));
> //	DFBCHECK (data->surface->Flip (data->surface, NULL, 0));
> */
594d638
<     //**FIXME - MoveResize()??
598a643
> 	MoveResize();
614,615c659,660
<     //**FIXME - -do something here
<     cerr << "AspectChanged()" << endl;
---
>     VideoOutput::AspectChanged(aspect);
>     MoveResize();
623a669,689
> void VideoOutputDirectfb::MoveResize(void)
> {
>     VideoOutput::MoveResize();
> 
> 	VERBOSE(VB_GENERAL, QString("DirectFB MoveResize : screen size %1x%2, proposed x : %3, y : %4, w : %5, h : %6")
> 								.arg(data->screen_width)
> 								.arg(data->screen_height)
> 								.arg(dispxoff)
> 								.arg(dispyoff)
> 								.arg(dispwoff)
> 								.arg(disphoff));
> 	//**FIXME support for zooming when dispwoff > screenwidth || disphoff > screenheight
> 	DFBCHECK(data->layer->SetScreenLocation(data->layer,
> 											(float)dispxoff/(float)data->screen_width,
> 											(float)dispyoff/(float)data->screen_height,
> 											(float)dispwoff/(float)data->screen_width,
> 											(float)disphoff/(float)data->screen_height));
> }
> 	
> 
> 
640c706
< 		//TO DO: set the three following parameters correctly
---
> 		//**FIXME set the three following parameters correctly
664d729
< 
669a735
> 	IDirectFBSurface *surface;
672a739,742
> 	//clear every surface we discover
> 	DFBCHECK(vodata->layer->GetSurface(vodata->layer, &surface));
> 	ClearSurface(surface);
> 
-------------- next part --------------
28c28
<     void AspectChanged(float aspect);
---
> 	void AspectChanged(float aspect);
30a31,33
> 	float GetDisplayAspect(void);
> 	void VideoOutputDirectfb::MoveResize();
> 
57d59
<     void ClearSurface(void);
81c83,94
< 
---
> static inline void ClearSurface(IDirectFBSurface *surface)
> {
>     if (surface)
>     {
>         for(int i=0; i<3; i++)
>         {
>             //DFBCHECK(surface->FillRectangle(surface, 0, 0, data->screen_width, data->screen_height));
>             surface->Clear(surface, 0x00, 0x00, 0x00, 0xff);
>             surface->Flip(surface, NULL, DSFLIP_ONSYNC);
>         }
>     }
> }


More information about the mythtv-dev mailing list