/* * video.c: A plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * * $Id: video-dfb.c,v 1.86 2009-06-14 18:00:58 lucke Exp $ */ #include #include #include #include #include "video-dfb.h" #include "utils.h" #include "setup-softdevice.h" #ifdef HAVE_CONFIG # include "config.h" #else # define HAVE_SetSourceRectangle 0 # if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23) # define HAVE_GraphicsDeviceDescription 0 # define HAVE_DIEF_REPEAT 0 # else # define HAVE_GraphicsDeviceDescription 1 # define HAVE_DIEF_REPEAT 1 # endif # if (DIRECTFB_MAJOR_VERSION > 0 || ((DIRECTFB_MINOR_VERSION == 9) && DIRECTFB_MICRO_VERSION > 22)) # define HAVE_DSCAPS_DOUBLE 1 # else # define HAVE_DSCAPS_DOUBLE 0 # endif #endif #ifdef HAVE_CLE266_MPEG_DECODER #include #endif // HAVE_CLE266_MPEG_DECODER //#define COLORKEY 17,8,79 #define COLORKEY 0,0,0 /* macro for a safe call to DirectFB functions */ #define DFBCHECK(x...) \ { \ DFBResult err = x; \ if (err != DFB_OK) { \ fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \ DirectFBErrorFatal( #x, err ); \ } \ } typedef struct { const char *shortName; const char *longName; IDirectFBDisplayLayer *layer; DFBResult result; } tLayerSelectItem; #define BES_LAYER 0 #define CRTC2_LAYER_OLD 1 #define CRTC2_LAYER_NEW 2 #define SPIC_LAYER 3 #define ANY_LAYER 4 tLayerSelectItem layerList [5] = { {"bes", "Matrox Backend Scaler", NULL, DFB_UNSUPPORTED}, {"crtc2", "Matrox CRTC2", NULL, DFB_UNSUPPORTED}, {"crtc2", "Matrox CRTC2 Layer", NULL, DFB_UNSUPPORTED}, {"spic", "Matrox CRTC2 Sub-Picture", NULL, DFB_UNSUPPORTED}, {NULL, NULL, NULL, DFB_UNSUPPORTED} }; // --- cDFBVideoOut ------------------------------------------------- IDirectFB *DFBWrapper; /* --------------------------------------------------------------------------- */ static DFBEnumerationResult EnumCallBack(unsigned int id, DFBDisplayLayerDescription desc, void *data) { tLayerSelectItem *layer = (tLayerSelectItem *)data; fprintf(stderr,"Layer %d %s",id, desc.name); fprintf(stderr," Type: "); if (desc.type & DLTF_BACKGROUND) fprintf(stderr,"background " ); if (desc.type & DLTF_GRAPHICS) fprintf(stderr,"graphics " ); if (desc.type & DLTF_STILL_PICTURE) fprintf(stderr,"picture " ); if (desc.type & DLTF_VIDEO) fprintf(stderr,"video " ); fprintf(stderr,"\n" ); fprintf(stderr," Caps: " ); if (desc.caps & DLCAPS_ALPHACHANNEL) fprintf(stderr,"alphachannel " ); if (desc.caps & DLCAPS_BRIGHTNESS) fprintf(stderr,"brightness " ); if (desc.caps & DLCAPS_CONTRAST) fprintf(stderr,"contrast " ); if (desc.caps & DLCAPS_DEINTERLACING) fprintf(stderr,"deinterlacing " ); if (desc.caps & DLCAPS_DST_COLORKEY) fprintf(stderr,"dst_colorkey " ); if (desc.caps & DLCAPS_FLICKER_FILTERING) fprintf(stderr,"flicker_filtering " ); if (desc.caps & DLCAPS_HUE) fprintf(stderr,"hue " ); if (desc.caps & DLCAPS_LEVELS) fprintf(stderr,"levels " ); if (desc.caps & DLCAPS_FIELD_PARITY) fprintf(stderr,"field_parity " ); if (desc.caps & DLCAPS_OPACITY) fprintf(stderr,"opacity " ); if (desc.caps & DLCAPS_SATURATION) fprintf(stderr,"saturation " ); if (desc.caps & DLCAPS_SCREEN_LOCATION) fprintf(stderr,"screen_location " ); if (desc.caps & DLCAPS_SRC_COLORKEY) fprintf(stderr,"src_colorkey " ); if (desc.caps & DLCAPS_SURFACE) fprintf(stderr,"surface " ); fprintf(stderr,"\n"); if ((layer->shortName && !strcmp (layer->longName,desc.name)) || (!layer->shortName && id != DLID_PRIMARY && desc.caps & DLCAPS_SURFACE)) { layer->layer = DFBWrapper->GetDisplayLayer(id); return DFENUM_CANCEL; } return DFENUM_OK; } /* --------------------------------------------------------------------------- */ static void reportCardInfo (IDirectFB *dfb) { #if HAVE_GraphicsDeviceDescription DFBGraphicsDeviceDescription caps; dfb->GetDeviceDescription(&caps); #else DFBCardCapabilities caps; dfb->GetCardCapabilities(&caps); #endif fprintf(stderr,"[dfb] RAM: %d bytes\n",caps.video_memory); fprintf(stderr,"[dfb] Accellerated Functions: "); if (caps.acceleration_mask == DFXL_NONE) fprintf(stderr,"none "); if (caps.acceleration_mask & DFXL_FILLRECTANGLE) fprintf(stderr,"FillRectange "); if (caps.acceleration_mask & DFXL_DRAWRECTANGLE) fprintf(stderr,"DrawRectange "); if (caps.acceleration_mask & DFXL_DRAWLINE) fprintf(stderr,"DrawLine "); if (caps.acceleration_mask & DFXL_FILLTRIANGLE) fprintf(stderr,"FillTriangle "); if (caps.acceleration_mask & DFXL_BLIT) fprintf(stderr,"Blit "); if (caps.acceleration_mask & DFXL_STRETCHBLIT) fprintf(stderr,"StretchBlit "); if (caps.acceleration_mask & DFXL_ALL) fprintf(stderr,"All "); fprintf(stderr,"\n"); fprintf(stderr,"[dfb] Drawing Flags: "); if (caps.drawing_flags == DSDRAW_NOFX ) fprintf(stderr,"none "); if (caps.drawing_flags & DSDRAW_BLEND ) fprintf(stderr,"Blend "); if (caps.drawing_flags & DSDRAW_DST_COLORKEY ) fprintf(stderr,"Colorkeying "); if (caps.drawing_flags & DSDRAW_SRC_PREMULTIPLY ) fprintf(stderr,"Src.premultiply "); if (caps.drawing_flags & DSDRAW_DST_PREMULTIPLY ) fprintf(stderr,"Dst.premultiply "); if (caps.drawing_flags & DSDRAW_DEMULTIPLY ) fprintf(stderr,"Demultiply "); if (caps.drawing_flags & DSDRAW_XOR ) fprintf(stderr,"Xor "); fprintf(stderr,"\n"); fprintf(stderr,"[dfb] Surface Blitting Flags: "); if (caps.blitting_flags == DSBLIT_NOFX ) fprintf(stderr,"none "); if (caps.blitting_flags & DSBLIT_BLEND_ALPHACHANNEL ) fprintf(stderr,"BlendAlpha "); if (caps.blitting_flags & DSBLIT_BLEND_COLORALPHA ) fprintf(stderr,"BlendColorAlpha "); if (caps.blitting_flags & DSBLIT_COLORIZE ) fprintf(stderr,"Colorize "); if (caps.blitting_flags & DSBLIT_SRC_COLORKEY ) fprintf(stderr,"SrcColorkey "); if (caps.blitting_flags & DSBLIT_DST_COLORKEY ) fprintf(stderr,"DstColorkey "); if (caps.blitting_flags & DSBLIT_SRC_PREMULTIPLY ) fprintf(stderr,"SrcPremultiply "); if (caps.blitting_flags & DSBLIT_DST_PREMULTIPLY ) fprintf(stderr,"DstPremultiply "); if (caps.blitting_flags & DSBLIT_DEMULTIPLY ) fprintf(stderr,"Demultiply "); if (caps.blitting_flags & DSBLIT_DEINTERLACE ) fprintf(stderr,"Deinterlace "); fprintf(stderr,"\n"); } /* --------------------------------------------------------------------------- */ // List Video Modes static DFBEnumerationResult EnumVideoModeCallback(int x, int y, int bpp, void *data) { fprintf(stderr,"%dx%d@%d ",x,y,bpp); return DFENUM_OK; } /* --------------------------------------------------------------------------- */ cDFBVideoOut::cDFBVideoOut(cSetupStore *setupStore, cSetupSoftlog *softlog) : cVideoOut(setupStore, softlog) { tLayerSelectItem *layerInfo; softlog->Log(SOFT_LOG_INFO, 0, "[dfb] init\n"); /* -------------------------------------------------------------------------- * default settings: source, destination and logical widht/height * are set to our well known dimensions (except fwidth+fheight). */ swidth = fwidth = 720; sheight = fheight = 576; tmpOsdSurface = NULL; screenPixelAspect = -1; currentPixelFormat = setupStore->pixelFormat; prevOsdMode = setupStore->osdMode; setupStore->osdMode = 0; isVIAUnichrome = false; clearAlpha = 0x00; clearBackground = 0; clearBackCount = 2; // by default for double buffering; videoLayerLevel = 1; OSDpresent = false; if(setupStore->viaTv) setupStore->tripleBuffering = 1; #if HAVE_SetSourceRectangle setupStore->setSourceRectangleLocked = false; useSetSourceRectangle = setupStore->useSetSourceRectangle; #else useSetSourceRectangle = setupStore->useSetSourceRectangle = false; setupStore->setSourceRectangleLocked = true; #endif try { DirectFB::Init(); dfb = DirectFB::Create(); if (!setupStore->useMGAtv) dfb->SetCooperativeLevel(DFSCL_FULLSCREEN); reportCardInfo (dfb); softlog->Log(SOFT_LOG_INFO, 0, "[dfb] Supported video Modes are:\n"); dfb->EnumVideoModes(EnumVideoModeCallback, NULL); fprintf(stderr,"\n"); /* -------------------------------------------------------------------------- * Thats for dfb access during layer enumeration */ DFBWrapper=dfb; softlog->Log(SOFT_LOG_INFO, 0, "[dfb] Enumerating display Layers\n"); osdLayer=dfb->GetDisplayLayer(DLID_PRIMARY); if (!osdLayer) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] no OSD layer exiting\n"); exit(EXIT_FAILURE); } if (!setupStore->useMGAtv) { softlog->Log(SOFT_LOG_INFO, 0, "[dfb] Configuring CooperativeLevel for OSD\n"); osdLayer->SetCooperativeLevel(DLSCL_ADMINISTRATIVE); } osdLayerDescription = osdLayer->GetDescription(); osdLayer->GetConfiguration(&osdLayerConfiguration); osdLayerConfiguration.flags = DLCONF_ALL; videoLayer = NULL; layerInfo = &layerList [ANY_LAYER]; if (setupStore->useMGAtv) { layerInfo = &layerList [CRTC2_LAYER_NEW]; currentPixelFormat = setupStore->pixelFormat = 2; setupStore->pixelFormatLocked = true; setupStore->useStretchBlit = 1; setupStore->stretchBlitLocked = true; if (!setupStore->screenPixelAspect) setupStore->screenPixelAspect = 1; } dfb->EnumDisplayLayers(EnumCallBack, layerInfo); videoLayer = layerInfo->layer; if (setupStore->useMGAtv && !videoLayer) { layerInfo = &layerList [CRTC2_LAYER_OLD]; softlog->Log(SOFT_LOG_INFO, 0, "[dfb] New layer name allocation failed. Trying old (dfb-0.9.20) layer name\n"); dfb->EnumDisplayLayers(EnumCallBack, layerInfo); videoLayer = layerInfo->layer; } if (!videoLayer) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb]: could not find suitable videolayer\n"); exit(EXIT_FAILURE); } videoLayerDescription = videoLayer->GetDescription(); /* -------------------------------------------------------------------------- * check for VIA Unichrome presence */ if (!strncmp (videoLayerDescription.name, "VIA Unichrome Video", 19)) { isVIAUnichrome = true; clearAlpha = 0xff; if (!strcmp (videoLayerDescription.name, "VIA Unichrome Video 3")) { /* ------------------------------------------------------------------- * DirectFB patched for CN700 support: restrict pixelformat to YUY2, * and disable hardware decoding support. * I420 == 0, YV12 == 1, YUY2 == 2 */ #ifdef HAVE_CLE266_MPEG_DECODER setupStore->cle266HWdecode = false; softlog->Log(SOFT_LOG_INFO, 0, "[dfb] disabling hw-decode support for this layer\n"); #endif currentPixelFormat = setupStore->pixelFormat = 2; setupStore->pixelFormatLocked = true; setupStore->useStretchBlit = 0; setupStore->stretchBlitLocked = true; useStretchBlit = false; } #ifdef HAVE_CLE266_MPEG_DECODER else if (setupStore->cle266HWdecode) { if (!SetupCle266Buffers(swidth, sheight)) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] Error allocating hardware buffers for " "CLE266 decoding: reverting to software decoding\n"); setupStore->cle266HWdecode = false; } else { // Need YV12 pixel format for blitting from harware buffer // I420 == 0, YV12 == 1, YUY2 == 2 currentPixelFormat = setupStore->pixelFormat = 0; setupStore->pixelFormatLocked = true; setupStore->useStretchBlit = 0; setupStore->stretchBlitLocked = true; useStretchBlit = false; } } #endif // HAVE_CLE266_MPEG_DECODER } ReportLayerInfo(osdLayer, "osdLayer"); if (osdLayerDescription.caps & DLCAPS_ALPHACHANNEL) { softlog->Log(SOFT_LOG_INFO, 0, "[dfb] osdLayer has alpha channel\n"); osdLayerConfiguration.options = DLOP_ALPHACHANNEL; videoLayerLevel = -1; } else { softlog->Log(SOFT_LOG_INFO, 0, "[dfb] osdLayer without !! alpha channel\n"); } osdLayer->SetCooperativeLevel(DLSCL_EXCLUSIVE); osdLayer->SetConfiguration(osdLayerConfiguration); if (setupStore->useMGAtv) EnableFieldParity(osdLayer); if (setupStore->viaTv) EnableFieldParity(videoLayer); /* ----------------------------------------------------------------------- * Do something common for both TV out modes * (moved from video.c) */ if (setupStore->useMGAtv || setupStore->viaTv) { dropStart = 21; // changed from 25 dropEnd = 15; dropInterval = 16; // changed from 8 //offsetClampLow = -10; //offsetClampHigh = 10; //offsetUse = 4; //offset = offsetAverage; //useAverage4Drop = true; } scrSurface = osdLayer->GetSurface(); ReportSurfaceCapabilities (scrSurface, "scrSurface"); if (scrSurface) { DFBSurfacePixelFormat fmt; double displayRatio; scrSurface->GetSize(&Xres,&Yres); softlog->Log(SOFT_LOG_INFO, 0, "[dfb] width = %d, height = %d\n", Xres, Yres); lwidth = dwidth = Xres; lheight = dheight = Yres; displayRatio = (double) Xres / (double) Yres; SetParValues(displayRatio, displayRatio); fmt = scrSurface->GetPixelFormat(); softlog->Log(SOFT_LOG_INFO, 0, "[dfb] got fmt = 0x%08x bpp = %d\n", fmt, DFB_BITS_PER_PIXEL(fmt)); Bpp = DFB_BITS_PER_PIXEL(fmt); /* --------------------------------------------------------------------- * In case of of AiRGB we have to reset clearAlpha value */ if (fmt == DSPF_AiRGB) clearAlpha = 0; /* --------------------------------------------------------------------- * clear screen surface at startup */ scrSurface->Clear(0,0,0,clearAlpha); scrSurface->Flip(); scrSurface->Clear(0,0,0,clearAlpha); osdDsc.flags = (DFBSurfaceDescriptionFlags) (DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT); osdDsc.caps = DSCAPS_NONE; DFB_ADD_SURFACE_CAPS(osdDsc.caps, DSCAPS_FLIPPING); DFB_ADD_SURFACE_CAPS(osdDsc.caps, DSCAPS_VIDEOONLY); osdDsc.width = Xres; osdDsc.height = Yres; osdDsc.pixelformat = DSPF_ARGB; useStretchBlit = false; OSDpseudo_alpha = true; if (setupStore->pixelFormat == 0) { vidDsc.pixelformat = DSPF_I420; setupStore->useStretchBlit = useStretchBlit = false; } else if (setupStore->pixelFormat == 1) { vidDsc.pixelformat = DSPF_YV12; setupStore->useStretchBlit = useStretchBlit = false; } else if (setupStore->pixelFormat == 2) { vidDsc.pixelformat = DSPF_YUY2; if (setupStore->useStretchBlit) { useStretchBlit = true; OSDpseudo_alpha = false; } } osdSurface = dfb->CreateSurface (osdDsc); osdSurface->Clear(0,0,0,clearAlpha); //clear and osdSurface->Flip(); // Flip the field osdSurface->Clear(0,0,0,clearAlpha); //clear and softlog->Log(SOFT_LOG_INFO, 0, "[dfb] Using this layer for OSD: (%s - [%dx%d])\n", osdLayerDescription.name, osdSurface->GetWidth(), osdSurface->GetHeight()); ReportSurfaceCapabilities (osdSurface, "osdSurface"); vidDsc.flags = (DFBSurfaceDescriptionFlags) (DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT); vidDsc.caps = DSCAPS_VIDEOONLY; vidDsc.width = fwidth; vidDsc.height = fheight; if (!setupStore->useMGAtv) { softlog->Log(SOFT_LOG_INFO, 0, "[dfb] Configuring CooperativeLevel for Overlay\n"); videoLayer->SetCooperativeLevel(DLSCL_ADMINISTRATIVE); if ((videoLayerLevel == 1)) BESColorkeyState(videoLayer, true); } if (useStretchBlit) { videoSurface = dfb->CreateSurface (vidDsc); videoSurface->Clear(0,0,0,clearAlpha); //clear and } else { videoSurface=videoLayer->GetSurface(); videoSurface->Clear(COLORKEY,clearAlpha); //clear and videoSurface->Flip(); // Flip the field videoSurface->Clear(COLORKEY,clearAlpha); //clear and videoSurface->Flip(); // Flip the field } ReportSurfaceCapabilities (videoSurface, "videoSurface"); softlog->Log(SOFT_LOG_INFO, 0, "[dfb] Using this layer for OSD: %s\n", osdLayerDescription.name); softlog->Log(SOFT_LOG_INFO, 0, "[dfb] Using this layer for Video out: %s\n", videoLayerDescription.name); } GetDisplayFrameTime(); /* create an event buffer with all devices attached */ events = dfb->CreateInputEventBuffer(DICAPS_ALL, (setupStore->useMGAtv) ? DFB_TRUE : DFB_FALSE); } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] init EXITING:action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; exit(EXIT_FAILURE); } } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::ReportSurfaceCapabilities (IDirectFBSurface *surf, const char *name) { DFBSurfaceCapabilities scaps; scaps = surf->GetCapabilities(); softlog->Log(SOFT_LOG_DEBUG, 0, "[dfb] surface capabilities for (%s): " "%s%s%s%s%s%s%s%s%s%s%sPixelFormat = 0x%08x\n", name, (scaps == DSCAPS_NONE) ? "none, ": "", (scaps & DSCAPS_PRIMARY) ? "primary, ": "", (scaps & DSCAPS_SYSTEMONLY) ? "systemonly, ": "", (scaps & DSCAPS_VIDEOONLY) ? "videoonly, ": "", (scaps & DSCAPS_DOUBLE) ? "double-buffered, ": "", (scaps & DSCAPS_FLIPPING) ? "flipping, ": "", (scaps & DSCAPS_SUBSURFACE) ? "subsurface, ": "", (scaps & DSCAPS_INTERLACED) ? "interlaced, ": "", (scaps & DSCAPS_SEPARATED) ? "separated, ": "", (scaps & DSCAPS_STATIC_ALLOC) ? "static-alloc, ": "", (scaps & DSCAPS_TRIPLE) ? "triple-buffered, ": "", surf->GetPixelFormat()); } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::BESColorkeyState(IDirectFBDisplayLayer *layer, bool state) { if (layer) { DFBDisplayLayerConfig dlc; dlc.flags = DLCONF_OPTIONS; dlc.options = (state) ? DLOP_DST_COLORKEY : DLOP_NONE; try { layer->SetConfiguration(dlc); layer->SetDstColorKey(COLORKEY); } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] BES-%s: action=%s, result=%s\n", (state) ? "ON" : "OFF", ex->GetAction(), ex->GetResult()); delete ex; } } } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::ReportLayerInfo(IDirectFBDisplayLayer *layer, const char *name) { DFBDisplayLayerConfig layerConfiguration; if (!layer) { softlog->Log(SOFT_LOG_INFO, 0, "[dfb] no layer info. layer == NULL\n"); return; } layer->GetConfiguration(&layerConfiguration); { softlog->Log(SOFT_LOG_INFO, 0, "[dfb] (%s): flags, options, pixelformat: %08x, %08x %08x\n", name, layerConfiguration.flags, layerConfiguration.options, layerConfiguration.pixelformat); softlog->Log(SOFT_LOG_INFO, 0, "[dfb] (%s): width, height: %d %d\n", name, layerConfiguration.width, layerConfiguration.height); } } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::EnableFieldParity(IDirectFBDisplayLayer *layer) { DFBDisplayLayerConfig dlc; DFBDisplayLayerDescription desc; desc = layer->GetDescription(); dlc.flags = (DFBDisplayLayerConfigFlags) (DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS); dlc.buffermode = DLBM_TRIPLE; softlog->Log(SOFT_LOG_INFO, 0, "[dfb] Set DLBM_TRIPLE for layer [%s]\n", desc.name); dlc.pixelformat = DSPF_ARGB; clearBackCount = 3; // 3 for triple, 2 for double buffering if (desc.caps & DLCAPS_FIELD_PARITY) { dlc.options = DLOP_FIELD_PARITY; softlog->Log(SOFT_LOG_INFO, 0, "[dfb] DLOP_FIELD_PARITY supported by layer [%s]\n", desc.name); } else { dlc.options = DLOP_NONE; softlog->Log(SOFT_LOG_INFO, 0, "[dfb] DLOP_FIELD_PARITY not supported by layer [%s]\n", desc.name); } try { layer->SetCooperativeLevel(DLSCL_EXCLUSIVE); layer->SetOpacity(0xff); layer->SetConfiguration(dlc); if (desc.caps & DLCAPS_FIELD_PARITY) SetFieldParity(layer, currentFieldOrder); } catch(DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] EnableFieldParity: action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; } } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::SetFieldParity(IDirectFBDisplayLayer *layer, int fieldOrder) { DFBDisplayLayerDescription desc; desc = layer->GetDescription(); if (!(desc.caps & DLCAPS_FIELD_PARITY)) return; softlog->Log(SOFT_LOG_INFO, 0, "[dfb] Set layer [%s] to (%s)\n", desc.name, (fieldOrder) ? "TOP field first" : "BOTTOM field first"); try { /* ----------------------------------------------------------------------- * ffmpeg has member top_field_first: 1 - top; 0 - bottom * dfb values are: 0 - top field first, 1 - bottom field first */ layer->SetFieldParity(!fieldOrder); } catch(DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] SetFieldParity: action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; } } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::GetDisplayFrameTime (void) { if (videoLayer) { struct timeval tv1, tv2; int t1, t2; try { videoLayer->GetScreen()->WaitForSync(); gettimeofday(&tv1,NULL); videoLayer->GetScreen()->WaitForSync(); gettimeofday(&tv2,NULL); } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] GetDisplayFrameTime: action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; tv1.tv_sec = tv2.tv_sec = tv1.tv_usec = tv2.tv_usec = 0; } t1 = (tv1.tv_sec & 1) * 1000000 + tv1.tv_usec; t2 = (tv2.tv_sec & 1) * 1000000 + tv2.tv_usec; softlog->Log(SOFT_LOG_INFO, 0, "[dfb] Display frame time is %d microseconds\n", t2 - t1); displayTimeUS = t2 - t1; } } /* --------------------------------------------------------------------------- */ bool cDFBVideoOut::Initialize (void) { /* ------------------------------------------------------------------------- * force reconfiguring of video layer so cle266 color key works */ aspect_changed = 1; SetParams (); aspect_changed = 0; /* ------------------------------------------------------------------------- * get up our remote running */ if (!dfbRemote) { dfbRemote = new cSoftRemote ("softdevice-dfb"); } videoInitialized = true; return true; } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::ProcessEvents () { DFBInputEvent event; if (!videoInitialized) return; while (events->GetEvent( DFB_EVENT(&event) )) { if (event.type == DIET_KEYPRESS && dfbRemote) { switch (event.key_symbol) { case DIKS_SHIFT: case DIKS_CONTROL: case DIKS_ALT: case DIKS_ALTGR: case DIKS_META: case DIKS_SUPER: case DIKS_HYPER: break; default: if ( CatchRemoteKey(dfbRemote->Name(), event.key_symbol, setupStore->cropModeToggleKey) ) { setupStore->CropModeNext(); } else { #if HAVE_DIEF_REPEAT dfbRemote->PutKey(event.key_symbol, event.flags & DIEF_REPEAT); #else dfbRemote->PutKey(event.key_symbol, false); #endif } break; } } } } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::SetParams() { DFBDisplayLayerConfig dlc; DFBDisplayLayerConfigFlags failed; if (videoLayer || useStretchBlit) { if ( ! videoSurface || aspect_changed || currentPixelFormat != setupStore->pixelFormat || cutTop != setupStore->cropTopLines || cutBottom != setupStore->cropBottomLines || cutLeft != setupStore->cropLeftCols || cutRight != setupStore->cropRightCols || useStretchBlit != setupStore->useStretchBlit || useSetSourceRectangle != setupStore->useSetSourceRectangle) { cutTop = setupStore->cropTopLines; cutBottom = setupStore->cropBottomLines; cutLeft = setupStore->cropLeftCols; cutRight = setupStore->cropRightCols; softlog->Log(SOFT_LOG_DEBUG, 0, "[dfb] (re)configuring Videolayer to %d x %d (%dx%d)\n", fwidth,fheight,swidth,sheight); dlc.flags = (DFBDisplayLayerConfigFlags)(DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | DLCONF_OPTIONS); useStretchBlit = false; useSetSourceRectangle = setupStore->useSetSourceRectangle; /* --------------------------------------------------------------------- * if we are in video underlay mode (videoLayerLevel == -1), we have * real alpha blending with videoLayer and osdLayer. */ OSDpseudo_alpha = (videoLayerLevel == 1); if (setupStore->pixelFormat == 0) { dlc.pixelformat = DSPF_I420; setupStore->useStretchBlit = useStretchBlit = false; } else if (setupStore->pixelFormat == 1) { dlc.pixelformat = DSPF_YV12; setupStore->useStretchBlit = useStretchBlit = false; } else if (setupStore->pixelFormat == 2) { dlc.pixelformat = DSPF_YUY2; if (setupStore->useStretchBlit) { useStretchBlit = true; OSDpseudo_alpha = false; } } if (useSetSourceRectangle || useStretchBlit) { /* -------------------------------------------------------------------- * this should be the settings if SetSourceRectangle is working for * all drivers. * SetSourceRectangle() moved, after layer is reconfigured */ dlc.width = fwidth; dlc.height = fheight; } else { dlc.width = swidth; dlc.height = sheight; } dlc.flags = (DFBDisplayLayerConfigFlags)((int) dlc.flags | DLCONF_OPTIONS); dlc.options = DLOP_FIELD_PARITY; #if HAVE_DSCAPS_DOUBLE dlc.flags = (DFBDisplayLayerConfigFlags) ((int) dlc.flags | DLCONF_SURFACE_CAPS); dlc.surface_caps = DSCAPS_DOUBLE; #endif vidDsc.flags = (DFBSurfaceDescriptionFlags) (DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT); vidDsc.caps = DSCAPS_VIDEOONLY; vidDsc.width = dlc.width; vidDsc.height = dlc.height; vidDsc.pixelformat = dlc.pixelformat; currentPixelFormat = setupStore->pixelFormat; pixelformat = dlc.pixelformat; if (!useStretchBlit) { if (videoSurface) videoSurface->Release(); videoSurface = NULL; /* -------------------------------------------------------------------- * set the default options to none */ dlc.options = (DFBDisplayLayerOptions)( DLOP_NONE ); #if 0 if (videoLayerDescription.caps & DLCAPS_DEINTERLACING) { /* ------------------------------------------------------------------ * if deinterlacing is supported we'll use that */ dlc.options = (DFBDisplayLayerOptions)( DLOP_DEINTERLACING ); } #endif if (videoLayerLevel == -1) { try { videoLayer->SetLevel(videoLayerLevel); } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] SetParams: action=%s, result=%s Failed: SetLevel()\n", ex->GetAction(), ex->GetResult()); delete ex; } } else if (videoLayerDescription.caps & DLCAPS_ALPHACHANNEL) { /* ------------------------------------------------------------------ * use alpha channel if it is supported and disable pseudo alpha mode */ dlc.options = (DFBDisplayLayerOptions)((int)dlc.options|DLOP_ALPHACHANNEL); OSDpseudo_alpha = false; } else { if (videoLayerDescription.caps & DLCAPS_DST_COLORKEY) { /* ---------------------------------------------------------------- * no alpha channel but destination color keying is supported */ dlc.options = (DFBDisplayLayerOptions)((int)dlc.options| DLOP_DST_COLORKEY); } } if (setupStore->useMGAtv || setupStore->viaTv) { dlc.options = (DFBDisplayLayerOptions)((int)dlc.options| DLOP_FIELD_PARITY); softlog->Log(SOFT_LOG_DEBUG, 0, "[dfb] SetParams: Enabling DLOP_FIELD_PARITY\n"); } /* * -------------------------------------------------------------------- * Try with triple or double buffering */ dlc.flags = (DFBDisplayLayerConfigFlags) ((int) dlc.flags | DLCONF_BUFFERMODE); dlc.buffermode = DLBM_UNKNOWN; if (setupStore->tripleBuffering) { dlc.buffermode = DLBM_TRIPLE; try { videoLayer->TestConfiguration(dlc, &failed); } catch (DFBException *ex) { if (failed & DLCONF_BUFFERMODE) { softlog->Log(SOFT_LOG_DEBUG, 0, "[dfb]: SetParms (): failed to set buffermode " "to triple, will try back video\n"); dlc.buffermode = DLBM_UNKNOWN; } delete ex; } } if (dlc.buffermode == DLBM_UNKNOWN) { dlc.buffermode = DLBM_BACKVIDEO; try { videoLayer->TestConfiguration(dlc, &failed); } catch (DFBException *ex) { if (failed & DLCONF_BUFFERMODE) { softlog->Log(SOFT_LOG_DEBUG, 0, "[dfb]: SetParams: failed to set buffermode " "to back video, reverting to normal\n"); dlc.buffermode = DLBM_FRONTONLY; } else { softlog->Log(SOFT_LOG_INFO, 0, "[dfb]: Testconfiguration failed flags: %08x " "(disabling failed flags)\n", failed); dlc.flags = (DFBDisplayLayerConfigFlags) (dlc.flags & ~failed); } delete ex; } } /* -------------------------------------------------------------------- * OK, try to set the video layer configuration */ try { videoLayer->SetConfiguration(dlc); #if HAVE_SetSourceRectangle if (useSetSourceRectangle) videoLayer->SetSourceRectangle (sxoff, syoff, swidth, sheight); #endif } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] SetParams: action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; } if (videoLayerDescription.caps & DLCAPS_SCREEN_LOCATION) { /* ------------------------------------------------------------------ * workaround for a bug in DirectFB: force SetScreenLocation to be * executed always. */ try { videoLayer->SetScreenLocation(0.0,0.0,0.5,0.5); videoLayer->SetScreenLocation((float) lxoff / (float) dwidth, (float) lyoff / (float) dheight, (float) lwidth / (float) dwidth, (float) lheight / (float) dheight); } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] SetParams() SetScreenLocation(): " "action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; } } else { softlog->Log(SOFT_LOG_INFO, 0, "Can't configure ScreenLocation. Hope it is Fullscreen\n"); } /* -------------------------------------------------------------------- * set colorkey now. some driver accepct that _after_ configuration * has been set ! But check that color keying is supported. */ try { if (videoLayerDescription.caps & DLCAPS_DST_COLORKEY) videoLayer->SetDstColorKey(COLORKEY); videoSurface=videoLayer->GetSurface(); videoSurface->Clear(COLORKEY,0xff); } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] SetParams (a) EXITING: action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; exit(EXIT_FAILURE); } } else { softlog->Log(SOFT_LOG_DEBUG, 0, "[dfb] creating new surface (stretchBlit)\n"); try { if (videoSurface) { /* ------------------------------------------------------------------ * clear previous used surface. there were some troubles when we * started in I420 mode, switched to YUY2 and video format changed * from 4:3 to 16:9 . */ videoSurface->Clear(COLORKEY,0); //clear and videoSurface->Release(); } if (setupStore->useMGAtv) { vidDsc.caps = DFB_ADD_SURFACE_CAPS(vidDsc.caps, DSCAPS_INTERLACED); } videoSurface=dfb->CreateSurface(vidDsc); /* -------------------------------------------------------------------- * Here is probably a bug in DirectFB, as Clear() does _not_ work * the same, as manual wipe out YUY2 surface. I tried Clear() on my * tests, but it did not solve the problem. That happens with my * Matrox G550. * videoSurface->Clear(0,0,0,0); * The workaround code assumes that in case of stretchBlit, pixelformat * YUY2 is used. */ { int *dst, i, j; int pitch; void *tmp_dst; videoSurface->Lock(DSLF_WRITE, &tmp_dst, &pitch); dst = (int *) tmp_dst; for(i = 0; i < vidDsc.height; ++i, dst += pitch/4) for (j = 0; j < vidDsc.width / 2; ++j) dst [j] = 0x80008000; videoSurface->Unlock(); } } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] SetParams (b) EXITING: action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; exit(EXIT_FAILURE); } } ReportSurfaceCapabilities (videoSurface, "videoSurface"); softlog->Log(SOFT_LOG_DEBUG, 0, "[dfb] (re)configured 0x%08x\n",pixelformat); } if (targetFieldOrder != currentFieldOrder) { if (setupStore->useMGAtv) SetFieldParity(osdLayer, targetFieldOrder); if (setupStore->viaTv) SetFieldParity(videoLayer, targetFieldOrder); currentFieldOrder = targetFieldOrder; } } else { softlog->Log(SOFT_LOG_ERROR, 0, "No Videolayer available. Exiting...\n"); exit(EXIT_FAILURE); } } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::Pause(void) { } /* ---------------------------------------------------------------------------- */ void cDFBVideoOut::OpenOSD () { IDirectFBSurface *tmpSurface; if (!videoInitialized) return; cVideoOut::OpenOSD(); try { tmpSurface = (useStretchBlit) ? osdSurface : scrSurface; tmpSurface->Clear(0,0,0,clearAlpha); tmpSurface->Flip(); tmpSurface->Clear(0,0,0,clearAlpha); } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] OpenOSD: action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; } } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::OSDStart() { IDirectFBSurface *tmpSurface; if (!videoInitialized) return; try { tmpSurface = (useStretchBlit) ? osdSurface : scrSurface; tmpSurface->SetBlittingFlags(DSBLIT_NOFX); } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] OSDStart: action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; } } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::GetLockOsdSurface(uint8_t *&osd, int &stride, bool *&DirtyLines) { int pitch; void *dst; dirtyLines = DirtyLines = NULL; osd = NULL; stride = 0; tmpOsdSurface = NULL; if (!videoInitialized) return; try { dirtyLines=DirtyLines=new bool[Yres]; memset(dirtyLines,false,sizeof(bool)*Yres); tmpOsdSurface = (useStretchBlit) ? osdSurface : scrSurface; tmpOsdSurface->Lock(DSLF_WRITE, &dst, &pitch) ; //printf("GetLockOsdSurface %p\n",tmpOsdSurface);fflush(stdout); osd=(uint8_t *)dst;stride=pitch; } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] Refresh: action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; } } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::CommitUnlockOsdSurface() { if (!videoInitialized || !dirtyLines || !tmpOsdSurface) return; //printf("CommitUnlockOsdSurface %p\n",tmpOsdSurface);fflush(stdout); try { DFBRectangle osdsrc; tmpOsdSurface->Unlock(); tmpOsdSurface->Flip(); int miny=0; int maxy=0; tmpOsdSurface->SetBlittingFlags(DSBLIT_NOFX); do { while (!dirtyLines[miny] && miny < Yres) miny++; if (miny >= Yres) break; maxy=miny; while (dirtyLines[maxy] && maxy < Yres) maxy++; osdsrc.x = 0; osdsrc.y = miny; osdsrc.w = Xres; osdsrc.h = maxy-miny + 1; tmpOsdSurface->Blit(tmpOsdSurface,&osdsrc,0,miny); //printf("CommitUnlockOsdSurface3 %p\n",tmpOsdSurface);fflush(stdout); miny=maxy; } while ( minyLog(SOFT_LOG_ERROR, 0, "[dfb] Refresh: action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; } //printf("CommitUnlockOsdSurface %p 4\n",tmpOsdSurface);fflush(stdout); delete[] dirtyLines; dirtyLines=NULL; tmpOsdSurface=NULL; clearBackground = 0; cVideoOut::CommitUnlockOsdSurface(); } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::GetOSDMode(int &Depth, bool &HasAlpha, bool &AlphaInversed, bool &IsYUV) { Depth=Bpp; HasAlpha=!OSDpseudo_alpha; AlphaInversed=isVIAUnichrome; IsYUV=false; } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::GetOSDDimension( int &Width, int &Height, int &xPan, int &yPan) { Width=Xres; Height=Yres; xPan = yPan = 0; } /* --------------------------------------------------------------------------- */ bool cDFBVideoOut::IsSoftOSDMode() { return cVideoOut::IsSoftOSDMode() || useStretchBlit; } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::CloseOSD() { IDirectFBSurface *tmpSurface; if (!videoInitialized) return; cVideoOut::CloseOSD(); tmpSurface = (useStretchBlit) ? osdSurface : scrSurface; try { if (useStretchBlit) { OSDpresent = false; clearBackground = clearBackCount; tmpSurface->Clear(COLORKEY,clearAlpha); //clear and } else { tmpSurface->Clear(COLORKEY,clearAlpha); //clear and tmpSurface->Flip(); // Flip the field if (!isVIAUnichrome) { tmpSurface->Clear(COLORKEY,clearAlpha); //clear and tmpSurface->Flip(); // Flip the field } } } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] CloseOSD: action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; } } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::ClearBorders() { /* --------------------------------------------------------------------- * clear parts of screen when OSD is present and which are not * covered by video. This avoids fading effects when 16:9 video * is shown on 4:3 screen (top & bottom) or when 4:3 video is shown * on 16:9 screen (left & right). */ if (OSDpresent || clearBackground > 0) { scrSurface->SetColor(0,0,0,0); if (clearBackground > 0) clearBackground--; /* ------------------------------------------------------------------- * clear top & bottom black bar area */ if (lyoff) { scrSurface->FillRectangle(0,0, dwidth,lyoff); scrSurface->FillRectangle(0,lyoff+lheight,dwidth,lyoff); } /* ------------------------------------------------------------------- * clear left & right black bar area */ if (lxoff) { scrSurface->FillRectangle(0,0, lxoff,dheight); scrSurface->FillRectangle(lxoff+lwidth,0,lxoff,dheight); } } } /* --------------------------------------------------------------------------- */ void cDFBVideoOut::YUV(sPicBuffer *buf) { DFBSurfaceFlipFlags flipFlags; IDirectFBSurface *flipSurface; uint8_t *dst; void *tmp_dst; int pitch; int hi; uint8_t *Py = buf->pixel[0] + (buf->edge_height)*buf->stride[0] + buf->edge_width; uint8_t *Pu = buf->pixel[1] + (buf->edge_height/2)*buf->stride[1] + buf->edge_width/2; uint8_t *Pv = buf->pixel[2] + (buf->edge_height/2)*buf->stride[2] + buf->edge_width/2; int Ystride = buf->stride[0]; int UVstride = buf->stride[1]; int Width = buf->width; int Height = buf->height; if (!videoInitialized) return; SetParams(); flipSurface = videoSurface; flipFlags = (setupStore->tripleBuffering) ? DSFLIP_NONE : DSFLIP_ONSYNC; //fprintf(stderr,"[dfb] draw frame (%d x %d) Y: %d UV: %d\n", Width, Height, Ystride, UVstride); try { #ifdef HAVE_CLE266_MPEG_DECODER int currentFB = -1; if (setupStore->cle266HWdecode) { // check if we use internal buffers currentFB=GetBufNum(buf); } if (setupStore->cle266HWdecode && currentFB < 4 && currentFB >= 0) { if (useSetSourceRectangle) { // we use an internal buffer and CLE266 HW decoding videoSurface->Blit(mpegfb[currentFB], NULL, 0, 0); } else { DFBRectangle sRect; sRect.x = sxoff + 2 * cutLeft; sRect.y = syoff + 2 * cutTop; sRect.w = swidth - 2 * (cutLeft + cutRight); sRect.h = sheight - 2 * (cutTop + cutBottom); videoSurface->Blit(mpegfb[currentFB], &sRect, cutLeft * 2, cutTop * 2); } } else { #endif // HAVE_CLE266_MPEG_DECODER videoSurface->Lock(DSLF_WRITE, &tmp_dst, &pitch); dst = (uint8_t *) tmp_dst; if (pixelformat == DSPF_I420 || pixelformat == DSPF_YV12) { if (useSetSourceRectangle) { Py += Ystride * cutTop * 2 + cutLeft * 2; Pv += UVstride * cutTop + cutLeft; Pu += UVstride * cutTop + cutLeft; dst += pitch * cutTop * 2; for(hi=cutTop*2; hi < Height-cutBottom*2; hi++){ fast_memcpy(dst + cutLeft * 2, Py, Width - (cutLeft + cutRight) * 2); Py += Ystride; dst += pitch; } dst += pitch * cutBottom * 2 + pitch * cutTop / 2; for(hi=cutTop; hi < Height/2-cutBottom; hi++) { fast_memcpy(dst + cutLeft, Pu, Width/2 - (cutLeft + cutRight)); Pu += UVstride; dst += pitch / 2; } dst += pitch * cutBottom / 2 + pitch * cutTop / 2; for(hi=cutTop; hi < Height/2-cutBottom; hi++) { fast_memcpy(dst + cutLeft, Pv, Width/2 - (cutLeft + cutRight)); Pv += UVstride; dst += pitch / 2; } } else { Py += (Ystride * syoff) + Ystride * cutTop * 2; Pv += (UVstride * syoff/2) + UVstride * cutTop; Pu += (UVstride * syoff/2) + UVstride * cutTop; dst += pitch * cutTop * 2; for(hi=cutTop*2; hi < sheight-cutBottom*2; hi++){ fast_memcpy(dst+cutLeft*2, Py+sxoff+cutLeft*2, swidth-(cutLeft+cutRight)*2); Py += Ystride; dst += pitch; } dst += pitch * cutBottom * 2 + pitch * cutTop / 2; for(hi=cutTop; hi < sheight/2-cutBottom; hi++) { fast_memcpy(dst+cutLeft, Pu+sxoff/2+cutLeft, swidth/2-(cutLeft+cutRight)); Pu += UVstride; dst += pitch / 2; } dst += pitch * cutBottom / 2 + pitch * cutTop / 2; for(hi=cutTop; hi < sheight/2-cutBottom; hi++) { fast_memcpy(dst+cutLeft, Pv+sxoff/2+cutLeft, swidth/2-(cutLeft+cutRight)); Pv += UVstride; dst += pitch / 2; } } } else if (pixelformat == DSPF_YUY2) { if (interlaceMode) { yv12_to_yuy2_il_mmx2(Py + Ystride * cutTop * 2 + cutLeft * 2, Pu + UVstride * cutTop + cutLeft, Pv + UVstride * cutTop + cutLeft, dst + pitch * cutTop * 2 + cutLeft * 4, Width - 2 * (cutLeft + cutRight), Height - 2 * (cutTop + cutBottom), Ystride, UVstride, pitch); } else { yv12_to_yuy2_fr_mmx2(Py + Ystride * cutTop * 2 + cutLeft * 2, Pu + UVstride * cutTop + cutLeft, Pv + UVstride * cutTop + cutLeft, dst + pitch * cutTop * 2 + cutLeft * 4, Width - 2 * (cutLeft + cutRight), Height - 2 * (cutTop + cutBottom), Ystride, UVstride, pitch); } } videoSurface->Unlock(); #ifdef HAVE_CLE266_MPEG_DECODER } #endif // HAVE_CLE266_MPEG_DECODER if (useStretchBlit) { DFBRectangle src, dst; src.x = sxoff; src.y = syoff; src.w = swidth; src.h = sheight; dst.x = lxoff; dst.y = lyoff; dst.w = lwidth; dst.h = lheight; //fprintf (stderr, "src (%d,%d %dx%d)\n", sxoff,syoff,swidth,sheight); //fprintf (stderr, "dst (%d,%d %dx%d)\n", lxoff,lyoff,lwidth,lheight); clearBackground = (aspect_changed) ? clearBackCount: clearBackground; ClearBorders (); scrSurface->SetBlittingFlags(DSBLIT_NOFX); scrSurface->StretchBlit(videoSurface, &src, &dst); if (OSDpresent) { scrSurface->SetBlittingFlags(DSBLIT_BLEND_ALPHACHANNEL); scrSurface->Blit(osdSurface, NULL, 0, 0); } flipFlags = DSFLIP_WAITFORSYNC; flipSurface = scrSurface; } flipSurface->Flip (NULL, flipFlags); } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "[dfb] YUV: action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; } } #ifdef HAVE_CLE266_MPEG_DECODER bool cDFBVideoOut::SetupCle266Buffers(int width, int height) { DFBSurfaceDescription dsc; int *buf; int y_offset, u_offset, v_offset, i; int mpegfb_stride; char *fbName = getFBName(); if (!CLE266MPEGInitialise(fbName)) { softlog->Log(SOFT_LOG_INFO, 0, "Initialising CLE266 decoder (%s): failed!\n", fbName); free(fbName); return false; } else { free(fbName); softlog->Log(SOFT_LOG_INFO, 0, "Initialising CLE266 decoder (%s): success!\n", fbName); } dsc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS); dsc.caps = DSCAPS_VIDEOONLY; dsc.pixelformat = DSPF_I420; //dsc.pixelformat = DSPF_YV12; dsc.width = width; dsc.height = height; /* Create the 4 MPEG buffers for decoding */ softlog->Log(SOFT_LOG_INFO, 0, "CLE266: Creating buffers for decoder\n"); for (int j=0; j < LAST_PICBUF; j++) mpegfb[j]=NULL; try { for (i = 0; i < 4; i++) { softlog->Log(SOFT_LOG_DEBUG, 0, "CLE266: Creating buffer number %i\n", i); mpegfb[i] = dfb->CreateSurface(dsc); mpegfb[i]->Clear(0,0,0,0); mpegfb[i]->Lock(DSLF_WRITE, (void**) &buf, &mpegfb_stride); mpegfb[i]->GetFramebufferOffset(&mpegfb_ofs[i]); if ( PicBuffer[i].use_count>0 || PicBuffer[i].max_width>0 || PicBuffer[i].max_height>0) { softlog->Log(SOFT_LOG_ERROR, 0, "Fatal error setting up CLE266 buffers!\n"); exit(-1); }; // at this point I know that the buffer is not already allocated PicBuffer[i].pixel[0] = (uint8_t*) buf; PicBuffer[i].pixel[1] = (uint8_t*) buf + height * mpegfb_stride; PicBuffer[i].pixel[2] = (uint8_t*) PicBuffer[i].pixel[1] +(height>>1)*(mpegfb_stride>>1); PicBuffer[i].stride[0] = mpegfb_stride; PicBuffer[i].stride[1] = PicBuffer[i].stride[2] = mpegfb_stride>>1; PicBuffer[i].format = PIX_FMT_YUV420P; PicBuffer[i].owner = this; PicBuffer[i].max_width = width; PicBuffer[i].max_height = height; PicBuffer[i].use_count = 2; // should never be freed!!! } } catch (DFBException *ex) { softlog->Log(SOFT_LOG_ERROR, 0, "CLE266: Error creating buffer: action=%s, result=%s\n", ex->GetAction(), ex->GetResult()); delete ex; return false; } /* Pass info to the decoder...*/ softlog->Log(SOFT_LOG_DEBUG, 0, "CLE266: passing mpegfb_stride\n"); CLE266MPEGSetStride(mpegfb_stride, mpegfb_stride >> 1 ); height = (height + 15) & ~15; width = (width + 15) & ~15; softlog->Log(SOFT_LOG_DEBUG, 0, "CLE266: passing buffers to decoder\n"); for (i = 0; i < 4; i++) { y_offset = mpegfb_ofs[i]; v_offset = y_offset + (mpegfb_stride * height); u_offset = v_offset + (mpegfb_stride >> 1) * (height >> 1); CLE266MPEGSetFrameBuffer(i,y_offset,u_offset,v_offset); } return true; } #endif // HAVE_CLE266_MPEG_DECODER /* --------------------------------------------------------------------------- */ cDFBVideoOut::~cDFBVideoOut() { softlog->Log(SOFT_LOG_DEBUG, 0, "Releasing DFB\n"); setupStore->osdMode = prevOsdMode; if (videoSurface) videoSurface->Release(); if (osdSurface) osdSurface->Release(); if (scrSurface) scrSurface->Release(); if (videoLayer) videoLayer->Release (); if (osdLayer) osdLayer->Release(); #ifdef HAVE_CLE266_MPEG_DECODER if (setupStore->cle266HWdecode) { CLE266MPEGClose(); for (int i = 0; i < 4; ++i) { if (mpegfb[i]) { mpegfb[i]->Unlock(); mpegfb[i]->Release(); } } } #endif // HAVE_CLE266_MPEG_DECODER if (dfb) dfb->Release(); } #ifdef USE_SUBPLUGINS /* --------------------------------------------------------------------------- */ extern "C" void * SubPluginCreator(cSetupStore *s, cSetupSoftlog *log) { return new cDFBVideoOut(s,log); } #endif