[mythtv] Improved MythTV DirectFB output
Kristof Pelckmans
kristof.pelckmans at antwerpen.be
Thu Apr 1 17:28:51 EST 2004
Messed up the patches somewhere along the way...
Quoting Kristof Pelckmans <kristof.pelckmans at antwerpen.be>:
> 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 --------------
5d4
<
12a12
> #include "mythcontext.h"
14a15,20
> #include <map>
> #include <linux/fb.h>
> #include <sys/ioctl.h>
> #include <fcntl.h>
> #include <unistd.h>
>
19a26,47
> #define DFBCHECKFAIL(dfbcommand, returnstmt...) \
> { \
> DFBResult err = dfbcommand; \
> \
> if (err != DFB_OK) \
> { \
> fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
> DirectFBError( #dfbcommand, err ); \
> return returnstmt; \
> } \
> }
>
> #define DFBCHECK(x...) \
> { \
> DFBResult err = x; \
> \
> if (err != DFB_OK) \
> { \
> fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
> DirectFBError( #x, err ); \
> } \
> }
20a49,102
>
>
> /*static const int FORMATS[1][2] =
> {
> //FMT_XVMC_IDCT_MPEG2,
> //FMT_XVMC_MOCO_MPEG2,
> //FMT_VIA_HWSLICE,
> //FMT_IA44,
> //FMT_AI44,
> //FMT_YUV422P
>
> {DSPF_UNKNOWN, FMT_NONE, "no format",
>
> //16bit ARGB (2 bytes, alpha 1 at 15, red 5 at 10, green 5 at 5, blue 5 at 0)
> {DSPF_ARGB1555, FMT_NONE, "16bit ARGB"},
>
> //16bit RGB (2 bytes, red 5 at 11, green 6 at 5, blue 5 at 0)
> {DSPF_RGB16, FMT_NONE, "16bit RGB"},
>
> //24bit RGB (3 bytes, red 8 at 16, green 8 at 8, blue 8 at 0)
> {DSPF_RGB24, FMT_RGB24, "24bit RGB"},
>
> //24bit RGB (4 bytes, nothing at 24, red 8 at 16, green 8 at 8, blue 8 at 0)
> {DSPF_RGB32, FMT_NONE, "24bit RGB"},
>
> //32bit ARGB (4 bytes, alpha 8 at 24, red 8 at 16, green 8 at 8, blue 8 at 0)
> {DSPF_ARGB, FMT_ARGB32, "32bit ARGB"},
>
> //8bit alpha (1 byte, alpha 8 at 0 ), e.g. anti-aliased text glyphs
> {DSPF_A8, FMT_NONE, "8bit alpha"},
>
> //A macropixel (32bit / 2 pixel) contains YUYV (starting with the LOWEST byte on the LEFT)
> {DSPF_YUY2, FMT_NONE, "A macropixel (32bit / 2 pixel) contains YUYV (starting with the LOWEST byte on the LEFT)"},
>
> //8bit true color (1 byte, red 3 at 5, green 3 at 2, blue 2 at 0
> {DSPF_RGB332, FMT_NONE, "8bit true color"},
>
> //A macropixel (32bit / 2 pixel) contains UYVY (starting with the LOWEST byte on the LEFT)
> {DSPF_UYVY, FMT_NONE, "UYVY"},
>
> //8 bit Y plane followed by 8 bit 2x2 subsampled U and V planes
> {DSPF_I420, FMT_NONE, "I420 : Yuv"},
>
> //8 bit Y plane followed by 8 bit 2x2 subsampled V and U planes
> {DSPF_YV12, FMT_YV12, "YV12 : Yvu"},
>
> //8 bit lookup table (palette)
> {DSPF_LUT8, FMT_NONE, "8 bit lookup table (palette)"},
>
> //4 bit alpha + 4 bit lookup table
> {DSPF_ALUT44, FMT_NONE, "ALUT44"}
> }
> */
>
147,148d228
<
<
155,165d234
< struct DirectfbParams
< {
< uint32_t format;
< int scale;
< int result;
< unsigned int id;
< unsigned int width;
< unsigned int height;
< int setsize;
< };
<
167a237
> //DirectFB hook
168a239,243
> //video output
> DFBCardCapabilities cardCapabilities;
> IDirectFBDisplayLayer *layer;
> DFBDisplayLayerDescription layerDesc;
> DFBDisplayLayerConfig layerConfig;
170c245
< struct DirectfbParams params;
---
> //input handling
172a248,251
> //buffers
> map<unsigned char *, IDirectFBSurface *> buffers;
> int screen_width;
> int screen_height;
174a254,255
> IDirectFBSurface *tempYV12Surface;
>
185,186d265
< DFBResult ret;
<
188,204c267,268
< ret = data->surface->Clear(data->surface, 0x00, 0x00, 0x00, 0x00);
< if (ret)
< {
< DirectFBError("Couldn't clear the buffers", ret);
< }
<
< ret = data->surface->Flip(data->surface, NULL, DSFLIP_ONSYNC);
< if (ret)
< {
< DirectFBError("Couldn't flip the buffers", ret);
< }
<
< ret = data->surface->Clear(data->surface, 0x00, 0x00, 0x00, 0x00);
< if (ret)
< {
< DirectFBError("Couldn't clear the buffers", ret);
< }
---
> ClearSurface(data->surface);
> DeleteDirectfbBuffers();
212a277,280
> if (tempYV12Surface)
> tempYV12Surface->Release(tempYV12Surface);
> if (data->layer)
> data->layer->Release(data->layer);
227d294
< DeleteDirectfbBuffers();
241,244c308
< DFBDisplayLayerConfig dlc;
< IDirectFBDisplayLayer *layer;
< IDirectFBSurface *primary;
<
---
>
247,261c311,314
< VideoOutput::InitBuffers(kNumBuffers, true, kNeedFreeFrames,
< kPrebufferFrames, kKeepPrebuffer);
< VideoOutput::Init(width, height, aspect, winid, winx, winy, winw, winh,
< embedid);
<
< ret = DirectFBInit(NULL,NULL);
<
< if (ret)
< {
< DirectFBError( "Couldn't initialize DirectFB", ret );
< return false;
< }
<
< DirectFBSetOption("bg-none",NULL);
< DirectFBSetOption("no-cursor",NULL);
---
> //determine screen size
> char *fb_dev_name = NULL;
> int fb_dev_fd;
> struct fb_var_screeninfo fb_vinfo;
263c316,317
< ret = DirectFBCreate( &(data->dfb) );
---
> if (!fb_dev_name && !(fb_dev_name = getenv("FRAMEBUFFER")))
> fb_dev_name = strdup("/dev/fb0");
265,329c319,327
< if (ret)
< {
< DirectFBError( "Couldn't create DirectFB subsystem", ret );
< return false;
< }
<
< ret = data->dfb->GetDisplayLayer(data->dfb, DLID_PRIMARY, &layer);
<
< if (ret)
< {
< DirectFBError("No primary display layer - WTF?", ret);
< return false;
< }
<
< layer->SetOpacity(layer, 0);
< ret = layer->GetSurface(layer, &primary);
<
< if (ret)
< {
< DirectFBError("Couldn't get primary display surface", ret);
< return false;
< }
<
< data->params.result = 0;
<
< ret = data->dfb->EnumDisplayLayers(data->dfb, LayerCallback, data);
<
< if (ret)
< {
< DirectFBError("Couldn't enumerate display layers", ret);
< return false;
< }
<
< ret = data->dfb->GetDisplayLayer(data->dfb, 1, &layer);
<
< if (ret)
< {
< DirectFBError("Couldn't get our display layer - this shouldn't happen", ret);
< return false;
< }
<
< ret = layer->SetCooperativeLevel(layer, DLSCL_EXCLUSIVE);
<
< if (ret)
< {
< DirectFBError("Couldn't get exclusive access", ret);
< return false;
< }
<
< //**FIXME set up size - should be based on width of video
< dlc.flags = (DFBDisplayLayerConfigFlags)(DLCONF_WIDTH | DLCONF_HEIGHT);
< dlc.width = width;
< dlc.height = height;
<
< ret = layer->SetConfiguration(layer, &dlc);
<
< if (ret)
< {
< DirectFBError("Couldn't set display size", ret);
< return false;
< }
<
< //**FIXME set up pixelformat - should be based on video
< dlc.flags = DLCONF_PIXELFORMAT;
< dlc.pixelformat = DSPF_YV12;
---
> 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;
>
331c329,330
< ret = layer->SetConfiguration(layer, &dlc);
---
> data->screen_width = (int)fb_vinfo.xres;
> data->screen_height = (int)fb_vinfo.yres;
333,337d331
< if (ret)
< {
< DirectFBError("Couldn't set requested pixelformat", ret);
< return false;
< }
339,341c333,337
< dlc.flags = DLCONF_BUFFERMODE;
< dlc.buffermode = DLBM_TRIPLE;
< ret = layer->SetConfiguration(layer, &dlc);
---
> //setup DirectFB
> DFBCHECKFAIL(DirectFBInit(NULL,NULL), false);
>
> DirectFBSetOption("bg-none",NULL);
> DirectFBSetOption("no-cursor",NULL);
343,345c339,362
< if (ret)
< {
< DirectFBError("Couldn't set up triple buffering, trying double", ret);
---
> DFBCHECKFAIL(DirectFBCreate( &(data->dfb) ), false);
>
> //determine output card capacities
> DFBCHECKFAIL(data->dfb->GetCardCapabilities(data->dfb, &(data->cardCapabilities)), false);
> VERBOSE(VB_GENERAL, QString("DirectFB output : card : %1")
> .arg((data->cardCapabilities.acceleration_mask & DFXL_BLIT) > 0 ?
> "hardware blit support" : "NO hardware blit support"));
>
>
> //look up an output layer that supports the right format, begin with the video format we have as input, fall back to others
> data->layerConfig.flags = (DFBDisplayLayerConfigFlags)(DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT);
> data->layerConfig.width = width;
> data->layerConfig.height = height;
> data->layerConfig.pixelformat = DSPF_I420;
>
> DFBCHECK(data->dfb->EnumDisplayLayers(data->dfb, LayerCallback, data));
>
> if(data->layer == NULL) {
> data->layerConfig.pixelformat = DSPF_YV12;
> DFBCHECK(data->dfb->EnumDisplayLayers(data->dfb, LayerCallback, data));
> if(data->layer == NULL) {
> return false;
> }
> }
347,348c364,365
< dlc.buffermode = DLBM_BACKVIDEO;
< ret = layer->SetConfiguration(layer, &dlc);
---
> //setup output layer
> DFBCHECKFAIL(data->layer->SetCooperativeLevel(data->layer, DLSCL_EXCLUSIVE), false);
350c367,374
< if (ret)
---
> //determine buffering capacities
> data->layerConfig.flags = (DFBDisplayLayerConfigFlags)(data->layerConfig.flags | DLCONF_BUFFERMODE);
> data->layerConfig.buffermode = DLBM_TRIPLE;
> if (data->layer->TestConfiguration(data->layer, &(data->layerConfig), NULL))
> {
> //try double buffering in video memory
> data->layerConfig.buffermode = DLBM_BACKVIDEO;
> if (data->layer->TestConfiguration(data->layer, &(data->layerConfig), NULL))
352,358c376,377
< dlc.buffermode = DLBM_BACKSYSTEM;
< ret = layer->SetConfiguration(layer, &dlc);
<
< if (ret)
< {
< DirectFBError("Couldn't set up double buffering, falling back to single buffer", ret);
< }
---
> //fall back to double buffering in system memory
> data->layerConfig.buffermode = DLBM_BACKSYSTEM;
360a380,381
>
> DFBCHECKFAIL(data->layer->SetConfiguration(data->layer, &(data->layerConfig)), false);
361a383,406
> VERBOSE(VB_GENERAL, QString("DirectFB output : layer : %1 : %2x%3, %4, %5 buffering")
> .arg(data->layerDesc.name)
> .arg(data->layerConfig.width)
> .arg(data->layerConfig.height)
> .arg(data->layerConfig.pixelformat == DSPF_I420 ? "I420 : Yuv" : "YV12 : Yvu")
> .arg(
> data->layerConfig.buffermode == DLBM_TRIPLE ? "triple" :
> data->layerConfig.buffermode == DLBM_BACKVIDEO ? "double" :
> "single")
> );
>
> //setup output surface
> DFBCHECKFAIL(data->layer->GetSurface(data->layer, &(data->surface)), false);
>
> DFBCHECKFAIL(data->surface->SetBlittingFlags(data->surface, DSBLIT_NOFX), false);
>
> DFBSurfaceCapabilities capabilities;
> DFBCHECKFAIL(data->surface->GetCapabilities(data->surface, &capabilities), false);
>
> VERBOSE(VB_GENERAL, QString("DirectFB output : surface : %1, %2, %3")
> .arg((capabilities & DSCAPS_VIDEOONLY) > 0 ? "in video memory" : "in sytem memory")
> .arg((capabilities & DSCAPS_PRIMARY) > 0 ? "primary surface" : "no primary surface")
> .arg((capabilities & DSCAPS_INTERLACED) > 0 ? "interlaced" : "not interlaced")
> );
363,378c408,410
< ret = layer->GetSurface(layer, &(data->surface));
<
< if (ret)
< {
< DirectFBError( "Couldn't get our layer's surface - this is bad", ret);
< return false;
< }
<
< ret = data->surface->SetBlittingFlags(data->surface, DSBLIT_NOFX);
<
< if (ret)
< {
< DirectFBError("Couldn't set up Blitting flags - continuing anyway", ret);
< }
<
< //**FIXME set surface properties - should use video
---
> //setup input buffers
> VideoOutput::InitBuffers(kNumBuffers, true, kNeedFreeFrames,
> kPrebufferFrames, kKeepPrebuffer);
382c414,415
< desc.pixelformat = DSPF_YV12;
---
> //can this change ?
> desc.pixelformat = DSPF_I420;
383a417,437
> if (!CreateDirectfbBuffers(desc))
> return false;
>
> VERBOSE(VB_GENERAL, QString("DirectFB input : %1 surface buffers : %1x%2, %3")
> .arg(kNumBuffers)
> .arg(desc.width)
> .arg(desc.height)
> .arg(desc.pixelformat == DSPF_I420 ? "I420 : Yuv" : "YV12 : Yvu")
> );
> //prepare to do a software conversion when the output format is Yvu
> //(DirectFB does not support software conversion from Yuv -> Yvu yet)
> if(data->layerConfig.pixelformat == DSPF_YV12)
> {
> desc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_HEIGHT | DSDESC_WIDTH | DSDESC_PIXELFORMAT | DSDESC_CAPS);
> desc.width = width;
> desc.height = height;
> desc.pixelformat = DSPF_YV12;
> //allocate in system memory
> desc.caps=DSCAPS_SYSTEMONLY;
> DFBCHECKFAIL(data->dfb->CreateSurface(data->dfb, &desc, &tempYV12Surface), false);
> }
385,411c439
< // clear the surface
< ret = data->surface->Clear(data->surface, 0x00, 0x00, 0x00, 0x00);
< if (ret)
< {
< DirectFBError("Couldn't clear the buffers", ret);
< }
<
< ret = data->surface->Flip(data->surface, NULL, DSFLIP_ONSYNC);
< if (ret)
< {
< DirectFBError("Couldn't flip the buffers", ret);
< }
<
< ret = data->surface->Clear(data->surface, 0x00, 0x00, 0x00, 0x00);
< if (ret)
< {
< DirectFBError("Couldn't clear the buffers", ret);
< }
<
< //show the surface
< ret = layer->SetOpacity(layer, 255);
<
< if (ret)
< {
< DirectFBError("Couldn't make our layer visible - nothing to see here, go home", ret);
< }
<
---
> //setup input handling
432,434d459
< if (!CreateDirectfbBuffers())
< return false;
<
435a461
> //first frame of the buffers
444c470,477
< XJ_started = true;
---
> 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));
445a479
> XJ_started = true;
449c483
< void VideoOutputDirectfb::PrepareFrame(VideoFrame *buffer)
---
> float VideoOutputDirectfb::GetDisplayAspect(void)
451,455c485,486
< DFBResult ret;
<
< int width, height, ysize, uvsize;
< unsigned char *framebuf, *src, *dst;
< int pitch;
---
> return (float)data->screen_width/(float)data->screen_height;
> }
456a488,489
> void VideoOutputDirectfb::PrepareFrame(VideoFrame *buffer)
> {
460,481c493
< width = buffer->width;
< height = buffer->height;
< ysize = width * height;
< uvsize = ysize / 4;
<
< ret = data->surface->Lock(data->surface, DSLF_WRITE, (void**)(&framebuf), &pitch);
<
< if (ret)
< {
< DirectFBError("Couldn't get write access to our surface", ret);
< return;
< }
<
< //memcpy(framebuf, buffer->buf, ysize * 3 / 2);
< //**FIXME copy the frame's planes onto the surface - should do different
< //behaviour depending on video?
< //y-plane
< memcpy(framebuf, buffer->buf, ysize);
< //u-plane
< memcpy(framebuf + width * height, buffer->buf + uvsize * 5, uvsize);
< //v-plane
< memcpy(framebuf + uvsize * 5, buffer->buf + ysize, uvsize);
---
> IDirectFBSurface *bufferSurface = data->buffers[buffer->buf];
483,488c495,553
< ret = data->surface->Unlock(data->surface);
<
< if (ret)
< {
< DirectFBError("Unlock() failed", ret);
< }
---
> if(data->layerConfig.pixelformat == DSPF_YV12)
> {
> //do a software conversion in a temporary memory buffer, since DirectFB does not handle this (yet ?)
> int pitch;
> int width, height;
> unsigned char *src, *dst;
>
> width = buffer->width;
> height = buffer->height;
> src = buffer->buf;
>
> DFBCHECKFAIL(tempYV12Surface->Lock(tempYV12Surface, DSLF_WRITE, (void **)&dst, &pitch));
> //! pitch is not considered : since the surface is in memory, normally there is no pitch
> //src Yuv -> dst Yvu
> //src Y -> dst Y
> memcpy(dst, src, width * height);
> //src V -> dst V
> memcpy(dst + width * height, src + width * height * 5 / 4, width * height / 4);
> //src U -> dst U
> memcpy(dst + width * height * 5 / 4, src + width * height, width * height / 4);
>
> DFBCHECK(tempYV12Surface->Unlock(tempYV12Surface));
> bufferSurface = tempYV12Surface;
> }
> if(!bufferSurface)
> return;
> if((data->cardCapabilities.acceleration_mask & DFXL_BLIT) > 0)
> {
> DFBCHECK(data->surface->Blit(data->surface, bufferSurface, NULL, 0, 0));
> }
> else
> {
> //unaccelerated hardware - probably you do not want this !
> int pitchsrc;
> int pitchdst;
> int width, height;
> unsigned char *src, *dst;
>
> width = buffer->width;
> height = buffer->height;
> DFBCHECKFAIL(bufferSurface->Lock(bufferSurface, DSLF_READ, (void **)&src, &pitchsrc));
> DFBCHECKFAIL(data->surface->Lock(data->surface, DSLF_WRITE, (void **)&dst, &pitchdst));
> //Y
> memcpy_pic(dst, src, width, height, pitchdst, pitchsrc);
> dst += pitchdst * height;
> src += pitchsrc * height;
> //u (I420) or v (YV12)
> width /= 2;
> height /= 2;
> pitchsrc /= 2;
> pitchdst /= 2;
> memcpy_pic(dst, src, width, height, pitchdst, pitchsrc);
> dst += pitchdst * height;
> src += pitchsrc * height;
> //v (I420) or y (YV12)
> memcpy_pic(dst, src, width, height, pitchdst, pitchsrc);
> DFBCHECK(bufferSurface->Unlock(bufferSurface));
> DFBCHECK(data->surface->Unlock(data->surface));
> }
493,495d557
< DFBResult ret;
<
< ret = data->surface->Flip(data->surface, NULL, DSFLIP_ONSYNC);
497,500c559
< if (ret)
< {
< DirectFBError("Couldn't flip the buffers", ret);
< }
---
> DFBCHECK(data->surface->Flip(data->surface, NULL, DSFLIP_ONSYNC));
518,519c577,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));
> */
552c634,638
< //**FIXME - MoveResize()??
---
> DFBSurfaceDescription desc;
> desc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_HEIGHT | DSDESC_WIDTH);
> desc.width = width;
> desc.height = height;
>
556c642,643
< CreateDirectfbBuffers();
---
> CreateDirectfbBuffers(desc);
> MoveResize();
572,573c659,660
< //**FIXME - -do something here
< cerr << "AspectChanged()" << endl;
---
> VideoOutput::AspectChanged(aspect);
> MoveResize();
582c669
< bool VideoOutputDirectfb::CreateDirectfbBuffers(void)
---
> void VideoOutputDirectfb::MoveResize(void)
583a671,696
> 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));
> }
>
>
>
> bool VideoOutputDirectfb::CreateDirectfbBuffers(DFBSurfaceDescription desc)
> {
> int pitch;
> //allocate each surface in system memory
> desc.flags = (DFBSurfaceDescriptionFlags)(desc.flags | DSDESC_CAPS);
> desc.caps=DSCAPS_SYSTEMONLY;
>
586,587c699,706
< vbuffers[i].height = XJ_height;
< vbuffers[i].width = XJ_width;
---
> IDirectFBSurface *bufferSurface;
> unsigned char *bufferSurfaceData;
> DFBCHECKFAIL(data->dfb->CreateSurface(data->dfb, &desc, &bufferSurface), false);
> DFBCHECKFAIL(bufferSurface->Lock(bufferSurface, DSLF_WRITE, (void **)&bufferSurfaceData, &pitch), false);
> data->buffers[bufferSurfaceData] = bufferSurface;
> vbuffers[i].height = desc.height;
> vbuffers[i].width = desc.width;
> //**FIXME set the three following parameters correctly
589c708,709
< vbuffers[i].size = XJ_height * XJ_width * 3 / 2;
---
> vbuffers[i].size = desc.height * desc.width * 3 / 2;
> //The format FMT_YV12 is a I420 ???? - Can the buffer format change ????
591c711
< vbuffers[i].buf = new unsigned char[vbuffers[i].size];
---
> vbuffers[i].buf = bufferSurfaceData;
599c719,720
< for (int i = 0 ; i < numbuffers +1; i++)
---
> map<unsigned char *, IDirectFBSurface *>::iterator iter = data->buffers.begin();
> for (int i = 0 ; iter != data->buffers.end() ; iter++, i++)
600a722,723
> DFBCHECK(iter->second->Unlock(iter->second));
> DFBCHECK(iter->second->Release(iter->second));
603a727
> data->buffers.clear();
606d729
< //**FIXME - is there a way to make this part of the class?
611,612d733
< struct DirectfbParams *params = &(vodata->params);
< IDirectFBDisplayLayer *layer;
613a735
> IDirectFBSurface *surface;
615,631c737
< ret = vodata->dfb->GetDisplayLayer(vodata->dfb, id, &layer);
<
< if (ret)
< {
< DirectFBError("Couldn't open layer", ret);
< return DFENUM_OK;
< }
<
< DFBDisplayLayerConfig dlc;
<
< if (params->setsize)
< {
< dlc.flags = (DFBDisplayLayerConfigFlags)(DLCONF_WIDTH | DLCONF_HEIGHT);
< dlc.width = params->width;
< dlc.height = params->height;
<
< ret = layer->SetConfiguration(layer, &dlc);
---
> DFBCHECKFAIL(vodata->dfb->GetDisplayLayer(vodata->dfb, id, &(vodata->layer)), DFENUM_OK);
633,642c739,741
< if (ret)
< {
< DirectFBError("Couldn't set layer size", ret);
< }
< }
<
< dlc.flags = DLCONF_PIXELFORMAT;
< dlc.pixelformat = DSPF_YV12;
<
< layer->SetOpacity(layer, 0);
---
> //clear every surface we discover
> DFBCHECK(vodata->layer->GetSurface(vodata->layer, &surface));
> ClearSurface(surface);
644,646c743
< ret = layer->TestConfiguration(layer, &dlc, NULL);
<
< layer->Release(layer);
---
> ret = vodata->layer->TestConfiguration(vodata->layer, &(vodata->layerConfig), NULL);
650,663c747,748
< if (params->result)
< {
< if (!params->scale && 0)
< {
< params->scale = 1;
< params->id = id;
< }
< else
< {
< params->result = 1;
< params->id = id;
< }
< }
<
---
> vodata->layerDesc = desc;
> return DFENUM_CANCEL;
665c750,752
<
---
> else {
> vodata->layer->Release(vodata->layer);
> }
-------------- next part --------------
28c28
< void AspectChanged(float aspect);
---
> void AspectChanged(float aspect);
30a31,33
> float GetDisplayAspect(void);
> void VideoOutputDirectfb::MoveResize();
>
55c58
< bool CreateDirectfbBuffers(void);
---
> bool CreateDirectfbBuffers(DFBSurfaceDescription);
61a65,93
> static inline void * memcpy_pic(unsigned char * dst, unsigned char * src, int bytesPerLine, int height, int dstStride, int srcStride)
> {
> int i;
> void *retval=dst;
>
> if(dstStride == srcStride) memcpy(dst, src, srcStride*height);
> else
> {
> for(i=0; i<height; i++)
> {
> memcpy(dst, src, bytesPerLine);
> src+= srcStride;
> dst+= dstStride;
> }
> }
>
> return retval;
> }
> static inline void ClearSurface(IDirectFBSurface *surface)
> {
> if (surface)
> {
> for(int i=0; i<3; i++)
> {
> surface->Clear(surface, 0x00, 0x00, 0x00, 0xff);
> surface->Flip(surface, NULL, DSFLIP_ONSYNC);
> }
> }
> }
More information about the mythtv-dev
mailing list