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);
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)
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;
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);
public:
enum cacheID
{
- cVPID, cAPID, cTPID, cPCRPID, cAC3PID, cVTYPE, cACHANNEL, cacheMax
+ cVPID, cAPID, cTPID, cPCRPID, cAC3PID,
+ cVTYPE, cACHANNEL, cAC3DELAY, cPCMDELAY, cacheMax
};
int getCacheEntry(cacheID);
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;
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;
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)
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);
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
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);
}
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();
return 0;
}
+RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
+{
+ ptr = this;
+ return 0;
+}
+
RESULT eDVBServicePlay::getName(std::string &name)
{
if (m_is_pvr)
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;
}
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;
pcrpid = program.pcrPid;
eDebug(", and the text pid is %04x", program.textPid);
tpid = program.textPid;
- achannel = program.audioChannel;
}
if (!m_decoder)
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);
m_decoder->start();
- m_current_audio_channel=achannel;
m_decoder->setAudioChannel(achannel);
// how we can do this better?
}
}
+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");
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:
RESULT timeshift(ePtr<iTimeshiftService> &ptr);
RESULT cueSheet(ePtr<iCueSheet> &ptr);
RESULT subtitle(ePtr<iSubtitleOutput> &ptr);
+ RESULT audioDelay(ePtr<iAudioDelay> &ptr);
// iPauseableService
RESULT pause();
RESULT disableSubtitles(eWidget *parent);
PyObject *getSubtitleList();
+ // iAudioDelay
+ int getAC3Delay();
+ int getPCMDelay();
+ void setAC3Delay(int);
+ void setPCMDelay(int);
+
private:
friend class eServiceFactoryDVB;
eServiceReference m_reference;
ePtr<iDVBDemux> m_decode_demux;
- int m_current_audio_channel;
int m_current_audio_stream;
int selectAudioStream(int n);
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();