[MPlayer-dev-eng] [PATCH] Add DVB teletext support

Reimar Döffinger Reimar.Doeffinger at gmx.de
Sun Aug 30 20:58:01 CEST 2009


On Sun, Aug 30, 2009 at 06:47:48PM +0000, Carl Eugen Hoyos wrote:
> Francesco Lavra <francescolavra <at> interfree.it> writes:
> 
> > I tried playing a DVB stream using the libavformat demuxer, and it
> > doesn't work. Using the command
> > mplayer -demuxer lavf dvb://<channel_name>
> > it hangs in av_open_input_stream(), while if I dump a DVB stream in a
> > file and try to play it with -demuxer lavf MPlayer exits with "LAVF: no
> > audio or video headers found - broken file?". Of course, in both cases
> > playing with the native TS demuxer works fine.
> 
> demuxer lavf does not work on ts files for some time.

It does work for me both with dvb directly and with captured files,
though not reliably.

> > Having said that, is still a pre-requisite that DVB teletext decoding
> > must work with libavformat to be included in MPlayer?
> 
> Definitely not.

Well, the design must in principle allow working with libavformat.
Something that you'd basically have to throw completely away and
rewrite from scratch to make it work with anything but the native ts
demuxer definitely isn't fine.
I attached the results of my hacks, but I am stuck since what comes out
of the demuxer (whether native or lavf) is not even slightly similar
to teletext data...
-------------- next part --------------
Index: stream/tvi_vbi.c
===================================================================
--- stream/tvi_vbi.c	(revision 29554)
+++ stream/tvi_vbi.c	(working copy)
@@ -99,7 +99,7 @@
 #include "input/input.h"
 #include "osdep/timer.h"
 
-//#define DEBUG_DUMP 1
+#define DEBUG_DUMP 1
 
 /// page magazine entry structure
 typedef struct mag_s{
@@ -898,7 +898,7 @@
         return;
     fprintf(f,"+========================================+\n");
     fprintf(f,"| lang:%d pagenum:0x%x subpagenum:%d flags:0x%x|\n",
-    pt->lang,
+    pt->primary_lang,
     pt->pagenum,
     pt->subpagenum,
     0);
@@ -1471,7 +1471,8 @@
     int d0,d1;
     int i=0;
     mp_msg(MSGT_TV,MSGL_DBG3,"vbi: vbi_decode\n");
-    for(linep=buf; !priv->cache_reset && linep<buf+priv->ptsp->bufsize; linep+=priv->ptsp->samples_per_line,i++){
+//    for(linep=buf; !priv->cache_reset && linep<buf+priv->ptsp->bufsize; linep+=priv->ptsp->samples_per_line,i++){
+{
 #if 0
         /*
           This routine is alternative implementation of raw VBI data decoding.
@@ -1480,9 +1481,10 @@
         */
         if(decode_raw_line_sine(priv,linep,data)<=0){
 #endif
-        if(decode_raw_line_runin(priv,linep,data)<=0){
-             continue; //this is not valid teletext line
-        }
+//        if(decode_raw_line_runin(priv,linep,data)<=0){
+//             continue; //this is not valid teletext line
+//        }
+memcpy(data, buf, 64);
         d0= corrHamm48[ data[0] ];
         d1= corrHamm48[ data[1] ];
 
@@ -1490,7 +1492,7 @@
            pll_add(priv,2,4);
            mp_msg(MSGT_TV,MSGL_V,"vbi_decode(%d):HammErr after decode_raw_line\n",i);
 
-           continue; //hamError
+//           continue; //hamError
         }
         magAddr=d0 & 0x7;
         pkt=(d0>>3)|(d1<<1);
@@ -1499,7 +1501,7 @@
         if(!pkt){
             decode_pkt0(priv,data+2,magAddr); //skip MRGA
         }else if(pkt>0 && pkt<VBI_ROWS){
-            if(!priv->mag[magAddr].pt) continue;
+//            if(!priv->mag[magAddr].pt) continue;
             decode_pkt_page(priv,data+2,magAddr,pkt);//skip MRGA
         }else if(pkt==27) {
             decode_pkt27(priv,data+2,magAddr);
Index: libmpdemux/demux_lavf.c
===================================================================
--- libmpdemux/demux_lavf.c	(revision 29554)
+++ libmpdemux/demux_lavf.c	(working copy)
@@ -385,6 +385,8 @@
                 type = 'a';
             else if(codec->codec_id == CODEC_ID_DVD_SUBTITLE)
                 type = 'v';
+            else if(codec->codec_id == CODEC_ID_DVB_TELETEXT)
+                type = 'd';
             else
                 break;
             sh_sub = new_sh_sub_sid(demuxer, i, priv->sub_streams);
Index: mpcommon.c
===================================================================
--- mpcommon.c	(revision 29554)
+++ mpcommon.c	(working copy)
@@ -12,6 +12,7 @@
 #include "version.h"
 #include "vobsub.h"
 #include "stream/tv.h"
+int teletext_control(void* p, int cmd, void *arg);
 #include "libavutil/intreadwrite.h"
 #include "m_option.h"
 
@@ -65,6 +66,9 @@
 }
 
 
+static void *teletext;
+void update_teletext(void);
+
 void update_subtitles(sh_video_t *sh_video, demux_stream_t *d_dvdsub, int reset)
 {
     unsigned char *packet=NULL;
@@ -142,10 +146,17 @@
 
         if (spudec_changed(vo_spudec))
             vo_osd_changed(OSDTYPE_SPU);
-    } else if (dvdsub_id >= 0 && (type == 't' || type == 'm' || type == 'a')) {
+    } else if (dvdsub_id >= 0 && (type == 't' || type == 'm' || type == 'a' || type == 'd')) {
         double curpts = sh_video->pts + sub_delay;
         double endpts;
         vo_sub = &subs;
+        if (type == 'd' && !teletext) {
+	    tt_stream_props tsp;
+            memset(&tsp, 0, sizeof(tsp));
+            teletext = &tsp;
+            if (teletext_control(NULL, TV_VBI_CONTROL_START, &teletext) != TVI_CONTROL_TRUE)
+                teletext = NULL;
+        }
         while (d_dvdsub->first) {
             double pts = ds_get_next_pts(d_dvdsub);
             if (pts > curpts)
@@ -157,6 +168,30 @@
                 len = FFMIN(len - 2, AV_RB16(packet));
                 packet += 2;
             }
+            if (type == 'd' && teletext) {
+                uint8_t *p = packet;
+                p++;
+                len--;
+#if 0
+int i;
+printf("\n");
+for (i = 0; i < len; i++) {
+if (!(i&15)) printf("\n");
+printf(" %02hhx", packet[i]);
+}
+printf("\n");
+#endif
+                while (len >= 44) {
+                    int sublen = p[1];
+                    uint8_t *start = p + 2;
+//printf("bulb! %i %i %x %x\n", len, sublen, (int)p[0], (int)p[1]);
+                    if (p[0] == 2 || p[0] == 3)
+                        teletext_control(teletext, TV_VBI_CONTROL_DECODE_PAGE, &start);
+                    p   += sublen + 2;
+                    len -= sublen + 2;
+                }
+                continue;
+            }
 #ifdef CONFIG_ASS
             if (ass_enabled) {
                 sh_sub_t* sh = d_dvdsub->sh;
@@ -198,38 +233,37 @@
                 vo_osd_changed(OSDTYPE_SUBTITLE);
             }
         }
+        if (type == 'd' && teletext)
+            update_teletext();
         if (sub_clear_text(&subs, curpts))
             vo_osd_changed(OSDTYPE_SUBTITLE);
     }
     current_module=NULL;
 }
 
-void update_teletext(sh_video_t *sh_video, demuxer_t *demuxer, int reset)
+void update_teletext(void)
 {
 #ifdef CONFIG_TV_TELETEXT
-    tvi_handle_t* tvh=demuxer->priv;
     int page_changed;
 
-    if (demuxer->type != DEMUXER_TYPE_TV || !tvh) return;
-
     //Also forcing page update when such ioctl is not supported or call error occured
-    if(tvh->functions->control(tvh->priv,TV_VBI_CONTROL_IS_CHANGED,&page_changed)!=TVI_CONTROL_TRUE)
+    if(teletext_control(teletext,TV_VBI_CONTROL_IS_CHANGED,&page_changed)!=TVI_CONTROL_TRUE)
         page_changed=1;
 
     if(!page_changed)
         return;
 
-    if(tvh->functions->control(tvh->priv,TV_VBI_CONTROL_GET_VBIPAGE,&vo_osd_teletext_page)!=TVI_CONTROL_TRUE)
+    if(teletext_control(teletext,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)
+    if(teletext_control(teletext,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)
+    if(teletext_control(teletext,TV_VBI_CONTROL_GET_MODE,&vo_osd_teletext_mode)!=TVI_CONTROL_TRUE)
         vo_osd_teletext_mode=0;
-    if(tvh->functions->control(tvh->priv,TV_VBI_CONTROL_GET_FORMAT,&vo_osd_teletext_format)!=TVI_CONTROL_TRUE)
+    if(teletext_control(teletext,TV_VBI_CONTROL_GET_FORMAT,&vo_osd_teletext_format)!=TVI_CONTROL_TRUE)
         vo_osd_teletext_format=0;
     vo_osd_changed(OSDTYPE_TELETEXT);
 
-    tvh->functions->control(tvh->priv,TV_VBI_CONTROL_MARK_UNCHANGED,NULL);
+    teletext_control(teletext,TV_VBI_CONTROL_MARK_UNCHANGED,NULL);
 #endif
 }
 
Index: libavformat/mpegts.c
===================================================================
--- libavformat/mpegts.c	(revision 19717)
+++ libavformat/mpegts.c	(working copy)
@@ -529,6 +529,7 @@
     { 0x6a, CODEC_TYPE_AUDIO,             CODEC_ID_AC3 }, /* AC-3 descriptor */
     { 0x7a, CODEC_TYPE_AUDIO,            CODEC_ID_EAC3 }, /* E-AC-3 descriptor */
     { 0x7b, CODEC_TYPE_AUDIO,             CODEC_ID_DTS },
+    { 0x56, CODEC_TYPE_SUBTITLE, CODEC_ID_DVB_TELETEXT },
     { 0x59, CODEC_TYPE_SUBTITLE, CODEC_ID_DVB_SUBTITLE }, /* subtitling descriptor */
     { 0 },
 };
@@ -699,6 +700,13 @@
                 mpegts_find_stream_type(st, desc_tag, DESC_types);
 
             switch(desc_tag) {
+            case 0x56: /* DVB teletext descriptor */
+                language[0] = get8(&p, desc_end);
+                language[1] = get8(&p, desc_end);
+                language[2] = get8(&p, desc_end);
+                language[3] = 0;
+                av_metadata_set(&st->metadata, "language", language);
+                break;
             case 0x59: /* subtitling descriptor */
                 language[0] = get8(&p, desc_end);
                 language[1] = get8(&p, desc_end);


More information about the MPlayer-dev-eng mailing list