Mercurial > mplayer.hg
view libvo/vo_directfb2.c @ 7581:31d0ea35c66b
Fixing potential future problem with buffer overrun
author | anders |
---|---|
date | Wed, 02 Oct 2002 11:00:37 +0000 |
parents | fcbe94c83ff6 |
children | 530d1c5f0c78 |
line wrap: on
line source
/* MPlayer video driver for DirectFramebuffer device (C) 2002 Written by Jiri Svoboda <Jiri.Svoboda@seznam.cz> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // directfb includes #include <directfb.h> // other things #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <ctype.h> #include <assert.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <sys/kd.h> #include "config.h" #include "video_out.h" #include "video_out_internal.h" #include "fastmemcpy.h" #include "sub.h" #include "aspect.h" #ifndef min #define min(x,y) (((x)<(y))?(x):(y)) #endif LIBVO_EXTERN(directfb) static vo_info_t vo_info = { "Direct Framebuffer Device", "directfb", "Jiri Svoboda Jiri.Svoboda@seznam.cz", "version 2.0beta" }; extern int verbose; /****************************** * vo_directfb globals * ******************************/ #define DFBCHECK(x...) \ { \ DFBResult err = x; \ \ if (err != DFB_OK) \ { \ fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \ DirectFBErrorFatal( #x, err ); \ } \ } /* * filled by preinit */ // main DirectFB handle static IDirectFB *dfb = NULL; // keyboard handle static IDirectFBInputDevice *keyboard = NULL; // A buffer for input events. static IDirectFBEventBuffer *buffer = NULL; /* * filled during config */ // handle of used layer static IDirectFBDisplayLayer *layer = NULL; // surface of used layer static IDirectFBSurface *primary = NULL; static int primarylocked = 0; // handle of temporary surface (if used) static IDirectFBSurface *frame = NULL; static int framelocked = 0; // flipping mode flag (layer/surface) static int flipping = 0; // scaling flag static int stretch = 0; // pictrure position static int xoffset=0,yoffset=0; // picture size static int out_width=0,out_height=0; // frame/primary size static int width=0,height=0; // frame primary format DFBSurfacePixelFormat pixel_format; /* static void (*draw_alpha_p)(int w, int h, unsigned char *src, unsigned char *srca, int stride, unsigned char *dst, int dstride); */ /****************************** * cmd line parameteres * ******************************/ /* command line/config file options */ #ifdef HAVE_FBDEV extern char *fb_dev_name; #else char *fb_dev_name; #endif /****************************** * implementation * ******************************/ void unlock() { if (frame && framelocked) frame->Unlock(frame); if (primary && primarylocked) primary->Unlock(primary); } static uint32_t preinit(const char *arg) { DFBResult ret; if (verbose) printf("DirectFB: Preinit entered\n"); DFBCHECK (DirectFBInit (NULL,NULL)); if (((directfb_major_version <= 0) && (directfb_minor_version <= 9) && (directfb_micro_version < 13))) { printf("DirectFB: Unsupported DirectFB version\n"); return 1; } /* * (set options) */ if (!fb_dev_name && !(fb_dev_name = getenv("FRAMEBUFFER"))) fb_dev_name = "/dev/fb0"; DFBCHECK (DirectFBSetOption ("fbdev",fb_dev_name)); // uncomment this if you do not wish to create a new vt for DirectFB // DFBCHECK (DirectFBSetOption ("no-vt-switch","")); // uncomment this if you want to allow vt switching // DFBCHECK (DirectFBSetOption ("vt-switching","")); // uncomment this if you want to hide gfx cursor (req dfb >=0.9.9) DFBCHECK (DirectFBSetOption ("no-cursor","")); // bg color fix DFBCHECK (DirectFBSetOption ("bg-color","00000000")); /* * (Initialize) */ DFBCHECK (DirectFBCreate (&dfb)); DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_FULLSCREEN)); /* * (Get keyboard) */ ret = dfb->GetInputDevice (dfb, DIDID_KEYBOARD, &keyboard); if (ret==DFB_OK) { if (verbose) { printf("DirectFB: Keyboard init OK\n"); } } else { keyboard = NULL; printf("DirectFB: Keyboard init FAILED\n"); } /* * Create an input buffer for the keyboard. */ if (keyboard) DFBCHECK (keyboard->CreateEventBuffer (keyboard, &buffer)); // just to start with clean ... if (buffer) buffer->Reset(buffer); if (verbose) { printf("DirectFB: Preinit OK\n"); } return 0; } DFBSurfacePixelFormat convformat(uint32_t format) { // add more formats !!! switch (format) { case IMGFMT_RGB32: return DSPF_RGB32; break; case IMGFMT_BGR32: return DSPF_RGB32; break; case IMGFMT_RGB24: return DSPF_RGB24; break; case IMGFMT_BGR24: return DSPF_RGB24; break; case IMGFMT_RGB16: return DSPF_RGB16; break; case IMGFMT_BGR16: return DSPF_RGB16; break; case IMGFMT_RGB15: return DSPF_RGB15; break; case IMGFMT_BGR15: return DSPF_RGB15; break; case IMGFMT_YUY2: return DSPF_YUY2; break; case IMGFMT_UYVY: return DSPF_UYVY; break; case IMGFMT_YV12: return DSPF_YV12; break; case IMGFMT_I420: return DSPF_I420; break; // case IMGFMT_IYUV: return DSPF_IYUV; break; default: return 0; } return 0; } typedef struct enum1_s { uint32_t format; int scale; int result; unsigned int id; unsigned int width; unsigned int height; int setsize; } enum1_t; DFBEnumerationResult test_format_callback( unsigned int id, DFBDisplayLayerDescription desc, void *data) { enum1_t *params =(enum1_t *)data; IDirectFBDisplayLayer *layer; DFBResult ret; ret = dfb->GetDisplayLayer( dfb, id, &layer); if (ret) { DirectFBError( "dfb->GetDisplayLayer failed", ret ); return DFENUM_OK; } else { DFBDisplayLayerConfig dlc; if (params->setsize) { dlc.flags = DLCONF_WIDTH |DLCONF_HEIGHT; dlc.width = params->width; dlc.height = params->height; layer->SetConfiguration(layer,&dlc); } dlc.flags = DLCONF_PIXELFORMAT; dlc.pixelformat = convformat(params->format); layer->SetOpacity(layer,0); ret = layer->TestConfiguration(layer,&dlc,NULL); layer->Release(layer); if (verbose) printf("DirectFB: Test format - layer %i scale/pos %i\n",id,(desc.caps & DLCAPS_SCREEN_LOCATION)); if (!ret) { // printf("Test OK\n"); if (params->result) { if ((!params->scale) && (desc.caps & DLCAPS_SCREEN_LOCATION)) { params->scale=1; params->id=id; if (verbose) printf("DirectFB: Test format - added layer %i scale/pos %i\n",id,(desc.caps & DLCAPS_SCREEN_LOCATION)); } } else { params->result=1; params->id=id; if (desc.caps & DLCAPS_SCREEN_LOCATION) params->scale=1; if (verbose) printf("DirectFB: Test format - added layer %i scale/pos %i\n",id,(desc.caps & DLCAPS_SCREEN_LOCATION)); }; }; }; return DFENUM_OK; } static uint32_t query_format(uint32_t format) { int ret = VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW|VFCAP_OSD; // osd should be removed in future -> will be handled outside... enum1_t params; if (!convformat(format)) return 0; // temporary disable YV12 // if (format == IMGFMT_YV12) return 0; // if (format == IMGFMT_I420) return 0; if (format == IMGFMT_IYUV) return 0; if (verbose) printf("DirectFB: Format query: %s\n",vo_format_name(format)); params.format=format; params.scale=0; params.result=0; params.setsize=0; DFBCHECK (dfb->EnumDisplayLayers(dfb,test_format_callback,¶ms)); if (params.result) { if (params.scale) ret |=VFCAP_HWSCALE_UP|VFCAP_HWSCALE_DOWN; return ret; } return 0; } typedef struct videomode_s { int width; int height; int out_width; int out_height; int overx; int overy; int bpp; } videomode_t; DFBEnumerationResult video_modes_callback( unsigned int width,unsigned int height,unsigned int bpp, void *data) { videomode_t *params =(videomode_t *)data; int overx=0,overy=0,closer=0,over=0; int we_are_under=0; if (verbose) printf("DirectFB: Validator entered %i %i %i\n",width,height,bpp); overx=width-params->out_width; overy=height-params->out_height; if (!params->width) { params->width=width; params->height=height; params->overx=overx; params->overy=overy; if (verbose) printf("DirectFB: Mode added %i %i %i\n",width,height,bpp); } if ((params->overy<0)||(params->overx<0)) we_are_under=1; // stored mode is smaller than req mode if (abs(overx*overy)<abs(params->overx * params->overy)) closer=1; // current mode is closer to desired res if ((overx>=0)&&(overy>=0)) over=1; // current mode is bigger or equaul to desired res if ((closer && (over || we_are_under)) || (we_are_under && over)) { params->width=width; params->height=height; params->overx=overx; params->overy=overy; if (verbose) printf("DirectFB: Better mode added %i %i %i\n",width,height,bpp); }; return DFENUM_OK; } #define CONFIG_ERROR -1 static uint32_t config(uint32_t s_width, uint32_t s_height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format) { /* * (Locals) */ // decode flags int fs = fullscreen & 0x01; int vm = fullscreen & 0x02; int zoom = fullscreen & 0x04; int flip = fullscreen & 0x08; DFBSurfaceDescription dsc; DFBResult ret; DFBDisplayLayerConfig dlc; DFBSurfaceCapabilities caps; enum1_t params; if (verbose) { printf("DirectFB: Config entered [%ix%i]\n",s_width,s_height); printf("DirectFB: With requested format: %s\n",vo_format_name(format)); } // initial clean-up if (frame) { frame->Release(frame); frame=NULL; } if (primary) { primary->Release(primary); primary=NULL; } if (layer) { layer->Release(layer); layer=NULL; } // vm things if (vm) { videomode_t params; params.out_width=d_width; params.out_height=d_height; params.width=0; params.height=0; switch (format) { case IMGFMT_RGB32: case IMGFMT_BGR32: params.bpp=32; break; case IMGFMT_RGB24: case IMGFMT_BGR24: params.bpp=24; break; case IMGFMT_RGB16: case IMGFMT_BGR16: case IMGFMT_RGB15: case IMGFMT_BGR15: params.bpp=16; break; default: params.bpp=0; } if (verbose) printf("DirectFB: Config - videomode change\n"); DFBCHECK (dfb->EnumVideoModes(dfb,video_modes_callback,¶ms)); ret=dfb->SetVideoMode(dfb,params.width,params.height,params.bpp); if (ret) { ret=dfb->SetVideoMode(dfb,params.width,params.height,24); if (ret) { ret=dfb->SetVideoMode(dfb,params.width,params.height,32); if (ret) { ret=dfb->SetVideoMode(dfb,params.width,params.height,16); if (ret) { ret=dfb->SetVideoMode(dfb,params.width,params.height,8); } } } } } // vm end // find best layer if (verbose) printf("DirectFB: Config - find suitable layer\n"); params.format=format; params.scale=0; params.result=0; params.width=s_width; params.height=s_height; params.setsize=1; DFBCHECK (dfb->EnumDisplayLayers(dfb,test_format_callback,¶ms)); if (!params.result) { printf("DirectFB: ConfigError - no suitable layer found\n"); params.id = DLID_PRIMARY; } /* Uncomment following if you want to use tvout on CRTC2 (requieres patch for DirectFB from Ville Syrjala) params.id=2; params.scale=0; params.result=1; */ if (verbose) printf("DirectFB: Config - layer %i\n",params.id); // try to setp-up proper configuration DFBCHECK (dfb->GetDisplayLayer( dfb, params.id, &layer)); if (params.scale) { if (verbose) printf("DirectFB: Config - set layer config (size)\n"); dlc.flags = DLCONF_WIDTH | DLCONF_HEIGHT; dlc.width = s_width; dlc.height = s_height; ret = layer->SetConfiguration(layer,&dlc); if (ret && (params.scale || verbose)) printf("DirectFB: ConfigError in layer configuration (size)\n"); } dlc.flags = DLCONF_PIXELFORMAT; dlc.pixelformat = convformat(params.format); // printf("DirectFB: Format [%x]\n",dlc.pixelformat); if (verbose) printf("DirectFB: Config - set layer config (format)\n"); ret = layer->SetConfiguration(layer,&dlc); if (ret) { printf("DirectFB: ConfigError in layer configuration (format)\n"); return CONFIG_ERROR; }; // flipping of layer dlc.flags = DLCONF_BUFFERMODE; dlc.buffermode = DLBM_BACKVIDEO; ret = layer->SetConfiguration( layer, &dlc ); if (ret!=DFB_OK) { dlc.buffermode = DLBM_BACKSYSTEM; ret = layer->SetConfiguration( layer, &dlc ); } // get layer surface ret = layer->GetSurface(layer,&primary); if (ret) { printf("DirectFB: ConfigError in obtaining surface\n"); return CONFIG_ERROR; // what shall we report on fail? } // test surface for flipping DFBCHECK(primary->GetCapabilities(primary,&caps)); // primary->Clear(primary,0,0,0,0); flipping = 0; if (caps & DSCAPS_FLIPPING) { ret = primary->Flip(primary,NULL,0); if (ret==DFB_OK) { // primary->Clear(primary,0,0,0,0); flipping = 1; } }; if (verbose) printf("DirectFB: Config - flipping = %i\n",flipping); // is scale needed ? Aspect ratio and layer pos/size // get surface size DFBCHECK(primary->GetSize(primary,&width,&height)); if (verbose) printf("DirectFB: Config - surface size = %ix%i\n",width,height); aspect_save_orig(s_width,s_height); aspect_save_prescale(d_width,d_height); if (params.scale) { aspect_save_screenres(10000,10000); aspect(&out_width,&out_height,A_ZOOM); ret = layer->SetScreenLocation(layer,(1-(float)out_width/10000)/2,(1-(float)out_height/10000)/2,((float)out_width/10000),((float)out_height/10000)); if (ret) printf("DirectFB: ConfigError in layer configuration (position)\n"); xoffset = 0; yoffset = 0; } else { aspect_save_screenres(width,height); if(fs) /* -fs */ aspect(&out_width,&out_height,A_ZOOM); else aspect(&out_width,&out_height,A_NOZOOM); xoffset = (width - out_width) / 2; yoffset = (height - out_height) / 2; } if (((s_width==out_width)&&(s_height==out_height)) || (params.scale)) { stretch = 0; } else { stretch = 1; } // temporary buffer in case of not flipping or scaling if ((!flipping) || stretch) { DFBCHECK (primary->GetPixelFormat (primary, &dsc.pixelformat)); dsc.flags = DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_WIDTH; dsc.width = s_width; dsc.height = s_height; DFBCHECK (dfb->CreateSurface( dfb, &dsc, &frame)); DFBCHECK(frame->GetSize(frame,&width,&height)); if (verbose) printf("DirectFB: Frame is active.\n"); } // get format for draw_alpha - should be removed soon - osd will be rendered outside vo driver if (frame) { DFBCHECK (frame->GetPixelFormat(frame,&pixel_format)); } else { DFBCHECK (primary->GetPixelFormat(primary,&pixel_format)); }; // finally turn on layer layer->SetOpacity(layer,255); if (verbose) printf("DirectFB: Config finished [%ix%i] - [%ix%i]\n",out_width,out_height,width,height); return 0; } static const vo_info_t *get_info(void) { return &vo_info; } extern void mplayer_put_key(int code); #include "../linux/keycodes.h" static void check_events(void) { if (buffer) { DFBInputEvent event; //if (verbose) printf ("DirectFB: Check events entered\n"); if (buffer->GetEvent(buffer, DFB_EVENT (&event)) == DFB_OK) { if (event.type == DIET_KEYPRESS) { switch (event.key_symbol) { case DIKS_ESCAPE: mplayer_put_key('q'); break; case DIKS_PAGE_UP: mplayer_put_key(KEY_PAGE_UP);break; case DIKS_PAGE_DOWN: mplayer_put_key(KEY_PAGE_DOWN);break; case DIKS_CURSOR_UP: mplayer_put_key(KEY_UP);break; case DIKS_CURSOR_DOWN: mplayer_put_key(KEY_DOWN);break; case DIKS_CURSOR_LEFT: mplayer_put_key(KEY_LEFT);break; case DIKS_CURSOR_RIGHT: mplayer_put_key(KEY_RIGHT);break; case DIKS_INSERT: mplayer_put_key(KEY_INSERT);break; case DIKS_DELETE: mplayer_put_key(KEY_DELETE);break; case DIKS_HOME: mplayer_put_key(KEY_HOME);break; case DIKS_END: mplayer_put_key(KEY_END);break; default:mplayer_put_key(event.key_symbol); }; }; }; // empty buffer, because of repeating (keyboard repeat is faster than key handling // and this causes problems during seek) // temporary workabout should be solved in the future buffer->Reset(buffer); } //if (verbose) printf ("DirectFB: Check events finished\n"); } static void flip_page(void) { DFBSurfaceBlittingFlags flags=DSBLIT_NOFX; unlock(); // unlock frame & primary // if (verbose) printf("DirectFB: Flip page entered"); DFBCHECK (primary->SetBlittingFlags(primary,flags)); if (frame) { if (stretch) { DFBRectangle rect; rect.x=xoffset; rect.y=yoffset; rect.w=out_width; rect.h=out_height; DFBCHECK (primary->StretchBlit(primary,frame,NULL,&rect)); } else { DFBCHECK (primary->Blit(primary,frame,NULL,xoffset,yoffset)); }; }; if (flipping) { DFBCHECK (primary->Flip (primary, NULL, DSFLIP_WAITFORSYNC)); } } static void uninit(void) { if (verbose ) printf("DirectFB: Uninit entered\n"); unlock(); /* * (Release) */ if (verbose ) printf("DirectFB: Release buffer\n"); if (buffer) buffer->Release (buffer); if (verbose ) printf("DirectFB: Release keyboard\n"); if (keyboard) keyboard->Release (keyboard); if (frame) { if (verbose ) printf("DirectFB: Release frame\n"); frame->Release (frame); }; if (verbose ) printf("DirectFB: Release primary\n"); if (primary) primary->Release (primary); // switch off BES // if (layer) layer->SetOpacity(layer,0); if (layer) layer->Release(layer); if (verbose ) printf("DirectFB: Release DirectFB library\n"); dfb->Release (dfb); if (verbose ) printf("DirectFB: Uninit done.\n"); } static uint32_t directfb_set_video_eq(char *data, int value) //data==name { DFBColorAdjustment ca; float factor = (float)0xffff / 200.0; DFBDisplayLayerDescription desc; unlock(); if (layer) { layer->GetDescription(layer,&desc); ca.flags=DCAF_NONE; if (! strcmp( data,"brightness" )) { if (desc.caps & DLCAPS_BRIGHTNESS) { ca.brightness = value * factor +0x8000; ca.flags |= DCAF_BRIGHTNESS; if (verbose) printf("DirectFB: SetVEq Brightness 0x%X %i\n",ca.brightness,value); } else return VO_FALSE; } if (! strcmp( data,"contrast" )) { if ((desc.caps & DLCAPS_CONTRAST)) { ca.contrast = value * factor + 0x8000; ca.flags |= DCAF_CONTRAST; if (verbose) printf("DirectFB: SetVEq Contrast 0x%X %i\n",ca.contrast,value); } else return VO_FALSE; } if (! strcmp( data,"hue" )) { if ((desc.caps & DLCAPS_HUE)) { ca.hue = value * factor + 0x8000; ca.flags |= DCAF_HUE; if (verbose) printf("DirectFB: SetVEq Hue 0x%X %i\n",ca.hue,value); } else return VO_FALSE; } if (! strcmp( data,"saturation" )) { if ((desc.caps & DLCAPS_SATURATION)) { ca.saturation = value * factor + 0x8000; ca.flags |= DCAF_SATURATION; if (verbose) printf("DirectFB: SetVEq Saturation 0x%X %i\n",ca.saturation,value); } else return VO_FALSE; } if (ca.flags != DCAF_NONE) { layer->SetColorAdjustment(layer,&ca); return VO_TRUE; } } return VO_FALSE; } static uint32_t directfb_get_video_eq(char *data, int *value) // data==name { DFBColorAdjustment ca; float factor = 200.0 / (float)0xffff; DFBDisplayLayerDescription desc; if (layer) { unlock(); layer->GetDescription(layer,&desc); layer->GetColorAdjustment(layer,&ca); if (! strcmp( data,"brightness" )) { if (desc.caps & DLCAPS_BRIGHTNESS) { *value = (int) ((ca.brightness-0x8000) * factor); if (verbose) printf("DirectFB: GetVEq Brightness 0x%X %i\n",ca.brightness,*value); return VO_TRUE; } else return VO_FALSE; } if (! strcmp( data,"contrast" )) { if ((desc.caps & DLCAPS_CONTRAST)) { *value = (int) ((ca.contrast-0x8000) * factor); if (verbose) printf("DirectFB: GetVEq Contrast 0x%X %i\n",ca.contrast,*value); return VO_TRUE; } else return VO_FALSE; } if (! strcmp( data,"hue" )) { if ((desc.caps & DLCAPS_HUE)) { *value = (int) ((ca.hue-0x8000) * factor); if (verbose) printf("DirectFB: GetVEq Hue 0x%X %i\n",ca.hue,*value); return VO_TRUE; } else return VO_FALSE; } if (! strcmp( data,"saturation" )) { if ((desc.caps & DLCAPS_SATURATION)) { *value = (int) ((ca.saturation-0x8000) * factor); if (verbose) printf("DirectFB: GetVEq Saturation 0x%X %i\n",ca.saturation,*value); return VO_TRUE; } else return VO_FALSE; } } return VO_FALSE; } static uint32_t get_image(mp_image_t *mpi) { int err; void *dst; int pitch; // if (verbose) printf("DirectFB: get_image() called\n"); if(mpi->flags&MP_IMGFLAG_READABLE) return VO_FALSE; // slow video ram if(mpi->type==MP_IMGTYPE_STATIC) return VO_FALSE; // it is not static // printf("width=%d vs. pitch=%d, flags=0x%X \n",mpi->width,pitch,mpi->flags); if((mpi->width==pitch) || (mpi->flags&(MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_ACCEPT_WIDTH))){ // we're lucky or codec accepts stride => ok, let's go! if (frame) { err = frame->Lock(frame,DSLF_WRITE,&dst,&pitch); framelocked=1; } else { err = primary->Lock(primary,DSLF_WRITE,&dst,&pitch); primarylocked=1; } if (err) { if (verbose) printf("DirectFB: DR lock failed!"); return VO_FALSE; }; if(mpi->flags&MP_IMGFLAG_PLANAR){ //YV12 format mpi->planes[0]=dst; if(mpi->flags&MP_IMGFLAG_SWAPPED){ mpi->planes[1]=dst + pitch*height; mpi->planes[2]=mpi->planes[1] + pitch*height/4; } else { mpi->planes[2]=dst + pitch*height; mpi->planes[1]=mpi->planes[2] + pitch*height/4; } mpi->width=width; mpi->stride[0]=pitch; mpi->stride[1]=mpi->stride[2]=pitch/2; } else { //YUY2 and RGB formats mpi->planes[0]=dst; mpi->width=width; mpi->stride[0]=pitch; } mpi->flags|=MP_IMGFLAG_DIRECT; // if (verbose) printf("DirectFB: get_image() SUCCESS -> Direct Rendering ENABLED\n"); return VO_TRUE; } return VO_FALSE; } static uint32_t draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y) { int i; unsigned int pitch; void *dst; void *dst2; void *srcp; unsigned int p; unlock(); if (frame) { DFBCHECK (frame->Lock(frame,DSLF_WRITE,&dst,&pitch)); framelocked = 1; } else { DFBCHECK (primary->Lock(primary,DSLF_WRITE,&dst,&pitch)); primarylocked = 1; }; p=min(w,pitch); dst += y*pitch + x; dst2 = dst + pitch*height - y*pitch + y*pitch/4 - x/2; srcp = src[0]; for (i=0;i<h;i++) { memcpy(dst,srcp,p); dst += pitch; srcp += stride[0]; } if (pixel_format == DSPF_YV12) { dst = dst2; srcp = src[2]; p = p/2; for (i=0;i<h/2;i++) { memcpy(dst,srcp,p); dst += pitch/2; srcp += stride[2]; } dst = dst2 + pitch*height/4; srcp = src[1]; for (i=0;i<h/2;i++) { memcpy(dst,srcp,p); dst += pitch/2; srcp += stride[1]; } } else { dst = dst2; srcp = src[1]; p = p/2; for (i=0;i<h/2;i++) { memcpy(dst,srcp,p); dst += pitch/2; srcp += stride[1]; } dst = dst2 + pitch*height/4; srcp = src[2]; for (i=0;i<h/2;i++) { memcpy(dst,srcp,p); dst += pitch/2; srcp += stride[2]; } } unlock(); return 0; } static uint32_t put_image(mp_image_t *mpi){ static IDirectFBSurface *tmp = NULL; DFBSurfaceDescription dsc; DFBRectangle rect; // if (verbose) printf("DirectFB: Put_image entered %i %i %i %i %i %i\n",mpi->x,mpi->y,mpi->w,mpi->h,mpi->width,mpi->height); unlock(); // already out? if((mpi->flags&(MP_IMGFLAG_DIRECT|MP_IMGFLAG_DRAW_CALLBACK))) { // if (verbose) printf("DirectFB: Put_image - nothing todo\n"); return VO_TRUE; } if (mpi->flags&MP_IMGFLAG_PLANAR) { // memcpy all planes - sad but necessary int i; unsigned int pitch; void *dst; void *src; unsigned int p; // if (verbose) printf("DirectFB: Put_image - planar branch\n"); if (frame) { DFBCHECK (frame->Lock(frame,DSLF_WRITE,&dst,&pitch)); framelocked = 1; } else { DFBCHECK (primary->Lock(primary,DSLF_WRITE,&dst,&pitch)); primarylocked = 1; }; p=min(mpi->w,pitch); src = mpi->planes[0]+mpi->y*mpi->stride[0]+mpi->x; for (i=0;i<mpi->h;i++) { memcpy(dst+i*pitch,src+i*mpi->stride[0],p); } if (pixel_format == DSPF_YV12) { dst += pitch*height; p = p/2; src = mpi->planes[2]+mpi->y*mpi->stride[2]+mpi->x/2; for (i=0;i<mpi->h/2;i++) { memcpy(dst+i*pitch/2,src+i*mpi->stride[2],p); } dst += pitch*height/4; src = mpi->planes[1]+mpi->y*mpi->stride[1]+mpi->x/2; for (i=0;i<mpi->h/2;i++) { memcpy(dst+i*pitch/2,src+i*mpi->stride[1],p); } } else { dst += pitch*height; p = p/2; src = mpi->planes[1]+mpi->y*mpi->stride[1]+mpi->x/2; for (i=0;i<mpi->h/2;i++) { memcpy(dst+i*pitch/2,src+i*mpi->stride[1],p); } dst += pitch*height/4; src = mpi->planes[2]+mpi->y*mpi->stride[2]+mpi->x/2; for (i=0;i<mpi->h/2;i++) { memcpy(dst+i*pitch/2,src+i*mpi->stride[2],p); } } unlock(); } else { dsc.flags = DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_WIDTH | DSDESC_PREALLOCATED; dsc.preallocated[0].data = mpi->planes[0]; dsc.preallocated[0].pitch = mpi->stride[0]; dsc.width = mpi->width; dsc.height = mpi->height; dsc.pixelformat = convformat(mpi->imgfmt); DFBCHECK (dfb->CreateSurface( dfb, &dsc, &tmp)); rect.x=mpi->x; rect.y=mpi->y; rect.w=mpi->w; rect.h=mpi->h; if (frame) { DFBCHECK (tmp->Blit(tmp,frame,&rect,0,0)); } else { DFBCHECK (tmp->Blit(tmp,primary,&rect,xoffset,yoffset)); }; tmp->Release(tmp); } return VO_TRUE; } static uint32_t control(uint32_t request, void *data, ...) { switch (request) { case VOCTRL_QUERY_FORMAT: return query_format(*((uint32_t*)data)); case VOCTRL_GET_IMAGE: return get_image(data); case VOCTRL_DRAW_IMAGE: return put_image(data); case VOCTRL_SET_EQUALIZER: { va_list ap; int value; va_start(ap, data); value = va_arg(ap, int); va_end(ap); return(directfb_set_video_eq(data, value)); } case VOCTRL_GET_EQUALIZER: { va_list ap; int *value; va_start(ap, data); value = va_arg(ap, int*); va_end(ap); return(directfb_get_video_eq(data, value)); } }; return VO_NOTIMPL; } // unused function static uint32_t draw_frame(uint8_t *src[]) { return -1; } // hopefully will be removed soon static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride) { void *dst; int pitch; unlock(); // isnt it silly I have to unlock surface and than lock again :-) if (frame) { DFBCHECK (frame->Lock(frame,DSLF_WRITE,&dst,&pitch)); framelocked = 1; } else { DFBCHECK (primary->Lock(primary,DSLF_WRITE,&dst,&pitch)); primarylocked = 1; }; switch(pixel_format) { case DSPF_RGB32: case DSPF_ARGB: vo_draw_alpha_rgb32(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 4*x0,pitch); break; case DSPF_RGB24: vo_draw_alpha_rgb24(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 3*x0,pitch); break; case DSPF_RGB16: vo_draw_alpha_rgb16(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 2*x0,pitch); break; case DSPF_RGB15: vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 2*x0,pitch); break; case DSPF_YUY2: vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 2*x0,pitch); break; case DSPF_UYVY: vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 2*x0 + 1,pitch); break; case DSPF_I420: case DSPF_YV12: vo_draw_alpha_yv12(w,h,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 1*x0,pitch); break; } unlock(); } static void draw_osd(void) { vo_draw_text(width,height,draw_alpha); }