X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/9e4a418c7ce0e0281ca8c06be4ee92a48eaab87a..f97a4e53dcd9321cfe4d026f8efac3a3fea1cb6a:/lib/dvb/dvb.cpp diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index 0eb614db..41c4f3ca 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -242,8 +242,8 @@ void eDVBResourceManager::addAdapter(iDVBAdapter *adapter) { if (prev_dvbt_frontend) { - prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (int)new_fe); - frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (int)&(*prev_dvbt_frontend)); + prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe); + frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend)); } prev_dvbt_frontend = new_fe; } @@ -322,7 +322,7 @@ RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr // check if another slot linked to this is in use eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend*) i->m_frontend->m_data[eDVBFrontend::SATPOS_DEPENDS_PTR]; - if ( (int)satpos_depends_to_fe != -1 ) + if ( (long)satpos_depends_to_fe != -1 ) { if (satpos_depends_to_fe->m_inuse) { @@ -335,7 +335,7 @@ RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr { eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) i->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR]; - while ( (int)next != -1 ) + while ( (long)next != -1 ) { if (next->m_inuse) { @@ -347,7 +347,7 @@ RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr } eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) i->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR]; - while ( (int)prev != -1 ) + while ( (long)prev != -1 ) { if (prev->m_inuse) { @@ -748,24 +748,119 @@ error: return ret; } +bool eDVBResourceManager::canMeasureFrontendInputPower() +{ + for (eSmartPtrList::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i) + { + return i->m_frontend->readInputpower() >= 0; + } + return false; +} + class eDVBChannelFilePush: public eFilePushThread { public: + eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); } void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; } + + /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */ + /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */ + void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */ protected: int m_iframe_search, m_iframe_state, m_pid; + int m_timebase_change; int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining); }; int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining) { -#if 0 /* not yet */ +#if 0 + if (m_timebase_change) + { + eDebug("timebase change: %d", m_timebase_change); + int offset; + for (offset = 0; offset < len; offset += 188) + { + unsigned char *pkt = (unsigned char*)_data + offset; + if (pkt[1] & 0x40) /* pusi */ + { + if (pkt[3] & 0x20) // adaption field present? + pkt += pkt[4] + 4 + 1; /* skip adaption field and header */ + else + pkt += 4; /* skip header */ + if (pkt[0] || pkt[1] || (pkt[2] != 1)) + { + eWarning("broken startcode"); + continue; + } + + pts_t pts = 0; + + if (pkt[7] & 0x80) // PTS present? + { + pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29; + pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22; + pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14; + pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7; + pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1; + +#if 0 + off_t off = 0; + RESULT r = m_tstools.fixupPTS(off, pts); + if (r) + eWarning("fixup PTS while trickmode playback failed.\n"); +#endif + + int sec = pts / 90000; + int frm = pts % 90000; + int min = sec / 60; + sec %= 60; + int hr = min / 60; + min %= 60; + int d = hr / 24; + hr %= 24; + +// eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm); + + pts += 0x80000000LL; + pts *= m_timebase_change; + pts >>= 16; + + sec = pts / 90000; + frm = pts % 90000; + min = sec / 60; + sec %= 60; + hr = min / 60; + min %= 60; + d = hr / 24; + hr %= 24; + +// eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm); + + pkt[9] &= ~0xE; + pkt[10] = 0; + pkt[11] &= ~1; + pkt[12] = 0; + pkt[13] &= ~1; + + pkt[9] |= (pts >> 29) & 0xE; + pkt[10] |= (pts >> 22) & 0xFF; + pkt[11] |= (pts >> 14) & 0xFE; + pkt[12] |= (pts >> 7) & 0xFF; + pkt[13] |= (pts << 1) & 0xFE; + } + } + } + } +#endif + +#if 1 /* not yet */ if (!m_iframe_search) return len; unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */ - eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]); +// eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]); unsigned char *d = data; while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3))) @@ -779,8 +874,8 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s { int picture_type = (d[5] >> 3) & 7; d += 4; - - eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid); + +// eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid); if (m_iframe_state == 1) { @@ -802,19 +897,19 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s { if (picture_type != 1) /* we are only interested in I frames */ continue; - + unsigned char *fts = data; while (fts < ts) { fts[1] |= 0x1f; fts[2] |= 0xff; /* drop packet */ - + fts += 188; } /* force payload only */ ts[3] &= ~0x30; ts[3] |= 0x10; - + // memset(ts + 4, 0xFF, (offset % 188) - 4); m_iframe_state = 1; @@ -948,18 +1043,17 @@ void eDVBChannel::cueSheetEvent(int event) /* 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"); @@ -968,6 +1062,10 @@ void eDVBChannel::cueSheetEvent(int event) } ASSERT(m_pvr_thread); m_pvr_thread->setIFrameSearch(m_skipmode_n != 0); + if (m_cue->m_skipmode_ratio != 0) + m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */ + else + m_pvr_thread->setTimebaseChange(0); /* normal playback */ eDebug("flush pvr"); flushPVR(m_cue->m_decoding_demux); eDebug("done"); @@ -1477,6 +1575,7 @@ void eCueSheet::clear() void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end) { + assert(begin < end); m_lock.WrLock(); m_spans.push_back(std::pair(begin, end)); m_lock.Unlock();