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.
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"
18 using namespace std::chrono_literals
;
20 const uint8_t rev_lut
[32] =
22 0x00,0x08,0x04,0x0c, /* upper nibble */
26 0x00,0x80,0x40,0xc0, /* lower nibble */
32 void CDVDTeletextTools::NextDec(int *i
) /* skip to next decimal */
36 if ((*i
& 0x0F) > 0x09)
39 if ((*i
& 0xF0) > 0x90)
46 void CDVDTeletextTools::PrevDec(int *i
) /* counting down */
50 if ((*i
& 0x0F) > 0x09)
53 if ((*i
& 0xF0) > 0x90)
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
)
65 *s
-- = number2char(c
);
70 signed int CDVDTeletextTools::deh24(unsigned char *p
)
72 int e
= hamm24par
[0][p
[0]]
76 int x
= hamm24val
[p
[0]]
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
));
99 CDVDTeletextData::~CDVDTeletextData()
102 ResetTeletextCache();
105 bool CDVDTeletextData::CheckStream(CDVDStreamInfo
&hints
)
107 if (hints
.codec
== AV_CODEC_ID_DVB_TELETEXT
)
113 bool CDVDTeletextData::OpenStream(CDVDStreamInfo hints
)
117 m_messageQueue
.Init();
119 if (hints
.codec
== AV_CODEC_ID_DVB_TELETEXT
)
121 CLog::Log(LOGINFO
, "Creating teletext data thread");
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
)
154 TextPageinfo_t
*p
= &(page
->pageinfo
);
163 for (unsigned char* const d26
: p
->ext
->p26
)
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
)
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()
223 TextPageinfo_t
*pageinfo_thread
;
224 unsigned char vtxt_row
[42];
225 unsigned char pagedata
[9][23*40];
226 unsigned char magazine
= 0xff;
229 CLog::Log(LOGINFO
, "running thread: CDVDTeletextData");
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 */
243 if (MSGQ_IS_ERROR(ret
))
245 if (!m_messageQueue
.ReceivedAbortRequest())
246 CLog::Log(LOGERROR
, "MSGQ_IS_ERROR returned true ({})", ret
);
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)
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
]);
297 if (packet_number
== 0)
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;
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 */
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;
332 if (IsDec(m_TXTCache
->PageReceiving
)) /* ignore other subpage bits for hex pages */
333 m_TXTCache
->CurrentSubPage
[magazine
] = b3
<<4 | b4
;
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
)
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]];
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;
377 if (use
== -1 && !m_TXTCache
->SubtitlePages
[i
].page
)
379 else if (m_TXTCache
->SubtitlePages
[i
].page
== m_TXTCache
->PageReceiving
)
386 if (found
== -1 && use
!= -1)
387 m_TXTCache
->SubtitlePages
[use
].page
= m_TXTCache
->PageReceiving
;
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
)
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);
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;
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) */
457 if (descode
== 0) // reading FLOF-Pagelinks
459 b1
= dehamming
[vtxt_row
[0]];
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);
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
;
487 l
>= 2 && 0 == m_TXTCache
->FlofPages
[m_TXTCache
->CurrentPage
[magazine
]][l
];
489 ; /* find used linkindex */
491 e
>= 1 && !isalnum(p
[e
]);
495 a
>= 0 && p
[a
] >= ' ';
496 a
--) /* find start */
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);
503 m_TXTCache
->ADIPTable
[m_TXTCache
->FlofPages
[m_TXTCache
->CurrentPage
[magazine
]][l
]][e
-a1
+1] = '\0';
511 else if (descode
== 4) /* level 2.5 links (ignore level 3.5 links of /4 and /5) */
516 if (!pageinfo_thread
->ext
)
517 pageinfo_thread
->ext
= (TextExtData_t
*) calloc(1, sizeof(TextExtData_t
));
518 if (!pageinfo_thread
->ext
)
520 if (!(pageinfo_thread
->ext
->p27
))
521 pageinfo_thread
->ext
->p27
= (Textp27_t
*) calloc(4, sizeof(Textp27_t
));
522 if (!(pageinfo_thread
->ext
->p27
))
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)
533 p
->drcs
= !!(i
& 0x02);
534 p
->l25
= !!(d1
& 0x04);
535 p
->l35
= !!(d1
& 0x08);
537 (((d1
& 0x000003c0) >> 6) |
538 ((d1
& 0x0003c000) >> (14-4)) |
539 ((d1
& 0x00003800) >> (11-8))) ^
540 (dehamming
[vtxt_row
[0]] << 8);
543 p
->subpage
= d2
>> 2;
544 if ((p
->page
& 0xff) == 0xff)
546 else if (p
->page
> 0x899)
548 // workaround for crash on RTL Shop ...
549 // sorry.. i dont understand whats going wrong here :)
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
);
556 pageinfo_link
->function
= p
->drcs
? FUNC_DRCS
: FUNC_POP
;
558 pageinfo_link
->function
= p
->drcs
? FUNC_GDRCS
: FUNC_GPOP
;
564 else if (packet_number
== 26)
566 int descode
= dehamming
[vtxt_row
[2]]; /* designation code (0..15) */
570 if (!pageinfo_thread
->ext
)
571 pageinfo_thread
->ext
= (TextExtData_t
*) calloc(1, sizeof(TextExtData_t
));
572 if (!pageinfo_thread
->ext
)
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) */
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
));
603 case 1: /* G0/G1 designation for older decoders, level 3.5: DCLUT4/16, colors for multicolored bitmaps */
605 case 2: /* page key */
607 case 3: /* types of PTUs in DRCS */
608 break; //! @todo implement
609 case 4: /* CLUTs 0/1, only level 3.5 */
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;
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())
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
;
668 int t1
= CDVDTeletextTools::deh24(&vtxt_row
[7-4]);
669 int t2
= CDVDTeletextTools::deh24(&vtxt_row
[10-4]);
671 if (t1
< 0 || t2
< 0)
675 (*ptExtData
) = (TextExtData_t
*) calloc(1, sizeof(TextExtData_t
));
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
++)
694 t2
|= CDVDTeletextTools::deh24(p
) << bitsleft
;
695 if (t2
< 0) /* hamming error */
700 (*ptExtData
)->bgr
[colorindex
] = t2
& 0x0fff;
704 if (t2
< 0 || bitsleft
!= 14)
706 (*ptExtData
)->p28Received
= 0;
709 (*ptExtData
)->DefScreenColor
= t2
& 0x1f;
711 (*ptExtData
)->DefRowColor
= t2
& 0x1f;
712 (*ptExtData
)->BlackBgSubst
= !!(t2
& 0x20);
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
];
723 CLog::Log(LOGERROR
, "CDVDTeletextData: trying to save a not allocated page!!");
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
];
736 CLog::Log(LOGERROR
, "CDVDTeletextData: trying to load a not allocated page!!");
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
]];
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
]] )
764 m_TXTCache
->CachedPages
++;