\r
if (audioEnabled)\r
{\r
- alen = Demuxer::getInstance()->writeAudio();\r
+ bool newdata=false;\r
+ alen = Demuxer::getInstance()->writeAudio(&newdata);\r
\r
+ if (newdata) cb.call(this);\r
if (alen)\r
{\r
- cb.call(this);\r
-// Log::getInstance()->log("Afeed", Log::DEBUG, "written");\r
+ //Log::getInstance()->log("Afeed", Log::DEBUG, "written");\r
}\r
else\r
{\r
AudioVPE::AudioVPE()
{
initted = 0;
- lastpacketnum=-1;
- currentpacketnum=-1;
streamType = 0;
volume = 20;
muted = 0;
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;
+int AudioVPE::init(UCHAR tstreamType) {
+ if (initted)
+ return 0;
+ initted = 1;
-// // if ((fdAudio = open("/dev/adec_mpg", O_RDWR | O_NONBLOCK)) < 0) return 0;
- // if ((fdAudio = open("/dev/adec_mpg", O_WRONLY)) < 0) return 0;
+ streamType = tstreamType;
- streamType = tstreamType;
+ if (!initAllParams()) {
+ shutdown();
+ return 0;
+ }
- if (!initAllParams())
- {
- shutdown();
- return 0;
- }
+ unMute();
- unMute();
- // Set the volume variable to what the hardware is set at now
- int hwvol = -1;
-/* int hwvolFail = ioctl(fdAudio, AV_GET_AUD_VOLUME, &hwvol);
- if (!hwvolFail)
- {
- volume = 20 - ((hwvol >> 16) & 0xFF);
- if ((volume < 0) || (volume > 20)) volume = 20;
- }*/
- return 1;
+ 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()
{
if (!initted) return 0;
initted = 0;
- //close(fdAudio);
+
+ 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) {
break;
};
- if (hdmi)
+ if (!hdmi)
VDR::getInstance()->configSave("AudioOMX", "AudioOutput", "analog");
else
VDR::getInstance()->configSave("AudioOMX", "AudioOutput", "HDMI");
+
+
+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;
return 1;
}
-int AudioVPE::play()
+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
{
- if (!initted) return 0;
- lastpacketnum=-1;
- currentpacketnum=-1;
+ 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;
- //if (ioctl(fdAudio, AV_SET_AUD_PLAY, 0) != 0) 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;
}
return 1;
}
-int AudioVPE::pause()
-{
- if (!initted) return 0;
+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);
- // if (ioctl(fdAudio, AV_SET_AUD_PAUSE, 1) != 0) return 0;
- return 1;
+ }
+ vw->UnlockClock();
+ vw->clockPause();
+ }
+ return 1;
}
int AudioVPE::unPause()
{
if (!initted) return 0;
-
- // if (ioctl(fdAudio, AV_SET_AUD_UNPAUSE, 1) != 0) return 0;
+ if (paused) {
+ paused=false; // may be also change omx clock
+ VideoVPEOGL *vw = (VideoVPEOGL*) Video::getInstance();
+ vw->clockUnpause();
+ }
return 1;
}
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");
packet = mplist.front();
}
-UINT AudioVPE::DeliverMediaSample(UCHAR* buffer, UINT* samplepos)
-{/*
- VideoVPEOGL *video=(VideoVPEOGL*)Video::getInstance();
- //Log::getInstance()->log("Audio", Log::DEBUG, "lastpacket %d lastbuddypacket %d currentpacket %d",lastpacketnum,video->getLastPacketNum(),packet.index);
- currentpacketnum=packet.index;
- if (lastpacketnum!=-1 && packet.index-1!=lastpacketnum && packet.index-1>video->getLastPacketNum()) return 0; //Not in order
-
- //format pes
- switch (packet.type) {
- case MPTYPE_MPEG_AUDIO:
- buffer[packet.pos_buffer + 3]=0xc0; break;
- case MPTYPE_AC3:
- buffer[packet.pos_buffer +buffer[packet.pos_buffer+8]+9]=0x80;
- buffer[packet.pos_buffer + 3]=0xbd; break;
- break;
- default:
- case MPTYPE_AC3_PRE13://Not tested no recording availiable
- buffer[packet.pos_buffer + 3]=0xbd; break;
- break;
- };
-
- if (packet.type!=lastAType && lastpacketnum!=-1){//Format Change //Push data out !
- video->deinitMuxer();
- lastAType=packet.type;
- video->initMuxer();
- }
- lastAType=packet.type;
-
-
- /* Mutex *mutex=video->getMuxMutex();
- mutex->Lock();
- FILE *muxout=video->getMuxFile();
- if (!muxout) {mutex->Unlock(); return 0;}*
- int written=0;
- //written=fwrite(buffer + packet.pos_buffer,1,packet.length,muxout);
- written=video->WriteOutTS(buffer + packet.pos_buffer,packet.length,packet.type);
- lastpacketnum=packet.index;
-
- //mutex->Unlock();
-
- //Log::getInstance()->log("Audio", Log::DEBUG, "wrote %d bytes to mux",written);
-
- if (written == (int)packet.length) { *samplepos = 0; return 1;}
- if (written <= 0) {
- return 0;
- }
- *samplepos = written;*/
- // Handle a partial write. Is this possible? Should we bother? No!
-
- *samplepos=packet.length;
- return 1;
+UINT AudioVPE::DeliverMediaSample(UCHAR* buffer, UINT* samplepos) {
+ DeliverMediaPacket(packet, buffer, samplepos);
+ if (*samplepos == packet.length) {
+ *samplepos = 0;
+ return 1;
+ } else
+ return 0;
}
-void AudioVPE::ResetTimeOffsets()
-{
+
+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();
+}
+
+
\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
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
- virtual long long SetStartOffset(long long curreftime, bool *rsync) { return 0; };\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
- int getLastPacketNum() {return lastpacketnum;}; \r
- int getCurrentPacketNum(){return currentpacketnum;};\r
+\r
UCHAR getLastAType() {return lastAType;}\r
\r
bool loadOptionsfromServer(VDR* vdr);\r
int initAllParams();\r
UCHAR streamType;\r
UCHAR lastAType;\r
- int lastpacketnum;\r
- int currentpacketnum;\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
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 STRTOULL _strtoui64 */\r
#define STRTOUL strtoul\r
#define CLOSESOCKET closesocket\r
+ #define DEFAULT_TCP_WINDOWSIZENR 1 /*=2048*/\r
\r
\r
#else\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 Alsa with ffmpeg in the end\r
- #define Video_TYPE VideoVPEOGL // This is Video based on VPE (Vomp Presentation Engine) should support OpenMax and ffmpeg and opengl in the end\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
\r
\r
\r
#define VPE_OMX_VIDEO_REND "OMX.broadcom.video_render"\r
#define VPE_OMX_VIDEO_DEINTERLACE "OMX.broadcom.image_fx"\r
#define VPE_OMX_CLOCK "OMX.broadcom.clock"\r
+ #define VPE_OMX_AUDIO_DECODER "OMX.broadcom.audio_decode"\r
+ #define VPE_OMX_AUDIO_REND "OMX.broadcom.audio_render"\r
\r
//#define VPE_LIBAV_SUPPORT\r
// #define VPE_LIBAV_MPEG2_TRANSCODING\r
\r
+ #define DEFAULT_TCP_WINDOWSIZENR 6 /*=2048*/\r
+\r
#endif\r
#ifdef VOMP_PLATTFORM_MVP\r
#define Remote_TYPE RemoteMVP\r
#define OsdStartDev "/dev/stbgfx"\r
#define Audio_TYPE AudioMVP\r
#define Video_TYPE VideoMVP\r
+ #define DEFAULT_TCP_WINDOWSIZENR 1 /*=2048*/\r
#endif\r
\r
#ifdef VOMP_PLATTFORM_NMT // This was the attempt to port vomp to nmt, it failed but maybe the code is useful at some time\r
#define OsdStartDev ""\r
#define Audio_TYPE AudioNMT\r
#define Video_TYPE VideoNMT\r
+ #define DEFAULT_TCP_WINDOWSIZENR 1 /*=2048*/\r
\r
#endif\r
\r
arcnt = 0;\r
}\r
\r
-bool Demuxer::writeAudio()\r
+bool Demuxer::writeAudio(bool * dataavail)\r
{\r
- return audiostream.drain();\r
+ return audiostream.drain(dataavail);\r
}\r
\r
-bool Demuxer::writeVideo()\r
+bool Demuxer::writeVideo(bool * dataavail)\r
{\r
- return videostream.drain();\r
+ return videostream.drain(dataavail);\r
}\r
\r
-bool Demuxer::writeTeletext()\r
+bool Demuxer::writeTeletext(bool * dataavail)\r
{\r
- return teletextstream.drain();\r
+ return teletextstream.drain(dataavail);\r
}\r
\r
bool Demuxer::submitPacket(PESPacket& packet)\r
void setAudioStream(int id);\r
void setTeletextStream(int id);\r
void setDVBSubtitleStream(int id);\r
- bool writeAudio();\r
- bool writeVideo();\r
- bool writeTeletext();\r
+ bool writeAudio(bool * dataavail=NULL);\r
+ bool writeVideo(bool * dataavail=NULL);\r
+ bool writeTeletext(bool * dataavail=NULL);\r
\r
virtual int scan(UCHAR* buf, int len) = 0;\r
virtual int findPTS(UCHAR* buf, int len, ULLONG* dest) = 0;\r
if (!teletext) return 0;\r
teletext->setRecordigMode(true);\r
unsigned int demux_video_size=2097152;\r
- if (video->supportsh264()) demux_video_size*=5;\r
+ unsigned int demux_audio_size=524288;\r
+ if (video->supportsh264()) {\r
+ demux_video_size*=5*2;//5;\r
+ demux_audio_size*=2;\r
+ }\r
\r
- if (!demuxer->init(this, audio, video,teletext, demux_video_size,524288,65536, framespersecond, subtitles))\r
+ if (!demuxer->init(this, audio, video,teletext, demux_video_size,demux_audio_size,65536, framespersecond, subtitles))\r
{\r
logger->log("Player", Log::ERR, "Demuxer failed to init");\r
shutdown();\r
while(1)\r
{\r
\r
-// logger->log("PlayerLiveTV", Log::DEBUG, "VS: %d pA %d",videoStartup,pendingAudioPlay);\r
+ logger->log("PlayerLiveTV", Log::DEBUG, "VS: %d pA %d",videoStartup,pendingAudioPlay);\r
if (videoStartup && !pendingAudioPlay) // we are in S_VIDEOSTARTUP, afeed has signalled that it has written some data\r
{\r
logger->log("PlayerLiveTV", Log::DEBUG, "Enter prebuffering");\r
\r
while(streamChunks.size())\r
{\r
+ logger->log("PlayerLiveTV", Log::DEBUG, "chunk mark1");\r
chunkToDemuxer();\r
+ logger->log("PlayerLiveTV", Log::DEBUG, "chunk mark2");\r
\r
if (state == S_PREBUFFERING)\r
{\r
+ logger->log("PlayerLiveTV", Log::DEBUG, "chunk mark3");\r
++preBufferCount;\r
ULONG percentDone = (ULONG)(preBufferCount / (float)preBufferAmount * 100);\r
logger->log("PlayerLiveTV", Log::DEBUG, "Prebuffering %lu%%", percentDone);\r
void Remote::EnterLearningMode(UCHAR command)
{
- learnmode = command; //Armed
+ learnmode = command; //Armed
}
void Remote::ResetToDefault()
translist[W_G_HCW(W_HCW_KC,KEY_PLAYPAUSE)] = PLAYPAUSE;
translist[W_G_HCW(W_HCW_KC,KEY_P)] = PLAYPAUSE;
translist[W_G_HCW(W_HCW_KC,KEY_NEXT)] = SKIPFORWARD;
+ translist[W_G_HCW(W_HCW_KC,KEY_F2)] = SKIPFORWARD;
translist[W_G_HCW(W_HCW_KC,KEY_PREVIOUS)] = SKIPBACK;
+ translist[W_G_HCW(W_HCW_KC,KEY_F1)] = SKIPBACK;
translist[W_G_HCW(W_HCW_KC,KEY_FORWARD)] = FORWARD;
+ translist[W_G_HCW(W_HCW_KC,KEY_F)] = FORWARD;
translist[W_G_HCW(W_HCW_KC,KEY_BACK)] = REVERSE;
+ translist[W_G_HCW(W_HCW_KC,KEY_R)] = REVERSE;
translist[W_G_HCW(W_HCW_KC,KEY_MUTE)] = MUTE;
translist[W_G_HCW(W_HCW_KC,KEY_F9)] = VOLUMEUP;
translist[W_G_HCW(W_HCW_KC,KEY_F10)] = VOLUMEDOWN;
return ret;\r
}\r
\r
-bool Stream::drain()\r
+bool Stream::drain(bool * dataavail)\r
{\r
bool ret = false;\r
+ if (dataavail) *dataavail=false;\r
lock();\r
UINT listlength = mediapackets.size();\r
if (listlength != 0)\r
{\r
draintarget->PrepareMediaSample(mediapackets, cur_packet_pos);\r
unLock();\r
+ if (dataavail) *dataavail=true;\r
UINT consumed = draintarget->DeliverMediaSample(outbuf, &cur_packet_pos);\r
lock();\r
if (consumed != 0) ret = true;\r
void shutdown();
void flush();
int put(const UCHAR* inbuf, int len, UCHAR type,unsigned int index);
- bool drain();
+ bool drain(bool * dataavail=NULL);
private:
MediaPacketList mediapackets;
void ThreadP::threadStop()
{
- threadActive = 0;
- // Signal thread here in case it's waiting
- threadSignal();
- pthread_join(pthread, NULL);
- this->threadPostStopCleanup();
+ if (threadActive) { // we need this, on some implementations this will fail, if already stopped
+ threadActive = 0;
+ // Signal thread here in case it's waiting
+ threadSignal();
+ pthread_join(pthread, NULL);
+ this->threadPostStopCleanup();
+ }
}
void ThreadP::threadCancel()
{
- threadActive = 0;
- pthread_cancel(pthread);
- pthread_join(pthread, NULL);
- this->threadPostStopCleanup();
+ if (threadActive) {
+ threadActive = 0;
+ pthread_cancel(pthread);
+ pthread_join(pthread, NULL);
+ this->threadPostStopCleanup();
+ }
}
VideoVPEOGL::VideoVPEOGL()
{
- lastpacketnum=-1;
#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
if (initted) return 0;
initted = 1;
-// if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
-
if (!setFormat(tformat)) { shutdown(); return 0; }
if (!setConnection(COMPOSITERGB)) { shutdown(); return 0; }
if (!setAspectRatio(ASPECT4X3)) { shutdown(); return 0; }
setTVsize(ASPECT4X3);
-/* if (format == PAL) setLetterboxBorder("38");
- else setLetterboxBorder("31");*/
-
- /* new stulibav */
{
if (!initted) return 0;
decoding_backend=0;
+ iframemode=false;
#ifdef VPE_OMX_SUPPORT
bool doomx=true;
Log::getInstance()->log("Video", Log::DEBUG, "enter play");
#endif
#ifdef VPE_OMX_SUPPORT
-int VideoVPEOGL::AllocateCodecsOMX()
+
+int VideoVPEOGL::initClock()
{
OMX_ERRORTYPE error;
- static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
+ clock_mutex.Lock();
+ if (clock_references==0)
+ {
- Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX");
- //Clock, move later to audio
+ static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
+ omx_events.clear();
- omx_events.clear();
+ error=OMX_GetHandle(&omx_clock,VPE_OMX_CLOCK,NULL,&callbacks);
- 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;
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Video", Log::DEBUG, "Init OMX clock failed %x", error);
- DeAllocateCodecsOMX();
+ 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;
+ }
- /* 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);
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);
+ 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;
clock_conf.eState=OMX_TIME_ClockStateWaitingForStartTime;
clock_conf.nStartTime=0;
clock_conf.nOffset=0;
- clock_conf.nWaitMask=OMX_CLOCKPORT0;
+ 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){
+ if (error!=OMX_ErrorNone) {
Log::getInstance()->log("Video", Log::DEBUG, "Clock IndexConfigTimeClockState failed %x", error);
- DeAllocateCodecsOMX();
- return 0;
}
+ omx_clock_output_port=p_param.nStartPortNumber;
+ clock_mutex.Unlock();
- OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refclock;
- memset(&refclock,0,sizeof(refclock));
- refclock.nSize=sizeof(refclock);
- refclock.nVersion.nVersion=OMX_VERSION;
+ return 1;
+}
- if (/*AUDIO*/ false) {
- refclock.eClock=OMX_TIME_RefClockAudio;
- } else {
- refclock.eClock=OMX_TIME_RefClockVideo;
- }
- error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeActiveRefClock,&refclock);
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Video", Log::DEBUG, "Clock OMX_IndexConfigTimeActiveRefClock failed %x", error);
- DeAllocateCodecsOMX();
- return 0;
+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);
}
- if (!ChangeComponentState(omx_clock,OMX_StateIdle)) {
- Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Idle");
- DeAllocateCodecsOMX();
- return 0;
+ 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};
- /* TODO end */
+ 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 {
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;
}
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));
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;
}
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;
}
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;
}
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;
}
-
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_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;
}
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;
}
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;
}
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();
- if (!ChangeComponentState(omx_clock,OMX_StateExecuting)) {
- Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Execute failed");
- DeAllocateCodecsOMX();
- return 0;
+ 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;
+ 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){
+ 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)
+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);
}
-int VideoVPEOGL::EnablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait)
+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);
}
-int VideoVPEOGL::DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait)
+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);
-int VideoVPEOGL::CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2)
+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) {
-int VideoVPEOGL::PrepareInputBufsOMX()
+int VideoVPEOGL::PrepareInputBufsOMX() //needs to be called with locked mutex
{
OMX_ERRORTYPE error;
OMX_PARAM_PORTDEFINITIONTYPE port_def_type;
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=10;
+ 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);
return 1;
}
-int VideoVPEOGL::DestroyInputBufsOMX()
+int VideoVPEOGL::DestroyInputBufsOMX() //need s to be called with locked mutex
{
OMX_ERRORTYPE error;
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);
// first stop the omx elements
if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) {
Log::getInstance()->log("Video", Log::DEBUG, "vid_dec ChangeComponentState");
- DeAllocateCodecsOMX();
- return 0;
- }
- if (!ChangeComponentState(omx_clock,OMX_StateIdle)) {
- Log::getInstance()->log("Video", Log::DEBUG, "vid_clock ChangeComponentState");
- DeAllocateCodecsOMX();
- return 0;
}
+ clock_mutex.Unlock();
+
+ idleClock();
+ clock_mutex.Lock();
+
if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) {
Log::getInstance()->log("Video", Log::DEBUG, "vid_shed ChangeComponentState");
- DeAllocateCodecsOMX();
- return 0;
+
}
if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) {
Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState");
- DeAllocateCodecsOMX();
- return 0;
+
}
}
- if (!CommandFinished(omx_vid_dec,OMX_CommandFlush,omx_codec_input_port)) {
- Log::getInstance()->log("Video", Log::DEBUG, "flush cmd codec input failed");
- }
-
- error=OMX_SendCommand(omx_vid_dec,OMX_CommandFlush, omx_codec_output_port, NULL);
- if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush codec out failed %x", error);
-
- }
-
-
-
error=OMX_SendCommand(omx_vid_sched,OMX_CommandFlush, omx_shed_input_port, NULL);
if (error!=OMX_ErrorNone){
Log::getInstance()->log("Video", Log::DEBUG, "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_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_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_FreeHandle(omx_vid_dec);
error=OMX_FreeHandle(omx_vid_sched);
error=OMX_FreeHandle(omx_vid_rend);
- error=OMX_FreeHandle(omx_clock);
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
int VideoVPEOGL::stop()
{
if (!initted) return 0;
+ iframemode=false;
#ifdef VPE_OMX_SUPPORT
//Check if libav mode
{
if (!initted) return 0;
+ iframemode=false;
+ DeAllocateCodecsOMX();
// if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0;
return 1;
}
ULLONG VideoVPEOGL::getCurrentTimestamp()
{
-
+ if (iframemode) return 0;
return lastreftimePTS;
}
target_time-current_time);
WaitUntil(target_time);
- Log::getInstance()->log("Video", Log::DEBUG, "Wait for display out");
+ 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;
+
+ //}
}
long long current_media_time=GetCurrentSystemTime()+playbacktimeoffset;
if (packet.synched &&
- (packet.presentation_time<0 || // preroll skip frames
- (packet.presentation_time-1000000LL)>(current_media_time))) { // we are late skip
- Log::getInstance()->log("Video", Log::DEBUG, "DeliverMediaPacketOMX Preroll or too late %lld %lld", packet.presentation_time,current_media_time);
+ (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;
-/* OMX_PARAM_PORTDEFINITIONTYPE port_image;
- memset(&port_image,0,sizeof(port_image));
- port_image.nSize=sizeof(port_image);
- port_image.nVersion.nVersion=OMX_VERSION;
- port_image.nPortIndex =omx_codec_output_port;
- error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_image);
- if (error!= OMX_ErrorNone){
- Log::getInstance()->log("Video", Log::DEBUG, "OMX_GetParameter failed %x", error);
- }
- Log::getInstance()->log("Video", Log::DEBUG, "Image port %d %d", port_image.format.video.nFrameWidth , port_image.format.video.nFrameHeight);*/
-
- /*First Check, if we have an audio sample*/
+ /*First Check, if we have an video sample*/
if (iframemode) {
//samplepos=0;
MILLISLEEP(10);
if (error!=OMX_ErrorNone){
Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error);
}
+ FrameWaitforDisplay(lastreftimeOMX);
cur_input_buf_omx=NULL;
}
}
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);
- cur_input_buf_omx=NULL;//write out old data
+
}
- // reftime1=packet.presentation_time;
- // reftime2=reftime1+1;
firstsynched=true;
} else {
if (!firstsynched) {//
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) {
Log::getInstance()->log("Video", Log::DEBUG, "packet synched marker");
#endif
-bool VideoVPEOGL::displayIFrame(const UCHAR* buffer, UINT length)
-{
- //write(fdVideo, buffer, length);
- if (!iframemode) EnterIframePlayback();
-// WriteOutTS(buffer,length, h264?MPTYPE_VIDEO_H264 :MPTYPE_VIDEO_MPEG2 );
+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
- lastpacketnum=-1;
- return true;
+ }
+ 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);
+ }
- return 0;
+ cur_input_buf_omx = NULL;
+ }
+ clock_mutex.Unlock();
+ iframemode=true;
+
+ return 1;
}
\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
long long SetStartAudioOffset(long long curreftime, bool *rsync);\r
virtual void ResetTimeOffsets();\r
\r
- static long long GetCurrentSystemTime();\r
- static void WaitUntil(long long time);\r
- void FrameWaitforDisplay(long long pts);\r
-\r
-\r
-\r
\r
- int getLastPacketNum() {return lastpacketnum;}; \r
#ifdef DEV\r
int test();\r
int test2();\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
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
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_rend_output_port;\r
OMX_U32 omx_shed_input_port;\r
OMX_U32 omx_shed_output_port;\r
OMX_U32 omx_shed_clock_port;\r
\r
\r
bool firstsynched;\r
- int lastpacketnum;\r
\r
EGLDisplay egl_display;\r
EGLSurface egl_surface;\r
option = new Option(8, "VDR-Pri 0=OK !See forums!", "General", "Live priority", Option::TYPE_INT, 100, 0, 0, NULL);\r
options.push_back(option);\r
wop->addOptionLine(option);\r
- option = new Option(13, "TCP receive window size", "Advanced", "TCP receive window", Option::TYPE_TEXT, 7, 1, 0, options13);\r
+ option = new Option(13, "TCP receive window size", "Advanced", "TCP receive window", Option::TYPE_TEXT, 7, /*1*/DEFAULT_TCP_WINDOWSIZENR, 0, options13);\r
options.push_back(option);\r
wop->addOptionLine(option);\r
option = new Option(14, "Use WSS (PAL only)", "General", "WSS", Option::TYPE_TEXT, 2, 0, 0, options14);\r