From c413ed86b56434966da43bdfb72490b80504f6c7 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sun, 26 Aug 2012 19:57:14 +0200 Subject: [PATCH] First timecode handling + Mpeg2 video hardware playback SD + HD --- defines.h | 2 +- player.cc | 2 +- videovpeogl.cc | 494 +++++++++++++++++++++++++++++++++++++------------ videovpeogl.h | 36 +++- 4 files changed, 405 insertions(+), 129 deletions(-) mode change 100755 => 100644 player.cc diff --git a/defines.h b/defines.h index 0e6648a..fcb0bf9 100644 --- a/defines.h +++ b/defines.h @@ -105,7 +105,7 @@ long long getTimeMS(); #define VPE_OMX_CLOCK "OMX.broadcom.clock" //#define VPE_LIBAV_SUPPORT - #define VPE_LIBAV_MPEG2_TRANSCODING + // #define VPE_LIBAV_MPEG2_TRANSCODING #endif #ifdef VOMP_PLATTFORM_MVP diff --git a/player.cc b/player.cc old mode 100755 new mode 100644 index c4f9569..2c2b5b0 --- a/player.cc +++ b/player.cc @@ -91,7 +91,7 @@ int Player::init(bool p_isPesRecording,double framespersecond) if (!teletext) return 0; teletext->setRecordigMode(true); unsigned int demux_video_size=2097152; - if (video->supportsh264()) demux_video_size*=5; + if (video->supportsh264()) demux_video_size*=5; if (!demuxer->init(this, audio, video,teletext, demux_video_size,524288,65536, framespersecond, subtitles)) { diff --git a/videovpeogl.cc b/videovpeogl.cc index d4346ea..b565266 100644 --- a/videovpeogl.cc +++ b/videovpeogl.cc @@ -64,6 +64,16 @@ VideoVPEOGL::VideoVPEOGL() transcodecodec_context_libav=NULL; #endif + offsetnotset=true; + offsetvideonotset=true; + offsetaudionotset=true; + startoffset=0; + lastrefaudiotime=0; + lastrefvideotime=0; + lastreftimeOMX=0; + lastreftimePTS=0; + firstsynched=false; + #ifdef BENCHMARK_FPS time_in_decoder=0; @@ -1021,6 +1031,7 @@ int VideoVPEOGL::play() decoding_backend=0; #ifdef VPE_OMX_SUPPORT bool doomx=true; + Log::getInstance()->log("Video", Log::DEBUG, "enter play"); if (h264) { if (!omx_h264) doomx=false; } else { @@ -1129,6 +1140,7 @@ int VideoVPEOGL::AllocateCodecsOMX() + /* TODO Clock config to separate method */ OMX_PORT_PARAM_TYPE p_param; memset(&p_param,0,sizeof(p_param)); p_param.nSize=sizeof(p_param); @@ -1142,7 +1154,7 @@ int VideoVPEOGL::AllocateCodecsOMX() omx_clock_output_port=p_param.nStartPortNumber; for (unsigned int i=0;ilog("Video", Log::DEBUG, "Disable Ports OMX clock failed %d",i); DeAllocateCodecsOMX(); return 0; @@ -1150,6 +1162,8 @@ int VideoVPEOGL::AllocateCodecsOMX() } + + OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf; memset(&clock_conf,0,sizeof(clock_conf)); clock_conf.nSize=sizeof(clock_conf); @@ -1158,7 +1172,7 @@ int VideoVPEOGL::AllocateCodecsOMX() clock_conf.nStartTime=0; clock_conf.nOffset=0; clock_conf.nWaitMask=OMX_CLOCKPORT0; - error=OMX_SetParameter(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf); + error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf); if (error!=OMX_ErrorNone){ Log::getInstance()->log("Video", Log::DEBUG, "Clock IndexConfigTimeClockState failed %x", error); DeAllocateCodecsOMX(); @@ -1166,6 +1180,36 @@ int VideoVPEOGL::AllocateCodecsOMX() } + OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refclock; + memset(&refclock,0,sizeof(refclock)); + refclock.nSize=sizeof(refclock); + refclock.nVersion.nVersion=OMX_VERSION; + + if (/*AUDIO*/ false) { + refclock.eClock=OMX_TIME_RefClockAudio; + } else { + refclock.eClock=OMX_TIME_RefClockVideo; + } + error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeActiveRefClock,&refclock); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Clock OMX_IndexConfigTimeActiveRefClock failed %x", error); + DeAllocateCodecsOMX(); + return 0; + } + + if (!ChangeComponentState(omx_clock,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Idle"); + DeAllocateCodecsOMX(); + return 0; + } + + + + + /* TODO end */ + + + if (h264) { error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_H264_DECODER,NULL,&callbacks); @@ -1240,10 +1284,11 @@ int VideoVPEOGL::AllocateCodecsOMX() return 0; } omx_shed_clock_port=p_param.nStartPortNumber; + Log::getInstance()->log("Video", Log::DEBUG, "scheduler ports %d %d %d ",omx_shed_input_port,omx_shed_output_port,omx_shed_clock_port); - 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)) { + if (!DisablePort(omx_vid_sched,omx_shed_input_port,true) || !DisablePort(omx_vid_sched,omx_shed_output_port,true) + || !DisablePort(omx_vid_sched,omx_shed_clock_port,true)) { Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video shed failed"); DeAllocateCodecsOMX(); return 0; @@ -1267,7 +1312,7 @@ int VideoVPEOGL::AllocateCodecsOMX() //omx_rend_output_port=p_param.nStartPortNumber+1; - if (!DisablePort(omx_vid_rend,omx_rend_input_port) /*|| !DisablePort(omx_vid_rend,omx_rend_output_port)*/ + if (!DisablePort(omx_vid_rend,omx_rend_input_port,true) /*|| !DisablePort(omx_vid_rend,omx_rend_output_port)*/ ) { Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video rend failed"); DeAllocateCodecsOMX(); @@ -1279,19 +1324,54 @@ int VideoVPEOGL::AllocateCodecsOMX() + 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 (!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"); + DeAllocateCodecsOMX(); + return 0; + } + + Log::getInstance()->log("Video", Log::DEBUG, "mark2 "); + if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "vid_sched idle ChangeComponentState"); + DeAllocateCodecsOMX(); + return 0; + } + + + + Log::getInstance()->log("Video", Log::DEBUG, "mark1 "); + if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_clock_port)) { + DeAllocateCodecsOMX(); + return 0; + } + + Log::getInstance()->log("Video", Log::DEBUG, "mark1 special "); + if ( !CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port)) { + DeAllocateCodecsOMX(); + return 0; + } + + + Log::getInstance()->log("Video", Log::DEBUG, "mark1b "); + + /* error=OMX_SendCommand(omx_vid_dec,OMX_CommandStateSet,OMX_StateIdle,0); if (error!=OMX_ErrorNone){ 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); @@ -1301,10 +1381,13 @@ int VideoVPEOGL::AllocateCodecsOMX() if (h264) { ft_type.eCompressionFormat=OMX_VIDEO_CodingAVC; } else { - //ft_type.eCompressionFormat=OMX_VIDEO_CodingMPEG2; +#ifndef VPE_LIBAV_MPEG2_TRANSCODING + ft_type.eCompressionFormat=OMX_VIDEO_CodingMPEG2; +#else ft_type.eCompressionFormat=OMX_VIDEO_CodingMPEG4; decoding_backend=VPE_DECODER_OMX_libav_TRANSCODE; InitTranscoderLibAV(); +#endif } Demuxer* demux=Demuxer::getInstance(); @@ -1332,31 +1415,6 @@ int VideoVPEOGL::AllocateCodecsOMX() } - if (!ChangeComponentState(omx_clock,OMX_StateIdle)) { - Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Idle"); - DeAllocateCodecsOMX(); - return 0; - } - - 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 (!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"); - DeAllocateCodecsOMX(); - return 0; - } - - if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_clock_port)) { - 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); @@ -1373,16 +1431,7 @@ int VideoVPEOGL::AllocateCodecsOMX() return 0; } - if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_input_port)) { - return 0; - } - if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) { - Log::getInstance()->log("Video", Log::DEBUG, "vid_sched idle ChangeComponentState"); - DeAllocateCodecsOMX(); - return 0; - } - if (!CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port) - ||!CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_output_port)){ + if ( !CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_output_port) || !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_input_port)) { DeAllocateCodecsOMX(); return 0; } @@ -1442,7 +1491,7 @@ int VideoVPEOGL::AllocateCodecsOMX() dispconf.set=OMX_DISPLAY_SET_LAYER ; dispconf.layer=1; - error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf); + error=OMX_SetConfig(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf); if (error!=OMX_ErrorNone){ Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error); DeAllocateCodecsOMX(); @@ -1470,17 +1519,34 @@ int VideoVPEOGL::AllocateCodecsOMX() return 0; }*/ + if (decoding_backend!=VPE_DECODER_OMX_libav_TRANSCODE) decoding_backend=VPE_DECODER_OMX; - + playbacktimeoffset=-GetCurrentSystemTime(); + paused=false; + omx_running=true; if (!ChangeComponentState(omx_clock,OMX_StateExecuting)) { - Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Exccute"); - DeAllocateCodecsOMX(); - return 0; + Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Execute failed"); + DeAllocateCodecsOMX(); + 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_ClockStateRunning; + error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Clock IndexConfigTimeClockState failed %x", error); + DeAllocateCodecsOMX(); + return 0; } - if (decoding_backend!=VPE_DECODER_OMX_libav_TRANSCODE) decoding_backend=VPE_DECODER_OMX; - omx_running=true; + + + return 1; } @@ -1555,11 +1621,13 @@ int VideoVPEOGL::CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 d if (current.event_type==OMX_EventError) { omx_events.erase(itty); omx_event_mutex.Unlock(); + Log::getInstance()->log("Video", Log::DEBUG, "Command Finished on Error"); return 0; } else if (current.event_type==OMX_EventCmdComplete && current.data1==command && current.data2==data2) { omx_events.erase(itty); omx_event_mutex.Unlock(); + //Log::getInstance()->log("Video", Log::DEBUG, "Command Finished Completed"); return 1; } } @@ -1598,7 +1666,7 @@ int VideoVPEOGL::PrepareInputBufsOMX() port_def_type.nBufferCountMin,port_def_type.nBufferSize,port_def_type.bEnabled,port_def_type.bPopulated, port_def_type.bBuffersContiguous,port_def_type.nBufferAlignment);*/ - port_def_type.nBufferCountActual=60; + port_def_type.nBufferCountActual=10; port_def_type.nBufferSize=max(port_def_type.nBufferSize,200000); // for transcoder important error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type); @@ -1694,20 +1762,83 @@ int VideoVPEOGL::DeAllocateCodecsOMX() { OMX_ERRORTYPE error; omx_running=false; + Log::getInstance()->log("Video", Log::DEBUG, "enter deallocatecodecsomx"); #ifdef VPE_LIBAV_MPEG2_TRANSCODING if (decoding_backend==VPE_DECODER_OMX_libav_TRANSCODE) DeInitTranscoderLibAV(); #endif + if (cur_input_buf_omx) { + cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_EOS; + 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 + } + if (omx_vid_dec) { + // first stop the omx elements + if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "vid_dec ChangeComponentState"); + DeAllocateCodecsOMX(); + return 0; + } + + if (!ChangeComponentState(omx_clock,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "vid_clock ChangeComponentState"); + DeAllocateCodecsOMX(); + return 0; + } + + if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "vid_shed ChangeComponentState"); + DeAllocateCodecsOMX(); + return 0; + } + + if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState"); + DeAllocateCodecsOMX(); + return 0; + } + + + + // TODO proper deinit sequence // first flush all buffers + 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_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"); + } + 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); @@ -1742,53 +1873,43 @@ int VideoVPEOGL::DeAllocateCodecsOMX() } - 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)) { + if (!CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_output_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 "); } + if (!DisablePort(omx_vid_rend,omx_rend_input_port,true)) { + Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 1"); + } + + - 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); + if (!DisablePort(omx_vid_dec,omx_codec_output_port,true)) { + Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 6"); } - 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_dec,omx_codec_input_port,true)) { + Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 7"); } + + + if (!DisablePort(omx_vid_sched,omx_shed_input_port,true)) { Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 3"); } @@ -1800,36 +1921,42 @@ int VideoVPEOGL::DeAllocateCodecsOMX() 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_dec,omx_codec_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){ + 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_clock_port,NULL,NULL); - if (error!=OMX_ErrorNone){ + + + 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); + + } + + 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_clock,omx_clock_output_port,NULL,NULL); - if (error!=OMX_ErrorNone){ + if (error!=OMX_ErrorNone) { Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error); } - error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,NULL,NULL); - if (error!=OMX_ErrorNone){ + error=OMX_SetupTunnel(omx_vid_sched,omx_shed_clock_port,NULL,NULL); + if (error!=OMX_ErrorNone) { Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error); } @@ -1838,6 +1965,13 @@ int VideoVPEOGL::DeAllocateCodecsOMX() + + + + + + + error=OMX_FreeHandle(omx_vid_dec); error=OMX_FreeHandle(omx_vid_sched); error=OMX_FreeHandle(omx_vid_rend); @@ -1847,6 +1981,7 @@ int VideoVPEOGL::DeAllocateCodecsOMX() Log::getInstance()->log("Video", Log::DEBUG, "FreeHandle failed %d", error); } } + Log::getInstance()->log("Video", Log::DEBUG, "leave deallocate codecs OMX"); return 1; } @@ -2361,15 +2496,26 @@ int VideoVPEOGL::reset() int VideoVPEOGL::pause() { if (!initted) return 0; + Log::getInstance()->log("Video", Log::DEBUG, "enter pause"); + if (!paused) { + paused=true; + //maybe also change omx clock? + pausetimecode=GetCurrentSystemTime(); -// if (ioctl(fdVideo, AV_SET_VID_PAUSE, 0) != 0) return 0; + } return 1; } -int VideoVPEOGL::unPause() // FIXME get rid - same as play!! +int VideoVPEOGL::unPause() // FIXME get rid - same as play!! Not here! { if (!initted) return 0; -// if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0; + Log::getInstance()->log("Video", Log::DEBUG, "enter unpause"); + + if (paused) { + playbacktimeoffset+=GetCurrentSystemTime()-pausetimecode; + paused=false; // may be also change omx clock + } + return 1; } @@ -2408,29 +2554,19 @@ int VideoVPEOGL::blank(void) ULLONG VideoVPEOGL::getCurrentTimestamp() { -/* sync_data_t timestamps; - if (ioctl(fdVideo, AV_GET_VID_TIMESTAMPS, ×tamps) == 0) - { - // FIXME are these the right way around? - - timestamps.stc = (timestamps.stc >> 31 ) | (timestamps.stc & 1); - timestamps.pts = (timestamps.pts >> 31 ) | (timestamps.pts & 1); - return timestamps.stc; - } - else - { - return 0; - }*/ - return 0; + return lastreftimePTS; } +// to be removed +/* ULONG VideoVPEOGL::timecodeToFrameNumber(ULLONG timecode) { if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25); else return (ULONG)(((double)timecode / (double)90000) * (double)30); } +*/ #ifdef DEV int VideoVPEOGL::test() { @@ -2450,6 +2586,111 @@ int VideoVPEOGL::test2() } #endif + + +long long VideoVPEOGL::SetStartOffset(long long curreftime, bool *rsync) +{ + *rsync=false; + if (offsetnotset) { + startoffset=curreftime;//offset is set for audio + offsetnotset=false; + offsetvideonotset=false; + } else { + if (offsetvideonotset) { + offsetvideonotset=false; + *rsync=true; + } else { + if ( (curreftime-lastrefvideotime)>10000000LL + || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync + startoffset+=curreftime-lastrefvideotime; + lastrefaudiotime+=curreftime-lastrefvideotime; + //*rsync=true; + offsetaudionotset=true; + + } + } + + } + + lastrefvideotime=curreftime; + + return startoffset; + +} + +long long VideoVPEOGL::SetStartAudioOffset(long long curreftime, bool *rsync) +{ + *rsync=false; + if (offsetnotset) { + startoffset=curreftime; + offsetnotset=false; + offsetaudionotset=false; + }else { + if (offsetaudionotset) { + offsetaudionotset=false; + *rsync=true; + } else { + if ( (curreftime-lastrefaudiotime)>10000000LL + || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync + startoffset+=curreftime-lastrefaudiotime; + lastrefvideotime+=curreftime-lastrefaudiotime; + //*rsync=true; + offsetvideonotset=true; + + } + } + + } + lastrefaudiotime=curreftime; + return startoffset; + +} + +void VideoVPEOGL::ResetTimeOffsets() { + offsetnotset=true; //called from demuxer + offsetvideonotset=true; + offsetaudionotset=true; + startoffset=0; + lastrefaudiotime=0; + lastrefvideotime=0; + lastreftimeOMX=0; + lastreftimePTS=0; +} + +long long VideoVPEOGL::GetCurrentSystemTime() +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec*10000000LL+ts.tv_nsec/100LL; +} + +void VideoVPEOGL::WaitUntil(long long time) +{ + struct timespec interval; + interval.tv_sec=time/10000000LL; + interval.tv_nsec=(time %10000000LL)*100LL; + while (clock_nanosleep(CLOCK_MONOTONIC,TIMER_ABSTIME,&interval,NULL)==EINTR) {}; +} + +void VideoVPEOGL::FrameWaitforDisplay(long long pts) +{ + //ok first calculate the absolute time + long long target_time=pts-playbacktimeoffset; + // we have to wait untile the next frame + long long offset=Demuxer::getInstance()->getFrameRate(); + long long current_time=GetCurrentSystemTime(); + if ((target_time-current_time)>5000000LL) target_time=current_time+5000000LL; // something is wrong do not wait too long + if (offset==0) offset=25; + offset=10000000LL/offset; + target_time+=offset; + Log::getInstance()->log("Video", Log::DEBUG, "Wait for display pts: %lld target: %lld sys: %lld off: %lld diff %lld",pts,target_time,current_time,offset, + target_time-current_time); + + WaitUntil(target_time); + Log::getInstance()->log("Video", Log::DEBUG, "Wait for display out"); +} + + void VideoVPEOGL::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos) { mediapacket = mplist.front(); @@ -2499,7 +2740,7 @@ UINT VideoVPEOGL::DeliverMediaPacketOMX(MediaPacket packet, //Later add fail back code for libav - /*if (!videoon) { +/* if (!videoon) { *samplepos+=packet.length; return packet.length; }*/ @@ -2507,6 +2748,11 @@ UINT VideoVPEOGL::DeliverMediaPacketOMX(MediaPacket packet, if (!omx_running) return 0; // if we are not runnig do not do this + if (packet.synched && packet.presentation_time<0) { + Log::getInstance()->log("Video", Log::DEBUG, "DeliverMediaPacketOMX Preroll %lld", packet.presentation_time); + *samplepos=packet.length; + return packet.length; + } OMX_ERRORTYPE error; @@ -2551,10 +2797,12 @@ UINT VideoVPEOGL::DeliverMediaPacketOMX(MediaPacket packet, if ( packet.synched ) { if (cur_input_buf_omx) { + cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_ENDOFFRAME; 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); } + FrameWaitforDisplay(lastreftimeOMX); cur_input_buf_omx=NULL;//write out old data } @@ -2594,22 +2842,34 @@ UINT VideoVPEOGL::DeliverMediaPacketOMX(MediaPacket packet, } else { ms->SetDiscontinuity(FALSE); }*/ - //if (packet.synched) { + if (packet.synched) { + Log::getInstance()->log("Video", Log::DEBUG, "packet synched marker"); //lastreftimePTS=packet.pts; if (omx_first_frame) { // TODO time cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_STARTTIME; + Log::getInstance()->log("Video", Log::DEBUG, "Starttime"); omx_first_frame=false; - } else - - //} - //else - //{ + } else { + //cur_input_buf_omx->nFlags=0; + 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); + lastreftimePTS=packet.pts; + cur_input_buf_omx->nTimeStamp=0;//lastreftimeOMX; // the clock component is faulty; + } + else + { cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN; + cur_input_buf_omx->nTimeStamp=0; // ms->SetSyncPoint(TRUE); - //} + } + if (packet.disconti) cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_DISCONTINUITY; + + } unsigned int haveToCopy=packet.length-*samplepos; @@ -3004,14 +3264,6 @@ UINT VideoVPEOGL::DeliverMediaPacketlibav(MediaPacket packet, #endif - - - - -void VideoVPEOGL::ResetTimeOffsets() -{ -} - bool VideoVPEOGL::displayIFrame(const UCHAR* buffer, UINT length) { //write(fdVideo, buffer, length); diff --git a/videovpeogl.h b/videovpeogl.h index e4ee138..97a589c 100644 --- a/videovpeogl.h +++ b/videovpeogl.h @@ -158,12 +158,12 @@ class VideoVPEOGL : public Video, public Thread_TYPE ULLONG getCurrentTimestamp(); bool displayIFrame(const UCHAR* bulibaver, UINT length); + virtual bool dtsTimefix(){return true;} //please we need dts time values + // Writing Data to Videodevice virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); virtual UINT DeliverMediaSample(UCHAR* bulibaver, UINT* samplepos); - virtual long long SetStartOffset(long long curreftime, bool *rsync) - { *rsync=false; return 0; }; - virtual void ResetTimeOffsets(); + virtual bool supportsh264(){return true;}; @@ -175,6 +175,14 @@ class VideoVPEOGL : public Video, public Thread_TYPE void returnOGLFrame(VPEOGLFrame *frame); void recycleOGLRefFrames(); + virtual long long SetStartOffset(long long curreftime, bool *rsync); + long long SetStartAudioOffset(long long curreftime, bool *rsync); + virtual void ResetTimeOffsets(); + + static long long GetCurrentSystemTime(); + static void WaitUntil(long long time); + void FrameWaitforDisplay(long long pts); + @@ -197,14 +205,30 @@ class VideoVPEOGL : public Video, public Thread_TYPE int EnterIframePlayback(); bool iframemode; - UINT DeliverMediaPacket(MediaPacket packet, - const UCHAR* bulibaver, - UINT *samplepos); + UINT DeliverMediaPacket(MediaPacket packet,const UCHAR* bulibaver,UINT *samplepos); + int decoding_backend; //1 omx, 2 libav, 3 omx through lib av transcoder #define VPE_DECODER_OMX 1 #define VPE_DECODER_libav 2 #define VPE_DECODER_OMX_libav_TRANSCODE 3 + + bool offsetnotset; + bool offsetvideonotset; + bool offsetaudionotset; + long long startoffset; + long long lastrefvideotime; + long long lastrefaudiotime; + OMX_TICKS lastreftimeOMX; + ULLONG lastreftimePTS; + + long long playbacktimeoffset; //this is the offset between the media time and system clock + long long pausetimecode; + bool paused; + + + + #ifdef VPE_OMX_SUPPORT static OMX_ERRORTYPE EventHandler_OMX(OMX_IN OMX_HANDLETYPE handle,OMX_IN OMX_PTR appdata, OMX_IN OMX_EVENTTYPE event_type,OMX_IN OMX_U32 data1, -- 2.39.2