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.
22 #include "videovpeogl.h"
25 #include "woptionpane.h"
35 lastAType = MPTYPE_MPEG_AUDIO;
40 canpass_pcm_mch=false;
42 prefered_ac3=0; //0 stereo PCM, 1 passthrough 2 Multichannel PCM
51 int AudioVPE::init(UCHAR tstreamType)
53 if (initted) return 0;
56 // // if ((fdAudio = open("/dev/adec_mpg", O_RDWR | O_NONBLOCK)) < 0) return 0;
57 // if ((fdAudio = open("/dev/adec_mpg", O_WRONLY)) < 0) return 0;
59 streamType = tstreamType;
69 // Set the volume variable to what the hardware is set at now
71 /* int hwvolFail = ioctl(fdAudio, AV_GET_AUD_VOLUME, &hwvol);
74 volume = 20 - ((hwvol >> 16) & 0xFF);
75 if ((volume < 0) || (volume > 20)) volume = 20;
81 int AudioVPE::initAllParams()
83 return (setStreamType(streamType) && setChannel() && setSource());
86 int AudioVPE::shutdown()
88 if (!initted) return 0;
94 bool AudioVPE::loadOptionsfromServer(VDR* vdr)
96 char *name=vdr->configLoad("AudioOMX","AC3DecodingMode");
99 if (STRCASECMP(name, "PCM") == 0) {
101 } else if (STRCASECMP(name, "Passthrough") == 0) {
103 } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
108 name = vdr->configLoad("AudioOMX", "Mp2DecodingMode");
111 if (STRCASECMP(name, "PCM") == 0) {
113 } else if (STRCASECMP(name, "Passthrough") == 0) {
115 } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
120 name = vdr->configLoad("AudioOMX", "Mp3DecodingMode");
123 if (STRCASECMP(name, "PCM") == 0) {
125 } else if (STRCASECMP(name, "Passthrough") == 0) {
127 } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
132 name = vdr->configLoad("AudioOMX", "AudioOutput");
135 if (STRCASECMP(name, "analog") == 0) {
137 } else if (STRCASECMP(name, "HDMI") == 0) {
147 bool AudioVPE::handleOptionChanges(Option* option)
149 if (Audio::handleOptionChanges(option))
151 switch (option->id) {
153 if (STRCASECMP(option->options[option->userSetChoice], "analog") == 0) {
155 } else if (STRCASECMP(option->options[option->userSetChoice], "HDMI")
163 if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
165 } else if (STRCASECMP(option->options[option->userSetChoice],
166 "Passthrough") == 0) {
168 } else if (STRCASECMP(option->options[option->userSetChoice],
169 "PCMMultichannel") == 0) {
175 if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
177 } else if (STRCASECMP(option->options[option->userSetChoice],
178 "Passthrough") == 0) {
180 } else if (STRCASECMP(option->options[option->userSetChoice],
181 "PCMMultichannel") == 0) {
187 if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
189 } else if (STRCASECMP(option->options[option->userSetChoice],
190 "Passthrough") == 0) {
192 } else if (STRCASECMP(option->options[option->userSetChoice],
193 "PCMMultichannel") == 0) {
203 bool AudioVPE::saveOptionstoServer()
206 switch (prefered_ac3) {
208 VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode", "PCM");
211 VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode",
215 VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode",
220 switch (prefered_mp2) {
222 VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode", "PCM");
225 VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode",
229 VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode",
234 switch (prefered_mp3) {
236 VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode", "PCM");
239 VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode",
243 VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode",
249 VDR::getInstance()->configSave("AudioOMX", "AudioOutput", "analog");
251 VDR::getInstance()->configSave("AudioOMX", "AudioOutput", "HDMI");
257 /*Option(UINT id, const char* displayText, const char* configSection, const char* configKey, UINT optionType,
258 UINT numChoices, UINT defaultChoice, UINT startInt,
259 const char * const * options, const char * const * optionkeys = NULL, AbstractOption* handler=NULL);*/
261 bool AudioVPE::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
263 if (!Audio::addOptionsToPanes(panenumber,options,pane)) return false;
270 static const char* audioopts[]={"analog","HDMI"};
271 option = new Option(4,tr("Audio Output"), "AudioOMX","AudioOutput",Option::TYPE_TEXT,2,0,0,audioopts,NULL,false,this);
272 options->push_back(option);
273 pane->addOptionLine(option);
276 char **ac3opts=new char *[3];
278 ac3opts[i]=new char[strlen("PCM")+1];
279 strcpy(ac3opts[i],"PCM");
282 ac3opts[i]=new char[strlen("Passthrough")+1];
283 strcpy(ac3opts[i],"PassThrough");
286 if (canpass_pcm_mch) {
287 ac3opts[i]=new char[strlen("PCMMultichannel")+1];
288 strcpy(ac3opts[i],"PCMMultichannel");
291 option = new Option(1 ,tr("AC3 HDMI Mode"), "AudioOMX", "AC3DecodingMode", Option::TYPE_TEXT, i, 0, 0, ac3opts,NULL,true, this);
292 options->push_back(option);
293 pane->addOptionLine(option);
295 char **mp2opts = new char *[3];
297 mp2opts[i] = new char[strlen("PCM") + 1];
298 strcpy(mp2opts[i], "PCM");
301 mp2opts[i] = new char[strlen("Passthrough") + 1];
302 strcpy(mp2opts[i], "PassThrough");
305 if (canpass_pcm_mch) {
306 mp2opts[i] = new char[strlen("PCMMultichannel") + 1];
307 strcpy(mp2opts[i], "PCMMultichannel");
310 option = new Option(2, tr("Mp2 HDMI Mode"), "AudioOMX",
311 "Mp2DecodingMode", Option::TYPE_TEXT, i, 0, 0,
312 mp2opts, NULL, true, this);
313 options->push_back(option);
314 pane->addOptionLine(option);
316 char **mp3opts = new char *[3];
318 mp3opts[i] = new char[strlen("PCM") + 1];
319 strcpy(mp3opts[i], "PCM");
322 mp3opts[i] = new char[strlen("Passthrough") + 1];
323 strcpy(mp3opts[i], "PassThrough");
326 if (canpass_pcm_mch) {
327 mp3opts[i] = new char[strlen("PCMMultichannel") + 1];
328 strcpy(mp3opts[i], "PCMMultichannel");
331 option = new Option(3, tr("Mp3 HDMI Mode"), "AudioOMX",
332 "Mp2DecodingMode", Option::TYPE_TEXT, i, 0, 0, mp3opts,
334 options->push_back(option);
335 pane->addOptionLine(option);
346 int AudioVPE::setStreamType(UCHAR type)
348 if (!initted) return 0;
350 // if (ioctl(fdAudio, AV_SET_AUD_STREAMTYPE, type) != 0) return 0;
354 int AudioVPE::setChannel()
356 if (!initted) return 0;
358 // if (ioctl(fdAudio, AV_SET_AUD_CHANNEL, 0) != 0) return 0;
362 int AudioVPE::setSource()
364 if (!initted) return 0;
366 // if (ioctl(fdAudio, AV_SET_AUD_SRC, 1) != 0) return 0;
372 if (!initted) return 0;
374 // if (ioctl(fdAudio, AV_SET_AUD_SYNC, 2) != 0) return 0;
380 if (!initted) return 0;
385 //if (ioctl(fdAudio, AV_SET_AUD_PLAY, 0) != 0) return 0;
391 if (!initted) return 0;
393 //if (ioctl(fdAudio, AV_SET_AUD_RESET, 0x11) != 0) return 0;
399 if (!initted) return 0;
401 // if (ioctl(fdAudio, AV_SET_AUD_MUTE, 1) != 0) return 0;
402 Log::getInstance()->log("Audio", Log::DEBUG, "MUTE MUTE MUTE");
408 int AudioVPE::unMute()
410 if (!initted) return 0;
412 // if (ioctl(fdAudio, AV_SET_AUD_MUTE, 0) != 0) return 0;
413 Log::getInstance()->log("Audio", Log::DEBUG, "MUTE OFF OFF OFF");
419 int AudioVPE::pause()
421 if (!initted) return 0;
423 // if (ioctl(fdAudio, AV_SET_AUD_PAUSE, 1) != 0) return 0;
427 int AudioVPE::unPause()
429 if (!initted) return 0;
431 // if (ioctl(fdAudio, AV_SET_AUD_UNPAUSE, 1) != 0) return 0;
435 int AudioVPE::reset()
437 if (!initted) return 0;
439 Log::getInstance()->log("Audio", Log::DEBUG, "reset called");
442 // if (ioctl(fdAudio, AV_SET_AUD_RESET, 0x11) != 0) return 0;
443 // Log::getInstance()->log("Audio", Log::DEBUG, "reset back");
444 // if (ioctl(fdAudio, AV_SET_AUD_PLAY, 0) != 0) return 0;
450 int AudioVPE::setVolume(int tvolume)
452 // parameter: 0 for silence, 20 for full
453 if ((tvolume < 0) || (tvolume > 20)) return 0;
455 // volume = 2 * (20 - volume);
456 // Right, that one was rubbish... 0-10 were almost
457 // inaudible, 11-20 did what should have been done
458 // over the whole 0-20 range
460 tvolume = 20 - tvolume;
462 audio_volume Avolume;
463 Avolume.frontleft = tvolume + Aoffset.frontleft;
464 Avolume.frontright = tvolume + Aoffset.frontright;
465 Avolume.rearleft = tvolume + Aoffset.rearleft;
466 Avolume.rearright = tvolume + Aoffset.rearright;
467 Avolume.center = tvolume + Aoffset.center;
468 Avolume.lfe = tvolume + Aoffset.lfe;
470 // if (ioctl(fdAudio, AV_SET_AUD_VOLUME, &Avolume) != 0) return 0;
472 // unsigned long vol = (tvolume << 24) | (tvolume << 16);
474 // Log::getInstance()->log("Audio", Log::DEBUG, "%lx", vol);
475 // Log::getInstance()->log("Audio", Log::DEBUG, "%i", tvolume);
477 // if (ioctl(fdAudio, AV_SET_AUD_VOLUME, &vol) != 0) return 0;
485 // return ioctl(fdAudio, AV_SET_AUD_STC, &stc);
487 /* aud_sync_parms_t a;
491 // int b = ioctl(fdAudio, AV_SET_AUD_DISABLE_SYNC, &a);
494 /*OK*/ //printf("Audio sync disable = %i\n", b);
502 void AudioVPE::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
504 packet = mplist.front();
507 UINT AudioVPE::DeliverMediaSample(UCHAR* buffer, UINT* samplepos)
509 VideoVPEOGL *video=(VideoVPEOGL*)Video::getInstance();
510 //Log::getInstance()->log("Audio", Log::DEBUG, "lastpacket %d lastbuddypacket %d currentpacket %d",lastpacketnum,video->getLastPacketNum(),packet.index);
511 currentpacketnum=packet.index;
512 if (lastpacketnum!=-1 && packet.index-1!=lastpacketnum && packet.index-1>video->getLastPacketNum()) return 0; //Not in order
515 switch (packet.type) {
516 case MPTYPE_MPEG_AUDIO:
517 buffer[packet.pos_buffer + 3]=0xc0; break;
519 buffer[packet.pos_buffer +buffer[packet.pos_buffer+8]+9]=0x80;
520 buffer[packet.pos_buffer + 3]=0xbd; break;
523 case MPTYPE_AC3_PRE13://Not tested no recording availiable
524 buffer[packet.pos_buffer + 3]=0xbd; break;
528 if (packet.type!=lastAType && lastpacketnum!=-1){//Format Change //Push data out !
529 video->deinitMuxer();
530 lastAType=packet.type;
533 lastAType=packet.type;
536 /* Mutex *mutex=video->getMuxMutex();
538 FILE *muxout=video->getMuxFile();
539 if (!muxout) {mutex->Unlock(); return 0;}*
541 //written=fwrite(buffer + packet.pos_buffer,1,packet.length,muxout);
542 written=video->WriteOutTS(buffer + packet.pos_buffer,packet.length,packet.type);
543 lastpacketnum=packet.index;
547 //Log::getInstance()->log("Audio", Log::DEBUG, "wrote %d bytes to mux",written);
549 if (written == (int)packet.length) { *samplepos = 0; return 1;}
553 *samplepos = written;*/
554 // Handle a partial write. Is this possible? Should we bother? No!
556 *samplepos=packet.length;
560 void AudioVPE::ResetTimeOffsets()