summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY3
-rw-r--r--Makefile6
-rw-r--r--audio.cpp18
-rw-r--r--audio.h5
-rw-r--r--decoder.cpp158
-rw-r--r--decoder.h7
-rw-r--r--demux.cpp12
-rw-r--r--demux.h2
-rw-r--r--global.h16
-rw-r--r--markad-standalone.cpp144
-rw-r--r--markad-standalone.h12
-rw-r--r--pes2es.h2
-rw-r--r--queue.cpp (renamed from tools.cpp)161
-rw-r--r--queue.h (renamed from tools.h)28
-rw-r--r--recv.cpp201
-rw-r--r--recv.h7
-rw-r--r--status.cpp4
-rw-r--r--streaminfo.cpp569
-rw-r--r--streaminfo.h11
-rw-r--r--ts2pkt.cpp16
-rw-r--r--ts2pkt.h3
-rw-r--r--vdr2pkt.h2
-rw-r--r--version.h2
-rw-r--r--video.cpp345
-rw-r--r--video.h44
25 files changed, 1074 insertions, 704 deletions
diff --git a/HISTORY b/HISTORY
index 0d9ea76..3ca0e5b 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,5 +1,8 @@
VDR Plugin 'markad' Revision History
----------------------------------
+2010-03-06: Version 0.0.5
+
+- Updated H264 handling
2009-09-27: Version 0.0.4
diff --git a/Makefile b/Makefile
index 5b664d1..671a4ab 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ VERSION = $(shell grep 'static const char \*VERSION *=' version.h | awk '{ print
### The C++ compiler and options:
CXX ?= g++
-CXXFLAGS ?= -fPIC -g -O0 -Wall -Woverloaded-virtual -Wno-parentheses
+CXXFLAGS ?= -fPIC -g -O2 -Wall -Woverloaded-virtual -Wno-parentheses
PKG-CONFIG ?= pkg-config
### The directory environment:
@@ -56,8 +56,8 @@ LIBS-CMD += $(shell $(PKG-CONFIG) --libs $(PKG-LIBS))
### The object files (add further files here):
OBJS-CMD = markad-standalone.o decoder.o
-OBJS-COMMON = common.o video.o audio.o demux.o tools.o vdr2pkt.o ts2pkt.o pes2es.o
-OBJS = $(PLUGIN).o recv.o status.o streaminfo.o $(OBJS-COMMON)
+OBJS-COMMON = streaminfo.o video.o audio.o demux.o queue.o vdr2pkt.o ts2pkt.o pes2es.o
+OBJS = $(PLUGIN).o recv.o status.o $(OBJS-COMMON)
### The main target:
diff --git a/audio.cpp b/audio.cpp
index 923812d..ec5ae94 100644
--- a/audio.cpp
+++ b/audio.cpp
@@ -65,19 +65,15 @@ MarkAdMark *cMarkAdAudio::Process(int LastIFrame)
ResetMark();
if (!LastIFrame) return NULL;
-
- if (macontext->State.ContentStarted)
+ if (ChannelChange(macontext->Audio.Info.Channels,channels))
{
- if (ChannelChange(macontext->Audio.Info.Channels,channels))
+ char *buf=NULL;
+ if (asprintf(&buf,"audio channel change from %i to %i (%i)", channels,
+ macontext->Audio.Info.Channels,LastIFrame)!=-1)
{
- char *buf=NULL;
- if (asprintf(&buf,"audio channel change from %i to %i (%i)", channels,
- macontext->Audio.Info.Channels,LastIFrame)!=-1)
- {
- isyslog("markad [%i]: %s",recvnumber, buf);
- AddMark(LastIFrame,buf);
- free(buf);
- }
+ isyslog("markad [%i]: %s",recvnumber, buf);
+ AddMark(LastIFrame,buf);
+ free(buf);
}
}
diff --git a/audio.h b/audio.h
index 3287f7d..69d0666 100644
--- a/audio.h
+++ b/audio.h
@@ -10,6 +10,8 @@
#define __audio_h_
#include <vdr/tools.h> // needed for (d/e/i)syslog
+#include <netinet/in.h> // for htonl
+
#include "global.h"
class cMarkAdAudio
@@ -24,10 +26,7 @@ private:
bool AddMark(int Position, const char *Comment);
int channels;
-
-private:
bool ChannelChange(int a, int b);
-
public:
cMarkAdAudio(int RecvNumber,MarkAdContext *maContext);
~cMarkAdAudio();
diff --git a/decoder.cpp b/decoder.cpp
index 27c4bf2..15d72de 100644
--- a/decoder.cpp
+++ b/decoder.cpp
@@ -8,12 +8,14 @@
#include "decoder.h"
-cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool hasAC3)
+cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool useMP2, bool hasAC3)
{
recvnumber=RecvNumber;
avcodec_init();
avcodec_register_all();
+ last_qscale_table=NULL;
+
cpu_set_t cpumask;
uint len = sizeof(cpumask);
int cpucount;
@@ -29,29 +31,36 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool hasAC3)
isyslog("markad [%i]: using libavcodec.so.%s with %i threads",recvnumber,
AV_STRINGIFY(LIBAVCODEC_VERSION),cpucount);
- CodecID mp2_codecid=CODEC_ID_MP2;
- AVCodec *mp2_codec= avcodec_find_decoder(mp2_codecid);
- if (mp2_codec)
+ if (useMP2)
{
- mp2_context = avcodec_alloc_context();
- if (mp2_context)
+ CodecID mp2_codecid=CODEC_ID_MP2;
+ AVCodec *mp2_codec= avcodec_find_decoder(mp2_codecid);
+ if (mp2_codec)
{
- mp2_context->thread_count=cpucount;
- if (avcodec_open(mp2_context, mp2_codec) < 0)
+ mp2_context = avcodec_alloc_context();
+ if (mp2_context)
+ {
+ mp2_context->thread_count=cpucount;
+ if (avcodec_open(mp2_context, mp2_codec) < 0)
+ {
+ esyslog("markad [%i]: could not open codec 0x%05x",recvnumber,mp2_codecid);
+ av_free(mp2_context);
+ mp2_context=NULL;
+ }
+ }
+ else
{
- esyslog("markad [%i]: could not open codec 0x%05x",recvnumber,mp2_codecid);
- av_free(mp2_context);
- mp2_context=NULL;
+ esyslog("markad [%i]: could not allocate mp2 context",recvnumber);
}
}
else
{
- esyslog("markad [%i]: could not allocate mp2 context",recvnumber);
+ esyslog("markad [%i]: codec 0x%05x not found",recvnumber,mp2_codecid);
+ mp2_context=NULL;
}
}
else
{
- esyslog("markad [%i]: codec 0x%05x not found",recvnumber,mp2_codecid);
mp2_context=NULL;
}
@@ -97,10 +106,17 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool hasAC3)
}
else
{
- video_codecid=CODEC_ID_MPEG2VIDEO;
+ video_codecid=CODEC_ID_MPEG2VIDEO_XVMC;
}
video_codec = avcodec_find_decoder(video_codecid);
+ if ((!video_codec) && (video_codecid==CODEC_ID_MPEG2VIDEO_XVMC))
+ {
+ // fallback to MPEG2VIDEO
+ video_codecid=CODEC_ID_MPEG2VIDEO;
+ video_codec=avcodec_find_decoder(video_codecid);
+ }
+
if (video_codec)
{
video_context = avcodec_alloc_context();
@@ -109,11 +125,45 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool hasAC3)
video_context->thread_count=cpucount;
if (video_codec->capabilities & CODEC_CAP_TRUNCATED)
video_context->flags|=CODEC_FLAG_TRUNCATED; // we do not send complete frames
+
video_context->flags|=CODEC_FLAG_EMU_EDGE; // now linesize should be the same as width
- video_context->flags2|=CODEC_FLAG2_CHUNKS; // needed for H264!
+
+ video_context->flags|=CODEC_FLAG_GRAY; // only decode grayscale
video_context->flags2|=CODEC_FLAG2_FAST; // really?
- if (avcodec_open(video_context, video_codec) < 0)
+ video_context->skip_idct=AVDISCARD_ALL;
+
+ if (video_codecid==CODEC_ID_H264)
+ {
+ video_context->flags2|=CODEC_FLAG2_CHUNKS; // needed for H264!
+ video_context->skip_loop_filter=AVDISCARD_ALL; // skip deblocking
+ video_context->skip_frame=AVDISCARD_NONREF; // P/I-frames
+ }
+ else
+ {
+ video_context->skip_frame=AVDISCARD_NONKEY; // I-frames
+ }
+
+ int ret=avcodec_open(video_context, video_codec);
+ if ((ret < 0) && (video_codecid==CODEC_ID_MPEG2VIDEO_XVMC))
+ {
+ // fallback to MPEG2VIDEO
+ video_codecid=CODEC_ID_MPEG2VIDEO;
+ video_codec=avcodec_find_decoder(video_codecid);
+ if (video_codec)
+ {
+ video_context->codec_type=CODEC_TYPE_UNKNOWN;
+ video_context->codec_id=CODEC_ID_NONE;
+ video_context->codec_tag=0;
+ memset(video_context->codec_name,0,sizeof(video_context->codec_name));
+ ret=avcodec_open(video_context, video_codec);
+ }
+ else
+ {
+ ret=-1;
+ }
+ }
+ if (ret < 0)
{
esyslog("markad [%i]: could not open codec 0x%05x",recvnumber,video_codecid);
av_free(video_context);
@@ -141,6 +191,16 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool hasAC3)
esyslog("markad [%i]: codec 0x%05x not found",recvnumber,video_codecid);
video_context=NULL;
}
+
+ if ((ac3_context) || (mp2_context))
+ {
+ audiobuf=(int16_t*) malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
+ }
+ else
+ {
+ audiobuf=NULL;
+ }
+
}
cMarkAdDecoder::~cMarkAdDecoder()
@@ -163,6 +223,7 @@ cMarkAdDecoder::~cMarkAdDecoder()
avcodec_close(mp2_context);
av_free(mp2_context);
}
+ if (audiobuf) free(audiobuf);
SetVideoInfos(NULL,NULL,NULL,NULL);
}
@@ -180,24 +241,25 @@ bool cMarkAdDecoder::DecodeMP2(MarkAdContext *maContext, uchar *espkt, int eslen
avpkt.data=espkt;
avpkt.size=eslen;
- DECLARE_ALIGNED(16,char,outbuf[AVCODEC_MAX_AUDIO_FRAME_SIZE]);
- int outbuf_size=AVCODEC_MAX_AUDIO_FRAME_SIZE;
+ audiobufsize=AVCODEC_MAX_AUDIO_FRAME_SIZE;
int ret=false;
+ int16_t Taudiobuf[AVCODEC_MAX_AUDIO_FRAME_SIZE];
while (avpkt.size>0)
{
#if LIBAVCODEC_VERSION_INT < ((52<<16)+(25<<8)+0)
- int len=avcodec_decode_audio2(mp2_context,(short *) &outbuf,&outbuf_size,
+ int len=avcodec_decode_audio2(mp2_context,Taudiobuf,&audiobufsize,
avpkt.data,avpkt.size);
#else
- int len=avcodec_decode_audio3(mp2_context,(short *) &outbuf,&outbuf_size,&avpkt);
+ int len=avcodec_decode_audio3(mp2_context,Taudiobuf,&audiobufsize,&avpkt);
#endif
if (len<0)
{
esyslog("markad [%i]: error decoding mp2",recvnumber);
break;
}
- else
+ if (audiobufsize>0)
{
+ memcpy(audiobuf,Taudiobuf,audiobufsize);
SetAudioInfos(maContext,ac3_context);
ret=true;
avpkt.size-=len;
@@ -212,6 +274,9 @@ bool cMarkAdDecoder::SetAudioInfos(MarkAdContext *maContext, AVCodecContext *Aud
if ((!maContext) || (!Audio_Context)) return false;
maContext->Audio.Info.Channels = Audio_Context->channels;
+ maContext->Audio.Data.SampleBuf=audiobuf;
+ maContext->Audio.Data.SampleBufLen=audiobufsize;
+ maContext->Audio.Data.Valid=true;
return true;
}
@@ -229,24 +294,25 @@ bool cMarkAdDecoder::DecodeAC3(MarkAdContext *maContext, uchar *espkt, int eslen
avpkt.data=espkt;
avpkt.size=eslen;
- DECLARE_ALIGNED(16,char,outbuf[AVCODEC_MAX_AUDIO_FRAME_SIZE]);
- int outbuf_size=AVCODEC_MAX_AUDIO_FRAME_SIZE;
int ret=false;
+ int16_t Taudiobuf[AVCODEC_MAX_AUDIO_FRAME_SIZE];
while (avpkt.size>0)
{
+ audiobufsize=AVCODEC_MAX_AUDIO_FRAME_SIZE;
#if LIBAVCODEC_VERSION_INT < ((52<<16)+(25<<8)+0)
- int len=avcodec_decode_audio2(ac3_context,(short *) &outbuf,&outbuf_size,
+ int len=avcodec_decode_audio2(ac3_context,Taudiobuf,&audiobufsize,
avpkt.data,avpkt.size);
#else
- int len=avcodec_decode_audio3(ac3_context,(short *) &outbuf,&outbuf_size,&avpkt);
+ int len=avcodec_decode_audio3(ac3_context,Taudiobuf,&audiobufsize,&avpkt);
#endif
if (len<0)
{
esyslog("markad [%i]: error decoding ac3",recvnumber);
break;
}
- else
+ if (audiobufsize>0)
{
+ memcpy(audiobuf,Taudiobuf,audiobufsize);
SetAudioInfos(maContext,ac3_context);
ret=true;
avpkt.size-=len;
@@ -277,32 +343,7 @@ bool cMarkAdDecoder::SetVideoInfos(MarkAdContext *maContext,AVCodecContext *Vide
maContext->Video.Info.Height=Video_Context->height;
maContext->Video.Info.Width=Video_Context->width;
- switch (Video_Frame->pict_type)
- {
- case FF_I_TYPE:
- maContext->Video.Info.Pict_Type=MA_I_TYPE;
- break;
- case FF_P_TYPE:
- maContext->Video.Info.Pict_Type=MA_P_TYPE;
- break;
- case FF_B_TYPE:
- maContext->Video.Info.Pict_Type=MA_B_TYPE;
- break;
- case FF_S_TYPE:
- maContext->Video.Info.Pict_Type=MA_S_TYPE;
- break;
- case FF_SI_TYPE:
- maContext->Video.Info.Pict_Type=MA_SI_TYPE;
- break;
- case FF_SP_TYPE:
- maContext->Video.Info.Pict_Type=MA_SP_TYPE;
- break;
- case FF_BI_TYPE:
- maContext->Video.Info.Pict_Type=MA_BI_TYPE;
- break;
- default:
- maContext->Video.Info.Pict_Type=0;
- }
+ maContext->Video.Info.Pict_Type=Video_Context->coded_frame->pict_type;
if (DAR)
{
@@ -316,6 +357,8 @@ bool cMarkAdDecoder::SetVideoInfos(MarkAdContext *maContext,AVCodecContext *Vide
bool cMarkAdDecoder::DecodeVideo(MarkAdContext *maContext,uchar *pkt, int plen)
{
+ if (!video_context) return false;
+
AVPacket avpkt;
#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(25<<8)+0)
av_init_packet(&avpkt);
@@ -330,6 +373,7 @@ bool cMarkAdDecoder::DecodeVideo(MarkAdContext *maContext,uchar *pkt, int plen)
// decode video
int video_frame_ready=0;
int len,ret=false;
+
while (avpkt.size>0)
{
#if LIBAVCODEC_VERSION_INT < ((52<<16)+(25<<8)+0)
@@ -351,9 +395,13 @@ bool cMarkAdDecoder::DecodeVideo(MarkAdContext *maContext,uchar *pkt, int plen)
}
if (video_frame_ready)
{
- AVRational dar;
- PAR2DAR(video_context->sample_aspect_ratio,&dar);
- if (SetVideoInfos(maContext,video_context,video_frame,&dar)) ret=true;
+ if (last_qscale_table!=video_frame->qscale_table)
+ {
+ AVRational dar;
+ PAR2DAR(video_context->sample_aspect_ratio,&dar);
+ if (SetVideoInfos(maContext,video_context,video_frame,&dar)) ret=true;
+ last_qscale_table=video_frame->qscale_table;
+ }
}
}
return ret;
diff --git a/decoder.h b/decoder.h
index c1e7f53..c14a48f 100644
--- a/decoder.h
+++ b/decoder.h
@@ -42,11 +42,16 @@ class cMarkAdDecoder
{
private:
int recvnumber;
+ int16_t *audiobuf;
+ int audiobufsize;
+
AVCodecContext *ac3_context;
AVCodecContext *mp2_context;
AVCodecContext *video_context;
AVFrame *video_frame;
+ int8_t *last_qscale_table;
+
bool SetAudioInfos(MarkAdContext *maContext, AVCodecContext *Audio_Context);
void PAR2DAR(AVRational a, AVRational *erg);
@@ -56,7 +61,7 @@ public:
bool DecodeVideo(MarkAdContext *maContext, uchar *pkt, int plen);
bool DecodeMP2(MarkAdContext *maContext, uchar *espkt, int eslen);
bool DecodeAC3(MarkAdContext *maContext, uchar *espkt, int eslen);
- cMarkAdDecoder(int recvnumber, bool useH264, bool hasAC3);
+ cMarkAdDecoder(int recvnumber, bool useH264, bool useMP2, bool hasAC3);
~cMarkAdDecoder();
};
diff --git a/demux.cpp b/demux.cpp
index 89855d7..fbe07de 100644
--- a/demux.cpp
+++ b/demux.cpp
@@ -69,7 +69,17 @@ void cMarkAdDemux::ProcessTS(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt,
uchar *pkt;
int pktlen;
- if (!ts2pkt) ts2pkt=new cMarkAdTS2Pkt(recvnumber,"TS2PES",262144);
+ if (!ts2pkt)
+ {
+ if (Pid.Type==MARKAD_PIDTYPE_VIDEO_H264)
+ {
+ ts2pkt=new cMarkAdTS2Pkt(recvnumber,"TS2H264",393216);
+ }
+ else
+ {
+ ts2pkt=new cMarkAdTS2Pkt(recvnumber,"TS2PKT",262144);
+ }
+ }
if (!ts2pkt) return;
ts2pkt->Process(Pid,Data,Count,&pkt,&pktlen);
diff --git a/demux.h b/demux.h
index 75c3b59..7955e0f 100644
--- a/demux.h
+++ b/demux.h
@@ -18,7 +18,7 @@
#endif
#include "global.h"
-#include "tools.h"
+#include "queue.h"
#include "vdr2pkt.h"
#include "ts2pkt.h"
#include "pes2es.h"
diff --git a/global.h b/global.h
index ff55afe..8ef28fc 100644
--- a/global.h
+++ b/global.h
@@ -51,20 +51,11 @@ typedef struct MarkAdContext
{
struct General
{
- time_t StartTime;
- time_t EndTime;
- bool ManualRecording;
MarkAdPid VPid;
MarkAdPid APid;
MarkAdPid DPid;
} General;
- struct State
- {
- int ContentStarted;
- int ContentStopped;
- } State;
-
struct Video
{
struct Info
@@ -73,6 +64,7 @@ typedef struct MarkAdContext
int Height; // height of pic
int Pict_Type; // picture type (I,P,B,S,SI,SP,BI)
MarkAdAspectRatio AspectRatio;
+ double FramesPerSecond;
} Info;
struct Data
@@ -92,10 +84,8 @@ typedef struct MarkAdContext
struct Data
{
bool Valid;
- uchar *SampleBufAC3;
- int SampleBufLenAC3;
- uchar *SampleBufMP2;
- int SampleBufLenMP2;
+ short *SampleBuf;
+ int SampleBufLen;
} Data;
} Audio;
diff --git a/markad-standalone.cpp b/markad-standalone.cpp
index 2b47d33..3537ecb 100644
--- a/markad-standalone.cpp
+++ b/markad-standalone.cpp
@@ -9,6 +9,8 @@
#include "markad-standalone.h"
cMarkAdStandalone *cmasta=NULL;
+int SysLogLevel=2;
+char markFileName[1024]="";
void syslog_with_tid(int priority, const char *format, ...)
{
@@ -27,9 +29,59 @@ void syslog_with_tid(int priority, const char *format, ...)
#endif
}
+char *cMarkAdStandalone::IndexToHMSF(int Index)
+{
+ if (macontext.Video.Info.FramesPerSecond==0.0) return NULL;
+ char *buf;
+ double Seconds;
+ int f = int(modf((Index+0.5)/macontext.Video.Info.FramesPerSecond,&Seconds)*
+ macontext.Video.Info.FramesPerSecond+1);
+ int s = int(Seconds);
+ int m = s / 60 % 60;
+ int h = s / 3600;
+ s %= 60;
+ if (asprintf(&buf,"%d:%02d:%02d.%02d",h,m,s,f)==-1) return NULL;
+ return buf;
+}
+
void cMarkAdStandalone::AddMark(MarkAdMark *Mark)
{
-// TODO: Implement this!
+ if (!Mark) return;
+
+ if (Mark->Comment)
+ {
+ char *buf=IndexToHMSF(Mark->Position);
+ if (buf)
+ {
+ fprintf(stderr,"%s %s\n",buf,Mark->Comment);
+ free(buf);
+ }
+ }
+// TODO: Implement creating marks/marks.vdr!
+
+}
+
+void cMarkAdStandalone::SaveFrame(int frame)
+{
+ if (!macontext.Video.Info.Width) return;
+ if (!macontext.Video.Data.Valid) return;
+
+ FILE *pFile;
+ char szFilename[32];
+
+ // Open file
+ sprintf(szFilename, "frame%06d.pgm", frame);
+ pFile=fopen(szFilename, "wb");
+ if (pFile==NULL)
+ return;
+
+ // Write header
+ fprintf(pFile, "P5\n%d %d\n255\n", macontext.Video.Info.Width,macontext.Video.Info.Height);
+
+ // Write pixel data
+ fwrite(macontext.Video.Data.Plane[0],1,macontext.Video.Info.Width*macontext.Video.Info.Height,pFile);
+ // Close file
+ fclose(pFile);
}
bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number)
@@ -60,15 +112,9 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number)
while ((dataread=read(f,data,datalen))>0)
{
if (abort) break;
- MarkAdMark *mark;
-
- if (common)
- {
- mark=common->Process(lastiframe);
- AddMark(mark);
- }
+ MarkAdMark *mark=NULL;
- if ((video_demux) && (decoder) && (video))
+ if ((video_demux) && (video) && (decoder) && (streaminfo))
{
uchar *pkt;
int pktlen;
@@ -91,11 +137,13 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number)
{
if (macontext.Video.Info.Pict_Type==MA_I_TYPE)
{
- lastiframe=framecnt;
+ lastiframe=framecnt-1;
+ mark=video->Process(lastiframe);
+ AddMark(mark);
}
- mark=video->Process(framecnt);
- AddMark(mark);
-
+ }
+ if (streaminfo->FindVideoInfos(&macontext,pkt,pktlen))
+ {
framecnt++;
}
}
@@ -105,7 +153,7 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number)
}
}
- if ((mp2_demux) && (decoder) && (audio))
+ if ((ac3_demux) && (streaminfo) && (audio))
{
uchar *pkt;
int pktlen;
@@ -115,7 +163,7 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number)
while (tslen>0)
{
- int len=mp2_demux->Process(macontext.General.APid,tspkt,tslen,&pkt,&pktlen);
+ int len=ac3_demux->Process(macontext.General.DPid,tspkt,tslen,&pkt,&pktlen);
if (len<0)
{
break;
@@ -124,8 +172,18 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number)
{
if (pkt)
{
- if (decoder->DecodeMP2(&macontext,pkt,pktlen))
+ if (streaminfo->FindAC3AudioInfos(&macontext,pkt,pktlen))
{
+ if ((!isTS) && (!noticeVDR_AC3))
+ {
+ dsyslog("markad [%i]: found AC3",recvnumber);
+ if (mp2_demux)
+ {
+ delete mp2_demux;
+ mp2_demux=NULL;
+ }
+ noticeVDR_AC3=true;
+ }
mark=audio->Process(lastiframe);
AddMark(mark);
}
@@ -136,7 +194,7 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number)
}
}
- if ((ac3_demux) && (decoder) && (audio))
+ if ((mp2_demux) && (decoder) && (audio))
{
uchar *pkt;
int pktlen;
@@ -146,7 +204,7 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number)
while (tslen>0)
{
- int len=ac3_demux->Process(macontext.General.DPid,tspkt,tslen,&pkt,&pktlen);
+ int len=mp2_demux->Process(macontext.General.APid,tspkt,tslen,&pkt,&pktlen);
if (len<0)
{
break;
@@ -155,8 +213,13 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number)
{
if (pkt)
{
- if (decoder->DecodeAC3(&macontext,pkt,pktlen))
+ if (decoder->DecodeMP2(&macontext,pkt,pktlen))
{
+ if ((!isTS) && (!noticeVDR_MP2))
+ {
+ dsyslog("markad [%i]: found MP2",recvnumber);
+ noticeVDR_MP2=true;
+ }
mark=audio->Process(lastiframe);
AddMark(mark);
}
@@ -166,6 +229,7 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number)
}
}
}
+
}
close(f);
return true;
@@ -337,9 +401,10 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory)
recvnumber=255;
abort=false;
+ noticeVDR_MP2=false;
+ noticeVDR_AC3=false;
+
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;
@@ -351,7 +416,6 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory)
decoder=NULL;
video=NULL;
audio=NULL;
- common=NULL;
return;
}
@@ -363,18 +427,28 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory)
abort=true;
}
macontext.General.APid.Num=0;
+ if (!markFileName[0]) strcpy(markFileName,"marks");
}
else
{
macontext.General.DPid.Num=-1;
macontext.General.VPid.Num=-1;
macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262;
+ if (!markFileName[0]) strcpy(markFileName,"marks.vdr");
}
if (macontext.General.VPid.Num)
{
- dsyslog("markad [%i]: using %s-video (0x%04x)",recvnumber,macontext.General.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264 ? "H264": "H262",
- macontext.General.VPid.Num);
+ if (isTS)
+ {
+ dsyslog("markad [%i]: using %s-video (0x%04x)",recvnumber,macontext.General.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264 ? "H264": "H262",
+ macontext.General.VPid.Num);
+ }
+ else
+ {
+ dsyslog("markad [%i]: using %s-video",
+ recvnumber,macontext.General.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264 ? "H264": "H262");
+ }
video_demux = new cMarkAdDemux(recvnumber);
}
else
@@ -384,7 +458,8 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory)
if (macontext.General.APid.Num)
{
- dsyslog("markad [%i]: using MP2 (0x%04x)",recvnumber,macontext.General.APid.Num);
+ if (macontext.General.APid.Num!=-1)
+ dsyslog("markad [%i]: using MP2 (0x%04x)",recvnumber,macontext.General.APid.Num);
mp2_demux = new cMarkAdDemux(recvnumber);
}
else
@@ -394,7 +469,8 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory)
if (macontext.General.DPid.Num)
{
- dsyslog("markad [%i]: using AC3 (0x%04x)",recvnumber,macontext.General.DPid.Num);
+ if (macontext.General.DPid.Num!=-1)
+ dsyslog("markad [%i]: using AC3 (0x%04x)",recvnumber,macontext.General.DPid.Num);
ac3_demux = new cMarkAdDemux(recvnumber);
}
else
@@ -405,17 +481,17 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory)
if (!abort)
{
decoder = new cMarkAdDecoder(recvnumber,macontext.General.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264,
- macontext.General.DPid.Num!=0);
+ macontext.General.APid.Num!=0,macontext.General.DPid.Num!=0);
video = new cMarkAdVideo(recvnumber,&macontext);
audio = new cMarkAdAudio(recvnumber,&macontext);
- common = new cMarkAdCommon(recvnumber,&macontext);
+ streaminfo = new cMarkAdStreamInfo;
}
else
{
decoder=NULL;
video=NULL;
audio=NULL;
- common=NULL;
+ streaminfo=NULL;
}
framecnt=0;
@@ -429,7 +505,7 @@ cMarkAdStandalone::~cMarkAdStandalone()
if (decoder) delete decoder;
if (video) delete video;
if (audio) delete audio;
- if (common) delete common;
+ if (streaminfo) delete streaminfo;
}
bool isnumber(const char *s)
@@ -557,6 +633,10 @@ int main(int argc, char *argv[])
bNice = true;
break;
+ case 'B':
+ // backupmarks
+ break;
+
case 'O':
// --OSD
break;
@@ -571,7 +651,6 @@ int main(int argc, char *argv[])
case 'j':
case 'a':
case 'S':
- case 'B':
case 'n':
case 'C':
break;
@@ -592,7 +671,8 @@ int main(int argc, char *argv[])
break;
case 1: // --markfile
- //setMarkfileName(optarg); // TODO: implement this
+ strncpy(markFileName,optarg,1024);
+ markFileName[1023]=0;
break;
case 2: // --loglevel
diff --git a/markad-standalone.h b/markad-standalone.h
index 145a9ea..fcde1fa 100644
--- a/markad-standalone.h
+++ b/markad-standalone.h
@@ -23,11 +23,9 @@
#include "decoder.h"
#include "video.h"
#include "audio.h"
-#include "common.h"
+#include "streaminfo.h"
#include "version.h"
-int SysLogLevel=2;
-
class cMarkAdStandalone
{
private:
@@ -142,14 +140,13 @@ unsigned Descriptor_Length:
8;
};
-
cMarkAdDemux *video_demux;
cMarkAdDemux *ac3_demux;
cMarkAdDemux *mp2_demux;
cMarkAdDecoder *decoder;
cMarkAdVideo *video;
cMarkAdAudio *audio;
- cMarkAdCommon *common;
+ cMarkAdStreamInfo *streaminfo;
MarkAdContext macontext;
int recvnumber;
@@ -159,6 +156,11 @@ unsigned Descriptor_Length:
int framecnt;
bool abort;
+ bool noticeVDR_MP2;
+ bool noticeVDR_AC3;
+
+ void SaveFrame(int Frame);
+ char *IndexToHMSF(int Index);
void AddMark(MarkAdMark *Mark);
bool CheckPATPMT(const char *Directory);
bool CheckTS(const char *Directory);
diff --git a/pes2es.h b/pes2es.h
index 5b74e43..58dd25e 100644
--- a/pes2es.h
+++ b/pes2es.h
@@ -18,7 +18,7 @@ typedef unsigned char uchar;
#include <string.h>
#include "global.h"
-#include "tools.h"
+#include "queue.h"
class cMarkAdPES2ES
{
diff --git a/tools.cpp b/queue.cpp
index 6c4edc5..f5f158e 100644
--- a/tools.cpp
+++ b/queue.cpp
@@ -6,18 +6,22 @@
* $Id$
*/
-#include "tools.h"
+#include "queue.h"
cMarkAdPaketQueue::cMarkAdPaketQueue(int RecvNumber, const char *Name, int Size)
{
recvnumber=RecvNumber;
inptr=0;
outptr=0;
+ memset(&pktinfo,0,sizeof(pktinfo));
pktinfo.pkthdr=-1;
maxqueue=Size;
name=strdup(Name);
buffer=(uchar *) malloc(Size+1);
if (!buffer) maxqueue=0;
+ scanner=0xFFFFFFFF;
+ scannerstart=-1;
+ percent=-1;
}
cMarkAdPaketQueue::~cMarkAdPaketQueue()
@@ -70,10 +74,13 @@ bool cMarkAdPaketQueue::Put(uchar *Data, int Size)
memcpy(&buffer[inptr],Data,Size);
inptr+=Size;
- if ((inptr>(0.9*maxqueue)) && (name))
+ int npercent=((double) inptr/(double) maxqueue)*100;
+
+ if ((npercent>90) && (name) && (npercent!=percent))
{
- dsyslog("markad [%i]: buffer %s usage: %3.f%%",recvnumber,
- name,((double) inptr/(double) maxqueue)*100);
+ dsyslog("markad [%i]: buffer %s usage: %3i%%",recvnumber,
+ name,npercent);
+ percent=npercent;
}
return true;
@@ -93,28 +100,45 @@ uchar *cMarkAdPaketQueue::Get(int *Size)
return ret;
}
-int cMarkAdPaketQueue::FindPktHeader(int Start, int *StreamSize,int *HeaderSize)
+int cMarkAdPaketQueue::FindPktHeader(int Start, int *StreamSize,int *HeaderSize, bool LongStartCode)
{
if ((!StreamSize) || (!HeaderSize)) return -1;
if (!Start) Start=outptr;
- if (Start>inptr) return -1;
+ if (Start>=inptr) return -1;
*StreamSize=0;
- *HeaderSize=4; // 0x0 0x0 0x1 0xNN
- unsigned long scanner=0xFFFFFFFF;
+ if (LongStartCode)
+ {
+ *HeaderSize=4; // 0x0 0x0 0x0 0x1
+ }
+ else
+ {
+ *HeaderSize=3; // 0x0 0x0 0x1
+ }
int i;
- for (i=Start; i<inptr; i++)
+ if (scanner!=0xFFFFFFFF)
{
scanner<<=8;
- if (scanner==0x00000100L)
+ scanner|=buffer[Start++];
+ }
+
+ for (i=Start; i<inptr; i++)
+ {
+ if (LongStartCode)
{
- break;
+ if (scanner==1L) break;
+ if ((scanner & 0xFFFFFFF0)==0x1E0L) break;
+ }
+ else
+ {
+ if ((scanner & 0x00FFFFFF)==1L) break;
}
+ scanner<<=8;
scanner|=buffer[i];
}
if (i==inptr) return -1;
-
+ if (LongStartCode) i--;
if (buffer[i]>=0xBC)// do we have a PES packet?
{
#define PESHDRSIZE 6
@@ -125,44 +149,63 @@ int cMarkAdPaketQueue::FindPktHeader(int Start, int *StreamSize,int *HeaderSize)
*StreamSize=(buffer[i+1]<<8)+buffer[i+2];
if (*StreamSize) (*StreamSize)+=PESHDRSIZE; // 6 Byte PES-Header
-
- struct PESHDROPT *peshdropt=(struct PESHDROPT *) &buffer[i+3];
- if (peshdropt->MarkerBits==0x2)
- {
- *HeaderSize=PESHDRSIZE+sizeof(struct PESHDROPT)+
- peshdropt->Length;
- }
- else
+ if (LongStartCode)
{
- *HeaderSize=PESHDRSIZE;
+ struct PESHDROPT *peshdropt=(struct PESHDROPT *) &buffer[i+3];
+ if (peshdropt->MarkerBits==0x2)
+ {
+ *HeaderSize=PESHDRSIZE+sizeof(struct PESHDROPT)+
+ peshdropt->Length;
+ }
+ else
+ {
+ *HeaderSize=PESHDRSIZE;
+ }
}
}
+
return i-3;
}
int cMarkAdPaketQueue::FindAudioHeader(int Start, int *FrameSize, int *HeaderSize, bool AC3)
{
+ if ((!FrameSize) || (!HeaderSize)) return -1;
if (!Start) Start=outptr;
- if (Start>inptr) return -1;
- if (FrameSize) (*FrameSize)=0;
- if (HeaderSize) (*HeaderSize)=4;
- unsigned short scanner=0x0;
+ if (Start>=inptr) return -1;
+ (*FrameSize)=0;
+ if (AC3)
+ {
+ (*HeaderSize)=2;
+ }
+ else
+ {
+ (*HeaderSize)=3;
+ }
int i;
+
+ if (scanner!=0xFFFFFFFF)
+ {
+ scanner<<=8;
+ scanner|=buffer[Start++];
+ }
+
for (i=Start; i<inptr; i++)
{
- scanner|=buffer[i];
+
if (AC3)
{
- if (scanner==0x0B77) break;
+ if ((scanner & 0x0000FFFF)==0xB77L) break;
}
else
{
- if ((scanner & 0xFFE0)==0xFFE0) break;
+ if ((scanner & 0x00000FFE)==0xFFEL) break;
}
+
scanner<<=8;
+ scanner|=buffer[i];
}
if (i==inptr) return -1;
- i--;
+ i-=2;
if (AC3)
{
@@ -170,7 +213,6 @@ int cMarkAdPaketQueue::FindAudioHeader(int Start, int *FrameSize, int *HeaderSiz
if (ac3hdr->SampleRateIndex==3) return -1; // reserved
if (ac3hdr->FrameSizeIndex>=38) return -1; // reserved
- if (HeaderSize) (*HeaderSize)=sizeof(struct AC3HDR);
if (FrameSize)
{
@@ -202,8 +244,6 @@ int cMarkAdPaketQueue::FindAudioHeader(int Start, int *FrameSize, int *HeaderSiz
if (mp2hdr->SampleRateIndex==3) return -1; //reserved
if (mp2hdr->Emphasis==2) return -1; // reserved
- if (HeaderSize) (*HeaderSize)=sizeof(struct MP2HDR);
-
if (FrameSize)
{
int bitRates[3][3][16] = // all values are specified as kbits/s
@@ -279,30 +319,48 @@ uchar *cMarkAdPaketQueue::GetPacket(int *Size, int Type)
{
if (!Size) return NULL;
*Size=0;
- if (!Length()) return NULL;
+ if (Length()<4) return NULL;
- if (pktinfo.pkthdr==-1)
+ if ((Type==MA_PACKET_H264) && (pktinfo.pktsyncsize>5) && (pktinfo.pkthdr!=-1))
{
+ // ignore PES paket
+ pktinfo.pkthdr=-1;
+ outptr+=pktinfo.pktsyncsize;
+ }
+ if (pktinfo.pkthdr==-1)
+ {
+ scanner=0xFFFFFFFF;
switch (Type)
{
case MA_PACKET_AC3:
- pktinfo.pkthdr=FindAudioHeader(0,&pktinfo.streamsize,&pktinfo.pkthdrsize, true);
+ pktinfo.pkthdr=FindAudioHeader(0,&pktinfo.streamsize,&pktinfo.pktsyncsize, true);
break;
case MA_PACKET_MP2:
- pktinfo.pkthdr=FindAudioHeader(0,&pktinfo.streamsize,&pktinfo.pkthdrsize, false);
+ pktinfo.pkthdr=FindAudioHeader(0,&pktinfo.streamsize,&pktinfo.pktsyncsize, false);
+ break;
+ case MA_PACKET_H264:
+ pktinfo.pkthdr=FindPktHeader(0,&pktinfo.streamsize,&pktinfo.pktsyncsize,true);
+ if (pktinfo.pktsyncsize>5)
+ {
+ // ignore PES paket
+ pktinfo.pkthdr=-1;
+ outptr+=pktinfo.pktsyncsize;
+ }
break;
default:
- pktinfo.pkthdr=FindPktHeader(0,&pktinfo.streamsize,&pktinfo.pkthdrsize);
+ pktinfo.pkthdr=FindPktHeader(0,&pktinfo.streamsize,&pktinfo.pktsyncsize,false);
+ break;
}
if (pktinfo.pkthdr==-1)
{
return NULL;
}
+ scannerstart=pktinfo.pkthdr+pktinfo.pktsyncsize;
}
- int start,streamsize,pkthdrsize,pkthdr=-1;
+ int streamsize,pktsyncsize,pkthdr=-1;
if (pktinfo.streamsize)
{
@@ -312,27 +370,33 @@ uchar *cMarkAdPaketQueue::GetPacket(int *Size, int Type)
}
else
{
- start=pktinfo.pkthdr+pktinfo.streamsize;
+ scannerstart=pktinfo.pkthdr+pktinfo.streamsize;
+ scanner=0xFFFFFFFF;
}
}
- else
- {
- start=pktinfo.pkthdr+pktinfo.pkthdrsize;
- }
switch (Type)
{
case MA_PACKET_AC3:
- pkthdr=FindAudioHeader(start,&streamsize,&pkthdrsize, true);
+ pkthdr=FindAudioHeader(scannerstart,&streamsize,&pktsyncsize, true);
break;
case MA_PACKET_MP2:
- pkthdr=FindAudioHeader(start,&streamsize,&pkthdrsize, false);
+ pkthdr=FindAudioHeader(scannerstart,&streamsize,&pktsyncsize, false);
+ break;
+ case MA_PACKET_H264:
+ pkthdr=FindPktHeader(scannerstart,&streamsize,&pktsyncsize, true);
break;
default:
- pkthdr=FindPktHeader(start,&streamsize,&pkthdrsize);
+ pkthdr=FindPktHeader(scannerstart,&streamsize,&pktsyncsize, false);
+ break;
}
- if (pkthdr==-1) return NULL;
+ if (pkthdr==-1)
+ {
+ scannerstart=inptr;
+ return NULL;
+ }
+ scannerstart=pkthdr+pktsyncsize;
uchar *ptr=&buffer[pktinfo.pkthdr];
@@ -350,6 +414,7 @@ uchar *cMarkAdPaketQueue::GetPacket(int *Size, int Type)
if (pktinfo.pkthdr>(4096+bytesleft))
{
memcpy(buffer,&buffer[pkthdr],bytesleft);
+ scannerstart-=outptr;
inptr=bytesleft;
outptr=0;
pkthdr=0;
@@ -357,7 +422,7 @@ uchar *cMarkAdPaketQueue::GetPacket(int *Size, int Type)
pktinfo.pkthdr=pkthdr;
pktinfo.streamsize=streamsize;
- pktinfo.pkthdrsize=pkthdrsize;
+ pktinfo.pktsyncsize=pktsyncsize;
return ptr;
}
diff --git a/tools.h b/queue.h
index 90d01e6..99c9a10 100644
--- a/tools.h
+++ b/queue.h
@@ -1,13 +1,13 @@
/*
- * tools.h: A plugin for the Video Disk Recorder
+ * queue.h: A plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
* $Id$
*/
-#ifndef __tools_h_
-#define __tools_h_
+#ifndef __queue_h_
+#define __queue_h_
#include <vdr/tools.h> // needed for (d/e/i)syslog
@@ -109,16 +109,23 @@ private:
struct pktinfo
{
int pkthdr;
- int pkthdrsize;
+ int pktsyncsize;
int streamsize;
+ bool ispes;
} pktinfo;
+ int percent;
+
uchar *buffer;
int maxqueue;
int inptr;
int outptr;
- int FindPktHeader(int Start, int *StreamSize,int *HeaderSize);
- int FindAudioHeader(int Start, int *FrameSize, int *HeaderSize, bool AC3);
+
+ unsigned long scanner;
+ int scannerstart;
+
+ int FindPktHeader(int Start, int *StreamSize,int *SyncSize, bool LongStartCode);
+ int FindAudioHeader(int Start, int *FrameSize, int *SyncSize, bool AC3);
public:
cMarkAdPaketQueue(int RecvNumber, const char *Name, int Size=32768);
~cMarkAdPaketQueue();
@@ -130,14 +137,17 @@ public:
{
inptr=outptr=0;
pktinfo.pkthdr=-1;
+ scanner=0xFFFFFFFF;
+ scannerstart=-1;
}
bool Inject(uchar *Data, int Size);
bool Put(uchar *Data, int Size);
uchar *Get(int *Size);
-#define MA_PACKET_PKT 1
-#define MA_PACKET_AC3 2
-#define MA_PACKET_MP2 3
+#define MA_PACKET_PKT 0x10 // 0x00 0x00 0x01 (PES / H262)
+#define MA_PACKET_H264 0x11 // 0x00 0x00 0x00 0x01 (H264)
+#define MA_PACKET_AC3 0x20
+#define MA_PACKET_MP2 0x30
uchar *GetPacket(int *Size, int Type);
};
diff --git a/recv.cpp b/recv.cpp
index b2e26f0..4192f72 100644
--- a/recv.cpp
+++ b/recv.cpp
@@ -8,12 +8,20 @@
#include "recv.h"
+#if APIVERSNUM > 10711
+cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *Timer)
+ :
+ cReceiver(Timer->Channel()->GetChannelID(), -1),
+ cThread("markad"),
+ buffer(MEGATS(3)), running(false) // 3MB Buffer
+#else
cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *Timer)
:
cReceiver(Timer->Channel()->GetChannelID(), -1,
Timer->Channel()->Vpid(),Timer->Channel()->Dpids()),
- cThread("markad"),
+ cThread("markad"),
buffer(MEGATS(3)), running(false) // 3MB Buffer
+#endif
{
if ((!Filename) || (!Timer)) return;
@@ -23,46 +31,37 @@ cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *T
// 10 ms timeout on getting TS frames
buffer.SetTimeouts(0, 10);
- bool useH264=false;
-#if APIVERSNUM >= 10700
-#ifdef DVBFE_DELSYS_DVBS2
- if (Timer->Channel()->System()==DVBFE_DELSYS_DVBS2) useH264=true;
-#else
- if (Timer->Channel()->System()==SYS_DVBS2) useH264=true;
-#endif
-#endif
memset(&macontext,0,sizeof(macontext));
- if (Timer->Event())
- {
- macontext.General.StartTime=Timer->Event()->StartTime();
- macontext.General.EndTime=Timer->Event()->EndTime();
- }
- else
- {
- macontext.General.StartTime=Timer->StartTime();
- macontext.General.EndTime=Timer->StopTime();
- macontext.General.ManualRecording=true;
- }
-
macontext.General.VPid.Num=Timer->Channel()->Vpid();
- if (useH264)
- {
- macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H264;
- }
- else
+
+#if APIVERSNUM == 10700
+#error "VDR-1.7.0 is not supported"
+#endif
+#if APIVERSNUM > 10700
+ switch Timer->Channel()->Vtype()
{
+ case 0x2:
macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262;
+ break;
+ case 0x1b:
+ macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H264;
+ break;
+ default:
+ macontext.General.VPid.Num=0;
+ macontext.General.VPid.Type=0;
+ break;
}
+#else
+ macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262;
+#endif
-// macontext.General.APid.Pid=Timer->Channel()->Apid(0); // TODO ... better solution?
-// macontext.General.APid.Type=MARKAD_PIDTYPE_AUDIO_MP2;
-
- macontext.General.DPid.Num=Timer->Channel()->Dpid(0); // TODO ... better solution?
+ macontext.General.DPid.Num=Timer->Channel()->Dpid(0); // ... better solution?
macontext.General.DPid.Type=MARKAD_PIDTYPE_AUDIO_AC3;
if (macontext.General.VPid.Num)
{
- dsyslog("markad [%i]: using %s-video",recvnumber,useH264 ? "H264": "H262");
+ dsyslog("markad [%i]: using %s-video",recvnumber,
+ (macontext.General.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264) ? "H264": "H262");
video=new cMarkAdVideo(RecvNumber,&macontext);
video_demux = new cMarkAdDemux(RecvNumber);
}
@@ -92,12 +91,31 @@ cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *T
}
streaminfo=new cMarkAdStreamInfo;
- common=new cMarkAdCommon(RecvNumber,&macontext);
marks.Load(Filename);
+
Index=NULL;
lastiframe=0;
framecnt=-1;
+ marksfound=false;
+
+ if (!marks.Count())
+ {
+ MarkAdMark tempmark;
+ char *buf;
+ tempmark.Position=0;
+ if (asprintf(&buf,"start of recording (0)")!=-1)
+ {
+ tempmark.Comment=buf;
+ AddMark(&tempmark,0);
+ isyslog("markad [%i]: %s",recvnumber,buf);
+ free(buf);
+ }
+ }
+ else
+ {
+ marksfound=true;
+ }
}
cMarkAdReceiver::~cMarkAdReceiver()
@@ -111,12 +129,27 @@ cMarkAdReceiver::~cMarkAdReceiver()
}
buffer.Clear();
+ if (lastiframe)
+ {
+ MarkAdMark tempmark;
+ tempmark.Position=lastiframe;
+ char *buf;
+
+ if (asprintf(&buf,"stop of recording (%i)",lastiframe)!=-1)
+ {
+ tempmark.Comment=buf;
+ AddMark(&tempmark,0);
+ isyslog("markad [%i]: %s",recvnumber,buf);
+ free(buf);
+ }
+ }
+
+ if (Index) delete Index;
if (video_demux) delete video_demux;
if (ac3_demux) delete ac3_demux;
if (streaminfo) delete streaminfo;
if (video) delete video;
if (audio) delete audio;
- if (common) delete common;
if (filename) free(filename);
}
@@ -181,22 +214,6 @@ void cMarkAdReceiver::Activate(bool On)
}
else if (running)
{
- if ((!macontext.State.ContentStopped) && (lastiframe))
- {
- MarkAdMark tempmark;
- tempmark.Position=lastiframe;
-
- char *buf;
- if (asprintf(&buf,"stop of user content (%i)",lastiframe)!=-1)
- {
- tempmark.Comment=buf;
- AddMark(&tempmark,0);
- isyslog("markad [%i]: %s",recvnumber,buf);
- free(buf);
- }
- }
-
- if (Index) delete Index;
running = false;
buffer.Signal();
Cancel(2);
@@ -228,8 +245,9 @@ void cMarkAdReceiver::Receive(uchar *Data, int Length)
void cMarkAdReceiver::AddMark(MarkAdMark *mark, int Priority)
{
if (!mark) return;
- if (!mark->Position) return;
if (!mark->Comment) return;
+ if (mark->Position<0) return;
+
cMark *newmark=marks.Add(mark->Position);
if (newmark)
{
@@ -242,35 +260,28 @@ void cMarkAdReceiver::AddMark(MarkAdMark *mark, int Priority)
}
marks.Save();
-#define MAXPOSDIFF (25*60*9) // = 9 min
-
- cMark *prevmark=marks.GetPrev(mark->Position);
- if (!prevmark) return;
- if (!prevmark->comment) return;
- if (abs(mark->Position-prevmark->position)>MAXPOSDIFF) return;
-
- int prevPriority=atoi(prevmark->comment+1);
- if (prevPriority==Priority) return;
-
- if (prevPriority>Priority)
+ if (!marksfound)
{
- // add text from mark to prevmark
- prevmark->comment=strcatrealloc(prevmark->comment," ");
- prevmark->comment=strcatrealloc(prevmark->comment,mark->Comment);
-
- dsyslog("markad [%i]: delete mark %i",recvnumber,newmark->position);
- marks.Del(newmark,true);
- }
- else
- {
- // add text from prevmark to mark
- mark->Comment=strcatrealloc(mark->Comment," ");
- mark->Comment=strcatrealloc(mark->Comment,prevmark->comment);
-
- dsyslog("markad [%i]: delete previous mark %i",recvnumber,prevmark->position);
- marks.Del(prevmark,true);
+ cMark *prevmark=marks.GetPrev(mark->Position);
+ if (!prevmark) return;
+ if (!prevmark->comment) return;
+ if (prevmark->position==0) return;
+#define MAXPOSDIFF (25*60*13) // = 13 min
+ if (abs(mark->Position-prevmark->position)>MAXPOSDIFF)
+ {
+ cMark *firstmark=marks.Get(0);
+ if (firstmark)
+ {
+ marks.Del(firstmark,true);
+ marks.Save();
+ marksfound=true;
+ }
+ }
+ else
+ {
+ marksfound=true;
+ }
}
- marks.Save();
}
void cMarkAdReceiver::Action()
@@ -283,12 +294,6 @@ void cMarkAdReceiver::Action()
lastiframe=LastIFrame();
MarkAdMark *mark;
- if (common)
- {
- mark=common->Process(lastiframe);
- AddMark(mark,0);
- }
-
if ((video_demux) && (streaminfo) && (video))
{
cTimeMs t;
@@ -309,20 +314,22 @@ void cMarkAdReceiver::Action()
{
if (pkt)
{
- streaminfo->FindVideoInfos(&macontext,pkt,pktlen);
- if (macontext.Video.Info.Pict_Type==MA_I_TYPE)
+ if (streaminfo->FindVideoInfos(&macontext,pkt,pktlen))
{
- if (framecnt==-1)
+ if (macontext.Video.Info.Pict_Type==MA_I_TYPE)
{
- framecnt=0;
- }
- else
- {
- mark=video->Process(lastiframe);
- AddMark(mark,3);
+ if (framecnt==-1)
+ {
+ framecnt=0;
+ }
+ else
+ {
+ mark=video->Process(lastiframe);
+ AddMark(mark,3);
+ }
}
+ if (framecnt!=-1) framecnt++;
}
- if (framecnt!=-1) framecnt++;
}
tspkt+=len;
tslen-=len;
@@ -354,9 +361,11 @@ void cMarkAdReceiver::Action()
{
if (pkt)
{
- streaminfo->FindAC3AudioInfos(&macontext,pkt,pktlen);
- mark=audio->Process(lastiframe);
- AddMark(mark,2);
+ if (streaminfo->FindAC3AudioInfos(&macontext,pkt,pktlen))
+ {
+ mark=audio->Process(lastiframe);
+ AddMark(mark,2);
+ }
}
tspkt+=len;
tslen-=len;
diff --git a/recv.h b/recv.h
index 5920f6f..96290ec 100644
--- a/recv.h
+++ b/recv.h
@@ -19,7 +19,6 @@
#include "streaminfo.h"
#include "audio.h"
#include "video.h"
-#include "common.h"
#if (APIVERSNUM >= 10700)
#include <linux/dvb/frontend.h>
@@ -58,6 +57,7 @@ private:
char *filename;
int lastiframe;
int framecnt;
+ bool marksfound;
char *strcatrealloc(char *dest, const char *src);
cMarks marks;
@@ -67,7 +67,6 @@ private:
MarkAdContext macontext;
cMarkAdStreamInfo *streaminfo;
- cMarkAdCommon *common;
cMarkAdAudio *audio;
cMarkAdVideo *video;
@@ -83,6 +82,10 @@ protected:
bool running;
public:
cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *Timer);
+ bool FoundMarks()
+ {
+ return marksfound;
+ }
const char *FileName()
{
return (const char *) filename;
diff --git a/status.cpp b/status.cpp
index bb308c9..1955549 100644
--- a/status.cpp
+++ b/status.cpp
@@ -72,6 +72,10 @@ void cStatusMarkAd::Recording(const cDevice *Device, const char *Name, const cha
dsyslog("markad [%i]: stop recording %s ",recvnumber,FileName);
((cDevice *) Device)->Detach(recv[recvnumber]);
+ if (!recv[recvnumber]->FoundMarks())
+ {
+ // TODO: start standalone markad with logo detection
+ }
delete recv[recvnumber];
recv[recvnumber]=NULL;
}
diff --git a/streaminfo.cpp b/streaminfo.cpp
index 2c0b6a3..e3692d6 100644
--- a/streaminfo.cpp
+++ b/streaminfo.cpp
@@ -8,9 +8,9 @@
#include "streaminfo.h"
-void cMarkAdStreamInfo::FindAC3AudioInfos(MarkAdContext *maContext, uchar *espkt, int eslen)
+bool cMarkAdStreamInfo::FindAC3AudioInfos(MarkAdContext *maContext, uchar *espkt, int eslen)
{
- if ((!maContext) || (!espkt)) return;
+ if ((!maContext) || (!espkt)) return false;
#pragma pack(1)
struct AC3HDR
@@ -43,8 +43,8 @@ unsigned AcMod:
if ((ac3hdr->Sync1==0x0b) && (ac3hdr->Sync2==0x77))
{
// some extra checks
- if (ac3hdr->SampleRateIndex==3) return; // reserved
- if (ac3hdr->FrameSizeIndex>=38) return; // reserved
+ if (ac3hdr->SampleRateIndex==3) return false; // reserved
+ if (ac3hdr->FrameSizeIndex>=38) return false; // reserved
maContext->Audio.Info.Channels=0;
int lfe_bitmask = 0x0;
@@ -87,34 +87,37 @@ unsigned AcMod:
if ((ac3hdr->LFE_Mix_VarField & lfe_bitmask)==lfe_bitmask)
maContext->Audio.Info.Channels++;
- }
+ return true;
+ }
+ return false;
}
-void cMarkAdStreamInfo::FindVideoInfos(MarkAdContext *maContext, uchar *pkt, int len)
+bool cMarkAdStreamInfo::FindVideoInfos(MarkAdContext *maContext, uchar *pkt, int len)
{
- if ((!maContext) || (!pkt) || (!len)) return;
- if (!maContext->General.VPid.Type) return;
+ if ((!maContext) || (!pkt) || (!len)) return false;
+ if (!maContext->General.VPid.Type) return false;
- if (maContext->General.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264)
- {
- FindH264VideoInfos(maContext, pkt, len);
- }
- else
+ switch (maContext->General.VPid.Type)
{
- FindH262VideoInfos(maContext, pkt, len);
+ case MARKAD_PIDTYPE_VIDEO_H264:
+ return FindH264VideoInfos(maContext, pkt, len);
+ break;
+ case MARKAD_PIDTYPE_VIDEO_H262:
+ return FindH262VideoInfos(maContext, pkt, len);
+ break;
}
+ return false;
}
-void cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt, int len)
+bool cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt, int len)
{
- if ((!maContext) || (!pkt) || (!len)) return;
-
- maContext->Video.Info.Pict_Type=0;
+ if ((!maContext) || (!pkt) || (!len)) return false;
- if ((pkt[3] & 0x1F)==NAL_AUD)
+ if ((pkt[4] & 0x1F)==NAL_AUD)
{
- switch (pkt[4] >> 5)
+
+ switch (pkt[5] >> 5)
{
case 0:
case 3:
@@ -127,262 +130,37 @@ void cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt,
maContext->Video.Info.Pict_Type=MA_P_TYPE;
break;
case 2:
- case 7: // B_FRAME;
+ case 7: // B_FRAME;
maContext->Video.Info.Pict_Type=MA_B_TYPE;
break;
default: // NO_PICTURE;
- maContext->Video.Info.Pict_Type=0;
+ return false;
break;
}
+ return true;
}
- if ((pkt[3] & 0x1F)==NAL_SPS)
+ if ((pkt[4] & 0x1F)==NAL_SPS)
{
uint8_t nal_data[len];
- const uint8_t *end = pkt + len;
- int nal_len = nalUnescape(nal_data, pkt + 4, int(end - pkt - 4));
-
- int profile_idc, level_idc, constraint_set3_flag, pic_order_cnt_type, i, j;
+ int nal_len = nalUnescape(nal_data, pkt + 5, len - 5);
cBitStream bs(nal_data, nal_len);
+ int profile_idc, pic_order_cnt_type, i, j;
+
uint32_t width=0;
uint32_t height=0;
uint32_t aspect_ratio_idc=0;
- uint32_t video_format=0;
double frame_rate=0;
- double bit_rate=0;
- bool cpb_dpb_delays_present_flag=false;
- bool pic_struct_present_flag=false;
bool frame_mbs_only_flag=false;
- bool mb_adaptive_frame_field_flag=false;
- uint32_t time_offset_length=0;
profile_idc = bs.getU8(); // profile_idc
- bs.skipBit(); // constraint_set0_flag
- bs.skipBit(); // constraint_set1_flag
- bs.skipBit(); // constraint_set2_flag
- constraint_set3_flag = bs.getBit(); // constraint_set3_flag
- bs.skipBits(4); // reserved_zero_4bits
- level_idc = bs.getU8(); // level_idc
+ bs.skipBits(8); // constraint_setN_flags and reserved_zero_Nbits
+ bs.skipBits(8); // level_idc
bs.skipUeGolomb(); // seq_parameter_set_id
- switch (profile_idc)
- {
- case 66: // baseline profile
- case 77: // main profile
- case 88: // extended profile
- switch (level_idc)
- {
- case 10: // level 1.0
- bit_rate = 64000;
- break;
- case 11: // level 1b / 1.1
- bit_rate = constraint_set3_flag ? 128000 : 192000;
- break;
- case 12: // level 1.2
- bit_rate = 384000;
- break;
- case 13: // level 1.3
- bit_rate = 768000;
- break;
- case 20: // level 2.0
- bit_rate = 2000000;
- break;
- case 21: // level 2.1
- bit_rate = 4000000;
- break;
- case 22: // level 2.2
- bit_rate = 4000000;
- break;
- case 30: // level 3.0
- bit_rate = 10000000;
- break;
- case 31: // level 3.1
- bit_rate = 14000000;
- break;
- case 32: // level 3.2
- bit_rate = 20000000;
- break;
- case 40: // level 4.0
- bit_rate = 20000000;
- break;
- case 41: // level 4.1
- bit_rate = 50000000;
- break;
- case 42: // level 4.2
- bit_rate = 50000000;
- break;
- case 50: // level 5.0
- bit_rate = 135000000;
- break;
- case 51: // level 5.1
- bit_rate = 240000000;
- break;
- default:
- break;
- }
- break;
- case 100: // high profile
- switch (level_idc)
- {
- case 10: // level 1.0
- bit_rate = 80000;
- break;
- case 11: // level 1b / 1.1
- bit_rate = constraint_set3_flag ? 160000 : 240000;
- break;
- case 12: // level 1.2
- bit_rate = 480000;
- break;
- case 13: // level 1.3
- bit_rate = 960000;
- break;
- case 20: // level 2.0
- bit_rate = 2500000;
- break;
- case 21: // level 2.1
- bit_rate = 5000000;
- break;
- case 22: // level 2.2
- bit_rate = 5000000;
- break;
- case 30: // level 3.0
- bit_rate = 12500000;
- break;
- case 31: // level 3.1
- bit_rate = 17500000;
- break;
- case 32: // level 3.2
- bit_rate = 25000000;
- break;
- case 40: // level 4.0
- bit_rate = 25000000;
- break;
- case 41: // level 4.1
- bit_rate = 62500000;
- break;
- case 42: // level 4.2
- bit_rate = 62500000;
- break;
- case 50: // level 5.0
- bit_rate = 168750000;
- break;
- case 51: // level 5.1
- bit_rate = 300000000;
- break;
- default:
- break;
- }
- break;
- case 110: // high 10 profile
- switch (level_idc)
- {
- case 10: // level 1.0
- bit_rate = 192000;
- break;
- case 11: // level 1b / 1.1
- bit_rate = constraint_set3_flag ? 384000 : 576000;
- break;
- case 12: // level 1.2
- bit_rate = 115200;
- break;
- case 13: // level 1.3
- bit_rate = 2304000;
- break;
- case 20: // level 2.0
- bit_rate = 6000000;
- break;
- case 21: // level 2.1
- bit_rate = 12000000;
- break;
- case 22: // level 2.2
- bit_rate = 12000000;
- break;
- case 30: // level 3.0
- bit_rate = 30000000;
- break;
- case 31: // level 3.1
- bit_rate = 42000000;
- break;
- case 32: // level 3.2
- bit_rate = 60000000;
- break;
- case 40: // level 4.0
- bit_rate = 60000000;
- break;
- case 41: // level 4.1
- bit_rate = 150000000;
- break;
- case 42: // level 4.2
- bit_rate = 150000000;
- break;
- case 50: // level 5.0
- bit_rate = 405000000;
- break;
- case 51: // level 5.1
- bit_rate = 720000000;
- break;
- default:
- break;
- }
- break;
- case 122: // high 4:2:2 profile
- case 144: // high 4:4:4 profile
- switch (level_idc)
- {
- case 10: // level 1.0
- bit_rate = 256000;
- break;
- case 11: // level 1b / 1.1
- bit_rate = constraint_set3_flag ? 512000 : 768000;
- break;
- case 12: // level 1.2
- bit_rate = 1536000;
- break;
- case 13: // level 1.3
- bit_rate = 3072000;
- break;
- case 20: // level 2.0
- bit_rate = 8000000;
- break;
- case 21: // level 2.1
- bit_rate = 16000000;
- break;
- case 22: // level 2.2
- bit_rate = 16000000;
- break;
- case 30: // level 3.0
- bit_rate = 40000000;
- break;
- case 31: // level 3.1
- bit_rate = 56000000;
- break;
- case 32: // level 3.2
- bit_rate = 80000000;
- break;
- case 40: // level 4.0
- bit_rate = 80000000;
- break;
- case 41: // level 4.1
- bit_rate = 200000000;
- break;
- case 42: // level 4.2
- bit_rate = 200000000;
- break;
- case 50: // level 5.0
- bit_rate = 540000000;
- break;
- case 51: // level 5.1
- bit_rate = 960000000;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- if ((profile_idc == 100) || (profile_idc == 110) || (profile_idc == 122) || (profile_idc == 144))
+ if ((profile_idc == 100) || (profile_idc == 110) || (profile_idc == 122) || (profile_idc == 244) ||
+ (profile_idc==44) || (profile_idc==83) || (profile_idc==86))
{
if (bs.getUeGolomb() == 3) // chroma_format_idc
bs.skipBit(); // residual_colour_transform_flag
@@ -419,7 +197,7 @@ void cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt,
for (i = 0; i < j; ++i)
bs.skipSeGolomb(); // offset_for_ref_frame[i]
}
- bs.skipUeGolomb(); // num_ref_frames
+ bs.skipUeGolomb(); // max num_ref_frames
bs.skipBit(); // gaps_in_frame_num_value_allowed_flag
width = bs.getUeGolomb() + 1; // pic_width_in_mbs_minus1
height = bs.getUeGolomb() + 1; // pic_height_in_mbs_minus1
@@ -427,7 +205,7 @@ void cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt,
width *= 16;
height *= 16 * (frame_mbs_only_flag ? 1 : 2);
if (!frame_mbs_only_flag)
- mb_adaptive_frame_field_flag = bs.getBit(); // mb_adaptive_frame_field_flag
+ bs.skipBit(); // mb_adaptive_frame_field_flag
bs.skipBit(); // direct_8x8_inference_flag
if (bs.getBit()) // frame_cropping_flag
{
@@ -458,7 +236,7 @@ void cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt,
bs.skipBit(); // overscan_approriate_flag
if (bs.getBit()) // video_signal_type_present_flag
{
- video_format = bs.getBits(3); // video_format
+ bs.skipBits(3); // video_format
bs.skipBit(); // video_full_range_flag
if (bs.getBit()) // colour_description_present_flag
{
@@ -478,64 +256,68 @@ void cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt,
num_units_in_tick = bs.getU32(); // num_units_in_tick
time_scale = bs.getU32(); // time_scale
if (num_units_in_tick > 0)
- frame_rate = time_scale / num_units_in_tick;
- bs.skipBit(); // fixed_frame_rate_flag
- }
- int nal_hrd_parameters_present_flag = bs.getBit(); // nal_hrd_parameters_present_flag
- if (nal_hrd_parameters_present_flag)
- {
- int cpb_cnt_minus1;
- cpb_cnt_minus1 = bs.getUeGolomb(); // cpb_cnt_minus1
- bs.skipBits(4); // bit_rate_scale
- bs.skipBits(4); // cpb_size_scale
- for (int i = 0; i < cpb_cnt_minus1; ++i)
- {
- bs.skipUeGolomb(); // bit_rate_value_minus1[i]
- bs.skipUeGolomb(); // cpb_size_value_minus1[i]
- bs.skipBit(); // cbr_flag[i]
- }
- bs.skipBits(5); // initial_cpb_removal_delay_length_minus1
- bs.skipBits(5); // cpb_removal_delay_length_minus1
- bs.skipBits(5); // dpb_output_delay_length_minus1
- time_offset_length = bs.getBits(5); // time_offset_length
- }
- int vlc_hrd_parameters_present_flag = bs.getBit(); // vlc_hrd_parameters_present_flag
- if (vlc_hrd_parameters_present_flag)
- {
- int cpb_cnt_minus1;
- cpb_cnt_minus1 = bs.getUeGolomb(); // cpb_cnt_minus1
- bs.skipBits(4); // bit_rate_scale
- bs.skipBits(4); // cpb_size_scale
- for (int i = 0; i < cpb_cnt_minus1; ++i)
- {
- bs.skipUeGolomb(); // bit_rate_value_minus1[i]
- bs.skipUeGolomb(); // cpb_size_value_minus1[i]
- bs.skipBit(); // cbr_flag[i]
- }
- bs.skipBits(5); // initial_cpb_removal_delay_length_minus1
- bs.skipBits(5); // cpb_removal_delay_length_minus1
- bs.skipBits(5); // dpb_output_delay_length_minus1
- time_offset_length = bs.getBits(5);// time_offset_length
- }
- cpb_dpb_delays_present_flag = (nal_hrd_parameters_present_flag | vlc_hrd_parameters_present_flag);
- if (cpb_dpb_delays_present_flag)
- bs.skipBit(); // low_delay_hrd_flag
- pic_struct_present_flag = bs.getBit(); // pic_struct_present_flag
- if (bs.getBit()) // bitstream_restriction_flag
- {
- bs.skipBit(); // motion_vectors_over_pic_boundaries_flag
- bs.skipUeGolomb(); // max_bytes_per_pic_denom
- bs.skipUeGolomb(); // max_bits_per_mb_denom
- bs.skipUeGolomb(); // log2_max_mv_length_horizontal
- bs.skipUeGolomb(); // log2_max_mv_length_vertical
- bs.skipUeGolomb(); // num_reorder_frames
- bs.skipUeGolomb(); // max_dec_frame_buffering
+ frame_rate = time_scale / (2*num_units_in_tick);
+
+ //bs.skipBit(); // fixed_frame_rate_flag
}
+ /*
+ int nal_hrd_parameters_present_flag = bs.getBit(); // nal_hrd_parameters_present_flag
+ if (nal_hrd_parameters_present_flag)
+ {
+ int cpb_cnt_minus1;
+ cpb_cnt_minus1 = bs.getUeGolomb(); // cpb_cnt_minus1
+ bs.skipBits(4); // bit_rate_scale
+ bs.skipBits(4); // cpb_size_scale
+ for (int i = 0; i <= cpb_cnt_minus1; i++)
+ {
+ bs.skipUeGolomb(); // bit_rate_value_minus1[i]
+ bs.skipUeGolomb(); // cpb_size_value_minus1[i]
+ bs.skipBit(); // cbr_flag[i]
+ }
+ bs.skipBits(5); // initial_cpb_removal_delay_length_minus1
+ bs.skipBits(5); // cpb_removal_delay_length_minus1
+ bs.skipBits(5); // dpb_output_delay_length_minus1
+ bs.skipBits(5); // time_offset_length
+ }
+ int vlc_hrd_parameters_present_flag = bs.getBit(); // vlc_hrd_parameters_present_flag
+ if (vlc_hrd_parameters_present_flag)
+ {
+ int cpb_cnt_minus1;
+ cpb_cnt_minus1 = bs.getUeGolomb(); // cpb_cnt_minus1
+ bs.skipBits(4); // bit_rate_scale
+ bs.skipBits(4); // cpb_size_scale
+ for (int i = 0; i <= cpb_cnt_minus1; i++)
+ {
+ bs.skipUeGolomb(); // bit_rate_value_minus1[i]
+ bs.skipUeGolomb(); // cpb_size_value_minus1[i]
+ bs.skipBit(); // cbr_flag[i]
+ }
+ bs.skipBits(5); // initial_cpb_removal_delay_length_minus1
+ bs.skipBits(5); // cpb_removal_delay_length_minus1
+ bs.skipBits(5); // dpb_output_delay_length_minus1
+ bs.skipBits(5); // time_offset_length
+ }
+ cpb_dpb_delays_present_flag = (nal_hrd_parameters_present_flag | vlc_hrd_parameters_present_flag);
+ if (cpb_dpb_delays_present_flag)
+ bs.skipBit(); // low_delay_hrd_flag
+ bs.skipBit(); // pic_struct_present_flag
+ if (bs.getBit()) // bitstream_restriction_flag
+ {
+ bs.skipBit(); // motion_vectors_over_pic_boundaries_flag
+ bs.skipUeGolomb(); // max_bytes_per_pic_denom
+ bs.skipUeGolomb(); // max_bits_per_mb_denom
+ bs.skipUeGolomb(); // log2_max_mv_length_horizontal
+ bs.skipUeGolomb(); // log2_max_mv_length_vertical
+ bs.skipUeGolomb(); // num_reorder_frames
+ bs.skipUeGolomb(); // max_dec_frame_buffering
+ }
+ */
}
if ((bs.getIndex() / 8)>0)
{
// set values
+ maContext->Video.Info.FramesPerSecond=frame_rate;
maContext->Video.Info.Width=width;
maContext->Video.Info.Height=height;
@@ -544,6 +326,30 @@ void cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt,
case 1:
maContext->Video.Info.AspectRatio.Num=1;
maContext->Video.Info.AspectRatio.Den=1;
+
+ if (height==1080)
+ {
+ if (width==1920)
+ {
+ maContext->Video.Info.AspectRatio.Num=16;
+ maContext->Video.Info.AspectRatio.Den=9;
+ }
+ }
+
+ if (height==720)
+ {
+ if (width==960)
+ {
+ maContext->Video.Info.AspectRatio.Num=4;
+ maContext->Video.Info.AspectRatio.Den=3;
+ }
+
+ if (width==1280)
+ {
+ maContext->Video.Info.AspectRatio.Num=16;
+ maContext->Video.Info.AspectRatio.Den=9;
+ }
+ }
break;
case 2:
maContext->Video.Info.AspectRatio.Num=12;
@@ -608,13 +414,22 @@ void cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt,
}
}
}
+ return false;
}
-void cMarkAdStreamInfo::FindH262VideoInfos(MarkAdContext *maContext, uchar *pkt, int len)
+const uint8_t *cMarkAdStreamInfo::nextStartCode(const uint8_t *start, const uint8_t *end)
{
- if ((!maContext) || (!pkt) || (!len)) return;
+ for (end -= 4; start < end; ++start)
+ {
+ if ((start[0] == 0x00) && (start[1] == 0x00) && (start[2] == 0x00) && (start[3] == 0x01))
+ return start;
+ }
+ return (end + 4);
+}
- maContext->Video.Info.Pict_Type=0;
+bool cMarkAdStreamInfo::FindH262VideoInfos(MarkAdContext *maContext, uchar *pkt, int len)
+{
+ if ((!maContext) || (!pkt) || (!len)) return false;
struct H262_SequenceHdr
{
@@ -665,7 +480,7 @@ unsigned TemporalReferenceL:
if (pichdr->Sync1==0 && pichdr->Sync2==0 && pichdr->Sync3==1 && pichdr->Sync4==0)
{
- if (maContext->Video.Info.Height==0) return;
+ if (maContext->Video.Info.Height==0) return false;
switch (pichdr->CodingType)
{
@@ -682,9 +497,10 @@ unsigned TemporalReferenceL:
maContext->Video.Info.Pict_Type=MA_D_TYPE;
break;
default:
- maContext->Video.Info.Pict_Type=0;
+ return false;
break;
}
+ return true;
}
if (seqhdr->Sync1==0 && seqhdr->Sync2==0 && seqhdr->Sync3==1 && seqhdr->Sync4==0xb3)
@@ -714,9 +530,127 @@ unsigned TemporalReferenceL:
default:
break;
}
+
+ switch (seqhdr->FrameRateIndex)
+ {
+ case 1:
+ maContext->Video.Info.FramesPerSecond=24000/1001; // 23.976 fps NTSC encapsulated
+ break;
+ case 2:
+ maContext->Video.Info.FramesPerSecond=24.0; // Standard international cinema film rate
+ break;
+ case 3:
+ maContext->Video.Info.FramesPerSecond=25.0; // PAL (625/50) video frame rate
+ break;
+
+ case 4:
+ maContext->Video.Info.FramesPerSecond=30000/1001; // 29.97 NTSC video frame rate
+ break;
+
+ case 5:
+ maContext->Video.Info.FramesPerSecond=30.0; // NTSC drop frame (525/60) video frame rate
+ break;
+
+ case 6:
+ maContext->Video.Info.FramesPerSecond=50.0; // double frame rate/progressive PAL
+ break;
+
+ case 7:
+ maContext->Video.Info.FramesPerSecond=60000/1001; // double frame rate NTSC
+ break;
+
+ case 8:
+ maContext->Video.Info.FramesPerSecond=60.0; // double frame rate drop-frame NTSC
+ break;
+
+ default:
+ break;
+ }
+
+ }
+ return false;
+}
+
+/*
+// taken from ffmpeg
+int cMarkAdStreamInfo::nalUnescape(uint8_t *dst, const uint8_t *src, int length)
+{
+ int i;
+
+#if HAVE_FAST_UNALIGNED
+# if HAVE_FAST_64BIT
+# define RS 7
+ for (i=0; i+1<length; i+=9)
+ {
+ if (!((~*(const uint64_t*)(src+i) & (*(const uint64_t*)(src+i) - 0x0100010001000101ULL)) & 0x8000800080008080ULL))
+# else
+# define RS 3
+ for (i=0; i+1<length; i+=5)
+ {
+ if (!((~*(const uint32_t*)(src+i) & (*(const uint32_t*)(src+i) - 0x01000101U)) & 0x80008080U))
+# endif
+ continue;
+ if (i>0 && !src[i]) i--;
+ while (src[i]) i++;
+#else
+# define RS 0
+ for (i=0; i+1<length; i+=2)
+ {
+ if (src[i]) continue;
+ if (i>0 && src[i-1]==0) i--;
+#endif
+ if (i+2<length && src[i+1]==0 && src[i+2]<=3)
+ {
+ if (src[i+2]!=3)
+ {
+ // startcode, so we must be past the end
+ length=i;
+ }
+ break;
+ }
+ i-= RS;
+ }
+
+ memcpy(dst,src,i);
+
+ if (i>=length-1) //no escaped 0
+ {
+ return length;
+ }
+
+ int si,di;
+ si=di=i;
+ while (si+2<length)
+ {
+ //remove escapes (very rare 1:2^22)
+ if (src[si+2]>3)
+ {
+ dst[di++]= src[si++];
+ dst[di++]= src[si++];
+ }
+ else if (src[si]==0 && src[si+1]==0)
+ {
+ if (src[si+2]==3) //escape
+ {
+ dst[di++]= 0;
+ dst[di++]= 0;
+ si+=3;
+ continue;
+ }
+ else //next start code
+ goto nsc;
+ }
+
+ dst[di++]= src[si++];
}
+ while (si<length)
+ dst[di++]= src[si++];
+nsc:
+ return di;
}
+*/
+
// taken from femon
int cMarkAdStreamInfo::nalUnescape(uint8_t *dst, const uint8_t *src, int len)
@@ -744,9 +678,10 @@ int cMarkAdStreamInfo::nalUnescape(uint8_t *dst, const uint8_t *src, int len)
return d;
}
+
cBitStream::cBitStream(const uint8_t *buf, const int len)
: data(buf),
- count(len),
+ count(len*8),
index(0)
{
}
diff --git a/streaminfo.h b/streaminfo.h
index 5c74b0c..7b94e21 100644
--- a/streaminfo.h
+++ b/streaminfo.h
@@ -10,6 +10,7 @@
#define __streaminfo_h_
#include <stdint.h>
+#include <string.h>
#include "global.h"
@@ -25,12 +26,12 @@ private:
NAL_END_SEQ = 0x0A // End of Sequence
};
int nalUnescape(uint8_t *dst, const uint8_t *src, int len);
-
- void FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt, int len);
- void FindH262VideoInfos(MarkAdContext *maContext, uchar *pkt, int len);
+ const uint8_t *nextStartCode(const uint8_t *start, const uint8_t *end);
+ bool FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt, int len);
+ bool FindH262VideoInfos(MarkAdContext *maContext, uchar *pkt, int len);
public:
- void FindVideoInfos(MarkAdContext *maContext, uchar *pkt, int len);
- void FindAC3AudioInfos(MarkAdContext *maContext, uchar *espkt, int eslen);
+ bool FindVideoInfos(MarkAdContext *maContext, uchar *pkt, int len);
+ bool FindAC3AudioInfos(MarkAdContext *maContext, uchar *espkt, int eslen);
};
diff --git a/ts2pkt.cpp b/ts2pkt.cpp
index dc624ee..de03992 100644
--- a/ts2pkt.cpp
+++ b/ts2pkt.cpp
@@ -22,6 +22,7 @@ cMarkAdTS2Pkt::~cMarkAdTS2Pkt()
void cMarkAdTS2Pkt::Reset(int ErrIndex)
{
+ sync=false;
switch (ErrIndex)
{
case MA_ERR_TSSIZE:
@@ -113,6 +114,12 @@ void cMarkAdTS2Pkt::Process(MarkAdPid Pid, uchar *TSData, int TSSize, uchar **Pk
return; // not for us
}
+ if (tshdr->PayloadStart) sync=true;
+ if (!sync)
+ {
+ return; // not synced
+ }
+
if ((counter!=-1) && (((counter+1) & 0xF)!=tshdr->Counter))
{
if (counter==tshdr->Counter)
@@ -177,6 +184,13 @@ void cMarkAdTS2Pkt::Process(MarkAdPid Pid, uchar *TSData, int TSSize, uchar **Pk
queue->Put(buf,buflen);
}
- *PktData=queue->GetPacket(PktSize,MA_PACKET_PKT);
+ if (Pid.Type==MARKAD_PIDTYPE_VIDEO_H264)
+ {
+ *PktData=queue->GetPacket(PktSize,MA_PACKET_H264);
+ }
+ else
+ {
+ *PktData=queue->GetPacket(PktSize,MA_PACKET_PKT);
+ }
return;
}
diff --git a/ts2pkt.h b/ts2pkt.h
index 13efe54..36e5066 100644
--- a/ts2pkt.h
+++ b/ts2pkt.h
@@ -23,7 +23,7 @@ typedef unsigned char uchar;
#include <string.h>
#include "global.h"
-#include "tools.h"
+#include "queue.h"
class cMarkAdTS2Pkt
{
@@ -104,6 +104,7 @@ unsigned Length:
int recvnumber;
int counter;
+ bool sync;
cMarkAdPaketQueue *queue;
diff --git a/vdr2pkt.h b/vdr2pkt.h
index 1820fbf..eacd7af 100644
--- a/vdr2pkt.h
+++ b/vdr2pkt.h
@@ -14,7 +14,7 @@ typedef unsigned char uchar;
#endif
#include "global.h"
-#include "tools.h"
+#include "queue.h"
class cMarkAdVDR2Pkt
{
diff --git a/version.h b/version.h
index 548a147..3bf67b5 100644
--- a/version.h
+++ b/version.h
@@ -9,6 +9,6 @@
#ifndef __version_h_
#define __version_h_
-static const char *VERSION = "0.0.4";
+static const char *VERSION = "0.0.5";
#endif
diff --git a/video.cpp b/video.cpp
index 858b49f..0d389e4 100644
--- a/video.cpp
+++ b/video.cpp
@@ -16,86 +16,124 @@ cMarkAdLogo::cMarkAdLogo(int RecvNumber, MarkAdContext *maContext)
GX[0][0] = -1;
GX[0][1] = 0;
GX[0][2] = 1;
- GX[1][0] = -2; // 2
+ GX[1][0] = -2;
GX[1][1] = 0;
- GX[1][2] = 2; // 2
+ GX[1][2] = 2;
GX[2][0] = -1;
GX[2][1] = 0;
GX[2][2] = 1;
// 3x3 GY Sobel mask
GY[0][0] = 1;
- GY[0][1] = 2; // 2
+ GY[0][1] = 2;
GY[0][2] = 1;
GY[1][0] = 0;
GY[1][1] = 0;
GY[1][2] = 0;
GY[2][0] = -1;
- GY[2][1] = -2; //2
+ GY[2][1] = -2;
GY[2][2] = -1;
- plane=NULL;
- first=true;
+ 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;
+
+ framecnt=0;
+ savedlastiframe=-1;
+ logostart=-1;
+ logostate=-1;
+ counter=0;
}
cMarkAdLogo::~cMarkAdLogo()
{
- if (plane) free(plane);
}
-void cMarkAdLogo::SaveFrame(int LastIFrame)
+void cMarkAdLogo::SaveLogo(int corner, int lastiframe)
{
if (!macontext) return;
if (!macontext->Video.Info.Width) return;
- if (!plane) return;
FILE *pFile;
char szFilename[32];
// Open file
- sprintf(szFilename, "frame%06d.pgm", LastIFrame);
+ sprintf(szFilename, "%iframe%06d.pgm", corner,lastiframe);
pFile=fopen(szFilename, "wb");
if (pFile==NULL)
return;
// Write header
- fprintf(pFile, "P5\n%d %d\n255\n", macontext->Video.Info.Width,LOGOHEIGHT);
+ fprintf(pFile, "P5\n%d %d\n255\n", LOGOWIDTH,LOGOHEIGHT);
// Write pixel data
- fwrite(plane,1,macontext->Video.Info.Width*LOGOHEIGHT,pFile);
+ fwrite(area[corner].plane,1,LOGOWIDTH*LOGOHEIGHT,pFile);
// Close file
fclose(pFile);
-
- dsyslog("markad saved frame %i",LastIFrame);
- if (LastIFrame>750) abort();
}
-int cMarkAdLogo::Process(int LastIFrame)
+void cMarkAdLogo::CheckCorner(int corner)
{
- if (!macontext) return 0;
- if (!macontext->Video.Info.Width) return 0;
- if (!macontext->Video.Data.Valid) return 0;
+ 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;
- if (!plane)
+ int xstart,xend,ystart,yend;
+
+ switch (corner)
{
- plane=(uchar *) malloc(LOGOHEIGHT*macontext->Video.Info.Width);
- if (!plane) return 0;
+ case TOP_LEFT:
+ xstart=0;
+ xend=LOGOWIDTH;
+ ystart=0;
+ yend=LOGOHEIGHT;
+ break;
+ case TOP_RIGHT:
+ xstart=macontext->Video.Info.Width-LOGOWIDTH;
+ xend=macontext->Video.Info.Width;
+ ystart=0;
+ yend=LOGOHEIGHT;
+ break;
+ case BOTTOM_LEFT:
+ xstart=0;
+ xend=LOGOWIDTH;
+ ystart=macontext->Video.Info.Height-LOGOHEIGHT;
+ yend=macontext->Video.Info.Height;
+ break;
+ case BOTTOM_RIGHT:
+ xstart=macontext->Video.Info.Width-LOGOWIDTH;
+ xend=macontext->Video.Info.Width;
+ ystart=macontext->Video.Info.Height-LOGOHEIGHT;
+ yend=macontext->Video.Info.Height;
+ break;
+ default:
+ return;
}
int SUM;
int sumX,sumY;
-
- for (int Y=0; Y<=LOGOHEIGHT-1; Y++)
+ area[corner].blackpixel=0;
+ for (int Y=ystart; Y<=yend-1; Y++)
{
- for (int X=0; X<=macontext->Video.Info.Width-1; X++)
+ for (int X=xstart; X<=xend-1; X++)
{
sumX=0;
sumY=0;
// image boundaries
- if (Y==0 || Y==LOGOHEIGHT-1)
+ if (Y<(ystart+15) || Y>(yend-15))
SUM=0;
- else if (X==0 || X==macontext->Video.Info.Width-1)
+ else if (X<(xstart+15) || X>(xend-15))
SUM=0;
// convolution starts here
else
@@ -127,12 +165,151 @@ int cMarkAdLogo::Process(int LastIFrame)
if (SUM>=127) SUM=255;
if (SUM<127) SUM=0;
- plane[X+Y*macontext->Video.Info.Width]=255-(uchar) (SUM);
+ int val = 255-(uchar) SUM;
+
+ if (area[corner].init)
+ {
+ area[corner].plane[(X-xstart)+(Y-ystart)*LOGOWIDTH]=val;
+ }
+ else
+ {
+ if (area[corner].plane[(X-xstart)+(Y-ystart)*LOGOWIDTH]!=val)
+ {
+ area[corner].plane[(X-xstart)+(Y-ystart)*LOGOWIDTH]=255;
+ }
+ }
+
+ if (area[corner].plane[(X-xstart)+(Y-ystart)*LOGOWIDTH]!=255)
+ area[corner].blackpixel++;
}
+
}
- //SaveFrame(LastIFrame);
+ area[corner].init=false;
+ if (area[corner].blackpixel<100) area[corner].blackpixel=0;
+}
- return 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++)
+ {
+ sum+=area[i].blackpixel;
+ }
+ 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;
+}
+*/
+
+int cMarkAdLogo::Process(int LastIFrame)
+{
+ if (!macontext) return 0;
+ if (!macontext->Video.Info.Width) return 0;
+ if (!macontext->Video.Data.Valid) return 0;
+
+ if ((macontext->Video.Info.Width>720) && (LOGOWIDTH==192))
+ {
+ LOGOWIDTH=288;
+ }
+
+ int ret=0;
+ CheckCorners(LastIFrame);
+// if (framecnt>=250) abort();
+ /*
+ if (framecnt>=MAXFRAMES)
+ {
+ if (logostate==-1)
+ {
+ if (LogoVisible())
+ {
+ 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;
+ }
+ }
+ }
+ }
+ */
+ if (savedlastiframe!=-1) framecnt+=(LastIFrame-savedlastiframe);
+ savedlastiframe=LastIFrame;
+
+ return ret;
}
cMarkAdBlackBordersHoriz::cMarkAdBlackBordersHoriz(int RecvNumber, MarkAdContext *maContext)
@@ -177,62 +354,25 @@ int cMarkAdBlackBordersHoriz::Process(int LastIFrame, int *BorderIFrame)
#define BRIGHTNESS 20
if (!macontext) return 0;
if (!macontext->Video.Data.Valid) return 0;
- return 0;
+ if (macontext->Video.Data.PlaneLinesize[0]!=macontext->Video.Info.Width) return 0;
*BorderIFrame=borderiframe;
- int x,y;
+ int x;
bool ftop=true,fbottom=true;
- if (macontext->Video.Data.PlaneLinesize[0]!=macontext->Video.Info.Width)
+ // "fast" method
+ for (x=(macontext->Video.Info.Height-CHECKHEIGHT)*macontext->Video.Info.Width;
+ x<macontext->Video.Info.Height*macontext->Video.Info.Width; x++)
{
- // slow (?) method
- for (y=(macontext->Video.Info.Height-CHECKHEIGHT); y<macontext->Video.Info.Height; y++)
- {
- for (x=0; x<macontext->Video.Info.Width; x++)
- {
- if (macontext->Video.Data.Plane[0][y*macontext->Video.Data.PlaneLinesize[0]+x]>
- BRIGHTNESS)
- {
- fbottom=false;
- y=macontext->Video.Info.Height;
- break;
- }
- }
- }
-
- if (fbottom)
- {
- for (y=0; y<CHECKHEIGHT; y++)
- {
- for (x=0; x<macontext->Video.Info.Width; x++)
- {
- if (macontext->Video.Data.Plane[0][y*macontext->Video.Data.PlaneLinesize[0]+x]
- >BRIGHTNESS)
- {
- ftop=false;
- y=CHECKHEIGHT;
- break;
- }
- }
- }
- }
+ if (macontext->Video.Data.Plane[0][x]>BRIGHTNESS) fbottom=false;
}
- else
- {
- // "fast" method
- for (x=(macontext->Video.Info.Height-CHECKHEIGHT)*macontext->Video.Info.Width;
- x<macontext->Video.Info.Height*macontext->Video.Info.Width; x++)
- {
- if (macontext->Video.Data.Plane[0][x]>BRIGHTNESS) fbottom=false;
- }
- if (fbottom)
+ if (fbottom)
+ {
+ for (x=0; x<(macontext->Video.Info.Width*CHECKHEIGHT); x++)
{
- for (x=0; x<(macontext->Video.Info.Width*CHECKHEIGHT); x++)
- {
- if (macontext->Video.Data.Plane[0][x]>BRIGHTNESS) ftop=false;
- }
+ if (macontext->Video.Data.Plane[0][x]>BRIGHTNESS) ftop=false;
}
}
@@ -338,42 +478,61 @@ bool cMarkAdVideo::AspectRatioChange(MarkAdAspectRatio *a, MarkAdAspectRatio *b)
}
-
MarkAdMark *cMarkAdVideo::Process(int LastIFrame)
{
ResetMark();
if (!LastIFrame) return NULL;
- logo->Process(LastIFrame);
-
- if (macontext->State.ContentStarted)
+ int lret=logo->Process(LastIFrame);
+ if (lret!=0)
{
- int borderiframe;
- int hret=hborder->Process(LastIFrame,&borderiframe);
-
- if ((hret>0) && (borderiframe))
+ char *buf=NULL;
+ if (lret>0)
{
- char *buf=NULL;
- if (asprintf(&buf,"detected start of horiz. borders (%i)",borderiframe)!=-1)
+ if (asprintf(&buf,"detected logo start (%i)",LastIFrame)!=-1)
{
isyslog("markad [%i]: %s",recvnumber,buf);
- AddMark(borderiframe,buf);
+ AddMark(LastIFrame,buf);
free(buf);
}
}
-
- if ((hret<0) && (borderiframe))
+ else
{
- char *buf=NULL;
- if (asprintf(&buf,"detected stop of horiz. borders (%i)",borderiframe)!=-1)
+ if (asprintf(&buf,"detected logo stop (%i)",LastIFrame)!=-1)
{
isyslog("markad [%i]: %s",recvnumber,buf);
- AddMark(borderiframe,buf);
+ AddMark(LastIFrame,buf);
free(buf);
}
}
}
+
+ int borderiframe;
+ int hret=hborder->Process(LastIFrame,&borderiframe);
+
+ if ((hret>0) && (borderiframe))
+ {
+ char *buf=NULL;
+ if (asprintf(&buf,"detected start of horiz. borders (%i)",borderiframe)!=-1)
+ {
+ isyslog("markad [%i]: %s",recvnumber,buf);
+ AddMark(borderiframe,buf);
+ free(buf);
+ }
+ }
+
+ if ((hret<0) && (borderiframe))
+ {
+ char *buf=NULL;
+ if (asprintf(&buf,"detected stop of horiz. borders (%i)",borderiframe)!=-1)
+ {
+ isyslog("markad [%i]: %s",recvnumber,buf);
+ AddMark(borderiframe,buf);
+ free(buf);
+ }
+ }
+
if (AspectRatioChange(&macontext->Video.Info.AspectRatio,&aspectratio))
{
char *buf=NULL;
diff --git a/video.h b/video.h
index ecc6d74..11805af 100644
--- a/video.h
+++ b/video.h
@@ -24,16 +24,52 @@
class cMarkAdLogo
{
private:
-#define LOGOHEIGHT 100
+#define MAXFRAMES 25
+
+ enum
+ {
+ TOP_LEFT,
+ TOP_RIGHT,
+ BOTTOM_LEFT,
+ BOTTOM_RIGHT
+ };
+
+ int LOGOHEIGHT; // max. 100
+ int LOGOWIDTH; // max. 288
+
+ struct area
+ {
+ uchar plane[28800];
+ bool init;
+ int blackpixel;
+// int cntfound;
+ } area[4];
+
+ int savedlastiframe;
+ int framecnt;
+
+ int logostart;
+
int GX[3][3];
int GY[3][3];
- uchar *plane;
- bool first;
+
+ 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);
public:
cMarkAdLogo(int RecvNumber, MarkAdContext *maContext);
~cMarkAdLogo();
- void SaveFrame(int LastIFrame);
int Process(int LastIFrame);
};