LDFLAGS = -Wall\r
LIBS = -L/opt/vc/lib -lpthread -lrt -lEGL -lGLESv2 -lopenmaxil -lbcm_host -lavformat -lavcodec -lavutil\r
\r
-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 \r
+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 \r
LIBS+= -ljpeg\r
CROSSLIBS = \r
INCLUDES = -DVOMP_PLATTFORM_RASPBERRY -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads \r
if (alen)\r
{\r
//Log::getInstance()->log("Afeed", Log::DEBUG, "written");\r
+ cb.call(this);\r
}\r
else\r
{\r
--- /dev/null
+/*
+ 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 "audioomx.h"
+#include "videoomx.h"
+#include "log.h"
+#include "vdr.h"
+#include "woptionpane.h"
+
+AudioOMX::AudioOMX()
+{
+ initted = 0;
+ streamType = 0;
+ volume = 20;
+ muted = 0;
+ lastAType = MPTYPE_MPEG_AUDIO;
+
+ canpass_ac3=false;
+ canpass_mp2=false;
+ canpass_mp3=false;
+ canpass_pcm_mch=false;
+
+ prefered_ac3=0; //0 stereo PCM, 1 passthrough 2 Multichannel PCM
+ prefered_mp2=0;
+ prefered_mp3=0;
+ hdmi=true;
+
+ omx_running=false;
+
+ omx_aud_rend/*dec*/=0;
+ cur_input_buf_omx=NULL;
+
+ ac3codec_libav=NULL;
+ ac3codec_context_libav=NULL;
+
+ mp23codec_libav=NULL;
+ mp23codec_context_libav=NULL;
+
+}
+
+AudioOMX::~AudioOMX()
+{
+}
+
+int AudioOMX::init(UCHAR tstreamType) {
+ if (initted)
+ return 0;
+ initted = 1;
+
+ streamType = tstreamType;
+
+ if (!initAllParams()) {
+ shutdown();
+ return 0;
+ }
+
+ unMute();
+
+
+
+ av_register_all();
+ av_log_set_flags(AV_LOG_SKIP_REPEATED);
+
+ ac3codec_libav = avcodec_find_decoder(CODEC_ID_AC3);
+ if (ac3codec_libav == NULL) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "Find libav ac3 decoder failed");
+ return 0;
+ }
+
+ mp23codec_libav = avcodec_find_decoder(CODEC_ID_MP3);
+ if (mp23codec_libav == NULL) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "Find libav mpeg audio decoder failed");
+ return 0;
+ }
+
+ return 1;
+}
+
+int AudioOMX::initAllParams()
+{
+ return (setStreamType(streamType) && setChannel() && setSource());
+}
+
+int AudioOMX::shutdown()
+{
+ if (!initted) return 0;
+ initted = 0;
+
+ Log::getInstance()->log("Audio", Log::DEBUG, "audio shutdown called");
+ DeAllocateCodecsOMX();
+
+ return 1;
+}
+
+bool AudioOMX::loadOptionsfromServer(VDR* vdr)
+{
+ Log::getInstance()->log("Audio", Log::DEBUG, "AudioOMX config load");
+ char *name=vdr->configLoad("AudioOMX","AC3DecodingMode");
+
+ if (name != NULL) {
+ if (STRCASECMP(name, "PCM") == 0) {
+ prefered_ac3 = 0;
+ } else if (STRCASECMP(name, "Passthrough") == 0) {
+ prefered_ac3 = 1;
+ } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
+ prefered_ac3 = 2;
+ }
+ }
+
+ name = vdr->configLoad("AudioOMX", "Mp2DecodingMode");
+
+ if (name != NULL) {
+ if (STRCASECMP(name, "PCM") == 0) {
+ prefered_mp2 = 0;
+ } else if (STRCASECMP(name, "Passthrough") == 0) {
+ prefered_mp2 = 1;
+ } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
+ prefered_mp2 = 2;
+ }
+ }
+
+ name = vdr->configLoad("AudioOMX", "Mp3DecodingMode");
+
+ if (name != NULL) {
+ if (STRCASECMP(name, "PCM") == 0) {
+ prefered_mp3 = 0;
+ } else if (STRCASECMP(name, "Passthrough") == 0) {
+ prefered_mp3 = 1;
+ } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
+ prefered_mp3 = 2;
+ }
+ }
+
+ name = vdr->configLoad("AudioOMX", "AudioOutput");
+
+ if (name != NULL) {
+ if (STRCASECMP(name, "analog") == 0) {
+ hdmi = false;
+ } else if (STRCASECMP(name, "HDMI") == 0) {
+ hdmi = true;
+ }
+ }
+
+
+ return true;
+
+}
+
+bool AudioOMX::handleOptionChanges(Option* option)
+{
+ if (Audio::handleOptionChanges(option))
+ return true;
+ switch (option->id) {
+ case 4: {
+ if (STRCASECMP(option->options[option->userSetChoice], "analog") == 0) {
+ hdmi = false;
+ } else if (STRCASECMP(option->options[option->userSetChoice], "HDMI")
+ == 0) {
+ hdmi = true;
+ }
+ return true;
+ }
+ break;
+ case 1: {
+ if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
+ prefered_ac3 = 0;
+ } else if (STRCASECMP(option->options[option->userSetChoice],
+ "Passthrough") == 0) {
+ prefered_ac3 = 1;
+ } else if (STRCASECMP(option->options[option->userSetChoice],
+ "PCMMultichannel") == 0) {
+ prefered_ac3 = 2;
+ }
+ }
+ break;
+ case 2: {
+ if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
+ prefered_mp2 = 0;
+ } else if (STRCASECMP(option->options[option->userSetChoice],
+ "Passthrough") == 0) {
+ prefered_mp2 = 1;
+ } else if (STRCASECMP(option->options[option->userSetChoice],
+ "PCMMultichannel") == 0) {
+ prefered_mp2 = 2;
+ }
+ }
+ break;
+ case 3: {
+ if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
+ prefered_mp3 = 0;
+ } else if (STRCASECMP(option->options[option->userSetChoice],
+ "Passthrough") == 0) {
+ prefered_mp3 = 1;
+ } else if (STRCASECMP(option->options[option->userSetChoice],
+ "PCMMultichannel") == 0) {
+ prefered_mp3 = 2;
+ }
+ }
+ break;
+ };
+ return false;
+
+}
+
+bool AudioOMX::saveOptionstoServer()
+{
+
+ switch (prefered_ac3) {
+ case 0:
+ VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode", "PCM");
+ break;
+ case 1:
+ VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode",
+ "Passthrough");
+ break;
+ case 2:
+ VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode",
+ "PCMMultichannel");
+ break;
+ };
+
+ switch (prefered_mp2) {
+ case 0:
+ VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode", "PCM");
+ break;
+ case 1:
+ VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode",
+ "Passthrough");
+ break;
+ case 2:
+ VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode",
+ "PCMMultichannel");
+ break;
+ };
+
+ switch (prefered_mp3) {
+ case 0:
+ VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode", "PCM");
+ break;
+ case 1:
+ VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode",
+ "Passthrough");
+ break;
+ case 2:
+ VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode",
+ "PCMMultichannel");
+ break;
+ };
+
+ if (!hdmi)
+ VDR::getInstance()->configSave("AudioOMX", "AudioOutput", "analog");
+ else
+ VDR::getInstance()->configSave("AudioOMX", "AudioOutput", "HDMI");
+
+
+ return true;
+}
+
+/*Option(UINT id, const char* displayText, const char* configSection, const char* configKey, UINT optionType,
+ UINT numChoices, UINT defaultChoice, UINT startInt,
+ const char * const * options, const char * const * optionkeys = NULL, AbstractOption* handler=NULL);*/
+
+bool AudioOMX::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
+{
+ if (!Audio::addOptionsToPanes(panenumber,options,pane)) return false;
+
+
+ Option* option;
+ if (panenumber == 2)
+ {
+
+ static const char* audioopts[]={"analog","HDMI"};
+ option = new Option(4,tr("Audio Output"), "AudioOMX","AudioOutput",Option::TYPE_TEXT,2,0,0,audioopts,NULL,false,this);
+ options->push_back(option);
+ pane->addOptionLine(option);
+
+
+ char **ac3opts=new char *[3];
+ int i=0;
+ ac3opts[i]=new char[strlen("PCM")+1];
+ strcpy(ac3opts[i],"PCM");
+ i++;
+ if (canpass_ac3) {
+ ac3opts[i]=new char[strlen("Passthrough")+1];
+ strcpy(ac3opts[i],"PassThrough");
+ i++;
+ }
+ if (canpass_pcm_mch) {
+ ac3opts[i]=new char[strlen("PCMMultichannel")+1];
+ strcpy(ac3opts[i],"PCMMultichannel");
+ i++;
+ }
+ option = new Option(1 ,tr("AC3 HDMI Mode"), "AudioOMX", "AC3DecodingMode", Option::TYPE_TEXT, i, 0, 0, ac3opts,NULL,true, this);
+ options->push_back(option);
+ pane->addOptionLine(option);
+
+ char **mp2opts = new char *[3];
+ i = 0;
+ mp2opts[i] = new char[strlen("PCM") + 1];
+ strcpy(mp2opts[i], "PCM");
+ i++;
+ if (canpass_mp2) {
+ mp2opts[i] = new char[strlen("Passthrough") + 1];
+ strcpy(mp2opts[i], "PassThrough");
+ i++;
+ }
+ if (canpass_pcm_mch) {
+ mp2opts[i] = new char[strlen("PCMMultichannel") + 1];
+ strcpy(mp2opts[i], "PCMMultichannel");
+ i++;
+ }
+ option = new Option(2, tr("Mp2 HDMI Mode"), "AudioOMX",
+ "Mp2DecodingMode", Option::TYPE_TEXT, i, 0, 0,
+ mp2opts, NULL, true, this);
+ options->push_back(option);
+ pane->addOptionLine(option);
+
+ char **mp3opts = new char *[3];
+ i = 0;
+ mp3opts[i] = new char[strlen("PCM") + 1];
+ strcpy(mp3opts[i], "PCM");
+ i++;
+ if (canpass_mp3) {
+ mp3opts[i] = new char[strlen("Passthrough") + 1];
+ strcpy(mp3opts[i], "PassThrough");
+ i++;
+ }
+ if (canpass_pcm_mch) {
+ mp3opts[i] = new char[strlen("PCMMultichannel") + 1];
+ strcpy(mp3opts[i], "PCMMultichannel");
+ i++;
+ }
+ option = new Option(3, tr("Mp3 HDMI Mode"), "AudioOMX",
+ "Mp2DecodingMode", Option::TYPE_TEXT, i, 0, 0, mp3opts,
+ NULL, true, this);
+ options->push_back(option);
+ pane->addOptionLine(option);
+
+
+ }
+
+ return true;
+}
+
+
+
+
+
+
+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");
+ AudioOMX *audio=(AudioOMX *)getInstance();
+ audio->ReturnEmptyOMXBuffer(buffer);
+ return OMX_ErrorNone;
+
+}
+
+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);
+ //Log::getInstance()->log("Audio", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size());
+ input_bufs_omx_mutex.Unlock();
+}
+
+ 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 AudioOMX::setStreamType(UCHAR type)
+{
+ if (!initted) return 0;
+
+ // if (ioctl(fdAudio, AV_SET_AUD_STREAMTYPE, type) != 0) return 0;
+ return 1;
+}
+
+int AudioOMX::setChannel()
+{
+ if (!initted) return 0;
+
+ // if (ioctl(fdAudio, AV_SET_AUD_CHANNEL, 0) != 0) return 0;
+ return 1;
+}
+
+int AudioOMX::setSource()
+{
+ if (!initted) return 0;
+
+ // if (ioctl(fdAudio, AV_SET_AUD_SRC, 1) != 0) return 0;
+ return 1;
+}
+
+int AudioOMX::sync()
+{
+ if (!initted) return 0;
+
+ // if (ioctl(fdAudio, AV_SET_AUD_SYNC, 2) != 0) return 0;
+ return 1;
+}
+
+int AudioOMX::play() {
+ if (!initted)
+ return 0;
+ lastAType=MPTYPE_MPEG_AUDIO;
+ Log::getInstance()->log("Audio", Log::DEBUG, "enter play");
+
+ if (!AllocateCodecsOMX()) {
+ return 0;
+ }
+ return 1;
+}
+
+
+int AudioOMX::ChangeAudioDestination() //clock aka omx mutex needs to be locked
+{
+ OMX_ERRORTYPE error;
+ const char * destinations[]={"local","hdmi"};
+ int dest=0;
+ if (hdmi) dest=1;
+ else dest=0;
+
+ OMX_CONFIG_BRCMAUDIODESTINATIONTYPE auddest;
+ memset(&auddest,0,sizeof(auddest));
+ auddest.nSize=sizeof(auddest);
+ auddest.nVersion.nVersion=OMX_VERSION;
+ strcpy((char *)auddest.sName, destinations[dest]);
+
+ Log::getInstance()->log("Audio", Log::DEBUG, "setting destination to: %s",auddest.sName);
+ error=OMX_SetConfig(omx_aud_rend,OMX_IndexConfigBrcmAudioDestination,&auddest);
+ if (error!=OMX_ErrorNone){
+ Log::getInstance()->log("Audio", Log::DEBUG, "Init OMX_IndexConfigBrcmAudioDestination failed %x %x %s", error,omx_aud_rend,auddest.sName);
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+ return 1;
+
+
+}
+
+int AudioOMX::ChangeAudioPortConfig() //clock aka omx mutex needs to be locked
+{
+ OMX_ERRORTYPE error;
+ //Ok first fidle a working configuration
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "ChangeAudioPortConfig");
+
+ if (hdmi) {
+ switch (lastAType) {
+ case MPTYPE_MPEG_AUDIO: {
+ if (prefered_mp2 == 3 && false) { //not supported yet
+
+ } else {
+ if (prefered_mp2 == 2 && canpass_mp2) {
+ passthrough = true;
+ } else
+ passthrough = false;
+ }
+ }
+ break;
+ case MPTYPE_AC3_PRE13:
+ case MPTYPE_AC3: {
+ if (prefered_ac3 == 3 && false) { //not supported yet
+
+ } else {
+ if (prefered_ac3 == 2 && canpass_ac3) {
+ passthrough = true;
+ } else
+ passthrough = false;
+ }
+ }
+ break;
+ case MPTYPE_MPEG_AUDIO_LAYER3: {
+ if (prefered_mp3 == 3 && false) { //not supported yet
+
+ } else {
+ if (prefered_mp3 == 2 && canpass_mp2) {
+ passthrough = true;
+ } else
+ passthrough = false;
+ }
+ }
+ break;
+ };
+ } else {
+ passthrough=false;
+ //mch=false; // multichannel also false
+ }
+
+
+
+ /*OMX_CONFIG_BOOLEANTYPE booly;
+ memset(&booly, 0, sizeof(booly));
+ booly.nSize = sizeof(booly);
+ booly.nVersion.nVersion = OMX_VERSION;
+ if (passthrough)
+ booly.bEnabled = OMX_TRUE;
+ else
+ booly.bEnabled = OMX_FALSE;
+
+ error = OMX_SetParameter(omx_aud_dec, OMX_IndexParamBrcmDecoderPassThrough,
+ &booly);
+ if (error != OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "Init OMX_IndexParamBrcmDecoderPassThrough failed %x", error);
+ DeAllocateCodecsOMX();
+ return 0;
+ }*/
+ VideoOMX *video=(VideoOMX*)Video::getInstance();
+
+
+ if (!omx_running) {
+ if (passthrough) {
+ // TODO coding
+ } else {
+
+ OMX_AUDIO_PARAM_PCMMODETYPE audio_pcm;
+ memset(&audio_pcm, 0, sizeof(audio_pcm));
+ audio_pcm.nSize = sizeof(audio_pcm);
+ audio_pcm.nVersion.nVersion = OMX_VERSION;
+ audio_pcm.nChannels = 2;
+ audio_pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+ audio_pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+ //audio_pcm.eChannelMapping[2]=OMX_AUDIO_ChannelMax;
+ audio_pcm.eNumData = OMX_NumericalDataSigned;
+ audio_pcm.eEndian = OMX_EndianLittle;
+ audio_pcm.bInterleaved = OMX_TRUE;
+ audio_pcm.nBitPerSample = 16;
+ audio_pcm.ePCMMode = OMX_AUDIO_PCMModeLinear;
+ audio_pcm.nChannels = 2;
+ audio_pcm.nSamplingRate = 48000;
+ audio_pcm.nPortIndex = omx_rend_input_port;
+ error = OMX_SetParameter(omx_aud_rend, OMX_IndexParamAudioPcm,
+ &audio_pcm);
+ if (error != OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "Init OMX_IndexParamAudioPcm failed %x %d", error,
+ omx_rend_input_port);
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+
+ }
+ }
+
+
+
+ return 1;
+
+
+
+}
+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!");
+ return 0;
+ }
+
+ ac3codec_context_libav->flags |= CODEC_FLAG_TRUNCATED;
+ ac3codec_context_libav->request_channels=2;
+
+ 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;
+ }
+
+ mp23codec_context_libav->flags |= CODEC_FLAG_TRUNCATED;
+ mp23codec_context_libav->request_channels=2;
+
+ 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 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 AudioOMX::AllocateCodecsOMX()
+{
+ OMX_ERRORTYPE error;
+ 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
+ VideoOMX *video=(VideoOMX*)Video::getInstance();
+
+ if (!InitDecoderLibAV()) 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;
+
+
+ if (!video->getClockAudioandInit(&omx_clock,&omx_clock_output_port)){
+ return 0;// get the clock and init it if necessary
+ }
+
+ /* TODO end */
+ if (!video->idleClock()) {
+ return 0;
+ }
+ video->LockClock();
+
+ error = OMX_GetHandle(&omx_aud_rend, VPE_OMX_AUDIO_REND, NULL, &callbacks);
+ if (error != OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "Init OMX audio rend failed %x", error);
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+
+ if (!ChangeAudioDestination()) {
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+
+ error = OMX_GetParameter(omx_aud_rend, OMX_IndexParamAudioInit, &p_param);
+ if (error != OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "Init OMX audio rend OMX_GetParameter failed %x", error);
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+ omx_rend_input_port = p_param.nStartPortNumber;
+
+ error = OMX_GetParameter(omx_aud_rend, OMX_IndexParamOtherInit, &p_param);
+ if (error != OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "Init OMX aud rend OMX_GetParameter failed %x", error);
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+ // buggy return value
+ omx_rend_clock_port = p_param.nStartPortNumber;
+
+
+/* error=OMX_GetHandle(&omx_aud_dec,VPE_OMX_AUDIO_DECODER,NULL,&callbacks);
+
+ if (error!=OMX_ErrorNone){
+ Log::getInstance()->log("Audio", Log::DEBUG, "Init OMX audio decoder failed %x", error);
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+
+ error=OMX_GetParameter(omx_aud_dec,OMX_IndexParamAudioInit,&p_param);
+ if (error!=OMX_ErrorNone){
+ Log::getInstance()->log("Audio", Log::DEBUG, "Init OMX audio decoder OMX_GetParameter failed %x", error);
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+ omx_codec_input_port=p_param.nStartPortNumber;
+ omx_codec_output_port=p_param.nStartPortNumber+1;
+
+ if (!video->DisablePort(omx_aud_dec,omx_codec_input_port) || !video->DisablePort(omx_aud_dec,omx_codec_output_port)) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "Disable Ports OMX audio decoder failed");
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }*/
+
+
+
+
+ if (!video->DisablePort(omx_aud_rend,omx_rend_input_port,true) ) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "Disable Ports OMX audio rend failed %d",omx_rend_input_port);
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+
+ if ( !video->DisablePort(omx_aud_rend, omx_rend_clock_port, true)) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "Disable Ports OMX rend clock port failed %d",omx_rend_clock_port);
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+
+
+
+
+ //Setuo chain
+
+
+ error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,omx_aud_rend,omx_rend_clock_port);
+ if (error!=OMX_ErrorNone){
+ Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Setup tunnel clock to rend failed %x %d %d", error,omx_clock_output_port,omx_rend_clock_port);
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+
+ if (!video->EnablePort(omx_clock,omx_clock_output_port,false) || !video->EnablePort(omx_aud_rend,omx_rend_clock_port,false)
+ ) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "Enable Ports OMX clock rend failed");
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+
+ if (!video->ChangeComponentState(omx_aud_rend,OMX_StateIdle)) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "aud_rend idle ChangeComponentState");
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+
+
+
+
+ if ( !video->CommandFinished(omx_aud_rend,OMX_CommandPortEnable,omx_rend_clock_port)) {
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+
+ if ( !video->CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port)) {
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+
+
+
+ if (!ChangeAudioPortConfig()){
+ Log::getInstance()->log("Audio", Log::NOTICE, "Change AudioPortConfig failed");
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+
+/* if (!video->ChangeComponentState(omx_aud_dec,OMX_StateIdle)) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "aud_dec ChangeComponentState");
+ DeAllocateCodecsOMX();
+ return 0;
+ }*/
+
+
+
+ if (!PrepareInputBufsOMX()) {
+ video->UnlockClock();
+ 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("Audio", 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("Audio", 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_aud_rend,OMX_StateExecuting)) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "omx_aud_rend ChangeComponentState Execute");
+ video->UnlockClock();
+ DeAllocateCodecsOMX();
+ return 0;
+ }
+
+
+ video->UnlockClock();
+ paused=false;
+ omx_running=true;
+
+
+ if (!video->setClockExecutingandRunning()) return 0;
+
+ Log::getInstance()->log("Audio", Log::NOTICE, "Allocate Codecs OMX finished");
+
+ return 1;
+}
+
+
+
+
+int AudioOMX::PrepareInputBufsOMX() //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_rend_input_port;//omx_codec_input_port;
+
+ error=OMX_GetParameter(omx_aud_rend/*dec*/,OMX_IndexParamPortDefinition, &port_def_type);
+
+ if (error!=OMX_ErrorNone){
+ Log::getInstance()->log("Audio", Log::DEBUG, "Get OMX OMX_IndexParamPortDefinition failed %x", error);
+ }
+
+
+ port_def_type.nBufferCountActual=2;
+ port_def_type.nBufferSize=max(port_def_type.nBufferSize,50000); // for transcoder important
+
+ error=OMX_SetParameter(omx_aud_rend/*dec*/,OMX_IndexParamPortDefinition, &port_def_type);
+
+ if (error!=OMX_ErrorNone){
+ Log::getInstance()->log("Audio", Log::DEBUG, "Set OMX OMX_IndexParamPortDefinition failed %x", error);
+ }
+
+
+ error=OMX_SendCommand(omx_aud_rend/*dec*/,OMX_CommandPortEnable,omx_rend_input_port/*codec*/,0);
+ if (error!=OMX_ErrorNone){
+ Log::getInstance()->log("Audio", 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_AllocateBuffer(omx_aud_rend/*dec*/,&buf_head,omx_rend_input_port/*codec*/,NULL,port_def_type.nBufferSize);
+ if (error!=OMX_ErrorNone){
+ Log::getInstance()->log("Audio", 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();
+
+ if (!video->CommandFinished(omx_aud_rend/*dec*/,OMX_CommandPortEnable,omx_rend_input_port /*codec*/)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int AudioOMX::DestroyInputBufsOMX() //call with clock mutex locked
+{
+ OMX_ERRORTYPE error;
+
+ cur_input_buf_omx=NULL;
+ input_bufs_omx_mutex.Lock();
+ for (int i=0; i< input_bufs_omx_all.size();i++) {
+ error=OMX_FreeBuffer(omx_aud_rend/*dec*/,omx_rend_input_port/*codec*/,input_bufs_omx_all[i]);
+ if (error!=OMX_ErrorNone){
+ Log::getInstance()->log("Audio", 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 AudioOMX::DeAllocateCodecsOMX()
+{
+ OMX_ERRORTYPE error;
+ omx_running=false;
+ VideoOMX *video=(VideoOMX*)Video::getInstance();
+ Log::getInstance()->log("Audio", Log::DEBUG, "enter deallocatecodecsomx");
+
+
+ video->LockClock();
+ if (cur_input_buf_omx) {
+ cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_EOS;
+ OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_aud_rend/*dec*/,cur_input_buf_omx);
+ if (error!=OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error);
+ }
+
+ cur_input_buf_omx=NULL;//write out old data
+ }
+
+ if (omx_aud_rend/*dec*/) {
+ // first stop the omx elements
+ /* if (!video->ChangeComponentState(omx_aud_dec,OMX_StateIdle)) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "aud_dec ChangeComponentState");
+ }*/
+
+ video->UnlockClock();
+ video->idleClock();
+ video->LockClock();
+
+ if (!video->ChangeComponentState(omx_aud_rend,OMX_StateIdle)) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "aud_rend ChangeComponentState");
+ }
+
+ // TODO proper deinit sequence
+ // first flush all buffers
+
+ error=OMX_SendCommand(omx_aud_rend,OMX_CommandFlush, omx_rend_input_port, NULL);
+ if (error!=OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Flush rend in failed %x", error);
+
+ }
+
+ /* error=OMX_SendCommand(omx_aud_dec,OMX_CommandFlush, omx_codec_input_port, NULL);
+ if (error!=OMX_ErrorNone){
+ Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Flush codec out failed %x", error);
+
+ }*/
+
+
+ /* if (!video->CommandFinished(omx_aud_dec,OMX_CommandFlush,omx_codec_input_port)) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "flush cmd codec input failed");
+ }*/
+
+
+
+ error=OMX_SendCommand(omx_clock,OMX_CommandFlush, omx_clock_output_port, NULL);
+ if (error!=OMX_ErrorNone){
+ Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Flush clock out failed %x", error);
+
+ }
+
+ error=OMX_SendCommand(omx_aud_rend,OMX_CommandFlush, omx_rend_clock_port, NULL);
+ if (error!=OMX_ErrorNone){
+ Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Flush rend clock failed %x", error);
+
+ }
+
+ if (!video->CommandFinished(omx_clock,OMX_CommandFlush,omx_clock_output_port) ||
+ !video->CommandFinished(omx_aud_rend,OMX_CommandFlush,omx_rend_clock_port)) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "flush cmd clock shed failed");
+ }
+
+ 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)) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 1");
+ }
+
+ /* if (!video->DisablePort(omx_aud_dec,omx_codec_output_port,true)) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 6");
+ }
+
+ if (!video->DisablePort(omx_aud_dec,omx_codec_input_port,true)) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 7");
+ }*/
+
+
+ if (!video->DisablePort(omx_aud_rend,omx_rend_clock_port,true)) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 4");
+ }
+
+ if (!video->DisablePort(omx_clock,omx_clock_output_port,true)) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 5");
+ }
+
+
+
+ /* error=OMX_SetupTunnel(omx_aud_dec,omx_codec_output_port,NULL,NULL);
+ if (error!=OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
+
+ }*/
+
+
+
+ error=OMX_SetupTunnel(omx_aud_rend,omx_rend_input_port,NULL,NULL);
+ if (error!=OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", 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("Audio", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
+
+ }
+
+ error=OMX_SetupTunnel(omx_aud_rend,omx_rend_clock_port,NULL,NULL);
+ if (error!=OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
+
+ }
+
+
+ //error=OMX_FreeHandle(omx_aud_dec);
+ error=OMX_FreeHandle(omx_aud_rend);
+ video->UnlockClock();
+ video->destroyClock();
+ omx_aud_rend/*dec*/=NULL;
+ if (error!=OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG, "FreeHandle failed %d", error);
+ }
+ } else {
+
+ video->UnlockClock();
+ DeinitDecoderLibAV();
+ }
+ Log::getInstance()->log("Audio", Log::DEBUG, "leave deallocate codecs OMX");
+
+ return 1;
+}
+
+
+
+int AudioOMX::stop()
+{
+ if (!initted) return 0;
+
+ Log::getInstance()->log("Audio", Log::DEBUG, "Audio stop called");
+ DeAllocateCodecsOMX();
+ //if (ioctl(fdAudio, AV_SET_AUD_RESET, 0x11) != 0) return 0;
+ return 1;
+}
+
+int AudioOMX::mute()
+{
+ if (!initted) return 0;
+
+// if (ioctl(fdAudio, AV_SET_AUD_MUTE, 1) != 0) return 0;
+ Log::getInstance()->log("Audio", Log::DEBUG, "MUTE MUTE MUTE");
+
+ muted = 1;
+ return 1;
+}
+
+int AudioOMX::unMute()
+{
+ if (!initted) return 0;
+
+// if (ioctl(fdAudio, AV_SET_AUD_MUTE, 0) != 0) return 0;
+ Log::getInstance()->log("Audio", Log::DEBUG, "MUTE OFF OFF OFF");
+
+ muted = 0;
+ return 1;
+}
+
+int AudioOMX::pause() {
+ if (!initted)
+ return 0;
+ if (!paused) {
+ paused = true;
+ VideoOMX *vw = (VideoOMX*) Video::getInstance();
+ vw->LockClock();
+ OMX_ERRORTYPE error;
+ error = OMX_SendCommand(omx_aud_rend, OMX_CommandFlush,
+ omx_rend_input_port, NULL);
+ if (error != OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "OMX_Flush rend in failed %x", error);
+
+ }
+ vw->UnlockClock();
+ vw->clockPause();
+ }
+ return 1;
+}
+
+int AudioOMX::unPause()
+{
+ if (!initted) return 0;
+ if (paused) {
+ paused=false; // may be also change omx clock
+ VideoOMX *vw = (VideoOMX*) Video::getInstance();
+ vw->clockUnpause();
+ }
+ return 1;
+}
+
+int AudioOMX::reset()
+{
+ if (!initted) return 0;
+//test();
+ Log::getInstance()->log("Audio", Log::DEBUG, "reset called");
+ DeAllocateCodecsOMX();
+
+// if (ioctl(fdAudio, AV_SET_AUD_RESET, 0x11) != 0) return 0;
+// Log::getInstance()->log("Audio", Log::DEBUG, "reset back");
+ // if (ioctl(fdAudio, AV_SET_AUD_PLAY, 0) != 0) return 0;
+
+ doMuting();
+ return 1;
+}
+
+int AudioOMX::setVolume(int tvolume)
+{
+ // parameter: 0 for silence, 20 for full
+ if ((tvolume < 0) || (tvolume > 20)) return 0;
+
+// volume = 2 * (20 - volume);
+// Right, that one was rubbish... 0-10 were almost
+// inaudible, 11-20 did what should have been done
+// over the whole 0-20 range
+
+ tvolume = 20 - tvolume;
+
+ audio_volume Avolume;
+ Avolume.frontleft = tvolume + Aoffset.frontleft;
+ Avolume.frontright = tvolume + Aoffset.frontright;
+ Avolume.rearleft = tvolume + Aoffset.rearleft;
+ Avolume.rearright = tvolume + Aoffset.rearright;
+ Avolume.center = tvolume + Aoffset.center;
+ Avolume.lfe = tvolume + Aoffset.lfe;
+
+// if (ioctl(fdAudio, AV_SET_AUD_VOLUME, &Avolume) != 0) return 0;
+
+// unsigned long vol = (tvolume << 24) | (tvolume << 16);
+//
+// Log::getInstance()->log("Audio", Log::DEBUG, "%lx", vol);
+// Log::getInstance()->log("Audio", Log::DEBUG, "%i", tvolume);
+
+// if (ioctl(fdAudio, AV_SET_AUD_VOLUME, &vol) != 0) return 0;
+ return 1;
+}
+
+#ifdef DEV
+int AudioOMX::test()
+{
+// ULLONG stc = 0;
+// return ioctl(fdAudio, AV_SET_AUD_STC, &stc);
+
+/* aud_sync_parms_t a;
+ a.parm1 = 0;
+ a.parm2 = 0;
+*/
+// int b = ioctl(fdAudio, AV_SET_AUD_DISABLE_SYNC, &a);
+
+
+ /*OK*/ //printf("Audio sync disable = %i\n", b);
+
+ return 1;
+
+
+}
+#endif
+
+void AudioOMX::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
+{
+ packet = mplist.front();
+}
+
+UINT AudioOMX::DeliverMediaSample(UCHAR* buffer, UINT* samplepos) {
+ DeliverMediaPacket(packet, buffer, samplepos);
+ if (*samplepos == packet.length) {
+ *samplepos = 0;
+ return 1;
+ } else
+ return 0;
+}
+
+
+long long AudioOMX::correctAudioLatency(long long pts,int addsamples,int srate) {
+
+ VideoOMX *video = (VideoOMX*) Video::getInstance();
+ video->LockClock();
+ OMX_PARAM_U32TYPE audio_lat;
+ OMX_ERRORTYPE error;
+ memset(&audio_lat, 0, sizeof(audio_lat));
+ audio_lat.nSize = sizeof(audio_lat);
+ audio_lat.nVersion.nVersion = OMX_VERSION;
+ audio_lat.nPortIndex = omx_rend_input_port;
+
+ error = OMX_GetConfig(omx_aud_rend, OMX_IndexConfigAudioRenderingLatency,
+ &audio_lat);
+ video->UnlockClock();
+ if (error != OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "Init OMX_IndexConfigAudioRenderingLatencyfailed %x %d", error,
+ omx_rend_input_port);
+ return pts; // no correction in case of error
+ }
+ /*Log::getInstance()->log("Audio", Log::DEBUG, "Current audio latency %d",
+ audio_lat.nU32);*/
+
+ long long workpts=0;
+ workpts+=addsamples;
+ workpts-=audio_lat.nU32;
+ workpts*=10LL*1000LL*1000LL;
+ workpts=workpts/((long long)srate); //one second /samplerate
+ workpts+=pts;
+
+ return workpts;
+}
+
+
+
+UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,
+ UINT *samplepos) {
+ /*First Check, if we have an audio sample*/
+ VideoOMX *vw = (VideoOMX*) Video::getInstance();
+ bool achange=false;
+ OMX_ERRORTYPE error;
+ Log *logger=Log::getInstance();
+ if (vw->InIframemode()) {
+ samplepos = 0;
+ MILLISLEEP(10);
+ return 0; //Not in iframe mode!
+ }
+
+ if (!omx_running) return 0; // if we are not runnig do not do this
+ if (paused) return 0; //Block if we pause
+
+ UINT headerstrip = 0;
+ if (packet.disconti) {
+ firstsynched = false;
+ if (cur_input_buf_omx) {
+ OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/,
+ cur_input_buf_omx);
+ if (error != OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "OMX_EmptyThisBuffer failed %x", error);
+ }
+ cur_input_buf_omx = NULL;
+ }
+ }
+
+ if (packet.type != lastAType) {//Format Change //Push data out !
+ firstsynched = false;
+ achange=true;
+ lastAType = packet.type;
+
+ if (cur_input_buf_omx) {
+ OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/,
+ cur_input_buf_omx);
+ if (error != OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "OMX_EmptyThisBuffer failed %x", error);
+ }
+ cur_input_buf_omx = NULL;
+ }
+ if (!ChangeAudioPortConfig()) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "Changing audio port config failed", error);
+ }
+
+ }
+
+ /*Inspect PES-Header */
+ if (*samplepos == 0 && packet.type != MPTYPE_MPEG_AUDIO_LAYER3) {//stripheader
+ headerstrip = buffer[packet.pos_buffer + 8] + 9;
+ if (packet.type == MPTYPE_AC3)
+ headerstrip += 4; //skip ac3 bytes
+ *samplepos += headerstrip;
+ if (packet.synched) {
+ if (cur_input_buf_omx) {
+ cur_input_buf_omx->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
+ OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/,
+ cur_input_buf_omx);
+ if (error != OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "OMX_EmptyThisBuffer failed %x", error);
+ }
+ //FrameWaitforDisplay(lastreftimeOMX);
+ vw->AdjustAudioPTS(correctAudioLatency(lastreftimeOMX,cur_input_buf_omx->nFilledLen/(2*2),48000));
+
+ cur_input_buf_omx = NULL;//write out old data
+ }
+ 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("Audio", 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("Audio", 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("Audio", 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("Audio", Log::DEBUG,
+ "Time code %lld pts %lld dts %lld", lastreftimeOMX, packet.pts,packet.dts);
+ lastreftimePTS = packet.pts;
+ cur_input_buf_omx->nTimeStamp =0;// lastreftimeOMX; // the clock component is faulty;
+ } else {
+ // Log::getInstance()->log("Audio", Log::DEBUG,
+ // "packet NOT synched marker");
+ cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
+ cur_input_buf_omx->nTimeStamp = 0;
+
+ }
+ if (packet.disconti || achange) {
+ cur_input_buf_omx->nFlags |= OMX_BUFFERFLAG_DISCONTINUITY;
+ //mp23codec_context_libav->frame_size=-1;
+ //ac3codec_context_libav->frame_size=-1;
+ }
+
+ }
+
+ unsigned int haveToCopy=packet.length-*samplepos;
+ if (passthrough) {
+ //TODO
+ } else {
+ int len;
+ int gotta;
+ int framesize=0;
+ int errcount=0;
+
+ AVCodecContext *current_context;
+ switch (packet.type) {
+ case MPTYPE_MPEG_AUDIO:
+ case MPTYPE_MPEG_AUDIO_LAYER3: {
+ current_context = mp23codec_context_libav;
+ if (current_context->frame_size<0) framesize=1152; //Maximum framesize
+ else framesize=current_context->frame_size;
+ }break;
+ case MPTYPE_AC3:
+ case MPTYPE_AC3_PRE13: {
+ current_context = ac3codec_context_libav;
+ }break;
+ };
+
+ incoming_paket_libav.data =(uint8_t*) buffer+packet.pos_buffer+*samplepos;
+ incoming_paket_libav.size = haveToCopy;
+
+ 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;
+ haveToCopy -= len;
+ *samplepos += len;
+ errcount=0;
+ if (current_context->frame_size>0) framesize=min(current_context->frame_size,haveToCopy);
+ else framesize=haveToCopy;
+ } else {
+ errcount++;
+ framesize=haveToCopy;
+ }
+
+ incoming_paket_libav.size =framesize;
+ if (gotta) {
+ //Log::getInstance()->log("Audio", Log::DEBUG,
+ // "Got a frame");
+ int dsize = av_samples_get_buffer_size(NULL,
+ current_context->channels, decode_frame_libav->nb_samples,
+ current_context->sample_fmt, 1);
+ if ((cur_input_buf_omx->nFilledLen + dsize)
+ > cur_input_buf_omx->nAllocLen ) {
+ // I doubt that this will ever happen
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "P 2 Time code %lld pts %lld", lastreftimeOMX, packet.pts);
+ OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/,
+ cur_input_buf_omx);
+ if (error != OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "OMX_EmptyThisBuffer failed %x", error);
+ }
+ cur_input_buf_omx = NULL;
+
+ if (!cur_input_buf_omx) {
+ int count = 0;
+ while (count < 10 && omx_running) {
+ count++;
+ input_bufs_omx_mutex.Lock();
+ if (input_bufs_omx_free.size() == 0) {
+ input_bufs_omx_mutex.Unlock();
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "Deliver MediaPacket no free sample");
+ MILLISLEEP(5);
+ if (!omx_running) return 0;
+ 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 *samplepos;
+ }
+
+ }
+
+ //Log::getInstance()->log("Audio", Log::DEBUG,"memcpy in %d %d %d" ,dsize,current_context->sample_rate,cur_input_buf_omx->nFilledLen);
+ memcpy(cur_input_buf_omx->pBuffer + cur_input_buf_omx->nFilledLen,
+ decode_frame_libav->data[0], dsize);
+ //Log::getInstance()->log("Audio", Log::DEBUG,"memcpy out");
+ cur_input_buf_omx->nFilledLen += dsize;
+ } else {
+ //Log::getInstance()->log("Audio", Log::DEBUG,"Incomplete mpeg frames in pes packet %d",incoming_paket_libav.size);
+ }
+
+ }
+
+ }
+
+ if (cur_input_buf_omx->nFilledLen) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "P 3 Time code %lld pts %lld", lastreftimeOMX, packet.pts);
+ error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/, cur_input_buf_omx);
+ if (error != OMX_ErrorNone) {
+ Log::getInstance()->log("Audio", Log::DEBUG,
+ "OMX_EmptyThisBuffer failed %x", error);
+ }
+ if (packet.synched) vw->AdjustAudioPTS(correctAudioLatency(lastreftimeOMX,cur_input_buf_omx->nFilledLen/(2*2),48000));
+ cur_input_buf_omx = NULL;
+ }
+
+
+
+ *samplepos=packet.length;
+ return packet.length;
+
+}
+
+
+
+long long AudioOMX::SetStartOffset(long long curreftime, bool *rsync){
+ VideoOMX *vw=(VideoOMX*)Video::getInstance();
+ return vw->SetStartAudioOffset(curreftime,rsync);
+}
+
+void AudioOMX::ResetTimeOffsets() {
+ VideoOMX *vw=(VideoOMX*)Video::getInstance();
+ vw->ResetTimeOffsets();
+}
+
+
--- /dev/null
+/*\r
+ Copyright 2004-2005 Chris Tallon, 2009,2012 Marten Richter\r
+\r
+ This file is part of VOMP.\r
+\r
+ VOMP is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ VOMP is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with VOMP; if not, write to the Free Software\r
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+*/\r
+\r
+#ifndef AUDIOOMX_H\r
+#define AUDIOOMX_H\r
+\r
+#include <stdio.h>\r
+#include <unistd.h>\r
+#include <fcntl.h>\r
+#include <sys/ioctl.h>\r
+\r
+#include "defines.h"\r
+#include "audio.h"\r
+#include "videoomx.h"\r
+\r
+extern "C" {\r
+#include <libavcodec/avcodec.h>\r
+#include <libavformat/avformat.h>\r
+}\r
+\r
+\r
+\r
+\r
+class AudioOMX : public Audio\r
+{\r
+ public:\r
+ AudioOMX();\r
+ virtual ~AudioOMX();\r
+\r
+ int init(UCHAR streamType);\r
+ int shutdown();\r
+\r
+ int setStreamType(UCHAR streamType);\r
+ int setChannel();\r
+ int setSource();\r
+ int sync();\r
+ int play();\r
+ int stop();\r
+ int pause();\r
+ int unPause();\r
+ int reset();\r
+ int setVolume(int volume);\r
+ int mute();\r
+ int unMute();\r
+ bool supportsAc3() { return true; }\r
+ virtual bool maysupportAc3(){return true;}\r
+\r
+ //Writing Data to Audiodevice\r
+ virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);\r
+ virtual UINT DeliverMediaSample(UCHAR* buffer, UINT *samplepos);\r
+ UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,UINT *samplepos);\r
+\r
+ virtual long long SetStartOffset(long long curreftime, bool *rsync);\r
+ virtual void ResetTimeOffsets();\r
+\r
+ virtual bool DrainTargetReady() {return omx_running;};\r
+\r
+\r
+ UCHAR getLastAType() {return lastAType;}\r
+\r
+ bool loadOptionsfromServer(VDR* vdr);\r
+ bool saveOptionstoServer();\r
+ bool addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane);\r
+ bool handleOptionChanges(Option* option);\r
+\r
+\r
+#ifdef DEV\r
+ int test();\r
+#endif\r
+\r
+ private:\r
+ int initAllParams();\r
+ UCHAR streamType;\r
+ UCHAR lastAType;\r
+ bool firstsynched;\r
+\r
+ MediaPacket packet;\r
+ UINT packetpos;\r
+\r
+ bool paused;\r
+\r
+ bool hdmi; // use hdmi as audio output\r
+ bool passthrough; // use audio passthrough for the current audio type\r
+\r
+ bool canpass_ac3;\r
+ bool canpass_mp2;\r
+ bool canpass_mp3;\r
+ bool canpass_pcm_mch;\r
+\r
+\r
+ int prefered_ac3; //0 stereo PCM, 1 passthrough 2 Multichannel PCM\r
+ int prefered_mp2;\r
+ int prefered_mp3;\r
+\r
+\r
+\r
+ static OMX_ERRORTYPE EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver);\r
+ static OMX_ERRORTYPE FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver);\r
+\r
+\r
+\r
+ void ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* bulibaver);\r
+\r
+ // OMX_HANDLETYPE omx_aud_dec;\r
+ OMX_HANDLETYPE omx_aud_rend;\r
+ OMX_HANDLETYPE omx_clock;\r
+\r
+ //OMX_U32 omx_codec_input_port;\r
+ //OMX_U32 omx_codec_output_port;\r
+ OMX_U32 omx_rend_input_port;\r
+ OMX_U32 omx_rend_clock_port;\r
+ OMX_U32 omx_clock_output_port;\r
+\r
+ OMX_TICKS lastreftimeOMX;\r
+ ULLONG lastreftimePTS;\r
+\r
+\r
+\r
+ int AllocateCodecsOMX();\r
+ int DeAllocateCodecsOMX();\r
+\r
+ int PrepareInputBufsOMX();\r
+ int DestroyInputBufsOMX();\r
+\r
+ int ChangeAudioPortConfig();\r
+ int ChangeAudioDestination();\r
+ long long correctAudioLatency(long long pts,int addsamples,int srate);\r
+\r
+ vector<OMX_BUFFERHEADERTYPE*> input_bufs_omx_all;\r
+ list<OMX_BUFFERHEADERTYPE*> input_bufs_omx_free;\r
+ Mutex input_bufs_omx_mutex;\r
+ OMX_BUFFERHEADERTYPE* cur_input_buf_omx;\r
+\r
+ bool omx_running;\r
+ bool omx_first_frame;\r
+ Mutex libav_mutex;\r
+\r
+ AVCodec *ac3codec_libav;\r
+ AVCodecContext *ac3codec_context_libav;\r
+ AVCodec *mp23codec_libav;\r
+ AVCodecContext *mp23codec_context_libav;\r
+ AVPacket incoming_paket_libav;\r
+ AVFrame *decode_frame_libav;\r
+\r
+\r
+\r
+ int InitDecoderLibAV();\r
+ void DeinitDecoderLibAV();\r
+\r
+};\r
+\r
+#endif\r
+++ /dev/null
-/*
- 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 "audiovpe.h"
-#include "videovpeogl.h"
-#include "log.h"
-#include "vdr.h"
-#include "woptionpane.h"
-
-AudioVPE::AudioVPE()
-{
- initted = 0;
- streamType = 0;
- volume = 20;
- muted = 0;
- lastAType = MPTYPE_MPEG_AUDIO;
-
- canpass_ac3=false;
- canpass_mp2=false;
- canpass_mp3=false;
- canpass_pcm_mch=false;
-
- prefered_ac3=0; //0 stereo PCM, 1 passthrough 2 Multichannel PCM
- prefered_mp2=0;
- prefered_mp3=0;
- hdmi=true;
-
- omx_running=false;
-
- omx_aud_rend/*dec*/=0;
- cur_input_buf_omx=NULL;
-
- ac3codec_libav=NULL;
- ac3codec_context_libav=NULL;
-
- mp23codec_libav=NULL;
- mp23codec_context_libav=NULL;
-
-}
-
-AudioVPE::~AudioVPE()
-{
-}
-
-int AudioVPE::init(UCHAR tstreamType) {
- if (initted)
- return 0;
- initted = 1;
-
- streamType = tstreamType;
-
- if (!initAllParams()) {
- shutdown();
- return 0;
- }
-
- unMute();
-
-
-
- av_register_all();
- av_log_set_flags(AV_LOG_SKIP_REPEATED);
-
- ac3codec_libav = avcodec_find_decoder(CODEC_ID_AC3);
- if (ac3codec_libav == NULL) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "Find libav ac3 decoder failed");
- return 0;
- }
-
- mp23codec_libav = avcodec_find_decoder(CODEC_ID_MP3);
- if (mp23codec_libav == NULL) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "Find libav mpeg audio decoder failed");
- return 0;
- }
-
- return 1;
-}
-
-int AudioVPE::initAllParams()
-{
- return (setStreamType(streamType) && setChannel() && setSource());
-}
-
-int AudioVPE::shutdown()
-{
- if (!initted) return 0;
- initted = 0;
-
- Log::getInstance()->log("Audio", Log::DEBUG, "audio shutdown called");
- DeAllocateCodecsOMX();
-
- return 1;
-}
-
-bool AudioVPE::loadOptionsfromServer(VDR* vdr)
-{
- Log::getInstance()->log("Audio", Log::DEBUG, "AudioOMX config load");
- char *name=vdr->configLoad("AudioOMX","AC3DecodingMode");
-
- if (name != NULL) {
- if (STRCASECMP(name, "PCM") == 0) {
- prefered_ac3 = 0;
- } else if (STRCASECMP(name, "Passthrough") == 0) {
- prefered_ac3 = 1;
- } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
- prefered_ac3 = 2;
- }
- }
-
- name = vdr->configLoad("AudioOMX", "Mp2DecodingMode");
-
- if (name != NULL) {
- if (STRCASECMP(name, "PCM") == 0) {
- prefered_mp2 = 0;
- } else if (STRCASECMP(name, "Passthrough") == 0) {
- prefered_mp2 = 1;
- } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
- prefered_mp2 = 2;
- }
- }
-
- name = vdr->configLoad("AudioOMX", "Mp3DecodingMode");
-
- if (name != NULL) {
- if (STRCASECMP(name, "PCM") == 0) {
- prefered_mp3 = 0;
- } else if (STRCASECMP(name, "Passthrough") == 0) {
- prefered_mp3 = 1;
- } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
- prefered_mp3 = 2;
- }
- }
-
- name = vdr->configLoad("AudioOMX", "AudioOutput");
-
- if (name != NULL) {
- if (STRCASECMP(name, "analog") == 0) {
- hdmi = false;
- } else if (STRCASECMP(name, "HDMI") == 0) {
- hdmi = true;
- }
- }
-
-
- return true;
-
-}
-
-bool AudioVPE::handleOptionChanges(Option* option)
-{
- if (Audio::handleOptionChanges(option))
- return true;
- switch (option->id) {
- case 4: {
- if (STRCASECMP(option->options[option->userSetChoice], "analog") == 0) {
- hdmi = false;
- } else if (STRCASECMP(option->options[option->userSetChoice], "HDMI")
- == 0) {
- hdmi = true;
- }
- return true;
- }
- break;
- case 1: {
- if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
- prefered_ac3 = 0;
- } else if (STRCASECMP(option->options[option->userSetChoice],
- "Passthrough") == 0) {
- prefered_ac3 = 1;
- } else if (STRCASECMP(option->options[option->userSetChoice],
- "PCMMultichannel") == 0) {
- prefered_ac3 = 2;
- }
- }
- break;
- case 2: {
- if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
- prefered_mp2 = 0;
- } else if (STRCASECMP(option->options[option->userSetChoice],
- "Passthrough") == 0) {
- prefered_mp2 = 1;
- } else if (STRCASECMP(option->options[option->userSetChoice],
- "PCMMultichannel") == 0) {
- prefered_mp2 = 2;
- }
- }
- break;
- case 3: {
- if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
- prefered_mp3 = 0;
- } else if (STRCASECMP(option->options[option->userSetChoice],
- "Passthrough") == 0) {
- prefered_mp3 = 1;
- } else if (STRCASECMP(option->options[option->userSetChoice],
- "PCMMultichannel") == 0) {
- prefered_mp3 = 2;
- }
- }
- break;
- };
- return false;
-
-}
-
-bool AudioVPE::saveOptionstoServer()
-{
-
- switch (prefered_ac3) {
- case 0:
- VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode", "PCM");
- break;
- case 1:
- VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode",
- "Passthrough");
- break;
- case 2:
- VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode",
- "PCMMultichannel");
- break;
- };
-
- switch (prefered_mp2) {
- case 0:
- VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode", "PCM");
- break;
- case 1:
- VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode",
- "Passthrough");
- break;
- case 2:
- VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode",
- "PCMMultichannel");
- break;
- };
-
- switch (prefered_mp3) {
- case 0:
- VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode", "PCM");
- break;
- case 1:
- VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode",
- "Passthrough");
- break;
- case 2:
- VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode",
- "PCMMultichannel");
- break;
- };
-
- if (!hdmi)
- VDR::getInstance()->configSave("AudioOMX", "AudioOutput", "analog");
- else
- VDR::getInstance()->configSave("AudioOMX", "AudioOutput", "HDMI");
-
-
- return true;
-}
-
-/*Option(UINT id, const char* displayText, const char* configSection, const char* configKey, UINT optionType,
- UINT numChoices, UINT defaultChoice, UINT startInt,
- const char * const * options, const char * const * optionkeys = NULL, AbstractOption* handler=NULL);*/
-
-bool AudioVPE::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
-{
- if (!Audio::addOptionsToPanes(panenumber,options,pane)) return false;
-
-
- Option* option;
- if (panenumber == 2)
- {
-
- static const char* audioopts[]={"analog","HDMI"};
- option = new Option(4,tr("Audio Output"), "AudioOMX","AudioOutput",Option::TYPE_TEXT,2,0,0,audioopts,NULL,false,this);
- options->push_back(option);
- pane->addOptionLine(option);
-
-
- char **ac3opts=new char *[3];
- int i=0;
- ac3opts[i]=new char[strlen("PCM")+1];
- strcpy(ac3opts[i],"PCM");
- i++;
- if (canpass_ac3) {
- ac3opts[i]=new char[strlen("Passthrough")+1];
- strcpy(ac3opts[i],"PassThrough");
- i++;
- }
- if (canpass_pcm_mch) {
- ac3opts[i]=new char[strlen("PCMMultichannel")+1];
- strcpy(ac3opts[i],"PCMMultichannel");
- i++;
- }
- option = new Option(1 ,tr("AC3 HDMI Mode"), "AudioOMX", "AC3DecodingMode", Option::TYPE_TEXT, i, 0, 0, ac3opts,NULL,true, this);
- options->push_back(option);
- pane->addOptionLine(option);
-
- char **mp2opts = new char *[3];
- i = 0;
- mp2opts[i] = new char[strlen("PCM") + 1];
- strcpy(mp2opts[i], "PCM");
- i++;
- if (canpass_mp2) {
- mp2opts[i] = new char[strlen("Passthrough") + 1];
- strcpy(mp2opts[i], "PassThrough");
- i++;
- }
- if (canpass_pcm_mch) {
- mp2opts[i] = new char[strlen("PCMMultichannel") + 1];
- strcpy(mp2opts[i], "PCMMultichannel");
- i++;
- }
- option = new Option(2, tr("Mp2 HDMI Mode"), "AudioOMX",
- "Mp2DecodingMode", Option::TYPE_TEXT, i, 0, 0,
- mp2opts, NULL, true, this);
- options->push_back(option);
- pane->addOptionLine(option);
-
- char **mp3opts = new char *[3];
- i = 0;
- mp3opts[i] = new char[strlen("PCM") + 1];
- strcpy(mp3opts[i], "PCM");
- i++;
- if (canpass_mp3) {
- mp3opts[i] = new char[strlen("Passthrough") + 1];
- strcpy(mp3opts[i], "PassThrough");
- i++;
- }
- if (canpass_pcm_mch) {
- mp3opts[i] = new char[strlen("PCMMultichannel") + 1];
- strcpy(mp3opts[i], "PCMMultichannel");
- i++;
- }
- option = new Option(3, tr("Mp3 HDMI Mode"), "AudioOMX",
- "Mp2DecodingMode", Option::TYPE_TEXT, i, 0, 0, mp3opts,
- NULL, true, this);
- options->push_back(option);
- pane->addOptionLine(option);
-
-
- }
-
- return true;
-}
-
-
-
-
-
-
-OMX_ERRORTYPE AudioVPE::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();
- audio->ReturnEmptyOMXBuffer(buffer);
- return OMX_ErrorNone;
-
-}
-
-void AudioVPE::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);
- //Log::getInstance()->log("Audio", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size());
- 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) {
- Log::getInstance()->log("Audio", Log::NOTICE, "FillBufferDone");
- return OMX_ErrorNone;
-}
-
-
-
-int AudioVPE::setStreamType(UCHAR type)
-{
- if (!initted) return 0;
-
- // if (ioctl(fdAudio, AV_SET_AUD_STREAMTYPE, type) != 0) return 0;
- return 1;
-}
-
-int AudioVPE::setChannel()
-{
- if (!initted) return 0;
-
- // if (ioctl(fdAudio, AV_SET_AUD_CHANNEL, 0) != 0) return 0;
- return 1;
-}
-
-int AudioVPE::setSource()
-{
- if (!initted) return 0;
-
- // if (ioctl(fdAudio, AV_SET_AUD_SRC, 1) != 0) return 0;
- return 1;
-}
-
-int AudioVPE::sync()
-{
- if (!initted) return 0;
-
- // if (ioctl(fdAudio, AV_SET_AUD_SYNC, 2) != 0) return 0;
- return 1;
-}
-
-int AudioVPE::play() {
- if (!initted)
- return 0;
- lastAType=MPTYPE_MPEG_AUDIO;
- Log::getInstance()->log("Audio", Log::DEBUG, "enter play");
-
- if (!AllocateCodecsOMX()) {
- return 0;
- }
- return 1;
-}
-
-
-int AudioVPE::ChangeAudioDestination() //clock aka omx mutex needs to be locked
-{
- OMX_ERRORTYPE error;
- const char * destinations[]={"local","hdmi"};
- int dest=0;
- if (hdmi) dest=1;
- else dest=0;
-
- OMX_CONFIG_BRCMAUDIODESTINATIONTYPE auddest;
- memset(&auddest,0,sizeof(auddest));
- auddest.nSize=sizeof(auddest);
- auddest.nVersion.nVersion=OMX_VERSION;
- strcpy((char *)auddest.sName, destinations[dest]);
-
- Log::getInstance()->log("Audio", Log::DEBUG, "setting destination to: %s",auddest.sName);
- error=OMX_SetConfig(omx_aud_rend,OMX_IndexConfigBrcmAudioDestination,&auddest);
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Audio", Log::DEBUG, "Init OMX_IndexConfigBrcmAudioDestination failed %x %x %s", error,omx_aud_rend,auddest.sName);
- DeAllocateCodecsOMX();
- return 0;
- }
- return 1;
-
-
-}
-
-int AudioVPE::ChangeAudioPortConfig() //clock aka omx mutex needs to be locked
-{
- OMX_ERRORTYPE error;
- //Ok first fidle a working configuration
- Log::getInstance()->log("Audio", Log::DEBUG,
- "ChangeAudioPortConfig");
-
- if (hdmi) {
- switch (lastAType) {
- case MPTYPE_MPEG_AUDIO: {
- if (prefered_mp2 == 3 && false) { //not supported yet
-
- } else {
- if (prefered_mp2 == 2 && canpass_mp2) {
- passthrough = true;
- } else
- passthrough = false;
- }
- }
- break;
- case MPTYPE_AC3_PRE13:
- case MPTYPE_AC3: {
- if (prefered_ac3 == 3 && false) { //not supported yet
-
- } else {
- if (prefered_ac3 == 2 && canpass_ac3) {
- passthrough = true;
- } else
- passthrough = false;
- }
- }
- break;
- case MPTYPE_MPEG_AUDIO_LAYER3: {
- if (prefered_mp3 == 3 && false) { //not supported yet
-
- } else {
- if (prefered_mp3 == 2 && canpass_mp2) {
- passthrough = true;
- } else
- passthrough = false;
- }
- }
- break;
- };
- } else {
- passthrough=false;
- //mch=false; // multichannel also false
- }
-
-
-
- /*OMX_CONFIG_BOOLEANTYPE booly;
- memset(&booly, 0, sizeof(booly));
- booly.nSize = sizeof(booly);
- booly.nVersion.nVersion = OMX_VERSION;
- if (passthrough)
- booly.bEnabled = OMX_TRUE;
- else
- booly.bEnabled = OMX_FALSE;
-
- error = OMX_SetParameter(omx_aud_dec, OMX_IndexParamBrcmDecoderPassThrough,
- &booly);
- if (error != OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "Init OMX_IndexParamBrcmDecoderPassThrough failed %x", error);
- DeAllocateCodecsOMX();
- return 0;
- }*/
- VideoVPEOGL *video=(VideoVPEOGL*)Video::getInstance();
-
-
- if (!omx_running) {
- if (passthrough) {
- // TODO coding
- } else {
-
- OMX_AUDIO_PARAM_PCMMODETYPE audio_pcm;
- memset(&audio_pcm, 0, sizeof(audio_pcm));
- audio_pcm.nSize = sizeof(audio_pcm);
- audio_pcm.nVersion.nVersion = OMX_VERSION;
- audio_pcm.nChannels = 2;
- audio_pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
- audio_pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
- //audio_pcm.eChannelMapping[2]=OMX_AUDIO_ChannelMax;
- audio_pcm.eNumData = OMX_NumericalDataSigned;
- audio_pcm.eEndian = OMX_EndianLittle;
- audio_pcm.bInterleaved = OMX_TRUE;
- audio_pcm.nBitPerSample = 16;
- audio_pcm.ePCMMode = OMX_AUDIO_PCMModeLinear;
- audio_pcm.nChannels = 2;
- audio_pcm.nSamplingRate = 48000;
- audio_pcm.nPortIndex = omx_rend_input_port;
- error = OMX_SetParameter(omx_aud_rend, OMX_IndexParamAudioPcm,
- &audio_pcm);
- if (error != OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "Init OMX_IndexParamAudioPcm failed %x %d", error,
- omx_rend_input_port);
- DeAllocateCodecsOMX();
- return 0;
- }
-
- }
- }
-
-
-
- return 1;
-
-
-
-}
-int AudioVPE::InitDecoderLibAV()
-{
- 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!");
- return 0;
- }
-
- ac3codec_context_libav->flags |= CODEC_FLAG_TRUNCATED;
- ac3codec_context_libav->request_channels=2;
-
- 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");
- 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!");
- return 0;
- }
-
- mp23codec_context_libav->flags |= CODEC_FLAG_TRUNCATED;
- mp23codec_context_libav->request_channels=2;
-
- 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");
- return 0;
- }
-
- av_init_packet(&incoming_paket_libav);
- decode_frame_libav=avcodec_alloc_frame();
-
-
-
- return 1;
-}
-
-void AudioVPE::DeinitDecoderLibAV() {
-
-
- if (ac3codec_context_libav) {
- avcodec_close(ac3codec_context_libav);
- av_free(ac3codec_context_libav);
- ac3codec_context_libav = NULL;
- av_free(decode_frame_libav);
-
- }
-
-}
-
-
-int AudioVPE::AllocateCodecsOMX()
-{
- OMX_ERRORTYPE error;
- static OMX_CALLBACKTYPE callbacks= {&VideoVPEOGL::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();
-
- if (!InitDecoderLibAV()) 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;
-
-
- if (!video->getClockAudioandInit(&omx_clock,&omx_clock_output_port)){
- return 0;// get the clock and init it if necessary
- }
-
- /* TODO end */
- if (!video->idleClock()) {
- return 0;
- }
- video->LockClock();
-
- error = OMX_GetHandle(&omx_aud_rend, VPE_OMX_AUDIO_REND, NULL, &callbacks);
- if (error != OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "Init OMX audio rend failed %x", error);
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
-
- if (!ChangeAudioDestination()) {
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
-
- error = OMX_GetParameter(omx_aud_rend, OMX_IndexParamAudioInit, &p_param);
- if (error != OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "Init OMX audio rend OMX_GetParameter failed %x", error);
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
- omx_rend_input_port = p_param.nStartPortNumber;
-
- error = OMX_GetParameter(omx_aud_rend, OMX_IndexParamOtherInit, &p_param);
- if (error != OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "Init OMX aud rend OMX_GetParameter failed %x", error);
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
- // buggy return value
- omx_rend_clock_port = p_param.nStartPortNumber;
-
-
-/* error=OMX_GetHandle(&omx_aud_dec,VPE_OMX_AUDIO_DECODER,NULL,&callbacks);
-
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Audio", Log::DEBUG, "Init OMX audio decoder failed %x", error);
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
-
- error=OMX_GetParameter(omx_aud_dec,OMX_IndexParamAudioInit,&p_param);
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Audio", Log::DEBUG, "Init OMX audio decoder OMX_GetParameter failed %x", error);
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
- omx_codec_input_port=p_param.nStartPortNumber;
- omx_codec_output_port=p_param.nStartPortNumber+1;
-
- if (!video->DisablePort(omx_aud_dec,omx_codec_input_port) || !video->DisablePort(omx_aud_dec,omx_codec_output_port)) {
- Log::getInstance()->log("Audio", Log::DEBUG, "Disable Ports OMX audio decoder failed");
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }*/
-
-
-
-
- if (!video->DisablePort(omx_aud_rend,omx_rend_input_port,true) ) {
- Log::getInstance()->log("Audio", Log::DEBUG, "Disable Ports OMX audio rend failed %d",omx_rend_input_port);
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
-
- if ( !video->DisablePort(omx_aud_rend, omx_rend_clock_port, true)) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "Disable Ports OMX rend clock port failed %d",omx_rend_clock_port);
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
-
-
-
-
- //Setuo chain
-
-
- error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,omx_aud_rend,omx_rend_clock_port);
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Setup tunnel clock to rend failed %x %d %d", error,omx_clock_output_port,omx_rend_clock_port);
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
-
- if (!video->EnablePort(omx_clock,omx_clock_output_port,false) || !video->EnablePort(omx_aud_rend,omx_rend_clock_port,false)
- ) {
- Log::getInstance()->log("Audio", Log::DEBUG, "Enable Ports OMX clock rend failed");
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
-
- if (!video->ChangeComponentState(omx_aud_rend,OMX_StateIdle)) {
- Log::getInstance()->log("Audio", Log::DEBUG, "aud_rend idle ChangeComponentState");
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
-
-
-
-
- if ( !video->CommandFinished(omx_aud_rend,OMX_CommandPortEnable,omx_rend_clock_port)) {
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
-
- if ( !video->CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port)) {
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
-
-
-
- if (!ChangeAudioPortConfig()){
- Log::getInstance()->log("Audio", Log::NOTICE, "Change AudioPortConfig failed");
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
-
-/* if (!video->ChangeComponentState(omx_aud_dec,OMX_StateIdle)) {
- Log::getInstance()->log("Audio", Log::DEBUG, "aud_dec ChangeComponentState");
- DeAllocateCodecsOMX();
- return 0;
- }*/
-
-
-
- if (!PrepareInputBufsOMX()) {
- video->UnlockClock();
- 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("Audio", 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("Audio", 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_aud_rend,OMX_StateExecuting)) {
- Log::getInstance()->log("Audio", Log::DEBUG, "omx_aud_rend ChangeComponentState Execute");
- video->UnlockClock();
- DeAllocateCodecsOMX();
- return 0;
- }
-
-
- video->UnlockClock();
- paused=false;
- omx_running=true;
-
-
- if (!video->setClockExecutingandRunning()) return 0;
-
- Log::getInstance()->log("Audio", Log::NOTICE, "Allocate Codecs OMX finished");
-
- return 1;
-}
-
-
-
-
-int AudioVPE::PrepareInputBufsOMX() //needs to be called with locvke omx clock mutex
-{
- VideoVPEOGL *video=(VideoVPEOGL*)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_rend_input_port;//omx_codec_input_port;
-
- error=OMX_GetParameter(omx_aud_rend/*dec*/,OMX_IndexParamPortDefinition, &port_def_type);
-
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Audio", Log::DEBUG, "Get OMX OMX_IndexParamPortDefinition failed %x", error);
- }
-
-
- port_def_type.nBufferCountActual=2;
- port_def_type.nBufferSize=max(port_def_type.nBufferSize,50000); // for transcoder important
-
- error=OMX_SetParameter(omx_aud_rend/*dec*/,OMX_IndexParamPortDefinition, &port_def_type);
-
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Audio", Log::DEBUG, "Set OMX OMX_IndexParamPortDefinition failed %x", error);
- }
-
-
- error=OMX_SendCommand(omx_aud_rend/*dec*/,OMX_CommandPortEnable,omx_rend_input_port/*codec*/,0);
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Audio", 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_AllocateBuffer(omx_aud_rend/*dec*/,&buf_head,omx_rend_input_port/*codec*/,NULL,port_def_type.nBufferSize);
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Audio", 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();
-
- if (!video->CommandFinished(omx_aud_rend/*dec*/,OMX_CommandPortEnable,omx_rend_input_port /*codec*/)) {
- return 0;
- }
-
- return 1;
-}
-
-int AudioVPE::DestroyInputBufsOMX() //call with clock mutex locked
-{
- OMX_ERRORTYPE error;
-
- cur_input_buf_omx=NULL;
- input_bufs_omx_mutex.Lock();
- for (int i=0; i< input_bufs_omx_all.size();i++) {
- error=OMX_FreeBuffer(omx_aud_rend/*dec*/,omx_rend_input_port/*codec*/,input_bufs_omx_all[i]);
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Audio", 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 AudioVPE::DeAllocateCodecsOMX()
-{
- OMX_ERRORTYPE error;
- omx_running=false;
- VideoVPEOGL *video=(VideoVPEOGL*)Video::getInstance();
- Log::getInstance()->log("Audio", Log::DEBUG, "enter deallocatecodecsomx");
- DeinitDecoderLibAV();
-
- video->LockClock();
- if (cur_input_buf_omx) {
- cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_EOS;
- OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_aud_rend/*dec*/,cur_input_buf_omx);
- if (error!=OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error);
- }
-
- cur_input_buf_omx=NULL;//write out old data
- }
-
- if (omx_aud_rend/*dec*/) {
- // first stop the omx elements
- /* if (!video->ChangeComponentState(omx_aud_dec,OMX_StateIdle)) {
- Log::getInstance()->log("Audio", Log::DEBUG, "aud_dec ChangeComponentState");
- }*/
-
- video->UnlockClock();
- video->idleClock();
- video->LockClock();
-
- if (!video->ChangeComponentState(omx_aud_rend,OMX_StateIdle)) {
- Log::getInstance()->log("Audio", Log::DEBUG, "aud_rend ChangeComponentState");
- }
-
- // TODO proper deinit sequence
- // first flush all buffers
-
- error=OMX_SendCommand(omx_aud_rend,OMX_CommandFlush, omx_rend_input_port, NULL);
- if (error!=OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Flush rend in failed %x", error);
-
- }
-
- /* error=OMX_SendCommand(omx_aud_dec,OMX_CommandFlush, omx_codec_input_port, NULL);
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Flush codec out failed %x", error);
-
- }*/
-
-
- /* if (!video->CommandFinished(omx_aud_dec,OMX_CommandFlush,omx_codec_input_port)) {
- Log::getInstance()->log("Audio", Log::DEBUG, "flush cmd codec input failed");
- }*/
-
-
-
- error=OMX_SendCommand(omx_clock,OMX_CommandFlush, omx_clock_output_port, NULL);
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Flush clock out failed %x", error);
-
- }
-
- error=OMX_SendCommand(omx_aud_rend,OMX_CommandFlush, omx_rend_clock_port, NULL);
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Flush rend clock failed %x", error);
-
- }
-
- if (!video->CommandFinished(omx_clock,OMX_CommandFlush,omx_clock_output_port) ||
- !video->CommandFinished(omx_aud_rend,OMX_CommandFlush,omx_rend_clock_port)) {
- Log::getInstance()->log("Audio", Log::DEBUG, "flush cmd clock shed failed");
- }
-
- DestroyInputBufsOMX();
-
- //todo flushing
- if (!video->DisablePort(omx_aud_rend,omx_rend_input_port,true)) {
- Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 1");
- }
-
- /* if (!video->DisablePort(omx_aud_dec,omx_codec_output_port,true)) {
- Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 6");
- }
-
- if (!video->DisablePort(omx_aud_dec,omx_codec_input_port,true)) {
- Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 7");
- }*/
-
-
- if (!video->DisablePort(omx_aud_rend,omx_rend_clock_port,true)) {
- Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 4");
- }
-
- if (!video->DisablePort(omx_clock,omx_clock_output_port,true)) {
- Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 5");
- }
-
-
-
- /* error=OMX_SetupTunnel(omx_aud_dec,omx_codec_output_port,NULL,NULL);
- if (error!=OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
-
- }*/
-
-
-
- error=OMX_SetupTunnel(omx_aud_rend,omx_rend_input_port,NULL,NULL);
- if (error!=OMX_ErrorNone) {
- Log::getInstance()->log("Audio", 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("Audio", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
-
- }
-
- error=OMX_SetupTunnel(omx_aud_rend,omx_rend_clock_port,NULL,NULL);
- if (error!=OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
-
- }
-
-
- //error=OMX_FreeHandle(omx_aud_dec);
- error=OMX_FreeHandle(omx_aud_rend);
- video->UnlockClock();
- video->destroyClock();
- omx_aud_rend/*dec*/=NULL;
- if (error!=OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG, "FreeHandle failed %d", error);
- }
- } else video->UnlockClock();
- Log::getInstance()->log("Audio", Log::DEBUG, "leave deallocate codecs OMX");
-
- return 1;
-}
-
-
-
-int AudioVPE::stop()
-{
- if (!initted) return 0;
-
- Log::getInstance()->log("Audio", Log::DEBUG, "Audio stop called");
- DeAllocateCodecsOMX();
- //if (ioctl(fdAudio, AV_SET_AUD_RESET, 0x11) != 0) return 0;
- return 1;
-}
-
-int AudioVPE::mute()
-{
- if (!initted) return 0;
-
-// if (ioctl(fdAudio, AV_SET_AUD_MUTE, 1) != 0) return 0;
- Log::getInstance()->log("Audio", Log::DEBUG, "MUTE MUTE MUTE");
-
- muted = 1;
- return 1;
-}
-
-int AudioVPE::unMute()
-{
- if (!initted) return 0;
-
-// if (ioctl(fdAudio, AV_SET_AUD_MUTE, 0) != 0) return 0;
- Log::getInstance()->log("Audio", Log::DEBUG, "MUTE OFF OFF OFF");
-
- muted = 0;
- return 1;
-}
-
-int AudioVPE::pause() {
- if (!initted)
- return 0;
- if (!paused) {
- paused = true;
- VideoVPEOGL *vw = (VideoVPEOGL*) Video::getInstance();
- vw->LockClock();
- OMX_ERRORTYPE error;
- error = OMX_SendCommand(omx_aud_rend, OMX_CommandFlush,
- omx_rend_input_port, NULL);
- if (error != OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "OMX_Flush rend in failed %x", error);
-
- }
- vw->UnlockClock();
- vw->clockPause();
- }
- return 1;
-}
-
-int AudioVPE::unPause()
-{
- if (!initted) return 0;
- if (paused) {
- paused=false; // may be also change omx clock
- VideoVPEOGL *vw = (VideoVPEOGL*) Video::getInstance();
- vw->clockUnpause();
- }
- return 1;
-}
-
-int AudioVPE::reset()
-{
- if (!initted) return 0;
-//test();
- Log::getInstance()->log("Audio", Log::DEBUG, "reset called");
- DeAllocateCodecsOMX();
-
-// if (ioctl(fdAudio, AV_SET_AUD_RESET, 0x11) != 0) return 0;
-// Log::getInstance()->log("Audio", Log::DEBUG, "reset back");
- // if (ioctl(fdAudio, AV_SET_AUD_PLAY, 0) != 0) return 0;
-
- doMuting();
- return 1;
-}
-
-int AudioVPE::setVolume(int tvolume)
-{
- // parameter: 0 for silence, 20 for full
- if ((tvolume < 0) || (tvolume > 20)) return 0;
-
-// volume = 2 * (20 - volume);
-// Right, that one was rubbish... 0-10 were almost
-// inaudible, 11-20 did what should have been done
-// over the whole 0-20 range
-
- tvolume = 20 - tvolume;
-
- audio_volume Avolume;
- Avolume.frontleft = tvolume + Aoffset.frontleft;
- Avolume.frontright = tvolume + Aoffset.frontright;
- Avolume.rearleft = tvolume + Aoffset.rearleft;
- Avolume.rearright = tvolume + Aoffset.rearright;
- Avolume.center = tvolume + Aoffset.center;
- Avolume.lfe = tvolume + Aoffset.lfe;
-
-// if (ioctl(fdAudio, AV_SET_AUD_VOLUME, &Avolume) != 0) return 0;
-
-// unsigned long vol = (tvolume << 24) | (tvolume << 16);
-//
-// Log::getInstance()->log("Audio", Log::DEBUG, "%lx", vol);
-// Log::getInstance()->log("Audio", Log::DEBUG, "%i", tvolume);
-
-// if (ioctl(fdAudio, AV_SET_AUD_VOLUME, &vol) != 0) return 0;
- return 1;
-}
-
-#ifdef DEV
-int AudioVPE::test()
-{
-// ULLONG stc = 0;
-// return ioctl(fdAudio, AV_SET_AUD_STC, &stc);
-
-/* aud_sync_parms_t a;
- a.parm1 = 0;
- a.parm2 = 0;
-*/
-// int b = ioctl(fdAudio, AV_SET_AUD_DISABLE_SYNC, &a);
-
-
- /*OK*/ //printf("Audio sync disable = %i\n", b);
-
- return 1;
-
-
-}
-#endif
-
-void AudioVPE::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
-{
- packet = mplist.front();
-}
-
-UINT AudioVPE::DeliverMediaSample(UCHAR* buffer, UINT* samplepos) {
- DeliverMediaPacket(packet, buffer, samplepos);
- if (*samplepos == packet.length) {
- *samplepos = 0;
- return 1;
- } else
- return 0;
-}
-
-
-long long AudioVPE::correctAudioLatency(long long pts,int addsamples,int srate) {
-
- VideoVPEOGL *video = (VideoVPEOGL*) Video::getInstance();
- video->LockClock();
- OMX_PARAM_U32TYPE audio_lat;
- OMX_ERRORTYPE error;
- memset(&audio_lat, 0, sizeof(audio_lat));
- audio_lat.nSize = sizeof(audio_lat);
- audio_lat.nVersion.nVersion = OMX_VERSION;
- audio_lat.nPortIndex = omx_rend_input_port;
-
- error = OMX_GetConfig(omx_aud_rend, OMX_IndexConfigAudioRenderingLatency,
- &audio_lat);
- video->UnlockClock();
- if (error != OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "Init OMX_IndexConfigAudioRenderingLatencyfailed %x %d", error,
- omx_rend_input_port);
- return pts; // no correction in case of error
- }
- /*Log::getInstance()->log("Audio", Log::DEBUG, "Current audio latency %d",
- audio_lat.nU32);*/
-
- long long workpts=0;
- workpts+=addsamples;
- workpts-=audio_lat.nU32;
- workpts*=10LL*1000LL*1000LL;
- workpts=workpts/((long long)srate); //one second /samplerate
- workpts+=pts;
-
- return workpts;
-}
-
-
-
-UINT AudioVPE::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,
- UINT *samplepos) {
- /*First Check, if we have an audio sample*/
- VideoVPEOGL *vw = (VideoVPEOGL*) Video::getInstance();
- bool achange=false;
- OMX_ERRORTYPE error;
- Log *logger=Log::getInstance();
- if (vw->InIframemode()) {
- samplepos = 0;
- MILLISLEEP(10);
- return 0; //Not in iframe mode!
- }
-
- if (!omx_running) return 0; // if we are not runnig do not do this
- if (paused) return 0; //Block if we pause
-
- UINT headerstrip = 0;
- if (packet.disconti) {
- firstsynched = false;
- if (cur_input_buf_omx) {
- OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/,
- cur_input_buf_omx);
- if (error != OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "OMX_EmptyThisBuffer failed %x", error);
- }
- cur_input_buf_omx = NULL;
- }
- }
-
- if (packet.type != lastAType) {//Format Change //Push data out !
- firstsynched = false;
- achange=true;
- lastAType = packet.type;
-
- if (cur_input_buf_omx) {
- OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/,
- cur_input_buf_omx);
- if (error != OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "OMX_EmptyThisBuffer failed %x", error);
- }
- cur_input_buf_omx = NULL;
- }
- if (!ChangeAudioPortConfig()) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "Changing audio port config failed", error);
- }
-
- }
-
- /*Inspect PES-Header */
- if (*samplepos == 0 && packet.type != MPTYPE_MPEG_AUDIO_LAYER3) {//stripheader
- headerstrip = buffer[packet.pos_buffer + 8] + 9;
- if (packet.type == MPTYPE_AC3)
- headerstrip += 4; //skip ac3 bytes
- *samplepos += headerstrip;
- if (packet.synched) {
- if (cur_input_buf_omx) {
- cur_input_buf_omx->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
- OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/,
- cur_input_buf_omx);
- if (error != OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "OMX_EmptyThisBuffer failed %x", error);
- }
- //FrameWaitforDisplay(lastreftimeOMX);
- vw->AdjustAudioPTS(correctAudioLatency(lastreftimeOMX,cur_input_buf_omx->nFilledLen/(2*2),48000));
-
- cur_input_buf_omx = NULL;//write out old data
- }
- 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("Audio", 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("Audio", 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("Audio", 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("Audio", Log::DEBUG,
- "Time code %lld pts %lld dts %lld", lastreftimeOMX, packet.pts,packet.dts);
- lastreftimePTS = packet.pts;
- cur_input_buf_omx->nTimeStamp =0;// lastreftimeOMX; // the clock component is faulty;
- } else {
- // Log::getInstance()->log("Audio", Log::DEBUG,
- // "packet NOT synched marker");
- cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
- cur_input_buf_omx->nTimeStamp = 0;
-
- }
- if (packet.disconti || achange) {
- cur_input_buf_omx->nFlags |= OMX_BUFFERFLAG_DISCONTINUITY;
- //mp23codec_context_libav->frame_size=-1;
- //ac3codec_context_libav->frame_size=-1;
- }
-
- }
-
- unsigned int haveToCopy=packet.length-*samplepos;
- if (passthrough) {
- //TODO
- } else {
- int len;
- int gotta;
- int framesize=0;
- int errcount=0;
-
- AVCodecContext *current_context;
- switch (packet.type) {
- case MPTYPE_MPEG_AUDIO:
- case MPTYPE_MPEG_AUDIO_LAYER3: {
- current_context = mp23codec_context_libav;
- if (current_context->frame_size<0) framesize=1152; //Maximum framesize
- else framesize=current_context->frame_size;
- }break;
- case MPTYPE_AC3:
- case MPTYPE_AC3_PRE13: {
- current_context = ac3codec_context_libav;
- }break;
- };
-
- incoming_paket_libav.data =(uint8_t*) buffer+packet.pos_buffer+*samplepos;
- incoming_paket_libav.size = haveToCopy;
-
- while (haveToCopy> 0 && errcount<2) {
-
- //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 (len>0) {
- incoming_paket_libav.data += len;
- haveToCopy -= len;
- *samplepos += len;
- errcount=0;
- if (current_context->frame_size>0) framesize=min(current_context->frame_size,haveToCopy);
- else framesize=haveToCopy;
- } else {
- errcount++;
- framesize=haveToCopy;
- }
-
- incoming_paket_libav.size =framesize;
- if (gotta) {
- //Log::getInstance()->log("Audio", Log::DEBUG,
- // "Got a frame");
- int dsize = av_samples_get_buffer_size(NULL,
- current_context->channels, decode_frame_libav->nb_samples,
- current_context->sample_fmt, 1);
- if ((cur_input_buf_omx->nFilledLen + dsize)
- > cur_input_buf_omx->nAllocLen ) {
- // I doubt that this will ever happen
- Log::getInstance()->log("Audio", Log::DEBUG,
- "P 2 Time code %lld pts %lld", lastreftimeOMX, packet.pts);
- OMX_ERRORTYPE error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/,
- cur_input_buf_omx);
- if (error != OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "OMX_EmptyThisBuffer failed %x", error);
- }
- cur_input_buf_omx = NULL;
-
- if (!cur_input_buf_omx) {
- int count = 0;
- while (count < 10 && omx_running) {
- count++;
- input_bufs_omx_mutex.Lock();
- if (input_bufs_omx_free.size() == 0) {
- input_bufs_omx_mutex.Unlock();
- Log::getInstance()->log("Audio", Log::DEBUG,
- "Deliver MediaPacket 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 *samplepos;
- }
-
- }
-
- //Log::getInstance()->log("Audio", Log::DEBUG,"memcpy in %d %d %d" ,dsize,current_context->sample_rate,cur_input_buf_omx->nFilledLen);
- memcpy(cur_input_buf_omx->pBuffer + cur_input_buf_omx->nFilledLen,
- decode_frame_libav->data[0], dsize);
- //Log::getInstance()->log("Audio", Log::DEBUG,"memcpy out");
- cur_input_buf_omx->nFilledLen += dsize;
- } else {
- //Log::getInstance()->log("Audio", Log::DEBUG,"Incomplete mpeg frames in pes packet %d",incoming_paket_libav.size);
- }
-
- }
-
- }
-
- if (cur_input_buf_omx->nFilledLen) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "P 3 Time code %lld pts %lld", lastreftimeOMX, packet.pts);
- error = OMX_EmptyThisBuffer(omx_aud_rend/*dec*/, cur_input_buf_omx);
- if (error != OMX_ErrorNone) {
- Log::getInstance()->log("Audio", Log::DEBUG,
- "OMX_EmptyThisBuffer failed %x", error);
- }
- if (packet.synched) vw->AdjustAudioPTS(correctAudioLatency(lastreftimeOMX,cur_input_buf_omx->nFilledLen/(2*2),48000));
- cur_input_buf_omx = NULL;
- }
-
-
-
- *samplepos=packet.length;
- return packet.length;
-
-}
-
-
-
-long long AudioVPE::SetStartOffset(long long curreftime, bool *rsync){
- VideoVPEOGL *vw=(VideoVPEOGL*)Video::getInstance();
- return vw->SetStartAudioOffset(curreftime,rsync);
-}
-
-void AudioVPE::ResetTimeOffsets() {
- VideoVPEOGL *vw=(VideoVPEOGL*)Video::getInstance();
- vw->ResetTimeOffsets();
-}
-
-
+++ /dev/null
-/*\r
- Copyright 2004-2005 Chris Tallon, 2009 Marten Richter\r
-\r
- This file is part of VOMP.\r
-\r
- VOMP is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; either version 2 of the License, or\r
- (at your option) any later version.\r
-\r
- VOMP is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with VOMP; if not, write to the Free Software\r
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
-*/\r
-\r
-#ifndef AUDIOVPE_H\r
-#define AUDIOVPE_H\r
-\r
-#include <stdio.h>\r
-#include <unistd.h>\r
-#include <fcntl.h>\r
-#include <sys/ioctl.h>\r
-\r
-#include "defines.h"\r
-#include "audio.h"\r
-#include "videovpeogl.h"\r
-\r
-extern "C" {\r
-#include <libavcodec/avcodec.h>\r
-#include <libavformat/avformat.h>\r
-}\r
-\r
-\r
-\r
-\r
-class AudioVPE : public Audio\r
-{\r
- public:\r
- AudioVPE();\r
- virtual ~AudioVPE();\r
-\r
- int init(UCHAR streamType);\r
- int shutdown();\r
-\r
- int setStreamType(UCHAR streamType);\r
- int setChannel();\r
- int setSource();\r
- int sync();\r
- int play();\r
- int stop();\r
- int pause();\r
- int unPause();\r
- int reset();\r
- int setVolume(int volume);\r
- int mute();\r
- int unMute();\r
- bool supportsAc3() { return true; }\r
- virtual bool maysupportAc3(){return true;}\r
-\r
- //Writing Data to Audiodevice\r
- virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);\r
- virtual UINT DeliverMediaSample(UCHAR* buffer, UINT *samplepos);\r
- UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,UINT *samplepos);\r
-\r
- virtual long long SetStartOffset(long long curreftime, bool *rsync);\r
- virtual void ResetTimeOffsets();\r
-\r
-\r
- UCHAR getLastAType() {return lastAType;}\r
-\r
- bool loadOptionsfromServer(VDR* vdr);\r
- bool saveOptionstoServer();\r
- bool addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane);\r
- bool handleOptionChanges(Option* option);\r
-\r
-\r
-#ifdef DEV\r
- int test();\r
-#endif\r
-\r
- private:\r
- int initAllParams();\r
- UCHAR streamType;\r
- UCHAR lastAType;\r
- bool firstsynched;\r
-\r
- MediaPacket packet;\r
- UINT packetpos;\r
-\r
- bool paused;\r
-\r
- bool hdmi; // use hdmi as audio output\r
- bool passthrough; // use audio passthrough for the current audio type\r
-\r
- bool canpass_ac3;\r
- bool canpass_mp2;\r
- bool canpass_mp3;\r
- bool canpass_pcm_mch;\r
-\r
-\r
- int prefered_ac3; //0 stereo PCM, 1 passthrough 2 Multichannel PCM\r
- int prefered_mp2;\r
- int prefered_mp3;\r
-\r
-\r
-\r
- static OMX_ERRORTYPE EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver);\r
- static OMX_ERRORTYPE FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver);\r
-\r
-\r
-\r
- void ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* bulibaver);\r
-\r
- // OMX_HANDLETYPE omx_aud_dec;\r
- OMX_HANDLETYPE omx_aud_rend;\r
- OMX_HANDLETYPE omx_clock;\r
-\r
- //OMX_U32 omx_codec_input_port;\r
- //OMX_U32 omx_codec_output_port;\r
- OMX_U32 omx_rend_input_port;\r
- OMX_U32 omx_rend_clock_port;\r
- OMX_U32 omx_clock_output_port;\r
-\r
- OMX_TICKS lastreftimeOMX;\r
- ULLONG lastreftimePTS;\r
-\r
-\r
-\r
- int AllocateCodecsOMX();\r
- int DeAllocateCodecsOMX();\r
-\r
- int PrepareInputBufsOMX();\r
- int DestroyInputBufsOMX();\r
-\r
- int ChangeAudioPortConfig();\r
- int ChangeAudioDestination();\r
- long long correctAudioLatency(long long pts,int addsamples,int srate);\r
-\r
- vector<OMX_BUFFERHEADERTYPE*> input_bufs_omx_all;\r
- list<OMX_BUFFERHEADERTYPE*> input_bufs_omx_free;\r
- Mutex input_bufs_omx_mutex;\r
- OMX_BUFFERHEADERTYPE* cur_input_buf_omx;\r
-\r
- bool omx_running;\r
- bool omx_first_frame;\r
-\r
- AVCodec *ac3codec_libav;\r
- AVCodecContext *ac3codec_context_libav;\r
- AVCodec *mp23codec_libav;\r
- AVCodecContext *mp23codec_context_libav;\r
- AVPacket incoming_paket_libav;\r
- AVFrame *decode_frame_libav;\r
-\r
-\r
- int InitDecoderLibAV();\r
- void DeinitDecoderLibAV();\r
-\r
-};\r
-\r
-#endif\r
#define Led_TYPE LedRaspberry //this is device dependent\r
#define Osd_TYPE OsdOpenGL // This OpenGL ES 2.0, in the moment only for raspberry, but might be splitted for other devices\r
#define OsdStartDev ""\r
- #define Audio_TYPE AudioVPE // This is Audio based on VPE (Vomp Presentation Engine) should support OpenMax and libav for decoding\r
- #define Video_TYPE VideoVPEOGL // This is Video based on VPE (Vomp Presentation Engine) should support OpenMax\r
+ #define Audio_TYPE AudioOMX // This is Audio based on OpenMax and libav for decoding\r
+ #define Video_TYPE VideoOMX // This is Video based on OpenMax\r
\r
\r
\r
virtual long long SetStartOffset(long long curreftime, bool *rsync)=0;\r
virtual void ResetTimeOffsets()=0;\r
\r
+ virtual bool DrainTargetReady() {return false;}; //if the draintarget is blocking in paused state, this tells that it is ready to rumble\r
+\r
virtual bool dtsTimefix(){return false;} //determines if the draintargets needs a mixure of pts and dts or not\r
\r
// The following two functions are used by the Stream\r
+++ /dev/null
-/*\r
- Copyright 2012 Marten Richter\r
-\r
- This file is part of VOMP.\r
-\r
- VOMP is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; either version 2 of the License, or\r
- (at your option) any later version.\r
-\r
- VOMP is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with VOMP; if not, write to the Free Software\r
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
-*/\r
-#include "glmocoshader.h"\r
-#include "videovpeogl.h"\r
-\r
-#define BLOCK_TEXTURE_WIDTH 2048\r
-#define BLOCK_TEXTURE_HEIGHT 1024\r
-#define BLOCK_SIZE 64\r
-#define BLOCK_PER_ROW (32)\r
-\r
-// This implementation is for framed coded pictures only!\r
-// I did not find any DVB recording with field coded pictures\r
-// so I do not think they exist here, anyway I suspect we\r
-// need a totally different shader in this case\r
-// so first write the frame coded shader\r
-// and then later add if necessary field based support.\r
-\r
-const GLchar moco_vertex_shader[] =\r
- "attribute vec4 block_pos;\n"\r
- "attribute vec2 block_edge;\n"\r
- "attribute vec4 block_types;\n"\r
- "attribute vec2 index;\n"\r
- "attribute vec4 PMV1;\n"\r
- "attribute vec4 PMV2;\n"\r
- "attribute float cbp;\n"\r
- "uniform vec2 pict_scale;\n"\r
- // "attribute vec2 tex_coord;\n"\r
- "varying vec4 out_yblockpos_x;\n"\r
- "varying vec4 out_yblockpos_y;\n"\r
- "varying vec4 out_uvblockpos_xy;\n"\r
- "varying vec2 out_block_edge;\n"\r
- "varying vec4 out_misc_info;\n"\r
-\r
- "varying float out_unsupported;\n"\r
- "varying vec4 out_moco_pos;\n"\r
- "varying vec4 out_moco_forward;\n"\r
- "varying vec4 out_moco_backward;\n"\r
-\r
-\r
- "const float one=1.0;\n"\r
- "const float czero=0.0;\n"\r
- "const float chalf=0.5;\n"\r
- "const float c1024=1024.0;\n"\r
- "const float c32=32.0;\n"\r
- // "const float c1over32=0.03125;\n"\r
- "const float c1over32=1./32.;\n"\r
-\r
-\r
- "const float c65536=65536.;\n"\r
-\r
-\r
-\r
- "const vec4 y_cbp=vec4(1.0,2.0,4.0,8.0);\n"\r
- "const vec3 uv_cbp=vec3(16.0,32.0,64.0);\n"\r
- "void main()\n"\r
- "{\n"\r
- // calculate cbp\r
- //" vec4 cbp_vec=vec4(cbp,cbp,cbp,cbp);\n"\r
-\r
- // old cbp code\r
- // " vec4 fmod_cbp_y=mod(cbp_vec,y_cbp);\n"\r
- // " vec2 fmod_cbp_uv=mod(cbp_vec.xy,uv_cbp.xy);\n"\r
- // " fmod_cbp_y.x=0.;\n"\r
- // " fmod_cbp_y=sign(vec4(fmod_cbp_y.yzw,fmod_cbp_uv.x)-fmod_cbp_y);\n"\r
- // " fmod_cbp_uv=sign(vec2(fmod_cbp_uv.y,cbp)-fmod_cbp_uv);\n"\r
- // resulting vector should indicate with block is present\r
- // now transform it to a sum (TODO vectorize this)\r
-\r
-//this code is better but nor really working\r
- /* " vec4 fmod_cbp_y=mod(cbp_vec,vec4(uv_cbp.zyx,y_cbp.w));\n"\r
- " vec2 fmod_cbp_uv=mod(cbp_vec.xy,y_cbp.zy);\n"\r
- " fmod_cbp_y=vec4(lessThanEqual(vec4(uv_cbp.yx,y_cbp.wz),fmod_cbp_y));\n"\r
- " fmod_cbp_uv=vec2(lessThanEqual(y_cbp.yx,fmod_cbp_uv));\n"\r
-\r
- " vec4 fmod_cbp_y2=fmod_cbp_y;\n"\r
- " vec2 fmod_cbp_uv2=fmod_cbp_uv;\n"\r
- " fmod_cbp_y2.y+=fmod_cbp_y2.x;\n"\r
- " fmod_cbp_y2.z+=fmod_cbp_y2.y;\n"\r
- " fmod_cbp_y2.w+=fmod_cbp_y2.z;\n"\r
- " fmod_cbp_uv2.x+=fmod_cbp_y2.w;\n"\r
- " fmod_cbp_uv2.y+=fmod_cbp_uv2.x;\n"*/\r
-\r
-\r
- " float tcbp=cbp;\n"\r
- " float tpos=czero;\n"\r
- " vec4 fmod_cbp_y=vec4(czero,czero,czero,czero);\n"\r
- " vec2 fmod_cbp_uv=vec2(czero,czero);\n"\r
- " vec4 fmod_cbp_y2=vec4(czero,czero,czero,czero);\n"\r
- " vec2 fmod_cbp_uv2=vec2(czero,czero);\n"\r
- " if (tcbp>=uv_cbp.y){\n"\r
- " fmod_cbp_y.x=one;\n"\r
- " fmod_cbp_y2.x=tpos;\n"\r
- " tpos++;\n"\r
- " tcbp-=uv_cbp.y;\n"\r
- " }\n"\r
- " if (tcbp>=uv_cbp.x){\n"\r
- " fmod_cbp_y.y=one;\n"\r
- " fmod_cbp_y2.y=tpos;\n"\r
- " tpos++;\n"\r
- " tcbp-=uv_cbp.x;\n"\r
- " }\n"\r
- " if (tcbp>=y_cbp.w){\n"\r
- " fmod_cbp_y.z=one;\n"\r
- " fmod_cbp_y2.z=tpos;\n"\r
- " tpos++;\n"\r
- " tcbp-=y_cbp.w;\n"\r
- " }\n"\r
- " if (tcbp>=y_cbp.z){\n"\r
- " fmod_cbp_y.w=one;\n"\r
- " fmod_cbp_y2.w=tpos;\n"\r
- " tpos++;\n"\r
- " tcbp-=y_cbp.z;\n"\r
- " }\n"\r
- " if (tcbp>=y_cbp.y){\n"\r
- " fmod_cbp_uv.x=one;\n"\r
- " fmod_cbp_uv2.x=tpos;\n"\r
- " tpos++;\n"\r
- " tcbp-=y_cbp.y;\n"\r
- " }\n"\r
- " if (tcbp>=y_cbp.x){\n"\r
- " fmod_cbp_uv.y=one;\n"\r
- " fmod_cbp_uv2.y=tpos;\n"\r
- // " tpos++;\n"\r
- // " tcbp-=y_cbp.y;\n"\r
- " }\n"\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
- // now calculate their position inside the short array\r
- " float m_index=index.x/*+index.y*c65536*/;\n" //Not Endian save\r
- " fmod_cbp_y2+=m_index;\n" //shift to the blocks\r
- " fmod_cbp_uv2+=m_index;\n"\r
-\r
- " out_yblockpos_y=floor((fmod_cbp_y2)*c1over32);\n"\r
- " out_uvblockpos_xy.zw=floor((fmod_cbp_uv2)*c1over32);\n"\r
- " out_yblockpos_x=fmod_cbp_y2-c32*out_yblockpos_y;\n"\r
- " out_uvblockpos_xy.xy=fmod_cbp_uv2-c32*out_uvblockpos_xy.zw;\n"\r
-\r
-\r
-\r
- //Kick out uncoded blocks\r
- // " out_yblockpos_y-=sign(fmod_cbp_y-one)*c1024;\n"\r
- // " out_uvblockpos_xy.zw-=sign(fmod_cbp_uv-one)*c1024;\n"\r
-\r
- " out_yblockpos_y=mix(vec4(c1024,c1024,c1024,c1024),out_yblockpos_y,fmod_cbp_y);\n"\r
- " out_uvblockpos_xy.zw=mix(vec2(c1024,c1024),out_uvblockpos_xy.zw,fmod_cbp_uv);\n"\r
-\r
-\r
- // set start positions\r
- // " vec4 motion_vertical=vec4(block_types.z,block_types.z,block_types.z,block_types.z);\n"\r
- // " vec4 mod_motion_vertical=mod(motion_vertical,vec4(y_cbp.yzw,uv_cbp.x));\n"\r
- // " mod_motion_vertical=vec4(lessThanEqual(y_cbp,mod_motion_vertical));\n"\r
-\r
- " out_moco_pos.xy=(block_pos.xy+block_edge.xy)*uv_cbp.x/*16*/+one;"\r
- " out_unsupported=czero;\n"\r
- " out_moco_pos.zw=vec2(czero,czero);\n"\r
- " out_misc_info.y=one;\n" // this is the y step\r
- " if (block_types.x<uv_cbp.x /* 16*/) {\n" // not intra coded\r
- " float forward_backward=mod(block_types.x,y_cbp.w /* 8*/);\n"\r
- " out_moco_pos.zw=vec2(one,czero);\n"\r
- " if (forward_backward>y_cbp.z /* 4*/) {\n"\r
- " out_moco_pos.zw=vec2(chalf,chalf);\n"\r
- //" out_unsupported=2.;\n"\r
- " } else if (forward_backward>y_cbp.y /* 2*/ ) {\n" //backward\r
- " out_moco_pos.zw=vec2(czero,one);\n"\r
- //" out_unsupported=2.;\n"\r
- " } else {\n" //forward\r
- " out_moco_pos.zw=vec2(one,czero);\n"\r
- " } \n"\r
- " if ((out_moco_pos.w+out_moco_pos.z)>y_cbp.x) {"\r
- " out_moco_pos.zw*=chalf;\n"\r
- " }\n"\r
- " if (block_types.y==y_cbp.y /*2*/) {" //Frame\r
- " out_moco_forward=vec4(PMV1.xy,PMV1.xy);\n"\r
- " out_moco_backward=vec4(PMV1.zw,PMV1.zw);\n"\r
- //" out_unsupported=2.;\n"\r
- " } else if (block_types.y==y_cbp.x /*1*/) {" //Field\r
- " out_moco_forward=vec4(PMV1.xy,PMV2.xy);\n"\r
- " out_moco_backward=vec4(PMV1.zw,PMV2.zw);\n"\r
-\r
- " float motion_vert=block_types.z;\n"\r
- " out_moco_forward.w-=one;\n"\r
- " out_moco_backward.w-=one;\n"\r
- " if (motion_vert>= y_cbp.w) {\n" //second_backward\r
- " motion_vert-=y_cbp.w;\n"\r
- " out_moco_backward.w+=one;\n"\r
- " }\n"\r
- " if (motion_vert>= y_cbp.z) {\n" //second_forward\r
- " motion_vert-=y_cbp.z;\n"\r
- " out_moco_forward.w+=one;\n"\r
- " }\n"\r
- " if (motion_vert>= y_cbp.y) {\n" //first_backward\r
- " motion_vert-=y_cbp.y;\n"\r
- " out_moco_backward.y+=one;\n"\r
- " }\n"\r
- " if (motion_vert>= y_cbp.x) {\n" //second_forward\r
- //" motion_vert-=y_cbp.z;\n"\r
- " out_moco_forward.y+=one;\n"\r
- " }\n"\r
- /* " out_moco_forward.y+=mod_motion_vertical.x;\n"\r
- " out_moco_backward.y+=mod_motion_vertical.y;\n"\r
- " out_moco_forward.w-=one-mod_motion_vertical.z;\n"\r
- " out_moco_backward.w-=one-mod_motion_vertical.w;\n"*/\r
- " out_misc_info.y=one;\n" // step to for field based\r
- // " out_unsupported=2.;\n"\r
- " } else {\n"\r
- " out_unsupported=1.;\n"\r
- " }\n"\r
- " }\n"\r
- // " if (cbp==63. || cbp==0.) out_unsupported=2.;\n"\r
- // " if (fmod_cbp_y.w==1. && mod(cbp,8.)>=4.) out_unsupported=2.;\n"\r
-\r
-\r
-\r
-\r
- " out_block_edge=block_edge;\n"\r
- " out_misc_info.x=block_types.w;\n"\r
- " vec4 out_pos=block_pos;\n"\r
- " out_pos.xy+=block_edge;\n"\r
- " out_pos.xy*=pict_scale;\n"\r
- " out_pos.xy-=vec2(one,one);"\r
- " out_pos.zw=vec2(one,one);"\r
- " gl_Position=out_pos;\n"\r
- "}\n";\r
-\r
-const GLchar moco_frag_shader[] =\r
- "precision mediump float;\n"\r
- "uniform sampler2D blocks;\n"\r
- "uniform sampler2D forward_pic;\n"\r
- "uniform sampler2D backward_pic;\n"\r
- "uniform vec2 pict_size;\n"\r
- "varying vec4 out_yblockpos_x;\n"\r
- "varying vec4 out_yblockpos_y;\n"\r
- "varying vec4 out_uvblockpos_xy;\n"\r
- "varying vec2 out_block_edge;\n"\r
- "varying vec4 out_misc_info;\n"// misc info x= DCT info, y= field based offsets\r
- "varying float out_unsupported;\n"\r
- "varying vec4 out_moco_forward;\n"\r
- "varying vec4 out_moco_backward;\n"\r
- "varying vec4 out_moco_pos;\n"\r
-\r
- "const float halfst=0.5;\n"\r
- "const float ctwo=2.0;\n"\r
- "const float cone=1.0;\n"\r
- "const float czero=0.0;\n"\r
- "const float sieben=7.0;\n"\r
- "const float acht=8.0;\n"\r
- "const float s8=1./8.;\n"\r
- "const float s16=1./16.;\n"\r
- "const float c1over2048=1./2048.;\n"\r
- "const float c1over1024=1./1024.;\n"\r
- "const float c255=255.;\n"\r
- "const float c65280=65280.;\n"\r
- "const float c65536=65536.;\n"\r
- "const float cstep=32767.;\n"\r
- "\n"\r
- "float unpack_short(vec2 income) {\n"\r
- " float temp=income.y*c65280+income.x*c255;\n"\r
- " temp-=step(cstep,temp)*c65536;\n"\r
- " return temp/c255;\n"\r
- "}"\r
- // "uniform sampler2D textureV;\n"\r
- // "uniform sampler2D textureY;\n"\r
-// "varying vec2 out_texCoord;\n"\r
- "void main()\n"\r
- "{\n"\r
- // first figure out the block num for y, first decide between up and down, fix me field\r
- //non field code\r
- " vec4 ypos_temp1;\n"\r
- " vec4 our_fragcol=vec4(czero,czero,czero,cone);\n"\r
- " bool upper_half;\n"\r
- " float line_step;\n"\r
- " if (out_misc_info.x!=0.) {\n" //test the dct type\r
- " upper_half=mod(floor(out_block_edge.y*acht),ctwo)==cone;\n"\r
- " line_step=cone;\n"\r
- "}else{\n"\r
- " upper_half=halfst<out_block_edge.y;\n"\r
- " line_step=ctwo;\n"\r
- "}\n"\r
- " if (upper_half) {\n"\r
- " ypos_temp1=vec4(out_yblockpos_x.z,out_yblockpos_y.z,out_yblockpos_x.w,out_yblockpos_y.w);\n"\r
- " } else {\n"\r
- " ypos_temp1=vec4(out_yblockpos_x.x,out_yblockpos_y.x,out_yblockpos_x.y,out_yblockpos_y.y);\n"\r
- " }\n"\r
- // " vec4 ypos_temp1=mix(vec4(out_yblockpos_x.x,out_yblockpos_y.x,out_yblockpos_x.y,out_yblockpos_y.y),"\r
- // " vec4(out_yblockpos_x.z,out_yblockpos_y.z,out_yblockpos_x.w,out_yblockpos_y.w),step(halfst,out_block_edge.y));\n"\r
- //field code\r
- // " vec4 ypos_temp1=mix(vec4(out_yblockpos_x.x,out_yblockpos_y.x,out_yblockpos_x.y,out_yblockpos_y.y),"\r
- // " vec4(out_yblockpos_x.z,out_yblockpos_y.z,out_yblockpos_x.w,out_yblockpos_y.w),step(s16,mod(out_block_edge.y,s8)));\n"\r
-\r
- //decide between left and right\r
- " vec4 ypos_temp2;\n"\r
- "if (halfst<out_block_edge.x){\n"\r
- " ypos_temp2.xy=ypos_temp1.zw;\n"\r
- " }else {\n"\r
- " ypos_temp2.xy=ypos_temp1.xy;\n"\r
- " }\n"\r
- //now get the intra 8x8 Block coordinates\r
- " vec2 ypos_temp3=floor(mod(out_block_edge*vec2(ctwo,line_step),cone)*acht);\n"\r
- " ypos_temp2.x=(ypos_temp3.x+(ypos_temp3.y+acht*(ypos_temp2.x))*acht);\n"\r
- //" bool subsample=(mod(ypos_temp2.x,ctwo)>halfst);\n"\r
- " bool subsample=mod(ypos_temp3.x,ctwo)==cone;\n"\r
- " ypos_temp2.x*=halfst;\n"\r
- " ypos_temp2.xy*=c1over1024;\n"\r
- " ypos_temp1=texture2D(blocks,ypos_temp2.xy);\n" // now select the right data\r
- "if (subsample){\n"\r
- " ypos_temp3.xy=ypos_temp1.zw;\n"\r
- //" ypos_temp2=vec2(cone,0.);\n"\r
- " }else {\n"\r
- " ypos_temp3.xy=ypos_temp1.xy;\n"\r
- " }\n"\r
- " our_fragcol.r=unpack_short(ypos_temp3.xy);\n"\r
-\r
- //now uv\r
- " ypos_temp3=floor(out_block_edge*acht);\n"\r
- " ypos_temp2.yw=floor(out_uvblockpos_xy.zw);\n"\r
- " ypos_temp2.xz=(ypos_temp3.x+(ypos_temp3.y+acht*(out_uvblockpos_xy.xy))*acht);\n"\r
- //" subsample=(mod(ypos_temp2.x,ctwo)>halfst);\n"\r
- " subsample=mod(ypos_temp3.x,ctwo)==cone;\n"\r
- " ypos_temp2.xz*=halfst;\n"\r
- " ypos_temp2*=c1over1024;\n"\r
-\r
- " ypos_temp1=texture2D(blocks,ypos_temp2.xy);\n" // now select the right data\r
- " if (subsample){\n"\r
- " ypos_temp3.xy=ypos_temp1.zw;\n"\r
- " }else {\n"\r
- " ypos_temp3.xy=ypos_temp1.xy;\n"\r
- " }\n"\r
- " our_fragcol.g=unpack_short(ypos_temp3.xy);\n"\r
-\r
- " ypos_temp1=texture2D(blocks,ypos_temp2.zw);\n" // now select the right data\r
- //" if (subsample){\n"\r
- " ypos_temp3.xy=ypos_temp1.zw;\n"\r
- //" }else {\n"\r
- " ypos_temp3.xy=ypos_temp1.xy;\n"\r
- //" }\n"\r
- " our_fragcol.b=unpack_short(ypos_temp3.rg);\n"\r
-\r
- //MOCO\r
- // decide if it is top or bottom\r
- " vec4 moco_work;\n"\r
- " if (mod(floor(out_moco_pos.y),ctwo)!=cone) {\n"\r
- " moco_work=vec4(out_moco_forward.xy,out_moco_backward.xy);\n"\r
- "} else {\n"\r
- " moco_work=vec4(out_moco_forward.zw,out_moco_backward.zw);\n"\r
- "}\n"\r
- // now we handle the y fetching\r
- " vec4 moco_temp;\n"\r
- " vec4 subpixel=floor(mod(moco_work,ctwo))*halfst; \n"\r
- " moco_temp=floor(moco_work*halfst)+floor(vec4(out_moco_pos.xy,out_moco_pos.xy));\n"\r
- " vec4 c00,c01,c10,c11;\n"\r
-\r
- " c00=texture2D(forward_pic,moco_temp.xy*pict_size);\n"\r
- " c01=texture2D(forward_pic,(moco_temp.xy+vec2(czero,out_misc_info.y))*pict_size);\n"\r
- " c10=texture2D(forward_pic,(moco_temp.xy+vec2(cone,czero))*pict_size);\n"\r
- " c11=texture2D(forward_pic,(moco_temp.xy+vec2(cone,out_misc_info.y))*pict_size);\n"\r
- " 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"\r
-\r
-\r
- " c00=texture2D(backward_pic,moco_temp.zw*pict_size);\n"//backward\r
- " c01=texture2D(backward_pic,(moco_temp.zw+vec2(czero,out_misc_info.y))*pict_size);\n"\r
- " c10=texture2D(backward_pic,(moco_temp.zw+vec2(cone,czero))*pict_size);\n"\r
- " c11=texture2D(backward_pic,(moco_temp.zw+vec2(cone,out_misc_info.y))*pict_size);\n"\r
- " 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"\r
- // now handle UV\r
- " subpixel=floor(mod(moco_work*halfst,ctwo))*halfst; \n"\r
- " moco_temp=(floor(moco_work*halfst*halfst)+floor(vec4(out_moco_pos.xy,out_moco_pos.xy)*halfst))*ctwo;\n"\r
-\r
- " c00=texture2D(forward_pic,moco_temp.xy*pict_size);\n"\r
- " c01=texture2D(forward_pic,(moco_temp.xy+vec2(czero,ctwo*out_misc_info.y))*pict_size);\n"\r
- " c10=texture2D(forward_pic,(moco_temp.xy+vec2(ctwo,czero))*pict_size);\n"\r
- " c11=texture2D(forward_pic,(moco_temp.xy+vec2(ctwo,ctwo*out_misc_info.y))*pict_size);\n"\r
- " 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"\r
-\r
- " c00=texture2D(backward_pic,moco_temp.zw*pict_size);\n"\r
- " c01=texture2D(backward_pic,(moco_temp.zw+vec2(czero,ctwo*out_misc_info.y))*pict_size);\n"\r
- " c10=texture2D(backward_pic,(moco_temp.zw+vec2(ctwo,czero))*pict_size);\n"\r
- " c11=texture2D(backward_pic,(moco_temp.zw+vec2(ctwo,ctwo*out_misc_info.y))*pict_size);\n"\r
- " 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"\r
-\r
- " gl_FragColor.rgb=our_fragcol.rgb;\n"\r
-// " gl_FragColor.rgb=vec3(our_fragcol.r,halfst,halfst);\n"\r
-// " if (out_unsupported==1.) {\n"\r
-// " gl_FragColor.gb=vec2(cone,0.0);\n"\r
-// "}else if (out_unsupported==2.) {\n"\r
-// " gl_FragColor.gb=vec2(0.0,cone);\n"\r
-// "}\n"\r
-\r
-\r
- //" ypos_temp2=mix(ypos_temp1.rg,ypos_temp1.ba,step(c1over2047,mod(ypos_temp2.x,c1over1023)));\n" //activate this\r
-\r
-\r
- //" gl_FragColor.r=subsample/acht;\n" //signed later TODO\r
- //" gl_FragColor.g=0.5;\n"\r
- //" gl_FragColor.b=0.5;\n"\r
- " gl_FragColor.a=1.0;\n"\r
- //" vec4 blocks=texture2D(blocks,gl_FragCoord.xy/600.);\n"\r
-// "help.x=texture2D(textureY,out_texCoord).r;\n"\r
-// "help.y=texture2D(textureU,out_texCoord).r;\n"\r
-// "help.z=texture2D(textureV,out_texCoord).r;\n" //-uv_corr;\n"\r
- // " gl_FragColor.rgba=blocks;\n"\r
- // " gl_FragColor.rgba=vec4(0.7,0.5,0.5,1.0);\n"\r
- //" gl_FragColor.a=1.;\n"\r
- "}\n";\r
-\r
-GLMocoShader::GLMocoShader(): GLShader("GLMocoShader")\r
-{\r
-\r
- frame_buf=0;\r
- blocks_loc=0;\r
-}\r
-\r
-GLMocoShader::~GLMocoShader()\r
-{\r
- //parent does everything\r
-}\r
-\r
-int GLMocoShader::init() {\r
-\r
- if (!initShaders(moco_vertex_shader, moco_frag_shader)) {\r
- Log::getInstance()->log("GLMocoShader", Log::ERR, "init Shaders failed for GLMocoShader");\r
- return 0;\r
- }\r
- loc_pict_scale = glGetUniformLocation(shad_program, "pict_scale");\r
- blocks_loc = glGetUniformLocation(shad_program, "blocks");\r
- forward_pic_loc = glGetUniformLocation(shad_program, "forward_pic");\r
- backward_pic_loc = glGetUniformLocation(shad_program, "backward_pic");\r
- pict_size_loc = glGetUniformLocation(shad_program, "pict_size");\r
-\r
-// frame_sampler_locY = glGetUniformLocation(shad_program, "textureY");\r
- // Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locY,glGetError());\r
-// frame_sampler_locU = glGetUniformLocation(shad_program, "textureU");\r
- //Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locU,glGetError());\r
-// frame_sampler_locV = glGetUniformLocation(shad_program, "textureV");\r
- glGenFramebuffers(1, &frame_buf);\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "genframe bufmark1 glerror %x",glGetError());\r
- glGenTextures(1, &data_blocks);\r
- glBindTexture(GL_TEXTURE_2D, data_blocks);\r
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, BLOCK_TEXTURE_WIDTH >>1, BLOCK_TEXTURE_HEIGHT, 0, GL_RGBA,\r
- GL_UNSIGNED_BYTE, NULL);\r
- char buffer[BLOCK_TEXTURE_WIDTH*2];\r
- memset(buffer,0,BLOCK_TEXTURE_WIDTH*2); // the last line is black, simplifies the shader algorithms\r
-\r
- glTexSubImage2D(GL_TEXTURE_2D,0,0,BLOCK_TEXTURE_HEIGHT-1,\r
- BLOCK_TEXTURE_WIDTH>>1,1,\r
- GL_RGBA,GL_UNSIGNED_BYTE,\r
- buffer);\r
-\r
- glGenBuffers(1,¯o_block);\r
- glBindBuffer(GL_ARRAY_BUFFER,macro_block);\r
- glBufferData(GL_ARRAY_BUFFER,4096*4*sizeof(XvMCMacroBlock),NULL,GL_DYNAMIC_DRAW);\r
- valid_macro_blocks=0;\r
-\r
-\r
- glGenBuffers(1,&triangles);\r
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,triangles);\r
- GLushort *tri_indices=(GLushort *)malloc(sizeof(GLushort)*4096*6);\r
- if (!tri_indices) {\r
- Log::getInstance()->log("GLMocoShader", Log::WARN, "allocating triindices failed");\r
- return 0;\r
- }\r
- GLushort *tri_indices_run=tri_indices;\r
- for (int i=0;i<4096;i++) {\r
- *tri_indices_run=i+0*4096; //strip\r
- tri_indices_run++;\r
- *tri_indices_run=i+2*4096; //strip\r
- tri_indices_run++;\r
- *tri_indices_run=i+1*4096; //strip\r
- tri_indices_run++;\r
- *tri_indices_run=i+3*4096; //strip\r
- tri_indices_run++;\r
- *tri_indices_run=i+3*4096; //strip\r
- tri_indices_run++;\r
- *tri_indices_run=i+1+0*4096; //strip\r
- tri_indices_run++;\r
- }\r
-\r
-\r
-\r
-\r
-\r
- glBufferData(GL_ELEMENT_ARRAY_BUFFER,4096*6*sizeof(GLushort),tri_indices,GL_STREAM_DRAW);\r
- free(tri_indices);\r
-\r
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);\r
- glBindBuffer(GL_ARRAY_BUFFER,0);\r
-\r
-\r
-\r
- return 1;\r
-\r
-}\r
-\r
-int GLMocoShader::deinit()\r
-{\r
- glDeleteFramebuffers(1, &frame_buf);\r
- glDeleteTextures(1, &data_blocks);\r
- return deinitShaders();\r
-}\r
-\r
-\r
-\r
-int GLMocoShader::uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMacroBlock *m_blocks,unsigned int num_m_blocks)\r
-{\r
- unsigned int height=(num_blocks)/(BLOCK_PER_ROW);\r
-\r
- glBindTexture(GL_TEXTURE_2D, data_blocks);\r
- glPixelStorei(GL_UNPACK_ALIGNMENT,1);\r
-\r
-\r
-\r
-\r
- Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark1 %d %d %d",height,num_blocks,num_m_blocks);\r
- glTexSubImage2D(GL_TEXTURE_2D,0,0,0,\r
- BLOCK_TEXTURE_WIDTH>>1,height,\r
- GL_RGBA,GL_UNSIGNED_BYTE,\r
- blocks);\r
-// Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError());\r
- glTexSubImage2D(GL_TEXTURE_2D,0,0,height,\r
- ((num_blocks%BLOCK_PER_ROW)>>1)*BLOCK_SIZE,1,\r
- GL_RGBA,GL_UNSIGNED_BYTE,\r
- blocks+height*BLOCK_PER_ROW*BLOCK_SIZE);\r
-\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError());\r
-\r
-\r
-\r
- glBindTexture(GL_TEXTURE_2D, 0);\r
-\r
- valid_macro_blocks=num_m_blocks;\r
- glBindBuffer(GL_ARRAY_BUFFER,macro_block);\r
- XvMCMacroBlock *m_blocks_run=m_blocks;\r
- XvMCMacroBlock *m_blocks_end=m_blocks+num_m_blocks;\r
- while (m_blocks_run!=m_blocks_end) {\r
- m_blocks_run->pad0=0xFF00;\r
- // Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks coded block %x %x %d",\r
- // m_blocks_run->coded_block_pattern, m_blocks_run->macroblock_type,m_blocks_run->index);\r
- m_blocks_run++;\r
-\r
- }\r
- // debug\r
-/* m_blocks[0].x=0;\r
- m_blocks[0].y=0;\r
- m_blocks[3]=m_blocks[2]=m_blocks[1]=m_blocks[0];\r
- m_blocks[0].pad0=0xFF00;\r
- m_blocks[1].pad0=0xFFFF;\r
- m_blocks[2].pad0=0x0000;\r
- m_blocks[3].pad0=0x00FF;\r
- m_blocks[1].x=0;\r
- m_blocks[1].y=0;\r
- m_blocks[2].x=0;\r
- m_blocks[2].y=0;\r
- m_blocks[3].x=0;\r
- m_blocks[3].y=0;*/\r
-\r
- glBufferSubData(GL_ARRAY_BUFFER, 0* sizeof(XvMCMacroBlock), num_m_blocks * sizeof(XvMCMacroBlock),\r
- m_blocks);\r
-\r
-\r
- m_blocks_run = m_blocks;\r
- m_blocks_end = m_blocks + num_m_blocks;\r
- while (m_blocks_run != m_blocks_end) {\r
- m_blocks_run->pad0 = 0xFFFF;\r
- m_blocks_run++;\r
- }\r
- glBufferSubData(GL_ARRAY_BUFFER, 4096* sizeof(XvMCMacroBlock), num_m_blocks * sizeof(XvMCMacroBlock),\r
- m_blocks);\r
-\r
-\r
- m_blocks_run = m_blocks;\r
- m_blocks_end = m_blocks + num_m_blocks;\r
- while (m_blocks_run != m_blocks_end) {\r
- m_blocks_run->pad0 = 0x0000;\r
- m_blocks_run++;\r
- }\r
- glBufferSubData(GL_ARRAY_BUFFER, 2 * 4096* sizeof(XvMCMacroBlock),\r
- num_m_blocks * sizeof(XvMCMacroBlock), m_blocks);\r
-\r
-\r
- m_blocks_run = m_blocks;\r
- m_blocks_end = m_blocks + num_m_blocks;\r
- while (m_blocks_run != m_blocks_end) {\r
- m_blocks_run->pad0 = 0x00FF;\r
- m_blocks_run++;\r
- }\r
- glBufferSubData(GL_ARRAY_BUFFER, 3 * 4096* sizeof(XvMCMacroBlock),\r
- num_m_blocks * sizeof(XvMCMacroBlock), m_blocks);\r
-\r
-\r
- glBindBuffer(GL_ARRAY_BUFFER,0);\r
-\r
- return 1;\r
-\r
-\r
-\r
-}\r
-\r
-int GLMocoShader::doMoCo(VPEOGLFrame *target,VPEOGLFrame *forward,VPEOGLFrame *backward)\r
-{\r
-\r
-// Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark-2 glerror %x %x",glGetError(),frame_buf);\r
-\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark-1 glerror %x %x",glGetError(),frame_buf);\r
- glBindFramebuffer(GL_FRAMEBUFFER, frame_buf);\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark1 glerror %x %x %x",glGetError(),target->textures[0],target->textures[1]);\r
-\r
-\r
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,\r
- GL_TEXTURE_2D, target->textures[0], 0);\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark1apres glerror %x",glGetError());\r
-\r
-\r
-\r
-\r
-\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2 glerror %x",glGetError());\r
-\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2a glerror %x",glGetError());\r
-\r
- int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);\r
- if (status == GL_FRAMEBUFFER_COMPLETE) {\r
- glViewport(0, 0, target->width,target->height);\r
- // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2b glerror %x",glGetError());\r
-\r
- XvMCMacroBlock * helperp=NULL;\r
-\r
- glClearColor(0.0f,0.5f,0.5f,1.f); //this black\r
- glClear(GL_COLOR_BUFFER_BIT);\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2c glerror %x",glGetError());\r
-\r
- glUseProgram(shad_program);\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark3 glerror %x",glGetError());\r
-\r
-\r
- const GLfloat pict_scale[]={ 32./((float)target->width),32./((float)target->height)};\r
-\r
- glUniform2fv(loc_pict_scale,1,(const GLfloat*)&pict_scale);\r
-\r
-\r
- const GLfloat pict_size[]={ 1./((float)target->width),1./((float)target->height)};\r
- glUniform2fv(pict_size_loc,1,(const GLfloat*)&pict_size);\r
-\r
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,triangles);\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark5 glerror %x",glGetError());\r
- glBindBuffer(GL_ARRAY_BUFFER,macro_block);\r
-\r
-\r
-\r
- glVertexAttribPointer(0, 2, GL_SHORT, GL_FALSE,\r
- sizeof(XvMCMacroBlock), NULL);\r
-\r
- glEnableVertexAttribArray(0);\r
-\r
- glVertexAttribPointer(1, 2, GL_UNSIGNED_BYTE, GL_TRUE,sizeof(XvMCMacroBlock), (const void *) &(helperp->pad0));\r
- glEnableVertexAttribArray(1);\r
-\r
- glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->macroblock_type));\r
- glEnableVertexAttribArray(2);\r
-\r
- glVertexAttribPointer(3, 1, GL_UNSIGNED_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->coded_block_pattern));\r
- glEnableVertexAttribArray(3);\r
- glVertexAttribPointer(4, 2, GL_UNSIGNED_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->index));\r
- glEnableVertexAttribArray(4);\r
-\r
- glVertexAttribPointer(5, 4, GL_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->PMV[0][0][0]));\r
- glEnableVertexAttribArray(5);\r
-\r
- glVertexAttribPointer(6, 4, GL_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->PMV[1][0][0]));\r
- glEnableVertexAttribArray(6);\r
-\r
-\r
-\r
-\r
- glActiveTexture(GL_TEXTURE0);\r
- glBindTexture(GL_TEXTURE_2D,data_blocks);\r
- glUniform1i(blocks_loc,0);\r
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);\r
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);\r
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);\r
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);\r
-\r
-\r
-\r
- if (forward) {\r
- // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo forward %x",forward->textures[0]);\r
- glActiveTexture(GL_TEXTURE1);\r
- glBindTexture(GL_TEXTURE_2D,forward->textures[0]);\r
- glUniform1i(forward_pic_loc,1);\r
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);\r
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);\r
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);\r
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);\r
-\r
- }\r
-\r
- if (backward) {\r
- glActiveTexture(GL_TEXTURE2);\r
- // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo backward %x",backward->textures[0]);\r
- glBindTexture(GL_TEXTURE_2D,backward->textures[0]);\r
- glUniform1i(backward_pic_loc,2);\r
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);\r
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);\r
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);\r
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);\r
-\r
- }\r
-\r
-\r
-\r
- glDrawElements(GL_TRIANGLE_STRIP, valid_macro_blocks*6,\r
- GL_UNSIGNED_SHORT, NULL);\r
-\r
-\r
- /*\r
- glVertexAttribPointer(0, 2, GL_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), 0);\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark3 glerror %x",glGetError());\r
- glEnableVertexAttribArray(0);\r
-\r
- glVertexAttribPointer(1, 2, GL_UNSIGNED_BYTE, GL_TRUE,sizeof(XvMCMacroBlock), (const void *) &(helperp->pad0));\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark3 glerror %x",glGetError());\r
- glEnableVertexAttribArray(1);*/\r
-\r
- // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark4 glerror %x",glGetError());\r
-\r
-\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark6 glerror %x",glGetError());\r
-\r
- // glDrawElements(GL_TRIANGLE_STRIP,/*valid_macro_blocks*/4,GL_UNSIGNED_SHORT,0);\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark7 glerror %x %x",glGetError(),valid_macro_blocks);\r
- //cleanup\r
-\r
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark5 glerror %x",glGetError());\r
- glBindBuffer(GL_ARRAY_BUFFER,0);\r
-\r
- glBindFramebuffer(GL_FRAMEBUFFER, 0);\r
- glActiveTexture(GL_TEXTURE0);\r
- glBindTexture(GL_TEXTURE_2D, 0);\r
- glActiveTexture(GL_TEXTURE1);\r
- glBindTexture(GL_TEXTURE_2D, 0);\r
- glActiveTexture(GL_TEXTURE2);\r
- glBindTexture(GL_TEXTURE_2D, 0);\r
- //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark8 glerror %x",glGetError());\r
- } else {\r
- glBindFramebuffer(GL_FRAMEBUFFER, 0);\r
- Log::getInstance()->log("GLMocoShader", Log::WARN, "framebuffer not complete %x",status);\r
- return -1;\r
- }\r
-\r
- glFinish(); // since the main rendering is done in a different thread we have to make sure rendering is finished before passing the texture\r
- // call this only in the last stage of rendering the moco frame\r
- return 0;\r
-\r
-\r
-\r
-}\r
-\r
-/*\r
-\r
-int GLMocoShader::PrepareRendering(GLuint y_tex, GLuint u_tex, GLuint v_tex) { // This Function setups the rendering pipeline according to the shaders standards\r
-\r
- //Log::getInstance()->log("OSD", Log::WARN, "mark1 glerror %x",glGetError());\r
-\r
-\r
- //Log::getInstance()->log("OSD", Log::WARN, "mark2 glerror %x",glGetError());\r
-\r
-\r
- glActiveTexture( GL_TEXTURE2);\r
- glBindTexture(GL_TEXTURE_2D, v_tex);\r
- glUniform1i(frame_sampler_locV, 2);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
-\r
- glActiveTexture( GL_TEXTURE1);\r
- glBindTexture(GL_TEXTURE_2D, u_tex);\r
- glUniform1i(frame_sampler_locU, 1);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
-\r
- glActiveTexture( GL_TEXTURE0);\r
- glBindTexture(GL_TEXTURE_2D, y_tex);\r
- glUniform1i(frame_sampler_locY, 0);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
- return 1;\r
-\r
-}*/\r
-\r
-int GLMocoShader::BindAttributes()\r
-{\r
- glBindAttribLocation(shad_program,0,"block_pos");\r
- glBindAttribLocation(shad_program,1,"block_edge");\r
- glBindAttribLocation(shad_program,2,"block_types");\r
- glBindAttribLocation(shad_program,3,"cbp");\r
- glBindAttribLocation(shad_program,4,"index");\r
- glBindAttribLocation(shad_program,5,"PMV1");\r
- glBindAttribLocation(shad_program,6,"PMV2");\r
-\r
- //glBindAttribLocation(shad_program,1,"tex_coord");\r
- return 1;\r
-}\r
+++ /dev/null
-/*\r
- Copyright 2012 Marten Richter\r
-\r
- This file is part of VOMP.\r
-\r
- VOMP is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; either version 2 of the License, or\r
- (at your option) any later version.\r
-\r
- VOMP is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with VOMP; if not, write to the Free Software\r
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
-*/\r
-\r
-#ifndef GL_MOCOSHADER_H\r
-#define GL_MOCOSHADER_H\r
-\r
-#include "glshader.h"\r
-#include <libavcodec/xvmc.h>\r
-\r
-struct VPEOGLFrame;\r
-struct VPE_FrameBuf;\r
-\r
-\r
-class GLMocoShader: public GLShader {\r
-public:\r
- GLMocoShader();\r
- virtual ~GLMocoShader();\r
-\r
- int init();\r
- int deinit();\r
-\r
- int uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMacroBlock *m_blocks,unsigned int num_m_blocks);\r
-\r
- int doMoCo(VPEOGLFrame *target,VPEOGLFrame *forward,VPEOGLFrame *backward);\r
-\r
-protected:\r
- virtual int BindAttributes();\r
- GLuint frame_buf;\r
- GLuint data_blocks;\r
- GLuint triangles;\r
- GLuint macro_block;\r
- GLint loc_pict_scale;\r
- GLint blocks_loc;\r
- GLint forward_pic_loc;\r
- GLint backward_pic_loc;\r
- GLint pict_size_loc;\r
- unsigned int valid_macro_blocks;\r
-\r
-\r
-\r
-};\r
-\r
-\r
-#endif\r
+++ /dev/null
-/*\r
- Copyright 2012 Marten Richter\r
-\r
- This file is part of VOMP.\r
-\r
- VOMP is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; either version 2 of the License, or\r
- (at your option) any later version.\r
-\r
- VOMP is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with VOMP; if not, write to the Free Software\r
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
-*/\r
-#include "glyuv400shader.h"\r
-\r
-const GLchar generic_vertex_shader[] =\r
- "attribute vec4 vec_pos;\n"\r
- "attribute vec2 tex_coord;\n"\r
- "varying vec2 out_texCoord;\n"\r
- "void main()\n"\r
- "{\n"\r
- " gl_Position=vec_pos;\n"\r
- " out_texCoord=tex_coord;\n"\r
- "}\n";\r
-\r
-const GLchar frame_frag_shader[] =\r
- "precision mediump float;\n"\r
- "uniform sampler2D textureU;\n"\r
- "uniform sampler2D textureV;\n"\r
- "uniform sampler2D textureY;\n"\r
- "const float uv_corr=0.5;\n"\r
- "const float y_corr=0.0625;\n"\r
- "const mat3 yuvtransform= mat3( 1.164 ,0.0 ,1.596 ,\n"\r
- " 1.164 ,-0.391,-0.813 ,\n"\r
- " 1.164,2.018 , 0.0 );\n"\r
-// "const mat3 yuvtransform= mat3( 1. ,1. ,1. ,\n"\r
-// " 0.0 ,-0.3960,2.029 ,\n"\r
-// " 1.140,-0.581 , 0.0 );\n"\r
-// "const mat3 yuvtransform= mat3( 1. ,0 ,0. ,\n"\r
-// " 0.0 ,1.,0. ,\n"\r
-// " 0.,0. , 1.0 );\n"\r
-// "const mat3 yuvtransform= mat3( 1. ,1. ,1. ,\n"\r
-// " 0.0 ,-0.03960,0.2029 ,\n"\r
-// " 0.1140,-0.0581 , 0.0 );\n"\r
- "varying vec2 out_texCoord;\n"\r
- "void main()\n"\r
- "{\n"\r
- " vec3 help;\n"\r
- "help.x=texture2D(textureY,out_texCoord).r-y_corr;\n"\r
- "help.y=texture2D(textureU,out_texCoord).r-uv_corr;\n"\r
- "help.z=texture2D(textureV,out_texCoord).r-uv_corr;\n" //-uv_corr;\n"\r
- " gl_FragColor.rgb=help*yuvtransform;\n"\r
- " gl_FragColor.a=1.;\n"\r
- "}\n";\r
-\r
-GLYuv400Shader::GLYuv400Shader(): GLShader("GLYuv400Shader")\r
-{\r
-\r
-}\r
-\r
-GLYuv400Shader::~GLYuv400Shader()\r
-{\r
- //parent does everything\r
-}\r
-\r
-int GLYuv400Shader::init() {\r
- if (!initShaders(generic_vertex_shader, frame_frag_shader)) {\r
- return 0;\r
- }\r
- frame_sampler_locY = glGetUniformLocation(shad_program, "textureY");\r
- // Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locY,glGetError());\r
- frame_sampler_locU = glGetUniformLocation(shad_program, "textureU");\r
- //Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locU,glGetError());\r
- frame_sampler_locV = glGetUniformLocation(shad_program, "textureV");\r
- return 1;\r
-\r
-}\r
-\r
-int GLYuv400Shader::deinit()\r
-{\r
- return deinitShaders();\r
-}\r
-\r
-int GLYuv400Shader::PrepareRendering(GLuint y_tex, GLuint u_tex, GLuint v_tex) { // This Function setups the rendering pipeline according to the shaders standards\r
- glUseProgram(shad_program);\r
- //Log::getInstance()->log("OSD", Log::WARN, "mark1 glerror %x",glGetError());\r
-\r
-\r
- //Log::getInstance()->log("OSD", Log::WARN, "mark2 glerror %x",glGetError());\r
-\r
-\r
- glActiveTexture( GL_TEXTURE2);\r
- glBindTexture(GL_TEXTURE_2D, v_tex);\r
- glUniform1i(frame_sampler_locV, 2);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
-\r
- glActiveTexture( GL_TEXTURE1);\r
- glBindTexture(GL_TEXTURE_2D, u_tex);\r
- glUniform1i(frame_sampler_locU, 1);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
-\r
- glActiveTexture( GL_TEXTURE0);\r
- glBindTexture(GL_TEXTURE_2D, y_tex);\r
- glUniform1i(frame_sampler_locY, 0);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
- return 1;\r
-\r
-}\r
-\r
-int GLYuv400Shader::BindAttributes()\r
-{\r
- glBindAttribLocation(shad_program,0,"vec_pos");\r
- glBindAttribLocation(shad_program,1,"tex_coord");\r
- return 1;\r
-}\r
+++ /dev/null
-/*\r
- Copyright 2012 Marten Richter\r
-\r
- This file is part of VOMP.\r
-\r
- VOMP is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; either version 2 of the License, or\r
- (at your option) any later version.\r
-\r
- VOMP is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with VOMP; if not, write to the Free Software\r
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
-*/\r
-\r
-#ifndef GL_YUV400SHADER_H\r
-#define GL_YUV400SHADER_H\r
-\r
-#include "glshader.h"\r
-\r
-class GLYuv400Shader: public GLShader {\r
-public:\r
- GLYuv400Shader();\r
- virtual ~GLYuv400Shader();\r
-\r
- int init();\r
- int deinit();\r
-\r
- int PrepareRendering(GLuint y_tex,GLuint u_tex,GLuint v_tex); // This Function setups the rendering pipeline according to the shaders standards\r
-\r
-protected:\r
- virtual int BindAttributes();\r
-\r
- GLint frame_sampler_locY;\r
- GLint frame_sampler_locU;\r
- GLint frame_sampler_locV;\r
-\r
-};\r
-\r
-\r
-#endif\r
+++ /dev/null
-/*\r
- Copyright 2012 Marten Richter\r
-\r
- This file is part of VOMP.\r
-\r
- VOMP is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; either version 2 of the License, or\r
- (at your option) any later version.\r
-\r
- VOMP is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with VOMP; if not, write to the Free Software\r
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
-*/\r
-#include "glyuv444shader.h"\r
-\r
-const GLchar generic_vertex_shader[] =\r
- "attribute vec4 vec_pos;\n"\r
- "attribute vec2 tex_coord;\n"\r
- "varying vec2 out_texCoord;\n"\r
- "void main()\n"\r
- "{\n"\r
- " gl_Position=vec_pos;\n"\r
- " out_texCoord=tex_coord;\n"\r
- "}\n";\r
-\r
-const GLchar frame_frag_shader[] =\r
- "precision mediump float;\n"\r
- "uniform sampler2D textureYUV;\n"\r
- "const float uv_corr=0.5;\n"\r
- "const float y_corr=0.0625;\n"\r
- "const mat3 yuvtransform= mat3( 1.164 ,0.0 ,1.596 ,\n"\r
- " 1.164 ,-0.391,-0.813 ,\n"\r
- " 1.164,2.018 , 0.0 );\n"\r
-// "const mat3 yuvtransform= mat3( 1. ,1. ,1. ,\n"\r
-// " 0.0 ,-0.3960,2.029 ,\n"\r
-// " 1.140,-0.581 , 0.0 );\n"\r
-// "const mat3 yuvtransform= mat3( 1. ,0 ,0. ,\n"\r
-// " 0.0 ,1.,0. ,\n"\r
-// " 0.,0. , 1.0 );\n"\r
-// "const mat3 yuvtransform= mat3( 1. ,1. ,1. ,\n"\r
-// " 0.0 ,-0.03960,0.2029 ,\n"\r
-// " 0.1140,-0.0581 , 0.0 );\n"\r
- "varying vec2 out_texCoord;\n"\r
- "void main()\n"\r
- "{\n"\r
- " vec3 help;\n"\r
- "help=texture2D(textureYUV,out_texCoord).rgb-vec3(y_corr,uv_corr,uv_corr);\n"\r
- "gl_FragColor.rgb=help*yuvtransform;\n"\r
- "gl_FragColor.a=1.;\n"\r
- "}\n";\r
-\r
-GLYuv444Shader::GLYuv444Shader(): GLShader("GLYuv444Shader")\r
-{\r
-\r
-}\r
-\r
-GLYuv444Shader::~GLYuv444Shader()\r
-{\r
- //parent does everything\r
-}\r
-\r
-int GLYuv444Shader::init() {\r
- if (!initShaders(generic_vertex_shader, frame_frag_shader)) {\r
- return 0;\r
- }\r
- frame_sampler_locYUV = glGetUniformLocation(shad_program, "textureYUV");\r
- return 1;\r
-\r
-}\r
-\r
-int GLYuv444Shader::deinit()\r
-{\r
- return deinitShaders();\r
-}\r
-\r
-int GLYuv444Shader::PrepareRendering(GLuint yuv_tex) { // This Function setups the rendering pipeline according to the shaders standards\r
- glUseProgram(shad_program);\r
- //Log::getInstance()->log("OSD", Log::WARN, "mark1 glerror %x",glGetError());\r
-\r
-\r
-\r
-\r
-\r
- glActiveTexture( GL_TEXTURE0);\r
- glBindTexture(GL_TEXTURE_2D, yuv_tex);\r
- //Log::getInstance()->log("OSD", Log::WARN, "mark3 glerror %x %x",glGetError(),yuv_tex);\r
- glUniform1i(frame_sampler_locYUV, 0);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
-\r
- return 1;\r
-\r
-}\r
-\r
-int GLYuv444Shader::BindAttributes()\r
-{\r
- glBindAttribLocation(shad_program,0,"vec_pos");\r
- glBindAttribLocation(shad_program,1,"tex_coord");\r
- return 1;\r
-}\r
+++ /dev/null
-/*\r
- Copyright 2012 Marten Richter\r
-\r
- This file is part of VOMP.\r
-\r
- VOMP is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; either version 2 of the License, or\r
- (at your option) any later version.\r
-\r
- VOMP is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with VOMP; if not, write to the Free Software\r
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
-*/\r
-\r
-#ifndef GL_YUV444SHADER_H\r
-#define GL_YUV444SHADER_H\r
-\r
-#include "glshader.h"\r
-\r
-class GLYuv444Shader: public GLShader {\r
-public:\r
- GLYuv444Shader();\r
- virtual ~GLYuv444Shader();\r
-\r
- int init();\r
- int deinit();\r
-\r
- int PrepareRendering(GLuint y_tex); // This Function setups the rendering pipeline according to the shaders standards\r
-\r
-protected:\r
- virtual int BindAttributes();\r
-\r
- GLint frame_sampler_locYUV;\r
-\r
-\r
-};\r
-\r
-\r
-#endif\r
#include "remotelinux.h"\r
#include "ledraspberry.h"\r
#include "osdopengl.h"\r
-#include "audiovpe.h"\r
-#include "videovpeogl.h"\r
+#include "audioomx.h"\r
+#include "videoomx.h"\r
\r
#endif\r
\r
\r
#include "osdopengl.h"\r
#include "mtd.h"\r
-#include "videovpeogl.h"\r
+#include "videoomx.h"\r
#include "surfaceopengl.h"\r
\r
\r
glmutex.Unlock();\r
return 0;\r
}\r
- if (!yuv400_shader.init()) {\r
- Log::getInstance()->log("OSD", Log::WARN, "Init Yuv400 Shader failed");\r
- glmutex.Unlock();\r
- return 0;\r
- }\r
\r
- if (!yuv444_shader.init()) {\r
- Log::getInstance()->log("OSD", Log::WARN, "Init Yuv444 Shader failed");\r
- glmutex.Unlock();\r
- return 0;\r
- }\r
\r
\r
\r
\r
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
\r
- if (((VideoVPEOGL*)Video::getInstance())->initUsingOSDObjects()!=1) { //call Video for init opengl stuff\r
+ if (((VideoOMX*)Video::getInstance())->initUsingOSDObjects()!=1) { //call Video for init opengl stuff\r
return 0;\r
}\r
\r
if (!initted) return 0;\r
initted = 0;\r
\r
- (((VideoVPEOGL*)Video::getInstance())->shutdownUsingOSDObjects());\r
+ (((VideoOMX*)Video::getInstance())->shutdownUsingOSDObjects());\r
\r
\r
osd_shader.deinit();\r
- yuv400_shader.deinit();\r
- yuv444_shader.deinit();\r
\r
glClear(GL_COLOR_BUFFER_BIT);\r
eglSwapBuffers(egl_display, egl_surface);\r
//glmutex.Lock();\r
\r
//glmutex.Unlock();\r
- VPEOGLFrame *frame=NULL;\r
int ts=0;\r
- VideoVPEOGL* video =(VideoVPEOGL*) Video::getInstance();\r
while (true)\r
{\r
ts=10;\r
unsigned int waittime=10;\r
\r
- if (initted){\r
-#ifdef VPE_LIBAV_SUPPORT\r
- if (!frame) frame=video->getReadyOGLFrame();\r
- if (frame) {\r
- InternalRendering(frame);\r
- // MILLISLEEP(1000);\r
- lastrendertime=getTimeMS();\r
- video->returnOGLFrame(frame); //please recycle it\r
- frame=NULL;\r
+ if (initted) {\r
+\r
+ long long time1 = getTimeMS();\r
+ if ((time1 - lastrendertime) > 200) {//5 fps for OSD updates are enough, avoids tearing\r
+ InternalRendering();\r
+ lastrendertime = getTimeMS();\r
\r
}\r
- else\r
-#endif\r
- {\r
- long long time1=getTimeMS();\r
- if ((time1-lastrendertime)>200) {//5 fps for OSD updates are enough, avoids tearing\r
- InternalRendering(NULL);\r
- lastrendertime=getTimeMS();\r
- }\r
- }\r
-#ifdef VPE_LIBAV_SUPPORT\r
- frame=video->getReadyOGLFrame();\r
-#endif\r
}\r
\r
-\r
- if (frame) ts=0;\r
threadCheckExit();\r
if (ts!=0) {\r
struct timespec target_time;\r
\r
\r
\r
-void OsdOpenGL::InternalRendering(VPEOGLFrame* frame){\r
+void OsdOpenGL::InternalRendering(){\r
BeginPainting();\r
\r
\r
glClearColor(0.0f,0.0f,0.0f,1.f);\r
glClear(GL_COLOR_BUFFER_BIT);\r
\r
- if (frame) {\r
- switch (frame->type) {\r
- case 1:\r
- yuv400_shader.PrepareRendering(frame->textures[0],frame->textures[1],frame->textures[2]);break;\r
- case 2:\r
- yuv444_shader.PrepareRendering(frame->textures[0]);break;\r
- }\r
-\r
-\r
-\r
-\r
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), osdvertices);\r
- glEnableVertexAttribArray(0);\r
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), &(osdvertices[0].u));\r
- glEnableVertexAttribArray(1);\r
-\r
-\r
- //Log::getInstance()->log("OSD", Log::WARN, "mark8 glerror %x %x",glGetError(),osd_sampler_loc);\r
-\r
-\r
-\r
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);\r
-\r
-\r
- }\r
-\r
-\r
-\r
-\r
osd_shader.PrepareRendering(((SurfaceOpenGL*)screen)->getTexture());\r
\r
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), osdvertices);\r
glEnableVertexAttribArray(1);\r
\r
\r
- if (frame!=NULL) { //This is ok for ffmpeg rendering not OMX\r
- glEnable(GL_BLEND);\r
- glBlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,GL_ZERO,GL_ONE);\r
\r
- } else {\r
- glDisable(GL_BLEND);\r
- }\r
+ glDisable(GL_BLEND);\r
+\r
\r
\r
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);\r
#include "log.h"\r
#include "threadp.h"\r
#include "mutex.h"\r
-#include "videovpeogl.h"\r
+#include "videoomx.h"\r
\r
#include "glosdshader.h"\r
-#include "glyuv400shader.h"\r
-#include "glyuv444shader.h"\r
\r
\r
\r
bool external_driving;\r
Mutex glmutex;\r
long long lastrendertime;\r
- void InternalRendering(VPEOGLFrame* frame);\r
+ void InternalRendering();\r
void InitVertexBuffer(float scalex,float scaley);\r
OSDVERTEX osdvertices[4];\r
GLubyte osdindices[6];\r
\r
GLOsdShader osd_shader;\r
- GLYuv400Shader yuv400_shader;\r
- GLYuv444Shader yuv444_shader;\r
\r
\r
\r
{\r
draintarget->PrepareMediaSample(mediapackets, cur_packet_pos);\r
unLock();\r
- if (dataavail) *dataavail=true;\r
+ if (dataavail && draintarget->DrainTargetReady()) *dataavail=true;\r
UINT consumed = draintarget->DeliverMediaSample(outbuf, &cur_packet_pos);\r
lock();\r
if (consumed != 0) ret = true;\r
--- /dev/null
+/*
+ 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;i<p_param.nPorts;i++) {
+ if (!DisablePort(omx_clock,p_param.nStartPortNumber+i,true) ) {
+ Log::getInstance()->log("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<VPE_OMX_EVENT>::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)<playbacktimeoffset) {
+ Log::getInstance()->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;
+}
+
--- /dev/null
+/*\r
+ Copyright 2004-2005 Chris Tallon 2009,2012 Marten Richter\r
+\r
+ This file is part of VOMP.\r
+\r
+ VOMP is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ VOMP is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with VOMP; if not, write to the Free Software\r
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+*/\r
+\r
+\r
+#ifndef VIDEOOMX_H\r
+#define VIDEOOMX_H\r
+\r
+#include "mutex.h"\r
+\r
+\r
+#include <stdio.h>\r
+#include <unistd.h>\r
+#include <fcntl.h>\r
+#include <sys/ioctl.h>\r
+#include <string.h>\r
+\r
+#include <stdint.h>\r
+\r
+#include <list>\r
+#include <vector>\r
+\r
+#include "defines.h"\r
+#include "video.h"\r
+#include "threadsystem.h"\r
+\r
+\r
+#include <IL/OMX_Core.h>\r
+#include <IL/OMX_Types.h>\r
+#include <IL/OMX_Component.h>\r
+#include <IL/OMX_Broadcom.h>\r
+\r
+\r
+struct VPE_OMX_EVENT {\r
+ OMX_IN OMX_HANDLETYPE handle;\r
+ OMX_IN OMX_PTR appdata;\r
+ OMX_IN OMX_EVENTTYPE event_type;\r
+ OMX_IN OMX_U32 data1;\r
+ OMX_IN OMX_U32 data2;\r
+ OMX_IN OMX_PTR event_data;\r
+};\r
+\r
+\r
+\r
+\r
+class AudioVPE;\r
+\r
+class VideoOMX : public Video\r
+{\r
+ friend class AudioOMX;\r
+ public:\r
+ VideoOMX();\r
+ virtual ~VideoOMX();\r
+\r
+ int init(UCHAR format);\r
+ int shutdown();\r
+\r
+ int setFormat(UCHAR format);\r
+ int setConnection(UCHAR connection);\r
+ int setAspectRatio(UCHAR aspectRatio); // This one does the pin 8 scart widescreen switching\r
+ int setMode(UCHAR mode);\r
+ int setTVsize(UCHAR size); // Is the TV a widescreen?\r
+ int setDefaultAspect();\r
+ int setSource();\r
+ int setPosition(int x, int y);\r
+ int sync();\r
+ int play();\r
+ int stop();\r
+ int pause();\r
+ int unPause();\r
+ int fastForward();\r
+ int unFastForward();\r
+ int reset();\r
+ int blank();\r
+ int signalOn();\r
+ int signalOff();\r
+ int attachFrameBuffer(); // What does this do?\r
+ ULONG timecodeToFrameNumber(ULLONG timecode);\r
+ ULLONG getCurrentTimestamp();\r
+ bool displayIFrame(const UCHAR* bulibaver, UINT length);\r
+\r
+ virtual bool dtsTimefix(){return true;} //please we need dts time values\r
+\r
+ // Writing Data to Videodevice\r
+ virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);\r
+ virtual UINT DeliverMediaSample(UCHAR* bulibaver, UINT* samplepos);\r
+\r
+\r
+ virtual bool supportsh264(){return true;};\r
+\r
+ int WriteOutTS(const unsigned char *bulibaver,int length, int type);\r
+ void WriteOutPATPMT();\r
+\r
+\r
+\r
+ virtual long long SetStartOffset(long long curreftime, bool *rsync);\r
+ long long SetStartAudioOffset(long long curreftime, bool *rsync);\r
+ virtual void ResetTimeOffsets();\r
+\r
+\r
+#ifdef DEV\r
+ int test();\r
+ int test2();\r
+#endif\r
+\r
+ int initUsingOSDObjects();\r
+ int shutdownUsingOSDObjects() {return shutdown();};\r
+\r
+\r
+\r
+ private:\r
+ int EnterIframePlayback();\r
+ bool iframemode;\r
+ bool InIframemode() {return iframemode;};\r
+\r
+ UINT DeliverMediaPacket(MediaPacket packet,const UCHAR* bulibaver,UINT *samplepos);\r
+\r
+#define VPE_DECODER_OMX 1\r
+\r
+\r
+\r
+ bool offsetnotset;\r
+ bool offsetvideonotset;\r
+ bool offsetaudionotset;\r
+ long long startoffset;\r
+ long long lastrefvideotime;\r
+ long long lastrefaudiotime;\r
+ OMX_TICKS lastreftimeOMX;\r
+ ULLONG lastreftimePTS;\r
+\r
+ long long playbacktimeoffset; //this is the offset between the media time and system clock\r
+ long long pausetimecode;\r
+ bool paused;\r
+\r
+ static long long GetCurrentSystemTime();\r
+ static void WaitUntil(long long time);\r
+ void FrameWaitforDisplay(long long pts);\r
+ void AdjustAudioPTS(long long pts);\r
+\r
+\r
+\r
+\r
+ static OMX_ERRORTYPE EventHandler_OMX(OMX_IN OMX_HANDLETYPE handle,OMX_IN OMX_PTR appdata,\r
+ OMX_IN OMX_EVENTTYPE event_type,OMX_IN OMX_U32 data1,\r
+ OMX_IN OMX_U32 data2,OMX_IN OMX_PTR event_data);\r
+ static OMX_ERRORTYPE EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver);\r
+ static OMX_ERRORTYPE FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver);\r
+\r
+ UINT DeliverMediaPacketOMX(MediaPacket packet,\r
+ const UCHAR* bulibaver,\r
+ UINT *samplepos);\r
+\r
+ int PrepareInputBufsOMX();\r
+ int DestroyInputBufsOMX();\r
+\r
+ void AddOmxEvent(VPE_OMX_EVENT new_event);\r
+ void ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* bulibaver);\r
+\r
+ int ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type);\r
+ int CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2);\r
+ int EnablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait);\r
+ int DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait=true);\r
+\r
+\r
+ int setClockExecutingandRunning();\r
+ int initClock();\r
+ void destroyClock();\r
+ int idleClock();\r
+ int getClockAudioandInit(OMX_HANDLETYPE *p_omx_clock,OMX_U32 *p_omx_clock_output_port);\r
+ int getClockVideoandInit();\r
+ void LockClock() {clock_mutex.Lock();};\r
+ void UnlockClock() {clock_mutex.Unlock();};\r
+ void clockPause();\r
+ void clockUnpause();\r
+\r
+ Mutex clock_mutex; //clock mutex is now responsible for all omx stuff\r
+\r
+\r
+\r
+ OMX_HANDLETYPE omx_vid_dec;\r
+ OMX_HANDLETYPE omx_vid_sched;\r
+ OMX_HANDLETYPE omx_vid_rend;\r
+ OMX_HANDLETYPE omx_clock;\r
+ int clock_references;\r
+\r
+\r
+ OMX_U32 omx_codec_input_port;\r
+ OMX_U32 omx_codec_output_port;\r
+ OMX_U32 omx_rend_input_port;\r
+ OMX_U32 omx_shed_input_port;\r
+ OMX_U32 omx_shed_output_port;\r
+ OMX_U32 omx_shed_clock_port;\r
+ OMX_U32 omx_clock_output_port;\r
+ // OMX_NALUFORMATSTYPE omx_nalu_format;\r
+\r
+\r
+\r
+ int AllocateCodecsOMX();\r
+ int DeAllocateCodecsOMX();\r
+\r
+ vector<OMX_BUFFERHEADERTYPE*> input_bufs_omx_all;\r
+ list<OMX_BUFFERHEADERTYPE*> input_bufs_omx_free;\r
+ Mutex input_bufs_omx_mutex;\r
+ OMX_BUFFERHEADERTYPE* cur_input_buf_omx;\r
+\r
+\r
+ bool omx_running;\r
+ bool omx_first_frame;\r
+\r
+ Mutex omx_event_mutex;\r
+\r
+ list<VPE_OMX_EVENT> omx_events;\r
+\r
+ bool omx_mpeg2;\r
+ bool omx_h264;\r
+\r
+\r
+\r
+ bool firstsynched;\r
+\r
+ \r
+ MediaPacket mediapacket;\r
+};\r
+\r
+#endif\r
+++ /dev/null
-/*
- 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<OMX_BUFFERHEADERTYPE*>::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<VPEOGLFrame*> keep;
- list<VPEOGLFrame*>::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<VPEOGLFrame*>::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;i<all_ogl_frames.size();i++) {
- if (all_ogl_frames[i]->pict_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;i<all_ogl_frames.size();i++) {
- if (all_ogl_frames[i]->pict_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;i<p_param.nPorts;i++) {
- if (!DisablePort(omx_clock,p_param.nStartPortNumber+i,true) ) {
- Log::getInstance()->log("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<VPE_OMX_EVENT>::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;i<all_frame_bufs.size();i++) {
- VPE_FrameBuf* current=all_frame_bufs[i];
- for (int x=0;x<4;x++) {
- if (current->data[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<VPE_FrameBuf*>::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<VPE_FrameBuf*>::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)<playbacktimeoffset) {
- Log::getInstance()->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;
-}
-
+++ /dev/null
-/*\r
- Copyright 2004-2005 Chris Tallon 2009 Marten Richter\r
-\r
- This file is part of VOMP.\r
-\r
- VOMP is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; either version 2 of the License, or\r
- (at your option) any later version.\r
-\r
- VOMP is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with VOMP; if not, write to the Free Software\r
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
-*/\r
-\r
-\r
-#ifndef VIDEOVPEOGL_H\r
-#define VIDEOVPEOGL_H\r
-\r
-#include "mutex.h"\r
-\r
-\r
-#include <stdio.h>\r
-#include <unistd.h>\r
-#include <fcntl.h>\r
-#include <sys/ioctl.h>\r
-#include <string.h>\r
-\r
-#include <stdint.h>\r
-\r
-#include <list>\r
-#include <vector>\r
-\r
-#include "defines.h"\r
-#include "video.h"\r
-#include "threadsystem.h"\r
-\r
-\r
-//#define EGL_EGLEXT_PROTOTYPES\r
-\r
-#include <GLES2/gl2.h>\r
-#include <EGL/egl.h>\r
-#include <EGL/eglext.h>\r
-\r
-#ifdef VPE_OMX_SUPPORT\r
-\r
-#include <IL/OMX_Core.h>\r
-#include <IL/OMX_Types.h>\r
-#include <IL/OMX_Component.h>\r
-#include <IL/OMX_Broadcom.h>\r
-\r
-\r
-struct VPE_OMX_EVENT {\r
- OMX_IN OMX_HANDLETYPE handle;\r
- OMX_IN OMX_PTR appdata;\r
- OMX_IN OMX_EVENTTYPE event_type;\r
- OMX_IN OMX_U32 data1;\r
- OMX_IN OMX_U32 data2;\r
- OMX_IN OMX_PTR event_data;\r
-};\r
-\r
-#endif\r
-\r
-#if defined(VPE_LIBAV_MPEG2_TRANSCODING) || defined(VPE_LIBAV_SUPPORT)\r
-extern "C" {\r
-#include <libavcodec/avcodec.h>\r
-#include <libavformat/avformat.h>\r
-#include <libavutil/imgutils.h>\r
-}\r
-#endif\r
-\r
-#ifdef VPE_LIBAV_MPEG2_TRANSCODING\r
-extern "C" {\r
-#include <libavcodec/transcode.h>\r
-}\r
-#if !defined(VPE_OMX_SUPPORT)\r
-#error "VPE_LIBAV_MPEG2_TRANSCODING defined, and not VPE_OMX_SUPPORT defined!"\r
-#endif\r
-#endif\r
-\r
-#ifdef VPE_LIBAV_SUPPORT\r
-\r
-#include <stdint.h>\r
-extern "C" {\r
-#include <libavcodec/xvmc.h>\r
-}\r
-#include "glmocoshader.h"\r
-\r
-struct VPEOGLFrame;\r
-\r
-struct VPE_FrameBuf\r
-{ //This is a frame bulibaver, nothing fancy just plain memory\r
- void *data[4];\r
- unsigned int size[4];\r
- unsigned int pict_num;\r
- VPEOGLFrame *ogl_ref;\r
- bool ogl_uploaded;\r
- int width, height;\r
- int stride;\r
-};\r
-\r
-#endif\r
-\r
-struct VPEOGLFrame {\r
- int type; //1 = YUV400, 2 YUV444\r
- GLuint textures[3]; // 0=RGB or Y, 1=U 2=V\r
- int width, height;\r
- int stride;\r
- unsigned int pict_num;\r
-/*\r
-#ifdef VPE_OMX_SUPPORT\r
- //OMX\r
- EGLImageKHR khr_image;\r
- OMX_BUFFERHEADERTYPE *omx_buf;\r
-#endif*/\r
-};\r
-\r
-\r
-\r
-\r
-class AudioVPE;\r
-\r
-class VideoVPEOGL : public Video, public Thread_TYPE\r
-{\r
- friend class AudioVPE;\r
- public:\r
- VideoVPEOGL();\r
- virtual ~VideoVPEOGL();\r
-\r
- int init(UCHAR format);\r
- int shutdown();\r
-\r
- int setFormat(UCHAR format);\r
- int setConnection(UCHAR connection);\r
- int setAspectRatio(UCHAR aspectRatio); // This one does the pin 8 scart widescreen switching\r
- int setMode(UCHAR mode);\r
- int setTVsize(UCHAR size); // Is the TV a widescreen?\r
- int setDefaultAspect();\r
- int setSource();\r
- int setPosition(int x, int y);\r
- int sync();\r
- int play();\r
- int stop();\r
- int pause();\r
- int unPause();\r
- int fastForward();\r
- int unFastForward();\r
- int reset();\r
- int blank();\r
- int signalOn();\r
- int signalOff();\r
- int attachFrameBuffer(); // What does this do?\r
- ULONG timecodeToFrameNumber(ULLONG timecode);\r
- ULLONG getCurrentTimestamp();\r
- bool displayIFrame(const UCHAR* bulibaver, UINT length);\r
-\r
- virtual bool dtsTimefix(){return true;} //please we need dts time values\r
-\r
- // Writing Data to Videodevice\r
- virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);\r
- virtual UINT DeliverMediaSample(UCHAR* bulibaver, UINT* samplepos);\r
-\r
-\r
- virtual bool supportsh264(){return true;};\r
-\r
- int WriteOutTS(const unsigned char *bulibaver,int length, int type);\r
- void WriteOutPATPMT();\r
-\r
-\r
- VPEOGLFrame *getReadyOGLFrame();\r
- void returnOGLFrame(VPEOGLFrame *frame);\r
- void recycleOGLRefFrames();\r
-\r
- virtual long long SetStartOffset(long long curreftime, bool *rsync);\r
- long long SetStartAudioOffset(long long curreftime, bool *rsync);\r
- virtual void ResetTimeOffsets();\r
-\r
-\r
-#ifdef DEV\r
- int test();\r
- int test2();\r
-#endif\r
-\r
- int initUsingOSDObjects();\r
- int shutdownUsingOSDObjects() {return shutdown();};\r
-\r
-#ifdef VPE_LIBAV_SUPPORT\r
- int getlibavDecodingMode() {return decoding_mode;};\r
-\r
-\r
-#endif\r
-\r
- private:\r
- int EnterIframePlayback();\r
- bool iframemode;\r
- bool InIframemode() {return iframemode;};\r
-\r
- UINT DeliverMediaPacket(MediaPacket packet,const UCHAR* bulibaver,UINT *samplepos);\r
-\r
- int decoding_backend; //1 omx, 2 libav, 3 omx through lib av transcoder\r
-#define VPE_DECODER_OMX 1\r
-#define VPE_DECODER_libav 2\r
-#define VPE_DECODER_OMX_libav_TRANSCODE 3\r
-\r
-\r
- bool offsetnotset;\r
- bool offsetvideonotset;\r
- bool offsetaudionotset;\r
- long long startoffset;\r
- long long lastrefvideotime;\r
- long long lastrefaudiotime;\r
- OMX_TICKS lastreftimeOMX;\r
- ULLONG lastreftimePTS;\r
-\r
- long long playbacktimeoffset; //this is the offset between the media time and system clock\r
- long long pausetimecode;\r
- bool paused;\r
-\r
- static long long GetCurrentSystemTime();\r
- static void WaitUntil(long long time);\r
- void FrameWaitforDisplay(long long pts);\r
- void AdjustAudioPTS(long long pts);\r
-\r
-\r
-\r
-\r
-#ifdef VPE_OMX_SUPPORT\r
- static OMX_ERRORTYPE EventHandler_OMX(OMX_IN OMX_HANDLETYPE handle,OMX_IN OMX_PTR appdata,\r
- OMX_IN OMX_EVENTTYPE event_type,OMX_IN OMX_U32 data1,\r
- OMX_IN OMX_U32 data2,OMX_IN OMX_PTR event_data);\r
- static OMX_ERRORTYPE EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver);\r
- static OMX_ERRORTYPE FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver);\r
-\r
- UINT DeliverMediaPacketOMX(MediaPacket packet,\r
- const UCHAR* bulibaver,\r
- UINT *samplepos);\r
-\r
- int PrepareInputBufsOMX();\r
- int DestroyInputBufsOMX();\r
-\r
- void AddOmxEvent(VPE_OMX_EVENT new_event);\r
- void ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* bulibaver);\r
-\r
- int ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type);\r
- int CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2);\r
- int EnablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait);\r
- int DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait=true);\r
-\r
-\r
- int setClockExecutingandRunning();\r
- int initClock();\r
- void destroyClock();\r
- int idleClock();\r
- int getClockAudioandInit(OMX_HANDLETYPE *p_omx_clock,OMX_U32 *p_omx_clock_output_port);\r
- int getClockVideoandInit();\r
- void LockClock() {clock_mutex.Lock();};\r
- void UnlockClock() {clock_mutex.Unlock();};\r
- void clockPause();\r
- void clockUnpause();\r
-\r
- Mutex clock_mutex; //clock mutex is now responsible for all omx stuff\r
-\r
-\r
-\r
- OMX_HANDLETYPE omx_vid_dec;\r
- OMX_HANDLETYPE omx_vid_sched;\r
- OMX_HANDLETYPE omx_vid_rend;\r
- OMX_HANDLETYPE omx_clock;\r
- int clock_references;\r
-\r
-\r
- OMX_U32 omx_codec_input_port;\r
- OMX_U32 omx_codec_output_port;\r
- OMX_U32 omx_rend_input_port;\r
- OMX_U32 omx_shed_input_port;\r
- OMX_U32 omx_shed_output_port;\r
- OMX_U32 omx_shed_clock_port;\r
- OMX_U32 omx_clock_output_port;\r
- // OMX_NALUFORMATSTYPE omx_nalu_format;\r
-\r
-\r
-\r
- int AllocateCodecsOMX();\r
- int DeAllocateCodecsOMX();\r
-\r
- vector<OMX_BUFFERHEADERTYPE*> input_bufs_omx_all;\r
- list<OMX_BUFFERHEADERTYPE*> input_bufs_omx_free;\r
- Mutex input_bufs_omx_mutex;\r
- OMX_BUFFERHEADERTYPE* cur_input_buf_omx;\r
-\r
-\r
- bool omx_running;\r
- bool omx_first_frame;\r
-\r
- Mutex omx_event_mutex;\r
-\r
- list<VPE_OMX_EVENT> omx_events;\r
-\r
- bool omx_mpeg2;\r
- bool omx_h264;\r
-\r
-\r
-\r
-\r
-#endif\r
-\r
-#ifdef VPE_LIBAV_MPEG2_TRANSCODING\r
- list<OMX_BUFFERHEADERTYPE*> input_bufs_omx_in_libav;\r
- vector<transcode_pix_fmt*> pix_fmt_omx_all;\r
- list<transcode_pix_fmt*> pix_fmt_omx_free;\r
- // this is for\r
- AVCodec *transcodecodec_libav;\r
- AVCodecContext *transcodecodec_context_libav;\r
- AVFrame transcode_frame_libav;\r
-\r
- static enum PixelFormat get_format_transcode(struct AVCodecContext *s, const enum PixelFormat *fmt);\r
- static int reget_buffer_transcode(struct AVCodecContext *c, AVFrame *pic);\r
- static int get_buffer_transcode(struct AVCodecContext *c, AVFrame *pic);\r
- OMX_BUFFERHEADERTYPE* GetFreeOMXBufferforlibav(transcode_pix_fmt **pix_trans);\r
- static void release_buffer_transcode(struct AVCodecContext *c, AVFrame *pic);\r
- void ReturnEmptyOMXBuffer_libav(OMX_BUFFERHEADERTYPE* buffer,transcode_pix_fmt *pix_fmt);\r
-\r
-\r
- UINT DeliverMediaPacketOMXTranscode(MediaPacket packet,const UCHAR* bulibaver,UINT *samplepos);\r
- int DecodePacketOMXTranscode();\r
- int InitTranscoderLibAV();\r
- int DeInitTranscoderLibAV();\r
-\r
-\r
-#endif\r
-\r
-#if defined(VPE_LIBAV_MPEG2_TRANSCODING) || defined(VPE_LIBAV_SUPPORT)\r
- AVPacket incom_packet_libav;\r
- int incom_packet_libav_size;\r
-\r
-\r
-#endif\r
-\r
-#ifdef VPE_LIBAV_SUPPORT // this is the data for software decoding subject to removal\r
-\r
- const static int VPE_NO_XVMC=0;\r
- const static int VPE_XVMC_MOCOMP=1;\r
- const static int VPE_XVMC_IDCT=2;\r
-\r
- int decoding_mode;\r
-\r
- AVCodec *mpeg2codec_libav;\r
- AVCodecContext *mpeg2codec_context_libav;\r
- vector<AVFrame*> dec_frame_libav_all;\r
- list<AVFrame*> dec_frame_libav_free;\r
- list<AVFrame*> dec_frame_libav_upload_and_view_pending;\r
- list<VPE_FrameBuf*> dec_frame_libav_upload_only_pending;\r
- //AVFrame* dec_frame_libav_uploading;\r
- VPE_FrameBuf* dec_frame_libav_uploading_framebuf;\r
- AVFrame* dec_frame_libav_decoding;\r
-\r
- void add_dec_frame_upload_only(struct AVCodecContext *s,const AVFrame* data);\r
-\r
- vector<VPE_FrameBuf*> all_frame_bufs;\r
- list<VPE_FrameBuf*> free_frame_bufs;\r
- list<VPE_FrameBuf*> locked_libav_frame_buf;\r
- list<VPE_FrameBuf*> locked_uploading_frame_buf;\r
-\r
- VPE_FrameBuf *getFrameBuf(unsigned int *size); //for libav\r
- void releaseFrameBufLibav(VPE_FrameBuf*data);\r
- void lockFrameBufUpload(VPE_FrameBuf* data);\r
- void releaseFrameBufUpload(VPE_FrameBuf* data);\r
-\r
- unsigned int framebuf_framenum;\r
-\r
- Mutex vpe_framebuf_mutex;\r
-\r
-\r
-\r
-\r
- Mutex dec_frame_libav_mutex;\r
-\r
-\r
-\r
- UINT DeliverMediaPacketlibav(MediaPacket packet,const UCHAR* bulibaver,UINT *samplepos);\r
- int AllocateCodecsLibav();\r
- int DeAllocateCodecsLibav();\r
- int DecodePacketlibav();\r
-\r
- static enum PixelFormat get_format_libav(struct AVCodecContext *s, const enum PixelFormat *fmt);\r
- static int get_buffer_libav(struct AVCodecContext *c, AVFrame *pic);\r
- static int reget_buffer_libav(struct AVCodecContext *c, AVFrame *pic);\r
- static void release_buffer_libav(struct AVCodecContext *c, AVFrame *pic);\r
-\r
- static void draw_horiz_band_libav(struct AVCodecContext *s, const AVFrame *src, int offset[4], int y, int type, int height);\r
-\r
- bool libav_running;\r
- bool libav_hastime; // signals if a pts is now\r
- long long libav_time;\r
-\r
- int libavwidth,libavheight,libavpixfmt;\r
- GLMocoShader *moco_shader;\r
-\r
- \r
-\r
-\r
- vector<VPEOGLFrame*> all_ogl_frames;\r
- list<VPEOGLFrame*> free_ogl_frames;\r
- list<VPEOGLFrame*> recycle_ref_ogl_frames;\r
- list<VPEOGLFrame*> ready_ogl_frames;\r
- int ogl_forward_ref_frame_num;\r
- int ogl_backward_ref_frame_num;\r
- VPEOGLFrame* ogl_forward_ref_frame;\r
- VPEOGLFrame* ogl_backward_ref_frame;\r
-\r
- bool ogl_frame_outside;\r
- Mutex ogl_frame_mutex;\r
-\r
- int AllocateYUV400OglTexture(VPEOGLFrame* outframe,int width,int height,int stride);\r
- int AllocateYUV444OglTexture(VPEOGLFrame* outframe,int width,int height,int stride);\r
-#endif\r
-\r
- virtual void threadMethod();\r
- virtual void threadPostStopCleanup();\r
-\r
-\r
-\r
- bool firstsynched;\r
-\r
- EGLDisplay egl_display;\r
- EGLSurface egl_surface;\r
- EGLContext egl_context;\r
-#ifdef BENCHMARK_FPS\r
- unsigned int time_in_decoder;\r
- unsigned int num_frames;\r
- unsigned int time_in_decoder_gl;\r
- unsigned int num_frames_gl;\r
-#endif\r
-\r
- \r
- MediaPacket mediapacket;\r
-};\r
-\r
-#endif\r