3 dvbtext - a teletext decoder for DVB cards.
4 (C) Dave Chapman <dave@dchapman.com> 2001.
6 The latest version can be found at http://www.linuxstb.org/dvbtext
10 Ralph Metzler for his work on both the DVB driver and his old
11 vbidecode package (some code and ideas in dvbtext are borrowed
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; either version 2 of the License, or
19 (at your option) any later version.
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36 #include <sys/ioctl.h>
40 #include <linux/dvb/dmx.h>
47 #define VTXDIR "/run/ttxd/spool"
49 //#define VTXDIR "/opt/TTx_Server/spool"
50 //#define VTXDIR "/video/vtx"
51 #define USAGE "\nUSAGE: dvbtext tpid1 tpid2 tpid3 .. tpid8\n\n"
53 // There seems to be a limit of 8 teletext streams - OK for most (but
54 // not all) transponders.
55 #define MAX_CHANNELS 9
57 typedef struct mag_struct_
{
63 unsigned char pagebuf
[25*40];
67 // unham 2 bytes into 1, report 2 bit errors but ignore them
68 unsigned char unham(unsigned char a
,unsigned char b
)
75 // fprintf(stderr,"bad ham!");
76 return (c2
<<4)|(0x0f&c1
);
79 void write_data(unsigned char* b
, int n
) {
83 fprintf(stderr
," %02x",b
[i
]);
87 fprintf(stderr
,"%c",b
[i
]&0x7f);
92 void set_line(mag_struct
*mag
, int line
, unsigned char* data
,int pnr
) {
100 memset(mag
->pagebuf
,' ', 25*40);
101 mag
->pnum
=unham(data
[0],data
[1]); // The lower two (hex) numbers of page
102 if (mag
->pnum
==0xff) return; // These are filler lines. Can use to update clock
103 // fprintf(stderr,"pagenum: %03x\n",c+mag->mag*0x100);
104 mag
->flags
=unham(data
[2],data
[3])&0x80;
105 mag
->flags
|=(c
&0x40)|((c
>>2)&0x20);
106 c
=unham(data
[6],data
[7]);
107 mag
->flags
|=((c
<<4)&0x10)|((c
<<2)&0x08)|(c
&0x04)|((c
>>1)&0x02)|((c
>>4)&0x01);
108 mag
->lang
=((c
>>5) & 0x07);
110 mag
->sub
=(unham(data
[4],data
[5])<<8)|(unham(data
[2],data
[3])&0x3f7f);
111 // mag->pnum = (mag->mag<<8)|((mag->sub&0x3f7f)<<16)|page;
112 // fprintf(stderr,"page: %x, pnum: %x, sub: %x\n",page,mag->pnum,mag->sub);
117 memcpy(mag
->pagebuf
+40*line
,data
,40);
121 sprintf(fname
,"%s/%d/%03x_%02x.vtx",VTXDIR
,pnr
,mag
->pnum
+(mag
->mag
*0x100),mag
->sub
&0xff);
122 // fprintf(stderr,"Writing to file %s\n",fname);
123 if ((fd
=fopen(fname
,"w"))) {
124 fwrite("VTXV4",1,5,fd
);
125 buf
=0x01; fwrite(&buf
,1,1,fd
);
126 buf
=mag
->mag
; fwrite(&buf
,1,1,fd
);
127 buf
=mag
->pnum
; fwrite(&buf
,1,1,fd
);
128 buf
=0x00; fwrite(&buf
,1,1,fd
); /* subpage?? */
129 buf
=0x00; fwrite(&buf
,1,1,fd
);
130 buf
=0x00; fwrite(&buf
,1,1,fd
);
131 buf
=0x00; fwrite(&buf
,1,1,fd
);
132 fwrite(mag
->pagebuf
,1,24*40,fd
);
141 void set_tt_filt(int fd
,uint16_t tt_pid
)
143 struct dmx_pes_filter_params pesFilterParams
;
145 pesFilterParams
.pid
= tt_pid
;
146 pesFilterParams
.input
= DMX_IN_FRONTEND
;
147 pesFilterParams
.output
= DMX_OUT_TS_TAP
;
148 pesFilterParams
.pes_type
= DMX_PES_OTHER
;
149 pesFilterParams
.flags
= DMX_IMMEDIATE_START
;
151 if (ioctl(fd
, DMX_SET_PES_FILTER
, &pesFilterParams
) < 0) {
152 fprintf(stderr
,"FILTER %i: ",tt_pid
);
153 perror("DMX SET PES FILTER");
157 void set_tt_filt(int fd
,uint16_t tt_pid
)
159 struct dmxPesFilterParams pesFilterParams
;
161 pesFilterParams
.pid
= tt_pid
;
162 pesFilterParams
.input
= DMX_IN_FRONTEND
;
163 pesFilterParams
.output
= DMX_OUT_TS_TAP
;
164 pesFilterParams
.pesType
= DMX_PES_OTHER
;
165 pesFilterParams
.flags
= DMX_IMMEDIATE_START
;
167 if (ioctl(fd
, DMX_SET_PES_FILTER
, &pesFilterParams
) < 0) {
168 fprintf(stderr
,"FILTER %i: ",tt_pid
);
169 perror("DMX SET PES FILTER");
174 int main(int argc
, char **argv
)
178 unsigned char buf
[188]; /* data buffer */
179 unsigned char mpag
,mag
,pack
;
183 /* Test channels - Astra 19E, 11837h, SR 27500 - e.g. ARD */
184 int pids
[MAX_CHANNELS
];
185 int pnrs
[MAX_CHANNELS
]={ 1,2,3,4,5,6,7,8 }; /* Directory names */
187 mag_struct mags
[MAX_CHANNELS
][8];
188 int fd
[MAX_CHANNELS
];
191 printf("dvbtext v%s - (C) Dave Chapman 2001\n",VERSION
);
192 printf("Latest version available from http://www.linuxstb.org/dvbtext\n");
199 for (i
=1;i
<argc
;i
++) {
200 pids
[count
]=atoi(argv
[i
]);
201 if (pids
[count
]) { count
++ ; }
207 printf("\nSorry, you can only set up to 8 filters.\n\n");
210 printf("Decoding %d teletext stream%s into %s/*\n",count
,(count
==1 ? "" : "s"),VTXDIR
);
217 for (m
=0;m
<count
;m
++) {
225 for (i
=0;i
<count
;i
++) {
227 if((fd
[i
] = open("/dev/dvb/adapter"ADAPTER
"/demux0",O_RDWR
)) < 0){
229 if((fd
[i
] = open("/dev/ost/demux",O_RDWR
)) < 0){
231 fprintf(stderr
,"FD %i: ",i
);
232 perror("DEMUX DEVICE: ");
238 if((fd_dvr
= open("/dev/dvb/adapter"ADAPTER
"/dvr0",O_RDONLY
)) < 0){
240 if((fd_dvr
= open("/dev/ost/dvr",O_RDONLY
)) < 0){
242 perror("DVR DEVICE: ");
246 /* Now we set the filters */
247 for (i
=0;i
<count
;i
++) {
248 set_tt_filt(fd
[i
],pids
[i
]);
252 n
= read(fd_dvr
,buf
,188);
253 // fprintf(stderr,"Read %d bytes\n",n);
254 // n=fwrite(buf,1,n,stdout);
255 // fprintf(stderr,"Wrote %d bytes\n",n);
258 pid
= ((buf
[1] & 0x1f) << 8) | buf
[2];
259 for (i
=0;i
<count
;i
++) {
261 // fprintf(stderr,"Received packet for PUD %i\n",pid);
267 // fprintf(stderr,"pid: %i\n",pid);
268 // fprintf(stderr,"ts_id %i\n",buf[3]);
270 // fprintf(stderr,"data_identifier =0x%02x\n",buf[0x31]);
272 if (buf
[4+i
*46]==3) {
273 //if (buf[4+i*46]==2) {
274 for (j
=(8+i
*46);j
<(50+i
*46);j
++) { buf
[j
]=invtab
[buf
[j
]]; }
275 // fprintf(stderr,"data[%d].data_unit_id =0x%02x\n",i,buf[0x4+i*46]);
276 // fprintf(stderr,"data[%d].data_unit_length=0x%02x\n",i,buf[0x5+i*46]);
277 // fprintf(stderr,"data[%d].fp_lo =0x%02x\n",i,buf[0x6+i*46]);
278 // fprintf(stderr,"data[%d].fc =0x%02x\n",i,buf[0x7+i*46]);
279 // fprintf(stderr,"data[%d].mapa_1 =0x%02x\n",i,buf[0x8+i*46]);
280 // fprintf(stderr,"data[%d].mapa_2 =0x%02x\n",i,buf[0x9+i*46]);
281 // fprintf(stderr,"data[%d].data =",i);
282 // write_data(&buf[0x0a+i*46],40);
284 mpag
=unham(buf
[0x8+i
*46],buf
[0x9+i
*46]);
287 set_line(&mags
[m
][mag
],pack
,&buf
[10+i
*46],pnrs
[m
]);
288 // fprintf(stderr,"i: %d mag=%d,pack=%d\n",i,mag,pack);
293 // fwrite(buf,1,n,stdout);
297 /* We never get here - but I'm including this for completeness. */
298 /* I hope that this doesn't cause any problems */
299 for (i
=0;i
<count
;i
++) close(fd
[i
]);