summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJochen Dolze <vdr@dolze.de>2010-03-09 23:10:50 +0100
committerJochen Dolze <vdr@dolze.de>2010-03-09 23:10:50 +0100
commitf64031be1c24e2a7dd7a7b02dae47dc2998e651d (patch)
treeb7c88a69d71b78ad975aed9014fee72e0407016f
parent48bbf63f913bc4c9c2cd5976ce286758a41c87b1 (diff)
downloadvdr-plugin-markad-f64031be1c24e2a7dd7a7b02dae47dc2998e651d.tar.gz
vdr-plugin-markad-f64031be1c24e2a7dd7a7b02dae47dc2998e651d.tar.bz2
Added working logo detection in standalone mode
-rw-r--r--global.h10
-rw-r--r--logos/S19.2E-1-1089-12003-A16:9.pgmbin0 -> 10518 bytes
-rw-r--r--logos/S19.2E-1-1089-12060-A16:9.pgmbin0 -> 10218 bytes
-rw-r--r--markad-standalone.cpp119
-rw-r--r--markad-standalone.h2
-rw-r--r--recv.cpp1
-rw-r--r--video.cpp441
-rw-r--r--video.h71
8 files changed, 419 insertions, 225 deletions
diff --git a/global.h b/global.h
index 8ef28fc..189613c 100644
--- a/global.h
+++ b/global.h
@@ -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
new file mode 100644
index 0000000..d47aa76
--- /dev/null
+++ b/logos/S19.2E-1-1089-12003-A16:9.pgm
Binary files differ
diff --git a/logos/S19.2E-1-1089-12060-A16:9.pgm b/logos/S19.2E-1-1089-12060-A16:9.pgm
new file mode 100644
index 0000000..85596d3
--- /dev/null
+++ b/logos/S19.2E-1-1089-12060-A16:9.pgm
Binary files differ
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:
diff --git a/recv.cpp b/recv.cpp
index 396edee..a7e99b5 100644
--- a/recv.cpp
+++ b/recv.cpp
@@ -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
diff --git a/video.cpp b/video.cpp
index 0d389e4..7fc0976 100644
--- a/video.cpp
+++ b/video.cpp
@@ -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);
diff --git a/video.h b/video.h
index 11805af..1fc6d20 100644
--- a/video.h
+++ b/video.h
@@ -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