eDVBResourceManager *eDVBResourceManager::instance;
eDVBResourceManager::eDVBResourceManager()
+ :m_releaseCachedChannelTimer(eApp)
{
avail = 1;
busy = 0;
eDebug("found %d adapter, %d frontends and %d demux",
m_adapter.size(), m_frontend.size(), m_demux.size());
+
+ CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel);
}
channel = m_cached_channel;
return 0;
}
+ m_cached_channel_state_changed_conn.disconnect();
m_cached_channel=0;
+ m_releaseCachedChannelTimer.stop();
}
// eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
return errChidNotFound;
}
m_cached_channel = channel = ch;
+ m_cached_channel_state_changed_conn =
+ CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
return 0;
}
+void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
+{
+ int state=0;
+ chan->getState(state);
+ switch (state)
+ {
+ case iDVBChannel::state_release:
+ case iDVBChannel::state_ok:
+ {
+ eDebug("stop release channel timer");
+ m_releaseCachedChannelTimer.stop();
+ break;
+ }
+ case iDVBChannel::state_last_instance:
+ {
+ eDebug("start release channel timer");
+ m_releaseCachedChannelTimer.start(3000, true);
+ break;
+ }
+ default: // ignore all other events
+ break;
+ }
+}
+
+void eDVBResourceManager::releaseCachedChannel()
+{
+ eDebug("release cached channel (timer timeout)");
+ m_cached_channel=0;
+}
+
RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
{
ePtr<eDVBAllocatedFrontend> fe;
if (m_cached_channel)
+ {
+ m_cached_channel_state_changed_conn.disconnect();
m_cached_channel=0;
+ m_releaseCachedChannelTimer.stop();
+ }
if (allocateFrontendByIndex(fe, frontend_index))
return errNoFrontend;
{
ePtr<eDVBAllocatedDemux> demux;
- if (m_cached_channel)
- m_cached_channel=0;
-
eDVBChannel *ch;
ch = new eDVBChannel(this, 0);
void eDVBChannel::cueSheetEvent(int event)
{
- /* we need proper locking here! */
- eDebug("CUE SHEET EVENT %d", event);
-
switch (event)
{
case eCueSheet::evtSeek:
break;
case eCueSheet::evtSkipmode:
{
- m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
- if (m_cue->m_skipmode_ratio)
{
- int bitrate = m_tstools.calcBitrate(); /* in bits/s */
- eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
- /* i agree that this might look a bit like black magic. */
- m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
- m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio;
-
- eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
-
- if (abs(m_skipmode_m) < abs(m_skipmode_n))
+ eSingleLocker l(m_cue->m_lock);
+ m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
+ if (m_cue->m_skipmode_ratio)
{
- eFatal("damn, something is wrong with this calculation");
+ int bitrate = m_tstools.calcBitrate(); /* in bits/s */
+ eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
+ /* i agree that this might look a bit like black magic. */
+ m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
+ m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
+
+ if (m_cue->m_skipmode_ratio < 0)
+ m_skipmode_m -= m_skipmode_n;
+
+ eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
+
+ if (abs(m_skipmode_m) < abs(m_skipmode_n))
+ {
+ eWarning("something is wrong with this calculation");
+ m_skipmode_n = m_skipmode_m = 0;
+ }
+
+ } else
+ {
+ eDebug("skipmode ratio is 0, normal play");
m_skipmode_n = m_skipmode_m = 0;
}
-
- } else
- {
- eDebug("skipmode ratio is 0, normal play");
- m_skipmode_n = m_skipmode_m = 0;
}
flushPVR(m_cue->m_decoding_demux);
break;
size = max;
return;
}
+
+ eSingleLocker l(m_cue->m_lock);
if (!m_cue->m_decoding_demux)
{
if (relative)
{
pts_t now;
- /* we're using the decoder's timestamp here. this
- won't work for radio (ouch). */
+ if (!m_cue->m_decoder)
+ {
+ eDebug("no decoder - can't seek relative");
+ continue;
+ }
+ if (m_cue->m_decoder->getPTS(0, now))
+ {
+ eDebug("decoder getPTS failed, can't seek relative");
+ continue;
+ }
if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
{
eDebug("seekTo: getCurrentPosition failed!");
void eDVBChannel::AddUse()
{
- ++m_use_count;
+ if (++m_use_count > 1 && m_state == state_last_instance)
+ {
+ m_state = state_ok;
+ m_stateChanged(this);
+ }
}
void eDVBChannel::ReleaseUse()
m_state = state_release;
m_stateChanged(this);
}
+ else if (m_use_count == 1)
+ {
+ m_state = state_last_instance;
+ m_stateChanged(this);
+ }
}
RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
if (!decoding_demux)
return -1;
- off_t begin = 0;
- /* getPTS for offset 0 is cached, so it doesn't harm. */
- int r = m_tstools.getPTS(begin, pos);
- if (r)
- {
- eDebug("tstools getpts(0) failed!");
- return r;
- }
-
pts_t now;
- /* TODO: this is a gross hack. */
- r = decoding_demux->getSTC(now, mode ? 128 : 0);
-
- if (r)
+ int r;
+
+ if (mode == 0) /* demux */
{
- eDebug("demux getSTC failed");
- return -1;
- }
+ r = decoding_demux->getSTC(now, 0);
+ if (r)
+ {
+ eDebug("demux getSTC failed");
+ return -1;
+ }
+ } else
+ now = pos; /* fixup supplied */
-// eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
- /* when we are less than 10 seconds before the start, return 0. */
- /* (we're just waiting for the timespam to start) */
- if ((now < pos) && ((pos - now) < 90000 * 10))
+ off_t off = 0; /* TODO: fixme */
+ r = m_tstools.fixupPTS(off, now);
+ if (r)
{
- pos = 0;
- return 0;
+ eDebug("fixup PTS failed");
+ return -1;
}
- if (now < pos) /* wrap around */
- pos = now + ((pts_t)1)<<33 - pos;
- else
- pos = now - pos;
+ pos = now;
return 0;
}
void eCueSheet::seekTo(int relative, const pts_t &pts)
{
- m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
+ {
+ eSingleLock l(m_lock);
+ m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
+ }
m_event(evtSeek);
}
void eCueSheet::clear()
{
+ eSingleLock l(m_lock);
m_spans.clear();
}
void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
{
- m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
+ {
+ eSingleLock l(m_lock);
+ m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
+ }
m_event(evtSpanChanged);
}
void eCueSheet::setSkipmode(const pts_t &ratio)
{
- m_skipmode_ratio = ratio;
+ {
+ eSingleLock l(m_lock);
+ m_skipmode_ratio = ratio;
+ }
m_event(evtSkipmode);
}
-void eCueSheet::setDecodingDemux(iDVBDemux *demux)
+void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
{
m_decoding_demux = demux;
+ m_decoder = decoder;
}
RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)