The included patch makes dfb:mgatv use YV12 colourspace for video and
the hardware subpicture layer for OSD. The patch is a prime example of
bad goal-oriented programming, but does what I wanted: improves
performance to the level that my 450 MHz P2 can now function as a DVB
box like no underpowered P2 has done before! Unfortunately, the patch
probably breaks everything else, but I'm too lazy to clean it up.
-- Heikki Lindholm
diff -Nru softdevice-orig/SoftOsd.c softdevice-work/SoftOsd.c
--- softdevice-orig/SoftOsd.c 2006-09-17 19:24:28.000000000 +0300
+++ softdevice-work/SoftOsd.c 2006-09-17 19:43:50.000000000 +0300
@@ -50,18 +50,20 @@
bitmap_Format=PF_None; // forces a clear after first SetMode
OSD_Bitmap=new uint32_t[OSD_STRIDE*(OSD_HEIGHT+4)];
+ indexedPaletteEntriesFilled = 0;
+ indexedPaletteChanged = false;
videoOut = VideoOut;
xPan = yPan = 0;
videoOut->OpenOSD();
xOfs=X;yOfs=Y;
ScreenOsdWidth=ScreenOsdHeight=0;
- int Depth; bool HasAlpha; bool AlphaInversed; bool IsYUV;
+ int Depth; bool HasAlpha; bool AlphaInversed; bool IsYUV; bool IsLUT;
uint8_t *PixelMask;
videoOut->AdjustOSDMode();
videoOut->GetOSDMode(Depth,HasAlpha,AlphaInversed,
- IsYUV,PixelMask);
+ IsYUV,IsLUT,PixelMask);
SetMode(Depth,HasAlpha,AlphaInversed,
- IsYUV,PixelMask);
+ IsYUV,IsLUT,PixelMask);
};
/*--------------------------------------------------------------------------*/
@@ -110,11 +112,12 @@
}
int Depth; bool HasAlpha; bool AlphaInversed; bool IsYUV;
+ bool IsLUT;
uint8_t *PixelMask;
videoOut->GetOSDMode(Depth,HasAlpha,AlphaInversed,
- IsYUV,PixelMask);
+ IsYUV,IsLUT,PixelMask);
bool modeChanged=SetMode(Depth,HasAlpha,AlphaInversed,
- IsYUV,PixelMask);
+ IsYUV,IsLUT,PixelMask);
if (newXPan != xPan || newYPan != yPan) {
xPan = newXPan;
@@ -155,10 +158,10 @@
RefreshAll=true;
};
- int Depth; bool HasAlpha; bool AlphaInversed; bool IsYUV;
+ int Depth; bool HasAlpha; bool AlphaInversed; bool IsYUV; bool IsLUT;
uint8_t *PixelMask;
- videoOut->GetOSDMode(Depth,HasAlpha,AlphaInversed,IsYUV,PixelMask);
- bool modeChanged=SetMode(Depth,HasAlpha,AlphaInversed,IsYUV,PixelMask);
+
videoOut->GetOSDMode(Depth,HasAlpha,AlphaInversed,IsYUV,IsLUT,PixelMask);
+ bool
modeChanged=SetMode(Depth,HasAlpha,AlphaInversed,IsYUV,IsLUT,PixelMask);
if (newXPan != xPan || newYPan != yPan) {
xPan = newXPan;
@@ -170,7 +173,19 @@
if (modeChanged)
videoOut->ClearOSD();
- if (IsYUV) {
+ if (IsLUT) {
+ uint8_t *osd; int stride; bool *dirtyLines;
+ videoOut->GetLockOsdSurface(osd,stride,dirtyLines);
+ if (indexedPaletteChanged) {
+ videoOut->UpdateOSDPalette((uint32_t *)indexedPalette,
16);
+ indexedPaletteChanged = false;
+ }
+ if (osd)
+
CopyToBitmapLUT(osd,stride,ScreenOsdWidth,ScreenOsdHeight,
+ RefreshAll,dirtyLines);
+ videoOut->CommitUnlockOsdSurface();
+ }
+ else if (IsYUV) {
uint8_t *osdPy; uint8_t *osdPu; uint8_t *osdPv;
uint8_t *osdPAlphaY; uint8_t *osdPAlphaUV;
int strideY; int strideUV;
@@ -196,7 +211,7 @@
/* --------------------------------------------------------------------------*/
bool cSoftOsd::SetMode(int Depth, bool HasAlpha, bool AlphaInversed,
- bool IsYUV,uint8_t *PixelMask) {
+ bool IsYUV,bool IsLUT,uint8_t *PixelMask) {
//OSDDEB("SetMode Depth %d HasAlpha %d IsYUV %d AlphaInversed %d
PixelMask %p\n",
// Depth,HasAlpha,IsYUV,AlphaInversed,PixelMask);
@@ -210,6 +225,15 @@
};
return false;
};
+ if (IsLUT) {
+ if ( bitmap_Format!= PF_ALUT44) {
+ bitmap_Format= PF_ALUT44;
+ Clear();
+ FlushBitmaps(false);
+ return true;
+ };
+ return false;
+ };
pixelMask=PixelMask;
switch (Depth) {
@@ -287,6 +311,49 @@
maxColors);
return;
};
+ if (bitmap_Format == PF_ALUT44) {
+ // abuse "palette" for index mapping
+ for (int i = 0; i < maxColors; i++) {
+ // do we already have this colour
+ int found = 0;
+ for (int j = 0; j < indexedPaletteEntriesFilled; j++) {
+ if ((uint32_t)orig_palette[i]&0x00FFFFFF ==
+ (uint32_t)indexedPalette[j]&0x00FFFFFF) {
+ palette[i] = j;
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ continue;
+ // if we have space add it
+ if (indexedPaletteEntriesFilled < 16) {
+ indexedPalette[indexedPaletteEntriesFilled] =
+ orig_palette[i]|0xFF000000;
+ palette[i] = indexedPaletteEntriesFilled++;
+ indexedPaletteChanged = true;
+ }
+ else { // if no space, try to find a closest match
+ int closest_i=-1, closest=4*0xFF;
+ for (int j = 0; j < 16; j++) {
+ // euclidean distance would be ideal, but too cumbersome
+ int r = ((uint32_t)orig_palette[i]>>16 & 0x000000FF-
+ (uint32_t)indexedPalette[j]>>16 &
0x000000FF)&0x000000FF;
+ int g = ((uint32_t)orig_palette[i]>>8 & 0x000000FF-
+ (uint32_t)indexedPalette[j]>>8 &
0x000000FF)&0x000000FF;
+ int b = ((uint32_t)orig_palette[i]>>0 & 0x000000FF-
+ (uint32_t)indexedPalette[j]>>0 &
0x000000FF)&0x000000FF;
+ int d = r+g+b;
+ if (d < closest) {
+ closest = d;
+ closest_i = j;
+ }
+ }
+ palette[i] = closest_i;
+ }
+ }
+ return;
+ }
memcpy(palette,orig_palette,sizeof(tColor)*maxColors);
@@ -350,18 +417,34 @@
OSD_WIDTH-bitmap->X0()-xOfs : x2;
int bitmap_yOfs=yOfs+bitmap->Y0()+Y_OFFSET;
- uint32_t *OSD_pointer=&OSD_Bitmap[(bitmap_yOfs+y1)*OSD_STRIDE+
- xOfs+bitmap->X0()+x1+X_OFFSET];
int missing_line_length=OSD_STRIDE-(x2-x1);
bool *dirty_line=&dirty_lines[bitmap_yOfs+y1];
-
- for (int y=y1; y<y2; y++) {
- for (int x=x1; x<x2; x++) {
- *(OSD_pointer++)=palette[*bitmap->Data(x,y)];
- }
- OSD_pointer+=missing_line_length;
- *(dirty_line++)=true;
- };
+ if (bitmap_Format == PF_ALUT44) {
+ uint8_t *OSD_pointer=&((uint8_t *)OSD_Bitmap)[(bitmap_yOfs+y1)
+ *OSD_STRIDE+xOfs+bitmap->X0()+x1+X_OFFSET];
+
+ for (int y=y1; y<y2; y++) {
+ for (int x=x1; x<x2; x++) {
+ *(OSD_pointer++)=(uint8_t)(
+
(((uint32_t)orig_palette[*bitmap->Data(x,y)]>>24)&0xF0)+
+
(palette[*bitmap->Data(x,y)]&0x0F));
+ }
+ OSD_pointer+=missing_line_length;
+ *(dirty_line++)=true;
+ };
+ }
+ else {
+ uint32_t *OSD_pointer=&OSD_Bitmap[(bitmap_yOfs+y1)*OSD_STRIDE+
+ xOfs+bitmap->X0()+x1+X_OFFSET];
+
+ for (int y=y1; y<y2; y++) {
+ for (int x=x1; x<x2; x++) {
+ *(OSD_pointer++)=palette[*bitmap->Data(x,y)];
+ }
+ OSD_pointer+=missing_line_length;
+ *(dirty_line++)=true;
+ };
+ }
bitmap->Clean();
return true;
};
@@ -1222,6 +1305,103 @@
OSDDEB("CopyToBitmap RGB down end\n");
};
+//---------------------------Indexed (LUT) modes ----------------------
+
+void cSoftOsd::CopyToBitmapLUT(uint8_t *dest, int linesize,
+ int dest_Width, int dest_Height, bool RefreshAll,
+ bool *dirtyLines) {
+ if (dest_Height < 40 || dest_Width < 40)
+ return;
+ fprintf(stderr, "CopyToBitmap LUT destsize:
%d,%d\n",dest_Width,dest_Height);
+
+ if (dest_Height>=OSD_HEIGHT)
+ ScaleVUpCopyToBitmapLUT(dest,linesize,dest_Width,dest_Height,
+ RefreshAll,dirtyLines);
+ else ScaleVDownCopyToBitmapLUT(dest,linesize,dest_Width,dest_Height,
+ RefreshAll,dirtyLines);
+};
+
+// -------------------------- scale vertical up -----------------------
+void cSoftOsd::ScaleVUpCopyToBitmapLUT(uint8_t *dest, int linesize,
+ int dest_Width, int dest_Height, bool RefreshAll,
+ bool *dest_dirtyLines) {
+
+ fprintf(stderr, "CopyToBitmap LUT VUp\n");
+ if ( bitmap_Format != PF_ALUT44) {
+ fprintf(stderr,"cSoftOsd error did not call SetMode()!\n");
+ // convert bitmap to argb
+ bitmap_Format = PF_ALUT44;
+ Clear();
+ FlushBitmaps(false);
+ };
+
+ cMutexLock dirty(&dirty_Mutex);
+
+ uint8_t *buf;
+ uint8_t *pixmap=(uint8_t *)OSD_Bitmap;
+
+ //printf("Scale to %d,%d\n",dest_Width,dest_Height);
+
+ for (int y=0; y<dest_Height; y++) {
+ int is_dirty=RefreshAll;
+ is_dirty|=dirty_lines[y];
+
+ if (!is_dirty)
+ continue;
+
+ // A BIG TODO
+ if (y >= OSD_HEIGHT)
+ break;
+
+ buf=dest+y*linesize;
+ memcpy(buf,pixmap+y*OSD_STRIDE,dest_Width-2);
+
+ if (dest_dirtyLines)
+ dest_dirtyLines[y]=true;
+ };
+ memset(dirty_lines,false,sizeof(dirty_lines));
+ OSDDEB("CopyToBitmap LUT up end\n");
+};
+
+
+//--------------------------- scale vertical down -----------------------------
+void cSoftOsd::ScaleVDownCopyToBitmapLUT(uint8_t *dest, int linesize,
+ int dest_Width, int dest_Height, bool RefreshAll,
+ bool *dest_dirtyLines) {
+
+ fprintf(stderr, "CopyToBitmap RGB Vdown\n");
+ if ( bitmap_Format != PF_ALUT44 ) {
+ fprintf(stderr,"cSoftOsd error did not call SetMode()!\n");
+ // convert bitmap to argb
+ bitmap_Format = PF_ALUT44;
+ Clear();
+ FlushBitmaps(false);
+ };
+
+ cMutexLock dirty(&dirty_Mutex);
+
+ uint8_t *buf;
+ uint8_t *pixmap=(uint8_t *)OSD_Bitmap;
+
+ //printf("Scale to %d,%d\n",dest_Width,dest_Height);
+
+ for (int y=0; y<dest_Height; y++) {
+ int is_dirty=RefreshAll;
+ is_dirty|=dirty_lines[y];
+
+ if (!is_dirty)
+ continue;
+
+
+ buf=dest+y*linesize;
+ memcpy(buf,pixmap+y*OSD_STRIDE,dest_Width-2);
+
+ if (dest_dirtyLines)
+ dest_dirtyLines[y]=true;
+ };
+ memset(dirty_lines,false,sizeof(dirty_lines));
+ OSDDEB("CopyToBitmap LUT up end\n");
+};
//------------------------ lowlevel scaling functions ------------------------
diff -Nru softdevice-orig/SoftOsd.h softdevice-work/SoftOsd.h
--- softdevice-orig/SoftOsd.h 2006-09-17 19:05:21.000000000 +0300
+++ softdevice-work/SoftOsd.h 2006-09-17 19:29:55.000000000 +0300
@@ -79,10 +79,14 @@
PF_ARGB32,
PF_inverseAlpha_ARGB32,
PF_pseudoAlpha_ARGB32,
- PF_AYUV
+ PF_AYUV,
+ PF_ALUT44
};
PixFormat bitmap_Format;
+ tColor indexedPalette[16]; // LUT44 is 4-bit
+ int indexedPaletteEntriesFilled;
+ bool indexedPaletteChanged;
void ConvertPalette(tColor *dest_palette, const tColor *orig_palette,
int maxColors);
@@ -95,7 +99,7 @@
virtual ~cSoftOsd();
bool SetMode(int Depth, bool HasAlpha, bool AlphaInversed,
- bool IsYUV, uint8_t *PixelMask=NULL);
+ bool IsYUV, bool IsLUT, uint8_t *PixelMask=NULL);
bool FlushBitmaps(bool OnlyDirty);
bool DrawConvertBitmap(cBitmap *Bitmap, bool OnlyDirty);
@@ -149,6 +153,15 @@
int dest_Width, int dest_Height, bool RefreshAll=false,
bool *dirtyLines=NULL);
+void CopyToBitmapLUT(uint8_t *dest, int linesize,
+ int dest_Width, int dest_Height, bool RefreshAll,
+ bool *dirtyLines);
+void ScaleVUpCopyToBitmapLUT(uint8_t *dest, int linesize,
+ int dest_Width, int dest_Height, bool RefreshAll,
+ bool *dest_dirtyLines);
+void ScaleVDownCopyToBitmapLUT(uint8_t *dest, int linesize,
+ int dest_Width, int dest_Height, bool RefreshAll,
+ bool *dest_dirtyLines);
private:
diff -Nru softdevice-orig/video-dfb.c softdevice-work/video-dfb.c
--- softdevice-orig/video-dfb.c 2006-09-17 19:23:21.000000000 +0300
+++ softdevice-work/video-dfb.c 2006-09-17 19:55:01.000000000 +0300
@@ -315,23 +315,23 @@
if (!setupStore->useMGAtv)
{
+ osdLayer=dfb->GetDisplayLayer(DLID_PRIMARY);
+ if (!osdLayer) {
+ fprintf(stderr,"[dfb] no OSD layer exiting\n");
+ exit(EXIT_FAILURE);
+ }
fprintf(stderr,"[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;
+ /*currentPixelFormat = setupStore->pixelFormat = 2;
setupStore->pixelFormatLocked = true;
setupStore->useStretchBlit = 1;
- setupStore->stretchBlitLocked = true;
+ setupStore->stretchBlitLocked = true;*/
if (!setupStore->screenPixelAspect)
setupStore->screenPixelAspect = 1;
@@ -353,6 +353,21 @@
exit(EXIT_FAILURE);
}
+ if (setupStore->useMGAtv)
+ {
+ layerInfo = &layerList [SPIC_LAYER];
+ dfb->EnumDisplayLayers(EnumCallBack, layerInfo);
+ osdLayer=layerInfo->layer;
+ if (!osdLayer) {
+ fprintf(stderr,"[dfb] no OSD layer exiting\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ osdLayerDescription = osdLayer->GetDescription();
+ osdLayer->GetConfiguration(&osdLayerConfiguration);
+ osdLayerConfiguration.flags = DLCONF_ALL;
+
videoLayerDescription = videoLayer->GetDescription();
/*
--------------------------------------------------------------------------
@@ -393,7 +408,7 @@
osdLayer->SetConfiguration(osdLayerConfiguration);
if (setupStore->useMGAtv)
- EnableFieldParity(osdLayer);
+ EnableFieldParity(videoLayer); // osdLayer);
if (setupStore->viaTv)
EnableFieldParity(videoLayer);
@@ -438,7 +453,7 @@
DFB_ADD_SURFACE_CAPS(osdDsc.caps, DSCAPS_VIDEOONLY);
osdDsc.width = Xres;
osdDsc.height = Yres;
- osdDsc.pixelformat = DSPF_ARGB;
+ osdDsc.pixelformat = DSPF_ALUT44; // DSPF_ARGB;
useStretchBlit = false;
OSDpseudo_alpha = true;
@@ -543,7 +558,7 @@
dlc.buffermode = DLBM_TRIPLE;
fprintf(stderr,"[dfb] Set DLBM_TRIPLE for layer [%s]\n", desc.name);
- dlc.pixelformat = DSPF_ARGB;
+ dlc.pixelformat = DSPF_YV12; //DSPF_ARGB;
clearBackCount = 3; // 3 for triple, 2 for double buffering
if (desc.caps & DLCAPS_FIELD_PARITY)
@@ -1140,15 +1155,32 @@
cVideoOut::CommitUnlockOsdSurface();
}
+void cDFBVideoOut::UpdateOSDPalette(uint32_t *new_palette, int entries) {
+ IDirectFBPalette *p;
+ DFBColor c[16];
+ if (!tmpOsdSurface)
+ return;
+ p = tmpOsdSurface->GetPalette();
+ for (int i = 0; i < 16; i++) {
+ c[i].a = 0xFF;
+ c[i].r = new_palette[i] >> 16 & 0xFF;
+ c[i].g = new_palette[i] >> 8 & 0xFF;
+ c[i].b = new_palette[i] & 0xFF;
+ }
+ p->SetEntries(&c[0],16,0);
+ p->Release();
+}
+
/* ---------------------------------------------------------------------------
*/
void cDFBVideoOut::GetOSDMode(int &Depth, bool &HasAlpha, bool &AlphaInversed,
- bool &IsYUV, uint8_t *&PixelMask)
+ bool &IsYUV, bool &IsLUT, uint8_t *&PixelMask)
{
Depth=Bpp;
HasAlpha=!OSDpseudo_alpha;
AlphaInversed=isVIAUnichrome;
IsYUV=false;
+ IsLUT=true;//XXX
PixelMask=NULL;
}
@@ -1336,6 +1368,13 @@
} else {
#endif // HAVE_CLE266_MPEG_DECODER
videoSurface->Lock(DSLF_WRITE, (void **)&dst, &pitch);
+ if (pixelformat == DSPF_YV12)
+ {
+ // compared to I420, YV12 has reversed U/V plane order
+ uint8_t *tmp = Pu;
+ Pu = Pv;
+ Pv = tmp;
+ }
if (pixelformat == DSPF_I420 || pixelformat == DSPF_YV12)
{
#if HAVE_SetSourceLocation
diff -Nru softdevice-orig/video-dfb.h softdevice-work/video-dfb.h
--- softdevice-orig/video-dfb.h 2006-09-17 19:05:27.000000000 +0300
+++ softdevice-work/video-dfb.h 2006-09-17 19:29:06.000000000 +0300
@@ -68,13 +68,14 @@
IDirectFBSurface *tmpOsdSurface;
virtual void OpenOSD();
virtual void GetOSDMode(int &Depth, bool &HasAlpha, bool &AlphaInversed,
- bool &IsYUV, uint8_t *&PixelMask);
+ bool &IsYUV, bool &IsLUT, uint8_t *&PixelMask);
virtual void GetOSDDimension(int &OsdWidth,int &OsdHeight,
int &xPan, int &yPan);
virtual void OSDStart();
virtual void GetLockOsdSurface(uint8_t *&osd, int &stride,
bool *&dirtyLines);
virtual void CommitUnlockOsdSurface();
+ virtual void UpdateOSDPalette(uint32_t *new_palette, int entries);
#else
virtual void Refresh();
#endif
diff -Nru softdevice-orig/video-fb.h softdevice-work/video-fb.h
--- softdevice-orig/video-fb.h 2006-09-17 19:05:28.000000000 +0300
+++ softdevice-work/video-fb.h 2006-09-17 19:28:37.000000000 +0300
@@ -32,7 +32,7 @@
virtual void OpenOSD();
virtual void ClearOSD();
virtual void GetOSDMode(int &Depth, bool &HasAlpha, bool &AlphaInversed,
- bool &IsYUV, uint8_t *&pixelmask)
+ bool &IsYUV, bool &IsLUT, uint8_t *&pixelmask)
{ Depth=16;HasAlpha=false;IsYUV=false;pixelmask=PixelMask; };
virtual void GetLockOsdSurface(uint8_t *&osd, int &stride,
bool *&dirtyLines);
diff -Nru softdevice-orig/video.h softdevice-work/video.h
--- softdevice-orig/video.h 2006-09-17 19:05:30.000000000 +0300
+++ softdevice-work/video.h 2006-09-17 19:27:36.000000000 +0300
@@ -28,11 +28,11 @@
#define DV_FORMAT_NORMAL 1
#define DV_FORMAT_WIDE 2
-#define OSD_FULL_WIDTH 736
+#define OSD_FULL_WIDTH 720 /* was 736 */
#define OSD_FULL_HEIGHT 576
#define SRC_HEIGHT 576
-#define SRC_WIDTH 736
+#define SRC_WIDTH 720 /* was 736 */
#if VDRVERSNUM < 10307
@@ -196,8 +196,8 @@
{ OsdWidth=-1;OsdHeight=-1; xPan = yPan = 0;};
virtual void GetOSDMode(int &Depth, bool &HasAlpha, bool &AlphaInversed,
- bool &IsYUV, uint8_t *&PixelMask)
- { Depth=32; HasAlpha=true; AlphaInversed=false; IsYUV=false;
+ bool &IsYUV, bool &IsLUT, uint8_t *&PixelMask)
+ { Depth=32; HasAlpha=true; AlphaInversed=false; IsYUV=false; IsLUT=false;
PixelMask=NULL;};
// should be implemented by all video out method to set the OSD pixel mode
@@ -207,7 +207,9 @@
{ osd=NULL; stride=0; dirtyLines=NULL;};
virtual void CommitUnlockOsdSurface()
{ OSDpresent=true; Osd_changed=1; };
-
+ // indexed
+ virtual void UpdateOSDPalette(uint32_t *new_palette, int entries) {};
+
// Software YUV mode
virtual void GetLockSoftOsdSurface(
uint8_t *&osdPy, uint8_t *&osdPu, uint8_t *&osdPv,
diff -Nru softdevice-orig/video-shm.h softdevice-work/video-shm.h
--- softdevice-orig/video-shm.h 2006-09-17 19:05:28.000000000 +0300
+++ softdevice-work/video-shm.h 2006-09-17 19:28:13.000000000 +0300
@@ -51,7 +51,7 @@
int &xPan, int &yPan);
virtual void GetOSDMode(int &Depth, bool &HasAlpha, bool
&AlphaInversed,
- bool &IsYUV, uint8_t *&PixelMask);
+ bool &IsYUV, bool &IsLUT, uint8_t *&PixelMask);
virtual void YUV(sPicBuffer* buf);
virtual void GetLockOsdSurface(uint8_t *&osd, int &stride,
_______________________________________________
Softdevice-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/softdevice-devel