]> git.gir.st - ttxd.git/blob - src/dvbtext-src/dvbtext.c
update to dvb-t2 (new hardware, software)
[ttxd.git] / src / dvbtext-src / dvbtext.c
1 /*
2
3 dvbtext - a teletext decoder for DVB cards.
4 (C) Dave Chapman <dave@dchapman.com> 2001.
5
6 The latest version can be found at http://www.linuxstb.org/dvbtext
7
8 Thanks to:
9
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
12 from vbidecode).
13
14 Copyright notice:
15
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.
20
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.
25
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.
29
30 */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <stdint.h>
35 #include <string.h>
36 #include <sys/ioctl.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39 #ifdef NEWSTRUCT
40 #include <linux/dvb/dmx.h>
41 #else
42 #include <ost/dmx.h>
43 #endif
44 #include "tables.h"
45
46 #define VERSION "0.1"
47 #define VTXDIR "/run/ttxd/spool"
48 #define ADAPTER "0"
49 //#define VTXDIR "/opt/TTx_Server/spool"
50 //#define VTXDIR "/video/vtx"
51 #define USAGE "\nUSAGE: dvbtext tpid1 tpid2 tpid3 .. tpid8\n\n"
52
53 // There seems to be a limit of 8 teletext streams - OK for most (but
54 // not all) transponders.
55 #define MAX_CHANNELS 9
56
57 typedef struct mag_struct_ {
58 int valid;
59 int mag;
60 unsigned char flags;
61 unsigned char lang;
62 int pnum,sub;
63 unsigned char pagebuf[25*40];
64 } mag_struct;
65
66 // FROM vbidecode
67 // unham 2 bytes into 1, report 2 bit errors but ignore them
68 unsigned char unham(unsigned char a,unsigned char b)
69 {
70 unsigned char c1,c2;
71
72 c1=unhamtab[a];
73 c2=unhamtab[b];
74 // if ((c1|c2)&0x40)
75 // fprintf(stderr,"bad ham!");
76 return (c2<<4)|(0x0f&c1);
77 }
78
79 void write_data(unsigned char* b, int n) {
80 int i;
81
82 for (i=0;i<n;i++) {
83 fprintf(stderr," %02x",b[i]);
84 }
85 fprintf(stderr,"\n");
86 for (i=0;i<n;i++) {
87 fprintf(stderr,"%c",b[i]&0x7f);
88 }
89 fprintf(stderr,"\n");
90 }
91
92 void set_line(mag_struct *mag, int line, unsigned char* data,int pnr) {
93 unsigned char c;
94 FILE * fd;
95 char fname[80];
96 unsigned char buf;
97
98 if (line==0) {
99 mag->valid=1;
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);
109
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);
113 }
114
115 if (mag->valid) {
116 if (line <= 23) {
117 memcpy(mag->pagebuf+40*line,data,40);
118 }
119
120 if (line==23) {
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);
133 fclose(fd);
134 }
135 mag->valid=0;
136 }
137 }
138 }
139
140 #ifdef NEWSTRUCT
141 void set_tt_filt(int fd,uint16_t tt_pid)
142 {
143 struct dmx_pes_filter_params pesFilterParams;
144
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;
150
151 if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
152 fprintf(stderr,"FILTER %i: ",tt_pid);
153 perror("DMX SET PES FILTER");
154 }
155 }
156 #else
157 void set_tt_filt(int fd,uint16_t tt_pid)
158 {
159 struct dmxPesFilterParams pesFilterParams;
160
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;
166
167 if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
168 fprintf(stderr,"FILTER %i: ",tt_pid);
169 perror("DMX SET PES FILTER");
170 }
171 }
172 #endif
173
174 int main(int argc, char **argv)
175 {
176 int pid;
177 int i,j,n,m;
178 unsigned char buf[188]; /* data buffer */
179 unsigned char mpag,mag,pack;
180
181 int fd_dvr;
182
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 */
186
187 mag_struct mags[MAX_CHANNELS][8];
188 int fd[MAX_CHANNELS];
189 int count;
190
191 printf("dvbtext v%s - (C) Dave Chapman 2001\n",VERSION);
192 printf("Latest version available from http://www.linuxstb.org/dvbtext\n");
193
194 if (argc==1) {
195 printf(USAGE);
196 return(-1);
197 } else {
198 count=0;
199 for (i=1;i<argc;i++) {
200 pids[count]=atoi(argv[i]);
201 if (pids[count]) { count++ ; }
202 }
203 }
204
205 if (count) {
206 if (count > 8) {
207 printf("\nSorry, you can only set up to 8 filters.\n\n");
208 return(-1);
209 } else {
210 printf("Decoding %d teletext stream%s into %s/*\n",count,(count==1 ? "" : "s"),VTXDIR);
211 }
212 } else {
213 printf(USAGE);
214 return(-1);
215 }
216
217 for (m=0;m<count;m++) {
218 mags[m][0].mag=8;
219 for (i=1;i<8;i++) {
220 mags[m][i].mag=i;
221 mags[m][i].valid=0;
222 }
223 }
224
225 for (i=0;i<count;i++) {
226 #ifdef NEWSTRUCT
227 if((fd[i] = open("/dev/dvb/adapter"ADAPTER"/demux0",O_RDWR)) < 0){
228 #else
229 if((fd[i] = open("/dev/ost/demux",O_RDWR)) < 0){
230 #endif
231 fprintf(stderr,"FD %i: ",i);
232 perror("DEMUX DEVICE: ");
233 return -1;
234 }
235 }
236
237 #ifdef NEWSTRUCT
238 if((fd_dvr = open("/dev/dvb/adapter"ADAPTER"/dvr0",O_RDONLY)) < 0){
239 #else
240 if((fd_dvr = open("/dev/ost/dvr",O_RDONLY)) < 0){
241 #endif
242 perror("DVR DEVICE: ");
243 return -1;
244 }
245
246 /* Now we set the filters */
247 for (i=0;i<count;i++) {
248 set_tt_filt(fd[i],pids[i]);
249 }
250
251 while (1) {
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);
256
257 m=-1;
258 pid= ((buf[1] & 0x1f) << 8) | buf[2];
259 for (i=0;i<count;i++) {
260 if (pid==pids[i]) {
261 // fprintf(stderr,"Received packet for PUD %i\n",pid);
262 m=i;
263 }
264 }
265
266 if (pid!=-1) {
267 // fprintf(stderr,"pid: %i\n",pid);
268 // fprintf(stderr,"ts_id %i\n",buf[3]);
269
270 // fprintf(stderr,"data_identifier =0x%02x\n",buf[0x31]);
271 for (i=0;i<4;i++) {
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);
283
284 mpag=unham(buf[0x8+i*46],buf[0x9+i*46]);
285 mag=mpag&7;
286 pack=(mpag>>3)&0x1f;
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);
289 }
290 }
291 // fflush(stdout);
292
293 // fwrite(buf,1,n,stdout);
294 }
295 }
296
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]);
300 close(fd_dvr);
301 return(0);
302 }
Imprint / Impressum