From 2fc9232451ee51c2a8ec70e2fee1ff23a3ca974f Mon Sep 17 00:00:00 2001 From: Marten Richter 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::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::const_iterator begin=mplist.begin(); + list::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 input_bufs_omx_free; list input_bufs_omx_present; list input_time_present; + list 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.2