From 8d0841a3c4d57ec102acc2a8ac09123b7ebdee27 Mon Sep 17 00:00:00 2001 From: Andreas Monzner Date: Thu, 22 Jun 2006 21:17:20 +0000 Subject: [PATCH] add possibility to set per service ac3/pcm delay (not yet via gui) to set a pcm or ac3 delay for a specific service edit your servicelist (/etc/enigma2/lamedb) example for pcm delay: 6dca:00c00000:044d:0001:1:0 Das Erste p:ARD,c:000065,c:010066,c:020068,c:030065,c:060001,c:080060 <-- 0x60 = 96ms PCM delay for AC3 delay set, c:07xxxx --- lib/dvb/decoder.cpp | 54 +++++++++++++++++++-- lib/dvb/decoder.h | 8 ++++ lib/dvb/idvb.h | 9 +++- lib/dvb/pmt.cpp | 50 +++++++++---------- lib/dvb/pmt.h | 3 +- lib/service/iservice.h | 16 +++++++ lib/service/servicedvb.cpp | 98 ++++++++++++++++++++++++++++++++------ lib/service/servicedvb.h | 10 +++- lib/service/servicemp3.h | 3 +- 9 files changed, 200 insertions(+), 51 deletions(-) diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp index 362289f3..a05c837c 100644 --- a/lib/dvb/decoder.cpp +++ b/lib/dvb/decoder.cpp @@ -530,6 +530,37 @@ int eTSMPEGDecoder::setState() return res; } +int eTSMPEGDecoder::m_pcm_delay=-1, + eTSMPEGDecoder::m_ac3_delay=-1; + +RESULT eTSMPEGDecoder::setPCMDelay(int delay) +{ + if (m_decoder == 0 && delay != m_pcm_delay ) + { + FILE *fp = fopen("/proc/stb/audio/audio_delay_pcm", "w"); + if (fp) + { + fprintf(fp, "%x", delay*90); + fclose(fp); + m_pcm_delay = delay; + } + } +} + +RESULT eTSMPEGDecoder::setAC3Delay(int delay) +{ + if ( m_decoder == 0 && delay != m_ac3_delay ) + { + FILE *fp = fopen("/proc/stb/audio/audio_delay_bitstream", "w"); + if (fp) + { + fprintf(fp, "%x", delay*90); + fclose(fp); + m_ac3_delay = delay; + } + } +} + eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder): m_demux(demux), m_changed(0), m_decoder(decoder) { demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event); @@ -565,15 +596,30 @@ RESULT eTSMPEGDecoder::setAudioPID(int apid, int type) return 0; } +int eTSMPEGDecoder::m_audio_channel = -1; + RESULT eTSMPEGDecoder::setAudioChannel(int channel) { - if (m_audio) - m_audio->setChannel(channel); - else - eDebug("eTSMPEGDecoder::setAudioChannel but no audio decoder exist"); + if (channel == -1) + channel = ac_stereo; + if (m_decoder == 0 && m_audio_channel != channel) + { + if (m_audio) + { + m_audio->setChannel(channel); + m_audio_channel=channel; + } + else + eDebug("eTSMPEGDecoder::setAudioChannel but no audio decoder exist"); + } return 0; } +int eTSMPEGDecoder::getAudioChannel() +{ + return m_audio_channel == -1 ? ac_stereo : m_audio_channel; +} + RESULT eTSMPEGDecoder::setSyncPCR(int pcrpid) { if (m_pcrpid != pcrpid) diff --git a/lib/dvb/decoder.h b/lib/dvb/decoder.h index 554d8c1b..b50a605b 100644 --- a/lib/dvb/decoder.h +++ b/lib/dvb/decoder.h @@ -82,6 +82,9 @@ public: class eTSMPEGDecoder: public Object, public iTSMPEGDecoder { + static int m_pcm_delay; + static int m_ac3_delay; + static int m_audio_channel; DECLARE_REF(eTSMPEGDecoder); private: ePtr m_demux; @@ -110,6 +113,11 @@ public: RESULT setVideoPID(int vpid, int type); RESULT setAudioPID(int apid, int type); RESULT setAudioChannel(int channel); + int getAudioChannel(); + RESULT setPCMDelay(int delay); + int getPCMDelay() { return m_pcm_delay; } + RESULT setAC3Delay(int delay); + int getAC3Delay() { return m_ac3_delay; } RESULT setSyncPCR(int pcrpid); RESULT setTextPID(int textpid); RESULT setSyncMaster(int who); diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h index 8bbbaafa..69342717 100644 --- a/lib/dvb/idvb.h +++ b/lib/dvb/idvb.h @@ -234,7 +234,8 @@ class eDVBService: public iStaticServiceInformation public: enum cacheID { - cVPID, cAPID, cTPID, cPCRPID, cAC3PID, cVTYPE, cACHANNEL, cacheMax + cVPID, cAPID, cTPID, cPCRPID, cAC3PID, + cVTYPE, cACHANNEL, cAC3DELAY, cPCMDELAY, cacheMax }; int getCacheEntry(cacheID); @@ -594,6 +595,12 @@ public: enum { ac_left, ac_stereo, ac_right }; /** Set Displayed Audio Channel */ virtual RESULT setAudioChannel(int channel)=0; + virtual int getAudioChannel()=0; + + virtual RESULT setPCMDelay(int delay)=0; + virtual int getPCMDelay()=0; + virtual RESULT setAC3Delay(int delay)=0; + virtual int getAC3Delay()=0; /** Set Displayed Videotext PID */ virtual RESULT setTextPID(int vpid)=0; diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index d0119508..d6f002e6 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -160,27 +160,27 @@ PyObject *eDVBServicePMTHandler::getCaIds() int eDVBServicePMTHandler::getProgramInfo(struct program &program) { ePtr > ptr; + int cached_apid_ac3 = -1; + int cached_apid_mpeg = -1; + int cached_vpid = -1; + int cached_tpid = -1; program.videoStreams.clear(); program.audioStreams.clear(); program.pcrPid = -1; program.pmtPid = -1; program.textPid = -1; - program.audioChannel = m_service ? m_service->getCacheEntry(eDVBService::cACHANNEL) : -1; + + if ( m_service && !m_service->cacheEmpty() ) + { + cached_vpid = m_service->getCacheEntry(eDVBService::cVPID); + cached_apid_mpeg = m_service->getCacheEntry(eDVBService::cAC3PID); + cached_apid_ac3 = m_service->getCacheEntry(eDVBService::cAPID); + cached_tpid = m_service->getCacheEntry(eDVBService::cTPID); + } if ( ((m_service && m_service->usePMT()) || !m_service) && !m_PMT.getCurrent(ptr)) { - int cached_apid_ac3 = -1; - int cached_apid_mpeg = -1; - int cached_vpid = -1; - int cached_tpid = -1; - if ( m_service && !m_service->cacheEmpty() ) - { - cached_vpid = m_service->getCacheEntry(eDVBService::cVPID); - cached_apid_mpeg = m_service->getCacheEntry(eDVBService::cAC3PID); - cached_apid_ac3 = m_service->getCacheEntry(eDVBService::cAPID); - cached_tpid = m_service->getCacheEntry(eDVBService::cTPID); - } eDVBTableSpec table_spec; ptr->getSpec(table_spec); program.pmtPid = table_spec.pid < 0x1fff ? table_spec.pid : -1; @@ -313,48 +313,44 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) return 0; } else if ( m_service && !m_service->cacheEmpty() ) { - int vpid = m_service->getCacheEntry(eDVBService::cVPID), - apid_ac3 = m_service->getCacheEntry(eDVBService::cAC3PID), - apid_mpeg = m_service->getCacheEntry(eDVBService::cAPID), - pcrpid = m_service->getCacheEntry(eDVBService::cPCRPID), - tpid = m_service->getCacheEntry(eDVBService::cTPID), + int cached_pcrpid = m_service->getCacheEntry(eDVBService::cPCRPID), vpidtype = m_service->getCacheEntry(eDVBService::cVTYPE), cnt=0; if ( vpidtype == -1 ) vpidtype = videoStream::vtMPEG2; - if ( vpid != -1 ) + if ( cached_vpid != -1 ) { videoStream s; - s.pid = vpid; + s.pid = cached_vpid; s.type = vpidtype; program.videoStreams.push_back(s); ++cnt; } - if ( apid_ac3 != -1 ) + if ( cached_apid_ac3 != -1 ) { audioStream s; s.type = audioStream::atAC3; - s.pid = apid_ac3; + s.pid = cached_apid_ac3; program.audioStreams.push_back(s); ++cnt; } - if ( apid_mpeg != -1 ) + if ( cached_apid_mpeg != -1 ) { audioStream s; s.type = audioStream::atMPEG; - s.pid = apid_mpeg; + s.pid = cached_apid_mpeg; program.audioStreams.push_back(s); ++cnt; } - if ( pcrpid != -1 ) + if ( cached_pcrpid != -1 ) { ++cnt; - program.pcrPid = pcrpid; + program.pcrPid = cached_pcrpid; } - if ( tpid != -1 ) + if ( cached_tpid != -1 ) { ++cnt; - program.textPid = tpid; + program.textPid = cached_tpid; } CAID_LIST &caids = m_service->m_ca; for (CAID_LIST::iterator it(caids.begin()); it != caids.end(); ++it) diff --git a/lib/dvb/pmt.h b/lib/dvb/pmt.h index 57176d1f..fc8b15dd 100644 --- a/lib/dvb/pmt.h +++ b/lib/dvb/pmt.h @@ -122,9 +122,8 @@ public: int pmtPid; int textPid; bool isCrypted() { return !caids.empty(); } - int audioChannel; }; - + int getProgramInfo(struct program &program); int getDataDemux(ePtr &demux); int getDecodeDemux(ePtr &demux); diff --git a/lib/service/iservice.h b/lib/service/iservice.h index fed66a29..7eeee693 100644 --- a/lib/service/iservice.h +++ b/lib/service/iservice.h @@ -389,6 +389,21 @@ public: TEMPLATE_TYPEDEF(ePtr, iAudioChannelSelectionPtr); +class iAudioDelay: public iObject +{ +#ifdef SWIG + iAudioDelay(); + ~iAudioDelay(); +#endif +public: + virtual int getAC3Delay()=0; + virtual int getPCMDelay()=0; + virtual void setAC3Delay(int)=0; + virtual void setPCMDelay(int)=0; +}; + +TEMPLATE_TYPEDEF(ePtr, iAudioDelayPtr); + class iSubserviceList: public iObject { #ifdef SWIG @@ -493,6 +508,7 @@ public: virtual SWIG_VOID(RESULT) timeshift(ePtr &SWIG_OUTPUT)=0; virtual SWIG_VOID(RESULT) cueSheet(ePtr &SWIG_OUTPUT)=0; virtual SWIG_VOID(RESULT) subtitle(ePtr &SWIG_OUTPUT)=0; + virtual SWIG_VOID(RESULT) audioDelay(ePtr &SWIG_OUTPUT)=0; }; TEMPLATE_TYPEDEF(ePtr, iPlayableServicePtr); diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index f7da3a3b..8f58cdee 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -630,7 +630,7 @@ RESULT eServiceFactoryDVB::lookupService(ePtr &service, const eServ } eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service): - m_reference(ref), m_dvb_service(service), m_is_paused(0), m_current_audio_channel(-1) + m_reference(ref), m_dvb_service(service), m_is_paused(0) { m_is_primary = 1; m_is_pvr = !m_reference.path.empty(); @@ -1069,6 +1069,12 @@ RESULT eDVBServicePlay::subtitle(ePtr &ptr) return 0; } +RESULT eDVBServicePlay::audioDelay(ePtr &ptr) +{ + ptr = this; + return 0; +} + RESULT eDVBServicePlay::getName(std::string &name) { if (m_is_pvr) @@ -1279,21 +1285,17 @@ int eDVBServicePlay::selectAudioStream(int i) int eDVBServicePlay::getCurrentChannel() { - return m_current_audio_channel == -1 ? STEREO : m_current_audio_channel; + return m_decoder ? m_decoder->getAudioChannel() : STEREO; } RESULT eDVBServicePlay::selectChannel(int i) { - if (i < iAudioChannelSelection::LEFT || i > iAudioChannelSelection::RIGHT) + if (i < LEFT || i > RIGHT) i = -1; // Stereo - if (m_current_audio_channel != i) - { - if (m_dvb_service) - m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i); - m_current_audio_channel=i; - if (m_decoder) - m_decoder->setAudioChannel(i); - } + if (m_dvb_service) + m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i); + if (m_decoder) + m_decoder->setAudioChannel(i); return 0; } @@ -1604,7 +1606,8 @@ void eDVBServicePlay::switchToTimeshift() void eDVBServicePlay::updateDecoder() { - int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1; + int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1; + eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler; bool defaultac3=false; @@ -1663,7 +1666,6 @@ void eDVBServicePlay::updateDecoder() pcrpid = program.pcrPid; eDebug(", and the text pid is %04x", program.textPid); tpid = program.textPid; - achannel = program.audioChannel; } if (!m_decoder) @@ -1681,6 +1683,39 @@ void eDVBServicePlay::updateDecoder() if (m_decoder) { + if (m_dvb_service) + { + achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL); + ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY); + pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY); + } +/* + else if (m_reference.path.length()) // workaround for recordings + { + eDebug("playback %s", m_reference.toString().c_str()); + + ePtr res_mgr; + if (!eDVBResourceManager::getInstance(res_mgr)) + { + ePtr db; + if (!res_mgr->getChannelList(db)) + { + ePtr origService; + eServiceReference tmp = m_reference; + tmp.path=""; + if (!db->getService((eServiceReferenceDVB&)tmp, origService)) + { + ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY); + pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY); + } + } + } + } +*/ + + m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay); + m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay); + m_decoder->setVideoPID(vpid, vpidtype); m_current_audio_stream = 0; m_decoder->setAudioPID(apid, apidtype); @@ -1699,7 +1734,6 @@ void eDVBServicePlay::updateDecoder() m_decoder->start(); - m_current_audio_channel=achannel; m_decoder->setAudioChannel(achannel); // how we can do this better? @@ -1947,6 +1981,42 @@ void eDVBServicePlay::checkSubtitleTiming() } } +int eDVBServicePlay::getAC3Delay() +{ + if (m_dvb_service) + return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY); + else if (m_decoder) + return m_decoder->getAC3Delay(); + else + return 0; +} + +int eDVBServicePlay::getPCMDelay() +{ + if (m_dvb_service) + return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY); + else if (m_decoder) + return m_decoder->getPCMDelay(); + else + return 0; +} + +void eDVBServicePlay::setAC3Delay(int delay) +{ + if (m_dvb_service) + m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay); + if (m_decoder) + m_decoder->setAC3Delay(delay); +} + +void eDVBServicePlay::setPCMDelay(int delay) +{ + if (m_dvb_service) + m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay); + if (m_decoder) + m_decoder->setPCMDelay(delay); +} + DEFINE_REF(eDVBServicePlay) eAutoInitPtr init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB"); diff --git a/lib/service/servicedvb.h b/lib/service/servicedvb.h index 42457598..29cff4d3 100644 --- a/lib/service/servicedvb.h +++ b/lib/service/servicedvb.h @@ -73,7 +73,7 @@ class eDVBServicePlay: public eDVBServiceBase, public iSeekableService, public Object, public iServiceInformation, public iAudioTrackSelection, public iAudioChannelSelection, public iSubserviceList, public iTimeshiftService, - public iCueSheet, public iSubtitleOutput + public iCueSheet, public iSubtitleOutput, public iAudioDelay { DECLARE_REF(eDVBServicePlay); public: @@ -95,6 +95,7 @@ public: RESULT timeshift(ePtr &ptr); RESULT cueSheet(ePtr &ptr); RESULT subtitle(ePtr &ptr); + RESULT audioDelay(ePtr &ptr); // iPauseableService RESULT pause(); @@ -146,6 +147,12 @@ public: RESULT disableSubtitles(eWidget *parent); PyObject *getSubtitleList(); + // iAudioDelay + int getAC3Delay(); + int getPCMDelay(); + void setAC3Delay(int); + void setPCMDelay(int); + private: friend class eServiceFactoryDVB; eServiceReference m_reference; @@ -177,7 +184,6 @@ private: ePtr m_decode_demux; - int m_current_audio_channel; int m_current_audio_stream; int selectAudioStream(int n); diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index 36c9da3c..32c9dc75 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -65,7 +65,8 @@ public: RESULT timeshift(ePtr &ptr) { ptr = 0; return -1; } RESULT cueSheet(ePtr &ptr) { ptr = 0; return -1; } RESULT subtitle(ePtr &ptr) { ptr = 0; return -1; } - + RESULT audioDelay(ePtr &ptr) { ptr = 0; return -1; } + // iPausableService RESULT pause(); RESULT unpause(); -- 2.30.2