[MPlayer-dev-eng] [PATCH] Teletext support try3 (5/5, rendering)

Vladimir Voroshilov voroshil at gmail.com
Sun Jul 15 12:59:49 CEST 2007


Hi, All

Here is fifth of 5 teletext patches.

1. Rendering is done through OSD, thus no color support.
2. Troubles with transparent mode rendering (funny colors, looks like
overflow somewhere at alpha calculation).
3. Don't know how to specify background and foreground color for text.

See also contents of first patch for some details.

-- 
Regards,
Vladimir Voroshilov     mailto:voroshil at gmail.com
JID: voroshil at gmail.com, voroshil at jabber.ru
ICQ: 95587719
-------------- next part --------------
Index: libvo/sub.h
===================================================================
--- libvo/sub.h	(revision 23784)
+++ libvo/sub.h	(working copy)
@@ -2,6 +2,10 @@
 #ifndef MPLAYER_SUB_H
 #define MPLAYER_SUB_H
 
+#ifdef HAVE_TV_TELETEXT
+#include "libmpcodecs/mp_image.h"
+#endif
+
 typedef struct mp_osd_bbox_s {
     int x1,y1,x2,y2;
 } mp_osd_bbox_t;
@@ -11,6 +15,7 @@
 #define OSDTYPE_PROGBAR 3
 #define OSDTYPE_SPU 4
 #define OSDTYPE_DVDNAV 5
+#define OSDTYPE_TELETEXT 6
 
 #define OSDFLAG_VISIBLE 1
 #define OSDFLAG_CHANGED 2
@@ -64,6 +69,12 @@
 
 extern unsigned char* vo_osd_text;
 
+#ifdef HAVE_TV_TELETEXT
+extern void* vo_osd_teletext_page;
+extern int vo_osd_teletext_half;
+extern int vo_osd_teletext_mode;
+#endif
+
 extern int vo_osd_progbar_type;
 extern int vo_osd_progbar_value;   // 0..255
 
Index: libvo/sub.c
===================================================================
--- libvo/sub.c	(revision 23784)
+++ libvo/sub.c	(working copy)
@@ -14,6 +14,10 @@
 #define OSD_NAV_BOX_ALPHA 0x7f
 #endif
 
+#ifdef HAVE_TV_TELETEXT
+#include "stream/tv.h"
+#endif
+
 #include "mplayer.h"
 #include "mp_msg.h"
 #include "help_mp.h"
@@ -68,6 +72,11 @@
 font_desc_t* sub_font=NULL;
 
 unsigned char* vo_osd_text=NULL;
+#ifdef HAVE_TV_TELETEXT
+void* vo_osd_teletext_page=NULL;
+int vo_osd_teletext_half = 0;
+int vo_osd_teletext_mode=0;
+#endif
 int sub_unicode=0;
 int sub_utf8=0;
 int sub_pos=100;
@@ -230,6 +239,245 @@
 }
 #endif
 
+#ifdef HAVE_TV_TELETEXT
+inline static void vo_update_text_teletext(mp_osd_obj_t *obj, int dxs, int dys)
+{
+    int h=0,w=0,i,j,c,font;
+    int wm,hm;
+    int color;
+    int x,y,x0,y0;
+    int cols,rows;
+    int wm12;
+    int hm13;
+    int hm23;
+    int start_row,max_rows;
+    int b,ax[6],ay[6],aw[6],ah[6];
+    tt_char tc;
+    tt_page* tp=vo_osd_teletext_page;
+    int* pu;
+    char* buf[9];
+
+    obj->flags|=OSDFLAG_CHANGED|OSDFLAG_VISIBLE;
+    if (!tp || !vo_osd_teletext_mode || !tp->active) {
+        obj->flags&=~OSDFLAG_VISIBLE;
+        return;
+    }
+    switch(vo_osd_teletext_half){
+    case 1:
+        start_row=0;
+        max_rows=VBI_ROWS/2;
+        break;
+    case 2:
+        start_row=VBI_ROWS/2;
+        max_rows=VBI_ROWS/2;
+        break;
+    default:
+        start_row=0;
+        max_rows=VBI_ROWS;
+        break;
+    }
+    wm=0;
+    hm=vo_font->height;
+    for(i=start_row;i<max_rows;i++){
+        for(j=0;j<VBI_COLUMNS;j++){
+            pu=&(tp->text[i*VBI_COLUMNS+j].unicode);
+            c = utf8_get_char(&pu);
+            render_one_glyph(vo_font, c);
+            if (wm<vo_font->width[c])
+                wm=vo_font->width[c];
+        }
+    }
+    wm+=vo_font->charspace;
+
+#if 0
+    hm=3*wm/2;
+    if(hm<vo_font->height){
+        hm=vo_font->height;
+        wm=2*hm/3;
+    }
+#else
+
+//    if(2*hm/3<wm){
+//        hm=3*wm/2;
+//    }else{
+        wm=2*hm/3;
+        hm=vo_font->height+1;
+//    }
+#endif
+    
+    cols=dxs/wm;
+    rows=dys/hm;
+
+    if(cols>VBI_COLUMNS)
+        cols=VBI_COLUMNS;
+    if(rows>max_rows)
+        rows=max_rows;
+    w=cols*wm-vo_font->charspace;
+    h=rows*hm-vo_font->charspace;
+
+    if(w<dxs)
+        x0=(dxs-w)/2;
+    else
+        x0=0;
+    y0=0;
+
+    wm12=wm>>1;
+    hm13=hm/3;
+    hm23=hm13<<1;
+
+    ax[0]=0;
+    ay[0]=0;
+    aw[0]=wm12;
+    ah[0]=hm13;
+    ax[1]=wm12;
+    ay[1]=0;
+    aw[1]=wm-wm12;
+    ah[1]=hm13;
+    ax[2]=0;
+    ay[2]=hm13;
+    aw[2]=wm12;
+    ah[2]=hm-hm23;
+    ax[3]=wm12;
+    ay[3]=hm13;
+    aw[3]=wm-wm12;
+    ah[3]=hm-hm23;
+    ax[4]=0;
+    ay[4]=hm-hm13;
+    aw[4]=wm12;
+    ah[4]=hm13;
+    ax[5]=wm12;
+    ay[5]=hm-hm13;
+    aw[5]=wm-wm12;
+    ah[5]=hm13;
+
+    obj->x = 0;
+    obj->y = 0;
+    obj->bbox.x1 = x0;
+    obj->bbox.y1 = 0;
+    obj->bbox.x2 = x0+w+wm;
+    obj->bbox.y2 = h;
+    obj->flags |= OSDFLAG_BBOX;
+    alloc_buf(obj);
+
+    for(i=0;i<9;i++)
+        buf[i]=malloc(wm*hm*4);
+
+    //alpha
+    if(vo_osd_teletext_mode==1 ||vo_osd_teletext_mode==3)
+        memset(buf[8],1,4*wm*hm);
+    else
+        memset(buf[8],200,4*wm*hm);
+    if(vo_osd_teletext_mode==1 ||vo_osd_teletext_mode==2){
+        //sorted by luma            // BGR
+        memset(buf[0],1  ,4*wm*hm); // 000
+        memset(buf[4],70 ,4*wm*hm); // 001 (original: 29. changed to be visible)
+        memset(buf[1],85 ,4*wm*hm); // 100 (original: 76, changed to separate from 4)
+        memset(buf[5],105,4*wm*hm); // 101
+        memset(buf[2],150,4*wm*hm); // 010
+        memset(buf[6],179,4*wm*hm); // 011
+        memset(buf[3],226,4*wm*hm); // 110
+        memset(buf[7],254,4*wm*hm); // 111
+    }else{
+        //inverted
+        memset(buf[0],254,4*wm*hm); // 000
+        memset(buf[4],226,4*wm*hm); // 001
+        memset(buf[1],179,4*wm*hm); // 100
+        memset(buf[5],150,4*wm*hm); // 101
+        memset(buf[2],105,4*wm*hm); // 010
+        memset(buf[6],85 ,4*wm*hm); // 011 (original: 76, changed to separate from 4)
+        memset(buf[3],70 ,4*wm*hm); // 110 (original: 29. changed to be visible)
+        memset(buf[7],1  ,4*wm*hm); // 111
+    }
+    y=-vo_font->charspace;
+    for(i=0;i<rows;i++){
+        x=x0;
+        for(j=0;j<cols;j++){
+            tc=tp->text[(i+start_row)*VBI_COLUMNS+j];
+            if(!tc.gfx){
+/* Rendering one text character */
+                pu=&(tc.unicode);
+                draw_alpha_buf(obj,x,y,wm,hm,buf[tc.bg],buf[8],0);
+                if(*pu==0x20 || *pu==0x00 || tc.ctl){ //space
+                    draw_alpha_buf(obj,x,y,wm,hm,buf[tc.bg],buf[8],0);
+                }else{
+                    c = utf8_get_char(&pu);
+                    if ((font=vo_font->font[c])>=0 && y+hm<dys){
+                        draw_alpha_buf(obj,
+                            x,y+vo_font->charspace,
+                            wm-vo_font->charspace/2,hm-vo_font->charspace,
+                            vo_font->pic_b[font]->bmp+vo_font->start[c],
+                            vo_font->pic_a[font]->bmp+vo_font->start[c],
+                            vo_font->pic_a[font]->w);
+                    }
+                }
+            }else{
+/*
+Rendering one graphics character
+TODO: support for separated graphics symbols (where six rectangles does not touch each other)
+
+    +--+    +--+    87654321
+    |01|    |12|    --------
+    |10| <= |34| <= 00100110 <= 0x26
+    |01|    |56|
+    +--+    +--+
+
+(0:wm/2)    (wm/2:wm-wm/2)
+
+********** *********** (0:hm/3)
+***   **** ****   ****
+*** 1 **** **** 2 **** 
+***   **** ****   ****
+********** ***********
+********** ***********
+
+********** *********** (hm/3:hm-2*hm/3)
+********** ***********
+***   **** ****   ****
+*** 3 **** **** 4 ****
+***   **** ****   ****
+********** ***********
+********** ***********
+********** ***********
+
+********** *********** (hm-hm/3:hm/3)
+***   **** ****   ****
+*** 5 **** **** 6 ****
+***   **** ****   **** 
+********** ***********   
+********** ***********
+
+*/              
+                if(tc.gfx>1){ //separated gfx
+                    for(b=0;b<6;b++){
+                        color=(tc.unicode>>b)&1?tc.fg:tc.bg;
+                        draw_alpha_buf(obj,x+ax[b]+1,y+ay[b]+1,aw[b]-2,ah[b]-2,buf[color],buf[8],0);
+                    }
+		    //separated gfx (background borders)
+		    //vertical
+                    draw_alpha_buf(obj,x        ,y,1,hm,buf[tc.bg],buf[8],0);
+                    draw_alpha_buf(obj,x+ax[1]-1,y,2,hm,buf[tc.bg],buf[8],0);
+                    draw_alpha_buf(obj,x+ax[1]+aw[1]-1,y,wm-ax[1]-aw[1]+1,hm,buf[tc.bg],buf[8],0);
+                    //horizontal
+                    draw_alpha_buf(obj,x,y      ,wm,1,buf[tc.bg],buf[8],0);
+                    draw_alpha_buf(obj,x,y+ay[0]+ah[0]-1,wm,2,buf[tc.bg],buf[8],0);
+                    draw_alpha_buf(obj,x,y+ay[2]+ah[2]-1,wm,2,buf[tc.bg],buf[8],0);
+                    draw_alpha_buf(obj,x,y+ay[4]+ah[4]-1,wm,hm-ay[4]-ah[4]+1,buf[tc.bg],buf[8],0);
+	        }else{
+                    for(b=0;b<6;b++){
+                        color=(tc.unicode>>b)&1?tc.fg:tc.bg;
+                        draw_alpha_buf(obj,x+ax[b],y+ay[b],aw[b],ah[b],buf[color],buf[8],0);
+                    }
+                }
+            }
+            x+=wm;
+        }
+        y+=hm;
+    }
+    for(i=0;i<9;i++)
+        free(buf[i]);
+}
+#endif
+
 int vo_osd_progbar_type=-1;
 int vo_osd_progbar_value=100;   // 0..256
 
@@ -866,6 +1114,11 @@
 	case OSDTYPE_SUBTITLE:
 	    vo_update_text_sub(obj,dxs,dys);
 	    break;
+#ifdef HAVE_TV_TELETEXT
+        case OSDTYPE_TELETEXT:
+            vo_update_text_teletext(obj,dxs,dys);
+            break;
+#endif
 	case OSDTYPE_PROGBAR:
 	    vo_update_text_progbar(obj,dxs,dys);
 	    break;
@@ -933,6 +1186,9 @@
 #ifdef USE_DVDNAV
     new_osd_obj(OSDTYPE_DVDNAV);
 #endif
+#if HAVE_TV_TELETEXT
+    new_osd_obj(OSDTYPE_TELETEXT);
+#endif
 #ifdef HAVE_FREETYPE
     force_load_font = 1;
 #endif
@@ -971,6 +1227,9 @@
 #ifdef USE_DVDNAV
         case OSDTYPE_DVDNAV:
 #endif
+#ifdef HAVE_TV_TELETEXT
+        case OSDTYPE_TELETEXT:
+#endif
 	case OSDTYPE_OSD:
 	case OSDTYPE_SUBTITLE:
 	case OSDTYPE_PROGBAR:
Index: mplayer.c
===================================================================
--- mplayer.c	(revision 23784)
+++ mplayer.c	(working copy)
@@ -1622,6 +1622,7 @@
 	decoded_frame = decode_video(sh_video, start, in_size, 0, pts);
 	if (decoded_frame) {
 	    update_subtitles(sh_video, mpctx->d_sub, 0);
+	    update_teletext(sh_video, mpctx->demuxer, 0);
 	    update_osd_msg();
 	    current_module = "filter video";
 	    if (filter_video(sh_video, decoded_frame, sh_video->pts))
@@ -2036,6 +2037,7 @@
 	    ++total_frame_cnt;
 	}
 	update_subtitles(sh_video, mpctx->d_sub, 0);
+	update_teletext(sh_video, mpctx->demuxer, 0);
 	update_osd_msg();
 	current_module = "decode_video";
 	decoded_frame = decode_video(sh_video, start, in_size, drop_frame,
@@ -2249,6 +2251,7 @@
 	// be completely wrong (probably 0).
 	mpctx->sh_video->pts = mpctx->d_video->pts;
 	update_subtitles(mpctx->sh_video, mpctx->d_sub, 1);
+	update_teletext(mpctx->sh_video, mpctx->demuxer, 1);
     }
       
     if (mpctx->sh_audio) {
Index: mpcommon.c
===================================================================
--- mpcommon.c	(revision 23784)
+++ mpcommon.c	(working copy)
@@ -7,6 +7,9 @@
 #include "libvo/video_out.h"
 #include "spudec.h"
 #include "vobsub.h"
+#ifdef HAVE_TV_TELETEXT
+#include "stream/tv.h"
+#endif
 
 double sub_last_pts = -303;
 
@@ -138,3 +141,19 @@
     }
     current_module=NULL;
 }
+
+void update_teletext(sh_video_t *sh_video, demuxer_t *demuxer, int reset)
+{
+#ifdef HAVE_TV_TELETEXT
+    tvi_handle_t* tvh=demuxer->priv;
+    if (demuxer->type != DEMUXER_TYPE_TV || !tvh) return;
+
+    if(tvh->functions->control(tvh->priv,TV_VBI_CONTROL_GET_VBIPAGE,&vo_osd_teletext_page)!=TVI_CONTROL_TRUE)
+        vo_osd_teletext_page=NULL;
+    if(tvh->functions->control(tvh->priv,TV_VBI_CONTROL_GET_HALF_PAGE,&vo_osd_teletext_half)!=TVI_CONTROL_TRUE)
+        vo_osd_teletext_half=0;
+    if(tvh->functions->control(tvh->priv,TV_VBI_CONTROL_GET_MODE,&vo_osd_teletext_mode)!=TVI_CONTROL_TRUE)
+        vo_osd_teletext_mode=0;
+    vo_osd_changed(OSDTYPE_TELETEXT);
+#endif
+}


More information about the MPlayer-dev-eng mailing list