From 8ea0dea4b44b4a94da45e5ff030a341b5874327b Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Mon, 28 May 2012 20:14:30 +0200 Subject: [PATCH] h264 allmost done but still not working --- draintarget.h | 2 +- osdopengl.cc | 2 +- osdopengl.h | 2 + stream.cc | 4 +- videovpeogl.cc | 685 +++++++++++++++++++++++++++++++++++++++++++++---- videovpeogl.h | 30 ++- 6 files changed, 669 insertions(+), 56 deletions(-) mode change 100644 => 100755 stream.cc diff --git a/draintarget.h b/draintarget.h index 26992bd..8457241 100755 --- a/draintarget.h +++ b/draintarget.h @@ -45,7 +45,7 @@ struct MediaPacket bool synched; int index; #ifndef VOMP_PLATTFORM_MVP - long long presentation_time;/* in 100 ns units*/ + long long presentation_time;/* native time of plattform, in 100 ns units(Windows)*/ bool disconti; #endif }; diff --git a/osdopengl.cc b/osdopengl.cc index f368c6a..f4ba7f7 100755 --- a/osdopengl.cc +++ b/osdopengl.cc @@ -164,7 +164,7 @@ int OsdOpenGL::init(void* device) bcm_display=vc_dispmanx_display_open(0); bcm_update=vc_dispmanx_update_start(0); bcm_element=vc_dispmanx_element_add(bcm_update,bcm_display, - 0,&dst_rect, 0, + 2,&dst_rect, 0, &src_rect,DISPMANX_PROTECTION_NONE,0, 0, (DISPMANX_TRANSFORM_T) 0); vc_dispmanx_update_submit_sync(bcm_update); diff --git a/osdopengl.h b/osdopengl.h index 9694c3f..ccdd317 100755 --- a/osdopengl.h +++ b/osdopengl.h @@ -126,6 +126,8 @@ private: GLint osd_sampler_loc; + + /* BCM specific */ uint32_t display_height; diff --git a/stream.cc b/stream.cc old mode 100644 new mode 100755 index eef823a..710b55c --- a/stream.cc +++ b/stream.cc @@ -82,7 +82,7 @@ int Stream::put(const UCHAR* inbuf, int len, UCHAR type,unsigned int index) newPacket.dts=0; newPacket.synched=false; newPacket.index=index; -#if defined(WIN32) || defined(__ANDROID__) +#ifndef VOMP_PLATTFORM_MVP newPacket.disconti=false; newPacket.presentation_time=0; #endif @@ -104,7 +104,7 @@ int Stream::put(const UCHAR* inbuf, int len, UCHAR type,unsigned int index) ( (ULLONG)(inbuf[18] & 0xFE) >> 1 ); hasdts=true; } -#if defined(WIN32) || defined(__ANDROID__) +#ifndef VOMP_PLATTFORM_MVP //ok we have the pts now convert it to a continously time code in 100ns units if (hasdts && draintarget->dtsTimefix()) newPacket.presentation_time=(ULLONG)(newPacket.dts*10000LL/90LL); else newPacket.presentation_time=(ULLONG)(newPacket.pts*10000LL/90LL); diff --git a/videovpeogl.cc b/videovpeogl.cc index 6c7bed4..508d457 100755 --- a/videovpeogl.cc +++ b/videovpeogl.cc @@ -38,6 +38,7 @@ VideoVPEOGL::VideoVPEOGL() omx_vid_dec=0; cur_input_buf_omx=NULL; + omx_h264=omx_mpeg2=true; } @@ -114,6 +115,17 @@ OMX_ERRORTYPE VideoVPEOGL::EventHandler_OMX(OMX_IN OMX_HANDLETYPE handle,OMX_IN Log::getInstance()->log("Video", Log::NOTICE, "eventHandler %x %x %x %x %x",handle,event_type,data1,data2,event_data); + struct VPE_OMX_EVENT new_event; + new_event.handle=handle; + new_event.appdata=appdata; + new_event.event_type=event_type; + new_event.data1=data1; + new_event.data2=data2; + new_event.event_data=event_data; + + VideoVPEOGL *video=(VideoVPEOGL *)getInstance(); + video->AddOmxEvent(new_event); + /* switch (event_type) { case OMX_EventCmdComplete: { @@ -124,13 +136,31 @@ OMX_ERRORTYPE VideoVPEOGL::EventHandler_OMX(OMX_IN OMX_HANDLETYPE handle,OMX_IN } +void VideoVPEOGL::AddOmxEvent(VPE_OMX_EVENT new_event) +{ + omx_event_mutex.Lock(); + omx_events.push_back(new_event); + omx_event_mutex.Unlock(); +} + + OMX_ERRORTYPE VideoVPEOGL::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer){ Log::getInstance()->log("Video", Log::NOTICE, "EmptyBufferDone"); + VideoVPEOGL *video=(VideoVPEOGL *)getInstance(); + video->ReturnEmptyOMXBuffer(buffer); return OMX_ErrorNone; } +void VideoVPEOGL::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){ + input_bufs_omx_mutex.Lock(); + Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.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(); +} + OMX_ERRORTYPE VideoVPEOGL::FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer) { Log::getInstance()->log("Video", Log::NOTICE, "FillBufferDone"); return OMX_ErrorNone; @@ -329,6 +359,14 @@ int VideoVPEOGL::play() return 1; // Otherwise fall back to ffmpeg + } else { + if (h264) { + omx_h264=false; + Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX failed asuume h264 unsupported"); + } else { + omx_mpeg2=false; + Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX failed asuume mpeg2 unsupported"); + } } #endif @@ -345,6 +383,8 @@ int VideoVPEOGL::AllocateCodecsOMX() Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX"); //Clock, move later to audio + omx_events.clear(); + error=OMX_GetHandle(&omx_clock,VPE_OMX_CLOCK,NULL,&callbacks); @@ -357,6 +397,7 @@ int VideoVPEOGL::AllocateCodecsOMX() OMX_PORT_PARAM_TYPE p_param; + memset(&p_param,0,sizeof(p_param)); p_param.nSize=sizeof(p_param); p_param.nVersion.nVersion=OMX_VERSION; error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param); @@ -365,10 +406,18 @@ int VideoVPEOGL::AllocateCodecsOMX() DeAllocateCodecsOMX(); return 0; } - omx_clock_output_port=p_param.nStartPortNumber+1; + omx_clock_output_port=p_param.nStartPortNumber; + + for (unsigned int i=0;ilog("Video", Log::DEBUG, "Disable Ports OMX clock failed %d",i); + return 0; + } + } OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf; + memset(&clock_conf,0,sizeof(clock_conf)); clock_conf.nSize=sizeof(clock_conf); clock_conf.nVersion.nVersion=OMX_VERSION; clock_conf.eState=OMX_TIME_ClockStateWaitingForStartTime; @@ -394,6 +443,9 @@ int VideoVPEOGL::AllocateCodecsOMX() return 0; } + + + memset(&p_param,0,sizeof(p_param)); p_param.nSize=sizeof(p_param); p_param.nVersion.nVersion=OMX_VERSION; error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamVideoInit,&p_param); @@ -405,6 +457,11 @@ int VideoVPEOGL::AllocateCodecsOMX() omx_codec_input_port=p_param.nStartPortNumber; omx_codec_output_port=p_param.nStartPortNumber+1; + if (!DisablePort(omx_vid_dec,omx_codec_input_port) || !DisablePort(omx_vid_dec,omx_codec_output_port)) { + Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video decoder failed"); + return 0; + } + error=OMX_GetHandle(&omx_vid_sched,VPE_OMX_VIDEO_SCHED,NULL,&callbacks); if (error!=OMX_ErrorNone){ @@ -423,10 +480,25 @@ int VideoVPEOGL::AllocateCodecsOMX() } omx_shed_input_port=p_param.nStartPortNumber; omx_shed_output_port=p_param.nStartPortNumber+1; - omx_shed_clock_port=p_param.nStartPortNumber+2; - error=OMX_GetHandle(&omx_vid_rend,VPE_OMX_VIDEO_SCHED,NULL,&callbacks); + error=OMX_GetParameter(omx_vid_sched,OMX_IndexParamOtherInit,&p_param); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler OMX_GetParameter failed %x", error); + DeAllocateCodecsOMX(); + return 0; + } + omx_shed_clock_port=p_param.nStartPortNumber; + + + if (!DisablePort(omx_vid_sched,omx_shed_input_port) || !DisablePort(omx_vid_sched,omx_shed_output_port) + || !DisablePort(omx_vid_sched,omx_shed_clock_port)) { + Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video shed failed"); + return 0; + } + + + error=OMX_GetHandle(&omx_vid_rend,VPE_OMX_VIDEO_REND,NULL,&callbacks); if (error!=OMX_ErrorNone){ Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video rend failed %x", error); DeAllocateCodecsOMX(); @@ -440,29 +512,35 @@ int VideoVPEOGL::AllocateCodecsOMX() return 0; } omx_rend_input_port=p_param.nStartPortNumber; - omx_rend_output_port=p_param.nStartPortNumber+1; + //omx_rend_output_port=p_param.nStartPortNumber+1; - //Setuo chain - error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,omx_vid_sched,omx_shed_clock_port); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel clock to sched failed %x %d %d", error,omx_clock_output_port,omx_shed_clock_port); - DeAllocateCodecsOMX(); - return 0; + if (!DisablePort(omx_vid_rend,omx_rend_input_port) /*|| !DisablePort(omx_vid_rend,omx_rend_output_port)*/ + ) { + Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video rend failed"); + return 0; } + //Setuo chain + + + - error=OMX_SendCommand(omx_clock,OMX_CommandStateSet,OMX_StateExecuting,0); + + + + +/* error=OMX_SendCommand(omx_vid_dec,OMX_CommandStateSet,OMX_StateIdle,0); if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "clock Send Command to OMX State Executing %x", error); + Log::getInstance()->log("Video", Log::DEBUG, "vid_dec Send Command to OMX State Idle %x", error); return 0; - } - + }*/ OMX_VIDEO_PARAM_PORTFORMATTYPE ft_type; + memset(&ft_type,0,sizeof(ft_type)); ft_type.nSize=sizeof(ft_type); ft_type.nVersion.nVersion=OMX_VERSION; @@ -475,19 +553,223 @@ int VideoVPEOGL::AllocateCodecsOMX() Demuxer* demux=Demuxer::getInstance(); - ft_type.xFramerate=demux->getFrameRate()*(1<<16); + ft_type.xFramerate=0;//25*(1<<16);//demux->getFrameRate()*(1<<16); + Log::getInstance()->log("Video", Log::DEBUG, "Framerate: %d",demux->getFrameRate()); error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamVideoPortFormat,&ft_type); if (error!=OMX_ErrorNone){ Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexParamVideoPortFormat failed %x", error); + return 0; + } + + + if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "vid_dec ChangeComponentState"); + return 0; } - error=OMX_SendCommand(omx_vid_dec,OMX_CommandStateSet,OMX_StateIdle,0); + if (!PrepareInputBufsOMX()) { + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark1"); + return 0; + } + + + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark2"); + if (!ChangeComponentState(omx_clock,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Idle"); + return 0; + } + + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark3"); + + + + error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,omx_vid_sched,omx_shed_clock_port); if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "vid_dec Send Command to OMX State Idle %x", error); + Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel clock to sched failed %x %d %d", error,omx_clock_output_port,omx_shed_clock_port); + DeAllocateCodecsOMX(); + return 0; + } + + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark4"); + + if (!EnablePort(omx_clock,omx_clock_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_clock_port,false) + ) { + Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX clock shed failed"); + return 0; + } + + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark5"); + + if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_clock_port)) { + return 0; + } + + + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark6"); + + + + + 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); + 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"); + return 0; + } + + if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_input_port)) { + return 0; + } + + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark6a"); + + if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "vid_sched idle ChangeComponentState"); + return 0; + } + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark6b"); + if (!CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port) + ||!CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_output_port)){ return 0; } + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark5c"); + + + + +//#error source port is enabled when destination goes idle chnage this + + + + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark7"); + + if (!ChangeComponentState(omx_vid_dec,OMX_StateExecuting)) { + Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_dec ChangeComponentState Execute"); + return 0; + } + + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark8"); + + + + + + + error=OMX_SetupTunnel(omx_vid_sched,omx_shed_output_port,omx_vid_rend,omx_rend_input_port); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel sched to rend failed %x", error); + DeAllocateCodecsOMX(); + return 0; + } + + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark9"); + if (!EnablePort(omx_vid_sched,omx_shed_output_port,false) || !EnablePort(omx_vid_rend,omx_rend_input_port,false) + ) { + Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX shed rend failed"); + return 0; + } + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark9a"); + + if (!CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_output_port) + || !CommandFinished(omx_vid_rend,OMX_CommandPortEnable,omx_rend_input_port)) { + return 0; + } + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark9b"); + if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState"); + return 0; + } + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark9c"); + + if (!ChangeComponentState(omx_vid_sched,OMX_StateExecuting)) { + Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_sched ChangeComponentState Execute"); + return 0; + } + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark9d"); + + + + + + if (!ChangeComponentState(omx_vid_rend,OMX_StateExecuting)) { + Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_rend ChangeComponentState Execute"); + return 0; + } + + //raspbi specifif + OMX_CONFIG_DISPLAYREGIONTYPE dispconf; + memset(&dispconf,0,sizeof(dispconf)); + dispconf.nSize=sizeof(dispconf); + dispconf.nVersion.nVersion=OMX_VERSION; + + dispconf.nPortIndex=omx_rend_input_port; + + dispconf.set=OMX_DISPLAY_SET_LAYER ; + dispconf.layer=1; + error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error); + return 0; + } + + dispconf.set=OMX_DISPLAY_SET_FULLSCREEN ; + dispconf.fullscreen=OMX_FALSE; + error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error); + return 0; + } + + dispconf.set=OMX_DISPLAY_SET_DEST_RECT; + dispconf.dest_rect.x_offset=100; + dispconf.dest_rect.y_offset=100; + dispconf.dest_rect.width=640; + dispconf.dest_rect.height=480; + error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error); + return 0; + } + + + + + if (!ChangeComponentState(omx_clock,OMX_StateExecuting)) { + Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Exccute"); + return 0; + } + + omx_running=true; + Log::getInstance()->log("Video", Log::DEBUG, "OMX mark10"); + + + + + + +/* + error=OMX_SendCommand(omx_vid_sched,OMX_CommandStateSet,OMX_StateIdle,0); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "vid_shed Send Command to OMX State Idle %x", error); + return 0; + } + + error=OMX_SendCommand(omx_vid_rend,OMX_CommandStateSet,OMX_StateIdle,0); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "vid_shed Send Command to OMX State Idle %x", error); + return 0; + }*/ + /* if (h264) { @@ -507,27 +789,14 @@ int VideoVPEOGL::AllocateCodecsOMX() - if (!PrepareInputBufsOMX()) { - return 0; - } //TODO activate this code /* - 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); - DeAllocateCodecsOMX(); - return 0; - } - error=OMX_SetupTunnel(omx_vid_sched,omx_shed_output_port,omx_vid_rend,omx_rend_input_port); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel sched to rend failed %x", error); - DeAllocateCodecsOMX(); - return 0; - }*/ + + */ @@ -592,11 +861,105 @@ int getHorizontalSize() { return horizontal_size; } } +int VideoVPEOGL::ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type) +{ + OMX_ERRORTYPE error; + error=OMX_SendCommand(handle,OMX_CommandStateSet,type,0); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to OMX State %x %x",handle,type, error); + return 0; + } + + if (!CommandFinished(handle,OMX_CommandStateSet,type)) { + return 0; + } + + return 1; +} + + +int VideoVPEOGL::EnablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait) +{ + OMX_ERRORTYPE error; + error=OMX_SendCommand(handle,OMX_CommandPortEnable,port,0); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to enable port %x %x",handle,port, error); + return 0; + } + + if (!wait) return 1; + if (!CommandFinished(handle,OMX_CommandPortEnable,port)) { + return 0; + } + + return 1; +} + + +int VideoVPEOGL::DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait) +{ + OMX_ERRORTYPE error; + error=OMX_SendCommand(handle,OMX_CommandPortDisable,port,0); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to disable port %x %x",handle,port, error); + return 0; + } + + if (!wait) return 1; + if (!CommandFinished(handle,OMX_CommandPortDisable,port)) { + return 0; + } + + + return 1; +} + + + + +int VideoVPEOGL::CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2) +{ + 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(); + return 0; + + } else if (current.event_type==OMX_EventCmdComplete && current.data1==command && current.data2==data2) { + omx_events.erase(itty); + omx_event_mutex.Unlock(); + return 1; + } + } + itty++; + + } + omx_event_mutex.Unlock(); + MILLISLEEP(2); + i++; + + } + Log::getInstance()->log("Video", Log::DEBUG, "CommandFinished waited too long %x %x %x",handle,command, data2); + return 0; + +} + + + + int VideoVPEOGL::PrepareInputBufsOMX() { 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_input_port; @@ -606,25 +969,64 @@ int VideoVPEOGL::PrepareInputBufsOMX() if (error!=OMX_ErrorNone){ Log::getInstance()->log("Video", Log::DEBUG, "Get OMX OMX_IndexParamPortDefinition failed %x", error); } + Log::getInstance()->log("Video", Log::DEBUG, "Port para %d %d %d %d %d %d %d", port_def_type.nBufferCountActual, + port_def_type.nBufferCountMin,port_def_type.nBufferSize,port_def_type.bEnabled,port_def_type.bPopulated, + port_def_type.bBuffersContiguous,port_def_type.nBufferAlignment); + Log::getInstance()->log("Video", Log::DEBUG, "OMX minimum buffer num %d", port_def_type.nBufferCountMin); + + port_def_type.nBufferCountActual=60; + + error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type); + + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Set OMX OMX_IndexParamPortDefinition failed %x", error); + } + + + Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark1"); + error=OMX_SendCommand(omx_vid_dec,OMX_CommandPortEnable,omx_codec_input_port,0); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Prepare Input bufs Send Command to enable port %x", error); + return 0; + } + Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark2"); + + + + Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark2a"); + input_bufs_omx_mutex.Lock(); - for (unsigned int i=0; i< port_def_type.nBufferCountMin;i++) { + for (unsigned int i=0; i< port_def_type.nBufferCountActual;i++) { - unsigned char* new_buffer_data=(unsigned char*)malloc(port_def_type.nBufferSize); + // unsigned char* new_buffer_data=(unsigned char*)malloc(port_def_type.nBufferSize); OMX_BUFFERHEADERTYPE *buf_head=NULL; - error=OMX_UseBuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nBufferSize,new_buffer_data); + /* error=OMX_UseBuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nBufferSize,new_buffer_data); if (error!=OMX_ErrorNone){ Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_UseBuffer failed %x", error); input_bufs_omx_mutex.Unlock(); return 0; + }*/ + error=OMX_AllocateBuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nBufferSize); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_AllocateBuffer failed %x", error); + input_bufs_omx_mutex.Unlock(); + return 0; } input_bufs_omx_all.push_back(buf_head); input_bufs_omx_free.push_back(buf_head); } - input_bufs_omx_mutex.Unlock(); omx_first_frame=true; - omx_running=true; + firstsynched=false; cur_input_buf_omx=NULL; + input_bufs_omx_mutex.Unlock(); + + + Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark3"); + if (!CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_input_port)) { + return 0; + } + Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark4"); return 1; } @@ -636,8 +1038,8 @@ int VideoVPEOGL::DestroyInputBufsOMX() cur_input_buf_omx=NULL; input_bufs_omx_mutex.Lock(); for (int i=0; i< input_bufs_omx_all.size();i++) { - free(input_bufs_omx_all[i]->pBuffer); - input_bufs_omx_all[i]->pBuffer=NULL; + // free(input_bufs_omx_all[i]->pBuffer); + // input_bufs_omx_all[i]->pBuffer=NULL; error=OMX_FreeBuffer(omx_vid_dec,omx_codec_input_port,input_bufs_omx_all[i]); if (error!=OMX_ErrorNone){ Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_FreeBuffer failed %x", error); @@ -657,20 +1059,119 @@ int VideoVPEOGL::DestroyInputBufsOMX() int VideoVPEOGL::DeAllocateCodecsOMX() { OMX_ERRORTYPE error; + omx_running=false; if (omx_vid_dec) { + // first flush all buffers + + 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); + + } + + if (!CommandFinished(omx_vid_dec,OMX_CommandFlush,omx_codec_output_port) || + !CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_input_port)) { + Log::getInstance()->log("Video", Log::DEBUG, "flush cmd codec shed failed"); + } + + error=OMX_SendCommand(omx_clock,OMX_CommandFlush, omx_clock_output_port, NULL); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush clock out failed %x", error); + + } + + error=OMX_SendCommand(omx_vid_sched,OMX_CommandFlush, omx_shed_clock_port, NULL); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush shed clock failed %x", error); + + } + + if (!CommandFinished(omx_clock,OMX_CommandFlush,omx_clock_output_port) || + !CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_clock_port)) { + Log::getInstance()->log("Video", Log::DEBUG, "flush cmd clock shed failed"); + } + + error=OMX_SendCommand(omx_vid_sched,OMX_CommandFlush, omx_shed_output_port, NULL); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush shed out failed %x", error); + + } + + error=OMX_SendCommand(omx_vid_rend,OMX_CommandFlush, omx_rend_input_port, NULL); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush rend in failed %x", error); + + } + + if (!CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_output_port) || + !CommandFinished(omx_vid_rend,OMX_CommandFlush,omx_rend_input_port)) { + Log::getInstance()->log("Video", Log::DEBUG, "flush cmd shed rend failed"); + } + + + + + error=OMX_SendCommand(omx_vid_dec,OMX_CommandFlush, omx_codec_input_port, NULL); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush codec out failed %x", error); + + } + + + if (!CommandFinished(omx_vid_dec,OMX_CommandFlush,omx_codec_input_port)) { + Log::getInstance()->log("Video", Log::DEBUG, "flush cmd codec input failed"); + } + DestroyInputBufsOMX(); //todo flushing + if (!DisablePort(omx_vid_rend,omx_rend_input_port,true)) { + Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 1"); + } + if (!DisablePort(omx_vid_sched,omx_shed_output_port,true)) { + Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 2 "); + } + error=OMX_SetupTunnel(omx_vid_rend,omx_rend_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_sched,omx_shed_output_port,NULL,NULL); if (error!=OMX_ErrorNone){ Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error); } + + if (!DisablePort(omx_vid_sched,omx_shed_input_port,true)) { + Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 3"); + } + + if (!DisablePort(omx_vid_sched,omx_shed_clock_port,true)) { + Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 4"); + } + + if (!DisablePort(omx_clock,omx_clock_output_port,true)) { + Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 5"); + } + if (!DisablePort(omx_vid_dec,omx_codec_output_port,true)) { + Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 6"); + } + + + + if (!DisablePort(omx_vid_dec,omx_codec_input_port,true)) { + Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 7"); + } + + 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); @@ -693,11 +1194,8 @@ int VideoVPEOGL::DeAllocateCodecsOMX() Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error); } - error=OMX_SetupTunnel(omx_vid_dec,omx_codec_input_port,NULL,NULL); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error); - } + @@ -846,13 +1344,27 @@ UINT VideoVPEOGL::DeliverMediaSample(UCHAR* buffer, UINT *samplepos) else return 0; } +//FILE * output_hack=NULL; +//FILE * output_hack2=NULL; +//FILE * input_hack=NULL; UINT VideoVPEOGL::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos) { + /*if (!output_hack) { + output_hack=fopen("/home/marten/test2.h264","wb"); + + } + if (!output_hack2) { + output_hack2=fopen("/home/marten/test3.h264","wb"); + + }*/ + /*if (!input_hack) { + input_hack=fopen("/opt/vc/src/hello_pi/hello_video/test.h264","rb"); + }*/ + - /*First Check, if we have an audio sample*/ if (packet.type == MPTYPE_VIDEO_H264) { @@ -872,6 +1384,23 @@ UINT VideoVPEOGL::DeliverMediaPacket(MediaPacket packet, if (!omx_running) return 0; // if we are not runnig do not do this + OMX_ERRORTYPE error; + + + + OMX_PARAM_PORTDEFINITIONTYPE port_image; + memset(&port_image,0,sizeof(port_image)); + port_image.nSize=sizeof(port_image); + port_image.nVersion.nVersion=OMX_VERSION; + port_image.nPortIndex =omx_codec_output_port; + error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_image); + if (error!= OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "OMX_GetParameter failed %x", error); + } + Log::getInstance()->log("Video", Log::DEBUG, "Image port %d %d", port_image.format.video.nFrameWidth , port_image.format.video.nFrameHeight); + + + /*First Check, if we have an audio sample*/ if (iframemode) { //samplepos=0; @@ -885,6 +1414,9 @@ UINT VideoVPEOGL::DeliverMediaPacket(MediaPacket packet, if (packet.disconti) { firstsynched=false; if (cur_input_buf_omx) { + // int read =fread(cur_input_buf_omx->pBuffer,1,cur_input_buf_omx->nFilledLen,input_hack); + Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket Empty this buffer1 %d", cur_input_buf_omx->nFilledLen); + // fwrite(cur_input_buf_omx->pBuffer,1,cur_input_buf_omx->nFilledLen,output_hack); OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx); if (error!=OMX_ErrorNone){ Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error); @@ -895,15 +1427,29 @@ UINT VideoVPEOGL::DeliverMediaPacket(MediaPacket packet, /*Inspect PES-Header */ + OMX_STATETYPE temp_state; + OMX_GetState(omx_vid_dec,&temp_state); + Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket Mark1 codec state %d",temp_state); if (*samplepos==0) {//stripheader headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/; + //headerstrip+=6; //h264 *samplepos+=headerstrip; + //fwrite(buffer+packet.pos_buffer+*samplepos,1,packet.length-*samplepos,output_hack2); + Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket Mark2a"); if ( packet.synched ) { + Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket Mark2b"); + if (cur_input_buf_omx) { + // int read =fread(cur_input_buf_omx->pBuffer,1,cur_input_buf_omx->nFilledLen,input_hack); + Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket Empty this buffer2 %d", cur_input_buf_omx->nFilledLen); + //fwrite(cur_input_buf_omx->pBuffer,1,cur_input_buf_omx->nFilledLen,output_hack); OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error); + } cur_input_buf_omx=NULL;//write out old data } @@ -912,27 +1458,32 @@ UINT VideoVPEOGL::DeliverMediaPacket(MediaPacket packet, firstsynched=true; } else { if (!firstsynched) {// + Log::getInstance()->log("Video", Log::DEBUG, "!firstsynched"); *samplepos=packet.length;//if we have not processed at least one return packet.length;//synched packet ignore it! } } } + Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket Mark3"); if (!cur_input_buf_omx) { 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"); return 0; // we do not have a free media sample } cur_input_buf_omx=input_bufs_omx_free.front(); cur_input_buf_omx->nFilledLen=0; cur_input_buf_omx->nOffset=0; + cur_input_buf_omx->nTimeStamp=0; input_bufs_omx_free.pop_front(); input_bufs_omx_mutex.Unlock(); } + Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket fillinge"); @@ -943,11 +1494,12 @@ UINT VideoVPEOGL::DeliverMediaPacket(MediaPacket packet, ms->SetDiscontinuity(FALSE); }*/ //if (packet.synched) { - + Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket fillinge test 2"); //lastreftimePTS=packet.pts; if (omx_first_frame) { // TODO time cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_STARTTIME; + omx_first_frame=false; } else //} @@ -962,18 +1514,49 @@ UINT VideoVPEOGL::DeliverMediaPacket(MediaPacket packet, } unsigned int haveToCopy=packet.length-*samplepos; - if (haveToCopy> (cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen)) { - cur_input_buf_omx->pBuffer=(OMX_U8*)realloc(cur_input_buf_omx->pBuffer,cur_input_buf_omx->nFilledLen+haveToCopy); - cur_input_buf_omx->nAllocLen=cur_input_buf_omx->nFilledLen+haveToCopy; + Log::getInstance()->log("Video", Log::DEBUG, "Buffersize: %d %d",cur_input_buf_omx->nAllocLen, haveToCopy); + while (haveToCopy> (cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen)) { + unsigned int cancopy=cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen; + memcpy(cur_input_buf_omx->pBuffer+cur_input_buf_omx->nFilledLen,buffer+packet.pos_buffer+*samplepos,cancopy); + haveToCopy-=cancopy; + cur_input_buf_omx->nFilledLen+=cancopy; + *samplepos+=cancopy; + // push old buffer out + //int read =fread(cur_input_buf_omx->pBuffer,1,cur_input_buf_omx->nFilledLen,input_hack); + Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket Empty this buffer3 %d", cur_input_buf_omx->nFilledLen); + //fwrite(cur_input_buf_omx->pBuffer,1,cur_input_buf_omx->nFilledLen,output_hack); + + OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error); + } + // 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"); + return *samplepos; // we do not have a free media sample + } + cur_input_buf_omx=input_bufs_omx_free.front(); + cur_input_buf_omx->nFilledLen=0; + cur_input_buf_omx->nOffset=0; + cur_input_buf_omx->nTimeStamp=0; + input_bufs_omx_free.pop_front(); + input_bufs_omx_mutex.Unlock(); + + cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN; + } - memcpy(cur_input_buf_omx->pBuffer,buffer+packet.pos_buffer+*samplepos,haveToCopy); - cur_input_buf_omx->nFilledLen=cur_input_buf_omx->nFilledLen+haveToCopy; + memcpy(cur_input_buf_omx->pBuffer+cur_input_buf_omx->nFilledLen, + buffer+packet.pos_buffer+*samplepos,haveToCopy); +// fwrite(buffer+packet.pos_buffer+*samplepos,1,haveToCopy,output_hack); + cur_input_buf_omx->nFilledLen+=haveToCopy; *samplepos+=haveToCopy; - return haveToCopy+headerstrip; + return *samplepos; #else diff --git a/videovpeogl.h b/videovpeogl.h index 98d8e08..e308a1f 100755 --- a/videovpeogl.h +++ b/videovpeogl.h @@ -51,10 +51,22 @@ #include #include + +struct VPE_OMX_EVENT { + OMX_IN OMX_HANDLETYPE handle; + OMX_IN OMX_PTR appdata; + OMX_IN OMX_EVENTTYPE event_type; + OMX_IN OMX_U32 data1; + OMX_IN OMX_U32 data2; + OMX_IN OMX_PTR event_data; +}; + #endif + + /* struct VPEOGLFrame { int type; //1 = RGB, 2 YUV @@ -104,7 +116,7 @@ class VideoVPEOGL : public Video virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); virtual UINT DeliverMediaSample(UCHAR* buffer, UINT* samplepos); virtual long long SetStartOffset(long long curreftime, bool *rsync) - { return 0; }; + { *rsync=false; return 0; }; virtual void ResetTimeOffsets(); virtual bool supportsh264(){return true;}; @@ -145,6 +157,14 @@ class VideoVPEOGL : public Video int PrepareInputBufsOMX(); int DestroyInputBufsOMX(); + void AddOmxEvent(VPE_OMX_EVENT new_event); + void ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer); + + int ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type); + int CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2); + int EnablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait); + int DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait=true); + OMX_HANDLETYPE omx_vid_dec; @@ -176,6 +196,14 @@ class VideoVPEOGL : public Video bool omx_running; bool omx_first_frame; + Mutex omx_event_mutex; + + list omx_events; + + bool omx_mpeg2; + bool omx_h264; + + #endif -- 2.39.2