? filepath
? opaquelogo.diff
? opaquelogo.patch
? opaquelogo.patch2
Index: NuppelVideoPlayer.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp,v
retrieving revision 1.399
diff -u -d -r1.399 NuppelVideoPlayer.cpp
--- NuppelVideoPlayer.cpp	3 Dec 2004 03:59:11 -0000	1.399
+++ NuppelVideoPlayer.cpp	3 Dec 2004 10:22:49 -0000
@@ -3316,16 +3316,20 @@
 
     commDetect->SetCommSkipAllBlanks(
         gContext->GetNumSetting("CommSkipAllBlanks", 1));
+    if (commercialskipmethod & COMM_DETECT_OPAQUE_LOGO)
+        commDetect->SearchForOpaqueLogo(this, fullSpeed, showPercentage);
 
     if (commercialskipmethod & COMM_DETECT_LOGO)
         commDetect->SearchForLogo(this, fullSpeed, showPercentage);
-
     QTime flagTime;
     flagTime.start();
 
     // the meat of the offline commercial detection code, scan through whole
     // file looking for indications of commercial breaks
     GetFrame(1,true);
+
+
+    
     if (showPercentage)
     {
         if (totalFrames)
Index: commercial_skip.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/commercial_skip.cpp,v
retrieving revision 1.30
diff -u -d -r1.30 commercial_skip.cpp
--- commercial_skip.cpp	24 Sep 2004 02:37:51 -0000	1.30
+++ commercial_skip.cpp	3 Dec 2004 10:22:49 -0000
@@ -43,7 +43,7 @@
 
     if (logoMinValues)
         delete [] logoMinValues;
-
+//    fclose(TIMELINEFP);
 #ifdef SHOW_DEBUG_WIN
     comm_debug_destroy();
 #endif
@@ -104,6 +104,8 @@
         delete [] logoMinValues;
     logoMinValues = new unsigned char[width * height];
 
+    
+//    TIMELINEFP=fopen("/home/kessels/timeline.txt","w");
     logoFrameCount = 0;
     logoInfoAvailable = false;
 
@@ -120,7 +122,7 @@
 #ifdef SHOW_DEBUG_WIN
     comm_debug_show(frame->buf);
 #endif
-
+//    if ((frame_number<100)||((frame_number % 100)==0)) printf("framenumber=%lli\n",frame_number);
     lastFrameWasBlank = frameIsBlank;
     lastFrameWasSceneChange = sceneHasChanged;
 
@@ -142,6 +144,29 @@
         stationLogoPresent = nowPresent;
     }
 
+    if ((logoInfoAvailable) && (commDetectMethod & COMM_DETECT_OPAQUE_LOGO))
+    {
+        bool nowPresent = CheckStationOpaqueLogo();
+
+	if (!stationLogoPresent && nowPresent)
+	{
+		//printf("start logo at %lli\n",frame_number);
+                logoCommBreakMap[frame_number] = MARK_START;
+	}
+        else if (stationLogoPresent && !nowPresent)
+	{
+		//printf("end logo at %lli\n",frame_number);
+            	logoCommBreakMap[frame_number] = MARK_END;
+	}
+	
+
+        stationLogoPresent = nowPresent;
+    }
+
+        
+    
+    
+    
     if (frame_number != -1)
     {
         if (frameIsBlank)
@@ -356,6 +381,96 @@
     return(false);
 }
 
+bool CommDetect::CheckStationOpaqueLogo(void)
+{
+
+//    static int outputfile=1800;
+    long totalerror;
+    long mintotalerror;
+    long pixels=0;
+    int offx;
+    int offy;
+    int bestoffx,bestoffy;
+    if (!logoInfoAvailable)
+    {
+        return(false);
+    }
+    mintotalerror=LONG_MAX;
+    for (offx=-4;offx<5;offx++)
+    {
+	    for (offy=-4;offy<5;offy++)
+	    {
+    		totalerror=0;
+		for (int y = logoMinY; y <= logoMaxY; y++)
+    		{
+			for (int x = logoMinX ; x <= logoMaxX ; x++)
+        		{
+            			if (logoCheckMask[y*width+x] != 0)
+	    			{
+	        			pixels++;
+	        			totalerror+=abs(frame_ptr[(y+offy)*width+(x+offx)]-logoMask[y*width+x]);
+	    			}
+        		}	
+    		}
+		if (totalerror<mintotalerror) 
+		{
+			mintotalerror=totalerror;
+			bestoffx=offx;
+			bestoffy=offy;
+		}
+	    }
+    }
+	    
+/*    
+    if (outputfile==1)
+    {
+        unsigned char errorvalues[width*height];
+        for (int y = logoMinY; y <= logoMaxY; y++)
+        {
+            for (int x = logoMinX ; x <= logoMaxX ; x++)
+            {
+	        long index=y*width+x;
+		if (logoCheckMask[index]==0)
+		{
+		    errorvalues[index]=0;
+		}
+		else
+		{
+		    if (frame_ptr[index]>logoMask[index])
+		    {
+	    	        errorvalues[index]=frame_ptr[index]-logoMask[index];
+		    }
+	            else
+		    {
+	    	        errorvalues[index]=logoMask[index]-frame_ptr[index];
+		    }
+		}
+	    }
+	}
+	printf("totalerror=%li  mintotalerror=%li\n",totalerror,mintotalerror);
+	FILE * fp = fopen("/home/kessels/ikwordgek.raw","w");
+        fwrite(logoMask,sizeof(unsigned char),width*height,fp);
+        fclose(fp);
+	fp = fopen("/home/kessels/ikwordgek0.raw","w");
+        fwrite(errorvalues,sizeof(unsigned char),width*height,fp);
+        fclose(fp);
+	
+	fp = fopen("/home/kessels/ikwordgek2.raw","w");
+        fwrite(logoCheckMask,sizeof(unsigned char),width*height,fp);
+        fclose(fp);
+	fp = fopen("/home/kessels/ikwordgek3.raw","w");
+        fwrite(frame_ptr,sizeof(unsigned char),width*height,fp);
+        fclose(fp);
+    }
+    if (outputfile!=0) outputfile--;
+*/
+    
+//    fprintf(TIMELINEFP,"logopresent \t%i\tbestoff(x,y)=(\t%i\t%i\t) mintotalerror\tpixels=\t%8li\t%8li\n" ,((mintotalerror*50)/pixels),bestoffx,bestoffy,mintotalerror,pixels);
+    return (((mintotalerror*50)/pixels)<10); 
+}
+
+
+
 void CommDetect::SetMinMaxPixels(VideoFrame *frame)
 {
     if (!logoFrameCount)
@@ -428,6 +543,10 @@
                                       marks = logoCommBreakMap;
                                       break;
 
+        case COMM_DETECT_OPAQUE_LOGO: BuildLogoCommList();
+                                      marks = logoCommBreakMap;
+                                      break;
+				      
         case COMM_DETECT_ALL:         BuildBlankFrameCommList();
                                       BuildSceneChangeCommList();
                                       BuildLogoCommList();
@@ -633,7 +752,7 @@
 //    for (int i = 0; i <= framesProcessed; i++)
 //    {
 //        int value = frameMap[i];
-        
+
 //    }
 }
 
@@ -970,7 +1089,7 @@
 bool CommDetect::FrameIsInCommBreak(long long f, QMap<long long, int> &breakMap)
 {
     for(long long i = f; i < framesProcessed; i++)
-        if (breakMap.contains(i)) 
+        if (breakMap.contains(i))
         {
             int type = breakMap[i];
             if ((type == MARK_COMM_END) || (i == f))
@@ -980,7 +1099,7 @@
         }
 
     for(long long i = f; i >= 0; i--)
-        if (breakMap.contains(i)) 
+        if (breakMap.contains(i))
         {
             int type = breakMap[i];
             if ((type == MARK_COMM_START) || (i == f))
@@ -1101,6 +1220,8 @@
     }
 }
 
+
+
 void CommDetect::SetLogoMaskArea()
 {
     logoMinX = width - 1;
@@ -1252,6 +1373,7 @@
         tmpMap[it.key()] = it.data();
 
     prev = tmpMap.begin();
+
     it = prev;
     it++;
     while(it != tmpMap.end())
@@ -1317,7 +1439,7 @@
     int counter = 0;
     unsigned char *mask[loops];
 
-    VERBOSE(VB_COMMFLAG, "Searching for Station Logo");
+    VERBOSE(VB_COMMFLAG, "Searching for Transparant Station Logo");
 
     for (int i = 0; i < loops; i++)
         mask[i] = new unsigned char[height * width];
@@ -1330,7 +1452,7 @@
 
     nvp->GetFrame(1,true);
 
-    while(counter < loops && loop < maxLoops && !nvp->eof) 
+    while(counter < loops && loop < maxLoops && !nvp->eof)
     {
         nvp->JumpToFrame(seekFrame);
         nvp->ClearAfterSeek();
@@ -1345,7 +1467,6 @@
             if (!fullSpeed)
                 usleep(10000);
         }
-
         GetLogoMask(mask[counter]);
 
         int pixelsInMask = 0;
@@ -1377,6 +1498,7 @@
 
     SetLogoMask(mask[0]);
 
+
     nvp->JumpToFrame(0);
     nvp->ClearAfterSeek();
 
@@ -1390,3 +1512,179 @@
         delete [] mask[i];
 }
 
+
+
+
+
+void CommDetect::SearchForOpaqueLogo(NuppelVideoPlayer *nvp, bool fullSpeed,
+                               bool verbose)
+{
+    int loops = 200;
+    int loop = 0;
+    int sampleSpacing = 1;
+    int seekIncrement = (int)(sampleSpacing * 10 * fps);
+    long long seekFrame = seekIncrement;
+    unsigned char *opaqueLogo[loops];
+    int opaqueLogoFound[loops];
+    unsigned char histogram[255];
+    unsigned char bandwidth=15;
+    VERBOSE(VB_COMMFLAG, "Searching for Opaque Station Logo");
+
+    if (verbose)
+    {
+        printf( "Opaque Logo2 Search" );
+        fflush( stdout );
+    }
+
+    nvp->GetFrame(1,true);
+    //first fetch a number of frames
+    while(loop < loops && !nvp->eof)
+    {
+        opaqueLogo[loop] = new unsigned char[height * width];        
+        nvp->JumpToFrame(seekFrame);
+        nvp->ClearAfterSeek();
+
+        VideoFrame *frame= nvp->videoOutput->GetLastDecodedFrame();
+        memcpy(opaqueLogo[loop], frame->buf, width * height);
+ 	//FILE *fp;
+    	//char filepath[100];
+        //sprintf(filepath,"/tmp/frame%02i.raw",loop);
+	//fp=fopen(filepath,"w");
+	//fwrite(opaqueLogo[loop],sizeof(unsigned char),width*height,fp);
+	//fclose(fp);
+            // sleep a little so we don't use all cpu even if we're niced
+            if (!fullSpeed)
+                usleep(10000);
+        seekFrame += seekIncrement;
+
+        loop++;
+    }
+    loops=loop;
+//    printf("fetched frames\n");
+//    fflush(stdout);
+         //determine most frequent value for each pixel and store that in logo.
+        //frames which match, get a raised haslogo
+        for (int y=0;y<height;y++)
+		for (int x=0;x<width;x++)
+		{
+			logoMask[y*width+x]=0;
+			logoCheckMask[y*width+x]=0;
+		}
+	
+	
+	for (int y = 11; y < height-11; y++) //borders are noisy
+        {
+                for (int x = 11; x < width-11; x++) //borders are noisy
+                {
+                        for(loop=0;loop< 0x100;loop++)
+                        {
+                               histogram[loop]=0;
+			}
+                        for(loop=0;loop<loops;loop++)
+                        {
+                                histogram[opaqueLogo[loop][y*width+x]]++;
+                        }
+                        int maxcount=0;
+                        int maxpos=0;
+                        for(loop=0;loop<0x100-bandwidth;loop++)
+                        {
+                                int pixelcount=0;
+                                for(int loop2=0;loop2<bandwidth;loop2++)
+                                {
+                                        pixelcount+=histogram[loop+loop2];
+                                }
+                                if (pixelcount>maxcount)
+                                {
+                                        //printf("%i ",maxcount);
+                                        maxcount=pixelcount;
+                                        maxpos=loop;
+                                }
+                        }
+                        if (maxcount>(loops*0.5))
+                        {
+                                long actualpos=0;
+                                for(loop=maxpos;loop<maxpos+bandwidth;loop++)
+                                {
+                                        actualpos+=loop*histogram[loop];
+                                }
+                                logoMask[y*width+x]=actualpos/maxcount;
+				logoCheckMask[y*width+x]+=64;//sets bitthat this pixel contained some info
+				for (int runvarx=x-2;runvarx<x+3;runvarx++)
+					for (int runvary=y-2;runvary<y+3;runvary++)
+						logoCheckMask[runvary*width+runvarx]++;//set info on neighbouring pixels
+                        }
+		
+                }
+        }
+	//FILE *fp;
+	//fp=fopen("/home/kessels/logonew.raw","w");
+        //fwrite(logoMask,sizeof(unsigned char),width*height,fp);
+        //fclose(fp);
+	long pixels=0;
+	
+//remove orphaned pixels
+        for (int y = 0; y < height; y++)
+                for (int x = 0; x < width; x++)
+			if (logoCheckMask[y*width+x]<64+9) 
+			{
+				logoCheckMask[y*width+x]=0;
+			}
+			else 
+			{
+				pixels++;//at least nine neighbouring pixel
+			}
+	
+	//fp=fopen("/home/kessels/logocheckmask.raw","w");
+        //fwrite(logoCheckMask,sizeof(unsigned char),width*height,fp);
+        //fclose(fp);
+
+    if (pixels < 30)
+    {
+        detectStationLogo = false;
+        return;
+    }
+    
+    
+    //now determine logoMask
+    logoMinX = width - 1;
+    logoMaxX = 0;
+    logoMinY = height - 1;
+    logoMaxY = 0;
+
+    for (int y = 0; y < height; y++)
+    {
+        for (int x = 0; x < width; x++)
+        {
+            if (logoCheckMask[y * width + x] !=0)
+            {
+                if (x < logoMinX)
+                    logoMinX = x;
+                if (y < logoMinY)
+                    logoMinY = y;
+                if (x > logoMaxX)
+                    logoMaxX = x;
+                if (y > logoMaxY)
+                    logoMaxY = y;
+            }
+        }
+    }
+   //printf("logo-location x:%3i-%3i y:%3i-%3i\n",logoMinX,logoMaxX,logoMinY,logoMaxY); 
+    
+    
+    logoInfoAvailable = true;
+
+
+
+    if (verbose)
+    {
+        printf( "\b\b\b\b\b\b\b\b\b\b\b" );
+        fflush( stdout );
+    }
+
+    nvp->JumpToFrame(0);
+    nvp->ClearAfterSeek();
+    nvp->GetFrame(1,true);
+    
+    for (int i = 0; i < loops; i++)
+        delete [] opaqueLogo[i];
+}
Index: commercial_skip.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/commercial_skip.h,v
retrieving revision 1.17
diff -u -d -r1.17 commercial_skip.h
--- commercial_skip.h	11 Mar 2004 04:35:32 -0000	1.17
+++ commercial_skip.h	3 Dec 2004 10:22:49 -0000
@@ -19,6 +19,7 @@
     COMM_DETECT_SCENE       = 0x02,
     COMM_DETECT_BLANK_SCENE = 0x03,
     COMM_DETECT_LOGO        = 0x04,
+    COMM_DETECT_OPAQUE_LOGO = 0x08,
     COMM_DETECT_ALL         = 0xFF
 };
 
@@ -73,13 +74,15 @@
     void SetLogoMaskArea();
     void GetLogoMask(unsigned char *mask);
     void SetLogoMask(unsigned char *mask);
+    bool GetOpaqueLogo(unsigned char *maskIn1,unsigned char *maskIn2,unsigned char *maskOut);
+    void CommDetect::SearchForOpaqueLogo(NuppelVideoPlayer *nvp, bool fullSpeed,bool verbose);
 
 
   private:
     bool CheckFrameIsBlank(void);
     bool CheckSceneHasChanged(void);
     bool CheckStationLogo(void);
-
+    bool CheckStationOpaqueLogo(void);
     int GetAvgBrightness(void);
 
     void CondenseMarkMap(QMap<long long, int>&map, int spacing, int length);
@@ -95,7 +98,7 @@
     double fps;
     double fpm;
     bool blankFramesOnly;
-
+    
     long long framesProcessed;
 
     bool detectBlankFrames;
@@ -110,6 +113,7 @@
     unsigned char *logoMask;
     unsigned char *logoCheckMask;
     bool logoInfoAvailable;
+    bool logoIsOpaque;
     int logoFrameCount;
     int logoMinX;
     int logoMaxX;
@@ -137,6 +141,7 @@
 
     int histogram[256];
     int lastHistogram[256];
+//    FILE * TIMELINEFP;
 };
 
 #endif
