From 957f4a08789aecf61b628f3862fa6aa3029e9f12 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sun, 27 Jul 2014 20:15:18 +0200 Subject: [PATCH] Add files missing in last commit, is still not working --- imageomx.cc | 859 ++++++++++++++++++++++++++++++++++++++++++++++++++++ imageomx.h | 104 +++++++ 2 files changed, 963 insertions(+) create mode 100644 imageomx.cc create mode 100644 imageomx.h diff --git a/imageomx.cc b/imageomx.cc new file mode 100644 index 0000000..d3c57a0 --- /dev/null +++ b/imageomx.cc @@ -0,0 +1,859 @@ +/* + Copyright 2004-2005 Chris Tallon, 2009,2014 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 "imageomx.h" +#include "videoomx.h" +#include "log.h" +#include "vdr.h" +#include "woptionpane.h" + +#include "osdopenvg.h" +#include + +ImageOMX::ImageOMX(OsdVector::PictureReader * treader):OsdVector::PictureDecoder(treader) +{ + initted = 0; + + omx_running=false; + pictInfValid=false; +} + +ImageOMX::~ImageOMX() +{ + +} + +void ImageOMX::init() +{ + AllocateCodecsOMX(); +} + +void ImageOMX::shutdown() +{ + Log::getInstance()->log("ImageOMX", Log::DEBUG, "shutdown"); + DeAllocateCodecsOMX(); +} + + + + + +OMX_ERRORTYPE ImageOMX::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer){ + + //Log::getInstance()->log("Image", Log::NOTICE, "EmptyBufferDone"); + ImageOMX *image=(ImageOMX *)buffer->pAppPrivate; + image->ReturnEmptyOMXBuffer(buffer); + return OMX_ErrorNone; + +} + +void ImageOMX::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){ + input_bufs_omx_mutex.Lock(); + if (buffer->pBuffer) { + free(buffer->pBuffer); + buffer->pBuffer = NULL; + } + buffer->nAllocLen= 0; + //Log::getInstance()->log("Image", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size()); + input_bufs_omx_free.push_back(buffer); + //Log::getInstance()->log("Image", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size()); + input_bufs_omx_mutex.Unlock(); +} + + OMX_ERRORTYPE ImageOMX::FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer) { + Log::getInstance()->log("ImageOmx", Log::NOTICE, "FillBufferDone"); + ImageOMX *image=(ImageOMX *)buffer->pAppPrivate; + image->ReturnFillOMXBuffer(buffer); + return OMX_ErrorNone; +} + + void ImageOMX::ReturnFillOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){ + //input_bufs_omx_mutex.Lock(); + omx_egl_filled = true; + //output_bufs_omx_full.push_back(buffer); + //input_bufs_omx_mutex.Unlock(); + } + + +/* + +int ImageOMX::play() { + if (!initted) + return 0; + lastAType=MPTYPE_MPEG_Image; + Log::getInstance()->log("Image", Log::DEBUG, "enter play"); + + ((VideoOMX*)Video::getInstance())->interlaceSwitch4Demux(); // switch resolution if necessary + + if (!AllocateCodecsOMX()) { + return 0; + } + return 1; +}*/ + + + + + +int ImageOMX::AllocateCodecsOMX() +{ + OMX_ERRORTYPE error; + static OMX_CALLBACKTYPE callbacks= {&VideoOMX::EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX}; + + Log::getInstance()->log("Image", Log::NOTICE, "Allocate Codecs OMX"); + //Clock, move later to Image + VideoOMX *video=(VideoOMX*)Video::getInstance(); + + 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; + + + video->LockClock(); + + + error = OMX_GetHandle(&omx_imag_decode, VPE_OMX_IMAGE_DECODER, NULL, &callbacks); + if (error != OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, + "Init OMX Image decoder failed %x", error); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + + + + error = OMX_GetParameter(omx_imag_decode, OMX_IndexParamImageInit, &p_param); + if (error != OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, + "Init OMX Image rend OMX_GetParameter failed %x", error); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + omx_image_input_port = p_param.nStartPortNumber; + omx_image_output_port = p_param.nStartPortNumber+1; + + error=OMX_GetHandle(&omx_egl_render,VPE_OMX_EGL_REND,NULL,&callbacks); + + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", Log::DEBUG, "Init OMX EGL renderer failed %x", error); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + + error=OMX_GetParameter(omx_egl_render,OMX_IndexParamVideoInit,&p_param); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", Log::DEBUG, "Init OMX EGL renderer OMX_GetParameter failed %x", error); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + omx_egl_input_port=p_param.nStartPortNumber; + omx_egl_output_port=p_param.nStartPortNumber+1; + + if (!video->DisablePort(omx_imag_decode,omx_image_input_port) || !video->DisablePort(omx_imag_decode,omx_image_output_port)) { + Log::getInstance()->log("Image", Log::DEBUG, "Disable Ports OMX Image decoder failed"); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + + + if (!video->DisablePort(omx_egl_render,omx_egl_input_port) || !video->DisablePort(omx_egl_render,omx_egl_output_port)) { + Log::getInstance()->log("Image", Log::DEBUG, "Disable Ports OMX Image decoder failed"); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + + if (!video->ChangeComponentState(omx_imag_decode,OMX_StateIdle)) { + Log::getInstance()->log("Image", Log::DEBUG, "image decode idle ChangeComponentState"); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + + if (!video->ChangeComponentState(omx_egl_render,OMX_StateIdle)) { + Log::getInstance()->log("Image", Log::DEBUG, "egl render idle ChangeComponentState"); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + + + + //Setuo chain + + + + + error=OMX_SetupTunnel(omx_imag_decode,omx_image_output_port,omx_egl_render,omx_egl_input_port); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", Log::DEBUG, "OMX_Setup tunnel decode to egl rend failed %x "); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + + if (!video->EnablePort(omx_imag_decode,omx_image_output_port,false) || !video->EnablePort(omx_egl_render,omx_egl_input_port,false) + ) { + Log::getInstance()->log("Image", Log::DEBUG, "Enable Ports OMXdecoder rend failed"); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + + + OMX_IMAGE_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_image_input_port; + + ft_type.eCompressionFormat=OMX_IMAGE_CodingJPEG; + + error=OMX_SetParameter(omx_imag_decode,OMX_IndexParamImagePortFormat,&ft_type); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", Log::DEBUG, "Init OMX_IndexParamVImagePortFormat failed %x", error); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + + + if ( !video->CommandFinished(omx_egl_render,OMX_CommandPortEnable,omx_egl_input_port)) { + video->UnlockClock(); + Log::getInstance()->log("Image", Log::DEBUG, "commandfinishes end eip"); + DeAllocateCodecsOMX(); + return 0; + } + + + if ( !video->CommandFinished(omx_imag_decode,OMX_CommandPortEnable,omx_image_output_port)) { + video->UnlockClock(); + Log::getInstance()->log("Image", Log::DEBUG, "commandfinishes end iop"); + DeAllocateCodecsOMX(); + return 0; + } + + + + + + + if (!PrepareInputBufsOMX(true)) { + video->UnlockClock(); + Log::getInstance()->log("Image", Log::DEBUG, "prepare input bufs failed"); + DeAllocateCodecsOMX(); + return 0; + } + + + +/* error=OMX_SetupTunnel(omx_aud_dec,omx_codec_output_port,omx_aud_rend,omx_rend_input_port); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", Log::DEBUG, "OMX_Setup tunnel dec to render failed %x", error); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + }*/ + + + +/* if (!video->EnablePort(omx_aud_dec,omx_codec_output_port,false) || !video->EnablePort(omx_aud_rend,omx_rend_input_port,false) + ) { + Log::getInstance()->log("Image", Log::DEBUG, "Enable Ports OMX codec rend failed"); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + }*/ + +/* if ( !video->CommandFinished(omx_aud_dec,OMX_CommandPortEnable,omx_codec_output_port) + || !video->CommandFinished(omx_aud_rend,OMX_CommandPortEnable,omx_rend_input_port)) { + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + }*/ + + if (!video->ChangeComponentState(omx_imag_decode,OMX_StateExecuting)) { + Log::getInstance()->log("Image", Log::DEBUG, "omx_image_decode ChangeComponentState Execute"); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + + + if (!video->ChangeComponentState(omx_egl_render,OMX_StateExecuting)) { + Log::getInstance()->log("Image", Log::DEBUG, "omx_egl_rendd ChangeComponentState Execute"); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + + if (!video->EnablePort(omx_imag_decode,omx_image_input_port,false) + ) { + Log::getInstance()->log("Image", Log::DEBUG, "Enable Ports OMXdecoder inputfailed"); + video->UnlockClock(); + DeAllocateCodecsOMX(); + return 0; + } + + + + + video->UnlockClock(); + omx_running=true; + + + + Log::getInstance()->log("Image", Log::NOTICE, "Allocate Codecs OMX finished"); + + return 1; +} + + +bool ImageOMX::decodePicture(LoadIndex index, unsigned char * buffer, unsigned int length) +{ + if (pictInfValid) return false; // does support only one image at a Time; + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture 1"); + EGLPictureCreator * pictcreat =dynamic_cast(Osd::getInstance()); + if (buffer[0]!= 0xff || buffer[1] !=0xd8) return false; // Jpeg magic numbers + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture 2"); + VideoOMX *video=(VideoOMX*)Video::getInstance(); + + + + if (!pictcreat) return false; + + // Use Buffer + OMX_BUFFERHEADERTYPE * bufhead; + + input_bufs_omx_mutex.Lock(); + int count =0; + while (input_bufs_omx_free.size()==0) { + input_bufs_omx_mutex.Unlock(); + //Log::getInstance()->log("Image", Log::DEBUG, "DMP mark 6"); + //Log::getInstance()->log("Image", Log::DEBUG, "Deliver MediaPacket no free sample"); + //return 0; // we do not have a free media sample + + count++; + if (count>100) return false; + MILLISLEEP(10); + + input_bufs_omx_mutex.Lock(); + + } + bufhead=input_bufs_omx_free.front(); + bufhead->nFilledLen=length; + bufhead->nAllocLen= length; + bufhead->nOffset=0; + bufhead->nTimeStamp=VideoOMX::intToOMXTicks(0); + bufhead->pBuffer=buffer; + bufhead->pAppPrivate=this; + input_bufs_omx_free.pop_front(); + input_bufs_omx_mutex.Unlock(); + + + bufhead->nFilledLen=bufhead->nAllocLen; + video->ProtOMXEmptyThisBuffer(omx_imag_decode, bufhead); + + int oldcancelstate; + int oldcanceltype; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldcancelstate); + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldcanceltype); + + video->LockClock(); + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture 3"); + + video->WaitForEvent(omx_imag_decode,OMX_EventPortSettingsChanged); + + 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_image_output_port; + + error=OMX_GetParameter(omx_imag_decode,OMX_IndexParamPortDefinition, &port_def_type); + if (error != OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, + "OMX_IndexParamPortDefinition fix failed %x", error); + video->UnlockClock(); + pthread_setcancelstate(oldcancelstate, NULL); + pthread_setcanceltype(oldcanceltype, NULL); + return false; + } + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture 4"); + + + + + + + + video->DisablePort(omx_egl_render,omx_egl_output_port,true); + video->DisablePort(omx_egl_render,omx_egl_input_port,false); + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture 6"); + video->DisablePort(omx_imag_decode,omx_image_output_port,false); + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture 5"); + + + if ( !video->CommandFinished(omx_egl_render,OMX_CommandPortDisable,omx_egl_input_port)) { + video->UnlockClock(); + Log::getInstance()->log("Image", Log::DEBUG, "commandfinishes end eip"); + DeAllocateCodecsOMX(); + return 0; + } + + + if ( !video->CommandFinished(omx_imag_decode,OMX_CommandPortDisable,omx_image_output_port)) { + video->UnlockClock(); + Log::getInstance()->log("Image", Log::DEBUG, "commandfinishes end iop"); + DeAllocateCodecsOMX(); + return 0; + } + + port_def_type.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; + port_def_type.format.image.nSliceHeight = 16; + port_def_type.format.image.nStride = 0; + error = OMX_SetParameter(omx_imag_decode, OMX_IndexParamPortDefinition, + &port_def_type); + if (error != OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, + "Set OMX_IndexParamPortDefinition1 failed %x", error); + video->UnlockClock(); + pthread_setcancelstate(oldcancelstate, NULL); + pthread_setcanceltype(oldcanceltype, NULL); + return false; + } + + + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture 5 6"); + + +/* port_def_type.nPortIndex=omx_egl_input_port; + error = OMX_SetParameter(omx_egl_render, OMX_IndexParamPortDefinition, + &port_def_type); + if (error != OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, + "Set OMX_IndexParamPortDefinition3 failed %x", error); + video->UnlockClock(); + pthread_setcancelstate(oldcancelstate, NULL); + pthread_setcanceltype(oldcanceltype, NULL); + return false; + }*/ + + pictInf.width = port_def_type.format.image.nFrameWidth; + pictInf.height = port_def_type.format.image.nFrameHeight; + pictInf.decoder = this; + pictInf.type = OsdVector::PictureInfo::RGBAMemBlock; + pictInf.lindex = index; + + + port_def_type.nPortIndex=omx_egl_output_port; + + error=OMX_GetParameter(omx_egl_render,OMX_IndexParamPortDefinition, &port_def_type); + if (error != OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, + "OMX_IndexParamPortDefinition fix failed %x", error); + video->UnlockClock(); + pthread_setcancelstate(oldcancelstate, NULL); + pthread_setcanceltype(oldcanceltype, NULL); + return false; + } + + + + port_def_type.nBufferCountActual = 1; + EGLDisplay egl_display; + if (!pictcreat->getEGLPicture(pictInf, &egl_display)) { + Log::getInstance()->log("Image", Log::DEBUG, + "getEGLPict failed"); + video->UnlockClock(); + pthread_setcancelstate(oldcancelstate, NULL); + pthread_setcanceltype(oldcanceltype, NULL); + return false; + } + + port_def_type.format.video.pNativeWindow = egl_display; + error = OMX_SetParameter(omx_egl_render, OMX_IndexParamPortDefinition, + &port_def_type); + if (error != OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, + "Set OMX_IndexParamPortDefinition3 failed %x", error); + video->UnlockClock(); + pthread_setcancelstate(oldcancelstate, NULL); + pthread_setcanceltype(oldcanceltype, NULL); + return false; + } + + + + + + + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture 7"); + video->WaitForEvent(omx_egl_render,OMX_EventPortSettingsChanged); + + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture 8"); + + error=OMX_SendCommand(omx_egl_render/*dec*/,OMX_CommandPortEnable,omx_egl_output_port/*codec*/,0); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", Log::DEBUG, "Prepare omx_egl_output_port Send Command to enable port %x", error); + return 0; + } + + OMX_BUFFERHEADERTYPE *buf_head_egl=NULL; + error=OMX_UseEGLImage(omx_egl_render/*dec*/,&buf_head_egl,omx_egl_output_port/*codec*/, this, pictInf.reference); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", Log::DEBUG, "Use OMX_UseEGLImage failed %x", error); + video->UnlockClock(); + pthread_setcancelstate(oldcancelstate, NULL); + pthread_setcanceltype(oldcanceltype, NULL); + return false; + } + buf_head_egl->pAppPrivate=this; + + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture 8 a"); + + + + + + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture 8 end"); + + video->EnablePort(omx_imag_decode,omx_image_output_port,false); + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture 9"); + //video->EnablePort(omx_egl_render,omx_egl_output_port,false); + + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture 10"); + + omx_egl_filled = false; + error = OMX_FillThisBuffer(omx_egl_render, buf_head_egl); + + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", Log::DEBUG, "OMX_FillThisBuffer failed %x", error); + video->UnlockClock(); + pthread_setcancelstate(oldcancelstate, NULL); + pthread_setcanceltype(oldcanceltype, NULL); + return false; + } + count =1; + video->UnlockClock(); + while (!omx_egl_filled) { + + count++; + if (count>100) { + pthread_setcancelstate(oldcancelstate, NULL); + pthread_setcanceltype(oldcanceltype, NULL); + Log::getInstance()->log("Image", Log::DEBUG, "No one filled my buffer"); + return false; + } + MILLISLEEP(10); + + + } + omx_egl_filled = false; + video->LockClock(); + + error=OMX_FreeBuffer(omx_egl_render/*dec*/, omx_egl_output_port/*codec*/,buf_head_egl); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", Log::DEBUG, "Use OMX_FreeBuffer 2 failed %x", error); + pthread_setcancelstate(oldcancelstate, NULL); + pthread_setcanceltype(oldcanceltype, NULL); + return false; + } + + + + video->UnlockClock(); + pthread_setcancelstate(oldcancelstate, NULL); + pthread_setcanceltype(oldcanceltype, NULL); + Log::getInstance()->log("Image", Log::DEBUG, + "decodePicture left"); + + pictInfValid=true; + return true; + +} + +bool ImageOMX::getDecodedPicture(struct OsdVector::PictureInfo& pict_inf) +{ + if (!pictInfValid) return false; + pict_inf=pictInf; + pictInfValid = false; + return true; +} + +void ImageOMX::freeReference(void * ref) +{ + +} + + +int ImageOMX::PrepareInputBufsOMX(bool setportdef) //needs to be called with locvke omx clock mutex +{ + VideoOMX *video=(VideoOMX*)Video::getInstance(); + 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_image_input_port;//omx_codec_input_port; + + error=OMX_GetParameter(omx_imag_decode/*dec*/,OMX_IndexParamPortDefinition, &port_def_type); + + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", Log::DEBUG, "Get OMX OMX_IndexParamPortDefinition failed %x", error); + } + + + if (setportdef) { + port_def_type.nBufferCountActual=10; + port_def_type.nBufferSize=max(port_def_type.nBufferSize,1000000); // for transcoder important + + error=OMX_SetParameter(omx_imag_decode/*dec*/,OMX_IndexParamPortDefinition, &port_def_type); + + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", Log::DEBUG, "Set OMX OMX_IndexParamPortDefinition failed %x", error); + } + } + + + error=OMX_SendCommand(omx_imag_decode/*dec*/,OMX_CommandPortEnable,omx_image_input_port/*codec*/,0); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", 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++) { + OMX_BUFFERHEADERTYPE *buf_head=NULL; + error=OMX_UseBuffer(omx_imag_decode/*dec*/,&buf_head,omx_image_input_port/*codec*/,this,port_def_type.nBufferSize, NULL); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", Log::DEBUG, "Use OMX_UseBuffer 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; + + + input_bufs_omx_mutex.Unlock(); + + if (!video->CommandFinished(omx_imag_decode/*dec*/,OMX_CommandPortEnable, omx_image_input_port /*codec*/)) { + return 0; + } + + return 1; +} + +int ImageOMX::DestroyInputBufsOMX() //call with clock mutex locked +{ + OMX_ERRORTYPE error; + + input_bufs_omx_mutex.Lock(); + for (int i=0; i< input_bufs_omx_all.size();i++) { + Log::getInstance()->log("Image", Log::DEBUG, "OMX_FreeBuffer mark"); + if (input_bufs_omx_all[i]->pBuffer) free(input_bufs_omx_all[i]->pBuffer); + error=OMX_FreeBuffer(omx_imag_decode/*dec*/,omx_image_input_port/*codec*/,input_bufs_omx_all[i]); + if (error!=OMX_ErrorNone){ + Log::getInstance()->log("Image", 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 ImageOMX::DestroyInputBufsOMXwhilePlaying() //call with clock mutex locked +{ + OMX_ERRORTYPE error; + + input_bufs_omx_mutex.Lock(); + while (input_bufs_omx_all.size()>0) { + if (input_bufs_omx_free.size()>0) { + // Destroy one buffer + vector::iterator itty=input_bufs_omx_all.begin(); + OMX_BUFFERHEADERTYPE* cur_buf=input_bufs_omx_free.front(); + for (; itty!= input_bufs_omx_all.end();itty++) { + if ((*itty)==cur_buf) { + input_bufs_omx_all.erase(itty); + input_bufs_omx_free.pop_front(); + break; + } + } + } else { + input_bufs_omx_mutex.Unlock(); + MILLISLEEP(5); + input_bufs_omx_mutex.Lock(); + } + } + + Log::getInstance()->log("Image", Log::DEBUG, "DestroyInputBufsOMXwhilePlaying %d %d", input_bufs_omx_all.size(),input_bufs_omx_free.size()); + input_bufs_omx_mutex.Unlock(); + return 1; +} + + +int ImageOMX::DeAllocateCodecsOMX() +{ + OMX_ERRORTYPE error; + omx_running=false; + VideoOMX *video=(VideoOMX*)Video::getInstance(); + Log::getInstance()->log("Image", Log::DEBUG, "enter deallocatecodecsomx"); + + + + Log::getInstance()->log("Image", Log::DEBUG, "deallocatecodecsomx mark 1"); + + Log::getInstance()->log("Image", Log::DEBUG, "deallocatecodecsomx mark 2"); + + video->LockClock(); + if (omx_imag_decode/*dec*/) { + + + if (!video->ChangeComponentState(omx_imag_decode,OMX_StateIdle)) { + Log::getInstance()->log("Image", Log::DEBUG, "omx_imag_decode ChangeComponentState"); + } + + if (!video->ChangeComponentState(omx_egl_render,OMX_StateIdle)) { + Log::getInstance()->log("Image", Log::DEBUG, "omx_egl_render ChangeComponentState"); + } + + // TODO proper deinit sequence + // first flush all buffers + + error=OMX_SendCommand(omx_imag_decode,OMX_CommandFlush, omx_image_input_port, NULL); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, "OMX_Flush rend in failed %x", error); + + } + + error=OMX_SendCommand(omx_imag_decode,OMX_CommandFlush, omx_image_output_port, NULL); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, "OMX_Flush rend in failed %x", error); + + } + + error=OMX_SendCommand(omx_egl_render,OMX_CommandFlush, omx_egl_input_port, NULL); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, "OMX_Flush rend in failed %x", error); + + } + + error=OMX_SendCommand(omx_egl_render,OMX_CommandFlush, omx_egl_output_port, NULL); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, "OMX_Flush rend in failed %x", error); + + } + + + + + Log::getInstance()->log("Image", Log::DEBUG, "deallocatecodecsomx mark 6"); + + if (!video->CommandFinished(omx_imag_decode,OMX_CommandFlush,omx_image_input_port) || + !video->CommandFinished(omx_egl_render,OMX_CommandFlush,omx_egl_input_port) || + !video->CommandFinished(omx_imag_decode,OMX_CommandFlush,omx_image_output_port) || + !video->CommandFinished(omx_egl_render,OMX_CommandFlush,omx_egl_output_port)) { + Log::getInstance()->log("Image", Log::DEBUG, "flush cmd clock shed failed"); + } + + + DestroyInputBufsOMX(); //We have to make sure that no buffers are in use + + Log::getInstance()->log("Image", Log::DEBUG, "deallocatecodecsomx mark 7"); + + //todo flushing + if (!video->DisablePort(omx_imag_decode,omx_image_output_port,true)) { + Log::getInstance()->log("Image", Log::DEBUG, "Disable Tunnel Port failed 1"); + } + + + if (!video->DisablePort(omx_egl_render,omx_egl_input_port,true)) { + Log::getInstance()->log("Image", Log::DEBUG, "Disable Tunnel Port failed 4"); + } + + + + + error=OMX_SetupTunnel(omx_imag_decode,omx_image_output_port,NULL,NULL); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error); + + } + + error=OMX_SetupTunnel(omx_egl_render,omx_egl_input_port,NULL,NULL); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error); + + } + + + Log::getInstance()->log("Image", Log::DEBUG, "deallocatecodecsomx mark 8"); + + + //error=OMX_FreeHandle(omx_aud_dec); + error=OMX_FreeHandle(omx_imag_decode); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, "FreeHandle failed %d", error); + } + error=OMX_FreeHandle(omx_egl_render); + if (error!=OMX_ErrorNone) { + Log::getInstance()->log("Image", Log::DEBUG, "FreeHandle failed %d", error); + } + video->UnlockClock(); + + omx_imag_decode/*dec*/=NULL; + omx_egl_render/*dec*/=NULL; + + } else { + + video->UnlockClock(); + } + Log::getInstance()->log("Image", Log::DEBUG, "leave deallocate codecs OMX"); + + return 1; +} diff --git a/imageomx.h b/imageomx.h new file mode 100644 index 0000000..31e0da7 --- /dev/null +++ b/imageomx.h @@ -0,0 +1,104 @@ +/* + Copyright 2004-2005 Chris Tallon, 2009,2012, 2014 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 IMAGEOMX_H +#define IMAGEOMX_H + +#include +#include +#include +#include + +#include +#include + +#include "defines.h" +#include "osdvector.h" +#include "videoomx.h" + + +class EGLPictureCreator { +public: + virtual bool getEGLPicture(struct OsdVector::PictureInfo & info, EGLDisplay * display ) = 0; +}; + + + +class ImageOMX : public OsdVector::PictureDecoder +{ + friend class VideoOMX; + public: + ImageOMX(OsdVector::PictureReader * treader); + virtual ~ImageOMX(); + + void init(); + void shutdown(); + + bool decodePicture(LoadIndex index, unsigned char * buffer, unsigned int length); + bool getDecodedPicture(struct OsdVector::PictureInfo& pict_inf); + void freeReference(void * ref); + + private: + + static OMX_ERRORTYPE EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver); + static OMX_ERRORTYPE FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver); + + + void ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* bulibaver); + void ReturnFillOMXBuffer(OMX_BUFFERHEADERTYPE* buffer); + + + OMX_HANDLETYPE omx_imag_decode; + OMX_HANDLETYPE omx_egl_render; + + OMX_U32 omx_image_input_port; + OMX_U32 omx_image_output_port; + + OMX_U32 omx_egl_input_port; + OMX_U32 omx_egl_output_port; + + + int AllocateCodecsOMX(); + int DeAllocateCodecsOMX(); + + int PrepareInputBufsOMX(bool setportdef); + int DestroyInputBufsOMX(); + int DestroyInputBufsOMXwhilePlaying(); + + + + vector input_bufs_omx_all; + list input_bufs_omx_free; + //list output_bufs_omx_full; + Mutex input_bufs_omx_mutex; + + bool omx_running; + bool omx_first_frame; + bool omx_egl_filled; + + int initted; + + protected: + OsdVector::PictureInfo pictInf; + bool pictInfValid; + +}; + +#endif -- 2.39.5