[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / cores / VideoPlayer / VideoPlayerTeletext.cpp
blob4e82c2d8c22aa6a070563e04e36093ad0f7d447d
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "VideoPlayerTeletext.h"
11 #include "DVDStreamInfo.h"
12 #include "cores/VideoPlayer/Interface/DemuxPacket.h"
13 #include "cores/VideoPlayer/Interface/TimingConstants.h"
14 #include "utils/log.h"
16 #include <mutex>
18 using namespace std::chrono_literals;
20 const uint8_t rev_lut[32] =
22 0x00,0x08,0x04,0x0c, /* upper nibble */
23 0x02,0x0a,0x06,0x0e,
24 0x01,0x09,0x05,0x0d,
25 0x03,0x0b,0x07,0x0f,
26 0x00,0x80,0x40,0xc0, /* lower nibble */
27 0x20,0xa0,0x60,0xe0,
28 0x10,0x90,0x50,0xd0,
29 0x30,0xb0,0x70,0xf0
32 void CDVDTeletextTools::NextDec(int *i) /* skip to next decimal */
34 (*i)++;
36 if ((*i & 0x0F) > 0x09)
37 *i += 0x06;
39 if ((*i & 0xF0) > 0x90)
40 *i += 0x60;
42 if (*i > 0x899)
43 *i = 0x100;
46 void CDVDTeletextTools::PrevDec(int *i) /* counting down */
48 (*i)--;
50 if ((*i & 0x0F) > 0x09)
51 *i -= 0x06;
53 if ((*i & 0xF0) > 0x90)
54 *i -= 0x60;
56 if (*i < 0x100)
57 *i = 0x899;
60 /* print hex-number into string, s points to last digit, caller has to provide enough space, no termination */
61 void CDVDTeletextTools::Hex2Str(char *s, unsigned int n)
63 do {
64 char c = (n & 0xF);
65 *s-- = number2char(c);
66 n >>= 4;
67 } while (n);
70 signed int CDVDTeletextTools::deh24(unsigned char *p)
72 int e = hamm24par[0][p[0]]
73 ^ hamm24par[1][p[1]]
74 ^ hamm24par[2][p[2]];
76 int x = hamm24val[p[0]]
77 + (p[1] & 127) * 16
78 + (p[2] & 127) * 2048;
80 return (x ^ hamm24cor[e]) | hamm24err[e];
84 CDVDTeletextData::CDVDTeletextData(CProcessInfo &processInfo)
85 : CThread("DVDTeletextData")
86 , IDVDStreamPlayer(processInfo)
87 , m_messageQueue("teletext")
89 m_speed = DVD_PLAYSPEED_NORMAL;
91 m_messageQueue.SetMaxDataSize(40 * 256 * 1024);
93 /* Initialize Data structures */
94 memset(&m_TXTCache->astCachetable, 0, sizeof(m_TXTCache->astCachetable));
95 memset(&m_TXTCache->astP29, 0, sizeof(m_TXTCache->astP29));
96 ResetTeletextCache();
99 CDVDTeletextData::~CDVDTeletextData()
101 StopThread();
102 ResetTeletextCache();
105 bool CDVDTeletextData::CheckStream(CDVDStreamInfo &hints)
107 if (hints.codec == AV_CODEC_ID_DVB_TELETEXT)
108 return true;
110 return false;
113 bool CDVDTeletextData::OpenStream(CDVDStreamInfo hints)
115 CloseStream(true);
117 m_messageQueue.Init();
119 if (hints.codec == AV_CODEC_ID_DVB_TELETEXT)
121 CLog::Log(LOGINFO, "Creating teletext data thread");
122 Create();
123 return true;
126 return false;
129 void CDVDTeletextData::CloseStream(bool bWaitForBuffers)
131 m_messageQueue.Abort();
133 // wait for decode_video thread to end
134 CLog::Log(LOGINFO, "waiting for teletext data thread to exit");
136 StopThread(); // will set this->m_bStop to true
138 m_messageQueue.End();
139 ResetTeletextCache();
143 void CDVDTeletextData::ResetTeletextCache()
145 std::unique_lock<CCriticalSection> lock(m_TXTCache->m_critSection);
147 /* Reset Data structures */
148 for (auto& pages : m_TXTCache->astCachetable)
150 for (TextCachedPage_t*& page : pages)
152 if (page)
154 TextPageinfo_t *p = &(page->pageinfo);
155 if (p->p24)
156 free(p->p24);
158 if (p->ext)
160 if (p->ext->p27)
161 free(p->ext->p27);
163 for (unsigned char* const d26 : p->ext->p26)
165 if (d26)
166 free(d26);
168 free(p->ext);
170 delete page;
171 page = 0;
176 for (int i = 0; i < 9; i++)
178 if (m_TXTCache->astP29[i])
180 if (m_TXTCache->astP29[i]->p27)
181 free(m_TXTCache->astP29[i]->p27);
183 for (unsigned char* const d26 : m_TXTCache->astP29[i]->p26)
185 if (d26)
186 free(d26);
188 free(m_TXTCache->astP29[i]);
189 m_TXTCache->astP29[i] = 0;
191 m_TXTCache->CurrentPage[i] = -1;
192 m_TXTCache->CurrentSubPage[i] = -1;
195 memset(&m_TXTCache->SubPageTable, 0xFF, sizeof(m_TXTCache->SubPageTable));
196 memset(&m_TXTCache->astP29, 0, sizeof(m_TXTCache->astP29));
197 memset(&m_TXTCache->BasicTop, 0, sizeof(m_TXTCache->BasicTop));
198 memset(&m_TXTCache->ADIPTable, 0, sizeof(m_TXTCache->ADIPTable));
199 memset(&m_TXTCache->FlofPages, 0, sizeof(m_TXTCache->FlofPages));
200 memset(&m_TXTCache->SubtitlePages, 0, sizeof(m_TXTCache->SubtitlePages));
201 memset(&m_TXTCache->astCachetable, 0, sizeof(m_TXTCache->astCachetable));
202 memset(&m_TXTCache->TimeString, 0x20, 8);
204 m_TXTCache->NationalSubset = NAT_DEFAULT;/* default */
205 m_TXTCache->NationalSubsetSecondary = NAT_DEFAULT;
206 m_TXTCache->ZapSubpageManual = false;
207 m_TXTCache->PageUpdate = false;
208 m_TXTCache->ADIP_PgMax = -1;
209 m_TXTCache->BTTok = false;
210 m_TXTCache->CachedPages = 0;
211 m_TXTCache->PageReceiving = -1;
212 m_TXTCache->Page = 0x100;
213 m_TXTCache->SubPage = m_TXTCache->SubPageTable[m_TXTCache->Page];
214 m_TXTCache->line30 = "";
215 if (m_TXTCache->SubPage == 0xff)
216 m_TXTCache->SubPage = 0;
219 void CDVDTeletextData::Process()
221 int b1, b2, b3, b4;
222 int packet_number;
223 TextPageinfo_t *pageinfo_thread;
224 unsigned char vtxt_row[42];
225 unsigned char pagedata[9][23*40];
226 unsigned char magazine = 0xff;
227 // int doupdate = 0;
229 CLog::Log(LOGINFO, "running thread: CDVDTeletextData");
231 while (!m_bStop)
233 std::shared_ptr<CDVDMsg> pMsg;
234 int iPriority = (m_speed == DVD_PLAYSPEED_PAUSE) ? 1 : 0;
235 MsgQueueReturnCode ret = m_messageQueue.Get(pMsg, 2s, iPriority);
237 if (ret == MSGQ_TIMEOUT)
239 /* Timeout for Teletext is not a bad thing, so we continue without error */
240 continue;
243 if (MSGQ_IS_ERROR(ret))
245 if (!m_messageQueue.ReceivedAbortRequest())
246 CLog::Log(LOGERROR, "MSGQ_IS_ERROR returned true ({})", ret);
248 break;
251 if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET))
253 std::unique_lock<CCriticalSection> lock(m_TXTCache->m_critSection);
255 DemuxPacket* pPacket = std::static_pointer_cast<CDVDMsgDemuxerPacket>(pMsg)->GetPacket();
256 uint8_t *Datai = pPacket->pData;
257 int rows = (pPacket->iSize - 1) / 46;
259 /* Is it a ITU-R System B Teletext stream in acc. to EN 300 472 */
260 if (Datai[0] >= 0x10 && Datai[0] <= 0x1F) /* Check we have a valid data identifier */
262 /* Go thru the pages stored inside this frame */
263 for (int row=0; row < rows; row++)
265 uint8_t *vtx_rowbyte = &Datai[(row*46)+1];
267 /* Check for valid data_unit_id */
268 if ((vtx_rowbyte[0] == 0x02 || vtx_rowbyte[0] == 0x03) && (vtx_rowbyte[1] == 0x2C))
270 /* clear rowbuffer */
271 /* convert row from lsb to msb (begin with magazine number) */
272 for (int i = 4; i < 46; i++)
274 uint8_t upper = (vtx_rowbyte[i] >> 4) & 0xf;
275 uint8_t lower = vtx_rowbyte[i] & 0xf;
276 vtxt_row[i-4] = (rev_lut[upper]) | (rev_lut[lower+16]);
279 /* get packet number */
280 b1 = dehamming[vtxt_row[0]];
281 b2 = dehamming[vtxt_row[1]];
283 if (b1 == 0xFF || b2 == 0xFF)
284 continue;
286 b1 &= 8;
288 /* get packet and magazine number */
289 packet_number = b1>>3 | b2<<1;
290 magazine = dehamming[vtxt_row[0]] & 7;
291 if (!magazine) magazine = 8;
293 if (packet_number == 0 && m_TXTCache->CurrentPage[magazine] != -1 && m_TXTCache->CurrentSubPage[magazine] != -1)
294 SavePage(m_TXTCache->CurrentPage[magazine], m_TXTCache->CurrentSubPage[magazine], pagedata[magazine]);
296 /* analyze row */
297 if (packet_number == 0)
299 /* get pagenumber */
300 b2 = dehamming[vtxt_row[3]];
301 b3 = dehamming[vtxt_row[2]];
303 if (b2 == 0xFF || b3 == 0xFF)
305 m_TXTCache->CurrentPage[magazine] = m_TXTCache->PageReceiving = -1;
306 continue;
309 m_TXTCache->CurrentPage[magazine] = m_TXTCache->PageReceiving = magazine<<8 | b2<<4 | b3;
311 if (b2 == 0x0f && b3 == 0x0f)
313 m_TXTCache->CurrentSubPage[magazine] = -1; /* ?ff: ignore data transmissions */
314 continue;
317 /* get subpagenumber */
318 b1 = dehamming[vtxt_row[7]];
319 b2 = dehamming[vtxt_row[6]];
320 b3 = dehamming[vtxt_row[5]];
321 b4 = dehamming[vtxt_row[4]];
323 if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF || b4 == 0xFF)
325 m_TXTCache->CurrentSubPage[magazine] = -1;
326 continue;
329 b1 &= 3;
330 b3 &= 7;
332 if (IsDec(m_TXTCache->PageReceiving)) /* ignore other subpage bits for hex pages */
333 m_TXTCache->CurrentSubPage[magazine] = b3<<4 | b4;
334 else
335 m_TXTCache->CurrentSubPage[magazine] = b4; /* max 16 subpages for hex pages */
337 /* store current subpage for this page */
338 m_TXTCache->SubPageTable[m_TXTCache->CurrentPage[magazine]] = m_TXTCache->CurrentSubPage[magazine];
340 AllocateCache(magazine);
341 LoadPage(m_TXTCache->CurrentPage[magazine], m_TXTCache->CurrentSubPage[magazine], pagedata[magazine]);
342 pageinfo_thread = &(m_TXTCache->astCachetable[m_TXTCache->CurrentPage[magazine]][m_TXTCache->CurrentSubPage[magazine]]->pageinfo);
343 if (!pageinfo_thread)
344 continue;
346 if ((m_TXTCache->PageReceiving & 0xff) == 0xfe) /* ?fe: magazine organization table (MOT) */
347 pageinfo_thread->function = FUNC_MOT;
349 /* check controlbits */
350 if (dehamming[vtxt_row[5]] & 8) /* C4 -> erase page */
352 memset(m_TXTCache->astCachetable[m_TXTCache->CurrentPage[magazine]][m_TXTCache->CurrentSubPage[magazine]]->data, ' ', 23*40);
353 memset(pagedata[magazine],' ', 23*40);
355 // if (dehamming[vtxt_row[9]] & 8) /* C8 -> update page */
356 // doupdate = m_TXTCache->PageReceiving;
358 pageinfo_thread->boxed = !!(dehamming[vtxt_row[7]] & 0x0c);
360 /* get country control bits */
361 b1 = dehamming[vtxt_row[9]];
362 if (b1 != 0xFF)
364 int countryCode = rev_lut[b1] & 0x07;
365 if (countryCode != NAT_DEFAULT)
367 pageinfo_thread->nationalvalid = 1;
368 pageinfo_thread->national = countryCode;
372 if (dehamming[vtxt_row[7]] & 0x08)// subtitle page
374 int i = 0, found = -1, use = -1;
375 for (; i < 8; i++)
377 if (use == -1 && !m_TXTCache->SubtitlePages[i].page)
378 use = i;
379 else if (m_TXTCache->SubtitlePages[i].page == m_TXTCache->PageReceiving)
381 found = i;
382 use = i;
383 break;
386 if (found == -1 && use != -1)
387 m_TXTCache->SubtitlePages[use].page = m_TXTCache->PageReceiving;
388 if (use != -1)
389 m_TXTCache->SubtitlePages[use].language = CountryConversionTable[pageinfo_thread->national];
392 /* check parity, copy line 0 to cache (start and end 8 bytes are not needed and used otherwise) */
393 unsigned char *p = m_TXTCache->astCachetable[m_TXTCache->CurrentPage[magazine]][m_TXTCache->CurrentSubPage[magazine]]->p0;
394 for (int i = 10; i < 42-8; i++)
395 *p++ = deparity[vtxt_row[i]];
397 if (!IsDec(m_TXTCache->PageReceiving))
398 continue; /* valid hex page number: just copy headline, ignore TimeString */
400 /* copy TimeString */
401 p = m_TXTCache->TimeString;
402 for (int i = 42-8; i < 42; i++)
403 *p++ = deparity[vtxt_row[i]];
405 else if (packet_number == 29 && dehamming[vtxt_row[2]]== 0) /* packet 29/0 replaces 28/0 for a whole magazine */
407 Decode_p2829(vtxt_row, &(m_TXTCache->astP29[magazine]));
409 else if (m_TXTCache->CurrentPage[magazine] != -1 && m_TXTCache->CurrentSubPage[magazine] != -1)
410 /* packet>0, 0 has been correctly received, buffer allocated */
412 pageinfo_thread = &(m_TXTCache->astCachetable[m_TXTCache->CurrentPage[magazine]][m_TXTCache->CurrentSubPage[magazine]]->pageinfo);
413 if (!pageinfo_thread)
414 continue;
416 /* pointer to current info struct */
417 if (packet_number <= 25)
419 unsigned char *p = NULL;
420 if (packet_number < 24)
422 p = pagedata[magazine] + 40*(packet_number-1);
424 else
426 if (!(pageinfo_thread->p24))
427 pageinfo_thread->p24 = (unsigned char*) calloc(2, 40);
428 if (pageinfo_thread->p24)
429 p = pageinfo_thread->p24 + (packet_number - 24) * 40;
431 if (p)
433 if (IsDec(m_TXTCache->CurrentPage[magazine]))
435 for (int i = 2; i < 42; i++)
437 *p++ = vtxt_row[i] & 0x7f; /* allow values with parity errors as some channels don't care :( */
440 else if ((m_TXTCache->CurrentPage[magazine] & 0xff) == 0xfe)
442 for (int i = 2; i < 42; i++)
444 *p++ = dehamming[vtxt_row[i]]; /* decode hamming 8/4 */
447 else /* other hex page: no parity check, just copy */
448 memcpy(p, &vtxt_row[2], 40);
451 else if (packet_number == 27)
453 int descode = dehamming[vtxt_row[2]]; /* designation code (0..15) */
454 if (descode == 0xff)
455 continue;
457 if (descode == 0) // reading FLOF-Pagelinks
459 b1 = dehamming[vtxt_row[0]];
460 if (b1 != 0xff)
462 b1 &= 7;
464 for (int i = 0; i < FLOFSIZE; i++)
466 b2 = dehamming[vtxt_row[4+i*6]];
467 b3 = dehamming[vtxt_row[3+i*6]];
469 if (b2 != 0xff && b3 != 0xff)
471 b4 = ((b1 ^ (dehamming[vtxt_row[8+i*6]]>>1)) & 6) | ((b1 ^ (dehamming[vtxt_row[6+i*6]]>>3)) & 1);
472 if (b4 == 0)
473 b4 = 8;
474 if (b2 <= 9 && b3 <= 9)
475 m_TXTCache->FlofPages[m_TXTCache->CurrentPage[magazine] ][i] = b4<<8 | b2<<4 | b3;
479 /* copy last 2 links to ADIPTable for TOP-Index */
480 if (pageinfo_thread->p24) /* packet 24 received */
482 int a, a1, e=39, l=3;
483 unsigned char *p = pageinfo_thread->p24;
486 for (;
487 l >= 2 && 0 == m_TXTCache->FlofPages[m_TXTCache->CurrentPage[magazine]][l];
488 l--)
489 ; /* find used linkindex */
490 for (;
491 e >= 1 && !isalnum(p[e]);
492 e--)
493 ; /* find end */
494 for (a = a1 = e - 1;
495 a >= 0 && p[a] >= ' ';
496 a--) /* find start */
497 if (p[a] > ' ')
498 a1 = a; /* first non-space */
499 if (a >= 0 && l >= 2)
501 strncpy(m_TXTCache->ADIPTable[m_TXTCache->FlofPages[m_TXTCache->CurrentPage[magazine]][l]], (const char*) &p[a1], 12);
502 if (e-a1 < 11)
503 m_TXTCache->ADIPTable[m_TXTCache->FlofPages[m_TXTCache->CurrentPage[magazine]][l]][e-a1+1] = '\0';
505 e = a - 1;
506 l--;
507 } while (l >= 2);
511 else if (descode == 4) /* level 2.5 links (ignore level 3.5 links of /4 and /5) */
513 int i;
514 Textp27_t *p;
516 if (!pageinfo_thread->ext)
517 pageinfo_thread->ext = (TextExtData_t*) calloc(1, sizeof(TextExtData_t));
518 if (!pageinfo_thread->ext)
519 continue;
520 if (!(pageinfo_thread->ext->p27))
521 pageinfo_thread->ext->p27 = (Textp27_t*) calloc(4, sizeof(Textp27_t));
522 if (!(pageinfo_thread->ext->p27))
523 continue;
524 p = pageinfo_thread->ext->p27;
525 for (i = 0; i < 4; i++)
527 int d1 = CDVDTeletextTools::deh24(&vtxt_row[6*i + 3]);
528 int d2 = CDVDTeletextTools::deh24(&vtxt_row[6*i + 6]);
529 if (d1 < 0 || d2 < 0)
530 continue;
532 p->local = i & 0x01;
533 p->drcs = !!(i & 0x02);
534 p->l25 = !!(d1 & 0x04);
535 p->l35 = !!(d1 & 0x08);
536 p->page =
537 (((d1 & 0x000003c0) >> 6) |
538 ((d1 & 0x0003c000) >> (14-4)) |
539 ((d1 & 0x00003800) >> (11-8))) ^
540 (dehamming[vtxt_row[0]] << 8);
541 if (p->page < 0x100)
542 p->page += 0x800;
543 p->subpage = d2 >> 2;
544 if ((p->page & 0xff) == 0xff)
545 p->page = 0;
546 else if (p->page > 0x899)
548 // workaround for crash on RTL Shop ...
549 // sorry.. i dont understand whats going wrong here :)
550 continue;
552 else if (m_TXTCache->astCachetable[p->page][0]) /* link valid && linked page cached */
554 TextPageinfo_t *pageinfo_link = &(m_TXTCache->astCachetable[p->page][0]->pageinfo);
555 if (p->local)
556 pageinfo_link->function = p->drcs ? FUNC_DRCS : FUNC_POP;
557 else
558 pageinfo_link->function = p->drcs ? FUNC_GDRCS : FUNC_GPOP;
560 p++; /* */
564 else if (packet_number == 26)
566 int descode = dehamming[vtxt_row[2]]; /* designation code (0..15) */
567 if (descode == 0xff)
568 continue;
570 if (!pageinfo_thread->ext)
571 pageinfo_thread->ext = (TextExtData_t*) calloc(1, sizeof(TextExtData_t));
572 if (!pageinfo_thread->ext)
573 continue;
574 if (!(pageinfo_thread->ext->p26[descode]))
575 pageinfo_thread->ext->p26[descode] = (unsigned char*) malloc(13 * 3);
576 if (pageinfo_thread->ext->p26[descode])
577 memcpy(pageinfo_thread->ext->p26[descode], &vtxt_row[3], 13 * 3);
579 else if (packet_number == 28)
581 int descode = dehamming[vtxt_row[2]]; /* designation code (0..15) */
583 if (descode == 0xff)
584 continue;
586 if (descode != 2)
588 int t1 = CDVDTeletextTools::deh24(&vtxt_row[7-4]);
589 pageinfo_thread->function = t1 & 0x0f;
590 int countryCode = (t1 >> 4) & 0x07;
591 if (!pageinfo_thread->nationalvalid && countryCode != NAT_DEFAULT)
593 pageinfo_thread->nationalvalid = 1;
594 pageinfo_thread->national = countryCode;
598 switch (descode) /* designation code */
600 case 0: /* basic level 1 page */
601 Decode_p2829(vtxt_row, &(pageinfo_thread->ext));
602 break;
603 case 1: /* G0/G1 designation for older decoders, level 3.5: DCLUT4/16, colors for multicolored bitmaps */
604 break; /* ignore */
605 case 2: /* page key */
606 break; /* ignore */
607 case 3: /* types of PTUs in DRCS */
608 break; //! @todo implement
609 case 4: /* CLUTs 0/1, only level 3.5 */
610 break; /* ignore */
611 default:
612 break; /* invalid, ignore */
613 } /* switch designation code */
615 else if (packet_number == 30)
617 m_TXTCache->line30 = "";
618 for (int i=26-4; i <= 45-4; i++) /* station ID */
619 m_TXTCache->line30.append(1, deparity[vtxt_row[i]]);
623 /* set update flag */
624 if (m_TXTCache->CurrentPage[magazine] == m_TXTCache->Page && m_TXTCache->CurrentSubPage[magazine] != -1)
626 SavePage(m_TXTCache->CurrentPage[magazine], m_TXTCache->CurrentSubPage[magazine], pagedata[magazine]);
627 m_TXTCache->PageUpdate = true;
628 // doupdate = 0;
629 if (!m_TXTCache->ZapSubpageManual)
630 m_TXTCache->SubPage = m_TXTCache->CurrentSubPage[magazine];
636 else if (pMsg->IsType(CDVDMsg::PLAYER_SETSPEED))
638 m_speed = std::static_pointer_cast<CDVDMsgInt>(pMsg)->m_value;
640 else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)
641 || pMsg->IsType(CDVDMsg::GENERAL_RESET))
643 ResetTeletextCache();
648 void CDVDTeletextData::OnExit()
650 CLog::Log(LOGINFO, "thread end: data_thread");
653 void CDVDTeletextData::Flush()
655 if(!m_messageQueue.IsInited())
656 return;
657 /* flush using message as this get's called from VideoPlayer thread */
658 /* and any demux packet that has been taken out of queue need to */
659 /* be disposed of before we flush */
660 m_messageQueue.Flush();
661 m_messageQueue.Put(std::make_shared<CDVDMsg>(CDVDMsg::GENERAL_FLUSH));
664 void CDVDTeletextData::Decode_p2829(unsigned char *vtxt_row, TextExtData_t **ptExtData)
666 unsigned int bitsleft, colorindex;
667 unsigned char *p;
668 int t1 = CDVDTeletextTools::deh24(&vtxt_row[7-4]);
669 int t2 = CDVDTeletextTools::deh24(&vtxt_row[10-4]);
671 if (t1 < 0 || t2 < 0)
672 return;
674 if (!(*ptExtData))
675 (*ptExtData) = (TextExtData_t*) calloc(1, sizeof(TextExtData_t));
676 if (!(*ptExtData))
677 return;
679 (*ptExtData)->p28Received = 1;
680 (*ptExtData)->DefaultCharset = (t1>>7) & 0x7f;
681 (*ptExtData)->SecondCharset = ((t1>>14) & 0x0f) | ((t2<<4) & 0x70);
682 (*ptExtData)->LSP = !!(t2 & 0x08);
683 (*ptExtData)->RSP = !!(t2 & 0x10);
684 (*ptExtData)->SPL25 = !!(t2 & 0x20);
685 (*ptExtData)->LSPColumns = (t2>>6) & 0x0f;
687 bitsleft = 8; /* # of bits not evaluated in val */
688 t2 >>= 10; /* current data */
689 p = &vtxt_row[13-4]; /* pointer to next data triplet */
690 for (colorindex = 0; colorindex < 16; colorindex++)
692 if (bitsleft < 12)
694 t2 |= CDVDTeletextTools::deh24(p) << bitsleft;
695 if (t2 < 0) /* hamming error */
696 break;
697 p += 3;
698 bitsleft += 18;
700 (*ptExtData)->bgr[colorindex] = t2 & 0x0fff;
701 bitsleft -= 12;
702 t2 >>= 12;
704 if (t2 < 0 || bitsleft != 14)
706 (*ptExtData)->p28Received = 0;
707 return;
709 (*ptExtData)->DefScreenColor = t2 & 0x1f;
710 t2 >>= 5;
711 (*ptExtData)->DefRowColor = t2 & 0x1f;
712 (*ptExtData)->BlackBgSubst = !!(t2 & 0x20);
713 t2 >>= 6;
714 (*ptExtData)->ColorTableRemapping = t2 & 0x07;
717 void CDVDTeletextData::SavePage(int p, int sp, unsigned char* buffer)
719 std::unique_lock<CCriticalSection> lock(m_TXTCache->m_critSection);
720 TextCachedPage_t* pg = m_TXTCache->astCachetable[p][sp];
721 if (!pg)
723 CLog::Log(LOGERROR, "CDVDTeletextData: trying to save a not allocated page!!");
724 return;
727 memcpy(pg->data, buffer, 23*40);
730 void CDVDTeletextData::LoadPage(int p, int sp, unsigned char* buffer)
732 std::unique_lock<CCriticalSection> lock(m_TXTCache->m_critSection);
733 TextCachedPage_t* pg = m_TXTCache->astCachetable[p][sp];
734 if (!pg)
736 CLog::Log(LOGERROR, "CDVDTeletextData: trying to load a not allocated page!!");
737 return;
740 memcpy(buffer, pg->data, 23*40);
743 void CDVDTeletextData::ErasePage(int magazine)
745 std::unique_lock<CCriticalSection> lock(m_TXTCache->m_critSection);
746 TextCachedPage_t* pg = m_TXTCache->astCachetable[m_TXTCache->CurrentPage[magazine]][m_TXTCache->CurrentSubPage[magazine]];
747 if (pg)
749 memset(&(pg->pageinfo), 0, sizeof(TextPageinfo_t)); /* struct pageinfo */
750 memset(pg->p0, ' ', 24);
751 memset(pg->data, ' ', 23*40);
755 void CDVDTeletextData::AllocateCache(int magazine)
757 /* check cachetable and allocate memory if needed */
758 if (m_TXTCache->astCachetable[m_TXTCache->CurrentPage[magazine]][m_TXTCache->CurrentSubPage[magazine]] == 0)
760 m_TXTCache->astCachetable[m_TXTCache->CurrentPage[magazine]][m_TXTCache->CurrentSubPage[magazine]] = new TextCachedPage_t;
761 if (m_TXTCache->astCachetable[m_TXTCache->CurrentPage[magazine]][m_TXTCache->CurrentSubPage[magazine]] )
763 ErasePage(magazine);
764 m_TXTCache->CachedPages++;