Ticket #1821: logodetectorpatch

File logodetectorpatch, 44.1 KB (added by lucas@…, 14 years ago)

the patch

Line 
1Index: programs/mythcommflag/ClassicLogoDetector.h
2===================================================================
3--- programs/mythcommflag/ClassicLogoDetector.h (revision 0)
4+++ programs/mythcommflag/ClassicLogoDetector.h (revision 0)
5@@ -0,0 +1,60 @@
6+#ifndef _CLASSICLOGOGEDETECTOR_H_
7+#define _CLASSICLOGOGEDETECTOR_H_
8+
9+#include "LogoDetectorBase.h"
10+
11+typedef struct edgemaskentry EdgeMaskEntry;
12+typedef struct VideoFrame_ VideoFrame;
13+class ClassicCommDetector;
14+
15+class ClassicLogoDetector : public LogoDetectorBase
16+{
17+public:
18+    ClassicLogoDetector(ClassicCommDetector* commDetector,unsigned int width, unsigned int height, unsigned int commdetectborder, unsigned int xspacing, unsigned int yspacing);
19+    ~ClassicLogoDetector();
20+
21+    bool searchForLogo(NuppelVideoPlayer* nvp);
22+    bool doesThisFrameContainTheFoundLogo(unsigned char* frame);
23+    bool pixelInsideLogo(unsigned int x, unsigned int y);
24+
25+    unsigned int getRequiredAvailableBufferForSearch();
26+
27+private:
28+    void SetLogoMaskArea();
29+    void SetLogoMask(unsigned char *mask);
30+    void DumpLogo(bool fromCurrentFrame,unsigned char* framePtr);
31+    void DetectEdges(VideoFrame *frame, EdgeMaskEntry *edges, int edgeDiff);
32+
33+    ClassicCommDetector* commDetector;
34+    unsigned int frameNumber;
35+    bool previousFrameWasSceneChange;
36+    unsigned int xspacing, yspacing;
37+    unsigned int commDetectBorder;
38+
39+    int commDetectLogoSamplesNeeded;
40+    int commDetectLogoSampleSpacing;
41+    int commDetectLogoSecondsNeeded;
42+    double commDetectLogoGoodEdgeThreshold;
43+    double commDetectLogoBadEdgeThreshold;
44+
45+    EdgeMaskEntry *edgeMask;
46+
47+    unsigned char *logoMaxValues;
48+    unsigned char *logoMinValues;
49+    unsigned char *logoFrame;
50+    unsigned char *logoMask;
51+    unsigned char *logoCheckMask;
52+    unsigned char *tmpBuf;
53+
54+    int logoEdgeDiff;
55+    unsigned int logoFrameCount;
56+    unsigned int logoMinX;
57+    unsigned int logoMaxX;
58+    unsigned int logoMinY;
59+    unsigned int logoMaxY;
60+
61+    bool logoInfoAvailable;
62+};
63+
64+
65+#endif
66Index: programs/mythcommflag/mythcommflag.pro
67===================================================================
68--- programs/mythcommflag/mythcommflag.pro      (revision 9932)
69+++ programs/mythcommflag/mythcommflag.pro      (working copy)
70@@ -10,5 +10,5 @@
71 QMAKE_CLEAN += $(TARGET)
72 
73 # Input
74-SOURCES += main.cpp ClassicCommDetector.cpp CommDetectorFactory.cpp CommDetectorBase.cpp
75-HEADERS += CommDetectorBase.h ClassicCommDetector.h SlotRelayer.h CustomEventRelayer.h CommDetectorFactory.h
76+SOURCES += main.cpp ClassicCommDetector.cpp CommDetectorFactory.cpp CommDetectorBase.cpp ClassicLogoDetector.cpp
77+HEADERS += CommDetectorBase.h ClassicCommDetector.h SlotRelayer.h CustomEventRelayer.h CommDetectorFactory.h ClassicLogoDetector.h LogoDetectorBase.h
78Index: programs/mythcommflag/ClassicCommDetector.cpp
79===================================================================
80--- programs/mythcommflag/ClassicCommDetector.cpp       (revision 9932)
81+++ programs/mythcommflag/ClassicCommDetector.cpp       (working copy)
82@@ -4,6 +4,7 @@
83 #include "CommDetector.h"
84 #include "ClassicCommDetector.h"
85 #include "libmythtv/NuppelVideoPlayer.h"
86+#include "ClassicLogoDetector.h"
87 
88 #include "qstring.h"
89 #include "libmyth/mythcontext.h"
90@@ -48,17 +49,10 @@
91         stopsAt(stopsAt_in),
92         recordingStartedAt(recordingStartedAt_in),
93         recordingStopsAt(recordingStopsAt_in),
94-        framesProcessed(0),preRoll(0),postRoll(0)
95+        framesProcessed(0),preRoll(0),postRoll(0),
96+        logoDetector(0)
97 {
98 
99-    edgeMask = NULL;
100-    logoFrame = NULL;
101-    logoMask = NULL;
102-    logoCheckMask = NULL;
103-    logoMaxValues = NULL;
104-    logoMinValues = NULL;
105-    tmpBuf = NULL;
106-
107     stillRecording = recordingStopsAt > QDateTime::currentDateTime();
108     
109     commDetectBorder =
110@@ -81,18 +75,7 @@
111         gContext->GetNumSetting("CommDetectMinShowLength", 65);
112     commDetectMaxCommLength =
113         gContext->GetNumSetting("CommDetectMaxCommLength", 125);
114-    commDetectLogoSamplesNeeded =
115-        gContext->GetNumSetting("CommDetectLogoSamplesNeeded", 240);
116-    commDetectLogoSampleSpacing =
117-        gContext->GetNumSetting("CommDetectLogoSampleSpacing", 2);
118-    commDetectLogoSecondsNeeded = commDetectLogoSamplesNeeded *
119-                                  commDetectLogoSampleSpacing;
120-    commDetectLogoGoodEdgeThreshold =
121-        gContext->GetSetting("CommDetectLogoGoodEdgeThreshold", "0.75")
122-        .toDouble();
123-    commDetectLogoBadEdgeThreshold =
124-        gContext->GetSetting("CommDetectLogoBadEdgeThreshold", "0.85")
125-        .toDouble();
126+
127     skipAllBlanks = !!gContext->GetNumSetting("CommSkipAllBlanks", 1);
128     commDetectBlankCanHaveLogo =
129         !!gContext->GetNumSetting("CommDetectBlankCanHaveLogo", 1);
130@@ -184,35 +167,6 @@
131 
132     framePtr = NULL;
133 
134-    if (edgeMask)
135-        delete [] edgeMask;
136-    edgeMask = new EdgeMaskEntry[width * height];
137-
138-    if (logoFrame)
139-        delete [] logoFrame;
140-    logoFrame = new unsigned char[width * height];
141-
142-    if (logoMask)
143-        delete [] logoMask;
144-    logoMask = new unsigned char[width * height];
145-
146-    if (logoCheckMask)
147-        delete [] logoCheckMask;
148-    logoCheckMask = new unsigned char[width * height];
149-
150-    if (logoMaxValues)
151-        delete [] logoMaxValues;
152-    logoMaxValues = new unsigned char[width * height];
153-
154-    if (logoMinValues)
155-        delete [] logoMinValues;
156-    logoMinValues = new unsigned char[width * height];
157-
158-    if (tmpBuf)
159-        delete [] tmpBuf;
160-    tmpBuf = new unsigned char[width * height];
161-
162-    logoFrameCount = 0;
163     logoInfoAvailable = false;
164 
165     ClearAllMaps();
166@@ -226,20 +180,7 @@
167 
168 ClassicCommDetector::~ClassicCommDetector()
169 {
170-    if (edgeMask)
171-        delete [] edgeMask;
172-    if (logoFrame)
173-        delete [] logoFrame;
174-    if (logoMask)
175-        delete [] logoMask;
176-    if (logoCheckMask)
177-        delete [] logoCheckMask;
178-    if (logoMaxValues)
179-        delete [] logoMaxValues;
180-    if (logoMinValues)
181-        delete [] logoMinValues;
182-    if (tmpBuf)
183-        delete [] tmpBuf;
184+    if (logoDetector) delete logoDetector;
185 }
186 
187 bool ClassicCommDetector::go()
188@@ -249,10 +190,17 @@
189     int requiredBuffer = 7;
190     int requiredHeadStart = requiredBuffer;
191 
192+    if (nvp->OpenFile() < 0)
193+        return false;
194+
195+    Init();
196+
197     if (commDetectMethod & COMM_DETECT_LOGO)
198     {
199+        logoDetector = new ClassicLogoDetector(this,width,height,commDetectBorder,horizSpacing,vertSpacing);
200+
201         requiredHeadStart += max(0,recordingStartedAt.secsTo(startedAt));
202-        requiredHeadStart += commDetectLogoSecondsNeeded;
203+        requiredHeadStart += logoDetector->getRequiredAvailableBufferForSearch();
204     }
205 
206     emit statusUpdate("Building Detection Buffer");
207@@ -272,11 +220,6 @@
208     if ((wereRecording) && (!stillRecording) && (secsSince < requiredHeadStart))
209         return false;
210 
211-    if (nvp->OpenFile() < 0)
212-        return false;
213-
214-    Init();
215-
216     aggressiveDetection = gContext->GetNumSetting("AggressiveCommDetect", 1);
217 
218     if (!nvp->InitVideo())
219@@ -287,9 +230,10 @@
220     }
221     nvp->SetCaptionsEnabled(false);
222 
223+    unsigned int length = static_cast<unsigned int>(nvp->GetLength());
224     if ((commDetectMethod & COMM_DETECT_LOGO) &&
225-        ((nvp->GetLength() == 0) ||
226-         (nvp->GetLength() > commDetectLogoSecondsNeeded)))
227+        ((length == 0) ||
228+         (length > logoDetector->getRequiredAvailableBufferForSearch())))
229     {
230         emit statusUpdate("Searching for Logo");
231 
232@@ -299,7 +243,7 @@
233             cerr.flush();
234         }
235 
236-        SearchForLogo();
237+        logoInfoAvailable = logoDetector->searchForLogo(nvp);
238 
239         if (showProgress)
240         {
241@@ -714,27 +658,30 @@
242         {
243             pixel = framePtr[y * width + x];
244 
245-            if ((commDetectMethod & COMM_DETECT_BLANKS) &&
246-                ((!commDetectBlankCanHaveLogo) ||
247-                 (!logoInfoAvailable) ||
248-                 ((logoInfoAvailable) &&
249-                  ((y < logoMinY) || (y > logoMaxY) ||
250-                   (x < logoMinX) || (x > logoMaxX)))))
251+            if (commDetectMethod & COMM_DETECT_BLANKS)
252             {
253-                blankPixelsChecked++;
254-                totBrightness += pixel;
255+                 bool checkPixel = false;
256+                 if (!commDetectBlankCanHaveLogo) checkPixel = true;
257+                 if (!logoInfoAvailable) checkPixel = true;
258+                     else if (!logoDetector->pixelInsideLogo(x,y)) checkPixel=true;
259 
260-                if (pixel < min)
261-                    min = pixel;
262+                 if (checkPixel)
263+                 {
264+                     blankPixelsChecked++;
265+                     totBrightness += pixel;
266
267+                     if (pixel < min)
268+                          min = pixel;
269 
270-                if (pixel > max)
271-                    max = pixel;
272+                     if (pixel > max)
273+                          max = pixel;
274 
275-                if (pixel > rowMax[y])
276-                    rowMax[y] = pixel;
277+                     if (pixel > rowMax[y])
278+                         rowMax[y] = pixel;
279 
280-                if (pixel > colMax[x])
281-                    colMax[x] = pixel;
282+                     if (pixel > colMax[x])
283+                         colMax[x] = pixel;
284+                 }
285             }
286 
287             if (commDetectMethod & COMM_DETECT_SCENE)
288@@ -854,7 +801,7 @@
289 
290     if ((logoInfoAvailable) && (commDetectMethod & COMM_DETECT_LOGO))
291     {
292-        stationLogoPresent = CheckEdgeLogo();
293+        stationLogoPresent = logoDetector->doesThisFrameContainTheFoundLogo(framePtr);
294     }
295 
296 #if 0
297@@ -2142,172 +2089,6 @@
298     VERBOSE(VB_COMMFLAG, "---------------------------------------------------");
299 }
300 
301-void ClassicCommDetector::DumpLogo(bool fromCurrentFrame)
302-{
303-    char scrPixels[] = " .oxX";
304-
305-    if (!logoInfoAvailable)
306-        return;
307-
308-    cerr << "\nLogo Data ";
309-    if (fromCurrentFrame)
310-        cerr << "from current frame\n";
311-
312-    cerr << "\n     ";
313-
314-    for(int x = logoMinX - 2; x <= (logoMaxX + 2); x++)
315-        cerr << (x % 10);
316-    cerr << "\n";
317-
318-    for(int y = logoMinY - 2; y <= (logoMaxY + 2); y++)
319-    {
320-        cerr << QString::number(y).rightJustify(3, ' ') << ": ";
321-        for(int x = logoMinX - 2; x <= (logoMaxX + 2); x++)
322-        {
323-            if (fromCurrentFrame)
324-            {
325-                cerr << scrPixels[framePtr[y * width + x] / 50];
326-            }
327-            else
328-            {
329-                switch (logoMask[y * width + x])
330-                {
331-                        case 0:
332-                        case 2: cerr << " ";
333-                        break;
334-                        case 1: cerr << "*";
335-                        break;
336-                        case 3: cerr << ".";
337-                        break;
338-                }
339-            }
340-        }
341-        cerr << "\n";
342-    }
343-    cerr.flush();
344-}
345-
346-void ClassicCommDetector::SetLogoMaskArea()
347-{
348-    VERBOSE(VB_COMMFLAG, "SetLogoMaskArea()");
349-
350-    logoMinX = width - 1;
351-    logoMaxX = 0;
352-    logoMinY = height - 1;
353-    logoMaxY = 0;
354-
355-    for (int y = 0; y < height; y++)
356-    {
357-        for (int x = 0; x < width; x++)
358-        {
359-            if (edgeMask[y * width + x].isedge)
360-            {
361-                if (x < logoMinX)
362-                    logoMinX = x;
363-                if (y < logoMinY)
364-                    logoMinY = y;
365-                if (x > logoMaxX)
366-                    logoMaxX = x;
367-                if (y > logoMaxY)
368-                    logoMaxY = y;
369-            }
370-        }
371-    }
372-
373-    logoMinX -= 5;
374-    logoMaxX += 5;
375-    logoMinY -= 5;
376-    logoMaxY += 5;
377-
378-    if (logoMinX < 4)
379-        logoMinX = 4;
380-    if (logoMaxX > (width-5))
381-        logoMaxX = (width-5);
382-    if (logoMinY < 4)
383-        logoMinY = 4;
384-    if (logoMaxY > (height-5))
385-        logoMaxY = (height-5);
386-}
387-
388-void ClassicCommDetector::SetLogoMask(unsigned char *mask)
389-{
390-    int pixels = 0;
391-
392-    memcpy(logoMask, mask, width * height);
393-
394-    SetLogoMaskArea();
395-
396-    for(int y = logoMinY; y <= logoMaxY; y++)
397-        for(int x = logoMinX; x <= logoMaxX; x++)
398-            if (!logoMask[y * width + x] == 1)
399-                pixels++;
400-
401-    if (pixels < 30)
402-    {
403-        detectStationLogo = false;
404-        return;
405-    }
406-
407-    // set the pixels around our logo
408-    for(int y = (logoMinY - 1); y <= (logoMaxY + 1); y++)
409-    {
410-        for(int x = (logoMinX - 1); x <= (logoMaxX + 1); x++)
411-        {
412-            if (!logoMask[y * width + x])
413-            {
414-                for (int y2 = y - 1; y2 <= (y + 1); y2++)
415-                {
416-                    for (int x2 = x - 1; x2 <= (x + 1); x2++)
417-                    {
418-                        if ((logoMask[y2 * width + x2] == 1) &&
419-                            (!logoMask[y * width + x]))
420-                        {
421-                            logoMask[y * width + x] = 2;
422-                            x2 = x + 2;
423-                            y2 = y + 2;
424-
425-                            logoCheckMask[y2 * width + x2] = 1;
426-                            logoCheckMask[y * width + x] = 1;
427-                        }
428-                    }
429-                }
430-            }
431-        }
432-    }
433-
434-    for(int y = (logoMinY - 2); y <= (logoMaxY + 2); y++)
435-    {
436-        for(int x = (logoMinX - 2); x <= (logoMaxX + 2); x++)
437-        {
438-            if (!logoMask[y * width + x])
439-            {
440-                for (int y2 = y - 1; y2 <= (y + 1); y2++)
441-                {
442-                    for (int x2 = x - 1; x2 <= (x + 1); x2++)
443-                    {
444-                        if ((logoMask[y2 * width + x2] == 2) &&
445-                            (!logoMask[y * width + x]))
446-                        {
447-                            logoMask[y * width + x] = 3;
448-                            x2 = x + 2;
449-                            y2 = y + 2;
450-
451-                            logoCheckMask[y * width + x] = 1;
452-                        }
453-                    }
454-                }
455-            }
456-        }
457-    }
458-
459-#ifdef SHOW_DEBUG_WIN
460-    DumpLogo(true);
461-#endif
462-
463-    logoFrameCount = 0;
464-    logoInfoAvailable = true;
465-}
466-
467 void ClassicCommDetector::CondenseMarkMap(QMap<long long, int>&map, int spacing,
468                                           int length)
469 {
470@@ -2412,258 +2193,7 @@
471 /* ideas for this method ported back from comskip.c mods by Jere Jones
472  * which are partially mods based on Myth's original commercial skip
473  * code written by Chris Pinkham. */
474-bool ClassicCommDetector::CheckEdgeLogo(void)
475-{
476 
477-    int radius = 2;
478-    int x, y;
479-    int pos1, pos2, pos3;
480-    int pixel;
481-    int goodEdges = 0;
482-    int badEdges = 0;
483-    int testEdges = 0;
484-    int testNotEdges = 0;
485-
486-    for (y = logoMinY; y <= logoMaxY; y++ )
487-    {
488-        for (x = logoMinX; x <= logoMaxX; x++ )
489-        {
490-            pos1 = y * width + x;
491-            pos2 = (y - radius) * width + x;
492-            pos3 = (y + radius) * width + x;
493-
494-            pixel = framePtr[pos1];
495-
496-            if (edgeMask[pos1].horiz)
497-            {
498-                if ((abs(framePtr[pos1 - radius] - pixel) >= logoEdgeDiff) ||
499-                    (abs(framePtr[pos1 + radius] - pixel) >= logoEdgeDiff))
500-                    goodEdges++;
501-                testEdges++;
502-            }
503-            else
504-            {
505-                if ((abs(framePtr[pos1 - radius] - pixel) >= logoEdgeDiff) ||
506-                    (abs(framePtr[pos1 + radius] - pixel) >= logoEdgeDiff))
507-                    badEdges++;
508-                testNotEdges++;
509-            }
510-
511-            if (edgeMask[pos1].vert)
512-            {
513-                if ((abs(framePtr[pos2] - pixel) >= logoEdgeDiff) ||
514-                    (abs(framePtr[pos3] - pixel) >= logoEdgeDiff))
515-                    goodEdges++;
516-                testEdges++;
517-            }
518-            else
519-            {
520-                if ((abs(framePtr[pos2] - pixel) >= logoEdgeDiff) ||
521-                    (abs(framePtr[pos3] - pixel) >= logoEdgeDiff))
522-                    badEdges++;
523-                testNotEdges++;
524-            }
525-        }
526-    }
527-
528-    double goodEdgeRatio = (double)goodEdges / (double)testEdges;
529-    double badEdgeRatio = (double)badEdges / (double)testNotEdges;
530-
531-    if ((goodEdgeRatio > commDetectLogoGoodEdgeThreshold) &&
532-        (badEdgeRatio < commDetectLogoBadEdgeThreshold))
533-        return true;
534-    else
535-        return false;
536-}
537-
538-
539-void ClassicCommDetector::SearchForLogo()
540-{
541-    int seekIncrement = (int)(commDetectLogoSampleSpacing * fps);
542-    long long seekFrame;
543-    int loops;
544-    int maxLoops = commDetectLogoSamplesNeeded;
545-    EdgeMaskEntry *edgeCounts;
546-    int pos, i, x, y, dx, dy;
547-    int edgeDiffs[] = {5, 7, 10, 15, 20, 30, 40, 50, 60, 0 };
548-
549-
550-    VERBOSE(VB_COMMFLAG, "Searching for Station Logo");
551-
552-    logoInfoAvailable = false;
553-
554-    edgeCounts = new EdgeMaskEntry[width * height];
555-
556-    for (i = 0; edgeDiffs[i] != 0 && !logoInfoAvailable; i++)
557-    {
558-        int pixelsInMask = 0;
559-
560-        VERBOSE(VB_COMMFLAG, QString("Trying with edgeDiff == %1")
561-                .arg(edgeDiffs[i]));
562-
563-        memset(edgeCounts, 0, sizeof(EdgeMaskEntry) * width * height);
564-        memset(edgeMask, 0, sizeof(EdgeMaskEntry) * width * height);
565-
566-        nvp->DiscardVideoFrame(nvp->GetRawVideoFrame(0));
567-
568-        loops = 0;
569-        seekFrame = preRoll + seekIncrement;
570-
571-        while(loops < maxLoops && !nvp->GetEof())
572-        {
573-            VideoFrame* vf = nvp->GetRawVideoFrame(seekFrame);
574-
575-            if ((loops % 50) == 0)
576-                emit breathe();
577-
578-            if (m_bStop)
579-            {
580-                nvp->DiscardVideoFrame(vf);
581-                return;
582-            }
583-
584-            if (!fullSpeed)
585-                usleep(10000);
586-
587-            DetectEdges(vf, edgeCounts, edgeDiffs[i]);
588-
589-            seekFrame += seekIncrement;
590-            loops++;
591-
592-            nvp->DiscardVideoFrame(vf);
593-        }
594-
595-        VERBOSE(VB_COMMFLAG, "Analyzing edge data");
596-
597-#ifdef SHOW_DEBUG_WIN
598-        unsigned char *fakeFrame;
599-        fakeFrame = new unsigned char[width * height * 3 / 2];
600-        memset(fakeFrame, 0, width * height * 3 / 2);
601-#endif
602-
603-        for (y = 0; y < height; y++)
604-        {
605-            if ((y > (height/4)) && (y < (height * 3 / 4)))
606-                continue;
607-
608-            for (x = 0; x < width; x++)
609-            {
610-                if ((x > (width/4)) && (x < (width * 3 / 4)))
611-                    continue;
612-
613-                pos = y * width + x;
614-
615-                if (edgeCounts[pos].isedge > (maxLoops * 0.66))
616-                {
617-                    edgeMask[pos].isedge = 1;
618-                    pixelsInMask++;
619-#ifdef SHOW_DEBUG_WIN
620-                    fakeFrame[pos] = 0xff;
621-#endif
622-
623-                }
624-
625-                if (edgeCounts[pos].horiz > (maxLoops * 0.66))
626-                    edgeMask[pos].horiz = 1;
627-
628-                if (edgeCounts[pos].vert > (maxLoops * 0.66))
629-                    edgeMask[pos].vert = 1;
630-
631-                if (edgeCounts[pos].ldiag > (maxLoops * 0.66))
632-                    edgeMask[pos].ldiag = 1;
633-
634-                if (edgeCounts[pos].rdiag > (maxLoops * 0.66))
635-                    edgeMask[pos].rdiag = 1;
636-            }
637-        }
638-
639-        SetLogoMaskArea();
640-
641-        for (y = logoMinY; y < logoMaxY; y++)
642-        {
643-            for (x = logoMinX; x < logoMaxX; x++)
644-            {
645-                int neighbors = 0;
646-
647-                if (!edgeMask[y * width + x].isedge)
648-                    continue;
649-
650-                for (dy = y - 2; dy <= (y + 2); dy++ )
651-                {
652-                    for (dx = x - 2; dx <= (x + 2); dx++ )
653-                    {
654-                        if (edgeMask[dy * width + dx].isedge)
655-                            neighbors++;
656-                    }
657-                }
658-
659-                if (neighbors < 5)
660-                    edgeMask[y * width + x].isedge = 0;
661-            }
662-        }
663-
664-        SetLogoMaskArea();
665-
666-        VERBOSE(VB_COMMFLAG, QString("Testing Logo area: topleft "
667-                                     "(%1,%2), bottomright (%3,%4)")
668-                                     .arg(logoMinX).arg(logoMinY)
669-                                     .arg(logoMaxX).arg(logoMaxY));
670-
671-#ifdef SHOW_DEBUG_WIN
672-        for (x = logoMinX; x < logoMaxX; x++)
673-        {
674-            pos = logoMinY * width + x;
675-            fakeFrame[pos] = 0x7f;
676-            pos = logoMaxY * width + x;
677-            fakeFrame[pos] = 0x7f;
678-        }
679-        for (y = logoMinY; y < logoMaxY; y++)
680-        {
681-            pos = y * width + logoMinX;
682-            fakeFrame[pos] = 0x7f;
683-            pos = y * width + logoMaxX;
684-            fakeFrame[pos] = 0x7f;
685-        }
686-
687-        comm_debug_show(fakeFrame);
688-        delete [] fakeFrame;
689-
690-        cerr << "Hit ENTER to continue" << endl;
691-        getchar();
692-#endif
693-
694-        if (((logoMaxX - logoMinX) < (width / 4)) &&
695-            ((logoMaxY - logoMinY) < (height / 4)) &&
696-            (pixelsInMask > 50))
697-        {
698-            logoInfoAvailable = true;
699-            logoEdgeDiff = edgeDiffs[i];
700-
701-            VERBOSE(VB_COMMFLAG, QString("Using Logo area: topleft "
702-                                         "(%1,%2), bottomright (%3,%4)")
703-                    .arg(logoMinX).arg(logoMinY)
704-                    .arg(logoMaxX).arg(logoMaxY));
705-        }
706-        else
707-        {
708-            VERBOSE(VB_COMMFLAG, QString("Rejecting Logo area: topleft "
709-                                         "(%1,%2), bottomright (%3,%4), "
710-                                         "pixelsInMask (%5). "
711-                                         "Not within specified limits.")
712-                    .arg(logoMinX).arg(logoMinY)
713-                    .arg(logoMaxX).arg(logoMaxY)
714-                    .arg(pixelsInMask));
715-        }
716-    }
717-
718-    delete [] edgeCounts;
719-
720-    if (!logoInfoAvailable)
721-        VERBOSE(VB_COMMFLAG, "No suitable logo area found.");
722-
723-    nvp->DiscardVideoFrame(nvp->GetRawVideoFrame(0));
724-}
725-
726 void ClassicCommDetector::CleanupFrameInfo(void)
727 {
728     VERBOSE(VB_COMMFLAG, "CommDetect::CleanupFrameInfo()");
729@@ -2753,63 +2283,6 @@
730     }
731 }
732 
733-void ClassicCommDetector::DetectEdges(VideoFrame *frame, EdgeMaskEntry *edges,
734-                                      int edgeDiff)
735-{
736-    int r = 2;
737-    unsigned char *buf = frame->buf;
738-    unsigned char p;
739-    int pos, x, y;
740-
741-    for (y = commDetectBorder + r; y < (height - commDetectBorder - r); y++)
742-    {
743-        if ((y > (height/4)) && (y < (height * 3 / 4)))
744-            continue;
745-
746-        for (x = commDetectBorder + r; x < (width - commDetectBorder - r); x++)
747-        {
748-            int edgeCount = 0;
749-
750-            if ((x > (width/4)) && (x < (width * 3 / 4)))
751-                continue;
752-
753-            pos = y * width + x;
754-            p = buf[pos];
755-
756-            if (( abs(buf[y * width + (x - r)] - p) >= edgeDiff) ||
757-                ( abs(buf[y * width + (x + r)] - p) >= edgeDiff))
758-            {
759-                edges[pos].horiz++;
760-                edgeCount++;
761-            }
762-
763-            if (( abs(buf[(y - r) * width + x] - p) >= edgeDiff) ||
764-                ( abs(buf[(y + r) * width + x] - p) >= edgeDiff))
765-            {
766-                edges[pos].vert++;
767-                edgeCount++;
768-            }
769-
770-            if (( abs(buf[(y - r) * width + (x - r)] - p) >= edgeDiff) ||
771-                ( abs(buf[(y + r) * width + (x + r)] - p) >= edgeDiff))
772-            {
773-                edges[pos].ldiag++;
774-                edgeCount++;
775-            }
776-
777-            if (( abs(buf[(y - r) * width + (x + r)] - p) >= edgeDiff) ||
778-                ( abs(buf[(y + r) * width + (x - r)] - p) >= edgeDiff))
779-            {
780-                edges[pos].rdiag++;
781-                edgeCount++;
782-            }
783-
784-            if (edgeCount >= 3)
785-                edges[pos].isedge++;
786-        }
787-    }
788-}
789-
790 void ClassicCommDetector::GetLogoCommBreakMap(QMap<long long, int> &map)
791 {
792     VERBOSE(VB_COMMFLAG, "CommDetect::GetLogoCommBreakMap()");
793@@ -2841,5 +2314,9 @@
794 
795 }
796 
797+void ClassicCommDetector::logoDetectorBreathe()
798+{
799+    emit breathe();
800+}
801 
802 /* vim: set expandtab tabstop=4 shiftwidth=4: */
803Index: programs/mythcommflag/LogoDetectorBase.h
804===================================================================
805--- programs/mythcommflag/LogoDetectorBase.h    (revision 0)
806+++ programs/mythcommflag/LogoDetectorBase.h    (revision 0)
807@@ -0,0 +1,30 @@
808+#ifndef _LOGODETECTORBASE_H_
809+#define _LOGODETECTORBASE_H_
810+
811+#include "qobject.h"
812+
813+class NuppelVideoPlayer;
814+
815+class LogoDetectorBase : public QObject
816+{
817+    Q_OBJECT
818+
819+public:
820+    LogoDetectorBase(unsigned int w,unsigned int h) : foundLogo(false), width(w),height(h) {};
821+    ~LogoDetectorBase() {};
822+
823+    virtual bool searchForLogo(NuppelVideoPlayer* nvp) = 0;
824+    virtual bool doesThisFrameContainTheFoundLogo(unsigned char* frame) = 0;
825+    virtual bool pixelInsideLogo(unsigned int x, unsigned int y) = 0;
826+    virtual unsigned int getRequiredAvailableBufferForSearch() = 0;
827+
828+signals:
829+    void haveNewInformation(unsigned int framenum, bool haslogo, float debugValue = 0.0);
830+
831+protected:
832+    bool foundLogo;
833+    unsigned int width, height;
834+};
835+
836+
837+#endif
838Index: programs/mythcommflag/ClassicCommDetector.h
839===================================================================
840--- programs/mythcommflag/ClassicCommDetector.h (revision 9932)
841+++ programs/mythcommflag/ClassicCommDetector.h (working copy)
842@@ -6,6 +6,7 @@
843 #include "qdatetime.h"
844 
845 class NuppelVideoPlayer;
846+class LogoDetectorBase;
847 
848 class ClassicCommDetector : public CommDetectorBase
849 {
850@@ -22,18 +23,11 @@
851         void recordingFinished(long long totalFileSize);
852         void requestCommBreakMapUpdate(void);
853 
854+        void logoDetectorBreathe();
855+
856+        friend class ClassicLogoDetector;
857     private:
858 
859-        typedef struct edgemaskentry
860-        {
861-            int isedge;
862-            int horiz;
863-            int vert;
864-            int rdiag;
865-            int ldiag;
866-        }
867-        EdgeMaskEntry;
868-
869         typedef struct frameinfo
870         {
871             int minBrightness;
872@@ -81,15 +75,9 @@
873         void MergeBlankCommList(void);
874         bool FrameIsInBreakMap(long long f, QMap<long long, int> &breakMap);
875         void DumpMap(QMap<long long, int> &map);
876-        void DumpLogo(bool fromCurrentFrame);
877-        void SetLogoMaskArea();
878-        void SetLogoMask(unsigned char *mask);
879         void CondenseMarkMap(QMap<long long, int>&map, int spacing, int length);
880         void ConvertShowMapToCommMap(QMap<long long, int>&map);
881-        bool CheckEdgeLogo(void);
882-        void SearchForLogo();
883         void CleanupFrameInfo(void);
884-        void DetectEdges(VideoFrame *frame, EdgeMaskEntry *edges, int edgeDiff);
885         void GetLogoCommBreakMap(QMap<long long, int> &map);
886 
887         int commDetectMethod;
888@@ -114,12 +102,7 @@
889         int commDetectMinCommBreakLength;
890         int commDetectMinShowLength;
891         int commDetectMaxCommLength;
892-        int commDetectLogoSamplesNeeded;
893-        int commDetectLogoSampleSpacing;
894-        int commDetectLogoSecondsNeeded;
895         bool commDetectBlankCanHaveLogo;
896-        double commDetectLogoGoodEdgeThreshold;
897-        double commDetectLogoBadEdgeThreshold;
898 
899         bool verboseDebugging;
900 
901@@ -146,24 +129,11 @@
902         bool detectSceneChanges;
903         bool detectStationLogo;
904 
905-        bool skipAllBlanks;
906-
907-        EdgeMaskEntry *edgeMask;
908-
909-        unsigned char *logoMaxValues;
910-        unsigned char *logoMinValues;
911-        unsigned char *logoFrame;
912-        unsigned char *logoMask;
913-        unsigned char *logoCheckMask;
914-        unsigned char *tmpBuf;
915         bool logoInfoAvailable;
916-        int logoEdgeDiff;
917-        int logoFrameCount;
918-        int logoMinX;
919-        int logoMaxX;
920-        int logoMinY;
921-        int logoMaxY;
922+        LogoDetectorBase* logoDetector;
923 
924+        bool skipAllBlanks;
925+
926         unsigned char *framePtr;
927 
928         QMap<long long, FrameInfoEntry> frameInfo;
929Index: programs/mythcommflag/ClassicLogoDetector.cpp
930===================================================================
931--- programs/mythcommflag/ClassicLogoDetector.cpp       (revision 0)
932+++ programs/mythcommflag/ClassicLogoDetector.cpp       (revision 0)
933@@ -0,0 +1,553 @@
934+#include "ClassicLogoDetector.h"
935+#include "ClassicCommDetector.h"
936+
937+#include "libmythtv/NuppelVideoPlayer.h"
938+#include "libmyth/mythcontext.h"  //To be able to use VERBOSE()
939+
940+typedef struct edgemaskentry
941+{
942+    int isedge;
943+    int horiz;
944+    int vert;
945+    int rdiag;
946+    int ldiag;
947+}
948+EdgeMaskEntry;
949+
950+
951+ClassicLogoDetector::ClassicLogoDetector(ClassicCommDetector* commdetector,unsigned int w, unsigned int h, unsigned int commdetectborder_in, unsigned int xspacing_in, unsigned int yspacing_in) :
952+    LogoDetectorBase(w,h),
953+    commDetector(commdetector),
954+    frameNumber(0),
955+    previousFrameWasSceneChange(false),
956+    xspacing(xspacing_in),
957+    yspacing(yspacing_in),
958+    commDetectBorder(commdetectborder_in)
959+{
960+    commDetectLogoSamplesNeeded =
961+        gContext->GetNumSetting("CommDetectLogoSamplesNeeded", 240);
962+    commDetectLogoSampleSpacing =
963+        gContext->GetNumSetting("CommDetectLogoSampleSpacing", 2);
964+    commDetectLogoGoodEdgeThreshold =
965+        gContext->GetSetting("CommDetectLogoGoodEdgeThreshold", "0.75")
966+        .toDouble();
967+    commDetectLogoBadEdgeThreshold =
968+        gContext->GetSetting("CommDetectLogoBadEdgeThreshold", "0.85")
969+        .toDouble();
970+   commDetectLogoSecondsNeeded = commDetectLogoSamplesNeeded *
971+                                  commDetectLogoSampleSpacing;
972+
973+
974+
975+    edgeMask = new EdgeMaskEntry[width * height];
976+    logoFrame = new unsigned char[width * height];
977+    logoMask = new unsigned char[width * height];
978+    logoCheckMask = new unsigned char[width * height];
979+    logoMaxValues = new unsigned char[width * height];
980+    logoMinValues = new unsigned char[width * height];
981+    tmpBuf = new unsigned char[width * height];
982+
983+    logoFrameCount = 0;
984+}
985+
986+unsigned int ClassicLogoDetector::getRequiredAvailableBufferForSearch()
987+{
988+    return commDetectLogoSecondsNeeded;
989+}
990+
991+ClassicLogoDetector::~ClassicLogoDetector()
992+{
993+    commDetector = 0;
994+    if (edgeMask)
995+        delete [] edgeMask;
996+    if (logoFrame)
997+        delete [] logoFrame;
998+    if (logoMask)
999+        delete [] logoMask;
1000+    if (logoCheckMask)
1001+        delete [] logoCheckMask;
1002+    if (logoMaxValues)
1003+        delete [] logoMaxValues;
1004+    if (logoMinValues)
1005+        delete [] logoMinValues;
1006+    if (tmpBuf)
1007+        delete [] tmpBuf;
1008+}
1009+
1010+bool ClassicLogoDetector::searchForLogo(NuppelVideoPlayer* nvp)
1011+{
1012+    int seekIncrement = (int)(commDetectLogoSampleSpacing * nvp->GetFrameRate());
1013+    long long seekFrame;
1014+    int loops;
1015+    int maxLoops = commDetectLogoSamplesNeeded;
1016+    EdgeMaskEntry *edgeCounts;
1017+    unsigned int pos, i, x, y, dx, dy;
1018+    int edgeDiffs[] = {5, 7, 10, 15, 20, 30, 40, 50, 60, 0 };
1019+
1020+
1021+    VERBOSE(VB_COMMFLAG, "Searching for Station Logo");
1022+
1023+    logoInfoAvailable = false;
1024+
1025+    edgeCounts = new EdgeMaskEntry[width * height];
1026+
1027+    for (i = 0; edgeDiffs[i] != 0 && !logoInfoAvailable; i++)
1028+    {
1029+        int pixelsInMask = 0;
1030+
1031+        VERBOSE(VB_COMMFLAG, QString("Trying with edgeDiff == %1")
1032+                .arg(edgeDiffs[i]));
1033+
1034+        memset(edgeCounts, 0, sizeof(EdgeMaskEntry) * width * height);
1035+        memset(edgeMask, 0, sizeof(EdgeMaskEntry) * width * height);
1036+
1037+        nvp->DiscardVideoFrame(nvp->GetRawVideoFrame(0));
1038+
1039+        loops = 0;
1040+        seekFrame = commDetector->preRoll + seekIncrement;
1041+        while(loops < maxLoops && !nvp->GetEof())
1042+        {
1043+            VideoFrame* vf = nvp->GetRawVideoFrame(seekFrame);
1044+
1045+            if ((loops % 50) == 0)
1046+                commDetector->logoDetectorBreathe();
1047+
1048+            if (commDetector->m_bStop)
1049+            {
1050+                nvp->DiscardVideoFrame(vf);
1051+                return false;
1052+            }
1053+
1054+            if (!commDetector->fullSpeed)
1055+                usleep(10000);
1056+
1057+            DetectEdges(vf, edgeCounts, edgeDiffs[i]);
1058+
1059+            seekFrame += seekIncrement;
1060+            loops++;
1061+
1062+            nvp->DiscardVideoFrame(vf);
1063+        }
1064+
1065+        VERBOSE(VB_COMMFLAG, "Analyzing edge data");
1066+
1067+#ifdef SHOW_DEBUG_WIN
1068+        unsigned char *fakeFrame;
1069+        fakeFrame = new unsigned char[width * height * 3 / 2];
1070+        memset(fakeFrame, 0, width * height * 3 / 2);
1071+#endif
1072+
1073+ for (y = 0; y < height; y++)
1074+        {
1075+            if ((y > (height/4)) && (y < (height * 3 / 4)))
1076+                continue;
1077+
1078+            for (x = 0; x < width; x++)
1079+            {
1080+                if ((x > (width/4)) && (x < (width * 3 / 4)))
1081+                    continue;
1082+
1083+                pos = y * width + x;
1084+
1085+                if (edgeCounts[pos].isedge > (maxLoops * 0.66))
1086+                {
1087+                    edgeMask[pos].isedge = 1;
1088+                    pixelsInMask++;
1089+#ifdef SHOW_DEBUG_WIN
1090+                    fakeFrame[pos] = 0xff;
1091+#endif
1092+
1093+                }
1094+
1095+                if (edgeCounts[pos].horiz > (maxLoops * 0.66))
1096+                    edgeMask[pos].horiz = 1;
1097+
1098+                if (edgeCounts[pos].vert > (maxLoops * 0.66))
1099+                    edgeMask[pos].vert = 1;
1100+
1101+                if (edgeCounts[pos].ldiag > (maxLoops * 0.66))
1102+                    edgeMask[pos].ldiag = 1;
1103+                if (edgeCounts[pos].rdiag > (maxLoops * 0.66))
1104+                    edgeMask[pos].rdiag = 1;
1105+            }
1106+        }
1107+
1108+        SetLogoMaskArea();
1109+
1110+        for (y = logoMinY; y < logoMaxY; y++)
1111+        {
1112+            for (x = logoMinX; x < logoMaxX; x++)
1113+            {
1114+                int neighbors = 0;
1115+
1116+                if (!edgeMask[y * width + x].isedge)
1117+                    continue;
1118+
1119+                for (dy = y - 2; dy <= (y + 2); dy++ )
1120+                {
1121+                    for (dx = x - 2; dx <= (x + 2); dx++ )
1122+                    {
1123+                        if (edgeMask[dy * width + dx].isedge)
1124+                            neighbors++;
1125+                    }
1126+                }
1127+
1128+                if (neighbors < 5)
1129+                    edgeMask[y * width + x].isedge = 0;
1130+            }
1131+        }
1132+
1133+        SetLogoMaskArea();
1134+        VERBOSE(VB_COMMFLAG, QString("Testing Logo area: topleft "
1135+                                     "(%1,%2), bottomright (%3,%4)")
1136+                                     .arg(logoMinX).arg(logoMinY)
1137+                                     .arg(logoMaxX).arg(logoMaxY));
1138+
1139+#ifdef SHOW_DEBUG_WIN
1140+        for (x = logoMinX; x < logoMaxX; x++)
1141+        {
1142+            pos = logoMinY * width + x;
1143+            fakeFrame[pos] = 0x7f;
1144+            pos = logoMaxY * width + x;
1145+            fakeFrame[pos] = 0x7f;
1146+        }
1147+        for (y = logoMinY; y < logoMaxY; y++)
1148+        {
1149+            pos = y * width + logoMinX;
1150+            fakeFrame[pos] = 0x7f;
1151+            pos = y * width + logoMaxX;
1152+            fakeFrame[pos] = 0x7f;
1153+        }
1154+
1155+        comm_debug_show(fakeFrame);
1156+        delete [] fakeFrame;
1157+
1158+        cerr << "Hit ENTER to continue" << endl;
1159+        getchar();
1160+#endif
1161+       if (((logoMaxX - logoMinX) < (width / 4)) &&
1162+            ((logoMaxY - logoMinY) < (height / 4)) &&
1163+            (pixelsInMask > 50))
1164+        {
1165+            logoInfoAvailable = true;
1166+            logoEdgeDiff = edgeDiffs[i];
1167+
1168+            VERBOSE(VB_COMMFLAG, QString("Using Logo area: topleft "
1169+                                         "(%1,%2), bottomright (%3,%4)")
1170+                    .arg(logoMinX).arg(logoMinY)
1171+                    .arg(logoMaxX).arg(logoMaxY));
1172+        }
1173+        else
1174+        {
1175+            VERBOSE(VB_COMMFLAG, QString("Rejecting Logo area: topleft "
1176+                                         "(%1,%2), bottomright (%3,%4), "
1177+                                         "pixelsInMask (%5). "
1178+                                         "Not within specified limits.")
1179+                    .arg(logoMinX).arg(logoMinY)
1180+                    .arg(logoMaxX).arg(logoMaxY)
1181+                    .arg(pixelsInMask));
1182+        }
1183+    }
1184+
1185+    delete [] edgeCounts;
1186+
1187+    if (!logoInfoAvailable)
1188+        VERBOSE(VB_COMMFLAG, "No suitable logo area found.");
1189+
1190+    nvp->DiscardVideoFrame(nvp->GetRawVideoFrame(0));
1191+    return logoInfoAvailable;
1192+}
1193+
1194+
1195+void ClassicLogoDetector::SetLogoMaskArea()
1196+{
1197+    VERBOSE(VB_COMMFLAG, "SetLogoMaskArea()");
1198+
1199+    logoMinX = width - 1;
1200+    logoMaxX = 0;
1201+    logoMinY = height - 1;
1202+    logoMaxY = 0;
1203+
1204+    for (unsigned int y = 0; y < height; y++)
1205+    {
1206+        for (unsigned int x = 0; x < width; x++)
1207+        {
1208+            if (edgeMask[y * width + x].isedge)
1209+            {
1210+                if (x < logoMinX)
1211+                    logoMinX = x;
1212+                if (y < logoMinY)
1213+                    logoMinY = y;
1214+                if (x > logoMaxX)
1215+                    logoMaxX = x;
1216+                if (y > logoMaxY)
1217+                    logoMaxY = y;
1218+            }
1219+        }
1220+    }
1221+
1222+    logoMinX -= 5;
1223+    logoMaxX += 5;
1224+    logoMinY -= 5;
1225+    logoMaxY += 5;
1226+
1227+    if (logoMinX < 4)
1228+        logoMinX = 4;
1229+    if (logoMaxX > (width-5))
1230+        logoMaxX = (width-5);
1231+    if (logoMinY < 4)
1232+        logoMinY = 4;
1233+    if (logoMaxY > (height-5))
1234+        logoMaxY = (height-5);
1235+}
1236+
1237+void ClassicLogoDetector::SetLogoMask(unsigned char *mask)
1238+{
1239+    int pixels = 0;
1240+
1241+    memcpy(logoMask, mask, width * height);
1242+
1243+    SetLogoMaskArea();
1244+
1245+    for(unsigned int y = logoMinY; y <= logoMaxY; y++)
1246+        for(unsigned int x = logoMinX; x <= logoMaxX; x++)
1247+            if (!logoMask[y * width + x] == 1)
1248+                pixels++;
1249+
1250+    if (pixels < 30)
1251+        return;
1252+
1253+    // set the pixels around our logo
1254+    for(unsigned int y = (logoMinY - 1); y <= (logoMaxY + 1); y++)
1255+    {
1256+        for(unsigned int x = (logoMinX - 1); x <= (logoMaxX + 1); x++)
1257+        {
1258+            if (!logoMask[y * width + x])
1259+            {
1260+                for (unsigned int y2 = y - 1; y2 <= (y + 1); y2++)
1261+                {
1262+                    for (unsigned int x2 = x - 1; x2 <= (x + 1); x2++)
1263+                    {
1264+                        if ((logoMask[y2 * width + x2] == 1) &&
1265+                            (!logoMask[y * width + x]))
1266+                        {
1267+                            logoMask[y * width + x] = 2;
1268+                            x2 = x + 2;
1269+                            y2 = y + 2;
1270+
1271+                            logoCheckMask[y2 * width + x2] = 1;
1272+                            logoCheckMask[y * width + x] = 1;
1273+                        }
1274+                    }
1275+                }
1276+            }
1277+        }
1278+    }
1279+    for(unsigned int y = (logoMinY - 2); y <= (logoMaxY + 2); y++)
1280+    {
1281+        for(unsigned int x = (logoMinX - 2); x <= (logoMaxX + 2); x++)
1282+        {
1283+            if (!logoMask[y * width + x])
1284+            {
1285+                for (unsigned int y2 = y - 1; y2 <= (y + 1); y2++)
1286+                {
1287+                    for (unsigned int x2 = x - 1; x2 <= (x + 1); x2++)
1288+                    {
1289+                        if ((logoMask[y2 * width + x2] == 2) &&
1290+                            (!logoMask[y * width + x]))
1291+                        {
1292+                            logoMask[y * width + x] = 3;
1293+                            x2 = x + 2;
1294+                            y2 = y + 2;
1295+
1296+                            logoCheckMask[y * width + x] = 1;
1297+                        }
1298+                    }
1299+                }
1300+            }
1301+        }
1302+    }
1303+
1304+#ifdef SHOW_DEBUG_WIN
1305+    DumpLogo(true,framePtr);
1306+#endif
1307+
1308+    logoFrameCount = 0;
1309+    logoInfoAvailable = true;
1310+}
1311+
1312+
1313+void ClassicLogoDetector::DumpLogo(bool fromCurrentFrame, unsigned char* framePtr)
1314+{
1315+    char scrPixels[] = " .oxX";
1316+
1317+    if (!logoInfoAvailable)
1318+        return;
1319+
1320+    cerr << "\nLogo Data ";
1321+    if (fromCurrentFrame)
1322+        cerr << "from current frame\n";
1323+
1324+    cerr << "\n     ";
1325+
1326+    for(unsigned int x = logoMinX - 2; x <= (logoMaxX + 2); x++)
1327+        cerr << (x % 10);
1328+    cerr << "\n";
1329+
1330+    for(unsigned int y = logoMinY - 2; y <= (logoMaxY + 2); y++)
1331+    {
1332+        cerr << QString::number(y).rightJustify(3, ' ') << ": ";
1333+        for(unsigned int x = logoMinX - 2; x <= (logoMaxX + 2); x++)
1334+        {
1335+            if (fromCurrentFrame)
1336+            {
1337+                cerr << scrPixels[framePtr[y * width + x] / 50];
1338+            }
1339+            else
1340+            {
1341+                switch (logoMask[y * width + x])
1342+                {
1343+                        case 0:
1344+                        case 2: cerr << " ";
1345+                        break;
1346+                        case 1: cerr << "*";
1347+                        break;
1348+                        case 3: cerr << ".";
1349+                        break;
1350+                }
1351+            }
1352+        }
1353+        cerr << "\n";
1354+    }
1355+    cerr.flush();
1356+}
1357+
1358+
1359+/* ideas for this method ported back from comskip.c mods by Jere Jones
1360+ * which are partially mods based on Myth's original commercial skip
1361+ * code written by Chris Pinkham. */
1362+bool ClassicLogoDetector::doesThisFrameContainTheFoundLogo(unsigned char* framePtr)
1363+{
1364+    int radius = 2;
1365+    unsigned int x, y;
1366+    int pos1, pos2, pos3;
1367+    int pixel;
1368+    int goodEdges = 0;
1369+    int badEdges = 0;
1370+    int testEdges = 0;
1371+    int testNotEdges = 0;
1372+
1373+    for (y = logoMinY; y <= logoMaxY; y++ )
1374+    {
1375+        for (x = logoMinX; x <= logoMaxX; x++ )
1376+        {
1377+            pos1 = y * width + x;
1378+            pos2 = (y - radius) * width + x;
1379+            pos3 = (y + radius) * width + x;
1380+
1381+            pixel = framePtr[pos1];
1382+
1383+            if (edgeMask[pos1].horiz)
1384+            {
1385+                if ((abs(framePtr[pos1 - radius] - pixel) >= logoEdgeDiff) ||
1386+                    (abs(framePtr[pos1 + radius] - pixel) >= logoEdgeDiff))
1387+                    goodEdges++;
1388+                testEdges++;
1389+            }
1390+            else
1391+            {
1392+                if ((abs(framePtr[pos1 - radius] - pixel) >= logoEdgeDiff) ||
1393+                    (abs(framePtr[pos1 + radius] - pixel) >= logoEdgeDiff))
1394+                    badEdges++;
1395+                testNotEdges++;
1396+            }
1397+
1398+            if (edgeMask[pos1].vert)
1399+            {
1400+                if ((abs(framePtr[pos2] - pixel) >= logoEdgeDiff) ||
1401+                    (abs(framePtr[pos3] - pixel) >= logoEdgeDiff))
1402+                    goodEdges++;
1403+                testEdges++;
1404+            }
1405+            else
1406+            {
1407+                if ((abs(framePtr[pos2] - pixel) >= logoEdgeDiff) ||
1408+                    (abs(framePtr[pos3] - pixel) >= logoEdgeDiff))
1409+                    badEdges++;
1410+                testNotEdges++;
1411+            }
1412+        }
1413+    }
1414+
1415+    frameNumber++;
1416+    double goodEdgeRatio = (double)goodEdges / (double)testEdges;
1417+    double badEdgeRatio = (double)badEdges / (double)testNotEdges;
1418+    if ((goodEdgeRatio > commDetectLogoGoodEdgeThreshold) &&
1419+        (badEdgeRatio < commDetectLogoBadEdgeThreshold))
1420+        return true;
1421+    else
1422+        return false;
1423+}
1424+
1425+bool ClassicLogoDetector::pixelInsideLogo(unsigned int x, unsigned int y)
1426+{
1427+    if (!logoInfoAvailable) return false;
1428+    return ((x > logoMinX) && (x < logoMaxX) && (y > logoMinY) && (y < logoMaxY));
1429+}
1430+
1431+void ClassicLogoDetector::DetectEdges(VideoFrame *frame, EdgeMaskEntry *edges,
1432+                                      int edgeDiff)
1433+{
1434+    int r = 2;
1435+    unsigned char *buf = frame->buf;
1436+    unsigned char p;
1437+    unsigned int pos, x, y;
1438+
1439+    for (y = commDetectBorder + r; y < (height - commDetectBorder - r); y++)
1440+    {
1441+        if ((y > (height/4)) && (y < (height * 3 / 4)))
1442+            continue;
1443+
1444+        for (x = commDetectBorder + r; x < (width - commDetectBorder - r); x++)
1445+        {
1446+            int edgeCount = 0;
1447+
1448+            if ((x > (width/4)) && (x < (width * 3 / 4)))
1449+                continue;
1450+
1451+            pos = y * width + x;
1452+            p = buf[pos];
1453+
1454+            if (( abs(buf[y * width + (x - r)] - p) >= edgeDiff) ||
1455+                ( abs(buf[y * width + (x + r)] - p) >= edgeDiff))
1456+            {
1457+                edges[pos].horiz++;
1458+                edgeCount++;
1459+            }
1460+            if (( abs(buf[(y - r) * width + x] - p) >= edgeDiff) ||
1461+                ( abs(buf[(y + r) * width + x] - p) >= edgeDiff))
1462+            {
1463+                edges[pos].vert++;
1464+                edgeCount++;
1465+            }
1466+
1467+            if (( abs(buf[(y - r) * width + (x - r)] - p) >= edgeDiff) ||
1468+                ( abs(buf[(y + r) * width + (x + r)] - p) >= edgeDiff))
1469+            {
1470+                edges[pos].ldiag++;
1471+                edgeCount++;
1472+            }
1473+
1474+            if (( abs(buf[(y - r) * width + (x + r)] - p) >= edgeDiff) ||
1475+                ( abs(buf[(y + r) * width + (x - r)] - p) >= edgeDiff))
1476+            {
1477+                edges[pos].rdiag++;
1478+                edgeCount++;
1479+            }
1480+
1481+            if (edgeCount >= 3)
1482+                edges[pos].isedge++;
1483+        }
1484+    }
1485+}
1486+