From ba8fa8b9be55cc6be8a426ac0c4fc970c8f6dd48 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Mon, 3 Sep 2012 01:34:34 +0200 Subject: [PATCH] Remove legacy output code and enhance new Stream interface --- GNUmakefile | 2 +- afeed.cc | 1 + audiovpe.cc => audioomx.cc | 141 +- audiovpe.h => audioomx.h | 18 +- defines.h | 4 +- draintarget.h | 2 + glmocoshader.cc | 823 -------- glmocoshader.h | 61 - glyuv400shader.cc | 124 -- glyuv400shader.h | 46 - glyuv444shader.cc | 106 - glyuv444shader.h | 45 - main.cc | 4 +- osdopengl.cc | 88 +- osdopengl.h | 8 +- stream.cc | 2 +- videoomx.cc | 1995 +++++++++++++++++++ videovpeogl.h => videoomx.h | 219 +-- videovpeogl.cc | 3630 ----------------------------------- 19 files changed, 2121 insertions(+), 5198 deletions(-) rename audiovpe.cc => audioomx.cc (92%) rename audiovpe.h => audioomx.h (89%) mode change 100755 => 100644 draintarget.h delete mode 100755 glmocoshader.cc delete mode 100755 glmocoshader.h delete mode 100755 glyuv400shader.cc delete mode 100755 glyuv400shader.h delete mode 100755 glyuv444shader.cc delete mode 100755 glyuv444shader.h mode change 100755 => 100644 main.cc create mode 100644 videoomx.cc rename videovpeogl.h => videoomx.h (50%) delete mode 100644 videovpeogl.cc diff --git a/GNUmakefile b/GNUmakefile index c7812ee..f15195c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -58,7 +58,7 @@ $(info Raspberry pi flags) LDFLAGS = -Wall LIBS = -L/opt/vc/lib -lpthread -lrt -lEGL -lGLESv2 -lopenmaxil -lbcm_host -lavformat -lavcodec -lavutil -OBJECTS += main.o threadp.o osdopengl.o surfaceopengl.o ledraspberry.o mtdraspberry.o videovpeogl.o audiovpe.o wjpegsimple.o remotelinux.o glshader.o glosdshader.o glyuv400shader.o glyuv444shader.o glmocoshader.o +OBJECTS += main.o threadp.o osdopengl.o surfaceopengl.o ledraspberry.o mtdraspberry.o videoomx.o audioomx.o wjpegsimple.o remotelinux.o glshader.o glosdshader.o LIBS+= -ljpeg CROSSLIBS = INCLUDES = -DVOMP_PLATTFORM_RASPBERRY -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads diff --git a/afeed.cc b/afeed.cc index 3649d39..ba24e52 100644 --- a/afeed.cc +++ b/afeed.cc @@ -80,6 +80,7 @@ void AFeed::threadMethod() if (alen) { //Log::getInstance()->log("Afeed", Log::DEBUG, "written"); + cb.call(this); } else { diff --git a/audiovpe.cc b/audioomx.cc similarity index 92% rename from audiovpe.cc rename to audioomx.cc index 2e544cf..87a82d2 100644 --- a/audiovpe.cc +++ b/audioomx.cc @@ -18,13 +18,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "audiovpe.h" -#include "videovpeogl.h" +#include "audioomx.h" +#include "videoomx.h" #include "log.h" #include "vdr.h" #include "woptionpane.h" -AudioVPE::AudioVPE() +AudioOMX::AudioOMX() { initted = 0; streamType = 0; @@ -55,11 +55,11 @@ AudioVPE::AudioVPE() } -AudioVPE::~AudioVPE() +AudioOMX::~AudioOMX() { } -int AudioVPE::init(UCHAR tstreamType) { +int AudioOMX::init(UCHAR tstreamType) { if (initted) return 0; initted = 1; @@ -95,12 +95,12 @@ int AudioVPE::init(UCHAR tstreamType) { return 1; } -int AudioVPE::initAllParams() +int AudioOMX::initAllParams() { return (setStreamType(streamType) && setChannel() && setSource()); } -int AudioVPE::shutdown() +int AudioOMX::shutdown() { if (!initted) return 0; initted = 0; @@ -111,7 +111,7 @@ int AudioVPE::shutdown() return 1; } -bool AudioVPE::loadOptionsfromServer(VDR* vdr) +bool AudioOMX::loadOptionsfromServer(VDR* vdr) { Log::getInstance()->log("Audio", Log::DEBUG, "AudioOMX config load"); char *name=vdr->configLoad("AudioOMX","AC3DecodingMode"); @@ -165,7 +165,7 @@ bool AudioVPE::loadOptionsfromServer(VDR* vdr) } -bool AudioVPE::handleOptionChanges(Option* option) +bool AudioOMX::handleOptionChanges(Option* option) { if (Audio::handleOptionChanges(option)) return true; @@ -221,7 +221,7 @@ bool AudioVPE::handleOptionChanges(Option* option) } -bool AudioVPE::saveOptionstoServer() +bool AudioOMX::saveOptionstoServer() { switch (prefered_ac3) { @@ -279,7 +279,7 @@ bool AudioVPE::saveOptionstoServer() UINT numChoices, UINT defaultChoice, UINT startInt, const char * const * options, const char * const * optionkeys = NULL, AbstractOption* handler=NULL);*/ -bool AudioVPE::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane) +bool AudioOMX::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane) { if (!Audio::addOptionsToPanes(panenumber,options,pane)) return false; @@ -366,16 +366,16 @@ bool AudioVPE::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pa -OMX_ERRORTYPE AudioVPE::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer){ +OMX_ERRORTYPE AudioOMX::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer){ //Log::getInstance()->log("Audio", Log::NOTICE, "EmptyBufferDone"); - AudioVPE *audio=(AudioVPE *)getInstance(); + AudioOMX *audio=(AudioOMX *)getInstance(); audio->ReturnEmptyOMXBuffer(buffer); return OMX_ErrorNone; } -void AudioVPE::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){ +void AudioOMX::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){ input_bufs_omx_mutex.Lock(); //Log::getInstance()->log("Audio", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size()); input_bufs_omx_free.push_back(buffer); @@ -383,14 +383,14 @@ void AudioVPE::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){ input_bufs_omx_mutex.Unlock(); } - OMX_ERRORTYPE AudioVPE::FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer) { + OMX_ERRORTYPE AudioOMX::FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer) { Log::getInstance()->log("Audio", Log::NOTICE, "FillBufferDone"); return OMX_ErrorNone; } -int AudioVPE::setStreamType(UCHAR type) +int AudioOMX::setStreamType(UCHAR type) { if (!initted) return 0; @@ -398,7 +398,7 @@ int AudioVPE::setStreamType(UCHAR type) return 1; } -int AudioVPE::setChannel() +int AudioOMX::setChannel() { if (!initted) return 0; @@ -406,7 +406,7 @@ int AudioVPE::setChannel() return 1; } -int AudioVPE::setSource() +int AudioOMX::setSource() { if (!initted) return 0; @@ -414,7 +414,7 @@ int AudioVPE::setSource() return 1; } -int AudioVPE::sync() +int AudioOMX::sync() { if (!initted) return 0; @@ -422,7 +422,7 @@ int AudioVPE::sync() return 1; } -int AudioVPE::play() { +int AudioOMX::play() { if (!initted) return 0; lastAType=MPTYPE_MPEG_AUDIO; @@ -435,7 +435,7 @@ int AudioVPE::play() { } -int AudioVPE::ChangeAudioDestination() //clock aka omx mutex needs to be locked +int AudioOMX::ChangeAudioDestination() //clock aka omx mutex needs to be locked { OMX_ERRORTYPE error; const char * destinations[]={"local","hdmi"}; @@ -461,7 +461,7 @@ int AudioVPE::ChangeAudioDestination() //clock aka omx mutex needs to be locked } -int AudioVPE::ChangeAudioPortConfig() //clock aka omx mutex needs to be locked +int AudioOMX::ChangeAudioPortConfig() //clock aka omx mutex needs to be locked { OMX_ERRORTYPE error; //Ok first fidle a working configuration @@ -529,7 +529,7 @@ int AudioVPE::ChangeAudioPortConfig() //clock aka omx mutex needs to be locked DeAllocateCodecsOMX(); return 0; }*/ - VideoVPEOGL *video=(VideoVPEOGL*)Video::getInstance(); + VideoOMX *video=(VideoOMX*)Video::getInstance(); if (!omx_running) { @@ -573,8 +573,9 @@ int AudioVPE::ChangeAudioPortConfig() //clock aka omx mutex needs to be locked } -int AudioVPE::InitDecoderLibAV() +int AudioOMX::InitDecoderLibAV() { + libav_mutex.Lock(); ac3codec_context_libav = avcodec_alloc_context3(ac3codec_libav); if (!ac3codec_context_libav) { Log::getInstance()->log("Audio", Log::DEBUG, "Alloc avcodec for ac3 decoding context failed!"); @@ -587,12 +588,14 @@ int AudioVPE::InitDecoderLibAV() int avc_ret = avcodec_open2(ac3codec_context_libav, ac3codec_libav, NULL); if (avc_ret < 0) { Log::getInstance()->log("Audio", Log::DEBUG, "Opening libav codec failed \n"); + libav_mutex.Unlock(); return 0; } mp23codec_context_libav = avcodec_alloc_context3(mp23codec_libav); if (!ac3codec_context_libav) { Log::getInstance()->log("Audio", Log::DEBUG, "Alloc avcodec for mp23 decoding context failed!"); + libav_mutex.Unlock(); return 0; } @@ -602,39 +605,46 @@ int AudioVPE::InitDecoderLibAV() avc_ret = avcodec_open2(mp23codec_context_libav, mp23codec_libav, NULL); if (avc_ret < 0) { Log::getInstance()->log("Audio", Log::DEBUG, "Opening libav codec failed \n"); + libav_mutex.Unlock(); return 0; } av_init_packet(&incoming_paket_libav); decode_frame_libav=avcodec_alloc_frame(); + libav_mutex.Unlock(); return 1; } -void AudioVPE::DeinitDecoderLibAV() { +void AudioOMX::DeinitDecoderLibAV() { + libav_mutex.Lock(); if (ac3codec_context_libav) { avcodec_close(ac3codec_context_libav); av_free(ac3codec_context_libav); ac3codec_context_libav = NULL; av_free(decode_frame_libav); + avcodec_close(mp23codec_context_libav); + av_free(mp23codec_context_libav); + mp23codec_context_libav = NULL; } + libav_mutex.Unlock(); } -int AudioVPE::AllocateCodecsOMX() +int AudioOMX::AllocateCodecsOMX() { OMX_ERRORTYPE error; - static OMX_CALLBACKTYPE callbacks= {&VideoVPEOGL::EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX}; + static OMX_CALLBACKTYPE callbacks= {&VideoOMX::EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX}; Log::getInstance()->log("Audio", Log::NOTICE, "Allocate Codecs OMX"); //Clock, move later to audio - VideoVPEOGL *video=(VideoVPEOGL*)Video::getInstance(); + VideoOMX *video=(VideoOMX*)Video::getInstance(); if (!InitDecoderLibAV()) return 0;; @@ -853,9 +863,9 @@ int AudioVPE::AllocateCodecsOMX() -int AudioVPE::PrepareInputBufsOMX() //needs to be called with locvke omx clock mutex +int AudioOMX::PrepareInputBufsOMX() //needs to be called with locvke omx clock mutex { - VideoVPEOGL *video=(VideoVPEOGL*)Video::getInstance(); + VideoOMX *video=(VideoOMX*)Video::getInstance(); OMX_ERRORTYPE error; OMX_PARAM_PORTDEFINITIONTYPE port_def_type; memset(&port_def_type,0,sizeof(port_def_type)); @@ -911,7 +921,7 @@ int AudioVPE::PrepareInputBufsOMX() //needs to be called with locvke omx clock m return 1; } -int AudioVPE::DestroyInputBufsOMX() //call with clock mutex locked +int AudioOMX::DestroyInputBufsOMX() //call with clock mutex locked { OMX_ERRORTYPE error; @@ -933,13 +943,13 @@ int AudioVPE::DestroyInputBufsOMX() //call with clock mutex locked } -int AudioVPE::DeAllocateCodecsOMX() +int AudioOMX::DeAllocateCodecsOMX() { OMX_ERRORTYPE error; omx_running=false; - VideoVPEOGL *video=(VideoVPEOGL*)Video::getInstance(); + VideoOMX *video=(VideoOMX*)Video::getInstance(); Log::getInstance()->log("Audio", Log::DEBUG, "enter deallocatecodecsomx"); - DeinitDecoderLibAV(); + video->LockClock(); if (cur_input_buf_omx) { @@ -1005,7 +1015,8 @@ int AudioVPE::DeAllocateCodecsOMX() Log::getInstance()->log("Audio", Log::DEBUG, "flush cmd clock shed failed"); } - DestroyInputBufsOMX(); + DestroyInputBufsOMX(); //We have to make sure that no buffers are in use + DeinitDecoderLibAV(); //todo flushing if (!video->DisablePort(omx_aud_rend,omx_rend_input_port,true)) { @@ -1066,7 +1077,11 @@ int AudioVPE::DeAllocateCodecsOMX() if (error!=OMX_ErrorNone) { Log::getInstance()->log("Audio", Log::DEBUG, "FreeHandle failed %d", error); } - } else video->UnlockClock(); + } else { + + video->UnlockClock(); + DeinitDecoderLibAV(); + } Log::getInstance()->log("Audio", Log::DEBUG, "leave deallocate codecs OMX"); return 1; @@ -1074,7 +1089,7 @@ int AudioVPE::DeAllocateCodecsOMX() -int AudioVPE::stop() +int AudioOMX::stop() { if (!initted) return 0; @@ -1084,7 +1099,7 @@ int AudioVPE::stop() return 1; } -int AudioVPE::mute() +int AudioOMX::mute() { if (!initted) return 0; @@ -1095,7 +1110,7 @@ int AudioVPE::mute() return 1; } -int AudioVPE::unMute() +int AudioOMX::unMute() { if (!initted) return 0; @@ -1106,12 +1121,12 @@ int AudioVPE::unMute() return 1; } -int AudioVPE::pause() { +int AudioOMX::pause() { if (!initted) return 0; if (!paused) { paused = true; - VideoVPEOGL *vw = (VideoVPEOGL*) Video::getInstance(); + VideoOMX *vw = (VideoOMX*) Video::getInstance(); vw->LockClock(); OMX_ERRORTYPE error; error = OMX_SendCommand(omx_aud_rend, OMX_CommandFlush, @@ -1127,18 +1142,18 @@ int AudioVPE::pause() { return 1; } -int AudioVPE::unPause() +int AudioOMX::unPause() { if (!initted) return 0; if (paused) { paused=false; // may be also change omx clock - VideoVPEOGL *vw = (VideoVPEOGL*) Video::getInstance(); + VideoOMX *vw = (VideoOMX*) Video::getInstance(); vw->clockUnpause(); } return 1; } -int AudioVPE::reset() +int AudioOMX::reset() { if (!initted) return 0; //test(); @@ -1153,7 +1168,7 @@ int AudioVPE::reset() return 1; } -int AudioVPE::setVolume(int tvolume) +int AudioOMX::setVolume(int tvolume) { // parameter: 0 for silence, 20 for full if ((tvolume < 0) || (tvolume > 20)) return 0; @@ -1185,7 +1200,7 @@ int AudioVPE::setVolume(int tvolume) } #ifdef DEV -int AudioVPE::test() +int AudioOMX::test() { // ULLONG stc = 0; // return ioctl(fdAudio, AV_SET_AUD_STC, &stc); @@ -1205,12 +1220,12 @@ int AudioVPE::test() } #endif -void AudioVPE::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos) +void AudioOMX::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos) { packet = mplist.front(); } -UINT AudioVPE::DeliverMediaSample(UCHAR* buffer, UINT* samplepos) { +UINT AudioOMX::DeliverMediaSample(UCHAR* buffer, UINT* samplepos) { DeliverMediaPacket(packet, buffer, samplepos); if (*samplepos == packet.length) { *samplepos = 0; @@ -1220,9 +1235,9 @@ UINT AudioVPE::DeliverMediaSample(UCHAR* buffer, UINT* samplepos) { } -long long AudioVPE::correctAudioLatency(long long pts,int addsamples,int srate) { +long long AudioOMX::correctAudioLatency(long long pts,int addsamples,int srate) { - VideoVPEOGL *video = (VideoVPEOGL*) Video::getInstance(); + VideoOMX *video = (VideoOMX*) Video::getInstance(); video->LockClock(); OMX_PARAM_U32TYPE audio_lat; OMX_ERRORTYPE error; @@ -1255,10 +1270,10 @@ long long AudioVPE::correctAudioLatency(long long pts,int addsamples,int srate) -UINT AudioVPE::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, +UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos) { /*First Check, if we have an audio sample*/ - VideoVPEOGL *vw = (VideoVPEOGL*) Video::getInstance(); + VideoOMX *vw = (VideoOMX*) Video::getInstance(); bool achange=false; OMX_ERRORTYPE error; Log *logger=Log::getInstance(); @@ -1414,8 +1429,20 @@ UINT AudioVPE::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, while (haveToCopy> 0 && errcount<2) { //Log::getInstance()->log("Audio", Log::DEBUG,"libav in %d %d",framesize,current_context->frame_size); + libav_mutex.Lock(); + if (!omx_running || !mp23codec_context_libav || !ac3codec_context_libav) { + libav_mutex.Unlock(); + return 0; + } + Log::getInstance()->log("Audio", Log::DEBUG,"libav in %d %d",framesize,current_context->frame_size); len = avcodec_decode_audio4(current_context, decode_frame_libav, &gotta, &incoming_paket_libav); + Log::getInstance()->log("Audio", Log::DEBUG,"libav out"); + if (!omx_running) { + libav_mutex.Unlock(); + return 0; + } + libav_mutex.Unlock(); // Log::getInstance()->log("Audio", Log::DEBUG,"libav out"); if (len>0) { incoming_paket_libav.data += len; @@ -1459,7 +1486,7 @@ UINT AudioVPE::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, Log::getInstance()->log("Audio", Log::DEBUG, "Deliver MediaPacket no free sample"); MILLISLEEP(5); - if (!omx_running) return false; + if (!omx_running) return 0; continue; } cur_input_buf_omx = input_bufs_omx_free.front(); @@ -1509,13 +1536,13 @@ UINT AudioVPE::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, -long long AudioVPE::SetStartOffset(long long curreftime, bool *rsync){ - VideoVPEOGL *vw=(VideoVPEOGL*)Video::getInstance(); +long long AudioOMX::SetStartOffset(long long curreftime, bool *rsync){ + VideoOMX *vw=(VideoOMX*)Video::getInstance(); return vw->SetStartAudioOffset(curreftime,rsync); } -void AudioVPE::ResetTimeOffsets() { - VideoVPEOGL *vw=(VideoVPEOGL*)Video::getInstance(); +void AudioOMX::ResetTimeOffsets() { + VideoOMX *vw=(VideoOMX*)Video::getInstance(); vw->ResetTimeOffsets(); } diff --git a/audiovpe.h b/audioomx.h similarity index 89% rename from audiovpe.h rename to audioomx.h index 7524c2e..526e3d7 100644 --- a/audiovpe.h +++ b/audioomx.h @@ -1,5 +1,5 @@ /* - Copyright 2004-2005 Chris Tallon, 2009 Marten Richter + Copyright 2004-2005 Chris Tallon, 2009,2012 Marten Richter This file is part of VOMP. @@ -18,8 +18,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef AUDIOVPE_H -#define AUDIOVPE_H +#ifndef AUDIOOMX_H +#define AUDIOOMX_H #include #include @@ -28,7 +28,7 @@ #include "defines.h" #include "audio.h" -#include "videovpeogl.h" +#include "videoomx.h" extern "C" { #include @@ -38,11 +38,11 @@ extern "C" { -class AudioVPE : public Audio +class AudioOMX : public Audio { public: - AudioVPE(); - virtual ~AudioVPE(); + AudioOMX(); + virtual ~AudioOMX(); int init(UCHAR streamType); int shutdown(); @@ -70,6 +70,8 @@ class AudioVPE : public Audio virtual long long SetStartOffset(long long curreftime, bool *rsync); virtual void ResetTimeOffsets(); + virtual bool DrainTargetReady() {return omx_running;}; + UCHAR getLastAType() {return lastAType;} @@ -148,6 +150,7 @@ class AudioVPE : public Audio bool omx_running; bool omx_first_frame; + Mutex libav_mutex; AVCodec *ac3codec_libav; AVCodecContext *ac3codec_context_libav; @@ -157,6 +160,7 @@ class AudioVPE : public Audio AVFrame *decode_frame_libav; + int InitDecoderLibAV(); void DeinitDecoderLibAV(); diff --git a/defines.h b/defines.h index 1cb045d..2c8174a 100644 --- a/defines.h +++ b/defines.h @@ -92,8 +92,8 @@ long long getTimeMS(); #define Led_TYPE LedRaspberry //this is device dependent #define Osd_TYPE OsdOpenGL // This OpenGL ES 2.0, in the moment only for raspberry, but might be splitted for other devices #define OsdStartDev "" - #define Audio_TYPE AudioVPE // This is Audio based on VPE (Vomp Presentation Engine) should support OpenMax and libav for decoding - #define Video_TYPE VideoVPEOGL // This is Video based on VPE (Vomp Presentation Engine) should support OpenMax + #define Audio_TYPE AudioOMX // This is Audio based on OpenMax and libav for decoding + #define Video_TYPE VideoOMX // This is Video based on OpenMax diff --git a/draintarget.h b/draintarget.h old mode 100755 new mode 100644 index 8457241..9e2032a --- a/draintarget.h +++ b/draintarget.h @@ -68,6 +68,8 @@ class DrainTarget virtual long long SetStartOffset(long long curreftime, bool *rsync)=0; virtual void ResetTimeOffsets()=0; + virtual bool DrainTargetReady() {return false;}; //if the draintarget is blocking in paused state, this tells that it is ready to rumble + virtual bool dtsTimefix(){return false;} //determines if the draintargets needs a mixure of pts and dts or not // The following two functions are used by the Stream diff --git a/glmocoshader.cc b/glmocoshader.cc deleted file mode 100755 index 11df477..0000000 --- a/glmocoshader.cc +++ /dev/null @@ -1,823 +0,0 @@ -/* - Copyright 2012 Marten Richter - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#include "glmocoshader.h" -#include "videovpeogl.h" - -#define BLOCK_TEXTURE_WIDTH 2048 -#define BLOCK_TEXTURE_HEIGHT 1024 -#define BLOCK_SIZE 64 -#define BLOCK_PER_ROW (32) - -// This implementation is for framed coded pictures only! -// I did not find any DVB recording with field coded pictures -// so I do not think they exist here, anyway I suspect we -// need a totally different shader in this case -// so first write the frame coded shader -// and then later add if necessary field based support. - -const GLchar moco_vertex_shader[] = - "attribute vec4 block_pos;\n" - "attribute vec2 block_edge;\n" - "attribute vec4 block_types;\n" - "attribute vec2 index;\n" - "attribute vec4 PMV1;\n" - "attribute vec4 PMV2;\n" - "attribute float cbp;\n" - "uniform vec2 pict_scale;\n" - // "attribute vec2 tex_coord;\n" - "varying vec4 out_yblockpos_x;\n" - "varying vec4 out_yblockpos_y;\n" - "varying vec4 out_uvblockpos_xy;\n" - "varying vec2 out_block_edge;\n" - "varying vec4 out_misc_info;\n" - - "varying float out_unsupported;\n" - "varying vec4 out_moco_pos;\n" - "varying vec4 out_moco_forward;\n" - "varying vec4 out_moco_backward;\n" - - - "const float one=1.0;\n" - "const float czero=0.0;\n" - "const float chalf=0.5;\n" - "const float c1024=1024.0;\n" - "const float c32=32.0;\n" - // "const float c1over32=0.03125;\n" - "const float c1over32=1./32.;\n" - - - "const float c65536=65536.;\n" - - - - "const vec4 y_cbp=vec4(1.0,2.0,4.0,8.0);\n" - "const vec3 uv_cbp=vec3(16.0,32.0,64.0);\n" - "void main()\n" - "{\n" - // calculate cbp - //" vec4 cbp_vec=vec4(cbp,cbp,cbp,cbp);\n" - - // old cbp code - // " vec4 fmod_cbp_y=mod(cbp_vec,y_cbp);\n" - // " vec2 fmod_cbp_uv=mod(cbp_vec.xy,uv_cbp.xy);\n" - // " fmod_cbp_y.x=0.;\n" - // " fmod_cbp_y=sign(vec4(fmod_cbp_y.yzw,fmod_cbp_uv.x)-fmod_cbp_y);\n" - // " fmod_cbp_uv=sign(vec2(fmod_cbp_uv.y,cbp)-fmod_cbp_uv);\n" - // resulting vector should indicate with block is present - // now transform it to a sum (TODO vectorize this) - -//this code is better but nor really working - /* " vec4 fmod_cbp_y=mod(cbp_vec,vec4(uv_cbp.zyx,y_cbp.w));\n" - " vec2 fmod_cbp_uv=mod(cbp_vec.xy,y_cbp.zy);\n" - " fmod_cbp_y=vec4(lessThanEqual(vec4(uv_cbp.yx,y_cbp.wz),fmod_cbp_y));\n" - " fmod_cbp_uv=vec2(lessThanEqual(y_cbp.yx,fmod_cbp_uv));\n" - - " vec4 fmod_cbp_y2=fmod_cbp_y;\n" - " vec2 fmod_cbp_uv2=fmod_cbp_uv;\n" - " fmod_cbp_y2.y+=fmod_cbp_y2.x;\n" - " fmod_cbp_y2.z+=fmod_cbp_y2.y;\n" - " fmod_cbp_y2.w+=fmod_cbp_y2.z;\n" - " fmod_cbp_uv2.x+=fmod_cbp_y2.w;\n" - " fmod_cbp_uv2.y+=fmod_cbp_uv2.x;\n"*/ - - - " float tcbp=cbp;\n" - " float tpos=czero;\n" - " vec4 fmod_cbp_y=vec4(czero,czero,czero,czero);\n" - " vec2 fmod_cbp_uv=vec2(czero,czero);\n" - " vec4 fmod_cbp_y2=vec4(czero,czero,czero,czero);\n" - " vec2 fmod_cbp_uv2=vec2(czero,czero);\n" - " if (tcbp>=uv_cbp.y){\n" - " fmod_cbp_y.x=one;\n" - " fmod_cbp_y2.x=tpos;\n" - " tpos++;\n" - " tcbp-=uv_cbp.y;\n" - " }\n" - " if (tcbp>=uv_cbp.x){\n" - " fmod_cbp_y.y=one;\n" - " fmod_cbp_y2.y=tpos;\n" - " tpos++;\n" - " tcbp-=uv_cbp.x;\n" - " }\n" - " if (tcbp>=y_cbp.w){\n" - " fmod_cbp_y.z=one;\n" - " fmod_cbp_y2.z=tpos;\n" - " tpos++;\n" - " tcbp-=y_cbp.w;\n" - " }\n" - " if (tcbp>=y_cbp.z){\n" - " fmod_cbp_y.w=one;\n" - " fmod_cbp_y2.w=tpos;\n" - " tpos++;\n" - " tcbp-=y_cbp.z;\n" - " }\n" - " if (tcbp>=y_cbp.y){\n" - " fmod_cbp_uv.x=one;\n" - " fmod_cbp_uv2.x=tpos;\n" - " tpos++;\n" - " tcbp-=y_cbp.y;\n" - " }\n" - " if (tcbp>=y_cbp.x){\n" - " fmod_cbp_uv.y=one;\n" - " fmod_cbp_uv2.y=tpos;\n" - // " tpos++;\n" - // " tcbp-=y_cbp.y;\n" - " }\n" - - - - - - - - - // now calculate their position inside the short array - " float m_index=index.x/*+index.y*c65536*/;\n" //Not Endian save - " fmod_cbp_y2+=m_index;\n" //shift to the blocks - " fmod_cbp_uv2+=m_index;\n" - - " out_yblockpos_y=floor((fmod_cbp_y2)*c1over32);\n" - " out_uvblockpos_xy.zw=floor((fmod_cbp_uv2)*c1over32);\n" - " out_yblockpos_x=fmod_cbp_y2-c32*out_yblockpos_y;\n" - " out_uvblockpos_xy.xy=fmod_cbp_uv2-c32*out_uvblockpos_xy.zw;\n" - - - - //Kick out uncoded blocks - // " out_yblockpos_y-=sign(fmod_cbp_y-one)*c1024;\n" - // " out_uvblockpos_xy.zw-=sign(fmod_cbp_uv-one)*c1024;\n" - - " out_yblockpos_y=mix(vec4(c1024,c1024,c1024,c1024),out_yblockpos_y,fmod_cbp_y);\n" - " out_uvblockpos_xy.zw=mix(vec2(c1024,c1024),out_uvblockpos_xy.zw,fmod_cbp_uv);\n" - - - // set start positions - // " vec4 motion_vertical=vec4(block_types.z,block_types.z,block_types.z,block_types.z);\n" - // " vec4 mod_motion_vertical=mod(motion_vertical,vec4(y_cbp.yzw,uv_cbp.x));\n" - // " mod_motion_vertical=vec4(lessThanEqual(y_cbp,mod_motion_vertical));\n" - - " out_moco_pos.xy=(block_pos.xy+block_edge.xy)*uv_cbp.x/*16*/+one;" - " out_unsupported=czero;\n" - " out_moco_pos.zw=vec2(czero,czero);\n" - " out_misc_info.y=one;\n" // this is the y step - " if (block_types.xy_cbp.z /* 4*/) {\n" - " out_moco_pos.zw=vec2(chalf,chalf);\n" - //" out_unsupported=2.;\n" - " } else if (forward_backward>y_cbp.y /* 2*/ ) {\n" //backward - " out_moco_pos.zw=vec2(czero,one);\n" - //" out_unsupported=2.;\n" - " } else {\n" //forward - " out_moco_pos.zw=vec2(one,czero);\n" - " } \n" - " if ((out_moco_pos.w+out_moco_pos.z)>y_cbp.x) {" - " out_moco_pos.zw*=chalf;\n" - " }\n" - " if (block_types.y==y_cbp.y /*2*/) {" //Frame - " out_moco_forward=vec4(PMV1.xy,PMV1.xy);\n" - " out_moco_backward=vec4(PMV1.zw,PMV1.zw);\n" - //" out_unsupported=2.;\n" - " } else if (block_types.y==y_cbp.x /*1*/) {" //Field - " out_moco_forward=vec4(PMV1.xy,PMV2.xy);\n" - " out_moco_backward=vec4(PMV1.zw,PMV2.zw);\n" - - " float motion_vert=block_types.z;\n" - " out_moco_forward.w-=one;\n" - " out_moco_backward.w-=one;\n" - " if (motion_vert>= y_cbp.w) {\n" //second_backward - " motion_vert-=y_cbp.w;\n" - " out_moco_backward.w+=one;\n" - " }\n" - " if (motion_vert>= y_cbp.z) {\n" //second_forward - " motion_vert-=y_cbp.z;\n" - " out_moco_forward.w+=one;\n" - " }\n" - " if (motion_vert>= y_cbp.y) {\n" //first_backward - " motion_vert-=y_cbp.y;\n" - " out_moco_backward.y+=one;\n" - " }\n" - " if (motion_vert>= y_cbp.x) {\n" //second_forward - //" motion_vert-=y_cbp.z;\n" - " out_moco_forward.y+=one;\n" - " }\n" - /* " out_moco_forward.y+=mod_motion_vertical.x;\n" - " out_moco_backward.y+=mod_motion_vertical.y;\n" - " out_moco_forward.w-=one-mod_motion_vertical.z;\n" - " out_moco_backward.w-=one-mod_motion_vertical.w;\n"*/ - " out_misc_info.y=one;\n" // step to for field based - // " out_unsupported=2.;\n" - " } else {\n" - " out_unsupported=1.;\n" - " }\n" - " }\n" - // " if (cbp==63. || cbp==0.) out_unsupported=2.;\n" - // " if (fmod_cbp_y.w==1. && mod(cbp,8.)>=4.) out_unsupported=2.;\n" - - - - - " out_block_edge=block_edge;\n" - " out_misc_info.x=block_types.w;\n" - " vec4 out_pos=block_pos;\n" - " out_pos.xy+=block_edge;\n" - " out_pos.xy*=pict_scale;\n" - " out_pos.xy-=vec2(one,one);" - " out_pos.zw=vec2(one,one);" - " gl_Position=out_pos;\n" - "}\n"; - -const GLchar moco_frag_shader[] = - "precision mediump float;\n" - "uniform sampler2D blocks;\n" - "uniform sampler2D forward_pic;\n" - "uniform sampler2D backward_pic;\n" - "uniform vec2 pict_size;\n" - "varying vec4 out_yblockpos_x;\n" - "varying vec4 out_yblockpos_y;\n" - "varying vec4 out_uvblockpos_xy;\n" - "varying vec2 out_block_edge;\n" - "varying vec4 out_misc_info;\n"// misc info x= DCT info, y= field based offsets - "varying float out_unsupported;\n" - "varying vec4 out_moco_forward;\n" - "varying vec4 out_moco_backward;\n" - "varying vec4 out_moco_pos;\n" - - "const float halfst=0.5;\n" - "const float ctwo=2.0;\n" - "const float cone=1.0;\n" - "const float czero=0.0;\n" - "const float sieben=7.0;\n" - "const float acht=8.0;\n" - "const float s8=1./8.;\n" - "const float s16=1./16.;\n" - "const float c1over2048=1./2048.;\n" - "const float c1over1024=1./1024.;\n" - "const float c255=255.;\n" - "const float c65280=65280.;\n" - "const float c65536=65536.;\n" - "const float cstep=32767.;\n" - "\n" - "float unpack_short(vec2 income) {\n" - " float temp=income.y*c65280+income.x*c255;\n" - " temp-=step(cstep,temp)*c65536;\n" - " return temp/c255;\n" - "}" - // "uniform sampler2D textureV;\n" - // "uniform sampler2D textureY;\n" -// "varying vec2 out_texCoord;\n" - "void main()\n" - "{\n" - // first figure out the block num for y, first decide between up and down, fix me field - //non field code - " vec4 ypos_temp1;\n" - " vec4 our_fragcol=vec4(czero,czero,czero,cone);\n" - " bool upper_half;\n" - " float line_step;\n" - " if (out_misc_info.x!=0.) {\n" //test the dct type - " upper_half=mod(floor(out_block_edge.y*acht),ctwo)==cone;\n" - " line_step=cone;\n" - "}else{\n" - " upper_half=halfsthalfst);\n" - " bool subsample=mod(ypos_temp3.x,ctwo)==cone;\n" - " ypos_temp2.x*=halfst;\n" - " ypos_temp2.xy*=c1over1024;\n" - " ypos_temp1=texture2D(blocks,ypos_temp2.xy);\n" // now select the right data - "if (subsample){\n" - " ypos_temp3.xy=ypos_temp1.zw;\n" - //" ypos_temp2=vec2(cone,0.);\n" - " }else {\n" - " ypos_temp3.xy=ypos_temp1.xy;\n" - " }\n" - " our_fragcol.r=unpack_short(ypos_temp3.xy);\n" - - //now uv - " ypos_temp3=floor(out_block_edge*acht);\n" - " ypos_temp2.yw=floor(out_uvblockpos_xy.zw);\n" - " ypos_temp2.xz=(ypos_temp3.x+(ypos_temp3.y+acht*(out_uvblockpos_xy.xy))*acht);\n" - //" subsample=(mod(ypos_temp2.x,ctwo)>halfst);\n" - " subsample=mod(ypos_temp3.x,ctwo)==cone;\n" - " ypos_temp2.xz*=halfst;\n" - " ypos_temp2*=c1over1024;\n" - - " ypos_temp1=texture2D(blocks,ypos_temp2.xy);\n" // now select the right data - " if (subsample){\n" - " ypos_temp3.xy=ypos_temp1.zw;\n" - " }else {\n" - " ypos_temp3.xy=ypos_temp1.xy;\n" - " }\n" - " our_fragcol.g=unpack_short(ypos_temp3.xy);\n" - - " ypos_temp1=texture2D(blocks,ypos_temp2.zw);\n" // now select the right data - //" if (subsample){\n" - " ypos_temp3.xy=ypos_temp1.zw;\n" - //" }else {\n" - " ypos_temp3.xy=ypos_temp1.xy;\n" - //" }\n" - " our_fragcol.b=unpack_short(ypos_temp3.rg);\n" - - //MOCO - // decide if it is top or bottom - " vec4 moco_work;\n" - " if (mod(floor(out_moco_pos.y),ctwo)!=cone) {\n" - " moco_work=vec4(out_moco_forward.xy,out_moco_backward.xy);\n" - "} else {\n" - " moco_work=vec4(out_moco_forward.zw,out_moco_backward.zw);\n" - "}\n" - // now we handle the y fetching - " vec4 moco_temp;\n" - " vec4 subpixel=floor(mod(moco_work,ctwo))*halfst; \n" - " moco_temp=floor(moco_work*halfst)+floor(vec4(out_moco_pos.xy,out_moco_pos.xy));\n" - " vec4 c00,c01,c10,c11;\n" - - " c00=texture2D(forward_pic,moco_temp.xy*pict_size);\n" - " c01=texture2D(forward_pic,(moco_temp.xy+vec2(czero,out_misc_info.y))*pict_size);\n" - " c10=texture2D(forward_pic,(moco_temp.xy+vec2(cone,czero))*pict_size);\n" - " c11=texture2D(forward_pic,(moco_temp.xy+vec2(cone,out_misc_info.y))*pict_size);\n" - " our_fragcol.r+=mix(mix(c00.r,c10.r,subpixel.x),mix(c01.r,c11.r,subpixel.x),subpixel.y)*out_moco_pos.z;\n" - - - " c00=texture2D(backward_pic,moco_temp.zw*pict_size);\n"//backward - " c01=texture2D(backward_pic,(moco_temp.zw+vec2(czero,out_misc_info.y))*pict_size);\n" - " c10=texture2D(backward_pic,(moco_temp.zw+vec2(cone,czero))*pict_size);\n" - " c11=texture2D(backward_pic,(moco_temp.zw+vec2(cone,out_misc_info.y))*pict_size);\n" - " our_fragcol.r+=mix(mix(c00.r,c10.r,subpixel.z),mix(c01.r,c11.r,subpixel.z),subpixel.w)*out_moco_pos.w;\n" - // now handle UV - " subpixel=floor(mod(moco_work*halfst,ctwo))*halfst; \n" - " moco_temp=(floor(moco_work*halfst*halfst)+floor(vec4(out_moco_pos.xy,out_moco_pos.xy)*halfst))*ctwo;\n" - - " c00=texture2D(forward_pic,moco_temp.xy*pict_size);\n" - " c01=texture2D(forward_pic,(moco_temp.xy+vec2(czero,ctwo*out_misc_info.y))*pict_size);\n" - " c10=texture2D(forward_pic,(moco_temp.xy+vec2(ctwo,czero))*pict_size);\n" - " c11=texture2D(forward_pic,(moco_temp.xy+vec2(ctwo,ctwo*out_misc_info.y))*pict_size);\n" - " our_fragcol.gb+=mix(mix(c00.gb,c10.gb,subpixel.x),mix(c01.gb,c11.gb,subpixel.x),subpixel.y)*out_moco_pos.z;\n" - - " c00=texture2D(backward_pic,moco_temp.zw*pict_size);\n" - " c01=texture2D(backward_pic,(moco_temp.zw+vec2(czero,ctwo*out_misc_info.y))*pict_size);\n" - " c10=texture2D(backward_pic,(moco_temp.zw+vec2(ctwo,czero))*pict_size);\n" - " c11=texture2D(backward_pic,(moco_temp.zw+vec2(ctwo,ctwo*out_misc_info.y))*pict_size);\n" - " our_fragcol.gb+=mix(mix(c00.gb,c10.gb,subpixel.z),mix(c01.gb,c11.gb,subpixel.z),subpixel.w)*out_moco_pos.w;\n" - - " gl_FragColor.rgb=our_fragcol.rgb;\n" -// " gl_FragColor.rgb=vec3(our_fragcol.r,halfst,halfst);\n" -// " if (out_unsupported==1.) {\n" -// " gl_FragColor.gb=vec2(cone,0.0);\n" -// "}else if (out_unsupported==2.) {\n" -// " gl_FragColor.gb=vec2(0.0,cone);\n" -// "}\n" - - - //" ypos_temp2=mix(ypos_temp1.rg,ypos_temp1.ba,step(c1over2047,mod(ypos_temp2.x,c1over1023)));\n" //activate this - - - //" gl_FragColor.r=subsample/acht;\n" //signed later TODO - //" gl_FragColor.g=0.5;\n" - //" gl_FragColor.b=0.5;\n" - " gl_FragColor.a=1.0;\n" - //" vec4 blocks=texture2D(blocks,gl_FragCoord.xy/600.);\n" -// "help.x=texture2D(textureY,out_texCoord).r;\n" -// "help.y=texture2D(textureU,out_texCoord).r;\n" -// "help.z=texture2D(textureV,out_texCoord).r;\n" //-uv_corr;\n" - // " gl_FragColor.rgba=blocks;\n" - // " gl_FragColor.rgba=vec4(0.7,0.5,0.5,1.0);\n" - //" gl_FragColor.a=1.;\n" - "}\n"; - -GLMocoShader::GLMocoShader(): GLShader("GLMocoShader") -{ - - frame_buf=0; - blocks_loc=0; -} - -GLMocoShader::~GLMocoShader() -{ - //parent does everything -} - -int GLMocoShader::init() { - - if (!initShaders(moco_vertex_shader, moco_frag_shader)) { - Log::getInstance()->log("GLMocoShader", Log::ERR, "init Shaders failed for GLMocoShader"); - return 0; - } - loc_pict_scale = glGetUniformLocation(shad_program, "pict_scale"); - blocks_loc = glGetUniformLocation(shad_program, "blocks"); - forward_pic_loc = glGetUniformLocation(shad_program, "forward_pic"); - backward_pic_loc = glGetUniformLocation(shad_program, "backward_pic"); - pict_size_loc = glGetUniformLocation(shad_program, "pict_size"); - -// frame_sampler_locY = glGetUniformLocation(shad_program, "textureY"); - // Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locY,glGetError()); -// frame_sampler_locU = glGetUniformLocation(shad_program, "textureU"); - //Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locU,glGetError()); -// frame_sampler_locV = glGetUniformLocation(shad_program, "textureV"); - glGenFramebuffers(1, &frame_buf); - //Log::getInstance()->log("GLMocoShader", Log::WARN, "genframe bufmark1 glerror %x",glGetError()); - glGenTextures(1, &data_blocks); - glBindTexture(GL_TEXTURE_2D, data_blocks); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, BLOCK_TEXTURE_WIDTH >>1, BLOCK_TEXTURE_HEIGHT, 0, GL_RGBA, - GL_UNSIGNED_BYTE, NULL); - char buffer[BLOCK_TEXTURE_WIDTH*2]; - memset(buffer,0,BLOCK_TEXTURE_WIDTH*2); // the last line is black, simplifies the shader algorithms - - glTexSubImage2D(GL_TEXTURE_2D,0,0,BLOCK_TEXTURE_HEIGHT-1, - BLOCK_TEXTURE_WIDTH>>1,1, - GL_RGBA,GL_UNSIGNED_BYTE, - buffer); - - glGenBuffers(1,¯o_block); - glBindBuffer(GL_ARRAY_BUFFER,macro_block); - glBufferData(GL_ARRAY_BUFFER,4096*4*sizeof(XvMCMacroBlock),NULL,GL_DYNAMIC_DRAW); - valid_macro_blocks=0; - - - glGenBuffers(1,&triangles); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,triangles); - GLushort *tri_indices=(GLushort *)malloc(sizeof(GLushort)*4096*6); - if (!tri_indices) { - Log::getInstance()->log("GLMocoShader", Log::WARN, "allocating triindices failed"); - return 0; - } - GLushort *tri_indices_run=tri_indices; - for (int i=0;i<4096;i++) { - *tri_indices_run=i+0*4096; //strip - tri_indices_run++; - *tri_indices_run=i+2*4096; //strip - tri_indices_run++; - *tri_indices_run=i+1*4096; //strip - tri_indices_run++; - *tri_indices_run=i+3*4096; //strip - tri_indices_run++; - *tri_indices_run=i+3*4096; //strip - tri_indices_run++; - *tri_indices_run=i+1+0*4096; //strip - tri_indices_run++; - } - - - - - - glBufferData(GL_ELEMENT_ARRAY_BUFFER,4096*6*sizeof(GLushort),tri_indices,GL_STREAM_DRAW); - free(tri_indices); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); - glBindBuffer(GL_ARRAY_BUFFER,0); - - - - return 1; - -} - -int GLMocoShader::deinit() -{ - glDeleteFramebuffers(1, &frame_buf); - glDeleteTextures(1, &data_blocks); - return deinitShaders(); -} - - - -int GLMocoShader::uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMacroBlock *m_blocks,unsigned int num_m_blocks) -{ - unsigned int height=(num_blocks)/(BLOCK_PER_ROW); - - glBindTexture(GL_TEXTURE_2D, data_blocks); - glPixelStorei(GL_UNPACK_ALIGNMENT,1); - - - - - Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark1 %d %d %d",height,num_blocks,num_m_blocks); - glTexSubImage2D(GL_TEXTURE_2D,0,0,0, - BLOCK_TEXTURE_WIDTH>>1,height, - GL_RGBA,GL_UNSIGNED_BYTE, - blocks); -// Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError()); - glTexSubImage2D(GL_TEXTURE_2D,0,0,height, - ((num_blocks%BLOCK_PER_ROW)>>1)*BLOCK_SIZE,1, - GL_RGBA,GL_UNSIGNED_BYTE, - blocks+height*BLOCK_PER_ROW*BLOCK_SIZE); - - //Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError()); - - - - glBindTexture(GL_TEXTURE_2D, 0); - - valid_macro_blocks=num_m_blocks; - glBindBuffer(GL_ARRAY_BUFFER,macro_block); - XvMCMacroBlock *m_blocks_run=m_blocks; - XvMCMacroBlock *m_blocks_end=m_blocks+num_m_blocks; - while (m_blocks_run!=m_blocks_end) { - m_blocks_run->pad0=0xFF00; - // Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks coded block %x %x %d", - // m_blocks_run->coded_block_pattern, m_blocks_run->macroblock_type,m_blocks_run->index); - m_blocks_run++; - - } - // debug -/* m_blocks[0].x=0; - m_blocks[0].y=0; - m_blocks[3]=m_blocks[2]=m_blocks[1]=m_blocks[0]; - m_blocks[0].pad0=0xFF00; - m_blocks[1].pad0=0xFFFF; - m_blocks[2].pad0=0x0000; - m_blocks[3].pad0=0x00FF; - m_blocks[1].x=0; - m_blocks[1].y=0; - m_blocks[2].x=0; - m_blocks[2].y=0; - m_blocks[3].x=0; - m_blocks[3].y=0;*/ - - glBufferSubData(GL_ARRAY_BUFFER, 0* sizeof(XvMCMacroBlock), num_m_blocks * sizeof(XvMCMacroBlock), - m_blocks); - - - m_blocks_run = m_blocks; - m_blocks_end = m_blocks + num_m_blocks; - while (m_blocks_run != m_blocks_end) { - m_blocks_run->pad0 = 0xFFFF; - m_blocks_run++; - } - glBufferSubData(GL_ARRAY_BUFFER, 4096* sizeof(XvMCMacroBlock), num_m_blocks * sizeof(XvMCMacroBlock), - m_blocks); - - - m_blocks_run = m_blocks; - m_blocks_end = m_blocks + num_m_blocks; - while (m_blocks_run != m_blocks_end) { - m_blocks_run->pad0 = 0x0000; - m_blocks_run++; - } - glBufferSubData(GL_ARRAY_BUFFER, 2 * 4096* sizeof(XvMCMacroBlock), - num_m_blocks * sizeof(XvMCMacroBlock), m_blocks); - - - m_blocks_run = m_blocks; - m_blocks_end = m_blocks + num_m_blocks; - while (m_blocks_run != m_blocks_end) { - m_blocks_run->pad0 = 0x00FF; - m_blocks_run++; - } - glBufferSubData(GL_ARRAY_BUFFER, 3 * 4096* sizeof(XvMCMacroBlock), - num_m_blocks * sizeof(XvMCMacroBlock), m_blocks); - - - glBindBuffer(GL_ARRAY_BUFFER,0); - - return 1; - - - -} - -int GLMocoShader::doMoCo(VPEOGLFrame *target,VPEOGLFrame *forward,VPEOGLFrame *backward) -{ - -// Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark-2 glerror %x %x",glGetError(),frame_buf); - - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark-1 glerror %x %x",glGetError(),frame_buf); - glBindFramebuffer(GL_FRAMEBUFFER, frame_buf); - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark1 glerror %x %x %x",glGetError(),target->textures[0],target->textures[1]); - - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, target->textures[0], 0); - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark1apres glerror %x",glGetError()); - - - - - - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2 glerror %x",glGetError()); - - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2a glerror %x",glGetError()); - - int status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status == GL_FRAMEBUFFER_COMPLETE) { - glViewport(0, 0, target->width,target->height); - // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2b glerror %x",glGetError()); - - XvMCMacroBlock * helperp=NULL; - - glClearColor(0.0f,0.5f,0.5f,1.f); //this black - glClear(GL_COLOR_BUFFER_BIT); - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2c glerror %x",glGetError()); - - glUseProgram(shad_program); - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark3 glerror %x",glGetError()); - - - const GLfloat pict_scale[]={ 32./((float)target->width),32./((float)target->height)}; - - glUniform2fv(loc_pict_scale,1,(const GLfloat*)&pict_scale); - - - const GLfloat pict_size[]={ 1./((float)target->width),1./((float)target->height)}; - glUniform2fv(pict_size_loc,1,(const GLfloat*)&pict_size); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,triangles); - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark5 glerror %x",glGetError()); - glBindBuffer(GL_ARRAY_BUFFER,macro_block); - - - - glVertexAttribPointer(0, 2, GL_SHORT, GL_FALSE, - sizeof(XvMCMacroBlock), NULL); - - glEnableVertexAttribArray(0); - - glVertexAttribPointer(1, 2, GL_UNSIGNED_BYTE, GL_TRUE,sizeof(XvMCMacroBlock), (const void *) &(helperp->pad0)); - glEnableVertexAttribArray(1); - - glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->macroblock_type)); - glEnableVertexAttribArray(2); - - glVertexAttribPointer(3, 1, GL_UNSIGNED_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->coded_block_pattern)); - glEnableVertexAttribArray(3); - glVertexAttribPointer(4, 2, GL_UNSIGNED_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->index)); - glEnableVertexAttribArray(4); - - glVertexAttribPointer(5, 4, GL_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->PMV[0][0][0])); - glEnableVertexAttribArray(5); - - glVertexAttribPointer(6, 4, GL_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->PMV[1][0][0])); - glEnableVertexAttribArray(6); - - - - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,data_blocks); - glUniform1i(blocks_loc,0); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); - - - - if (forward) { - // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo forward %x",forward->textures[0]); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D,forward->textures[0]); - glUniform1i(forward_pic_loc,1); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); - - } - - if (backward) { - glActiveTexture(GL_TEXTURE2); - // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo backward %x",backward->textures[0]); - glBindTexture(GL_TEXTURE_2D,backward->textures[0]); - glUniform1i(backward_pic_loc,2); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); - - } - - - - glDrawElements(GL_TRIANGLE_STRIP, valid_macro_blocks*6, - GL_UNSIGNED_SHORT, NULL); - - - /* - glVertexAttribPointer(0, 2, GL_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), 0); - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark3 glerror %x",glGetError()); - glEnableVertexAttribArray(0); - - glVertexAttribPointer(1, 2, GL_UNSIGNED_BYTE, GL_TRUE,sizeof(XvMCMacroBlock), (const void *) &(helperp->pad0)); - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark3 glerror %x",glGetError()); - glEnableVertexAttribArray(1);*/ - - // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark4 glerror %x",glGetError()); - - - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark6 glerror %x",glGetError()); - - // glDrawElements(GL_TRIANGLE_STRIP,/*valid_macro_blocks*/4,GL_UNSIGNED_SHORT,0); - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark7 glerror %x %x",glGetError(),valid_macro_blocks); - //cleanup - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark5 glerror %x",glGetError()); - glBindBuffer(GL_ARRAY_BUFFER,0); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, 0); - //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark8 glerror %x",glGetError()); - } else { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - Log::getInstance()->log("GLMocoShader", Log::WARN, "framebuffer not complete %x",status); - return -1; - } - - glFinish(); // since the main rendering is done in a different thread we have to make sure rendering is finished before passing the texture - // call this only in the last stage of rendering the moco frame - return 0; - - - -} - -/* - -int GLMocoShader::PrepareRendering(GLuint y_tex, GLuint u_tex, GLuint v_tex) { // This Function setups the rendering pipeline according to the shaders standards - - //Log::getInstance()->log("OSD", Log::WARN, "mark1 glerror %x",glGetError()); - - - //Log::getInstance()->log("OSD", Log::WARN, "mark2 glerror %x",glGetError()); - - - glActiveTexture( GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, v_tex); - glUniform1i(frame_sampler_locV, 2); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glActiveTexture( GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, u_tex); - glUniform1i(frame_sampler_locU, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glActiveTexture( GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, y_tex); - glUniform1i(frame_sampler_locY, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - return 1; - -}*/ - -int GLMocoShader::BindAttributes() -{ - glBindAttribLocation(shad_program,0,"block_pos"); - glBindAttribLocation(shad_program,1,"block_edge"); - glBindAttribLocation(shad_program,2,"block_types"); - glBindAttribLocation(shad_program,3,"cbp"); - glBindAttribLocation(shad_program,4,"index"); - glBindAttribLocation(shad_program,5,"PMV1"); - glBindAttribLocation(shad_program,6,"PMV2"); - - //glBindAttribLocation(shad_program,1,"tex_coord"); - return 1; -} diff --git a/glmocoshader.h b/glmocoshader.h deleted file mode 100755 index 66b9256..0000000 --- a/glmocoshader.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright 2012 Marten Richter - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef GL_MOCOSHADER_H -#define GL_MOCOSHADER_H - -#include "glshader.h" -#include - -struct VPEOGLFrame; -struct VPE_FrameBuf; - - -class GLMocoShader: public GLShader { -public: - GLMocoShader(); - virtual ~GLMocoShader(); - - int init(); - int deinit(); - - int uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMacroBlock *m_blocks,unsigned int num_m_blocks); - - int doMoCo(VPEOGLFrame *target,VPEOGLFrame *forward,VPEOGLFrame *backward); - -protected: - virtual int BindAttributes(); - GLuint frame_buf; - GLuint data_blocks; - GLuint triangles; - GLuint macro_block; - GLint loc_pict_scale; - GLint blocks_loc; - GLint forward_pic_loc; - GLint backward_pic_loc; - GLint pict_size_loc; - unsigned int valid_macro_blocks; - - - -}; - - -#endif diff --git a/glyuv400shader.cc b/glyuv400shader.cc deleted file mode 100755 index 976c7aa..0000000 --- a/glyuv400shader.cc +++ /dev/null @@ -1,124 +0,0 @@ -/* - Copyright 2012 Marten Richter - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#include "glyuv400shader.h" - -const GLchar generic_vertex_shader[] = - "attribute vec4 vec_pos;\n" - "attribute vec2 tex_coord;\n" - "varying vec2 out_texCoord;\n" - "void main()\n" - "{\n" - " gl_Position=vec_pos;\n" - " out_texCoord=tex_coord;\n" - "}\n"; - -const GLchar frame_frag_shader[] = - "precision mediump float;\n" - "uniform sampler2D textureU;\n" - "uniform sampler2D textureV;\n" - "uniform sampler2D textureY;\n" - "const float uv_corr=0.5;\n" - "const float y_corr=0.0625;\n" - "const mat3 yuvtransform= mat3( 1.164 ,0.0 ,1.596 ,\n" - " 1.164 ,-0.391,-0.813 ,\n" - " 1.164,2.018 , 0.0 );\n" -// "const mat3 yuvtransform= mat3( 1. ,1. ,1. ,\n" -// " 0.0 ,-0.3960,2.029 ,\n" -// " 1.140,-0.581 , 0.0 );\n" -// "const mat3 yuvtransform= mat3( 1. ,0 ,0. ,\n" -// " 0.0 ,1.,0. ,\n" -// " 0.,0. , 1.0 );\n" -// "const mat3 yuvtransform= mat3( 1. ,1. ,1. ,\n" -// " 0.0 ,-0.03960,0.2029 ,\n" -// " 0.1140,-0.0581 , 0.0 );\n" - "varying vec2 out_texCoord;\n" - "void main()\n" - "{\n" - " vec3 help;\n" - "help.x=texture2D(textureY,out_texCoord).r-y_corr;\n" - "help.y=texture2D(textureU,out_texCoord).r-uv_corr;\n" - "help.z=texture2D(textureV,out_texCoord).r-uv_corr;\n" //-uv_corr;\n" - " gl_FragColor.rgb=help*yuvtransform;\n" - " gl_FragColor.a=1.;\n" - "}\n"; - -GLYuv400Shader::GLYuv400Shader(): GLShader("GLYuv400Shader") -{ - -} - -GLYuv400Shader::~GLYuv400Shader() -{ - //parent does everything -} - -int GLYuv400Shader::init() { - if (!initShaders(generic_vertex_shader, frame_frag_shader)) { - return 0; - } - frame_sampler_locY = glGetUniformLocation(shad_program, "textureY"); - // Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locY,glGetError()); - frame_sampler_locU = glGetUniformLocation(shad_program, "textureU"); - //Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locU,glGetError()); - frame_sampler_locV = glGetUniformLocation(shad_program, "textureV"); - return 1; - -} - -int GLYuv400Shader::deinit() -{ - return deinitShaders(); -} - -int GLYuv400Shader::PrepareRendering(GLuint y_tex, GLuint u_tex, GLuint v_tex) { // This Function setups the rendering pipeline according to the shaders standards - glUseProgram(shad_program); - //Log::getInstance()->log("OSD", Log::WARN, "mark1 glerror %x",glGetError()); - - - //Log::getInstance()->log("OSD", Log::WARN, "mark2 glerror %x",glGetError()); - - - glActiveTexture( GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, v_tex); - glUniform1i(frame_sampler_locV, 2); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glActiveTexture( GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, u_tex); - glUniform1i(frame_sampler_locU, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glActiveTexture( GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, y_tex); - glUniform1i(frame_sampler_locY, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - return 1; - -} - -int GLYuv400Shader::BindAttributes() -{ - glBindAttribLocation(shad_program,0,"vec_pos"); - glBindAttribLocation(shad_program,1,"tex_coord"); - return 1; -} diff --git a/glyuv400shader.h b/glyuv400shader.h deleted file mode 100755 index 9e78665..0000000 --- a/glyuv400shader.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright 2012 Marten Richter - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef GL_YUV400SHADER_H -#define GL_YUV400SHADER_H - -#include "glshader.h" - -class GLYuv400Shader: public GLShader { -public: - GLYuv400Shader(); - virtual ~GLYuv400Shader(); - - int init(); - int deinit(); - - int PrepareRendering(GLuint y_tex,GLuint u_tex,GLuint v_tex); // This Function setups the rendering pipeline according to the shaders standards - -protected: - virtual int BindAttributes(); - - GLint frame_sampler_locY; - GLint frame_sampler_locU; - GLint frame_sampler_locV; - -}; - - -#endif diff --git a/glyuv444shader.cc b/glyuv444shader.cc deleted file mode 100755 index 2c90f77..0000000 --- a/glyuv444shader.cc +++ /dev/null @@ -1,106 +0,0 @@ -/* - Copyright 2012 Marten Richter - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#include "glyuv444shader.h" - -const GLchar generic_vertex_shader[] = - "attribute vec4 vec_pos;\n" - "attribute vec2 tex_coord;\n" - "varying vec2 out_texCoord;\n" - "void main()\n" - "{\n" - " gl_Position=vec_pos;\n" - " out_texCoord=tex_coord;\n" - "}\n"; - -const GLchar frame_frag_shader[] = - "precision mediump float;\n" - "uniform sampler2D textureYUV;\n" - "const float uv_corr=0.5;\n" - "const float y_corr=0.0625;\n" - "const mat3 yuvtransform= mat3( 1.164 ,0.0 ,1.596 ,\n" - " 1.164 ,-0.391,-0.813 ,\n" - " 1.164,2.018 , 0.0 );\n" -// "const mat3 yuvtransform= mat3( 1. ,1. ,1. ,\n" -// " 0.0 ,-0.3960,2.029 ,\n" -// " 1.140,-0.581 , 0.0 );\n" -// "const mat3 yuvtransform= mat3( 1. ,0 ,0. ,\n" -// " 0.0 ,1.,0. ,\n" -// " 0.,0. , 1.0 );\n" -// "const mat3 yuvtransform= mat3( 1. ,1. ,1. ,\n" -// " 0.0 ,-0.03960,0.2029 ,\n" -// " 0.1140,-0.0581 , 0.0 );\n" - "varying vec2 out_texCoord;\n" - "void main()\n" - "{\n" - " vec3 help;\n" - "help=texture2D(textureYUV,out_texCoord).rgb-vec3(y_corr,uv_corr,uv_corr);\n" - "gl_FragColor.rgb=help*yuvtransform;\n" - "gl_FragColor.a=1.;\n" - "}\n"; - -GLYuv444Shader::GLYuv444Shader(): GLShader("GLYuv444Shader") -{ - -} - -GLYuv444Shader::~GLYuv444Shader() -{ - //parent does everything -} - -int GLYuv444Shader::init() { - if (!initShaders(generic_vertex_shader, frame_frag_shader)) { - return 0; - } - frame_sampler_locYUV = glGetUniformLocation(shad_program, "textureYUV"); - return 1; - -} - -int GLYuv444Shader::deinit() -{ - return deinitShaders(); -} - -int GLYuv444Shader::PrepareRendering(GLuint yuv_tex) { // This Function setups the rendering pipeline according to the shaders standards - glUseProgram(shad_program); - //Log::getInstance()->log("OSD", Log::WARN, "mark1 glerror %x",glGetError()); - - - - - - glActiveTexture( GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, yuv_tex); - //Log::getInstance()->log("OSD", Log::WARN, "mark3 glerror %x %x",glGetError(),yuv_tex); - glUniform1i(frame_sampler_locYUV, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - return 1; - -} - -int GLYuv444Shader::BindAttributes() -{ - glBindAttribLocation(shad_program,0,"vec_pos"); - glBindAttribLocation(shad_program,1,"tex_coord"); - return 1; -} diff --git a/glyuv444shader.h b/glyuv444shader.h deleted file mode 100755 index 86bcbc6..0000000 --- a/glyuv444shader.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright 2012 Marten Richter - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef GL_YUV444SHADER_H -#define GL_YUV444SHADER_H - -#include "glshader.h" - -class GLYuv444Shader: public GLShader { -public: - GLYuv444Shader(); - virtual ~GLYuv444Shader(); - - int init(); - int deinit(); - - int PrepareRendering(GLuint y_tex); // This Function setups the rendering pipeline according to the shaders standards - -protected: - virtual int BindAttributes(); - - GLint frame_sampler_locYUV; - - -}; - - -#endif diff --git a/main.cc b/main.cc old mode 100755 new mode 100644 index b91b671..b60fe02 --- a/main.cc +++ b/main.cc @@ -69,8 +69,8 @@ extern "C" #include "remotelinux.h" #include "ledraspberry.h" #include "osdopengl.h" -#include "audiovpe.h" -#include "videovpeogl.h" +#include "audioomx.h" +#include "videoomx.h" #endif diff --git a/osdopengl.cc b/osdopengl.cc index 6717f64..b4bd06d 100644 --- a/osdopengl.cc +++ b/osdopengl.cc @@ -21,7 +21,7 @@ #include "osdopengl.h" #include "mtd.h" -#include "videovpeogl.h" +#include "videoomx.h" #include "surfaceopengl.h" @@ -219,17 +219,7 @@ int OsdOpenGL::init(void* device) glmutex.Unlock(); return 0; } - if (!yuv400_shader.init()) { - Log::getInstance()->log("OSD", Log::WARN, "Init Yuv400 Shader failed"); - glmutex.Unlock(); - return 0; - } - if (!yuv444_shader.init()) { - Log::getInstance()->log("OSD", Log::WARN, "Init Yuv444 Shader failed"); - glmutex.Unlock(); - return 0; - } @@ -238,7 +228,7 @@ int OsdOpenGL::init(void* device) eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ); - if (((VideoVPEOGL*)Video::getInstance())->initUsingOSDObjects()!=1) { //call Video for init opengl stuff + if (((VideoOMX*)Video::getInstance())->initUsingOSDObjects()!=1) { //call Video for init opengl stuff return 0; } @@ -300,12 +290,10 @@ int OsdOpenGL::shutdown() if (!initted) return 0; initted = 0; - (((VideoVPEOGL*)Video::getInstance())->shutdownUsingOSDObjects()); + (((VideoOMX*)Video::getInstance())->shutdownUsingOSDObjects()); osd_shader.deinit(); - yuv400_shader.deinit(); - yuv444_shader.deinit(); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(egl_display, egl_surface); @@ -328,41 +316,22 @@ void OsdOpenGL::threadMethod() //glmutex.Lock(); //glmutex.Unlock(); - VPEOGLFrame *frame=NULL; int ts=0; - VideoVPEOGL* video =(VideoVPEOGL*) Video::getInstance(); while (true) { ts=10; unsigned int waittime=10; - if (initted){ -#ifdef VPE_LIBAV_SUPPORT - if (!frame) frame=video->getReadyOGLFrame(); - if (frame) { - InternalRendering(frame); - // MILLISLEEP(1000); - lastrendertime=getTimeMS(); - video->returnOGLFrame(frame); //please recycle it - frame=NULL; + if (initted) { + + long long time1 = getTimeMS(); + if ((time1 - lastrendertime) > 200) {//5 fps for OSD updates are enough, avoids tearing + InternalRendering(); + lastrendertime = getTimeMS(); } - else -#endif - { - long long time1=getTimeMS(); - if ((time1-lastrendertime)>200) {//5 fps for OSD updates are enough, avoids tearing - InternalRendering(NULL); - lastrendertime=getTimeMS(); - } - } -#ifdef VPE_LIBAV_SUPPORT - frame=video->getReadyOGLFrame(); -#endif } - - if (frame) ts=0; threadCheckExit(); if (ts!=0) { struct timespec target_time; @@ -388,7 +357,7 @@ void OsdOpenGL::threadPostStopCleanup() -void OsdOpenGL::InternalRendering(VPEOGLFrame* frame){ +void OsdOpenGL::InternalRendering(){ BeginPainting(); @@ -402,35 +371,6 @@ void OsdOpenGL::InternalRendering(VPEOGLFrame* frame){ glClearColor(0.0f,0.0f,0.0f,1.f); glClear(GL_COLOR_BUFFER_BIT); - if (frame) { - switch (frame->type) { - case 1: - yuv400_shader.PrepareRendering(frame->textures[0],frame->textures[1],frame->textures[2]);break; - case 2: - yuv444_shader.PrepareRendering(frame->textures[0]);break; - } - - - - - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), osdvertices); - glEnableVertexAttribArray(0); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), &(osdvertices[0].u)); - glEnableVertexAttribArray(1); - - - //Log::getInstance()->log("OSD", Log::WARN, "mark8 glerror %x %x",glGetError(),osd_sampler_loc); - - - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - - } - - - - osd_shader.PrepareRendering(((SurfaceOpenGL*)screen)->getTexture()); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), osdvertices); @@ -439,13 +379,9 @@ void OsdOpenGL::InternalRendering(VPEOGLFrame* frame){ glEnableVertexAttribArray(1); - if (frame!=NULL) { //This is ok for ffmpeg rendering not OMX - glEnable(GL_BLEND); - glBlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,GL_ZERO,GL_ONE); - } else { - glDisable(GL_BLEND); - } + glDisable(GL_BLEND); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); diff --git a/osdopengl.h b/osdopengl.h index e2446e3..401889d 100644 --- a/osdopengl.h +++ b/osdopengl.h @@ -34,11 +34,9 @@ #include "log.h" #include "threadp.h" #include "mutex.h" -#include "videovpeogl.h" +#include "videoomx.h" #include "glosdshader.h" -#include "glyuv400shader.h" -#include "glyuv444shader.h" @@ -114,14 +112,12 @@ private: bool external_driving; Mutex glmutex; long long lastrendertime; - void InternalRendering(VPEOGLFrame* frame); + void InternalRendering(); void InitVertexBuffer(float scalex,float scaley); OSDVERTEX osdvertices[4]; GLubyte osdindices[6]; GLOsdShader osd_shader; - GLYuv400Shader yuv400_shader; - GLYuv444Shader yuv444_shader; diff --git a/stream.cc b/stream.cc index e2b1e55..abea315 100644 --- a/stream.cc +++ b/stream.cc @@ -170,7 +170,7 @@ bool Stream::drain(bool * dataavail) { draintarget->PrepareMediaSample(mediapackets, cur_packet_pos); unLock(); - if (dataavail) *dataavail=true; + if (dataavail && draintarget->DrainTargetReady()) *dataavail=true; UINT consumed = draintarget->DeliverMediaSample(outbuf, &cur_packet_pos); lock(); if (consumed != 0) ret = true; diff --git a/videoomx.cc b/videoomx.cc new file mode 100644 index 0000000..3a04916 --- /dev/null +++ b/videoomx.cc @@ -0,0 +1,1995 @@ +/* + Copyright 2004-2005 Chris Tallon, 2009 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "videoomx.h" +#include "audioomx.h" +#include "mtdraspberry.h" +#include "demuxer.h" +#include "osdopengl.h" + +// temp +#include "log.h" + +//A lot of parts of this file are heavily inspired by xbmc omx implementations + +VideoOMX::VideoOMX() { + + omx_running = false; + + omx_vid_dec = 0; + cur_input_buf_omx = NULL; + omx_h264 = omx_mpeg2 = true; + clock_references = 0; + + offsetnotset = true; + offsetvideonotset = true; + offsetaudionotset = true; + startoffset = 0; + lastrefaudiotime = 0; + lastrefvideotime = 0; + lastreftimeOMX = 0; + lastreftimePTS = 0; + firstsynched = false; + +} + +VideoOMX::~VideoOMX() +{ + instance = NULL; +} + +int VideoOMX::init(UCHAR tformat) +{ + if (initted) return 0; + initted = 1; + + if (!setFormat(tformat)) { shutdown(); return 0; } + if (!setConnection(COMPOSITERGB)) { shutdown(); return 0; } + if (!setAspectRatio(ASPECT4X3)) { shutdown(); return 0; } + if (!setMode(NORMAL)) { shutdown(); return 0; } + if (!setSource()) { shutdown(); return 0; } + if (!attachFrameBuffer()) { shutdown(); return 0; } + + setTVsize(ASPECT4X3); + + + + + + //stop(); + + + + return 1; +} + +int VideoOMX::initUsingOSDObjects() +{ + +// we are called before the audio + OMX_ERRORTYPE error; + error=OMX_Init(); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX failed %x", error); + return 0; + } + + return 1; +} + + +OMX_ERRORTYPE VideoOMX::EventHandler_OMX(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) { + + 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; + + VideoOMX *video=(VideoOMX *)getInstance(); + video->AddOmxEvent(new_event); + +/* switch (event_type) { + case OMX_EventCmdComplete: { + + } break; + }*/ + + return OMX_ErrorNone; + +} + +void VideoOMX::AddOmxEvent(VPE_OMX_EVENT new_event) +{ + omx_event_mutex.Lock(); + omx_events.push_back(new_event); + omx_event_mutex.Unlock(); +} + + +OMX_ERRORTYPE VideoOMX::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer){ + + //Log::getInstance()->log("Video", Log::NOTICE, "EmptyBufferDone"); + VideoOMX *video=(VideoOMX *)getInstance(); + video->ReturnEmptyOMXBuffer(buffer); + return OMX_ErrorNone; + +} + +void VideoOMX::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 VideoOMX::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; +} + + + +int VideoOMX::shutdown() +{ + if (!initted) return 0; + initted = 0; + + DeAllocateCodecsOMX(); + OMX_Deinit(); + return 1; +} + + +int VideoOMX::setTVsize(UCHAR ttvsize) +{ +/* tvsize = ttvsize; + + // Override the aspect ratio usage, temporarily use to set the video chip mode + if (!setAspectRatio(tvsize)) { shutdown(); return 0; } + close(fdVideo); + if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0; + if (!setSource()) { shutdown(); return 0; } + if (!attachFramebuffer()) { shutdown(); return 0; } + + // Reopening the fd causes the scart aspect line to go back to 4:3 + // Set this again to the same as the tv screen size + if (!setAspectRatio(tvsize)) { shutdown(); return 0; } + + // mode == LETTERBOX is invalid if the TV is widescreen + if (tvsize == ASPECT16X9) setMode(NORMAL); +*/ + return 1; +} + +int VideoOMX::setDefaultAspect() +{ + return setAspectRatio(tvsize); +} + + + +int VideoOMX::setFormat(UCHAR tformat) +{ + if (!initted) return 0; + if ((tformat != PAL) && (tformat != NTSC)) return 0; + format = tformat; + +// if (ioctl(fdVideo, AV_SET_VID_DISP_FMT, format) != 0) return 0; + + if (format == NTSC) + { + screenWidth = 720; + screenHeight = 480; + } + if (format == PAL) + { + screenWidth = 720; + screenHeight = 576; + } + + return 1; +} + +int VideoOMX::setConnection(UCHAR tconnection) +{ + if (!initted) return 0; + if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0; + connection = tconnection; + +// if (ioctl(fdVideo, AV_SET_VID_OUTPUT, connection) != 0) return 0; + return 1; +} + +int VideoOMX::setAspectRatio(UCHAR taspectRatio) +{ + if (!initted) return 0; + if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0; + aspectRatio = taspectRatio; + + Log::getInstance()->log("Video", Log::DEBUG, "Setting aspect to %i", aspectRatio); + +// if (ioctl(fdVideo, AV_SET_VID_RATIO, aspectRatio) != 0) return 0; + return 1; +} + +int VideoOMX::setMode(UCHAR tmode) +{ + if (!initted) return 0; + + if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode + + if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH) + && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0; + mode = tmode; + +// if (ioctl(fdVideo, AV_SET_VID_MODE, mode) != 0) return 0; + return 1; +} + +int VideoOMX::signalOff() +{ +// if (ioctl(fdVideo, AV_SET_VID_DENC, 0) != 0) return 0; + return 1; +} + +int VideoOMX::signalOn() +{ +// if (ioctl(fdVideo, AV_SET_VID_DENC, 1) != 0) return 0; + return 1; +} + +int VideoOMX::setSource() +{ + if (!initted) return 0; + + // What does this do... +// if (ioctl(fdVideo, AV_SET_VID_SRC, 1) != 0) return 0; + return 1; +} + +int VideoOMX::setPosition(int x, int y) +{ + if (!initted) return 0; + +// vid_pos_regs_t pos_d; +// pos_d.x = x; +// pos_d.y = y; + +/* vid_pos_regs_t pos_d; + + memset(&pos_d, 0, sizeof(pos_d)); + + pos_d.dest.y = y; + pos_d.dest.x = x; +/* +typedef struct { + int w; + int h; + int scale; + int x1; + int y; + int x; + int y2; + int x3; + int y3; + int x4; + int y4; +} vid_pos_regs_t; +*/ + +/* + pos_d.w = 100; + pos_d.h = 30; + pos_d.scale = 2; + pos_d.x1 = 0; + pos_d.y = 100; // Top left X + pos_d.x = 50; // Top left Y + pos_d.y2 = 30; + pos_d.x3 = 60; + pos_d.y3 = 90; + pos_d.x4 = 120; + pos_d.y4 = 150; +*/ + +// if (ioctl(fdVideo, AV_SET_VID_POSITION, &pos_d) != 0) return 0; + return 1; +} + +int VideoOMX::sync() +{ + if (!initted) return 0; + +// if (ioctl(fdVideo, AV_SET_VID_SYNC, 2) != 0) return 0; + return 1; +} + + +int VideoOMX::play() { + if (!initted) + return 0; + iframemode = false; + Log::getInstance()->log("Video", Log::DEBUG, "enter play"); + + if (AllocateCodecsOMX()) { + return 1; + // Otherwise fall back to libav + } else { + if (h264) { + omx_h264 = false; + Log::getInstance()->log("Video", Log::NOTICE, + "Allocate Codecs OMX failed assume h264 unsupported"); + } else { + omx_mpeg2 = false; + Log::getInstance()->log("Video", Log::NOTICE, + "Allocate Codecs OMX failed assume mpeg2 unsupported"); + } + } + + return 0; + +} + + +int VideoOMX::initClock() +{ + OMX_ERRORTYPE error; + clock_mutex.Lock(); + if (clock_references==0) + { + + static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX}; + omx_events.clear(); + + error=OMX_GetHandle(&omx_clock,VPE_OMX_CLOCK,NULL,&callbacks); + + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX clock failed %x", error); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + /* 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); + p_param.nVersion.nVersion=OMX_VERSION; + error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + omx_clock_output_port=p_param.nStartPortNumber; + + for (unsigned int i=0;ilog("Video", Log::DEBUG, "Disable Ports OMX clock failed %d",i); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + } + + + + + } + Log::getInstance()->log("Video", Log::DEBUG, "init omx clock %x %x",this,omx_clock); + clock_references++; + clock_mutex.Unlock(); + return 1; +} + +int VideoOMX::getClockAudioandInit(OMX_HANDLETYPE *p_omx_clock,OMX_U32 *p_omx_clock_output_port) +{ + OMX_ERRORTYPE error; + *p_omx_clock=NULL; + *p_omx_clock_output_port=0; + + if (!initClock()) { + return 0; + } + clock_mutex.Lock(); + + OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refclock; + memset(&refclock,0,sizeof(refclock)); + refclock.nSize=sizeof(refclock); + refclock.nVersion.nVersion=OMX_VERSION; + + refclock.eClock=OMX_TIME_RefClockAudio; + + //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); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + 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); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error); + clock_mutex.Unlock(); + 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_ClockStateWaitingForStartTime; + clock_conf.nStartTime=0; + clock_conf.nOffset=0; + if (clock_references==1) clock_conf.nWaitMask=OMX_CLOCKPORT1; + else clock_conf.nWaitMask=OMX_CLOCKPORT0|OMX_CLOCKPORT1; + error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Video", Log::DEBUG, "AuI Clock IndexConfigTimeClockState failed %x", error); + } + + + *p_omx_clock_output_port=p_param.nStartPortNumber+1; + *p_omx_clock=omx_clock; + clock_mutex.Unlock(); + return 1; +} + +int VideoOMX::getClockVideoandInit() +{ + OMX_ERRORTYPE error; + + if (!initClock()) { + return 0; + } + clock_mutex.Lock(); + + if (clock_references==1) { // only if no audio is attached to this clock! + OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refclock; + memset(&refclock,0,sizeof(refclock)); + refclock.nSize=sizeof(refclock); + refclock.nVersion.nVersion=OMX_VERSION; + + //refclock.eClock=OMX_TIME_RefClockAudio; + + 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); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + } + + 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); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error); + clock_mutex.Unlock(); + 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_ClockStateWaitingForStartTime; + clock_conf.nStartTime=0; + clock_conf.nOffset=0; + if (clock_references==1) clock_conf.nWaitMask=OMX_CLOCKPORT0; + else clock_conf.nWaitMask=OMX_CLOCKPORT0|OMX_CLOCKPORT1; + error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Video", Log::DEBUG, "VuI Clock IndexConfigTimeClockState failed %x", error); + } + + omx_clock_output_port=p_param.nStartPortNumber; + clock_mutex.Unlock(); + + return 1; +} + +void VideoOMX::clockUnpause() +{ + OMX_ERRORTYPE error; + clock_mutex.Lock(); + 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; + clock_conf.nStartTime=0; + clock_conf.nOffset=0; + clock_conf.nWaitMask=OMX_CLOCKPORT1; + error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Video", Log::DEBUG, "ClockUnpause IndexConfigTimeClockState failed %x", error); + } + + clock_mutex.Unlock(); +} + + +void VideoOMX::clockPause() +{ + OMX_ERRORTYPE error; + clock_mutex.Lock(); + 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_ClockStateStopped; + clock_conf.nStartTime=0; + clock_conf.nOffset=0; + clock_conf.nWaitMask=OMX_CLOCKPORT1; + error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Video", Log::DEBUG, "ClockUnpause IndexConfigTimeClockState failed %x", error); + } + clock_mutex.Unlock(); +} + + + +int VideoOMX::AllocateCodecsOMX() +{ + OMX_ERRORTYPE error; + static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX}; + + Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX"); + //Clock, move later to audio including events + + Log::getInstance()->log("Video", Log::DEBUG, "Nmark1 "); + 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"); + return 0; + } + /* TODO end */ + + + clock_mutex.Lock(); + if (h264) { + error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_H264_DECODER,NULL,&callbacks); + } else { + error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_MPEG2_DECODER,NULL,&callbacks); + } + + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video decoder failed %x", error); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + + Log::getInstance()->log("Video", Log::DEBUG, "Nmark3 "); + 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_vid_dec,OMX_IndexParamVideoInit,&p_param); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX h264 decoder OMX_GetParameter failed %x", error); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + 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"); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + Log::getInstance()->log("Video", Log::DEBUG, "Nmark4 "); + + OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE conceal; + memset(&conceal,0,sizeof(conceal)); + conceal.nSize=sizeof(conceal); + conceal.nVersion.nVersion=OMX_VERSION; + conceal.bStartWithValidFrame=OMX_FALSE; + + error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamBrcmVideoDecodeErrorConcealment,&conceal); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "OMX_IndexParamBrcmVideoDecodeErrorConcealment failed %x", error); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + + error=OMX_GetHandle(&omx_vid_sched,VPE_OMX_VIDEO_SCHED,NULL,&callbacks); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler failed %x", error); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + + + error=OMX_GetParameter(omx_vid_sched,OMX_IndexParamVideoInit,&p_param); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler OMX_GetParameter failed %x", error); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + omx_shed_input_port=p_param.nStartPortNumber; + omx_shed_output_port=p_param.nStartPortNumber+1; + + + 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); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + 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,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"); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + 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); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + error=OMX_GetParameter(omx_vid_rend,OMX_IndexParamVideoInit,&p_param); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video rend OMX_GetParameter failed %x", error); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + omx_rend_input_port=p_param.nStartPortNumber; + //omx_rend_output_port=p_param.nStartPortNumber+1; + + + 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"); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + //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); + clock_mutex.Unlock(); + 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"); + clock_mutex.Unlock(); + 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"); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + + + Log::getInstance()->log("Video", Log::DEBUG, "mark1 "); + if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_clock_port)) { + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + + + + Log::getInstance()->log("Video", Log::DEBUG, "mark1 special "); + if ( !CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port)) { + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + clock_mutex.Unlock(); + + + 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); + ft_type.nVersion.nVersion=OMX_VERSION; + + ft_type.nPortIndex=omx_codec_input_port; + if (h264) { + ft_type.eCompressionFormat=OMX_VIDEO_CodingAVC; + } else { + 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()); + 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); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + + if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "vid_dec ChangeComponentState"); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + + if (!PrepareInputBufsOMX()) { + 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 ( !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)) { + Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_dec ChangeComponentState Execute"); + clock_mutex.Unlock(); + 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); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + 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"); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + if (!CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_output_port) + || !CommandFinished(omx_vid_rend,OMX_CommandPortEnable,omx_rend_input_port)) { + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState"); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + + if (!ChangeComponentState(omx_vid_sched,OMX_StateExecuting)) { + Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_sched ChangeComponentState Execute"); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + + if (!ChangeComponentState(omx_vid_rend,OMX_StateExecuting)) { + Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_rend ChangeComponentState Execute"); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + 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_SetConfig(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + 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); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + 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); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + }*/ + + + playbacktimeoffset=-GetCurrentSystemTime(); + paused=false; + iframemode=false; + omx_running=true; + clock_mutex.Unlock(); + + setClockExecutingandRunning(); + + + + + + return 1; +} + +int VideoOMX::idleClock() +{ + OMX_ERRORTYPE error; + OMX_STATETYPE temp_state; + clock_mutex.Lock(); + OMX_GetState(omx_clock,&temp_state); + + if (temp_state!=OMX_StateIdle) { + if (!ChangeComponentState(omx_clock,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Idle failed"); + clock_mutex.Unlock(); + return 0; + } + } + clock_mutex.Unlock(); + return 1; +} + +int VideoOMX::setClockExecutingandRunning() +{ + OMX_ERRORTYPE error; + OMX_STATETYPE temp_state; + clock_mutex.Lock(); + OMX_GetState(omx_clock,&temp_state); + + if (temp_state!=OMX_StateExecuting) { + if (!ChangeComponentState(omx_clock,OMX_StateExecuting)) { + Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Execute failed"); + clock_mutex.Unlock(); + 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); + clock_mutex.Unlock(); + DeAllocateCodecsOMX(); + return 0; + } + clock_mutex.Unlock(); + return 1; + +} + + +int VideoOMX::ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type) //needs to be called with locked mutex +{ + 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 VideoOMX::EnablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait) //needs to be called with locked mutex +{ + 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 VideoOMX::DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait) //needs to be called with locked mutex +{ + 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 VideoOMX::CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2) //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, "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; + } + } + 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 VideoOMX::PrepareInputBufsOMX() //needs to be called with locked mutex +{ + 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; + + error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type); + + 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);*/ + + port_def_type.nBufferCountActual=60; + port_def_type.nBufferSize=max(port_def_type.nBufferSize,200000); // for transcoder important + + 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); + } + + + 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; + } + + input_bufs_omx_mutex.Lock(); + for (unsigned int i=0; i< port_def_type.nBufferCountActual;i++) { + + // 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); + 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); + } + omx_first_frame=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; +} + +int VideoOMX::DestroyInputBufsOMX() //need s to be called with locked mutex +{ + OMX_ERRORTYPE error; + + 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; + 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); + input_bufs_omx_mutex.Unlock(); + return 0; + } + + } + input_bufs_omx_all.clear(); + input_bufs_omx_free.clear(); + input_bufs_omx_mutex.Unlock(); + +} + + + + +int VideoOMX::DeAllocateCodecsOMX() +{ + OMX_ERRORTYPE error; + omx_running=false; + Log::getInstance()->log("Video", Log::DEBUG, "enter deallocatecodecsomx"); + + clock_mutex.Lock(); + 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"); + + } + clock_mutex.Unlock(); + + idleClock(); + clock_mutex.Lock(); + + + if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "vid_shed ChangeComponentState"); + + } + + if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) { + Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState"); + + } + + + + // 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); + + } + + + + 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); + + } + + + + if (!CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_output_port) ) { + Log::getInstance()->log("Video", Log::DEBUG, "flush cmd shed rend failed"); + } + + + + + + + DestroyInputBufsOMX(); + + //todo flushing + 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"); + } + + + + + 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"); + } + + + + + 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"); + } + + + + + 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) { + 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); + + } + + 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) { + 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) { + Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error); + + } + + + + + error=OMX_FreeHandle(omx_vid_dec); + error=OMX_FreeHandle(omx_vid_sched); + error=OMX_FreeHandle(omx_vid_rend); + omx_vid_dec=NULL; + clock_mutex.Unlock(); + destroyClock(); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Video", Log::DEBUG, "FreeHandle failed %d", error); + } + } else clock_mutex.Unlock(); + Log::getInstance()->log("Video", Log::DEBUG, "leave deallocate codecs OMX"); + + return 1; +} + + +void VideoOMX::destroyClock() +{ + clock_mutex.Lock(); + if (clock_references>0) { + clock_references--; + if (clock_references==0) { + OMX_ERRORTYPE error; + Log::getInstance()->log("Video", Log::DEBUG, "destroy omx clock"); + error=OMX_FreeHandle(omx_clock); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Video", Log::DEBUG, "FreeHandle failed %d", error); + } + + } + } + clock_mutex.Unlock(); + +} + +int VideoOMX::stop() +{ + if (!initted) return 0; + iframemode=false; + + //Check if libav mode + DeAllocateCodecsOMX(); + + + + +// if (ioctl(fdVideo, AV_SET_VID_STOP, 0) != 0) return 0; + return 1; +} + +int VideoOMX::reset() +{ + if (!initted) return 0; + + iframemode=false; + DeAllocateCodecsOMX(); +// if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; + return 1; +} + +int VideoOMX::pause() +{ + if (!initted) return 0; + Log::getInstance()->log("Video", Log::DEBUG, "enter pause"); + if (!paused) { + paused=true; + //maybe also change omx clock? + pausetimecode=GetCurrentSystemTime(); + + } + return 1; +} + +int VideoOMX::unPause() // FIXME get rid - same as play!! Not here! +{ + if (!initted) 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; +} + +int VideoOMX::fastForward() +{ + if (!initted) return 0; + +// if (ioctl(fdVideo, AV_SET_VID_libavWD, 1) != 0) return 0; + return 1; +} + +int VideoOMX::unFastForward() +{ + if (!initted) return 0; + +// if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; // don't need this. + + //// if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0; + return 1; +} + +int VideoOMX::attachFrameBuffer() +{ + if (!initted) return 0; + +// if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0; + return 1; +} + +int VideoOMX::blank(void) +{ +// if (ioctl(fdVideo, AV_SET_VID_FB, 1) != 0) return 0; +// if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0; + return 1; +} + +ULLONG VideoOMX::getCurrentTimestamp() +{ + if (iframemode) return 0; + return lastreftimePTS; +} + +// to be removed +/* +ULONG VideoOMX::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 VideoOMX::test() +{ + return 0; + +// ULLONG stc = 0; +// return ioctl(fdVideo, AV_SET_VID_STC, &stc); +/* + // reset(); + return 1; +*/ +} + +int VideoOMX::test2() +{ + return 0; +} +#endif + + + +long long VideoOMX::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 VideoOMX::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 VideoOMX::ResetTimeOffsets() { + offsetnotset=true; //called from demuxer + offsetvideonotset=true; + offsetaudionotset=true; + startoffset=0; + lastrefaudiotime=0; + lastrefvideotime=0; + lastreftimeOMX=0; + lastreftimePTS=0; +} + +long long VideoOMX::GetCurrentSystemTime() +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec*10000000LL+ts.tv_nsec/100LL; +} + +void VideoOMX::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 VideoOMX::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 %lld",GetCurrentSystemTime()); +} + +void VideoOMX::AdjustAudioPTS(long long pts) +{ + long long newplaybacktimeoffset=pts-GetCurrentSystemTime(); +/* if ((newplaybacktimeoffset-1000000LL)>playbacktimeoffset + || (newplaybacktimeoffset+1000000LL)log("Video", Log::DEBUG, "Adjust Playbackoffsettime o: %lld n: %lld", + playbacktimeoffset,newplaybacktimeoffset);*/ + playbacktimeoffset=newplaybacktimeoffset; + + //} +} + + +void VideoOMX::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos) +{ + mediapacket = mplist.front(); +} + +UINT VideoOMX::DeliverMediaSample(UCHAR* buffer, UINT *samplepos) +{ + DeliverMediaPacket(mediapacket, buffer, samplepos); + if (*samplepos == mediapacket.length) { + *samplepos = 0; + return 1; + } + else return 0; +} + +UINT VideoOMX::DeliverMediaPacket(MediaPacket packet, + const UCHAR* buffer, + UINT *samplepos) +{ + if (packet.type == MPTYPE_VIDEO_H264) + { + h264=true; + } + else + { + h264=false; + } + + + //Later add fail back code for libav +/* if (!videoon) { + *samplepos+=packet.length; + return packet.length; + }*/ + + + if (!omx_running) return 0; // if we are not runnig do not do this + if (paused) return 0; //Block if we pause + + long long current_media_time=GetCurrentSystemTime()+playbacktimeoffset; + if (packet.synched && + (packet.presentation_time<0 /*|| // preroll skip frames + (packet.presentation_time+5000000LL)<(current_media_time)*/)) { // we are late skip + Log::getInstance()->log("Video", Log::DEBUG, "DeliverMediaPacketOMX Preroll or too late %lld %lld; %lld", packet.presentation_time,current_media_time,playbacktimeoffset); + *samplepos=packet.length; + return packet.length; + } + + OMX_ERRORTYPE error; + + /*First Check, if we have an video sample*/ + if (iframemode) { + //samplepos=0; + MILLISLEEP(10); + return 0; //Not in iframe mode! + } + + UINT headerstrip=0; + if (packet.disconti) { + firstsynched=false; + if (cur_input_buf_omx) { + 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; + } + } + + /*Inspect PES-Header */ + +// OMX_STATETYPE temp_state; +// OMX_GetState(omx_vid_dec,&temp_state); + + if (*samplepos==0) {//stripheader + headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/; + if (h264) Log::getInstance()->log("Video", Log::DEBUG, "PES info %x %x %x %x", + buffer[packet.pos_buffer+0],buffer[packet.pos_buffer+1],buffer[packet.pos_buffer+2],buffer[packet.pos_buffer+3]); + *samplepos+=headerstrip; + 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); + } + cur_input_buf_omx=NULL;//write out old data + FrameWaitforDisplay(lastreftimeOMX); + + + } + firstsynched=true; + } else { + if (!firstsynched) {// + *samplepos=packet.length;//if we have not processed at least one + return packet.length;//synched packet ignore it! + } + } + } + + 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(); + } + + + + + if (cur_input_buf_omx->nFilledLen==0) {//will only be changed on first packet + 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 { + //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; + + 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 + + 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+cur_input_buf_omx->nFilledLen, + buffer+packet.pos_buffer+*samplepos,haveToCopy); + cur_input_buf_omx->nFilledLen+=haveToCopy; + + + + *samplepos+=haveToCopy; + + return *samplepos; + +} + + + + +bool VideoOMX::displayIFrame(const UCHAR* buffer, UINT length) { + if (!omx_running) return false; + if (!iframemode) + EnterIframePlayback(); + + int haveToCopy = length; + + 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 false; // 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(); + } + + int read_pos = 0; + unsigned int pattern, packet_length; + unsigned int headerstrip = 0; + bool first = true; + if (length < 4){ + return false; + } + //Now we strip the pes header + pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]); + while (read_pos + 7 <= length) { + pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos + 3]; + if (pattern < 0x000001E0 || pattern > 0x000001EF) { + read_pos++; + continue; + } else { + headerstrip = buffer[read_pos + 8] + 9/*is this right*/; + packet_length = ((buffer[read_pos + 4] << 8) + | (buffer[read_pos + 5])) + 6; + if (read_pos + packet_length > length) + read_pos = length; + else { + if ((headerstrip < packet_length) + && (cur_input_buf_omx->nFilledLen + packet_length + - headerstrip) > cur_input_buf_omx->nAllocLen) { + if (first) { + cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_STARTTIME; + + } else { + cur_input_buf_omx->nFlags + |= OMX_BUFFERFLAG_TIME_UNKNOWN; + + } + cur_input_buf_omx->nTimeStamp = 0; + 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; + + if (!cur_input_buf_omx) { + int count = 0; + while (count < 100 && omx_running && iframemode) { + count++; + + input_bufs_omx_mutex.Lock(); + if (input_bufs_omx_free.size() == 0) { + input_bufs_omx_mutex.Unlock(); + Log::getInstance()->log("Video", Log::DEBUG, + "Ifrane no free sample"); + MILLISLEEP(5); + if (!omx_running) return false; + continue; + } + 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(); + break; + } + if (!cur_input_buf_omx) + return false; + } + + } + if (packet_length > headerstrip) { + memcpy( + cur_input_buf_omx->pBuffer + + cur_input_buf_omx->nFilledLen, + buffer + read_pos + headerstrip, + packet_length - headerstrip); + cur_input_buf_omx->nFilledLen += packet_length + - headerstrip; + } + read_pos += packet_length; + + pattern = (buffer[read_pos] << 16) + | (buffer[read_pos + 1] << 8) | (buffer[read_pos + 2]); + } + } + } + + if (first) { + cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_STARTTIME; + + } else { + cur_input_buf_omx->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; + + } + cur_input_buf_omx->nTimeStamp = 0; + 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; + + + MILLISLEEP(40); //Block a bit + return true; +} + +int VideoOMX::EnterIframePlayback() +{ + clock_mutex.Lock(); + if (cur_input_buf_omx) { + 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; + } + clock_mutex.Unlock(); + iframemode=true; + + return 1; +} + diff --git a/videovpeogl.h b/videoomx.h similarity index 50% rename from videovpeogl.h rename to videoomx.h index 2acda35..b006f88 100644 --- a/videovpeogl.h +++ b/videoomx.h @@ -1,5 +1,5 @@ /* - Copyright 2004-2005 Chris Tallon 2009 Marten Richter + Copyright 2004-2005 Chris Tallon 2009,2012 Marten Richter This file is part of VOMP. @@ -19,8 +19,8 @@ */ -#ifndef VIDEOVPEOGL_H -#define VIDEOVPEOGL_H +#ifndef VIDEOOMX_H +#define VIDEOOMX_H #include "mutex.h" @@ -41,14 +41,6 @@ #include "threadsystem.h" -//#define EGL_EGLEXT_PROTOTYPES - -#include -#include -#include - -#ifdef VPE_OMX_SUPPORT - #include #include #include @@ -64,73 +56,17 @@ struct VPE_OMX_EVENT { OMX_IN OMX_PTR event_data; }; -#endif - -#if defined(VPE_LIBAV_MPEG2_TRANSCODING) || defined(VPE_LIBAV_SUPPORT) -extern "C" { -#include -#include -#include -} -#endif - -#ifdef VPE_LIBAV_MPEG2_TRANSCODING -extern "C" { -#include -} -#if !defined(VPE_OMX_SUPPORT) -#error "VPE_LIBAV_MPEG2_TRANSCODING defined, and not VPE_OMX_SUPPORT defined!" -#endif -#endif - -#ifdef VPE_LIBAV_SUPPORT - -#include -extern "C" { -#include -} -#include "glmocoshader.h" - -struct VPEOGLFrame; - -struct VPE_FrameBuf -{ //This is a frame bulibaver, nothing fancy just plain memory - void *data[4]; - unsigned int size[4]; - unsigned int pict_num; - VPEOGLFrame *ogl_ref; - bool ogl_uploaded; - int width, height; - int stride; -}; - -#endif - -struct VPEOGLFrame { - int type; //1 = YUV400, 2 YUV444 - GLuint textures[3]; // 0=RGB or Y, 1=U 2=V - int width, height; - int stride; - unsigned int pict_num; -/* -#ifdef VPE_OMX_SUPPORT - //OMX - EGLImageKHR khr_image; - OMX_BUFFERHEADERTYPE *omx_buf; -#endif*/ -}; - class AudioVPE; -class VideoVPEOGL : public Video, public Thread_TYPE +class VideoOMX : public Video { - friend class AudioVPE; + friend class AudioOMX; public: - VideoVPEOGL(); - virtual ~VideoVPEOGL(); + VideoOMX(); + virtual ~VideoOMX(); int init(UCHAR format); int shutdown(); @@ -172,9 +108,6 @@ class VideoVPEOGL : public Video, public Thread_TYPE void WriteOutPATPMT(); - VPEOGLFrame *getReadyOGLFrame(); - void returnOGLFrame(VPEOGLFrame *frame); - void recycleOGLRefFrames(); virtual long long SetStartOffset(long long curreftime, bool *rsync); long long SetStartAudioOffset(long long curreftime, bool *rsync); @@ -189,12 +122,8 @@ class VideoVPEOGL : public Video, public Thread_TYPE int initUsingOSDObjects(); int shutdownUsingOSDObjects() {return shutdown();}; -#ifdef VPE_LIBAV_SUPPORT - int getlibavDecodingMode() {return decoding_mode;}; -#endif - private: int EnterIframePlayback(); bool iframemode; @@ -202,10 +131,8 @@ class VideoVPEOGL : public Video, public Thread_TYPE 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; @@ -229,7 +156,6 @@ class VideoVPEOGL : public Video, public Thread_TYPE -#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, OMX_IN OMX_U32 data2,OMX_IN OMX_PTR event_data); @@ -306,137 +232,8 @@ class VideoVPEOGL : public Video, public Thread_TYPE - -#endif - -#ifdef VPE_LIBAV_MPEG2_TRANSCODING - list input_bufs_omx_in_libav; - vector pix_fmt_omx_all; - list pix_fmt_omx_free; - // this is for - AVCodec *transcodecodec_libav; - AVCodecContext *transcodecodec_context_libav; - AVFrame transcode_frame_libav; - - static enum PixelFormat get_format_transcode(struct AVCodecContext *s, const enum PixelFormat *fmt); - static int reget_buffer_transcode(struct AVCodecContext *c, AVFrame *pic); - static int get_buffer_transcode(struct AVCodecContext *c, AVFrame *pic); - OMX_BUFFERHEADERTYPE* GetFreeOMXBufferforlibav(transcode_pix_fmt **pix_trans); - static void release_buffer_transcode(struct AVCodecContext *c, AVFrame *pic); - void ReturnEmptyOMXBuffer_libav(OMX_BUFFERHEADERTYPE* buffer,transcode_pix_fmt *pix_fmt); - - - UINT DeliverMediaPacketOMXTranscode(MediaPacket packet,const UCHAR* bulibaver,UINT *samplepos); - int DecodePacketOMXTranscode(); - int InitTranscoderLibAV(); - int DeInitTranscoderLibAV(); - - -#endif - -#if defined(VPE_LIBAV_MPEG2_TRANSCODING) || defined(VPE_LIBAV_SUPPORT) - AVPacket incom_packet_libav; - int incom_packet_libav_size; - - -#endif - -#ifdef VPE_LIBAV_SUPPORT // this is the data for software decoding subject to removal - - const static int VPE_NO_XVMC=0; - const static int VPE_XVMC_MOCOMP=1; - const static int VPE_XVMC_IDCT=2; - - int decoding_mode; - - AVCodec *mpeg2codec_libav; - AVCodecContext *mpeg2codec_context_libav; - vector dec_frame_libav_all; - list dec_frame_libav_free; - list dec_frame_libav_upload_and_view_pending; - list dec_frame_libav_upload_only_pending; - //AVFrame* dec_frame_libav_uploading; - VPE_FrameBuf* dec_frame_libav_uploading_framebuf; - AVFrame* dec_frame_libav_decoding; - - void add_dec_frame_upload_only(struct AVCodecContext *s,const AVFrame* data); - - vector all_frame_bufs; - list free_frame_bufs; - list locked_libav_frame_buf; - list locked_uploading_frame_buf; - - VPE_FrameBuf *getFrameBuf(unsigned int *size); //for libav - void releaseFrameBufLibav(VPE_FrameBuf*data); - void lockFrameBufUpload(VPE_FrameBuf* data); - void releaseFrameBufUpload(VPE_FrameBuf* data); - - unsigned int framebuf_framenum; - - Mutex vpe_framebuf_mutex; - - - - - Mutex dec_frame_libav_mutex; - - - - UINT DeliverMediaPacketlibav(MediaPacket packet,const UCHAR* bulibaver,UINT *samplepos); - int AllocateCodecsLibav(); - int DeAllocateCodecsLibav(); - int DecodePacketlibav(); - - static enum PixelFormat get_format_libav(struct AVCodecContext *s, const enum PixelFormat *fmt); - static int get_buffer_libav(struct AVCodecContext *c, AVFrame *pic); - static int reget_buffer_libav(struct AVCodecContext *c, AVFrame *pic); - static void release_buffer_libav(struct AVCodecContext *c, AVFrame *pic); - - static void draw_horiz_band_libav(struct AVCodecContext *s, const AVFrame *src, int offset[4], int y, int type, int height); - - bool libav_running; - bool libav_hastime; // signals if a pts is now - long long libav_time; - - int libavwidth,libavheight,libavpixfmt; - GLMocoShader *moco_shader; - - - - - vector all_ogl_frames; - list free_ogl_frames; - list recycle_ref_ogl_frames; - list ready_ogl_frames; - int ogl_forward_ref_frame_num; - int ogl_backward_ref_frame_num; - VPEOGLFrame* ogl_forward_ref_frame; - VPEOGLFrame* ogl_backward_ref_frame; - - bool ogl_frame_outside; - Mutex ogl_frame_mutex; - - int AllocateYUV400OglTexture(VPEOGLFrame* outframe,int width,int height,int stride); - int AllocateYUV444OglTexture(VPEOGLFrame* outframe,int width,int height,int stride); -#endif - - virtual void threadMethod(); - virtual void threadPostStopCleanup(); - - - bool firstsynched; - EGLDisplay egl_display; - EGLSurface egl_surface; - EGLContext egl_context; -#ifdef BENCHMARK_FPS - unsigned int time_in_decoder; - unsigned int num_frames; - unsigned int time_in_decoder_gl; - unsigned int num_frames_gl; -#endif - MediaPacket mediapacket; }; diff --git a/videovpeogl.cc b/videovpeogl.cc deleted file mode 100644 index 1ce1253..0000000 --- a/videovpeogl.cc +++ /dev/null @@ -1,3630 +0,0 @@ -/* - Copyright 2004-2005 Chris Tallon, 2009 Marten Richter - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "videovpeogl.h" -#include "audiovpe.h" -#include "mtdraspberry.h" -#include "demuxer.h" -#include "osdopengl.h" - -// temp -#include "log.h" - -//A lot of parts of this file are heavily inspired by xbmc omx implementations - -VideoVPEOGL::VideoVPEOGL() -{ - -#ifdef VPE_OMX_SUPPORT - omx_running=false; - - omx_vid_dec=0; - cur_input_buf_omx=NULL; - omx_h264=omx_mpeg2=true; - clock_references=0; -#endif - -#ifdef VPE_LIBAV_SUPPORT - mpeg2codec_context_libav=NULL; - libav_running=false; - dec_frame_libav_uploading_framebuf=NULL; - dec_frame_libav_decoding=NULL; - ogl_frame_outside=false; - //decoding_mode=VPE_NO_XVMC; - decoding_mode=VPE_XVMC_MOCOMP; - //decoding_mode=VPE_XVMC_IDCT; - framebuf_framenum=0; - moco_shader=NULL; - - ogl_forward_ref_frame_num=0; - ogl_backward_ref_frame_num=0; - ogl_forward_ref_frame=NULL; - ogl_backward_ref_frame=NULL; -#endif - -#ifdef VPE_LIBAV_MPEG2_TRANSCODING - transcodecodec_libav=NULL; - 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; - num_frames=0; - time_in_decoder_gl=0; - num_frames_gl=0; -#endif - -} - -VideoVPEOGL::~VideoVPEOGL() -{ - instance = NULL; -} - -int VideoVPEOGL::init(UCHAR tformat) -{ - if (initted) return 0; - initted = 1; - - if (!setFormat(tformat)) { shutdown(); return 0; } - if (!setConnection(COMPOSITERGB)) { shutdown(); return 0; } - if (!setAspectRatio(ASPECT4X3)) { shutdown(); return 0; } - if (!setMode(NORMAL)) { shutdown(); return 0; } - if (!setSource()) { shutdown(); return 0; } - if (!attachFrameBuffer()) { shutdown(); return 0; } - - setTVsize(ASPECT4X3); - - - - - - //stop(); - - - - return 1; -} - -int VideoVPEOGL::initUsingOSDObjects() -{ - EGLDisplay i_egl_display; - EGLSurface i_egl_surface; - EGLContext i_egl_context; - EGLConfig i_egl_config; - OsdOpenGL *osd=(OsdOpenGL*)osd->getInstance(); - osd->getEGLObjs(&i_egl_display,&i_egl_surface,&i_egl_context, &i_egl_config); - const EGLint attr_context[]={ - EGL_CONTEXT_CLIENT_VERSION,2, - EGL_NONE - }; - - egl_display=i_egl_display; - egl_context=eglCreateContext(egl_display,i_egl_config,i_egl_context,attr_context); - if (egl_context==EGL_NO_CONTEXT) { - Log::getInstance()->log("Video", Log::WARN, "Creating egl context failed! %x",eglGetError()); - return 0; - } - // We create a dummy surface here, in order to allow two contexts - const EGLint attr_pbuffer[]={ - EGL_WIDTH, 1, EGL_HEIGHT,1, - EGL_NONE - }; - egl_surface=eglCreatePbufferSurface(egl_display,i_egl_config,attr_pbuffer); - if (egl_surface==EGL_NO_SURFACE) { - Log::getInstance()->log("Video", Log::WARN, "Creating egl pbuffer failed! %x",eglGetError()); - return 0; - } - - - - - //egl_surface=i_egl_surface; - //egl_context=i_egl_context; - - -#ifdef VPE_OMX_SUPPORT -// we are called before the audio - OMX_ERRORTYPE error; - error=OMX_Init(); - if (error!=OMX_ErrorNone) { - Log::getInstance()->log("Video", Log::DEBUG, "Init OMX failed %x", error); - return 0; - } - - //our callbacks move to play? - -#endif - -#if defined(VPE_LIBAV_MPEG2_TRANSCODING) || defined(VPE_LIBAV_SUPPORT) - av_register_all(); -#endif - -#ifdef VPE_LIBAV_SUPPORT - - - if (decoding_mode==VPE_NO_XVMC) { - mpeg2codec_libav=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO); - } else { - mpeg2codec_libav=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO_XVMC); - } - if (mpeg2codec_libav==NULL) { - Log::getInstance()->log("Video", Log::DEBUG, "Find libav mpeg2 codec failed"); - return 0; - } -#endif -#ifdef VPE_LIBAV_MPEG2_TRANSCODING - transcodecodec_libav=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO_MPEG4); - if (transcodecodec_libav==NULL) { - Log::getInstance()->log("Video", Log::DEBUG, "Find libav mpeg2 transcoder failed"); - return 0; - } -#endif - - - threadStart(); - return 1; -} - - -#ifdef VPE_OMX_SUPPORT - -OMX_ERRORTYPE VideoVPEOGL::EventHandler_OMX(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) { - - 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: { - - } break; - }*/ - - return OMX_ErrorNone; - -} - -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; -} - -#ifdef VPE_LIBAV_MPEG2_TRANSCODING - - enum PixelFormat VideoVPEOGL::get_format_transcode(struct AVCodecContext *s, const enum PixelFormat *fmt) - { - enum PixelFormat ret_pix=PIX_FMT_NONE; - - while (*fmt!=PIX_FMT_NONE) { - if (*fmt== PIX_FMT_TRANSCODE ) { - ret_pix=PIX_FMT_TRANSCODE; - } - fmt++; - } - return ret_pix; - } - - int VideoVPEOGL::reget_buffer_transcode(struct AVCodecContext *c, AVFrame *pic) - { - Log::getInstance()->log("Video", Log::DEBUG,"Buffer reusing! Should not happen!Not Implemented! \n"); - - return -1; - } - - int VideoVPEOGL::get_buffer_transcode(struct AVCodecContext *c, AVFrame *pic) - { - - //reget logic from mplayer - if (pic->opaque && pic->data[0] && (!pic->buffer_hints ||pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE )){ - Log::getInstance()->log("Video", Log::DEBUG,"Buffer reusing! Should not happen!\n"); - return 0; - } - - - if (c->pix_fmt!=PIX_FMT_TRANSCODE ) { - Log::getInstance()->log("Video", Log::DEBUG,"We only support transcode pixel fmt\n"); - return 0; - } - VideoVPEOGL *video=(VideoVPEOGL *)getInstance(); - transcode_pix_fmt *pix_trans=NULL; - OMX_BUFFERHEADERTYPE* our_buf=video->GetFreeOMXBufferforlibav(&pix_trans); - if (our_buf==NULL|| pix_trans==NULL) { - Log::getInstance()->log("Video", Log::DEBUG,"Getting buffer failed\n"); - return -1; - } else { - - } - - - - - //populate pict - pic->type=FF_BUFFER_TYPE_USER; // we are controlling the buffers - - pic->base[0]=(uint8_t*)our_buf; // our buf - //pic->extended_data=pic->data; - if(c->pkt) pic->pkt_pts=c->pkt->pts; - else pic->pkt_pts=AV_NOPTS_VALUE; - pic->width=c->width; - pic->height=c->height; - pic->format=c->pix_fmt; - pic->sample_aspect_ratio=c->sample_aspect_ratio; - pic->reordered_opaque= c->reordered_opaque; - //pic->age=INT_MAX; - pic->data[0]=(uint8_t*)pix_trans; - pix_trans->transcode_id=AV_TRANSCODE_ID; - pix_trans->packet.data=(uint8_t*)our_buf->pBuffer; - pix_trans->packet.size=our_buf->nAllocLen; - //that is all folks - - return 0; - - } - - OMX_BUFFERHEADERTYPE* VideoVPEOGL::GetFreeOMXBufferforlibav(transcode_pix_fmt **pix_trans) - { - OMX_BUFFERHEADERTYPE* returned_buf=NULL; - *pix_trans=NULL; - int time_out=0; - - while (returned_buf==NULL && time_out<100){ - input_bufs_omx_mutex.Lock(); - if (input_bufs_omx_free.size()!=0) { - returned_buf=input_bufs_omx_free.front(); - returned_buf->nFilledLen=0; - returned_buf->nOffset=0; - returned_buf->nTimeStamp=0; - input_bufs_omx_free.pop_front(); - input_bufs_omx_in_libav.push_back(returned_buf); - input_bufs_omx_mutex.Unlock(); - returned_buf->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN; - break; - } - input_bufs_omx_mutex.Unlock(); - Log::getInstance()->log("Video", Log::DEBUG, "GetFreeOMXBuffer_libav no free sample block"); - time_out++; - MILLISLEEP(20); - } - if (returned_buf) { - *pix_trans=pix_fmt_omx_free.front(); - pix_fmt_omx_free.pop_front(); // we assume that there is always a twin - } - return returned_buf; - } - - void VideoVPEOGL::release_buffer_transcode(struct AVCodecContext *c, AVFrame *pic) - { - VideoVPEOGL *video=(VideoVPEOGL *)getInstance(); - video->ReturnEmptyOMXBuffer_libav((OMX_BUFFERHEADERTYPE*) pic->base[0],(transcode_pix_fmt *)pic->data[0]); - pic->data[0]=NULL; //without doing this avcodec is going to cry - } - - void VideoVPEOGL::ReturnEmptyOMXBuffer_libav(OMX_BUFFERHEADERTYPE* buffer,transcode_pix_fmt *pix_fmt){ - input_bufs_omx_mutex.Lock(); - // We only return it, if it was not passed to OMX! - Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer_libav %d",input_bufs_omx_free.size()); - pix_fmt_omx_free.push_back(pix_fmt); - list::iterator itty=input_bufs_omx_in_libav.begin(); - while (itty!=input_bufs_omx_in_libav.end()) { - if (*itty==buffer) { - input_bufs_omx_in_libav.remove(buffer); - input_bufs_omx_free.push_back(buffer); - Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer_libav %d",input_bufs_omx_free.size()); - break; - } - } - input_bufs_omx_mutex.Unlock(); - } - - -#endif - -#endif - -int VideoVPEOGL::shutdown() -{ - if (!initted) return 0; - initted = 0; - threadCancel(); - - decoding_backend=0; -#ifdef VPE_OMX_SUPPORT - DeAllocateCodecsOMX(); - OMX_Deinit(); -#endif -#ifdef VPE_LIBAV_SUPPORT - DeAllocateCodecsLibav(); -#endif - eglDestroyContext(egl_display,egl_context); -// close(fdVideo); - return 1; -} -#ifdef VPE_LIBAV_SUPPORT -int VideoVPEOGL::AllocateYUV400OglTexture(VPEOGLFrame* outframe,int width,int height,int stride) -{ - Log::getInstance()->log("Video", Log::NOTICE, "Allocate ogl texture 400"); - // Y - glGenTextures(1, &outframe->textures[0]); - glBindTexture(GL_TEXTURE_2D, outframe->textures[0]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, stride, height, 0, GL_LUMINANCE, - GL_UNSIGNED_BYTE, NULL); - // U - glGenTextures(1, &outframe->textures[1]); - glBindTexture(GL_TEXTURE_2D, outframe->textures[1]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, stride>>1, height>>1, 0, GL_LUMINANCE, - GL_UNSIGNED_BYTE, NULL); - // V - glGenTextures(1, &outframe->textures[2]); - glBindTexture(GL_TEXTURE_2D, outframe->textures[2]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, stride>>1, height>>1, 0, GL_LUMINANCE, - GL_UNSIGNED_BYTE, NULL); - outframe->height=height; - outframe->width=width; - outframe->stride=stride; - outframe->type=1; - return 1; -} - -int VideoVPEOGL::AllocateYUV444OglTexture(VPEOGLFrame* outframe,int width,int height,int stride) -{ - Log::getInstance()->log("Video", Log::NOTICE, "Allocate ogl texture 444"); - // Y - glGenTextures(1, &outframe->textures[0]); - glBindTexture(GL_TEXTURE_2D, outframe->textures[0]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, NULL); - outframe->textures[1]=outframe->textures[2]=0; // no handles here - - - - - outframe->type=2; - outframe->height=height; - outframe->width=width; - outframe->stride=stride;// does not make any sense otherwise, just to prevent reallocating - return 1; -} - - -VPEOGLFrame *VideoVPEOGL::getReadyOGLFrame(){ - VPEOGLFrame *return_obj=NULL; - ogl_frame_mutex.Lock(); - if (ready_ogl_frames.size()>0) { - return_obj=ready_ogl_frames.front(); - ready_ogl_frames.pop_front(); - //Log::getInstance()->log("Video", Log::WARN, "readyOGLRFrame markoutgoing num: %d",return_obj->pict_num); - ogl_frame_outside=true; - } - ogl_frame_mutex.Unlock(); - return return_obj; -} - -void VideoVPEOGL::returnOGLFrame(VPEOGLFrame *frame) -{ - ogl_frame_mutex.Lock(); - if (frame) { - ogl_frame_outside=false; - //Log::getInstance()->log("Video", Log::WARN, "returnOGLRFrame mark incoming num: %d",frame->pict_num); - if (frame->pict_num==ogl_forward_ref_frame_num || - frame->pict_num==ogl_backward_ref_frame_num ) { - recycle_ref_ogl_frames.push_back(frame); - } else { - free_ogl_frames.push_back(frame); - } - } - ogl_frame_mutex.Unlock(); -} - -void VideoVPEOGL::recycleOGLRefFrames() -{ - // This function recycles frames formerly used as reference frame - ogl_frame_mutex.Lock(); - list keep; - list::iterator itty=recycle_ref_ogl_frames.begin(); - while (itty!=recycle_ref_ogl_frames.end()) { - // Log::getInstance()->log("Video", Log::WARN, "recycleOGLRefFrame mark3"); - if ((*itty)->pict_num==ogl_forward_ref_frame_num - || (*itty)->pict_num==ogl_backward_ref_frame_num) - { - // ok we have to keep this - keep.push_back(*itty); - } else { - free_ogl_frames.push_back(*itty); - } - itty++; - } - recycle_ref_ogl_frames.clear(); - recycle_ref_ogl_frames=keep; - - ogl_frame_mutex.Unlock(); - - -} -#endif - -void VideoVPEOGL::threadMethod() -{ - if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) { - Log::getInstance()->log("Video", Log::WARN, "Making egl Current failed in thread %d",eglGetError()); - return; - } - long long run=0; - while (1) { - bool sleep=true; - - run++; -#ifdef VPE_LIBAV_SUPPORT - bool upload=false; - bool view=false; - dec_frame_libav_mutex.Lock(); - AVFrame* dec_frame_libav_uploading_int=NULL; - - - if (dec_frame_libav_upload_and_view_pending.size()>0 ) { - - dec_frame_libav_uploading_int=dec_frame_libav_upload_and_view_pending.front(); - dec_frame_libav_uploading_framebuf=(VPE_FrameBuf*)dec_frame_libav_uploading_int->base[0]; - //Log::getInstance()->log("Video", Log::WARN, "threadMethod u and view %d %lld %x",(dec_frame_libav_uploading_framebuf)->pict_num,run, - // dec_frame_libav_uploading_framebuf); - // if (dec_frame_libav_upload_only_pending.size()>0) Log::getInstance()->log("Video", Log::WARN, "threadMethod u and view2 %d", - // ((VPE_FrameBuf*)dec_frame_libav_upload_only_pending.front())->pict_num); - - view=true; - if ((dec_frame_libav_uploading_framebuf)->ogl_uploaded || decoding_mode==VPE_NO_XVMC ) { - dec_frame_libav_upload_and_view_pending.pop_front(); - if (decoding_mode==VPE_NO_XVMC) upload=true; - } else { - dec_frame_libav_uploading_framebuf=NULL; - dec_frame_libav_uploading_int=NULL; // if not uploaded do not do it yet - view=false; //do the upload - // Log::getInstance()->log("Video", Log::WARN, "threadMethod u and view view canceled"); - } - } - - if (!view && dec_frame_libav_upload_only_pending.size()>0) { //this is for uploading reference frames ahead - - dec_frame_libav_uploading_framebuf=dec_frame_libav_upload_only_pending.front(); - //Log::getInstance()->log("Video", Log::WARN, "threadMethod u %d %lld %x",((VPE_FrameBuf*)dec_frame_libav_uploading_framebuf)->pict_num,run, - // dec_frame_libav_uploading_framebuf); - dec_frame_libav_upload_only_pending.pop_front(); - view=false; - upload=true; - /* if (((VPE_FrameBuf*)dec_frame_libav_uploading->base[0])->ogl_uploaded) { - upload=false; - dec_frame_libav_uploading=NULL; //do not upload again - }*/ - } - - - - - - - if (dec_frame_libav_upload_and_view_pending.size()>0 - ||dec_frame_libav_upload_only_pending.size()>0) sleep=false; - - dec_frame_libav_mutex.Unlock(); - - - if (dec_frame_libav_uploading_framebuf) { - - //Code Block for debugging if needed - /* Log::getInstance()->log("Video", Log::WARN, "Iterate all free ogl frames"); - ogl_frame_mutex.Lock(); - list::iterator itty=free_ogl_frames.begin(); - while (itty!=free_ogl_frames.end()) { - Log::getInstance()->log("Video", Log::WARN, "free ogl pict num %d",(*itty)->pict_num); - - itty++; - } - - itty=recycle_ref_ogl_frames.begin(); - while (itty!=recycle_ref_ogl_frames.end()) { - Log::getInstance()->log("Video", Log::WARN, "recycle ogl pict num %d",(*itty)->pict_num); - - itty++; - } - itty=ready_ogl_frames.begin(); - while (itty!=ready_ogl_frames.end()) { - Log::getInstance()->log("Video", Log::WARN, "ready ogl pict num %d",(*itty)->pict_num); - - itty++; - } - ogl_frame_mutex.Unlock();*/ - - - if (upload) { - int width,height,pixfmt; - //First get a free ogl image - VPEOGLFrame* out_frame=NULL; - //int msleep=0; - while (!out_frame) { - ogl_frame_mutex.Lock(); - // Log::getInstance()->log("Video", Log::WARN, "threadMethod mark upload 1a %d %d %d %d %d",all_ogl_frames.size(),free_ogl_frames.size(), - // recycle_ref_ogl_frames.size(),ready_ogl_frames.size(),ogl_frame_outside); - if (all_ogl_frames.size()==0) { - ogl_frame_mutex.Unlock(); break; - } - - if (free_ogl_frames.size()>0) { - width=libavwidth; - height=libavheight; - pixfmt=libavpixfmt; - out_frame=free_ogl_frames.front(); - free_ogl_frames.pop_front(); - } else { - ogl_frame_mutex.Unlock(); - MILLISLEEP(2); - // msleep+=2; - ogl_frame_mutex.Lock(); - } - // if (msleep)Log::getInstance()->log("Video", Log::WARN, "msleep FPS %d",msleep); - ogl_frame_mutex.Unlock(); - } - bool failed=false; - if (out_frame) { - // Log::getInstance()->log("Video", Log::WARN, "outframes old pict num: %d",out_frame->pict_num); - if (out_frame->textures[0]==0 || out_frame->width!=width || - out_frame->height!=height || out_frame->stride!=dec_frame_libav_uploading_framebuf->stride) { - if (out_frame->textures[0]!=0) { - glDeleteTextures(1,&out_frame->textures[0]); - out_frame->textures[0]=0; - } - if (out_frame->textures[1]!=0) { - glDeleteTextures(1,&out_frame->textures[1]); - out_frame->textures[1]=0; - } - if (out_frame->textures[2]!=0) { - glDeleteTextures(1,&out_frame->textures[2]); - out_frame->textures[2]=0; - } - - if (decoding_mode==VPE_NO_XVMC) { - if (!AllocateYUV400OglTexture(out_frame,width,height,dec_frame_libav_uploading_framebuf->stride)) failed=true; - } else { - if (!AllocateYUV444OglTexture(out_frame,width,height,dec_frame_libav_uploading_framebuf->stride)) failed=true; //We use a YUV 444 texture in this case - // the shaders are easier to implement - } - } - dec_frame_libav_uploading_framebuf->ogl_ref=out_frame; - dec_frame_libav_uploading_framebuf->ogl_uploaded=true; - - - if (!failed) { - //up to now only YUV data, this is for reference only, since the pi is too slow. - if (decoding_mode==VPE_NO_XVMC) { - glBindTexture(GL_TEXTURE_2D, out_frame->textures[0]); - glPixelStorei(GL_UNPACK_ALIGNMENT,1); - glTexSubImage2D(GL_TEXTURE_2D,0,0,0, - out_frame->stride,out_frame->height, - GL_LUMINANCE,GL_UNSIGNED_BYTE, - dec_frame_libav_uploading_framebuf->data[0]); - - glBindTexture(GL_TEXTURE_2D, out_frame->textures[1]); - glPixelStorei(GL_UNPACK_ALIGNMENT,1); - glTexSubImage2D(GL_TEXTURE_2D,0,0,0, - out_frame->stride>>1,out_frame->height>>1, - GL_LUMINANCE,GL_UNSIGNED_BYTE, - dec_frame_libav_uploading_framebuf->data[1]); - - glBindTexture(GL_TEXTURE_2D, out_frame->textures[2]); - glPixelStorei(GL_UNPACK_ALIGNMENT,1); - glTexSubImage2D(GL_TEXTURE_2D,0,0,0, - out_frame->stride>>1,out_frame->height>>1, - GL_LUMINANCE,GL_UNSIGNED_BYTE, - dec_frame_libav_uploading_framebuf->data[2]); - } else { - //XVMC case - xvmc_pix_fmt * pix_fmt=(xvmc_pix_fmt *)dec_frame_libav_uploading_framebuf->data[2]; - if (moco_shader && pix_fmt) { - -#ifdef BENCHMARK_FPS - int cur_time=getTimeMS(); -#endif - moco_shader->uploadDataBlocks(pix_fmt->data_blocks,pix_fmt->next_free_data_block_num, - pix_fmt->mv_blocks , pix_fmt->filled_mv_blocks_num ); - // Log::getInstance()->log("Video", Log::WARN, "Pictnum %d Forward %d Backward %d ",pix_fmt->p_surface, - // pix_fmt->p_past_surface,pix_fmt->p_future_surface); - - if (((int)pix_fmt->p_future_surface)!=0 && ogl_backward_ref_frame_num!=((int)pix_fmt->p_future_surface)) - { - //Now determine the frame, that fits - ogl_frame_mutex.Lock(); - bool found=false; - for (int i=0;ipict_num==((int)pix_fmt->p_future_surface)) - { - ogl_forward_ref_frame=ogl_backward_ref_frame; //mpeg life time axioms - ogl_forward_ref_frame_num=ogl_backward_ref_frame_num; - ogl_backward_ref_frame=all_ogl_frames[i]; - ogl_backward_ref_frame_num=(int)pix_fmt->p_future_surface; - found=true; - break; - } - } - // if (!found) {// for debugging - // Log::getInstance()->log("Video", Log::WARN, "Emergency reference frame not found"); - // exit(0); - // } - - ogl_frame_mutex.Unlock(); - recycleOGLRefFrames(); //needed for recycling of reference frames - } - // Log::getInstance()->log("Video", Log::WARN, "Pictnum mark1"); - -/* - if ( ((int)pix_fmt->p_past_surface)==ogl_backward_ref_frame_num) - { - - }*/ - - if (((int)pix_fmt->p_past_surface)!=0 && ogl_forward_ref_frame_num!=((int)pix_fmt->p_past_surface)) - { - //Now determine the frame, that fits - ogl_frame_mutex.Lock(); - bool found=false; - for (int i=0;ipict_num==((int)pix_fmt->p_past_surface)) - { - ogl_forward_ref_frame=all_ogl_frames[i]; - ogl_forward_ref_frame_num=(int)pix_fmt->p_past_surface; // This should not happen, or for DMV, who knows - found=true; - break; - } - } - // if (!found) { - // Log::getInstance()->log("Video", Log::WARN, "Emergency reference frame not found %d %d",ogl_forward_ref_frame_num, - // ((int)pix_fmt->p_past_surface)); - // exit(0); - // } - - ogl_frame_mutex.Unlock(); - recycleOGLRefFrames(); //needed for recycling of reference frames - - } - //Log::getInstance()->log("Video", Log::WARN, "Pictnum mark2"); - - if (decoding_mode==VPE_XVMC_MOCOMP) - { - //DCT Blocks upload - - } else { - //DCT Blocks upload - } - out_frame->pict_num=dec_frame_libav_uploading_framebuf->pict_num; - - // Log::getInstance()->log("Video", Log::WARN, "Pictnum mark3"); - - moco_shader->doMoCo(out_frame,(((int)pix_fmt->p_past_surface)!=0)? ogl_forward_ref_frame:NULL, - (((int)pix_fmt->p_future_surface)!=0)? ogl_backward_ref_frame:NULL); - -#ifdef BENCHMARK_FPS - time_in_decoder_gl+=getTimeMS()-cur_time; - num_frames_gl++; - if ((num_frames_gl%100)==0) { - float fps=1000./(float)(time_in_decoder_gl); - fps*=((float)num_frames_gl); - Log::getInstance()->log("Video", Log::NOTICE, "Current GL Decoding FPS %g", fps); - } -#endif - - //Log::getInstance()->log("Video", Log::WARN, "Pictnum mark4"); - // Excute motion compensation - } else { - //Log::getInstance()->log("Video", Log::WARN, "moco pixfmt error abort"); - // exit(0); - } - } - - - - } - } - - } - - - - if (view) { - - //Log::getInstance()->log("Video", Log::WARN, "threadMethod mark view"); - VPEOGLFrame* out_frame=dec_frame_libav_uploading_framebuf->ogl_ref; - xvmc_pix_fmt * pix_fmt=(xvmc_pix_fmt *)dec_frame_libav_uploading_framebuf->data[2]; - /* Log::getInstance()->log("Video", Log::WARN, "View Pictnum %d Forward %d Backward %d pict_num %d",pix_fmt->p_surface, - pix_fmt->p_past_surface,pix_fmt->p_future_surface,out_frame->pict_num); - Log::getInstance()->log("Video", Log::WARN, "Real Pictnum %d ",out_frame->pict_num);*/ - - releaseFrameBufUpload(dec_frame_libav_uploading_framebuf); - ogl_frame_mutex.Lock(); - ready_ogl_frames.push_back(out_frame); - ogl_frame_mutex.Unlock(); - ((OsdOpenGL*)Osd::getInstance())->AdviseAboutNewFrame(); //Tell him, that we have a frame waiting - - dec_frame_libav_mutex.Lock(); - dec_frame_libav_free.push_back(dec_frame_libav_uploading_int); - dec_frame_libav_mutex.Unlock(); - } - - - dec_frame_libav_mutex.Lock(); - dec_frame_libav_uploading_framebuf=NULL; - - if (dec_frame_libav_upload_and_view_pending.size()>0 - ||dec_frame_libav_upload_only_pending.size()>0) sleep=false; - - dec_frame_libav_mutex.Unlock(); - - - - } -#endif - - if (sleep) { - struct timespec target_time; - int ts=20; //20 ms - clock_gettime(CLOCK_REALTIME,&target_time); - target_time.tv_nsec+=1000000LL*ts; - if (target_time.tv_nsec>999999999) { - target_time.tv_nsec-=1000000000L; - target_time.tv_sec+=1; - } - threadWaitForSignalTimed(&target_time); - //Log::getInstance()->log("Video", Log::WARN, "threadMethod signalled FPS"); - } - threadCheckExit(); - } - -} - - -void VideoVPEOGL::threadPostStopCleanup() -{ - eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ); -#ifdef VPE_LIBAV_SUPPORT - dec_frame_libav_uploading_framebuf=NULL; -#endif -} - - - - -int VideoVPEOGL::setTVsize(UCHAR ttvsize) -{ -/* tvsize = ttvsize; - - // Override the aspect ratio usage, temporarily use to set the video chip mode - if (!setAspectRatio(tvsize)) { shutdown(); return 0; } - close(fdVideo); - if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0; - if (!setSource()) { shutdown(); return 0; } - if (!attachFramebuffer()) { shutdown(); return 0; } - - // Reopening the fd causes the scart aspect line to go back to 4:3 - // Set this again to the same as the tv screen size - if (!setAspectRatio(tvsize)) { shutdown(); return 0; } - - // mode == LETTERBOX is invalid if the TV is widescreen - if (tvsize == ASPECT16X9) setMode(NORMAL); -*/ - return 1; -} - -int VideoVPEOGL::setDefaultAspect() -{ - return setAspectRatio(tvsize); -} - - - -int VideoVPEOGL::setFormat(UCHAR tformat) -{ - if (!initted) return 0; - if ((tformat != PAL) && (tformat != NTSC)) return 0; - format = tformat; - -// if (ioctl(fdVideo, AV_SET_VID_DISP_FMT, format) != 0) return 0; - - if (format == NTSC) - { - screenWidth = 720; - screenHeight = 480; - } - if (format == PAL) - { - screenWidth = 720; - screenHeight = 576; - } - - return 1; -} - -int VideoVPEOGL::setConnection(UCHAR tconnection) -{ - if (!initted) return 0; - if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0; - connection = tconnection; - -// if (ioctl(fdVideo, AV_SET_VID_OUTPUT, connection) != 0) return 0; - return 1; -} - -int VideoVPEOGL::setAspectRatio(UCHAR taspectRatio) -{ - if (!initted) return 0; - if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0; - aspectRatio = taspectRatio; - - Log::getInstance()->log("Video", Log::DEBUG, "Setting aspect to %i", aspectRatio); - -// if (ioctl(fdVideo, AV_SET_VID_RATIO, aspectRatio) != 0) return 0; - return 1; -} - -int VideoVPEOGL::setMode(UCHAR tmode) -{ - if (!initted) return 0; - - if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode - - if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH) - && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0; - mode = tmode; - -// if (ioctl(fdVideo, AV_SET_VID_MODE, mode) != 0) return 0; - return 1; -} - -int VideoVPEOGL::signalOff() -{ -// if (ioctl(fdVideo, AV_SET_VID_DENC, 0) != 0) return 0; - return 1; -} - -int VideoVPEOGL::signalOn() -{ -// if (ioctl(fdVideo, AV_SET_VID_DENC, 1) != 0) return 0; - return 1; -} - -int VideoVPEOGL::setSource() -{ - if (!initted) return 0; - - // What does this do... -// if (ioctl(fdVideo, AV_SET_VID_SRC, 1) != 0) return 0; - return 1; -} - -int VideoVPEOGL::setPosition(int x, int y) -{ - if (!initted) return 0; - -// vid_pos_regs_t pos_d; -// pos_d.x = x; -// pos_d.y = y; - -/* vid_pos_regs_t pos_d; - - memset(&pos_d, 0, sizeof(pos_d)); - - pos_d.dest.y = y; - pos_d.dest.x = x; -/* -typedef struct { - int w; - int h; - int scale; - int x1; - int y; - int x; - int y2; - int x3; - int y3; - int x4; - int y4; -} vid_pos_regs_t; -*/ - -/* - pos_d.w = 100; - pos_d.h = 30; - pos_d.scale = 2; - pos_d.x1 = 0; - pos_d.y = 100; // Top left X - pos_d.x = 50; // Top left Y - pos_d.y2 = 30; - pos_d.x3 = 60; - pos_d.y3 = 90; - pos_d.x4 = 120; - pos_d.y4 = 150; -*/ - -// if (ioctl(fdVideo, AV_SET_VID_POSITION, &pos_d) != 0) return 0; - return 1; -} - -int VideoVPEOGL::sync() -{ - if (!initted) return 0; - -// if (ioctl(fdVideo, AV_SET_VID_SYNC, 2) != 0) return 0; - return 1; -} - - - - -int VideoVPEOGL::play() -{ - if (!initted) return 0; - decoding_backend=0; - iframemode=false; -#ifdef VPE_OMX_SUPPORT - bool doomx=true; - Log::getInstance()->log("Video", Log::DEBUG, "enter play"); - if (h264) { - if (!omx_h264) doomx=false; - } else { - if (!omx_mpeg2) doomx=false; - } - if (doomx) { - if (AllocateCodecsOMX()) { - //decoding_backend=VPE_DECODER_OMX; - return 1; - // Otherwise fall back to libav - } else { - if (h264) { - omx_h264=false; - Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX failed assume h264 unsupported"); - } else { - omx_mpeg2=false; - Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX failed assume mpeg2 unsupported"); - } - } - } -#endif -#ifdef VPE_LIBAV_SUPPORT - if (AllocateCodecsLibav()) { - decoding_backend=VPE_DECODER_libav; - return 1; - // Otherwise fall back to libav - } -#endif - return 0; - - - -} - -#ifdef VPE_LIBAV_MPEG2_TRANSCODING - -int VideoVPEOGL::InitTranscoderLibAV() { - transcodecodec_context_libav = avcodec_alloc_context3(transcodecodec_libav); - if (!transcodecodec_context_libav) { - Log::getInstance()->log("Video", Log::DEBUG, "Alloc avcodec context failed!"); - return 0; - } - - transcodecodec_context_libav->slice_flags = SLICE_FLAG_CODED_ORDER; - - transcodecodec_context_libav->pix_fmt = PIX_FMT_TRANSCODE; - transcodecodec_context_libav->get_format = get_format_transcode; - transcodecodec_context_libav->get_buffer = get_buffer_transcode; - transcodecodec_context_libav->reget_buffer = reget_buffer_transcode; - transcodecodec_context_libav->release_buffer = release_buffer_transcode; - //transcodecodec_context_libav->flags |= CODEC_FLAG_TRUNCATED; - //transcodecodec_context_libav->time_base.den=9000; //pts values 90 KHz Clock /10; - - int avc_ret = avcodec_open2(transcodecodec_context_libav, transcodecodec_libav, NULL); - if (avc_ret < 0) { - Log::getInstance()->log("Video", Log::DEBUG, "Opening libav codec failed \n"); - return 0; - } - - memset(&incom_packet_libav, 0, sizeof(incom_packet_libav)); - incom_packet_libav_size = 200000; - incom_packet_libav.data = (uint8_t*) av_malloc(incom_packet_libav_size + FF_INPUT_BUFFER_PADDING_SIZE); - - return 1; -} - - - -int VideoVPEOGL::DeInitTranscoderLibAV() { - - av_free(incom_packet_libav.data); - incom_packet_libav.data=NULL; - incom_packet_libav_size=0; - - if (transcodecodec_context_libav) { - avcodec_close(transcodecodec_context_libav); - av_free(transcodecodec_context_libav); - transcodecodec_context_libav=NULL; - - } - - return 1; -} - -#endif - -#ifdef VPE_OMX_SUPPORT - -int VideoVPEOGL::initClock() -{ - OMX_ERRORTYPE error; - clock_mutex.Lock(); - if (clock_references==0) - { - - static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX}; - omx_events.clear(); - - error=OMX_GetHandle(&omx_clock,VPE_OMX_CLOCK,NULL,&callbacks); - - if (error!=OMX_ErrorNone) { - Log::getInstance()->log("Video", Log::DEBUG, "Init OMX clock failed %x", error); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - /* 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); - p_param.nVersion.nVersion=OMX_VERSION; - error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param); - if (error!=OMX_ErrorNone) { - Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - omx_clock_output_port=p_param.nStartPortNumber; - - for (unsigned int i=0;ilog("Video", Log::DEBUG, "Disable Ports OMX clock failed %d",i); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - } - - - - - } - Log::getInstance()->log("Video", Log::DEBUG, "init omx clock %x %x",this,omx_clock); - clock_references++; - clock_mutex.Unlock(); - return 1; -} - -int VideoVPEOGL::getClockAudioandInit(OMX_HANDLETYPE *p_omx_clock,OMX_U32 *p_omx_clock_output_port) -{ - OMX_ERRORTYPE error; - *p_omx_clock=NULL; - *p_omx_clock_output_port=0; - - if (!initClock()) { - return 0; - } - clock_mutex.Lock(); - - OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refclock; - memset(&refclock,0,sizeof(refclock)); - refclock.nSize=sizeof(refclock); - refclock.nVersion.nVersion=OMX_VERSION; - - refclock.eClock=OMX_TIME_RefClockAudio; - - //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); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - 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); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error); - clock_mutex.Unlock(); - 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_ClockStateWaitingForStartTime; - clock_conf.nStartTime=0; - clock_conf.nOffset=0; - if (clock_references==1) clock_conf.nWaitMask=OMX_CLOCKPORT1; - else clock_conf.nWaitMask=OMX_CLOCKPORT0|OMX_CLOCKPORT1; - error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf); - if (error!=OMX_ErrorNone) { - Log::getInstance()->log("Video", Log::DEBUG, "Clock IndexConfigTimeClockState failed %x", error); - } - - - *p_omx_clock_output_port=p_param.nStartPortNumber+1; - *p_omx_clock=omx_clock; - clock_mutex.Unlock(); - return 1; -} - -int VideoVPEOGL::getClockVideoandInit() -{ - OMX_ERRORTYPE error; - - if (!initClock()) { - return 0; - } - clock_mutex.Lock(); - - if (clock_references==1) { // only if no audio is attached to this clock! - OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refclock; - memset(&refclock,0,sizeof(refclock)); - refclock.nSize=sizeof(refclock); - refclock.nVersion.nVersion=OMX_VERSION; - - //refclock.eClock=OMX_TIME_RefClockAudio; - - 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); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - } - - 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); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error); - clock_mutex.Unlock(); - 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_ClockStateWaitingForStartTime; - clock_conf.nStartTime=0; - clock_conf.nOffset=0; - if (clock_references==1) clock_conf.nWaitMask=OMX_CLOCKPORT0; - else clock_conf.nWaitMask=OMX_CLOCKPORT0|OMX_CLOCKPORT1; - error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf); - if (error!=OMX_ErrorNone) { - Log::getInstance()->log("Video", Log::DEBUG, "Clock IndexConfigTimeClockState failed %x", error); - } - - omx_clock_output_port=p_param.nStartPortNumber; - clock_mutex.Unlock(); - - return 1; -} - -void VideoVPEOGL::clockUnpause() -{ - OMX_ERRORTYPE error; - clock_mutex.Lock(); - 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; - clock_conf.nStartTime=0; - clock_conf.nOffset=0; - clock_conf.nWaitMask=OMX_CLOCKPORT1; - error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf); - if (error!=OMX_ErrorNone) { - Log::getInstance()->log("Video", Log::DEBUG, "ClockUnpause IndexConfigTimeClockState failed %x", error); - } - - clock_mutex.Unlock(); -} - - -void VideoVPEOGL::clockPause() -{ - OMX_ERRORTYPE error; - clock_mutex.Lock(); - 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_ClockStateStopped; - clock_conf.nStartTime=0; - clock_conf.nOffset=0; - clock_conf.nWaitMask=OMX_CLOCKPORT1; - error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf); - if (error!=OMX_ErrorNone) { - Log::getInstance()->log("Video", Log::DEBUG, "ClockUnpause IndexConfigTimeClockState failed %x", error); - } - clock_mutex.Unlock(); -} - - - -int VideoVPEOGL::AllocateCodecsOMX() -{ - OMX_ERRORTYPE error; - static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX}; - - Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX"); - //Clock, move later to audio including events - - Log::getInstance()->log("Video", Log::DEBUG, "Nmark1 "); - 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"); - return 0; - } - /* TODO end */ - - - clock_mutex.Lock(); - if (h264) { - error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_H264_DECODER,NULL,&callbacks); - } else { - error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_MPEG2_DECODER,NULL,&callbacks); - } - - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video decoder failed %x", error); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - - Log::getInstance()->log("Video", Log::DEBUG, "Nmark3 "); - 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_vid_dec,OMX_IndexParamVideoInit,&p_param); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "Init OMX h264 decoder OMX_GetParameter failed %x", error); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - 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"); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - Log::getInstance()->log("Video", Log::DEBUG, "Nmark4 "); - - OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE conceal; - memset(&conceal,0,sizeof(conceal)); - conceal.nSize=sizeof(conceal); - conceal.nVersion.nVersion=OMX_VERSION; - conceal.bStartWithValidFrame=OMX_FALSE; - - error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamBrcmVideoDecodeErrorConcealment,&conceal); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "OMX_IndexParamBrcmVideoDecodeErrorConcealment failed %x", error); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - - error=OMX_GetHandle(&omx_vid_sched,VPE_OMX_VIDEO_SCHED,NULL,&callbacks); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler failed %x", error); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - - - error=OMX_GetParameter(omx_vid_sched,OMX_IndexParamVideoInit,&p_param); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler OMX_GetParameter failed %x", error); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - omx_shed_input_port=p_param.nStartPortNumber; - omx_shed_output_port=p_param.nStartPortNumber+1; - - - 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); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - 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,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"); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - 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); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - error=OMX_GetParameter(omx_vid_rend,OMX_IndexParamVideoInit,&p_param); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video rend OMX_GetParameter failed %x", error); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - omx_rend_input_port=p_param.nStartPortNumber; - //omx_rend_output_port=p_param.nStartPortNumber+1; - - - 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"); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - //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); - clock_mutex.Unlock(); - 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"); - clock_mutex.Unlock(); - 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"); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - - - Log::getInstance()->log("Video", Log::DEBUG, "mark1 "); - if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_clock_port)) { - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - - - - Log::getInstance()->log("Video", Log::DEBUG, "mark1 special "); - if ( !CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port)) { - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - clock_mutex.Unlock(); - - - 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); - ft_type.nVersion.nVersion=OMX_VERSION; - - ft_type.nPortIndex=omx_codec_input_port; - if (h264) { - ft_type.eCompressionFormat=OMX_VIDEO_CodingAVC; - } else { -#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(); - - 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); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - - if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) { - Log::getInstance()->log("Video", Log::DEBUG, "vid_dec ChangeComponentState"); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - - if (!PrepareInputBufsOMX()) { - 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 ( !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)) { - Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_dec ChangeComponentState Execute"); - clock_mutex.Unlock(); - 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); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - 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"); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - if (!CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_output_port) - || !CommandFinished(omx_vid_rend,OMX_CommandPortEnable,omx_rend_input_port)) { - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) { - Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState"); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - - if (!ChangeComponentState(omx_vid_sched,OMX_StateExecuting)) { - Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_sched ChangeComponentState Execute"); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - - if (!ChangeComponentState(omx_vid_rend,OMX_StateExecuting)) { - Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_rend ChangeComponentState Execute"); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - 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_SetConfig(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - 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); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - 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); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - }*/ - - if (decoding_backend!=VPE_DECODER_OMX_libav_TRANSCODE) decoding_backend=VPE_DECODER_OMX; - - playbacktimeoffset=-GetCurrentSystemTime(); - paused=false; - iframemode=false; - omx_running=true; - clock_mutex.Unlock(); - - setClockExecutingandRunning(); - - - - - - return 1; -} - -int VideoVPEOGL::idleClock() -{ - OMX_ERRORTYPE error; - OMX_STATETYPE temp_state; - clock_mutex.Lock(); - OMX_GetState(omx_clock,&temp_state); - - if (temp_state!=OMX_StateIdle) { - if (!ChangeComponentState(omx_clock,OMX_StateIdle)) { - Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Idle failed"); - clock_mutex.Unlock(); - return 0; - } - } - clock_mutex.Unlock(); - return 1; -} - -int VideoVPEOGL::setClockExecutingandRunning() -{ - OMX_ERRORTYPE error; - OMX_STATETYPE temp_state; - clock_mutex.Lock(); - OMX_GetState(omx_clock,&temp_state); - - if (temp_state!=OMX_StateExecuting) { - if (!ChangeComponentState(omx_clock,OMX_StateExecuting)) { - Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Execute failed"); - clock_mutex.Unlock(); - 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); - clock_mutex.Unlock(); - DeAllocateCodecsOMX(); - return 0; - } - clock_mutex.Unlock(); - return 1; - -} - - -int VideoVPEOGL::ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type) //needs to be called with locked mutex -{ - 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) //needs to be called with locked mutex -{ - 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) //needs to be called with locked mutex -{ - 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) //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, "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; - } - } - 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() //needs to be called with locked mutex -{ - 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; - - error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type); - - 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);*/ - - port_def_type.nBufferCountActual=60; - port_def_type.nBufferSize=max(port_def_type.nBufferSize,200000); // for transcoder important - - 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); - } - - - 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; - } - - input_bufs_omx_mutex.Lock(); - for (unsigned int i=0; i< port_def_type.nBufferCountActual;i++) { - - // 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); - 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); -#ifdef VPE_LIBAV_MPEG2_TRANSCODING - transcode_pix_fmt* new_pix=NULL; - new_pix=(transcode_pix_fmt*)malloc(sizeof(transcode_pix_fmt)); - pix_fmt_omx_all.push_back(new_pix); - pix_fmt_omx_free.push_back(new_pix); -#endif - } - omx_first_frame=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; -} - -int VideoVPEOGL::DestroyInputBufsOMX() //need s to be called with locked mutex -{ - OMX_ERRORTYPE error; - - 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; - 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); - input_bufs_omx_mutex.Unlock(); - return 0; - } - -#ifdef VPE_LIBAV_MPEG2_TRANSCODING - free(pix_fmt_omx_all[i]); -#endif - } - input_bufs_omx_all.clear(); - input_bufs_omx_free.clear(); -#ifdef VPE_LIBAV_MPEG2_TRANSCODING - input_bufs_omx_in_libav.clear(); - pix_fmt_omx_all.clear(); - pix_fmt_omx_free.clear(); -#endif - input_bufs_omx_mutex.Unlock(); - -} - - - - -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 - - clock_mutex.Lock(); - 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"); - - } - clock_mutex.Unlock(); - - idleClock(); - clock_mutex.Lock(); - - - if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) { - Log::getInstance()->log("Video", Log::DEBUG, "vid_shed ChangeComponentState"); - - } - - if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) { - Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState"); - - } - - - - // 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); - - } - - - - 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); - - } - - - - if (!CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_output_port) ) { - Log::getInstance()->log("Video", Log::DEBUG, "flush cmd shed rend failed"); - } - - - - - - - DestroyInputBufsOMX(); - - //todo flushing - 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"); - } - - - - - 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"); - } - - - - - 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"); - } - - - - - 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) { - 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); - - } - - 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) { - 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) { - Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error); - - } - - - - - error=OMX_FreeHandle(omx_vid_dec); - error=OMX_FreeHandle(omx_vid_sched); - error=OMX_FreeHandle(omx_vid_rend); - omx_vid_dec=NULL; - clock_mutex.Unlock(); - destroyClock(); - if (error!=OMX_ErrorNone) { - Log::getInstance()->log("Video", Log::DEBUG, "FreeHandle failed %d", error); - } - } else clock_mutex.Unlock(); - Log::getInstance()->log("Video", Log::DEBUG, "leave deallocate codecs OMX"); - - return 1; -} - - -void VideoVPEOGL::destroyClock() -{ - clock_mutex.Lock(); - if (clock_references>0) { - clock_references--; - if (clock_references==0) { - OMX_ERRORTYPE error; - Log::getInstance()->log("Video", Log::DEBUG, "destroy omx clock"); - error=OMX_FreeHandle(omx_clock); - if (error!=OMX_ErrorNone) { - Log::getInstance()->log("Video", Log::DEBUG, "FreeHandle failed %d", error); - } - - } - } - clock_mutex.Unlock(); - -} - -#endif - - -#ifdef VPE_LIBAV_SUPPORT - -enum PixelFormat VideoVPEOGL::get_format_libav(struct AVCodecContext *s, const enum PixelFormat *fmt) -{ - int dec_mode=((VideoVPEOGL*)getInstance())->getlibavDecodingMode(); - enum PixelFormat ret_pix=PIX_FMT_NONE; - if (dec_mode==VPE_NO_XVMC) return PIX_FMT_NONE; - while (*fmt!=PIX_FMT_NONE) { - if (*fmt== PIX_FMT_XVMC_MPEG2_IDCT && dec_mode==VPE_XVMC_IDCT) { - ret_pix=PIX_FMT_XVMC_MPEG2_IDCT; - } else if (*fmt== PIX_FMT_XVMC_MPEG2_MC && dec_mode==VPE_XVMC_MOCOMP) { - ret_pix=PIX_FMT_XVMC_MPEG2_MC; - } - fmt++; - } - return ret_pix; -} - -// we use this function to push the data to ogl out before hand, this is only useful for xvmc -void VideoVPEOGL::draw_horiz_band_libav(struct AVCodecContext *s, const AVFrame *src, int offset[4], int y, int type, int height) -{ - if ((y+height)==src->height) { - /* Log::getInstance()->log("Video", Log::NOTICE, "draw_horiz_band %d %d %d %d %d!",y,type,height,((xvmc_pix_fmt *)src->data[2])->p_surface, - ((xvmc_pix_fmt *)src->data[2])->picture_structure);*/ - if (((xvmc_pix_fmt *)src->data[2])->picture_structure!=3) { - Log::getInstance()->log("Video", Log::ERR, "Non frame pict not supported! Yet! Please send sample to authors!"); exit(0); - } - ((VideoVPEOGL*)Video::getInstance())->add_dec_frame_upload_only(s,src); - } - -} - -int VideoVPEOGL::reget_buffer_libav(struct AVCodecContext *c, AVFrame *pic) -{ - Log::getInstance()->log("Video", Log::ERR, "Buffer reusing! Should not happen!Not Implemented!"); - return -1; -} - -int VideoVPEOGL::get_buffer_libav(struct AVCodecContext *c, AVFrame *pic) -{ - unsigned int want_sizes[4]={0,0,0,0}; - AVPicture pict; - bool normal_pixs=false; - int num_blocks=0; - int num_dct_blocks=0; - - int s_a[4]; - //reget logic from mplayer - if (pic->opaque && pic->data[0] && (!pic->buffer_hints ||pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE )){ - Log::getInstance()->log("Video", Log::ERR, "Buffer reusing! Should not happen!"); - return 0; - } - - - if (c->pix_fmt!=PIX_FMT_XVMC_MPEG2_IDCT &&c->pix_fmt!=PIX_FMT_XVMC_MPEG2_MC) { - normal_pixs=true; - // standard pixel format - // this is written using much inspiration from libav util.c, so portions from there - int width,height; - - width=c->width; - height=c->height; - - avcodec_align_dimensions2(c, &width, &height, s_a); - if ((c->flags & CODEC_FLAG_EMU_EDGE)==0) { - width+=2*16; - height+=2*16; - } - // Now we have to determine alignment size - bool unaligned=true; - while (unaligned) { - av_image_fill_linesizes(pict.linesize, c->pix_fmt, width); //linesizes are derived - width+=width & ~(width-1); //trick from libav, now determine, if the alignment is ok - unaligned=false; - for (int i=0;i<4;i++) { - if ((pict.linesize[i]%s_a[i])!=0) { - unaligned=true; - break; - } - } - } - int tot_size=av_image_fill_pointers(pict.data, c->pix_fmt, height, NULL, pict.linesize); //get sizes - for (int i=0;i<4 ;i++) { - if (i<3 && pict.data[i+1]) { - want_sizes[i]=pict.data[i+1]-pict.data[i]; - want_sizes[i]+=16; - } else { - want_sizes[i]=(tot_size-(pict.data[i]-pict.data[0])); - want_sizes[i]+=16; - break; - } - } - - } else { - //TODO set linesizes! - - num_blocks=((c->width+15)/16)*((c->height+15)/16); - num_dct_blocks=num_blocks*6; //6 blocks per macroblock - - want_sizes[2]=sizeof(xvmc_pix_fmt); - want_sizes[1]=sizeof(short)*num_dct_blocks*8*8; - want_sizes[0]=sizeof(XvMCMacroBlock)*num_blocks; - pict.linesize[0]=pict.linesize[1]=pict.linesize[2]=pict.linesize[3]=0; - - } - - VPE_FrameBuf *frame_buf=((VideoVPEOGL*)Video::getInstance())->getFrameBuf(want_sizes); - frame_buf->ogl_ref=NULL; //do not use old references, crash instead! - frame_buf->ogl_uploaded=false; //not uploaded yet - frame_buf->width=pic->width; - frame_buf->height=pic->height; - frame_buf->stride=pic->linesize[0]; - - //Log::getInstance()->log("Video", Log::NOTICE, "get buffer %x",frame_buf); - if (!frame_buf) { - Log::getInstance()->log("Video", Log::ERR, "Getting buffer libav failed"); - return -1; - } - - - //populate pict - pic->type=FF_BUFFER_TYPE_USER; // we are controlling the buffers - int hchr_shift,vchr_shift; - avcodec_get_chroma_sub_sample(c->pix_fmt,&hchr_shift,&vchr_shift); - const int pixel_size = av_pix_fmt_descriptors[c->pix_fmt].comp[0].step_minus1+1; - for (int i=0;i<4;i++) { - pic->data[i]=(uint8_t*)frame_buf->data[i]; - pic->linesize[i]=pict.linesize[i]; - if (normal_pixs) { - - int edge_width=16; - int edge_height=16; - if (i!=0) { - edge_width>>=hchr_shift; - edge_height>>=vchr_shift; - } - pic->data[i]+=FFALIGN((pic->linesize[i]*16) + (pixel_size*edge_width), s_a[i]); - } - } - - pic->base[0]=(uint8_t*)frame_buf; // our structure - //pic->extended_data=pic->data; - if(c->pkt) pic->pkt_pts=c->pkt->pts; - else pic->pkt_pts=AV_NOPTS_VALUE; - pic->width=c->width; - pic->height=c->height; - pic->format=c->pix_fmt; - pic->sample_aspect_ratio=c->sample_aspect_ratio; - pic->reordered_opaque= c->reordered_opaque; - pic->age=INT_MAX; - if (!normal_pixs) { - xvmc_pix_fmt *pix_xvmc=(xvmc_pix_fmt *)pic->data[2]; - pix_xvmc->xvmc_id=AV_XVMC_ID; - pix_xvmc->data_blocks=(short*)pic->data[1]; - pix_xvmc->mv_blocks=(XvMCMacroBlock*)pic->data[0]; - pix_xvmc->allocated_mv_blocks=num_blocks; - pix_xvmc->allocated_data_blocks=num_dct_blocks; - if (c->pix_fmt==PIX_FMT_XVMC_MPEG2_IDCT) pix_xvmc->idct=1; - else pix_xvmc->idct=0; - pix_xvmc->unsigned_intra=1; // let see what happens - pix_xvmc->p_surface=(XvMCSurface*)frame_buf->pict_num; - pix_xvmc->start_mv_blocks_num=0; - pix_xvmc->filled_mv_blocks_num=0; - pix_xvmc->next_free_data_block_num=0; - //that is all folks - - - } - - return 0; - -} - -void VideoVPEOGL::release_buffer_libav(struct AVCodecContext *c, AVFrame *pic) -{ -// Log::getInstance()->log("Video", Log::NOTICE, "release buffer %x",pic->base[0]); - ((VideoVPEOGL*)Video::getInstance())->releaseFrameBufLibav((VPE_FrameBuf*) pic->base[0]); - pic->base[0]=NULL; - pic->data[0]=pic->data[1]=pic->data[2]=pic->data[3]=NULL; - - -} - -int VideoVPEOGL::AllocateCodecsLibav() -{ - if (libav_running) DeAllocateCodecsLibav(); - libav_hastime=false; - Log::getInstance()->log("Video", Log::NOTICE, "AllocateCodecslibav"); - mpeg2codec_context_libav=avcodec_alloc_context(); - if (mpeg2codec_context_libav==NULL) { - Log::getInstance()->log("Video", Log::DEBUG, "Creating libav codec context failed"); - return 0; - } - if (decoding_mode!=VPE_NO_XVMC) { - mpeg2codec_context_libav->slice_flags=SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD; - if (decoding_mode==VPE_XVMC_MOCOMP) mpeg2codec_context_libav->pix_fmt=PIX_FMT_XVMC_MPEG2_MC; - else mpeg2codec_context_libav->pix_fmt=PIX_FMT_XVMC_MPEG2_IDCT; - mpeg2codec_context_libav->get_format=get_format_libav; - mpeg2codec_context_libav->draw_horiz_band=draw_horiz_band_libav; - - } - mpeg2codec_context_libav->get_buffer=get_buffer_libav; - mpeg2codec_context_libav->reget_buffer=reget_buffer_libav; - mpeg2codec_context_libav->release_buffer=release_buffer_libav; - - - - int avc_ret=avcodec_open(mpeg2codec_context_libav, mpeg2codec_libav); - if (avc_ret<0) { - Log::getInstance()->log("Video", Log::DEBUG, "Opening libav codec failed "); - return 0; - } - memset(&incom_packet_libav,0,sizeof(incom_packet_libav)); - incom_packet_libav_size=200000; - incom_packet_libav.data=(uint8_t*)av_malloc(incom_packet_libav_size+FF_INPUT_BUFFER_PADDING_SIZE); - - dec_frame_libav_mutex.Lock(); - for (int i=0;i<3;i++) { - AVFrame *dec_frame_libav=avcodec_alloc_frame(); // may be we need multiple frames, if we want to use async texture upload - if (!dec_frame_libav) { - Log::getInstance()->log("Video", Log::DEBUG, "Allocating dec_frame failed"); - return 0; - } - dec_frame_libav_all.push_back(dec_frame_libav); - dec_frame_libav_free.push_back(dec_frame_libav); - } - dec_frame_libav_decoding=NULL; - dec_frame_libav_mutex.Unlock(); - - ogl_frame_mutex.Lock(); - //Allocate texture structs, since we do not know the sizes, we do not allocate the textures yet - for (int i=0;i<5;i++) { - VPEOGLFrame *new_frame=(VPEOGLFrame *)malloc(sizeof(VPEOGLFrame)); - new_frame->type=1; //1 = YUV, 2 RGB - new_frame->textures[0]=0; - new_frame->textures[1]=0; - new_frame->textures[2]=0; - new_frame->width=new_frame->height=0; - all_ogl_frames.push_back(new_frame); - free_ogl_frames.push_back(new_frame); - - } - ogl_frame_outside=false; - - ogl_frame_mutex.Unlock(); - - if (decoding_mode==VPE_XVMC_MOCOMP) { - OsdOpenGL* osd=(OsdOpenGL*)osd->getInstance(); - osd->BeginPainting(); // get OpenGl context - moco_shader=new GLMocoShader(); - moco_shader->init(); - osd->EndPainting(); - } - - libav_running=true; - - return 1; - -} - -int VideoVPEOGL::DeAllocateCodecsLibav() -{ - libav_running=false; - Log::getInstance()->log("Video", Log::NOTICE, "DeAllocateCodecslibav"); - dec_frame_libav_mutex.Lock(); - dec_frame_libav_upload_and_view_pending.clear(); - dec_frame_libav_upload_only_pending.clear(); - dec_frame_libav_free.clear(); - dec_frame_libav_mutex.Unlock(); - while (dec_frame_libav_uploading_framebuf) { - Log::getInstance()->log("Video", Log::NOTICE, "Wait for uploading to finish"); - MILLISLEEP(20); - } - dec_frame_libav_mutex.Lock(); - for (int i=0; i< dec_frame_libav_all.size();i++) { - av_free(dec_frame_libav_all[i]); - } - - dec_frame_libav_all.clear(); - - av_free(incom_packet_libav.data); - incom_packet_libav.data=NULL; - incom_packet_libav_size=0; - - dec_frame_libav_mutex.Unlock(); - dec_frame_libav_decoding=NULL; - while (ogl_frame_outside) { - Log::getInstance()->log("Video", Log::NOTICE, "Wait for ogl frame from outside"); - MILLISLEEP(20); - } - - ((OsdOpenGL*)Osd::getInstance())->BeginPainting(); // get osd's context - ogl_frame_mutex.Lock(); - for (int i=0; i< dec_frame_libav_all.size();i++) { - VPEOGLFrame * del_frame=all_ogl_frames[i]; - if (del_frame->textures[0]==0) { - glDeleteTextures(1,&del_frame->textures[0]); - del_frame->textures[0]=0; - } - if (del_frame->textures[1]==0) { - glDeleteTextures(1,&del_frame->textures[1]); - del_frame->textures[1]=0; - } - if (del_frame->textures[2]==0) { - glDeleteTextures(1,&del_frame->textures[2]); - del_frame->textures[2]=0; - } - - free(all_ogl_frames[i]); - } - all_ogl_frames.clear(); - free_ogl_frames.clear(); - ready_ogl_frames.clear(); - recycle_ref_ogl_frames.clear(); - ogl_forward_ref_frame_num=0; - ogl_backward_ref_frame_num=0; - ogl_forward_ref_frame=NULL; - ogl_backward_ref_frame=NULL; - - ogl_frame_mutex.Unlock(); - ((OsdOpenGL*)Osd::getInstance())->EndPainting(); - - - if (mpeg2codec_context_libav) { - avcodec_close(mpeg2codec_context_libav); - av_free(mpeg2codec_context_libav); - mpeg2codec_context_libav=NULL; - - } - - - - vpe_framebuf_mutex.Lock(); - - for (int i=0;idata[x]) { - av_free(current->data[x]); - } - } - free(current); - } - all_frame_bufs.clear(); - free_frame_bufs.clear(); - locked_libav_frame_buf.clear(); - locked_uploading_frame_buf.clear(); - - vpe_framebuf_mutex.Unlock(); - - - - if (moco_shader) { - OsdOpenGL* osd=(OsdOpenGL*)osd->getInstance(); - osd->BeginPainting(); // get OpenGl context - moco_shader->deinit(); - delete moco_shader; - moco_shader=NULL; - osd->EndPainting(); - } - - - - - - return 1; -} - - -VPE_FrameBuf *VideoVPEOGL::getFrameBuf(unsigned int *size) -{ //for libav - VPE_FrameBuf* current=NULL; - vpe_framebuf_mutex.Lock(); - if (free_frame_bufs.size()>0) { - current=free_frame_bufs.front(); - free_frame_bufs.pop_front(); - } else if (all_frame_bufs.size()<6) { - current=(VPE_FrameBuf*)malloc(sizeof(VPE_FrameBuf)); - memset(current,0,sizeof(VPE_FrameBuf)); - } else { - Log::getInstance()->log("Video", Log::NOTICE, "Framebuffer underrun!"); - vpe_framebuf_mutex.Unlock(); - return NULL; // We do not have a frame buffer - } - locked_libav_frame_buf.push_back(current); - vpe_framebuf_mutex.Unlock(); - //check if we need reallocation - for (int x=0;x<4;x++) { - if (current->size[x]!=size[x]) { - current->data[x]=av_realloc(current->data[x],size[x]); - current->size[x]=size[x]; - } - } - framebuf_framenum++; - current->pict_num=framebuf_framenum; //This is used for tracking reference frames through the conversion pipeline - return current; - -} - -void VideoVPEOGL::lockFrameBufUpload(VPE_FrameBuf* buf) -{ - // first find frame_buf memory - - //Log::getInstance()->log("Video", Log::NOTICE, "lock buffer upload %x",buf); - VPE_FrameBuf* current=buf; - vpe_framebuf_mutex.Lock(); - if (current) locked_uploading_frame_buf.push_back(current); //locked - vpe_framebuf_mutex.Unlock(); - -} - - -void VideoVPEOGL::releaseFrameBufLibav(VPE_FrameBuf* buf) -{ - // first find frame_buf memory - //Log::getInstance()->log("Video", Log::NOTICE, "release buffer libav %x",buf); - VPE_FrameBuf* current=buf; - vpe_framebuf_mutex.Lock(); - if (current) { - locked_libav_frame_buf.remove(current); //unlocked - list::iterator itty=locked_uploading_frame_buf.begin(); - bool inlist=false; - while (itty!=locked_uploading_frame_buf.end()) { - if (*itty==current) { - inlist=true; - break; - } - itty++; - } - if (!inlist) { - free_frame_bufs.push_back(current); - } - } - vpe_framebuf_mutex.Unlock(); -} - -void VideoVPEOGL::releaseFrameBufUpload(VPE_FrameBuf* buf) -{ - // first find frame_buf memory - VPE_FrameBuf* current=buf; - //Log::getInstance()->log("Video", Log::NOTICE, "release buffer upload %x",buf); - vpe_framebuf_mutex.Lock(); - if (current) { - locked_uploading_frame_buf.remove(current); //unlocked - list::iterator itty=locked_libav_frame_buf.begin(); - bool inlist=false; - while (itty!=locked_libav_frame_buf.end()) { - if (*itty==current) { - inlist=true; - break; - } - itty++; - } - if (!inlist) { - free_frame_bufs.push_back(current); - } - } - vpe_framebuf_mutex.Unlock(); -} - -void VideoVPEOGL::add_dec_frame_upload_only(struct AVCodecContext *s,const AVFrame* data) -{ - dec_frame_libav_mutex.Lock(); - libavwidth=s->width; - libavheight=s->height; - libavpixfmt=s->pix_fmt; - //Log::getInstance()->log("Video", Log::DEBUG, "add_dec Frame info %d %d %d %d %x",libavwidth,libavheight,libavpixfmt,((VPE_FrameBuf*)data->base[0])->pict_num,data->base[0]); - - dec_frame_libav_upload_only_pending.push_back((VPE_FrameBuf*)data->base[0]); // we are only uploading - dec_frame_libav_mutex.Unlock(); - threadSignal(); -} - - - - - -#endif - -int VideoVPEOGL::stop() -{ - if (!initted) return 0; - iframemode=false; - -#ifdef VPE_OMX_SUPPORT - //Check if libav mode - if (decoding_backend==VPE_DECODER_OMX) DeAllocateCodecsOMX(); - decoding_backend=0; - -#endif - - - -// if (ioctl(fdVideo, AV_SET_VID_STOP, 0) != 0) return 0; - return 1; -} - -int VideoVPEOGL::reset() -{ - if (!initted) return 0; - - iframemode=false; - DeAllocateCodecsOMX(); -// if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; - return 1; -} - -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(); - - } - return 1; -} - -int VideoVPEOGL::unPause() // FIXME get rid - same as play!! Not here! -{ - if (!initted) 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; -} - -int VideoVPEOGL::fastForward() -{ - if (!initted) return 0; - -// if (ioctl(fdVideo, AV_SET_VID_libavWD, 1) != 0) return 0; - return 1; -} - -int VideoVPEOGL::unFastForward() -{ - if (!initted) return 0; - -// if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; // don't need this. - - //// if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0; - return 1; -} - -int VideoVPEOGL::attachFrameBuffer() -{ - if (!initted) return 0; - -// if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0; - return 1; -} - -int VideoVPEOGL::blank(void) -{ -// if (ioctl(fdVideo, AV_SET_VID_FB, 1) != 0) return 0; -// if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0; - return 1; -} - -ULLONG VideoVPEOGL::getCurrentTimestamp() -{ - if (iframemode) 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() -{ - return 0; - -// ULLONG stc = 0; -// return ioctl(fdVideo, AV_SET_VID_STC, &stc); -/* - // reset(); - return 1; -*/ -} - -int VideoVPEOGL::test2() -{ - return 0; -} -#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 %lld",GetCurrentSystemTime()); -} - -void VideoVPEOGL::AdjustAudioPTS(long long pts) -{ - long long newplaybacktimeoffset=pts-GetCurrentSystemTime(); -/* if ((newplaybacktimeoffset-1000000LL)>playbacktimeoffset - || (newplaybacktimeoffset+1000000LL)log("Video", Log::DEBUG, "Adjust Playbackoffsettime o: %lld n: %lld", - playbacktimeoffset,newplaybacktimeoffset);*/ - playbacktimeoffset=newplaybacktimeoffset; - - //} -} - - -void VideoVPEOGL::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos) -{ - mediapacket = mplist.front(); -} - -UINT VideoVPEOGL::DeliverMediaSample(UCHAR* buffer, UINT *samplepos) -{ - DeliverMediaPacket(mediapacket, buffer, samplepos); - if (*samplepos == mediapacket.length) { - *samplepos = 0; - return 1; - } - else return 0; -} - -UINT VideoVPEOGL::DeliverMediaPacket(MediaPacket packet, - const UCHAR* buffer, - UINT *samplepos) -{ - if (packet.type == MPTYPE_VIDEO_H264) - { - h264=true; - } - else - { - h264=false; - } - switch (decoding_backend) { - default: case 0: return 0; // no backend runnigng -#ifdef VPE_OMX_SUPPORT - case VPE_DECODER_OMX: return DeliverMediaPacketOMX(packet,buffer,samplepos); -#ifdef VPE_LIBAV_MPEG2_TRANSCODING - case VPE_DECODER_OMX_libav_TRANSCODE: return DeliverMediaPacketOMXTranscode(packet,buffer,samplepos); -#endif -#endif -#ifdef VPE_LIBAV_SUPPORT - case VPE_DECODER_libav: return DeliverMediaPacketlibav(packet,buffer,samplepos); -#endif - } -} - -#ifdef VPE_OMX_SUPPORT -UINT VideoVPEOGL::DeliverMediaPacketOMX(MediaPacket packet, - const UCHAR* buffer, - UINT *samplepos) -{ - - - //Later add fail back code for libav -/* if (!videoon) { - *samplepos+=packet.length; - return packet.length; - }*/ - - - if (!omx_running) return 0; // if we are not runnig do not do this - if (paused) return 0; //Block if we pause - - long long current_media_time=GetCurrentSystemTime()+playbacktimeoffset; - if (packet.synched && - (packet.presentation_time<0 /*|| // preroll skip frames - (packet.presentation_time+5000000LL)<(current_media_time)*/)) { // we are late skip - Log::getInstance()->log("Video", Log::DEBUG, "DeliverMediaPacketOMX Preroll or too late %lld %lld; %lld", packet.presentation_time,current_media_time,playbacktimeoffset); - *samplepos=packet.length; - return packet.length; - } - - OMX_ERRORTYPE error; - - /*First Check, if we have an video sample*/ - if (iframemode) { - //samplepos=0; - MILLISLEEP(10); - return 0; //Not in iframe mode! - } - - UINT headerstrip=0; - if (packet.disconti) { - firstsynched=false; - if (cur_input_buf_omx) { - 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; - } - } - - /*Inspect PES-Header */ - -// OMX_STATETYPE temp_state; -// OMX_GetState(omx_vid_dec,&temp_state); - - if (*samplepos==0) {//stripheader - headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/; - if (h264) Log::getInstance()->log("Video", Log::DEBUG, "PES info %x %x %x %x", - buffer[packet.pos_buffer+0],buffer[packet.pos_buffer+1],buffer[packet.pos_buffer+2],buffer[packet.pos_buffer+3]); - *samplepos+=headerstrip; - 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); - } - cur_input_buf_omx=NULL;//write out old data - FrameWaitforDisplay(lastreftimeOMX); - - - } - firstsynched=true; - } else { - if (!firstsynched) {// - *samplepos=packet.length;//if we have not processed at least one - return packet.length;//synched packet ignore it! - } - } - } - - 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(); - } - - - - - if (cur_input_buf_omx->nFilledLen==0) {//will only be changed on first packet - 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 { - //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; - - 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 - - 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+cur_input_buf_omx->nFilledLen, - buffer+packet.pos_buffer+*samplepos,haveToCopy); - cur_input_buf_omx->nFilledLen+=haveToCopy; - - - - *samplepos+=haveToCopy; - - return *samplepos; - -} - -#endif - -#ifdef VPE_LIBAV_MPEG2_TRANSCODING - - - -int VideoVPEOGL::DecodePacketOMXTranscode() -{ - unsigned int haveToCopy=incom_packet_libav.size; - if (incom_packet_libav.size==0) return 1; // we are already empty - - - while (haveToCopy>0) { - int dec_bytes=0; - int frame_ready=0; - - // Log::getInstance()->log("Video", Log::DEBUG, "Push data to decoder"); - -#ifdef BENCHMARK_FPS - int cur_time=getTimeMS(); -#endif - dec_bytes=avcodec_decode_video2(transcodecodec_context_libav, &transcode_frame_libav, - &frame_ready, &incom_packet_libav); -#ifdef BENCHMARK_FPS - time_in_decoder+=getTimeMS()-cur_time; - if (frame_ready) num_frames++; - if ((num_frames%100)==0) { - float fps=1000./(float)(time_in_decoder); - fps*=((float)num_frames); - Log::getInstance()->log("Video", Log::NOTICE, "Current Pure Decoding FPS %g", fps); - } -#endif - if (dec_bytes<0) { - Log::getInstance()->log("Video", Log::DEBUG, "Decoding frame failed %x", dec_bytes); - return 0; - } - haveToCopy-=dec_bytes; - if (frame_ready) { - struct transcode_pix_fmt *transcode=(struct transcode_pix_fmt *)transcode_frame_libav.data[0]; - //if (!benchmark) fwrite(transcode->packet.data,transcode->packet.size,1,output_file); - - - //add omx magic, this should be an omx packet - OMX_BUFFERHEADERTYPE* omx_packet=(OMX_BUFFERHEADERTYPE*)transcode_frame_libav.base[0]; - omx_packet->nFilledLen=transcode->packet.size; - - input_bufs_omx_mutex.Lock(); - input_bufs_omx_in_libav.remove(omx_packet); // say that it is passed down to the decoder - input_bufs_omx_mutex.Unlock(); - - OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,omx_packet); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error); - } - - - - } - - } - incom_packet_libav.size=0; - return 1; - -} - - -UINT VideoVPEOGL::DeliverMediaPacketOMXTranscode(MediaPacket packet, - const UCHAR* buffer, - UINT *samplepos) -{ - //Later add fail back code for libav - /*if (!videoon) { - *samplepos+=packet.length; - return packet.length; - }*/ - - if (!omx_running) return 0; // if we are not runnig do not do this - - - if (iframemode) { - //samplepos=0; - MILLISLEEP(10); - return 0; //Not in iframe mode! - } - - UINT headerstrip=0; - if (packet.disconti) { - firstsynched=false; - if (!DecodePacketOMXTranscode()) return 0; - } - - /*Inspect PES-Header */ - if (*samplepos==0) {//stripheader - headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/; - *samplepos+=headerstrip; - if ( packet.synched ) { - - if (!DecodePacketOMXTranscode()) return 0; // WriteOut old Data - - - incom_packet_libav.pts=packet.pts/3600; - incom_packet_libav.dts=packet.dts/3600; - // reftime1=packet.presentation_time; - // reftime2=reftime1+1; - firstsynched=true; - } else { - incom_packet_libav.pts=0; - incom_packet_libav.dts=0; - if (!firstsynched) {// - *samplepos=packet.length;//if we have not processed at least one - return packet.length;//synched packet ignore it! - } - } - } - - - - - - - /*if (cur_input_buf_omx->nFilledLen==0) {//will only be changed on first packet - /*if (packet.disconti) { - ms->SetDiscontinuity(TRUE); - } else { - ms->SetDiscontinuity(FALSE); - }* - //if (packet.synched) { - - //lastreftimePTS=packet.pts; - if (omx_first_frame) { // TODO time - cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_STARTTIME; - omx_first_frame=false; - } else - - //} - //else - //{ - cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN; - - - // ms->SetSyncPoint(TRUE); - //} - - }*/ - unsigned int haveToCopy=packet.length-*samplepos; - - if ((incom_packet_libav_size-incom_packet_libav.size)< haveToCopy) { - // if the buffer is to small reallocate - incom_packet_libav_size+=haveToCopy; - incom_packet_libav.data=(uint8_t*)av_realloc(incom_packet_libav.data,incom_packet_libav_size+FF_INPUT_BUFFER_PADDING_SIZE); - Log::getInstance()->log("Video", Log::DEBUG, "Reallocate avpacket buffer to %d", incom_packet_libav_size); - } - memcpy(incom_packet_libav.data+incom_packet_libav.size,buffer+packet.pos_buffer+*samplepos,haveToCopy); - incom_packet_libav.size+=haveToCopy; - - *samplepos+=haveToCopy; - - - return *samplepos; - - -} - -#endif - - -#ifdef VPE_LIBAV_SUPPORT -int VideoVPEOGL::DecodePacketlibav() -{ - unsigned int haveToCopy=incom_packet_libav.size; - if (incom_packet_libav.size==0) return 1; // we are already empty - while (haveToCopy>0) { - int dec_bytes=0; - int frame_ready=0; - - // Log::getInstance()->log("Video", Log::DEBUG, "Push data to decoder"); - -#ifdef BENCHMARK_FPS - int cur_time=getTimeMS(); -#endif - dec_bytes=avcodec_decode_video2(mpeg2codec_context_libav, dec_frame_libav_decoding, - &frame_ready, &incom_packet_libav); -#ifdef BENCHMARK_FPS - time_in_decoder+=getTimeMS()-cur_time; - if (frame_ready) num_frames++; - if ((num_frames%100)==0) { - float fps=1000./(float)(time_in_decoder); - fps*=((float)num_frames); - Log::getInstance()->log("Video", Log::NOTICE, "Current Pure Decoding FPS %g", fps); - } -#endif - if (dec_bytes<0) { - Log::getInstance()->log("Video", Log::DEBUG, "Decoding frame failed %x", dec_bytes); - return 0; - } - haveToCopy-=dec_bytes; - if (frame_ready) { - // Log::getInstance()->log("Video", Log::DEBUG, "We have a frame push it to osd"); - - lockFrameBufUpload((VPE_FrameBuf*)dec_frame_libav_decoding->base[0]); //lock for upload, so that ffmpeg does not reuse - dec_frame_libav_mutex.Lock(); - libavwidth=mpeg2codec_context_libav->width; - libavheight=mpeg2codec_context_libav->height; - libavpixfmt=mpeg2codec_context_libav->pix_fmt; - // Log::getInstance()->log("Video", Log::DEBUG, "Frame info %d %d %d",libavwidth,libavheight,libavpixfmt); - // Log::getInstance()->log("Video", Log::DEBUG, "Frame info %d %d %d %d %x",libavwidth,libavheight,libavpixfmt, - // ((VPE_FrameBuf*)dec_frame_libav_decoding->base[0])->pict_num,dec_frame_libav_decoding->base[0]); - - - dec_frame_libav_upload_and_view_pending.push_back(dec_frame_libav_decoding); - dec_frame_libav_decoding=NULL; - if (dec_frame_libav_free.size()>0) { - dec_frame_libav_decoding=dec_frame_libav_free.front(); - dec_frame_libav_free.pop_front(); - dec_frame_libav_mutex.Unlock(); - threadSignal(); - libav_hastime=false; - } else { - libav_hastime=false; - dec_frame_libav_mutex.Unlock(); - Log::getInstance()->log("Video", Log::DEBUG, "We have no free buffers 2 FPS"); - threadSignal(); - // No free buffers - return 0; - } - - - } - - } - incom_packet_libav.size=0; - return 1; - -} - - -UINT VideoVPEOGL::DeliverMediaPacketlibav(MediaPacket packet, - const UCHAR* buffer, - UINT *samplepos) -{ - //Later add fail back code for libav - /*if (!videoon) { - *samplepos+=packet.length; - return packet.length; - }*/ - - if (!libav_running) return 0; // if we are not runnig do not do this - - - if (iframemode) { - //samplepos=0; - MILLISLEEP(10); - return 0; //Not in iframe mode! - } - - UINT headerstrip=0; - if (packet.disconti) { - firstsynched=false; - if (!DecodePacketlibav()) return 0; - } - - /*Inspect PES-Header */ - if (!dec_frame_libav_decoding) { - dec_frame_libav_mutex.Lock(); - if (dec_frame_libav_free.size()>0) { - dec_frame_libav_decoding=dec_frame_libav_free.front(); - dec_frame_libav_free.pop_front(); - dec_frame_libav_mutex.Unlock(); - } else { - Log::getInstance()->log("Video", Log::DEBUG, "We have no free buffers FPS"); - dec_frame_libav_mutex.Unlock(); - // No free buffers - return 0; - } - } - - - - if (*samplepos==0) {//stripheader - headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/; - *samplepos+=headerstrip; - if ( packet.synched ) { - - if (!DecodePacketlibav()) return 0; // WriteOut old Data - - libav_time=packet.presentation_time; - libav_hastime=true; - // reftime1=packet.presentation_time; - // reftime2=reftime1+1; - firstsynched=true; - } else { - if (!firstsynched) {// - *samplepos=packet.length;//if we have not processed at least one - return packet.length;//synched packet ignore it! - } - } - } - - - - - - - /*if (cur_input_buf_omx->nFilledLen==0) {//will only be changed on first packet - /*if (packet.disconti) { - ms->SetDiscontinuity(TRUE); - } else { - ms->SetDiscontinuity(FALSE); - }* - //if (packet.synched) { - - //lastreftimePTS=packet.pts; - if (omx_first_frame) { // TODO time - cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_STARTTIME; - omx_first_frame=false; - } else - - //} - //else - //{ - cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN; - - - // ms->SetSyncPoint(TRUE); - //} - - }*/ - unsigned int haveToCopy=packet.length-*samplepos; - - if ((incom_packet_libav_size-incom_packet_libav.size)< haveToCopy) { - // if the buffer is to small reallocate - incom_packet_libav_size+=haveToCopy; - incom_packet_libav.data=(uint8_t*)av_realloc(incom_packet_libav.data,incom_packet_libav_size+FF_INPUT_BUFFER_PADDING_SIZE); - Log::getInstance()->log("Video", Log::DEBUG, "Reallocate avpacket buffer to %d", incom_packet_libav_size); - } - memcpy(incom_packet_libav.data+incom_packet_libav.size,buffer+packet.pos_buffer+*samplepos,haveToCopy); - incom_packet_libav.size+=haveToCopy; - - *samplepos+=haveToCopy; - - - return *samplepos; - - -} - -#endif - - -bool VideoVPEOGL::displayIFrame(const UCHAR* buffer, UINT length) { - if (!omx_running) return false; - if (!iframemode) - EnterIframePlayback(); - - int haveToCopy = length; - - 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 false; // 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(); - } - - int read_pos = 0; - unsigned int pattern, packet_length; - unsigned int headerstrip = 0; - bool first = true; - if (length < 4){ - return false; - } - //Now we strip the pes header - pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]); - while (read_pos + 7 <= length) { - pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos + 3]; - if (pattern < 0x000001E0 || pattern > 0x000001EF) { - read_pos++; - continue; - } else { - headerstrip = buffer[read_pos + 8] + 9/*is this right*/; - packet_length = ((buffer[read_pos + 4] << 8) - | (buffer[read_pos + 5])) + 6; - if (read_pos + packet_length > length) - read_pos = length; - else { - if ((headerstrip < packet_length) - && (cur_input_buf_omx->nFilledLen + packet_length - - headerstrip) > cur_input_buf_omx->nAllocLen) { - if (first) { - cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_STARTTIME; - - } else { - cur_input_buf_omx->nFlags - |= OMX_BUFFERFLAG_TIME_UNKNOWN; - - } - cur_input_buf_omx->nTimeStamp = 0; - 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; - - if (!cur_input_buf_omx) { - int count = 0; - while (count < 100 && omx_running && iframemode) { - count++; - - input_bufs_omx_mutex.Lock(); - if (input_bufs_omx_free.size() == 0) { - input_bufs_omx_mutex.Unlock(); - Log::getInstance()->log("Video", Log::DEBUG, - "Ifrane no free sample"); - MILLISLEEP(5); - if (!omx_running) return false; - continue; - } - 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(); - break; - } - if (!cur_input_buf_omx) - return false; - } - - } - if (packet_length > headerstrip) { - memcpy( - cur_input_buf_omx->pBuffer - + cur_input_buf_omx->nFilledLen, - buffer + read_pos + headerstrip, - packet_length - headerstrip); - cur_input_buf_omx->nFilledLen += packet_length - - headerstrip; - } - read_pos += packet_length; - - pattern = (buffer[read_pos] << 16) - | (buffer[read_pos + 1] << 8) | (buffer[read_pos + 2]); - } - } - } - - if (first) { - cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_STARTTIME; - - } else { - cur_input_buf_omx->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; - - } - cur_input_buf_omx->nTimeStamp = 0; - 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; - - - MILLISLEEP(40); //Block a bit - return true; -} - -int VideoVPEOGL::EnterIframePlayback() -{ - clock_mutex.Lock(); - if (cur_input_buf_omx) { - 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; - } - clock_mutex.Unlock(); - iframemode=true; - - return 1; -} - -- 2.39.2