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"
48 //#define VTXDIR "/opt/TTx_Server/spool"
49 //#define VTXDIR "/video/vtx"
50 #define USAGE "\nUSAGE: dvbtext tpid1 tpid2 tpid3 .. tpid8\n\n"
52 // There seems to be a limit of 8 teletext streams - OK for most (but
53 // not all) transponders.
54 #define MAX_CHANNELS 9
56 typedef struct mag_struct_ {
62 unsigned char pagebuf[25*40];
66 // unham 2 bytes into 1, report 2 bit errors but ignore them
67 unsigned char unham(unsigned char a,unsigned char b)
74 // fprintf(stderr,"bad ham!");
75 return (c2<<4)|(0x0f&c1);
78 void write_data(unsigned char* b, int n) {
82 fprintf(stderr," %02x",b[i]);
86 fprintf(stderr,"%c",b[i]&0x7f);
91 void set_line(mag_struct *mag, int line, unsigned char* data,int pnr) {
99 memset(mag->pagebuf,' ', 25*40);
100 mag->pnum=unham(data[0],data[1]); // The lower two (hex) numbers of page
101 if (mag->pnum==0xff) return; // These are filler lines. Can use to update clock
102 // fprintf(stderr,"pagenum: %03x\n",c+mag->mag*0x100);
103 mag->flags=unham(data[2],data[3])&0x80;
104 mag->flags|=(c&0x40)|((c>>2)&0x20);
105 c=unham(data[6],data[7]);
106 mag->flags|=((c<<4)&0x10)|((c<<2)&0x08)|(c&0x04)|((c>>1)&0x02)|((c>>4)&0x01);
107 mag->lang=((c>>5) & 0x07);
109 mag->sub=(unham(data[4],data[5])<<8)|(unham(data[2],data[3])&0x3f7f);
110 // mag->pnum = (mag->mag<<8)|((mag->sub&0x3f7f)<<16)|page;
111 // fprintf(stderr,"page: %x, pnum: %x, sub: %x\n",page,mag->pnum,mag->sub);
116 memcpy(mag->pagebuf+40*line,data,40);
120 sprintf(fname,"%s/%d/%03x_%02x.vtx",VTXDIR,pnr,mag->pnum+(mag->mag*0x100),mag->sub&0xff);
121 // fprintf(stderr,"Writing to file %s\n",fname);
122 if ((fd=fopen(fname,"w"))) {
123 fwrite("VTXV4",1,5,fd);
124 buf=0x01; fwrite(&buf,1,1,fd);
125 buf=mag->mag; fwrite(&buf,1,1,fd);
126 buf=mag->pnum; fwrite(&buf,1,1,fd);
127 buf=0x00; fwrite(&buf,1,1,fd); /* subpage?? */
128 buf=0x00; fwrite(&buf,1,1,fd);
129 buf=0x00; fwrite(&buf,1,1,fd);
130 buf=0x00; fwrite(&buf,1,1,fd);
131 fwrite(mag->pagebuf,1,24*40,fd);
140 void set_tt_filt(int fd,uint16_t tt_pid)
142 struct dmx_pes_filter_params pesFilterParams;
144 pesFilterParams.pid = tt_pid;
145 pesFilterParams.input = DMX_IN_FRONTEND;
146 pesFilterParams.output = DMX_OUT_TS_TAP;
147 pesFilterParams.pes_type = DMX_PES_OTHER;
148 pesFilterParams.flags = DMX_IMMEDIATE_START;
150 if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
151 fprintf(stderr,"FILTER %i: ",tt_pid);
152 perror("DMX SET PES FILTER");
156 void set_tt_filt(int fd,uint16_t tt_pid)
158 struct dmxPesFilterParams pesFilterParams;
160 pesFilterParams.pid = tt_pid;
161 pesFilterParams.input = DMX_IN_FRONTEND;
162 pesFilterParams.output = DMX_OUT_TS_TAP;
163 pesFilterParams.pesType = DMX_PES_OTHER;
164 pesFilterParams.flags = DMX_IMMEDIATE_START;
166 if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
167 fprintf(stderr,"FILTER %i: ",tt_pid);
168 perror("DMX SET PES FILTER");
173 int main(int argc, char **argv)
177 unsigned char buf[188]; /* data buffer */
178 unsigned char mpag,mag,pack;
182 /* Test channels - Astra 19E, 11837h, SR 27500 - e.g. ARD */
183 int pids[MAX_CHANNELS];
184 int pnrs[MAX_CHANNELS]={ 1,2,3,4,5,6,7,8 }; /* Directory names */
186 mag_struct mags[MAX_CHANNELS][8];
187 int fd[MAX_CHANNELS];
190 printf("dvbtext v%s - (C) Dave Chapman 2001\n",VERSION);
191 printf("Latest version available from http://www.linuxstb.org/dvbtext\n");
198 for (i=1;i<argc;i++) {
199 pids[count]=atoi(argv[i]);
200 if (pids[count]) { count++ ; }
206 printf("\nSorry, you can only set up to 8 filters.\n\n");
209 printf("Decoding %d teletext stream%s into %s/*\n",count,(count==1 ? "" : "s"),VTXDIR);
216 for (m=0;m<count;m++) {
224 for (i=0;i<count;i++) {
226 if((fd[i] = open("/dev/dvb/adapter1/demux0",O_RDWR)) < 0){
228 if((fd[i] = open("/dev/ost/demux",O_RDWR)) < 0){
230 fprintf(stderr,"FD %i: ",i);
231 perror("DEMUX DEVICE: ");
237 if((fd_dvr = open("/dev/dvb/adapter1/dvr0",O_RDONLY)) < 0){
239 if((fd_dvr = open("/dev/ost/dvr",O_RDONLY)) < 0){
241 perror("DVR DEVICE: ");
245 /* Now we set the filters */
246 for (i=0;i<count;i++) {
247 set_tt_filt(fd[i],pids[i]);
251 n = read(fd_dvr,buf,188);
252 // fprintf(stderr,"Read %d bytes\n",n);
253 // n=fwrite(buf,1,n,stdout);
254 // fprintf(stderr,"Wrote %d bytes\n",n);
257 pid= ((buf[1] & 0x1f) << 8) | buf[2];
258 for (i=0;i<count;i++) {
260 // fprintf(stderr,"Received packet for PUD %i\n",pid);
266 // fprintf(stderr,"pid: %i\n",pid);
267 // fprintf(stderr,"ts_id %i\n",buf[3]);
269 // fprintf(stderr,"data_identifier =0x%02x\n",buf[0x31]);
271 if (buf[4+i*46]==2) {
272 for (j=(8+i*46);j<(50+i*46);j++) { buf[j]=invtab[buf[j]]; }
273 // fprintf(stderr,"data[%d].data_unit_id =0x%02x\n",i,buf[0x4+i*46]);
274 // fprintf(stderr,"data[%d].data_unit_length=0x%02x\n",i,buf[0x5+i*46]);
275 // fprintf(stderr,"data[%d].fp_lo =0x%02x\n",i,buf[0x6+i*46]);
276 // fprintf(stderr,"data[%d].fc =0x%02x\n",i,buf[0x7+i*46]);
277 // fprintf(stderr,"data[%d].mapa_1 =0x%02x\n",i,buf[0x8+i*46]);
278 // fprintf(stderr,"data[%d].mapa_2 =0x%02x\n",i,buf[0x9+i*46]);
279 // fprintf(stderr,"data[%d].data =",i);
280 // write_data(&buf[0x0a+i*46],40);
282 mpag=unham(buf[0x8+i*46],buf[0x9+i*46]);
285 set_line(&mags[m][mag],pack,&buf[10+i*46],pnrs[m]);
286 // fprintf(stderr,"i: %d mag=%d,pack=%d\n",i,mag,pack);
291 // fwrite(buf,1,n,stdout);
295 /* We never get here - but I'm including this for completeness. */
296 /* I hope that this doesn't cause any problems */
297 for (i=0;i<count;i++) close(fd[i]);