[MPlayer-cvslog] r24310 - in trunk: DOCS/man/en/mplayer.1 cfg-common.h help/help_mp-en.h stream/stream_tv.c stream/tv.h stream/tvi_vbi.c
voroshil
subversion at mplayerhq.hu
Fri Aug 31 18:53:28 CEST 2007
Author: voroshil
Date: Fri Aug 31 18:53:27 2007
New Revision: 24310
Log:
Support for selecting language via packet 28.
Also allows to select default teletext language.
It will be used if language is not specified by network provider
via packet 28.
Modified:
trunk/cfg-common.h
trunk/stream/stream_tv.c
trunk/stream/tv.h
trunk/stream/tvi_vbi.c
Changes in other areas also in this revision:
Modified:
trunk/DOCS/man/en/mplayer.1
trunk/help/help_mp-en.h
Modified: trunk/cfg-common.h
==============================================================================
--- trunk/cfg-common.h (original)
+++ trunk/cfg-common.h Fri Aug 31 18:53:27 2007
@@ -464,6 +464,7 @@ m_option_t tvopts_conf[]={
{"tdevice", &stream_tv_defaults.tdevice, CONF_TYPE_STRING, 0, 0, 0, NULL},
{"tpage", &stream_tv_defaults.tpage, CONF_TYPE_INT, CONF_RANGE, 100, 899, NULL},
{"tformat", &stream_tv_defaults.tformat, CONF_TYPE_INT, CONF_RANGE, 0, 3, NULL},
+ {"tlang", &stream_tv_defaults.tlang, CONF_TYPE_INT, CONF_RANGE, -1, 0x7f, NULL},
#endif
{"audioid", &stream_tv_defaults.audio_id, CONF_TYPE_INT, CONF_RANGE, 0, 9, NULL},
{NULL, NULL, 0, 0, 0, 0, NULL}
Modified: trunk/stream/stream_tv.c
==============================================================================
--- trunk/stream/stream_tv.c (original)
+++ trunk/stream/stream_tv.c Fri Aug 31 18:53:27 2007
@@ -75,6 +75,7 @@ tv_param_t stream_tv_defaults = {
NULL, //tdevice
0, //tformat
100, //tpage
+ 0, //tlang
0, //scan_autostart
50, //scan_threshold
Modified: trunk/stream/tv.h
==============================================================================
--- trunk/stream/tv.h (original)
+++ trunk/stream/tv.h Fri Aug 31 18:53:27 2007
@@ -50,6 +50,7 @@ typedef struct tv_param_s {
char *tdevice; ///< teletext device
int tformat; ///< teletext display format
int tpage; ///< start teletext page
+ int tlang; ///< primary language code
int scan;
int scan_threshold;
@@ -276,7 +277,7 @@ typedef struct tt_char_s{
unsigned char bg; ///< background color
unsigned char gfx; ///< 0-no gfx, 1-solid gfx, 2-separated gfx
unsigned char ctl; ///< control character
- unsigned char lng; ///< lang: 0-lating,1-national
+ unsigned char lng; ///< lang: 0-secondary language,1-primary language
unsigned char raw; ///< raw character (as received from device)
} tt_char;
@@ -288,7 +289,8 @@ typedef struct tt_link_s{
typedef struct tt_page_s{
int pagenum; ///< page number
int subpagenum; ///< subpage number
- unsigned char lang; ///< language code
+ unsigned char primary_lang; ///< primary language code
+ unsigned char secondary_lang; ///< secondary language code
unsigned char active; ///< page is complete and ready for rendering
unsigned char flags; ///< page flags, not used
unsigned char raw[VBI_ROWS*VBI_COLUMNS]; ///< page data
Modified: trunk/stream/tvi_vbi.c
==============================================================================
--- trunk/stream/tvi_vbi.c (original)
+++ trunk/stream/tvi_vbi.c Fri Aug 31 18:53:27 2007
@@ -103,7 +103,6 @@
typedef struct mag_s{
tt_page* pt;
int order;
- int lang;
} mag_t;
typedef struct {
@@ -116,6 +115,8 @@ typedef struct {
teletext_format tformat; ///< see teletext_format enum
teletext_zoom zoom; ///< see teletext_zoom enum
mag_t* mag; ///< pages magazine (has 8 entities)
+ int primary_language; ///< primary character set
+ int secondary_language; ///< secondary character set
/// Currently displayed page (with additional info, e.g current time)
tt_char display_page[VBI_ROWS*VBI_COLUMNS];
/// number of raw bytes between two subsequent encoded bits
@@ -320,25 +321,132 @@ static unsigned int latin_subchars[8][13
{0x23,0x24,0x40,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x7b,0x7c,0x7d,0x7e}
};
-static int lang2id (int lang){
- return LATIN;
+/**
+ * List of supported languages.
+ *
+ * lang_code bits for primary Language:
+ * bits 7-4 corresponds to bits 14-11 of 28 packet's first triplet
+ * bits 3-1 corresponds to bits C12-C14 of packet 0 (lang)
+ *
+ * lang_code bits for secondary Language:
+ * bits 7-5 corresponds to bits 3-1 of 28 packet's second triplet
+ * bits 4,2 corresponds to bits 18,16 of 28 packet's first triplet
+ * bits 3,1 corresponds to bits 15,17 of 28 packet's first triplet
+ *
+ * For details see Tables 32 and 33 of specification (subclause 15.2)
+ */
+struct {
+ unsigned char lang_code;
+ unsigned char charset;
+ char* lang_name;
+} tt_languages[]=
+{
+ { 0x01, LATIN, "French"},
+ { 0x02, LATIN, "Swedish/Finnish/Hungarian"},
+ { 0x03, LATIN, "Czech/Slovak"},
+ { 0x04, LATIN, "German"},
+ { 0x05, LATIN, "Portuguese/Spanish"},
+ { 0x06, LATIN, "Italian"},
+
+ { 0x08, LATIN, "Polish"},
+ { 0x09, LATIN, "French"},
+ { 0x0a, LATIN, "Swedish/Finnish/Hungarian"},
+ { 0x0b, LATIN, "Czech/Slovak"},
+ { 0x0c, LATIN, "German"},
+ { 0x0e, LATIN, "Italian"},
+
+ { 0x10, LATIN, "English"},
+ { 0x11, LATIN, "French"},
+ { 0x12, LATIN, "Swedish/Finnish/Hungarian"},
+ { 0x13, LATIN, "Turkish"},
+ { 0x14, LATIN, "German"},
+ { 0x15, LATIN, "Portuguese/Spanish"},
+ { 0x16, LATIN, "Italian"},
+
+ { 0x1d, LATIN, "Serbian/Croatian/Slovenian (Latin)"},
+
+ { 0x20, CYRILLIC1, "Serbian/Croatian (Cyrillic)"},
+ { 0x21, CYRILLIC2, "Russian, Bulgarian"},
+ { 0x22, LATIN, "Estonian"},
+ { 0x23, LATIN, "Czech/Slovak"},
+ { 0x24, LATIN, "German"},
+ { 0x25, CYRILLIC3, "Ukrainian"},
+ { 0x26, LATIN, "Lettish/Lithuanian"},
+
+ { 0x33, LATIN, "Turkish"},
+ { 0x37, GREEK, "Greek"},
+
+ { 0x40, LATIN, "English"},
+ { 0x41, LATIN, "French"},
+// { 0x47, ARABIC, "Arabic"},
+
+// { 0x55, HEBREW, "Hebrew"},
+// { 0x57, ARABIC, "Arabic"},
+
+ { 0x00, LATIN, "English"},
+};
+
+/**
+ * \brief 24/18 Hamming code decoding
+ * \param data bytes with hamming code (array must be at least 3 bytes long)
+ * \return -1 if multiple bit error occured, D1-DI data bits - otherwise
+ *
+ * \note Bits must be correctly ordered, that is for 24/18 (lowest bit first)
+ * P1 P2 D1 P3 D2 D3 D4 P4 D5 D6 D7 D8 D9 DA DB P5 DC DD DE DF DG DH DI P6
+ */
+int corrHamm24(unsigned char *data){
+ unsigned char syndrom=0;
+ int cw=data[0] | (data[1]<<8) | (data[2]<<16);
+ int i;
+
+ for(i=0;i<23;i++)
+ syndrom^=((cw>>i)&1)*(i+33);
+
+ syndrom^=(cw>>11)&32;
+
+ if(syndrom&31){
+ if(syndrom < 32 || syndrom > 55)
+ return -1;
+ cw ^= 1<<((syndrom&31)-1);
+ }
+
+ return (cw&4)>>2 |
+ (cw&0x70)>>3 |
+ (cw&0x3f00)>>4 |
+ (cw&0x3f0000)>>5;
+}
+
+/**
+ * \brief converts language bits to charset index
+ * \param lang language bits
+ * \return charset index in lang_chars array
+ */
+static int lang2charset (int lang){
+ int i;
+ for(i=0;tt_languages[i].lang_code;i++)
+ if(tt_languages[i].lang_code==lang)
+ break;
+
+ return tt_languages[i].charset;
}
/**
* \brief convert chars from curent teletext codepage into MPlayer charset
* \param p raw teletext char to decode
- * \param lang teletext internal language code (see lang2id)
+ * \param charset index on lang_chars
+ * \param lang index in substitution array (latin charset only)
* \return UTF8 char
*
* \remarks
* routine will analyze raw member of given tt_char structure and
* fill unicode member of the same struct with appropriate utf8 code.
*/
-static unsigned int conv2uni(unsigned int p,int lang)
+static unsigned int conv2uni(unsigned int p,int charset,int lang)
{
- int charset=lang2id(lang);
+
if(p<0x80 && p>=0x20){
if(charset==LATIN){
+ lang&=7;
if (p>=0x23 && p<=0x24){
return latin_subchars[lang][p-0x23];
}else if (p==0x40){
@@ -452,7 +560,8 @@ static void put_to_cache(priv_vbi_t* pri
}
pgc->pagenum=pg->pagenum;
pgc->subpagenum=pg->subpagenum;
- pgc->lang=pg->lang;
+ pgc->primary_lang=pg->primary_lang;
+ pgc->secondary_lang=pg->secondary_lang;
pgc->flags=pg->flags;
for(j=0;j<6;++j)
pgc->links[j]=pg->links[j];
@@ -559,17 +668,22 @@ static void destroy_cache(priv_vbi_t* pr
/**
* \brief converts raw teletext page into useful format (1st rendering stage)
* \param pg page to decode
- *
+ * \param raw raw data to decode page from
+ * \param primary_lang primary language code
+ * \param secondary_lang secondary language code
+*
* Routine fills tt_char structure of each teletext_page character with proper
* info about foreground and background colors, character
* type (graphics/control/text).
*/
-static void decode_page(tt_char* p,int lang,unsigned char* raw)
+static void decode_page(tt_char* p,unsigned char* raw,int primary_lang,int secondary_lang)
{
int row,col;
+ int prim_charset=lang2charset(primary_lang);
+ int sec_charset=lang2charset(secondary_lang);
for(row=0;row<VBI_ROWS;row++) {
- int lat=(lang==0);
+ int prim_lang=1;
int gfx=0;
int fg_color=7;
int bg_color=0;
@@ -586,7 +700,7 @@ static void decode_page(tt_char* p,int l
continue;
}
p[i].gfx=gfx?(separated?2:1):0;
- p[i].lng=lat?0:lang;
+ p[i].lng=prim_lang;
p[i].ctl=(c&0x60)==0?1:0;
p[i].fg=fg_color;
p[i].bg=bg_color;
@@ -609,7 +723,7 @@ static void decode_page(tt_char* p,int l
}else if (c<=0x1a){ //Contiguous/Separated gfx
separated=!(c&1);
}else if (c<=0x1b){
- lat=!lat;
+ prim_lang=!prim_lang;
}else if (c<=0x1d){
bg_color=(c&1)?fg_color:0;
p[i].bg=bg_color;
@@ -633,9 +747,13 @@ static void decode_page(tt_char* p,int l
p[i].unicode=c-0x20;
if (p[i].unicode>0x3f) p[i].unicode-=0x20;
tt_held=p[i];
- }else
- p[i].unicode=conv2uni(c,p[i].lng);
-
+ }else{
+ if(p[i].lng){
+ p[i].unicode=conv2uni(c,prim_charset,primary_lang&7);
+ }else{
+ p[i].unicode=conv2uni(c,sec_charset,secondary_lang&7);
+ }
+ }
p[i].fg=fg_color;
p[i].bg=bg_color;
}
@@ -684,7 +802,7 @@ static void prepare_visible_page(priv_vb
priv->display_page[i]=tt_space;
}
}else{
- decode_page(priv->display_page,pg->lang,pg->raw);
+ decode_page(priv->display_page,pg->raw,pg->primary_lang,pg->secondary_lang);
mp_msg(MSGT_TV,MSGL_DBG3,"page #%x was decoded!\n",pg->pagenum);
}
@@ -759,7 +877,7 @@ static void render2text(tt_page* pt,FILE
0);
fprintf(f,"+----------------------------------------+\n");
- decode_page(dp,pt->lang,pt->raw);
+ decode_page(dp,pt->raw,pt->primary_lang,pt->secondary_lang);
for(i=0;i<VBI_ROWS;i++){
fprintf(f,"|");
if(colored) fprintf(f,"\033[40m");
@@ -959,8 +1077,11 @@ static int decode_pkt0(priv_vbi_t* priv,
if (!priv->mag[magAddr].pt)
priv->mag[magAddr].pt= malloc(sizeof(tt_page));
- priv->mag[magAddr].lang=(d[7]>>1)&0x7;
- priv->mag[magAddr].pt->lang=priv->mag[magAddr].lang;
+ if(priv->primary_language)
+ priv->mag[magAddr].pt->primary_lang=priv->primary_language;
+ else
+ priv->mag[magAddr].pt->primary_lang= (d[7]&7)>>1;
+ priv->mag[magAddr].pt->secondary_lang=priv->secondary_language;
priv->mag[magAddr].pt->subpagenum=(d[2]|(d[3]<<4)|(d[4]<<8)|(d[5]<<12))&0x3f7f;
priv->mag[magAddr].pt->pagenum=(magAddr<<8) | d[0] | (d[1]<<4);
priv->mag[magAddr].pt->flags=( d[6] | (d[7]<<4));
@@ -1119,6 +1240,46 @@ static int decode_pkt27(priv_vbi_t* priv
}
/**
+ * \brief Decode teletext X/28/0 Format 1 packet
+ * \param priv private data structure
+ * \param data raw teletext data
+ *
+ * Primary G0 charset is transmitted in bits 14-8 of Triplet 1
+ * See Table 32 of specification for details.
+ *
+ * Secondary G0 charset is transmitted in bits 3-1 of Triplet 2 and
+ * bits 18-15 of Triplet 1
+ * See Table 33 of specification for details.
+ *
+ */
+static void decode_pkt28(priv_vbi_t* priv,unsigned char*data){
+ int d;
+ int t1,t2;
+ d=corrHamm48[ data[0] ];
+ if(d) return; //this is not X/28/0 Format 1 packet or error occured
+
+ t1=corrHamm24(data+1);
+ t2=corrHamm24(data+4);
+ if (t1<0 || t2<0){
+ pll_add(priv,1,4);
+ return;
+ }
+
+ priv->primary_language=(t1>>7)&0x7f;
+ priv->secondary_language=((t2<<4) | (t1>>14))&0x7f;
+ if (priv->secondary_language==0x7f)
+ //No secondary language required
+ priv->secondary_language=priv->primary_language;
+ else // Swapping bits 1 and 3
+ priv->secondary_language=(priv->secondary_language&0x7a) |
+ (priv->secondary_language&4)>>2 |
+ (priv->secondary_language&1)<<2;
+
+ mp_msg(MSGT_TV,MSGL_DBG2,"pkt28: language: primary=%02x secondary=0x%02x\n",
+ priv->primary_language,priv->secondary_language);
+}
+
+/**
* \brief decodes raw vbi data (signal amplitudes) into sequence of bytes
* \param priv private data structure
* \param buf raw vbi data (one line of frame)
@@ -1311,6 +1472,8 @@ static void vbi_decode(priv_vbi_t* priv,
decode_pkt_page(priv,data+2,magAddr,pkt);//skip MRGA
}else if(pkt==27) {
decode_pkt27(priv,data+2,magAddr);
+ }else if(pkt==28){
+ decode_pkt28(priv,data+2);
}else if(pkt==30){
decode_pkt30(priv,data+2,magAddr);
} else {
@@ -1455,6 +1618,7 @@ int teletext_control(void* p, int cmd, v
switch (cmd) {
case TV_VBI_CONTROL_RESET:
{
+ int i;
tv_param_t* tv_param=arg;
pthread_mutex_lock(&(priv->buffer_mutex));
priv->pagenumdec=0;
@@ -1463,6 +1627,25 @@ int teletext_control(void* p, int cmd, v
priv->tformat=tv_param->tformat;
priv->subpagenum=0;
pll_reset(priv,fine_tune);
+ if(tv_param->tlang==-1){
+ mp_msg(MSGT_TV,MSGL_INFO,MSGTR_TV_TTSupportedLanguages);
+ for(i=0; tt_languages[i].lang_code; i++){
+ mp_msg(MSGT_TV,MSGL_INFO," %3d %s\n",
+ tt_languages[i].lang_code, tt_languages[i].lang_name);
+ }
+ mp_msg(MSGT_TV,MSGL_INFO," %3d %s\n",
+ tt_languages[i].lang_code, tt_languages[i].lang_name);
+ }else{
+ for(i=0; tt_languages[i].lang_code; i++){
+ if(tt_languages[i].lang_code==tv_param->tlang)
+ break;
+ }
+ if (priv->primary_language!=tt_languages[i].lang_code){
+ mp_msg(MSGT_TV,MSGL_INFO,MSGTR_TV_TTSelectedLanguage,
+ tt_languages[i].lang_name);
+ priv->primary_language=tt_languages[i].lang_code;
+ }
+ }
pthread_mutex_unlock(&(priv->buffer_mutex));
return TVI_CONTROL_TRUE;
}
More information about the MPlayer-cvslog
mailing list