summaryrefslogtreecommitdiff
path: root/command
diff options
context:
space:
mode:
authorJochen Dolze <vdr@dolze.de>2012-09-28 23:25:34 +0200
committerJochen Dolze <vdr@dolze.de>2012-09-28 23:25:34 +0200
commit71bcd626abd6f79bb8521837efd94461ec811545 (patch)
tree14dbb1ae4830b630fed083f9a3d344df8c244d47 /command
parent82920ea01d29d74894dae87a868e63b8d0acb717 (diff)
downloadvdr-plugin-markad-71bcd626abd6f79bb8521837efd94461ec811545.tar.gz
vdr-plugin-markad-71bcd626abd6f79bb8521837efd94461ec811545.tar.bz2
Added speedup for decoding H264/H262
Added fix for OSD message Added fix for 'ALERT: stopping before end of broadcast' Code cleanups
Diffstat (limited to 'command')
-rw-r--r--command/decoder.cpp63
-rw-r--r--command/decoder.h1
-rw-r--r--command/demux.cpp9
-rw-r--r--command/markad-standalone.cpp141
-rw-r--r--command/markad-standalone.h5
-rw-r--r--command/video.cpp5
6 files changed, 136 insertions, 88 deletions
diff --git a/command/decoder.cpp b/command/decoder.cpp
index f9a9627..4b207a1 100644
--- a/command/decoder.cpp
+++ b/command/decoder.cpp
@@ -111,6 +111,7 @@ cMarkAdDecoder::cMarkAdDecoder(bool useH264, int Threads)
last_qscale_table=NULL;
skipframes=true;
+ addPkt=false;
noticeERRVID=false;
cpu_set_t cpumask;
@@ -177,19 +178,20 @@ cMarkAdDecoder::cMarkAdDecoder(bool useH264, int Threads)
{
if (video_codec->capabilities & CODEC_CAP_TRUNCATED)
video_context->flags|=CODEC_FLAG_TRUNCATED; // we do not send complete frames
-
+ video_context->flags|=CODEC_FLAG_LOW_DELAY;
video_context->flags2|=CODEC_FLAG2_FAST; // really?
video_context->skip_idct=AVDISCARD_ALL;
- av_log_set_level(AV_LOG_FATAL); // silence decoder output
-
- if (video_codecid==CODEC_ID_H264)
- {
- video_context->flags2|=CODEC_FLAG2_CHUNKS; // needed for H264!
- }
- else
+ if (video_codecid!=CODEC_ID_H264)
{
video_context->skip_frame=AVDISCARD_NONKEY; // just I-frames
+ } else {
+ video_context->flags2|=CODEC_FLAG2_CHUNKS;
+#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(47<<8)+0)
+ av_log_set_level(AV_LOG_FATAL); // silence decoder output
+#else
+ av_log_set_level(AV_LOG_QUIET);
+#endif
}
video_context->codec_id = video_codecid;
video_context->codec_type = AVMEDIA_TYPE_VIDEO;
@@ -384,26 +386,18 @@ bool cMarkAdDecoder::DecodeVideo(MarkAdContext *maContext,uchar *pkt, int plen)
if (!video_frame) return false;
maContext->Video.Data.Valid=false;
- if ((video_context->codec_id==CODEC_ID_H264) && (!video_context->skip_frame))
- {
- // with H264 we cannot set skip_frame just to NONKEY, is depends on Interlaced...
- if (maContext->Video.Info.Height)
- {
- if (maContext->Video.Info.Interlaced)
- {
- video_context->skip_frame=AVDISCARD_BIDIR; // just P/I-frames
- video_context->skip_loop_filter=AVDISCARD_BIDIR;
- }
- else
- {
- video_context->skip_frame=AVDISCARD_NONKEY; // just I-frames
- video_context->skip_loop_filter=AVDISCARD_NONKEY;
- }
+ if (video_context->codec_id==CODEC_ID_H264) {
+ if (plen>=5) {
+ if (((pkt[4] & 0x1F)==9) && (pkt[5]==0x10)) addPkt=true;
}
- else
- {
- return false;
+ if (!addPkt) return false;
+ }
+
+ if (video_context->codec_id==CODEC_ID_MPEG2VIDEO) {
+ if (plen>=5) {
+ if (!pkt[0] && !pkt[1] && (pkt[2]==1) && !pkt[3] && ((pkt[5] & 8)==8)) addPkt=true;
}
+ if (!addPkt) return false;
}
AVPacket avpkt;
@@ -436,6 +430,7 @@ bool cMarkAdDecoder::DecodeVideo(MarkAdContext *maContext,uchar *pkt, int plen)
{
esyslog("error decoding video");
noticeERRVID=true;
+ addPkt=false;
}
break;
}
@@ -446,20 +441,10 @@ bool cMarkAdDecoder::DecodeVideo(MarkAdContext *maContext,uchar *pkt, int plen)
}
if (video_frame_ready)
{
- if (video_context->skip_frame!=AVDISCARD_DEFAULT)
- {
- if (last_qscale_table!=video_frame->qscale_table)
- {
- if (SetVideoInfos(maContext,video_context,video_frame)) ret=true;
- last_qscale_table=video_frame->qscale_table;
- }
- }
- else
- {
- if (SetVideoInfos(maContext,video_context,video_frame)) ret=true;
- }
- break;
+ if (SetVideoInfos(maContext,video_context,video_frame)) ret=true;
}
+ if (!len) break;
}
+ if (ret) addPkt=false;
return ret;
}
diff --git a/command/decoder.h b/command/decoder.h
index 707ca56..416f74c 100644
--- a/command/decoder.h
+++ b/command/decoder.h
@@ -51,6 +51,7 @@ private:
bool SetVideoInfos(MarkAdContext *maContext,AVCodecContext *Video_Context,
AVFrame *Video_Frame);
bool noticeERRVID;
+ bool addPkt;
public:
bool DecodeVideo(MarkAdContext *maContext, uchar *pkt, int plen);
bool Clear();
diff --git a/command/demux.cpp b/command/demux.cpp
index b136d17..5e7bf86 100644
--- a/command/demux.cpp
+++ b/command/demux.cpp
@@ -602,7 +602,7 @@ void cTS2Pkt::Clear(AvPacket *Pkt)
Pkt->Type=0;
Pkt->Stream=0;
}
- sync=false;
+ firstsync=sync=false;
counter=-1;
if (queue) queue->Clear();
}
@@ -1186,7 +1186,7 @@ bool cDemux::vdraddpatpmt(uchar *data, int count)
// a picture starts @376, vdr outputs 0 (!)
int pid;
if (checkts(data,count,pid)!=0) return false;
- if ((!pid) || (pid==132))
+ if ((!pid) || (pid==132)) // 0=PAT 132=PMT
{
last_bplen=0;
vdroffset+=count;
@@ -1242,10 +1242,7 @@ int cDemux::Process(uchar *Data, int Count, AvPacket *pkt)
if ((raw) && (!Data) && (!Count))
{
uchar Dummy[6];
- if (TS)
- {
- }
- else
+ if (!TS)
{
Dummy[0]=0;
Dummy[1]=0;
diff --git a/command/markad-standalone.cpp b/command/markad-standalone.cpp
index 91ecb97..effa186 100644
--- a/command/markad-standalone.cpp
+++ b/command/markad-standalone.cpp
@@ -94,6 +94,7 @@ cOSDMessage::cOSDMessage(const char *Host, int Port)
msg=NULL;
host=strdup(Host);
port=Port;
+ send(this);
}
cOSDMessage::~cOSDMessage()
@@ -103,10 +104,14 @@ cOSDMessage::~cOSDMessage()
if (host) free((void*) host);
}
-bool cOSDMessage::readreply(int fd)
+bool cOSDMessage::readreply(int fd, char **reply)
{
usleep(400000);
char c=' ';
+ int repsize=0;
+ int msgsize=0;
+ bool skip=false;
+ if (reply) *reply=NULL;
do
{
struct pollfd fds;
@@ -118,6 +123,22 @@ bool cOSDMessage::readreply(int fd)
if (ret<=0) return false;
if (fds.revents!=POLLIN) return false;
if (read(fd,&c,1)<0) return false;
+ if ((reply) && (!skip) && (c!=10) && (c!=13)) {
+ msgsize++;
+ while ((msgsize+5)>repsize) {
+ repsize+=80;
+ char *tmp=(char *) realloc(*reply,repsize);
+ if (!tmp) {
+ free(*reply);
+ *reply=NULL;
+ skip=true;
+ } else {
+ *reply=tmp;
+ }
+ }
+ (*reply)[msgsize-1]=c;
+ (*reply)[msgsize]=0;
+ }
}
while (c!='\n');
return true;
@@ -150,21 +171,39 @@ void *cOSDMessage::send(void *posd)
return NULL;
}
- if (!osd->readreply(sock))
+ char *reply=NULL;
+ if (!osd->readreply(sock,&reply))
{
+ if (reply) free(reply);
close(sock);
return NULL;
}
ssize_t ret;
- ret=write(sock,"MESG ",5);
- if (ret!=(ssize_t)-1) ret=write(sock,osd->msg,strlen(osd->msg));
- if (ret!=(ssize_t)-1) ret=write(sock,"\r\n",2);
+ if (osd->msg) {
+ if (reply) free(reply);
+ ret=write(sock,"MESG ",5);
+ if (ret!=(ssize_t)-1) ret=write(sock,osd->msg,strlen(osd->msg));
+ if (ret!=(ssize_t)-1) ret=write(sock,"\r\n",2);
- if (!osd->readreply(sock) || (ret==(ssize_t)-1))
- {
- close(sock);
- return NULL;
+ if (!osd->readreply(sock) || (ret==(ssize_t)-1))
+ {
+ close(sock);
+ return NULL;
+ }
+ } else {
+ if (reply) {
+ char *cs=strrchr(reply,';');
+ if (cs) {
+ cs+=2;
+ trcs(cs);
+ } else {
+ trcs("UTF-8"); // just a guess
+ }
+ free(reply);
+ } else {
+ trcs("UTF-8"); // just a guess
+ }
}
ret=write(sock,"QUIT\r\n",6);
@@ -312,22 +351,28 @@ void cMarkAdStandalone::CheckStart()
macontext.Info.AspectRatio.Num=macontext.Video.Info.AspectRatio.Num;
macontext.Info.AspectRatio.Den=macontext.Video.Info.AspectRatio.Den;
- isyslog("aspectratio of %i:%i detected. %s",
- macontext.Video.Info.AspectRatio.Num,
- macontext.Video.Info.AspectRatio.Den,
- ((macontext.Video.Info.AspectRatio.Num==4) &&
- (macontext.Video.Info.AspectRatio.Den==3)) ?
- "logo/border detection disabled" : "");
+ if (macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264) {
+ isyslog("aspectratio of %i:%i detected",
+ macontext.Video.Info.AspectRatio.Num,
+ macontext.Video.Info.AspectRatio.Den);
+ } else {
+ isyslog("aspectratio of %i:%i detected%s",
+ macontext.Video.Info.AspectRatio.Num,
+ macontext.Video.Info.AspectRatio.Den,
+ ((macontext.Video.Info.AspectRatio.Num==4) &&
+ (macontext.Video.Info.AspectRatio.Den==3)) ?
+ ". logo/border detection disabled" : "");
- if ((macontext.Video.Info.AspectRatio.Num==4) &&
- (macontext.Video.Info.AspectRatio.Den==3))
- {
- bDecodeVideo=false;
- macontext.Video.Options.IgnoreLogoDetection=true;
- marks.Del(MT_CHANNELSTART);
- marks.Del(MT_CHANNELSTOP);
- // start mark must be around iStart
- begin=marks.GetAround(macontext.Video.Info.FramesPerSecond*(MAXRANGE*4),iStart,MT_ASPECTSTART);
+ if ((macontext.Video.Info.AspectRatio.Num==4) &&
+ (macontext.Video.Info.AspectRatio.Den==3))
+ {
+ bDecodeVideo=false;
+ macontext.Video.Options.IgnoreLogoDetection=true;
+ marks.Del(MT_CHANNELSTART);
+ marks.Del(MT_CHANNELSTOP);
+ // start mark must be around iStart
+ begin=marks.GetAround(macontext.Video.Info.FramesPerSecond*(MAXRANGE*4),iStart,MT_ASPECTSTART);
+ }
}
if (!bDecodeVideo)
@@ -696,6 +741,7 @@ bool cMarkAdStandalone::ProcessFile2ndPass(clMark **Mark1, clMark **Mark2,int Nu
iframe=Frame;
int actframe=Frame;
int framecounter=0;
+ int pframe=-1;
MarkAdPos *pos=NULL;
@@ -788,7 +834,7 @@ bool cMarkAdStandalone::ProcessFile2ndPass(clMark **Mark1, clMark **Mark2,int Nu
if (pn>mSTART) dRes=decoder->DecodeVideo(&macontext,pkt.Data,pkt.Length);
if (dRes)
{
- if ((actframe-iframe)<=3)
+ if (pframe!=lastiframe)
{
if (pn>mSTART) pos=video->ProcessOverlap(lastiframe,Frames,(pn==mBEFORE));
framecounter++;
@@ -800,6 +846,7 @@ bool cMarkAdStandalone::ProcessFile2ndPass(clMark **Mark1, clMark **Mark2,int Nu
close(f);
return true;
}
+ pframe=lastiframe;
}
}
tspkt+=len;
@@ -926,6 +973,8 @@ bool cMarkAdStandalone::ProcessFile(int Number)
int dataread;
dsyslog("processing file %05i",Number);
+ int pframe=-1;
+
demux->NewFile();
while ((dataread=read(f,data,datalen))>0)
{
@@ -974,7 +1023,6 @@ bool cMarkAdStandalone::ProcessFile(int Number)
{
CalculateCheckPositions(tStart*macontext.Video.Info.FramesPerSecond);
}
-
if (macontext.Config->GenIndex)
{
marks.WriteIndex(directory,isTS,demux->Offset(),macontext.Video.Info.Pict_Type,Number);
@@ -1001,12 +1049,11 @@ bool cMarkAdStandalone::ProcessFile(int Number)
dRes=true;
}
}
-
if ((decoder) && (bDecodeVideo))
dRes=decoder->DecodeVideo(&macontext,pkt.Data,pkt.Length);
if (dRes)
{
- if ((framecnt-iframe)<=3)
+ if (pframe!=lastiframe)
{
MarkAdMarks *vmarks=video->Process(lastiframe,iframe);
if (vmarks)
@@ -1017,7 +1064,6 @@ bool cMarkAdStandalone::ProcessFile(int Number)
}
}
//SaveFrame(lastiframe); // TODO: JUST FOR DEBUGGING!
-
if (iStart>0)
{
if ((inBroadCast) && (lastiframe>chkSTART)) CheckStart();
@@ -1026,6 +1072,7 @@ bool cMarkAdStandalone::ProcessFile(int Number)
{
if (lastiframe>chkSTOP) CheckStop();
}
+ pframe=lastiframe;
}
}
}
@@ -1147,7 +1194,7 @@ void cMarkAdStandalone::Process()
{
if (length && startTime)
{
- if (time(NULL)>(startTime+(time_t) length))
+ if ((time(NULL)>(startTime+(time_t) length)) || (gotendmark))
{
int iIndexError=false;
int tframecnt=macontext.Config->GenIndex ? framecnt : 0;
@@ -1425,7 +1472,7 @@ bool cMarkAdStandalone::SaveInfo()
return (err==false);
}
-time_t cMarkAdStandalone::GetBroadcastStart(time_t start, int fd)
+time_t cMarkAdStandalone::GetBroadcastStart(time_t start, int bstart, int fd)
{
// get broadcast start from atime of directory (if the volume is mounted with noatime)
struct mntent *ent;
@@ -1457,8 +1504,11 @@ time_t cMarkAdStandalone::GetBroadcastStart(time_t start, int fd)
if ((useatime) && (stat(directory,&statbuf)!=-1))
{
- isyslog("getting broadcast start from directory atime");
- return statbuf.st_atime;
+ if (fabs(difftime(start,statbuf.st_atime))<1800)
+ {
+ isyslog("getting broadcast start from directory atime");
+ return statbuf.st_atime;
+ }
}
// try to get from mtime
@@ -1490,7 +1540,9 @@ time_t cMarkAdStandalone::GetBroadcastStart(time_t start, int fd)
t.tm_sec=0;
t.tm_isdst=-1;
isyslog("getting broadcast start from directory (can be wrong)");
- return mktime(&t);
+ time_t e=mktime(&t);
+ e-=(time_t) bstart;
+ return e;
}
}
}
@@ -1541,6 +1593,7 @@ bool cMarkAdStandalone::LoadInfo()
char *line=NULL;
size_t linelen;
+ int bstart=0;
while (getline(&line,&linelen,f)!=-1)
{
if (line[0]=='C')
@@ -1586,6 +1639,16 @@ bool cMarkAdStandalone::LoadInfo()
if (cr) *cr=0;
}
}
+ if (line[0]=='@')
+ {
+ /* if we have an epgsearch line, we can assume the prestart time */
+ char *pbstart=strstr(line,"<bstart>");
+ if (pbstart) {
+ pbstart+=8;
+ bstart=atoi(pbstart);
+ if ((bstart>3600) || (bstart<0)) bstart=0;
+ }
+ }
if (line[0]=='F')
{
int fps;
@@ -1647,7 +1710,7 @@ bool cMarkAdStandalone::LoadInfo()
if ((length) && (!bIgnoreTimerInfo) && (startTime))
{
- time_t rStart=GetBroadcastStart(startTime,fileno(f));
+ time_t rStart=GetBroadcastStart(startTime,bstart,fileno(f));
if (rStart)
{
tStart=(int) (startTime-rStart);
@@ -2211,7 +2274,7 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig *
if (config->OSD)
{
osd= new cOSDMessage(config->svdrphost,config->svdrpport);
- if (osd) osd->Send("%s %s",tr("starting markad for"),ptitle);
+ if (osd) osd->Send("%s '%s'",tr("starting markad for"),ptitle);
}
else
{
@@ -2257,7 +2320,7 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig *
if (macontext.Info.ChannelName)
isyslog("channel %s",macontext.Info.ChannelName);
if (macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264)
- macontext.Video.Options.IgnoreAspectRatio=true;
+ macontext.Video.Options.IgnoreAspectRatio=true;
}
framecnt=0;
@@ -2300,11 +2363,11 @@ cMarkAdStandalone::~cMarkAdStandalone()
{
if (abort)
{
- osd->Send("%s %s",tr("markad aborted for"),ptitle);
+ osd->Send("%s '%s'",tr("markad aborted for"),ptitle);
}
else
{
- osd->Send("%s %s",tr("markad finished for"),ptitle);
+ osd->Send("%s '%s'",tr("markad finished for"),ptitle);
}
}
diff --git a/command/markad-standalone.h b/command/markad-standalone.h
index 0a339e7..b213983 100644
--- a/command/markad-standalone.h
+++ b/command/markad-standalone.h
@@ -16,6 +16,7 @@
#include "streaminfo.h"
#include "marks.h"
+#define trcs(c) bind_textdomain_codeset("markad",c)
#define tr(s) dgettext("markad",s)
#define IGNORE_VIDEOINFO 1
@@ -34,7 +35,7 @@ private:
char *msg;
pthread_t tid;
static void *send(void *osd);
- bool readreply(int fd);
+ bool readreply(int fd, char **reply=NULL);
public:
int Send(const char *format, ...);
cOSDMessage(const char *Host, int Port);
@@ -220,7 +221,7 @@ unsigned Descriptor_Length:
int skipped; // skipped bytes in whole file
bool inBroadCast; // are we in a broadcast (or ad)?
- time_t GetBroadcastStart(time_t start, int fd);
+ time_t GetBroadcastStart(time_t start, int bstart, int fd);
void CheckIndexGrowing();
char *indexFile;
int sleepcnt;
diff --git a/command/video.cpp b/command/video.cpp
index 054b66b..9b21c51 100644
--- a/command/video.cpp
+++ b/command/video.cpp
@@ -338,8 +338,9 @@ int cMarkAdLogo::Detect(int framenumber, int *logoframenumber)
if (processed==1)
{
- if ((area.intensity>100) || (area.status!=LOGO_VISIBLE) &&
- (area.intensity>180)) return LOGO_NOCHANGE;
+ // if we only have one plane we are "vulnerable"
+ // to very bright pictures, so ignore them...
+ if (area.intensity>100) return LOGO_NOCHANGE;
}
int ret=LOGO_NOCHANGE;