diff options
-rw-r--r-- | global.h | 10 | ||||
-rw-r--r-- | logos/S19.2E-1-1089-12003-A16:9.pgm | bin | 0 -> 10518 bytes | |||
-rw-r--r-- | logos/S19.2E-1-1089-12060-A16:9.pgm | bin | 0 -> 10218 bytes | |||
-rw-r--r-- | markad-standalone.cpp | 119 | ||||
-rw-r--r-- | markad-standalone.h | 2 | ||||
-rw-r--r-- | recv.cpp | 1 | ||||
-rw-r--r-- | video.cpp | 441 | ||||
-rw-r--r-- | video.h | 71 |
8 files changed, 419 insertions, 225 deletions
@@ -49,8 +49,18 @@ typedef struct MarkAdPid typedef struct MarkAdContext { + char *LogoDir; // Logo Directory, default /var/lib/markad + + struct StandAlone + { + int LogoExtraction; + int LogoWidth; + int LogoHeight; + } StandAlone; + struct General { + char *ChannelID; MarkAdPid VPid; MarkAdPid APid; MarkAdPid DPid; diff --git a/logos/S19.2E-1-1089-12003-A16:9.pgm b/logos/S19.2E-1-1089-12003-A16:9.pgm Binary files differnew file mode 100644 index 0000000..d47aa76 --- /dev/null +++ b/logos/S19.2E-1-1089-12003-A16:9.pgm diff --git a/logos/S19.2E-1-1089-12060-A16:9.pgm b/logos/S19.2E-1-1089-12060-A16:9.pgm Binary files differnew file mode 100644 index 0000000..85596d3 --- /dev/null +++ b/logos/S19.2E-1-1089-12060-A16:9.pgm diff --git a/markad-standalone.cpp b/markad-standalone.cpp index 3537ecb..ad2edc5 100644 --- a/markad-standalone.cpp +++ b/markad-standalone.cpp @@ -11,6 +11,10 @@ cMarkAdStandalone *cmasta=NULL; int SysLogLevel=2; char markFileName[1024]=""; +char logoDirectory[1024]=""; +int logoExtraction=-1; +int logoWidth=-1; +int logoHeight=-1; void syslog_with_tid(int priority, const char *format, ...) { @@ -252,6 +256,41 @@ void cMarkAdStandalone::Process(const char *Directory) } } +bool cMarkAdStandalone::LoadInfo(const char *Directory) +{ + char *buf; + if (isTS) + { + if (asprintf(&buf,"%s/info",Directory)==-1) return false; + } + else + { + if (asprintf(&buf,"%s/info.vdr",Directory)==-1) return false; + } + + FILE *f; + f=fopen(buf,"r"); + if (!f) + { + free(buf); + return false; + } + + int result=fscanf(f,"%*c %as %*s",&macontext.General.ChannelID); + fclose(f); + free(buf); + if (result==0 || result==EOF) + { + macontext.General.ChannelID=NULL; + return false; + } + else + { + return true; + } + +} + bool cMarkAdStandalone::CheckTS(const char *Directory) { MaxFiles=0; @@ -405,6 +444,11 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory) noticeVDR_AC3=false; memset(&macontext,0,sizeof(macontext)); + macontext.LogoDir=logoDirectory; + macontext.StandAlone.LogoExtraction=logoExtraction; + macontext.StandAlone.LogoWidth=logoWidth; + macontext.StandAlone.LogoHeight=logoHeight; + macontext.General.DPid.Type=MARKAD_PIDTYPE_AUDIO_AC3; macontext.General.APid.Type=MARKAD_PIDTYPE_AUDIO_MP2; @@ -480,6 +524,11 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory) if (!abort) { + if (!LoadInfo(Directory)) + { + esyslog("markad [%i]: failed loading info - logo detection impossible",recvnumber); + } + decoder = new cMarkAdDecoder(recvnumber,macontext.General.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264, macontext.General.APid.Num!=0,macontext.General.DPid.Num!=0); video = new cMarkAdVideo(recvnumber,&macontext); @@ -499,6 +548,7 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory) cMarkAdStandalone::~cMarkAdStandalone() { + if (macontext.General.ChannelID) free(macontext.General.ChannelID); if (video_demux) delete video_demux; if (ac3_demux) delete ac3_demux; if (mp2_demux) delete mp2_demux; @@ -527,13 +577,21 @@ int usage() "-b --background\n" " markad runs as a background-process\n" " this will be automatically set if called with \"after\"\n" - "-p, --priority\n" + "-l --logocachedir\n" + " directory where logos stored, default /var/lib/markad\n" + "-p, --priority level=<priority>\n" " priority-level of markad when running in background\n" - " [19...-19] default 19\n" + " <19...-19> default 19\n" "-v, --verbose\n" " increments loglevel by one, can be given multiple times\n" "-B --backupmarks\n" " make a backup of the existing marks\n" + "-L --extractlogo=<direction>[,width[,height]]\n" + " extracts logo to /tmp as pgm files (must be renamed)\n" + " <direction> 0 = top left, 1 = top right\n" + " 2 = bottom left, 3 = bottom right\n" + " [width] range from 50 to %i, default 192\n" + " [height] range from 20 to %i, default 100\n" "-O, --OSD\n" " markad sends an OSD-Message for start and end\n" "-V --version\n" @@ -547,7 +605,7 @@ int usage() "edited markad exits immediately if called with \"edited\"\n" "nice runs markad with nice(19)\n" "\n<record> is the name of the directory where the recording\n" - " is stored\n\n" + " is stored\n\n",LOGO_MAXWIDTH,LOGO_MAXHEIGHT ); return -1; } @@ -573,6 +631,10 @@ int main(int argc, char *argv[]) bool bAfter=false,bBefore=false,bEdited=false,bFork=false,bNice=false,bImmediateCall=false; int niceLevel = 19; char *recDir=NULL; + char *tok,*str; + int ntok; + + strcpy(logoDirectory,"/var/lib/markad"); while (1) { @@ -582,6 +644,7 @@ int main(int argc, char *argv[]) {"statisticfile",1,0,'s' }, {"logocachedir", 1, 0, 'l'}, + {"extractlogo", 1, 0, 'L'}, {"verbose", 0, 0, 'v'}, {"background", 0, 0, 'b'}, {"priority",1,0,'p'}, @@ -605,7 +668,7 @@ int main(int argc, char *argv[]) {0, 0, 0, 0} }; - c = getopt_long (argc, argv, "s:l:vbp:cjoaOSBCV", + c = getopt_long (argc, argv, "s:l:vbp:cjoaOSBCVL:", long_options, &option_index); if (c == -1) break; @@ -645,8 +708,54 @@ int main(int argc, char *argv[]) // --overlap break; - case 's': case 'l': + strncpy(logoDirectory,optarg,1024); + logoDirectory[1023]=0; + break; + + case 'L': + str=optarg; + ntok=0; + while (tok=strtok(str,",")) + { + switch (ntok) + { + case 0: + logoExtraction=atoi(tok); + if ((logoExtraction<0) || (logoExtraction>3)) + { + fprintf(stderr, "markad: invalid extractlogo value: %s\n", tok); + return 2; + } + break; + + case 1: + logoWidth=atoi(tok); + if ((logoWidth<50) || (logoWidth>LOGO_MAXWIDTH)) + { + fprintf(stderr, "markad: invalid width value: %s\n", tok); + return 2; + } + break; + + case 2: + logoHeight=atoi(tok); + if ((logoHeight<20) || (logoHeight>LOGO_MAXHEIGHT)) + { + fprintf(stderr, "markad: invalid height value: %s\n", tok); + return 2; + } + break; + + default: + break; + } + str=NULL; + ntok++; + } + break; + + case 's': case 'c': case 'j': case 'a': diff --git a/markad-standalone.h b/markad-standalone.h index fcde1fa..3323fec 100644 --- a/markad-standalone.h +++ b/markad-standalone.h @@ -162,8 +162,10 @@ unsigned Descriptor_Length: void SaveFrame(int Frame); char *IndexToHMSF(int Index); void AddMark(MarkAdMark *Mark); + bool CheckPATPMT(const char *Directory); bool CheckTS(const char *Directory); + bool LoadInfo(const char *Directory); bool ProcessFile(const char *Directory, int Number); public: @@ -37,6 +37,7 @@ cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *T buffer.SetTimeouts(0, 10); memset(&macontext,0,sizeof(macontext)); + macontext.StandAlone.LogoExtraction=-1; // we are not standalone ;) macontext.General.VPid.Num=Timer->Channel()->Vpid(); #if APIVERSNUM > 10700 @@ -11,8 +11,10 @@ cMarkAdLogo::cMarkAdLogo(int RecvNumber, MarkAdContext *maContext) { macontext=maContext; + recvnumber=RecvNumber; // 3x3 GX Sobel mask + GX[0][0] = -1; GX[0][1] = 0; GX[0][2] = 1; @@ -36,61 +38,92 @@ cMarkAdLogo::cMarkAdLogo(int RecvNumber, MarkAdContext *maContext) memset(&area,0,sizeof(area)); - area[TOP_LEFT].init=true; - area[TOP_RIGHT].init=true; - area[BOTTOM_LEFT].init=true; - area[BOTTOM_RIGHT].init=true; - - LOGOHEIGHT=100; - LOGOWIDTH=192; + LOGOHEIGHT=LOGO_DEFHEIGHT; + LOGOWIDTH=LOGO_DEFWIDTH; - framecnt=0; - savedlastiframe=-1; - logostart=-1; - logostate=-1; - counter=0; + area.status=UNINITIALIZED; } cMarkAdLogo::~cMarkAdLogo() { } -void cMarkAdLogo::SaveLogo(int corner, int lastiframe) +int cMarkAdLogo::Load(char *file) { - if (!macontext) return; - if (!macontext->Video.Info.Width) return; - + // Load mask FILE *pFile; - char szFilename[32]; + area.valid=false; + area.corner=-1; + pFile=fopen(file, "rb"); + if (!pFile) return -1; - // Open file - sprintf(szFilename, "%iframe%06d.pgm", corner,lastiframe); - pFile=fopen(szFilename, "wb"); - if (pFile==NULL) - return; + fscanf(pFile, "P5\n#C%i\n%d %d\n255\n#", &area.corner,&LOGOWIDTH,&LOGOHEIGHT); - // Write header - fprintf(pFile, "P5\n%d %d\n255\n", LOGOWIDTH,LOGOHEIGHT); + if ((LOGOWIDTH<=0) || (LOGOHEIGHT<=0) || (LOGOWIDTH>LOGO_MAXWIDTH) || (LOGOHEIGHT>LOGO_MAXHEIGHT) || + (area.corner<TOP_LEFT) || (area.corner>BOTTOM_RIGHT)) + { + fclose(pFile); + return -2; + } + + fread(&area.mask,1,LOGOWIDTH*LOGOHEIGHT,pFile); + + for (int i=0; i<LOGOWIDTH*LOGOHEIGHT; i++) + { + if (!area.mask[i]) area.mpixel++; + } - // Write pixel data - fwrite(area[corner].plane,1,LOGOWIDTH*LOGOHEIGHT,pFile); - // Close file fclose(pFile); + area.valid=true; + return 0; } -void cMarkAdLogo::CheckCorner(int corner) + + +void cMarkAdLogo::Save(int lastiframe, uchar *picture) { if (!macontext) return; - if (!macontext->Video.Info.Width) return; - if (!macontext->Video.Info.Height) return; - if (!macontext->Video.Data.Valid) return; - if (corner>BOTTOM_RIGHT) return; - if (corner<TOP_LEFT) return; + + char *buf=NULL; + if (asprintf(&buf,"%s/%06d-%s-A%i:%i.pgm","/tmp/",lastiframe, + macontext->General.ChannelID, + area.aspectratio.Num,area.aspectratio.Den)!=-1) + { + // Open file + FILE *pFile=fopen(buf, "wb"); + if (pFile==NULL) + { + free(buf); + return; + } + + // Write header + fprintf(pFile, "P5\n#C%i\n%d %d\n255\n", area.corner, LOGOWIDTH,LOGOHEIGHT); + + // Write pixel data + fwrite(picture,1,LOGOWIDTH*LOGOHEIGHT,pFile); + // Close file + fclose(pFile); + free(buf); + } +} + +int cMarkAdLogo::Detect(int lastiframe, int *logoiframe) +{ + // Detection is made with Sobel-Operator + + if (!macontext) return 0; + if (!macontext->Video.Info.Width) return 0; + if (!macontext->Video.Info.Height) return 0; + if (!macontext->Video.Data.Valid) return 0; + + if (area.corner>BOTTOM_RIGHT) return 0; + if (area.corner<TOP_LEFT) return 0; int xstart,xend,ystart,yend; - switch (corner) + switch (area.corner) { case TOP_LEFT: xstart=0; @@ -117,199 +150,230 @@ void cMarkAdLogo::CheckCorner(int corner) yend=macontext->Video.Info.Height; break; default: - return; + return 0; } - int SUM; - int sumX,sumY; - area[corner].blackpixel=0; + long SUMA=0; for (int Y=ystart; Y<=yend-1; Y++) { for (int X=xstart; X<=xend-1; X++) { - sumX=0; - sumY=0; - - // image boundaries - if (Y<(ystart+15) || Y>(yend-15)) - SUM=0; - else if (X<(xstart+15) || X>(xend-15)) - SUM=0; - // convolution starts here - else + area.source[(X-xstart)+(Y-ystart)*LOGOWIDTH]=macontext->Video.Data.Plane[0][X+(Y*macontext->Video.Info.Width)]; + SUMA+=area.source[(X-xstart)+(Y-ystart)*LOGOWIDTH]; + } + } + SUMA/=(LOGOWIDTH*LOGOHEIGHT); +#if 0 + if (SUMA>=100) + { + + int avg=255-(int) SUMA; + printf("SUMA =%li, avg=%i\n", SUMA,avg); + SUMA=0; + for (int Y=ystart; Y<=yend-1; Y++) + { + for (int X=xstart; X<=xend-1; X++) { - // X Gradient approximation - for (int I=-1; I<=1; I++) + int val=macontext->Video.Data.Plane[0][X+(Y*macontext->Video.Info.Width)]; + val=(val - avg); + if (val<0) val=0; + area.source[(X-xstart)+(Y-ystart)*LOGOWIDTH]=val; + SUMA+=val; + } + } + SUMA/=(LOGOWIDTH*LOGOHEIGHT); + printf("SUMA now =%li\n", SUMA); + } +#endif + + int ret=NOCHANGE; + + if (SUMA<100) + { + + int SUM; + int sumX,sumY; + area.rpixel=0; + for (int Y=ystart; Y<=yend-1; Y++) + { + for (int X=xstart; X<=xend-1; X++) + { + sumX=0; + sumY=0; + + // image boundaries + if (Y<(ystart+15) || Y>(yend-15)) + SUM=0; + else if (X<(xstart+15) || X>(xend-15)) + SUM=0; + // convolution starts here + else { - for (int J=-1; J<=1; J++) + // X Gradient approximation + for (int I=-1; I<=1; I++) { - sumX=sumX+ (int) ((*(macontext->Video.Data.Plane[0]+X+I+ - (Y+J)*macontext->Video.Info.Width))*GX[I+1][J+1]); + for (int J=-1; J<=1; J++) + { + sumX=sumX+ (int) ((*(macontext->Video.Data.Plane[0]+X+I+ + (Y+J)*macontext->Video.Info.Width))*GX[I+1][J+1]); + } } - } - // Y Gradient approximation - for (int I=-1; I<=1; I++) - { - for (int J=-1; J<=1; J++) + // Y Gradient approximation + for (int I=-1; I<=1; I++) { - sumY=sumY+ (int) ((*(macontext->Video.Data.Plane[0]+X+I+ - (Y+J)*macontext->Video.Info.Width))*GY[I+1][J+1]); + for (int J=-1; J<=1; J++) + { + sumY=sumY+ (int) ((*(macontext->Video.Data.Plane[0]+X+I+ + (Y+J)*macontext->Video.Info.Width))*GY[I+1][J+1]); + } } + + // Gradient Magnitude approximation + SUM = abs(sumX) + abs(sumY); } - // Gradient Magnitude approximation - SUM = abs(sumX) + abs(sumY); - } + if (SUM>=127) SUM=255; + if (SUM<127) SUM=0; + + int val = 255-(uchar) SUM; + + area.sobel[(X-xstart)+(Y-ystart)*LOGOWIDTH]=val; - if (SUM>=127) SUM=255; - if (SUM<127) SUM=0; + area.result[(X-xstart)+(Y-ystart)*LOGOWIDTH]=(area.mask[(X-xstart)+(Y-ystart)*LOGOWIDTH] + val) & 255; - int val = 255-(uchar) SUM; + if (!area.result[(X-xstart)+(Y-ystart)*LOGOWIDTH]) area.rpixel++; - if (area[corner].init) + } + } + if (macontext->StandAlone.LogoExtraction==-1) + { + if (area.status==UNINITIALIZED) { - area[corner].plane[(X-xstart)+(Y-ystart)*LOGOWIDTH]=val; + // Initialize + if (area.rpixel>(area.mpixel*0.4)) + { + area.status=LOGO; + } + else + { + area.status=NOLOGO; + } } - else + + if (area.rpixel>=(area.mpixel*0.4)) { - if (area[corner].plane[(X-xstart)+(Y-ystart)*LOGOWIDTH]!=val) + if (area.status==NOLOGO) { - area[corner].plane[(X-xstart)+(Y-ystart)*LOGOWIDTH]=255; + if (area.counter>LOGO_MAXCOUNT) + { + area.status=ret=LOGO; + *logoiframe=area.lastiframe; + area.counter=0; + } + else + { + if (!area.counter) area.lastiframe=lastiframe; + area.counter++; + } + } + else + { + area.counter=0; } } - if (area[corner].plane[(X-xstart)+(Y-ystart)*LOGOWIDTH]!=255) - area[corner].blackpixel++; + if (area.rpixel<(area.mpixel*0.4)) + { + if (area.status==LOGO) + { + if (area.counter>LOGO_MAXCOUNT) + { + area.status=ret=NOLOGO; + *logoiframe=area.lastiframe; + area.counter=0; + } + else + { + if (!area.counter) area.lastiframe=lastiframe; + area.counter++; + } + } + else + { + area.counter=0; + } + } + } + else + { + Save(lastiframe,area.sobel); } - - } - area[corner].init=false; - if (area[corner].blackpixel<100) area[corner].blackpixel=0; -} - -void cMarkAdLogo::CheckCorners(int lastiframe) -{ - for (int i=TOP_LEFT; i<=BOTTOM_RIGHT; i++) - { - CheckCorner(i); -// printf("%i ",area[i].blackpixel); -// SaveLogo(i,lastiframe); - } -// printf("\n"); -} - -void cMarkAdLogo::RestartLogoDetection() -{ - for (int i=TOP_LEFT; i<=BOTTOM_RIGHT; i++) - { - area[i].init=true; -// area[i].cntfound=1; } - framecnt=0; - counter++; -} - -bool cMarkAdLogo::LogoVisible() -{ - int sum=0; - for (int i=TOP_LEFT; i<=BOTTOM_RIGHT; i++) + else { - sum+=area[i].blackpixel; + if (area.status==LOGO) area.counter=0; } - return (sum!=0); -} -/* -void cMarkAdLogo::ResetLogoDetection() -{ - for (int i=TOP_LEFT; i<=BOTTOM_RIGHT; i++) - { - area[i].init=true; - area[i].cntfound=0; - } - framecnt=0; - counter=0; -} - -bool cMarkAdLogo::LogoFound() -{ - for (int i=TOP_LEFT; i<=BOTTOM_RIGHT; i++) - { - printf("%i ",area[i].cntfound); - } - printf("\n"); - return false; + return ret; } -*/ -int cMarkAdLogo::Process(int LastIFrame) +int cMarkAdLogo::Process(int LastIFrame, int *LogoIFrame) { - if (!macontext) return 0; - if (!macontext->Video.Info.Width) return 0; - if (!macontext->Video.Data.Valid) return 0; + if (!macontext) return ERROR; + if (!macontext->Video.Data.Valid) return ERROR; + if (!macontext->Video.Info.Width) return ERROR; + if (!macontext->LogoDir) return ERROR; + if (!macontext->General.ChannelID) return ERROR; - if ((macontext->Video.Info.Width>720) && (LOGOWIDTH==192)) + if (macontext->StandAlone.LogoExtraction==-1) { - LOGOWIDTH=288; - } - int ret=0; - CheckCorners(LastIFrame); -// if (framecnt>=250) abort(); - /* - if (framecnt>=MAXFRAMES) + if ((area.aspectratio.Num!=macontext->Video.Info.AspectRatio.Num) || + (area.aspectratio.Den!=macontext->Video.Info.AspectRatio.Den)) { - if (logostate==-1) + area.valid=false; // just to be sure! + char *buf=NULL; + if (asprintf(&buf,"%s/%s-A%i:%i.pgm",macontext->LogoDir,macontext->General.ChannelID, + macontext->Video.Info.AspectRatio.Num,macontext->Video.Info.AspectRatio.Den)!=-1) { - if (LogoVisible()) + int ret=Load(buf); + switch (ret) { - logostate=1; - } - else - { - logostate=0; - } - printf("Initial logo state %i\n",logostate); - abort(); - } - else - { - if (!LogoVisible() && logostate==1) - { - if (logostart==-1) logostart=LastIFrame; - RestartLogoDetection(); - printf("%i\n",counter); - if (counter>=2) - { - printf("%i Logo gone\n",logostart); - logostart=-1; - counter=0; - logostate=0; - ret=-1; - } - } - if (LogoVisible() && logostate==0) - { - if (logostart==-1) logostart=LastIFrame; - RestartLogoDetection(); - printf("%i\n",counter); - if (counter>=2) - { - printf("%i Logo start\n",logostart); - logostart=-1; - counter=0; - logostate=1; - ret=1; - } + case -1: + esyslog("markad [%i]: failed to open %s",recvnumber,buf); + + break; + + case -2: + esyslog("markad [%i]: format error in %s",recvnumber,buf); + break; } + free(buf); } + area.aspectratio.Num=macontext->Video.Info.AspectRatio.Num; + area.aspectratio.Den=macontext->Video.Info.AspectRatio.Den; + } + } + else + { + area.aspectratio.Num=macontext->Video.Info.AspectRatio.Num; + area.aspectratio.Den=macontext->Video.Info.AspectRatio.Den; + area.corner=macontext->StandAlone.LogoExtraction; + if (macontext->StandAlone.LogoWidth!=-1) + { + LOGOWIDTH=macontext->StandAlone.LogoWidth; } - */ - if (savedlastiframe!=-1) framecnt+=(LastIFrame-savedlastiframe); - savedlastiframe=LastIFrame; + if (macontext->StandAlone.LogoHeight!=-1) + { + LOGOHEIGHT=macontext->StandAlone.LogoHeight; + } + area.valid=true; + } - return ret; + if (!area.valid) return ERROR; + + return Detect(LastIFrame,LogoIFrame); } cMarkAdBlackBordersHoriz::cMarkAdBlackBordersHoriz(int RecvNumber, MarkAdContext *maContext) @@ -483,13 +547,14 @@ MarkAdMark *cMarkAdVideo::Process(int LastIFrame) ResetMark(); if (!LastIFrame) return NULL; - int lret=logo->Process(LastIFrame); - if (lret!=0) + int logoiframe; + int lret=logo->Process(LastIFrame,&logoiframe); + if ((lret>=-1) && (lret!=0)) { char *buf=NULL; if (lret>0) { - if (asprintf(&buf,"detected logo start (%i)",LastIFrame)!=-1) + if (asprintf(&buf,"detected logo start (%i)",logoiframe)!=-1) { isyslog("markad [%i]: %s",recvnumber,buf); AddMark(LastIFrame,buf); @@ -498,7 +563,7 @@ MarkAdMark *cMarkAdVideo::Process(int LastIFrame) } else { - if (asprintf(&buf,"detected logo stop (%i)",LastIFrame)!=-1) + if (asprintf(&buf,"detected logo stop (%i)",logoiframe)!=-1) { isyslog("markad [%i]: %s",recvnumber,buf); AddMark(LastIFrame,buf); @@ -12,19 +12,21 @@ #include <vdr/tools.h> // needed for (d/e/i)syslog #include <time.h> +#include <math.h> +#include "global.h" -#if 1 -#include <stdio.h> -#endif +#define LOGO_MAXHEIGHT 140 +#define LOGO_MAXWIDTH 288 -#include <math.h> +#define LOGO_DEFHEIGHT 100 +#define LOGO_DEFWIDTH 192 -#include "global.h" +#define LOGO_MAXCOUNT 3 class cMarkAdLogo { private: -#define MAXFRAMES 25 + int recvnumber; enum { @@ -34,43 +36,48 @@ private: BOTTOM_RIGHT }; - int LOGOHEIGHT; // max. 100 - int LOGOWIDTH; // max. 288 - - struct area + enum { - uchar plane[28800]; - bool init; - int blackpixel; -// int cntfound; - } area[4]; + ERROR=-3, + UNINITIALIZED=-2, + NOLOGO=-1, + NOCHANGE=0, + LOGO=1 + }; - int savedlastiframe; - int framecnt; + int LOGOHEIGHT; // max. 140 + int LOGOWIDTH; // 192-288 - int logostart; +#define MAXPIXEL LOGO_MAXWIDTH*LOGO_MAXHEIGHT + struct areaT + { + uchar source[MAXPIXEL]; // original grayscale picture + uchar sobel[MAXPIXEL]; // monochrome picture with edges (after sobel) + uchar mask[MAXPIXEL]; // monochrome mask of logo + uchar result[MAXPIXEL]; // result of sobel + mask + int rpixel; // black pixel in result + int mpixel; // black pixel in mask + int status; + int lastiframe; + int counter; + int corner; + MarkAdAspectRatio aspectratio; + bool valid; + } area; + + int G[5][5]; int GX[3][3]; int GY[3][3]; - int counter; - - int logostate; MarkAdContext *macontext; - void CheckCorner(int corner); - void CheckCorners(int lastiframe); - void RestartLogoDetection(); - bool LogoVisible(); - - /* - void ResetLogoDetection(); - bool LogoFound(); - */ - void SaveLogo(int corner, int lastiframe); + int Detect(int lastiframe, int *logoiframe); // ret 1 = logo, 0 = unknown, -1 = no logo + int Load(char *file); + void Save(int lastiframe, uchar *picture); public: cMarkAdLogo(int RecvNumber, MarkAdContext *maContext); ~cMarkAdLogo(); - int Process(int LastIFrame); + int Process(int LastIFrame, int *LogoIFrame); }; class cMarkAdBlackBordersHoriz |