summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--decoder.cpp21
-rw-r--r--decoder.h2
-rw-r--r--markad-standalone.cpp320
-rw-r--r--markad-standalone.h135
-rw-r--r--recv.cpp17
-rw-r--r--ts2pkt.cpp20
6 files changed, 343 insertions, 172 deletions
diff --git a/decoder.cpp b/decoder.cpp
index 029e025..12ac059 100644
--- a/decoder.cpp
+++ b/decoder.cpp
@@ -109,6 +109,8 @@ void cMarkAdDecoder::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt, in
{
if ((!maContext) || (!pkt) || (!len)) return;
+ maContext->Video.Info.Pict_Type=0;
+
if ((pkt[3] & 0x1F)==NAL_AUD)
{
switch (pkt[4] >> 5)
@@ -611,6 +613,8 @@ void cMarkAdDecoder::FindH262VideoInfos(MarkAdContext *maContext, uchar *pkt, in
{
if ((!maContext) || (!pkt) || (!len)) return;
+ maContext->Video.Info.Pict_Type=0;
+
struct H262_SequenceHdr
{
unsigned Sync1:
@@ -660,6 +664,8 @@ unsigned TemporalReferenceL:
if (pichdr->Sync1==0 && pichdr->Sync2==0 && pichdr->Sync3==1 && pichdr->Sync4==0)
{
+ if (maContext->Video.Info.Height==0) return;
+
switch (pichdr->CodingType)
{
case 1:
@@ -730,7 +736,7 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool hasAC3)
cpucount=CPU_COUNT(&cpumask);
}
- isyslog("markad [%i]: using %i threads",recvnumber,cpucount);
+ isyslog("markad [%i]: using ffmpeg with %i threads",recvnumber,cpucount);
CodecID mp2_codecid=CODEC_ID_MP2;
AVCodec *mp2_codec= avcodec_find_decoder(mp2_codecid);
@@ -1045,7 +1051,7 @@ bool cMarkAdDecoder::SetVideoInfos(MarkAdContext *maContext,AVCodecContext *Vide
}
#endif
-bool cMarkAdDecoder::DecodeVideo(MarkAdContext *maContext,uchar *pkt, int len)
+bool cMarkAdDecoder::DecodeVideo(MarkAdContext *maContext,uchar *pkt, int plen)
{
#ifdef HAVE_AVCODEC
AVPacket avpkt;
@@ -1057,7 +1063,7 @@ bool cMarkAdDecoder::DecodeVideo(MarkAdContext *maContext,uchar *pkt, int len)
avpkt.pos = -1;
#endif
avpkt.data=pkt;
- avpkt.size=len;
+ avpkt.size=plen;
// decode video
int video_frame_ready=0;
@@ -1090,7 +1096,14 @@ bool cMarkAdDecoder::DecodeVideo(MarkAdContext *maContext,uchar *pkt, int len)
}
return ret;
#else
- return true;
+ if (maContext->Video.Info.Pict_Type!=0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
#endif
}
diff --git a/decoder.h b/decoder.h
index 5bad924..2006781 100644
--- a/decoder.h
+++ b/decoder.h
@@ -71,7 +71,7 @@ private:
void FindH262VideoInfos(MarkAdContext *maContext, uchar *pkt, int len);
public:
void FindVideoInfos(MarkAdContext *maContext, uchar *pkt, int len);
- bool DecodeVideo(MarkAdContext *maContext, uchar *pkt, int len);
+ bool DecodeVideo(MarkAdContext *maContext, uchar *pkt, int plen);
bool DecodeMP2(MarkAdContext *maContext, uchar *espkt, int eslen);
void FindAC3AudioInfos(MarkAdContext *maContext, uchar *espkt, int eslen);
bool DecodeAC3(MarkAdContext *maContext, uchar *espkt, int eslen);
diff --git a/markad-standalone.cpp b/markad-standalone.cpp
index 03b123d..902ca1c 100644
--- a/markad-standalone.cpp
+++ b/markad-standalone.cpp
@@ -25,103 +25,14 @@ void syslog_with_tid(int priority, const char *format, ...)
#endif
}
-int cMarkAdIndex::GetNext(off_t Offset)
-{
- if (index_fd==-1) return 0;
-
- struct tIndexPes
- {
- uint32_t offset;
- uchar type;
- uchar number;
- uint16_t reserved;
- };
-
- struct tIndexTs
- {
-uint64_t offset:
- 40;
-unsigned reserved:
- 7;
-unsigned independent:
- 1;
-uint16_t number:
- 16;
- };
-
- if (offset>Offset) return iframe;
- if (ts)
- {
- struct tIndexTs its;
- if (read(index_fd,&its,sizeof(its))==-1) return 0;
- offset=(off_t) its.offset;
- if (its.independent==1) iframe=index;
- }
- else
- {
- struct tIndexPes ipes;
- if (read(index_fd,&ipes,sizeof(ipes))==-1) return 0;
- offset=ipes.offset;
- if (ipes.type==1) iframe=index;
- }
- index++;
- return iframe;
-}
-
-bool cMarkAdIndex::Open(const char *Directory)
-{
- if (!Directory) return false;
- char *ibuf;
- if (asprintf(&ibuf,"%s/index.vdr",Directory)==-1) return false;
- index_fd = open(ibuf,O_RDONLY);
- free(ibuf);
- maxfiles=999;
- if (index_fd==-1)
- {
- // second try just index -> ts format
- if (asprintf(&ibuf,"%s/index",Directory)==-1) return false;
- index_fd = open(ibuf,O_RDONLY);
- free(ibuf);
- if (index_fd==-1)
- {
- fprintf(stderr,"Cannot open index file in %s\n",Directory);
- return false;
- }
- ts=true;
- maxfiles=65535;
- }
- return true;
-}
-
-void cMarkAdIndex::Close()
-{
- if (index_fd!=-1) close(index_fd);
-}
-
-cMarkAdIndex::cMarkAdIndex(const char *Directory)
-{
- if (!Directory) return;
- iframe=0;
- offset=0;
- index=0;
- index_fd=-1;
- ts=false;
- Open(Directory);
-}
-
-cMarkAdIndex::~cMarkAdIndex()
-{
- Close();
-}
-
void cMarkAdStandalone::AddMark(MarkAdMark *Mark)
{
// TODO: Implement this!
}
-bool cMarkAdStandalone::ProcessFile(int Number)
+bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number)
{
- if (!dir) return false;
+ if (!Directory) return false;
if (!Number) return false;
uchar *data;
@@ -129,12 +40,12 @@ bool cMarkAdStandalone::ProcessFile(int Number)
int dataread;
char *fbuf;
- if (index->isTS())
+ if (isTS)
{
datalen=70688; // multiple of 188
data=(uchar *) malloc(datalen);
if (!data) return false;
- if (asprintf(&fbuf,"%s/%05i.ts",dir,Number)==-1)
+ if (asprintf(&fbuf,"%s/%05i.ts",Directory,Number)==-1)
{
free(data);
return false;
@@ -145,7 +56,7 @@ bool cMarkAdStandalone::ProcessFile(int Number)
datalen=69632; // VDR paket size
data=(uchar *) malloc(datalen);
if (!data) return false;
- if (asprintf(&fbuf,"%s/%03i.vdr",dir,Number)==-1)
+ if (asprintf(&fbuf,"%s/%03i.vdr",Directory,Number)==-1)
{
free(data);
return false;
@@ -154,13 +65,16 @@ bool cMarkAdStandalone::ProcessFile(int Number)
int f=open(fbuf,O_RDONLY);
free(fbuf);
- if (f==-1) return false;
+ if (f==-1)
+ {
+ free(data);
+ return false;
+ }
- int lastiframe;
+ int lastiframe=0;
while ((dataread=read(f,data,datalen))>0)
{
- lastiframe=LastIFrame(Number,lseek(f,0,SEEK_CUR)-dataread);
MarkAdMark *mark;
if (common)
@@ -191,8 +105,13 @@ bool cMarkAdStandalone::ProcessFile(int Number)
decoder->FindVideoInfos(&macontext,pkt,pktlen);
if (decoder->DecodeVideo(&macontext,pkt,pktlen))
{
- mark=video->Process(lastiframe);
- AddMark(mark);
+ if (macontext.Video.Info.Pict_Type==MA_I_TYPE)
+ {
+ lastiframe=framecnt;
+ mark=video->Process(lastiframe);
+ AddMark(mark);
+ }
+ framecnt++;
}
}
tspkt+=len;
@@ -269,33 +188,161 @@ bool cMarkAdStandalone::ProcessFile(int Number)
return true;
}
-int cMarkAdStandalone::LastIFrame(int Number, off_t Offset)
+void cMarkAdStandalone::Process(const char *Directory)
{
- return index->GetNext(Offset);
+ for (int i=1; i<=MaxFiles; i++)
+ {
+ if (!ProcessFile(Directory,i))
+ {
+ break;
+ }
+ }
}
+bool cMarkAdStandalone::CheckTS(const char *Directory)
+{
+ MaxFiles=0;
+ isTS=false;
+ if (!Directory) return false;
+ char *buf;
+ if (asprintf(&buf,"%s/00001.ts",Directory)==-1) return false;
+ struct stat statbuf;
+ if (stat(buf,&statbuf)==-1)
+ {
+ if (errno!=ENOENT)
+ {
+ free(buf);
+ return false;
+ }
+ free(buf);
+ if (asprintf(&buf,"%s/001.vdr",Directory)==-1) return false;
+ if (stat(buf,&statbuf)==-1)
+ {
+ free(buf);
+ return false;
+ }
+ free(buf);
+ // VDR detected
+ isTS=false;
+ MaxFiles=999;
+ return true;
+ }
+ free(buf);
+ // TS detected
+ isTS=true;
+ MaxFiles=65535;
+ return true;
+}
-void cMarkAdStandalone::Process()
+void cMarkAdStandalone::CheckPATPMT(const char *Directory)
{
- if (!index) return;
+ char *buf;
+ if (asprintf(&buf,"%s/00001.ts",Directory)==-1) return;
- for (int i=1; i<=index->MaxFiles(); i++)
+ int fd=open(buf,O_RDONLY);
+ free(buf);
+ if (fd==-1) return;
+
+ uchar patpmt[376];
+
+ if (read(fd,patpmt,sizeof(patpmt))!=sizeof(patpmt))
+ {
+ close(fd);
+ return;
+ }
+ close(fd);
+
+ // some checks
+ if ((patpmt[0]!=0x47) || (patpmt[188]!=0x47)) return; // no TS-Sync
+ if (((patpmt[1] & 0x5F)!=0x40) && (patpmt[2]!=0)) return; // no PAT
+ if ((patpmt[3] & 0x10)!=0x10) return; // PAT not without AFC
+ if ((patpmt[191] & 0x10)!=0x10) return; // PMT not without AFC
+ struct PAT *pat = (struct PAT *) &patpmt[5];
+
+ // more checks
+ if (pat->reserved1!=3) return; // is always 11
+ if (pat->reserved3!=7) return; // is always 111
+
+ int pid=pat->pid_L+(pat->pid_H<<8);
+ int pmtpid=((patpmt[189] & 0x1f)<<8)+patpmt[190];
+ if (pid!=pmtpid) return; // pid in PAT differs from pid in PMT
+
+ struct PMT *pmt = (struct PMT *) &patpmt[193];
+
+ // still more checks
+ if (pmt->reserved1!=3) return; // is always 11
+ if (pmt->reserved2!=3) return; // is always 11
+ if (pmt->reserved3!=7) return; // is always 111
+ if (pmt->reserved4!=15) return; // is always 1111
+
+ if ((pmt->program_number_H!=pat->program_number_H) ||
+ (pmt->program_number_L!=pat->program_number_L)) return;
+
+ int desc_len=(pmt->program_info_length_H<<8)+pmt->program_info_length_L;
+ if (desc_len>166) return; // beyond patpmt buffer
+
+ int section_end = 196+(pmt->section_length_H<<8)+pmt->section_length_L;
+ section_end-=4; // we don't care about the CRC32
+ if (section_end>376) return; //beyond patpmt buffer
+
+ int i=205+desc_len;
+
+ while (i<section_end)
{
- if (!ProcessFile(i))
+ struct STREAMINFO *si = (struct STREAMINFO *) &patpmt[i];
+
+ // oh no -> more checks!
+ if (si->reserved1!=7) return;
+ if (si->reserved2!=15) return;
+
+ int pid=(si->PID_H<<8)+si->PID_L;
+
+ switch (si->stream_type)
{
+ case 0x1:
+ case 0x2:
+ macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262;
+ macontext.General.VPid.Num=pid;
+ break;
+
+ case 0x3:
+ case 0x4:
+ macontext.General.APid.Num=pid;
+
+ case 0x6:
+ macontext.General.DPid.Num=pid;
+ break;
+
+ case 0x1b:
+ macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H264;
+ macontext.General.VPid.Num=pid;
+ macontext.General.H264=true;
break;
}
+
+ int esinfo_len=(si->ES_info_length_H<<8)+si->ES_info_length_L;
+
+ i+=(sizeof(struct STREAMINFO)+esinfo_len);
}
+
+ return;
}
cMarkAdStandalone::cMarkAdStandalone(const char *Directory)
{
- dir=strdup(Directory);
+ recvnumber=255;
- index = new cMarkAdIndex(Directory);
- if (!index)
+ memset(&macontext,0,sizeof(macontext));
+ macontext.General.StartTime=0;
+ macontext.General.EndTime=time(NULL)+(7*86400);
+ macontext.General.DPid.Type=MARKAD_PIDTYPE_AUDIO_AC3;
+ macontext.General.APid.Type=MARKAD_PIDTYPE_AUDIO_MP2;
+
+ if (!CheckTS(Directory))
{
- video_demux=ac3_demux=mp2_demux=NULL;
+ video_demux=NULL;
+ ac3_demux=NULL;
+ mp2_demux=NULL;
decoder=NULL;
video=NULL;
audio=NULL;
@@ -303,44 +350,54 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory)
return;
}
- memset(&macontext,0,sizeof(macontext));
- macontext.General.StartTime=0;
- macontext.General.EndTime=time(NULL)+(7*86400);
- macontext.General.DPid.Type=MARKAD_PIDTYPE_AUDIO_AC3;
- macontext.General.APid.Type=MARKAD_PIDTYPE_AUDIO_MP2;
-
- if (index->isTS())
+ if (isTS)
{
- macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H264;
- macontext.General.H264=true;
+ CheckPATPMT(Directory);
}
else
{
+ // TODO: get infos from VDR PES
macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262;
macontext.General.H264=false;
}
- macontext.General.VPid.Num=0x3ff;
- //macontext.General.DPid.Num=0x403;
- //macontext.General.APid.Num=0;
-
- video_demux = new cMarkAdDemux(255);
+ if (macontext.General.VPid.Num)
+ {
+ dsyslog("markad [%i]: using %s-video",recvnumber,macontext.General.H264 ? "H264": "H262");
+ video_demux = new cMarkAdDemux(recvnumber);
+ }
+ else
+ {
+ video_demux=NULL;
+ }
if (macontext.General.APid.Num)
{
- mp2_demux = new cMarkAdDemux(255);
+ dsyslog("markad [%i]: using mp2",recvnumber);
+ mp2_demux = new cMarkAdDemux(recvnumber);
+ }
+ else
+ {
+ mp2_demux=NULL;
}
if (macontext.General.DPid.Num)
{
- ac3_demux = new cMarkAdDemux(255);
+ dsyslog("markad [%i]: using ac3",recvnumber);
+ ac3_demux = new cMarkAdDemux(recvnumber);
+ }
+ else
+ {
+ ac3_demux=NULL;
}
- decoder = new cMarkAdDecoder(255,index->isTS(),
+ decoder = new cMarkAdDecoder(recvnumber,macontext.General.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264,
macontext.General.DPid.Num!=0);
- video = new cMarkAdVideo(255,&macontext);
- audio = new cMarkAdAudio(255,&macontext);
- common = new cMarkAdCommon(255,&macontext);
+ video = new cMarkAdVideo(recvnumber,&macontext);
+ audio = new cMarkAdAudio(recvnumber,&macontext);
+ common = new cMarkAdCommon(recvnumber,&macontext);
+
+ framecnt=0;
}
cMarkAdStandalone::~cMarkAdStandalone()
@@ -352,9 +409,6 @@ cMarkAdStandalone::~cMarkAdStandalone()
if (video) delete video;
if (audio) delete audio;
if (common) delete common;
- if (index) delete index;
-
- if (dir) free(dir);
}
bool isnumber(const char *s)
@@ -696,7 +750,7 @@ int main(int argc, char *argv[])
cMarkAdStandalone *cmasta = new cMarkAdStandalone(recDir);
if (cmasta)
{
- cmasta->Process();
+ cmasta->Process(recDir);
delete cmasta;
}
diff --git a/markad-standalone.h b/markad-standalone.h
index cd4a023..e6693b6 100644
--- a/markad-standalone.h
+++ b/markad-standalone.h
@@ -28,36 +28,112 @@
int SysLogLevel=2;
-class cMarkAdIndex
+class cMarkAdStandalone
{
private:
- int index_fd; // index file descriptor
- int maxfiles;
- bool ts;
- int index;
- int iframe;
- off_t offset;
+ struct PAT
+ {
+unsigned table_id:
+ 8;
+unsigned section_length_H:
+ 4;
+unsigned reserved1:
+ 2;
+unsigned zero:
+ 1;
+unsigned section_syntax_indicator:
+ 1;
+unsigned section_length_L:
+ 8;
+unsigned transport_stream_id_H:
+ 8;
+unsigned transport_stream_id_L:
+ 8;
+unsigned current_next_indicator:
+ 1;
+unsigned version_number:
+ 5;
+unsigned reserved2:
+ 2;
+unsigned section_number:
+ 8;
+unsigned last_section_number:
+ 8;
+unsigned program_number_H:
+ 8;
+unsigned program_number_L:
+ 8;
+unsigned pid_H:
+ 5;
+unsigned reserved3:
+ 3;
+unsigned pid_L:
+ 8;
+ };
- bool Open(const char *Directory);
- void Close();
-public:
- bool isTS()
+ struct PMT
{
- return ts;
- }
- int MaxFiles()
+unsigned table_id:
+ 8;
+unsigned section_length_H:
+ 4;
+unsigned reserved1:
+ 2;
+unsigned zero:
+ 1;
+unsigned section_syntax_indicator:
+ 1;
+unsigned section_length_L:
+ 8;
+unsigned program_number_H:
+ 8;
+unsigned program_number_L:
+ 8;
+unsigned current_next_indicator:
+ 1;
+unsigned version_number:
+ 5;
+unsigned reserved2:
+ 2;
+unsigned section_number:
+ 8;
+unsigned last_section_number:
+ 8;
+unsigned PCR_PID_H:
+ 5;
+unsigned reserved3:
+ 3;
+unsigned PCR_PID_L:
+ 8;
+unsigned program_info_length_H:
+ 4;
+unsigned reserved4:
+ 4;
+unsigned program_info_length_L:
+ 8;
+ };
+
+#pragma pack(1)
+ struct STREAMINFO
{
- return maxfiles;
- }
- int GetNext(off_t Offset);
- cMarkAdIndex(const char *Directory);
- ~cMarkAdIndex();
-};
+unsigned stream_type:
+ 8;
+unsigned PID_H:
+ 5;
+unsigned reserved1:
+ 3;
+unsigned PID_L:
+ 8;
+unsigned ES_info_length_H:
+ 4;
+unsigned reserved2:
+ 4;
+unsigned ES_info_length_L:
+ 8;
+ };
+#pragma pack()
-class cMarkAdStandalone
-{
-private:
cMarkAdDemux *video_demux;
cMarkAdDemux *ac3_demux;
cMarkAdDemux *mp2_demux;
@@ -67,16 +143,19 @@ private:
cMarkAdCommon *common;
MarkAdContext macontext;
- char *dir;
+ int recvnumber;
- cMarkAdIndex *index;
+ bool isTS;
+ int MaxFiles;
+ int framecnt;
void AddMark(MarkAdMark *Mark);
- int LastIFrame(int Number, off_t Offset);
- bool ProcessFile(int Number);
+ void CheckPATPMT(const char *Directory);
+ bool CheckTS(const char *Directory);
+ bool ProcessFile(const char *Directory, int Number);
public:
- void Process();
+ void Process(const char *Directory);
cMarkAdStandalone(const char *Directory);
~cMarkAdStandalone();
};
diff --git a/recv.cpp b/recv.cpp
index f0cd2c5..04a2c17 100644
--- a/recv.cpp
+++ b/recv.cpp
@@ -184,7 +184,15 @@ int cMarkAdReceiver::LastIFrame()
return 0;
}
}
- return Index->GetNextIFrame(Index->Last(),false,NULL,NULL,NULL,true);
+ int iframe=Index->GetNextIFrame(Index->Last(),false,NULL,NULL,NULL,true);
+ if (iframe>0)
+ {
+ return iframe;
+ }
+ else
+ {
+ return 0;
+ }
}
void cMarkAdReceiver::Activate(bool On)
@@ -316,8 +324,11 @@ void cMarkAdReceiver::Action()
decoder->FindVideoInfos(&macontext,pkt,pktlen);
if (decoder->DecodeVideo(&macontext,pkt,pktlen))
{
- mark=video->Process(lastiframe);
- AddMark(mark,3);
+ if (macontext.Video.Info.Pict_Type==MA_I_TYPE)
+ {
+ mark=video->Process(lastiframe);
+ AddMark(mark,3);
+ }
}
}
tspkt+=len;
diff --git a/ts2pkt.cpp b/ts2pkt.cpp
index 2aca980..049d8e4 100644
--- a/ts2pkt.cpp
+++ b/ts2pkt.cpp
@@ -235,13 +235,17 @@ int cMarkAdTS2Pkt::Process(MarkAdPid Pid, uchar *TSData, int TSSize, uchar **Pkt
Reset(MA_ERR_TOBIG);
return TS_SIZE;
}
- if (buflen<=0)
+ if (buflen<0)
{
// error in size
Reset(MA_ERR_NEG);
return TS_SIZE;
}
-
+ if (buflen==0)
+ {
+ // no data?
+ return TS_SIZE;
+ }
}
pktdata=(uchar *) realloc(pktdata,pktsize+buflen);
if (!pktdata)
@@ -307,11 +311,21 @@ int cMarkAdTS2Pkt::Process(MarkAdPid Pid, uchar *TSData, int TSSize, uchar **Pkt
pktdatalast=pktdata;
int bufleftsize=pktsize-(pktinfo.pkthdr+size);
- if (bufleftsize<=0)
+ if (bufleftsize<0)
{
+ pktdata=NULL;
Reset(MA_ERR_NEG);
return bytes_processed;
}
+
+ if (bufleftsize==0)
+ {
+ pktinfo.pkthdr=-1;
+ pktdata=NULL;
+ pktsize=0;
+ return bytes_processed;
+ }
+
uchar *bufleft=(uchar *) malloc(bufleftsize);
if (!bufleft)
{