diff options
| author | Felix Domke <tmbinc@elitedvb.net> | 2009-03-31 15:51:31 +0200 |
|---|---|---|
| committer | Felix Domke <tmbinc@elitedvb.net> | 2009-03-31 15:51:31 +0200 |
| commit | bce53d4a67d1655a496eebe5912c8573e880114e (patch) | |
| tree | 9b410fbcaf0f4a22f1cf3489b635e3e94e47a6d8 /lib/dvb | |
| parent | 166db5a9c9222c82939eede51d964c706039ebe8 (diff) | |
| parent | 54475ce18e43482b2ec1a150f7fa07c3464ec6d2 (diff) | |
| download | enigma2-bce53d4a67d1655a496eebe5912c8573e880114e.tar.gz enigma2-bce53d4a67d1655a496eebe5912c8573e880114e.zip | |
Merge commit 'origin/master' into tmbinc/FixTimingBugs
Diffstat (limited to 'lib/dvb')
| -rw-r--r-- | lib/dvb/db.cpp | 13 | ||||
| -rw-r--r-- | lib/dvb/db.h | 4 | ||||
| -rw-r--r-- | lib/dvb/dvb.cpp | 5 | ||||
| -rw-r--r-- | lib/dvb/dvbtime.cpp | 42 | ||||
| -rw-r--r-- | lib/dvb/dvbtime.h | 3 | ||||
| -rw-r--r-- | lib/dvb/frontend.cpp | 2 | ||||
| -rw-r--r-- | lib/dvb/idvb.h | 4 | ||||
| -rw-r--r-- | lib/dvb/scan.cpp | 33 | ||||
| -rw-r--r-- | lib/dvb/scan.h | 4 | ||||
| -rw-r--r-- | lib/dvb/sec.cpp | 12 | ||||
| -rw-r--r-- | lib/dvb/sec.h | 3 | ||||
| -rw-r--r-- | lib/dvb/subtitle.cpp | 5 | ||||
| -rw-r--r-- | lib/dvb/subtitle.h | 1 | ||||
| -rw-r--r-- | lib/dvb/teletext.cpp | 141 | ||||
| -rw-r--r-- | lib/dvb/teletext.h | 4 |
15 files changed, 207 insertions, 69 deletions
diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp index e6108ab5..e4d9ad22 100644 --- a/lib/dvb/db.cpp +++ b/lib/dvb/db.cpp @@ -839,7 +839,7 @@ PyObject *eDVBDB::readSatellites(ePyObject sat_list, ePyObject sat_dict, ePyObje PyDict_SetItem(tp_dict, sat_pos, tplist); for (ElementConstIterator it(sat_elements.begin()); it != sat_elements.end(); ++it) { -// eDebug("\telement: %s", (*it)->name().c_str()); + //eDebug("\telement: %s", (*it)->name().c_str()); const AttributeList &tp_attributes = (*it)->getAttributeList(); AttributeConstIterator end = tp_attributes.end(); modulation = eDVBFrontendParametersSatellite::Modulation_QPSK; @@ -856,8 +856,8 @@ PyObject *eDVBDB::readSatellites(ePyObject sat_list, ePyObject sat_dict, ePyObje for (AttributeConstIterator it(tp_attributes.begin()); it != end; ++it) { - //eDebug("\t\tattr: %s", at->name().c_str()); at = *it; + //eDebug("\t\tattr: %s", at->name().c_str()); name = at->name(); if (name == "modulation") dest = &modulation; else if (name == "system") dest = &system; @@ -872,6 +872,7 @@ PyObject *eDVBDB::readSatellites(ePyObject sat_list, ePyObject sat_dict, ePyObje else if (name == "onid") dest = &onid; if (dest) { + //eDebug("\t\t\tvalue: %s", at->value().c_str()); tmp = strtol(at->value().c_str(), &end_ptr, 10); if (!*end_ptr) *dest = tmp; @@ -1201,15 +1202,17 @@ RESULT eDVBDB::removeServices(eDVBChannelID chid, unsigned int orbpos) if ((unsigned int)sat.orbital_position != orbpos) remove=false; } - if ( remove && chid.dvbnamespace != eNs ) + if ( remove && chid.dvbnamespace != eNs ) // namespace given? { - if (system == iDVBFrontend::feCable && chid.dvbnamespace.get() == (int)0xFFFF0000) + if ( system == iDVBFrontend::feCable && chid.dvbnamespace.get() == (int)0xFFFF0000 ) ; - else if (system == iDVBFrontend::feTerrestrial && chid.dvbnamespace.get() == (int)0xEEEE0000) + else if ( system == iDVBFrontend::feTerrestrial && chid.dvbnamespace.get() == (int)0xEEEE0000 ) ; else if ( chid.dvbnamespace != ch.dvbnamespace ) remove=false; } + else if ( system == iDVBFrontend::feCable || system == iDVBFrontend::feTerrestrial ) + remove=false; if ( remove && chid.original_network_id != eOnid && chid.original_network_id != ch.original_network_id ) remove=false; if ( remove && chid.transport_stream_id != eTsid && chid.transport_stream_id != ch.transport_stream_id ) diff --git a/lib/dvb/db.h b/lib/dvb/db.h index 55e008fb..11fb1ab1 100644 --- a/lib/dvb/db.h +++ b/lib/dvb/db.h @@ -51,11 +51,11 @@ public: RESULT getChannelFrontendData(const eDVBChannelID &id, ePtr<iDVBFrontendParameters> &parm); - RESULT addService(const eServiceReferenceDVB &service, eDVBService *service); + RESULT addService(const eServiceReferenceDVB &referenc, eDVBService *service); RESULT getService(const eServiceReferenceDVB &reference, ePtr<eDVBService> &service); RESULT flush(); - RESULT startQuery(ePtr<iDVBChannelListQuery> &query, eDVBChannelQuery *query, const eServiceReference &source); + RESULT startQuery(ePtr<iDVBChannelListQuery> &query, eDVBChannelQuery *q, const eServiceReference &source); RESULT getBouquet(const eServiceReference &ref, eBouquet* &bouquet); ////// diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index 4bbed519..1c4eef8a 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -1026,11 +1026,6 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s fts += 188; } - /* force payload only */ - ts[3] &= ~0x30; - ts[3] |= 0x10; - -// memset(ts + 4, 0xFF, (offset % 188) - 4); m_iframe_state = 1; } diff --git a/lib/dvb/dvbtime.cpp b/lib/dvb/dvbtime.cpp index d879cfac..a6830dc0 100644 --- a/lib/dvb/dvbtime.cpp +++ b/lib/dvb/dvbtime.cpp @@ -20,7 +20,7 @@ void setRTC(time_t time) FILE *f = fopen("/proc/stb/fp/rtc", "w"); if (f) { - if (fprintf(f, "%u", time)) + if (fprintf(f, "%u", (unsigned int)time)) prev_time = time; else eDebug("write /proc/stb/fp/rtc failed (%m)"); @@ -47,8 +47,11 @@ time_t getRTC() if (f) { // sanity check to detect corrupt atmel firmware - if (fscanf(f, "%u", &rtc_time) != 1) + unsigned int tmp; + if (fscanf(f, "%u", &tmp) != 1) eDebug("read /proc/stb/fp/rtc failed (%m)"); + else + rtc_time=tmp; fclose(f); } else @@ -145,7 +148,7 @@ eDVBLocalTimeHandler *eDVBLocalTimeHandler::instance; DEFINE_REF(eDVBLocalTimeHandler); eDVBLocalTimeHandler::eDVBLocalTimeHandler() - :m_time_ready(false), m_updateNonTunedTimer(eTimer::create(eApp)) + :m_use_dvb_time(false), m_updateNonTunedTimer(eTimer::create(eApp)), m_time_ready(false) { if ( !instance ) instance=this; @@ -214,6 +217,33 @@ void eDVBLocalTimeHandler::writeTimeOffsetData( const char* filename ) } } +void eDVBLocalTimeHandler::setUseDVBTime(bool b) +{ + if (m_use_dvb_time != b) { + if (m_use_dvb_time) { + eDebug("[eDVBLocalTimeHandler] disable sync local time with transponder time!"); + std::map<iDVBChannel*, channel_data>::iterator it = + m_knownChannels.begin(); + for (; it != m_knownChannels.end(); ++it) { + if (it->second.m_prevChannelState == iDVBChannel::state_ok) + it->second.tdt = 0; + } + } + else { + eDebug("[eDVBLocalTimeHandler] enable sync local time with transponder time!"); + std::map<iDVBChannel*, channel_data>::iterator it = + m_knownChannels.begin(); + for (; it != m_knownChannels.end(); ++it) { + if (it->second.m_prevChannelState == iDVBChannel::state_ok) { + it->second.tdt = new TDT(it->second.channel); + it->second.tdt->start(); + } + } + } + m_use_dvb_time = b; + } +} + void eDVBLocalTimeHandler::updateNonTuned() { updateTime(-1, 0, 0); @@ -440,8 +470,10 @@ void eDVBLocalTimeHandler::DVBChannelStateChanged(iDVBChannel *chan) case iDVBChannel::state_ok: eDebug("[eDVBLocalTimerHandler] channel %p running", chan); m_updateNonTunedTimer->stop(); - it->second.tdt = new TDT(it->second.channel); - it->second.tdt->start(); + if (m_use_dvb_time) { + it->second.tdt = new TDT(it->second.channel); + it->second.tdt->start(); + } break; case iDVBChannel::state_release: eDebug("[eDVBLocalTimerHandler] remove channel %p", chan); diff --git a/lib/dvb/dvbtime.h b/lib/dvb/dvbtime.h index 3f8d9b7d..3afff75e 100644 --- a/lib/dvb/dvbtime.h +++ b/lib/dvb/dvbtime.h @@ -54,6 +54,7 @@ class eDVBLocalTimeHandler: public Object ePtr<eConnection> m_stateChangedConn; int m_prevChannelState; }; + bool m_use_dvb_time; ePtr<eTimer> m_updateNonTunedTimer; friend class TDT; std::map<iDVBChannel*, channel_data> m_knownChannels; @@ -78,6 +79,8 @@ public: eDVBLocalTimeHandler(); ~eDVBLocalTimeHandler(); #endif + bool getUseDVBTime() { return m_use_dvb_time; } + void setUseDVBTime(bool b); PSignal0<void> m_timeUpdated; bool ready() const { return m_time_ready; } static eDVBLocalTimeHandler *getInstance() { return instance; } diff --git a/lib/dvb/frontend.cpp b/lib/dvb/frontend.cpp index 5df17931..f2fc12b3 100644 --- a/lib/dvb/frontend.cpp +++ b/lib/dvb/frontend.cpp @@ -858,6 +858,8 @@ int eDVBFrontend::readFrontendData(int type) if (snr != 0) ret = 10 * (int)(-100 * (log10(snr) - log10(255))); } + else if (!strcmp(m_description, "BCM4506")) + ret = (snr * 100) >> 8; if (type == signalQuality) { diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h index cfa98ecf..26ab5e53 100644 --- a/lib/dvb/idvb.h +++ b/lib/dvb/idvb.h @@ -385,13 +385,13 @@ public: virtual RESULT getChannelFrontendData(const eDVBChannelID &id, ePtr<iDVBFrontendParameters> &parm)=0; - virtual RESULT addService(const eServiceReferenceDVB &service, eDVBService *service)=0; + virtual RESULT addService(const eServiceReferenceDVB &reference, eDVBService *service)=0; virtual RESULT getService(const eServiceReferenceDVB &reference, ePtr<eDVBService> &service)=0; virtual RESULT flush()=0; virtual RESULT getBouquet(const eServiceReference &ref, eBouquet* &bouquet)=0; - virtual RESULT startQuery(ePtr<iDVBChannelListQuery> &query, eDVBChannelQuery *query, const eServiceReference &source)=0; + virtual RESULT startQuery(ePtr<iDVBChannelListQuery> &query, eDVBChannelQuery *q, const eServiceReference &source)=0; }; #endif // SWIG diff --git a/lib/dvb/scan.cpp b/lib/dvb/scan.cpp index 76c71011..379ab8e9 100644 --- a/lib/dvb/scan.cpp +++ b/lib/dvb/scan.cpp @@ -740,11 +740,20 @@ void eDVBScan::channelDone() } case iDVBFrontend::feTerrestrial: { + ePtr<iDVBFrontend> fe; eDVBFrontendParametersTerrestrial parm; m_ch_current->getDVBT(parm); snprintf(sname, 255, "%d SID 0x%02x", parm.frequency/1000, m_pmt_in_progress->first); + if (!m_channel->getFrontend(fe)) + { + ePyObject tp_dict = PyDict_New(); + fe->getTransponderData(tp_dict, false); + m_corrected_frequencys[m_chid_current] = + PyInt_AsLong(PyDict_GetItemString(tp_dict, "frequency")); + Py_DECREF(tp_dict); + } break; } case iDVBFrontend::feCable: @@ -765,7 +774,8 @@ void eDVBScan::channelDone() if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) { SCAN_eDebug("add not scrambled!"); - std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service)); + std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = + m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service)); if (i.second) { m_last_service = i.first; @@ -922,6 +932,24 @@ void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags) for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch) { + int system; + ch->second->getSystem(system); + if (system == iDVBFrontend::feTerrestrial) + { + std::map<eDVBChannelID, unsigned int>::iterator it = m_corrected_frequencys.find(ch->first); + if (it != m_corrected_frequencys.end()) + { + eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second); + eDVBFrontendParametersTerrestrial parm; + p->getDVBT(parm); + eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d", + ch->first.transport_stream_id.get(), ch->first.original_network_id.get(), + ch->first.dvbnamespace.get(), it->second, parm.frequency); + parm.frequency = it->second; + p->setDVBT(parm); + m_corrected_frequencys.erase(it); + } + } if (m_flags & scanOnlyFree) { eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second); @@ -1036,7 +1064,8 @@ RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescription } } - std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service)); + std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = + m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service)); if (i.second) { diff --git a/lib/dvb/scan.h b/lib/dvb/scan.h index 38ac784f..9f0dd6ef 100644 --- a/lib/dvb/scan.h +++ b/lib/dvb/scan.h @@ -50,7 +50,9 @@ class eDVBScan: public Object, public iObject /* scan state variables */ int m_channel_state; int m_ready, m_ready_all; - + + std::map<eDVBChannelID, unsigned int> m_corrected_frequencys; // yet just used for DVB-T + std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> > m_new_channels; std::map<eServiceReferenceDVB, ePtr<eDVBService> > m_new_services; std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator m_last_service; diff --git a/lib/dvb/sec.cpp b/lib/dvb/sec.cpp index ac1a2028..d14acc85 100644 --- a/lib/dvb/sec.cpp +++ b/lib/dvb/sec.cpp @@ -563,7 +563,7 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA compare.tone = iDVBFrontend::toneOff; sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) ); sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) ); - sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE]) ); + sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE_DISABLE_BEFORE_DISEQC]) ); if (diseqc13V) vlt = iDVBFrontend::voltage13; @@ -705,7 +705,7 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA compare.tone = iDVBFrontend::toneOff; sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) ); sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) ); - sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE]) ); + sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE_DISABLE_BEFORE_DISEQC]) ); compare.voltage = iDVBFrontend::voltageOff; compare.steps = +4; @@ -839,7 +839,7 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA compare.tone = tone; sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) ); sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, tone) ); - sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE]) ); + sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_FINAL_CONT_TONE_CHANGE]) ); sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) ); cmd.direction=1; // check for running rotor @@ -884,7 +884,7 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA compare.tone = tone; sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) ); sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, tone) ); - sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE]) ); + sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_FINAL_CONT_TONE_CHANGE]) ); } sec_sequence.push_back( eSecCommand(eSecCommand::UPDATE_CURRENT_SWITCHPARMS) ); @@ -897,11 +897,11 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA compare.voltage = iDVBFrontend::voltageOff; sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) ); sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) ); - sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) ); + sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS] ) ); sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) ); sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) ); - sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MOTOR_CMD]) ); // wait 150msec after voltage change + sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS]) ); // wait 20 ms after voltage change eDVBDiseqcCommand diseqc; memset(diseqc.data, 0, MAX_DISEQC_LENGTH); diff --git a/lib/dvb/sec.h b/lib/dvb/sec.h index 5bff6bf7..5d969328 100644 --- a/lib/dvb/sec.h +++ b/lib/dvb/sec.h @@ -271,7 +271,8 @@ class eDVBSatelliteEquipmentControl: public iDVBSatelliteEquipmentControl DECLARE_REF(eDVBSatelliteEquipmentControl); public: enum { - DELAY_AFTER_CONT_TONE=0, // delay after continuous tone change + DELAY_AFTER_CONT_TONE_DISABLE_BEFORE_DISEQC=0, // delay after continuous tone disable before diseqc command + DELAY_AFTER_FINAL_CONT_TONE_CHANGE, // delay after continuous tone change before tune DELAY_AFTER_FINAL_VOLTAGE_CHANGE, // delay after voltage change at end of complete sequence DELAY_BETWEEN_DISEQC_REPEATS, // delay between repeated diseqc commands DELAY_AFTER_LAST_DISEQC_CMD, // delay after last diseqc command diff --git a/lib/dvb/subtitle.cpp b/lib/dvb/subtitle.cpp index f4b5b7e4..642327bb 100644 --- a/lib/dvb/subtitle.cpp +++ b/lib/dvb/subtitle.cpp @@ -345,6 +345,8 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment) } } + page->state = page_state; + //eDebug("page updated: old: %d, new: %d", page->page_version_number, page_version_number); // when acquisition point or mode change: remove all displayed pages. if ((page_state == 1) || (page_state == 2)) @@ -804,7 +806,8 @@ void eDVBSubtitleParser::subtitle_redraw_all() subtitle_page *page = m_pages; while(page) { - subtitle_redraw(page->page_id); + if (page->state != 0) + subtitle_redraw(page->page_id); page = page->next; } #else diff --git a/lib/dvb/subtitle.h b/lib/dvb/subtitle.h index fb9c51a2..09d6cd47 100644 --- a/lib/dvb/subtitle.h +++ b/lib/dvb/subtitle.h @@ -71,6 +71,7 @@ struct subtitle_page int page_id; time_t page_time_out; int page_version_number; + int state; int pcs_size; subtitle_page_region *page_regions; diff --git a/lib/dvb/teletext.cpp b/lib/dvb/teletext.cpp index ca0412e3..de4c6d75 100644 --- a/lib/dvb/teletext.cpp +++ b/lib/dvb/teletext.cpp @@ -127,7 +127,7 @@ unsigned int Latin_G2_set[6*16] = { // This is a very simple en300 706 telext decoder. // It can only decode a single page at a time, thus it's only used -// for subtitles. +// for subtitles. And it ONLY support LATIN Charsets yet! DEFINE_REF(eDVBTeletextParser); @@ -149,6 +149,15 @@ static inline unsigned char decode_hamming_84(unsigned char *b) static inline unsigned long decode_hamming_2418(unsigned char *b) { + static const unsigned char rev[16] = { + 0x00,0x08,0x04,0x0c, + 0x02,0x0a,0x06,0x0e, + 0x01,0x09,0x05,0x0d, + 0x03,0x0b,0x07,0x0f + }; + b[0] = rev[b[0] >> 4] | (rev[b[0] & 0xf] << 4); + b[1] = rev[b[1] >> 4] | (rev[b[1] & 0xf] << 4); + b[2] = rev[b[2] >> 4] | (rev[b[2] & 0xf] << 4); return ((b[0] & 0x04) >> 2) | ((b[0] & 0x70) >> 3) | ((b[1] & 0x7f) << 4) | ((b[2] & 0x7f) << 11); } @@ -258,7 +267,7 @@ void eDVBTeletextParser::processPESPacket(__u8 *pkt, int len) int M = magazine_and_packet_address & 7, Y = magazine_and_packet_address >> 3; // eDebug("line %d, framing code: %02x, M=%02x, Y=%02x", line_offset, framing_code, m_M, m_Y); - + if (Y == 0) /* page header */ { int X = decode_hamming_84(data + 1) * 0x10 + decode_hamming_84(data), @@ -315,19 +324,10 @@ void eDVBTeletextParser::processPESPacket(__u8 *pkt, int len) } else if (Y == 26 && m_page_open && M == m_page_M) { // int designation_code = decode_hamming_84(data); - static const unsigned char rev[16] = { - 0x00,0x08,0x04,0x0c, - 0x02,0x0a,0x06,0x0e, - 0x01,0x09,0x05,0x0d, - 0x03,0x0b,0x07,0x0f - }; int display_row=-1, display_column=-1; for (int a = 1; a < 40; a+=3) { int val; - data[a] = rev[data[a] >> 4] | (rev[data[a] & 0xf] << 4); - data[a+1] = rev[data[a+1] >> 4] | (rev[data[a+1] & 0xf] << 4); - data[a+2] = rev[data[a+2] >> 4] | (rev[data[a+2] & 0xf] << 4); if ((val=decode_hamming_2418(data+a)) >= 0) { unsigned char addr = val & 0x3F; @@ -401,12 +401,63 @@ void eDVBTeletextParser::processPESPacket(__u8 *pkt, int len) } } else if (Y > 29) /*eDebug("non handled packet 30, 31", Y, decode_hamming_84(data))*/; - else if (Y == 29) - eDebug("non handled packet M/%d/%d", Y, decode_hamming_84(data)); - else if (m_page_open) + else if (Y == 29 && M == m_page_M) { - if (M == m_page_M) - eDebug("non handled packet X/%d/%d", Y, decode_hamming_84(data)); + int designation_code = decode_hamming_84(data++); + if (designation_code == 0) // 29/0 + { + m_M29_t1 = decode_hamming_2418(data); + m_M29_t2 = decode_hamming_2418(data+3); + if ((m_M29_t1 & 0xF) == 0) // format1 + m_M29_0_valid = 1; + else + eDebug("non handled packet M/%d/0 format %d", Y, m_M29_t1 & 0xF); + } + else + eDebug("non handled packet M/%d/%d", Y, designation_code); + } + else if (m_page_open && M == m_page_M) + { + int designation_code = decode_hamming_84(data++); + if (Y == 28 && designation_code == 0) // 28/0 + { +#if 1 + m_X28_t1 = decode_hamming_2418(data); + m_X28_t2 = decode_hamming_2418(data+3); + if ((m_X28_t1 & 0xF) == 0) // format1 + m_X28_0_valid = 1; + else + eDebug("non handled packet X/%d/0 format %d", Y, m_X28_t1 & 0xF); +#else + int i=0; + for (; i < 39; i+=3) + { + int tripletX = decode_hamming_2418(data+i); + if (tripletX >= 0) + { + if (i == 0) + { + if ((m_X28_t1 & 0xF) == 0) // format1 + m_X28_0_valid = 1; + m_X28_t1 = tripletX; + } + else if (i == 1) + m_X28_t2 = tripletX; + + char *c = get_bits(tripletX, 18); + int x=0; + for (; x < 18; ++x) + eDebugNoNewLine("%c", c[x]); + eDebug(""); + } + else + eDebug("decode_hamming_2418 failed!\n"); + data += 3; + } +#endif + } + else + eDebug("non handled packet X/%d/%d", Y, designation_code); } } } @@ -430,6 +481,7 @@ void eDVBTeletextParser::handlePageStart() { m_subtitle_page.clear(); m_modifications.clear(); + m_X28_0_valid = 0; // eDebug("erase page!"); } // else @@ -463,28 +515,46 @@ void eDVBTeletextParser::handleLine(unsigned char *data, int len) nat_opts = (m_C & (1<<14) ? 1 : 0) | (m_C & (1<<13) ? 2 : 0) | (m_C & (1<<12) ? 4 : 0), - nat_subset = NationalOptionSubsetsLookup[Gtriplet*8+nat_opts]; -/* eDebug("nat_opts = %d, nat_subset = %d, C121314 = %d%d%d", - nat_opts, nat_subset, - (m_C & (1<<12))?1:0, - (m_C & (1<<13))?1:0, - (m_C & (1<<14))?1:0);*/ + nat_subset_2 = NationalOptionSubsetsLookup[Gtriplet*8+nat_opts], + nat_subset = nat_subset_2, + second_G0_set = 0; + + if (m_X28_0_valid) + { + nat_subset = NationalOptionSubsetsLookup[(m_X28_t1 >> 7) & 0x7F]; + nat_subset_2 = NationalOptionSubsetsLookup[((m_X28_t1 >> 14) & 0xF) | ((m_X28_t2 & 7) << 4)]; +// eDebug("X/28/0 nat_subset %d, nat_subset2 %d", nat_subset, nat_subset_2); + } + else if (m_M29_0_valid) + { + nat_subset = NationalOptionSubsetsLookup[(m_M29_t1 >> 7) & 0x7F]; + nat_subset_2 = NationalOptionSubsetsLookup[((m_M29_t1 >> 14) & 0xF) | ((m_M29_t2 & 7) << 4)]; +// eDebug("M/29/0 nat_subset %d, nat_subset2 %d", nat_subset, nat_subset_2); + } +/* else + eDebug("nat_opts = %d, nat_subset = %d, C121314 = %d%d%d", + nat_opts, nat_subset, + (m_C & (1<<12))?1:0, + (m_C & (1<<13))?1:0, + (m_C & (1<<14))?1:0);*/ // eDebug("handle subtitle line: %d len", len); for (int i=0; i<len; ++i) { + unsigned char b = decode_odd_parity(data + i); std::map<int,unsigned int>::iterator it = m_modifications.find((m_Y<<16)|i); + if (it != m_modifications.end()) { unsigned int utf8_code = it->second; +// eDebugNoNewLine("%c[%d]", b, b); if (utf8_code < 0x10) { int mode = utf8_code; - unsigned char ch = decode_odd_parity(data + i); - if (ch > 96 && ch < 123) - utf8_code = diacr_lower_cmap[(ch-97)*15+mode-1]; - else if (ch > 64 && ch < 91) - utf8_code = diacr_upper_cmap[(ch-65)*15+mode-1]; + if (b > 96 && b < 123) + utf8_code = diacr_lower_cmap[(b-97)*15+mode-1]; + else if (b > 64 && b < 91) + utf8_code = diacr_upper_cmap[(b-65)*15+mode-1]; } if (utf8_code > 0xFFFFFF) out[outidx++]=(utf8_code&0xFF000000)>>24; @@ -498,8 +568,6 @@ void eDVBTeletextParser::handleLine(unsigned char *data, int len) continue; } - unsigned char b = decode_odd_parity(data + i); - if (b < 0x10) /* spacing attribute */ { if (b < 8) /* colors */ @@ -522,17 +590,11 @@ void eDVBTeletextParser::handleLine(unsigned char *data, int len) /* ignore other attributes */ } else if (m_box_open>1) { - //eDebugNoNewLine("%c", b); +// eDebugNoNewLine("%c(%d)", b, b); /* no more than one whitespace, only printable chars */ if (((!last_was_white) || (b != ' ')) && (b >= 0x20)) { - int cur_nat_subset = nat_subset; - - if (b == 0x24) // workaround for currency sign.. the only on non latin1 char in G0 set - { - cur_nat_subset = 9; - b = 36; - } + int cur_nat_subset = second_G0_set ? nat_subset_2 : nat_subset; unsigned char offs = NationalReplaceMap[b]; if (offs) @@ -551,9 +613,11 @@ void eDVBTeletextParser::handleLine(unsigned char *data, int len) out[outidx++] = b; last_was_white = b == ' '; } + else if (b == 0x1b) // ESC ... switch between default G0 and second G0 charset + second_G0_set ^= 1; } } - //eDebug(""); +// eDebug(""); addSubtitleString(color, std::string((const char*)out, outidx)); } @@ -575,6 +639,7 @@ void eDVBTeletextParser::setPageAndMagazine(int page, int magazine) eDebug("enable teletext subtitle page %x%02x", magazine, page); else eDebug("disable teletext subtitles"); + m_M29_0_valid = 0; m_page_M = magazine; /* magazine to look for */ if (magazine != -1) m_page_M &= 7; diff --git a/lib/dvb/teletext.h b/lib/dvb/teletext.h index a07c6aea..880fa569 100644 --- a/lib/dvb/teletext.h +++ b/lib/dvb/teletext.h @@ -50,7 +50,9 @@ private: eDVBTeletextSubtitlePage m_subtitle_page; int m_C, m_Y, m_pid, m_page_M, m_page_X, m_page_open, m_double_height, m_box_open; - + int m_X28_0_valid, m_X28_t1, m_X28_t2; + int m_M29_0_valid, m_M29_t1, m_M29_t2; + void handlePageStart(); void handleLine(unsigned char *line, int len); void handlePageEnd(int have_pts, const pts_t &pts); |
