add possibility to set per service ac3/pcm delay (not yet via gui)
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>
Thu, 22 Jun 2006 21:17:20 +0000 (21:17 +0000)
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>
Thu, 22 Jun 2006 21:17:20 +0000 (21:17 +0000)
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
lib/dvb/decoder.h
lib/dvb/idvb.h
lib/dvb/pmt.cpp
lib/dvb/pmt.h
lib/service/iservice.h
lib/service/servicedvb.cpp
lib/service/servicedvb.h
lib/service/servicemp3.h

index 362289f3196dc20cd2c29a73a78a37c2847e3501..a05c837c9a10ae5cf4f5f51e0253d602066e182e 100644 (file)
@@ -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)
index 554d8c1bd1420296b66f0fbf7be150c004f74196..b50a605ba1184f77e94f14ecba642795aa48bc5d 100644 (file)
@@ -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<eDVBDemux> 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);
index 8bbbaafa473c89b773f4909149fe5991fe5496b0..69342717a872960ddee71dab71de2a892e4cf330 100644 (file)
@@ -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;
index d0119508470a6642f9e81c14b5f5081d9b5b99a3..d6f002e6dda59320b85d3aaf108307e493361c7c 100644 (file)
@@ -160,27 +160,27 @@ PyObject *eDVBServicePMTHandler::getCaIds()
 int eDVBServicePMTHandler::getProgramInfo(struct program &program)
 {
        ePtr<eTable<ProgramMapSection> > 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)
index 57176d1f363d189365c445f47faf74d0b56efddf..fc8b15dd99237e6d433a09fc13bf4a646ce2e4bc 100644 (file)
@@ -122,9 +122,8 @@ public:
                int pmtPid;
                int textPid;
                bool isCrypted() { return !caids.empty(); }
-               int audioChannel;
        };
-       
+
        int getProgramInfo(struct program &program);
        int getDataDemux(ePtr<iDVBDemux> &demux);
        int getDecodeDemux(ePtr<iDVBDemux> &demux);
index fed66a290a8d03928e5f6efc0a7c7f5e6f1b7ef6..7eeee6936ed76dbc859ae7c1b577f8cf988a32b3 100644 (file)
@@ -389,6 +389,21 @@ public:
 
 TEMPLATE_TYPEDEF(ePtr<iAudioChannelSelection>, 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<iAudioDelay>, iAudioDelayPtr);
+
 class iSubserviceList: public iObject
 {
 #ifdef SWIG
@@ -493,6 +508,7 @@ public:
        virtual SWIG_VOID(RESULT) timeshift(ePtr<iTimeshiftService> &SWIG_OUTPUT)=0;
        virtual SWIG_VOID(RESULT) cueSheet(ePtr<iCueSheet> &SWIG_OUTPUT)=0;
        virtual SWIG_VOID(RESULT) subtitle(ePtr<iSubtitleOutput> &SWIG_OUTPUT)=0;
+       virtual SWIG_VOID(RESULT) audioDelay(ePtr<iAudioDelay> &SWIG_OUTPUT)=0;
 };
 
 TEMPLATE_TYPEDEF(ePtr<iPlayableService>, iPlayableServicePtr);
index f7da3a3bd3f48ebddd0f26a2ea163f1517718d73..8f58cdee0b79f06f3c14485484e453559a02b553 100644 (file)
@@ -630,7 +630,7 @@ RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &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<iSubtitleOutput> &ptr)
        return 0;
 }
 
+RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &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<eDVBResourceManager> res_mgr;
+                       if (!eDVBResourceManager::getInstance(res_mgr))
+                       {
+                               ePtr<iDVBChannelList> db;
+                               if (!res_mgr->getChannelList(db))
+                               {
+                                       ePtr<eDVBService> 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<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");
index 42457598d401cee9bbc7ce5adfb1245ececb31fd..29cff4d344dcd7591f0604c12093121806521bc5 100644 (file)
@@ -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<iTimeshiftService> &ptr);
        RESULT cueSheet(ePtr<iCueSheet> &ptr);
        RESULT subtitle(ePtr<iSubtitleOutput> &ptr);
+       RESULT audioDelay(ePtr<iAudioDelay> &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<iDVBDemux> m_decode_demux;
 
-       int m_current_audio_channel;
        int m_current_audio_stream;
        int selectAudioStream(int n);
        
index 36c9da3c25281f6e2d42e8062b7c3e6bd8450983..32c9dc75f28bc5df4e8a20eff7be1eff090a3f2a 100644 (file)
@@ -65,7 +65,8 @@ public:
        RESULT timeshift(ePtr<iTimeshiftService> &ptr) { ptr = 0; return -1; }
        RESULT cueSheet(ePtr<iCueSheet> &ptr) { ptr = 0; return -1; }
        RESULT subtitle(ePtr<iSubtitleOutput> &ptr) { ptr = 0; return -1; }
-       
+       RESULT audioDelay(ePtr<iAudioDelay> &ptr) { ptr = 0; return -1; }
+
                // iPausableService
        RESULT pause();
        RESULT unpause();