diff -u --new-file '--exclude=version.h' a/plugin/Makefile b/plugin/Makefile
--- a/plugin/Makefile	2019-12-09 19:34:14.812757828 +0100
+++ b/plugin/Makefile	2019-12-09 19:34:14.836758064 +0100
@@ -27,6 +27,10 @@
 
 export CFLAGS   = $(call PKGCFG,cflags)
 export CXXFLAGS = $(call PKGCFG,cxxflags)
+CXXVERION=$(shell $(CXX) -dumpversion)
+ifeq ($(CXXVERION),4.8)
+export CXXFLAGS += -std=c++11   # to prevent a lot of compiler warnings with Ubuntu 14.04
+endif
 
 ### The version number of VDR's plugin API:
 
diff -u --new-file '--exclude=version.h' a/plugin/markad.cpp b/plugin/markad.cpp
--- a/plugin/markad.cpp	2017-03-13 18:56:14.000000000 +0100
+++ b/plugin/markad.cpp	2019-12-09 19:34:14.836758064 +0100
@@ -54,10 +54,15 @@
 const char *cPluginMarkAd::CommandLineHelp(void)
 {
     // Return a string that describes all known command line options.
-    return "  -b DIR,   --bindir=DIR        use DIR as location for markad executable\n"
-           "                                (default: /usr/bin)\n"
-           "  -l DIR    --logocachedir=DIR  use DIR as location for markad logos\n"
-           "                                (default: /var/lib/markad)\n";
+    return "  -b DIR,   --bindir=DIR         use DIR as location for markad executable\n"
+           "                                 (default: /usr/bin)\n"
+           "  -l DIR    --logocachedir=DIR   use DIR as location for markad logos\n"
+           "                                 (default: /var/lib/markad)\n"
+           "            --loglevel=<level>   sets loglevel to the specified value\n"
+           "                                 <level> 1=error 2=info 3=debug 4=trace\n"
+           "            --astopoffs=<value>  (default is 100)\n"
+           "                                  assumed stop offset in seconds range from 0 to 240\n"
+           "            --cDecoder            use new cDecoder class)\n";
 }
 
 bool cPluginMarkAd::ProcessArgs(int argc, char *argv[])
@@ -65,9 +70,11 @@
     // Command line argument processing
     static struct option long_options[] =
     {
-        { "bindir",      required_argument, NULL, 'b'
-        },
-        { "logocachedir",      required_argument, NULL, 'l'},
+        { "bindir",       required_argument, NULL, 'b'},
+        { "logocachedir", required_argument, NULL, 'l'},
+        { "loglevel",     required_argument, NULL, '1'},
+        { "astopoffs",    required_argument, NULL, '2'},
+        { "cDecoder",      no_argument,       NULL, '3'},
         { NULL, 0, NULL, 0 }
     };
 
@@ -103,6 +110,15 @@
                 return false;
             }
             break;
+        case '1':
+            loglevel=atoi(optarg);
+            break;
+        case '2':
+            astopoffs=atoi(optarg);
+            break;
+        case '3':
+            cDecoder=true;
+            break;
         default:
             return false;
         }
@@ -132,6 +148,13 @@
     // Start any background activities the plugin shall perform.
     lastcheck=0;
     setup.PluginName=Name();
+    if (loglevel) 
+        if(! asprintf(&setup.LogLevel," --loglevel=%i ",loglevel))
+            esyslog("markad: asprintf ouf of memory");
+    if (astopoffs>=0)
+        if(! asprintf(&setup.aStopOffs," --astopoffs=%i ",astopoffs))
+            esyslog("markad: asprintf ouf of memory");
+    setup.cDecoder=cDecoder;
     setup.LogoDir=logodir;
     statusMonitor = new cStatusMarkAd(bindir,logodir,&setup);
     return (statusMonitor!=NULL);
diff -u --new-file '--exclude=version.h' a/plugin/markad.h b/plugin/markad.h
--- a/plugin/markad.h	2017-03-13 18:56:14.000000000 +0100
+++ b/plugin/markad.h	2019-12-09 19:34:14.836758064 +0100
@@ -23,6 +23,9 @@
     cStatusMarkAd *statusMonitor;
     char *bindir;
     char *logodir;
+    int loglevel=0;
+    int astopoffs=-1;
+    bool cDecoder=false;
     struct setup setup;
     char title[80];
     time_t lastcheck;
diff -u --new-file '--exclude=version.h' a/plugin/setup.h b/plugin/setup.h
--- a/plugin/setup.h	2017-03-13 18:56:14.000000000 +0100
+++ b/plugin/setup.h	2019-12-09 19:34:14.836758064 +0100
@@ -25,6 +25,9 @@
     bool LogoOnly;
     bool DeferredShutdown;
     const char *LogoDir;
+    char *LogLevel=NULL;
+    char *aStopOffs=NULL;
+    bool cDecoder=false;
     const char *PluginName;
 };
 
diff -u --new-file '--exclude=version.h' a/plugin/status.cpp b/plugin/status.cpp
--- a/plugin/status.cpp	2017-03-13 18:56:14.000000000 +0100
+++ b/plugin/status.cpp	2019-12-09 19:34:14.836758064 +0100
@@ -72,7 +72,7 @@
 {
     if ((Direct) && (Get(FileName)!=-1)) return false;
 
-    cString cmd = cString::sprintf("\"%s\"/markad %s%s%s%s%s%s%s -l \"%s\" %s \"%s\"",
+    cString cmd = cString::sprintf("\"%s\"/markad %s%s%s%s%s%s%s%s%s%s -l \"%s\" %s \"%s\"",
                                    bindir,
                                    setup->Verbose ? " -v " : "",
                                    setup->SaveInfo ? " -I " : "",
@@ -85,7 +85,11 @@
                                    setup->NoMargins ? " -i 4 " : "",
                                    setup->SecondPass ? "" : " --pass1only ",
                                    setup->Log2Rec ? " -R " : "",
-                                   logodir,Direct ? "-O after" : "--online=2 before",
+				   setup->LogLevel ? setup->LogLevel : "",
+				   setup->aStopOffs ? setup->aStopOffs : "",
+				   setup->cDecoder ? " --cDecoder " : "",
+                                   logodir,
+				   Direct ? "-O after" : "--online=2 before",
                                    FileName);
     usleep(1000000); // wait 1 second
     if (SystemExec(cmd)!=-1)
@@ -152,12 +156,13 @@
 #endif
         {
 #if APIVERSNUM>=10722
-            if (Timer->Recording() && const_cast<cDevice *>(Device)->IsTunedToTransponder(Timer->Channel()) &&
-            (difftime(time(NULL),Timer->StartTime())<60))
-            {
-                timer=Timer;
-                break;
-            }
+            if (Timer->Recording() && const_cast<cDevice *>(Device)->IsTunedToTransponder(Timer->Channel()))
+                if (difftime(time(NULL),Timer->StartTime())<60)
+                {
+                    timer=Timer;
+                    break;
+                }
+	        else esyslog("markad: recording start is later than timer start, ignoring");
 #else
             if (Timer->Recording() && Device->IsTunedToTransponder(Timer->Channel()) &&
                     (difftime(time(NULL),Timer->StartTime())<60))
@@ -301,9 +306,10 @@
     char *buf;
     if (asprintf(&buf,"%s/markad.pid",recs[Position].FileName)==-1) return false;
 
+    usleep(500*1000);   // wait 500ms to give markad time to create pid file
     FILE *fpid=fopen(buf,"r");
     if (fpid)
-    {
+    {  
         free(buf);
         int pid;
         ret=fscanf(fpid,"%10i\n",&pid);
@@ -312,6 +318,7 @@
     }
     else
     {
+	esyslog("markad: failed to open pid file %s with errno %i", buf, errno);
         if (errno==ENOENT)
         {
             // no such file or directory -> markad done or crashed
diff -u --new-file '--exclude=version.h' a/command/audio.cpp b/command/audio.cpp
--- a/command/audio.cpp	2017-03-13 18:56:14.000000000 +0100
+++ b/command/audio.cpp	2019-12-09 19:34:14.836758064 +0100
@@ -36,7 +36,7 @@
 void cMarkAdAudio::resetmark()
 {
     if (!mark.Type) return;
-    memset(&mark,0,sizeof(mark));
+    mark={};
 }
 
 void cMarkAdAudio::setmark(int type, int position, int channelsbefore, int channelsafter)
diff -u --new-file '--exclude=version.h' a/command/decoder.cpp b/command/decoder.cpp
--- a/command/decoder.cpp	2019-12-09 19:34:14.824757945 +0100
+++ b/command/decoder.cpp	2019-12-09 19:34:14.836758064 +0100
@@ -14,6 +14,8 @@
 #include <cstdlib>
 
 #include "decoder.h"
+#include "debug.h"
+
 
 #ifndef DECLARE_ALIGNED
 #define DECLARE_ALIGNED(n,t,v) t v __attribute__ ((aligned (n)))
@@ -544,3 +546,4 @@
     if (ret) addPkt=false;
     return ret;
 }
+
diff -u --new-file '--exclude=version.h' a/command/decoder_new.cpp b/command/decoder_new.cpp
--- a/command/decoder_new.cpp	1970-01-01 01:00:00.000000000 +0100
+++ b/command/decoder_new.cpp	2019-12-09 19:34:14.836758064 +0100
@@ -0,0 +1,475 @@
+#include "decoder_new.h"
+extern "C"{
+#include "debug.h"
+}
+
+
+cDecoder::cDecoder() {
+    av_init_packet(&avpkt);
+    codec = NULL;
+    codecCtx = NULL;
+}
+
+cDecoder::~cDecoder() {
+    av_packet_unref(&avpkt);
+    avcodec_free_context(&codecCtx);
+    avformat_close_input(&avctx);
+}
+
+bool cDecoder::DecodeDir(const char * recDir) {
+    if (!recDir) return false;
+    char *filename;
+    if (asprintf(&recordingDir,"%s",recDir)==-1) {
+        esyslog("cDecoder::DecodeDir(): failed to allocate string, out of memory?");
+        return false;
+    }
+    fileNumber++;
+    if (asprintf(&filename,"%s/%05i.ts",recDir,fileNumber)==-1) {
+        esyslog("cDecoder::DecodeDir(): failed to allocate string, out of memory?");
+        return false;
+    }
+    return this->DecodeFile(filename);
+}
+
+void cDecoder::Reset(){
+    fileNumber=0;
+    framenumber=0;
+    msgGetFrameInfo=false;
+}
+
+bool cDecoder::DecodeFile(const char * filename) {
+    if (!filename) return false;
+    if (avctx) avformat_close_input(&avctx);
+#if LIBAVCODEC_VERSION_INT < ((58<<16)+(54<<8)+100)
+    av_register_all();
+#endif
+    if (avformat_open_input(&avctx, filename, NULL, NULL) == 0) {
+        if (msgDecodeFile) isyslog("cDecoder::DecodeFile(): decode file %s",filename);
+    }
+    else {
+        if (fileNumber <= 1) esyslog("cDecoder::DecodeFile(): Could not open source file %s", filename);
+        return(false);
+    }
+    if (avformat_find_stream_info(avctx, NULL) <0) {
+        esyslog("cDecoder::DecodeFile(): Could not get stream infos %s", filename);
+        return(false);
+    }
+    for (unsigned int i=0; i<avctx->nb_streams; i++) {
+        if (isVideoStream()) {
+#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
+            codec=avcodec_find_decoder(avctx->streams[avpkt.stream_index]->codecpar->codec_id);
+#else
+            codec=avcodec_find_decoder(avctx->streams[avpkt.stream_index]->codec->codec_id);
+#endif
+            if (!codec) {
+                esyslog("cDecoder::DecodeFile(): could nit find decoder for stream");
+                return(false);
+            }
+            if (msgDecodeFile) isyslog("cDecoder::DecodeFile(): using decoder %s for stream %i",codec->long_name,i);
+            codecCtx=avcodec_alloc_context3(codec);
+            if (!codecCtx) {
+                esyslog("cDecoder::DecodeFile(): avcodec_alloc_context3 failed");
+                return(false);
+            }
+#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
+            if (avcodec_parameters_to_context(codecCtx,avctx->streams[avpkt.stream_index]->codecpar) < 0) {
+#else
+            if (avcodec_copy_context(codecCtx,avctx->streams[avpkt.stream_index]->codec) < 0) {
+#endif
+                esyslog("cDecoder::DecodeFile(): avcodec_parameters_to_context failed");
+                return(false);
+            }
+            if (avcodec_open2(codecCtx, codec, NULL) < 0) {
+                esyslog("cDecoder::DecodeFile(): avcodec_open2 failed");
+                return(false);
+            }
+            break;
+        }
+    }
+    msgDecodeFile=false;
+    return(true);
+}
+
+int cDecoder::GetVideoHeight() {
+    if (!avctx) return 0;
+    for (unsigned int i=0; i<avctx->nb_streams; i++) {
+#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
+        if (avctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+            return avctx->streams[i]->codecpar->height;
+#else
+        if (avctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+            return avctx->streams[i]->codec->height;
+#endif
+        }
+    }
+    esyslog("cDecoder::GetVideoHeight(): failed");
+    return 0;
+}
+
+int cDecoder::GetVideoWidth() {
+    if (!avctx) return 0;
+    for (unsigned int i=0; i<avctx->nb_streams; i++) {
+#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
+        if (avctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+            return avctx->streams[i]->codecpar->width;
+#else
+        if (avctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+            return avctx->streams[i]->codec->width;
+#endif
+        }
+    }
+    esyslog("cDecoder::GetVideoWidth(): failed");
+    return 0;
+}
+
+
+int cDecoder::GetVideoFramesPerSecond() {
+    if (!avctx) return 0;
+    for (unsigned int i=0; i<avctx->nb_streams; i++) {
+#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
+        if (avctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+#else
+        if (avctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+#endif
+            return av_q2d(avctx->streams[i]->avg_frame_rate);
+        }
+    }
+    esyslog("cDecoder::GetVideoFramesPerSecond(): could not find average frame rate");
+    return 0;
+}
+
+int cDecoder::GetVideoRealFrameRate() {
+    if (!avctx) return 0;
+    for (unsigned int i=0; i<avctx->nb_streams; i++) {
+#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
+        if (avctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+#else
+        if (avctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+#endif
+#if LIBAVCODEC_VERSION_INT >= ((58<<16)+(54<<8)+100)
+            return av_q2d(avctx->streams[i]->r_frame_rate);
+#else
+            return av_q2d(av_stream_get_r_frame_rate(avctx->streams[i]));
+#endif
+        }
+    }
+    esyslog("cDecoder::GetVideoRealFrameRate(): could not find real frame rate");
+    return 0;
+}
+
+
+bool cDecoder::GetNextFrame() {
+    if (!avctx) return false;
+    long int pts_time_ms=0;
+    iFrameData.Valid=false;
+    av_packet_unref(&avpkt);
+    if (av_read_frame(avctx, &avpkt) == 0 ) {
+#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
+       if (avctx->streams[avpkt.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+#else
+       if (avctx->streams[avpkt.stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+#endif
+             framenumber++;
+             if (isVideoIFrame()) {
+                 iFrameCount++;
+                 if ((iFrameInfoVector.empty()) || (framenumber > iFrameInfoVector.back().iFrameNumber)) {
+                     if (avpkt.pts != AV_NOPTS_VALUE) {   // store a iframe number pts index
+                         pts_time_ms=(avpkt.pts - avctx->streams[avpkt.stream_index]->start_time)*av_q2d(avctx->streams[avpkt.stream_index]->time_base)*100;
+                         iFrameInfo newFrameInfo;
+                         newFrameInfo.fileNumber=fileNumber;
+                         newFrameInfo.iFrameNumber=framenumber;
+                         newFrameInfo.pts_time_ms=pts_time_ms_LastFile+pts_time_ms;
+                         iFrameInfoVector.push_back(newFrameInfo);
+                     }
+                     else esyslog("cDecoder::GetNextFrame(): failed to get pts for frame %li", framenumber);
+                 }
+             }
+        }
+        return true;
+    }
+    pts_time_ms_LastFile += iFrameInfoVector.back().pts_time_ms;
+    dsyslog("cDecoder::GetNextFrame(): start time next file %li",pts_time_ms_LastFile);
+    return false;
+}
+
+bool cDecoder::SeekToFrame(long int iFrame) {
+    if (!avctx) return false;
+    if (framenumber > iFrame) {
+        dsyslog("cDecoder::SeekToFrame(): could not seek backward");
+        return false;
+    }
+    while (framenumber < iFrame) {
+        if (!this->GetNextFrame()) 
+            if (!this->DecodeDir(recordingDir)) {
+                dsyslog("cDecoder::SeekFrame(): failed for frame (%li) at frame (%li)", iFrame, framenumber);
+                return false;
+        }
+    }
+    return true;
+}
+
+bool cDecoder::GetFrameInfo(MarkAdContext *maContext) {
+    if (!avctx) return false;
+    iFrameData.Valid=false;
+    if (avFrame) av_frame_free(&avFrame);
+    if (isVideoStream()) {
+        if (isVideoIFrame() || stateEAGAIN) {
+            avFrame=av_frame_alloc();
+            if (!avFrame) {
+               esyslog("cDecoder::GetFrameInfo(): av_frame_alloc failed");
+               return false;
+            }
+#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
+            avFrame->height=avctx->streams[avpkt.stream_index]->codecpar->height;
+            avFrame->width=avctx->streams[avpkt.stream_index]->codecpar->width;
+            avFrame->format=codecCtx->pix_fmt;
+#else
+            avFrame->height=avctx->streams[avpkt.stream_index]->codec->height;
+            avFrame->width=avctx->streams[avpkt.stream_index]->codec->width;
+#endif
+            int rc=av_frame_get_buffer(avFrame,32);
+            if (rc != 0) {
+                esyslog("cDecoder::GetFrameInfo(): av_frame_get_buffer failed rc=%i", rc);
+                return false;
+            }
+
+#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
+//            dsyslog("---framenumber %li",framenumber);
+            rc=avcodec_send_packet(codecCtx,&avpkt);
+            if (rc  < 0) {
+                switch (rc) {
+                    case AVERROR(EAGAIN): 
+                        dsyslog("DEBUG: cDecoder::GetFrameInfo(): avcodec_send_packet error EAGAIN at frame %li", framenumber);
+                        break;
+                    case AVERROR(ENOMEM): 
+                        dsyslog("DEBUG: cDecoder::GetFrameInfo(): avcodec_send_packet error ENOMEM at frame %li", framenumber);
+                        break;
+                    case AVERROR(EINVAL): 
+                        dsyslog("DEBUG: cDecoder::GetFrameInfo(): avcodec_send_packet error EINVAL at frame %li", framenumber);
+                        break;
+                    case AVERROR_INVALIDDATA:
+                        dsyslog("DEBUG: cDecoder::GetFrameInfo(): avcodec_send_packet error AVERROR_INVALIDDATA at frame %li", framenumber); // this could happen on the start of a recording
+                        break;
+                    default: 
+                        dsyslog("DEBUG: cDecoder::GetFrameInfo(): avcodec_send_packet failed with rc=%i at frame %li",rc,framenumber);
+                        break;
+                }
+                return false;
+            }
+            rc = avcodec_receive_frame(codecCtx,avFrame);
+            if (rc < 0) {
+                switch (rc) {
+                    case AVERROR(EAGAIN): 
+                        tsyslog("TRACE: cDecoder::GetFrameInfo(): avcodec_receive_frame error EAGAIN at frame %li", framenumber); 
+                        stateEAGAIN=true;
+                        break;
+                    case AVERROR(EINVAL): 
+                        dsyslog("DEBUG: cDecoder::GetFrameInfo(): avcodec_receive_frame error EINVAL at frame %li", framenumber);
+                        break;
+                    default: 
+                        dsyslog("DEBUG: cDecoder::GetFrameInfo(): avcodec_receive_frame: decode of frame (%li) failed with return code %i", framenumber, rc);
+                        break;
+                }
+                return false;
+            }
+#else
+            int video_frame_ready=0;
+            rc=avcodec_decode_video2(codecCtx,avFrame,&video_frame_ready,&avpkt);
+            if (rc < 0) {
+                esyslog("cDecoder::GetFrameInfo(): avcodec_decode_video2 decode of frame (%li) failed with return code %i", framenumber, rc);
+                return false;
+            }
+#endif
+            stateEAGAIN=false;
+
+            if (avFrame->interlaced_frame != interlaced_frame) {
+                isyslog("found %s video format",(avFrame->interlaced_frame) ? "interlaced" : "non interlaced");
+                interlaced_frame=avFrame->interlaced_frame;
+            }
+            for (int i=0; i<4; i++) {
+                if (avFrame->data[i]) {
+                    maContext->Video.Data.Plane[i]=avFrame->data[i];
+                    maContext->Video.Data.PlaneLinesize[i]=avFrame->linesize[i];
+                    maContext->Video.Data.Valid=true;
+                }
+            }
+
+            int sample_aspect_ratio_num = avFrame->sample_aspect_ratio.num;
+            int sample_aspect_ratio_den = avFrame->sample_aspect_ratio.den;
+            if ((sample_aspect_ratio_num == 0) || (sample_aspect_ratio_den == 0)) {
+                    esyslog("cDecoder::GetFrameInfo(): invalid aspect ratio (%i:%i) at frame (%li)", sample_aspect_ratio_num, sample_aspect_ratio_den, framenumber);
+                    return false;
+            }
+            if ((sample_aspect_ratio_num == 1) && (sample_aspect_ratio_den == 1)) {
+                if ((avFrame->width == 1280) && (avFrame->height  ==  720) ||
+                    (avFrame->width == 1920) && (avFrame->height  == 1080)) {
+                    sample_aspect_ratio_num = 16;
+                    sample_aspect_ratio_den = 9;
+                }
+                else {
+                    esyslog("cDecoder::GetFrameInfo(): unknown aspect ratio to video width %i hight %i at frame %li)", avFrame->width, avFrame->height, framenumber);
+                    return false;
+                }
+            }
+            else {
+                if ((sample_aspect_ratio_num==64) && (sample_aspect_ratio_den==45)){
+                    sample_aspect_ratio_num =16;
+                    sample_aspect_ratio_den = 9;
+                }
+                else if ((sample_aspect_ratio_num==32) && (sample_aspect_ratio_den==17)){
+                         sample_aspect_ratio_num =16;
+                         sample_aspect_ratio_den = 9;
+                     }
+                     else if ((sample_aspect_ratio_num==16) && (sample_aspect_ratio_den==15)){
+                              sample_aspect_ratio_num =4;
+                              sample_aspect_ratio_den =3;
+                          }
+                          else if ((sample_aspect_ratio_num==4) && (sample_aspect_ratio_den==3)){
+//                                   sample_aspect_ratio_num =4;
+//                                   sample_aspect_ratio_den =3;
+                               }
+                          else esyslog("cDecoder::GetFrameInfo(): unknown aspect ratio (%i:%i) at frame (%li)", 
+                                                                               sample_aspect_ratio_num, sample_aspect_ratio_den, framenumber);
+            }
+            if ((maContext->Video.Info.AspectRatio.Num != sample_aspect_ratio_num) ||
+               ( maContext->Video.Info.AspectRatio.Den != sample_aspect_ratio_den)) {
+                if (msgGetFrameInfo) dsyslog("cDecoder::GetFrameInfo(): aspect ratio changed from (%i:%i) to (%i:%i) at frame %li",
+                                                                                                        maContext->Video.Info.AspectRatio.Num, 
+                                                                                                        maContext->Video.Info.AspectRatio.Den, 
+                                                                                                        sample_aspect_ratio_num, 
+                                                                                                        sample_aspect_ratio_den,
+                                                                                                        framenumber);
+                maContext->Video.Info.AspectRatio.Num=sample_aspect_ratio_num;
+                maContext->Video.Info.AspectRatio.Den=sample_aspect_ratio_den;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    if (isAudioStream()) {
+        if (isAudioAC3Frame()) {
+#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
+            if (maContext->Audio.Info.Channels != avctx->streams[avpkt.stream_index]->codecpar->channels) {
+                dsyslog("cDecoder::GetFrameInfo(): audio channels changed from %i to %i at frame (%li)", maContext->Audio.Info.Channels, 
+                                                                                                        avctx->streams[avpkt.stream_index]->codecpar->channels, 
+                                                                                                        framenumber);
+                maContext->Audio.Info.Channels = avctx->streams[avpkt.stream_index]->codecpar->channels;
+#else
+            if (maContext->Audio.Info.Channels != avctx->streams[avpkt.stream_index]->codec->channels) {
+                dsyslog("cDecoder::GetFrameInfo(): audio channels changed from %i to %i at frame (%li)", maContext->Audio.Info.Channels, 
+                                                                                                        avctx->streams[avpkt.stream_index]->codec->channels, 
+                                                                                                        framenumber);
+                maContext->Audio.Info.Channels = avctx->streams[avpkt.stream_index]->codec->channels;
+#endif
+            }
+        }
+        return true;
+    }
+    return false;
+}
+
+bool cDecoder::isVideoStream() {
+    if (!avctx) return false;
+#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
+    if (avctx->streams[avpkt.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) return true;
+#else
+    if (avctx->streams[avpkt.stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO) return true;
+#endif
+    return false;
+}
+
+bool cDecoder::isAudioStream() {
+    if (!avctx) return false;
+#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
+    if (avctx->streams[avpkt.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) return true;
+#else
+    if (avctx->streams[avpkt.stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO) return true;
+#endif
+    return false;
+}
+
+bool cDecoder::isAudioAC3Frame() {
+    if (!avctx) return false;
+#define AUDIOFORMATAC3 8
+#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
+    if (avctx->streams[avpkt.stream_index]->codecpar->format == AUDIOFORMATAC3) return true;
+#else
+    if (avctx->streams[avpkt.stream_index]->codec->sample_fmt == AUDIOFORMATAC3) return true;
+#endif
+    return false;
+}
+
+bool cDecoder::isVideoIFrame() {
+    if (!avctx) return false;
+    if (!isVideoStream()) return false;
+    if ((avpkt.flags & AV_PKT_FLAG_KEY) != 0)  return true;
+    return false;
+}
+
+
+long int cDecoder::GetFrameNumber(){
+    return framenumber;
+}
+
+long int cDecoder::GetIFrameCount(){
+    return iFrameCount;
+}
+
+bool cDecoder::isInterlacedVideo(){
+    if (interlaced_frame > 0) return true;
+    return false;
+}
+
+long int cDecoder::GetIFrameRangeCount(long int beginFrame, long int endFrame) {
+    int counter=0;
+    for (std::vector<iFrameInfo>::iterator iInfo = iFrameInfoVector.begin(); iInfo != iFrameInfoVector.end(); ++iInfo) {
+        if (iInfo->iFrameNumber >= beginFrame) {
+            counter++;
+            if (iInfo->iFrameNumber >= endFrame) return counter;
+        }
+    }
+    dsyslog("cDecoder::GetIFrameCount(): failed beginFrame (%li) endFrame (%li) last frame in index list (%li)", beginFrame, endFrame, iFrameInfoVector.back().iFrameNumber);
+    return(0);
+}
+
+long int cDecoder::GetIFrameBefore(long int iFrame) {
+    long int before_iFrame=0;
+    for (std::vector<iFrameInfo>::iterator iInfo = iFrameInfoVector.begin(); iInfo != iFrameInfoVector.end(); ++iInfo) {
+        if (iInfo->iFrameNumber >= iFrame) {
+            return before_iFrame;
+        }
+        else before_iFrame=iInfo->iFrameNumber;
+    }
+    dsyslog("cDecoder::GetNearestIFrame(): failed for frame (%li)", iFrame);
+    return 0;
+}
+
+
+long int cDecoder::GetTimeFromIFrame(long int iFrame) {
+    long int before_pts=0;
+    long int before_iFrame=0;
+    if (iFrameInfoVector.empty()) esyslog("cDecoder::GetTimeFromIFrame(): iFrame Index not initialized");
+    for (std::vector<iFrameInfo>::iterator iInfo = iFrameInfoVector.begin(); iInfo != iFrameInfoVector.end(); ++iInfo) {
+        if (iFrame == iInfo->iFrameNumber) {
+            dsyslog("cDecoder::GetTimeFromIFrame(): iFrame (%li) time is %lims", iFrame, iInfo->pts_time_ms);
+            return iInfo->pts_time_ms;
+        }
+        if (iInfo->iFrameNumber > iFrame) {
+            if (abs(iFrame - before_iFrame) < abs(iFrame - iInfo->iFrameNumber)) {
+                esyslog("cDecoder::GetTimeFromIFrame(): frame (%li) is not an iFrame, returning time from iFrame before (%li) %lims",iFrame,before_iFrame,before_pts);
+                return before_pts;
+            }
+            else {
+                dsyslog("cDecoder::GetTimeFromIFrame(): frame (%li) is not an iFrame, returning time from iFrame after (%li) %lims",iFrame,iInfo->iFrameNumber,iInfo->pts_time_ms);
+                return iInfo->pts_time_ms;
+            }
+        }
+        else {
+            before_iFrame=iInfo->iFrameNumber;
+            before_pts=iInfo->pts_time_ms;
+        }
+    }
+    esyslog("cDecoder::GetTimeFromIFrame(): could not find time for frame %li",iFrame);
+    return 0;
+}
diff -u --new-file '--exclude=version.h' a/command/decoder_new.h b/command/decoder_new.h
--- a/command/decoder_new.h	1970-01-01 01:00:00.000000000 +0100
+++ b/command/decoder_new.h	2019-12-13 11:35:06.034554038 +0100
@@ -0,0 +1,67 @@
+#include <vector>
+#include "global.h"
+
+extern "C"{
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+#include <libavformat/avio.h>
+#include <libavutil/file.h>
+}
+
+#define CDECODER 50
+#define MAXEAGAINERRORS 10
+
+class cDecoder
+{
+    public:
+        cDecoder();
+        ~cDecoder();
+        bool DecodeDir(const char * recDir);
+	void Reset();
+        bool DecodeFile(const char * filename);
+        int GetVideoHeight();
+        int GetVideoWidth();
+        int GetVideoFramesPerSecond();
+	int GetVideoRealFrameRate();
+        bool GetNextFrame();
+	bool SeekToFrame(long int iFrame);
+        bool GetFrameInfo(MarkAdContext *maContext);
+        bool isVideoStream();
+        bool isVideoIFrame();
+	bool isAudioStream();
+	bool isAudioAC3Frame();
+        long int GetFrameNumber();
+	long int GetIFrameCount();
+	bool isInterlacedVideo();
+	long int GetIFrameRangeCount(long int beginFrame, long int endFrame);
+	long int GetIFrameBefore(long int iFrame);
+        long int GetTimeFromIFrame(long int iFrame);
+
+    private:
+	char *recordingDir=NULL;
+        int fileNumber=0;
+        AVFormatContext *avctx = NULL;
+        AVPacket avpkt;
+        AVCodec *codec;
+        AVCodecContext *codecCtx;
+	AVFrame *avFrame = NULL;
+        long int framenumber=-1;
+        long int iFrameCount=0;
+	long int pts_time_ms_LastFile=0;
+        struct iFrameInfo
+        {
+	    int fileNumber=0;
+            long int iFrameNumber=0;
+            long int pts_time_ms=0;
+        };
+        std::vector<iFrameInfo> iFrameInfoVector;
+        struct structFrameData {
+            bool Valid=false; // flag, if true data is valid
+            uchar *Plane[4];  // picture planes (YUV420)
+            int PlaneLinesize[4]; // size int bytes of each picture plane line
+        } iFrameData;
+	bool msgDecodeFile=true;
+	bool msgGetFrameInfo=true;
+	int interlaced_frame=-1;
+	bool stateEAGAIN=false;
+};
diff -u --new-file '--exclude=version.h' a/command/demux.cpp b/command/demux.cpp
--- a/command/demux.cpp	2017-03-13 18:56:14.000000000 +0100
+++ b/command/demux.cpp	2019-12-09 19:34:14.836758064 +0100
@@ -648,6 +648,7 @@
                 esyslog("sequence error %i->%i (0x%04x)",counter,tshdr->Counter,pid);
             }
             Clear(Pkt);
+//	    dsyslog("---queue->Skipped() %i", queue->Skipped());
             skipped+=queue->Skipped();
             if (!tshdr->PayloadStart)
             {
diff -u --new-file '--exclude=version.h' a/command/global.h b/command/global.h
--- a/command/global.h	2017-03-13 18:56:14.000000000 +0100
+++ b/command/global.h	2019-12-09 19:34:14.836758064 +0100
@@ -29,25 +29,29 @@
 #define MT_ASSUMEDSTART   (unsigned char) 0x11
 #define MT_ASSUMEDSTOP    (unsigned char) 0x12
 
-#define MT_LOGOCHANGE     (unsigned char) 0x20
-#define MT_LOGOSTART      (unsigned char) 0x21
-#define MT_LOGOSTOP       (unsigned char) 0x22
-
-#define MT_HBORDERCHANGE  (unsigned char) 0x30
-#define MT_HBORDERSTART   (unsigned char) 0x31
-#define MT_HBORDERSTOP    (unsigned char) 0x32
-
-#define MT_VBORDERCHANGE  (unsigned char) 0x40
-#define MT_VBORDERSTART   (unsigned char) 0x41
-#define MT_VBORDERSTOP    (unsigned char) 0x42
-
-#define MT_ASPECTCHANGE   (unsigned char) 0x50
-#define MT_ASPECTSTART    (unsigned char) 0x51
-#define MT_ASPECTSTOP     (unsigned char) 0x52
-
-#define MT_CHANNELCHANGE  (unsigned char) 0x60
-#define MT_CHANNELSTART   (unsigned char) 0x61
-#define MT_CHANNELSTOP    (unsigned char) 0x62
+#define MT_BLACKCHANGE    (unsigned char) 0x20
+#define MT_NOBLACKSTART   (unsigned char) 0x21
+#define MT_NOBLACKSTOP    (unsigned char) 0x22
+
+#define MT_LOGOCHANGE     (unsigned char) 0x30
+#define MT_LOGOSTART      (unsigned char) 0x31
+#define MT_LOGOSTOP       (unsigned char) 0x32
+
+#define MT_HBORDERCHANGE  (unsigned char) 0x40
+#define MT_HBORDERSTART   (unsigned char) 0x41
+#define MT_HBORDERSTOP    (unsigned char) 0x42
+
+#define MT_VBORDERCHANGE  (unsigned char) 0x50
+#define MT_VBORDERSTART   (unsigned char) 0x51
+#define MT_VBORDERSTOP    (unsigned char) 0x52
+
+#define MT_ASPECTCHANGE   (unsigned char) 0x60
+#define MT_ASPECTSTART    (unsigned char) 0x61
+#define MT_ASPECTSTOP     (unsigned char) 0x62
+
+#define MT_CHANNELCHANGE  (unsigned char) 0x70
+#define MT_CHANNELSTART   (unsigned char) 0x71
+#define MT_CHANNELSTOP    (unsigned char) 0x72
 
 #define MT_RECORDINGSTART (unsigned char) 0xD1
 #define MT_RECORDINGSTOP  (unsigned char) 0xD2
@@ -68,6 +72,9 @@
     int svdrpport;
     int threads;
     int astopoffs;
+    int posttimer;
+    bool use_cDecoder=false;
+    const char *recDir;
 
     bool DecodeVideo;
     bool DecodeAudio;
@@ -88,16 +95,16 @@
 
 typedef struct MarkAdAspectRatio
 {
-    int Num;
-    int Den;
+    int Num=0;
+    int Den=0;
 } MarkAdAspectRatio;
 
 typedef struct MarkAdMark
 {
-    int Type;
-    int Position;
-    int ChannelsBefore;
-    int ChannelsAfter;
+    int Type=0;
+    int Position=0;
+    int ChannelsBefore=0;
+    int ChannelsAfter=0;
     MarkAdAspectRatio AspectRatioBefore;
     MarkAdAspectRatio AspectRatioAfter;
 } MarkAdMark;
@@ -116,12 +123,13 @@
 
 typedef struct MarkAdPid
 {
-    int Num;
-    int Type;
+    int Num=0;
+    int Type=0;
 } MarkAdPid;
 
 typedef struct MarkAdContext
 {
+//    cDecoder *ptr_cDecoder;
     const MarkAdConfig *Config;
 
     struct Info
@@ -141,6 +149,7 @@
         struct Options
         {
             bool IgnoreAspectRatio;
+            bool IgnoreBlackScreenDetection=false;
             bool IgnoreLogoDetection;
             bool WeakMarksOk;
         } Options;
@@ -153,7 +162,7 @@
             int Pix_Fmt; // Pixel format (see libavutil/pixfmt.h)
             MarkAdAspectRatio AspectRatio;
             double FramesPerSecond;
-            bool Interlaced;
+            bool Interlaced=false;
         } Info;
 
         struct Data
diff -u --new-file '--exclude=version.h' a/command/Makefile b/command/Makefile
--- a/command/Makefile	2019-12-09 19:34:14.812757828 +0100
+++ b/command/Makefile	2019-12-09 19:34:14.836758064 +0100
@@ -21,14 +21,17 @@
 CXX      ?= g++
 export CXXFLAGS ?= $(call PKGCFG,cxxflags)
 export CXXFLAGS ?= -g -rdynamic -O3 -funroll-loops -Wall -Wextra -Woverloaded-virtual -Wno-parentheses
-export CXXFLAGS += -std=c++11  # to prevent a lot of compiler warnings with Ubuntu 14.04
+CXXVERION=$(shell $(CXX) -dumpversion)
+ifeq ($(CXXVERION),4.8)
+export CXXFLAGS += -std=c++11   # to prevent a lot of compiler warnings with Ubuntu 14.04
+endif
 #
 PKG-CONFIG ?= pkg-config
 STRIP ?= strip
 
 ### Includes and Defines (add further entries here):
-PKG-LIBS += libavcodec libavutil
-PKG-INCLUDES += libavcodec libavutil
+PKG-LIBS += libavcodec libavutil libavformat
+PKG-INCLUDES += libavcodec libavutil libavformat
 
 DEFINES += -D_GNU_SOURCE 
 DEFINES += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
@@ -44,7 +47,7 @@
 
 ### The object files (add further files here):
 
-OBJS = markad-standalone.o decoder.o marks.o streaminfo.o video.o audio.o demux.o
+OBJS = markad-standalone.o decoder.o marks.o streaminfo.o video.o audio.o demux.o decoder_new.o
 
 ### The main target:
 
diff -u --new-file '--exclude=version.h' a/command/markad-standalone.cpp b/command/markad-standalone.cpp
--- a/command/markad-standalone.cpp	2019-12-09 19:34:14.000000000 +0100
+++ b/command/markad-standalone.cpp	2019-12-13 18:58:30.373624620 +0100
@@ -36,6 +36,7 @@
 
 bool SYSLOG=false;
 bool LOG2REC=false;
+cDecoder* ptr_cDecoder = NULL;
 cMarkAdStandalone *cmasta=NULL;
 int SysLogLevel=2;
 
@@ -78,7 +79,7 @@
         if (ctime_r(&now,buf)) {
             buf[strlen(buf)-6]=0;
         }
-	else dsyslog("ctime_r failed");
+        else dsyslog("ctime_r failed");
         char fmt[255];
         snprintf(fmt, sizeof(fmt), "%s%s [%d] %s", LOG2REC ? "":"markad: ",buf, getpid(), format);
         va_start(ap, format);
@@ -233,41 +234,103 @@
     if (!startframe) return;
     if (!macontext.Video.Info.FramesPerSecond) return;
 
-    int delta=macontext.Video.Info.FramesPerSecond*MAXRANGE;
-    int len_in_frames=macontext.Video.Info.FramesPerSecond*length;
-    int len_in_framesA=macontext.Video.Info.FramesPerSecond*(length+macontext.Config->astopoffs);
-
+    isyslog("startframe %i", startframe);
+    
     iStart=-startframe;
-    iStop=-(startframe+len_in_frames);
-    iStopA=-(startframe+len_in_framesA);
-    //chkSTART=-iStart+(1.1*delta);
-    chkSTART=-iStart+delta;
-    dsyslog("chkSTART set to %i",chkSTART);
-    chkSTOP=-iStop+(3*delta);
+    iStop = -(startframe + macontext.Video.Info.FramesPerSecond * length) ;
+
+    iStartA=abs(iStart);
+    iStopA =startframe + macontext.Video.Info.FramesPerSecond * (length + macontext.Config->astopoffs - 30);
+    chkSTOP=startframe + macontext.Video.Info.FramesPerSecond * (length + macontext.Config->posttimer);
+
+    chkSTART=abs(iStart) + macontext.Video.Info.FramesPerSecond * 4*MAXRANGE;  
+
+    dsyslog("assumed start frame %i", iStartA);
+    dsyslog("assumed stop frame %i", iStopA);
+    isyslog("chkSTART set to %i",chkSTART);
+    isyslog("chkSTOP set to %i", chkSTOP);
 }
 
 void cMarkAdStandalone::CheckStop()
 {
-    dsyslog("checking stop");
+    dsyslog("checking stop (%i)", lastiframe);
     int delta=macontext.Video.Info.FramesPerSecond*MAXRANGE;
-    clMark *end=marks.GetAround(delta,iStop,MT_STOP,0x0F);
+    if (ignoreHborder) {
+        dsyslog("delete all border marks");
+        marks.Del(MT_HBORDERSTART);
+        marks.Del(MT_HBORDERSTOP);
+    }
+    clMark *end=marks.GetAround(3*delta,iStopA,MT_ASPECTSTOP);      // try if we can get a good stop mark, start with MT_ASPECTSTOP
+    if (!end) {
+        dsyslog("no MT_ASPECTSTOP mark found");
+        end=marks.GetAround(3*delta,iStopA,MT_HBORDERSTOP);         // try MT_HBORDERSTOP
+        if (!end) {
+            dsyslog("no MT_HBORDERSTOP mark found");
+            end=marks.GetAround(delta,iStopA,MT_LOGOSTOP);        // try MT_LOGOSTOP
+            if (!end) {
+                dsyslog("no MT_LOGOSTOP mark found");
+                end=marks.GetAround(INT_MAX,iStopA,MT_STOP,0x0F);    // try any type of stop mark
+            }
+            else dsyslog("MT_LOGOSTOP found at frame %i", end->position);
+        }
+        else dsyslog("MT_HBORDERSTOP found at frame %i", end->position);
+    }
+    else dsyslog("MT_ASPECTSTOP found at frame %i", end->position);
+    clMark *lastStart=marks.GetAround(INT_MAX,lastiframe,MT_START,0x0F);  
 
     if (end)
-    {
-        marks.DelTill(end->position,false);
+    { 
+        dsyslog("found end mark at (%i)", end->position);
+        if (end->type != MT_NOBLACKSTOP){     // we found a stron mark, delete all blackscreen marks
+            clMark *mark=marks.GetFirst();
+            while (mark) {
+                if ((mark->position >= iStopA-macontext.Video.Info.FramesPerSecond*MAXRANGE) &&   // there could be a valid black screen start mark
+                              (mark->position < end->position) && 
+                              ((mark->type == MT_NOBLACKSTART) || (mark->type == MT_NOBLACKSTOP))){
+                    dsyslog("found stronger mark delete black screen mark (%i)", mark->position);
+                    clMark *tmp=mark;
+                    mark=mark->Next();
+                    marks.Del(tmp);
+                    continue;
+                }
+                mark=mark->Next();
+            }
+        }
+
+        if ((end->type == MT_NOBLACKSTOP) && (end->position < iStopA)) {        // if stop mark is MT_NOBLACKSTOP and it is not after iStopA try next, better save than sorry 
+           clMark *end2=marks.GetAround(delta,end->position+2*delta,MT_STOP,0x0F);
+           if (end2) {
+               dsyslog("stop mark is week, use next stop mark at (%i)", end2->position);
+               end=end2;
+           }
+        }
+
         isyslog("using mark on position %i as stop mark",end->position);
+        marks.DelTill(end->position,false);
+
+        if ( end->position < iStopA - 3*delta ) {    // last found stop mark to early, adding STOP mark at the end
+                                                     // this can happen by audio channel change too if the next broadcast has also 6 channels
+            if ( ( lastStart) && ( lastStart->position > end->position ) ) {
+                isyslog("last STOP mark results in to short recording, set STOP at the end of the recording (%i)", lastiframe);
+                MarkAdMark mark={};
+                mark.Position=lastiframe;
+                mark.Type=MT_ASSUMEDSTOP;
+                AddMark(&mark);
+            }
+        }
     }
     else
     {
+        dsyslog("no stop mark found");
         //fallback
         if (iStopinBroadCast)
         {
-            MarkAdMark mark;
-            memset(&mark,0,sizeof(mark));
-            mark.Position=iStopA;
+            dsyslog("add stop mark at %i",iStopA+delta);
+            MarkAdMark mark={};
+            mark.Position=iStopA+delta;
             mark.Type=MT_ASSUMEDSTOP;
             AddMark(&mark);
-            marks.DelTill(iStopA,false);
+            marks.DelTill(iStopA+delta,false);
         }
         else
         {
@@ -281,8 +344,20 @@
 
 void cMarkAdStandalone::CheckStart()
 {
-    dsyslog("checking start");
+    dsyslog("checking start (%i)", lastiframe);
+
+//  only for debugging
+/*    clMark *mark=marks.GetFirst();
+    while (mark) {
+        dsyslog("--- mark->position %i type 0x%X", mark->position, mark->type);
+        mark=mark->Next();
+    }
+*/
+
     clMark *begin=NULL;
+    int delta=macontext.Video.Info.FramesPerSecond*MAXRANGE;
+
+    macontext.Video.Options.IgnoreBlackScreenDetection=true;   // use black sceen setection only to find start mark
 
     if ((macontext.Info.Channels) && (macontext.Audio.Info.Channels) &&
             (macontext.Info.Channels!=macontext.Audio.Info.Channels))
@@ -332,8 +407,19 @@
             macontext.Video.Options.IgnoreLogoDetection=true;
             marks.Del(MT_ASPECTSTART);
             marks.Del(MT_ASPECTSTOP);
-            // start mark must be around istart
-            begin=marks.GetAround(INT_MAX,iStart,MT_CHANNELSTART);
+            // start mark must be around iStartA
+            begin=marks.GetAround(INT_MAX,iStartA,MT_CHANNELSTART);
+            if (!begin) {
+                dsyslog("no audio channel start mark found, try horizontal border as start mark");
+                begin=marks.GetAround(INT_MAX,iStartA,MT_HBORDERSTART);
+                if (begin) {
+                    dsyslog("found horizontal border and add this as assumed start (%i)",begin->position);
+                    MarkAdMark mark={};
+                    mark.Position=begin->position;
+                    mark.Type=MT_ASSUMEDSTART;
+                    AddMark(&mark);
+                }
+            }
         }
         else
         {
@@ -384,8 +470,16 @@
             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);
+            // start mark must be around iStartA
+            begin=marks.GetAround(macontext.Video.Info.FramesPerSecond*(MAXRANGE*4),iStartA,MT_ASPECTSTART);
+            if ((begin) && (begin->position < abs(iStartA)/4)) {    // this is not a valid start, try if there is better start mark
+                clMark *begin2=marks.GetAround(iStartA,iStartA+delta,MT_START,0x0F);
+                if (begin2) {
+                    begin2->type=MT_ASSUMEDSTART;  // most types of marks will be deleted if we do aspect ratio detecetion
+                    dsyslog("changing start position from (%i) to next start mark (%i)", begin->position, begin2->position);
+                    begin=begin2;
+                }
+            }
         }
     }
 
@@ -399,11 +493,29 @@
         marks.Del(MT_VBORDERSTART);
         marks.Del(MT_VBORDERSTOP);
     }
+    else {
+        clMark *bStart=marks.GetAround(iStartA+delta,iStartA+delta,MT_HBORDERSTART);    
+        if (!bStart) {   
+            dsyslog("no horizontal border at start found, ignore horizontal border detection");
+            ignoreHborder=true;
+        }
+        else {
+            dsyslog("horizontal border start found at (%i)", bStart->position);
+            clMark *bStop=marks.GetAround(delta,bStart->position,MT_HBORDERSTOP);    
+            if ( (bStop) && (bStop->position > bStart->position)) {
+                isyslog("horizontal border STOP (%i) after horizontal border START (%i) found, this is the end of the previous recording, delete marks",bStop->position,bStart->position);
+                    marks.Del(bStart);
+                    marks.Del(bStop);
+
+            }
+        }
+    }
 
     if (!begin)
     {
-        begin=marks.GetAround(macontext.Video.Info.FramesPerSecond*(MAXRANGE*2),iStart,MT_START,0x0F);
+        begin=marks.GetAround(iStartA,iStartA,MT_START,0x0F);
         if (begin) {
+            dsyslog("found start mark at (%i)", begin->position);
             clMark *begin2=marks.GetAround(macontext.Video.Info.FramesPerSecond*MAXRANGE,begin->position,MT_START,0x0F);
             if (begin2) {
                 if (begin2->type>begin->type) {
@@ -420,29 +532,84 @@
                     }
                 }
             }
+            if (begin->type == MT_NOBLACKSTART) {  // this is weak, check if there is a better logo mark
+                clMark *begin3=marks.GetAround(iStartA+delta,iStartA+delta,MT_LOGOSTART);
+                if (begin3) {
+                    if (begin3->position > iStartA/4) {
+                        isyslog("mark on position %i stronger than mark on position %i as start mark",begin3->position,begin->position);
+                        begin=begin3;
+                    }
+                }
+                else {    // if there is no logo start mark and we do not use logo detection after start, use blackscreen mark only if it is not to late
+                   if (!bDecodeVideo && (begin->position > (iStartA + macontext.Video.Info.FramesPerSecond*2*MAXRANGE))) { // we are lost, use startframe as start mark
+                       dsyslog("start of black screen to late (%i) setting start to startframe (%i)", begin->position, iStart);
+                       marks.DelTill(chkSTART);
+                       MarkAdMark mark={};
+                       mark.Position=iStart;
+                       mark.Type=MT_ASSUMEDSTART;
+                       AddMark(&mark);
+                       begin=marks.GetAround(iStartA,iStartA,MT_START,0x0F);
+                       CalculateCheckPositions(iStart);
+                   }
+                }
+            }
+            if ((begin->type == MT_LOGOSTART) && (begin->position < iStartA/4)) {    // this is not a valid start, try next start mark
+                clMark *begin4=marks.GetAround(iStartA,iStartA+delta,MT_START,0x0F);
+                if (begin4) {
+                    dsyslog("changing start position from (%i) to next start mark (%i)", begin->position, begin4->position);
+                    begin=begin4;
+                }
+            }
         }
     }
     if (begin)
     {
-        marks.DelTill(begin->position);
+        marks.DelTill(begin->position);    // delete all marks till start mark
         CalculateCheckPositions(begin->position);
         isyslog("using mark on position %i as start mark",begin->position);
 
-        if ((begin->type==MT_VBORDERSTART) || (begin->type==MT_HBORDERSTART))
-        {
+        if ((begin->type==MT_VBORDERSTART) || (begin->type==MT_HBORDERSTART)) {
             isyslog("%s borders, logo detection disabled",(begin->type==MT_HBORDERSTART) ? "horizontal" : "vertical");
             macontext.Video.Options.IgnoreLogoDetection=true;
             marks.Del(MT_LOGOSTART);
             marks.Del(MT_LOGOSTOP);
         }
 
+        clMark *mark=marks.GetFirst();   // delete all black screen marks because they are weak, execpt the start mark
+        while (mark)
+        {
+            if (( (mark->type == MT_NOBLACKSTART) || (mark->type == MT_NOBLACKSTOP) ) && (mark->position > begin->position) ) {
+                dsyslog("delete black screen mark at position (%i)", mark->position);
+                clMark *tmp=mark;
+                mark=mark->Next();
+                marks.Del(tmp);
+                continue;
+            }
+            mark=mark->Next();
+        }
+        if (begin->type == MT_LOGOSTART) {
+            clMark *mark=marks.GetFirst();
+            while (mark)
+            {
+                if ( (mark->type == MT_LOGOSTART) && (mark->position > begin->position) && (mark->position <= chkSTART)) {
+                    if ( mark->Next() && (mark->Next()->type == MT_LOGOSTOP)) {
+                        dsyslog("delete logo mark at position (%i),(%i) between STARTLOGO (%i) and chkSTART (%i)", mark->position, mark->Next()->position, begin->position, chkSTART);
+                        clMark *tmp=mark;
+                        mark=mark->Next()->Next();
+                        marks.Del(tmp->Next());
+                        marks.Del(tmp);
+                        continue;
+                    }
+                }
+                mark=mark->Next();
+            } 
+        }
     }
     else
     {
         //fallback
         marks.DelTill(chkSTART);
-        MarkAdMark mark;
-        memset(&mark,0,sizeof(mark));
+        MarkAdMark mark={};
         mark.Position=iStart;
         mark.Type=MT_ASSUMEDSTART;
         AddMark(&mark);
@@ -452,19 +619,71 @@
     return;
 }
 
-void cMarkAdStandalone::CheckLogoMarks()
+void cMarkAdStandalone::CheckLogoMarks()            // cleanup marks that make no sense
 {
+    isyslog("cleanup marks");
     clMark *mark=marks.GetFirst();
-    while (mark)
-    {
+    while (mark) {
+        
+        if (((mark->type & 0x0F)==MT_START) && (mark->Next()) && ((mark->Next()->type & 0x0F)==MT_START)) {  // two start marks, delete second
+            dsyslog("start mark (%i) folowed by start mark (%i) delete second", mark->position, mark->Next()->position);
+            marks.Del(mark->Next());
+            continue;
+        }
+        if (((mark->type & 0x0F)==MT_STOP) && (mark->Next()) && ((mark->Next()->type & 0x0F)==MT_STOP)) {  // two stop marks, delete second
+            dsyslog("stop mark (%i) folowed by stop mark (%i) delete first", mark->position, mark->Next()->position);
+            clMark *tmp=mark;
+            mark=mark->Next();
+            marks.Del(tmp);
+            continue;
+        }
+
+        if ((mark->type==MT_NOBLACKSTOP) && mark->Next() && (mark->Next()->type==MT_NOBLACKSTART)) {
+            int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*4);
+            if (abs(mark->Next()->position-mark->position)<=MARKDIFF) {
+                double distance=(mark->Next()->position-mark->position)/macontext.Video.Info.FramesPerSecond;
+                isyslog("mark distance between STOP and START too short (%.1fs), deleting %i,%i", distance, mark->position, mark->Next()->position);
+                clMark *tmp=mark;
+                mark=mark->Next()->Next();
+                marks.Del(tmp->Next());
+                marks.Del(tmp);
+                continue;
+            }
+        }
+
+        if ((mark->type==MT_NOBLACKSTOP) && mark->Next() && (mark->Next()->type==MT_NOBLACKSTART)) {
+            if ((mark->Next()->position>iStopA-macontext.Video.Info.FramesPerSecond*MAXRANGE) && (mark->position>iStopA-macontext.Video.Info.FramesPerSecond*MAXRANGE)) {
+                isyslog("blackscreen start mark followed by blackscreen stop mark, deleting %i,%i", mark->position, mark->Next()->position);
+                clMark *tmp=mark;
+                mark=mark->Next()->Next();
+                marks.Del(tmp->Next());
+                marks.Del(tmp);
+                continue;
+            }
+        }
+
+        if ((mark->type==MT_LOGOSTART) && mark->Next() && mark->Next()->type==MT_LOGOSTOP)
+        {
+            int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*60);
+            if (abs(mark->Next()->position-mark->position)<=MARKDIFF)
+            {
+                double distance=(mark->Next()->position-mark->position)/macontext.Video.Info.FramesPerSecond;
+                isyslog("mark distance between START and STOP too short (%.1fs), deleting %i,%i", distance, mark->position, mark->Next()->position);
+                clMark *tmp=mark;
+                mark=mark->Next()->Next();
+                marks.Del(tmp->Next());
+                if (marks.GetFirst()->position!=tmp->position) marks.Del(tmp);  // do not delete start mark
+                continue;
+            }
+        }
+
         if ((mark->type==MT_LOGOSTOP) && mark->Next() && mark->Next()->type==MT_LOGOSTART)
         {
-            int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*30);
+            int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*50);
             if (abs(mark->Next()->position-mark->position)<=MARKDIFF)
             {
                 double distance=(mark->Next()->position-mark->position)/macontext.Video.Info.FramesPerSecond;
-                isyslog("mark distance too short (%.1fs), deleting %i,%i",distance,
-                        mark->position,mark->Next()->position);
+                isyslog("mark distance between STOP and START too short (%.1fs), deleting %i,%i", distance, mark->position, mark->Next()->position);
                 clMark *tmp=mark;
                 mark=mark->Next()->Next();
                 marks.Del(tmp->Next());
@@ -472,6 +691,13 @@
                 continue;
             }
         }
+
+        if (((mark->type & 0x0F)==MT_START) && (!mark->Next())) {      // delete start mark at the end
+            if (marks.GetFirst()->position != mark->position) {        // do not delete start mark
+                dsyslog("deleting START mark at the end");
+                marks.Del(mark);
+            }
+        }
         mark=mark->Next();
     }
 }
@@ -492,6 +718,12 @@
     case MT_ASSUMEDSTOP:
         if (asprintf(&comment,"assuming stop (%i)",Mark->Position)==-1) comment=NULL;
         break;
+    case MT_NOBLACKSTART:
+        if (asprintf(&comment,"detected end of black screen (%i)*",Mark->Position)==-1) comment=NULL;
+        break;
+    case MT_NOBLACKSTOP:
+        if (asprintf(&comment,"detected start of black screen (%i)",Mark->Position)==-1) comment=NULL;
+        break;
     case MT_LOGOSTART:
         if (asprintf(&comment,"detected logo start (%i)*",Mark->Position)==-1) comment=NULL;
         break;
@@ -573,18 +805,17 @@
         }
     }
 
-    /*
-    if ((Mark->Type==MT_LOGOSTART) && (!iStart) && (Mark->Position<abs(iStop)))
+    if (((Mark->Type & 0x0F)==MT_START) && (!iStart) && (Mark->Position < (abs(iStopA) - 2*macontext.Video.Info.FramesPerSecond*MAXRANGE )))
     {
-        clMark *prev=marks.GetPrev(Mark->Position,MT_LOGOSTOP);
+
+        clMark *prev=marks.GetPrev(Mark->Position,(Mark->Type & 0xF0)|MT_STOP);
         if (prev)
         {
-            int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*10);
-            if ((Mark->Position-prev->position)<MARKDIFF)
+            int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*10);    // maybe this is only ia short logo detection failure o
+            if ( (Mark->Position - prev->position) < MARKDIFF )
             {
                 double distance=(Mark->Position-prev->position)/macontext.Video.Info.FramesPerSecond;
-                isyslog("mark distance too short (%.1fs), deleting %i,%i",distance,
-                        prev->position,Mark->Position);
+                isyslog("mark distance between STOP an START too short (%.1fs), deleting %i,%i",distance, prev->position,Mark->Position);
                 if (!macontext.Video.Options.WeakMarksOk) inBroadCast=false;
                 marks.Del(prev);
                 if (comment) free(comment);
@@ -592,9 +823,8 @@
             }
         }
     }
-    */
 
-    if (((Mark->Type & 0x0F)==MT_STOP) && (!iStart) && (Mark->Position<abs(iStop)))
+    if (((Mark->Type & 0x0F)==MT_STOP) && (!iStart) && (Mark->Position < abs(iStopA) - macontext.Video.Info.FramesPerSecond*MAXRANGE ))
     {
         clMark *prev=marks.GetPrev(Mark->Position,(Mark->Type & 0xF0)|MT_START);
         if (prev)
@@ -602,17 +832,16 @@
             int MARKDIFF;
             if ((Mark->Type & 0xF0)==MT_LOGOCHANGE)
             {
-                MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*180);
+                MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*110);
             }
             else
             {
-                MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*10);
+                MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*90);
             }
-            if ((Mark->Position-prev->position)<MARKDIFF)
+            if ((Mark->Position - prev->position) < MARKDIFF)
             {
-                double distance=(Mark->Position-prev->position)/macontext.Video.Info.FramesPerSecond;
-                isyslog("mark distance too short (%.1fs), deleting %i,%i",distance,
-                        prev->position,Mark->Position);
+                double distance=(Mark->Position - prev->position)/macontext.Video.Info.FramesPerSecond;
+                isyslog("mark distance between START and STOP too short (%.1fs), deleting %i,%i",distance,prev->position,Mark->Position);
                 if (!macontext.Video.Options.WeakMarksOk) inBroadCast=false;
                 marks.Del(prev);
                 if (comment) free(comment);
@@ -701,7 +930,7 @@
         dsyslog("slept too much");
         return; // we already slept too much
     }
-
+    if (ptr_cDecoder) framecnt = ptr_cDecoder->GetFrameNumber();
     bool notenough=true;
     do
     {
@@ -712,7 +941,7 @@
             }
             return;
         }
-
+       
         int maxframes=statbuf.st_size/8;
         if (maxframes<(framecnt+200))
         {
@@ -723,7 +952,7 @@
                     if (time(NULL)>(startTime+(time_t) length))
                     {
                         // "old" recording
-                        tsyslog("assuming old recording, now>startTime+length");
+//                        tsyslog("assuming old recording, now>startTime+length");
                         return;
                     }
                     else
@@ -740,7 +969,7 @@
                     return;
                 }
             }
-            marks.Save(directory,macontext.Video.Info.FramesPerSecond,isTS);
+            marks.Save(directory,&macontext, ptr_cDecoder, isTS);
             unsigned int sleeptime=WAITTIME;
             time_t sleepstart=time(NULL);
             double slepttime=0;
@@ -813,7 +1042,7 @@
         free(buf);
         save=true;
     }
-    if (save) marks.Save(directory,macontext.Video.Info.FramesPerSecond,isTS,true);
+    if (save) marks.Save(directory,&macontext,ptr_cDecoder,isTS,true);
 }
 
 bool cMarkAdStandalone::ProcessFile2ndPass(clMark **Mark1, clMark **Mark2,int Number, off_t Offset,
@@ -848,7 +1077,6 @@
     int actframe=Frame;
     int framecounter=0;
     int pframe=-1;
-
     MarkAdPos *pos=NULL;
 
     while (framecounter<Frames)
@@ -936,7 +1164,7 @@
                                 if (pframe!=lastiframe)
                                 {
                                     if (pn>mSTART) pos=video->ProcessOverlap(lastiframe,Frames,(pn==mBEFORE),
-                                                           (macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264));
+                                                       (macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264));
                                     framecounter++;
                                 }
                                 if ((pos) && (pn==mAFTER))
@@ -974,6 +1202,100 @@
     return true;
 }
 
+bool cMarkAdStandalone::ProcessMark2ndPass(clMark **mark1, clMark **mark2) {
+
+    if (!mark1) return false;
+    if (!*mark1) return false;
+    if (!mark2) return false;
+    if (!*mark2) return false;
+
+    long int iFrameCount=0;
+    int fRange=0;
+    MarkAdPos *ptr_MarkAdPos=NULL;
+
+    if (!Reset(false))
+    {
+        // reset all, but marks
+        esyslog("failed resetting state");
+        return false;
+    }
+
+    fRange=macontext.Video.Info.FramesPerSecond*120;     // 40s + 80s
+    int fRangeBegin=(*mark1)->position-fRange;           // 120 seconds before first mark
+    if (fRangeBegin<0) fRangeBegin=0;                    // but not before beginning of broadcast
+    fRangeBegin=ptr_cDecoder->GetIFrameBefore(fRangeBegin);
+    if (!fRangeBegin) {
+        dsyslog("cMarkAdStandalone::ProcessMark2ndPass() GetIFrameBefore failed for frame (%i)", fRangeBegin);
+        return false;
+    }
+    if (!ptr_cDecoder->SeekToFrame(fRangeBegin)) {
+        esyslog("cDecoder: could not seek to frame (%i)", fRangeBegin);
+        return false;
+    }
+    iFrameCount=ptr_cDecoder->GetIFrameRangeCount(fRangeBegin, (*mark1)->position);
+    if (iFrameCount<=0) {
+            dsyslog("cMarkAdStandalone::ProcessMark2ndPass() GetIFrameRangeCount failed at range (%i,%i))", fRangeBegin, (*mark1)->position);
+            return false;
+    }
+    while (ptr_cDecoder->GetFrameNumber() <= (*mark1)->position ) {
+        if (abort) return false;
+        if (!ptr_cDecoder->GetNextFrame()) {
+            dsyslog("cMarkAdStandalone::ProcessMark2ndPass() GetNextFrame failed at frame (%li)", ptr_cDecoder->GetFrameNumber());
+            return false;
+        }
+        if (!ptr_cDecoder->isVideoStream()) continue;
+        if (!ptr_cDecoder->GetFrameInfo(&macontext)) {
+            if (ptr_cDecoder->isVideoIFrame()) 
+                tsyslog("TRACE: cMarkAdStandalone::ProcessMark2ndPass() before mark GetFrameInfo failed at frame (%li)", ptr_cDecoder->GetFrameNumber());
+            continue;          
+        }
+        if (ptr_cDecoder->isVideoIFrame()) {
+            ptr_MarkAdPos=video->ProcessOverlap(ptr_cDecoder->GetFrameNumber(),iFrameCount,true,(macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264));
+        }
+   }
+
+    fRange=macontext.Video.Info.FramesPerSecond*320; // 160s + 160s
+    fRangeBegin=ptr_cDecoder->GetIFrameBefore((*mark2)->position);
+    if (!fRangeBegin) {
+        dsyslog("cMarkAdStandalone::ProcessMark2ndPass() GetIFrameBefore failed for frame (%i)", fRangeBegin);
+        return false;
+    }
+    int fRangeEnd=(*mark2)->position+fRange;         // 320 seconds after second mark
+    if (!ptr_cDecoder->SeekToFrame((*mark2)->position)) {
+        esyslog("cDecoder: could not seek to frame (%i)", fRangeBegin);
+        return false;
+    }
+    iFrameCount=ptr_cDecoder->GetIFrameRangeCount(fRangeBegin, fRangeEnd)-2;
+    if (iFrameCount<=0) {
+            dsyslog("cMarkAdStandalone::ProcessMark2ndPass() GetIFrameRangeCount failed at range (%i,%i))", fRangeBegin, (*mark1)->position);
+            return false;
+    }
+    while (ptr_cDecoder->GetFrameNumber() <= fRangeEnd ) {
+        if (abort) return false;
+        if (!ptr_cDecoder->GetNextFrame()) {
+            dsyslog("cMarkAdStandalone::ProcessMark2ndPass() GetNextFrame failed at frame (%li)", ptr_cDecoder->GetFrameNumber());
+            return false;
+        }
+        if (!ptr_cDecoder->isVideoStream()) continue;
+        if (!ptr_cDecoder->GetFrameInfo(&macontext)) {
+            if (ptr_cDecoder->isVideoIFrame())
+                tsyslog("TRACE: cMarkAdStandalone::ProcessMark2ndPass() after mark GetFrameInfo failed at frame (%li)", ptr_cDecoder->GetFrameNumber());
+            continue;
+        }
+        if (ptr_cDecoder->isVideoIFrame()) {
+            ptr_MarkAdPos=video->ProcessOverlap(ptr_cDecoder->GetFrameNumber(),iFrameCount,false,(macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264));
+        }
+        if (ptr_MarkAdPos) dsyslog("cMarkAdStandalone::ProcessMark2ndPass found overlap in frames (%i,%i)", ptr_MarkAdPos->FrameNumberBefore, ptr_MarkAdPos->FrameNumberAfter);
+        if (ptr_MarkAdPos) {
+            // found overlap
+            ChangeMarks(mark1,mark2,ptr_MarkAdPos);
+            return true;
+        }
+    }
+    return false;
+}
+
+
 void cMarkAdStandalone::Process2ndPass()
 {
     if (abort) return;
@@ -998,13 +1320,17 @@
     clMark *p1=NULL,*p2=NULL;
 
     if (marks.Count()<4) return; // we cannot do much without marks
-
     p1=marks.GetFirst();
     if (!p1) return;
 
     p1=p1->Next();
     if (p1) p2=p1->Next();
 
+    if (ptr_cDecoder) {
+        ptr_cDecoder->Reset();
+        ptr_cDecoder->DecodeDir(directory);
+    }
+
     while ((p1) && (p2))
     {
         if (!infoheader)
@@ -1015,25 +1341,31 @@
         off_t offset;
         int number,frame,iframes;
         int frange=macontext.Video.Info.FramesPerSecond*120; // 40s + 80s
-	int frange_begin=p1->position-frange; // 120 seconds before first mark
-	if (frange_begin<0) frange_begin=0; // but not before beginning of broadcast
+        int frange_begin=p1->position-frange; // 120 seconds before first mark
+        if (frange_begin<0) frange_begin=0; // but not before beginning of broadcast
 
-        if (marks.ReadIndex(directory,isTS,frange_begin,frange,&number,&offset,&frame,&iframes))
-        {
-            if (!ProcessFile2ndPass(&p1,NULL,number,offset,frame,iframes)) break;
+        if (ptr_cDecoder) {
+            if (!ProcessMark2ndPass(&p1,&p2)) {
+                dsyslog("cDecoder: ProcessMark2ndPass no overlap found for marks at frames (%i) and (%i)", p1->position, p2->position);
+            }
+        }
+        else {
+            if (marks.ReadIndex(directory,isTS,frange_begin,frange,&number,&offset,&frame,&iframes))
+            {
+                if (!ProcessFile2ndPass(&p1,NULL,number,offset,frame,iframes)) break;
 
-            frange=macontext.Video.Info.FramesPerSecond*320; // 160s + 160s
-            if (marks.ReadIndex(directory,isTS,p2->position,frange,&number,&offset,&frame,&iframes))
+                frange=macontext.Video.Info.FramesPerSecond*320; // 160s + 160s
+                if (marks.ReadIndex(directory,isTS,p2->position,frange,&number,&offset,&frame,&iframes))
+                {
+                    if (!ProcessFile2ndPass(&p1,&p2,number,offset,frame,iframes)) break;
+                }
+            }
+            else
             {
-                if (!ProcessFile2ndPass(&p1,&p2,number,offset,frame,iframes)) break;
+                esyslog("error reading index");
+                return;
             }
         }
-        else
-        {
-            esyslog("error reading index");
-            return;
-        }
-
         p1=p2->Next();
         if (p1)
         {
@@ -1046,6 +1378,7 @@
     }
 }
 
+
 bool cMarkAdStandalone::ProcessFile(int Number)
 {
     if (!directory) return false;
@@ -1075,7 +1408,6 @@
     }
 
     int f=open(fbuf,O_RDONLY);
-    free(fbuf);
     if (f==-1) {
         if (isTS) {
             dsyslog("failed to open %05i.ts",Number);
@@ -1084,13 +1416,14 @@
         }
         return false;
     }
+    free(fbuf);
 
     int dataread;
     dsyslog("processing file %05i",Number);
 
     int pframe=-1;
-
     demux->NewFile();
+
 again:
     while ((dataread=read(f,data,datalen))>0)
     {
@@ -1183,13 +1516,17 @@
                                             AddMark(&vmarks->Number[i]);
                                         }
                                     }
-                                    //SaveFrame(lastiframe);  // TODO: JUST FOR DEBUGGING!
+//                                    if (lastiframe == 14716) SaveFrame(lastiframe);  // TODO: JUST FOR DEBUGGING!
                                     if (iStart>0)
                                     {
                                         if ((inBroadCast) && (lastiframe>chkSTART)) CheckStart();
                                     }
-                                    if ((iStop>0) && (iStopA>0))
-                                    {
+                                    if ((lastiframe>iStopA-macontext.Video.Info.FramesPerSecond*MAXRANGE) && 
+                                                                (macontext.Video.Options.IgnoreBlackScreenDetection)) {
+                                            dsyslog("start black screen detection");
+                                            macontext.Video.Options.IgnoreBlackScreenDetection=false;   // use black sceen setection only to find end mark
+                                    }
+                                    if ((iStop>0) && (iStopA>0)) {
                                         if (lastiframe>chkSTOP) CheckStop();
                                     }
                                     pframe=lastiframe;
@@ -1277,28 +1614,130 @@
     return ret;
 }
 
+void cMarkAdStandalone::ProcessFrame(cDecoder *ptr_cDecoder)
+{
+    if ((macontext.Config->logoExtraction!=-1) && (ptr_cDecoder->GetIFrameCount()>=512)) {    // extract logo
+        isyslog("finished logo extraction, please check /tmp for pgm files");
+        abort=true;
+    }
+
+    if (ptr_cDecoder->GetFrameInfo(&macontext)) {
+        if (ptr_cDecoder->isVideoStream()) {
+            if (ptr_cDecoder->isInterlacedVideo() && !macontext.Video.Info.Interlaced && (macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264) &&
+                                                     (ptr_cDecoder->GetVideoFramesPerSecond()==25) && (ptr_cDecoder->GetVideoRealFrameRate()==50)) {
+                dsyslog("change internal frame rate to handle H.264 interlaced video");
+                macontext.Video.Info.FramesPerSecond*=2;
+                macontext.Video.Info.Interlaced=true;
+                CalculateCheckPositions(tStart*macontext.Video.Info.FramesPerSecond);
+            }
+            lastiframe=iframe;
+            if ((iStart<0) && (lastiframe>-iStart)) iStart=lastiframe;
+            if ((iStop<0) && (lastiframe>-iStop)) {
+                iStop=lastiframe;
+                iStopinBroadCast=inBroadCast;
+            }
+            if ((iStopA<0) && (lastiframe>-iStopA)) {
+                iStopA=lastiframe;
+            }
+            iframe=ptr_cDecoder->GetFrameNumber();
+
+            if (!video) {
+                esyslog("cMarkAdStandalone::ProcessFrame() video not initialized");
+                return;
+            }
+            if (!macontext.Video.Data.Valid) {
+                isyslog("cMarkAdStandalone::ProcessFrame faild to get video data of frame (%li)", ptr_cDecoder->GetFrameNumber());
+                return;
+            }
+
+            if ((lastiframe>iStopA-macontext.Video.Info.FramesPerSecond*MAXRANGE) &&
+                                     ((macontext.Video.Options.IgnoreBlackScreenDetection) || (macontext.Video.Options.IgnoreLogoDetection))) {
+                    isyslog("restart logo and black screen detection at frame (%li)",ptr_cDecoder->GetFrameNumber());
+                    bDecodeVideo=true;
+                    macontext.Video.Options.IgnoreBlackScreenDetection=false;   // use black sceen setection only to find end mark
+                    if (macontext.Video.Options.IgnoreLogoDetection==true) {
+                        macontext.Video.Options.IgnoreLogoDetection=false;
+                        if (video) video->Clear();    // reset logo decoder status
+                    }
+            }
+
+            if (bDecodeVideo) {
+                MarkAdMarks *vmarks=video->Process(lastiframe,iframe);
+                if (vmarks) {
+                    for (int i=0; i<vmarks->Count; i++) {
+                        AddMark(&vmarks->Number[i]);
+                    }
+                }
+//          if (lastiframe == 14716) SaveFrame(lastiframe);  // TODO: JUST FOR DEBUGGING!
+                if (iStart>0) {
+                    if ((inBroadCast) && (lastiframe>chkSTART)) CheckStart();
+                }
+                if ((iStop>0) && (iStopA>0)) {
+                    if (lastiframe>chkSTOP) CheckStop();
+                }
+            }
+        }
+        if(ptr_cDecoder->isAudioAC3Frame()) {
+             MarkAdMark *amark=audio->Process(lastiframe,iframe);
+            if (amark) AddMark(amark);
+        }
+    }
+}
+
 void cMarkAdStandalone::ProcessFile()
 {
-    for (int i=1; i<=MaxFiles; i++)
-    {
-        if (abort) break;
-        if (!ProcessFile(i)) break;
-        if ((gotendmark) && (!macontext.Config->GenIndex)) break;
+    if (macontext.Config->use_cDecoder) {
+        dsyslog("use cDecoder class V0.%i", CDECODER);
+        ptr_cDecoder = new cDecoder();
+        CheckIndexGrowing();
+        while(ptr_cDecoder->DecodeDir(directory)) {
+            if (abort) {
+                ptr_cDecoder->~cDecoder();
+                break;
+            }
+            if(ptr_cDecoder->GetFrameNumber() < 0) {
+                macontext.Video.Info.Height=ptr_cDecoder->GetVideoHeight();
+                isyslog("video hight: %i", macontext.Video.Info.Height);
+
+                macontext.Video.Info.Width=ptr_cDecoder->GetVideoWidth();
+                isyslog("video width: %i", macontext.Video.Info.Width);
+
+                macontext.Video.Info.FramesPerSecond=ptr_cDecoder->GetVideoFramesPerSecond();
+                isyslog("average frame rate %i frames per second",(int) macontext.Video.Info.FramesPerSecond);
+                isyslog("real frame rate    %i frames per second",ptr_cDecoder->GetVideoRealFrameRate());
+
+                CalculateCheckPositions(tStart*macontext.Video.Info.FramesPerSecond);
+            }
+            while(ptr_cDecoder->GetNextFrame()) {
+                if (abort) {
+                    ptr_cDecoder->~cDecoder();
+                    break;
+                }
+                cMarkAdStandalone::ProcessFrame(ptr_cDecoder);
+                CheckIndexGrowing();
+            }
+        }
+    }
+    else {
+        for (int i=1; i<=MaxFiles; i++)
+        {
+            if (abort) break;
+            if (!ProcessFile(i)) break;
+            if ((gotendmark) && (!macontext.Config->GenIndex)) break;
+        }
     }
 
-    if (!abort)
-    {
-        CheckLogoMarks();
+    if (!abort) {
         if ((iStop>0) && (iStopA>0)) CheckStop(); // no stopmark till now?
-        if ((inBroadCast) && (!gotendmark) && (lastiframe))
-        {
+        CheckLogoMarks();
+        if ((inBroadCast) && (!gotendmark) && (lastiframe)) {
             MarkAdMark tempmark;
             tempmark.Type=MT_RECORDINGSTOP;
             tempmark.Position=lastiframe;
             AddMark(&tempmark);
         }
     }
-    if (demux) skipped=demux->Skipped();
+    if ( !macontext.Config->use_cDecoder && demux) skipped=demux->Skipped();
 }
 
 void cMarkAdStandalone::Process()
@@ -1312,58 +1751,62 @@
     marks.CloseIndex(directory,isTS);
     if (!abort)
     {
-        if (marks.Save(directory,macontext.Video.Info.FramesPerSecond,isTS))
+        if (marks.Save(directory,&macontext,ptr_cDecoder,isTS))
         {
             if (length && startTime)
-            {
-                if ((time(NULL)>(startTime+(time_t) length)) || (gotendmark))
-                {
-                    int iIndexError=false;
-                    int tframecnt=macontext.Config->GenIndex ? framecnt : 0;
-                    if (marks.CheckIndex(directory,isTS,&tframecnt,&iIndexError))
+            {   
+                if (!ptr_cDecoder ){  // new decoder class does not use the vdr index file
+                                      // and does not support to create an new index file
+                                      // use vdr to create a new index
+                    if (((time(NULL)>(startTime+(time_t) length)) || (gotendmark)) && !ptr_cDecoder )  
                     {
-                        if (iIndexError)
+                        int iIndexError=false;
+                        int tframecnt=macontext.Config->GenIndex ? framecnt : 0;
+                        if (marks.CheckIndex(directory,isTS,&tframecnt,&iIndexError))
                         {
-                            if (macontext.Config->GenIndex)
+                            if (iIndexError)
                             {
-                                switch (iIndexError)
-                                {
-                                case IERR_NOTFOUND:
-                                    isyslog("no index found");
-                                    break;
-                                case IERR_TOOSHORT:
-                                    isyslog("index too short");
-                                    break;
-                                default:
-                                    isyslog("index doesn't match marks");
-                                    break;
-                                }
-                                if (RegenerateIndex())
+                                if (macontext.Config->GenIndex)
                                 {
-                                    isyslog("recreated index");
+                                    switch (iIndexError)
+                                    { 
+                                    case IERR_NOTFOUND:
+                                        isyslog("no index found");
+                                        break;
+                                    case IERR_TOOSHORT:
+                                        isyslog("index too short");
+                                        break;
+                                    default:
+                                        isyslog("index doesn't match marks");
+                                        break;
+                                    }
+                                    if (RegenerateIndex())
+                                    {
+                                        isyslog("recreated index");
+                                    }
+                                    else
+                                    {
+                                        esyslog("failed to recreate index");
+                                    }
                                 }
                                 else
                                 {
-                                    esyslog("failed to recreate index");
-                                }
-                            }
-                            else
-                            {
-                                esyslog("index doesn't match marks%s",
-                                        ((isTS) || ((macontext.Info.VPid.Type==
+                                    esyslog("index doesn't match marks%s",
+                                            ((isTS) || ((macontext.Info.VPid.Type==
                                                      MARKAD_PIDTYPE_VIDEO_H264) && (!isTS))) ?
-                                        ", sorry you're lost" :
-                                        ", please run genindex");
+                                            ", sorry you're lost" :
+                                            ", please run genindex");
+                                }
                             }
                         }
+                        if (macontext.Config->SaveInfo) SaveInfo();
+                    }
+                    else
+                    {
+                        // this shouldn't be reached
+                        if (macontext.Config->logoExtraction==-1)
+                            esyslog("ALERT: stopping before end of broadcast");
                     }
-                    if (macontext.Config->SaveInfo) SaveInfo();
-                }
-                else
-                {
-                    // this shouldn't be reached
-                    if (macontext.Config->logoExtraction==-1)
-                        esyslog("ALERT: stopping before end of broadcast");
                 }
             }
         }
@@ -1677,6 +2120,8 @@
     int len=strlen(macontext.Info.ChannelName);
     if (!len) return false;
 
+    dsyslog("using logo directory %s",macontext.Config->logoDirectory);
+    dsyslog("searching logo for %s",macontext.Info.ChannelName);
     DIR *dir=opendir(macontext.Config->logoDirectory);
     if (!dir) return false;
 
@@ -1815,6 +2260,7 @@
             }
         }
     }
+    if ((macontext.Info.AspectRatio.Num==0) && (macontext.Info.AspectRatio.Den==0)) isyslog("no broadcast aspectratio found in info");
     if (line) free(line);
 
     if ((length) && (!bIgnoreTimerInfo) && (startTime))
@@ -1827,9 +2273,10 @@
             {
                 if (length+tStart>0)
                 {
-                    isyslog("broadcast start truncated by %im, length will be corrected",-tStart/60);
+//                    isyslog("broadcast start truncated by %im, length will be corrected",-tStart/60);
+                    isyslog("broadcast start may be truncated or restarted by %im ",-tStart/60);
                     startTime=rStart;
-                    length+=tStart;
+//                    length+=tStart;
                     tStart=1;
                 }
                 else
@@ -2216,7 +2663,7 @@
     duplicate=false;
     title[0]=0;
 
-    memset(&macontext,0,sizeof(macontext));
+    macontext={};
     macontext.Config=config;
 
     bDecodeVideo=config->DecodeVideo;
@@ -2370,7 +2817,7 @@
 
     if (tStart>1) {
         if (tStart<60) tStart=60;
-        isyslog("pre-timer %im",tStart/60);
+        isyslog("pre-timer %is",tStart);
     }
     if (length) isyslog("broadcast length %im",length/60);
 
@@ -2580,6 +3027,10 @@
            "                  port of a remote VDR for OSD messages\n"
            "                --astopoffs=<value> (default is 100)\n"
            "                  assumed stop offset in seconds range from 0 to 240\n"
+           "                --posttimer=<value> (default is 600)\n"
+           "                  additional recording after timer end in seconds range from 0 to 1200\n"
+           "                --cDecoder\n"
+           "                  use new cDecoder class, be carefull this is still experimental\n"
            "\ncmd: one of\n"
            "-                            dummy-parameter if called directly\n"
            "after                        markad starts to analyze the recording\n"
@@ -2655,9 +3106,7 @@
     int online=0;
     bool bPass2Only=false;
     bool bPass1Only=false;
-
-    struct config config;
-    memset(&config,0,sizeof(config));
+    struct config config={};
 
     // set defaults
     config.DecodeVideo=true;
@@ -2668,6 +3117,7 @@
     config.logoHeight=-1;
     config.threads=-1;
     config.astopoffs=100;
+    config.posttimer=600;
     strcpy(config.svdrphost,"127.0.0.1");
     strcpy(config.logoDirectory,"/var/lib/markad");
 
@@ -2688,8 +3138,7 @@
         int option_index = 0;
         static struct option long_options[] =
         {
-            {"ac3",0,0,'a'
-            },
+            {"ac3",0,0,'a'},
             {"background", 0, 0, 'b'},
             {"comments", 0, 0, 'c'},
             {"disable", 1, 0, 'd'},
@@ -2705,6 +3154,8 @@
 
             {"asd",0,0,6},
             {"astopoffs",1,0,12},
+            {"posttimer",1,0,13},
+            {"cDecoder",0,0,14},
             {"loglevel",1,0,2},
             {"markfile",1,0,1},
             {"nopid",0,0,5},
@@ -2866,8 +3317,10 @@
             // --extractlogo
             str=optarg;
             ntok=0;
-            while (tok=strtok(str,","))
+            while (true)
             {
+                tok=strtok(str,",");
+                if (!tok) break;
                 switch (ntok)
                 {
                 case 0:
@@ -3028,6 +3481,22 @@
             }
             break;
 
+        case 13: // --posttimer
+            if (isnumber(optarg) && atoi(optarg) >= 0 && atoi(optarg) <= 1200)
+            {
+                config.posttimer=atoi(optarg);
+            }
+            else
+            {
+                fprintf(stderr, "markad: invalid posttimer value: %s\n", optarg);
+                return 2;
+            }
+            break;
+
+        case 14: // --cDecoder
+            config.use_cDecoder=true;
+            break;
+
         default:
             printf ("? getopt returned character code 0%o ? (option_index %d)\n", c,option_index);
         }
@@ -3063,6 +3532,7 @@
                 if ( strstr(argv[optind],".rec") != NULL )
                 {
                     recDir=realpath(argv[optind],NULL);
+                    config.recDir=recDir;
                 }
             }
             optind++;
@@ -3205,6 +3675,14 @@
         cmasta = new cMarkAdStandalone(recDir,&config);
         if (!cmasta) return -1;
 
+        isyslog("parameter --loglevel is set to %i", SysLogLevel); 
+        dsyslog("parameter --logocachedir is set to %s",config.logoDirectory);
+        dsyslog("parameter --threads is set to %i", config.threads); 
+        dsyslog("parameter --astopoffs is set to %i",config.astopoffs); 
+        if (LOG2REC) dsyslog("parameter --log2rec is set"); 
+        if (config.use_cDecoder) dsyslog("parameter --cDecoder is set"); 
+        if (config.Before) dsyslog("parameter Before is set"); 
+
         if (!bPass2Only) cmasta->Process();
         if (!bPass1Only) cmasta->Process2ndPass();
         delete cmasta;
diff -u --new-file '--exclude=version.h' a/command/markad-standalone.h b/command/markad-standalone.h
--- a/command/markad-standalone.h	2017-03-13 18:56:14.000000000 +0100
+++ b/command/markad-standalone.h	2019-12-09 19:34:14.836758064 +0100
@@ -210,8 +210,10 @@
     int tStart;        // pretimer in seconds
     int iStart;        // pretimer in frames (negative if unset)
     int iStop;         // endposition in frames (negative if unset)
+    int iStartA;       // assumed startposition in frames
     int iStopA;        // assumed endposition in frames (negative if unset)
-    bool iStopinBroadCast; // in broadcast @ iStop position?
+    bool ignoreHborder=false; // ignore horizontal borders, if there are none at the start of the recording
+    bool iStopinBroadCast;    // in broadcast @ iStop position?
 
     void CheckStop();
     void CheckStart();
@@ -246,8 +248,10 @@
     bool SetFileUID(char *File);
     bool RegenerateIndex();
     bool ProcessFile2ndPass(clMark **Mark1, clMark **Mark2, int Number, off_t Offset, int Frame, int Frames);
+    bool ProcessMark2ndPass(clMark **Mark1, clMark **Mark2);
     bool ProcessFile(int Number);
     void ProcessFile();
+    void ProcessFrame(cDecoder *ptr_cDecoder);
 public:
     cMarkAdStandalone(const char *Directory, const MarkAdConfig *config);
     ~cMarkAdStandalone();
diff -u --new-file '--exclude=version.h' a/command/marks.cpp b/command/marks.cpp
--- a/command/marks.cpp	2017-03-13 18:56:14.000000000 +0100
+++ b/command/marks.cpp	2019-12-09 19:34:14.836758064 +0100
@@ -16,6 +16,11 @@
 #include <fcntl.h>
 
 #include "marks.h"
+#include "decoder.h"
+extern "C"
+{
+#include "debug.h"
+}
 
 clMark::clMark(int Type, int Position, const char *Comment)
 {
@@ -191,7 +196,12 @@
     clMark *m2=GetNext(Position,Type,Mask);
 
     if (!m1 && !m2) return NULL;
-    if (!m1 && m2) return m2;
+
+    if (!m1 && m2) {
+        if (abs(Position-m2->position)>Frames) return NULL;
+        else return m2;
+    }
+
     if (m1 && !m2)
     {
         if (abs(Position-m1->position)>Frames) return NULL;
@@ -200,10 +210,12 @@
 
     if (abs(m1->position-Position)>abs(m2->position-Position))
     {
-        return m2;
+        if (abs(Position-m2->position)>Frames) return NULL;
+        else return m2;
     }
     else
     {
+        if (abs(Position-m1->position)>Frames) return NULL;
         return m1;
     }
 }
@@ -259,15 +271,19 @@
 
 clMark *clMarks::Add(int Type, int Position,const char *Comment)
 {
+
     clMark *newmark;
     if ((newmark=Get(Position)))
     {
-        if ((newmark->comment) && (Comment))
-        {
-            free(newmark->comment);
-            newmark->comment=strdup(Comment);
+        dsyslog("duplicate mark on position %i type 0x%X and type 0x%x", Position, Type, newmark->type);
+        if (Type > newmark->type){   // keep the stronger mark
+            if ((newmark->comment) && (Comment))
+            {
+                free(newmark->comment);
+                newmark->comment=strdup(Comment);
+            }
+            newmark->type=Type;
         }
-        newmark->type=Type;
         return newmark;
     }
 
@@ -346,12 +362,19 @@
     return NULL;
 }
 
-char *clMarks::IndexToHMSF(int Index, double FramesPerSecond)
+char *clMarks::IndexToHMSF(int Index, MarkAdContext *maContext, cDecoder *ptr_cDecoder)
 {
+    double FramesPerSecond=maContext->Video.Info.FramesPerSecond;
     if (FramesPerSecond==0.0) return NULL;
     char *buf=NULL;
     double Seconds;
-    int f = int(modf((Index+0.5)/FramesPerSecond,&Seconds)*FramesPerSecond+1);
+    int f=0;
+    if (maContext->Config->use_cDecoder && (maContext->Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264) && ptr_cDecoder) {
+        f = int(modf(float(ptr_cDecoder->GetTimeFromIFrame(Index))/100,&Seconds)*100);
+    }
+    else {
+        f = int(modf((Index+0.5)/FramesPerSecond,&Seconds)*FramesPerSecond+1);
+    }
     int s = int(Seconds);
     int m = s / 60 % 60;
     int h = s / 3600;
@@ -689,7 +712,7 @@
     return true;
 }
 
-bool clMarks::Save(const char *Directory, double FrameRate, bool isTS, bool Force)
+bool clMarks::Save(const char *Directory, MarkAdContext *maContext, cDecoder *ptr_cDecoder, bool isTS, bool Force)
 {
     if (!first) return false;
     if ((savedcount==count) && (!Force)) return false;
@@ -709,7 +732,7 @@
     clMark *mark=first;
     while (mark)
     {
-        char *buf=IndexToHMSF(mark->position,FrameRate);
+        char *buf=IndexToHMSF(mark->position,maContext,ptr_cDecoder);
         if (buf)
         {
             fprintf(mf,"%s %s\n",buf,mark->comment ? mark->comment : "");
diff -u --new-file '--exclude=version.h' a/command/marks.h b/command/marks.h
--- a/command/marks.h	2019-12-09 19:34:14.000000000 +0100
+++ b/command/marks.h	2019-12-09 19:34:14.836758064 +0100
@@ -9,6 +9,8 @@
 #define __marks_h_
 
 #include <string.h>
+#include "global.h"
+#include "decoder_new.h"
 
 class clMark
 {
@@ -69,7 +71,7 @@
 
     char filename[1024];
     clMark *first,*last;
-    char *IndexToHMSF(int Index, double FramesPerSecond);
+    char *IndexToHMSF(int Index, MarkAdContext *maContext, cDecoder *ptr_cDecoder);
     int count;
     int savedcount;
     int indexfd;
@@ -114,7 +116,7 @@
     }
     bool Backup(const char *Directory, bool isTS);
     bool Load(const char *Directory, double FrameRate, bool isTS);
-    bool Save(const char *Directory, double FrameRate, bool isTS, bool Force=false);
+    bool Save(const char *Directory, MarkAdContext *maContext, cDecoder *ptr_cDecoder, bool isTS, bool Force=false);
 #define IERR_NOTFOUND 1
 #define IERR_TOOSHORT 2
 #define IERR_SEEK 3
diff -u --new-file '--exclude=version.h' a/command/video.cpp b/command/video.cpp
--- a/command/video.cpp	2017-03-13 18:56:14.000000000 +0100
+++ b/command/video.cpp	2019-12-09 19:34:14.836758064 +0100
@@ -49,11 +49,12 @@
         LOGOHEIGHT=LOGO_DEFHDHEIGHT;
         LOGOWIDTH=LOGO_DEFHDWIDTH;
     }
-    else
+    else if (maContext->Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H262)
     {
         LOGOHEIGHT=LOGO_DEFHEIGHT;
         LOGOWIDTH=LOGO_DEFWIDTH;
     }
+    else dsyslog("cMarkAdLogo::cMarkAdLogo maContext->Info.VPid.Type %i not valid", maContext->Info.VPid.Type);
 
     pixfmt_info=false;
     Clear();
@@ -61,12 +62,14 @@
 
 void cMarkAdLogo::Clear()
 {
-    memset(&area,0,sizeof(area));
+    area={};
+//    memset(&area,0,sizeof(area));
     area.status=LOGO_UNINITIALIZED;
 }
 
 int cMarkAdLogo::Load(const char *directory, char *file, int plane)
 {
+    if (plane==0) dsyslog("cMarkAdLogo::Load load logo file name %s", file);
     if ((plane<0) || (plane>3)) return -3;
 
     char *path;
@@ -136,6 +139,7 @@
 
 void cMarkAdLogo::Save(int framenumber, uchar picture[4][MAXPIXEL], int plane)
 {
+
     if (!macontext) return;
     if ((plane<0) || (plane>3)) return;
     if (!macontext->Info.ChannelName) return;
@@ -338,13 +342,14 @@
     if (extract) return LOGO_NOCHANGE;
     if (!processed) return LOGO_ERROR;
 
-    //tsyslog("rp=%5i mp=%5i mpV=%5.f mpI=%5.f i=%3i s=%i",rpixel,mpixel,(mpixel*LOGO_VMARK),(mpixel*LOGO_IMARK),area.intensity,area.status);
+//    tsyslog("frame (%6i) rp=%5i mp=%5i mpV=%5.f mpI=%5.f i=%3i s=%i",framenumber, rpixel,mpixel,(mpixel*LOGO_VMARK),(mpixel*LOGO_IMARK),area.intensity,area.status);
 
     if (processed==1)
     {
         // if we only have one plane we are "vulnerable"
         // to very bright pictures, so ignore them...
-        if (area.intensity>180) return LOGO_NOCHANGE;
+//        if (area.intensity>180) return LOGO_NOCHANGE;
+        if (area.intensity>150) return LOGO_NOCHANGE;
     }
 
     int ret=LOGO_NOCHANGE;
@@ -421,15 +426,27 @@
     if (!macontext->Video.Data.Valid)
     {
         area.status=LOGO_UNINITIALIZED;
+        dsyslog("video data not valid");
+        return LOGO_ERROR;
+    }
+    if (!macontext->Video.Info.Width) {
+        dsyslog("video width info missing");
+        return LOGO_ERROR;
+    }
+    if (!macontext->Video.Info.Height) {
+        dsyslog("video high info missing");
+        return LOGO_ERROR;
+    }
+    if (!macontext->Config->logoDirectory[0]) { 
+        dsyslog("logoDirectory missing");
+        return LOGO_ERROR;
+    }
+    if (!macontext->Info.ChannelName) {
+        dsyslog("ChannelName missing");
         return LOGO_ERROR;
     }
-    if (!macontext->Video.Info.Width) return LOGO_ERROR;
-    if (!macontext->Video.Info.Height) return LOGO_ERROR;
-    if (!macontext->Config->logoDirectory[0]) return LOGO_ERROR;
-    if (!macontext->Info.ChannelName) return LOGO_ERROR;
-
     if (macontext->Config->logoExtraction==-1)
-    {
+    { 
         if ((area.aspectratio.Num!=macontext->Video.Info.AspectRatio.Num) ||
                 (area.aspectratio.Den!=macontext->Video.Info.AspectRatio.Den))
         {
@@ -477,6 +494,68 @@
     return Detect(FrameNumber,LogoFrameNumber);
 }
 
+cMarkAdBlackScreen::cMarkAdBlackScreen(MarkAdContext *maContext)
+{
+    macontext=maContext;
+    Clear();
+}
+
+void cMarkAdBlackScreen::Clear()
+{
+    blackScreenstatus=BLACKSCREEN_UNINITIALIZED;
+}
+
+int cMarkAdBlackScreen::Process(int FrameNumber, int *BlackIFrame)
+{ 
+#define BLACKNESS 20
+    if (!macontext) return 0;
+    if (!macontext->Video.Data.Valid) return 0;
+    if (macontext->Video.Info.FramesPerSecond==0) return 0;
+    *BlackIFrame=0;
+    if (!macontext->Video.Info.Height) { 
+        dsyslog("cMarkAdBlackScreen::Process() missing macontext->Video.Info.Height");
+        return 0;
+    }
+    int height=macontext->Video.Info.Height;
+
+    if (!macontext->Video.Info.Width) {
+        dsyslog("cMarkAdBlackScreen::Process() missing macontext->Video.Info.Width");
+        return 0;
+    }
+    int width=macontext->Video.Info.Width;
+
+    int end=height*width;
+    int cnt=0;
+    int val=0;
+    if (!macontext->Video.Data.Plane[0]) {
+        dsyslog("cMarkAdBlackScreen::Process() Video.Data.Plane[0] missing");
+        return 0;
+    }
+
+    for (int x=0; x<end; x++)
+    {
+        val+=macontext->Video.Data.Plane[0][x];
+        cnt++;
+    }
+    val/=cnt;
+    if (val<BLACKNESS) {
+        if (blackScreenstatus!=BLACKSCREEN_VISIBLE) {
+            *BlackIFrame=FrameNumber;
+            blackScreenstatus=BLACKSCREEN_VISIBLE;
+            return -1; // detected start of black screen
+        }
+    }
+    else {
+        if (blackScreenstatus!=BLACKSCREEN_INVISIBLE)
+        {
+            *BlackIFrame=FrameNumber;
+            blackScreenstatus=BLACKSCREEN_INVISIBLE;
+            return 1; // detected stop of black screen
+        } 
+    }
+    return 0;
+}
+
 cMarkAdBlackBordersHoriz::cMarkAdBlackBordersHoriz(MarkAdContext *maContext)
 {
     macontext=maContext;
@@ -500,9 +579,16 @@
     // Assumption: If we have 4:3, we should have aspectratio-changes!
     //if (macontext->Video.Info.AspectRatio.Num==4) return 0; // seems not to be true in all countries?
     *BorderIFrame=0;
-
+    if (!macontext->Video.Info.Height) {
+        dsyslog("cMarkAdBlackBordersHoriz::Process() video hight missing");
+        return 0;
+    }
     int height=macontext->Video.Info.Height-VOFFSET;
 
+    if (!macontext->Video.Data.PlaneLinesize[0]) {
+        dsyslog("cMarkAdBlackBordersHoriz::Process() Video.Data.PlaneLinesize[0] not initalized");
+        return 0;
+    }
     int start=(height-CHECKHEIGHT)*macontext->Video.Data.PlaneLinesize[0];
     int end=height*macontext->Video.Data.PlaneLinesize[0];
     bool ftop=true,fbottom=true;
@@ -597,6 +683,10 @@
     bool fleft=true,fright=true;
     int val=0,cnt=0;
 
+    if(!macontext->Video.Data.PlaneLinesize[0]) {
+        dsyslog("Video.Data.PlaneLinesize[0] missing");
+        return 0;
+    }
     int end=macontext->Video.Data.PlaneLinesize[0]*(macontext->Video.Info.Height-VOFFSET_);
     int i=VOFFSET_*macontext->Video.Data.PlaneLinesize[0];
     while (i<end) {
@@ -712,7 +802,11 @@
         similar+=abs(hist1[i]-hist2[i]);
     }
     //printf("%6i\n",similar);
-    if (similar<similarCutOff) return true;
+    if (similar<similarCutOff) {
+//       dsyslog("---areSimilar() similarCutOff %8i",similarCutOff);
+//       dsyslog("---areSimilar() similar       %8i",similar);
+       return true;
+    }
     return false;
 }
 
@@ -730,6 +824,7 @@
             bool simil=areSimilar(histbuf[OV_BEFORE][B].histogram,histbuf[OV_AFTER][A].histogram);
             if (simil)
             {
+//                dsyslog("---cMarkAdOverlap::Detect() similar frames (%6i) (%6i) ",histbuf[OV_BEFORE][B].framenumber,histbuf[OV_AFTER][A].framenumber);
                 tmpA=A;
                 tmpB=B;
                 start=A+1;
@@ -741,8 +836,7 @@
             }
             else
             {
-                //if (simcnt) printf("simcnt=%i\n",simcnt);
-
+//                if (simcnt) dsyslog("---simcnt=%i",simcnt);
                 if (simcnt>similarMaxCnt)
                 {
                     if ((histbuf[OV_BEFORE][tmpB].framenumber>result.FrameNumberBefore) &&
@@ -777,11 +871,20 @@
 
 MarkAdPos *cMarkAdOverlap::Process(int FrameNumber, int Frames, bool BeforeAd, bool H264)
 {
+//    dsyslog("---cMarkAdOverlap::Process FrameNumber %i", FrameNumber);
+//    dsyslog("---cMarkAdOverlap::Process Frames %i", Frames);
+//    dsyslog("---cMarkAdOverlap::Process BeforeAd %i", BeforeAd);
+//    dsyslog("---cMarkAdOverlap::Process H264 %i", H264);
+//    dsyslog("---cMarkAdOverlap::Process lastframenumber %i", lastframenumber);
+//    dsyslog("---cMarkAdOverlap::Process histcnt[OV_BEFORE] %i", histcnt[OV_BEFORE]);
+//    dsyslog("---cMarkAdOverlap::Process histcnt[OV_AFTER] %i", histcnt[OV_AFTER]);
     if ((lastframenumber>0) && (!similarMaxCnt))
     {
         similarCutOff=50000; // lower is harder!
-        if (H264) similarCutOff*=6;
-        similarMaxCnt=4;
+//        if (H264) similarCutOff*=6;
+        if (H264) similarCutOff*=4;       // reduce false similar detection in H.264 streams
+//        similarMaxCnt=4;
+        similarMaxCnt=10;
     }
 
     if (BeforeAd)
@@ -831,8 +934,9 @@
 {
     macontext=maContext;
 
-    memset(&marks,0,sizeof(marks));
-
+//    memset(&marks,0,sizeof(marks));
+    marks={};
+    blackScreen=new cMarkAdBlackScreen(maContext);
     hborder=new cMarkAdBlackBordersHoriz(maContext);
     vborder=new cMarkAdBlackBordersVert(maContext);
     logo = new cMarkAdLogo(maContext);
@@ -843,6 +947,7 @@
 cMarkAdVideo::~cMarkAdVideo()
 {
     resetmarks();
+    if (blackScreen) delete blackScreen;
     if (hborder) delete hborder;
     if (vborder) delete vborder;
     if (logo) delete logo;
@@ -855,6 +960,7 @@
     aspectratio.Den=0;
     framelast=0;
     framebeforelast=0;
+    if (blackScreen) blackScreen->Clear();
     if (hborder) hborder->Clear();
     if (vborder) vborder->Clear();
     if (logo) logo->Clear();
@@ -862,7 +968,8 @@
 
 void cMarkAdVideo::resetmarks()
 {
-    memset(&marks,0,sizeof(marks));
+    marks={};
+//    memset(&marks,0,sizeof(marks));
 }
 
 bool cMarkAdVideo::addmark(int type, int position, MarkAdAspectRatio *before,
@@ -906,6 +1013,7 @@
 
 MarkAdPos *cMarkAdVideo::ProcessOverlap(int FrameNumber, int Frames, bool BeforeAd, bool H264)
 {
+
     if (!FrameNumber) return NULL;
     if (!overlap) overlap=new cMarkAdOverlap(macontext);
     if (!overlap) return NULL;
@@ -918,15 +1026,25 @@
     if ((!FrameNumber) && (!FrameNumberNext)) return NULL;
 
     resetmarks();
+    if (!macontext->Video.Options.IgnoreBlackScreenDetection) {
+        int blackScreenframenumber=0;
+        int blackret=blackScreen->Process(FrameNumber,&blackScreenframenumber);
+        if (blackret>0) 
+        { 
+            addmark(MT_NOBLACKSTART,blackScreenframenumber);
+        }
+        else if (blackret<0)
+        {
+            addmark(MT_NOBLACKSTOP,blackScreenframenumber);
+        }
+    }
 
     int hborderframenumber;
     int hret=hborder->Process(FrameNumber,&hborderframenumber);
-
     if ((hret>0) && (hborderframenumber!=-1))
     {
         addmark(MT_HBORDERSTART,hborderframenumber);
     }
-
     if ((hret<0) && (hborderframenumber!=-1))
     {
         addmark(MT_HBORDERSTOP,hborderframenumber);
@@ -934,12 +1052,10 @@
 
     int vborderframenumber;
     int vret=vborder->Process(FrameNumber,&vborderframenumber);
-
     if ((vret>0) && (vborderframenumber!=-1))
     {
         addmark(MT_VBORDERSTART,vborderframenumber);
     }
-
     if ((vret<0) && (vborderframenumber!=-1))
     {
         addmark(MT_VBORDERSTOP,vborderframenumber);
@@ -967,17 +1083,21 @@
                 addmark(MT_HBORDERSTOP,framebeforelast);
                 hborder->SetStatusBorderInvisible();
             }
-
-            if ((macontext->Video.Info.AspectRatio.Num==4) &&
-                    (macontext->Video.Info.AspectRatio.Den==3))
-            {
-                addmark(MT_ASPECTSTART,start ? FrameNumber : FrameNumberNext,
-                        &aspectratio,&macontext->Video.Info.AspectRatio);
+            if ((macontext->Info.AspectRatio.Num == 4) && (macontext->Info.AspectRatio.Den == 3)) {
+                if ((macontext->Video.Info.AspectRatio.Num==4) && (macontext->Video.Info.AspectRatio.Den==3)) {
+                    addmark(MT_ASPECTSTART,start ? FrameNumber : FrameNumberNext,&aspectratio,&macontext->Video.Info.AspectRatio);
+                }
+                else {
+                    addmark(MT_ASPECTSTOP,framelast,&aspectratio,&macontext->Video.Info.AspectRatio);
+                }
             }
-            else
-            {
-                addmark(MT_ASPECTSTOP,framelast,&aspectratio,
-                        &macontext->Video.Info.AspectRatio);
+            else {
+                if ((macontext->Video.Info.AspectRatio.Num==16) && (macontext->Video.Info.AspectRatio.Den==9)) {
+                    addmark(MT_ASPECTSTART,start ? FrameNumber : FrameNumberNext,&aspectratio,&macontext->Video.Info.AspectRatio);
+                }
+                else {
+                    addmark(MT_ASPECTSTOP,framelast,&aspectratio,&macontext->Video.Info.AspectRatio);
+                }
             }
         }
 
diff -u --new-file '--exclude=version.h' a/command/video.h b/command/video.h
--- a/command/video.h	2017-03-13 18:56:14.000000000 +0100
+++ b/command/video.h	2019-12-09 19:34:14.840758102 +0100
@@ -34,6 +34,13 @@
 
 enum
 {
+    BLACKSCREEN_UNINITIALIZED=-2,
+    BLACKSCREEN_INVISIBLE=-1,
+    BLACKSCREEN_VISIBLE=1
+};
+
+enum
+{
     HBORDER_UNINITIALIZED=-2,
     HBORDER_INVISIBLE=-1,
     HBORDER_VISIBLE=1
@@ -150,6 +157,17 @@
     void Clear();
 };
 
+class cMarkAdBlackScreen
+{
+private:
+    int blackScreenstatus;
+    MarkAdContext *macontext;
+public:
+    cMarkAdBlackScreen(MarkAdContext *maContext);
+    int Process(int FrameNumber,int *BlackFrameNumber);
+    void Clear();
+};
+
 class cMarkAdBlackBordersHoriz
 {
 private:
@@ -197,6 +215,7 @@
     MarkAdMarks marks;
 
     MarkAdAspectRatio aspectratio;
+    cMarkAdBlackScreen *blackScreen;
     cMarkAdBlackBordersHoriz *hborder;
     cMarkAdBlackBordersVert *vborder;
     cMarkAdLogo *logo;
