[unifi/f31] Update to 5.12.0.
by Richard Shaw
Summary of changes:
4154a61... Update to 5.12.0. (*)
(*) This commit already existed in another branch; no separate mail sent
4 years, 11 months
[vdr-markad] Dropped vdr-markad-ffmpeg4-fix.patch Add 00-markad-libavcodec58-V0-01.diff Add 01-markad-Makefile-V0
by Martin Gansser
commit 7381521ba916ab4f5042977085d03d006543f25e
Author: Martin Gansser <mgansser(a)online.de>
Date: Tue Dec 3 15:50:01 2019 +0100
Dropped vdr-markad-ffmpeg4-fix.patch
Add 00-markad-libavcodec58-V0-01.diff
Add 01-markad-Makefile-V0-06.diff
Add 02-deprecated-V0-04.diff
Add 04-markad-decoder-V0-24.diff
00-markad-libavcodec58-V0-01.diff | 176 +++
01-markad-Makefile-V0-06.diff | 272 +++++
02-deprecated-V0-04.diff | 74 ++
03-markad-decoder-V0-24.diff | 2319 +++++++++++++++++++++++++++++++++++++
sources | 2 +-
vdr-markad-ffmpeg4-fix.patch | 86 --
vdr-markad.spec | 42 +-
7 files changed, 2862 insertions(+), 109 deletions(-)
---
diff --git a/00-markad-libavcodec58-V0-01.diff b/00-markad-libavcodec58-V0-01.diff
new file mode 100644
index 0000000..c7ec59b
--- /dev/null
+++ b/00-markad-libavcodec58-V0-01.diff
@@ -0,0 +1,176 @@
+diff -u -r --new-file '--exclude=logos' '--exclude=version.h' '--exclude=po' a/command/decoder.cpp b/command/decoder.cpp
+--- a/command/decoder.cpp 2019-11-24 21:19:25.993386029 +0000
++++ b/command/decoder.cpp 2019-11-25 20:52:15.916895405 +0000
+@@ -103,18 +103,18 @@
+ #endif
+
+ #if LIBAVCODEC_VERSION_INT < ((55<<16)+(18<<8)+102)
+-#ifndef AV_CODEC_ID_H264
+-#define AV_CODEC_ID_H264 CODEC_ID_H264
+-#endif
+-#ifndef AV_CODEC_ID_MPEG2VIDEO
+-#define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
+-#endif
+-#ifndef AV_CODEC_ID_MPEG2VIDEO_XVMC
+-#define AV_CODEC_ID_MPEG2VIDEO_XVMC CODEC_ID_MPEG2VIDEO_XVMC
+-#endif
+-#ifndef AV_CODEC_ID_NONE
+-#define AV_CODEC_ID_NONE CODEC_ID_NONE
+-#endif
++ #ifndef AV_CODEC_ID_H264
++ #define AV_CODEC_ID_H264 CODEC_ID_H264
++ #endif
++ #ifndef AV_CODEC_ID_MPEG2VIDEO
++ #define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
++ #endif
++ #ifndef AV_CODEC_ID_MPEG2VIDEO_XVMC
++ #define AV_CODEC_ID_MPEG2VIDEO_XVMC CODEC_ID_MPEG2VIDEO_XVMC
++ #endif
++ #ifndef AV_CODEC_ID_NONE
++ #define AV_CODEC_ID_NONE CODEC_ID_NONE
++ #endif
+ #endif
+
+ cMarkAdDecoder::cMarkAdDecoder(bool useH264, int Threads)
+@@ -180,16 +180,21 @@
+ }
+ else
+ {
++#if LIBAVCODEC_VERSION_INT >= ((58<<16)+(54<<8)+100)
++ video_codecid=AV_CODEC_ID_MPEG2VIDEO;
++#else
+ video_codecid=AV_CODEC_ID_MPEG2VIDEO_XVMC;
++#endif
+ }
+-
+ video_codec = avcodec_find_decoder(video_codecid);
++#if LIBAVCODEC_VERSION_INT < ((58<<16)+(54<<8)+100)
+ if ((!video_codec) && (video_codecid==AV_CODEC_ID_MPEG2VIDEO_XVMC))
+ {
+ // fallback to MPEG2VIDEO
+ video_codecid=AV_CODEC_ID_MPEG2VIDEO;
+ video_codec=avcodec_find_decoder(video_codecid);
+ }
++#endif
+
+ if (video_codec)
+ {
+@@ -200,17 +205,28 @@
+ #endif
+ if (video_context)
+ {
++#if LIBAVCODEC_VERSION_INT >= ((58<<16)+(54<<8)+100)
++ if (video_codec->capabilities & AV_CODEC_CAP_TRUNCATED)
++ video_context->flags|=AV_CODEC_FLAG_TRUNCATED; // we do not send complete frames
++ video_context->flags|=AV_CODEC_FLAG_LOW_DELAY;
++ video_context->flags2|=AV_CODEC_FLAG2_FAST; // really?
++#else
+ if (video_codec->capabilities & CODEC_CAP_TRUNCATED)
+ video_context->flags|=CODEC_FLAG_TRUNCATED; // we do not send complete frames
+ video_context->flags|=CODEC_FLAG_LOW_DELAY;
+ video_context->flags2|=CODEC_FLAG2_FAST; // really?
++#endif
+ video_context->skip_idct=AVDISCARD_ALL;
+
+ if (video_codecid!=AV_CODEC_ID_H264)
+ {
+ video_context->skip_frame=AVDISCARD_NONKEY; // just I-frames
+ } else {
++#if LIBAVCODEC_VERSION_INT >= ((58<<16)+(54<<8)+100)
++ video_context->flags2|=AV_CODEC_FLAG2_CHUNKS;
++#else
+ video_context->flags2|=CODEC_FLAG2_CHUNKS;
++#endif
+ #if LIBAVCODEC_VERSION_INT >= ((52<<16)+(47<<8)+0)
+ av_log_set_level(AV_LOG_FATAL); // silence decoder output
+ #else
+@@ -224,6 +240,7 @@
+ #else
+ int ret=avcodec_open(video_context, video_codec);
+ #endif
++#if LIBAVCODEC_VERSION_INT < ((58<<16)+(54<<8)+100)
+ if ((ret < 0) && (video_codecid==AV_CODEC_ID_MPEG2VIDEO_XVMC))
+ {
+ // fallback to MPEG2VIDEO
+@@ -234,21 +251,22 @@
+ video_context->codec_type=AVMEDIA_TYPE_UNKNOWN;
+ video_context->codec_id=AV_CODEC_ID_NONE;
+ video_context->codec_tag=0;
+-#if (LIBAVCODEC_VERSION_MAJOR < 57)
++ #if (LIBAVCODEC_VERSION_MAJOR < 57)
+ memset(video_context->codec_name,0,sizeof(video_context->codec_name));
+-#endif
+-#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(5<<8)+0)
++ #endif
++ #if LIBAVCODEC_VERSION_INT >= ((53<<16)+(5<<8)+0)
+ video_context->thread_count=threadcount;
+ ret=avcodec_open2(video_context, video_codec, NULL);
+-#else
++ #else
+ ret=avcodec_open(video_context, video_codec);
+-#endif
++ #endif
+ }
+ else
+ {
+ ret=-1;
+ }
+ }
++#endif
+ if (ret < 0)
+ {
+ switch (video_codecid)
+@@ -256,9 +274,11 @@
+ case AV_CODEC_ID_H264:
+ esyslog("could not open codec for H264");
+ break;
++#if LIBAVCODEC_VERSION_INT < ((58<<16)+(54<<8)+100)
+ case AV_CODEC_ID_MPEG2VIDEO_XVMC:
+ esyslog("could not open codec MPEG2 (XVMC)");
+ break;
++#endif
+ case AV_CODEC_ID_MPEG2VIDEO:
+ esyslog("could not open codec MPEG2");
+ break;
+@@ -322,8 +342,10 @@
+ case AV_CODEC_ID_H264:
+ esyslog("codec for H264 not found");
+ break;
++#if LIBAVCODEC_VERSION_INT < ((58<<16)+(54<<8)+100)
+ case AV_CODEC_ID_MPEG2VIDEO_XVMC:
+ esyslog("codec for MPEG2 (XVMC) not found");
++#endif
+ break;
+ case AV_CODEC_ID_MPEG2VIDEO:
+ esyslog("codec for MPEG2 not found");
+diff -u -r --new-file '--exclude=logos' '--exclude=version.h' '--exclude=po' a/command/markad-standalone.cpp b/command/markad-standalone.cpp
+--- a/command/markad-standalone.cpp 2019-11-24 21:19:26.029386427 +0000
++++ b/command/markad-standalone.cpp 2019-11-25 21:22:42.619607452 +0000
+@@ -73,11 +73,12 @@
+ }
+ else
+ {
+- char buf[255]={0};
++ char buf[27]={0};
+ const time_t now=time(NULL);
+ if (ctime_r(&now,buf)) {
+ buf[strlen(buf)-6]=0;
+ }
++ 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);
+diff -u -r --new-file '--exclude=logos' '--exclude=version.h' '--exclude=po' a/command/marks.h b/command/marks.h
+--- a/command/marks.h 2019-11-24 21:19:26.029386427 +0000
++++ b/command/marks.h 2019-11-25 21:46:15.441506332 +0000
+@@ -89,8 +89,9 @@
+ {
+ if (FileName)
+ {
+- strncpy(filename,FileName,sizeof(filename)-1);
++ strncpy(filename,FileName,sizeof(filename));
+ filename[sizeof(filename)-1]=0;
++
+ }
+ }
+ clMark *Add(int Type, int Position, const char *Comment = NULL);
diff --git a/01-markad-Makefile-V0-06.diff b/01-markad-Makefile-V0-06.diff
new file mode 100644
index 0000000..b210696
--- /dev/null
+++ b/01-markad-Makefile-V0-06.diff
@@ -0,0 +1,272 @@
+Index: vdr-plugin-markad-0.1.4.git20170313/Makefile
+===================================================================
+--- vdr-plugin-markad-0.1.4.git20170313.orig/Makefile 2019-11-29 15:28:34.503165499 +0100
++++ vdr-plugin-markad-0.1.4.git20170313/Makefile 2019-11-29 15:28:34.495165632 +0100
+@@ -4,15 +4,38 @@
+ # dont remove the next line, its needed for the VDR Makefile
+ # $(LIBDIR)/$@.$(APIVERSION)
+
+-DIRS = command plugin
++### The version number of this plugin (taken from the main source file):
+
+-$(shell GITVERSION=`git rev-parse --short HEAD 2> /dev/null`; if [ "$$GITVERSION" ]; then sed "s/\";/ ($$GITVERSION)\";/" version.dist > version.h; else cp version.dist version.h; fi)
+ VERSION = $(shell grep 'static const char \*VERSION *=' version.h | awk '{ print $$6 }' | sed -e 's/[";]//g')
++GITTAG = $(shell git describe --always 2>/dev/null)
++$(shell GITVERSION=`git rev-parse --short HEAD 2> /dev/null`; if [ "$$GITVERSION" ]; then sed "s/\";/ ($$GITVERSION)\";/" version.dist > version.h; else cp version.dist version.h; fi)
++
++### The directory environment:
++
++# Use package data if installed...otherwise assume we're under the VDR source directory:
++PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." pkg-config --variable=$(1) vdr))
++LIBDIR = $(call PKGCFG,libdir)
++LOCDIR = $(call PKGCFG,locdir)
++PLGCFG = $(call PKGCFG,plgcfg)
++CFGDIR = $(call PKGCFG,configdir)
++#
++TMPDIR ?= /tmp
++DIRS = command plugin
++
++### The compiler options:
++export CFLAGS = $(call PKGCFG,cflags)
++export CXXFLAGS = $(call PKGCFG,cxxflags)
+
+-TMPDIR = /tmp
+ ARCHIVE = markad-$(VERSION)
+ PACKAGE = vdr-$(ARCHIVE)
+
++### The version number of VDR's plugin API:
++APIVERSION = $(call PKGCFG,apiversion)
++
++### Allow user defined options to overwrite defaults:
++-include $(PLGCFG)
++
++
+ all:
+ for i in $(DIRS); do $(MAKE) -C $$i; done
+
+Index: vdr-plugin-markad-0.1.4.git20170313/plugin/Makefile
+===================================================================
+--- vdr-plugin-markad-0.1.4.git20170313.orig/plugin/Makefile 2019-11-29 15:28:34.503165499 +0100
++++ vdr-plugin-markad-0.1.4.git20170313/plugin/Makefile 2019-11-29 15:28:34.495165632 +0100
+@@ -1,54 +1,51 @@
+ #
+ # Makefile for a Video Disk Recorder plugin
++# Adapted to the new VDR makefile environment by Stefan Hofmann
+ #
++# $Id: $
+
+ # The official name of this plugin.
+ # This name will be used in the '-P...' option of VDR to load the plugin.
+ # By default the main source file also carries this name.
+-# IMPORTANT: the presence of this macro is important for the Make.config
+-# file. So it must be defined, even if it is not used here!
+-#
+-PLUGIN = markad
+-
+-### The version number of this plugin (taken from the main source file):
+
+-$(shell GITVERSION=`git rev-parse --short HEAD 2> /dev/null`; if [ "$$GITVERSION" ]; then sed "s/\";/ ($$GITVERSION)\";/" ../version.dist > ../version.h; else cp ../version.dist ../version.h; fi)
+-VERSION = $(shell grep 'static const char \*VERSION *=' ../version.h | awk '{ print $$6 }' | sed -e 's/[";]//g')
++PLUGIN = markad
+
+-### The C++ compiler and options:
++### The version number of this plugin (taken from the version header file):
+
+-CXX ?= g++
+-CXXFLAGS ?= -fPIC -g -O2 -Wall -Wextra -Woverloaded-virtual -Wno-parentheses
++VERSION = $(shell grep 'static const char \*VERSION *=' version.h | awk '{ print $$6 }' | sed -e 's/[";]//g')
+
+ ### The directory environment:
+
+-VDRDIR ?= ../../../..
+-LIBDIR ?= ../../../lib
++# Use package data if installed...otherwise assume we're under the VDR source directory:
++PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../../.." pkg-config --variable=$(1) vdr))
++LIBDIR = $(call PKGCFG,libdir)
++LOCDIR = $(call PKGCFG,locdir)
++#
+ TMPDIR ?= /tmp
+
+-### Make sure that necessary options are included:
+-
+--include $(VDRDIR)/Make.global
++### The compiler options:
+
+-### Allow user defined options to overwrite defaults:
++export CFLAGS = $(call PKGCFG,cflags)
++export CXXFLAGS = $(call PKGCFG,cxxflags)
+
+--include $(VDRDIR)/Make.config
++### The version number of VDR's plugin API:
+
+-### The version number of VDR's plugin API (taken from VDR's "config.h"):
+-
+-APIVERSION = $(shell sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h)
++APIVERSION = $(call PKGCFG,apiversion)
+
+ ### The name of the distribution archive:
+
+ ARCHIVE = $(PLUGIN)-$(VERSION)
+ PACKAGE = vdr-$(ARCHIVE)
+
++### The name of the shared object file:
++
++SOFILE = libvdr-$(PLUGIN).so
++
+ ### Includes and Defines (add further entries here):
+
+-INCLUDES += -I$(VDRDIR)/include
++INCLUDES +=
+
+-DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
+-DEFINES += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
++DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
+
+ ### The object files (add further files here):
+
+@@ -56,12 +53,12 @@
+
+ ### The main target:
+
+-all: libvdr-$(PLUGIN).so i18n
++all: $(SOFILE) i18n
+
+ ### Implicit rules:
+
+ %.o: %.cpp
+- $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
++ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
+
+ ### Dependencies:
+
+@@ -75,36 +72,39 @@
+ ### Internationalization (I18N):
+
+ PODIR = po
+-LOCALEDIR = $(VDRDIR)/locale
+ I18Npo = $(wildcard $(PODIR)/*.po)
+-I18Nmsgs = $(addprefix $(LOCALEDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file))))))
++I18Nmo = $(addsuffix .mo, $(foreach file, $(I18Npo), $(basename $(file))))
++I18Nmsgs = $(addprefix $(DESTDIR)$(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file))))))
+ I18Npot = $(PODIR)/$(PLUGIN).pot
+
+ %.mo: %.po
+ msgfmt -c -o $@ $<
+
+ $(I18Npot): $(wildcard *.cpp *.h)
+- xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --msgid-bugs-address='<see README>' -o $@ $^
++ xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<vdr(a)dolze.de>' -o $@ `ls $^`
+
+ %.po: $(I18Npot)
+- msgmerge -U --no-wrap --no-location --backup=none -q $@ $<
++ msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
+ @touch $@
+
+-$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
+- @mkdir -p $(dir $@)
+- cp $< $@
++$(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
++ install -D -m644 $< $@
+
+ .PHONY: i18n
+-i18n: $(I18Nmsgs) $(I18Npot)
++i18n: $(I18Nmo) $(I18Npot)
++
++install-i18n: $(I18Nmsgs)
+
+ ### Targets:
+
+-install: all
+- cp --remove-destination libvdr-$(PLUGIN).so $(LIBDIR)/libvdr-$(PLUGIN).so.$(APIVERSION)
++$(SOFILE): $(OBJS)
++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
++
++install-lib: $(SOFILE)
++ install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
+
+-libvdr-$(PLUGIN).so: $(OBJS)
+- $(CXX) $(CXXFLAGS) -shared $(OBJS) $(LIBS) -o $@
+- cp --remove-destination libvdr-$(PLUGIN).so $(LIBDIR)/libvdr-$(PLUGIN).so.$(APIVERSION)
++install: install-lib install-i18n
+
+ clean:
+- @-rm -f $(OBJS) $(DEPFILE) *.so *.so.* *.tgz core* *~ $(PODIR)/*.mo $(PODIR)/*.pot
++ @-rm -f $(PODIR)/*.mo $(PODIR)/*.pot
++ @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~
+Index: vdr-plugin-markad-0.1.4.git20170313/command/Makefile
+===================================================================
+--- vdr-plugin-markad-0.1.4.git20170313.orig/command/Makefile 2019-11-29 15:28:34.503165499 +0100
++++ vdr-plugin-markad-0.1.4.git20170313/command/Makefile 2019-11-29 15:28:53.018858486 +0100
+@@ -10,15 +10,23 @@
+ $(shell GITVERSION=`git rev-parse --short HEAD 2> /dev/null`; if [ "$$GITVERSION" ]; then sed "s/\";/ ($$GITVERSION)\";/" ../version.dist > ../version.h; else cp ../version.dist ../version.h; fi)
+ VERSION = $(shell grep 'static const char \*VERSION *=' ../version.h | awk '{ print $$6 }' | sed -e 's/[";]//g')
+
+-### The C++ compiler and options:
++# Use package data if installed...otherwise assume we're under the VDR source directory:
++PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../../.." pkg-config --variable=$(1) vdr))
++LIBDIR = $(call PKGCFG,libdir)
++LOCDIR = $(call PKGCFG,locdir)
++PLGCFG = $(call PKGCFG,plgcfg)
++CFGDIR = $(call PKGCFG,configdir)
+
++### The C++ compiler and options:
+ CXX ?= g++
+-CXXFLAGS ?= -g -rdynamic -O3 -funroll-loops -Wall -Wextra -Woverloaded-virtual -Wno-parentheses
++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
++#
+ PKG-CONFIG ?= pkg-config
+ STRIP ?= strip
+
+ ### Includes and Defines (add further entries here):
+-
+ PKG-LIBS += libavcodec libavutil
+ PKG-INCLUDES += libavcodec libavutil
+
+@@ -36,7 +44,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
+
+ ### The main target:
+
+@@ -59,9 +67,9 @@
+ ### Internationalization (I18N):
+
+ PODIR = po
+-LOCALEDIR = $(DESTDIR)/usr/share/locale
++LOCALEDIR = /usr/share/locale
+ I18Npo = $(wildcard $(PODIR)/*.po)
+-I18Nmsgs = $(addprefix $(LOCALEDIR)/, $(addsuffix /LC_MESSAGES/markad.mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file))))))
++I18Nmsgs = $(addprefix $(DESTDIR)$(LOCALEDIR)/, $(addsuffix /LC_MESSAGES/markad.mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file))))))
+ I18Npot = $(PODIR)/markad.pot
+
+ %.mo: %.po
+@@ -74,9 +82,8 @@
+ msgmerge -U --no-wrap --no-location --backup=none -q $@ $<
+ @touch $@
+
+-$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/markad.mo: $(PODIR)/%.mo
+- @mkdir -p $(dir $@)
+- cp $< $@
++$(I18Nmsgs): $(DESTDIR)$(LOCALEDIR)/%/LC_MESSAGES/markad.mo: $(PODIR)/%.mo
++ install -D -m644 $< $@
+
+ .PHONY: i18n
+ i18n: $(I18Npot)
+@@ -94,10 +101,9 @@
+
+ install: install-doc markad $(I18Nmsgs)
+ @mkdir -p $(DESTDIR)/usr/bin
+- @cp --remove-destination markad $(DESTDIR)/usr/bin/markad
+- @$(STRIP) $(DESTDIR)/usr/bin/markad
++ install -D markad $(DESTDIR)/usr/bin/markad
+ @mkdir -p $(DESTDIR)/var/lib/markad
+- @cp -u logos/* $(DESTDIR)/var/lib/markad
++ install -D logos/* $(DESTDIR)/var/lib/markad
+ @echo markad installed
+
+ clean:
diff --git a/02-deprecated-V0-04.diff b/02-deprecated-V0-04.diff
new file mode 100644
index 0000000..d27dd47
--- /dev/null
+++ b/02-deprecated-V0-04.diff
@@ -0,0 +1,74 @@
+--- a/command/decoder.cpp 2019-11-29 16:43:13.167805436 +0100
++++ b/command/decoder.cpp 2019-11-29 16:51:16.644580236 +0100
+@@ -122,7 +122,9 @@
+ #if LIBAVCODEC_VERSION_INT < ((53<<16)+(7<<8)+1)
+ avcodec_init();
+ #endif
++#if LIBAVCODEC_VERSION_INT < ((58<<16)+(54<<8)+100)
+ avcodec_register_all();
++#endif
+
+ last_qscale_table=NULL;
+ skipframes=true;
+@@ -383,7 +385,28 @@
+ #endif
+ if (dest)
+ {
++#if LIBAVCODEC_VERSION_INT >= ((57<<16)+(107<<8)+100)
++ AVCodecParameters *par = avcodec_parameters_alloc();
++ int rc = avcodec_parameters_from_context(par,video_context);
++ if ( rc < 0 ) {
++ esyslog("ERROR (%s,%d): avcodec_parameters_from_context() failed rc=%d", __FILE__, __LINE__, rc);
++ ret = false;
++ }
++ else {
++ rc = avcodec_parameters_to_context(dest,par);
++ if ( rc < 0) {
++ esyslog("ERROR (%s,%d): avcodec_parameters_to_context() failed rc=%d", __FILE__, __LINE__, rc);
++ ret = false;
++ }
++ }
++ avcodec_parameters_free(&par);
++ dest->skip_frame=video_context->skip_frame;
++ dest->flags=video_context->flags;
++ dest->flags2=video_context->flags2;
++ dest->skip_idct=video_context->skip_idct;
++#else
+ if (avcodec_copy_context(dest,video_context)!=0) ret=false;
++#endif
+ }
+ else
+ {
+@@ -475,11 +498,27 @@
+ while (avpkt.size>0)
+ {
+ #if LIBAVCODEC_VERSION_INT < ((52<<16)+(25<<8)+0)
+- len=avcodec_decode_video(video_context,video_frame,&video_frame_ready,
+- avpkt.data,avpkt.size);
+-#else
+- len=avcodec_decode_video2(video_context,video_frame,&video_frame_ready,
+- &avpkt);
++ len=avcodec_decode_video(video_context,video_frame,&video_frame_ready,avpkt.data,avpkt.size);
++#elif LIBAVCODEC_VERSION_INT < ((57<<16)+(107<<8)+100)
++ len=avcodec_decode_video2(video_context,video_frame,&video_frame_ready,&avpkt);
++#else
++ len=avcodec_send_packet(video_context,&avpkt);
++ if (len < 0) {
++ if (len == AVERROR(EAGAIN)) dsyslog("avcodec_send_packet error EAGAIN");
++ if (len == AVERROR(ENOMEM)) dsyslog("avcodec_send_packet error ENOMEM");
++ if (len == AVERROR(EINVAL)) dsyslog("avcodec_send_packet error EINVAL");
++ if (len != AVERROR_INVALIDDATA) { // this is normal at the start of the file
++ esyslog("avcodec_send_packet failed with rc=%i",len);
++ }
++ }
++ len = avcodec_receive_frame(video_context,video_frame);
++ if (len < 0) {
++ if (len == AVERROR(EINVAL)) dsyslog("avcodec_receive_frame error EINVAL");
++ if (len == AVERROR(EAGAIN)) len=0;
++ }
++ else {
++ video_frame_ready = true;
++ }
+ #endif
+ if (len<0)
+ {
diff --git a/03-markad-decoder-V0-24.diff b/03-markad-decoder-V0-24.diff
new file mode 100644
index 0000000..f88bae3
--- /dev/null
+++ b/03-markad-decoder-V0-24.diff
@@ -0,0 +1,2319 @@
+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-01 14:06:01.587871907 +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-01 14:06:01.587871907 +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-01 14:06:01.587871907 +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-01 14:06:01.587871907 +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-01 14:06:01.587871907 +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-01 14:06:01.579871822 +0100
++++ b/command/decoder.cpp 2019-12-01 14:06:01.587871907 +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-01 21:15:37.750414902 +0100
+@@ -0,0 +1,427 @@
++#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: failed to allocate string, out of memory?");
++ return false;
++ }
++ fileNumber++;
++ if (asprintf(&filename,"%s/%05i.ts",recDir,fileNumber)==-1) {
++ esyslog("cDecoder: 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: decode file %s",filename);
++ }
++ else {
++ if (fileNumber <= 1) esyslog("cDecoder: Could not open source file %s", filename);
++ return(false);
++ }
++ if (avformat_find_stream_info(avctx, NULL) <0) {
++ esyslog("cDecoder: 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: using decoder %s for stream",codec->long_name);
++ 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 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 (avpkt.flags == AV_PKT_FLAG_KEY) {
++ 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 iframe %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 (avpkt.flags == AV_PKT_FLAG_KEY) {
++ 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) {
++ if (rc == AVERROR(EAGAIN)) dsyslog("cDecoder::GetFrameInfo() avcodec_send_packet error EAGAIN at frame %li", framenumber);
++ else if (rc == AVERROR(ENOMEM)) dsyslog("cDecoder::GetFrameInfo() avcodec_send_packet error ENOMEM at frame %li", framenumber);
++ else if (rc == AVERROR(EINVAL)) dsyslog("cDecoder::GetFrameInfo() avcodec_send_packet error EINVAL at frame %li", framenumber);
++ else if (rc == AVERROR_INVALIDDATA) dsyslog("cDecoder::GetFrameInfo() avcodec_send_packet error AVERROR_INVALIDDATA at frame %li", framenumber); // this could happen on the start of a recording
++ else dsyslog("cDecoder::GetFrameInfo() avcodec_send_packet failed with rc=%i at frame %li",rc,framenumber);
++ return false;
++ }
++ if (rc < 0) {
++ esyslog("cDecoder::GetFrameInfo() avcodec_send_packet NULL failed with rc=%i at frame %li",rc,framenumber);
++ return false;
++ }
++// rc=avcodec_send_packet(codecCtx,NULL); // force immediate decoding
++
++ rc = avcodec_receive_frame(codecCtx,avFrame);
++ if (rc < 0) {
++ if (rc == AVERROR(EAGAIN)) dsyslog("cDecoder::GetFrameInfo() avcodec_receive_frame error EAGAIN at frame %li", framenumber);
++ else if (rc == AVERROR(EINVAL)) dsyslog("cDecoder::GetFrameInfo() avcodec_receive_frame error EINVAL at frame %li", framenumber);
++ else dsyslog("cDecoder::GetFrameInfo() avcodec_receive_frame: decode of frame (%li) failed with return code %i", framenumber, rc);
++// avcodec_flush_buffers(codecCtx); // Reset the internal decoder state
++ return false;
++ }
++// avcodec_flush_buffers(codecCtx); // Reset the internal decoder state
++#else
++ int rc=0;
++ 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
++
++ 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 iframe (%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 iframe (%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 iframe %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;
++ }
++
++ 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 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) return true;
++ return false;
++}
++
++
++long int cDecoder::GetFrameNumber(){
++ return framenumber;
++}
++
++long int cDecoder::GetIFrameCount(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: 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: frame (%li) is not an iFrame, returning time from iFrame before (%li) %lims",iFrame,before_iFrame,before_pts);
++ return before_pts;
++ }
++ else {
++ esyslog("cDecoder: 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: 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-01 14:06:01.591871950 +0100
+@@ -0,0 +1,58 @@
++#include <vector>
++#include "global.h"
++
++extern "C"{
++#include <libavcodec/avcodec.h>
++#include <libavformat/avformat.h>
++#include <libavformat/avio.h>
++#include <libavutil/file.h>
++}
++
++class cDecoder
++{
++ public:
++ cDecoder();
++ ~cDecoder();
++ bool DecodeDir(const char * recDir);
++ void Reset();
++ bool DecodeFile(const char * filename);
++ int GetVideoHeight();
++ int GetVideoWidth();
++ int GetVideoFramesPerSecond();
++ 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(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 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;
++};
+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-01 14:06:01.591871950 +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-01 14:06:01.591871950 +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;
+diff -u --new-file '--exclude=version.h' a/command/Makefile b/command/Makefile
+--- a/command/Makefile 2019-12-01 14:06:01.567871696 +0100
++++ b/command/Makefile 2019-12-01 14:06:01.591871950 +0100
+@@ -27,8 +27,8 @@
+ 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 +44,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-01 14:06:01.000000000 +0100
++++ b/command/markad-standalone.cpp 2019-12-01 21:53:49.817128272 +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,37 +234,84 @@
+ 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) + macontext.Video.Info.FramesPerSecond * 30; // try to skip the start ad
++ 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);
++ if (ignoreHborder) {
++ marks.Del(MT_HBORDERSTART);
++ marks.Del(MT_HBORDERSTOP);
++ }
+ int delta=macontext.Video.Info.FramesPerSecond*MAXRANGE;
+- clMark *end=marks.GetAround(delta,iStop,MT_STOP,0x0F);
++ clMark *end=marks.GetAround(3*delta,iStopA,MT_ASPECTSTOP); // try if we can get a good stop mark
++ if (!end) {
++ dsyslog("no MT_ASPECTSTOP mark found");
++ end=marks.GetAround(INT_MAX,iStopA,MT_STOP,0x0F); // try any type of stop mark
++ }
++ 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);
+- isyslog("using mark on position %i as stop mark",end->position);
++ {
++ dsyslog("found end mark at (%i)", end->position);
++ if (end->type == MT_NOBLACKSTOP) { // this is a week mark, try if there exists another stop mark
++ clMark *end2=marks.GetAround(delta,iStopA-delta,MT_STOP,0x0F);
++ if ((end2) && (end2->type != MT_NOBLACKSTOP) && (end2->position >= iStopA - 3*delta)) {
++ dsyslog("stop mark is week, use stronger stop mark at (%i)", end2->position);
++ end=end2;
++ }
++ else { // try next stop mark, better save than sorry
++ clMark *end3=marks.GetAround(2*delta,end2->position+2*delta,MT_STOP,0x0F);
++ if (end3) {
++ dsyslog("stop mark is week, use next stop mark at (%i)", end3->position);
++ end=end3;
++ }
++ }
++
++ }
++ 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 {
++ marks.DelTill(end->position,false);
++ isyslog("using mark on position %i as stop mark",end->position);
++ }
++ }
++ else {
++ marks.DelTill(end->position,false);
++ isyslog("using mark on position %i as stop mark",end->position);
++ }
+ }
+ else
+ {
++ dsyslog("no STOP mark found");
+ //fallback
+ if (iStopinBroadCast)
+ {
+- MarkAdMark mark;
+- memset(&mark,0,sizeof(mark));
++ MarkAdMark mark={};
+ mark.Position=iStopA;
+ mark.Type=MT_ASSUMEDSTOP;
+ AddMark(&mark);
+@@ -281,8 +329,11 @@
+
+ void cMarkAdStandalone::CheckStart()
+ {
+- dsyslog("checking start");
++ dsyslog("checking start (%i)", lastiframe);
+ 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 +383,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 +446,8 @@
+ 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);
+ }
+ }
+
+@@ -399,11 +461,29 @@
+ marks.Del(MT_VBORDERSTART);
+ marks.Del(MT_VBORDERSTOP);
+ }
++ else {
++ clMark *bStart=marks.GetAround(iStartA,iStartA,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(iStartA,iStartA,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 +500,84 @@
+ }
+ }
+ }
++ if (begin->type == MT_NOBLACKSTART) { // this is weak, check if there is a better logo mark
++ clMark *begin3=marks.GetAround(iStartA,iStartA,MT_LOGOSTART);
++ if (begin3) {
++ if (begin3->position > 0) {
++ 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 < abs(iStart)/3)) { // 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);
+@@ -457,14 +592,45 @@
+ clMark *mark=marks.GetFirst();
+ while (mark)
+ {
++
++ 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_LOGOSTART) && mark->Next() && mark->Next()->type==MT_LOGOSTOP)
++ {
++// int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*30);
++ 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();
++ if (tmp->Next()->Next()) marks.Del(tmp->Next()); // do not delete stop mark
++ marks.Del(tmp);
++ 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 +638,16 @@
+ continue;
+ }
+ }
++
++ 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)", mark->position, mark->Next()->position);
++ marks.Del(mark->Next());
++ }
++ if (((mark->type & 0x0F)==MT_START) && (!mark->Next())) { // delete start mark at the end
++ dsyslog("deleting START mark at the end");
++ marks.Del(mark);
++ break;
++ }
+ mark=mark->Next();
+ }
+ }
+@@ -492,6 +668,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 +755,18 @@
+ }
+ }
+
+- /*
+- if ((Mark->Type==MT_LOGOSTART) && (!iStart) && (Mark->Position<abs(iStop)))
++// if ( (Mark->Type == MT_LOGOSTART) && (!iStart) && (Mark->Position < (abs(iStopA) - macontext.Video.Info.FramesPerSecond*MAXRANGE )))
++ if (((Mark->Type & 0x0F)==MT_START) && (!iStart) && (Mark->Position < (abs(iStopA) - 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 +774,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 +783,18 @@
+ int MARKDIFF;
+ if ((Mark->Type & 0xF0)==MT_LOGOCHANGE)
+ {
+- MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*180);
++// MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*120);
++// MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*80);
++ 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,6 +883,7 @@
+ dsyslog("slept too much");
+ return; // we already slept too much
+ }
++ if (ptr_cDecoder) framecnt = ptr_cDecoder->GetFrameNumber();
+
+ bool notenough=true;
+ do
+@@ -740,7 +923,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 +996,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 +1031,6 @@
+ int actframe=Frame;
+ int framecounter=0;
+ int pframe=-1;
+-
+ MarkAdPos *pos=NULL;
+
+ while (framecounter<Frames)
+@@ -936,7 +1118,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 +1156,94 @@
+ 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->GetIFrameCount(fRangeBegin, (*mark1)->position);
++ if (iFrameCount<=0) {
++ dsyslog("cMarkAdStandalone::ProcessMark2ndPass() GetIFrameCount 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->isVideoIFrame()) continue;
++ if (!ptr_cDecoder->GetFrameInfo(&macontext)) {
++ dsyslog("cMarkAdStandalone::ProcessMark2ndPass() GetFrameInfo failed at frame (%li)", ptr_cDecoder->GetFrameNumber());
++ return false;
++ }
++ 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->GetIFrameCount(fRangeBegin, fRangeEnd)-2;
++ if (iFrameCount<=0) {
++ dsyslog("cMarkAdStandalone::ProcessMark2ndPass() GetIFrameCount 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->isVideoIFrame()) continue;
++ if (!ptr_cDecoder->GetFrameInfo(&macontext)) {
++ dsyslog("cMarkAdStandalone::ProcessMark2ndPass() GetFrameInfo failed at frame (%li)", ptr_cDecoder->GetFrameNumber());
++ return false;
++ }
++ ptr_MarkAdPos=video->ProcessOverlap(ptr_cDecoder->GetFrameNumber(),iFrameCount,false,(macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264));
++ if (ptr_MarkAdPos) dsyslog("cMarkAdStandalone::ProcessMark2ndPass 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 +1268,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 +1289,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 +1326,7 @@
+ }
+ }
+
++
+ bool cMarkAdStandalone::ProcessFile(int Number)
+ {
+ if (!directory) return false;
+@@ -1075,7 +1356,6 @@
+ }
+
+ int f=open(fbuf,O_RDONLY);
+- free(fbuf);
+ if (f==-1) {
+ if (isTS) {
+ dsyslog("failed to open %05i.ts",Number);
+@@ -1084,13 +1364,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 +1464,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 +1562,120 @@
+ return ret;
+ }
+
++void cMarkAdStandalone::ProcessFrame(cDecoder *ptr_cDecoder)
++{
++ if ((macontext.Config->logoExtraction!=-1) && (ptr_cDecoder->GetFrameNumber()>=256)) { // extract logo
++ isyslog("finished logo extraction, please check /tmp for pgm files");
++ abort=true;
++ }
++
++ ptr_cDecoder->GetFrameInfo(&macontext);
++ if(ptr_cDecoder->isVideoStream()) {
++ if(ptr_cDecoder->isVideoIFrame()) {
++ 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))) {
++ dsyslog("start 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
++ macontext.Video.Options.IgnoreLogoDetection=false;
++ }
++
++ 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");
++ 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("video frames per second %f", macontext.Video.Info.FramesPerSecond);
++
++ 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,7 +1689,7 @@
+ 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)
+ {
+@@ -1677,6 +2054,8 @@
+ int len=strlen(macontext.Info.ChannelName);
+ if (!len) return false;
+
++ dsyslog("using logo directory %s",macontext.Config->logoDirectory);
++ dsyslog("searching for logo file %s-P0.pgm",macontext.Info.ChannelName);
+ DIR *dir=opendir(macontext.Config->logoDirectory);
+ if (!dir) return false;
+
+@@ -1815,6 +2194,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 +2207,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 +2597,8 @@
+ duplicate=false;
+ title[0]=0;
+
+- memset(&macontext,0,sizeof(macontext));
++ macontext={};
++// memset(&macontext,0,sizeof(macontext));
+ macontext.Config=config;
+
+ bDecodeVideo=config->DecodeVideo;
+@@ -2370,7 +2752,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 +2962,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 to fix mark timestamps in HD videos\n"
+ "\ncmd: one of\n"
+ "- dummy-parameter if called directly\n"
+ "after markad starts to analyze the recording\n"
+@@ -2656,8 +3042,8 @@
+ bool bPass2Only=false;
+ bool bPass1Only=false;
+
+- struct config config;
+- memset(&config,0,sizeof(config));
++ struct config config={};
++// memset(&config,0,sizeof(config));
+
+ // set defaults
+ config.DecodeVideo=true;
+@@ -2668,6 +3054,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 +3075,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 +3091,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 +3254,11 @@
+ // --extractlogo
+ str=optarg;
+ ntok=0;
+- while (tok=strtok(str,","))
++// while (tok=strtok(str,","))
++ while (true)
+ {
++ tok=strtok(str,",");
++ if (!tok) break;
+ switch (ntok)
+ {
+ case 0:
+@@ -3028,6 +3419,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 +3470,7 @@
+ if ( strstr(argv[optind],".rec") != NULL )
+ {
+ recDir=realpath(argv[optind],NULL);
++ config.recDir=recDir;
+ }
+ }
+ optind++;
+@@ -3205,6 +3613,13 @@
+ cmasta = new cMarkAdStandalone(recDir,&config);
+ if (!cmasta) return -1;
+
++ esyslog("parameter --loglevel is set to %i", SysLogLevel);
++ dsyslog("parameter --logocachedir is set to %s",config.logoDirectory);
++ dsyslog("parameter --log2rec is set");
++ dsyslog("parameter --threads is set to %i", config.threads);
++ dsyslog("parameter --astopoffs is set to %i",config.astopoffs);
++ dsyslog("parameter --cDecoder 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-01 14:06:01.591871950 +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-01 14:06:01.591871950 +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)
+ {
+@@ -346,12 +351,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 +701,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 +721,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-01 14:06:01.000000000 +0100
++++ b/command/marks.h 2019-12-01 14:06:01.591871950 +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-01 14:06:01.591871950 +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)
+ {
++// dsyslog("--- cMarkAdLogo::Load plane %i", plane);
+ if ((plane<0) || (plane>3)) return -3;
+
+ char *path;
+@@ -338,13 +341,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 +425,28 @@
+ 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;
+ }
+
+@@ -727,9 +821,11 @@
+ for (int A=start; A<histcnt[OV_AFTER]; A++)
+ {
+ //printf("%6i %6i ",histbuf[OV_BEFORE][B].framenumber,histbuf[OV_AFTER][A].framenumber);
++// dsyslog("---cMarkAdOverlap::Detect() similarCutOff %8i",similarCutOff);
+ 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,7 +837,7 @@
+ }
+ else
+ {
+- //if (simcnt) printf("simcnt=%i\n",simcnt);
++// if (simcnt) dsyslog("---simcnt=%i",simcnt);
+
+ if (simcnt>similarMaxCnt)
+ {
+@@ -777,11 +873,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 +936,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 +949,7 @@
+ cMarkAdVideo::~cMarkAdVideo()
+ {
+ resetmarks();
++ if (blackScreen) delete blackScreen;
+ if (hborder) delete hborder;
+ if (vborder) delete vborder;
+ if (logo) delete logo;
+@@ -855,6 +962,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 +970,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 +1015,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 +1028,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 +1054,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 +1085,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-01 14:06:01.591871950 +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;
diff --git a/sources b/sources
index 2f58001..7a20152 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-674756f4f033c42fc6f51a8dc68a8b2b vdr-plugin-markad-ea2e182ec798375f3830f8b794e7408576f139ad.tar.bz2
+SHA512 (vdr-plugin-markad-ea2e182ec798375f3830f8b794e7408576f139ad.tar.bz2) = 426e4b986bbe802ca9dba61dba0b00045207ca71e5707a514a32d72e1c79bd6b01eae84af078f1f2c0903840be559ef4c9388228cb4b909067ef7076043d5588
diff --git a/vdr-markad.spec b/vdr-markad.spec
index 47acf4a..6444e36 100644
--- a/vdr-markad.spec
+++ b/vdr-markad.spec
@@ -1,10 +1,11 @@
%global commit0 ea2e182ec798375f3830f8b794e7408576f139ad
%global shortcommit0 %(c=%{commit0}; echo ${c:0:7})
%global gitdate 20170313
+%global sname markad
Name: vdr-markad
Version: 0.1.4
-Release: 25.%{gitdate}git%{shortcommit0}%{?dist}
+Release: 26.%{gitdate}git%{shortcommit0}%{?dist}
Summary: Advanced commercial detection for VDR
License: GPLv2+
# how to get the tarball
@@ -13,8 +14,10 @@ License: GPLv2+
URL: http://projects.vdr-developer.org/projects/plg-markad
Source0: http://projects.vdr-developer.org/git/vdr-plugin-markad.git/snapshot/vdr-...
Source1: %{name}.conf
-Patch0: %{name}-ffmpeg4-fix.patch
-
+Patch0: 00-markad-libavcodec58-V0-01.diff
+Patch1: 01-markad-Makefile-V0-06.diff
+Patch2: 02-deprecated-V0-04.diff
+Patch3: 03-markad-decoder-V0-24.diff
BuildRequires: gcc-c++
BuildRequires: vdr-devel >= 1.7.30
BuildRequires: ffmpeg-devel
@@ -26,32 +29,20 @@ VDR-Plugin: markad - %{summary}
%prep
%autosetup -p 1 -n vdr-plugin-markad-%{commit0}
+sed -i -e 's|$(DESTDIR)/var/lib/markad|$(DESTDIR)/var/lib/vdr/data/markad|' command/Makefile
+sed -i -e 's|/LC_MESSAGES/markad.mo|/LC_MESSAGES/vdr-markad.mo|' command/Makefile
+
%build
make CFLAGS="%{optflags} -fPIC" CXXFLAGS="%{optflags} -fPIC" %{?_smp_mflags} \
LIBDIR=. VDRDIR=%{_libdir}/vdr VDRINCDIR=%{_includedir} \
LOCALEDIR=./locale all
%install
-install -dm 755 $RPM_BUILD_ROOT%{vdr_plugindir}
-install -pm 755 plugin/libvdr-markad.so.%{vdr_apiversion} $RPM_BUILD_ROOT%{vdr_plugindir}
-install -Dpm 644 %{SOURCE1} \
- $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/vdr-plugins.d/markad.conf
-
-install -dm 755 $RPM_BUILD_ROOT%{_bindir}
-install -pm 755 command/markad $RPM_BUILD_ROOT%{_bindir}
+make install DESTDIR=%{buildroot}
-# locale
-install -dm 755 $RPM_BUILD_ROOT%{_datadir}/locale
-cp -pR plugin/locale/* $RPM_BUILD_ROOT%{_datadir}/locale
-
-# copy logos
-install -dm 755 $RPM_BUILD_ROOT%{vdr_vardir}/markad/logos
-cp -pR command/logos/* $RPM_BUILD_ROOT%{vdr_vardir}/markad/logos
-
-# install man
-pushd command
-make install-doc DESTDIR=$RPM_BUILD_ROOT
-popd
+install -dm 755 %{buildroot}%{vdr_plugindir}
+install -Dpm 644 %{SOURCE1} \
+ %{buildroot}%{_sysconfdir}/sysconfig/vdr-plugins.d/markad.conf
%find_lang %{name}
@@ -70,6 +61,13 @@ fi
%{vdr_vardir}/markad/
%changelog
+* Tue Dec 03 2019 Martin Gansser <martinkg(a)fedoraproject.org> - 0.1.4-26.20170313gitea2e182
+- Dropped vdr-markad-ffmpeg4-fix.patch
+- Add 00-markad-libavcodec58-V0-01.diff
+- Add 01-markad-Makefile-V0-06.diff
+- Add 02-deprecated-V0-04.diff
+- Add 04-markad-decoder-V0-24.diff
+
* Wed Aug 07 2019 Leigh Scott <leigh123linux(a)gmail.com> - 0.1.4-25.20170313gitea2e182
- Rebuild for new ffmpeg version
4 years, 11 months
[dptfxtract] New upstream release
by Benjamin Berg
Summary of changes:
17da035... New upstream release (*)
(*) This commit already existed in another branch; no separate mail sent
4 years, 11 months
[dptfxtract/f31] New upstream release
by Benjamin Berg
commit 17da035d3c52e4857d4a14851deac897a6a8d491
Author: Benjamin Berg <bberg(a)redhat.com>
Date: Tue Dec 3 14:48:02 2019 +0100
New upstream release
Permit madvise syscall (#5451)
.gitignore | 1 +
dptfxtract.service | 2 +-
dptfxtract.spec | 8 ++++++--
sources | 2 +-
4 files changed, 9 insertions(+), 4 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 5b7a07a..2a7fb2e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/v1.3.tar.gz
/v1.4.1.tar.gz
+/v1.4.2.tar.gz
diff --git a/dptfxtract.service b/dptfxtract.service
index 8e0a68f..766d554 100644
--- a/dptfxtract.service
+++ b/dptfxtract.service
@@ -35,7 +35,7 @@ LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
-SystemCallFilter=@basic-io @file-system @signal @process ioctl mprotect brk
+SystemCallFilter=@basic-io @file-system @signal @process ioctl mprotect brk madvise
SystemCallArchitectures=native
[Install]
diff --git a/dptfxtract.spec b/dptfxtract.spec
index cba5ea7..02bd4af 100644
--- a/dptfxtract.spec
+++ b/dptfxtract.spec
@@ -1,6 +1,6 @@
Name: dptfxtract
-Version: 1.4.1
-Release: 2%{?dist}
+Version: 1.4.2
+Release: 1%{?dist}
Summary: Utility to generate a thermald configuration from DPTF
License: Redistributable, no modification permitted
@@ -60,6 +60,10 @@ ln -s ../dptfxtract.service %{buildroot}%{_unitdir}/thermald.service.wants/dptfx
%changelog
+* Tue Dec 03 2019 Benjamin Berg <bberg(a)redhat.com> - 1.4.2-1
+- New upstream release
+- Permit madvise syscall (#5451)
+
* Sat Aug 10 2019 RPM Fusion Release Engineering <leigh123linux(a)gmail.com> - 1.4.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
diff --git a/sources b/sources
index 88041cb..ea681fb 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-e8c6fa0c7f3835c9a7f3ded61f9b8a57 v1.4.1.tar.gz
+SHA512 (v1.4.2.tar.gz) = 5960fcf283a58929d937697984b65adbd4732ca6d3b4aae4471acd3a9e97b56231a46afa26ffca18b14ac9c3331b45e93bc5491b2f95e2126f496b7c770c08a7
4 years, 11 months
[chromium-freeworld] Fix: Symbols still present even after adding -g0
by hellbanger
commit ecef62aa1c36d1d1b51ac20353899b4f38974460
Author: Akarshan Biswas <akarshanbiswas(a)fedoraproject.org>
Date: Tue Dec 3 12:55:21 2019 +0530
Fix: Symbols still present even after adding -g0
chromium-freeworld.spec | 17 ++---------------
1 file changed, 2 insertions(+), 15 deletions(-)
---
diff --git a/chromium-freeworld.spec b/chromium-freeworld.spec
index 6b22005..21efa85 100644
--- a/chromium-freeworld.spec
+++ b/chromium-freeworld.spec
@@ -528,21 +528,6 @@ sed -i.orig -e 's/getenv("CHROME_VERSION_EXTRA")/"%{name}"/' $FILE
export AR=ar NM=nm AS=as
export CC=gcc CXX=g++
-# Set proper cflags, cxxflags
-%if 0%{?fedora} >= 31
-export CFLAGS="$(echo '%{__global_cflags}' |sed -e 's/-fexceptions//' \
- -e 's/-Werror=format-security//' \
- -e 's/-pipe//' \
- -e 's/-g/-g1/g' \
- -e 's/-g1record-g1cc-switches//' )"
-export CXXFLAGS="$(echo '%{?__global_cxxflags}%{!?__global_cxxflags:%{__global_cflags}}' | sed -e 's/-fexceptions//' \
- -e 's/-Werror=format-security//' \
- -e 's/-pipe//' \
- -e 's/-g/-g1/g' \
- -e 's/-g1record-g1cc-switches//' )"
-
-export LDFLAGS='%{__global_ldflags}'
-%endif
# GN needs gold to bootstrap
export LDFLAGS="$LDFLAGS -fuse-ld=gold"
@@ -633,6 +618,8 @@ gn_args+=(
gn_args+=(
%if %{debug_pkg}
symbol_level=1
+%else
+ symbol_level=0
%endif
)
tools/gn/bootstrap/bootstrap.py --gn-gen-args "${gn_args[*]}"
4 years, 11 months
[unifi] Update to 5.12.0.
by Richard Shaw
commit 4154a6185f87dbf625184a35e7a48c4bdffc9528
Author: Richard Shaw <hobbes1069(a)gmail.com>
Date: Mon Dec 2 21:22:23 2019 -0600
Update to 5.12.0.
.gitignore | 1 +
sources | 2 +-
unifi.spec | 7 +++++--
3 files changed, 7 insertions(+), 3 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 3a4d7f7..0a72a2c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,4 @@
/UniFi-5.10.25.unix.zip
/UniFi-5.11.39.unix.zip
/UniFi-5.11.46.unix.zip
+/UniFi-5.12.35.unix.zip
diff --git a/sources b/sources
index fffa539..940535e 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-2500602b70ec7ce55ad964354e8b3574 UniFi-5.11.46.unix.zip
+SHA512 (UniFi-5.12.35.unix.zip) = 4e6b3726e5b6e43c1688fbdefe816eedb1cefc671bc9f861cc06f1c4f52a903670e033c2c5b2c66c5ed2c3f42e8f573e6245fe483a32a0df33283d46ccb5d96a
diff --git a/unifi.spec b/unifi.spec
index 4c7470a..9cb0022 100644
--- a/unifi.spec
+++ b/unifi.spec
@@ -4,8 +4,8 @@
%global __strip /bin/true
Name: unifi
-Version: 5.11.46
-Release: 3%{?dist}
+Version: 5.12.35
+Release: 1%{?dist}
Summary: Ubiquiti UniFi controller
License: Proprietary
@@ -283,6 +283,9 @@ fi
%changelog
+* Tue Dec 03 2019 Richard Shaw <hobbes1069(a)gmail.com> - 5.12.35-1
+- Update to 5.12.0.
+
* Thu Oct 10 2019 Richard Shaw <hobbes1069(a)gmail.com> - 5.11.46-3
- Remove mongod requires and move config info to SETUP.
- Fix Requires for java to comply with guidelines.
4 years, 11 months