[vdr-plugin-rpihddevice] 03/10: Imported Upstream version 1.0.0

Tobias Grimm tiber-guest at moszumanska.debian.org
Sun Oct 18 09:22:15 UTC 2015


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 a63c8269bf96e0da9bdc4b659447a1578b29d652
Author: Tobias Grimm <etobi at debian.org>
Date:   Sun Oct 18 10:53:42 2015 +0200

    Imported Upstream version 1.0.0
---
 HISTORY       |  15 ++++++++
 README        |   2 +
 audio.c       |  18 ++++-----
 audio.h       |   2 +-
 display.c     |  39 +++++++++++++------
 display.h     |  16 +++++---
 omx.c         | 120 ++++++++++++++++++++++++++++++++--------------------------
 omx.h         |  29 +++++++-------
 omxdevice.c   | 101 ++++++++++++++++++++++++------------------------
 omxdevice.h   |  10 +++--
 ovgosd.c      |  72 ++++++++++++++++++++---------------
 ovgosd.h      |   2 +-
 po/de_DE.po   |  11 +++---
 po/fi_FI.po   |  16 +++-----
 po/fr_FR.po   |  72 +++++++++++++++++++++++++++++++++++
 po/hu_HU.po   |  25 +++++-------
 po/it_IT.po   |  72 +++++++++++++++++++++++++++++++++++
 rpihddevice.c |   6 +--
 setup.c       |  20 ++++++++--
 setup.h       |  12 +++++-
 tools.h       |  38 +++++++++++++++++++
 21 files changed, 478 insertions(+), 220 deletions(-)

diff --git a/HISTORY b/HISTORY
index 0006722..c365b6f 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,6 +1,21 @@
 VDR Plugin 'rpihddevice' Revision History
 -----------------------------------------
 
+2015-10-18: Version 1.0.0
+-------------------------
+- new:
+  - updated Hungarian translations (thanks to Füley István)
+  - updated Finnish translations (thanks to Rolf Ahrenberg)
+  - added Italian translations (thanks to Gerlando Falauto)
+  - added French translations (thanks to Cyril Jaquier)
+  - added plugin options to specify video and OSD layers
+- fixed:
+  - don't crop OSD images to pixmap size to allow scaled drawing
+  - treat zero as valid PTS value
+  - perform save / restore region direct on pixmaps for accelerated OSDs
+  - wait for the OVG thread to be ready when creating an accelerated OSD
+  - set field sync when output interlaced material at interlaced display mode
+
 2015-04-29: Version 0.1.0
 -------------------------
 - new:
diff --git a/README b/README
index 99ec55b..8698888 100644
--- a/README
+++ b/README
@@ -68,6 +68,8 @@ Options:
   -d, --disable-osd  Disables creation of OSD layer and prevents the plugin of
                      allocating any OSD related resources. If set, VDR's dummy
                      OSD is used, when selecting rpihddevice as primary device.
+  -v, --video-layer  Specify the dispmanx layer for video (default 0)
+  -o, --osd-layer    Specify the dispmanx layer for OSD (default 2)
 
 Plugin-Setup:
 
diff --git a/audio.c b/audio.c
index 7c7b460..6a2864a 100644
--- a/audio.c
+++ b/audio.c
@@ -115,9 +115,9 @@ public:
 		return m_packet.size;
 	}
 
-	uint64_t GetPts(void)
+	int64_t GetPts(void)
 	{
-		uint64_t pts = 0;
+		int64_t pts = OMX_INVALID_PTS;
 		m_mutex->Lock();
 
 		if (!m_ptsQueue.empty())
@@ -174,7 +174,7 @@ public:
 		m_mutex->Unlock();
 	}
 
-	bool Append(const unsigned char *data, uint64_t pts, unsigned int length)
+	bool Append(const unsigned char *data, int64_t pts, unsigned int length)
 	{
 		m_mutex->Lock();
 		bool ret = true;
@@ -219,7 +219,7 @@ public:
 					// clear current PTS since it's not valid anymore after
 					// shrinking the packet
 					if (!retainPts)
-						m_ptsQueue.front()->pts = 0;
+						m_ptsQueue.front()->pts = OMX_INVALID_PTS;
 
 					m_ptsQueue.front()->length -= length;
 					length = 0;
@@ -339,10 +339,10 @@ private:
 
 	struct Pts
 	{
-		Pts(uint64_t _pts, unsigned int _length)
+		Pts(int64_t _pts, unsigned int _length)
 			: pts(_pts), length(_length) { };
 
-		uint64_t 		pts;
+		int64_t 		pts;
 		unsigned int 	length;
 	};
 
@@ -893,7 +893,7 @@ public:
 		delete m_mutex;
 	}
 
-	int WriteSamples(uint8_t** data, int samples, uint64_t pts,
+	int WriteSamples(uint8_t** data, int samples, int64_t pts,
 			AVSampleFormat sampleFormat = AV_SAMPLE_FMT_NONE)
 	{
 		if (!Ready())
@@ -1134,7 +1134,7 @@ private:
 #endif
 
 	AVSampleFormat       m_pcmSampleFormat;
-	uint64_t             m_pts;
+	int64_t              m_pts;
 };
 
 /* ------------------------------------------------------------------------- */
@@ -1244,7 +1244,7 @@ int cRpiAudioDecoder::DeInit(void)
 }
 
 bool cRpiAudioDecoder::WriteData(const unsigned char *buf, unsigned int length,
-		uint64_t pts)
+		int64_t pts)
 {
 	Lock();
 
diff --git a/audio.h b/audio.h
index 9560513..8ff2b47 100644
--- a/audio.h
+++ b/audio.h
@@ -26,7 +26,7 @@ public:
 	virtual int DeInit(void);
 
 	virtual bool WriteData(const unsigned char *buf, unsigned int length,
-			uint64_t pts = 0);
+			int64_t pts = 0);
 
 	virtual bool Poll(void);
 	virtual void Reset(void);
diff --git a/display.c b/display.c
index c839d59..a03fc00 100644
--- a/display.c
+++ b/display.c
@@ -16,6 +16,8 @@ extern "C" {
 #include "interface/vmcs_host/vc_dispmanx.h"
 }
 
+#include <bcm_host.h>
+
 cRpiDisplay* cRpiDisplay::s_instance = 0;
 
 cRpiDisplay* cRpiDisplay::GetInstance(void)
@@ -53,6 +55,7 @@ cRpiDisplay* cRpiDisplay::GetInstance(void)
 
 void cRpiDisplay::DropInstance(void)
 {
+	SetHvsSyncUpdate(cScanMode::eProgressive);
 	delete s_instance;
 	s_instance = 0;
 }
@@ -96,16 +99,24 @@ int cRpiDisplay::GetSize(int &width, int &height, double &aspect)
 	return -1;
 }
 
-int cRpiDisplay::SetVideoFormat(int width, int height, int frameRate,
-		bool interlaced)
+int cRpiDisplay::SetVideoFormat(const cVideoFrameFormat *frameFormat)
 {
 	cRpiDisplay* instance = GetInstance();
 	if (instance)
-		return instance->Update(width, height, frameRate, interlaced);
+		return instance->Update(frameFormat);
 
 	return -1;
 }
 
+int cRpiDisplay::SetHvsSyncUpdate(cScanMode::eMode scanMode)
+{
+	char response[64];
+	DBG("SetHvsSyncUpdate(%s)", cScanMode::Str(scanMode));
+	return vc_gencmd(response, sizeof(response), "hvs_update_fields %d",
+			scanMode == cScanMode::eTopFieldFirst    ? 1 :
+			scanMode == cScanMode::eBottomFieldFirst ? 2 : 0);
+}
+
 cRpiVideoPort::ePort cRpiDisplay::GetVideoPort(void)
 {
 	cRpiDisplay* instance = GetInstance();
@@ -152,7 +163,7 @@ int cRpiDisplay::Snapshot(unsigned char* frame, int width, int height)
 	return -1;
 }
 
-int cRpiDisplay::Update(int width, int height, int frameRate, bool interlaced)
+int cRpiDisplay::Update(const cVideoFrameFormat *frameFormat)
 {
 	if (cRpiSetup::GetVideoResolution() == cVideoResolution::eDontChange &&
 				cRpiSetup::GetVideoFrameRate() == cVideoFrameRate::eDontChange)
@@ -171,10 +182,10 @@ int cRpiDisplay::Update(int width, int height, int frameRate, bool interlaced)
 	case cVideoResolution::e1080: newWidth = 1920; newHeight = 1080; break;
 
 	case cVideoResolution::eFollowVideo:
-		if (width && height)
+		if (frameFormat->width && frameFormat->height)
 		{
-			newWidth = width;
-			newHeight = height;
+			newWidth = frameFormat->width;
+			newHeight = frameFormat->height;
 		}
 		break;
 
@@ -194,10 +205,10 @@ int cRpiDisplay::Update(int width, int height, int frameRate, bool interlaced)
 	case cVideoFrameRate::e60p: newFrameRate = 60; newInterlaced = false; break;
 
 	case cVideoFrameRate::eFollowVideo:
-		if (frameRate)
+		if (frameFormat->frameRate)
 		{
-			newFrameRate = frameRate;
-			newInterlaced = interlaced;
+			newFrameRate = frameFormat->frameRate;
+			newInterlaced = frameFormat->Interlaced();
 		}
 		break;
 
@@ -209,7 +220,8 @@ int cRpiDisplay::Update(int width, int height, int frameRate, bool interlaced)
 	// set new mode only if necessary
 	if (newWidth != m_width || newHeight != m_height ||
 			newFrameRate != m_frameRate || newInterlaced != m_interlaced)
-		return SetMode(newWidth, newHeight, newFrameRate, newInterlaced);
+		return SetMode(newWidth, newHeight, newFrameRate,
+				newInterlaced ? frameFormat->scanMode : cScanMode::eProgressive);
 
 	return 0;
 }
@@ -299,8 +311,11 @@ cRpiHDMIDisplay::~cRpiHDMIDisplay()
 }
 
 int cRpiHDMIDisplay::SetMode(int width, int height, int frameRate,
-		bool interlaced)
+		cScanMode::eMode scanMode)
 {
+	SetHvsSyncUpdate(scanMode);
+	bool interlaced = cScanMode::Interlaced(scanMode);
+
 	for (int i = 0; i < m_modes->nModes; i++)
 	{
 		if (m_modes->modes[i].width == width &&
diff --git a/display.h b/display.h
index d954a2e..5af4e02 100644
--- a/display.h
+++ b/display.h
@@ -25,8 +25,7 @@ public:
 
 	static int Snapshot(unsigned char* frame, int width, int height);
 
-	static int SetVideoFormat(int width, int height, int frameRate,
-			bool interlaced);
+	static int SetVideoFormat(const cVideoFrameFormat *frameFormat);
 
 protected:
 
@@ -34,12 +33,15 @@ protected:
 			cRpiVideoPort::ePort port);
 	virtual ~cRpiDisplay();
 
-	int Update(int width, int height, int frameRate, bool interlaced);
+	int Update(const cVideoFrameFormat *videoFormat);
 
-	virtual int SetMode(int width, int height, int frameRate, bool interlaced) {
+	virtual int SetMode(int width, int height, int frameRate,
+			cScanMode::eMode scanMode) {
 		return -1;
 	}
 
+	static int SetHvsSyncUpdate(cScanMode::eMode scanMode);
+
 	int m_width;
 	int m_height;
 	int m_frameRate;
@@ -65,7 +67,8 @@ public:
 
 private:
 
-	virtual int SetMode(int width, int height, int frameRate, bool interlaced);
+	virtual int SetMode(int width, int height, int frameRate,
+			cScanMode::eMode scanMode);
 	int SetMode(int group, int mode);
 
 	static void TvServiceCallback(void *data, unsigned int reason,
@@ -91,7 +94,8 @@ public:
 
 private:
 
-	virtual int SetMode(int width, int height, int frameRate, bool interlaced) {
+	virtual int SetMode(int width, int height, int frameRate,
+			cScanMode::eMode scanMode) {
 		return 0;
 	}
 };
diff --git a/omx.c b/omx.c
index eb04028..b3aa466 100644
--- a/omx.c
+++ b/omx.c
@@ -297,28 +297,34 @@ void cOmx::HandlePortSettingsChanged(unsigned int portId)
 				&interlace) != OMX_ErrorNone)
 			ELOG("failed to get video decoder interlace config!");
 
-		m_videoFormat.width = portdef.format.video.nFrameWidth;
-		m_videoFormat.height = portdef.format.video.nFrameHeight;
-		m_videoFormat.interlaced = interlace.eMode != OMX_InterlaceProgressive;
+		m_videoFrameFormat.width = portdef.format.video.nFrameWidth;
+		m_videoFrameFormat.height = portdef.format.video.nFrameHeight;
+		m_videoFrameFormat.scanMode =
+				interlace.eMode == OMX_InterlaceProgressive ? cScanMode::eProgressive :
+				interlace.eMode == OMX_InterlaceFieldSingleUpperFirst ? cScanMode::eTopFieldFirst :
+				interlace.eMode == OMX_InterlaceFieldSingleLowerFirst ? cScanMode::eBottomFieldFirst :
+				interlace.eMode == OMX_InterlaceFieldsInterleavedUpperFirst ? cScanMode::eTopFieldFirst :
+				interlace.eMode == OMX_InterlaceFieldsInterleavedLowerFirst ? cScanMode::eBottomFieldFirst :
+						cScanMode::eProgressive;
 
 		// discard 4 least significant bits, since there might be some deviation
 		// due to jitter in time stamps
-		m_videoFormat.frameRate = ALIGN_UP(
+		m_videoFrameFormat.frameRate = ALIGN_UP(
 				portdef.format.video.xFramerate & 0xfffffff0, 1 << 16) >> 16;
 
 		// workaround for progressive streams detected as interlaced video by
 		// the decoder due to missing SEI parsing
 		// see: https://github.com/raspberrypi/firmware/issues/283
 		// update: with FW from 2015/01/18 this is not necessary anymore
-		if (m_videoFormat.interlaced && m_videoFormat.frameRate >= 50)
+		if (m_videoFrameFormat.Interlaced() && m_videoFrameFormat.frameRate >= 50)
 		{
 			DLOG("%di looks implausible, you should use a recent firmware...",
-					m_videoFormat.frameRate * 2);
+					m_videoFrameFormat.frameRate * 2);
 			//m_videoFormat.interlaced = false;
 		}
 
-		if (m_videoFormat.interlaced)
-			m_videoFormat.frameRate = m_videoFormat.frameRate * 2;
+		if (m_videoFrameFormat.Interlaced())
+			m_videoFrameFormat.frameRate = m_videoFrameFormat.frameRate * 2;
 
 		if (m_onStreamStart)
 			m_onStreamStart(m_onStreamStartData);
@@ -332,7 +338,7 @@ void cOmx::HandlePortSettingsChanged(unsigned int portId)
 		OMX_INIT_STRUCT(extraBuffers);
 		extraBuffers.nPortIndex = 130;
 
-		if (cRpiDisplay::IsProgressive() && m_videoFormat.interlaced)
+		if (cRpiDisplay::IsProgressive() && m_videoFrameFormat.Interlaced())
 		{
 			bool fastDeinterlace = portdef.format.video.nFrameWidth *
 					portdef.format.video.nFrameHeight > 576 * 720;
@@ -437,10 +443,10 @@ cOmx::cOmx() :
 	memset(m_tun, 0, sizeof(m_tun));
 	memset(m_comp, 0, sizeof(m_comp));
 
-	m_videoFormat.width = 0;
-	m_videoFormat.height = 0;
-	m_videoFormat.frameRate = 0;
-	m_videoFormat.interlaced = false;
+	m_videoFrameFormat.width = 0;
+	m_videoFrameFormat.height = 0;
+	m_videoFrameFormat.frameRate = 0;
+	m_videoFrameFormat.scanMode = cScanMode::eProgressive;
 }
 
 cOmx::~cOmx()
@@ -448,7 +454,7 @@ cOmx::~cOmx()
 	delete m_portEvents;
 }
 
-int cOmx::Init(void)
+int cOmx::Init(int layer)
 {
 	m_client = ilclient_init();
 	if (m_client == NULL)
@@ -523,6 +529,7 @@ int cOmx::Init(void)
 	ilclient_change_component_state(m_comp[eVideoFx], OMX_StateIdle);
 	ilclient_change_component_state(m_comp[eAudioRender], OMX_StateIdle);
 
+	SetDisplayLayer(layer);
 	SetClockLatencyTarget();
 	SetBufferStallThreshold(20000);
 	SetClockReference(cOmx::eClockRefVideo);
@@ -587,7 +594,7 @@ int64_t cOmx::FromOmxTicks(OMX_TICKS &ticks)
 	return ret;
 }
 
-void cOmx::PtsToTicks(uint64_t pts, OMX_TICKS &ticks)
+void cOmx::PtsToTicks(int64_t pts, OMX_TICKS &ticks)
 {
 	// ticks = pts * OMX_TICKS_PER_SECOND / PTSTICKS
 	pts = pts * 100 / 9;
@@ -595,10 +602,10 @@ void cOmx::PtsToTicks(uint64_t pts, OMX_TICKS &ticks)
 	ticks.nHighPart = pts >> 32;
 }
 
-uint64_t cOmx::TicksToPts(OMX_TICKS &ticks)
+int64_t cOmx::TicksToPts(OMX_TICKS &ticks)
 {
 	// pts = ticks * PTSTICKS / OMX_TICKS_PER_SECOND
-	uint64_t pts = ticks.nHighPart;
+	int64_t pts = ticks.nHighPart;
 	pts = (pts << 32) + ticks.nLowPart;
 	pts = pts * 9 / 100;
 	return pts;
@@ -606,7 +613,7 @@ uint64_t cOmx::TicksToPts(OMX_TICKS &ticks)
 
 int64_t cOmx::GetSTC(void)
 {
-	int64_t stc = -1;
+	int64_t stc = OMX_INVALID_PTS;
 	OMX_TIME_CONFIG_TIMESTAMPTYPE timestamp;
 	OMX_INIT_STRUCT(timestamp);
 	timestamp.nPortIndex = OMX_ALL;
@@ -859,6 +866,18 @@ void cOmx::StopVideo(void)
 {
 	Lock();
 
+	// disable port buffers and allow video decoder to reconfig
+	ilclient_disable_port_buffers(m_comp[eVideoDecoder], 130,
+			m_spareVideoBuffers, NULL, NULL);
+
+	m_spareVideoBuffers = 0;
+	m_handlePortEvents = false;
+
+	m_videoFrameFormat.width = 0;
+	m_videoFrameFormat.height = 0;
+	m_videoFrameFormat.frameRate = 0;
+	m_videoFrameFormat.scanMode = cScanMode::eProgressive;
+
 	// put video decoder into idle
 	ilclient_change_component_state(m_comp[eVideoDecoder], OMX_StateIdle);
 
@@ -879,18 +898,6 @@ void cOmx::StopVideo(void)
 	ilclient_disable_tunnel(&m_tun[eVideoSchedulerToVideoRender]);
 	ilclient_change_component_state(m_comp[eVideoRender], OMX_StateIdle);
 
-	// disable port buffers and allow video decoder to reconfig
-	ilclient_disable_port_buffers(m_comp[eVideoDecoder], 130,
-			m_spareVideoBuffers, NULL, NULL);
-
-	m_spareVideoBuffers = 0;
-
-	m_videoFormat.width = 0;
-	m_videoFormat.height = 0;
-	m_videoFormat.frameRate = 0;
-	m_videoFormat.interlaced = false;
-
-	m_handlePortEvents = false;
 	Unlock();
 }
 
@@ -1173,15 +1180,6 @@ int cOmx::SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels,
 	return 0;
 }
 
-void cOmx::GetVideoFormat(int &width, int &height, int &frameRate,
-		bool &interlaced)
-{
-	width = m_videoFormat.width;
-	height = m_videoFormat.height;
-	frameRate = m_videoFormat.frameRate;
-	interlaced = m_videoFormat.interlaced;
-}
-
 void cOmx::SetDisplayMode(bool fill, bool noaspect)
 {
 	OMX_CONFIG_DISPLAYREGIONTYPE region;
@@ -1217,7 +1215,20 @@ void cOmx::SetDisplayRegion(int x, int y, int width, int height)
 		ELOG("failed to set display region!");
 }
 
-OMX_BUFFERHEADERTYPE* cOmx::GetAudioBuffer(uint64_t pts)
+void cOmx::SetDisplayLayer(int layer)
+{
+	OMX_CONFIG_DISPLAYREGIONTYPE region;
+	OMX_INIT_STRUCT(region);
+	region.nPortIndex = 90;
+	region.layer = layer;
+	region.set = (OMX_DISPLAYSETTYPE)(OMX_DISPLAY_SET_LAYER);
+
+	if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eVideoRender]),
+			OMX_IndexConfigDisplayRegion, &region) != OMX_ErrorNone)
+		ELOG("failed to set display region!");
+}
+
+OMX_BUFFERHEADERTYPE* cOmx::GetAudioBuffer(int64_t pts)
 {
 	Lock();
 	OMX_BUFFERHEADERTYPE* buf = 0;
@@ -1241,19 +1252,20 @@ OMX_BUFFERHEADERTYPE* cOmx::GetAudioBuffer(uint64_t pts)
 		buf->nOffset = 0;
 		buf->nFlags = 0;
 
-		if (m_setAudioStartTime)
-			buf->nFlags |= OMX_BUFFERFLAG_STARTTIME;
-		else if (!pts)
+		if (pts == OMX_INVALID_PTS)
 			buf->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
-
+		else if (m_setAudioStartTime)
+		{
+			buf->nFlags |= OMX_BUFFERFLAG_STARTTIME;
+			m_setAudioStartTime = false;
+		}
 		cOmx::PtsToTicks(pts, buf->nTimeStamp);
-		m_setAudioStartTime = false;
 	}
 	Unlock();
 	return buf;
 }
 
-OMX_BUFFERHEADERTYPE* cOmx::GetVideoBuffer(uint64_t pts)
+OMX_BUFFERHEADERTYPE* cOmx::GetVideoBuffer(int64_t pts)
 {
 	Lock();
 	OMX_BUFFERHEADERTYPE* buf = 0;
@@ -1277,17 +1289,19 @@ OMX_BUFFERHEADERTYPE* cOmx::GetVideoBuffer(uint64_t pts)
 		buf->nOffset = 0;
 		buf->nFlags = 0;
 
-		if (m_setVideoStartTime)
-			buf->nFlags |= OMX_BUFFERFLAG_STARTTIME;
-		else if (!pts)
+		if (pts == OMX_INVALID_PTS)
 			buf->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
-
+		else if (m_setVideoStartTime)
+		{
+			buf->nFlags |= OMX_BUFFERFLAG_STARTTIME;
+			m_setVideoStartTime = false;
+		}
 		if (m_setVideoDiscontinuity)
+		{
 			buf->nFlags |= OMX_BUFFERFLAG_DISCONTINUITY;
-
+			m_setVideoDiscontinuity = false;
+		}
 		cOmx::PtsToTicks(pts, buf->nTimeStamp);
-		m_setVideoStartTime = false;
-		m_setVideoDiscontinuity = false;
 	}
 	Unlock();
 	return buf;
diff --git a/omx.h b/omx.h
index 6988ad4..957db98 100644
--- a/omx.h
+++ b/omx.h
@@ -15,6 +15,8 @@ extern "C"
 #include "ilclient.h"
 }
 
+#define OMX_INVALID_PTS -1
+
 class cOmxEvents;
 
 class cOmx : public cThread
@@ -24,7 +26,7 @@ public:
 
 	cOmx();
 	virtual ~cOmx();
-	int Init(void);
+	int Init(int layer);
 	int DeInit(void);
 
 	void SetBufferStallCallback(void (*onBufferStall)(void*), void* data);
@@ -33,8 +35,8 @@ public:
 
 	static OMX_TICKS ToOmxTicks(int64_t val);
 	static int64_t FromOmxTicks(OMX_TICKS &ticks);
-	static void PtsToTicks(uint64_t pts, OMX_TICKS &ticks);
-	static uint64_t TicksToPts(OMX_TICKS &ticks);
+	static void PtsToTicks(int64_t pts, OMX_TICKS &ticks);
+	static int64_t TicksToPts(OMX_TICKS &ticks);
 
 	int64_t GetSTC(void);
 	bool IsClockRunning(void);
@@ -78,14 +80,17 @@ public:
 	int SetupAudioRender(cAudioCodec::eCodec outputFormat,
 			int channels, cRpiAudioPort::ePort audioPort,
 			int samplingRate = 0, int frameSize = 0);
-	void GetVideoFormat(int &width, int &height, int &frameRate,
-			bool &interlaced);
+
+	const cVideoFrameFormat *GetVideoFrameFormat(void) {
+		return &m_videoFrameFormat;
+	}
 
 	void SetDisplayMode(bool letterbox, bool noaspect);
 	void SetDisplayRegion(int x, int y, int width, int height);
+	void SetDisplayLayer(int layer);
 
-	OMX_BUFFERHEADERTYPE* GetAudioBuffer(uint64_t pts = 0);
-	OMX_BUFFERHEADERTYPE* GetVideoBuffer(uint64_t pts = 0);
+	OMX_BUFFERHEADERTYPE* GetAudioBuffer(int64_t pts = OMX_INVALID_PTS);
+	OMX_BUFFERHEADERTYPE* GetVideoBuffer(int64_t pts = OMX_INVALID_PTS);
 
 	bool PollVideo(void);
 
@@ -128,15 +133,7 @@ private:
 	COMPONENT_T	*m_comp[cOmx::eNumComponents + 1];
 	TUNNEL_T 	 m_tun[cOmx::eNumTunnels + 1];
 
-	struct VideoFormat
-	{
-		int width;
-		int height;
-		int frameRate;
-		bool interlaced;
-	};
-
-	VideoFormat m_videoFormat;
+	cVideoFrameFormat m_videoFrameFormat;
 
 	bool m_setAudioStartTime;
 	bool m_setVideoStartTime;
diff --git a/omxdevice.c b/omxdevice.c
index a470be6..c5df12a 100644
--- a/omxdevice.c
+++ b/omxdevice.c
@@ -37,7 +37,7 @@ const uchar cOmxDevice::PesVideoHeader[14] = {
 	0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-cOmxDevice::cOmxDevice(void (*onPrimaryDevice)(void)) :
+cOmxDevice::cOmxDevice(void (*onPrimaryDevice)(void), int layer) :
 	cDevice(),
 	m_onPrimaryDevice(onPrimaryDevice),
 	m_omx(new cOmx()),
@@ -56,7 +56,8 @@ cOmxDevice::cOmxDevice(void (*onPrimaryDevice)(void)) :
 	m_trickRequest(0),
 	m_audioPts(0),
 	m_videoPts(0),
-	m_lastStc(0)
+	m_lastStc(0),
+	m_layer(layer)
 {
 }
 
@@ -72,7 +73,7 @@ cOmxDevice::~cOmxDevice()
 
 int cOmxDevice::Init(void)
 {
-	if (m_omx->Init() < 0)
+	if (m_omx->Init(m_layer) < 0)
 	{
 		ELOG("failed to initialize OMX!");
 		return -1;
@@ -120,10 +121,8 @@ void cOmxDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect)
 
 void cOmxDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect)
 {
-	bool interlaced;
-	int frameRate;
-
-	m_omx->GetVideoFormat(Width, Height, frameRate, interlaced);
+	Height = m_omx->GetVideoFrameFormat()->height;
+	Width = m_omx->GetVideoFrameFormat()->width;
 
 	if (Height)
 		VideoAspect = (double)Width / Height;
@@ -216,6 +215,7 @@ void cOmxDevice::StillPicture(const uchar *Data, int Length)
 		m_mutex->Lock();
 		m_playbackSpeed = eNormal;
 		m_direction = eForward;
+		m_hasVideo = false;
 		m_omx->StopClock();
 
 		// to get a picture displayed, PlayVideo() needs to be called
@@ -258,31 +258,36 @@ int cOmxDevice::PlayAudio(const uchar *Data, int Length, uchar Id)
 
 	m_mutex->Lock();
 	int ret = Length;
-	int64_t pts = PesHasPts(Data) ? PesGetPts(Data) : 0;
+	int64_t pts = PesHasPts(Data) ? PesGetPts(Data) : OMX_INVALID_PTS;
 
-	if (!m_hasAudio)
+	if (pts != OMX_INVALID_PTS)
 	{
-		m_hasAudio = true;
-		m_omx->SetClockReference(cOmx::eClockRefAudio);
-
-		if (!m_hasVideo)
-		{
-			DBG("audio first");
-			m_omx->SetClockScale(s_playbackSpeeds[m_direction][m_playbackSpeed]);
-			m_omx->StartClock(m_hasVideo, m_hasAudio);
-			m_audioPts = PTS_START_OFFSET + pts;
-			m_playMode = pmAudioOnly;
-		}
-		else
+		if (!m_hasAudio)
 		{
-			m_audioPts = m_videoPts + PtsDiff(m_videoPts & MAX33BIT, pts);
-			m_playMode = pmAudioVideo;
+			m_hasAudio = true;
+			m_omx->SetClockReference(cOmx::eClockRefAudio);
+
+			if (!m_hasVideo)
+			{
+				DBG("audio first");
+				m_omx->SetClockScale(
+						s_playbackSpeeds[m_direction][m_playbackSpeed]);
+				m_omx->StartClock(m_hasVideo, m_hasAudio);
+				m_audioPts = PTS_START_OFFSET + pts;
+				m_playMode = pmAudioOnly;
+			}
+			else
+			{
+				m_audioPts = m_videoPts + PtsDiff(m_videoPts & MAX33BIT, pts);
+				m_playMode = pmAudioVideo;
+			}
 		}
-	}
 
-	if (pts)
-	{
 		int64_t ptsDiff = PtsDiff(m_audioPts & MAX33BIT, pts);
+
+		if ((m_audioPts & ~MAX33BIT) != (m_audioPts + ptsDiff & ~MAX33BIT))
+			DBG("audio PTS wrap around");
+
 		m_audioPts += ptsDiff;
 
 		// keep track of direction in case of trick speed
@@ -305,7 +310,8 @@ int cOmxDevice::PlayAudio(const uchar *Data, int Length, uchar Id)
 			data += 4;
 			length -= 4;
 		}
-		if (!m_audio->WriteData(data, length, pts ? m_audioPts : 0))
+		if (!m_audio->WriteData(data, length,
+				pts != OMX_INVALID_PTS ? m_audioPts : OMX_INVALID_PTS))
 			ret = 0;
 	}
 	m_mutex->Unlock();
@@ -327,9 +333,10 @@ int cOmxDevice::PlayVideo(const uchar *Data, int Length, bool EndOfFrame)
 
 	m_mutex->Lock();
 	int ret = Length;
-	int64_t pts = PesHasPts(Data) ? PesGetPts(Data) : 0;
+	int64_t pts = PesHasPts(Data) ? PesGetPts(Data) : OMX_INVALID_PTS;
 
-	if (!m_hasVideo && pts && m_videoCodec == cVideoCodec::eInvalid)
+	if (!m_hasVideo && pts != OMX_INVALID_PTS &&
+			m_videoCodec == cVideoCodec::eInvalid)
 	{
 		m_videoCodec = ParseVideoCodec(Data + PesPayloadOffset(Data),
 				Length - PesPayloadOffset(Data));
@@ -346,7 +353,8 @@ int cOmxDevice::PlayVideo(const uchar *Data, int Length, bool EndOfFrame)
 		}
 	}
 
-	if (!m_hasVideo && pts && cRpiSetup::IsVideoCodecSupported(m_videoCodec))
+	if (!m_hasVideo && pts != OMX_INVALID_PTS &&
+			cRpiSetup::IsVideoCodecSupported(m_videoCodec))
 	{
 		m_hasVideo = true;
 		if (!m_hasAudio)
@@ -367,7 +375,7 @@ int cOmxDevice::PlayVideo(const uchar *Data, int Length, bool EndOfFrame)
 
 	if (m_hasVideo)
 	{
-		if (pts)
+		if (pts != OMX_INVALID_PTS)
 		{
 			int64_t ptsDiff = PtsDiff(m_videoPts & MAX33BIT, pts);
 			m_videoPts += ptsDiff;
@@ -383,8 +391,8 @@ int cOmxDevice::PlayVideo(const uchar *Data, int Length, bool EndOfFrame)
 
 		while (Length > 0)
 		{
-			if (OMX_BUFFERHEADERTYPE *buf =
-					m_omx->GetVideoBuffer(pts ? m_videoPts : 0))
+			if (OMX_BUFFERHEADERTYPE *buf =	m_omx->GetVideoBuffer(
+					pts != OMX_INVALID_PTS ? m_videoPts : OMX_INVALID_PTS))
 			{
 				buf->nFilledLen = buf->nAllocLen < (unsigned)Length ?
 						buf->nAllocLen : Length;
@@ -408,7 +416,7 @@ int cOmxDevice::PlayVideo(const uchar *Data, int Length, bool EndOfFrame)
 				ret = 0;
 				break;
 			}
-			pts = 0;
+			pts = OMX_INVALID_PTS;
 		}
 	}
 	m_mutex->Unlock();
@@ -435,7 +443,7 @@ bool cOmxDevice::SubmitEOS(void)
 int64_t cOmxDevice::GetSTC(void)
 {
 	int64_t stc = m_omx->GetSTC();
-	if (stc)
+	if (stc != OMX_INVALID_PTS)
 		m_lastStc = stc;
 	return m_lastStc & MAX33BIT;
 }
@@ -635,9 +643,12 @@ void cOmxDevice::HandleBufferStall()
 	ELOG("buffer stall!");
 	m_mutex->Lock();
 
-	FlushStreams();
+	FlushStreams(true);
+	m_omx->StopVideo();
+
 	m_hasAudio = false;
 	m_hasVideo = false;
+	m_videoCodec = cVideoCodec::eInvalid;
 
 	m_mutex->Unlock();
 }
@@ -659,15 +670,11 @@ void cOmxDevice::HandleStreamStart()
 {
 	DBG("HandleStreamStart()");
 
-	int width, height, frameRate;
-	bool interlaced;
+	const cVideoFrameFormat *format = m_omx->GetVideoFrameFormat();
+	DLOG("video stream started %dx%d@%d%s",	format->width, format->height,
+			format->frameRate, format->Interlaced() ? "i" : "p");
 
-	m_omx->GetVideoFormat(width, height, frameRate, interlaced);
-
-	DLOG("video stream started %dx%d@%d%s",
-			width, height, frameRate, interlaced ? "i" : "p");
-
-	cRpiDisplay::SetVideoFormat(width, height, frameRate, interlaced);
+	cRpiDisplay::SetVideoFormat(format);
 }
 
 void cOmxDevice::HandleVideoSetupChanged()
@@ -690,11 +697,7 @@ void cOmxDevice::HandleVideoSetupChanged()
 		break;
 	}
 
-	int width, height, frameRate;
-	bool interlaced;
-
-	m_omx->GetVideoFormat(width, height, frameRate, interlaced);
-	cRpiDisplay::SetVideoFormat(width, height, frameRate, interlaced);
+	cRpiDisplay::SetVideoFormat(m_omx->GetVideoFrameFormat());
 }
 
 void cOmxDevice::FlushStreams(bool flushVideoRender)
diff --git a/omxdevice.h b/omxdevice.h
index e57137c..ed69639 100644
--- a/omxdevice.h
+++ b/omxdevice.h
@@ -20,7 +20,7 @@ class cOmxDevice : cDevice
 
 public:
 
-	cOmxDevice(void (*onPrimaryDevice)(void));
+	cOmxDevice(void (*onPrimaryDevice)(void), int layer);
 	virtual ~cOmxDevice();
 
 	virtual int Init(void);
@@ -177,10 +177,12 @@ private:
 	int		m_playDirection;
 	int		m_trickRequest;
 
-	uint64_t	m_audioPts;
-	uint64_t	m_videoPts;
+	int64_t	m_audioPts;
+	int64_t	m_videoPts;
 
-	int64_t 	m_lastStc;
+	int64_t	m_lastStc;
+
+	int m_layer;
 };
 
 #endif
diff --git a/ovgosd.c b/ovgosd.c
index c9963e5..7d94a06 100644
--- a/ovgosd.c
+++ b/ovgosd.c
@@ -932,8 +932,9 @@ public:
 			}
 
 			m_savedRegion->rect.Set(m_x, m_y, m_w, m_h);
-			vgGetPixels(m_savedRegion->image, 0, 0,
-					m_x, m_target->height - m_h - m_y - 1, m_w, m_h);
+			vgGetPixels(m_savedRegion->image, 0, 0, m_savedRegion->rect.X(),
+					m_target->height - m_savedRegion->rect.Bottom() - 1,
+					m_savedRegion->rect.Width(), m_savedRegion->rect.Height());
 		}
 		return true;
 	}
@@ -1577,14 +1578,8 @@ public:
 
 	virtual bool Execute(cEgl *egl)
 	{
-		int w = min((m_x < 0 ? m_w + m_x : m_w), m_target->width);
-		int h = min((m_y < 0 ? m_h + m_y : m_h), m_target->height);
-
-		int x = m_x < 0 ? 0 : m_x;
-		int y = m_y < 0 ? 0 : m_y;
-
-		w = min(w, m_target->width - x);
-		h = min(h, m_target->height - y);
+		int w = min(m_w, vgGeti(VG_MAX_IMAGE_WIDTH));
+		int h = min(m_h, vgGeti(VG_MAX_IMAGE_HEIGHT));
 
 		if (w <= 0 || h <= 0)
 			return true;
@@ -1599,7 +1594,7 @@ public:
 
 		vgLoadIdentity();
 		vgScale(1.0f, -1.0f);
-		vgTranslate(x, y - m_target->height);
+		vgTranslate(m_x, m_y - m_target->height);
 		vgScale(m_scaleX, m_scaleY);
 
 		VGImage image = vgCreateImage(VG_sARGB_8888, w, h,
@@ -1611,11 +1606,9 @@ public:
 			return false;
 		}
 
-		int offsetX = m_x < 0 ? -m_x : 0;
-		int offsetY = m_y < 0 ? -m_y : 0;
+		vgImageSubData(image, m_argb, m_w * sizeof(tColor),
+				VG_sARGB_8888, 0, 0, w, h);
 
-		vgImageSubData(image, m_argb + offsetY * m_w + offsetX,
-				m_w * sizeof(tColor), VG_sARGB_8888, 0, 0, w, h);
 		vgDrawImage(image);
 
 		vgDestroyImage(image);
@@ -1643,8 +1636,8 @@ class cOvgThread : public cThread
 {
 public:
 
-	cOvgThread() :
-		cThread("ovgthread"), m_wait(new cCondWait()), m_stalled(false)
+	cOvgThread(int layer) :	cThread("ovgthread"),
+		m_wait(new cCondWait()), m_stalled(false), m_layer(layer)
 	{
 		for (int i = 0; i < OVG_MAX_OSDIMAGES; i++)
 			m_images[i].used = false;
@@ -1821,7 +1814,7 @@ protected:
 			VC_RECT_T dstRect = { 0, 0, egl.window.width, egl.window.height };
 
 			egl.window.element = vc_dispmanx_element_add(
-					update, display, 2 /*layer*/, &dstRect, 0, &srcRect,
+					update, display, m_layer, &dstRect, 0, &srcRect,
 					DISPMANX_PROTECTION_NONE, 0, 0, (DISPMANX_TRANSFORM_T)0);
 
 			vc_dispmanx_update_submit_sync(update);
@@ -1928,6 +1921,7 @@ private:
 	std::queue<cOvgCmd*> m_commands;
 	cCondWait *m_wait;
 	bool m_stalled;
+	int m_layer;
 
 	tOvgImageRef m_images[OVG_MAX_OSDIMAGES];
 
@@ -1945,11 +1939,13 @@ public:
 		cPixmap(Layer, ViewPort, DrawPort),
 		m_ovg(ovg),
 		m_buffer(buffer),
+		m_savedRegion(new cOvgSavedRegion()),
 		m_dirty(false)
 	{ }
 
 	virtual ~cOvgPixmap()
 	{
+		m_ovg->DoCmd(new cOvgCmdDropRegion(m_savedRegion));
 		m_ovg->DoCmd(new cOvgCmdDestroySurface(m_buffer));
 	}
 
@@ -2212,6 +2208,18 @@ public:
 		Scroll(Dest, Source, true);
 	}
 
+	virtual void SaveRegion(const cRect &Source)
+	{
+		m_ovg->DoCmd(new cOvgCmdSaveRegion(m_buffer, m_savedRegion,
+				Source.X(), Source.Y(), Source.Width(), Source.Height()));
+	}
+
+	virtual void RestoreRegion(void)
+	{
+		m_ovg->DoCmd(new cOvgCmdRestoreRegion(m_buffer, m_savedRegion));
+		SetDirty();
+	}
+
 	virtual void CopyToTarget(cOvgRenderTarget *target, int left, int top)
 	{
 		LOCK_PIXMAPS;
@@ -2252,6 +2260,7 @@ private:
 
 	cOvgThread       *m_ovg;
 	cOvgRenderTarget *m_buffer;
+	cOvgSavedRegion  *m_savedRegion;
 
 	bool m_dirty;
 };
@@ -2265,14 +2274,16 @@ public:
 	cOvgOsd(int Left, int Top, uint Level, cOvgThread *ovg) :
 		cOsd(Left, Top, Level),
 		m_ovg(ovg),
-		m_surface(new cOvgRenderTarget()),
-		m_savedRegion(new cOvgSavedRegion())
-	{ }
+		m_surface(new cOvgRenderTarget())
+	{
+		cTimeMs timer(10000);
+		while (!m_ovg->MaxImageSize().Height() && !timer.TimedOut())
+			cCondWait::SleepMs(100);
+	}
 
 	virtual ~cOvgOsd()
 	{
 		SetActive(false);
-		m_ovg->DoCmd(new cOvgCmdDropRegion(m_savedRegion));
 		m_ovg->DoCmd(new cOvgCmdDestroySurface(m_surface));
 	}
 
@@ -2380,20 +2391,20 @@ public:
 
 	virtual void SaveRegion(int x1, int y1, int x2, int y2)
 	{
-		if (!Active())
+		if (!Active() || !m_pixmaps[0])
 			return;
 
-		m_ovg->DoCmd(new cOvgCmdSaveRegion(m_surface, m_savedRegion,
-				x1 + Left(), y1 + Top(), x2 - x1 + 1, y2 - y1 + 1));
+		m_pixmaps[0]->SaveRegion(
+				cRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1).Shifted(
+					- m_pixmaps[0]->ViewPort().Point()));
 	}
 
 	virtual void RestoreRegion(void)
 	{
-		if (!Active())
+		if (!Active() || !m_pixmaps[0])
 			return;
 
-		m_ovg->DoCmd(new cOvgCmdRestoreRegion(m_surface, m_savedRegion));
-		m_ovg->DoCmd(new cOvgCmdFlush(m_surface), true);
+		m_pixmaps[0]->RestoreRegion();
 	}
 
 	virtual void DrawPixel(int x, int y, tColor Color)
@@ -2556,7 +2567,6 @@ private:
 	cOvgThread           *m_ovg;
 	cOvgRenderTarget     *m_surface;
 	cVector<cOvgPixmap *> m_pixmaps;
-	cOvgSavedRegion      *m_savedRegion;
 };
 
 /* ------------------------------------------------------------------------- */
@@ -2684,12 +2694,12 @@ private:
 
 cRpiOsdProvider* cRpiOsdProvider::s_instance = 0;
 
-cRpiOsdProvider::cRpiOsdProvider() :
+cRpiOsdProvider::cRpiOsdProvider(int layer) :
 	cOsdProvider(),
 	m_ovg(0)
 {
 	DLOG("new cOsdProvider()");
-	m_ovg = new cOvgThread();
+	m_ovg = new cOvgThread(layer);
 	s_instance = this;
 }
 
diff --git a/ovgosd.h b/ovgosd.h
index a8d309d..9803c4a 100644
--- a/ovgosd.h
+++ b/ovgosd.h
@@ -16,7 +16,7 @@ class cRpiOsdProvider : public cOsdProvider
 
 public:
 
-	cRpiOsdProvider();
+	cRpiOsdProvider(int layer);
 	~cRpiOsdProvider();
 
 	static void ResetOsd(bool cleanup = false);
diff --git a/po/de_DE.po b/po/de_DE.po
index bb2c49d..3c37270 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -1,21 +1,22 @@
 # German translations for vdr-rpihddevice package.
 # Copyright (C) 2013 THE vdr-rpihddevice'S COPYRIGHT HOLDER
 # This file is distributed under the same license as the vdr-rpihddevice package.
-#  <thomas at reufer.ch>, 2013.
+# Thomas Reufer <thomas at reufer.ch>, 2013-2015.
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: vdr-rpihddevice 0.0.4\n"
+"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: 2013-10-14 13:36+0200\n"
-"Last-Translator:  <thomas at reufer.ch>\n"
-"Language-Team: German <translation-team-de at lists.sourceforge.net>\n"
+"PO-Revision-Date: 2015-10-12 09:33+0100\n"
+"Last-Translator: Thomas Reufer <thomas at reufer.ch>\n"
+"Language-Team: German\n"
 "Language: de\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 1.5.5\n"
 
 msgid "video format not supported!"
 msgstr "Videoformat nicht unterstützt!"
diff --git a/po/fi_FI.po b/po/fi_FI.po
index 834946d..2b2258f 100644
--- a/po/fi_FI.po
+++ b/po/fi_FI.po
@@ -1,7 +1,7 @@
 # Finnish translations for vdr-rpihddevice package.
 # Copyright (C) 2014 THE vdr-rpihddevice'S COPYRIGHT HOLDER
 # This file is distributed under the same license as the vdr-rpihddevice package.
-# Rolf Ahrenberg, 2014
+# Rolf Ahrenberg, 2014-2015
 #
 msgid ""
 msgstr ""
@@ -29,13 +29,13 @@ msgid "HDMI"
 msgstr "HDMI"
 
 msgid "pass through"
-msgstr ""
+msgstr "läpivienti"
 
 msgid "multi channel PCM"
-msgstr ""
+msgstr "monikanava PCM"
 
 msgid "stereo PCM"
-msgstr ""
+msgstr "stereo PCM"
 
 msgid "box"
 msgstr "kehystys"
@@ -65,13 +65,7 @@ msgid "Audio Port"
 msgstr "Äänilähtö"
 
 msgid "Digital Audio Format"
-msgstr ""
+msgstr "Digitaaliäänen formaatti"
 
 msgid "Use GPU accelerated OSD"
 msgstr "Käytä GPU-kiihdytettyä OSD:tä"
-
-#~ msgid "Digital Audio Pass-Through"
-#~ msgstr "Digitaaliäänen läpivienti"
-
-#~ msgid "Ignore Audio EDID"
-#~ msgstr "Jätä äänen EDID huomioimatta"
diff --git a/po/fr_FR.po b/po/fr_FR.po
new file mode 100644
index 0000000..dfb92b9
--- /dev/null
+++ b/po/fr_FR.po
@@ -0,0 +1,72 @@
+# French translations for vdr-rpihddevice package.
+# Copyright (C) 2015 THE vdr-rpihddevice'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the vdr-rpihddevice package.
+# Cyril Jaquier, 2015
+#
+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"
+"PO-Revision-Date: 2015-10-15 06:56+0100\n"
+"Last-Translator: Cyril Jaquier <cyril.jaquier at jaqpot.net>\n"
+"Language-Team: French\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.5.5\n"
+
+msgid "video format not supported!"
+msgstr "Format vidéo non supporté !"
+
+msgid "HD output device for Raspberry Pi"
+msgstr "Périphérique de sortie HD pour Raspberry Pi"
+
+msgid "analog"
+msgstr "analogue"
+
+msgid "HDMI"
+msgstr "HDMI"
+
+msgid "pass through"
+msgstr "pass through"
+
+msgid "multi channel PCM"
+msgstr "PCM multicanal"
+
+msgid "stereo PCM"
+msgstr "PCM stéréo"
+
+msgid "box"
+msgstr "box"
+
+msgid "crop"
+msgstr "rogner"
+
+msgid "stretch"
+msgstr "étirer"
+
+msgid "default"
+msgstr "par défaut"
+
+msgid "follow video"
+msgstr "comme l'original"
+
+msgid "Resolution"
+msgstr "Résolution"
+
+msgid "Frame Rate"
+msgstr "Cadence d'images"
+
+msgid "Video Framing"
+msgstr "Aspect de l'image"
+
+msgid "Audio Port"
+msgstr "Sortie audio"
+
+msgid "Digital Audio Format"
+msgstr "Format audio digital"
+
+msgid "Use GPU accelerated OSD"
+msgstr "OSD accéléré par GPU"
diff --git a/po/hu_HU.po b/po/hu_HU.po
index d40c9ee..7206b02 100644
--- a/po/hu_HU.po
+++ b/po/hu_HU.po
@@ -1,15 +1,16 @@
-# Copyright (C) 2013 THE vdr-rpihddevice'S COPYRIGHT HOLDER
+# Italian translations for vdr-rpihddevice package.
+# Copyright (C) 2015 THE vdr-rpihddevice'S COPYRIGHT HOLDER
 # This file is distributed under the same license as the vdr-rpihddevice package.
-#  <thomas at reufer.ch>, 2013.
+# Füley István, 2015
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: vdr-rpihddevice 0.0.4\n"
+"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: 2014-12-03 12:18+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: \n"
+"Language-Team: Hungarian\n"
 "Language: hu\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -30,13 +31,13 @@ msgid "HDMI"
 msgstr "HDMI"
 
 msgid "pass through"
-msgstr ""
+msgstr "pass through"
 
 msgid "multi channel PCM"
-msgstr ""
+msgstr "többcsatornás PCM"
 
 msgid "stereo PCM"
-msgstr ""
+msgstr "sztereó PCM"
 
 msgid "box"
 msgstr "keretben"
@@ -66,13 +67,7 @@ msgid "Audio Port"
 msgstr "Hang kimenet"
 
 msgid "Digital Audio Format"
-msgstr ""
+msgstr "Digitális hang formátum"
 
 msgid "Use GPU accelerated OSD"
 msgstr "Hardveresen (GPU) gyorsított OSD"
-
-#~ msgid "Digital Audio Pass-Through"
-#~ msgstr "Digitális hang átjátszás"
-
-#~ msgid "Ignore Audio EDID"
-#~ msgstr "Audio EDID figyelmen kivül hagyása"
diff --git a/po/it_IT.po b/po/it_IT.po
new file mode 100644
index 0000000..c21fd2e
--- /dev/null
+++ b/po/it_IT.po
@@ -0,0 +1,72 @@
+# Italian translations for vdr-rpihddevice package.
+# Copyright (C) 2015 THE vdr-rpihddevice'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the vdr-rpihddevice package.
+# Gerlando Falauto, 2015
+#
+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"
+"PO-Revision-Date: 2015-10-15 07:01+0100\n"
+"Last-Translator: Gerlando Falauto <gerlando.falauto at gmail.com>\n"
+"Language-Team: Italian\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.5.5\n"
+
+msgid "video format not supported!"
+msgstr "Formato video non supportato!"
+
+msgid "HD output device for Raspberry Pi"
+msgstr "Dispositivo di uscita HD per Raspberry Pi"
+
+msgid "analog"
+msgstr "analogica"
+
+msgid "HDMI"
+msgstr "HDMI"
+
+msgid "pass through"
+msgstr "pass through"
+
+msgid "multi channel PCM"
+msgstr "PCM multicanale"
+
+msgid "stereo PCM"
+msgstr "PCM stereo"
+
+msgid "box"
+msgstr "bande nere"
+
+msgid "crop"
+msgstr "ritagliato"
+
+msgid "stretch"
+msgstr "stirato"
+
+msgid "default"
+msgstr "default"
+
+msgid "follow video"
+msgstr "come nel video"
+
+msgid "Resolution"
+msgstr "Risoluzione"
+
+msgid "Frame Rate"
+msgstr "Frequenza fotogrammi"
+
+msgid "Video Framing"
+msgstr "Rapporto d'aspetto"
+
+msgid "Audio Port"
+msgstr "Uscita audio"
+
+msgid "Digital Audio Format"
+msgstr "Formato audio digitale"
+
+msgid "Use GPU accelerated OSD"
+msgstr "Usa accelerazione GPU per OSD"
diff --git a/rpihddevice.c b/rpihddevice.c
index aef1a48..b738d0a 100644
--- a/rpihddevice.c
+++ b/rpihddevice.c
@@ -13,7 +13,7 @@
 #include "display.h"
 #include "tools.h"
 
-static const char *VERSION        = "0.1.0";
+static const char *VERSION        = "1.0.0";
 static const char *DESCRIPTION    = trNOOP("HD output device for Raspberry Pi");
 
 class cPluginRpiHdDevice : public cPlugin
@@ -25,7 +25,7 @@ private:
 	static void OnPrimaryDevice(void)
 	{
 		if (cRpiSetup::HasOsd())
-			new cRpiOsdProvider();
+			new cRpiOsdProvider(cRpiSetup::OsdLayer());
 	}
 
 public:
@@ -65,7 +65,7 @@ bool cPluginRpiHdDevice::Initialize(void)
 	if (!cRpiSetup::IsVideoCodecSupported(cVideoCodec::eMPEG2))
 		DLOG("MPEG2 video decoder not enabled!");
 
-	m_device = new cOmxDevice(&OnPrimaryDevice);
+	m_device = new cOmxDevice(&OnPrimaryDevice, cRpiSetup::VideoLayer());
 
 	if (m_device)
 		return !m_device->Init();
diff --git a/setup.c b/setup.c
index 8bc1d74..7d4296c 100644
--- a/setup.c
+++ b/setup.c
@@ -332,24 +332,38 @@ void cRpiSetup::Set(AudioParameters audio, VideoParameters video,
 bool cRpiSetup::ProcessArgs(int argc, char *argv[])
 {
 	static struct option long_options[] = {
-			{ "disable-osd", no_argument, NULL, 'd' },
+			{ "disable-osd", no_argument,       NULL, 'd' },
+			{ "video-layer", required_argument, NULL, 'v' },
+			{ "osd-layer",   required_argument, NULL, 'o' },
 	};
 	int c;
-	while ((c = getopt_long(argc, argv, "d", long_options, NULL)) != -1)
+	while ((c = getopt_long(argc, argv, "do:v:", long_options, NULL)) != -1)
 	{
 		switch (c)
 		{
 		case 'd':
 			m_plugin.hasOsd = false;
 			break;
+		case 'o':
+			m_plugin.osdLayer = atoi(optarg);
+			break;
+		case 'v':
+			m_plugin.videoLayer = atoi(optarg);
+			break;
 		default:
 			return false;
 		}
 	}
+	DBG("dispmanx layers: video=%d, osd=%d (%s)",
+			m_plugin.videoLayer, m_plugin.osdLayer,
+			m_plugin.hasOsd ? "enabled" : "disabled");
+
 	return true;
 }
 
 const char *cRpiSetup::CommandLineHelp(void)
 {
-	return "  -d,       --disable-osd  disable OSD\n";
+	return	"  -d,       --disable-osd  disable OSD\n"
+			"  -v,       --video-layer  dispmanx layer for video (default 0)\n"
+			"  -o,       --osd-layer    dispmanx layer for OSD (default 2)\n";
 }
diff --git a/setup.h b/setup.h
index 72f8195..33585f6 100644
--- a/setup.h
+++ b/setup.h
@@ -61,9 +61,11 @@ public:
 	struct PluginParameters
 	{
 		PluginParameters() :
-			hasOsd(true) { }
+			hasOsd(true), videoLayer(0), osdLayer(2) { }
 
 		bool hasOsd;
+		int videoLayer;
+		int osdLayer;
 	};
 
 	static bool HwInit(void);
@@ -121,6 +123,14 @@ public:
 		return GetInstance()->m_plugin.hasOsd;
 	}
 
+	static int VideoLayer(void) {
+		return GetInstance()->m_plugin.videoLayer;
+	}
+
+	static int OsdLayer(void) {
+		return GetInstance()->m_plugin.osdLayer;
+	}
+
 	static void SetHDMIChannelMapping(bool passthrough, int channels);
 
 	static cRpiSetup* GetInstance(void);
diff --git a/tools.h b/tools.h
index 2589e56..f218a99 100644
--- a/tools.h
+++ b/tools.h
@@ -175,4 +175,42 @@ public:
 	}
 };
 
+class cScanMode
+{
+public:
+
+	enum eMode {
+		eProgressive,
+		eTopFieldFirst,
+		eBottomFieldFirst
+	};
+
+	static const char* Str(eMode mode) {
+		return 	(mode == eProgressive)      ? "progressive"      :
+				(mode == eTopFieldFirst)    ? "interlaced (tff)" :
+				(mode == eBottomFieldFirst) ? "interlaced (bff)" : "unknown";
+	}
+
+	static const bool Interlaced(eMode mode) {
+		return mode != eProgressive;
+	}
+};
+
+class cVideoFrameFormat
+{
+public:
+
+	cVideoFrameFormat() : width(0), height(0), frameRate(0),
+		scanMode(cScanMode::eProgressive) { };
+
+	int width;
+	int height;
+	int frameRate;
+	cScanMode::eMode scanMode;
+
+	bool Interlaced(void) const {
+		return cScanMode::Interlaced(scanMode);
+	}
+};
+
 #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