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