2 Copyright 2004-2005 Chris Tallon, 2009 Marten Richter
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include "woptionpane.h"
27 #include "osdopenvg.h"
36 lastAType = MPTYPE_MPEG_AUDIO;
42 canpass_pcm_mch=false;
44 prefered_ac3=0; //0 stereo PCM, 1 passthrough 2 Multichannel PCM
52 omx_aud_rend/*dec*/=0;
53 cur_input_buf_omx=NULL;
56 ac3codec_context_libav=NULL;
59 mp23codec_context_libav=NULL;
61 decompress_buffer=NULL;
62 decompress_buffer_size=0;
63 decompress_buffer_filled=0;
71 int AudioOMX::init(UCHAR tstreamType) {
76 streamType = tstreamType;
78 if (!initAllParams()) {
85 decompress_buffer_size=20000;
86 decompress_buffer=(UCHAR*)malloc(decompress_buffer_size);
87 decompress_buffer_filled=0;
92 av_log_set_flags(AV_LOG_SKIP_REPEATED);
94 ac3codec_libav = avcodec_find_decoder(CODEC_ID_AC3);
95 if (ac3codec_libav == NULL) {
96 Log::getInstance()->log("Audio", Log::DEBUG,
97 "Find libav ac3 decoder failed");
101 mp23codec_libav = avcodec_find_decoder(CODEC_ID_MP3);
102 if (mp23codec_libav == NULL) {
103 Log::getInstance()->log("Audio", Log::DEBUG,
104 "Find libav mpeg audio decoder failed");
108 aaclatmcodec_libav = avcodec_find_decoder(CODEC_ID_AAC_LATM);
109 if (aaclatmcodec_libav == NULL) {
110 Log::getInstance()->log("Audio", Log::DEBUG,
111 "Find libav aac latm decoder failed");
117 ret=vc_tv_hdmi_audio_supported( EDID_AudioFormat_eMPEG1,2,EDID_AudioSampleRate_e48KHz,0);
121 Log::getInstance()->log("Audio", Log::NOTICE,
122 "TV hdmi supports mpeg1 layer 1 and 2");
124 ret=vc_tv_hdmi_audio_supported( EDID_AudioFormat_eMP3,2,EDID_AudioSampleRate_e48KHz,0);
128 Log::getInstance()->log("Audio", Log::NOTICE,
129 "TV hdmi supports mpeg1 layer 3");
132 ret=vc_tv_hdmi_audio_supported( EDID_AudioFormat_eAC3,6,EDID_AudioSampleRate_e48KHz,0);
135 Log::getInstance()->log("Audio", Log::NOTICE,
136 "TV hdmi supports AC3");
138 ret=vc_tv_hdmi_audio_supported( EDID_AudioFormat_eAAC,6,EDID_AudioSampleRate_e48KHz,0);
142 Log::getInstance()->log("Audio", Log::NOTICE,
143 "TV hdmi supports AAC");
146 canpass_pcm_mch=false;
151 int AudioOMX::initAllParams()
153 return (setStreamType(streamType) && setChannel() && setSource());
156 int AudioOMX::shutdown()
158 if (!initted) return 0;
161 Log::getInstance()->log("Audio", Log::DEBUG, "audio shutdown called");
162 DeAllocateCodecsOMX();
164 free(decompress_buffer);
165 decompress_buffer=NULL;
166 decompress_buffer_size=0;
167 decompress_buffer_filled=0;
172 bool AudioOMX::loadOptionsfromServer(VDR* vdr)
174 Log::getInstance()->log("Audio", Log::DEBUG, "AudioOMX config load");
175 char *name=vdr->configLoad("AudioOMX","AC3DecodingMode");
178 if (STRCASECMP(name, "PCM") == 0) {
180 } else if (STRCASECMP(name, "Passthrough") == 0) {
182 } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
187 name = vdr->configLoad("AudioOMX", "Mp2DecodingMode");
190 if (STRCASECMP(name, "PCM") == 0) {
192 } else if (STRCASECMP(name, "Passthrough") == 0) {
194 } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
199 name = vdr->configLoad("AudioOMX", "AACDecodingMode");
202 if (STRCASECMP(name, "PCM") == 0) {
204 } else if (STRCASECMP(name, "Passthrough") == 0) {
206 } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
211 name = vdr->configLoad("AudioOMX", "Mp3DecodingMode");
214 if (STRCASECMP(name, "PCM") == 0) {
216 } else if (STRCASECMP(name, "Passthrough") == 0) {
218 } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
223 name = vdr->configLoad("AudioOMX", "AudioOutput");
226 if (STRCASECMP(name, "analog") == 0) {
228 } else if (STRCASECMP(name, "HDMI") == 0) {
238 bool AudioOMX::handleOptionChanges(Option* option)
240 if (Audio::handleOptionChanges(option))
242 switch (option->id) {
244 if (STRCASECMP(option->options[option->userSetChoice], "analog") == 0) {
246 } else if (STRCASECMP(option->options[option->userSetChoice], "HDMI")
254 if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
256 } else if (STRCASECMP(option->options[option->userSetChoice],
257 "Passthrough") == 0) {
259 } else if (STRCASECMP(option->options[option->userSetChoice],
260 "PCMMultichannel") == 0) {
266 if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
268 } else if (STRCASECMP(option->options[option->userSetChoice],
269 "Passthrough") == 0) {
271 } else if (STRCASECMP(option->options[option->userSetChoice],
272 "PCMMultichannel") == 0) {
278 if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
280 } else if (STRCASECMP(option->options[option->userSetChoice],
281 "Passthrough") == 0) {
283 } else if (STRCASECMP(option->options[option->userSetChoice],
284 "PCMMultichannel") == 0) {
290 if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
292 } else if (STRCASECMP(option->options[option->userSetChoice],
293 "Passthrough") == 0) {
295 } else if (STRCASECMP(option->options[option->userSetChoice],
296 "PCMMultichannel") == 0) {
306 bool AudioOMX::saveOptionstoServer()
309 switch (prefered_ac3) {
311 VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode", "PCM");
314 VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode",
318 VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode",
323 switch (prefered_aac) {
325 VDR::getInstance()->configSave("AudioOMX", "AACDecodingMode", "PCM");
328 VDR::getInstance()->configSave("AudioOMX", "AACDecodingMode",
332 VDR::getInstance()->configSave("AudioOMX", "AACDecodingMode",
337 switch (prefered_mp2) {
339 VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode", "PCM");
342 VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode",
346 VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode",
351 switch (prefered_mp3) {
353 VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode", "PCM");
356 VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode",
360 VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode",
366 VDR::getInstance()->configSave("AudioOMX", "AudioOutput", "analog");
368 VDR::getInstance()->configSave("AudioOMX", "AudioOutput", "HDMI");
374 /*Option(UINT id, const char* displayText, const char* configSection, const char* configKey, UINT optionType,
375 UINT numChoices, UINT defaultChoice, UINT startInt,
376 const char * const * options, const char * const * optionkeys = NULL, AbstractOption* handler=NULL);*/
378 bool AudioOMX::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
380 if (!Audio::addOptionsToPanes(panenumber,options,pane)) return false;
387 static const char* audioopts[]={"analog","HDMI"};
388 option = new Option(4,tr("Audio Output"), "AudioOMX","AudioOutput",Option::TYPE_TEXT,2,0,0,audioopts,NULL,false,this);
389 options->push_back(option);
390 pane->addOptionLine(option);
393 char **ac3opts=new char *[3];
395 ac3opts[i]=new char[strlen("PCM")+1];
396 strcpy(ac3opts[i],"PCM");
399 ac3opts[i]=new char[strlen("Passthrough")+1];
400 strcpy(ac3opts[i],"PassThrough");
403 if (canpass_pcm_mch) {
404 ac3opts[i]=new char[strlen("PCMMultichannel")+1];
405 strcpy(ac3opts[i],"PCMMultichannel");
408 option = new Option(1 ,tr("AC3 HDMI Mode"), "AudioOMX", "AC3DecodingMode", Option::TYPE_TEXT, i, 0, 0, ac3opts,NULL,true, this);
409 options->push_back(option);
410 pane->addOptionLine(option);
412 /* char **aacopts = new char *[3];
414 aacopts[i] = new char[strlen("PCM") + 1];
415 strcpy(mp2opts[i], "PCM");
418 aacopts[i] = new char[strlen("Passthrough") + 1];
419 strcpy(aacopts[i], "PassThrough");
422 if (canpass_pcm_mch) {
423 aacopts[i] = new char[strlen("PCMMultichannel") + 1];
424 strcpy(aacopts[i], "PCMMultichannel");
427 option = new Option(5, tr("Mp2 HDMI Mode"), "AudioOMX",
428 "AACDecodingMode", Option::TYPE_TEXT, i, 0, 0,
429 aacopts, NULL, true, this);
430 options->push_back(option);
431 pane->addOptionLine(option);
434 char **mp2opts = new char *[3];
436 mp2opts[i] = new char[strlen("PCM") + 1];
437 strcpy(mp2opts[i], "PCM");
440 mp2opts[i] = new char[strlen("Passthrough") + 1];
441 strcpy(mp2opts[i], "PassThrough");
444 if (canpass_pcm_mch) {
445 mp2opts[i] = new char[strlen("PCMMultichannel") + 1];
446 strcpy(mp2opts[i], "PCMMultichannel");
449 option = new Option(2, tr("Mp2 HDMI Mode"), "AudioOMX",
450 "Mp2DecodingMode", Option::TYPE_TEXT, i, 0, 0,
451 mp2opts, NULL, true, this);
452 options->push_back(option);
453 pane->addOptionLine(option);
455 char **mp3opts = new char *[3];
457 mp3opts[i] = new char[strlen("PCM") + 1];
458 strcpy(mp3opts[i], "PCM");
461 mp3opts[i] = new char[strlen("Passthrough") + 1];
462 strcpy(mp3opts[i], "PassThrough");
465 if (canpass_pcm_mch) {
466 mp3opts[i] = new char[strlen("PCMMultichannel") + 1];
467 strcpy(mp3opts[i], "PCMMultichannel");
470 option = new Option(3, tr("Mp3 HDMI Mode"), "AudioOMX",
471 "Mp2DecodingMode", Option::TYPE_TEXT, i, 0, 0, mp3opts,
473 options->push_back(option);
474 pane->addOptionLine(option);*/
475 // Comment unsupported modes out
488 OMX_ERRORTYPE AudioOMX::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer){
490 //Log::getInstance()->log("Audio", Log::NOTICE, "EmptyBufferDone");
491 AudioOMX *audio=(AudioOMX *)getInstance();
492 audio->ReturnEmptyOMXBuffer(buffer);
493 return OMX_ErrorNone;
497 void AudioOMX::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){
498 input_bufs_omx_mutex.Lock();
499 //Log::getInstance()->log("Audio", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size());
500 input_bufs_omx_free.push_back(buffer);
501 //Log::getInstance()->log("Audio", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size());
502 input_bufs_omx_mutex.Unlock();
505 OMX_ERRORTYPE AudioOMX::FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer) {
506 Log::getInstance()->log("Audio", Log::NOTICE, "FillBufferDone");
507 return OMX_ErrorNone;
512 int AudioOMX::setStreamType(UCHAR type)
514 if (!initted) return 0;
516 // if (ioctl(fdAudio, AV_SET_AUD_STREAMTYPE, type) != 0) return 0;
520 int AudioOMX::setChannel()
522 if (!initted) return 0;
524 // if (ioctl(fdAudio, AV_SET_AUD_CHANNEL, 0) != 0) return 0;
528 int AudioOMX::setSource()
530 if (!initted) return 0;
532 // if (ioctl(fdAudio, AV_SET_AUD_SRC, 1) != 0) return 0;
538 if (!initted) return 0;
540 // if (ioctl(fdAudio, AV_SET_AUD_SYNC, 2) != 0) return 0;
544 int AudioOMX::play() {
547 lastAType=MPTYPE_MPEG_AUDIO;
548 Log::getInstance()->log("Audio", Log::DEBUG, "enter play");
550 ((VideoOMX*)Video::getInstance())->interlaceSwitch4Demux(); // switch resolution if necessary
552 if (!AllocateCodecsOMX()) {
559 int AudioOMX::ChangeAudioDestination() //clock aka omx mutex needs to be locked
562 const char * destinations[]={"local","hdmi"};
567 OMX_CONFIG_BRCMAUDIODESTINATIONTYPE auddest;
568 memset(&auddest,0,sizeof(auddest));
569 auddest.nSize=sizeof(auddest);
570 auddest.nVersion.nVersion=OMX_VERSION;
571 strcpy((char *)auddest.sName, destinations[dest]);
573 Log::getInstance()->log("Audio", Log::DEBUG, "setting destination to: %s",auddest.sName);
574 error=OMX_SetConfig(omx_aud_rend,OMX_IndexConfigBrcmAudioDestination,&auddest);
575 if (error!=OMX_ErrorNone){
576 Log::getInstance()->log("Audio", Log::DEBUG, "Init OMX_IndexConfigBrcmAudioDestination failed %x %x %s", error,omx_aud_rend,auddest.sName);
577 DeAllocateCodecsOMX();
585 int AudioOMX::ChangeAudioPortConfig(bool disport) //clock aka omx mutex needs to be locked
588 //Ok first fidle a working configuration
589 Log::getInstance()->log("Audio", Log::DEBUG,
590 "ChangeAudioPortConfig");
592 OMX_AUDIO_CODINGTYPE encoding;
595 case MPTYPE_MPEG_AUDIO: {
596 if (prefered_mp2 == 2 && false) { //not supported yet
599 if (prefered_mp2 == 1 && canpass_mp2) {
601 encoding=OMX_AUDIO_CodingMP3;
604 encoding=OMX_AUDIO_CodingPCM;
609 case MPTYPE_AAC_LATM: {
610 if (prefered_aac == 2 && false) { //not supported yet
613 Log::getInstance()->log("Audio", Log::DEBUG,
614 "ChangeAudioPortConfig debug %d %d",prefered_aac,canpass_aac);
615 if (prefered_aac == 1 && canpass_aac) {
617 encoding=OMX_AUDIO_CodingAAC;
620 encoding=OMX_AUDIO_CodingPCM;
625 case MPTYPE_AC3_PRE13:
627 if (prefered_ac3 == 2 && false) { //not supported yet
630 Log::getInstance()->log("Audio", Log::DEBUG,
631 "ChangeAudioPortConfig debug %d %d",prefered_ac3,canpass_ac3);
632 if (prefered_ac3 == 1 && canpass_ac3) {
634 encoding=OMX_AUDIO_CodingDDP;
637 encoding=OMX_AUDIO_CodingPCM;
642 case MPTYPE_MPEG_AUDIO_LAYER3: {
643 if (prefered_mp3 == 2 && false) { //not supported yet
646 if (prefered_mp3 == 1 && canpass_mp2) {
648 encoding=OMX_AUDIO_CodingMP3;
651 encoding=OMX_AUDIO_CodingPCM;
659 encoding=OMX_AUDIO_CodingPCM;
660 //mch=false; // multichannel also false
665 /*OMX_CONFIG_BOOLEANTYPE booly;
666 memset(&booly, 0, sizeof(booly));
667 booly.nSize = sizeof(booly);
668 booly.nVersion.nVersion = OMX_VERSION;
670 booly.bEnabled = OMX_TRUE;
672 booly.bEnabled = OMX_FALSE;
674 error = OMX_SetParameter(omx_aud_dec, OMX_IndexParamBrcmDecoderPassThrough,
676 if (error != OMX_ErrorNone) {
677 Log::getInstance()->log("Audio", Log::DEBUG,
678 "Init OMX_IndexParamBrcmDecoderPassThrough failed %x", error);
679 DeAllocateCodecsOMX();
682 VideoOMX* video=(VideoOMX*)Video::getInstance();
684 video->DisablePort(omx_aud_rend,omx_rend_input_port,false);
685 //DestroyInputBufsOMXwhilePlaying();
686 //video->CommandFinished(omx_aud_rend,OMX_CommandPortDisable,omx_rend_input_port);
691 OMX_AUDIO_PARAM_PORTFORMATTYPE format;
692 memset(&format, 0, sizeof(format));
693 format.nSize = sizeof(format);
694 format.nVersion.nVersion = OMX_VERSION;
695 format.nPortIndex = omx_rend_input_port;
696 error = OMX_GetParameter(omx_aud_rend, OMX_IndexParamAudioPortFormat,
698 if (error != OMX_ErrorNone) {
699 Log::getInstance()->log("Audio", Log::DEBUG,
700 "Get OMX_IndexParamAudioPortFormat failed %x %d", error,
701 omx_rend_input_port);
706 Log::getInstance()->log("Audio", Log::DEBUG,
707 "Get OMX_IndexParamAudioPortFormat returned %d",format.eEncoding );
708 format.eEncoding = encoding;
710 error = OMX_SetParameter(omx_aud_rend, OMX_IndexParamAudioPortFormat,
712 if (error != OMX_ErrorNone) {
713 Log::getInstance()->log("Audio", Log::DEBUG,
714 "Set OMX_IndexParamAudioPortFormat failed %x %d %d", error,
715 omx_rend_input_port,format.eEncoding );
720 case OMX_AUDIO_CodingPCM: {
721 OMX_AUDIO_PARAM_PCMMODETYPE audio_pcm;
722 memset(&audio_pcm, 0, sizeof(audio_pcm));
723 audio_pcm.nSize = sizeof(audio_pcm);
724 audio_pcm.nVersion.nVersion = OMX_VERSION;
725 audio_pcm.nChannels = 2;
726 audio_pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
727 audio_pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
728 //audio_pcm.eChannelMapping[2]=OMX_AUDIO_ChannelMax;
729 audio_pcm.eNumData = OMX_NumericalDataSigned;
730 audio_pcm.eEndian = OMX_EndianLittle;
731 audio_pcm.bInterleaved = OMX_TRUE;
732 audio_pcm.nBitPerSample = 16;
733 audio_pcm.ePCMMode = OMX_AUDIO_PCMModeLinear;
734 audio_pcm.nChannels = 2;
735 audio_pcm.nSamplingRate = 48000;
736 audio_pcm.nPortIndex = omx_rend_input_port;
737 error = OMX_SetParameter(omx_aud_rend, OMX_IndexParamAudioPcm,
739 if (error != OMX_ErrorNone) {
740 Log::getInstance()->log("Audio", Log::DEBUG,
741 "Init OMX_IndexParamAudioPcm failed %x %d", error,
742 omx_rend_input_port);
746 case OMX_AUDIO_CodingDDP: {
747 OMX_AUDIO_PARAM_DDPTYPE audio_ddp;
748 memset(&audio_ddp, 0, sizeof(audio_ddp));
749 audio_ddp.nSize = sizeof(audio_ddp);
750 audio_ddp.nVersion.nVersion = OMX_VERSION;
751 audio_ddp.nPortIndex = omx_rend_input_port;
752 audio_ddp.nChannels = 8; //unknown
753 audio_ddp.nBitRate=0;
754 audio_ddp.nSampleRate=48000;
755 audio_ddp.eChannelMapping[0] =OMX_AUDIO_ChannelLF;
756 audio_ddp.eChannelMapping[1] =OMX_AUDIO_ChannelRF;
757 audio_ddp.eChannelMapping[2] =OMX_AUDIO_ChannelCF;
758 audio_ddp.eChannelMapping[3] =OMX_AUDIO_ChannelLFE;
759 audio_ddp.eChannelMapping[4] =OMX_AUDIO_ChannelLR;
760 audio_ddp.eChannelMapping[5] =OMX_AUDIO_ChannelRR;
761 audio_ddp.eChannelMapping[6] =OMX_AUDIO_ChannelLS;
762 audio_ddp.eChannelMapping[7] =OMX_AUDIO_ChannelRS;
763 audio_ddp.eChannelMapping[8] =OMX_AUDIO_ChannelCS;
764 error = OMX_SetParameter(omx_aud_rend, OMX_IndexParamAudioDdp,
766 if (error != OMX_ErrorNone) {
767 Log::getInstance()->log("Audio", Log::DEBUG,
768 "Init OMX_IndexParamAudioDdp failed %x %d", error,
769 omx_rend_input_port);
774 default: break; //Make compiler happy
781 //PrepareInputBufsOMX(false);
782 video->EnablePort(omx_aud_rend,omx_rend_input_port,false);
792 int AudioOMX::InitDecoderLibAV()
795 ac3codec_context_libav = avcodec_alloc_context3(ac3codec_libav);
796 if (!ac3codec_context_libav) {
797 Log::getInstance()->log("Audio", Log::DEBUG, "Alloc avcodec for ac3 decoding context failed!");
801 ac3codec_context_libav->flags |= CODEC_FLAG_TRUNCATED;
802 ac3codec_context_libav->request_channels=2;
804 int avc_ret = avcodec_open2(ac3codec_context_libav, ac3codec_libav, NULL);
806 Log::getInstance()->log("Audio", Log::DEBUG, "Opening libav codec failed \n");
807 libav_mutex.Unlock();
811 aaclatmcodec_context_libav = avcodec_alloc_context3(aaclatmcodec_libav);
812 if (!aaclatmcodec_context_libav) {
813 Log::getInstance()->log("Audio", Log::DEBUG, "Alloc avcodec for aac decoding context failed!");
817 aaclatmcodec_context_libav->flags |= CODEC_FLAG_TRUNCATED;
818 aaclatmcodec_context_libav->request_channels=2;
820 avc_ret = avcodec_open2(aaclatmcodec_context_libav, aaclatmcodec_libav, NULL);
822 Log::getInstance()->log("Audio", Log::DEBUG, "Opening libav codec failed \n");
823 libav_mutex.Unlock();
828 mp23codec_context_libav = avcodec_alloc_context3(mp23codec_libav);
829 if (!ac3codec_context_libav) {
830 Log::getInstance()->log("Audio", Log::DEBUG, "Alloc avcodec for mp23 decoding context failed!");
831 libav_mutex.Unlock();
835 mp23codec_context_libav->flags |= CODEC_FLAG_TRUNCATED;
836 mp23codec_context_libav->request_channels=2;
838 avc_ret = avcodec_open2(mp23codec_context_libav, mp23codec_libav, NULL);
840 Log::getInstance()->log("Audio", Log::DEBUG, "Opening libav codec failed \n");
841 libav_mutex.Unlock();
845 av_init_packet(&incoming_paket_libav);
846 decode_frame_libav=avcodec_alloc_frame();
847 libav_mutex.Unlock();
848 decompress_buffer_filled=0;
855 void AudioOMX::DeinitDecoderLibAV() {
859 if (ac3codec_context_libav) {
860 avcodec_close(ac3codec_context_libav);
861 av_free(ac3codec_context_libav);
862 ac3codec_context_libav = NULL;
864 avcodec_close(aaclatmcodec_context_libav);
865 av_free(aaclatmcodec_context_libav);
866 aaclatmcodec_context_libav = NULL;
868 av_free(decode_frame_libav);
870 avcodec_close(mp23codec_context_libav);
871 av_free(mp23codec_context_libav);
872 mp23codec_context_libav = NULL;
875 libav_mutex.Unlock();
880 int AudioOMX::AllocateCodecsOMX()
883 static OMX_CALLBACKTYPE callbacks= {&VideoOMX::EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
885 Log::getInstance()->log("Audio", Log::NOTICE, "Allocate Codecs OMX");
886 //Clock, move later to audio
887 VideoOMX *video=(VideoOMX*)Video::getInstance();
889 if (!InitDecoderLibAV()) return 0;;
892 OMX_PORT_PARAM_TYPE p_param;
893 memset(&p_param,0,sizeof(p_param));
894 p_param.nSize=sizeof(p_param);
895 p_param.nVersion.nVersion=OMX_VERSION;
898 if (!video->getClockAudioandInit(&omx_clock,&omx_clock_output_port)){
899 return 0;// get the clock and init it if necessary
903 if (!video->idleClock()) {
908 error = OMX_GetHandle(&omx_aud_rend, VPE_OMX_AUDIO_REND, NULL, &callbacks);
909 if (error != OMX_ErrorNone) {
910 Log::getInstance()->log("Audio", Log::DEBUG,
911 "Init OMX audio rend failed %x", error);
912 video->UnlockClock();
913 DeAllocateCodecsOMX();
917 if (!ChangeAudioDestination()) {
918 video->UnlockClock();
919 DeAllocateCodecsOMX();
923 error = OMX_GetParameter(omx_aud_rend, OMX_IndexParamAudioInit, &p_param);
924 if (error != OMX_ErrorNone) {
925 Log::getInstance()->log("Audio", Log::DEBUG,
926 "Init OMX audio rend OMX_GetParameter failed %x", error);
927 video->UnlockClock();
928 DeAllocateCodecsOMX();
931 omx_rend_input_port = p_param.nStartPortNumber;
933 error = OMX_GetParameter(omx_aud_rend, OMX_IndexParamOtherInit, &p_param);
934 if (error != OMX_ErrorNone) {
935 Log::getInstance()->log("Audio", Log::DEBUG,
936 "Init OMX aud rend OMX_GetParameter failed %x", error);
937 video->UnlockClock();
938 DeAllocateCodecsOMX();
941 // buggy return value
942 omx_rend_clock_port = p_param.nStartPortNumber;
945 /* error=OMX_GetHandle(&omx_aud_dec,VPE_OMX_AUDIO_DECODER,NULL,&callbacks);
947 if (error!=OMX_ErrorNone){
948 Log::getInstance()->log("Audio", Log::DEBUG, "Init OMX audio decoder failed %x", error);
949 video->UnlockClock();
950 DeAllocateCodecsOMX();
954 error=OMX_GetParameter(omx_aud_dec,OMX_IndexParamAudioInit,&p_param);
955 if (error!=OMX_ErrorNone){
956 Log::getInstance()->log("Audio", Log::DEBUG, "Init OMX audio decoder OMX_GetParameter failed %x", error);
957 video->UnlockClock();
958 DeAllocateCodecsOMX();
961 omx_codec_input_port=p_param.nStartPortNumber;
962 omx_codec_output_port=p_param.nStartPortNumber+1;
964 if (!video->DisablePort(omx_aud_dec,omx_codec_input_port) || !video->DisablePort(omx_aud_dec,omx_codec_output_port)) {
965 Log::getInstance()->log("Audio", Log::DEBUG, "Disable Ports OMX audio decoder failed");
966 video->UnlockClock();
967 DeAllocateCodecsOMX();
974 if (!video->DisablePort(omx_aud_rend,omx_rend_input_port,true) ) {
975 Log::getInstance()->log("Audio", Log::DEBUG, "Disable Ports OMX audio rend failed %d",omx_rend_input_port);
976 video->UnlockClock();
977 DeAllocateCodecsOMX();
981 if ( !video->DisablePort(omx_aud_rend, omx_rend_clock_port, true)) {
982 Log::getInstance()->log("Audio", Log::DEBUG,
983 "Disable Ports OMX rend clock port failed %d",omx_rend_clock_port);
984 video->UnlockClock();
985 DeAllocateCodecsOMX();
995 error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,omx_aud_rend,omx_rend_clock_port);
996 if (error!=OMX_ErrorNone){
997 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);
998 video->UnlockClock();
999 DeAllocateCodecsOMX();
1003 if (!video->EnablePort(omx_clock,omx_clock_output_port,false) || !video->EnablePort(omx_aud_rend,omx_rend_clock_port,false)
1005 Log::getInstance()->log("Audio", Log::DEBUG, "Enable Ports OMX clock rend failed");
1006 video->UnlockClock();
1007 DeAllocateCodecsOMX();
1011 if (!video->ChangeComponentState(omx_aud_rend,OMX_StateIdle)) {
1012 Log::getInstance()->log("Audio", Log::DEBUG, "aud_rend idle ChangeComponentState");
1013 video->UnlockClock();
1014 DeAllocateCodecsOMX();
1021 if ( !video->CommandFinished(omx_aud_rend,OMX_CommandPortEnable,omx_rend_clock_port)) {
1022 video->UnlockClock();
1023 DeAllocateCodecsOMX();
1027 if ( !video->CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port)) {
1028 video->UnlockClock();
1029 DeAllocateCodecsOMX();
1035 if (!ChangeAudioPortConfig(false)){
1036 Log::getInstance()->log("Audio", Log::NOTICE, "Change AudioPortConfig failed");
1037 video->UnlockClock();
1038 DeAllocateCodecsOMX();
1042 /* if (!video->ChangeComponentState(omx_aud_dec,OMX_StateIdle)) {
1043 Log::getInstance()->log("Audio", Log::DEBUG, "aud_dec ChangeComponentState");
1044 DeAllocateCodecsOMX();
1050 if (!PrepareInputBufsOMX(true)) {
1051 video->UnlockClock();
1052 DeAllocateCodecsOMX();
1058 /* error=OMX_SetupTunnel(omx_aud_dec,omx_codec_output_port,omx_aud_rend,omx_rend_input_port);
1059 if (error!=OMX_ErrorNone){
1060 Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Setup tunnel dec to render failed %x", error);
1061 video->UnlockClock();
1062 DeAllocateCodecsOMX();
1068 /* if (!video->EnablePort(omx_aud_dec,omx_codec_output_port,false) || !video->EnablePort(omx_aud_rend,omx_rend_input_port,false)
1070 Log::getInstance()->log("Audio", Log::DEBUG, "Enable Ports OMX codec rend failed");
1071 video->UnlockClock();
1072 DeAllocateCodecsOMX();
1076 /* if ( !video->CommandFinished(omx_aud_dec,OMX_CommandPortEnable,omx_codec_output_port)
1077 || !video->CommandFinished(omx_aud_rend,OMX_CommandPortEnable,omx_rend_input_port)) {
1078 video->UnlockClock();
1079 DeAllocateCodecsOMX();
1083 if (!video->ChangeComponentState(omx_aud_rend,OMX_StateExecuting)) {
1084 Log::getInstance()->log("Audio", Log::DEBUG, "omx_aud_rend ChangeComponentState Execute");
1085 video->UnlockClock();
1086 DeAllocateCodecsOMX();
1091 video->UnlockClock();
1094 video->clockUnpause();
1097 if (!video->setClockExecutingandRunning()) return 0;
1099 Log::getInstance()->log("Audio", Log::NOTICE, "Allocate Codecs OMX finished");
1107 int AudioOMX::PrepareInputBufsOMX(bool setportdef) //needs to be called with locvke omx clock mutex
1109 VideoOMX *video=(VideoOMX*)Video::getInstance();
1110 OMX_ERRORTYPE error;
1111 OMX_PARAM_PORTDEFINITIONTYPE port_def_type;
1112 memset(&port_def_type,0,sizeof(port_def_type));
1113 port_def_type.nSize=sizeof(port_def_type);
1114 port_def_type.nVersion.nVersion=OMX_VERSION;
1115 port_def_type.nPortIndex=omx_rend_input_port;//omx_codec_input_port;
1117 error=OMX_GetParameter(omx_aud_rend/*dec*/,OMX_IndexParamPortDefinition, &port_def_type);
1119 if (error!=OMX_ErrorNone){
1120 Log::getInstance()->log("Audio", Log::DEBUG, "Get OMX OMX_IndexParamPortDefinition failed %x", error);
1125 port_def_type.nBufferCountActual=2;
1126 port_def_type.nBufferSize=max(port_def_type.nBufferSize,50000); // for transcoder important
1128 error=OMX_SetParameter(omx_aud_rend/*dec*/,OMX_IndexParamPortDefinition, &port_def_type);
1130 if (error!=OMX_ErrorNone){
1131 Log::getInstance()->log("Audio", Log::DEBUG, "Set OMX OMX_IndexParamPortDefinition failed %x", error);
1136 error=OMX_SendCommand(omx_aud_rend/*dec*/,OMX_CommandPortEnable,omx_rend_input_port/*codec*/,0);
1137 if (error!=OMX_ErrorNone){
1138 Log::getInstance()->log("Audio", Log::DEBUG, "Prepare Input bufs Send Command to enable port %x", error);
1142 input_bufs_omx_mutex.Lock();
1143 for (unsigned int i=0; i< port_def_type.nBufferCountActual;i++) {
1144 OMX_BUFFERHEADERTYPE *buf_head=NULL;
1145 error=OMX_AllocateBuffer(omx_aud_rend/*dec*/,&buf_head,omx_rend_input_port/*codec*/,NULL,port_def_type.nBufferSize);
1146 if (error!=OMX_ErrorNone){
1147 Log::getInstance()->log("Audio", Log::DEBUG, "Use OMX_AllocateBuffer failed %x", error);
1148 input_bufs_omx_mutex.Unlock();
1151 input_bufs_omx_all.push_back(buf_head);
1152 input_bufs_omx_free.push_back(buf_head);
1154 omx_first_frame=true;
1157 cur_input_buf_omx=NULL;
1158 input_bufs_omx_mutex.Unlock();
1160 if (!video->CommandFinished(omx_aud_rend/*dec*/,OMX_CommandPortEnable,omx_rend_input_port /*codec*/)) {
1167 int AudioOMX::DestroyInputBufsOMX() //call with clock mutex locked
1169 OMX_ERRORTYPE error;
1171 cur_input_buf_omx=NULL;
1172 input_bufs_omx_mutex.Lock();
1173 for (int i=0; i< input_bufs_omx_all.size();i++) {
1174 error=OMX_FreeBuffer(omx_aud_rend/*dec*/,omx_rend_input_port/*codec*/,input_bufs_omx_all[i]);
1175 if (error!=OMX_ErrorNone){
1176 Log::getInstance()->log("Audio", Log::DEBUG, "Use OMX_FreeBuffer failed %x", error);
1177 input_bufs_omx_mutex.Unlock();
1182 input_bufs_omx_all.clear();
1183 input_bufs_omx_free.clear();
1184 input_bufs_omx_mutex.Unlock();
1188 int AudioOMX::DestroyInputBufsOMXwhilePlaying() //call with clock mutex locked
1190 OMX_ERRORTYPE error;
1192 cur_input_buf_omx=NULL;
1193 input_bufs_omx_mutex.Lock();
1194 while (input_bufs_omx_all.size()>0) {
1195 if (input_bufs_omx_free.size()>0) {
1196 // Destroy one buffer
1197 vector<OMX_BUFFERHEADERTYPE*>::iterator itty=input_bufs_omx_all.begin();
1198 OMX_BUFFERHEADERTYPE* cur_buf=input_bufs_omx_free.front();
1199 for (; itty!= input_bufs_omx_all.end();itty++) {
1200 if ((*itty)==cur_buf) {
1201 input_bufs_omx_all.erase(itty);
1202 input_bufs_omx_free.pop_front();
1207 input_bufs_omx_mutex.Unlock();
1209 input_bufs_omx_mutex.Lock();
1213 Log::getInstance()->log("Audio", Log::DEBUG, "DestroyInputBufsOMXwhilePlaying %d %d", input_bufs_omx_all.size(),input_bufs_omx_free.size());
1214 input_bufs_omx_mutex.Unlock();
1219 int AudioOMX::DeAllocateCodecsOMX()
1221 OMX_ERRORTYPE error;
1223 VideoOMX *video=(VideoOMX*)Video::getInstance();
1224 Log::getInstance()->log("Audio", Log::DEBUG, "enter deallocatecodecsomx");
1228 Log::getInstance()->log("Audio", Log::DEBUG, "deallocatecodecsomx mark 1");
1229 if (cur_input_buf_omx) {
1230 cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_EOS;
1231 OMX_ERRORTYPE error=video->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/,cur_input_buf_omx);
1232 if (error!=OMX_ErrorNone) {
1233 Log::getInstance()->log("Audio", Log::DEBUG, "OMX_EmptyThisBuffer 6 failed %x", error);
1236 cur_input_buf_omx=NULL;//write out old data
1238 Log::getInstance()->log("Audio", Log::DEBUG, "deallocatecodecsomx mark 2");
1241 if (omx_aud_rend/*dec*/) {
1242 // first stop the omx elements
1243 /* if (!video->ChangeComponentState(omx_aud_dec,OMX_StateIdle)) {
1244 Log::getInstance()->log("Audio", Log::DEBUG, "aud_dec ChangeComponentState");
1246 Log::getInstance()->log("Audio", Log::DEBUG, "deallocatecodecsomx mark 3");
1248 video->UnlockClock();
1249 Log::getInstance()->log("Audio", Log::DEBUG, "deallocatecodecsomx mark 4");
1251 Log::getInstance()->log("Audio", Log::DEBUG, "deallocatecodecsomx mark 5");
1254 if (!video->ChangeComponentState(omx_aud_rend,OMX_StateIdle)) {
1255 Log::getInstance()->log("Audio", Log::DEBUG, "aud_rend ChangeComponentState");
1258 // TODO proper deinit sequence
1259 // first flush all buffers
1261 error=OMX_SendCommand(omx_aud_rend,OMX_CommandFlush, omx_rend_input_port, NULL);
1262 if (error!=OMX_ErrorNone) {
1263 Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Flush rend in failed %x", error);
1267 /* error=OMX_SendCommand(omx_aud_dec,OMX_CommandFlush, omx_codec_input_port, NULL);
1268 if (error!=OMX_ErrorNone){
1269 Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Flush codec out failed %x", error);
1274 /* if (!video->CommandFinished(omx_aud_dec,OMX_CommandFlush,omx_codec_input_port)) {
1275 Log::getInstance()->log("Audio", Log::DEBUG, "flush cmd codec input failed");
1280 error=OMX_SendCommand(omx_clock,OMX_CommandFlush, omx_clock_output_port, NULL);
1281 if (error!=OMX_ErrorNone){
1282 Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Flush clock out failed %x", error);
1286 error=OMX_SendCommand(omx_aud_rend,OMX_CommandFlush, omx_rend_clock_port, NULL);
1287 if (error!=OMX_ErrorNone){
1288 Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Flush rend clock failed %x", error);
1291 Log::getInstance()->log("Audio", Log::DEBUG, "deallocatecodecsomx mark 6");
1293 if (!video->CommandFinished(omx_clock,OMX_CommandFlush,omx_clock_output_port) ||
1294 !video->CommandFinished(omx_aud_rend,OMX_CommandFlush,omx_rend_clock_port)) {
1295 Log::getInstance()->log("Audio", Log::DEBUG, "flush cmd clock shed failed");
1298 DestroyInputBufsOMX(); //We have to make sure that no buffers are in use
1299 Log::getInstance()->log("Audio", Log::DEBUG, "deallocatecodecsomx mark 6a");
1300 DeinitDecoderLibAV();
1301 Log::getInstance()->log("Audio", Log::DEBUG, "deallocatecodecsomx mark 7");
1304 if (!video->DisablePort(omx_aud_rend,omx_rend_input_port,true)) {
1305 Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 1");
1308 /* if (!video->DisablePort(omx_aud_dec,omx_codec_output_port,true)) {
1309 Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 6");
1312 if (!video->DisablePort(omx_aud_dec,omx_codec_input_port,true)) {
1313 Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 7");
1317 if (!video->DisablePort(omx_aud_rend,omx_rend_clock_port,true)) {
1318 Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 4");
1321 if (!video->DisablePort(omx_clock,omx_clock_output_port,true)) {
1322 Log::getInstance()->log("Audio", Log::DEBUG, "Disable Tunnel Port failed 5");
1327 /* error=OMX_SetupTunnel(omx_aud_dec,omx_codec_output_port,NULL,NULL);
1328 if (error!=OMX_ErrorNone) {
1329 Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1335 error=OMX_SetupTunnel(omx_aud_rend,omx_rend_input_port,NULL,NULL);
1336 if (error!=OMX_ErrorNone) {
1337 Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1341 error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,NULL,NULL);
1342 if (error!=OMX_ErrorNone) {
1343 Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1347 error=OMX_SetupTunnel(omx_aud_rend,omx_rend_clock_port,NULL,NULL);
1348 if (error!=OMX_ErrorNone) {
1349 Log::getInstance()->log("Audio", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1352 Log::getInstance()->log("Audio", Log::DEBUG, "deallocatecodecsomx mark 8");
1355 //error=OMX_FreeHandle(omx_aud_dec);
1356 error=OMX_FreeHandle(omx_aud_rend);
1357 video->UnlockClock();
1358 video->destroyClock();
1359 omx_aud_rend/*dec*/=NULL;
1360 if (error!=OMX_ErrorNone) {
1361 Log::getInstance()->log("Audio", Log::DEBUG, "FreeHandle failed %d", error);
1365 video->UnlockClock();
1366 DeinitDecoderLibAV();
1368 Log::getInstance()->log("Audio", Log::DEBUG, "leave deallocate codecs OMX");
1375 int AudioOMX::stop()
1377 if (!initted) return 0;
1379 Log::getInstance()->log("Audio", Log::DEBUG, "Audio stop called");
1380 DeAllocateCodecsOMX();
1381 //if (ioctl(fdAudio, AV_SET_AUD_RESET, 0x11) != 0) return 0;
1385 int AudioOMX::mute() {
1388 Log::getInstance()->log("Audio", Log::DEBUG, "MUTE MUTE MUTE");
1389 VideoOMX *vw = (VideoOMX*) Video::getInstance();
1393 OMX_AUDIO_CONFIG_MUTETYPE amute;
1394 memset(&amute, 0, sizeof(amute));
1395 amute.nSize = sizeof(amute);
1396 amute.nVersion.nVersion = OMX_VERSION;
1397 amute.nPortIndex = omx_rend_input_port;
1398 amute.bMute = OMX_TRUE;
1399 OMX_ERRORTYPE error= OMX_SetParameter(omx_aud_rend, OMX_IndexConfigAudioMute,
1401 if (error != OMX_ErrorNone) {
1402 Log::getInstance()->log("Audio", Log::DEBUG,
1403 "Set OMX_IndexConfigAudioMute failed %x %d", error,
1404 omx_rend_input_port);
1415 int AudioOMX::unMute()
1417 if (!initted) return 0;
1419 Log::getInstance()->log("Audio", Log::DEBUG, "MUTE OFF OFF OFF");
1420 VideoOMX *vw = (VideoOMX*) Video::getInstance();
1424 OMX_AUDIO_CONFIG_MUTETYPE amute;
1425 memset(&amute, 0, sizeof(amute));
1426 amute.nSize = sizeof(amute);
1427 amute.nVersion.nVersion = OMX_VERSION;
1428 amute.nPortIndex = omx_rend_input_port;
1429 amute.bMute = OMX_FALSE;
1430 OMX_ERRORTYPE error = OMX_SetParameter(omx_aud_rend, OMX_IndexConfigAudioMute,
1432 if (error != OMX_ErrorNone) {
1433 Log::getInstance()->log("Audio", Log::DEBUG,
1434 "Set OMX_IndexConfigAudioMute failed %x %d", error,
1435 omx_rend_input_port);
1446 int AudioOMX::pause() {
1450 VideoOMX *vw = (VideoOMX*) Video::getInstance();
1456 int AudioOMX::unPause()
1458 if (!initted) return 0;
1460 VideoOMX *vw = (VideoOMX*) Video::getInstance();
1467 int AudioOMX::reset()
1469 if (!initted) return 0;
1471 Log::getInstance()->log("Audio", Log::DEBUG, "reset called");
1472 DeAllocateCodecsOMX();
1474 // if (ioctl(fdAudio, AV_SET_AUD_RESET, 0x11) != 0) return 0;
1475 // Log::getInstance()->log("Audio", Log::DEBUG, "reset back");
1476 // if (ioctl(fdAudio, AV_SET_AUD_PLAY, 0) != 0) return 0;
1482 int AudioOMX::setVolume(int tvolume)
1484 // parameter: 0 for silence, 20 for full
1485 if ((tvolume < 0) || (tvolume > 20)) return 0;
1487 // volume = 2 * (20 - volume);
1488 // Right, that one was rubbish... 0-10 were almost
1489 // inaudible, 11-20 did what should have been done
1490 // over the whole 0-20 range
1494 VideoOMX *vw = (VideoOMX*) Video::getInstance();
1498 OMX_AUDIO_CONFIG_VOLUMETYPE avol;
1499 memset(&avol, 0, sizeof(avol));
1500 avol.nSize = sizeof(avol);
1501 avol.nVersion.nVersion = OMX_VERSION;
1502 avol.nPortIndex = omx_rend_input_port;
1503 avol.bLinear=OMX_FALSE;
1504 avol.sVolume.nValue =(volume-20)*200;
1505 OMX_ERRORTYPE error = OMX_SetParameter(omx_aud_rend, OMX_IndexConfigAudioVolume,
1507 if (error != OMX_ErrorNone) {
1508 Log::getInstance()->log("Audio", Log::DEBUG,
1509 "Set OMX_IndexConfigAudioVolume failed %x %d", error,
1510 omx_rend_input_port);
1521 int AudioOMX::test()
1524 // return ioctl(fdAudio, AV_SET_AUD_STC, &stc);
1526 /* aud_sync_parms_t a;
1530 // int b = ioctl(fdAudio, AV_SET_AUD_DISABLE_SYNC, &a);
1533 /*OK*/ //printf("Audio sync disable = %i\n", b);
1541 unsigned int AudioOMX::AdvanceMpAudioSync(const UCHAR *data,unsigned int size,unsigned int *framesize)
1543 if (size<=2) return size; // silly;
1544 unsigned int test=0;
1546 while (test+1<size) {
1547 if (data[test]==0xFF && (data[test+1] &0xe0)==0xe0) return test; // probably FrameSync
1553 unsigned int AudioOMX::AdvanceAc3AudioSync(const UCHAR *data,unsigned int size,unsigned int *framesize)
1555 if (size<=4) return size; // silly;
1556 const int frm_size_tab[] = { 64, 64, 80, 80, 96, 96, 112, 112, 128, 128,
1557 160, 160, 192, 192, 224, 224, 256, 256, 320, 320, 384, 384, 448,
1558 448, 512, 512, 640, 640, 768, 768, 896, 896, 1024, 1024, 1152,
1559 1152, 1280, 1280, };
1560 unsigned int test=0;
1561 *framesize=20000; //if we do not find a start code do not decompress
1562 while (test+4<size) {
1563 if (data[test]==0x0B && data[test+1]==0x77) {
1564 // now figure out the length of the frame
1565 unsigned char code=data[test+4];
1566 unsigned char fscod=(code& 0xC0)>>6;
1567 unsigned char frmsize=(code &0x3f);
1568 if (fscod!=0) Log::getInstance()->log("Audio", Log::DEBUG, "warning we only support 48 KHz sampling rate");
1569 *framesize=frm_size_tab[frmsize]*2;
1570 return test; // probably FrameSync
1577 unsigned int AudioOMX::AdvanceAacLatmAudioSync(const UCHAR *data,unsigned int size,unsigned int *framesize)
1579 if (size<=4) return size; // silly;
1580 unsigned int test=0;
1581 *framesize=20000; //if we do not find a start code do not decompress
1582 while (test+4<size) {
1583 if (data[test] ==0x56 && (data[test+1]& 0xe0)==0xe0) {
1584 // now figure out the length of the frame
1585 unsigned int length= ((0x1f & data[test+1])<<8) | data[test+2];
1587 return test; // probably FrameSync
1595 void AudioOMX::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
1597 packet = mplist.front();
1600 UINT AudioOMX::DeliverMediaSample(UCHAR* buffer, UINT* samplepos) {
1601 DeliverMediaPacket(packet, buffer, samplepos);
1602 if (*samplepos == packet.length) {
1610 long long AudioOMX::correctAudioLatency(long long pts,int addsamples,int srate) {
1612 VideoOMX *video = (VideoOMX*) Video::getInstance();
1614 OMX_PARAM_U32TYPE audio_lat;
1615 OMX_ERRORTYPE error;
1616 memset(&audio_lat, 0, sizeof(audio_lat));
1617 audio_lat.nSize = sizeof(audio_lat);
1618 audio_lat.nVersion.nVersion = OMX_VERSION;
1619 audio_lat.nPortIndex = omx_rend_input_port;
1621 error = OMX_GetConfig(omx_aud_rend, OMX_IndexConfigAudioRenderingLatency,
1623 video->UnlockClock();
1624 if (error != OMX_ErrorNone) {
1625 Log::getInstance()->log("Audio", Log::DEBUG,
1626 "Init OMX_IndexConfigAudioRenderingLatencyfailed %x %d", error,
1627 omx_rend_input_port);
1628 return pts; // no correction in case of error
1630 /*Log::getInstance()->log("Audio", Log::DEBUG, "Current audio latency %d",
1633 long long workpts=0;
1634 workpts+=addsamples;
1635 workpts-=audio_lat.nU32;
1636 workpts*=10LL*1000LL*1000LL;
1637 workpts=workpts/((long long)srate); //one second /samplerate
1645 UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer,
1647 /*First Check, if we have an audio sample*/
1648 VideoOMX *vw = (VideoOMX*) Video::getInstance();
1650 OMX_ERRORTYPE error;
1651 Log *logger=Log::getInstance();
1652 if (vw->InIframemode()) {
1655 return 0; //Not in iframe mode!
1658 if (!omx_running) return 0; // if we are not runnig do not do this
1659 if (vw->isClockPaused()) return 0; //Block if we pause
1660 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 1");
1662 //Log::getInstance()->log("Audio", Log::DEBUG, "DeliverMediaPacketOMX time %lld",packet.presentation_time);
1664 /* if (packet.synched && packet.presentation_time <= 0) {
1665 *samplepos = packet.length;
1666 firstsynched = false;
1668 Log::getInstance()->log("Audio", Log::DEBUG,
1669 "DeliverMediaPacketOMX Frameskip");
1670 return packet.length;
1673 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 2");
1675 UINT headerstrip = 0;
1676 if (packet.disconti) {
1677 firstsynched = false;
1678 decompress_buffer_filled=0;
1679 if (cur_input_buf_omx) {
1680 OMX_ERRORTYPE error = vw->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/,
1682 if (error != OMX_ErrorNone) {
1683 Log::getInstance()->log("Audio", Log::DEBUG,
1684 "OMX_EmptyThisBuffer 1 failed %x", error);
1686 cur_input_buf_omx = NULL;
1690 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 3");
1691 if (packet.type != lastAType) {//Format Change //Push data out !
1692 firstsynched = false;
1694 Log::getInstance()->log("Audio", Log::DEBUG,"Notice audio type change %d %d", packet.type,lastAType);
1695 lastAType = packet.type;
1696 decompress_buffer_filled=0;
1698 if (cur_input_buf_omx) {
1699 OMX_ERRORTYPE error = vw->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/,
1701 if (error != OMX_ErrorNone) {
1702 Log::getInstance()->log("Audio", Log::DEBUG,
1703 "OMX_EmptyThisBuffer 2 failed %x", error);
1705 cur_input_buf_omx = NULL;
1710 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldcancelstate);
1711 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldcanceltype);
1713 if (!ChangeAudioPortConfig(true)) {
1714 Log::getInstance()->log("Audio", Log::DEBUG,
1715 "Changing audio port config failed", error);
1718 pthread_setcancelstate(oldcancelstate, NULL);
1719 pthread_setcanceltype(oldcanceltype, NULL);
1723 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 4");
1725 /*Inspect PES-Header */
1726 if (*samplepos == 0 && packet.type != MPTYPE_MPEG_AUDIO_LAYER3) {//stripheader
1727 headerstrip = buffer[packet.pos_buffer + 8] + 9;
1728 if (packet.type == MPTYPE_AC3)
1729 headerstrip += 4; //skip ac3 bytes
1730 *samplepos += headerstrip;
1731 if (packet.synched) {
1732 if (cur_input_buf_omx) {
1733 //cur_input_buf_omx->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
1734 OMX_ERRORTYPE error = vw->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/,
1736 if (error != OMX_ErrorNone) {
1737 Log::getInstance()->log("Audio", Log::DEBUG,
1738 "OMX_EmptyThisBuffer 3 failed %x", error);
1740 //vw->AdjustAudioPTS(correctAudioLatency(lastreftimeOMX,cur_input_buf_omx->nFilledLen/(2*2),48000));
1742 cur_input_buf_omx = NULL;//write out old data
1744 firstsynched = true;
1745 //decompress_buffer_filled=0;
1747 if (!firstsynched) {//
1748 *samplepos = packet.length;//if we have not processed at least one
1749 decompress_buffer_filled=0;
1750 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 5");
1751 return packet.length;//synched packet ignore it!
1755 if (!cur_input_buf_omx) {
1756 input_bufs_omx_mutex.Lock();
1757 if (input_bufs_omx_free.size()==0) {
1758 input_bufs_omx_mutex.Unlock();
1759 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 6");
1760 //Log::getInstance()->log("Audio", Log::DEBUG, "Deliver MediaPacket no free sample");
1761 return 0; // we do not have a free media sample
1764 cur_input_buf_omx=input_bufs_omx_free.front();
1765 cur_input_buf_omx->nFilledLen=0;
1766 cur_input_buf_omx->nOffset=0;
1767 cur_input_buf_omx->nTimeStamp=VideoOMX::intToOMXTicks(0);
1768 input_bufs_omx_free.pop_front();
1769 input_bufs_omx_mutex.Unlock();
1771 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 7");
1773 if (cur_input_buf_omx->nFilledLen == 0) {//will only be changed on first packet
1774 if (packet.synched) {
1775 //Log::getInstance()->log("Audio", Log::DEBUG,
1776 // "packet synched marker");
1778 //lastreftimePTS=packet.pts;
1779 if (omx_first_frame) { // TODO time
1780 cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_STARTTIME;
1781 Log::getInstance()->log("Audio", Log::DEBUG, "Starttime");
1782 omx_first_frame = false;
1784 cur_input_buf_omx->nFlags = 0;
1785 //cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_TIME_UNKNOWN;
1787 lastreftimeOMX = packet.presentation_time;
1788 //Log::getInstance()->log("Audio", Log::DEBUG,
1789 // "Time code %lld pts %lld dts %lld", lastreftimeOMX, packet.pts,packet.dts);
1790 lastreftimePTS = packet.pts;
1791 cur_input_buf_omx->nTimeStamp = VideoOMX::intToOMXTicks(lastreftimeOMX/10LL); // the clock component is faulty;
1793 // Log::getInstance()->log("Audio", Log::DEBUG,
1794 // "packet NOT synched marker");
1795 cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
1796 cur_input_buf_omx->nTimeStamp = VideoOMX::intToOMXTicks(0);
1799 if (packet.disconti || achange) {
1800 cur_input_buf_omx->nFlags |= OMX_BUFFERFLAG_DISCONTINUITY;
1801 //mp23codec_context_libav->frame_size=-1;
1802 //ac3codec_context_libav->frame_size=-1;
1806 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 8");
1808 if (*samplepos>packet.length) *samplepos=0; //propably the thread got interrupted and sample is not valid any more!
1809 unsigned int haveToCopy=packet.length-*samplepos;
1812 while (haveToCopy>0) {
1813 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 9");
1815 unsigned int gotframesize=0;
1817 switch (packet.type) {
1818 case MPTYPE_MPEG_AUDIO:
1819 case MPTYPE_MPEG_AUDIO_LAYER3: {
1820 adv = AdvanceMpAudioSync(buffer+packet.pos_buffer+*samplepos,
1821 haveToCopy,&gotframesize);
1825 case MPTYPE_AC3_PRE13: {
1826 adv = AdvanceAc3AudioSync(buffer+packet.pos_buffer+*samplepos,
1827 haveToCopy,&gotframesize);
1831 case MPTYPE_AAC_LATM: {
1832 adv = AdvanceAacLatmAudioSync(buffer+packet.pos_buffer+*samplepos,
1833 haveToCopy,&gotframesize);
1837 if (adv!=haveToCopy) {
1842 *samplepos=packet.length; //no ac3 sync byte
1843 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 10");
1844 return packet.length;
1847 // so everything is fine now do a memcpy
1848 int cancopy=min(haveToCopy,cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen);
1849 memcpy(cur_input_buf_omx->pBuffer+cur_input_buf_omx->nFilledLen,buffer+packet.pos_buffer+*samplepos,cancopy);
1850 haveToCopy-=cancopy;
1851 cur_input_buf_omx->nFilledLen+=cancopy;
1852 *samplepos+=cancopy;
1853 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 11");
1855 error = vw->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/, cur_input_buf_omx);
1856 if (error != OMX_ErrorNone) {
1857 Log::getInstance()->log("Audio", Log::DEBUG,
1858 "OMX_EmptyThisBuffer 5 failed %x", error);
1860 cur_input_buf_omx=NULL;
1863 input_bufs_omx_mutex.Lock();
1864 if (input_bufs_omx_free.size()==0) {
1865 input_bufs_omx_mutex.Unlock();
1866 // Log::getInstance()->log("Audio", Log::DEBUG, "Deliver MediaPacket no free sample2");
1867 return *samplepos; // we do not have a free media sample
1869 cur_input_buf_omx=input_bufs_omx_free.front();
1870 cur_input_buf_omx->nFilledLen=0;
1871 cur_input_buf_omx->nOffset=0;
1872 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
1873 cur_input_buf_omx->nTimeStamp=VideoOMX::intToOMXTicks(0);
1874 input_bufs_omx_free.pop_front();
1875 input_bufs_omx_mutex.Unlock();
1877 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 12");
1880 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 13");
1888 AVCodecContext *current_context;
1889 switch (packet.type) {
1890 case MPTYPE_MPEG_AUDIO:
1891 case MPTYPE_MPEG_AUDIO_LAYER3: {
1892 current_context = mp23codec_context_libav;
1893 if (current_context->frame_size<0) framesize=1152; //Maximum framesize
1894 else framesize=current_context->frame_size;
1896 case MPTYPE_AAC_LATM: {
1897 current_context = aaclatmcodec_context_libav;
1900 case MPTYPE_AC3_PRE13: {
1901 current_context = ac3codec_context_libav;
1905 if (decompress_buffer_filled) { // have a remaining paket
1906 incoming_paket_libav.data =(uint8_t*) decompress_buffer;
1907 memcpy(decompress_buffer+decompress_buffer_filled,
1908 buffer+packet.pos_buffer+*samplepos,
1909 min(haveToCopy,decompress_buffer_size-decompress_buffer_filled));
1910 incoming_paket_libav.size = decompress_buffer_filled
1911 +min(haveToCopy,decompress_buffer_size-decompress_buffer_filled);
1912 //Log::getInstance()->log("Audio", Log::DEBUG,"Use saved audio buffer %d",packet.type);
1914 incoming_paket_libav.data =(uint8_t*) buffer+packet.pos_buffer+*samplepos;
1915 incoming_paket_libav.size = haveToCopy;
1917 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 18");
1919 while (haveToCopy> 0 && errcount<3) {
1921 //Log::getInstance()->log("Audio", Log::DEBUG,"libav in %d %d",framesize,current_context->frame_size);
1922 //Log::getInstance()->log("Audio", Log::DEBUG, "libav in %d %d",
1923 // framesize, current_context->frame_size);
1925 bool donotdecompress=false;
1926 unsigned int gotframesize=0;
1927 if (!decompress_buffer_filled) { // only do this if no old data is present
1929 switch (packet.type) {
1930 case MPTYPE_MPEG_AUDIO:
1931 case MPTYPE_MPEG_AUDIO_LAYER3: {
1932 adv = AdvanceMpAudioSync(incoming_paket_libav.data,
1933 incoming_paket_libav.size,&gotframesize);
1937 case MPTYPE_AC3_PRE13: {
1938 adv = AdvanceAc3AudioSync(incoming_paket_libav.data,
1939 incoming_paket_libav.size,&gotframesize);
1942 case MPTYPE_AAC_LATM: {
1943 adv = AdvanceAacLatmAudioSync(incoming_paket_libav.data,
1944 incoming_paket_libav.size,&gotframesize);
1949 incoming_paket_libav.data += adv;
1950 incoming_paket_libav.size-=adv;
1953 /*if (current_context->frame_size>0) framesize=min(current_context->frame_size,haveToCopy);
1954 else*/ framesize=haveToCopy;
1955 //Log::getInstance()->log("Audio", Log::DEBUG,"Advance by %d %d from %d",adv,packet.type,*samplepos );
1956 if (haveToCopy <= 0) {
1957 // Log::getInstance()->log("Audio", Log::DEBUG,"No sync code in packet remove %d",packet.type);
1958 *samplepos=packet.length;
1959 return packet.length;
1965 if (gotframesize>0 && gotframesize>haveToCopy) {
1966 donotdecompress=true;
1967 errcount=100; // exit loop
1969 // else Log::getInstance()->log("Audio", Log::DEBUG,"Loop run" );
1971 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 19");
1972 if (!donotdecompress) {
1975 pthread_testcancel();
1976 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldcancelstate);
1977 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldcanceltype);
1979 if (!omx_running || !mp23codec_context_libav
1980 || !ac3codec_context_libav) {
1981 libav_mutex.Unlock();
1984 libav_mutex.Unlock();
1985 // Log::getInstance()->log("Audio", Log::DEBUG,"libav out");
1986 len = avcodec_decode_audio4(current_context, decode_frame_libav,
1987 &gotta, &incoming_paket_libav);
1988 //Log::getInstance()->log("Audio", Log::DEBUG, "libav out1");
1989 pthread_setcancelstate(oldcancelstate, NULL);
1990 pthread_setcanceltype(oldcanceltype, NULL);
1991 pthread_testcancel();
1997 //Log::getInstance()->log("Audio", Log::DEBUG, "libav out2");
1998 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 20");
2000 libav_mutex.Unlock();
2004 if (decompress_buffer_filled) { // reset to normal decoding
2006 Log::getInstance()->log("Audio", Log::DEBUG,"saved audio: %d",len);
2007 haveToCopy -= min(len-decompress_buffer_filled,0);
2008 *samplepos += min(len-decompress_buffer_filled,0);
2009 //if (current_context->frame_size>0) framesize=min(current_context->frame_size,haveToCopy);
2010 /*else*/ framesize=haveToCopy;
2012 framesize=haveToCopy;
2014 incoming_paket_libav.data =(uint8_t*) buffer+packet.pos_buffer+*samplepos;
2016 decompress_buffer_filled=0;
2020 incoming_paket_libav.data += len;
2024 /*if (current_context->frame_size>0) framesize=min(current_context->frame_size,haveToCopy);
2025 else*/framesize=haveToCopy;
2028 framesize=haveToCopy;
2031 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 21");
2033 incoming_paket_libav.size =framesize;
2035 //Log::getInstance()->log("Audio", Log::DEBUG,
2037 int dsize = av_samples_get_buffer_size(NULL,
2038 current_context->channels, decode_frame_libav->nb_samples,
2039 current_context->sample_fmt, 1);
2040 if (current_context->channels==1) dsize*=2; // we convert mono to stereo
2041 if ((cur_input_buf_omx->nFilledLen + dsize)
2042 > cur_input_buf_omx->nAllocLen ) {
2043 // I doubt that this will ever happen
2044 // Log::getInstance()->log("Audio", Log::DEBUG,
2045 // "P 2 Time code %lld pts %lld", lastreftimeOMX, packet.pts);
2046 OMX_ERRORTYPE error = vw->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/,
2048 if (error != OMX_ErrorNone) {
2049 Log::getInstance()->log("Audio", Log::DEBUG,
2050 "OMX_EmptyThisBuffer 4 failed %x", error);
2052 cur_input_buf_omx = NULL;
2054 if (!cur_input_buf_omx) {
2056 while (count < 10 && omx_running) {
2058 input_bufs_omx_mutex.Lock();
2059 if (input_bufs_omx_free.size() == 0) {
2060 input_bufs_omx_mutex.Unlock();
2061 // Log::getInstance()->log("Audio", Log::DEBUG,
2062 // "Deliver MediaPacket no free sample");
2064 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark22");
2065 if (!omx_running) return *samplepos;
2066 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 23");
2069 cur_input_buf_omx = input_bufs_omx_free.front();
2070 cur_input_buf_omx->nFilledLen = 0;
2071 cur_input_buf_omx->nOffset = 0;
2072 cur_input_buf_omx->nTimeStamp = VideoOMX::intToOMXTicks(0);
2073 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
2074 input_bufs_omx_free.pop_front();
2075 input_bufs_omx_mutex.Unlock();
2078 if (!cur_input_buf_omx) return *samplepos;
2083 //Log::getInstance()->log("Audio", Log::DEBUG,"memcpy in %d %d %d" ,dsize,current_context->sample_rate,cur_input_buf_omx->nFilledLen);
2084 if (current_context->channels!=1) {
2085 memcpy(cur_input_buf_omx->pBuffer + cur_input_buf_omx->nFilledLen,
2086 decode_frame_libav->data[0], dsize);
2087 } else { //convert to stereo
2088 unsigned short* startbuffer=(unsigned short* )decode_frame_libav->data[0];
2089 unsigned short* endbuffer=(unsigned short* )(decode_frame_libav->data[0]+dsize/2);
2090 unsigned short* destbuffer=(unsigned short* )(cur_input_buf_omx->pBuffer + cur_input_buf_omx->nFilledLen);
2091 while (startbuffer!=endbuffer) {
2092 unsigned short temp=*startbuffer;
2100 //Log::getInstance()->log("Audio", Log::DEBUG,"memcpy out");
2101 cur_input_buf_omx->nFilledLen += dsize;
2103 //Log::getInstance()->log("Audio", Log::DEBUG,"Incomplete mpeg frames in pes packet %d %d",incoming_paket_libav.size,packet.length);
2104 /* uint8_t a1=incoming_paket_libav.data[0];
2105 uint8_t a2=incoming_paket_libav.data[1];
2106 uint8_t a3=incoming_paket_libav.data[2];
2107 uint8_t a4=incoming_paket_libav.data[3];*/
2108 // Log::getInstance()->log("Audio", Log::DEBUG,"Header %x %x %x %x",a1,a2,
2113 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 24");
2114 decompress_buffer_filled=0;
2116 Log::getInstance()->log("Audio", Log::DEBUG,"We can not decompress %d save for later %d %x %x",haveToCopy,packet.type,incoming_paket_libav.data,packet.pos_buffer);
2117 memcpy(decompress_buffer,incoming_paket_libav.data,min(haveToCopy,decompress_buffer_size));
2119 decompress_buffer_filled=min(haveToCopy,decompress_buffer_size);
2123 if (cur_input_buf_omx->nFilledLen) {
2124 //Log::getInstance()->log("Audio", Log::DEBUG,
2125 // "P 3 Time code %lld pts %lld", lastreftimeOMX, packet.pts);
2126 error = vw->ProtOMXEmptyThisBuffer(omx_aud_rend/*dec*/, cur_input_buf_omx);
2127 if (error != OMX_ErrorNone) {
2128 Log::getInstance()->log("Audio", Log::DEBUG,
2129 "OMX_EmptyThisBuffer 5 failed %x", error);
2131 //if (packet.synched) vw->AdjustAudioPTS(correctAudioLatency(lastreftimeOMX,cur_input_buf_omx->nFilledLen/(2*2),48000));
2132 cur_input_buf_omx = NULL;
2137 //Log::getInstance()->log("Audio", Log::DEBUG, "DMP mark 25");
2139 *samplepos=packet.length;
2140 return packet.length;
2146 long long AudioOMX::SetStartOffset(long long curreftime, bool *rsync){
2147 VideoOMX *vw=(VideoOMX*)Video::getInstance();
2148 return vw->SetStartAudioOffset(curreftime,rsync);
2151 void AudioOMX::ResetTimeOffsets() {
2152 VideoOMX *vw=(VideoOMX*)Video::getInstance();
2153 vw->ResetTimeOffsets();