From 4a1fcf9cf94c9217ce3a133b130dfd923a683ca3 Mon Sep 17 00:00:00 2001 From: Scott Theisen Date: Fri, 8 Nov 2024 19:44:02 -0500 Subject: [PATCH] remove libmythtv/recorders/vbitext NuppelVideoRecorder::FormatTT() was the only user of VBIData::teletextpage, so vbi_event() now has no effects. Since no data is ever extracted, the calls to vbi_add_handler() and thus vbi_open() are now pointless and can be removed. V4LRecorder::m_palVbiCb and m_palVbiTt will then always be nullptr, so they can be removed. After copying the value of the VT_WIDTH constant to its use in cc608reader.cpp, the vbitext directory is now unused and can be removed. --- mythtv/libs/libmythtv/CMakeLists.txt | 9 - .../libs/libmythtv/captions/cc608reader.cpp | 3 +- .../libmythtv/captions/teletextdecoder.cpp | 1 - mythtv/libs/libmythtv/libmythtv.pro | 13 - .../libs/libmythtv/recorders/v4lrecorder.cpp | 70 +- mythtv/libs/libmythtv/recorders/v4lrecorder.h | 12 - .../libs/libmythtv/recorders/vbitext/dllist.h | 62 -- .../libs/libmythtv/recorders/vbitext/lang.cpp | 221 ------ .../libs/libmythtv/recorders/vbitext/lang.h | 23 - .../libs/libmythtv/recorders/vbitext/vbi.cpp | 682 ------------------ mythtv/libs/libmythtv/recorders/vbitext/vbi.h | 62 -- mythtv/libs/libmythtv/recorders/vbitext/vt.h | 65 -- 12 files changed, 4 insertions(+), 1219 deletions(-) delete mode 100644 mythtv/libs/libmythtv/recorders/vbitext/dllist.h delete mode 100644 mythtv/libs/libmythtv/recorders/vbitext/lang.cpp delete mode 100644 mythtv/libs/libmythtv/recorders/vbitext/lang.h delete mode 100644 mythtv/libs/libmythtv/recorders/vbitext/vbi.cpp delete mode 100644 mythtv/libs/libmythtv/recorders/vbitext/vbi.h delete mode 100644 mythtv/libs/libmythtv/recorders/vbitext/vt.h diff --git a/mythtv/libs/libmythtv/CMakeLists.txt b/mythtv/libs/libmythtv/CMakeLists.txt index 8ac32eb3b6b..713a880f2ea 100644 --- a/mythtv/libs/libmythtv/CMakeLists.txt +++ b/mythtv/libs/libmythtv/CMakeLists.txt @@ -241,15 +241,6 @@ if(WIN32) if(HAVE_DXVA2) target_compile_definitions(mythtv PRIVATE USING_DXVA2) endif() -else(WIN32) - target_sources( - mythtv - PRIVATE recorders/vbitext/dllist.h - recorders/vbitext/lang.h - recorders/vbitext/vbi.h - recorders/vbitext/vt.h - recorders/vbitext/vbi.cpp - recorders/vbitext/lang.cpp) endif(WIN32) target_compile_definitions(mythtv PRIVATE MTV_API) diff --git a/mythtv/libs/libmythtv/captions/cc608reader.cpp b/mythtv/libs/libmythtv/captions/cc608reader.cpp index 3261fa21288..6709e600514 100644 --- a/mythtv/libs/libmythtv/captions/cc608reader.cpp +++ b/mythtv/libs/libmythtv/captions/cc608reader.cpp @@ -2,11 +2,10 @@ #include "captions/cc608reader.h" #include "mythplayer.h" -#include "recorders/vbitext/vbi.h" CC608Reader::CC608Reader(MythPlayer *parent) : m_parent(parent), - m_maxTextSize(8 * (sizeof(teletextsubtitle) + VT_WIDTH)) + m_maxTextSize(8 * (sizeof(teletextsubtitle) + 40)) { for (int i = 0; i < MAXTBUFFER; i++) m_inputBuffers[i].buffer = new unsigned char[m_maxTextSize + 1]; diff --git a/mythtv/libs/libmythtv/captions/teletextdecoder.cpp b/mythtv/libs/libmythtv/captions/teletextdecoder.cpp index f6b3a6bc76f..79b12802cf0 100644 --- a/mythtv/libs/libmythtv/captions/teletextdecoder.cpp +++ b/mythtv/libs/libmythtv/captions/teletextdecoder.cpp @@ -22,7 +22,6 @@ extern "C" { #include -#include "recorders/vbitext/vt.h" } #include "libmythbase/mythlogging.h" diff --git a/mythtv/libs/libmythtv/libmythtv.pro b/mythtv/libs/libmythtv/libmythtv.pro index a9dd040ad5c..985909c4937 100644 --- a/mythtv/libs/libmythtv/libmythtv.pro +++ b/mythtv/libs/libmythtv/libmythtv.pro @@ -77,19 +77,6 @@ cygwin:DEFINES += _WIN32 # Enable Valgrind, i.e. disable some timeouts using_valgrind:DEFINES += USING_VALGRIND -# old libvbitext (Caption decoder) -#using_v4l2 { - - !mingw:!win32-msvc* { - HEADERS += recorders/vbitext/dllist.h - HEADERS += recorders/vbitext/lang.h - HEADERS += recorders/vbitext/vbi.h - HEADERS += recorders/vbitext/vt.h - SOURCES += recorders/vbitext/vbi.cpp - SOURCES += recorders/vbitext/lang.cpp - } -#} - QMAKE_CLEAN += $(TARGET) $(TARGETA) $(TARGETD) $(TARGET0) $(TARGET1) $(TARGET2) ########################################################################## diff --git a/mythtv/libs/libmythtv/recorders/v4lrecorder.cpp b/mythtv/libs/libmythtv/recorders/v4lrecorder.cpp index dfa5bda8299..58b2ec2161b 100644 --- a/mythtv/libs/libmythtv/recorders/v4lrecorder.cpp +++ b/mythtv/libs/libmythtv/recorders/v4lrecorder.cpp @@ -14,7 +14,6 @@ #include "captions/vbi608extractor.h" #include "v4lrecorder.h" -#include "vbitext/vbi.h" #include "tv_rec.h" #define TVREC_CARDNUM \ @@ -65,58 +64,18 @@ void V4LRecorder::SetOption(const QString &name, const QString &value) DTVRecorder::SetOption(name, value); } -static void vbi_event(void *data_in, struct vt_event *ev) -{ - auto *data = static_cast(data_in); - switch (ev->type) - { - case EV_PAGE: - { - auto *vtp = (struct vt_page *) ev->p1; - if (vtp->flags & PG_SUBTITLE) - { -#if 0 - LOG(VB_GENERAL, LOG_DEBUG, QString("subtitle page %1.%2") - .arg(vtp->pgno, 0, 16) .arg(vtp->subno, 0, 16)); -#endif - data->foundteletextpage = true; - memcpy(&(data->teletextpage), vtp, sizeof(vt_page)); - } - } - break; - - case EV_HEADER: - case EV_XPACKET: - break; - } -} - int V4LRecorder::OpenVBIDevice(void) { int fd = -1; if (m_vbiFd >= 0) return m_vbiFd; - struct VBIData *vbi_cb = nullptr; - struct vbi *pal_tt = nullptr; uint width = 0; uint start_line = 0; uint line_count = 0; QByteArray vbidev = m_vbiDeviceName.toLatin1(); - if (VBIMode::PAL_TT == m_vbiMode) - { - pal_tt = vbi_open(vbidev.constData(), nullptr, 99, -1); - if (pal_tt) - { - fd = pal_tt->fd; - vbi_cb = new VBIData; - memset(vbi_cb, 0, sizeof(VBIData)); - vbi_cb->nvr = this; - vbi_add_handler(pal_tt, vbi_event, vbi_cb); - } - } - else if (VBIMode::NTSC_CC == m_vbiMode) + if (VBIMode::NTSC_CC == m_vbiMode) { fd = open(vbidev.constData(), O_RDONLY/*|O_NONBLOCK*/); } @@ -181,12 +140,7 @@ int V4LRecorder::OpenVBIDevice(void) #endif // USING_V4L2 } - if (VBIMode::PAL_TT == m_vbiMode) - { - m_palVbiCb = vbi_cb; - m_palVbiTt = pal_tt; - } - else if (VBIMode::NTSC_CC == m_vbiMode) + if (VBIMode::NTSC_CC == m_vbiMode) { m_ntscVbiWidth = width; m_ntscVbiStartLine = start_line; @@ -204,14 +158,6 @@ void V4LRecorder::CloseVBIDevice(void) if (m_vbiFd < 0) return; - if (m_palVbiTt) - { - vbi_del_handler(m_palVbiTt, vbi_event, m_palVbiCb); - vbi_close(m_palVbiTt); - delete m_palVbiCb; - m_palVbiCb = nullptr; - } - else { delete m_vbi608; m_vbi608 = nullptr; close(m_vbiFd); @@ -259,17 +205,7 @@ void V4LRecorder::RunVBIDevice(void) LOG(VB_GENERAL, LOG_DEBUG, LOC + "vbi select timed out"); continue; // either failed or timed out.. } - if (VBIMode::PAL_TT == m_vbiMode) - { - m_palVbiCb->foundteletextpage = false; - vbi_handler(m_palVbiTt, m_palVbiTt->fd); - if (m_palVbiCb->foundteletextpage) - { - // decode VBI as teletext subtitles - FormatTT(m_palVbiCb); - } - } - else if (VBIMode::NTSC_CC == m_vbiMode) + if (VBIMode::NTSC_CC == m_vbiMode) { int ret = read(m_vbiFd, ptr, ptr_end - ptr); ptr = (ret > 0) ? ptr + ret : ptr; diff --git a/mythtv/libs/libmythtv/recorders/v4lrecorder.h b/mythtv/libs/libmythtv/recorders/v4lrecorder.h index 8ad0af071bb..af4b7935a72 100644 --- a/mythtv/libs/libmythtv/recorders/v4lrecorder.h +++ b/mythtv/libs/libmythtv/recorders/v4lrecorder.h @@ -6,21 +6,12 @@ #include "libmythtv/captions/cc608decoder.h" #include "libmythtv/recorders/dtvrecorder.h" -#include "libmythtv/recorders/vbitext/vt.h" #include "libmythtv/tv.h" // for VBIMode class VBI608Extractor; class VBIThread; class TVRec; -struct vbi; -struct VBIData -{ - RecorderBase *nvr; - vt_page teletextpage; - bool foundteletextpage; -}; - /// Abstract base class for Video4Linux based recorders. class MTV_PUBLIC V4LRecorder : public DTVRecorder { @@ -40,15 +31,12 @@ class MTV_PUBLIC V4LRecorder : public DTVRecorder void RunVBIDevice(void); virtual bool IsHelperRequested(void) const; - virtual void FormatTT(struct VBIData */*vbidata*/) {} virtual void FormatCC(uint /*code1*/, uint /*code2*/) {} protected: QString m_audioDeviceName; QString m_vbiDeviceName; int m_vbiMode {VBIMode::None}; - struct VBIData *m_palVbiCb {nullptr}; - struct vbi *m_palVbiTt {nullptr}; uint m_ntscVbiWidth {0}; uint m_ntscVbiStartLine {0}; uint m_ntscVbiLineCount {0}; diff --git a/mythtv/libs/libmythtv/recorders/vbitext/dllist.h b/mythtv/libs/libmythtv/recorders/vbitext/dllist.h deleted file mode 100644 index 5c92441d9e5..00000000000 --- a/mythtv/libs/libmythtv/recorders/vbitext/dllist.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef DLLIST_H -#define DLLIST_H - -#ifdef __cplusplus -extern "C" { -#endif - -struct dl_node -{ - struct dl_node *next; - struct dl_node *prev; -}; - -struct dl_head -{ - struct dl_node *first; - struct dl_node *null; - struct dl_node *last; -}; - -static inline struct dl_head * -dl_init(struct dl_head *h) -{ - h->first = (struct dl_node *)&h->null; - h->null = nullptr; - h->last = (struct dl_node *)&h->first; - return h; -} - -static inline struct dl_node * -dl_remove(struct dl_node *n) -{ - n->prev->next = n->next; - n->next->prev = n->prev; - return n; -} - -static inline struct dl_node * -dl_insert_after(struct dl_node *p, struct dl_node *n) -{ - n->next = p->next; - n->prev = p; - p->next = n; - n->next->prev = n; - return n; -} - -#define dl_empty(h) ((h)->first->next == nullptr) -#define dl_insert_before(p, n) dl_insert_after((p)->prev, (n)) -#define dl_insert_first(h, n) ({ struct dl_node *_n = (n); \ - dl_insert_before((h)->first, _n); }) -#define dl_insert_last(h, n) ({ struct dl_node *_n = (n); \ - dl_insert_after((h)->last, _n); }) -#define dl_remove_first(h) dl_remove((h)->first) // mustn't be empty! -#define dl_remove_last(h) dl_remove((h)->last) // mustn't be empty! - -#ifdef __cplusplus -} -#endif - -#endif /* DLLIST_H */ - diff --git a/mythtv/libs/libmythtv/recorders/vbitext/lang.cpp b/mythtv/libs/libmythtv/recorders/vbitext/lang.cpp deleted file mode 100644 index d1191e7f31c..00000000000 --- a/mythtv/libs/libmythtv/recorders/vbitext/lang.cpp +++ /dev/null @@ -1,221 +0,0 @@ -#include -#include -#include -#include "vt.h" -#include "lang.h" - -int isLatin1 = -1; - -static std::array lang_char; - -/* Yankable latin charset :-) - !"#$%&'()*+,-./0123456789:;<=>? - @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ - `abcdefghijklmnopqrstuvwxyz{|}~ - ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ - ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß - àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ -*/ - - - -struct mark { const std::string m_g0, m_latin1, m_latin2; }; -static const std::array marks = -{{ - /* none */ { "#", - "\xA4", /* ¤ */ - "$" }, - /* grave - ` */ { " aeiouAEIOU", /* `àèìòùÀÈÌÒÙ */ - "`\xE0\xE8\xEC\xF2\xF9\xC0\xC8\xCC\xD2\xD9", - "`aeiouAEIOU" }, - /* acute - ' */ { " aceilnorsuyzACEILNORSUYZ", - "'\xE1\x63\xE9\xEDln\xF3rs\xFA\xFDz\xC1\x43\xC9\xCDLN\xD3RS\xDA\xDDZ", /* 'ácéílnórsúýzÁCÉÍLNÓRSÚÝZ */ - "'\xE1\xE6\xE9\xED\xE5\xF1\xF3\xE0\xB6\xFA\xFD\xBC\xC1\xC6\xC9\xCD\xC5\xD1\xD3\xC0\xA6\xDAݬ" /* 'áæéíåñóà¶úý¼ÁÆÉÍÅÑÓÀ¦Úݬ */ }, - /* cirumflex - ^ */ { " aeiouAEIOU", - "^\xE2\xEA\xEE\xF4\xFB\xC2\xCA\xCE\xD4\xDB", /* ^âêîôûÂÊÎÔÛ */ - "^\xE2\x65\xEE\xF4\x75\xC2\x45\xCE\xD4\x55" }, /* ^âeîôuÂEÎÔU */ - /* tilde - ~ */ { " anoANO", - "~\xE3\xF1\xF5\xC3\xD1\xD5", /* ~ãñõÃÑÕ */ - "~anoANO" }, - /* ??? - */ { "", - "", - "" }, - /* breve - u */ { "aA", - "aA", - "\xE3\xC3" /* ãà */ }, - /* abovedot - · */ { "zZ", - "zZ", - "\xBF\xAF" /* ¿¯ */ }, - /* diaeresis ¨ */ { "aeiouAEIOU", - "\xE4\xEB\xEF\xF6\xFC\xC4\xCB\xCF\xD6\xDC", /* äëïöüÄËÏÖÜ */ - "\xE4\xEB\x69\xF6\xFC\xC4\xCB\x49\xD6\xDC" /* äëiöüÄËIÖÜ */}, - /* ??? - . */ { "", - "", - "" }, - /* ringabove - ° */ { " auAU", - "\xB0\xE5\x75\xC5\x55", /* °åuÅU */ - "\xB0\x61\xF9\x41\xD9" /* °aùAÙ */ }, - /* cedilla - ¸ */ { "cstCST", - "\xE7\x73\x74\xC7\x53\x54", /* çstÇST */ - "\xE7\xBA\xFE\xC7\xAA\xDE" /* çºþÇªÞ */ }, - /* ??? - _ */ { " ", - "_", - "_" }, - /* dbl acute - " */ { " ouOU", - "\"ouOU", - "\x22\xF5\xFB\xD5\xDB" /* \"õûÕÛ */ }, - /* ogonek - \, */ { "aeAE", - "aeAE", - "\xB1\xEA\xA1\xCA" /* ±ê¡Ê */ }, - /* caron - v */ { "cdelnrstzCDELNRSTZ", - "cdelnrstzCDELNRSTZ", - "\xE8\xEF\xEC\xB5\xF2\xF8\xB9\xBB\xBE\xC8\xCF̥\xD2ة\xAB\xAE" /* èïìµòø¹»¾ÈÏÌ¥ÒØ©«® */ }, -}}; - -static const std::string g2map_latin1 = - /*0123456789abcdef*/ - "\x20\xA1\xA2\xA3\x24\xA5\x23\xA7\xA4\x27\x22\xAB\x20\x20\x20\x20" /* ¡¢£$¥#§¤'\"« */ - "\xB0\xB1\xB2\xB3\xD7\xB5\xB6\xB7\xF7\x27\x22\xBB\xBC\xBD\xBE\xBF" /* °±²³×µ¶·÷'\"»¼½¾¿ */ - "\x20\x60\xB4\x5E\x7E\x20\x20\x20\xA8\x2e\xB0\xB8\x5F\x22\x20\x20" /* `´^~ ¨.°¸_\" */ - "\x5F\xB9\xAE\xA9\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" /* _¹®© */ - "\x20\xC6\xD0\xAA\x48\x20\x49\x4C\x4C\xD8\x20\xBA\xDE\x54\x4E\x6E" /* ÆЪH ILLØ ºÞTNn */ - "\x4B\xE6\x64\xF0\x68\x69\x69\x6C\x6C\xF8\x20\xDF\xFE\x74\x6E\x7f"; /* Kædðhiillø ßþtn\x7f" */ - -static const std::string g2map_latin2 = - /*0123456789abcdef*/ - "\x20\x69\x63\x4C\x24\x59\x23\xA7\xA4\x27\x22\x3C\x20\x20\x20\x20" /* icL$Y#§¤'\"< */ - "\xB0\x20\x20\x20\xD7\x75\x20\x20\xF7\x27\x22\x3E\x20\x20\x20\x20" /* ° ×u ÷'\"> */ - "\x20\x60\xB4\x5E\x7E\x20\xA2\xFF\xA8\x2E\xB0\xB8\x5F\xBD\xB2\xB7" /* `´^~ ¢ÿ¨.°¸_½²· */ - "\x2D\x20\x52\x43\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20" /* - RC */ - "\x20\x20\xD0\x61\x48\x20\x69\x4C\xA3\x4F\x20\x6F\x70\x54\x4E\x6e" /* ÐaH iL£O opTNn */ - "\x4B\x20\xF0\x64\x68\x69\x69\x6C\xB3\x6F\x20\xDF\x70\x74\x6e\x7f"; /* K ðdhiil³o ßptn\x7f" */ - - - -void -lang_init(void) -{ - int i = 0; - - lang_char.fill(0); - for (i = 1; i <= 13; i++) - lang_char[(unsigned char)(lang_chars[0][i])] = i; -} - - -void -conv2latin(unsigned char *p, int n, int lang) -{ - int gfx = 0; - - while (n--) - { - int c = *p; - if (lang_char[c]) - { - if (! gfx || (c & 0xa0) != 0x20) - *p = lang_chars[lang + 1][lang_char[c]]; - } - else if ((c & 0xe8) == 0) - { - gfx = c & 0x10; - } - p++; - } -} - - - -void -init_enhance(struct enhance *eh) -{ - eh->next_des = 0; -} - -void -add_enhance(struct enhance *eh, int dcode, std::array& data) -{ - if (dcode == eh->next_des) - { - memcpy(eh->trip + (static_cast(dcode) * 13), - data.cbegin(), data.size() * sizeof(unsigned int)); - eh->next_des++; - } - else - { - eh->next_des = -1; - } -} - -void -do_enhancements(struct enhance *eh, struct vt_page *vtp) -{ - int8_t row = 0; - - if (eh->next_des < 1) - return; - - for (unsigned int *p = eh->trip, *e = p + (static_cast(eh->next_des) * 13); p < e; p++) - { - if (*p % 2048 != 2047) - { - int8_t adr = *p % 64; - int8_t mode = *p / 64 % 32; - int8_t data = *p / 2048 % 128; - - //printf("%2x,%d,%d ", mode, adr, data); - if (adr < 40) - { - // col functions - switch (mode) - { - case 15: // char from G2 set - if (adr < VT_WIDTH && row < VT_HEIGHT) - { - if (isLatin1) - vtp->data[row][adr] = g2map_latin1[data-32]; - else - vtp->data[row][adr] = g2map_latin2[data-32]; - } - break; - case 16 ... 31: // char from G0 set with diacritical mark - if (adr < VT_WIDTH && row < VT_HEIGHT) - { - const struct mark *mark = &marks[mode - 16]; - size_t index = mark->m_g0.find(data); - if (index != std::string::npos) - { - if (isLatin1) - data = mark->m_latin1[index]; - else - data = mark->m_latin2[index]; - } - vtp->data[row][adr] = data; - } - break; - } - } - else - { - // row functions - adr -= 40; - if (adr == 0) - adr = 24; - - switch (mode) - { - case 1: // full row color - case 4: // set active position - row = adr; - break; - case 7: // address row 0 (+ full row color) - if (adr == 23) - row = 0; - break; - } - } - } - } - //printf("\n"); -} - diff --git a/mythtv/libs/libmythtv/recorders/vbitext/lang.h b/mythtv/libs/libmythtv/recorders/vbitext/lang.h deleted file mode 100644 index 6de33b4e7da..00000000000 --- a/mythtv/libs/libmythtv/recorders/vbitext/lang.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef LANG_H -#define LANG_H - -#include "captions/vbilut.h" -#include "vt.h" - -extern int isLatin1; - -struct enhance -{ - int next_des; // next expected designation code - unsigned int trip[13*16]; // tripplets -}; - -void lang_init(void); -void conv2latin(unsigned char *p, int n, int lang); - -void init_enhance(struct enhance *eh); -void add_enhance(struct enhance *eh, int dcode, std::array& data); -void do_enhancements(struct enhance *eh, struct vt_page *vtp); - -#endif // LANG_H - diff --git a/mythtv/libs/libmythtv/recorders/vbitext/vbi.cpp b/mythtv/libs/libmythtv/recorders/vbitext/vbi.cpp deleted file mode 100644 index f0396e10124..00000000000 --- a/mythtv/libs/libmythtv/recorders/vbitext/vbi.cpp +++ /dev/null @@ -1,682 +0,0 @@ -// POSIX headers -#include -#include - -#include - -// ANSI C++ headers -#include -#include -#include -#include -#include -#include -#include - -#ifdef USING_V4L2 -#include -#endif // USING_V4L2 - -// vbitext headers -#include "captions/vbilut.h" -#include "vbi.h" -#include "vt.h" - -static constexpr int FAC = { 1<<16 }; // factor for fix-point arithmetic - -static unsigned char *rawbuf = nullptr;// one common buffer for raw vbi data. -#ifdef USING_V4L2 -static int rawbuf_size; // its current size -#endif // USING_V4L2 - -/***** bttv api *****/ -#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int) - - -static void -error(const char *str, ...) -{ - va_list ap; - - va_start(ap, str); - vfprintf(stderr, str, ap); - fprintf(stderr, "\n"); - va_end(ap); -} - - -static int -chk_parity(uint8_t *p, int n) -{ - int err = 0; - - for (err = 0; n--; p++) - { - if (hamm24par[0][*p] & 32) - *p &= 0x7f; - else - *p = BAD_CHAR, err++; - } - return err; -} - -static void -out_of_sync(struct vbi *vbi) -{ - int i = 0; - - // discard all in progress pages - for (i = 0; i < 8; ++i) - vbi->rpage[i].page->flags &= ~PG_ACTIVE; -} - - -// send an event to all clients - -static void -vbi_send(struct vbi *vbi, int type, int i1, int i2, int i3, void *p1) -{ - struct vt_event ev {}; - struct vbi_client *cl = nullptr; - struct vbi_client *cln = nullptr; - - ev.resource = vbi; - ev.type = type; - ev.i1 = i1; - ev.i2 = i2; - ev.i3 = i3; - ev.p1 = p1; - - for (cl = reinterpret_cast(vbi->clients[0].first); - (cln = reinterpret_cast(cl->node->next)) != nullptr; - cl = cln) - cl->handler(cl->data, &ev); -} - -static void -vbi_send_page(struct vbi *vbi, struct raw_page *rvtp, int page) -{ - if (rvtp->page->flags & PG_ACTIVE) - { - if (rvtp->page->pgno % 256 != page) - { - struct vt_page *cvtp = nullptr; - rvtp->page->flags &= ~PG_ACTIVE; - do_enhancements(rvtp->enh, rvtp->page); -// if (vbi->cache) -// cvtp = vbi->cache->op->put(vbi->cache, rvtp->page); - vbi_send(vbi, EV_PAGE, 0, 0, 0, cvtp ?: rvtp->page); - } - } -} - -// fine tune pll -// this routines tries to adjust the sampling point of the decoder. -// it collects parity and hamming errors and moves the sampling point -// a 10th of a bitlength left or right. - -static constexpr int8_t PLL_SAMPLES { 4 }; // number of err vals to collect -static constexpr int8_t PLL_ERROR { 4 }; // if this err val is crossed, readjust -//static constexpr int8_t PLL_ADJUST { 4 }; // max/min adjust (10th of bitlength) - -static void -pll_add(struct vbi *vbi, int n, int err) -{ - if (vbi->pll_fixed) - return; - - // limit burst errors - err = std::min(err, PLL_ERROR*2/3); - - vbi->pll_err += err; - vbi->pll_cnt += n; - if (vbi->pll_cnt < PLL_SAMPLES) - return; - - if (vbi->pll_err > PLL_ERROR) - { - if (vbi->pll_err > vbi->pll_lerr) - vbi->pll_dir = -vbi->pll_dir; - vbi->pll_lerr = vbi->pll_err; - - vbi->pll_adj += vbi->pll_dir; - if (vbi->pll_adj < -PLL_ADJUST || vbi->pll_adj > PLL_ADJUST) - { - vbi->pll_adj = 0; - vbi->pll_dir = -1; - vbi->pll_lerr = 0; - } - -#ifdef DEBUG - printf("pll_adj = %2d\n", vbi->pll_adj); -#endif - } - vbi->pll_cnt = 0; - vbi->pll_err = 0; -} - -void -vbi_pll_reset(struct vbi *vbi, int fine_tune) -{ - vbi->pll_fixed = static_cast(fine_tune >= -PLL_ADJUST && fine_tune <= PLL_ADJUST); - - vbi->pll_err = 0; - vbi->pll_lerr = 0; - vbi->pll_cnt = 0; - vbi->pll_dir = -1; - vbi->pll_adj = 0; - if (vbi->pll_fixed) - vbi->pll_adj = fine_tune; -#ifdef DEBUG - if (vbi->pll_fixed) - printf("pll_reset (fixed@%d)\n", vbi->pll_adj); - else - printf("pll_reset (auto)\n"); -#endif -} - -// process one videotext packet - -static int -vt_line(struct vbi *vbi, unsigned char *p) -{ - struct vt_page *cvtp = nullptr; - struct raw_page *rvtp = nullptr; - int err = 0; - - int hdr = hamm16(p, &err); - if (err & 0xf000) - return -4; - - int mag = hdr & 7; - int mag8 = mag?: 8; - int pkt = (hdr >> 3) & 0x1f; - p += 2; - - rvtp = vbi->rpage + mag; - cvtp = rvtp->page; - - switch (pkt) - { - case 0: - { - int b1 = hamm16(p, &err); // page number - int b2 = hamm16(p+2, &err); // subpage number + flags - int b3 = hamm16(p+4, &err); // subpage number + flags - int b4 = hamm16(p+6, &err); // language code + more flags - - if (vbi->ppage->page->flags & PG_MAGSERIAL) - vbi_send_page(vbi, vbi->ppage, b1); - vbi_send_page(vbi, rvtp, b1); - - if (err & 0xf000) - return 4; - - cvtp->errors = (err >> 8) + chk_parity(p + 8, 32);; - cvtp->pgno = mag8 * 256 + b1; - cvtp->subno = (b2 + b3 * 256) & 0x3f7f; - cvtp->lang = "\0\4\2\6\1\5\3\7"[b4 >> 5] + (isLatin1 ? 0 : 8); - cvtp->flags = b4 & 0x1f; - cvtp->flags |= b3 & 0xc0; - cvtp->flags |= (b2 & 0x80) >> 2; - cvtp->lines = 1; - cvtp->flof = 0; - vbi->ppage = rvtp; - - pll_add(vbi, 1, cvtp->errors); - - conv2latin(p + 8, 32, cvtp->lang); - vbi_send(vbi, EV_HEADER, cvtp->pgno, cvtp->subno, cvtp->flags, p); - - if (b1 == 0xff) - return 0; - - cvtp->flags |= PG_ACTIVE; - init_enhance(rvtp->enh); - memcpy(cvtp->data[0]+0, p, 40); - memset(cvtp->data[0]+40, ' ', sizeof(cvtp->data)-40); - return 0; - } - - case 1 ... 24: - { - pll_add(vbi, 1, err = chk_parity(p, 40)); - - if (~cvtp->flags & PG_ACTIVE) - return 0; - - cvtp->errors += err; - cvtp->lines |= 1 << pkt; - conv2latin(p, 40, cvtp->lang); - memcpy(cvtp->data[pkt], p, 40); - return 0; - } - case 26: - { - if (~cvtp->flags & PG_ACTIVE) - return 0; - - int d = hamm8(p, &err); - if (err & 0xf000) - return 4; - - std::array t {}; - for (ptrdiff_t i = 0; i < 13; ++i) - t[i] = hamm24(p + 1 + (3*i), &err); - if (err & 0xf000) - return 4; - - //printf("enhance on %x/%x\n", cvtp->pgno, cvtp->subno); - add_enhance(rvtp->enh, d, t); - return 0; - } - case 27: - { - // FLOF data (FastText) - if (~cvtp->flags & PG_ACTIVE) - return 0; // -1 flushes all pages. we may never resync again :( - - int b1 = hamm8(p, &err); - int b2 = hamm8(p + 37, &err); - if (err & 0xf000) - return 4; - if (b1 != 0 || !(b2 & 8)) - return 0; - - for (ptrdiff_t i = 0; i < 6; ++i) - { - err = 0; - b1 = hamm16(p+1+(6*i), &err); - b2 = hamm16(p+3+(6*i), &err); - int b3 = hamm16(p+5+(6*i), &err); - if (err & 0xf000) - return 1; - int x = (b2 >> 7) | ((b3 >> 5) & 0x06); - cvtp->link[i].pgno = ((mag ^ x) ?: 8) * 256 + b1; - cvtp->link[i].subno = (b2 + b3 * 256) & 0x3f7f; - } - cvtp->flof = 1; - return 0; - } - case 30: - { - if (mag8 != 8) - return 0; - - p[0] = hamm8(p, &err); // designation code - p[1] = hamm16(p+1, &err); // initial page - p[3] = hamm16(p+3, &err); // initial subpage + mag - p[5] = hamm16(p+5, &err); // initial subpage + mag - if (err & 0xf000) - return 4; - - err += chk_parity(p+20, 20); - conv2latin(p+20, 20, 0); - - vbi_send(vbi, EV_XPACKET, mag8, pkt, err, p); - return 0; - } - default: - // unused at the moment... - //vbi_send(vbi, EV_XPACKET, mag8, pkt, err, p); - return 0; - } - return 0; -} - - - -// process one raw vbi line - -static int -vbi_line(struct vbi *vbi, const unsigned char *p) -{ - std::array data {}; - std::array dt {}; - std::array hi {}; - std::array lo {}; - int i = 0; - int n = 0; - int bpb = vbi->bpb; - - /* remove DC. edge-detector */ - for (i = vbi->soc; i < vbi->eoc; ++i) - dt[i] = p[i+(bpb/FAC)] - p[i]; // amplifies the edges best. - - /* set barrier */ - for (i = vbi->eoc; i < vbi->eoc+16; i += 2) - dt[i] = 100, dt[i+1] = -100; - - /* find 6 rising and falling edges */ - for (i = vbi->soc, n = 0; n < 6; ++n) - { - while (dt[i] < 32) - i++; - hi[n] = i; - while (dt[i] > -32) - i++; - lo[n] = i; - } - if (i >= vbi->eoc) - return -1; // not enough periods found - - i = hi[5] - hi[1]; // length of 4 periods (8 bits) - if (i < vbi->bp8bl || i > vbi->bp8bh) - return -1; // bad frequency - - /* AGC and sync-reference */ - unsigned char min = 255; - unsigned char max = 0; - int sync = 0; - for (i = hi[4]; i < hi[5]; ++i) - if (p[i] > max) - max = p[i], sync = i; - for (i = lo[4]; i < lo[5]; ++i) - min = std::min(p[i], min); - int thr = (min + max) / 2; - - p += sync; - - /* search start-byte 11100100 */ - for (i = 4*bpb + vbi->pll_adj*bpb/10; i < 16*bpb; i += bpb) - { - if (p[i/FAC] > thr && p[(i+bpb)/FAC] > thr) // two ones is enough... - { - /* got it... */ - data.fill(0); - - for (n = 0; n < 43*8; ++n, i += bpb) - if (p[i/FAC] > thr) - data[n/8] |= 1 << (n%8); - - if (data[0] != 0x27) // really 11100100? (rev order!) - return -1; - - i = vt_line(vbi, data.data()+1); - if (i != 0) - { - if (i < 0) - pll_add(vbi, 2, -i); - else - pll_add(vbi, 1, i); - } - return 0; - } - } - return -1; -} - - - -// called when new vbi data is waiting - -void -vbi_handler(struct vbi *vbi, [[maybe_unused]] int fd) -{ - int n = 0; - unsigned int seq = 0; - - n = read(vbi->fd, rawbuf, vbi->bufsize); - - if (dl_empty(vbi->clients)) - return; - - if (n != vbi->bufsize) - return; - - seq = *(unsigned int *)&rawbuf[n - 4]; - if (vbi->seq+1 != seq) - { - out_of_sync(vbi); - if (seq < 3 && vbi->seq >= 3) - vbi_reset(vbi); - } - vbi->seq = seq; - - if (seq > 1) // the first may contain data from prev channel - { -#if 1 - for (int i = 0; i+vbi->bpl <= n; i += vbi->bpl) - vbi_line(vbi, rawbuf + i); -#else - /* work-around for old saa7134 driver versions (prior 0.2.6) */ - for (int i = 16 * vbi->bpl; i + vbi->bpl <= n; i += vbi->bpl) - vbi_line(vbi, rawbuf + i); - - for (int i = 0; i + vbi->bpl <= 16 * vbi->bpl; i += vbi->bpl) - vbi_line(vbi, rawbuf + i); -#endif - } -} - - - -int -vbi_add_handler(struct vbi *vbi, vbic_handler handler, void *data) -{ - auto *cl = new struct vbi_client; - if (cl == nullptr) - return -1; - cl->handler = handler; - cl->data = data; - // cl is not leaking, the first struct element has the same address - // as the struct - dl_insert_last(vbi->clients, cl->node); - return 0; // cppcheck-suppress memleak -} - - - -void -vbi_del_handler(struct vbi *vbi, vbic_handler handler, void *data) -{ - struct vbi_client *cl = nullptr; - - for (cl = reinterpret_cast(vbi->clients->first); - cl->node->next != nullptr; - cl = reinterpret_cast(cl->node->next)) - { - if (cl->handler == handler && cl->data == data) - { - dl_remove(cl->node); - delete cl; - break; - } - } -} - -#ifdef USING_V4L2 -static int -set_decode_parms(struct vbi *vbi, struct v4l2_vbi_format *p) -{ - if (p->sample_format != V4L2_PIX_FMT_GREY) - { - fprintf(stderr, "got pix fmt %x\n", p->sample_format); - error("v4l2: unsupported vbi data format"); - return -1; - } - - // some constants from the standard: - // horizontal frequency fh = 15625Hz - // teletext bitrate ft = 444*fh = 6937500Hz - // teletext identification sequence 10101010 10101010 11100100 - // 13th bit of seq rel to falling hsync 12us -1us +0.4us - // I search for the clock run-in (10101010 10101010) from 12us-1us-12.5/ft - // (earliest first bit) to 12us+0.4us+3.5/ft (latest last bit) - // earlist first bit tf = 12us-1us-12.5/ft = 9.2us - // latest last bit tl = 12us+0.4us+3.5/ft = 12.9us - // total number of used bits n = (2+1+2+40)*8 = 360 - - int bpl = p->samples_per_line; // bytes per line - double fs = p->sampling_rate; // sampling rate - double bpb = fs/6937500.0; // bytes per bit - int soc = (int)(9.2e-6*fs) - (int)p->offset; // start of clock run-in - int eoc = (int)(12.9e-6*fs) - (int)p->offset; // end of clock run-in - soc = std::max(soc, 0); - eoc = std::min(eoc, bpl - (int)(43*8*bpb)); - if (eoc - soc < (int)(16*bpb)) - { - // line too short or offset too large or wrong sample_rate - error("v4l2: broken vbi format specification"); - return -1; - } - if (eoc > 240) - { - // the vbi_line routine can hold max 240 values in its work buffer - error("v4l2: unable to handle these sampling parameters"); - return -1; - } - - vbi->bpb = lround(bpb * FAC); - vbi->soc = soc; - vbi->eoc = eoc; - vbi->bp8bl = 0.97 * 8*bpb; // -3% tolerance - vbi->bp8bh = 1.03 * 8*bpb; // +3% tolerance - - vbi->bpl = bpl; - vbi->bufsize = bpl * (p->count[0] + p->count[1]); - - return 0; -} -#endif // USING_V4L2 - -static int -setup_dev([[maybe_unused]] struct vbi *vbi) -{ -#ifdef USING_V4L2 - struct v4l2_format v4l2_format {}; - struct v4l2_vbi_format *vbifmt = &v4l2_format.fmt.vbi; - - memset(&v4l2_format, 0, sizeof(v4l2_format)); - v4l2_format.type = V4L2_BUF_TYPE_VBI_CAPTURE; - if (ioctl(vbi->fd, VIDIOC_G_FMT, &v4l2_format) == -1) - { - error("Video 4 Linux version 1 support is not enabled."); - return -1; - } - - if (set_decode_parms(vbi, vbifmt) == -1) - return -1; - - if (vbi->bpl < 1 || vbi->bufsize < vbi->bpl || vbi->bufsize % vbi->bpl != 0) - { - error("strange size of vbi buffer (%d/%d)", vbi->bufsize, vbi->bpl); - return -1; - } - - // grow buffer if necessary - if (rawbuf_size < vbi->bufsize) - { - delete [] rawbuf; - rawbuf_size = vbi->bufsize; - rawbuf = new u_char[rawbuf_size]; - if (rawbuf == nullptr) - { - error("unable to allocate in setup_dev()\n"); - } - } - - return 0; -#else - return -1; -#endif // USING_V4L2 -} - - - -struct vbi * -vbi_open(const char *vbi_dev_name, - [[maybe_unused]] struct cache *ca, - int fine_tune, - int big_buf) -{ - static int s_inited = 0; - struct vbi *vbi = nullptr; - - if (! s_inited) - lang_init(); - s_inited = 1; - - vbi = new struct vbi; - if (vbi == nullptr) - { - error("out of memory"); - goto fail1; - } - - vbi->fd = open(vbi_dev_name, O_RDONLY); - if (vbi->fd == -1) - { - error("cannot open vbi device"); - goto fail2; - } - - if (big_buf != -1) - error("-oldbttv/-newbttv is obsolete. option ignored."); - - if (setup_dev(vbi) == -1) - goto fail3; - -// vbi->cache = ca; - - dl_init(vbi->clients); - vbi->seq = 0; - out_of_sync(vbi); - vbi->ppage = vbi->rpage; - - vbi_pll_reset(vbi, fine_tune); -// ECA removed fdset_add_fd(fds, vbi->fd, vbi_handler, vbi); - return vbi; - -fail3: - close(vbi->fd); -fail2: - delete vbi; -fail1: - return nullptr; -} - - - -void -vbi_close(struct vbi *vbi) -{ -// fdset_del_fd(fds, vbi->fd); -// if (vbi->cache) -// vbi->cache->op->close(vbi->cache); - close(vbi->fd); - delete vbi; -} - - -struct vt_page * -vbi_query_page([[maybe_unused]] struct vbi *vbi, - [[maybe_unused]] int pgno, - [[maybe_unused]] int subno) -{ -#ifdef IMPLEMENTED - struct vt_page *vtp = 0; - - if (vbi->cache) - vtp = vbi->cache->op->get(vbi->cache, pgno, subno); - if (vtp == 0) - { - // EV_PAGE will come later... - return 0; - } - - vbi_send(vbi, EV_PAGE, 1, 0, 0, vtp); - return vtp; -#else - return nullptr; -#endif -} - -void -vbi_reset(struct vbi *vbi) -{ -// if (vbi->cache) -// vbi->cache->op->reset(vbi->cache); - vbi_send(vbi, EV_RESET, 0, 0, 0, nullptr); -} - diff --git a/mythtv/libs/libmythtv/recorders/vbitext/vbi.h b/mythtv/libs/libmythtv/recorders/vbitext/vbi.h deleted file mode 100644 index 06c621e4fa1..00000000000 --- a/mythtv/libs/libmythtv/recorders/vbitext/vbi.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef VBI_H -#define VBI_H - -#include "vt.h" -#include "dllist.h" -#include "lang.h" -//#include "cache.h" - -static constexpr int8_t PLL_ADJUST { 4 }; - -struct raw_page -{ - struct vt_page page[1]; - struct enhance enh[1]; -}; - -struct vbi -{ - int fd; - struct cache *cache; - struct dl_head clients[1]; - // raw buffer management - int bufsize; // nr of bytes sent by this device - int bpl; // bytes per line - unsigned int seq; - // page assembly - struct raw_page rpage[8]; // one for each magazin - struct raw_page *ppage; // points to page of previous pkt0 - // phase correction - int pll_fixed; // 0 = auto, 1..2*PLL_ADJUST+1 = fixed - int pll_adj; - int pll_dir; - int pll_cnt; - int pll_err, pll_lerr; - // v4l2 decoder data - int bpb; // bytes per bit * 2^16 - int bp8bl, bp8bh; // bytes per 8-bit low/high - int soc, eoc; // start/end of clock run-in -}; - -using vbic_handler = void (*)(void *data, struct vt_event *ev); - -struct vbi_client -{ - struct dl_node node[1]; - vbic_handler handler; - void *data; -}; - -struct vbi *vbi_open(const char *vbi_dev_name, struct cache *ca, int fine_tune, - int big_buf); -void vbi_close(struct vbi *vbi); -void vbi_reset(struct vbi *vbi); -int vbi_add_handler(struct vbi *vbi, vbic_handler handler, void *data); -void vbi_del_handler(struct vbi *vbi, vbic_handler handler, void *data); -struct vt_page *vbi_query_page(struct vbi *vbi, int pgno, int subno); -void vbi_pll_reset(struct vbi *vbi, int fine_tune); - -void vbi_handler(struct vbi *vbi, int fd); - -#endif - diff --git a/mythtv/libs/libmythtv/recorders/vbitext/vt.h b/mythtv/libs/libmythtv/recorders/vbitext/vt.h deleted file mode 100644 index 8dd1a560b63..00000000000 --- a/mythtv/libs/libmythtv/recorders/vbitext/vt.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef VT_H -#define VT_H - -#define VT_WIDTH 40 -#define VT_HEIGHT 25 -#define BAD_CHAR 0xb8 // substitute for chars with bad parity - -struct vt_event -{ - int type; - void *resource; /* struct xio_win *, struct vbi *, ... */ - int i1, i2, i3, i4; - void *p1; -}; - -#define EV_CLOSE 1 -#define EV_KEY 2 // i1:KEY_xxx i2:shift-flag -#define EV_MOUSE 3 // i1:button i2:shift-flag i3:x i4:y -#define EV_SELECTION 4 // i1:len p1:data -#define EV_PAGE 5 // p1:vt_page i1:query-flag -#define EV_HEADER 6 // i1:pgno i2:subno i3:flags p1:data -#define EV_XPACKET 7 // i1:mag i2:pkt i3:errors p1:data -#define EV_RESET 8 // ./. -#define EV_TIMER 9 // ./. - -#define KEY_F(i) (1000+(i)) -#define KEY_LEFT 2001 -#define KEY_RIGHT 2002 -#define KEY_UP 2003 -#define KEY_DOWN 2004 -#define KEY_PUP 2005 -#define KEY_PDOWN 2006 -#define KEY_DEL 2007 -#define KEY_INS 2008 - -struct vt_page -{ - int pgno, subno; // the wanted page number - int lang; // language code - int flags; // misc flags (see PG_xxx below) - int errors; // number of single bit errors in page - unsigned int lines; // 1 bit for each line received - unsigned char data[VT_HEIGHT][VT_WIDTH]; // page contents - int flof; // page has FastText links - struct { - int pgno; - int subno; - } link[6]; // FastText links (FLOF) -}; - -#define PG_SUPPHEADER 0x01 // C7 row 0 is not to be displayed -#define PG_UPDATE 0x02 // C8 row 1-28 has modified (editors flag) -#define PG_OUTOFSEQ 0x04 // C9 page out of numerical order -#define PG_NODISPLAY 0x08 // C10 rows 1-24 is not to be displayed -#define PG_MAGSERIAL 0x10 // C11 serial trans. (any pkt0 terminates page) -#define PG_ERASE 0x20 // C4 clear previously stored lines -#define PG_NEWSFLASH 0x40 // C5 box it and insert into normal video pict. -#define PG_SUBTITLE 0x80 // C6 box it and insert into normal video pict. -// my flags -#define PG_ACTIVE 0x100 // currently fetching this page - -#define ANY_SUB 0x3f7f // universal subpage number - -#endif -