1 |
pcg |
1.1 |
#include "EXTERN.h" |
2 |
|
|
#include "perl.h" |
3 |
|
|
#include "XSUB.h" |
4 |
|
|
|
5 |
|
|
#include <sys/types.h> |
6 |
|
|
#include <unistd.h> |
7 |
|
|
#include <sys/mman.h> |
8 |
|
|
|
9 |
|
|
#include "../gppport.h" |
10 |
|
|
|
11 |
|
|
/* loosely based on the program vbidecode.cc by Ralph Metzler */ |
12 |
|
|
|
13 |
|
|
typedef unsigned int UI; |
14 |
|
|
typedef unsigned char u8; |
15 |
|
|
typedef U16 u16; |
16 |
|
|
|
17 |
|
|
/* calculates odd parity, medium-efficient */ |
18 |
|
|
static int |
19 |
|
|
parodd(U32 data) |
20 |
|
|
{ |
21 |
|
|
u8 p4[16] = { 0,1,1,0, 1,0,0,1, 1,0,0,1, 0,1,1,0 }; |
22 |
|
|
int parity = 1; |
23 |
|
|
|
24 |
|
|
do { |
25 |
|
|
parity ^= p4[data & 15]; |
26 |
|
|
data >>= 4; |
27 |
|
|
} while (data); |
28 |
|
|
|
29 |
|
|
return parity; |
30 |
|
|
} |
31 |
|
|
|
32 |
|
|
static u8 invtab[256] = { |
33 |
|
|
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, |
34 |
|
|
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, |
35 |
|
|
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, |
36 |
|
|
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, |
37 |
|
|
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, |
38 |
|
|
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, |
39 |
|
|
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, |
40 |
|
|
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, |
41 |
|
|
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, |
42 |
|
|
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, |
43 |
|
|
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, |
44 |
|
|
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, |
45 |
|
|
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, |
46 |
|
|
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, |
47 |
|
|
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, |
48 |
|
|
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, |
49 |
|
|
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, |
50 |
|
|
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, |
51 |
|
|
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, |
52 |
|
|
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, |
53 |
|
|
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, |
54 |
|
|
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, |
55 |
|
|
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, |
56 |
|
|
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, |
57 |
|
|
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, |
58 |
|
|
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, |
59 |
|
|
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, |
60 |
|
|
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, |
61 |
|
|
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, |
62 |
|
|
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, |
63 |
|
|
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, |
64 |
|
|
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, |
65 |
|
|
}; |
66 |
|
|
|
67 |
|
|
static u8 unhamtab[256] = { |
68 |
|
|
0x01, 0xff, 0x81, 0x01, 0xff, 0x00, 0x01, 0xff, |
69 |
|
|
0xff, 0x02, 0x01, 0xff, 0x0a, 0xff, 0xff, 0x07, |
70 |
|
|
0xff, 0x00, 0x01, 0xff, 0x00, 0x80, 0xff, 0x00, |
71 |
|
|
0x06, 0xff, 0xff, 0x0b, 0xff, 0x00, 0x03, 0xff, |
72 |
|
|
0xff, 0x0c, 0x01, 0xff, 0x04, 0xff, 0xff, 0x07, |
73 |
|
|
0x06, 0xff, 0xff, 0x07, 0xff, 0x07, 0x07, 0x87, |
74 |
|
|
0x06, 0xff, 0xff, 0x05, 0xff, 0x00, 0x0d, 0xff, |
75 |
|
|
0x86, 0x06, 0x06, 0xff, 0x06, 0xff, 0xff, 0x07, |
76 |
|
|
0xff, 0x02, 0x01, 0xff, 0x04, 0xff, 0xff, 0x09, |
77 |
|
|
0x02, 0x82, 0xff, 0x02, 0xff, 0x02, 0x03, 0xff, |
78 |
|
|
0x08, 0xff, 0xff, 0x05, 0xff, 0x00, 0x03, 0xff, |
79 |
|
|
0xff, 0x02, 0x03, 0xff, 0x03, 0xff, 0x83, 0x03, |
80 |
|
|
0x04, 0xff, 0xff, 0x05, 0x84, 0x04, 0x04, 0xff, |
81 |
|
|
0xff, 0x02, 0x0f, 0xff, 0x04, 0xff, 0xff, 0x07, |
82 |
|
|
0xff, 0x05, 0x05, 0x85, 0x04, 0xff, 0xff, 0x05, |
83 |
|
|
0x06, 0xff, 0xff, 0x05, 0xff, 0x0e, 0x03, 0xff, |
84 |
|
|
0xff, 0x0c, 0x01, 0xff, 0x0a, 0xff, 0xff, 0x09, |
85 |
|
|
0x0a, 0xff, 0xff, 0x0b, 0x8a, 0x0a, 0x0a, 0xff, |
86 |
|
|
0x08, 0xff, 0xff, 0x0b, 0xff, 0x00, 0x0d, 0xff, |
87 |
|
|
0xff, 0x0b, 0x0b, 0x8b, 0x0a, 0xff, 0xff, 0x0b, |
88 |
|
|
0x0c, 0x8c, 0xff, 0x0c, 0xff, 0x0c, 0x0d, 0xff, |
89 |
|
|
0xff, 0x0c, 0x0f, 0xff, 0x0a, 0xff, 0xff, 0x07, |
90 |
|
|
0xff, 0x0c, 0x0d, 0xff, 0x0d, 0xff, 0x8d, 0x0d, |
91 |
|
|
0x06, 0xff, 0xff, 0x0b, 0xff, 0x0e, 0x0d, 0xff, |
92 |
|
|
0x08, 0xff, 0xff, 0x09, 0xff, 0x09, 0x09, 0x89, |
93 |
|
|
0xff, 0x02, 0x0f, 0xff, 0x0a, 0xff, 0xff, 0x09, |
94 |
|
|
0x88, 0x08, 0x08, 0xff, 0x08, 0xff, 0xff, 0x09, |
95 |
|
|
0x08, 0xff, 0xff, 0x0b, 0xff, 0x0e, 0x03, 0xff, |
96 |
|
|
0xff, 0x0c, 0x0f, 0xff, 0x04, 0xff, 0xff, 0x09, |
97 |
|
|
0x0f, 0xff, 0x8f, 0x0f, 0xff, 0x0e, 0x0f, 0xff, |
98 |
|
|
0x08, 0xff, 0xff, 0x05, 0xff, 0x0e, 0x0d, 0xff, |
99 |
|
|
0xff, 0x0e, 0x0f, 0xff, 0x0e, 0x8e, 0xff, 0x0e, |
100 |
|
|
}; |
101 |
|
|
|
102 |
|
|
#define VBI_BPL 2048 |
103 |
|
|
|
104 |
|
|
#define FREQ_PAL 35.468950 |
105 |
|
|
#define FREQ_NTSC 28.636363 |
106 |
|
|
#define FREQ FREQ_PAL |
107 |
|
|
|
108 |
|
|
#define FREQ_VT_PAL 6.9375 |
109 |
|
|
#define FREQ_VT_NTSC 5.72725 |
110 |
pcg |
1.2 |
#define FREQ_VT FREQ_VT_PAL /* Replace by FREQ_VT_NTSC and pray that it works */ |
111 |
pcg |
1.1 |
/*#define FREQ_VT 6.165*/ /* teletext-like signal on france, 0xe7 instead of 0x27 */ |
112 |
|
|
#define FREQ_CRYPT 4.5 /* found on premiere */ |
113 |
|
|
#define FREQ_VPS 2.5 /* probably only pal */ |
114 |
|
|
#define FREQ_VDAT 2.0 /* videodat */ |
115 |
|
|
#define FREQ_VC 0.77 /* videocrypt, just ignore */ |
116 |
|
|
|
117 |
|
|
#define VBI_VT 0x0001 |
118 |
|
|
#define VBI_VPS 0x0002 |
119 |
|
|
#define VBI_VDAT 0x0004 |
120 |
|
|
#define VBI_VC 0x0008 |
121 |
|
|
#define VBI_OTHER 0x0010 |
122 |
|
|
#define VBI_EMPTY 0x8000 |
123 |
|
|
|
124 |
|
|
typedef long FP; |
125 |
|
|
|
126 |
|
|
#define FP_BITS 16 |
127 |
|
|
#define FP_0_5 D2FP(0.5) |
128 |
|
|
|
129 |
|
|
#define D2FP(d) ((FP)((d) * (1<<FP_BITS) + 0.5)) |
130 |
|
|
#define I2FP(i) ((FP)(i) << FP_BITS) |
131 |
|
|
#define FP2I(fp) (((fp) + FP_0_5) >> FP_BITS) |
132 |
|
|
|
133 |
|
|
#define VT_COLS 40 |
134 |
|
|
#define VT_LINES 36 |
135 |
|
|
|
136 |
|
|
typedef struct { |
137 |
|
|
UI types; /* required types */ |
138 |
|
|
|
139 |
|
|
int offset; /* signal offset */ |
140 |
|
|
int did_agc : 1; /* did we already do agc this frame? */ |
141 |
|
|
|
142 |
|
|
int y; /* the line number */ |
143 |
|
|
u8 *line; /* the current line */ |
144 |
|
|
FP step; /* the bit step */ |
145 |
|
|
FP pos; /* position */ |
146 |
|
|
} decoder; |
147 |
|
|
|
148 |
|
|
static void |
149 |
|
|
decoder_init (decoder *dec, UI types) |
150 |
|
|
{ |
151 |
|
|
dec->types = types; |
152 |
|
|
dec->did_agc = 0; |
153 |
|
|
} |
154 |
|
|
|
155 |
|
|
static void |
156 |
|
|
decoder_scan_start (decoder *dec, UI a, UI b) |
157 |
|
|
{ |
158 |
|
|
u8 *p = dec->line + a; |
159 |
|
|
UI med = 128 - dec->offset; |
160 |
|
|
do |
161 |
|
|
{ |
162 |
|
|
if (*p >= med) |
163 |
|
|
break; |
164 |
|
|
} |
165 |
|
|
while (++p < dec->line + b); |
166 |
|
|
|
167 |
|
|
/* find maximum */ |
168 |
|
|
while (p[1] > p[0]) |
169 |
|
|
p++; |
170 |
|
|
|
171 |
|
|
dec->pos = I2FP (p - dec->line); |
172 |
|
|
} |
173 |
|
|
|
174 |
|
|
|
175 |
|
|
static u8 |
176 |
|
|
get_byte (decoder *dec) |
177 |
|
|
{ |
178 |
|
|
u8 byte; |
179 |
|
|
int bit = 8; |
180 |
|
|
|
181 |
|
|
/* if the next bit is a one bit, try to re-center the decoder on it */ |
182 |
|
|
if ((dec->offset + dec->line[FP2I(dec->pos)]) & 0x80) |
183 |
|
|
{ |
184 |
|
|
/*if (dec->line[FP2I(dec->pos)] < dec->line[FP2I(dec->pos)+1]) |
185 |
|
|
dec->pos += I2FP(1);*/ /* why is this casuing checksum errors? */ |
186 |
|
|
/*if (dec->line[FP2I(dec->pos)] < dec->line[FP2I(dec->pos)-1]) |
187 |
|
|
dec->pos -= I2FP(1);*/ |
188 |
|
|
} |
189 |
|
|
|
190 |
|
|
byte=0; |
191 |
|
|
do |
192 |
|
|
{ |
193 |
|
|
byte >>= 1; |
194 |
|
|
byte |= ((dec->offset + dec->line[FP2I(dec->pos)]) & 0x80); |
195 |
|
|
dec->pos += dec->step; |
196 |
|
|
} |
197 |
|
|
while (--bit); |
198 |
|
|
|
199 |
|
|
return byte; |
200 |
|
|
} |
201 |
|
|
|
202 |
|
|
/* get shift-encoded byte */ |
203 |
|
|
static u8 |
204 |
|
|
get_byte_SE (decoder *dec) |
205 |
|
|
{ |
206 |
|
|
u8 byte; |
207 |
|
|
int bit = 8; |
208 |
|
|
|
209 |
|
|
do |
210 |
|
|
{ |
211 |
|
|
byte >>= 1; |
212 |
|
|
byte |= (dec->line[FP2I(dec->pos)] |
213 |
|
|
> dec->line[FP2I(dec->pos + dec->step/2)]) << 7; |
214 |
|
|
dec->pos += dec->step; |
215 |
|
|
} |
216 |
|
|
while (--bit); |
217 |
|
|
|
218 |
|
|
/* if the next bit is a one bit, try to re-center the decoder on it */ |
219 |
|
|
if (dec->line[FP2I(dec->pos)] > 128-dec->offset) |
220 |
|
|
{ |
221 |
|
|
if (dec->line[FP2I(dec->pos)] > dec->line[FP2I(dec->pos)+1]) |
222 |
|
|
dec->pos += I2FP(1); |
223 |
|
|
if (dec->line[FP2I(dec->pos)] < dec->line[FP2I(dec->pos)-1]) |
224 |
|
|
dec->pos -= I2FP(1); |
225 |
|
|
} |
226 |
|
|
|
227 |
|
|
return byte; |
228 |
|
|
} |
229 |
|
|
|
230 |
|
|
static u8 |
231 |
|
|
unham4(u8 a) |
232 |
|
|
{ |
233 |
|
|
return unhamtab[a] & 15; |
234 |
|
|
} |
235 |
|
|
|
236 |
|
|
static u8 |
237 |
|
|
unham8(u8 a, u8 b) |
238 |
|
|
{ |
239 |
|
|
u8 c1 = unhamtab[a]; |
240 |
|
|
u8 c2 = unhamtab[b]; |
241 |
|
|
|
242 |
|
|
if ( (c1|c2) & 0x40) |
243 |
|
|
/* 2 bit error */; |
244 |
|
|
|
245 |
|
|
return (c1 & 15) |
246 |
|
|
| (c2 << 4); |
247 |
|
|
} |
248 |
|
|
|
249 |
|
|
static u16 unham16(u8 a, u8 b, u8 c) |
250 |
|
|
{ |
251 |
|
|
U32 d = (((c << 8) | b) << 8) | c; |
252 |
|
|
int A = parodd (d & 0x555555); |
253 |
|
|
int B = parodd (d & 0x666666); |
254 |
|
|
int C = parodd (d & 0x787878); |
255 |
|
|
int D = parodd (d & 0x007f80); |
256 |
|
|
int E = parodd (d & 0x7f8000); |
257 |
|
|
int F = parodd (d & 0xffffff); |
258 |
|
|
int bit; |
259 |
|
|
|
260 |
|
|
d = (((d >> 16) & 0x7f) << 11) |
261 |
|
|
| (((d >> 8) & 0x7f) << 4) |
262 |
|
|
| (((d >> 4) & 0x07) << 1) |
263 |
|
|
| (((d >> 2) & 0x01) ); |
264 |
|
|
|
265 |
|
|
if (A&B&C&D&E) |
266 |
|
|
return d; |
267 |
|
|
if (F) |
268 |
|
|
return -1; /* double bit error */ |
269 |
|
|
|
270 |
|
|
/* correct the single bit error */ |
271 |
|
|
return d ^ (1 << (31 - 16*E + 8*D + 4*C + 2*B + A)); |
272 |
|
|
} |
273 |
|
|
|
274 |
|
|
static unsigned char |
275 |
|
|
rev (unsigned char x) |
276 |
|
|
{ |
277 |
|
|
return ((x>>7)&1)<<0 | |
278 |
|
|
((x>>6)&1)<<1 | |
279 |
|
|
((x>>5)&1)<<2 | |
280 |
|
|
((x>>4)&1)<<3 | |
281 |
|
|
((x>>3)&1)<<4 | |
282 |
|
|
((x>>2)&1)<<5 | |
283 |
|
|
((x>>1)&1)<<6 | |
284 |
|
|
((x>>0)&1)<<7; |
285 |
|
|
} |
286 |
|
|
|
287 |
|
|
static SV * |
288 |
|
|
decoder_decode_vps (decoder *dec, u8 *data) |
289 |
|
|
{ |
290 |
|
|
AV *av = newAV (); |
291 |
|
|
|
292 |
|
|
av_push (av, newSViv (VBI_VPS)); |
293 |
|
|
av_push (av, newSVpvn (data+3, 1)); |
294 |
|
|
av_push (av, newSViv (data[4] & 3)); /* "unknown", "stereo ", "mono ", "dual " */ |
295 |
|
|
/* ch, day, mon, hour, min */ |
296 |
|
|
av_push (av, newSViv (rev (data[ 4]) <<12 & 0xf000 |
297 |
|
|
| rev (data[10]) & 0x00c0 |
298 |
|
|
| rev (data[12]) <<10 & 0x0c00 |
299 |
|
|
| rev (data[13]) << 2 & 0x0300 |
300 |
|
|
| rev (data[13]) & 0x003f)); |
301 |
|
|
av_push (av, newSViv (rev (data[10]) >> 1 & 31)); |
302 |
|
|
av_push (av, newSViv (rev (data[10]) << 3 & 8 | rev (data[11]) >> 5)); |
303 |
|
|
av_push (av, newSViv (rev (data[11]) & 31)); |
304 |
|
|
av_push (av, newSViv (rev (data[12]) >> 2)); |
305 |
|
|
av_push (av, newSViv (rev (data[14]))); |
306 |
|
|
|
307 |
|
|
return newRV_noinc ((SV*)av); |
308 |
|
|
} |
309 |
|
|
|
310 |
|
|
static SV * |
311 |
|
|
decoder_decode_vt (decoder *dec, u8 *data) |
312 |
|
|
{ |
313 |
|
|
AV *av = newAV (); |
314 |
|
|
u8 mpag = unham8 (data[3], data[4]); |
315 |
|
|
u8 mag = mpag & 7; |
316 |
|
|
u8 pack = (mpag & 0xf8) >> 3; |
317 |
|
|
|
318 |
|
|
av_push (av, newSViv (VBI_VT)); |
319 |
|
|
av_push (av, newSViv (mag)); |
320 |
|
|
av_push (av, newSViv (pack)); |
321 |
|
|
|
322 |
|
|
switch (pack) |
323 |
|
|
{ |
324 |
|
|
/* ets300-706 */ |
325 |
|
|
case 0: |
326 |
|
|
av_push (av, newSVpvn (data+5, 40)); |
327 |
|
|
av_push (av, newSViv (unham8 (data[5], data[6]) | (mag << 8))); |
328 |
|
|
av_push (av, newSViv (unham8 (data[7], data[8]) |
329 |
|
|
| (unham8 (data[9], data[10]) << 8) |
330 |
|
|
| (unham8 (data[11], data[12]) << 16))); |
331 |
|
|
break; |
332 |
|
|
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: |
333 |
|
|
case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: |
334 |
|
|
case 21: case 22: case 23: case 24: case 25: |
335 |
|
|
av_push (av, newSVpvn (data+5, 40)); |
336 |
|
|
break; |
337 |
|
|
case 26: case 27: case 28: case 29: /* enhancement packets */ |
338 |
|
|
av_push (av, newSViv (unham4 (data[5]))); |
339 |
|
|
av_push (av, newSViv (unham16 (data[ 6], data[ 7], data[ 8]))); |
340 |
|
|
av_push (av, newSViv (unham16 (data[ 9], data[10], data[11]))); |
341 |
|
|
av_push (av, newSViv (unham16 (data[12], data[13], data[14]))); |
342 |
|
|
av_push (av, newSViv (unham16 (data[15], data[16], data[17]))); |
343 |
|
|
av_push (av, newSViv (unham16 (data[18], data[19], data[20]))); |
344 |
|
|
av_push (av, newSViv (unham16 (data[21], data[22], data[23]))); |
345 |
|
|
av_push (av, newSViv (unham16 (data[24], data[25], data[26]))); |
346 |
|
|
av_push (av, newSViv (unham16 (data[27], data[28], data[29]))); |
347 |
|
|
av_push (av, newSViv (unham16 (data[30], data[31], data[32]))); |
348 |
|
|
av_push (av, newSViv (unham16 (data[33], data[34], data[35]))); |
349 |
|
|
av_push (av, newSViv (unham16 (data[36], data[37], data[38]))); |
350 |
|
|
av_push (av, newSViv (unham16 (data[39], data[40], data[41]))); |
351 |
|
|
av_push (av, newSViv (unham16 (data[42], data[43], data[44]))); |
352 |
|
|
break; |
353 |
|
|
/* ets300-706 & ets300-231 */ |
354 |
|
|
case 30: |
355 |
|
|
{ |
356 |
|
|
UI dc = unham4 (data[5]); |
357 |
|
|
av_push (av, newSViv (dc)); |
358 |
|
|
if ((dc >> 1) == 0) |
359 |
|
|
{ |
360 |
|
|
av_push (av, newSViv (unham8 (data[6], data[7]) | (mag << 8))); |
361 |
|
|
av_push (av, newSViv (unham8 (data[8], data[9]) |
362 |
|
|
| unham8 (data[10], data[11]) << 8)); |
363 |
|
|
av_push (av, newSViv (rev (data[12]) << 8 | rev (data[13]))); |
364 |
|
|
} |
365 |
|
|
else if ((dc >> 1) == 8) |
366 |
|
|
{ |
367 |
|
|
/* pdc */ |
368 |
|
|
} |
369 |
|
|
} |
370 |
|
|
break; |
371 |
|
|
case 31: |
372 |
|
|
{ |
373 |
|
|
UI ft = unham4 (data[5]); |
374 |
|
|
UI al = unham4 (data[6]); |
375 |
|
|
UI i, addr = 0; |
376 |
|
|
|
377 |
|
|
/* ets300-708, IDL */ |
378 |
|
|
/* http://sunsite.cnlab-switch.ch/ftp/mirror/internet-drafts/draft-ietf-ipvbi-tv-signal-00.txt */ |
379 |
|
|
|
380 |
|
|
for(i=0; i<al&7; i++) |
381 |
|
|
addr = addr << 4 | unham4 (data[i+7]); |
382 |
|
|
|
383 |
|
|
av_push (av, newSViv (ft)); |
384 |
|
|
av_push (av, newSViv (addr)); |
385 |
|
|
break; |
386 |
|
|
} |
387 |
|
|
default: |
388 |
|
|
av_push (av, newSVpvn (data+5, 40)); |
389 |
|
|
} |
390 |
|
|
return newRV_noinc ((SV*)av); |
391 |
|
|
} |
392 |
|
|
|
393 |
|
|
static SV * |
394 |
|
|
decoder_decode_other (decoder *dec) |
395 |
|
|
{ |
396 |
|
|
AV *av = newAV (); |
397 |
|
|
FP pos = dec->pos; |
398 |
|
|
u8 data[6]; |
399 |
|
|
|
400 |
|
|
av_push (av, newSViv (VBI_OTHER)); |
401 |
|
|
|
402 |
|
|
dec->step = D2FP (FREQ / FREQ_CRYPT); /* found on premiere */ |
403 |
|
|
data [0] = get_byte (dec); |
404 |
|
|
data [1] = get_byte (dec); |
405 |
|
|
data [2] = get_byte (dec); |
406 |
|
|
if (data[0] == 0x55 && data[1] == 0xd0 && data[2] == 0x18) |
407 |
|
|
{ |
408 |
|
|
/* premiere */ |
409 |
|
|
av_push (av, newSViv (1)); |
410 |
|
|
} |
411 |
|
|
else |
412 |
|
|
av_push (av, newSViv (0)); |
413 |
|
|
|
414 |
|
|
return newRV_noinc ((SV*)av); |
415 |
|
|
} |
416 |
|
|
|
417 |
|
|
static SV * |
418 |
|
|
decoder_decode_empty (decoder *dec) |
419 |
|
|
{ |
420 |
|
|
AV *av = newAV (); |
421 |
|
|
av_push (av, newSViv (VBI_EMPTY)); |
422 |
|
|
return newRV_noinc ((SV*)av); |
423 |
|
|
} |
424 |
|
|
|
425 |
|
|
static SV * |
426 |
|
|
decoder_decode (decoder *dec, UI y, u8 *line) |
427 |
|
|
{ |
428 |
|
|
UI type; |
429 |
|
|
u8 data[45]; /* 45 bytes per line are max. */ |
430 |
|
|
UI i; |
431 |
|
|
int did_agc; |
432 |
|
|
|
433 |
|
|
type = VBI_VT | VBI_EMPTY | VBI_OTHER | VBI_VC; /* can be everywhere */ |
434 |
|
|
if (y == 16 - 7) type |= VBI_VPS; |
435 |
|
|
if (y > 17 - 7) type |= VBI_VDAT; |
436 |
|
|
|
437 |
|
|
type &= dec->types; |
438 |
|
|
|
439 |
|
|
/* don't do anything unless we need to */ |
440 |
|
|
if (type) |
441 |
|
|
{ |
442 |
|
|
dec->line = line; |
443 |
|
|
dec->y = y; |
444 |
|
|
dec->pos = 0; |
445 |
|
|
|
446 |
|
|
did_agc = dec->did_agc; |
447 |
|
|
|
448 |
|
|
/* maybe do agc? */ |
449 |
|
|
if (!dec->did_agc || y == 20-7) |
450 |
|
|
{ |
451 |
|
|
u8 *n = line + 120; |
452 |
|
|
u8 max = 0, min = 255; |
453 |
|
|
do |
454 |
|
|
{ |
455 |
|
|
if (*n > max) max = *n; |
456 |
|
|
if (*n < min) min = *n; |
457 |
|
|
} |
458 |
|
|
while (++n < line + 300); |
459 |
|
|
|
460 |
|
|
if (max > min + 30) |
461 |
|
|
{ |
462 |
|
|
dec->offset = 128 - (((int)max + (int)min) >> 1); |
463 |
|
|
dec->did_agc = 1; |
464 |
|
|
} |
465 |
|
|
} |
466 |
|
|
|
467 |
|
|
if (dec->did_agc) |
468 |
|
|
{ |
469 |
|
|
if (type & VBI_VT) |
470 |
|
|
{ |
471 |
|
|
dec->step = D2FP (FREQ / FREQ_VT); |
472 |
|
|
decoder_scan_start (dec, 50, 350); |
473 |
|
|
|
474 |
|
|
data[0] = get_byte (dec); |
475 |
|
|
if ((data[0] & 0xfe) == 0x54) |
476 |
|
|
{ |
477 |
|
|
data[1] = get_byte (dec); |
478 |
|
|
switch (data[1]) |
479 |
|
|
{ |
480 |
|
|
case 0x27: |
481 |
|
|
dec->pos -= dec->step * 2; |
482 |
|
|
case 0x4e: |
483 |
|
|
dec->pos -= dec->step * 2; |
484 |
|
|
case 0x9d: |
485 |
|
|
dec->pos -= dec->step * 2; |
486 |
|
|
case 0x75: |
487 |
|
|
dec->pos -= dec->step * 2; |
488 |
|
|
case 0xd5: |
489 |
|
|
dec->pos -= dec->step * 2; |
490 |
|
|
data[1] = 0x55; |
491 |
|
|
case 0x55: |
492 |
|
|
break; |
493 |
|
|
default: |
494 |
|
|
/* no teletext page */ |
495 |
|
|
} |
496 |
|
|
|
497 |
|
|
if (data[1] == 0x55) |
498 |
|
|
{ |
499 |
|
|
data[2] = get_byte (dec); |
500 |
|
|
if (data[2] == 0x27 || data[2] == 0xe7) |
501 |
|
|
{ |
502 |
|
|
for (i = 3; i < 45; i++) |
503 |
|
|
data[i] = get_byte (dec); |
504 |
|
|
return decoder_decode_vt (dec, data); |
505 |
|
|
} |
506 |
|
|
} |
507 |
|
|
} |
508 |
|
|
} |
509 |
|
|
|
510 |
|
|
if (type & VBI_VPS) |
511 |
|
|
{ |
512 |
|
|
decoder_scan_start (dec, 150, 260); |
513 |
|
|
dec->step = D2FP (FREQ / FREQ_VPS); /* shift encoding, two "pixels"/bit (skip the 2nd) */ |
514 |
|
|
data[0] = get_byte_SE (dec); |
515 |
|
|
if (data[0] == 0xff) |
516 |
|
|
{ |
517 |
|
|
data[1] = get_byte_SE (dec); |
518 |
|
|
if (data[1] == 0x5d || data[1] == 0x5f) |
519 |
|
|
{ |
520 |
|
|
for (i = 2; i < 16; i++) |
521 |
|
|
data[i] = get_byte_SE (dec); |
522 |
|
|
return decoder_decode_vps (dec, data); |
523 |
|
|
} |
524 |
|
|
} |
525 |
|
|
} |
526 |
|
|
|
527 |
|
|
#if 0 |
528 |
|
|
if (type & VBI_VDAT) |
529 |
|
|
{ |
530 |
|
|
dec->step = D2FP (FREQ / FREQ_VDAT); |
531 |
|
|
decoder_scan_start (dec, 150, 200); |
532 |
|
|
} |
533 |
|
|
|
534 |
|
|
if (type & VBI_VC) |
535 |
|
|
{ |
536 |
|
|
dec->step = D2FP (FREQ / FREQ_VC); |
537 |
|
|
decoder_scan_start (dec, 150, 200); |
538 |
|
|
} |
539 |
|
|
#endif |
540 |
|
|
|
541 |
root |
1.3 |
/* watch out for empty lines, test signals etc.. */ |
542 |
pcg |
1.1 |
if (type & VBI_OTHER) |
543 |
|
|
{ |
544 |
|
|
dec->did_agc = did_agc; /* other signals do not affect agc, yet */ |
545 |
|
|
|
546 |
|
|
dec->step = D2FP (FREQ); |
547 |
|
|
decoder_scan_start (dec, 100, 500); |
548 |
|
|
if (dec->pos < I2FP (450)) |
549 |
|
|
return decoder_decode_other (dec); |
550 |
|
|
} |
551 |
|
|
} |
552 |
|
|
|
553 |
|
|
dec->did_agc = did_agc; |
554 |
|
|
|
555 |
|
|
if (type & VBI_EMPTY) |
556 |
|
|
return decoder_decode_empty (dec); |
557 |
|
|
} |
558 |
|
|
|
559 |
|
|
return 0; |
560 |
|
|
} |
561 |
|
|
|
562 |
|
|
/* vtx decoding routines taken from videotext-0.6.971023, |
563 |
|
|
* Copyright (c) 1994-96 Martin Buck */ |
564 |
|
|
|
565 |
|
|
#define VTX_COLMASK 0x07 |
566 |
|
|
#define VTX_BGMASK (0x07 << 3) |
567 |
|
|
#define VTX_G1 (1 << 6) |
568 |
|
|
#define VTX_GRSEP (1 << 8) |
569 |
|
|
#define VTX_HIDDEN (1 << 9) |
570 |
|
|
#define VTX_BOX (1 << 10) |
571 |
|
|
#define VTX_FLASH (1 << 11) |
572 |
|
|
#define VTX_DOUBLE1 (1 << 12) |
573 |
|
|
#define VTX_DOUBLE2 (1 << 13) |
574 |
|
|
#define VTX_INVERT (1 << 14) |
575 |
|
|
#define VTX_DOUBLE (VTX_DOUBLE1 | VTX_DOUBLE2) |
576 |
|
|
|
577 |
|
|
static const u8 g0_to_iso_table[256] = |
578 |
|
|
" " |
579 |
|
|
" !\"£$%&'()*+,-./0123456789:;<=>?" |
580 |
|
|
"@ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ^#" |
581 |
|
|
"-abcdefghijklmnopqrstuvwxyzäöüß#" |
582 |
|
|
" " |
583 |
|
|
" " |
584 |
|
|
" " |
585 |
|
|
" "; |
586 |
|
|
|
587 |
|
|
/* one-to-one copy */ |
588 |
|
|
static int |
589 |
|
|
decode_vtpage (u8 *src, UI lines, u8 *chr, u16 *attr) |
590 |
|
|
{ |
591 |
|
|
UI line, col, pos, graphics, grhold, doubleht, nextattr = 0; |
592 |
|
|
u16 *lastattr, default_attrib = 7, next_attrib; |
593 |
|
|
u8 c, *lastchr, default_chr = ' '; |
594 |
|
|
UI lang; |
595 |
|
|
|
596 |
|
|
lang = 4; |
597 |
|
|
pos = 0; |
598 |
|
|
doubleht = 0; |
599 |
|
|
|
600 |
|
|
for (line = 0; line < lines; line++) { |
601 |
|
|
lastchr = &default_chr; |
602 |
|
|
lastattr = &default_attrib; |
603 |
|
|
graphics = grhold = 0; |
604 |
|
|
if (doubleht && pos > 40) { |
605 |
|
|
for (col = 0; col <= 39; col++) { |
606 |
|
|
if (attr[pos - 40] & VTX_DOUBLE1) { |
607 |
|
|
chr[pos] = chr[pos - 40]; |
608 |
|
|
chr[pos - 40] = ' '; |
609 |
|
|
attr[pos] = (attr[pos - 40] & ~VTX_DOUBLE1) | VTX_DOUBLE2; |
610 |
|
|
} else { |
611 |
|
|
chr[pos] = ' '; |
612 |
|
|
attr[pos] = attr[pos - 40]; |
613 |
|
|
} |
614 |
|
|
pos++; |
615 |
|
|
} |
616 |
|
|
doubleht = 0; |
617 |
|
|
} else { |
618 |
|
|
for (col = 0; col <= 39; col++) { |
619 |
|
|
c = src[pos]; |
620 |
|
|
if (parodd(c)) { |
621 |
|
|
chr[pos] = 254; /* Parity error */ |
622 |
|
|
attr[pos] = 7; |
623 |
|
|
/* return 0 */ /*?*/ |
624 |
|
|
} else if ((c & 0x7f) >= 32) { /* Normal character */ |
625 |
|
|
c &= 0x7f; |
626 |
|
|
if (!graphics || (c >= 64 && c <= 95)) { |
627 |
|
|
chr[pos] = g0_to_iso_table [c]; |
628 |
|
|
attr[pos] = *lastattr; |
629 |
|
|
} else { |
630 |
|
|
chr[pos] = c + (c >= 96 ? 64 : 96); |
631 |
|
|
attr[pos] = *lastattr | VTX_G1; |
632 |
|
|
} |
633 |
|
|
} else { |
634 |
|
|
c &= 0x7f; |
635 |
|
|
chr[pos] = ((grhold && graphics ) ? *lastchr : ' '); |
636 |
|
|
if (c <= 7) { /* Set alphanumerics-color */ |
637 |
|
|
attr[pos] = *lastattr; |
638 |
|
|
next_attrib = (*lastattr & ~(VTX_COLMASK | VTX_HIDDEN)) + c; |
639 |
|
|
nextattr = 1; |
640 |
|
|
graphics = 0; |
641 |
|
|
} else if (c == 8 || c == 9) { /* Flash on/off */ |
642 |
|
|
attr[pos] = (*lastattr & ~VTX_FLASH) + VTX_FLASH * (c == 8); |
643 |
|
|
} else if (c == 10 || c == 11) { /* End/start box */ |
644 |
|
|
attr[pos] = (*lastattr & ~VTX_BOX) + VTX_BOX * (c == 11); |
645 |
|
|
} else if (c == 12 || c == 13) { /* Normal/double height */ |
646 |
|
|
attr[pos] = (*lastattr & ~VTX_DOUBLE1) + VTX_DOUBLE1 * (c == 13); |
647 |
|
|
if (c == 13) |
648 |
|
|
doubleht = 1; |
649 |
|
|
} else if (c == 14 || c == 15 || c == 27) { /* SO, SI, ESC (ignored) */ |
650 |
|
|
attr[pos] = *lastattr; |
651 |
|
|
} else if (c >= 16 && c <= 23) { /* Set graphics-color */ |
652 |
|
|
attr[pos] = *lastattr; |
653 |
|
|
next_attrib = (*lastattr & ~(VTX_COLMASK | VTX_HIDDEN)) + c - 16; |
654 |
|
|
nextattr = 1; |
655 |
|
|
graphics = 1; |
656 |
|
|
} else if (c == 24) { /* Conceal display */ |
657 |
|
|
attr[pos] = *lastattr | VTX_HIDDEN; |
658 |
|
|
} else if (c == 25 || c == 26) { /* Contiguous/separated graphics */ |
659 |
|
|
attr[pos] = (*lastattr & ~VTX_GRSEP) + VTX_GRSEP * (c == 26); |
660 |
|
|
} else if (c == 28) { /* Black background */ |
661 |
|
|
attr[pos] = *lastattr & ~VTX_BGMASK; |
662 |
|
|
} else if (c == 29) { /* Set background */ |
663 |
|
|
attr[pos] = (*lastattr & ~VTX_BGMASK) + ((*lastattr & VTX_COLMASK) << 3); |
664 |
|
|
} else if (c == 30 || c == 31) { /* Hold/release graphics */ |
665 |
|
|
attr[pos] = *lastattr; |
666 |
|
|
grhold = (c == 30); |
667 |
|
|
if (grhold && graphics) |
668 |
|
|
chr[pos] = *lastchr; |
669 |
|
|
} else { |
670 |
|
|
return 0; |
671 |
|
|
} |
672 |
|
|
} |
673 |
|
|
lastchr = chr + pos; |
674 |
|
|
if (nextattr) { |
675 |
|
|
lastattr = &next_attrib; |
676 |
|
|
nextattr = 0; |
677 |
|
|
} else { |
678 |
|
|
lastattr = attr + pos; |
679 |
|
|
} |
680 |
|
|
pos++; |
681 |
|
|
} |
682 |
|
|
} |
683 |
|
|
} |
684 |
|
|
return 1; |
685 |
|
|
} |
686 |
|
|
|
687 |
|
|
static SV * |
688 |
|
|
decode_ansi (u8 *chr, u16 *atr) |
689 |
|
|
{ |
690 |
|
|
UI x; |
691 |
|
|
SV *sv = newSVpvn ("", 0); |
692 |
|
|
u16 o; |
693 |
|
|
|
694 |
|
|
for (x=0; x<VT_COLS; x++) |
695 |
|
|
{ |
696 |
|
|
u16 a = *atr++; |
697 |
|
|
if (x == 0 || (a&0x07) != (o&0x07)) |
698 |
|
|
sv_catpvf (sv, "\x1b[3%dm", a&7); |
699 |
|
|
if (x == 0 || (a&0x38) != (o&0x38)) |
700 |
|
|
sv_catpvf (sv, "\x1b[4%dm", (o&0x38)>>3); |
701 |
|
|
if (x == 0 || (a&VTX_FLASH) != (o&VTX_FLASH)) |
702 |
|
|
sv_catpvf (sv, "\x1b[%sm", a&VTX_FLASH ? "7" : ""); |
703 |
|
|
|
704 |
|
|
sv_catpvf (sv, "%c", a & VTX_G1 ? '×' : *chr); |
705 |
|
|
|
706 |
|
|
chr++; |
707 |
|
|
o = a; |
708 |
|
|
} |
709 |
|
|
|
710 |
|
|
sv_catpv (sv, "\x1b[37;40;0m"); |
711 |
|
|
|
712 |
|
|
return sv; |
713 |
|
|
} |
714 |
|
|
|
715 |
|
|
#define valid_packet(sv) (SvPOK(packet) && SvCUR(packet) == 40) |
716 |
|
|
#define consume_byte(store) \ |
717 |
|
|
if (bp >= 39) \ |
718 |
|
|
{ \ |
719 |
|
|
SV **sv = av_fetch(stream, pi, 0); pi++; \ |
720 |
|
|
if (!sv) \ |
721 |
|
|
goto eostream; \ |
722 |
|
|
packet = *sv; \ |
723 |
|
|
if (!valid_packet (pascket)) \ |
724 |
|
|
goto skip; \ |
725 |
|
|
p = SvPV_nolen (packet); \ |
726 |
|
|
bp = 0; \ |
727 |
|
|
} \ |
728 |
|
|
(store) = p[++bp] |
729 |
|
|
|
730 |
|
|
static void |
731 |
|
|
decode_stream (AV *stream) |
732 |
|
|
{ |
733 |
|
|
dSP; |
734 |
|
|
|
735 |
|
|
while (av_len (stream) >= 0) |
736 |
|
|
{ |
737 |
|
|
UI pi = 1; |
738 |
|
|
SV *packet = *av_fetch(stream, 0, 1); |
739 |
|
|
|
740 |
|
|
if (valid_packet (packet)) |
741 |
|
|
{ |
742 |
|
|
u8 *p = SvPV_nolen(packet); |
743 |
|
|
u8 bp = p[0] == 0xff ? p[1] : unham4 (p[0])*3+1; |
744 |
|
|
|
745 |
|
|
if (bp <= 12*3+1 && p[bp] == 0xa1) |
746 |
|
|
{ |
747 |
|
|
u8 buf[4]; |
748 |
|
|
|
749 |
|
|
consume_byte (buf[0]); consume_byte (buf[1]); |
750 |
|
|
consume_byte (buf[2]); consume_byte (buf[3]); |
751 |
|
|
|
752 |
|
|
{ |
753 |
|
|
u16 sh = unham8 (buf[0], buf[1]) | unham8 (buf[2], buf[3]) << 8; |
754 |
|
|
u8 bt = sh & 0x1f; |
755 |
|
|
u16 bl = sh >> 5; |
756 |
|
|
SV *block = sv_2mortal (newSVpvn (&bt, 1)); |
757 |
|
|
|
758 |
|
|
while (bl--) |
759 |
|
|
{ |
760 |
|
|
consume_byte (buf[0]); |
761 |
|
|
sv_catpvn (block, buf, 1); |
762 |
|
|
} |
763 |
|
|
|
764 |
|
|
EXTEND (SP, 1); |
765 |
|
|
PUSHs (block); |
766 |
|
|
|
767 |
|
|
/* optimize, do only when still in first packet! */ |
768 |
|
|
do { |
769 |
|
|
if (bp >= 39) |
770 |
|
|
break; |
771 |
|
|
|
772 |
|
|
bp++; |
773 |
|
|
if (p[bp] == 0xa1) |
774 |
|
|
{ |
775 |
|
|
p[0] = 0xff; |
776 |
|
|
p[1] = bp; |
777 |
|
|
pi--; |
778 |
|
|
break; |
779 |
|
|
} |
780 |
|
|
} while (p[bp] = 0x5e); |
781 |
|
|
} |
782 |
|
|
} |
783 |
|
|
} |
784 |
|
|
|
785 |
|
|
skip: |
786 |
|
|
while (pi--) |
787 |
|
|
SvREFCNT_dec(av_shift(stream)); |
788 |
|
|
} |
789 |
|
|
eostream: |
790 |
|
|
|
791 |
|
|
PUTBACK; |
792 |
|
|
} |
793 |
|
|
|
794 |
|
|
static u8 * |
795 |
|
|
unham_block (u8 *src, UI len, u8 *dst, UI dlen) |
796 |
|
|
{ |
797 |
|
|
u16 sh = *src | (len-1)<<5; |
798 |
|
|
u8 sum = ( sh & 15) |
799 |
|
|
+ ((sh >> 4) & 15) |
800 |
|
|
+ ((sh >> 8) & 15) |
801 |
|
|
+ ((sh >> 12) & 15); |
802 |
|
|
|
803 |
|
|
if (len < 5) |
804 |
|
|
return 0; |
805 |
|
|
|
806 |
|
|
sum += unham8 (src[1], src[2]); |
807 |
|
|
src += 3; len -= 3; |
808 |
|
|
|
809 |
|
|
dlen--; |
810 |
|
|
|
811 |
|
|
if (len < dlen) |
812 |
|
|
return 0; |
813 |
|
|
|
814 |
|
|
while (dlen) |
815 |
|
|
{ |
816 |
|
|
*dst = unham8 (src[0], src[1]); |
817 |
|
|
sum += (*dst >> 4) + (*dst & 15); |
818 |
|
|
#if 0 |
819 |
|
|
printf ("%02x ", *dst); |
820 |
|
|
#endif |
821 |
|
|
dst++; src += 2; dlen--; |
822 |
|
|
} |
823 |
|
|
#if 0 |
824 |
|
|
printf ("\n"); |
825 |
|
|
printf ("sh = %04x, len = %02x, sum = %02x\n", sh, len, sum); |
826 |
|
|
#endif |
827 |
|
|
if (sum) |
828 |
|
|
return 0; |
829 |
|
|
|
830 |
|
|
return src; |
831 |
|
|
} |
832 |
|
|
|
833 |
|
|
/* must not be a macro, see nvec */ |
834 |
|
|
static U32 |
835 |
|
|
vec(u8 *d, UI bit, UI len) |
836 |
|
|
{ |
837 |
|
|
U32 word = bit >> 3; |
838 |
|
|
|
839 |
|
|
/*printf ("vec(%d,%d) %d (%d)\n",bit,len,(bit & 7) + len,(bit & 7) + len < 32);*/ |
840 |
|
|
assert ((bit & 7) + len < 32); |
841 |
|
|
|
842 |
|
|
word = (d[word] ) |
843 |
|
|
| (d[word+1] << 8) |
844 |
|
|
| (d[word+2] << 16) |
845 |
|
|
| (d[word+3] << 24); |
846 |
|
|
|
847 |
|
|
return (word >> (bit & 7)) & (((U32)1 << len) - 1); |
848 |
|
|
} |
849 |
|
|
|
850 |
|
|
#define hv_store_sv(name,value) hv_store (hv, #name, strlen(#name), (SV*)(value), 0) |
851 |
|
|
#define hv_store_iv(name,value) hv_store_sv (name, newSViv (value)) |
852 |
|
|
#define nvec(bits) vec (c, (ofs += (bits)) - (bits), (bits)) |
853 |
|
|
|
854 |
|
|
#define decode_escape_sequences(av) \ |
855 |
|
|
{ \ |
856 |
|
|
UI no_escapes = nvec (8); \ |
857 |
|
|
av = newAV (); \ |
858 |
|
|
while (no_escapes--) \ |
859 |
|
|
{ \ |
860 |
|
|
AV *esc = newAV (); \ |
861 |
|
|
av_push (esc, newSViv (nvec (10))); \ |
862 |
|
|
av_push (esc, newSViv (nvec (6))); \ |
863 |
|
|
av_push (esc, newSViv (nvec (8))); \ |
864 |
|
|
av_push (av, newRV_noinc((SV*)esc)); \ |
865 |
|
|
} \ |
866 |
|
|
} |
867 |
|
|
|
868 |
|
|
#define decode_transparent_string(sv, len) \ |
869 |
|
|
{ \ |
870 |
|
|
UI l = len; \ |
871 |
|
|
sv = newSVpvn (s, l); \ |
872 |
|
|
s += l; \ |
873 |
|
|
while (l--) \ |
874 |
|
|
SvPV_nolen (sv)[l] &= 0x7f; \ |
875 |
|
|
} |
876 |
|
|
|
877 |
|
|
#define decode_descriptor_loop(av, ll) \ |
878 |
|
|
av = newAV (); \ |
879 |
|
|
while (ll--) \ |
880 |
|
|
{ \ |
881 |
|
|
AV *desc = newAV (); \ |
882 |
|
|
av_push (desc, newSViv (nvec (6))); \ |
883 |
|
|
av_push (desc, newSViv (nvec (6))); \ |
884 |
|
|
av_push (desc, newSViv (nvec (8))); \ |
885 |
|
|
av_push (av, newRV_noinc((SV*)desc)); \ |
886 |
|
|
} |
887 |
|
|
|
888 |
|
|
static void |
889 |
|
|
decode_epg (HV *hv, UI appid, u8 *c, u8 *s) |
890 |
|
|
{ |
891 |
|
|
UI ofs = 16; |
892 |
|
|
UI len; |
893 |
|
|
AV *av; |
894 |
|
|
SV *sv; |
895 |
|
|
|
896 |
|
|
hv_store_iv (ca_mode, nvec(2)); |
897 |
|
|
hv_store_iv (_copyright, nvec(1)); |
898 |
|
|
|
899 |
|
|
ofs++; /* reserved */ |
900 |
|
|
|
901 |
|
|
switch (appid) |
902 |
|
|
{ |
903 |
|
|
case 1: |
904 |
|
|
{ |
905 |
|
|
hv_store_iv (epg_version, nvec( 6)); |
906 |
|
|
hv_store_iv (epg_version_swo, nvec( 6)); |
907 |
|
|
hv_store_iv (no_navigation, nvec(16)); |
908 |
|
|
hv_store_iv (no_osd, nvec(16)); |
909 |
|
|
hv_store_iv (no_message, nvec(16)); |
910 |
|
|
hv_store_iv (no_navigation_swo,nvec(16)); |
911 |
|
|
hv_store_iv (no_osd_swo, nvec(16)); |
912 |
|
|
hv_store_iv (no_message_swo, nvec(16)); |
913 |
|
|
len = nvec(8); |
914 |
|
|
hv_store_iv (this_network_op, nvec( 8)); |
915 |
|
|
decode_transparent_string (sv, nvec (5)); |
916 |
|
|
hv_store_sv (service_name, sv); |
917 |
|
|
hv_store_iv (no_updates, nvec( 1)); |
918 |
|
|
|
919 |
|
|
ofs += 2; |
920 |
|
|
|
921 |
|
|
av = newAV (); |
922 |
|
|
while (len--) |
923 |
|
|
{ |
924 |
|
|
HV *hv = newHV (); |
925 |
|
|
int LTO; |
926 |
|
|
hv_store_iv (cni, nvec (16)); |
927 |
|
|
LTO = nvec (7) * 15; |
928 |
|
|
if (nvec(1)) |
929 |
|
|
LTO = -LTO; |
930 |
|
|
hv_store_iv (lto, LTO); |
931 |
|
|
hv_store_iv (no_days, nvec( 5)); |
932 |
|
|
decode_transparent_string (sv, nvec( 5)); |
933 |
|
|
hv_store_sv (netwop_name, sv); |
934 |
|
|
hv_store_iv (default_alphabet, nvec( 7)); |
935 |
|
|
hv_store_iv (prog_start_no, nvec(16)); |
936 |
|
|
hv_store_iv (prog_stop_no, nvec(16)); |
937 |
|
|
hv_store_iv (prog_stop_no_swo, nvec(16)); |
938 |
|
|
hv_store_iv (network_add_info, nvec(11)); |
939 |
|
|
|
940 |
|
|
av_push (av, newRV_noinc ((SV*)hv)); |
941 |
|
|
} |
942 |
|
|
hv_store_sv (networks, newRV_noinc ((SV*)av)); |
943 |
|
|
break; |
944 |
|
|
} |
945 |
|
|
case 2: |
946 |
|
|
{ |
947 |
|
|
UI background_reuse; |
948 |
|
|
|
949 |
|
|
hv_store_iv (block_no, nvec(16)); |
950 |
|
|
hv_store_iv (audio_mode, vec(c, ofs, 12) & 3); |
951 |
|
|
hv_store_iv (feature_flags, nvec(12)); |
952 |
|
|
hv_store_iv (netwop_no, nvec( 8)); |
953 |
|
|
hv_store_iv (start_time, nvec(16)); |
954 |
|
|
hv_store_iv (start_date, nvec(16)); |
955 |
|
|
hv_store_iv (stop_time, nvec(16)); |
956 |
|
|
hv_store_iv (_pil, nvec(20)); |
957 |
|
|
hv_store_iv (parental_rating, nvec( 4)); |
958 |
|
|
hv_store_iv (editorial_rating,nvec( 3)); |
959 |
|
|
{ |
960 |
|
|
UI no_themes = nvec( 3); |
961 |
|
|
UI no_sortcrit = nvec( 3); |
962 |
|
|
UI descriptor_looplength = nvec( 6); |
963 |
|
|
background_reuse = nvec( 1); |
964 |
|
|
|
965 |
|
|
av = newAV (); |
966 |
|
|
while (no_themes--) |
967 |
|
|
av_push (av, newSViv (nvec (8))); |
968 |
|
|
hv_store_sv (themes, newRV_noinc((SV*)av)); |
969 |
|
|
|
970 |
|
|
av = newAV (); |
971 |
|
|
while (no_sortcrit--) |
972 |
|
|
av_push (av, newSViv (nvec (8))); |
973 |
|
|
hv_store_sv (sortcrits, newRV_noinc((SV*)av)); |
974 |
|
|
|
975 |
|
|
decode_descriptor_loop (av, descriptor_looplength); |
976 |
|
|
hv_store_sv (descriptors, newRV_noinc((SV*)av)); |
977 |
|
|
|
978 |
|
|
ofs = (ofs+7) & ~7; |
979 |
|
|
|
980 |
|
|
decode_escape_sequences (av); |
981 |
|
|
hv_store_sv (title_escape_sequences, newRV_noinc((SV*)av)); |
982 |
|
|
decode_transparent_string (sv, nvec (8)); |
983 |
|
|
hv_store_sv (title, sv); |
984 |
|
|
} |
985 |
|
|
|
986 |
|
|
if (background_reuse) |
987 |
|
|
hv_store_iv (title_length, nvec (16)); |
988 |
|
|
else |
989 |
|
|
{ |
990 |
|
|
decode_escape_sequences (av); |
991 |
|
|
hv_store_sv (shortinfo_escape_sequences, newRV_noinc((SV*)av)); |
992 |
|
|
decode_transparent_string (sv, nvec (8)); |
993 |
|
|
hv_store_sv (shortinfo, sv); |
994 |
|
|
|
995 |
|
|
len = nvec (3); |
996 |
|
|
ofs += 2; |
997 |
|
|
switch (len) |
998 |
|
|
{ |
999 |
|
|
case 0: |
1000 |
|
|
decode_escape_sequences (av); |
1001 |
|
|
hv_store_sv (longinfo_escape_sequences, newRV_noinc((SV*)av)); |
1002 |
|
|
decode_transparent_string (sv, nvec (8)); |
1003 |
|
|
hv_store_sv (longinfo, sv); |
1004 |
|
|
break; |
1005 |
|
|
case 1: |
1006 |
|
|
decode_escape_sequences (av); |
1007 |
|
|
hv_store_sv (longinfo_escape_sequences, newRV_noinc((SV*)av)); |
1008 |
|
|
decode_transparent_string (sv, nvec (10)); |
1009 |
|
|
hv_store_sv (longinfo, sv); |
1010 |
|
|
break; |
1011 |
|
|
default: |
1012 |
|
|
printf ("UNKNOWN LONGINFO TYPE %d\n", len); |
1013 |
|
|
} |
1014 |
|
|
} |
1015 |
|
|
|
1016 |
|
|
break; |
1017 |
|
|
} |
1018 |
|
|
case 3: |
1019 |
|
|
{ |
1020 |
|
|
UI descriptor_ll; |
1021 |
|
|
hv_store_iv (block_no, nvec(16)); |
1022 |
|
|
hv_store_iv (header_size, nvec( 2)); |
1023 |
|
|
len = nvec(4); |
1024 |
|
|
hv_store_iv (message_size, nvec( 3)); |
1025 |
|
|
ofs++; |
1026 |
|
|
descriptor_ll = nvec(6); |
1027 |
|
|
decode_descriptor_loop (av, descriptor_ll); |
1028 |
|
|
hv_store_sv (descriptors, newRV_noinc((SV*)av)); |
1029 |
|
|
ofs = (ofs+7) & ~7; |
1030 |
|
|
|
1031 |
|
|
decode_escape_sequences (av); |
1032 |
|
|
hv_store_sv (header_escape_sequences, newRV_noinc((SV*)av)); |
1033 |
|
|
|
1034 |
|
|
decode_transparent_string (sv, nvec(8)); |
1035 |
|
|
hv_store_sv (header, sv); |
1036 |
|
|
|
1037 |
|
|
hv_store_iv (message_attribute,nvec(8)); |
1038 |
|
|
|
1039 |
|
|
av = newAV (); |
1040 |
|
|
while (len--) |
1041 |
|
|
{ |
1042 |
|
|
AV *av2; |
1043 |
|
|
UI len; |
1044 |
|
|
HV *hv = newHV (); |
1045 |
|
|
|
1046 |
|
|
hv_store_iv (next_id, nvec(16)); |
1047 |
|
|
hv_store_iv (next_type, nvec( 4)); |
1048 |
|
|
|
1049 |
|
|
len = nvec(4); |
1050 |
|
|
av2 = newAV (); |
1051 |
|
|
while (len--) |
1052 |
|
|
{ |
1053 |
|
|
UI kind = nvec(8); |
1054 |
|
|
av_push (av2, newSViv (kind)); |
1055 |
|
|
switch (kind) |
1056 |
|
|
{ |
1057 |
|
|
case 0x02: case 0x10: case 0x11: case 0x18: |
1058 |
|
|
case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: |
1059 |
|
|
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: |
1060 |
|
|
case 0x40: case 0x41: |
1061 |
|
|
av_push (av2, newSViv (nvec ( 8))); |
1062 |
|
|
break; |
1063 |
|
|
|
1064 |
|
|
case 0x80: case 0x81: |
1065 |
|
|
av_push (av2, newSViv (nvec (16))); |
1066 |
|
|
break; |
1067 |
|
|
|
1068 |
|
|
case 0xc0: |
1069 |
|
|
av_push (av2, newSViv (nvec (12))); |
1070 |
|
|
av_push (av2, newSViv (nvec (12))); |
1071 |
|
|
break; |
1072 |
|
|
|
1073 |
|
|
case 0xc8: case 0xc9: |
1074 |
|
|
av_push (av2, newSViv (nvec (24))); |
1075 |
|
|
break; |
1076 |
|
|
|
1077 |
|
|
default: |
1078 |
|
|
abort (); |
1079 |
|
|
} |
1080 |
|
|
} |
1081 |
|
|
hv_store_sv (attributes, newRV_noinc((SV*)av2)); |
1082 |
|
|
|
1083 |
|
|
decode_escape_sequences (av2); |
1084 |
|
|
hv_store_sv (header_escape_sequences, newRV_noinc((SV*)av2)); |
1085 |
|
|
decode_transparent_string (sv, nvec(8)); |
1086 |
|
|
hv_store_sv (event, sv); |
1087 |
|
|
|
1088 |
|
|
av_push (av, newRV_noinc((SV*)hv)); |
1089 |
|
|
} |
1090 |
|
|
hv_store_sv (events, newRV_noinc((SV*)av)); |
1091 |
|
|
|
1092 |
|
|
break; |
1093 |
|
|
} |
1094 |
|
|
case 4: |
1095 |
|
|
{ |
1096 |
|
|
UI block_no = nvec (16); |
1097 |
|
|
UI descriptor_ll; |
1098 |
|
|
UI msg_len; |
1099 |
|
|
hv_store_iv (block_no, block_no); |
1100 |
|
|
hv_store_iv (message_attribute,nvec(8)); |
1101 |
|
|
hv_store_iv (header_size, nvec(3)); |
1102 |
|
|
hv_store_iv (message_size, nvec(3)); |
1103 |
|
|
descriptor_ll = nvec(6); |
1104 |
|
|
if (!block_no) |
1105 |
|
|
{ |
1106 |
|
|
decode_escape_sequences (av); |
1107 |
|
|
hv_store_sv (message_escape_sequences, newRV_noinc((SV*)av)); |
1108 |
|
|
msg_len = nvec(10); |
1109 |
|
|
ofs += 6; |
1110 |
|
|
} |
1111 |
|
|
|
1112 |
|
|
decode_escape_sequences (av); |
1113 |
|
|
hv_store_sv (header_escape_sequences, newRV_noinc((SV*)av)); |
1114 |
|
|
|
1115 |
|
|
decode_transparent_string (sv, nvec(8)); |
1116 |
|
|
hv_store_sv (header, sv); |
1117 |
|
|
|
1118 |
|
|
if (!block_no) |
1119 |
|
|
{ |
1120 |
|
|
decode_transparent_string (sv, msg_len); |
1121 |
|
|
hv_store_sv (message, sv); |
1122 |
|
|
} |
1123 |
|
|
|
1124 |
|
|
decode_descriptor_loop (av, descriptor_ll); |
1125 |
|
|
hv_store_sv (descriptors, newRV_noinc((SV*)av)); |
1126 |
|
|
break; |
1127 |
|
|
} |
1128 |
|
|
case 5: |
1129 |
|
|
{ |
1130 |
|
|
UI descriptor_ll; |
1131 |
|
|
hv_store_iv (block_no, nvec(16)); |
1132 |
|
|
descriptor_ll = nvec(6); |
1133 |
|
|
decode_descriptor_loop (av, descriptor_ll); |
1134 |
|
|
hv_store_sv (descriptors, newRV_noinc((SV*)av)); |
1135 |
|
|
ofs = (ofs+7) & ~7; |
1136 |
|
|
|
1137 |
|
|
decode_escape_sequences (av); |
1138 |
|
|
hv_store_sv (message_escape_sequences, newRV_noinc((SV*)av)); |
1139 |
|
|
|
1140 |
|
|
decode_transparent_string (sv, nvec(10)); |
1141 |
|
|
hv_store_sv (message, sv); |
1142 |
|
|
|
1143 |
|
|
break; |
1144 |
|
|
} |
1145 |
|
|
default: |
1146 |
|
|
printf ("UNKNOWN EPG DATATYPE ($%02x)\n", appid); |
1147 |
|
|
} |
1148 |
|
|
} |
1149 |
|
|
|
1150 |
|
|
static SV * |
1151 |
|
|
decode_block(u8 *b, UI len, AV *bi) |
1152 |
|
|
{ |
1153 |
|
|
dSP; |
1154 |
|
|
u8 ctrl[1024]; |
1155 |
|
|
u8 bt = *b; |
1156 |
|
|
|
1157 |
|
|
if (bt == 0) |
1158 |
|
|
{ |
1159 |
|
|
if ((b = unham_block (b, len, ctrl, (len-1)>>1 ))) |
1160 |
|
|
{ |
1161 |
|
|
UI app_no = ctrl[0]; |
1162 |
|
|
UI app; |
1163 |
|
|
av_clear (bi); |
1164 |
|
|
for (app=1; app<=app_no; app++) |
1165 |
|
|
av_store (bi, app, newSViv (vec (ctrl, app*16-8, 16))); |
1166 |
|
|
} |
1167 |
|
|
} |
1168 |
|
|
else if (len >= 5) |
1169 |
|
|
{ |
1170 |
|
|
if (bt <= av_len (bi) && SvOK(*av_fetch (bi, bt, 0))) |
1171 |
|
|
{ |
1172 |
|
|
u16 appid = SvIV (*av_fetch (bi, bt, 0)); |
1173 |
|
|
if (appid == 0) /* EPG */ |
1174 |
|
|
{ |
1175 |
|
|
if ((b = unham_block (b, len, ctrl, unham8 (b[3], b[4]) | (unham4 (b[5]) << 8) & 1023))) |
1176 |
|
|
{ |
1177 |
|
|
HV *hv = newHV (); |
1178 |
|
|
/* _now_ we have an epg structure. decode it */ |
1179 |
|
|
|
1180 |
|
|
appid = vec(ctrl,10,6); |
1181 |
|
|
EXTEND (SP, 2); |
1182 |
|
|
PUSHs (sv_2mortal (newSViv (appid))); |
1183 |
|
|
PUSHs (sv_2mortal (newRV_noinc ((SV*)hv))); |
1184 |
|
|
|
1185 |
|
|
decode_epg (hv, appid, ctrl, b); |
1186 |
|
|
} |
1187 |
|
|
else |
1188 |
|
|
printf ("checksum error found block %d, len %d, appid = %d (clen 0)\n", bt, len, appid); |
1189 |
|
|
} |
1190 |
|
|
else |
1191 |
|
|
/* other applications not defined (to my knowledge) */; |
1192 |
|
|
} |
1193 |
|
|
else |
1194 |
|
|
/* no bundle info: can't parse yet */; |
1195 |
|
|
} |
1196 |
|
|
|
1197 |
|
|
PUTBACK; |
1198 |
|
|
} |
1199 |
|
|
|
1200 |
|
|
MODULE = Video::Capture::VBI PACKAGE = Video::Capture::VBI |
1201 |
|
|
|
1202 |
|
|
PROTOTYPES: ENABLE |
1203 |
|
|
|
1204 |
|
|
int |
1205 |
|
|
unham4(data) |
1206 |
|
|
SV * data |
1207 |
|
|
CODE: |
1208 |
|
|
STRLEN len; |
1209 |
|
|
unsigned char *d = (unsigned char *)SvPV (data, len); |
1210 |
|
|
|
1211 |
|
|
if (len < 1) |
1212 |
|
|
croak ("unham4: length must be at least 1"); |
1213 |
|
|
|
1214 |
|
|
RETVAL = unham4 (*d); |
1215 |
|
|
OUTPUT: |
1216 |
|
|
RETVAL |
1217 |
|
|
|
1218 |
|
|
int |
1219 |
|
|
unham8(data) |
1220 |
|
|
SV * data |
1221 |
|
|
CODE: |
1222 |
|
|
STRLEN len; |
1223 |
|
|
unsigned char *d = (unsigned char *)SvPV (data, len); |
1224 |
|
|
|
1225 |
|
|
if (len < 2) |
1226 |
|
|
croak ("unham8: length must be at least 2"); |
1227 |
|
|
|
1228 |
|
|
RETVAL = unham8 (d[0], d[1]); |
1229 |
|
|
OUTPUT: |
1230 |
|
|
RETVAL |
1231 |
|
|
|
1232 |
|
|
void |
1233 |
|
|
decode_field(field, types) |
1234 |
|
|
SV * field |
1235 |
|
|
unsigned int types |
1236 |
|
|
PPCODE: |
1237 |
|
|
UI lines = SvCUR(field) / VBI_BPL; |
1238 |
|
|
UI line; |
1239 |
|
|
decoder dec; |
1240 |
|
|
|
1241 |
|
|
decoder_init (&dec, types); |
1242 |
|
|
|
1243 |
|
|
EXTEND (SP, lines); |
1244 |
|
|
for (line = 0; line < lines; line++) |
1245 |
|
|
{ |
1246 |
|
|
SV *sv = decoder_decode (&dec, line, ((u8*)SvPV_nolen(field)) + line * VBI_BPL); |
1247 |
|
|
if (sv) |
1248 |
|
|
PUSHs (sv_2mortal (sv)); |
1249 |
|
|
} |
1250 |
|
|
|
1251 |
|
|
void |
1252 |
|
|
decode_vtpage(data) |
1253 |
|
|
SV * data |
1254 |
|
|
PPCODE: |
1255 |
|
|
u8 chr[VT_COLS*VT_LINES]; |
1256 |
|
|
u16 atr[VT_COLS*VT_LINES]; |
1257 |
|
|
UI lines; |
1258 |
|
|
|
1259 |
|
|
if (!SvPOK(data)) |
1260 |
|
|
XSRETURN_EMPTY; |
1261 |
|
|
|
1262 |
|
|
lines = SvCUR(data) / VT_COLS; |
1263 |
|
|
|
1264 |
|
|
if (lines > VT_LINES) |
1265 |
|
|
croak ("videotext cannot have more than %d lines (argument has %d lines)\n", VT_LINES, lines); |
1266 |
|
|
|
1267 |
|
|
Zero(chr, VT_COLS*VT_LINES, u8); |
1268 |
|
|
Zero(atr, VT_COLS*VT_LINES, u16); |
1269 |
|
|
if (decode_vtpage (SvPV_nolen(data), lines, chr, atr)) |
1270 |
|
|
{ |
1271 |
|
|
AV *av = newAV (); |
1272 |
|
|
UI n; |
1273 |
|
|
|
1274 |
|
|
for (n = 0; n < VT_COLS*lines; n++) |
1275 |
|
|
av_push (av, newSViv (atr[n])); |
1276 |
|
|
|
1277 |
|
|
EXTEND (SP, 2); |
1278 |
|
|
PUSHs (sv_2mortal (newSVpvn (chr, VT_COLS*lines))); |
1279 |
|
|
PUSHs (sv_2mortal (newRV_noinc ((SV*)av))); |
1280 |
|
|
} |
1281 |
|
|
|
1282 |
|
|
PROTOTYPES: DISABLE |
1283 |
|
|
|
1284 |
|
|
void |
1285 |
|
|
decode_ansi(chr, atr) |
1286 |
|
|
SV * chr |
1287 |
|
|
SV * atr |
1288 |
|
|
PPCODE: |
1289 |
|
|
UI lines = SvCUR(chr) / VT_COLS; |
1290 |
|
|
UI attr_i = 0; |
1291 |
|
|
u8 *_chr = SvPV_nolen (chr); |
1292 |
|
|
u16 _atr[VT_COLS]; |
1293 |
|
|
|
1294 |
|
|
EXTEND (SP, lines); |
1295 |
|
|
|
1296 |
|
|
while (lines--) |
1297 |
|
|
{ |
1298 |
|
|
UI attr_j; |
1299 |
|
|
for(attr_j = 0; attr_j < VT_COLS; attr_j++) |
1300 |
|
|
_atr[attr_j] = SvIV (*av_fetch ((AV*)SvRV (atr), attr_i+attr_j, 1)); |
1301 |
|
|
|
1302 |
|
|
PUSHs (sv_2mortal (decode_ansi (_chr, _atr))); |
1303 |
|
|
|
1304 |
|
|
_chr += VT_COLS; |
1305 |
|
|
attr_i += VT_COLS; |
1306 |
|
|
} |
1307 |
|
|
|
1308 |
|
|
unsigned int |
1309 |
|
|
bcd2dec(bcd) |
1310 |
|
|
unsigned int bcd |
1311 |
|
|
CODE: |
1312 |
|
|
UI digit = 1; |
1313 |
|
|
RETVAL = 0; |
1314 |
|
|
while (bcd) |
1315 |
|
|
{ |
1316 |
|
|
if ((bcd & 15) > 9) |
1317 |
|
|
XSRETURN_EMPTY; |
1318 |
|
|
|
1319 |
|
|
RETVAL += (bcd & 15) * digit; |
1320 |
|
|
digit *= 10; |
1321 |
|
|
bcd >>= 4; |
1322 |
|
|
} |
1323 |
|
|
OUTPUT: |
1324 |
|
|
RETVAL |
1325 |
|
|
|
1326 |
|
|
PROTOTYPES: ENABLE |
1327 |
|
|
|
1328 |
|
|
MODULE = Video::Capture::VBI PACKAGE = Video::Capture::VBI::EPG |
1329 |
|
|
|
1330 |
|
|
void |
1331 |
|
|
decode_stream(stream) |
1332 |
|
|
SV * stream |
1333 |
|
|
PPCODE: |
1334 |
|
|
if (!SvROK(stream) || SvTYPE(SvRV(stream)) != SVt_PVAV) |
1335 |
|
|
croak ("decode_epg stream works on arrayrefs"); |
1336 |
|
|
|
1337 |
|
|
PUTBACK; |
1338 |
|
|
decode_stream ((AV*)SvRV(stream)); |
1339 |
|
|
SPAGAIN; |
1340 |
|
|
|
1341 |
|
|
SV * |
1342 |
|
|
decode_block(block, bundle) |
1343 |
|
|
SV * block |
1344 |
|
|
SV * bundle |
1345 |
|
|
PPCODE: |
1346 |
|
|
if (!SvROK(bundle) || SvTYPE(SvRV(bundle)) != SVt_PVAV) |
1347 |
|
|
croak ("bundle info must be arrayref"); |
1348 |
|
|
|
1349 |
|
|
PUTBACK; |
1350 |
|
|
decode_block (SvPV_nolen(block), SvCUR(block), (AV*)SvRV(bundle)); |
1351 |
|
|
SPAGAIN; |
1352 |
|
|
|
1353 |
|
|
BOOT: |
1354 |
|
|
{ |
1355 |
|
|
HV *stash = gv_stashpvn("Video::Capture::VBI", 19, TRUE); |
1356 |
|
|
|
1357 |
|
|
newCONSTSUB(stash,"VBI_VT", newSViv(VBI_VT)); |
1358 |
|
|
newCONSTSUB(stash,"VBI_VPS", newSViv(VBI_VPS)); |
1359 |
|
|
newCONSTSUB(stash,"VBI_VDAT", newSViv(VBI_VDAT)); |
1360 |
|
|
newCONSTSUB(stash,"VBI_VC", newSViv(VBI_VC)); |
1361 |
|
|
newCONSTSUB(stash,"VBI_EMPTY", newSViv(VBI_EMPTY)); |
1362 |
|
|
newCONSTSUB(stash,"VBI_OTHER", newSViv(VBI_OTHER)); |
1363 |
|
|
|
1364 |
|
|
newCONSTSUB(stash,"VTX_COLMASK",newSViv(VTX_COLMASK)); |
1365 |
|
|
newCONSTSUB(stash,"VTX_GRSEP", newSViv(VTX_GRSEP)); |
1366 |
|
|
newCONSTSUB(stash,"VTX_HIDDEN", newSViv(VTX_HIDDEN)); |
1367 |
|
|
newCONSTSUB(stash,"VTX_BOX", newSViv(VTX_BOX)); |
1368 |
|
|
newCONSTSUB(stash,"VTX_FLASH", newSViv(VTX_FLASH)); |
1369 |
|
|
newCONSTSUB(stash,"VTX_DOUBLE1",newSViv(VTX_DOUBLE1)); |
1370 |
|
|
newCONSTSUB(stash,"VTX_DOUBLE2",newSViv(VTX_DOUBLE2)); |
1371 |
|
|
newCONSTSUB(stash,"VTX_INVERT", newSViv(VTX_INVERT)); |
1372 |
|
|
newCONSTSUB(stash,"VTX_DOUBLE", newSViv(VTX_DOUBLE)); |
1373 |
|
|
} |
1374 |
|
|
|