[vdr-plugin-rpihddevice] 02/06: New upstream version 1.0.3+git20180115

Tobias Grimm tiber-guest at moszumanska.debian.org
Mon Jan 15 19:11:58 UTC 2018


This is an automated email from the git hooks/post-receive script.

tiber-guest pushed a commit to branch master
in repository vdr-plugin-rpihddevice.

commit c4ad17d6186b8b8b8d26fe8abec1087f6cafb844
Author: Tobias Grimm <git at e-tobi.net>
Date:   Mon Jan 15 20:08:42 2018 +0100

    New upstream version 1.0.3+git20180115
---
 .gitignore  |  11 ++++
 .project    |  79 +++++++++++++++++++++++
 HISTORY     |  12 ++++
 Makefile    |  10 ++-
 display.c   | 210 +++++++++++++++++++++++++++++++++++++++++++++++-------------
 display.h   |  20 ++++--
 omx.c       |  40 +++++++++---
 omx.h       |   4 +-
 omxdevice.c |  39 ++++++++---
 ovgosd.c    |  53 ++++++++++-----
 po/de_DE.po |  13 +++-
 po/fi_FI.po |  11 +++-
 po/fr_FR.po |  11 +++-
 po/hu_HU.po |  11 +++-
 po/it_IT.po |  11 +++-
 setup.c     |  30 +++++++--
 setup.h     |  21 ++++--
 tools.c     | 111 ++++++++++++++++++++++++++++++++
 tools.h     |  22 +++++++
 19 files changed, 617 insertions(+), 102 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..91f9a15
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+.dependencies
+*.a
+*.o
+*.so
+*~
+po/*.pot
+po/*.mo
+.settings
+.cproject
+.project
+
diff --git a/.project b/.project
new file mode 100644
index 0000000..b385bd0
--- /dev/null
+++ b/.project
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>rpihddevice</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+			<triggers>clean,full,incremental,</triggers>
+			<arguments>
+				<dictionary>
+					<key>?name?</key>
+					<value></value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.append_environment</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
+					<value>all</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildArguments</key>
+					<value></value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildCommand</key>
+					<value>make</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
+					<value>clean</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.contents</key>
+					<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
+					<value>false</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableFullBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
+					<value>all</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.stopOnError</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
+					<value>true</value>
+				</dictionary>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+			<triggers>full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.cdt.core.cnature</nature>
+		<nature>org.eclipse.cdt.core.ccnature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+	</natures>
+</projectDescription>
diff --git a/HISTORY b/HISTORY
index a9acf89..a9ccd92 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,6 +1,18 @@
 VDR Plugin 'rpihddevice' Revision History
 -----------------------------------------
 
+- new:
+  - updated Hungarian translations (thanks to Füley István)
+  - make use of advanced deinterlacer configurable
+  - add debug option to log number of executed OpenVG commands and flushes
+  - set OMX clock pre-roll to 250ms for live TV (transfer mode)
+- fixed:
+  - reset video format settings on pixel aspect ratio change 
+  - always resample audio with less than 2 and  more than 6 channels
+  - fixed compilation with GCC-6
+  - implement proper handling of display and pixel aspect ratios
+  - fixed vertical text position
+
 2016-04-23: Version 1.0.3
 -------------------------
 - new:
diff --git a/Makefile b/Makefile
index a0605b8..5c27c65 100644
--- a/Makefile
+++ b/Makefile
@@ -50,6 +50,7 @@ SOFILE = libvdr-$(PLUGIN).so
 DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
 DEFINES += -DHAVE_LIBOPENMAX=2 -DOMX -DOMX_SKIP64BIT -DUSE_EXTERNAL_OMX -DHAVE_LIBBCM_HOST -DUSE_EXTERNAL_LIBBCM_HOST -DUSE_VCHIQ_ARM
 DEFINES += -Wno-psabi -Wno-write-strings -fpermissive
+DEFINES += -D__STL_CONFIG_H
 
 CXXFLAGS += -D__STDC_CONSTANT_MACROS
 
@@ -59,7 +60,7 @@ VCLIBDIR =$(SDKSTAGE)/opt/vc/lib
 
 INCLUDES += -I$(ILCDIR) -I$(VCINCDIR) -I$(VCINCDIR)/interface/vcos/pthreads 
 INCLUDES += -I$(VCINCDIR)/interface/vmcs_host/linux
- 
+
 LDLIBS  += -lbcm_host -lvcos -lvchiq_arm -lopenmaxil -lGLESv2 -lEGL -lpthread -lrt
 LDLIBS  += -Wl,--whole-archive $(ILCDIR)/libilclient.a -Wl,--no-whole-archive
 LDFLAGS += -L$(VCLIBDIR)
@@ -79,6 +80,11 @@ ifeq ($(DEBUG_BUFFERS), 1)
     DEFINES += -DDEBUG_BUFFERS
 endif
 
+DEBUG_OVGSTAT ?= 0
+ifeq ($(DEBUG_OVGSTAT), 1)
+    DEFINES += -DDEBUG_OVGSTAT
+endif
+
 ENABLE_AAC_LATM ?= 0
 ifeq ($(ENABLE_AAC_LATM), 1)
     DEFINES += -DENABLE_AAC_LATM
@@ -112,7 +118,7 @@ INCLUDES += $(shell pkg-config --cflags freetype2)
 ### The object files (add further files here):
 
 ILCLIENT = $(ILCDIR)/libilclient.a
-OBJS = $(PLUGIN).o setup.o omx.o audio.o omxdevice.o ovgosd.o display.o
+OBJS = $(PLUGIN).o tools.o setup.o omx.o audio.o omxdevice.o ovgosd.o display.o
 
 ### The main target:
 
diff --git a/display.c b/display.c
index f4f5273..7add79c 100644
--- a/display.c
+++ b/display.c
@@ -55,6 +55,7 @@ cRpiDisplay* cRpiDisplay::GetInstance(void)
 						tvstate.display.hdmi.width,
 						tvstate.display.hdmi.height,
 						tvstate.display.hdmi.frame_rate,
+						tvstate.display.hdmi.aspect_ratio,
 						tvstate.display.hdmi.scan_mode != 0,
 						tvstate.display.hdmi.group,
 						tvstate.display.hdmi.mode);
@@ -70,7 +71,7 @@ cRpiDisplay* cRpiDisplay::GetInstance(void)
 				DISPMANX_MODEINFO_T mode;
 				if (vc_dispmanx_display_get_info(display, &mode) >= 0)
 					s_instance = new cRpiDefaultDisplay(id,
-							mode.width, mode.height);
+							mode.width, mode.height, SDTV_ASPECT_4_3);
 
 				vc_dispmanx_display_close(display);
 			}
@@ -78,7 +79,7 @@ cRpiDisplay* cRpiDisplay::GetInstance(void)
 		if (!s_instance)
 		{
 			ELOG("failed to get display information!");
-			s_instance = new cRpiDefaultDisplay(id, 720, 576);
+			s_instance = new cRpiDefaultDisplay(id, 720, 576, SDTV_ASPECT_4_3);
 		}
 	}
 
@@ -93,11 +94,12 @@ void cRpiDisplay::DropInstance(void)
 }
 
 cRpiDisplay::cRpiDisplay(int id, int width, int height, int frameRate,
-		bool interlaced, bool fixedMode) :
+		int aspectRatio, bool interlaced, bool fixedMode) :
 	m_id(id),
 	m_width(width),
 	m_height(height),
 	m_frameRate(frameRate),
+	m_aspectRatio(aspectRatio),
 	m_interlaced(interlaced),
 	m_fixedMode(fixedMode)
 {
@@ -126,7 +128,19 @@ int cRpiDisplay::GetSize(int &width, int &height, double &aspect)
 	{
 		width = instance->m_width;
 		height = instance->m_height;
-		aspect = (double)width / height;
+		switch (instance->m_aspectRatio)
+		{
+		case HDMI_ASPECT_4_3:
+			aspect = 4.0 / 3.0;
+			break;
+		case HDMI_ASPECT_16_9:
+			aspect = 16.0 / 9.0;
+			break;
+		default:
+			aspect = (double)width / height;
+			break;
+		}
+		aspect /= (double)width / height;
 		return 0;
 	}
 	return -1;
@@ -205,6 +219,62 @@ int cRpiDisplay::Snapshot(unsigned char* frame, int width, int height)
 	return -1;
 }
 
+void cRpiDisplay::GetModeFormat(const cVideoFrameFormat *format,
+		int &modeX, int &modeY, int &aspectRatio)
+{
+	/*                |  Format   |  PAR  |   Mode    |  DAR |
+	 * -------------------------------------------------------
+	 * NTSC SD MPEG-2 |  720x480  |  8:9  |  720x480  |  4:3 |
+	 * NTSC SD MPEG-4 |  720x480  | 10:11 |  720x480  |  4:3 |
+	 * NTSC SD MPEG-2 |  720x480  | 32:27 |  720x480  | 16:9 |
+	 * NTSC SD MPEG-4 |  720x480  | 40:33 |  720x480  | 16:9 |
+	 * PAL  SD MPEG-2 |  720x576  | 16:15 |  720x576  |  4:3 |
+	 * PAL  SD MPEG-4 |  720x576  | 12:11 |  720x576  |  4:3 |
+	 * PAL  SD MPEG-2 |  720x576  | 64:45 |  720x576  | 16:9 |
+	 * PAL  SD MPEG-4 |  720x576  | 16:11 |  720x576  | 16:9 |
+	 *      HD        | 1280x720  |  1:1  | 1280x720  | 16:9 |
+	 *      HD        | 1280x1080 |  3:2  | 1920x1080 | 16:9 |
+	 *      HD        | 1920x1080 |  1:1  | 1920x1080 | 16:9 |
+	 */
+
+	aspectRatio = HDMI_ASPECT_UNKNOWN;
+	modeY = format->height;
+
+	switch (modeY)
+	{
+	case 480:
+		if ((format->pixelWidth == 8 && format->pixelHeight == 9) ||
+				(format->pixelWidth == 10 && format->pixelHeight == 11))
+			aspectRatio = HDMI_ASPECT_4_3;
+		else if ((format->pixelWidth == 32 && format->pixelHeight == 27) ||
+				(format->pixelWidth == 40 && format->pixelHeight == 33))
+			aspectRatio = HDMI_ASPECT_16_9;
+		modeX = format->width;
+		break;
+
+	case 576:
+		if ((format->pixelWidth == 16 && format->pixelHeight == 15) ||
+				(format->pixelWidth == 12 && format->pixelHeight == 11))
+			aspectRatio = HDMI_ASPECT_4_3;
+		else if ((format->pixelWidth == 64 && format->pixelHeight == 45) ||
+				(format->pixelWidth == 16 && format->pixelHeight == 11))
+			aspectRatio = HDMI_ASPECT_16_9;
+		modeX = format->width;
+		break;
+
+	default:
+		ILOG("unknown video frame format: %dx%d@%d%s PAR(%d:%d)",
+				format->width, format->height, format->frameRate,
+				format->Interlaced() ? "i" : "p",
+				format->pixelWidth, format->pixelHeight);
+	case 720:
+	case 1080:
+		aspectRatio = HDMI_ASPECT_16_9;
+		modeX = format->width *	format->pixelWidth / format->pixelHeight;
+		break;
+	}
+}
+
 int cRpiDisplay::Update(const cVideoFrameFormat *frameFormat)
 {
 	if (m_fixedMode || (
@@ -215,21 +285,49 @@ int cRpiDisplay::Update(const cVideoFrameFormat *frameFormat)
 	int newWidth = m_width;
 	int newHeight = m_height;
 	int newFrameRate = m_frameRate;
+	int newAspectRatio = m_aspectRatio;
 	bool newInterlaced = m_interlaced;
 
 	switch (cRpiSetup::GetVideoResolution())
 	{
-	case cVideoResolution::e480:  newWidth = 720;  newHeight = 480;  break;
-	case cVideoResolution::e576:  newWidth = 720;  newHeight = 576;  break;
-	case cVideoResolution::e720:  newWidth = 1280; newHeight = 720;  break;
-	case cVideoResolution::e1080: newWidth = 1920; newHeight = 1080; break;
+	case cVideoResolution::e480:
+		newWidth = 720;
+		newHeight = 480;
+		newAspectRatio = HDMI_ASPECT_4_3;
+		break;
+
+	case cVideoResolution::e480w:
+		newWidth = 720;
+		newHeight = 480;
+		newAspectRatio = HDMI_ASPECT_16_9;
+		break;
+
+	case cVideoResolution::e576:
+		newWidth = 720;
+		newHeight = 576;
+		newAspectRatio = HDMI_ASPECT_4_3;
+		break;
+
+	case cVideoResolution::e576w:
+		newWidth = 720;
+		newHeight = 576;
+		newAspectRatio = HDMI_ASPECT_16_9;
+		break;
+
+	case cVideoResolution::e720:
+		newWidth = 1280;
+		newHeight = 720;
+		newAspectRatio = HDMI_ASPECT_16_9;
+		break;
+
+	case cVideoResolution::e1080:
+		newWidth = 1920;
+		newHeight = 1080;
+		newAspectRatio = HDMI_ASPECT_16_9;
+		break;
 
 	case cVideoResolution::eFollowVideo:
-		if (frameFormat->width && frameFormat->height)
-		{
-			newWidth = frameFormat->width;
-			newHeight = frameFormat->height;
-		}
+		GetModeFormat(frameFormat, newWidth, newHeight, newAspectRatio);
 		break;
 
 	default:
@@ -262,13 +360,26 @@ int cRpiDisplay::Update(const cVideoFrameFormat *frameFormat)
 
 	// set new mode only if necessary
 	if (newWidth != m_width || newHeight != m_height ||
-			newFrameRate != m_frameRate || newInterlaced != m_interlaced)
-		return SetMode(newWidth, newHeight, newFrameRate,
+			newFrameRate != m_frameRate || newInterlaced != m_interlaced ||
+			newAspectRatio != m_aspectRatio)
+		return SetMode(newWidth, newHeight, newFrameRate, newAspectRatio,
 				newInterlaced ? frameFormat->scanMode : cScanMode::eProgressive);
 
 	return 0;
 }
 
+const char* cRpiDisplay::AspectRatioStr(int aspectRatio)
+{
+	return	aspectRatio == HDMI_ASPECT_4_3   ? "4:3"   :
+			aspectRatio == HDMI_ASPECT_14_9  ? "14:9"  :
+			aspectRatio == HDMI_ASPECT_16_9  ? "16:9"  :
+			aspectRatio == HDMI_ASPECT_5_4   ? "5:4"   :
+			aspectRatio == HDMI_ASPECT_16_10 ? "16:10" :
+			aspectRatio == HDMI_ASPECT_15_9  ? "15:9"  :
+			aspectRatio == HDMI_ASPECT_64_27 ? "64:27" :
+			aspectRatio == HDMI_ASPECT_21_9  ? "21:9"  : "unknown";
+}
+
 /* ------------------------------------------------------------------------- */
 
 #define HDMI_MAX_MODES 64
@@ -281,8 +392,8 @@ public:
 };
 
 cRpiHDMIDisplay::cRpiHDMIDisplay(int id, int width, int height, int frameRate,
-		bool interlaced, int group, int mode) :
-	cRpiDisplay(id, width, height, frameRate, interlaced, false),
+		int aspectRatio, bool interlaced, int group, int mode) :
+	cRpiDisplay(id, width, height, frameRate, aspectRatio, interlaced, false),
 	m_modes(new cRpiHDMIDisplay::ModeList()),
 	m_group(group),
 	m_mode(mode),
@@ -304,7 +415,7 @@ cRpiHDMIDisplay::cRpiHDMIDisplay(int id, int width, int height, int frameRate,
 		DLOG("supported HDMI modes:");
 		for (int i = 0; i < m_modes->nModes; i++)
 		{
-			DLOG("%s[%02d]: %4dx%4d@%2d%s | %s | %3d.%03dMHz%s%s",
+			DLOG("%s[%02d]: %4dx%4d@%2d%s | %*s | %3d.%03dMHz%s%s",
 				m_modes->modes[i].group == HDMI_RES_GROUP_CEA ? "CEA" :
 				m_modes->modes[i].group == HDMI_RES_GROUP_DMT ? "DMT" : "---",
 				m_modes->modes[i].code,
@@ -312,14 +423,7 @@ cRpiHDMIDisplay::cRpiHDMIDisplay(int id, int width, int height, int frameRate,
 				m_modes->modes[i].height,
 				m_modes->modes[i].frame_rate,
 				m_modes->modes[i].scan_mode ? "i" : "p",
-				m_modes->modes[i].aspect_ratio == HDMI_ASPECT_4_3   ? " 4:3 " :
-				m_modes->modes[i].aspect_ratio == HDMI_ASPECT_14_9  ? "14:9 " :
-				m_modes->modes[i].aspect_ratio == HDMI_ASPECT_16_9  ? "16:9 " :
-				m_modes->modes[i].aspect_ratio == HDMI_ASPECT_5_4   ? " 5:4 " :
-				m_modes->modes[i].aspect_ratio == HDMI_ASPECT_16_10 ? "16:10" :
-				m_modes->modes[i].aspect_ratio == HDMI_ASPECT_15_9  ? "15:9 " :
-				m_modes->modes[i].aspect_ratio == HDMI_ASPECT_21_9  ? "21:9 " :
-					"unknown aspect ratio",
+				5, AspectRatioStr(m_modes->modes[i].aspect_ratio),
 				m_modes->modes[i].pixel_freq / 1000000,
 				m_modes->modes[i].pixel_freq % 1000000 / 1000,
 				m_modes->modes[i].native ? " (native)" : "",
@@ -354,31 +458,50 @@ cRpiHDMIDisplay::~cRpiHDMIDisplay()
 }
 
 int cRpiHDMIDisplay::SetMode(int width, int height, int frameRate,
-		cScanMode::eMode scanMode)
+		int aspectRatio, cScanMode::eMode scanMode)
 {
 	SetHvsSyncUpdate(scanMode);
-	bool interlaced = cScanMode::Interlaced(scanMode);
+	int interlaced = cScanMode::Interlaced(scanMode) ? 1 : 0;
+	int mode = -1, altMode = -1;
 
-	for (int i = 0; i < m_modes->nModes; i++)
+	for (int i = 0; i < m_modes->nModes && mode == -1; i++)
 	{
 		if (m_modes->modes[i].width == width &&
 				m_modes->modes[i].height == height &&
 				m_modes->modes[i].frame_rate == frameRate &&
+				m_modes->modes[i].aspect_ratio == aspectRatio &&
 				m_modes->modes[i].scan_mode == interlaced)
-		{
-			DLOG("setting HDMI mode to %dx%d@%2d%s", width, height,
-					frameRate, interlaced ? "i" : "p");
-
-			m_width = width;
-			m_height = height;
-			m_frameRate = frameRate;
-			m_interlaced = interlaced;
-			return SetMode(m_modes->modes[i].group, m_modes->modes[i].code);
-		}
+			mode = i;
+
+		else if (m_modes->modes[i].height == height &&
+				m_modes->modes[i].frame_rate == frameRate &&
+				m_modes->modes[i].aspect_ratio == aspectRatio &&
+				m_modes->modes[i].scan_mode == interlaced)
+			altMode = i;
+	}
+
+	if (mode == -1 && altMode != -1)
+		mode = altMode;
+
+	if (mode != -1)
+	{
+		m_width = m_modes->modes[mode].width;
+		m_height = m_modes->modes[mode].height;
+		m_frameRate = m_modes->modes[mode].frame_rate;
+		m_aspectRatio = m_modes->modes[mode].aspect_ratio;
+		m_interlaced = m_modes->modes[mode].scan_mode;
+
+		DLOG("setting HDMI mode to %dx%d@%2d%s (%s)", m_width, m_height,
+				m_frameRate, m_interlaced ? "i" : "p",
+				AspectRatioStr(m_aspectRatio));
+
+		return SetMode(m_modes->modes[mode].group, m_modes->modes[mode].code);
 	}
 
-	DLOG("failed to set HDMI mode to %dx%d@%2d%s",
-		width, height, frameRate, interlaced ? "i" : "p");
+	DLOG("failed to set HDMI mode to %dx%d@%2d%s (%s)",
+			width, height, frameRate, interlaced ? "i" : "p",
+			AspectRatioStr(aspectRatio));
+
 	return -1;
 }
 
@@ -414,7 +537,8 @@ void cRpiHDMIDisplay::TvServiceCallback(void *data, unsigned int reason,
 
 /* ------------------------------------------------------------------------- */
 
-cRpiDefaultDisplay::cRpiDefaultDisplay(int id, int width, int height) :
-	cRpiDisplay(id, width, height, 50, false, true)
+cRpiDefaultDisplay::cRpiDefaultDisplay(int id, int width, int height,
+		int aspectRatio) :
+	cRpiDisplay(id, width, height, 50, aspectRatio, false, true)
 {
 }
diff --git a/display.h b/display.h
index 7a203e3..b062aa7 100644
--- a/display.h
+++ b/display.h
@@ -44,23 +44,29 @@ public:
 
 protected:
 
-	cRpiDisplay(int id, int width, int height, int frameRate, bool interlaced,
-			bool fixedMode);
+	cRpiDisplay(int id, int width, int height, int frameRate, int aspectRatio,
+			bool interlaced, bool fixedMode);
 	virtual ~cRpiDisplay();
 
 	int Update(const cVideoFrameFormat *videoFormat);
 
-	virtual int SetMode(int width, int height, int frameRate,
+	virtual int SetMode(int width, int height, int frameRate, int aspectRatio,
 			cScanMode::eMode scanMode) {
 		return 0;
 	}
 
 	static int SetHvsSyncUpdate(cScanMode::eMode scanMode);
 
+	static void GetModeFormat(const cVideoFrameFormat *format,
+			int &modeX, int &modeY, int &aspectRatio);
+
+	static const char* AspectRatioStr(int aspectRatio);
+
 	int m_id;
 	int m_width;
 	int m_height;
 	int m_frameRate;
+	int m_aspectRatio;
 	bool m_interlaced;
 	bool m_fixedMode;
 
@@ -78,13 +84,13 @@ class cRpiHDMIDisplay : public cRpiDisplay
 
 public:
 
-	cRpiHDMIDisplay(int id, int width, int height, int frameRate, bool interlaced,
-			int group, int mode);
+	cRpiHDMIDisplay(int id, int width, int height, int frameRate,
+			int aspectRatio, bool interlaced, int group, int mode);
 	virtual ~cRpiHDMIDisplay();
 
 private:
 
-	virtual int SetMode(int width, int height, int frameRate,
+	virtual int SetMode(int width, int height, int frameRate, int aspectRatio,
 			cScanMode::eMode scanMode);
 	int SetMode(int group, int mode);
 
@@ -107,7 +113,7 @@ class cRpiDefaultDisplay : public cRpiDisplay
 
 public:
 
-	cRpiDefaultDisplay(int id, int width, int height);
+	cRpiDefaultDisplay(int id, int width, int height, int aspectRatio);
 
 };
 
diff --git a/omx.c b/omx.c
index 3881c14..a1361bd 100644
--- a/omx.c
+++ b/omx.c
@@ -21,6 +21,7 @@
 
 #include "omx.h"
 #include "display.h"
+#include "setup.h"
 
 #include <vdr/tools.h>
 #include <vdr/thread.h>
@@ -31,8 +32,6 @@ extern "C" {
 
 #include "bcm_host.h"
 
-#define OMX_PRE_ROLL 0
-
 // default: 20x 81920 bytes, now 128x 64k (8M)
 #define OMX_VIDEO_BUFFERS 128
 #define OMX_VIDEO_BUFFERSIZE KILOBYTE(64);
@@ -206,9 +205,19 @@ void cOmx::Action(void)
 				break;
 
 			case cOmxEvents::eConfigChanged:
-				if (event->data == OMX_IndexConfigBufferStall)
+				switch (event->data)
+				{
+				case OMX_IndexParamBrcmPixelAspectRatio:
+					if (m_handlePortEvents)
+						HandlePortSettingsChanged(131);
+					break;
+				case OMX_IndexConfigBufferStall:
 					if (IsBufferStall() && !IsClockFreezed() && m_onBufferStall)
 						m_onBufferStall(m_onBufferStallData);
+					break;
+				default:
+					break;
+				}
 				break;
 
 			case cOmxEvents::eEndOfStream:
@@ -362,8 +371,11 @@ void cOmx::HandlePortSettingsChanged(unsigned int portId)
 
 		if (cRpiDisplay::IsProgressive() && m_videoFrameFormat.Interlaced())
 		{
-			bool fastDeinterlace = portdef.format.video.nFrameWidth *
-					portdef.format.video.nFrameHeight > 576 * 720;
+			bool fastDeinterlace = !cRpiSetup::UseAdvancedDeinterlacer(
+					portdef.format.video.nFrameWidth,
+					portdef.format.video.nFrameHeight);
+
+			DBG("using %s deinterlacer", fastDeinterlace ? "fast" : "advanced");
 
 			filterparam.nNumParams = 4;
 			filterparam.nParams[0] = 3;
@@ -551,6 +563,7 @@ int cOmx::Init(int display, int layer)
 
 	SetDisplay(display, layer);
 	SetClockLatencyTarget();
+	SetPARChangeCallback(true);
 	SetBufferStallThreshold(20000);
 	SetClockReference(cOmx::eClockRefVideo);
 
@@ -662,7 +675,7 @@ bool cOmx::IsClockRunning(void)
 		return false;
 }
 
-void cOmx::StartClock(bool waitForVideo, bool waitForAudio)
+void cOmx::StartClock(bool waitForVideo, bool waitForAudio, int preRollMs)
 {
 	DBG("StartClock(%svideo, %saudio)",
 			waitForVideo ? "" : "no ",
@@ -672,7 +685,7 @@ void cOmx::StartClock(bool waitForVideo, bool waitForAudio)
 	OMX_INIT_STRUCT(cstate);
 
 	cstate.eState = OMX_TIME_ClockStateRunning;
-	cstate.nOffset = ToOmxTicks(-1000LL * OMX_PRE_ROLL);
+	cstate.nOffset = ToOmxTicks(-1000LL * preRollMs);
 
 	if (waitForVideo)
 	{
@@ -698,7 +711,6 @@ void cOmx::StopClock(void)
 	OMX_INIT_STRUCT(cstate);
 
 	cstate.eState = OMX_TIME_ClockStateStopped;
-	cstate.nOffset = ToOmxTicks(-1000LL * OMX_PRE_ROLL);
 
 	if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eClock]),
 			OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone)
@@ -821,6 +833,18 @@ void cOmx::SetClockLatencyTarget(void)
 		ELOG("failed set video render latency target!");
 }
 
+void cOmx::SetPARChangeCallback(bool enable)
+{
+	OMX_CONFIG_REQUESTCALLBACKTYPE reqCallback;
+	OMX_INIT_STRUCT(reqCallback);
+	reqCallback.nPortIndex = 131;
+	reqCallback.bEnable = enable ? OMX_TRUE : OMX_FALSE;
+	reqCallback.nIndex = OMX_IndexParamBrcmPixelAspectRatio;
+	if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eVideoDecoder]),
+			OMX_IndexConfigRequestCallback, &reqCallback) != OMX_ErrorNone)
+		ELOG("failed to set video aspect ratio change call back!");
+}
+
 void cOmx::SetBufferStallThreshold(int delayMs)
 {
 	if (delayMs > 0)
diff --git a/omx.h b/omx.h
index c0daffa..e633746 100644
--- a/omx.h
+++ b/omx.h
@@ -62,7 +62,8 @@ public:
 		eClockStateWaitForAudioVideo
 	};
 
-	void StartClock(bool waitForVideo = false, bool waitForAudio = false);
+	void StartClock(bool waitForVideo = false, bool waitForAudio = false,
+			int preRollMs = 0);
 	void StopClock(void);
 	void ResetClock(void);
 
@@ -178,6 +179,7 @@ private:
 
 	void HandlePortBufferEmptied(eOmxComponent component);
 	void HandlePortSettingsChanged(unsigned int portId);
+	void SetPARChangeCallback(bool enable);
 	void SetBufferStallThreshold(int delayMs);
 	bool IsBufferStall(void);
 
diff --git a/omxdevice.c b/omxdevice.c
index 684f68d..c646f90 100644
--- a/omxdevice.c
+++ b/omxdevice.c
@@ -22,6 +22,7 @@
 #include "audio.h"
 #include "display.h"
 #include "setup.h"
+#include "tools.h"
 
 #include <vdr/thread.h>
 #include <vdr/remux.h>
@@ -33,6 +34,9 @@
 #define S(x) ((int)(floor(x * pow(2, 16))))
 #define PTS_START_OFFSET (32 * (MAX33BIT + 1))
 
+#define PRE_ROLL_LIVE 250
+#define PRE_ROLL_PLAYBACK 0
+
 // trick speeds as defined in vdr/dvbplayer.c
 const int cOmxDevice::s_playbackSpeeds[eNumDirections][eNumPlaybackSpeeds] = {
 	{ S(0.0f), S( 0.125f), S( 0.25f), S( 0.5f), S( 1.0f), S( 2.0f), S( 4.0f), S( 12.0f) },
@@ -289,7 +293,8 @@ int cOmxDevice::PlayAudio(const uchar *Data, int Length, uchar Id)
 				DBG("audio first");
 				m_omx->SetClockScale(
 						s_playbackSpeeds[m_direction][m_playbackSpeed]);
-				m_omx->StartClock(m_hasVideo, m_hasAudio);
+				m_omx->StartClock(m_hasVideo, m_hasAudio,
+						Transferring() ? PRE_ROLL_LIVE : PRE_ROLL_PLAYBACK);
 				m_audioPts = PTS_START_OFFSET + pts;
 				m_playMode = pmAudioOnly;
 			}
@@ -382,7 +387,8 @@ int cOmxDevice::PlayVideo(const uchar *Data, int Length, bool EndOfFrame)
 			DBG("video first");
 			m_omx->SetClockReference(cOmx::eClockRefVideo);
 			m_omx->SetClockScale(s_playbackSpeeds[m_direction][m_playbackSpeed]);
-			m_omx->StartClock(m_hasVideo, m_hasAudio);
+			m_omx->StartClock(m_hasVideo, m_hasAudio,
+					Transferring() ? PRE_ROLL_LIVE : PRE_ROLL_PLAYBACK);
 			m_videoPts = PTS_START_OFFSET + pts;
 			m_playMode = pmVideoOnly;
 		}
@@ -686,7 +692,8 @@ void cOmxDevice::HandleEndOfStream()
 	// flush pipes and restart clock after still image
 	FlushStreams();
 	m_omx->SetClockScale(s_playbackSpeeds[m_direction][m_playbackSpeed]);
-	m_omx->StartClock(m_hasVideo, m_hasAudio);
+	m_omx->StartClock(m_hasVideo, m_hasAudio,
+			Transferring() ? PRE_ROLL_LIVE : PRE_ROLL_PLAYBACK);
 
 	m_mutex->Unlock();
 }
@@ -696,18 +703,17 @@ void cOmxDevice::HandleStreamStart()
 	DBG("HandleStreamStart()");
 
 	const cVideoFrameFormat *format = m_omx->GetVideoFrameFormat();
-	DLOG("video stream started %dx%d@%d%s PAR(%d:%d)",
+	DLOG("video stream started %dx%d@%d%s, PAR=%d/%d",
 			format->width, format->height, format->frameRate,
 			format->Interlaced() ? "i" : "p",
 			format->pixelWidth, format->pixelHeight);
 
-	cRpiDisplay::SetVideoFormat(format);
+	HandleVideoSetupChanged();
 }
 
 void cOmxDevice::HandleVideoSetupChanged()
 {
-	DBG("HandleVideoSetupChanged()");
-
+	// apply framing parameters
 	switch (cRpiSetup::GetVideoFraming())
 	{
 	default:
@@ -724,7 +730,24 @@ void cOmxDevice::HandleVideoSetupChanged()
 		break;
 	}
 
-	cRpiDisplay::SetVideoFormat(m_omx->GetVideoFrameFormat());
+	const cVideoFrameFormat *format = m_omx->GetVideoFrameFormat();
+	double videoPAR = format->pixelHeight ?
+			(double)format->pixelWidth / format->pixelHeight : 1.0f;
+
+	// update display format according current video stream
+	cRpiDisplay::SetVideoFormat(format);
+
+	// get updated display format ...
+	int width, height;
+	double displayPAR;
+	cRpiDisplay::GetSize(width, height, displayPAR);
+
+	// ... and set video render format accordingly
+	cRational renderPAR = cRational(videoPAR / displayPAR);
+	renderPAR.Reduce(100);
+	m_omx->SetPixelAspectRatio(renderPAR.num, renderPAR.den);
+	DLOG("display PAR=%0.3f, setting video render PAR=%d/%d",
+			displayPAR, renderPAR.num, renderPAR.den);
 }
 
 void cOmxDevice::FlushStreams(bool flushVideoRender)
diff --git a/ovgosd.c b/ovgosd.c
index 685dadb..4c2652c 100644
--- a/ovgosd.c
+++ b/ovgosd.c
@@ -757,6 +757,7 @@ public:
 
 	virtual bool Execute(cEgl *egl) = 0;
 	virtual const char* Description(void) = 0;
+	virtual bool IsFlush(void) { return false; };
 
 protected:
 
@@ -776,6 +777,7 @@ public:
 		cOvgCmd(target) { }
 
 	virtual const char* Description(void) { return "Flush"; }
+	virtual bool IsFlush(void) { return true; };
 
 	virtual bool Execute(cEgl *egl)
 	{
@@ -1207,14 +1209,14 @@ public:
 			if (m_alignment & taLeft)
 			{
 				if (m_alignment & taBorder)
-					offsetX += max(height / TEXT_ALIGN_BORDER, 1.0f);
+					offsetX += std::max(height / TEXT_ALIGN_BORDER, 1.0f);
 			}
 			else if (m_alignment & taRight)
 			{
 				if (width < m_w)
 					offsetX += m_w - width;
 				if (m_alignment & taBorder)
-					offsetX -= max(height / TEXT_ALIGN_BORDER, 1.0f);
+					offsetX -= std::max(height / TEXT_ALIGN_BORDER, 1.0f);
 			}
 			else
 			{
@@ -1240,12 +1242,9 @@ public:
 		vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
 		vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);
 
-		// some magic offset to conform with VDR's text rendering
-		offsetY -= 0.06f * m_fontSize;
-
 		vgLoadIdentity();
 		vgTranslate(m_x + offsetX,
-				m_target->height - m_y - m_fontSize - offsetY + 1);
+				m_target->height - m_y - height + descender - offsetY + 1);
 		vgScale(m_fontSize, m_fontSize);
 
 		VGfloat origin[2] = { 0.0f, 0.0f };
@@ -1253,10 +1252,11 @@ public:
 
 		cOvgPaintBox::SetScissoring(
 				m_w ? m_x : m_x + floor(offsetX),
-				m_h ? m_target->height - m_y - m_h : m_target->height - m_y -
-						m_fontSize - floor(descender) + 1,
-				m_w ? m_w : floor(width) + 1,
-				m_h ? m_h : m_fontSize + floor(descender) - 1);
+				m_h ? m_target->height - m_y - m_h :
+						m_target->height - m_y - floor(height),
+				m_w ? m_w : floor(width),
+				m_h ? m_h : floor(height));
+
 
 		if (m_colorBg != clrTransparent)
 		{
@@ -1592,8 +1592,8 @@ public:
 
 	virtual bool Execute(cEgl *egl)
 	{
-		int w = min(m_w, vgGeti(VG_MAX_IMAGE_WIDTH));
-		int h = min(m_h, vgGeti(VG_MAX_IMAGE_HEIGHT));
+		int w = std::min(m_w, vgGeti(VG_MAX_IMAGE_WIDTH));
+		int h = std::min(m_h, vgGeti(VG_MAX_IMAGE_HEIGHT));
 
 		if (w <= 0 || h <= 0)
 			return true;
@@ -1866,6 +1866,11 @@ protected:
 			vgSetfv(VG_CLEAR_COLOR, 4, color);
 			vgClear(0, 0, egl.window.width, egl.window.height);
 
+#ifdef DEBUG_OVGSTAT
+			cTimeMs timer;
+			int commands = 0, flushes = 0;
+#endif
+
 			bool reset = false;
 			while (!reset)
 			{
@@ -1878,6 +1883,22 @@ protected:
 					m_commands.pop();
 					Unlock();
 
+#ifdef DEBUG_OVGSTAT
+					if (timer.TimedOut())
+					{
+						if (commands || flushes)
+						{
+							DLOG("[OpenVG] commands executed: %d, flushes: %d",
+									commands, flushes);
+							commands = 0;
+							flushes = 0;
+						}
+						timer.Set(1000);
+					}
+					commands++;
+					if (cmd->IsFlush())
+						flushes++;
+#endif
 					reset = cmd ? !cmd->Execute(&egl) : true;
 
 					VGErrorCode err = vgGetError();
@@ -2354,11 +2375,11 @@ public:
 		{
 			ELOG("[OpenVG] cannot allocate pixmap of %dpx x %dpx, "
 					"clipped to %dpx x %dpx!", width, height,
-					min(width, m_ovg->MaxImageSize().Width()),
-					min(height, m_ovg->MaxImageSize().Height()));
+					std::min(width, m_ovg->MaxImageSize().Width()),
+					std::min(height, m_ovg->MaxImageSize().Height()));
 
-			width = min(width, m_ovg->MaxImageSize().Width());
-			height = min(height, m_ovg->MaxImageSize().Height());
+			width = std::min(width, m_ovg->MaxImageSize().Width());
+			height = std::min(height, m_ovg->MaxImageSize().Height());
 		}
 #endif
 		// create pixel buffer and wait until command has been completed
diff --git a/po/de_DE.po b/po/de_DE.po
index 3c37270..a221585 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: vdr-rpihddevice 1.0.0\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2015-03-14 19:22+0100\n"
-"PO-Revision-Date: 2015-10-12 09:33+0100\n"
+"POT-Creation-Date: 2016-04-27 15:09+0200\n"
+"PO-Revision-Date: 2016-04-27 15:11+0100\n"
 "Last-Translator: Thomas Reufer <thomas at reufer.ch>\n"
 "Language-Team: German\n"
 "Language: de\n"
@@ -54,12 +54,21 @@ msgstr "Voreinstellung"
 msgid "follow video"
 msgstr "wie Video"
 
+msgid "for SD video only"
+msgstr "nur für SD-Video"
+
+msgid "always"
+msgstr "immer"
+
 msgid "Resolution"
 msgstr "Auflösung"
 
 msgid "Frame Rate"
 msgstr "Bildwiederholrate"
 
+msgid "Use Advanced Deinterlacer"
+msgstr "Benutze erweiterten Deinterlacer"
+
 msgid "Video Framing"
 msgstr "Seitenverhältnis-Anpassung"
 
diff --git a/po/fi_FI.po b/po/fi_FI.po
index 2b2258f..2dcff96 100644
--- a/po/fi_FI.po
+++ b/po/fi_FI.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: vdr-rpihddevice 0.0.8\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2015-03-14 19:22+0100\n"
+"POT-Creation-Date: 2016-04-27 15:09+0200\n"
 "PO-Revision-Date: 2014-03-22 03:22+0200\n"
 "Last-Translator: Rolf Ahrenberg\n"
 "Language-Team: Finnish <vdr at linuxtv.org>\n"
@@ -52,12 +52,21 @@ msgstr "oletus"
 msgid "follow video"
 msgstr "lähetteen mukaan"
 
+msgid "for SD video only"
+msgstr ""
+
+msgid "always"
+msgstr ""
+
 msgid "Resolution"
 msgstr "Resoluutio"
 
 msgid "Frame Rate"
 msgstr "Ruudunpäivitys"
 
+msgid "Use Advanced Deinterlacer"
+msgstr ""
+
 msgid "Video Framing"
 msgstr "Kuvan rajaustapa"
 
diff --git a/po/fr_FR.po b/po/fr_FR.po
index dfb92b9..a0dd2cd 100644
--- a/po/fr_FR.po
+++ b/po/fr_FR.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: vdr-rpihddevice 1.0.0\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2015-10-14 17:58+0200\n"
+"POT-Creation-Date: 2016-04-27 15:09+0200\n"
 "PO-Revision-Date: 2015-10-15 06:56+0100\n"
 "Last-Translator: Cyril Jaquier <cyril.jaquier at jaqpot.net>\n"
 "Language-Team: French\n"
@@ -53,12 +53,21 @@ msgstr "par défaut"
 msgid "follow video"
 msgstr "comme l'original"
 
+msgid "for SD video only"
+msgstr ""
+
+msgid "always"
+msgstr ""
+
 msgid "Resolution"
 msgstr "Résolution"
 
 msgid "Frame Rate"
 msgstr "Cadence d'images"
 
+msgid "Use Advanced Deinterlacer"
+msgstr ""
+
 msgid "Video Framing"
 msgstr "Aspect de l'image"
 
diff --git a/po/hu_HU.po b/po/hu_HU.po
index 7206b02..fa8130e 100644
--- a/po/hu_HU.po
+++ b/po/hu_HU.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: vdr-rpihddevice 1.0.0\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2015-03-14 19:22+0100\n"
+"POT-Creation-Date: 2016-04-27 15:09+0200\n"
 "PO-Revision-Date: 2015-10-16 13:49+0200\n"
 "Last-Translator: Füley István <ifuley at tigercomp dot ro>\n"
 "Language-Team: Hungarian\n"
@@ -54,12 +54,21 @@ msgstr "alapértelmezett"
 msgid "follow video"
 msgstr "video szerinti"
 
+msgid "for SD video only"
+msgstr "csak SD videónál"
+
+msgid "always"
+msgstr "mindig"
+
 msgid "Resolution"
 msgstr "Felbontás"
 
 msgid "Frame Rate"
 msgstr "Képfrissítés"
 
+msgid "Use Advanced Deinterlacer"
+msgstr "Fejlett deinterlacer használata"
+
 msgid "Video Framing"
 msgstr "Video képarány"
 
diff --git a/po/it_IT.po b/po/it_IT.po
index c21fd2e..3b35087 100644
--- a/po/it_IT.po
+++ b/po/it_IT.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: vdr-rpihddevice 1.0.0\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2015-10-14 17:58+0200\n"
+"POT-Creation-Date: 2016-04-27 15:09+0200\n"
 "PO-Revision-Date: 2015-10-15 07:01+0100\n"
 "Last-Translator: Gerlando Falauto <gerlando.falauto at gmail.com>\n"
 "Language-Team: Italian\n"
@@ -53,12 +53,21 @@ msgstr "default"
 msgid "follow video"
 msgstr "come nel video"
 
+msgid "for SD video only"
+msgstr ""
+
+msgid "always"
+msgstr ""
+
 msgid "Resolution"
 msgstr "Risoluzione"
 
 msgid "Frame Rate"
 msgstr "Frequenza fotogrammi"
 
+msgid "Use Advanced Deinterlacer"
+msgstr ""
+
 msgid "Video Framing"
 msgstr "Rapporto d'aspetto"
 
diff --git a/setup.c b/setup.c
index 99b90d6..1ad488b 100644
--- a/setup.c
+++ b/setup.c
@@ -59,10 +59,12 @@ public:
 
 		m_videoResolution[0] = tr("default");
 		m_videoResolution[1] = tr("follow video");
-		m_videoResolution[2] = "720x480";
-		m_videoResolution[3] = "720x576";
-		m_videoResolution[4] = "1280x720";
-		m_videoResolution[5] = "1920x1080";
+		m_videoResolution[2] = "720x480 (4:3)";
+		m_videoResolution[3] = "720x480 (16:9)";
+		m_videoResolution[4] = "720x576 (4:3)";
+		m_videoResolution[5] = "720x576 (16:9)";
+		m_videoResolution[6] = "1280x720";
+		m_videoResolution[7] = "1920x1080";
 
 		m_videoFrameRate[0] = tr("default");
 		m_videoFrameRate[1] = tr("follow video");
@@ -74,6 +76,10 @@ public:
 		m_videoFrameRate[7] = "60i";
 		m_videoFrameRate[8] = "60p";
 
+		m_useAdvancedDeinterlacer[0] = trVDR("no");
+		m_useAdvancedDeinterlacer[1] = tr("for SD video only");
+		m_useAdvancedDeinterlacer[2] = tr("always");
+
 		Setup();
 	}
 
@@ -101,6 +107,7 @@ protected:
 		SetupStore("VideoFraming", m_video.framing);
 		SetupStore("Resolution", m_video.resolution);
 		SetupStore("FrameRate", m_video.frameRate);
+		SetupStore("AdvancedDeinterlacer", m_video.advancedDeinterlacer);
 
 		SetupStore("AcceleratedOsd", m_osd.accelerated);
 
@@ -117,11 +124,16 @@ private:
 		if (!cRpiDisplay::IsFixedMode())
 		{
 			Add(new cMenuEditStraItem(
-				tr("Resolution"), &m_video.resolution, 6, m_videoResolution));
+				tr("Resolution"), &m_video.resolution, 8, m_videoResolution));
 
 			Add(new cMenuEditStraItem(
 				tr("Frame Rate"), &m_video.frameRate, 9, m_videoFrameRate));
 		}
+		if (cRpiDisplay::IsProgressive())
+			Add(new cMenuEditStraItem(
+					tr("Use Advanced Deinterlacer"),
+					&m_video.advancedDeinterlacer, 3,
+					m_useAdvancedDeinterlacer));
 
 		Add(new cMenuEditStraItem(
 				tr("Video Framing"), &m_video.framing, 3, m_videoFraming));
@@ -149,8 +161,9 @@ private:
 	const char *m_audioPort[2];
 	const char *m_audioFormat[3];
 	const char *m_videoFraming[3];
-	const char *m_videoResolution[6];
+	const char *m_videoResolution[8];
 	const char *m_videoFrameRate[9];
+	const char *m_useAdvancedDeinterlacer[3];
 };
 
 /* ------------------------------------------------------------------------- */
@@ -222,6 +235,9 @@ bool cRpiSetup::IsAudioFormatSupported(cAudioCodec::eCodec codec,
 	if (codec == cAudioCodec::eMPG || codec == cAudioCodec::eAAC)
 		return false;
 
+	if (channels < 2 || channels > 6)
+		return false;
+
 	switch (GetAudioFormat())
 	{
 	case cAudioFormat::ePassThrough:
@@ -310,6 +326,8 @@ bool cRpiSetup::Parse(const char *name, const char *value)
 		m_video.resolution = atoi(value);
 	else if (!strcasecmp(name, "FrameRate"))
 		m_video.frameRate = atoi(value);
+	else if (!strcasecmp(name, "AdvancedDeinterlacer"))
+		m_video.advancedDeinterlacer = atoi(value);
 	else if (!strcasecmp(name, "AcceleratedOsd"))
 		m_osd.accelerated = atoi(value);
 	else return false;
diff --git a/setup.h b/setup.h
index a91b8e1..f33d5ea 100644
--- a/setup.h
+++ b/setup.h
@@ -52,15 +52,18 @@ public:
 		VideoParameters() :
 			framing(0),
 			resolution(0),
-			frameRate(0) { }
+			frameRate(0),
+			advancedDeinterlacer(1){ }
 
 		int framing;
 		int resolution;
 		int frameRate;
+		int advancedDeinterlacer;
 
 		bool operator!=(const VideoParameters& a) {
 			return (a.framing != framing) || (a.resolution != resolution) ||
-					(a.frameRate != frameRate);
+					(a.frameRate != frameRate) ||
+					(a.advancedDeinterlacer != advancedDeinterlacer);
 		}
 	};
 
@@ -108,9 +111,11 @@ public:
 	static cVideoResolution::eResolution GetVideoResolution(void) {
 		return	GetInstance()->m_video.resolution == 1 ? cVideoResolution::eFollowVideo :
 				GetInstance()->m_video.resolution == 2 ? cVideoResolution::e480 :
-				GetInstance()->m_video.resolution == 3 ? cVideoResolution::e576 :
-				GetInstance()->m_video.resolution == 4 ? cVideoResolution::e720 :
-				GetInstance()->m_video.resolution == 5 ? cVideoResolution::e1080 :
+				GetInstance()->m_video.resolution == 3 ? cVideoResolution::e480w :
+				GetInstance()->m_video.resolution == 4 ? cVideoResolution::e576 :
+				GetInstance()->m_video.resolution == 5 ? cVideoResolution::e576w :
+				GetInstance()->m_video.resolution == 6 ? cVideoResolution::e720 :
+				GetInstance()->m_video.resolution == 7 ? cVideoResolution::e1080 :
 						cVideoResolution::eDontChange;
 	}
 
@@ -126,6 +131,12 @@ public:
 						cVideoFrameRate::eDontChange;
 	}
 
+	static bool UseAdvancedDeinterlacer(int width, int height) {
+		return GetInstance()->m_video.advancedDeinterlacer == 0 ? false :
+				GetInstance()->m_video.advancedDeinterlacer == 1 ?
+						(width * height <= 576 * 720 ? true : false) : true;
+	}
+
 	static bool IsAudioFormatSupported(cAudioCodec::eCodec codec,
 			int channels, int samplingRate);
 
diff --git a/tools.c b/tools.c
new file mode 100644
index 0000000..e807045
--- /dev/null
+++ b/tools.c
@@ -0,0 +1,111 @@
+/*
+ * rpihddevice - VDR HD output device for Raspberry Pi
+ * Copyright (C) 2014, 2015, 2016 Thomas Reufer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <vdr/tools.h>
+#include "tools.h"
+#include <algorithm>
+
+/*
+ * ffmpeg's implementation for rational numbers:
+ * https://github.com/FFmpeg/FFmpeg/blob/master/libavutil/rational.c
+ */
+
+cRational::cRational(double d) :
+	num(0), den(0)
+{
+	int exp;
+	frexp(d, &exp);
+
+	den = 1LL << (29 - std::max(exp - 1, 0));
+	num = floor(d * den + 0.5);
+
+	Reduce(INT_MAX);
+}
+
+bool cRational::Reduce(int max)
+{
+	cRational a0 = cRational(0, 1), a1 = cRational(1, 0);
+	int sign = (num < 0) ^ (den < 0);
+	if (int div = Gcd(abs(num), abs(den)))
+	{
+		num = abs(num) / div;
+		den = abs(den) / div;
+	}
+	if (num <= max && den <= max)
+	{
+		a1 = cRational(num, den);
+		den = 0;
+	}
+	while (den)
+	{
+		int x = num / den;
+		int nextDen = num - den * x;
+		cRational a2 = cRational(x * a1.num + a0.num, x * a1.den + a0.den);
+		if (a2.num > max || a2.den > max)
+		{
+			if (a1.num)
+				x = (max - a0.num) / a1.num;
+			if (a1.den)
+				x = std::min(x, (max - a0.den) / a1.den);
+			if (den * (2 * x * a1.den + a0.den) > num * a1.den)
+				a1 = cRational(x * a1.num + a0.num, x * a1.den + a0.den);
+			break;
+		}
+		a0 = a1;
+		a1 = a2;
+		num = den;
+		den = nextDen;
+	}
+	num = sign ? -a1.num : a1.num;
+	den = a1.den;
+	return den == 0;
+}
+
+/*
+ * Stein's binary GCD algorithm:
+ * https://en.wikipedia.org/wiki/Binary_GCD_algorithm
+ */
+
+int cRational::Gcd(int u, int v)
+{
+    if (u == v || v == 0)
+        return u;
+
+    if (u == 0)
+        return v;
+
+    // look for factors of 2
+    if (~u & 1) // u is even
+    {
+        if (v & 1) // v is odd
+            return Gcd(u >> 1, v);
+        else // both u and v are even
+            return Gcd(u >> 1, v >> 1) << 1;
+    }
+
+    if (~v & 1) // u is odd, v is even
+        return Gcd(u, v >> 1);
+
+    // reduce larger argument
+    if (u > v)
+        return Gcd((u - v) >> 1, v);
+
+    return Gcd((v - u) >> 1, u);
+}
diff --git a/tools.h b/tools.h
index c6d198f..4a1a6c5 100644
--- a/tools.h
+++ b/tools.h
@@ -38,7 +38,9 @@ public:
 		eDontChange = 0,
 		eFollowVideo,
 		e480,
+		e480w,
 		e576,
+		e576w,
 		e720,
 		e1080
 	};
@@ -47,7 +49,9 @@ public:
 		return	(resolution == eDontChange)  ? "don't change" :
 				(resolution == eFollowVideo) ? "follow video" :
 				(resolution == e480)         ? "480"          :
+				(resolution == e480w)        ? "480w"         :
 				(resolution == e576)         ? "576"          :
+				(resolution == e576w)        ? "576w"         :
 				(resolution == e720)         ? "720"          :
 				(resolution == e1080)        ? "1080"         :	"unknown";
 	}
@@ -215,4 +219,22 @@ public:
 	}
 };
 
+class cRational
+{
+public:
+
+	cRational(double d);
+	cRational(int _num, int _den) : num(_num), den(_den) { }
+
+	bool Reduce(int max);
+
+	int num;
+	int den;
+
+private:
+
+	cRational();
+	static int Gcd(int u, int v);
+};
+
 #endif

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-vdr-dvb/vdr-plugin-rpihddevice.git



More information about the pkg-vdr-dvb-changes mailing list