From fe9c79a96232f5e5dd12158bf948188110412664 Mon Sep 17 00:00:00 2001 From: ghost Date: Thu, 30 Oct 2008 21:21:46 +0100 Subject: Add DiSEqC reset after voltage enable and tune failed... hopefully this fixes problems with some DiSEqC switches --- lib/dvb/frontend.cpp | 7 ++++++- lib/dvb/sec.cpp | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) (limited to 'lib/dvb') diff --git a/lib/dvb/frontend.cpp b/lib/dvb/frontend.cpp index 1bcacc03..635de8f5 100644 --- a/lib/dvb/frontend.cpp +++ b/lib/dvb/frontend.cpp @@ -1492,7 +1492,12 @@ void eDVBFrontend::tuneLoop() // called by m_tuneTimer eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: "); for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i) eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]); - eDebugNoSimulate(""); + if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3)) + eDebugNoSimulate("(DiSEqC reset)"); + else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3)) + eDebugNoSimulate("(DiSEqC peripherial power on)"); + else + eDebugNoSimulate(""); ++m_sec_sequence.current(); break; case eSecCommand::SEND_TONEBURST: diff --git a/lib/dvb/sec.cpp b/lib/dvb/sec.cpp index ca9e4ec8..35a8d04a 100644 --- a/lib/dvb/sec.cpp +++ b/lib/dvb/sec.cpp @@ -372,6 +372,7 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA bool doSetVoltageToneFrontend = true; bool sendDiSEqC = false; bool forceChanged = false; + bool needDiSEqCReset = false; long band=0, voltage = iDVBFrontend::voltageOff, tone = iDVBFrontend::toneOff, @@ -418,6 +419,9 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA sec_fe->getData(eDVBFrontend::ROTOR_CMD, lastRotorCmd); sec_fe->getData(eDVBFrontend::ROTOR_POS, curRotorPos); + if (lastcsw == lastucsw && lastToneburst == lastucsw && lastucsw == -1) + needDiSEqCReset = true; + if ( sat.frequency > lnb_param.m_lof_threshold ) band |= 1; @@ -623,6 +627,23 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS]) ); sec_sequence.push_back( eSecCommand(eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS) ); + if (needDiSEqCReset) + { + eDVBDiseqcCommand diseqc; + memset(diseqc.data, 0, MAX_DISEQC_LENGTH); + diseqc.len = 3; + diseqc.data[0] = 0xE0; + diseqc.data[1] = 0; + diseqc.data[2] = 0; + // diseqc reset + sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) ); + sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) ); + diseqc.data[2] = 3; + // diseqc peripherial powersupply on + sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) ); + sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 150) ); + } + for (int seq_repeat = 0; seq_repeat < (di_param.m_seq_repeat?2:1); ++seq_repeat) { if ( send_mask & 4 ) -- cgit v1.2.3 From 6c6704a6c897cef2aca87bd8d5a732ae1a2bac4a Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Fri, 31 Oct 2008 02:03:15 +0100 Subject: Patch by Anders Holst: * Undo "sparse-AP-fix" At March 25 a patch was checked in that makes sure that AP:s closer than half a second from each other are filtered away. I don't know the exact purpose of this fix, but I don't think it is a good idea: Besides being the cause of bugs 4 and 5 above, all seek operations are based on the AP:s, and it is a pity to cripple the precision here. And for example, when cutting movies it is important to be able to reach the right GOP boundary. (And the next fix relies on all boundaries being available.) (If you wonder, bug 5 was caused by a destructive interaction of this with the discontinuity handling.) * Hit GOP:s somewhat before GOP start It turns out that if you jump exactly to the GOP start, then that GOP is nevertheless skipped and playback starts from the GOP thereafter. However, if you jump to (at least) one frame before the GOP start, playback starts from that GOP. I don't know if this is a bug in the driver or elsewhere, but the best I can do is this workaround: Hit the GOP by jumping to half a GOP length before the GOP start. (By scanning the ts file it is of course possible to find the exact frame boundaries, but why bother since anywhere between the previous GOP start and the previous frame start will do.) Similarly, to show the first frame of a GOP, a few more frames must be included. Therefore, add half a GOP at the end of each source span. * Jump over discontinuities during AP relative seek The above two fixes together *almost* take care of bugs 1 and 2 above. Now seekRelative(1) moves one forward and seekRelative(-1) one backwards. However, at discontinuities they may get stuck. This is remedied by an extra if statement to check for discontinuities when stepping throught the AP:s in AP relative seek. * Stop after last source span In the function eDVBChannel::getNextSourceSpan there was no code to take care of the case when the seeked-to point is after the last source span. Currently it just goes on until the movie ends. I have added code for this, which takes care of bug 3, and as a fortunate bonus effect bug 6 too. (But please check my code here, I hope I can use current_offset the way I do, and return 0 size when it should stop.) --- lib/dvb/dvb.cpp | 32 +++++++++++++++++++++----------- lib/dvb/pvrparse.cpp | 48 +++++++++++++++++++++++++++++++++--------------- lib/dvb/pvrparse.h | 2 +- lib/dvb/tstools.cpp | 7 +++++-- lib/dvb/tstools.h | 2 +- 5 files changed, 61 insertions(+), 30 deletions(-) (limited to 'lib/dvb') diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index 68d9a0dd..6edf9e87 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -1195,7 +1195,7 @@ void eDVBChannel::cueSheetEvent(int event) { off_t offset_in, offset_out; pts_t pts_in = i->first, pts_out = i->second; - if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out)) + if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1)) { eDebug("span translation failed.\n"); continue; @@ -1323,13 +1323,13 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off eDebug("AP relative seeking failed!"); } else { - eDebug("next ap is %llx\n", pts); pts = nextap; + eDebug("next ap is %llx\n", pts); } } off_t offset = 0; - if (m_tstools.getOffset(offset, pts)) + if (m_tstools.getOffset(offset, pts, -1)) { eDebug("get offset for pts=%lld failed!", pts); continue; @@ -1403,16 +1403,26 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off } } - if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0)) - { - eDebug("reached SOF"); - m_skipmode_m = 0; - m_pvr_thread->sendEvent(eFilePushThread::evtUser); + if (m_source_span.empty()) { + if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0)) + { + eDebug("reached SOF"); + m_skipmode_m = 0; + m_pvr_thread->sendEvent(eFilePushThread::evtUser); + } + start = current_offset; + size = max; + } else { + off_t tmp = align(m_source_span.rbegin()->second, blocksize); + if (current_offset == tmp) { + start = current_offset; + size = 0; + } else { + start = tmp - align(512*1024, blocksize); + size = align(512*1024, blocksize); + } } - start = current_offset; - size = max; - eDebug("END OF CUESHEET. (%08llx, %d)", start, size); return; } diff --git a/lib/dvb/pvrparse.cpp b/lib/dvb/pvrparse.cpp index 1b827d3c..35ba9091 100644 --- a/lib/dvb/pvrparse.cpp +++ b/lib/dvb/pvrparse.cpp @@ -36,8 +36,6 @@ int eMPEGStreamInformation::load(const char *filename) return -1; m_access_points.clear(); m_pts_to_offset.clear(); - pts_t last = -(1LL<<62); - int loaded = 0, skipped = 0; while (1) { unsigned long long d[2]; @@ -48,16 +46,9 @@ int eMPEGStreamInformation::load(const char *filename) d[0] = bswap_64(d[0]); d[1] = bswap_64(d[1]); #endif - if ((d[1] - last) > 90000/2) - { - m_access_points[d[0]] = d[1]; - m_pts_to_offset.insert(std::pair(d[1], d[0])); - last = d[1]; - loaded++; - } else - skipped++; + m_access_points[d[0]] = d[1]; + m_pts_to_offset.insert(std::pair(d[1], d[0])); } - eDebug("loaded %d, skipped %d", loaded, skipped); fclose(f); fixupDiscontinuties(); return 0; @@ -216,30 +207,45 @@ pts_t eMPEGStreamInformation::getInterpolated(off_t offset) return before_ts + diff; } -off_t eMPEGStreamInformation::getAccessPoint(pts_t ts) +off_t eMPEGStreamInformation::getAccessPoint(pts_t ts, int marg) { /* FIXME: more efficient implementation */ off_t last = 0; + off_t last2 = 0; + pts_t lastc = 0; for (std::map::const_iterator i(m_access_points.begin()); i != m_access_points.end(); ++i) { pts_t delta = getDelta(i->first); pts_t c = i->second - delta; - if (c > ts) - break; + if (c > ts) { + if (marg > 0) + return (last + i->first)/376*188; + else if (marg < 0) + return (last + last2)/376*188; + else + return last; + } + lastc = c; + last2 = last; last = i->first; } - return last; + if (marg < 0) + return (last + last2)/376*188; + else + return last; } int eMPEGStreamInformation::getNextAccessPoint(pts_t &ts, const pts_t &start, int direction) { off_t offset = getAccessPoint(start); + pts_t c1, c2; std::map::const_iterator i = m_access_points.find(offset); if (i == m_access_points.end()) { eDebug("getNextAccessPoint: initial AP not found"); return -1; } + c1 = i->second - getDelta(i->first); while (direction) { if (direction > 0) @@ -247,6 +253,12 @@ int eMPEGStreamInformation::getNextAccessPoint(pts_t &ts, const pts_t &start, in if (i == m_access_points.end()) return -1; ++i; + c2 = i->second - getDelta(i->first); + if (c1 == c2) { // Discontinuity + ++i; + c2 = i->second - getDelta(i->first); + } + c1 = c2; direction--; } if (direction < 0) @@ -257,6 +269,12 @@ int eMPEGStreamInformation::getNextAccessPoint(pts_t &ts, const pts_t &start, in return -1; } --i; + c2 = i->second - getDelta(i->first); + if (c1 == c2) { // Discontinuity + --i; + c2 = i->second - getDelta(i->first); + } + c1 = c2; direction++; } } diff --git a/lib/dvb/pvrparse.h b/lib/dvb/pvrparse.h index 69bb9924..b2ddd23d 100644 --- a/lib/dvb/pvrparse.h +++ b/lib/dvb/pvrparse.h @@ -41,7 +41,7 @@ public: /* inter/extrapolate timestamp from offset */ pts_t getInterpolated(off_t offset); - off_t getAccessPoint(pts_t ts); + off_t getAccessPoint(pts_t ts, int marg=0); int getNextAccessPoint(pts_t &ts, const pts_t &start, int direction); diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp index 5157ef22..bd7ebce2 100644 --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@ -209,11 +209,14 @@ int eDVBTSTools::fixupPTS(const off_t &offset, pts_t &now) } } -int eDVBTSTools::getOffset(off_t &offset, pts_t &pts) +int eDVBTSTools::getOffset(off_t &offset, pts_t &pts, int marg) { if (m_use_streaminfo) { - offset = m_streaminfo.getAccessPoint(pts); + if (pts >= m_pts_end && marg > 0 && m_end_valid) + offset = m_offset_end; + else + offset = m_streaminfo.getAccessPoint(pts, marg); return 0; } else { diff --git a/lib/dvb/tstools.h b/lib/dvb/tstools.h index 13168253..4bc04729 100644 --- a/lib/dvb/tstools.h +++ b/lib/dvb/tstools.h @@ -40,7 +40,7 @@ public: int fixupPTS(const off_t &offset, pts_t &pts); /* get (approximate) offset corresponding to PTS */ - int getOffset(off_t &offset, pts_t &pts); + int getOffset(off_t &offset, pts_t &pts, int marg=0); int getNextAccessPoint(pts_t &ts, const pts_t &start, int direction); -- cgit v1.2.3 From bac628cdd294815c4c09f8f6634357d4f2baadf9 Mon Sep 17 00:00:00 2001 From: ghost Date: Sun, 2 Nov 2008 10:40:46 +0100 Subject: small fix --- lib/dvb/dvbtime.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/dvb') diff --git a/lib/dvb/dvbtime.cpp b/lib/dvb/dvbtime.cpp index 83ca3355..c4335795 100644 --- a/lib/dvb/dvbtime.cpp +++ b/lib/dvb/dvbtime.cpp @@ -394,7 +394,9 @@ void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan, int up m_knownChannels.find(chan); if ( it != m_knownChannels.end() ) { - it->second.tdt = new TDT(chan, it->second.tdt->getUpdateCount()); + int updateCount = it->second.tdt->getUpdateCount(); + it->second.tdt = 0; + it->second.tdt = new TDT(chan, updateCount); it->second.tdt->startTimer(60*60*1000); // restart TDT for this transponder in 60min } } -- cgit v1.2.3 From 09fd651afb1107d45f5d400fad6bb4bb9b825439 Mon Sep 17 00:00:00 2001 From: ghost Date: Sun, 2 Nov 2008 10:42:12 +0100 Subject: check sid and tsid before start automatic service update (STD update) --- lib/dvb/pmt.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'lib/dvb') diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index 6082bf4a..13734e0d 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -135,7 +135,19 @@ void eDVBServicePMTHandler::PATready(int) if (pmtpid == -1) serviceEvent(eventNoPATEntry); else + { // here we know a pat entry for this service id exist m_PMT.begin(eApp, eDVBPMTSpec(pmtpid, m_reference.getServiceID().get()), m_demux); + if (m_reference.path.empty()) + { // also check the tsid now before start sdt update + eDVBChannelID chid; + m_reference.getChannelID(chid); + if (eTransportStreamID((*i)->getTableIdExtension()) == chid.transport_stream_id) + { + m_dvb_scan = new eDVBScan(m_channel, true, false); + m_dvb_scan->connectEvent(slot(*this, &eDVBServicePMTHandler::SDTScanEvent), m_scan_event_connection); + } + } + } } else serviceEvent(eventNoPAT); } @@ -604,10 +616,7 @@ int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, m_channelEvent_connection); if (ref.path.empty()) - { - m_dvb_scan = new eDVBScan(m_channel, true, false); - m_dvb_scan->connectEvent(slot(*this, &eDVBServicePMTHandler::SDTScanEvent), m_scan_event_connection); - } + m_dvb_scan = 0; } else { if (res == eDVBResourceManager::errAllSourcesBusy) -- cgit v1.2.3 From 1a1aa77247ad62a590f7c91d4e5b9c7b45c9dd25 Mon Sep 17 00:00:00 2001 From: ghost Date: Sun, 2 Nov 2008 12:52:14 +0100 Subject: Revert "check sid and tsid before start automatic service update (STD update)" This reverts commit 21812866841eec7ab7a79ee61067581f8202df55. --- lib/dvb/pmt.cpp | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'lib/dvb') diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index 13734e0d..6082bf4a 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -135,19 +135,7 @@ void eDVBServicePMTHandler::PATready(int) if (pmtpid == -1) serviceEvent(eventNoPATEntry); else - { // here we know a pat entry for this service id exist m_PMT.begin(eApp, eDVBPMTSpec(pmtpid, m_reference.getServiceID().get()), m_demux); - if (m_reference.path.empty()) - { // also check the tsid now before start sdt update - eDVBChannelID chid; - m_reference.getChannelID(chid); - if (eTransportStreamID((*i)->getTableIdExtension()) == chid.transport_stream_id) - { - m_dvb_scan = new eDVBScan(m_channel, true, false); - m_dvb_scan->connectEvent(slot(*this, &eDVBServicePMTHandler::SDTScanEvent), m_scan_event_connection); - } - } - } } else serviceEvent(eventNoPAT); } @@ -616,7 +604,10 @@ int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, m_channelEvent_connection); if (ref.path.empty()) - m_dvb_scan = 0; + { + m_dvb_scan = new eDVBScan(m_channel, true, false); + m_dvb_scan->connectEvent(slot(*this, &eDVBServicePMTHandler::SDTScanEvent), m_scan_event_connection); + } } else { if (res == eDVBResourceManager::errAllSourcesBusy) -- cgit v1.2.3 From f3078c3363b29cdb8ccf05cbb251392966137977 Mon Sep 17 00:00:00 2001 From: ghost Date: Mon, 3 Nov 2008 21:05:52 +0100 Subject: dont do SDT update when tuned to wrong transponder --- lib/dvb/pmt.cpp | 12 ++++++++++-- lib/dvb/scan.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'lib/dvb') diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index 6082bf4a..692428d7 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -524,8 +524,15 @@ void eDVBServicePMTHandler::SDTScanEvent(int event) eDebug("no channel list"); else { - m_dvb_scan->insertInto(db, true); - eDebug("sdt update done!"); + eDVBChannelID chid; + m_reference.getChannelID(chid); + if (chid == m_dvb_scan->getCurrentChannelID()) + { + m_dvb_scan->insertInto(db, true); + eDebug("sdt update done!"); + } + else + eDebug("ignore sdt update data.... incorrect transponder tuned!!!"); } break; } @@ -605,6 +612,7 @@ int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, if (ref.path.empty()) { + m_dvb_scan = 0; m_dvb_scan = new eDVBScan(m_channel, true, false); m_dvb_scan->connectEvent(slot(*this, &eDVBServicePMTHandler::SDTScanEvent), m_scan_event_connection); } diff --git a/lib/dvb/scan.h b/lib/dvb/scan.h index 95e3fb39..38ac784f 100644 --- a/lib/dvb/scan.h +++ b/lib/dvb/scan.h @@ -110,6 +110,7 @@ public: void getLastServiceName(std::string &name); RESULT getFrontend(ePtr &); RESULT getCurrentTransponder(ePtr &); + eDVBChannelID getCurrentChannelID() { return m_chid_current; } }; #endif -- cgit v1.2.3 From 58ee3c3a218a0aa5d45e9c465eb9759375b4129c Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Mon, 17 Nov 2008 00:08:58 +0100 Subject: By Anders Holst: * I have checked the effect on DM800 of the margin before GOP:s, introduced by the "timing bugs" patch and needed for DM7025. As was previously noted, the margins are not needed on DM800. Fortunately it turns out also not to have any significant adverse effects: When jumping back or forward I expected some flickering, but there are none at all! There is only one small effect as far as I have found: When a cut list is used, there are somewhat more flickering at the cut points than without the margins. Since there are flickering also without the margins, this may be considered a less serious effect. If you consider this effect serious enough though, or think that it is cleaner to separate the code for DM7025 and DM800 since the margin is needed for one but not the other, then I can try to produce such a patch. Otherwise I suggest to wait with this. * In the original timing bugs patch there were a fix to stop playback after the last OUT cut. It did this by setting the size of the next source span to 0. But this turned out not to be a good idea: It seems that playback stops immediately when the next size is set to zero, and not when the buffer is used up. Therefore playback may stop some seconds before the actual end. If instead a jump is made to the last position in the file and a non-zero size is used there, then for some reason it plays up the whole buffer. Don't ask me why it is like this. A modification to this effect is anyway included below. * Rewind did not work at all for HD movies on DM800. The picture just freezes. It is because HD movies have another sequence at beginning of frames than normal movies. There is a rather simple fix, looking for both HD and normal sequences, in the trickmode playback code. (If the HD movie sequence condition seems complicated, it is because it has to make sure not to be accidentally triggered by normal movies.) --- lib/dvb/dvb.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'lib/dvb') diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index 6edf9e87..7b05feb4 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -985,9 +985,9 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s unsigned char *ts = data + ts_offset; int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF; - if ((d[3] == 0) && (m_pid == pid)) /* picture start */ + if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid)) /* picture start */ { - int picture_type = (d[5] >> 3) & 7; + int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1); d += 4; // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid); @@ -1413,10 +1413,13 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off start = current_offset; size = max; } else { - off_t tmp = align(m_source_span.rbegin()->second, blocksize); - if (current_offset == tmp) { - start = current_offset; - size = 0; + off_t tmp2, tmp = align(m_source_span.rbegin()->second, blocksize); + pts_t len; + getLength(len); + m_tstools.getOffset(tmp2, len, 1); + if (current_offset == tmp || current_offset == tmp2) { + start = tmp2; + size = max; } else { start = tmp - align(512*1024, blocksize); size = align(512*1024, blocksize); -- cgit v1.2.3 From 638123eeac3874577ca1454c3420b15dd4ccdbc0 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Mon, 17 Nov 2008 00:10:33 +0100 Subject: By Anders Holst: only record MPEG-4 I-frames to ap-file --- lib/dvb/pvrparse.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/dvb') diff --git a/lib/dvb/pvrparse.cpp b/lib/dvb/pvrparse.cpp index 35ba9091..dfc62249 100644 --- a/lib/dvb/pvrparse.cpp +++ b/lib/dvb/pvrparse.cpp @@ -370,7 +370,8 @@ int eMPEGStreamParserTS::processPacket(const unsigned char *pkt, off_t offset) eDebug("Sequence header but no valid PTS value."); } - if (pkt[3] == 0x09) /* MPEG4 AVC unit access delimiter */ + if (pkt[3] == 0x09 && /* MPEG4 AVC unit access delimiter */ + (pkt[4] >> 5) == 0) /* and I-frame */ { if (ptsvalid) { -- cgit v1.2.3 From 401863ab3c54d849a22cd0fb677dec487621ab97 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Mon, 17 Nov 2008 15:35:42 +0100 Subject: lock on pids only if video startcode is in a pes header --- lib/dvb/dvb.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'lib/dvb') diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index 7b05feb4..8afa70db 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -1031,10 +1031,20 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s } } else if ((d[3] & 0xF0) == 0xE0) /* video stream */ { - if (m_pid != pid) + /* verify that this is actually a PES header, not just some ES data */ + if (ts[1] & 0x40) /* PUSI set */ { - eDebug("now locked to pid %04x", pid); - m_pid = pid; + int payload_start = 4; + if (ts[3] & 0x20) /* adaptation field present */ + payload_start += ts[4] + 1; /* skip AF */ + if (payload_start == (offset%184)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */ + { + if (m_pid != pid) + { + eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]); + m_pid = pid; + } + } } // m_pid = 0x6e; d += 4; -- cgit v1.2.3 From a9efd192b545113282c7c7891a231570f49f27e6 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Mon, 17 Nov 2008 17:19:06 +0100 Subject: fix comment, don't memmem over end of packet --- lib/dvb/dvb.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib/dvb') diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index 3ad086de..07cc611b 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -973,7 +973,7 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s } #endif -#if 1 /* not yet */ +#if 1 /* This codepath is required on Broadcom-based Dreamboxes (DM800, DM8000) and strips away non-I-frames. */ if (!m_iframe_search) return len; @@ -982,7 +982,7 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s // 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))) + while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3))) { int offset = d - data; int ts_offset = offset - offset % 188; /* offset to the start of TS packet */ @@ -1054,7 +1054,6 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s d += 4; } else d += 4; /* ignore */ - } if (m_iframe_state == 1) -- cgit v1.2.3 From 39bd88513deee4a1a00993212c76e503fdd47fe7 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Mon, 17 Nov 2008 22:54:04 +0100 Subject: fix typo --- lib/dvb/dvb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/dvb') diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index 07cc611b..28012e7a 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -1041,7 +1041,7 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s int payload_start = 4; if (ts[3] & 0x20) /* adaptation field present */ payload_start += ts[4] + 1; /* skip AF */ - if (payload_start == (offset%184)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */ + if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */ { if (m_pid != pid) { -- cgit v1.2.3 From 4f7990ff2a55874b9eb65e3c9cd47dacb9f76deb Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Tue, 18 Nov 2008 00:40:19 +0100 Subject: rework decoder states --- lib/dvb/decoder.cpp | 208 ++++++++++++++++------------------ lib/dvb/decoder.h | 42 +++++-- lib/dvb/idvb.h | 33 ++---- lib/python/Screens/InfoBarGenerics.py | 17 ++- lib/service/iservice.h | 2 + lib/service/servicedvb.cpp | 40 ++++--- lib/service/servicedvb.h | 1 + 7 files changed, 177 insertions(+), 166 deletions(-) (limited to 'lib/dvb') diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp index 6ad39225..66b923a6 100644 --- a/lib/dvb/decoder.cpp +++ b/lib/dvb/decoder.cpp @@ -39,7 +39,7 @@ DEFINE_REF(eDVBAudio); eDVBAudio::eDVBAudio(eDVBDemux *demux, int dev) - :m_demux(demux), m_dev(dev), m_is_freezed(0) + :m_demux(demux), m_dev(dev) { char filename[128]; #if HAVE_DVB_API_VERSION < 3 @@ -194,7 +194,7 @@ int eDVBAudio::startPid(int pid, int type) */ } - eDebugNoNewLine("AUDIO_SET_BYPASS - "); + eDebugNoNewLine("AUDIO_SET_BYPASS(%d) - ", bypass); if (::ioctl(m_fd, AUDIO_SET_BYPASS_MODE, bypass) < 0) eDebug("failed (%m)"); else @@ -240,28 +240,20 @@ void eDVBAudio::flush() void eDVBAudio::freeze() { - if (!m_is_freezed) - { - eDebugNoNewLine("AUDIO_PAUSE - "); - if (::ioctl(m_fd, AUDIO_PAUSE) < 0) - eDebug("failed (%m)"); - else - eDebug("ok"); - m_is_freezed=1; - } + eDebugNoNewLine("AUDIO_PAUSE - "); + if (::ioctl(m_fd, AUDIO_PAUSE) < 0) + eDebug("failed (%m)"); + else + eDebug("ok"); } void eDVBAudio::unfreeze() { - if (m_is_freezed) - { - eDebugNoNewLine("AUDIO_CONTINUE - "); - if (::ioctl(m_fd, AUDIO_CONTINUE) < 0) - eDebug("failed (%m)"); - else - eDebug("ok"); - m_is_freezed=0; - } + eDebugNoNewLine("AUDIO_CONTINUE - "); + if (::ioctl(m_fd, AUDIO_CONTINUE) < 0) + eDebug("failed (%m)"); + else + eDebug("ok"); } void eDVBAudio::setChannel(int channel) @@ -299,7 +291,7 @@ eDVBAudio::~eDVBAudio() DEFINE_REF(eDVBVideo); eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev) - :m_demux(demux), m_dev(dev), m_is_slow_motion(0), m_is_fast_forward(0), m_is_freezed(0) + :m_demux(demux), m_dev(dev) { char filename[128]; #if HAVE_DVB_API_VERSION < 3 @@ -461,34 +453,25 @@ void eDVBVideo::flush() void eDVBVideo::freeze() { - if (!m_is_freezed) - { - eDebugNoNewLine("VIDEO_FREEZE - "); - if (::ioctl(m_fd, VIDEO_FREEZE) < 0) - eDebug("failed (%m)"); - else - eDebug("ok"); - m_is_freezed=1; - } + eDebugNoNewLine("VIDEO_FREEZE - "); + if (::ioctl(m_fd, VIDEO_FREEZE) < 0) + eDebug("failed (%m)"); + else + eDebug("ok"); } void eDVBVideo::unfreeze() { - if (m_is_freezed) - { - eDebugNoNewLine("VIDEO_CONTINUE - "); - if (::ioctl(m_fd, VIDEO_CONTINUE) < 0) - eDebug("failed (%m)"); - else - eDebug("ok"); - m_is_freezed=0; - } + eDebugNoNewLine("VIDEO_CONTINUE - "); + if (::ioctl(m_fd, VIDEO_CONTINUE) < 0) + eDebug("failed (%m)"); + else + eDebug("ok"); } int eDVBVideo::setSlowMotion(int repeat) { - eDebugNoNewLine("VIDEO_SLOWMOTION - "); - m_is_slow_motion = repeat; + eDebugNoNewLine("VIDEO_SLOWMOTION(%d) - ", repeat); int ret = ::ioctl(m_fd, VIDEO_SLOWMOTION, repeat); if (ret < 0) eDebug("failed(%m)"); @@ -499,8 +482,7 @@ int eDVBVideo::setSlowMotion(int repeat) int eDVBVideo::setFastForward(int skip) { - eDebugNoNewLine("VIDEO_FAST_FORWARD - "); - m_is_fast_forward = skip; + eDebugNoNewLine("VIDEO_FAST_FORWARD(%d) - ", skip); int ret = ::ioctl(m_fd, VIDEO_FAST_FORWARD, skip); if (ret < 0) eDebug("failed(%m)"); @@ -527,11 +509,6 @@ int eDVBVideo::getPTS(pts_t &now) eDVBVideo::~eDVBVideo() { - if (m_is_slow_motion) - setSlowMotion(0); - if (m_is_fast_forward) - setFastForward(0); - unfreeze(); if (m_fd >= 0) ::close(m_fd); if (m_fd_demux >= 0) @@ -750,14 +727,14 @@ int eTSMPEGDecoder::setState() { int res = 0; - int noaudio = m_is_sm || m_is_ff || m_is_trickmode; + int noaudio = (m_state != statePlay) && (m_state != statePause); int nott = noaudio; /* actually same conditions */ if ((noaudio && m_audio) || (!m_audio && !noaudio)) - m_changed |= changeAudio; + m_changed |= changeAudio | changeState; if ((nott && m_text) || (!m_text && !nott)) - m_changed |= changeText; + m_changed |= changeText | changeState; bool changed = !!m_changed; #if HAVE_DVB_API_VERSION < 3 @@ -900,6 +877,39 @@ int eTSMPEGDecoder::setState() m_changed &= ~changeText; } #endif + + if (m_changed & changeState) + { + /* play, slowmotion, fast-forward */ + int state_table[6][4] = + { + /* [stateStop] = */ {0, 0, 0}, + /* [statePause] = */ {0, 0, 0}, + /* [statePlay] = */ {1, 0, 0}, + /* [stateDecoderFastForward] = */ {1, 0, m_ff_sm_ratio}, + /* [stateHighspeedFastForward] = */ {1, 0, 1}, + /* [stateSlowMotion] = */ {1, m_ff_sm_ratio, 0} + }; + int *s = state_table[m_state]; + if (m_video) + { + m_video->setSlowMotion(s[1]); + m_video->setFastForward(s[2]); + if (s[0]) + m_video->unfreeze(); + else + m_video->freeze(); + } + if (m_audio) + { + if (s[0]) + m_audio->unfreeze(); + else + m_audio->freeze(); + } + m_changed &= ~changeState; + } + if (changed && !m_video && m_audio && m_radio_pic.length()) showSinglePic(m_radio_pic.c_str()); @@ -946,7 +956,7 @@ eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder) { demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event_conn); CONNECT(m_showSinglePicTimer->timeout, eTSMPEGDecoder::finishShowSinglePic); - m_is_ff = m_is_sm = m_is_trickmode = 0; + m_state = stateStop; } eTSMPEGDecoder::~eTSMPEGDecoder() @@ -1028,82 +1038,61 @@ RESULT eTSMPEGDecoder::setSyncMaster(int who) return -1; } -RESULT eTSMPEGDecoder::start() -{ - RESULT r; - r = setState(); - if (r) - return r; - return unfreeze(); -} - - /* preroll is start in freezed mode. */ -RESULT eTSMPEGDecoder::preroll() +RESULT eTSMPEGDecoder::set() { return setState(); } -RESULT eTSMPEGDecoder::freeze(int cont) -{ - if (m_video) - m_video->freeze(); - - if (m_audio) - m_audio->freeze(); - - return 0; -} - -RESULT eTSMPEGDecoder::unfreeze() -{ - if (m_video) - m_video->unfreeze(); - - if (m_audio) - m_audio->unfreeze(); - - return 0; -} - -RESULT eTSMPEGDecoder::setSinglePictureMode(int when) +RESULT eTSMPEGDecoder::play() { - return -1; + if (m_state == statePlay) + return 0; + m_state = statePlay; + m_changed |= changeState; + return setState(); } -RESULT eTSMPEGDecoder::setPictureSkipMode(int what) +RESULT eTSMPEGDecoder::pause() { - return -1; + if (m_state == statePause) + return 0; + m_state = statePause; + m_changed |= changeState; + return setState(); } RESULT eTSMPEGDecoder::setFastForward(int frames_to_skip) { - m_is_ff = frames_to_skip != 0; + if ((m_state == stateDecoderFastForward) && (m_ff_sm_ratio == frames_to_skip)) + return 0; - setState(); - unfreeze(); // audio might be restarted and still in preroll (freezed) state. + m_state = stateDecoderFastForward; + m_ff_sm_ratio = frames_to_skip; + m_changed |= changeState; + return setState(); - if (m_video) - return m_video->setFastForward(frames_to_skip); - else - return -1; +// return m_video->setFastForward(frames_to_skip); } RESULT eTSMPEGDecoder::setSlowMotion(int repeat) { - m_is_sm = repeat != 0; + if ((m_state == stateSlowMotion) && (m_ff_sm_ratio == repeat)) + return 0; - setState(); - unfreeze(); // audio might be restarted and still in preroll (freezed) state. - - if (m_video) - return m_video->setSlowMotion(repeat); - else - return -1; + m_state = stateSlowMotion; + m_ff_sm_ratio = repeat; + m_changed |= changeState; + return setState(); } -RESULT eTSMPEGDecoder::setZoom(int what) +RESULT eTSMPEGDecoder::setTrickmode() { - return -1; + if (m_state == stateTrickmode) + return 0; + + m_state = stateTrickmode; + m_changed |= changeState; + return setState(); } RESULT eTSMPEGDecoder::flush() @@ -1127,13 +1116,6 @@ void eTSMPEGDecoder::demux_event(int event) } } -RESULT eTSMPEGDecoder::setTrickmode(int what) -{ - m_is_trickmode = what; - setState(); - return 0; -} - RESULT eTSMPEGDecoder::getPTS(int what, pts_t &pts) { if (what == 0) /* auto */ diff --git a/lib/dvb/decoder.h b/lib/dvb/decoder.h index 05e07ef9..04501fe6 100644 --- a/lib/dvb/decoder.h +++ b/lib/dvb/decoder.h @@ -119,10 +119,12 @@ private: changeVideo = 1, changeAudio = 2, changePCR = 4, - changeText = 8 + changeText = 8, + changeState = 16, }; int m_changed, m_decoder; - int m_is_ff, m_is_sm, m_is_trickmode; + int m_state; + int m_ff_sm_ratio; int setState(); ePtr m_demux_event_conn; ePtr m_video_event_conn; @@ -148,17 +150,33 @@ public: RESULT setSyncPCR(int pcrpid); RESULT setTextPID(int textpid); RESULT setSyncMaster(int who); - RESULT start(); - RESULT preroll(); - RESULT freeze(int cont); - RESULT unfreeze(); - RESULT setSinglePictureMode(int when); - RESULT setPictureSkipMode(int what); - RESULT setFastForward(int frames_to_skip); - RESULT setSlowMotion(int repeat); - RESULT setZoom(int what); + + /* + The following states exist: + + - stop: data source closed, no playback + - pause: data source active, decoder paused + - play: data source active, decoder consuming + - decoder fast forward: data source linear, decoder drops frames + - trickmode, highspeed reverse: data source fast forwards / reverses, decoder just displays frames as fast as it can + - slow motion: decoder displays frames multiple times + */ + enum { + stateStop, + statePause, + statePlay, + stateDecoderFastForward, + stateTrickmode, + stateSlowMotion + }; + RESULT set(); /* just apply settings, keep state */ + RESULT play(); /* -> play */ + RESULT pause(); /* -> pause */ + RESULT setFastForward(int frames_to_skip); /* -> decoder fast forward */ + RESULT setSlowMotion(int repeat); /* -> slow motion **/ + RESULT setTrickmode(); /* -> highspeed fast forward */ + RESULT flush(); - RESULT setTrickmode(int what); RESULT showSinglePic(const char *filename); RESULT setRadioPic(const std::string &filename); /* what 0=auto, 1=video, 2=audio. */ diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h index cda05894..bd1c7035 100644 --- a/lib/dvb/idvb.h +++ b/lib/dvb/idvb.h @@ -662,37 +662,24 @@ public: /** Set Sync mode to either audio or video master */ virtual RESULT setSyncMaster(int who)=0; - /** Apply settings with starting video */ - virtual RESULT start()=0; - /** Apply settings but don't start yet */ - virtual RESULT preroll()=0; + /** Apply settings but don't change state */ + virtual RESULT set()=0; + /* all those apply settings, then transition to the given state */ - /** Freeze frame. Either continue decoding (without display) or halt. */ - virtual RESULT freeze(int cont)=0; - /** Continue after freeze. */ - virtual RESULT unfreeze()=0; + /** play */ + virtual RESULT play()=0; + /** Freeze frame. */ + virtual RESULT pause()=0; /** fast forward by skipping frames. 0 is disabled, 2 is twice-the-speed, ... */ virtual RESULT setFastForward(int skip=0)=0; - // stop on .. Picture - enum { spm_I, spm_Ref, spm_Any }; - /** Stop on specific decoded picture. For I-Frame display. */ - virtual RESULT setSinglePictureMode(int when)=0; - - enum { pkm_B, pkm_PB }; - /** Fast forward by skipping either B or P/B pictures */ - virtual RESULT setPictureSkipMode(int what)=0; - /** Slow Motion by repeating pictures */ virtual RESULT setSlowMotion(int repeat)=0; - - enum { zoom_Normal, zoom_PanScan, zoom_Letterbox, zoom_Fullscreen }; - /** Set Zoom. mode *must* be fitting. */ - virtual RESULT setZoom(int what)=0; - - virtual RESULT setTrickmode(int what) = 0; + /** Display any complete data as fast as possible */ + virtual RESULT setTrickmode()=0; + virtual RESULT getPTS(int what, pts_t &pts) = 0; virtual RESULT showSinglePic(const char *filename) = 0; diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index cdaa2c1e..409018de 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -779,12 +779,21 @@ class InfoBarSeek: print "not pauseable." state = self.SEEK_STATE_PLAY - oldstate = self.seekstate self.seekstate = state - for i in range(3): - if oldstate[i] != self.seekstate[i]: - (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i]) + if pauseable is not None: + if self.seekstate[0]: + print "resolved to PAUSE" + pauseable.pause() + elif self.seekstate[1]: + print "resolved to FAST FORWARD" + pauseable.setFastForward(self.seekstate[1]) + elif self.seekstate[2]: + print "resolved to SLOW MOTION" + pauseable.setSlowMotion(self.seekstate[2]) + else: + print "resolved to PLAY" + pauseable.unpause() for c in self.onPlayStateChanged: c(self.seekstate) diff --git a/lib/service/iservice.h b/lib/service/iservice.h index 02fc4508..e27752a2 100644 --- a/lib/service/iservice.h +++ b/lib/service/iservice.h @@ -392,6 +392,8 @@ class iPauseableService: public iObject ~iPausableService(); #endif public: + + /* this will set the *state* directly. So just call a SINGLE function of those at a time. */ virtual RESULT pause()=0; virtual RESULT unpause()=0; diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 7e6c0337..af3ab206 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -1281,7 +1281,9 @@ RESULT eDVBServicePlay::pause(ePtr &ptr) RESULT eDVBServicePlay::setSlowMotion(int ratio) { + assert(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */ eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio); + setFastForward_internal(0); if (m_decoder) return m_decoder->setSlowMotion(ratio); else @@ -1291,6 +1293,12 @@ RESULT eDVBServicePlay::setSlowMotion(int ratio) RESULT eDVBServicePlay::setFastForward(int ratio) { eDebug("eDVBServicePlay::setFastForward(%d)", ratio); + assert(ratio); + return setFastForward_internal(ratio); +} + +RESULT eDVBServicePlay::setFastForward_internal(int ratio) +{ int skipmode, ffratio; if (ratio > 8) @@ -1323,7 +1331,12 @@ RESULT eDVBServicePlay::setFastForward(int ratio) if (!m_decoder) return -1; - return m_decoder->setFastForward(ffratio); + if (ffratio == 0) + return 0; + else if (ffratio != 1) + return m_decoder->setFastForward(ffratio); + else + return m_decoder->setTrickmode(); } RESULT eDVBServicePlay::seek(ePtr &ptr) @@ -1352,10 +1365,10 @@ RESULT eDVBServicePlay::getLength(pts_t &len) RESULT eDVBServicePlay::pause() { eDebug("eDVBServicePlay::pause"); - if (!m_is_paused && m_decoder) + setFastForward_internal(0); + if (m_decoder) { - m_is_paused = 1; - return m_decoder->freeze(0); + return m_decoder->pause(); } else return -1; } @@ -1363,10 +1376,10 @@ RESULT eDVBServicePlay::pause() RESULT eDVBServicePlay::unpause() { eDebug("eDVBServicePlay::unpause"); - if (m_is_paused && m_decoder) + setFastForward_internal(0); + if (m_decoder) { - m_is_paused = 0; - return m_decoder->unfreeze(); + return m_decoder->play(); } else return -1; } @@ -1448,9 +1461,8 @@ RESULT eDVBServicePlay::getPlayPosition(pts_t &pos) RESULT eDVBServicePlay::setTrickmode(int trick) { - if (m_decoder) - m_decoder->setTrickmode(trick); - return 0; + /* currently unimplemented */ + return -1; } RESULT eDVBServicePlay::isCurrentlySeekable() @@ -1761,7 +1773,7 @@ RESULT eDVBServicePlay::selectTrack(unsigned int i) { int ret = selectAudioStream(i); - if (m_decoder->start()) + if (m_decoder->play()) return -5; return ret; @@ -2486,12 +2498,12 @@ void eDVBServicePlay::updateDecoder() m_teletext_parser->start(program.textPid); if (!m_is_primary) - m_decoder->setTrickmode(1); + m_decoder->setTrickmode(); if (m_is_paused) - m_decoder->preroll(); + m_decoder->pause(); else - m_decoder->start(); + m_decoder->play(); if (vpid > 0 && vpid < 0x2000) ; diff --git a/lib/service/servicedvb.h b/lib/service/servicedvb.h index d19b92d6..c19e1ed5 100644 --- a/lib/service/servicedvb.h +++ b/lib/service/servicedvb.h @@ -218,6 +218,7 @@ private: int m_current_audio_stream; int selectAudioStream(int n = -1); + RESULT setFastForward_internal(int ratio); /* timeshift */ ePtr m_record; -- cgit v1.2.3 From 979cdde152f5998de6593f1d3b6998bb224d5c97 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Fri, 13 Feb 2009 01:13:59 +0100 Subject: fix merge --- lib/dvb/decoder.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/dvb') diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp index f73dbdd9..6f0ead65 100644 --- a/lib/dvb/decoder.cpp +++ b/lib/dvb/decoder.cpp @@ -295,7 +295,6 @@ eDVBAudio::~eDVBAudio() DEFINE_REF(eDVBVideo); eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev) -<<<<<<< HEAD:lib/dvb/decoder.cpp : m_demux(demux), m_dev(dev), m_width(-1), m_height(-1), m_framerate(-1), m_aspect(-1), m_progressive(-1) { -- cgit v1.2.3 From dce87891f204f8e1f7151c4a3ba00b9dd048e795 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Fri, 13 Feb 2009 03:41:57 +0100 Subject: - While recording, collect startcodes and save them into ".sc"-files - this allows finding iframes for fast forward/reverse more easily - when in fast forward, strictly just output good (=complete iframes) data (this might break dm7025, we will fix this later) - draw smaller, fixed-size bar in position gauge --- lib/dvb/decoder.cpp | 4 +- lib/dvb/demux.cpp | 28 ++- lib/dvb/demux.h | 2 +- lib/dvb/dvb.cpp | 56 +++-- lib/dvb/idemux.h | 2 +- lib/dvb/pvrparse.cpp | 302 ++++++++++++++++++++------ lib/dvb/pvrparse.h | 26 ++- lib/dvb/tstools.cpp | 70 +++++- lib/dvb/tstools.h | 2 + lib/gui/epositiongauge.cpp | 2 +- lib/python/Components/Converter/StringList.py | 6 + lib/python/Components/Renderer/Listbox.py | 4 + lib/service/servicedvb.cpp | 18 +- lib/service/servicedvbrecord.cpp | 10 +- 14 files changed, 416 insertions(+), 116 deletions(-) (limited to 'lib/dvb') diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp index 6f0ead65..a4cffb77 100644 --- a/lib/dvb/decoder.cpp +++ b/lib/dvb/decoder.cpp @@ -1071,7 +1071,9 @@ RESULT eTSMPEGDecoder::setAC3Delay(int delay) } eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder) - :m_demux(demux), m_changed(0), m_decoder(decoder), m_video_clip_fd(-1), m_showSinglePicTimer(eTimer::create(eApp)) + : m_demux(demux), + m_vpid(-1), m_vtype(-1), m_apid(-1), m_atype(-1), m_pcrpid(-1), m_textpid(-1), + m_changed(0), m_decoder(decoder), m_video_clip_fd(-1), m_showSinglePicTimer(eTimer::create(eApp)) { demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event_conn); CONNECT(m_showSinglePicTimer->timeout, eTSMPEGDecoder::finishShowSinglePic); diff --git a/lib/dvb/demux.cpp b/lib/dvb/demux.cpp index 810b10a5..918ecec6 100644 --- a/lib/dvb/demux.cpp +++ b/lib/dvb/demux.cpp @@ -402,9 +402,10 @@ class eDVBRecordFileThread: public eFilePushThread { public: eDVBRecordFileThread(); - void setTimingPID(int pid); + void setTimingPID(int pid, int type); - void saveTimingInformation(const std::string &filename); + void startSaveMetaInformation(const std::string &filename); + void stopSaveMetaInformation(); int getLastPTS(pts_t &pts); protected: int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining); @@ -422,14 +423,19 @@ eDVBRecordFileThread::eDVBRecordFileThread() m_current_offset = 0; } -void eDVBRecordFileThread::setTimingPID(int pid) +void eDVBRecordFileThread::setTimingPID(int pid, int type) { - m_ts_parser.setPid(pid); + m_ts_parser.setPid(pid, type); } -void eDVBRecordFileThread::saveTimingInformation(const std::string &filename) +void eDVBRecordFileThread::startSaveMetaInformation(const std::string &filename) { - m_stream_info.save(filename.c_str()); + m_stream_info.startSave(filename.c_str()); +} + +void eDVBRecordFileThread::stopSaveMetaInformation() +{ + m_stream_info.stopSave(); } int eDVBRecordFileThread::getLastPTS(pts_t &pts) @@ -520,6 +526,9 @@ RESULT eDVBTSRecorder::start() ::ioctl(m_source_fd, DMX_START); #endif + + if (m_target_filename != "") + m_thread->startSaveMetaInformation(m_target_filename); m_thread->start(m_source_fd, m_target_fd); m_running = 1; @@ -553,11 +562,11 @@ RESULT eDVBTSRecorder::removePID(int pid) return 0; } -RESULT eDVBTSRecorder::setTimingPID(int pid) +RESULT eDVBTSRecorder::setTimingPID(int pid, int type) { if (m_running) return -1; - m_thread->setTimingPID(pid); + m_thread->setTimingPID(pid, type); return 0; } @@ -590,8 +599,7 @@ RESULT eDVBTSRecorder::stop() close(m_source_fd); m_source_fd = -1; - if (m_target_filename != "") - m_thread->saveTimingInformation(m_target_filename + ".ap"); + m_thread->stopSaveMetaInformation(); return 0; } diff --git a/lib/dvb/demux.h b/lib/dvb/demux.h index 14501b98..7a697d49 100644 --- a/lib/dvb/demux.h +++ b/lib/dvb/demux.h @@ -94,7 +94,7 @@ public: RESULT addPID(int pid); RESULT removePID(int pid); - RESULT setTimingPID(int pid); + RESULT setTimingPID(int pid, int type); RESULT setTargetFD(int fd); RESULT setTargetFilename(const char *filename); diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index c320fc78..4bbed519 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -974,7 +974,7 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s } #endif -#if 1 /* This codepath is required on Broadcom-based Dreamboxes (DM800, DM8000) and strips away non-I-frames. */ +#if 0 if (!m_iframe_search) return len; @@ -1272,6 +1272,21 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m); current_offset += align(m_skipmode_m, blocksize); + + if (m_skipmode_m) + { + eDebug("we are at %llx, and we try to find the iframe here:", current_offset); + size_t iframe_len; + off_t iframe_start = current_offset; + + if (m_tstools.findIFrame(iframe_start, iframe_len, (m_skipmode_m < 0) ? -1 : +1)) + eDebug("failed"); + else + { + current_offset = align(iframe_start, blocksize); + max = align(iframe_len, blocksize); + } + } while (!m_cue->m_seek_requests.empty()) { @@ -1348,6 +1363,10 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off eDebug("get offset for pts=%lld failed!", pts); continue; } + + size_t iframe_len; + /* try to align to iframe */ + m_tstools.findIFrame(offset, iframe_len, pts < 0 ? -1 : 1); eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset); current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */ @@ -1417,30 +1436,23 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off } } - if (m_source_span.empty()) { - if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0)) - { - eDebug("reached SOF"); - m_skipmode_m = 0; - m_pvr_thread->sendEvent(eFilePushThread::evtUser); - } + if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0)) + { + eDebug("reached SOF"); + m_skipmode_m = 0; + m_pvr_thread->sendEvent(eFilePushThread::evtUser); + } + + if (m_source_span.empty()) + { start = current_offset; size = max; - } else { - off_t tmp2, tmp = align(m_source_span.rbegin()->second, blocksize); - pts_t len; - getLength(len); - m_tstools.getOffset(tmp2, len, 1); - if (current_offset == tmp || current_offset == tmp2) { - start = tmp2; - size = max; - } else { - start = tmp - align(512*1024, blocksize); - size = align(512*1024, blocksize); - } + eDebug("NO CUESHEET. (%08llx, %d)", start, size); + } else + { + start = current_offset; + size = 0; } - - eDebug("END OF CUESHEET. (%08llx, %d)", start, size); return; } diff --git a/lib/dvb/idemux.h b/lib/dvb/idemux.h index 9432afb6..e92b1e75 100644 --- a/lib/dvb/idemux.h +++ b/lib/dvb/idemux.h @@ -30,7 +30,7 @@ public: virtual RESULT addPID(int pid) = 0; virtual RESULT removePID(int pid) = 0; - virtual RESULT setTimingPID(int pid) = 0; + virtual RESULT setTimingPID(int pid, int type) = 0; virtual RESULT setTargetFD(int fd) = 0; /* for saving additional meta data. */ diff --git a/lib/dvb/pvrparse.cpp b/lib/dvb/pvrparse.cpp index 71cbd602..1393bf77 100644 --- a/lib/dvb/pvrparse.cpp +++ b/lib/dvb/pvrparse.cpp @@ -6,9 +6,36 @@ #error no byte order defined! #endif -int eMPEGStreamInformation::save(const char *filename) +eMPEGStreamInformation::eMPEGStreamInformation() + : m_structure_cache_valid(0), m_structure_read(0), m_structure_write(0) { - FILE *f = fopen(filename, "wb"); +} + +eMPEGStreamInformation::~eMPEGStreamInformation() +{ + if (m_structure_read) + fclose(m_structure_read); + if (m_structure_write) + fclose(m_structure_write); +} + +int eMPEGStreamInformation::startSave(const char *filename) +{ + m_filename = filename; + m_structure_write = fopen((m_filename + ".sc").c_str(), "wb"); + return 0; +} + +int eMPEGStreamInformation::stopSave(void) +{ + if (m_structure_write) + { + fclose(m_structure_write); + m_structure_write = 0; + } + if (m_filename == "") + return -1; + FILE *f = fopen((m_filename + ".ap").c_str(), "wb"); if (!f) return -1; @@ -31,7 +58,11 @@ int eMPEGStreamInformation::save(const char *filename) int eMPEGStreamInformation::load(const char *filename) { - FILE *f = fopen(filename, "rb"); + m_filename = filename; + if (m_structure_read) + fclose(m_structure_read); + m_structure_read = fopen((std::string(m_filename) + ".sc").c_str(), "rb"); + FILE *f = fopen((std::string(m_filename) + ".ap").c_str(), "rb"); if (!f) return -1; m_access_points.clear(); @@ -284,6 +315,117 @@ int eMPEGStreamInformation::getNextAccessPoint(pts_t &ts, const pts_t &start, in return 0; } +void eMPEGStreamInformation::writeStructureEntry(off_t offset, structure_data data) +{ + unsigned long long d[2]; +#if BYTE_ORDER == BIG_ENDIAN + d[0] = offset; + d[1] = data; +#else + d[0] = bswap_64(offset); + d[1] = bswap_64(data); +#endif + if (m_structure_write) + fwrite(d, sizeof(d), 1, m_structure_write); +} + +int eMPEGStreamInformation::getStructureEntry(off_t &offset, unsigned long long &data, int get_next) +{ + if (!m_structure_read) + { + eDebug("getStructureEntry failed because of no m_structure_read"); + return -1; + } + + const int struture_cache_entries = sizeof(m_structure_cache) / 16; + if ((!m_structure_cache_valid) || ((off_t)m_structure_cache[0] > offset) || ((off_t)m_structure_cache[(struture_cache_entries - (get_next ? 2 : 1)) * 2] <= offset)) + { + fseek(m_structure_read, 0, SEEK_END); + int l = ftell(m_structure_read); + unsigned long long d[2]; + const int entry_size = sizeof d; + + /* do a binary search */ + int count = l / entry_size; + int i = 0; + + while (count) + { + int step = count >> 1; + + fseek(m_structure_read, (i + step) * entry_size, SEEK_SET); + if (!fread(d, 1, entry_size, m_structure_read)) + { + eDebug("read error at entry %d", i); + return -1; + } + +#if BYTE_ORDER != BIG_ENDIAN + d[0] = bswap_64(d[0]); + d[1] = bswap_64(d[1]); +#endif +// eDebug("%d: %08llx > %llx", i, d[0], d[1]); + + if (d[0] < (unsigned long long)offset) + { + i += step + 1; + count -= step + 1; + } else + count = step; + } + + eDebug("found %d", i); + + /* put that in the middle */ + i -= struture_cache_entries / 2; + if (i < 0) + i = 0; + eDebug("cache starts at %d", i); + fseek(m_structure_read, i * entry_size, SEEK_SET); + int num = fread(m_structure_cache, entry_size, struture_cache_entries, m_structure_read); + eDebug("%d entries", num); + for (i = 0; i < struture_cache_entries; ++i) + { + if (i < num) + { +#if BYTE_ORDER != BIG_ENDIAN + m_structure_cache[i * 2] = bswap_64(m_structure_cache[i * 2]); + m_structure_cache[i * 2 + 1] = bswap_64(m_structure_cache[i * 2 + 1]); +#endif + } else + { + m_structure_cache[i * 2] = 0x7fffffffffffffffULL; /* fill with harmless content */ + m_structure_cache[i * 2 + 1] = 0; + } + } + m_structure_cache_valid = 1; + } + + int i = 0; + while ((off_t)m_structure_cache[i * 2] <= offset) + { + ++i; + if (i == struture_cache_entries) + { + eDebug("structure data consistency fail!, we are looking for %llx, but last entry is %llx", offset, m_structure_cache[i*2-2]); + return -1; + } + } + if (!i) + { + eDebug("structure data (first entry) consistency fail!"); + return -1; + } + + if (!get_next) + --i; + +// eDebug("[%d] looked for %llx, found %llx=%llx", sizeof offset, offset, m_structure_cache[i * 2], m_structure_cache[i * 2 + 1]); + offset = m_structure_cache[i * 2]; + data = m_structure_cache[i * 2 + 1]; + return 0; +} + eMPEGStreamParserTS::eMPEGStreamParserTS(eMPEGStreamInformation &streaminfo): m_streaminfo(streaminfo), m_pktptr(0), m_pid(-1), m_need_next_packet(0), m_skip(0), m_last_pts_valid(0) { } @@ -293,16 +435,15 @@ int eMPEGStreamParserTS::processPacket(const unsigned char *pkt, off_t offset) if (!wantPacket(pkt)) eWarning("something's wrong."); - const unsigned char *end = pkt + 188; + const unsigned char *end = pkt + 188, *begin = pkt; - if (!(pkt[3] & 0x10)) - { - eWarning("[TSPARSE] PUSI set but no payload."); - return 0; - } + int pusi = !!(pkt[1] & 0x40); - if (pkt[3] & 0x20) // adaption field present? - pkt += pkt[4] + 4 + 1; /* skip adaption field and header */ + if (!(pkt[3] & 0x10)) /* no payload? */ + return 0; + + if (pkt[3] & 0x20) // adaptation field present? + pkt += pkt[4] + 4 + 1; /* skip adaptation field and header */ else pkt += 4; /* skip header */ @@ -311,78 +452,96 @@ int eMPEGStreamParserTS::processPacket(const unsigned char *pkt, off_t offset) eWarning("[TSPARSE] dropping huge adaption field"); return 0; } - - // ok, we now have the start of the payload, aligned with the PES packet start. - if (pkt[0] || pkt[1] || (pkt[2] != 1)) - { - eWarning("broken startcode"); - return 0; - } - - + pts_t pts = 0; int ptsvalid = 0; - if (pkt[7] & 0x80) // PTS present? + if (pusi) { - 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; - ptsvalid = 1; - - m_last_pts = pts; - m_last_pts_valid = 1; - -#if 0 - 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; + // ok, we now have the start of the payload, aligned with the PES packet start. + if (pkt[0] || pkt[1] || (pkt[2] != 1)) + { + eWarning("broken startcode"); + return 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; + ptsvalid = 1; + + m_last_pts = pts; + m_last_pts_valid = 1; + + #if 0 + 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("pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm); + #endif + } - eDebug("pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm); -#endif + /* advance to payload */ + pkt += pkt[8] + 9; } - - /* advance to payload */ - pkt += pkt[8] + 9; - /* sometimes, there are zeros before the startcode. */ while (pkt < (end-4)) - if (pkt[0] || pkt[1] || pkt[2]) - break; - else - pkt++; - - /* if startcode found */ -// eDebug("%02x %02x %02x %02x", pkt[0], pkt[1], pkt[2], pkt[3]); - if (!(pkt[0] || pkt[1] || (pkt[2] != 1))) { - if (pkt[3] == 0xb3) /* sequence header */ + int pkt_offset = pkt - begin; + if (!(pkt[0] || pkt[1] || (pkt[2] != 1))) { - if (ptsvalid) +// eDebug("SC %02x %02x %02x %02x, %02x", pkt[0], pkt[1], pkt[2], pkt[3], pkt[4]); + int sc = pkt[3]; + + if (m_streamtype == 0) /* mpeg2 */ { - m_streaminfo.m_access_points[offset] = pts; -// eDebug("Sequence header at %llx, pts %llx", offset, pts); - } else - /*eDebug("Sequence header but no valid PTS value.")*/; - } + if ((sc == 0x00) || (sc == 0xb3) || (sc == 0xb8)) /* picture, sequence, group start code */ + { + unsigned long long data = sc | (pkt[4] << 8) | (pkt[5] << 16) | (pkt[6] << 24); + m_streaminfo.writeStructureEntry(offset + pkt_offset, data & 0xFFFFFFFFULL); + } + if (pkt[3] == 0xb3) /* sequence header */ + { + if (ptsvalid) + { + m_streaminfo.m_access_points[offset] = pts; + // eDebug("Sequence header at %llx, pts %llx", offset, pts); + } else + /*eDebug("Sequence header but no valid PTS value.")*/; + } + } - if (pkt[3] == 0x09 && /* MPEG4 AVC unit access delimiter */ - (pkt[4] >> 5) == 0) /* and I-frame */ - { - if (ptsvalid) + if (m_streamtype == 1) /* H.264 */ { - m_streaminfo.m_access_points[offset] = pts; -// eDebug("MPEG4 AVC UAD at %llx, pts %llx", offset, pts); - } else - /*eDebug("MPEG4 AVC UAD but no valid PTS value.")*/; + if (sc == 0x09) + { + /* store image type */ + unsigned long long data = sc | (pkt[4] << 8); + m_streaminfo.writeStructureEntry(offset + pkt_offset, data); + } + if (pkt[3] == 0x09 && /* MPEG4 AVC NAL unit access delimiter */ + (pkt[4] >> 5) == 0) /* and I-frame */ + { + if (ptsvalid) + { + m_streaminfo.m_access_points[offset] = pts; + // eDebug("MPEG4 AVC UAD at %llx, pts %llx", offset, pts); + } else + /*eDebug("MPEG4 AVC UAD but no valid PTS value.")*/; + } + } } + ++pkt; } return 0; } @@ -405,7 +564,7 @@ inline int eMPEGStreamParserTS::wantPacket(const unsigned char *hdr) const if (hdr[1] & 0x40) /* pusi set: yes. */ return 1; - return 0; + return m_streamtype == 0; /* we need all packets for MPEG2, but only PUSI packets for H.264 */ } void eMPEGStreamParserTS::parseData(off_t offset, const void *data, unsigned int len) @@ -520,10 +679,11 @@ void eMPEGStreamParserTS::parseData(off_t offset, const void *data, unsigned int } } -void eMPEGStreamParserTS::setPid(int _pid) +void eMPEGStreamParserTS::setPid(int _pid, int type) { m_pktptr = 0; m_pid = _pid; + m_streamtype = type; } int eMPEGStreamParserTS::getLastPTS(pts_t &last_pts) diff --git a/lib/dvb/pvrparse.h b/lib/dvb/pvrparse.h index 20d33470..28c0314a 100644 --- a/lib/dvb/pvrparse.h +++ b/lib/dvb/pvrparse.h @@ -12,6 +12,8 @@ class eMPEGStreamInformation { public: + eMPEGStreamInformation(); + ~eMPEGStreamInformation(); /* we order by off_t here, since the timestamp may */ /* wrap around. */ /* we only record sequence start's pts values here. */ @@ -23,7 +25,8 @@ public: /* these are non-fixed up pts value (like m_access_points), just used to accelerate stuff. */ std::multimap m_pts_to_offset; - int save(const char *filename); + int startSave(const char *filename); + int stopSave(void); int load(const char *filename); /* recalculates timestampDeltas */ @@ -46,6 +49,23 @@ public: int getNextAccessPoint(pts_t &ts, const pts_t &start, int direction); bool empty(); + + typedef unsigned long long structure_data; + /* this is usually: + sc | (other_information << 8) + but is really specific to the used video encoder. + */ + void writeStructureEntry(off_t offset, structure_data data); + + /* get a structure entry at given offset (or previous one, if no exact match was found). + optionall, return next element. Offset will be returned. this allows you to easily + get previous and next structure elements. */ + int getStructureEntry(off_t &offset, unsigned long long &data, int get_next); + + std::string m_filename; + int m_structure_cache_valid; + unsigned long long m_structure_cache[1024]; + FILE *m_structure_read, *m_structure_write; }; /* Now we define the parser's state: */ @@ -54,7 +74,7 @@ class eMPEGStreamParserTS public: eMPEGStreamParserTS(eMPEGStreamInformation &streaminfo); void parseData(off_t offset, const void *data, unsigned int len); - void setPid(int pid); + void setPid(int pid, int streamtype); int getLastPTS(pts_t &last_pts); private: eMPEGStreamInformation &m_streaminfo; @@ -62,7 +82,7 @@ private: int m_pktptr; int processPacket(const unsigned char *pkt, off_t offset); inline int wantPacket(const unsigned char *hdr) const; - int m_pid; + int m_pid, m_streamtype; int m_need_next_packet; int m_skip; int m_last_pts_valid; diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp index bd7ebce2..7ac86f08 100644 --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@ -32,7 +32,10 @@ int eDVBTSTools::openFile(const char *filename, int nostreaminfo) closeFile(); if (!nostreaminfo) - m_streaminfo.load((std::string(filename) + ".ap").c_str()); + { + eDebug("loading streaminfo for %s", filename); + m_streaminfo.load(filename); + } if (!m_streaminfo.empty()) m_use_streaminfo = 1; @@ -562,3 +565,68 @@ int eDVBTSTools::findPMT(int &pmt_pid, int &service_id) return -1; } + +int eDVBTSTools::findIFrame(off_t &_offset, size_t &len, int direction) +{ + off_t offset = _offset; +// eDebug("trying to find iFrame at %llx", offset); + + if (!m_use_streaminfo) + { + eDebug("can't get next iframe without streaminfo"); + return -1; + } + + /* let's find the iframe before the given offset */ + unsigned long long data; + while (1) + { + if (m_streaminfo.getStructureEntry(offset, data, (direction == 0) ? 1 : 0)) + { + eDebug("getting structure info for origin offset failed."); + return -1; + } + if (offset == 0x7fffffffffffffffLL) /* eof */ + { + eDebug("reached eof"); + return -1; + } + /* data is usually the start code in the lower 8 bit, and the next byte <<8. we extract the picture type from there */ + /* we know that we aren't recording startcode 0x09 for mpeg2, so this is safe */ + int is_start = (data & 0xE0FF) == 0x0009; /* H.264 NAL unit access delimiter with I-frame*/ + is_start |= (data & 0x3800FF) == 0x080000; /* MPEG2 picture start code with I-frame */ +// eDebug("%08llx@%llx -> %d", data, offset, is_start); + if (is_start) + break; + + if (direction == -1) + --offset; /* move to previous entry */ + else if (direction == +1) + direction = 0; + } + /* let's find the next frame after the given offset */ + off_t start = offset; + + do { + if (m_streaminfo.getStructureEntry(offset, data, 1)) + { + eDebug("get next failed"); + return -1; + } + if (offset == 0x7fffffffffffffffLL) /* eof */ + { + eDebug("reached eof (while looking for end of iframe)"); + return -1; + } +// eDebug("%08llx@%llx", data, offset); + } while (((data & 0xFF) != 9) && ((data & 0xFF) != 0x00)); /* next frame */ + + /* align to TS pkt start */ + start = start - (start % 188); + offset = offset - (offset % 188); + + len = offset - start; + _offset = start; +// eDebug("result: offset=%llx, len: %ld", offset, (int)len); + return 0; +} diff --git a/lib/dvb/tstools.h b/lib/dvb/tstools.h index 4bc04729..a8e0751e 100644 --- a/lib/dvb/tstools.h +++ b/lib/dvb/tstools.h @@ -55,6 +55,8 @@ public: int takeSample(off_t off, pts_t &p); int findPMT(int &pmt_pid, int &service_id); + + int findIFrame(off_t &offset, size_t &len, int direction); private: int m_pid; int m_maxrange; diff --git a/lib/gui/epositiongauge.cpp b/lib/gui/epositiongauge.cpp index b3ee5111..ff98c080 100644 --- a/lib/gui/epositiongauge.cpp +++ b/lib/gui/epositiongauge.cpp @@ -144,7 +144,7 @@ int ePositionGauge::event(int event, void *data, void *data2) { painter.setForegroundColor(gRGB(m_foreground_color)); int xi = scale(in), xo = scale(out); - painter.fill(eRect(xi, 10, xo-xi, s.height()-14)); + painter.fill(eRect(xi, (s.height()-4) / 2, xo-xi, 4)); } in = m_length; diff --git a/lib/python/Components/Converter/StringList.py b/lib/python/Components/Converter/StringList.py index c9488db0..08794b34 100644 --- a/lib/python/Components/Converter/StringList.py +++ b/lib/python/Components/Converter/StringList.py @@ -19,8 +19,11 @@ class StringList(Converter): def selectionChanged(self, index): self.source.selectionChanged(index) # update all non-master targets + print "changed selection in listbox!" for x in self.downstream_elements: + print "downstream element", x if x is not self.master: + print "is not master, so update to index", index x.index = index @cached @@ -43,3 +46,6 @@ class StringList(Converter): self.master.index = index index = property(getIndex, setIndex) + + def entry_changed(self, index): + self.downstream_elements.entry_changed(index) \ No newline at end of file diff --git a/lib/python/Components/Renderer/Listbox.py b/lib/python/Components/Renderer/Listbox.py index 8e510b4c..7a895330 100644 --- a/lib/python/Components/Renderer/Listbox.py +++ b/lib/python/Components/Renderer/Listbox.py @@ -78,3 +78,7 @@ class Listbox(Renderer, object): def changed(self, what): self.content = self.source.content + + def entry_changed(self, index): + if self.instance is not None: + self.instance.entryChanged(index) diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 33cd865e..e3d960d4 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -370,13 +370,17 @@ int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref) struct stat s; stat(ref.path.c_str(), &s); - if (tstools.openFile(ref.path.c_str())) + if (tstools.openFile(ref.path.c_str(), 1)) return 0; /* check if cached data is still valid */ if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length)) return m_parser.m_length / 90000; + /* open again, this time with stream info */ + if (tstools.openFile(ref.path.c_str())) + return 0; + /* otherwise, re-calc length and update meta file */ pts_t len; if (tstools.calcLen(len)) @@ -502,6 +506,7 @@ RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list= 0)) + { + eDebug("timeshift EOF, so let's go live"); switchToLive(); + } break; } } @@ -1173,9 +1181,9 @@ RESULT eDVBServicePlay::setFastForward_internal(int ratio) if (!m_decoder) return -1; - + if (ffratio == 0) - return 0; + return m_decoder->play(); else if (ffratio != 1) return m_decoder->setFastForward(ffratio); else @@ -1211,6 +1219,7 @@ RESULT eDVBServicePlay::pause() setFastForward_internal(0); if (m_decoder) { + m_is_paused = 1; return m_decoder->pause(); } else return -1; @@ -1222,6 +1231,7 @@ RESULT eDVBServicePlay::unpause() setFastForward_internal(0); if (m_decoder) { + m_is_paused = 0; return m_decoder->play(); } else return -1; @@ -2136,6 +2146,8 @@ void eDVBServicePlay::switchToLive() if (!m_timeshift_active) return; + eDebug("SwitchToLive"); + m_cue = 0; m_decoder = 0; m_decode_demux = 0; diff --git a/lib/service/servicedvbrecord.cpp b/lib/service/servicedvbrecord.cpp index c2767e8d..5b7b5d8c 100644 --- a/lib/service/servicedvbrecord.cpp +++ b/lib/service/servicedvbrecord.cpp @@ -270,7 +270,7 @@ int eDVBServiceRecord::doRecord() if (program.pmtPid != -1) pids_to_record.insert(program.pmtPid); // PMT - int timing_pid = -1; + int timing_pid = -1, timing_pid_type = -1; eDebugNoNewLine("RECORD: have %d video stream(s)", program.videoStreams.size()); if (!program.videoStreams.empty()) @@ -283,7 +283,10 @@ int eDVBServiceRecord::doRecord() pids_to_record.insert(i->pid); if (timing_pid == -1) + { timing_pid = i->pid; + timing_pid_type = i->type; + } if (i != program.videoStreams.begin()) eDebugNoNewLine(", "); @@ -302,7 +305,10 @@ int eDVBServiceRecord::doRecord() pids_to_record.insert(i->pid); if (timing_pid == -1) + { timing_pid = i->pid; + timing_pid_type = -1; + } if (i != program.audioStreams.begin()) eDebugNoNewLine(", "); @@ -358,7 +364,7 @@ int eDVBServiceRecord::doRecord() } if (timing_pid != -1) - m_record->setTimingPID(timing_pid); + m_record->setTimingPID(timing_pid, timing_pid_type); m_pids_active = pids_to_record; -- cgit v1.2.3 From 5698c2b573e69c2e62ee8212893f620f0588c208 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Fri, 13 Feb 2009 14:40:56 +0100 Subject: better fix for timeshift --- lib/dvb/pmt.cpp | 5 ++++- lib/service/servicedvb.cpp | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'lib/dvb') diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index 279ec74f..0198c8f7 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -605,12 +605,15 @@ void eDVBServicePMTHandler::SDTScanEvent(int event) } } -int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, eCueSheet *cue, bool simulate) +int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, eCueSheet *cue, bool simulate, eDVBService *service) { RESULT res=0; m_reference = ref; m_use_decode_demux = use_decode_demux; + + /* use given service as backup. This is used for timeshift where we want to clone the live stream using the cache, but in fact have a PVR channel */ + m_service = service; /* is this a normal (non PVR) channel? */ if (ref.path.empty()) diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 4773d097..8a609095 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -2189,7 +2189,7 @@ void eDVBServicePlay::switchToTimeshift() r.path = m_timeshift_file; m_cue = new eCueSheet(); - m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */ + m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */ eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now."); pause(); @@ -2205,7 +2205,7 @@ void eDVBServicePlay::updateDecoder() eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler; eDVBServicePMTHandler::program program; - if (h.getProgramInfo(program) && m_service_handler.getProgramInfo(program)) + if (h.getProgramInfo(program)) eDebug("getting program info failed."); else { -- cgit v1.2.3 From d043db1c05a2d5c66b6faddd6f18d18a5a832515 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Fri, 13 Feb 2009 14:45:13 +0100 Subject: allow service to be overridden for pvr services --- lib/dvb/pmt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/dvb') diff --git a/lib/dvb/pmt.h b/lib/dvb/pmt.h index 3e22174b..cabc6ace 100644 --- a/lib/dvb/pmt.h +++ b/lib/dvb/pmt.h @@ -204,7 +204,7 @@ public: int getChannel(eUsePtr &channel); void resetCachedProgram() { m_have_cached_program = false; } - int tune(eServiceReferenceDVB &ref, int use_decode_demux, eCueSheet *sg=0, bool simulate=false); + int tune(eServiceReferenceDVB &ref, int use_decode_demux, eCueSheet *sg=0, bool simulate=false, eDVBService *service = 0); void free(); private: bool m_have_cached_program; -- cgit v1.2.3 From c178c52d01ede2b9c474fd4a3677acdecf18f0c6 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Fri, 13 Feb 2009 14:45:41 +0100 Subject: show decoder state --- lib/dvb/decoder.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/dvb') diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp index a4cffb77..edefd764 100644 --- a/lib/dvb/decoder.cpp +++ b/lib/dvb/decoder.cpp @@ -855,6 +855,9 @@ int eTSMPEGDecoder::setState() if ((nott && m_text) || (!m_text && !nott)) m_changed |= changeText | changeState; + const char *decoder_states[] = {"stop", "pause", "play", "decoderfastforward", "trickmode", "slowmotion"}; + eDebug("decoder state: %s, vpid=%d, apid=%d", decoder_states[m_state], m_vpid, m_apid); + bool changed = !!m_changed; #if HAVE_DVB_API_VERSION < 3 bool checkAVSync = m_changed & (changeAudio|changeVideo|changePCR); -- cgit v1.2.3 From 166db5a9c9222c82939eede51d964c706039ebe8 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Wed, 18 Feb 2009 03:09:08 +0100 Subject: optional fuzzing support --- lib/dvb/demux.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'lib/dvb') diff --git a/lib/dvb/demux.cpp b/lib/dvb/demux.cpp index 918ecec6..11465186 100644 --- a/lib/dvb/demux.cpp +++ b/lib/dvb/demux.cpp @@ -5,6 +5,13 @@ #include #include +// #define FUZZING 1 + +#if FUZZING + /* change every 1:FUZZING_PROPABILITY byte */ +#define FUZZING_PROPABILITY 100 +#endif + #if HAVE_DVB_API_VERSION < 3 #include @@ -178,6 +185,14 @@ void eDVBSectionReader::data(int) __u8 data[4096]; // max. section size int r; r = ::read(fd, data, 4096); +#if FUZZING + int j; + for (j = 0; j < r; ++j) + { + if (!(rand()%FUZZING_PROPABILITY)) + data[j] ^= rand(); + } +#endif if(r < 0) { eWarning("ERROR reading section - %m\n"); @@ -243,11 +258,13 @@ RESULT eDVBSectionReader::start(const eDVBSectionFilterMask &mask) #else sct.flags = DMX_IMMEDIATE_START; #endif +#if !FUZZING if (mask.flags & eDVBSectionFilterMask::rfCRC) { sct.flags |= DMX_CHECK_CRC; checkcrc = 1; } else +#endif checkcrc = 0; memcpy(sct.filter.filter, mask.data, DMX_FILTER_SIZE); -- cgit v1.2.3