/* tuxtxt_common.h * for license info see the other tuxtxt files */ #include #include #include #include #include #include #if TUXTXT_COMPRESS == 1 #include #endif #include #include tuxtxt_cache_struct tuxtxt_cache; static pthread_mutex_t tuxtxt_cache_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t tuxtxt_cache_biglock = PTHREAD_MUTEX_INITIALIZER; int tuxtxt_get_zipsize(int p,int sp) { tstCachedPage* pg = tuxtxt_cache.astCachetable[p][sp]; if (!pg) return 0; #if TUXTXT_COMPRESS == 1 return pg->ziplen; #elif TUXTXT_COMPRESS == 2 pthread_mutex_lock(&tuxtxt_cache_lock); int zipsize = 0,i,j; for (i = 0; i < 23*5; i++) for (j = 0; j < 8; j++) zipsize += pg->bitmask[i]>>j & 0x01; zipsize+=23*5;//bitmask pthread_mutex_unlock(&tuxtxt_cache_lock); return zipsize; #else return 23*40; #endif } void tuxtxt_compress_page(int p, int sp, unsigned char* buffer) { pthread_mutex_lock(&tuxtxt_cache_lock); tstCachedPage* pg = tuxtxt_cache.astCachetable[p][sp]; if (!pg) { printf("tuxtxt: trying to compress a not allocated page!!\n"); pthread_mutex_unlock(&tuxtxt_cache_lock); return; } #if TUXTXT_COMPRESS == 1 unsigned char pagecompressed[23*40]; uLongf comprlen = 23*40; if (compress2(pagecompressed,&comprlen,buffer,23*40,Z_BEST_SPEED) == Z_OK) { if (pg->pData) free(pg->pData);//realloc(pg->pData,j); realloc scheint nicht richtig zu funktionieren? pg->pData = malloc(comprlen); pg->ziplen = 0; if (pg->pData) { pg->ziplen = comprlen; memmove(pg->pData,pagecompressed,comprlen); } } #elif TUXTXT_COMPRESS == 2 int i,j=0; unsigned char cbuf[23*40]; memset(pg->bitmask,0,sizeof(pg->bitmask)); for (i = 0; i < 23*40; i++) { if (i && buffer[i] == buffer[i-1]) continue; pg->bitmask[i>>3] |= 0x80>>(i&0x07); cbuf[j++]=buffer[i]; } if (pg->pData) free(pg->pData);//realloc(pg->pData,j); realloc scheint nicht richtig zu funktionieren? pg->pData = (unsigned char*)malloc(j); if (pg->pData) { memmove(pg->pData,cbuf,j); } else memset(pg->bitmask,0,sizeof(pg->bitmask)); #else //if (pg->pData) memmove(pg->data,buffer,23*40); #endif pthread_mutex_unlock(&tuxtxt_cache_lock); } void tuxtxt_decompress_page(int p, int sp, unsigned char* buffer) { pthread_mutex_lock(&tuxtxt_cache_lock); tstCachedPage* pg = tuxtxt_cache.astCachetable[p][sp]; memset(buffer,' ',23*40); if (!pg) { printf("tuxtxt: trying to decompress a not allocated page!!\n"); pthread_mutex_unlock(&tuxtxt_cache_lock); return; } #if TUXTXT_COMPRESS == 1 if (pg->pData) { if (pg->ziplen) { uLongf comprlen = 23*40; uncompress(buffer,&comprlen,pg->pData,pg->ziplen); } #elif TUXTXT_COMPRESS == 2 if (pg->pData) { int i,j=0; char c=0x20; for (i = 0; i < 23*40; i++) { if (pg->bitmask[i>>3] & 0x80>>(i&0x07)) c = pg->pData[j++]; buffer[i] = c; } #else { memmove(buffer,pg->data,23*40); #endif } pthread_mutex_unlock(&tuxtxt_cache_lock); } void tuxtxt_next_dec(int *i) /* skip to next decimal */ { (*i)++; if ((*i & 0x0F) > 0x09) *i += 0x06; if ((*i & 0xF0) > 0x90) *i += 0x60; if (*i > 0x899) *i = 0x100; } void tuxtxt_prev_dec(int *i) /* counting down */ { (*i)--; if ((*i & 0x0F) > 0x09) *i -= 0x06; if ((*i & 0xF0) > 0x90) *i -= 0x60; if (*i < 0x100) *i = 0x899; } int tuxtxt_is_dec(int i) { return ((i & 0x00F) <= 9) && ((i & 0x0F0) <= 0x90); } int tuxtxt_next_hex(int i) /* return next existing non-decimal page number */ { int startpage = i; if (startpage < 0x100) startpage = 0x100; do { i++; if (i > 0x8FF) i = 0x100; if (i == startpage) break; } while ((tuxtxt_cache.subpagetable[i] == 0xFF) || tuxtxt_is_dec(i)); return i; } /* * TOP-Text * Info entnommen aus videotext-0.6.19991029, * Copyright (c) 1994-96 Martin Buck */ void tuxtxt_decode_btt() { /* basic top table */ int i, current, b1, b2, b3, b4; unsigned char btt[23*40] = {0}; if (tuxtxt_cache.subpagetable[0x1f0] == 0xff || 0 == tuxtxt_cache.astCachetable[0x1f0][tuxtxt_cache.subpagetable[0x1f0]]) /* not yet received */ return; tuxtxt_decompress_page(0x1f0,tuxtxt_cache.subpagetable[0x1f0],btt); if (btt[799] == ' ') /* not completely received or error */ return; current = 0x100; for (i = 0; i < 800; i++) { b1 = btt[i]; if (b1 == ' ') b1 = 0; else { b1 = dehamming[b1]; if (b1 == 0xFF) /* hamming error in btt */ { btt[799] = ' '; /* mark btt as not received */ return; } } tuxtxt_cache.basictop[current] = b1; tuxtxt_next_dec(¤t); } /* page linking table */ tuxtxt_cache.maxadippg = -1; /* rebuild table of adip pages */ for (i = 0; i < 10; i++) { b1 = dehamming[btt[800 + 8*i +0]]; if (b1 == 0xE) continue; /* unused */ else if (b1 == 0xF) break; /* end */ b4 = dehamming[btt[800 + 8*i +7]]; if (b4 != 2) /* only adip, ignore multipage (1) */ continue; b2 = dehamming[btt[800 + 8*i +1]]; b3 = dehamming[btt[800 + 8*i +2]]; if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF) { printf("TuxTxt \n", i); btt[799] = ' '; /* mark btt as not received */ return; } b1 = b1<<8 | b2<<4 | b3; /* page number */ tuxtxt_cache.adippg[++tuxtxt_cache.maxadippg] = b1; } #if TUXTXT_DEBUG printf("TuxTxt \n"); #endif tuxtxt_cache.bttok = 1; } void tuxtxt_decode_adip() /* additional information table */ { int i, p, j, b1, b2, b3, charfound; unsigned char padip[23*40]; for (i = 0; i <= tuxtxt_cache.maxadippg; i++) { p = tuxtxt_cache.adippg[i]; if (!p || tuxtxt_cache.subpagetable[p] == 0xff || 0 == tuxtxt_cache.astCachetable[p][tuxtxt_cache.subpagetable[p]]) /* not cached (avoid segfault) */ continue; tuxtxt_decompress_page(p,tuxtxt_cache.subpagetable[p],padip); for (j = 0; j < 44; j++) { b1 = dehamming[padip[20*j+0]]; if (b1 == 0xE) continue; /* unused */ if (b1 == 0xF) break; /* end */ b2 = dehamming[padip[20*j+1]]; b3 = dehamming[padip[20*j+2]]; if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF) { printf("TuxTxt \n", p, j, padip[20*j+0], padip[20*j+1], padip[20*j+2], b1, b2, b3 ); return; } if (b1>8 || b2>9 || b3>9) /* ignore extries with invalid or hex page numbers */ { continue; } b1 = b1<<8 | b2<<4 | b3; /* page number */ charfound = 0; /* flag: no printable char found */ for (b2 = 11; b2 >= 0; b2--) { b3 = deparity[padip[20*j + 8 + b2]]; if (b3 < ' ') b3 = ' '; if (b3 == ' ' && !charfound) tuxtxt_cache.adip[b1][b2] = '\0'; else { tuxtxt_cache.adip[b1][b2] = b3; charfound = 1; } } } /* next link j */ tuxtxt_cache.adippg[i] = 0; /* completely decoded: clear entry */ #if TUXTXT_DEBUG printf("TuxTxt \n", p); #endif } /* next adip page i */ while ((tuxtxt_cache.maxadippg >= 0) && !tuxtxt_cache.adippg[tuxtxt_cache.maxadippg]) /* and shrink table */ tuxtxt_cache.maxadippg--; } /****************************************************************************** * GetSubPage * ******************************************************************************/ int tuxtxt_GetSubPage(int page, int subpage, int offset) { int loop; for (loop = subpage + offset; loop != subpage; loop += offset) { if (loop < 0) loop = 0x79; else if (loop > 0x79) loop = 0; if (loop == subpage) break; if (tuxtxt_cache.astCachetable[page][loop]) { #if TUXTXT_DEBUG printf("TuxTxt \n", page, subpage); #endif return loop; } } #if TUXTXT_DEBUG printf("TuxTxt \n"); #endif return subpage; } /****************************************************************************** * clear_cache * ******************************************************************************/ void tuxtxt_clear_cache(void) { pthread_mutex_lock(&tuxtxt_cache_biglock); pthread_mutex_lock(&tuxtxt_cache_lock); int clear_page, clear_subpage, d26; tuxtxt_cache.maxadippg = -1; tuxtxt_cache.bttok = 0; tuxtxt_cache.cached_pages = 0; tuxtxt_cache.page_receiving = -1; tuxtxt_cache.vtxtpid = -1; memset(&tuxtxt_cache.subpagetable, 0xFF, sizeof(tuxtxt_cache.subpagetable)); memset(&tuxtxt_cache.basictop, 0, sizeof(tuxtxt_cache.basictop)); memset(&tuxtxt_cache.adip, 0, sizeof(tuxtxt_cache.adip)); memset(&tuxtxt_cache.flofpages, 0 , sizeof(tuxtxt_cache.flofpages)); memset(&tuxtxt_cache.timestring, 0x20, 8); unsigned char magazine; for (magazine = 1; magazine < 9; magazine++) { tuxtxt_cache.current_page [magazine] = -1; tuxtxt_cache.current_subpage [magazine] = -1; } for (clear_page = 0; clear_page < 0x900; clear_page++) for (clear_subpage = 0; clear_subpage < 0x80; clear_subpage++) if (tuxtxt_cache.astCachetable[clear_page][clear_subpage]) { tstPageinfo *p = &(tuxtxt_cache.astCachetable[clear_page][clear_subpage]->pageinfo); if (p->p24) free(p->p24); if (p->ext) { if (p->ext->p27) free(p->ext->p27); for (d26=0; d26 < 16; d26++) if (p->ext->p26[d26]) free(p->ext->p26[d26]); free(p->ext); } #if TUXTXT_COMPRESS >0 if (tuxtxt_cache.astCachetable[clear_page][clear_subpage]->pData) free(tuxtxt_cache.astCachetable[clear_page][clear_subpage]->pData); #endif free(tuxtxt_cache.astCachetable[clear_page][clear_subpage]); tuxtxt_cache.astCachetable[clear_page][clear_subpage] = 0; } for (clear_page = 0; clear_page < 9; clear_page++) { if (tuxtxt_cache.astP29[clear_page]) { if (tuxtxt_cache.astP29[clear_page]->p27) free(tuxtxt_cache.astP29[clear_page]->p27); for (d26=0; d26 < 16; d26++) if (tuxtxt_cache.astP29[clear_page]->p26[d26]) free(tuxtxt_cache.astP29[clear_page]->p26[d26]); free(tuxtxt_cache.astP29[clear_page]); tuxtxt_cache.astP29[clear_page] = 0; } tuxtxt_cache.current_page [clear_page] = -1; tuxtxt_cache.current_subpage [clear_page] = -1; } memset(&tuxtxt_cache.astCachetable, 0, sizeof(tuxtxt_cache.astCachetable)); memset(&tuxtxt_cache.astP29, 0, sizeof(tuxtxt_cache.astP29)); #if TUXTXT_DEBUG printf("TuxTxt cache cleared\n"); #endif pthread_mutex_unlock(&tuxtxt_cache_lock); pthread_mutex_unlock(&tuxtxt_cache_biglock); } /****************************************************************************** * init_demuxer * ******************************************************************************/ static cDemux * dmx = NULL; int tuxtxt_init_demuxer(int source = 0); int tuxtxt_init_demuxer(int source) { if(dmx == NULL) { dmx = new cDemux(source); dmx->Open(DMX_PES_CHANNEL, NULL, 2* 3008 * 62 /*64*1024*/); printf("TuxTxt: source demux %d\n", source); } #if TUXTXT_DEBUG printf("TuxTxt: initialized\n"); #endif /* init successfull */ return 1; } /****************************************************************************** * CacheThread support functions * ******************************************************************************/ void tuxtxt_decode_p2829(unsigned char *vtxt_row, tstExtData **ptExtData) { int bitsleft, colorindex; unsigned char *p; int t1 = deh24(&vtxt_row[7-4]); int t2 = deh24(&vtxt_row[10-4]); if (t1 < 0 || t2 < 0) { #if TUXTXT_DEBUG printf("TuxTxt \n"); #endif return; } if (!(*ptExtData)) (*ptExtData) = (tstExtData*)calloc(1, sizeof(tstExtData)); if (!(*ptExtData)) return; (*ptExtData)->p28Received = 1; (*ptExtData)->DefaultCharset = (t1>>7) & 0x7f; (*ptExtData)->SecondCharset = ((t1>>14) & 0x0f) | ((t2<<4) & 0x70); (*ptExtData)->LSP = !!(t2 & 0x08); (*ptExtData)->RSP = !!(t2 & 0x10); (*ptExtData)->SPL25 = !!(t2 & 0x20); (*ptExtData)->LSPColumns = (t2>>6) & 0x0f; bitsleft = 8; /* # of bits not evaluated in val */ t2 >>= 10; /* current data */ p = &vtxt_row[13-4]; /* pointer to next data triplet */ for (colorindex = 0; colorindex < 16; colorindex++) { if (bitsleft < 12) { t2 |= deh24(p) << bitsleft; if (t2 < 0) /* hamming error */ break; p += 3; bitsleft += 18; } (*ptExtData)->bgr[colorindex] = t2 & 0x0fff; bitsleft -= 12; t2 >>= 12; } if (t2 < 0 || bitsleft != 14) { #if TUXTXT_DEBUG printf("TuxTxt \n", t2, bitsleft); #endif (*ptExtData)->p28Received = 0; return; } (*ptExtData)->DefScreenColor = t2 & 0x1f; t2 >>= 5; (*ptExtData)->DefRowColor = t2 & 0x1f; (*ptExtData)->BlackBgSubst = !!(t2 & 0x20); t2 >>= 6; (*ptExtData)->ColorTableRemapping = t2 & 0x07; } void tuxtxt_erase_page(int magazine) { tstCachedPage* pg = tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]; if (pg) { memset(&(pg->pageinfo), 0, sizeof(tstPageinfo)); /* struct pageinfo */ memset(pg->p0, ' ', 24); #if TUXTXT_COMPRESS == 1 if (pg->pData) { free(pg->pData); pg->pData = NULL; } #elif TUXTXT_COMPRESS == 2 memset(pg->bitmask, 0, 23*5); #else memset(pg->data, ' ', 23*40); #endif } } void tuxtxt_clear_p26(tstExtData* extData) { pthread_mutex_lock(&tuxtxt_cache_lock); for(int i = 0; i < 16; ++i) { if(0 != extData->p26[i]) { memset(extData->p26[i], 0x00, 13 * 3); } } pthread_mutex_unlock(&tuxtxt_cache_lock); } void tuxtxt_allocate_cache(int magazine) { // Lock here as we have a possible race here with // tuxtxt_clear_cache(). We should not be allocating and // freeing at the same time. // *** this is probably worked around by tuxtxt_cacehe_biglock now *** --seife pthread_mutex_lock(&tuxtxt_cache_lock); /* check cachetable and allocate memory if needed */ if (tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]] == 0) { tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]] = (tstCachedPage*) malloc(sizeof(tstCachedPage)); if (tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]] ) { #if TUXTXT_COMPRESS >0 tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->pData = 0; #endif tuxtxt_erase_page(magazine); tuxtxt_cache.cached_pages++; } else // Be a little verbose in case a crash is going to happen. { printf("tuxtxt: memory allocation failed!!! expect a crash\n"); } } pthread_mutex_unlock(&tuxtxt_cache_lock); } /****************************************************************************** * CacheThread * ******************************************************************************/ static int stop_cache = 0; void *tuxtxt_CacheThread(void * /*arg*/) { const unsigned char rev_lut[32] = { 0x00,0x08,0x04,0x0c, /* upper nibble */ 0x02,0x0a,0x06,0x0e, 0x01,0x09,0x05,0x0d, 0x03,0x0b,0x07,0x0f, 0x00,0x80,0x40,0xc0, /* lower nibble */ 0x20,0xa0,0x60,0xe0, 0x10,0x90,0x50,0xd0, 0x30,0xb0,0x70,0xf0 }; unsigned char pes_packet[184*20]; unsigned char vtxt_row[42]; int line, byte/*, bit*/; int b1, b2, b3, b4; int packet_number; int doupdate=0; unsigned char magazine = 0xff; unsigned char pagedata[9][23*40]; tstPageinfo *pageinfo_thread; set_threadname("tuxtxt:cache"); printf("TuxTxt running thread...(%04x)\n",tuxtxt_cache.vtxtpid); tuxtxt_cache.receiving = 1; nice(3); while (!stop_cache) { /* check stopsignal */ pthread_testcancel(); if (!tuxtxt_cache.receiving) continue; /* read packet */ ssize_t readcnt = 0; readcnt = dmx->Read(pes_packet, sizeof (pes_packet), 1000); //if (readcnt != sizeof(pes_packet)) if ((readcnt <= 0) || (readcnt % 184)) { #if TUXTXT_DEBUG if(readcnt > 0) printf ("TuxTxt: readerror: %d\n", readcnt); #endif continue; } /* this "big hammer lock" is a hack: it avoids a crash if * tuxtxt_clear_cache() is called while the cache thread is in the * middle of the following loop, leading to tuxtxt_cache.current_page[] * etc. being set to -1 and tuxtxt_cache.astCachetable[] etc. being set * to NULL * it probably also avoids the possible race in tuxtxt_allocate_cache() */ pthread_mutex_lock(&tuxtxt_cache_biglock); /* analyze it */ for (line = 0; line < readcnt/0x2e /*4*/; line++) { unsigned char *vtx_rowbyte = &pes_packet[line*0x2e]; if ((vtx_rowbyte[1] == 0x2C) && (vtx_rowbyte[0] == 0x02 || vtx_rowbyte[0] == 0x03)) { /* clear rowbuffer */ /* convert row from lsb to msb (begin with magazin number) */ for (byte = 4; byte < 46; byte++) { unsigned char upper,lower; upper = (vtx_rowbyte[byte] >> 4) & 0xf; lower = vtx_rowbyte[byte] & 0xf; vtxt_row[byte-4] = (rev_lut[upper]) | (rev_lut[lower+16]); } /* get packet number */ b1 = dehamming[vtxt_row[0]]; b2 = dehamming[vtxt_row[1]]; if (b1 == 0xFF || b2 == 0xFF) { #if TUXTXT_DEBUG printf("TuxTxt \n"); #endif continue; } b1 &= 8; packet_number = b1>>3 | b2<<1; /* get magazine number */ magazine = dehamming[vtxt_row[0]] & 7; if (!magazine) magazine = 8; if (packet_number == 0 && tuxtxt_cache.current_page[magazine] != -1 && tuxtxt_cache.current_subpage[magazine] != -1) tuxtxt_compress_page(tuxtxt_cache.current_page[magazine],tuxtxt_cache.current_subpage[magazine],pagedata[magazine]); //printf("********************** receiving packet %d page %03x subpage %02x\n",packet_number, tuxtxt_cache.current_page[magazine],tuxtxt_cache.current_subpage[magazine]);//FIXME /* analyze row */ if (packet_number == 0) { /* get pagenumber */ b2 = dehamming[vtxt_row[3]]; b3 = dehamming[vtxt_row[2]]; if (b2 == 0xFF || b3 == 0xFF) { tuxtxt_cache.current_page[magazine] = tuxtxt_cache.page_receiving = -1; #if TUXTXT_DEBUG printf("TuxTxt \n"); #endif continue; } tuxtxt_cache.current_page[magazine] = tuxtxt_cache.page_receiving = magazine<<8 | b2<<4 | b3; if (b2 == 0x0f && b3 == 0x0f) { tuxtxt_cache.current_subpage[magazine] = -1; /* ?ff: ignore data transmissions */ continue; } /* get subpagenumber */ b1 = dehamming[vtxt_row[7]]; b2 = dehamming[vtxt_row[6]]; b3 = dehamming[vtxt_row[5]]; b4 = dehamming[vtxt_row[4]]; if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF || b4 == 0xFF) { #if TUXTXT_DEBUG printf("TuxTxt \n"); #endif tuxtxt_cache.current_subpage[magazine] = -1; continue; } #if 0 /* ? */ b1 &= 3; #endif b3 &= 7; if (tuxtxt_is_dec(tuxtxt_cache.page_receiving)) /* ignore other subpage bits for hex pages */ { #if 0 /* ? */ if (b1 != 0 || b2 != 0) { #if TUXTXT_DEBUG printf("TuxTxt \n", tuxtxt_cache.page_receiving, b1, b2, b3, b4); #endif tuxtxt_cache.current_subpage[magazine] = -1; continue; } else #endif tuxtxt_cache.current_subpage[magazine] = b3<<4 | b4; } else tuxtxt_cache.current_subpage[magazine] = b4; /* max 16 subpages for hex pages */ /* store current subpage for this page */ tuxtxt_cache.subpagetable[tuxtxt_cache.current_page[magazine]] = tuxtxt_cache.current_subpage[magazine]; tuxtxt_allocate_cache(magazine); tuxtxt_decompress_page(tuxtxt_cache.current_page[magazine],tuxtxt_cache.current_subpage[magazine],pagedata[magazine]); pageinfo_thread = &(tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->pageinfo); if ((tuxtxt_cache.page_receiving & 0xff) == 0xfe) /* ?fe: magazine organization table (MOT) */ pageinfo_thread->function = FUNC_MOT; /* check controlbits */ if (dehamming[vtxt_row[5]] & 8) /* C4 -> erase page */ { #if TUXTXT_COMPRESS == 1 tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->ziplen = 0; #elif TUXTXT_COMPRESS == 2 memset(tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->bitmask, 0, 23*5); #else memset(tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->data, ' ', 23*40); #endif memset(pagedata[magazine],' ', 23*40); } if (dehamming[vtxt_row[9]] & 8) /* C8 -> update page */ doupdate = tuxtxt_cache.page_receiving; pageinfo_thread->boxed = !!(dehamming[vtxt_row[7]] & 0x0c); /* get country control bits */ b1 = dehamming[vtxt_row[9]]; if (b1 == 0xFF) { #if TUXTXT_DEBUG printf("TuxTxt \n"); #endif } else { //pageinfo_thread->nationalvalid = 1;// FIXME without full eval some is broken pageinfo_thread->national = rev_lut[b1] & 0x07; //printf("TuxTxt 0: b1=%x\n", rev_lut[b1]); } /* check parity, copy line 0 to cache (start and end 8 bytes are not needed and used otherwise) */ unsigned char *p = tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->p0; for (byte = 10; byte < 42-8; byte++) *p++ = deparity[vtxt_row[byte]]; if (!tuxtxt_is_dec(tuxtxt_cache.page_receiving)) continue; /* valid hex page number: just copy headline, ignore timestring */ /* copy timestring */ p = tuxtxt_cache.timestring; for (; byte < 42; byte++) *p++ = deparity[vtxt_row[byte]]; } /* (packet_number == 0) */ else if (packet_number == 29 && dehamming[vtxt_row[2]]== 0) /* packet 29/0 replaces 28/0 for a whole magazine */ { tuxtxt_decode_p2829(vtxt_row, &(tuxtxt_cache.astP29[magazine])); } else if (tuxtxt_cache.current_page[magazine] != -1 && tuxtxt_cache.current_subpage[magazine] != -1) /* packet>0, 0 has been correctly received, buffer allocated */ { pageinfo_thread = &(tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->pageinfo); /* pointer to current info struct */ if (packet_number <= 25) { unsigned char *p = NULL; if (packet_number < 24) p = pagedata[magazine] + 40*(packet_number-1); else { if (!(pageinfo_thread->p24)) pageinfo_thread->p24 = (unsigned char*) calloc(2, 40); if (pageinfo_thread->p24) p = pageinfo_thread->p24 + (packet_number - 24) * 40; } if (p) { if (tuxtxt_is_dec(tuxtxt_cache.current_page[magazine])) for (byte = 2; byte < 42; byte++) *p++ = deparity[vtxt_row[byte]]; /* check/remove parity bit */ else if ((tuxtxt_cache.current_page[magazine] & 0xff) == 0xfe) for (byte = 2; byte < 42; byte++) *p++ = dehamming[vtxt_row[byte]]; /* decode hamming 8/4 */ else /* other hex page: no parity check, just copy */ memmove(p, &vtxt_row[2], 40); } } else if (packet_number == 27) { int descode = dehamming[vtxt_row[2]]; /* designation code (0..15) */ if (descode == 0xff) { #if TUXTXT_DEBUG printf("TuxTxt \n"); #endif continue; } if (descode == 0) // reading FLOF-Pagelinks { b1 = dehamming[vtxt_row[0]]; if (b1 != 0xff) { b1 &= 7; for (byte = 0; byte < FLOFSIZE; byte++) { b2 = dehamming[vtxt_row[4+byte*6]]; b3 = dehamming[vtxt_row[3+byte*6]]; if (b2 != 0xff && b3 != 0xff) { b4 = ((b1 ^ (dehamming[vtxt_row[8+byte*6]]>>1)) & 6) | ((b1 ^ (dehamming[vtxt_row[6+byte*6]]>>3)) & 1); if (b4 == 0) b4 = 8; if (b2 <= 9 && b3 <= 9) tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine] ][byte] = b4<<8 | b2<<4 | b3; } } /* copy last 2 links to adip for TOP-Index */ if (pageinfo_thread->p24) /* packet 24 received */ { int a, a1, e=39, l=3; char *p = (char*) pageinfo_thread->p24; do { for (; l >= 2 && 0 == tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l]; l--) ; /* find used linkindex */ for (; e >= 1 && !isalnum(p[e]); e--) ; /* find end */ for (a = a1 = e - 1; a >= 0 && p[a] >= ' '; a--) /* find start */ if (p[a] > ' ') a1 = a; /* first non-space */ if (a >= 0 && l >= 2) { strncpy((char *) tuxtxt_cache.adip[tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l]], &p[a1], 12); if (e-a1 < 11) tuxtxt_cache.adip[tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l]][e-a1+1] = '\0'; #if 0 //TUXTXT_DEBUG printf(" %03x/%02x %d %d %d %d %03x %s\n", tuxtxt_cache.current_page[magazine], tuxtxt_cache.current_subpage[magazine], l, a, a1, e, tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l], tuxtxt_cache.adip[tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l]] ); #endif } e = a - 1; l--; } while (l >= 2); } } } else if (descode == 4) /* level 2.5 links (ignore level 3.5 links of /4 and /5) */ { int i; tstp27 *p; if (!pageinfo_thread->ext) pageinfo_thread->ext = (tstExtData*) calloc(1, sizeof(tstExtData)); if (!pageinfo_thread->ext) continue; if (!(pageinfo_thread->ext->p27)) pageinfo_thread->ext->p27 = (tstp27*) calloc(4, sizeof(tstp27)); if (!(pageinfo_thread->ext->p27)) continue; p = pageinfo_thread->ext->p27; for (i = 0; i < 4; i++) { int d1 = deh24(&vtxt_row[6*i + 3]); int d2 = deh24(&vtxt_row[6*i + 6]); if (d1 < 0 || d2 < 0) { #if TUXTXT_DEBUG printf("TuxTxt \n"); #endif continue; } p->local = i & 0x01; p->drcs = !!(i & 0x02); p->l25 = !!(d1 & 0x04); p->l35 = !!(d1 & 0x08); p->page = (((d1 & 0x000003c0) >> 6) | ((d1 & 0x0003c000) >> (14-4)) | ((d1 & 0x00003800) >> (11-8))) ^ (dehamming[vtxt_row[0]] << 8); if (p->page < 0x100) p->page += 0x800; p->subpage = d2 >> 2; if ((p->page & 0xff) == 0xff) p->page = 0; else if (p->page > 0x899) { // workaround for crash on RTL printf("[TuxTxt] page > 0x899 ... ignore!!!!!!\n"); continue; } else if (tuxtxt_cache.astCachetable[p->page][0]) /* link valid && linked page cached */ { tstPageinfo *pageinfo_link = &(tuxtxt_cache.astCachetable[p->page][0]->pageinfo); if (p->local) pageinfo_link->function = p->drcs ? FUNC_DRCS : FUNC_POP; else pageinfo_link->function = p->drcs ? FUNC_GDRCS : FUNC_GPOP; } p++; /* */ } } } else if (packet_number == 26) { int descode = dehamming[vtxt_row[2]]; /* designation code (0..15) */ if (descode == 0xff) { #if TUXTXT_DEBUG printf("TuxTxt \n"); #endif continue; } if (!pageinfo_thread->ext) pageinfo_thread->ext = (tstExtData*) calloc(1, sizeof(tstExtData)); if (!pageinfo_thread->ext) continue; if (!(pageinfo_thread->ext->p26[descode])) pageinfo_thread->ext->p26[descode] = (unsigned char*) malloc(13 * 3); if (pageinfo_thread->ext->p26[descode]) memmove(pageinfo_thread->ext->p26[descode], &vtxt_row[3], 13 * 3); #if 0//TUXTXT_DEBUG int i, t, m; printf("P%03x/%02x %02d/%x", tuxtxt_cache.current_page[magazine], tuxtxt_cache.current_subpage[magazine], packet_number, dehamming[vtxt_row[2]]); for (i=7-4; i <= 45-4; i+=3) /* dump all triplets */ { t = deh24(&vtxt_row[i]); /* mode/adr/data */ m = (t>>6) & 0x1f; printf(" M%02xA%02xD%03x", m, t & 0x3f, (t>>11) & 0x7f); if (m == 0x1f) /* terminator */ break; } putchar('\n'); #endif } else if (packet_number == 28) { int descode = dehamming[vtxt_row[2]]; /* designation code (0..15) */ if (descode == 0xff) { #if TUXTXT_DEBUG printf("TuxTxt \n"); #endif continue; } if (descode != 2) { int t1 = deh24(&vtxt_row[7-4]); pageinfo_thread->function = t1 & 0x0f; if (!pageinfo_thread->nationalvalid) { //printf("TuxTxt 28: t1=%x\n", t1>>4); // pageinfo_thread->nationalvalid = 1; // FIXME without full eval some is broken pageinfo_thread->national = (t1>>4) & 0x07; } } switch (descode) /* designation code */ { case 0: /* basic level 1 page */ { tuxtxt_decode_p2829(vtxt_row, &(pageinfo_thread->ext)); break; } case 1: /* G0/G1 designation for older decoders, level 3.5: DCLUT4/16, colors for multicolored bitmaps */ { break; /* ignore */ } case 2: /* page key */ { break; /* ignore */ } case 3: /* types of PTUs in DRCS */ { break; /* TODO */ } case 4: /* CLUTs 0/1, only level 3.5 */ { break; /* ignore */ } default: { break; /* invalid, ignore */ } } /* switch designation code */ } else if (packet_number == 30) { #if 0//TUXTXT_DEBUG int i; printf("p%03x/%02x %02d/%x ", tuxtxt_cache.current_page[magazine], tuxtxt_cache.current_subpage[magazine], packet_number, dehamming[vtxt_row[2]]); for (i=26-4; i <= 45-4; i++) /* station ID */ putchar(deparity[vtxt_row[i]]); putchar('\n'); #endif } } /* set update flag */ if (tuxtxt_cache.current_page[magazine] == tuxtxt_cache.page && tuxtxt_cache.current_subpage[magazine] != -1) { tuxtxt_compress_page(tuxtxt_cache.current_page[magazine],tuxtxt_cache.current_subpage[magazine],pagedata[magazine]); tuxtxt_cache.pageupdate = 1+(doupdate == tuxtxt_cache.page ? 1: 0); doupdate=0; if (!tuxtxt_cache.zap_subpage_manual) tuxtxt_cache.subpage = tuxtxt_cache.current_subpage[magazine]; } } #if 0 else printf("line %d row %X %X, continue\n", line, vtx_rowbyte[0], vtx_rowbyte[1]); #endif } pthread_mutex_unlock(&tuxtxt_cache_biglock); } pthread_exit(NULL); } /****************************************************************************** * start_thread * ******************************************************************************/ int tuxtxt_start_thread(int source = 0); int tuxtxt_start_thread(int source) { if (tuxtxt_cache.vtxtpid == -1) return 0; tuxtxt_cache.thread_starting = 1; tuxtxt_init_demuxer(source); dmx->pesFilter(tuxtxt_cache.vtxtpid); dmx->Start(); stop_cache = 0; /* create decode-thread */ if (pthread_create(&tuxtxt_cache.thread_id, NULL, tuxtxt_CacheThread, NULL) != 0) { perror("TuxTxt "); tuxtxt_cache.thread_starting = 0; return 0; } #if 1//TUXTXT_DEBUG printf("TuxTxt service started %x\n", tuxtxt_cache.vtxtpid); #endif tuxtxt_cache.receiving = 1; tuxtxt_cache.thread_starting = 0; return 1; } /****************************************************************************** * stop_thread * ******************************************************************************/ int tuxtxt_stop_thread() { /* stop decode-thread */ if (tuxtxt_cache.thread_id != 0) { #if 0 if (pthread_cancel(tuxtxt_cache.thread_id) != 0) { perror("TuxTxt "); return 0; } #endif stop_cache = 1; if (pthread_join(tuxtxt_cache.thread_id, &tuxtxt_cache.thread_result) != 0) { perror("TuxTxt "); return 0; } tuxtxt_cache.thread_id = 0; } if(dmx) { dmx->Stop(); delete dmx; dmx = NULL; } #if 1//TUXTXT_DEBUG printf("TuxTxt stopped service %x\n", tuxtxt_cache.vtxtpid); #endif return 1; }