From 2fc9232451ee51c2a8ec70e2fee1ff23a3ca974f Mon Sep 17 00:00:00 2001
From: Marten Richter <marten.richter@freenet.de>
Date: Sun, 9 Sep 2012 22:41:46 +0200
Subject: [PATCH] Add deinterlacing for SD + enhance performance of consuming
 media packets

---
 boxx.cc     |   8 +-
 video.h     |   3 +
 videoomx.cc | 576 ++++++++++++++++++++++++++++++++++++++++++++++------
 videoomx.h  |  19 +-
 videowin.h  |   1 +
 5 files changed, 535 insertions(+), 72 deletions(-)

diff --git a/boxx.cc b/boxx.cc
index 1e31c13..e10d2ad 100644
--- a/boxx.cc
+++ b/boxx.cc
@@ -144,15 +144,15 @@ void Boxx::blt(Region& r)
   destination x on screen
   destination y on screen
   */
-	  Log::getInstance()->log("Boxx", Log::DEBUG, "blt mark 1");
+
   if (parent) abort(); // if (parent) then this is a child boxx. It can not blt.
-  Log::getInstance()->log("Boxx", Log::DEBUG, "blt mark 2");
+
   // this shouldn't be here
   r.x -= area.x;
   r.y -= area.y;
-  Log::getInstance()->log("Boxx", Log::DEBUG, "blt mark 3");
+
   surface->updateToScreen(r.x, r.y, r.w, r.h, area.x + r.x, area.y + r.y);
-  Log::getInstance()->log("Boxx", Log::DEBUG, "blt mark 4");
+
 }
 
 int Boxx::getScreenX()
diff --git a/video.h b/video.h
index e09d017..2980d2c 100644
--- a/video.h
+++ b/video.h
@@ -45,6 +45,7 @@ class Video: public DrainTarget, public AbstractOption
     virtual int init(UCHAR format)=0;
     virtual int shutdown()=0;
     virtual int setFormat(UCHAR format)=0;
+    virtual UCHAR getSupportedFormats() { return COMPOSITERGB | SVIDEO;}; // if it returns zero there are no different formats
     virtual int setConnection(UCHAR connection)=0;
     virtual int setAspectRatio(UCHAR aspectRatio)=0;   // This one does the pin 8 scart widescreen switching
     virtual int setMode(UCHAR mode)=0;
@@ -112,6 +113,8 @@ class Video: public DrainTarget, public AbstractOption
     // Video connections - AV_SET_VID_OUTPUT
     const static UCHAR COMPOSITERGB = 1;
     const static UCHAR SVIDEO = 2;
+    const static UCHAR HDMI = 4;
+    const static UCHAR HDMI3D = 16; //For future use
 
     // Video aspect ratios - AV_SET_VID_RATIO
     const static UCHAR ASPECT4X3 = 0;
diff --git a/videoomx.cc b/videoomx.cc
index 56e35e3..7bda5c7 100644
--- a/videoomx.cc
+++ b/videoomx.cc
@@ -23,6 +23,8 @@
 #include "mtdraspberry.h"
 #include "demuxer.h"
 #include "osdopengl.h"
+#include "vdr.h"
+#include "woptionpane.h"
 
 // temp
 #include "log.h"
@@ -50,6 +52,7 @@ VideoOMX::VideoOMX() {
 
 	mode=NORMAL;
 	xpos=ypos=0.f;
+	deinterlace=2; //advanced
 
 }
 
@@ -144,7 +147,7 @@ OMX_ERRORTYPE VideoOMX::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN O
 
 void VideoOMX::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){
 	input_bufs_omx_mutex.Lock();
-//	Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d %d %d",input_bufs_omx_free.size(),input_bufs_omx_present.size(),input_bufs_omx_all.size());
+	//Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d %d %d",input_bufs_omx_free.size(),input_bufs_omx_present.size(),input_bufs_omx_all.size());
 	input_bufs_omx_free.push_back(buffer);
 	//Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size());
 	input_bufs_omx_mutex.Unlock();
@@ -168,6 +171,100 @@ int VideoOMX::shutdown()
 }
 
 
+
+bool VideoOMX::loadOptionsfromServer(VDR* vdr)
+{
+	Log::getInstance()->log("Video", Log::DEBUG, "VideoOMX config load");
+    char *name=vdr->configLoad("VideoOMX","SDDeinterlacing");
+
+    if (name != NULL) {
+		if (STRCASECMP(name, "None") == 0) {
+			deinterlace = 0;
+		}/* else if (STRCASECMP(name, "LineDouble") == 0) {
+			deinterlace = 1;
+		}*/ else if (STRCASECMP(name, "Advanced") == 0) {
+			deinterlace = 2;
+		} /*else if (STRCASECMP(name, "Crazy") == 0) {
+			deinterlace = 3; // this does not activate deinterlacing but a image filter, just for fun
+		}*/
+		Log::getInstance()->log("Video", Log::DEBUG, "Set deinterlacing to %s %d",name,deinterlace);
+	}
+
+   return true;
+
+}
+
+bool VideoOMX::handleOptionChanges(Option* option)
+{
+    if (Video::handleOptionChanges(option))
+		return true;
+	switch (option->id) {
+	case 1: {
+		if (STRCASECMP(option->options[option->userSetChoice], "None") == 0) {
+			deinterlace = 0;
+		} /*else if (STRCASECMP(option->options[option->userSetChoice], "LineDouble")
+				== 0) {
+			deinterlace = 1;
+		}*/ else if (STRCASECMP(option->options[option->userSetChoice], "Advanced")
+				== 0) {
+			deinterlace = 2;
+		} /*else if (STRCASECMP(option->options[option->userSetChoice], "Crazy")
+				== 0) {
+			deinterlace = 3;
+		}*/
+		Log::getInstance()->log("Video", Log::DEBUG, "Set deinterlacing to %s %d",option->options[option->userSetChoice],deinterlace);
+		return true;
+	}
+	break;
+	};
+	return false;
+
+}
+
+bool VideoOMX::saveOptionstoServer()
+{
+
+    switch (deinterlace) {
+	case 0:
+		VDR::getInstance()->configSave("VideoOMX","SDDeinterlacing", "None");
+		break;
+	/*case 1:
+		VDR::getInstance()->configSave("VideoOMX","SDDeinterlacing", "LineDouble");
+		break;*/
+	case 2:
+		VDR::getInstance()->configSave("VideoOMX","SDDeinterlacing", "Advanced");
+		break;
+	/*case 3:
+		VDR::getInstance()->configSave("VideoOMX","SDDeinterlacing", "Crazy");
+		break;*/
+	};
+
+    return true;
+}
+
+/*Option(UINT id, const char* displayText, const char* configSection, const char* configKey, UINT optionType,
+           UINT numChoices, UINT defaultChoice, UINT startInt,
+           const char * const * options, const char * const * optionkeys = NULL, AbstractOption* handler=NULL);*/
+
+bool VideoOMX::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
+{
+    if (!Video::addOptionsToPanes(panenumber,options,pane)) return false;
+
+
+    Option* option;
+    if (panenumber == 2)
+    {
+    	static const char* deinterlaceopts[]={"None",/*"LineDouble",*/"Advanced"/*,"Crazy"*/};
+    	option = new Option(1,tr("SD Deinterlacing"), "VideoOMX","SDDeinterlacing",Option::TYPE_TEXT,/*4,2*/2,1,0,deinterlaceopts,NULL,false,this);
+    	options->push_back(option);
+    	pane->addOptionLine(option);
+    }
+
+    return true;
+}
+
+
+
 int VideoOMX::setTVsize(UCHAR ttvsize)
 {
 /*  tvsize = ttvsize;
@@ -623,14 +720,26 @@ int VideoOMX::AllocateCodecsOMX()
 	OMX_ERRORTYPE error;
 	static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
 
+	Demuxer* demux=Demuxer::getInstance();
+
+	dodeint=false;
+
 	Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX");
 	//Clock, move later to audio including events
 
-	Log::getInstance()->log("Video", Log::DEBUG, "Nmark1 ");
+	if (deinterlace!=0 && demux->getHorizontalSize()<=720) { //only deinterlace SD material
+		dodeint=true;
+		deint_first_frame=true;
+
+		Log::getInstance()->log("Video", Log::NOTICE, "Deinterlacing activated %d",deinterlace);
+
+	}
+
+
 	if (!getClockVideoandInit()){
 		return 0;// get the clock and init it if necessary
 	}
-	Log::getInstance()->log("Video", Log::DEBUG, "Nmark2 ");
+
 
 	if (!idleClock()) {
 		Log::getInstance()->log("Video", Log::DEBUG, "idleClock failed");
@@ -692,6 +801,41 @@ int VideoOMX::AllocateCodecsOMX()
 		return 0;
 	}
 
+	if (dodeint) {
+		error = OMX_GetHandle(&omx_vid_deint, VPE_OMX_VIDEO_DEINTERLACE, NULL,
+				&callbacks);
+		if (error != OMX_ErrorNone) {
+			Log::getInstance()->log("Video", Log::DEBUG,
+					"Init OMX video deinterlacer failed %x", error);
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
+
+		error = OMX_GetParameter(omx_vid_deint, OMX_IndexParamImageInit,
+				&p_param);
+		if (error != OMX_ErrorNone) {
+			Log::getInstance()->log("Video", Log::DEBUG,
+					"Init OMX video deinterlacer OMX_GetParameter failed %x",
+					error);
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
+		omx_deint_input_port = p_param.nStartPortNumber;
+		omx_deint_output_port = p_param.nStartPortNumber + 1;
+
+		if (!DisablePort(omx_vid_deint, omx_deint_input_port, true)
+				|| !DisablePort(omx_vid_deint, omx_deint_output_port, true)) {
+			Log::getInstance()->log("Video", Log::DEBUG,
+					"Disable Ports OMX video deint failed");
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
+
+	}
+
 
 	error=OMX_GetHandle(&omx_vid_sched,VPE_OMX_VIDEO_SCHED,NULL,&callbacks);
 	if (error!=OMX_ErrorNone){
@@ -832,7 +976,7 @@ int VideoOMX::AllocateCodecsOMX()
 		ft_type.eCompressionFormat=OMX_VIDEO_CodingMPEG2;
 	}
 
-	Demuxer* demux=Demuxer::getInstance();
+
 
     ft_type.xFramerate=0;//25*(1<<16);//demux->getFrameRate()*(1<<16);
     Log::getInstance()->log("Video", Log::DEBUG, "Framerate: %d",demux->getFrameRate());
@@ -859,29 +1003,113 @@ int VideoOMX::AllocateCodecsOMX()
 		return 0;
 	}
 
+	if (!dodeint) {
+		error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,omx_vid_sched,omx_shed_input_port);
+		if (error!=OMX_ErrorNone){
+			Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel dec to sched failed %x", error);
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
 
-	error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,omx_vid_sched,omx_shed_input_port);
-	if (error!=OMX_ErrorNone){
-		Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel dec to sched failed %x", error);
-		clock_mutex.Unlock();
-		DeAllocateCodecsOMX();
-		return 0;
-	}
 
 
+		if (!EnablePort(omx_vid_dec,omx_codec_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_input_port,false)
+		) {
+			Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX codec shed failed");
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
 
-	if (!EnablePort(omx_vid_dec,omx_codec_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_input_port,false)
-						) {
-		Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX codec shed failed");
-		clock_mutex.Unlock();
-		DeAllocateCodecsOMX();
-		return 0;
-	}
+		if ( !CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_output_port) || !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_input_port)) {
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
+
+	} else {
+
+		error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,omx_vid_deint,omx_deint_input_port);
+		if (error!=OMX_ErrorNone){
+			Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel dec to deint failed %x", error);
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
+
+
+
+		if (!EnablePort(omx_vid_dec,omx_codec_output_port,false) || !EnablePort(omx_vid_deint,omx_deint_input_port,false)
+		) {
+			Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX codec deint failed");
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
+
+		if ( !CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_output_port) || !CommandFinished(omx_vid_deint,OMX_CommandPortEnable,omx_deint_input_port)) {
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
+
+		if (!ChangeComponentState(omx_vid_deint,OMX_StateIdle)) {
+			Log::getInstance()->log("Video", Log::DEBUG, "vid_deint ChangeComponentState");
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
+
+		OMX_CONFIG_IMAGEFILTERPARAMSTYPE imagefilter;
+		memset(&imagefilter,0,sizeof(imagefilter));
+		imagefilter.nSize=sizeof(imagefilter);
+		imagefilter.nVersion.nVersion=OMX_VERSION;
+
+		imagefilter.nPortIndex=omx_deint_output_port;
+		imagefilter.nNumParams=1;
+		imagefilter.nParams[0]=3;//???
+		switch (deinterlace) {
+		case 1:
+			imagefilter.eImageFilter=OMX_ImageFilterDeInterlaceLineDouble; break;
+		case 2:
+			imagefilter.eImageFilter=OMX_ImageFilterDeInterlaceAdvanced; break;
+		case 3:
+			imagefilter.eImageFilter=OMX_ImageFilterFilm; break;
+		}
+
+
+		error=OMX_SetConfig(omx_vid_deint,OMX_IndexConfigCommonImageFilterParameters,&imagefilter);
+		if (error!=OMX_ErrorNone){
+			Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigCommonImageFilterParameters failed %x", error);
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
+
+
+		error=OMX_SetupTunnel(omx_vid_deint,omx_deint_output_port,omx_vid_sched,omx_shed_input_port);
+		if (error!=OMX_ErrorNone){
+			Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel deint to sched failed %x", error);
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
+
+		if (!EnablePort(omx_vid_deint,omx_deint_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_input_port,false)
+		) {
+			Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX deint shed failed");
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
+
+		if ( !CommandFinished(omx_vid_deint,OMX_CommandPortEnable,omx_deint_output_port) || !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_input_port)) {
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
 
-	if ( !CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_output_port) || !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_input_port)) {
-		clock_mutex.Unlock();
-		DeAllocateCodecsOMX();
-		return 0;
 	}
 
 	if (!ChangeComponentState(omx_vid_dec,OMX_StateExecuting)) {
@@ -921,6 +1149,16 @@ int VideoOMX::AllocateCodecsOMX()
 		return 0;
 	}
 
+	if (dodeint) {
+		if (!ChangeComponentState(omx_vid_deint,OMX_StateExecuting)) {
+			Log::getInstance()->log("Video", Log::DEBUG, "vid_vid_deint ChangeComponentState");
+			clock_mutex.Unlock();
+			DeAllocateCodecsOMX();
+			return 0;
+		}
+		DisablePort(omx_vid_deint,omx_deint_output_port,false);
+		DisablePort(omx_vid_deint,omx_deint_input_port,false);
+	}
 
 	if (!ChangeComponentState(omx_vid_sched,OMX_StateExecuting)) {
 		Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_sched ChangeComponentState Execute");
@@ -1100,7 +1338,41 @@ int VideoOMX::DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait) //needs
 	return 1;
 }
 
+int VideoOMX::WaitForEvent(OMX_HANDLETYPE handle,OMX_U32 event) //needs to be called with locked mutex
+{
+	int i=0;
+	while (i<1000) {
+		omx_event_mutex.Lock();
+		list<VPE_OMX_EVENT>::iterator itty=omx_events.begin();
+		while (itty!=omx_events.end()) {
+
+			VPE_OMX_EVENT current=*itty;
+			if (current.handle==handle) { //this is ours
+				if (current.event_type==OMX_EventError) {
+					omx_events.erase(itty);
+					omx_event_mutex.Unlock();
+					Log::getInstance()->log("Video", Log::DEBUG, "WaitForEvent Finished on Error");
+					return 0;
 
+				} else if (current.event_type==event) {
+					omx_events.erase(itty);
+					omx_event_mutex.Unlock();
+					Log::getInstance()->log("Video", Log::DEBUG, "WaitForEvent Finished Completed");
+					return 1;
+				}
+			}
+			itty++;
+
+		}
+		omx_event_mutex.Unlock();
+		MILLISLEEP(2);
+		i++;
+
+	}
+	Log::getInstance()->log("Video", Log::DEBUG, "WaitForEvent waited too long %x %x",handle,event);
+	return 0;
+
+}
 
 
 int VideoOMX::CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2) //needs to be called with locked mutex
@@ -1234,6 +1506,7 @@ int VideoOMX::DestroyInputBufsOMX() //need s to be called with locked mutex
 	input_bufs_omx_free.clear();
 	input_bufs_omx_present.clear();
 	input_time_present.clear();
+	input_is_last.clear();
 	input_bufs_omx_mutex.Unlock();
 
 }
@@ -1270,6 +1543,14 @@ int VideoOMX::DeAllocateCodecsOMX()
 		idleClock();
 		clock_mutex.Lock();
 
+		if (dodeint) {
+			if (!ChangeComponentState(omx_vid_deint, OMX_StateIdle)) {
+				Log::getInstance()->log("Video", Log::DEBUG,
+						"vid_deint ChangeComponentState");
+
+			}
+		}
+
 
 		if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) {
 			Log::getInstance()->log("Video", Log::DEBUG, "vid_shed ChangeComponentState");
@@ -1286,33 +1567,95 @@ int VideoOMX::DeAllocateCodecsOMX()
         // TODO proper deinit sequence
 		// first flush all buffers
 
+		if (!dodeint) {
 
-		error = OMX_SendCommand(omx_vid_dec, OMX_CommandFlush,
-				omx_codec_output_port, NULL);
-		if (error != OMX_ErrorNone) {
-			Log::getInstance()->log("Video", Log::DEBUG,
-					"OMX_Flush codec out failed %x", error);
+			error = OMX_SendCommand(omx_vid_dec, OMX_CommandFlush,
+					omx_codec_output_port, NULL);
+			if (error != OMX_ErrorNone) {
+				Log::getInstance()->log("Video", Log::DEBUG,
+						"OMX_Flush codec out failed %x", error);
 
-		}
+			}
 
-		error = OMX_SendCommand(omx_vid_sched, OMX_CommandFlush,
-				omx_shed_input_port, NULL);
-		if (error != OMX_ErrorNone) {
-			Log::getInstance()->log("Video", Log::DEBUG,
-					"OMX_Flush shed in failed %x", error);
+			error = OMX_SendCommand(omx_vid_sched, OMX_CommandFlush,
+					omx_shed_input_port, NULL);
+			if (error != OMX_ErrorNone) {
+				Log::getInstance()->log("Video", Log::DEBUG,
+						"OMX_Flush shed in failed %x", error);
+
+			}
+
+			if (!CommandFinished(omx_vid_dec, OMX_CommandFlush,
+					omx_codec_output_port)) {
+				Log::getInstance()->log("Video", Log::DEBUG,
+						"flush cmd codec  failed");
+			}
+
+			if (!CommandFinished(omx_vid_sched, OMX_CommandFlush,
+					omx_shed_input_port)) {
+				Log::getInstance()->log("Video", Log::DEBUG,
+						"flush cmd  shed failed");
+			}
+		} else {
+			error = OMX_SendCommand(omx_vid_dec, OMX_CommandFlush,
+					omx_codec_output_port, NULL);
+			if (error != OMX_ErrorNone) {
+				Log::getInstance()->log("Video", Log::DEBUG,
+						"OMX_Flush codec out failed %x", error);
+
+			}
+
+			error = OMX_SendCommand(omx_vid_deint, OMX_CommandFlush,
+					omx_deint_input_port, NULL);
+			if (error != OMX_ErrorNone) {
+				Log::getInstance()->log("Video", Log::DEBUG,
+						"OMX_Flush deint in failed %x", error);
+
+			}
+
+			if (!CommandFinished(omx_vid_dec, OMX_CommandFlush,
+					omx_codec_output_port)) {
+				Log::getInstance()->log("Video", Log::DEBUG,
+						"flush cmd codec  failed");
+			}
+
+			if (!CommandFinished(omx_vid_deint, OMX_CommandFlush,
+					omx_deint_input_port)) {
+				Log::getInstance()->log("Video", Log::DEBUG,
+						"flush cmd  deint failed");
+			}
+
+			//m
+			error = OMX_SendCommand(omx_vid_deint, OMX_CommandFlush,
+					omx_deint_output_port, NULL);
+			if (error != OMX_ErrorNone) {
+				Log::getInstance()->log("Video", Log::DEBUG,
+						"OMX_Flush deint out failed %x", error);
+
+			}
+
+			error = OMX_SendCommand(omx_vid_sched, OMX_CommandFlush,
+					omx_shed_input_port, NULL);
+			if (error != OMX_ErrorNone) {
+				Log::getInstance()->log("Video", Log::DEBUG,
+						"OMX_Flush shed in failed %x", error);
+
+			}
+
+			if (!CommandFinished(omx_vid_deint, OMX_CommandFlush,
+					omx_deint_output_port)) {
+				Log::getInstance()->log("Video", Log::DEBUG,
+						"flush cmd deint  failed");
+			}
+
+			if (!CommandFinished(omx_vid_sched, OMX_CommandFlush,
+					omx_shed_input_port)) {
+				Log::getInstance()->log("Video", Log::DEBUG,
+						"flush cmd  shed failed");
+			}
 
-		}
 
-		if (!CommandFinished(omx_vid_dec, OMX_CommandFlush,
-				omx_codec_output_port)) {
-			Log::getInstance()->log("Video", Log::DEBUG,
-					"flush cmd codec  failed");
-		}
 
-		if (!CommandFinished(omx_vid_sched, OMX_CommandFlush,
-				omx_shed_input_port)) {
-			Log::getInstance()->log("Video", Log::DEBUG,
-					"flush cmd  shed failed");
 		}
 
 
@@ -1406,6 +1749,17 @@ int VideoOMX::DeAllocateCodecsOMX()
 			Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 7");
 		}
 
+		if (dodeint) {
+			if (!DisablePort(omx_vid_deint,omx_deint_output_port,true)) {
+				Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 6a");
+			}
+
+
+
+			if (!DisablePort(omx_vid_deint,omx_deint_input_port,true)) {
+				Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 7a");
+			}
+		}
 
 
 
@@ -1430,6 +1784,19 @@ int VideoOMX::DeAllocateCodecsOMX()
 
 		}
 
+		if (dodeint) {
+			error=OMX_SetupTunnel(omx_vid_deint,omx_deint_input_port,NULL,NULL);
+			if (error!=OMX_ErrorNone) {
+				Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
+			}
+
+
+			error=OMX_SetupTunnel(omx_vid_deint,omx_deint_output_port,NULL,NULL);
+			if (error!=OMX_ErrorNone) {
+				Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
+			}
+		}
+
 		error=OMX_SetupTunnel(omx_vid_sched,omx_shed_input_port,NULL,NULL);
 		if (error!=OMX_ErrorNone) {
 			Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
@@ -1468,6 +1835,7 @@ int VideoOMX::DeAllocateCodecsOMX()
 		error=OMX_FreeHandle(omx_vid_dec);
 		error=OMX_FreeHandle(omx_vid_sched);
 		error=OMX_FreeHandle(omx_vid_rend);
+		if (dodeint) error=OMX_FreeHandle(omx_vid_deint);
 		omx_vid_dec=NULL;
 		clock_mutex.Unlock();
 		destroyClock();
@@ -1723,7 +2091,7 @@ bool VideoOMX::FrameSkip(long long pts)
 			skip=true; // we are too slow
 			skipping=true;
 		/*	Log::getInstance()->log("Video", Log::DEBUG,
-														"Skipping frames1 %lld %lld",target_time-current_time,pts);
+														"Skipping frames1 %lld %lld %d",target_time-current_time,pts,Demuxer::getInstance()->getFrameRate());
 			Log::getInstance()->log("Video", Log::DEBUG, "skip detail pts: %lld target: %lld sys: %lld off: %lld diff %lld",pts,target_time,current_time,offset,
 						target_time-current_time);*/
 		}  else {
@@ -1733,7 +2101,7 @@ bool VideoOMX::FrameSkip(long long pts)
 		if ((target_time - current_time) < 0000LL) { //skip a bit more
 			skip = true; // we are too slow
 			skipping = true;
-		/*	Log::getInstance()->log("Video", Log::DEBUG,"Skipping frames2 %lld %lld",target_time-current_time,pts);
+		/*	Log::getInstance()->log("Video", Log::DEBUG,"Skipping frames2 %lld %lld %d",target_time-current_time,pts,Demuxer::getInstance()->getFrameRate());
 			Log::getInstance()->log("Video", Log::DEBUG, "skip detail pts: %lld target: %lld sys: %lld off: %lld diff %lld",pts,target_time,current_time,offset,
 									target_time-current_time);*/
 		} else {
@@ -1792,14 +2160,17 @@ void VideoOMX::threadMethod()
 
 		OMX_BUFFERHEADERTYPE* pict=NULL;
 		long long time;
+		bool islast;
 		if (!paused) {
 			input_bufs_omx_mutex.Lock();
 			if (input_bufs_omx_present.size()>0) {
 
 				pict=input_bufs_omx_present.front();
 				time=input_time_present.front();
+				islast=input_is_last.front();
 				input_bufs_omx_present.pop_front();
 				input_time_present.pop_front();
+				input_is_last.pop_front();
 			}
 			input_bufs_omx_mutex.Unlock();
 		}
@@ -1807,7 +2178,7 @@ void VideoOMX::threadMethod()
 		if ( pict) {
 			//Log::getInstance()->log("Video", Log::DEBUG,
 			//											"Got pict");
-			if (time!=0 &&FrameSkip(time) && !(pict->nFlags &OMX_BUFFERFLAG_STARTTIME)) {
+			if (time!=0 && FrameSkip(time) && !(pict->nFlags &OMX_BUFFERFLAG_STARTTIME)) {
 
 				input_bufs_omx_mutex.Lock();
 				input_bufs_omx_free.push_back(pict);
@@ -1819,7 +2190,8 @@ void VideoOMX::threadMethod()
 					Log::getInstance()->log("Video", Log::DEBUG,
 							"OMX_EmptyThisBuffer failed %x", error);
 				}
-				if (time!=0) FrameWaitforDisplay(time);
+				if (deint_first_frame && dodeint) DeinterlaceFix();
+				if (islast) FrameWaitforDisplay(time);
 			}
 		} else {
 			MILLISLEEP(5);
@@ -1831,11 +2203,76 @@ void VideoOMX::threadMethod()
 											"end thread");
 }
 
-void VideoOMX::PutBufferToPres(OMX_BUFFERHEADERTYPE* buffer, long long time)
+void VideoOMX::DeinterlaceFix()
+{
+
+	Demuxer* demux=Demuxer::getInstance();
+	clock_mutex.Lock();
+	OMX_ERRORTYPE error;
+	OMX_PARAM_PORTDEFINITIONTYPE port_def_type;
+	memset(&port_def_type,0,sizeof(port_def_type));
+	port_def_type.nSize=sizeof(port_def_type);
+	port_def_type.nVersion.nVersion=OMX_VERSION;
+	port_def_type.nPortIndex=omx_codec_output_port;
+
+	error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type);
+	if (error != OMX_ErrorNone) {
+		Log::getInstance()->log("Video", Log::DEBUG,
+				"OMX_IndexParamPortDefinition fix failed %x", error);
+		clock_mutex.Unlock();
+		return;
+	}
+
+	if (port_def_type.format.video.nFrameWidth == demux->getHorizontalSize()
+			&& port_def_type.format.video.nFrameHeight == demux->getVerticalSize()){
+		Log::getInstance()->log("Video", Log::DEBUG,
+							"Deinit first frame fix");
+		deint_first_frame=false;
+
+		WaitForEvent(omx_vid_dec,OMX_EventPortSettingsChanged);
+		DisablePort(omx_vid_dec,omx_codec_output_port,false);
+		DisablePort(omx_vid_sched,omx_shed_input_port,false);
+		DisablePort(omx_vid_deint,omx_deint_output_port,false);
+		DisablePort(omx_vid_deint,omx_deint_input_port,false);
+
+		port_def_type.nPortIndex=omx_deint_input_port;
+		error = OMX_SetParameter(omx_vid_deint, OMX_IndexParamPortDefinition,
+				&port_def_type);
+		if (error != OMX_ErrorNone) {
+			Log::getInstance()->log("Video", Log::DEBUG,
+					"Set OMX_IndexParamPortDefinition1 failed %x", error);
+			clock_mutex.Unlock();
+			return;
+		}
+
+		port_def_type.nPortIndex=omx_deint_output_port;
+		error = OMX_SetParameter(omx_vid_deint, OMX_IndexParamPortDefinition,
+				&port_def_type);
+		if (error != OMX_ErrorNone) {
+			Log::getInstance()->log("Video", Log::DEBUG,
+					"Set OMX_IndexParamPortDefinition2 failed %x", error);
+			clock_mutex.Unlock();
+			return;
+		}
+
+
+		EnablePort(omx_vid_dec,omx_codec_output_port,false);
+		EnablePort(omx_vid_deint,omx_deint_input_port,false);
+		EnablePort(omx_vid_deint,omx_deint_output_port,false);
+		EnablePort(omx_vid_sched,omx_shed_input_port,false);
+	}
+	clock_mutex.Unlock();
+
+
+}
+
+
+void VideoOMX::PutBufferToPres(OMX_BUFFERHEADERTYPE* buffer, long long time,bool islast)
 {
 	input_bufs_omx_mutex.Lock();
 	input_bufs_omx_present.push_back(buffer);
 	input_time_present.push_back(time);
+	input_is_last.push_back(islast);
 	input_bufs_omx_mutex.Unlock();
 
 }
@@ -1860,17 +2297,27 @@ OMX_ERRORTYPE VideoOMX::ProtOMXEmptyThisBuffer(OMX_HANDLETYPE handle, OMX_BUFFER
 
 void VideoOMX::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
 {
-  mediapacket = mplist.front();
+  mediapackets.clear();
+  list<MediaPacket>::const_iterator begin=mplist.begin();
+  list<MediaPacket>::const_iterator itty=mplist.begin();
+  advance(itty,min(mplist.size(),50));
+  mediapackets.insert(mediapackets.begin(),begin,itty);//front
 }
 
 UINT VideoOMX::DeliverMediaSample(UCHAR* buffer, UINT *samplepos)
 {
-  DeliverMediaPacket(mediapacket, buffer, samplepos);
-  if (*samplepos == mediapacket.length) {
-    *samplepos = 0;
-    return 1;
-  }
-  else return 0;
+	int consumed=0;
+	while (mediapackets.size()) {
+		MediaPacket mediapacket=mediapackets.front();
+	    DeliverMediaPacket(mediapacket, buffer, samplepos);
+	    if (*samplepos == mediapacket.length) {
+	    	*samplepos = 0;
+	    	mediapackets.pop_front();
+	    	consumed++;
+	    	//return 1;
+	    } else return consumed;
+	}
+	return consumed;
 }
 
 UINT VideoOMX::DeliverMediaPacket(MediaPacket packet,
@@ -1919,7 +2366,7 @@ UINT VideoOMX::DeliverMediaPacket(MediaPacket packet,
 	if (packet.disconti) {
 		firstsynched=false;
 		if (cur_input_buf_omx) {
-			PutBufferToPres(cur_input_buf_omx, lastreftimeOMX);
+			PutBufferToPres(cur_input_buf_omx, lastreftimeOMX,true);
 			cur_input_buf_omx=NULL;
 		}
 	}
@@ -1937,7 +2384,7 @@ UINT VideoOMX::DeliverMediaPacket(MediaPacket packet,
 		if ( packet.synched ) {
 			if (cur_input_buf_omx) {
 				cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_ENDOFFRAME;
-				PutBufferToPres(cur_input_buf_omx, lastreftimeOMX);
+				PutBufferToPres(cur_input_buf_omx, lastreftimeOMX,true);
 				cur_input_buf_omx=NULL;//write out old data
 
 
@@ -1984,7 +2431,7 @@ UINT VideoOMX::DeliverMediaPacket(MediaPacket packet,
 			   cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_TIME_UNKNOWN;
 		   }
 		   lastreftimeOMX=packet.presentation_time;
-		 //  Log::getInstance()->log("Video", Log::DEBUG, "Time code %lld pts %lld", lastreftimeOMX,packet.pts);
+		  // Log::getInstance()->log("Video", Log::DEBUG, "Time code %lld pts %lld", lastreftimeOMX,packet.pts);
 		   lastreftimePTS=packet.pts;
 		   cur_input_buf_omx->nTimeStamp=0;//lastreftimeOMX; // the clock component is faulty;
 		}
@@ -1992,8 +2439,7 @@ UINT VideoOMX::DeliverMediaPacket(MediaPacket packet,
 		{
 			cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
 			cur_input_buf_omx->nTimeStamp=0;
-
-
+			//Log::getInstance()->log("Video", Log::DEBUG, "packet unsynched marker");
 			//  ms->SetSyncPoint(TRUE);
 		}
 		if (packet.disconti) cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_DISCONTINUITY;
@@ -2011,12 +2457,12 @@ UINT VideoOMX::DeliverMediaPacket(MediaPacket packet,
 		*samplepos+=cancopy;
 		// push old buffer out
 
-		PutBufferToPres(cur_input_buf_omx, 0LL);
+		PutBufferToPres(cur_input_buf_omx, lastreftimeOMX,false);
 		// get5 new buffer
 		input_bufs_omx_mutex.Lock();
 		if (input_bufs_omx_free.size()==0) {
 			input_bufs_omx_mutex.Unlock();
-			//Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket no free sample");
+		//	Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket no free sample2");
 			return *samplepos; // we do not have a free media sample
 		}
 		cur_input_buf_omx=input_bufs_omx_free.front();
@@ -2101,7 +2547,7 @@ bool VideoOMX::displayIFrame(const UCHAR* buffer, UINT length) {
 
 					}
 					cur_input_buf_omx->nTimeStamp = 0;
-					PutBufferToPres(cur_input_buf_omx, 0);
+					PutBufferToPres(cur_input_buf_omx, 0,false);
 					cur_input_buf_omx = NULL;
 
 					if (!cur_input_buf_omx) {
@@ -2156,7 +2602,7 @@ bool VideoOMX::displayIFrame(const UCHAR* buffer, UINT length) {
 
 	}
 	cur_input_buf_omx->nTimeStamp = 0;
-	PutBufferToPres(cur_input_buf_omx, 0);
+	PutBufferToPres(cur_input_buf_omx, 0,false);
 	cur_input_buf_omx = NULL;
 
 
@@ -2168,7 +2614,7 @@ int VideoOMX::EnterIframePlayback()
 {
 	clock_mutex.Lock();
 	if (cur_input_buf_omx) {
-		PutBufferToPres(cur_input_buf_omx, lastreftimeOMX);
+		PutBufferToPres(cur_input_buf_omx, lastreftimeOMX,true);
 
 		cur_input_buf_omx = NULL;
 	}
diff --git a/videoomx.h b/videoomx.h
index 260774a..b4f8a42 100644
--- a/videoomx.h
+++ b/videoomx.h
@@ -114,6 +114,11 @@ class VideoOMX : public Video, public Thread_TYPE
 	long long SetStartAudioOffset(long long curreftime, bool *rsync);
 	virtual void ResetTimeOffsets();
 
+	bool loadOptionsfromServer(VDR* vdr);
+	bool saveOptionstoServer();
+	bool addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane);
+	bool handleOptionChanges(Option* option);
+
 
 #ifdef DEV
     int test();
@@ -177,6 +182,7 @@ class VideoOMX : public Video, public Thread_TYPE
 
 	   int ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type);
 	   int CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2);
+	   int WaitForEvent(OMX_HANDLETYPE handle,OMX_U32 event);
 	   int EnablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait);
 	   int DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait=true);
 
@@ -199,13 +205,19 @@ class VideoOMX : public Video, public Thread_TYPE
 
 	   OMX_HANDLETYPE omx_vid_dec;
 	   OMX_HANDLETYPE omx_vid_sched;
+	   OMX_HANDLETYPE omx_vid_deint;
 	   OMX_HANDLETYPE omx_vid_rend;
 	   OMX_HANDLETYPE omx_clock;
 	   int clock_references;
+	   bool dodeint; //deinterlacer was activated in omx filtergraph
+	   bool deint_first_frame; //handle frame change
+	   void DeinterlaceFix();
 
 
 	   OMX_U32 omx_codec_input_port;
 	   OMX_U32 omx_codec_output_port;
+	   OMX_U32 omx_deint_input_port;
+	   OMX_U32 omx_deint_output_port;
 	   OMX_U32 omx_rend_input_port;
 	   OMX_U32 omx_shed_input_port;
 	   OMX_U32 omx_shed_output_port;
@@ -222,10 +234,11 @@ class VideoOMX : public Video, public Thread_TYPE
 	   list<OMX_BUFFERHEADERTYPE*> input_bufs_omx_free;
 	   list<OMX_BUFFERHEADERTYPE*> input_bufs_omx_present;
 	   list<long long> input_time_present;
+	   list<bool> input_is_last;
 	   Mutex input_bufs_omx_mutex;
 	   OMX_BUFFERHEADERTYPE* cur_input_buf_omx;
 
-	   void PutBufferToPres(OMX_BUFFERHEADERTYPE* buffer, long long time);
+	   void PutBufferToPres(OMX_BUFFERHEADERTYPE* buffer, long long time,bool is_last);
 	   void threadMethod();
 	   void threadPostStopCleanup();
 
@@ -239,8 +252,8 @@ class VideoOMX : public Video, public Thread_TYPE
 
 	   bool omx_mpeg2;
 	   bool omx_h264;
-	   UCHAR mode;
 	   float xpos,ypos;
+	   int deinterlace;
 	   void updateMode();//called internally to adjust for different parameters
 
 
@@ -248,7 +261,7 @@ class VideoOMX : public Video, public Thread_TYPE
    bool firstsynched;
 
     
-	MediaPacket mediapacket;
+   MediaPacketList mediapackets;
 };
 
 #endif
diff --git a/videowin.h b/videowin.h
index 48682cf..dc9fa77 100644
--- a/videowin.h
+++ b/videowin.h
@@ -59,6 +59,7 @@ public:
 	int shutdown();
 
 	int setFormat(UCHAR format);
+	virtual UCHAR getSupportedFormats() { return 0;};
 	int setConnection(UCHAR connection);
 	int setAspectRatio(UCHAR aspectRatio);   // This one does the pin 8 scart widescreen switching
 	UCHAR getAspectRatio(){return aspectRatio;};
-- 
2.39.5