1 /*
2 * libzvbi -- VBI device simulation
3 *
4 * Copyright (C) 2004, 2007 Michael H. Schimek
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA.
20 */
21
22 /* $Id: io-sim.c,v 1.18 2009-12-14 23:43:40 mschimek Exp $ */
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #ifdef _MSC_VER
29 #define _USE_MATH_DEFINES /* Needed for M_PI and M_LN2 */
30 #endif
31 #include <math.h> /* sin(), log() */
32 #include <errno.h>
33 #include <ctype.h> /* isspace() */
34 #include <limits.h> /* INT_MAX */
35
36 #include "misc.h"
37 #include "sliced.h"
38 #include "sampling_par.h"
39 #include "raw_decoder.h"
40 #include "hamm.h"
41
42 # define sp_sample_format sampling_format
43 # define SAMPLES_PER_LINE(sp) \
44 ((sp)->bytes_per_line / VBI_PIXFMT_BPP ((sp)->sampling_format))
45 # define SYSTEM_525(sp) \
46 (525 == (sp)->scanning)
47
48 #include "io-sim.h"
49
50 /*
51 * @addtogroup Rawenc Raw VBI encoder
52 * @ingroup Raw
53 * @brief Converting sliced VBI data to raw VBI images.
54 *
55 * These are functions converting sliced VBI data to raw VBI images as
56 * transmitted in the vertical blanking interval of analog video standards.
57 * They are mainly intended for tests of the libzvbi bit slicer and
58 * raw VBI decoder.
59 */
60
61 # define VBI_PIXFMT_RGB24_LE VBI_PIXFMT_RGB24
62 # define VBI_PIXFMT_BGR24_LE VBI_PIXFMT_BGR24
63 # define VBI_PIXFMT_RGBA24_LE VBI_PIXFMT_RGBA32_LE
64 # define VBI_PIXFMT_BGRA24_LE VBI_PIXFMT_BGRA32_LE
65 # define VBI_PIXFMT_RGBA24_BE VBI_PIXFMT_RGBA32_BE
66 # define VBI_PIXFMT_BGRA24_BE VBI_PIXFMT_BGRA32_BE
67 # define vbi_pixfmt_bytes_per_pixel VBI_PIXFMT_BPP
68
69 #define PI 3.1415926535897932384626433832795029
70
71 #define PULSE(zero_level) \
72 do { \
73 if (0 == seq) { \
74 raw[i] = SATURATE (zero_level, 0, 255); \
75 } else if (3 == seq) { \
76 raw[i] = SATURATE (zero_level + (int) signal_amp, \
77 0, 255); \
78 } else if ((seq ^ bit) & 1) { /* down */ \
79 double r = sin (q * tr - (PI / 2.0)); \
80 r = r * r * signal_amp; \
81 raw[i] = SATURATE (zero_level + (int) r, 0, 255); \
82 } else { /* up */ \
83 double r = sin (q * tr); \
84 r = r * r * signal_amp; \
85 raw[i] = SATURATE (zero_level + (int) r, 0, 255); \
86 } \
87 } while (0)
88
89 #define PULSE_SEQ(zero_level) \
90 do { \
91 double tr; \
92 unsigned int bit; \
93 unsigned int byte; \
94 unsigned int seq; \
95 \
96 tr = t - t1; \
97 bit = tr * bit_rate; \
98 byte = bit >> 3; \
99 bit &= 7; \
100 seq = (buf[byte] >> 7) + buf[byte + 1] * 2; \
101 seq = (seq >> bit) & 3; \
102 PULSE (zero_level); \
103 } while (0)
104
105 _vbi_inline void
vbi_sincos(double x,double * sinx,double * cosx)106 vbi_sincos (double x, double *sinx, double *cosx)
107 {
108 *sinx = sin (x);
109 *cosx = cos (x);
110 }
111
112 #define vbi_log2(x) (log (x) / M_LN2)
113
114 static void
signal_teletext(uint8_t * raw,const vbi_sampling_par * sp,int black_level,double signal_amp,double bit_rate,unsigned int frc,unsigned int payload,const vbi_sliced * sliced)115 signal_teletext (uint8_t * raw,
116 const vbi_sampling_par * sp,
117 int black_level,
118 double signal_amp,
119 double bit_rate,
120 unsigned int frc, unsigned int payload, const vbi_sliced * sliced)
121 {
122 double bit_period = 1.0 / bit_rate;
123 /* Teletext System B: Sixth CRI pulse at 12 us
124 (+.5 b/c we start with a 0 bit). */
125 double t1 = 12e-6 - 13 * bit_period;
126 double t2 = t1 + (payload * 8 + 24 + 1) * bit_period;
127 double q = (PI / 2.0) * bit_rate;
128 double sample_period = 1.0 / sp->sampling_rate;
129 unsigned int samples_per_line;
130 uint8_t buf[64];
131 unsigned int i;
132 double t;
133
134 buf[0] = 0x00;
135 buf[1] = 0x55; /* clock run-in */
136 buf[2] = 0x55;
137 buf[3] = frc;
138
139 memcpy (buf + 4, sliced->data, payload);
140
141 buf[payload + 4] = 0x00;
142
143 t = sp->offset / (double) sp->sampling_rate;
144
145 samples_per_line = SAMPLES_PER_LINE (sp);
146
147 for (i = 0; i < samples_per_line; ++i) {
148 if (t >= t1 && t < t2)
149 PULSE_SEQ (black_level);
150
151 t += sample_period;
152 }
153 }
154
155 static void
signal_vps(uint8_t * raw,const vbi_sampling_par * sp,int black_level,int white_level,const vbi_sliced * sliced)156 signal_vps (uint8_t * raw,
157 const vbi_sampling_par * sp,
158 int black_level, int white_level, const vbi_sliced * sliced)
159 {
160 static const uint8_t biphase[] = {
161 0xAA, 0x6A, 0x9A, 0x5A,
162 0xA6, 0x66, 0x96, 0x56,
163 0xA9, 0x69, 0x99, 0x59,
164 0xA5, 0x65, 0x95, 0x55
165 };
166 double bit_rate = 15625 * 160 * 2;
167 double t1 = 12.5e-6 - .5 / bit_rate;
168 double t4 = t1 + ((4 + 13 * 2) * 8) / bit_rate;
169 double q = (PI / 2.0) * bit_rate;
170 double sample_period = 1.0 / sp->sampling_rate;
171 unsigned int samples_per_line;
172 double signal_amp = (0.5 / 0.7) * (white_level - black_level);
173 uint8_t buf[32];
174 unsigned int i;
175 double t;
176
177 CLEAR (buf);
178
179 buf[1] = 0x55; /* 0101 0101 */
180 buf[2] = 0x55; /* 0101 0101 */
181 buf[3] = 0x51; /* 0101 0001 */
182 buf[4] = 0x99; /* 1001 1001 */
183
184 for (i = 0; i < 13; ++i) {
185 unsigned int b = sliced->data[i];
186
187 buf[5 + i * 2] = biphase[b >> 4];
188 buf[6 + i * 2] = biphase[b & 15];
189 }
190
191 buf[6 + 12 * 2] &= 0x7F;
192
193 t = sp->offset / (double) sp->sampling_rate;
194
195 samples_per_line = SAMPLES_PER_LINE (sp);
196
197 for (i = 0; i < samples_per_line; ++i) {
198 if (t >= t1 && t < t4)
199 PULSE_SEQ (black_level);
200
201 t += sample_period;
202 }
203 }
204
205 static void
wss_biphase(uint8_t buf[32],const vbi_sliced * sliced)206 wss_biphase (uint8_t buf[32], const vbi_sliced * sliced)
207 {
208 unsigned int bit;
209 unsigned int data;
210 unsigned int i;
211
212 /* 29 bit run-in and 24 bit start code, lsb first. */
213
214 buf[0] = 0x00;
215 buf[1] = 0x1F; /* 0001 1111 */
216 buf[2] = 0xC7; /* 1100 0111 */
217 buf[3] = 0x71; /* 0111 0001 */
218 buf[4] = 0x1C; /* 000 | 1 1100 */
219 buf[5] = 0x8F; /* 1000 1111 */
220 buf[6] = 0x07; /* 0000 0111 */
221 buf[7] = 0x1F; /* 1 1111 */
222
223 bit = 8 + 29 + 24;
224 data = sliced->data[0] + sliced->data[1] * 256;
225
226 for (i = 0; i < 14; ++i) {
227 static const unsigned int biphase[] = { 0x38, 0x07 };
228 unsigned int byte;
229 unsigned int shift;
230 unsigned int seq;
231
232 byte = bit >> 3;
233 shift = bit & 7;
234 bit += 6;
235
236 seq = biphase[data & 1] << shift;
237 data >>= 1;
238
239 assert (byte < 31);
240
241 buf[byte] |= seq;
242 buf[byte + 1] = seq >> 8;
243 }
244 }
245
246 static void
signal_wss_625(uint8_t * raw,const vbi_sampling_par * sp,int black_level,int white_level,const vbi_sliced * sliced)247 signal_wss_625 (uint8_t * raw,
248 const vbi_sampling_par * sp,
249 int black_level, int white_level, const vbi_sliced * sliced)
250 {
251 double bit_rate = 15625 * 320;
252 double t1 = 11.0e-6 - .5 / bit_rate;
253 double t4 = t1 + (29 + 24 + 14 * 6 + 1) / bit_rate;
254 double q = (PI / 2.0) * bit_rate;
255 double sample_period = 1.0 / sp->sampling_rate;
256 double signal_amp = (0.5 / 0.7) * (white_level - black_level);
257 unsigned int samples_per_line;
258 uint8_t buf[32];
259 unsigned int i;
260 double t;
261
262 CLEAR (buf);
263
264 wss_biphase (buf, sliced);
265
266 t = sp->offset / (double) sp->sampling_rate;
267
268 samples_per_line = SAMPLES_PER_LINE (sp);
269
270 for (i = 0; i < samples_per_line; ++i) {
271 if (t >= t1 && t < t4)
272 PULSE_SEQ (black_level);
273
274 t += sample_period;
275 }
276 }
277
278 static void
signal_closed_caption(uint8_t * raw,const vbi_sampling_par * sp,int blank_level,int white_level,unsigned int flags,double bit_rate,const vbi_sliced * sliced)279 signal_closed_caption (uint8_t * raw,
280 const vbi_sampling_par * sp,
281 int blank_level,
282 int white_level,
283 unsigned int flags, double bit_rate, const vbi_sliced * sliced)
284 {
285 double D = 1.0 / bit_rate;
286 double t0 = 10.5e-6; /* CRI start half amplitude (EIA 608-B) */
287 double t1 = t0 - .25 * D; /* CRI start, blanking level */
288 double t2 = t1 + 7 * D; /* CRI 7 cycles */
289 /* First start bit, left edge half amplitude, minus rise time. */
290 double t3 = t0 + 6.5 * D - 120e-9;
291 double q1 = PI * bit_rate * 2;
292 /* Max. rise/fall time 240 ns (EIA 608-B). */
293 double q2 = PI / 120e-9;
294 double signal_mean;
295 double signal_high;
296 double sample_period = 1.0 / sp->sampling_rate;
297 unsigned int samples_per_line;
298 double t;
299 unsigned int data;
300 unsigned int i;
301
302 /* Twice 7 data + odd parity, start bit 0 -> 1 */
303
304 data = (sliced->data[1] << 12) + (sliced->data[0] << 4) + 8;
305
306 t = sp->offset / (double) sp->sampling_rate;
307
308 samples_per_line = SAMPLES_PER_LINE (sp);
309
310 if (flags & _VBI_RAW_SHIFT_CC_CRI) {
311 /* Wrong signal shape found by Rich Kadel,
312 zapping-misc@lists.sourceforge.net 2006-07-16. */
313 t0 += D / 2;
314 t1 += D / 2;
315 t2 += D / 2;
316 }
317
318 if (flags & _VBI_RAW_LOW_AMP_CC) {
319 /* Low amplitude signal found by Rich Kadel,
320 zapping-misc@lists.sourceforge.net 2007-08-15. */
321 white_level = white_level * 6 / 10;
322 }
323
324 signal_mean = (white_level - blank_level) * .25; /* 25 IRE */
325 signal_high = blank_level + (white_level - blank_level) * .5;
326
327 for (i = 0; i < samples_per_line; ++i) {
328 if (t >= t1 && t < t2) {
329 raw[i] = SATURATE (blank_level + (1.0 - cos (q1 * (t - t1)))
330 * signal_mean, 0, 255);
331 } else {
332 unsigned int bit;
333 unsigned int seq;
334 double d;
335
336 d = t - t3;
337 bit = d * bit_rate;
338 seq = (data >> bit) & 3;
339
340 d -= bit * D;
341 if ((1 == seq || 2 == seq)
342 && fabs (d) < .120e-6) {
343 int level;
344
345 if (1 == seq)
346 level = blank_level + (1.0 + cos (q2 * d))
347 * signal_mean;
348 else
349 level = blank_level + (1.0 - cos (q2 * d))
350 * signal_mean;
351 raw[i] = SATURATE (level, 0, 255);
352 } else if (data & (2 << bit)) {
353 raw[i] = SATURATE (signal_high, 0, 255);
354 } else {
355 raw[i] = SATURATE (blank_level, 0, 255);
356 }
357 }
358
359 t += sample_period;
360 }
361 }
362
363 static void
clear_image(uint8_t * p,unsigned int value,unsigned int width,unsigned int height,unsigned int bytes_per_line)364 clear_image (uint8_t * p,
365 unsigned int value,
366 unsigned int width, unsigned int height, unsigned int bytes_per_line)
367 {
368 if (width == bytes_per_line) {
369 memset (p, value, height * bytes_per_line);
370 } else {
371 while (height-- > 0) {
372 memset (p, value, width);
373 p += bytes_per_line;
374 }
375 }
376 }
377
378 /*
379 * @param raw Noise will be added to this raw VBI image.
380 * @param sp Describes the raw VBI data in the buffer. @a sp->sampling_format
381 * must be @c VBI_PIXFMT_Y8 (@c VBI_PIXFMT_YUV420 in libzvbi 0.2.x).
382 * Note for compatibility in libzvbi 0.2.x vbi_sampling_par is a
383 * synonym of vbi_raw_decoder, but the (private) decoder fields in
384 * this structure are ignored.
385 * @param min_freq Minimum frequency of the noise in Hz.
386 * @param max_freq Maximum frequency of the noise in Hz. @a min_freq and
387 * @a max_freq define the cut off frequency at the half power points
388 * (gain -3 dB).
389 * @param amplitude Maximum amplitude of the noise, should lie in range
390 * 0 to 256.
391 * @param seed Seed for the pseudo random number generator built into
392 * this function. Given the same @a seed value the function will add
393 * the same noise, which can be useful for tests.
394 *
395 * This function adds white noise to a raw VBI image.
396 *
397 * To produce realistic noise @a min_freq = 0, @a max_freq = 5e6 and
398 * @a amplitude = 20 to 50 seems appropriate.
399 *
400 * @returns
401 * FALSE if the @a sp sampling parameters are invalid.
402 *
403 * @since 0.2.26
404 */
405 vbi_bool
vbi_raw_add_noise(uint8_t * raw,const vbi_sampling_par * sp,unsigned int min_freq,unsigned int max_freq,unsigned int amplitude,unsigned int seed)406 vbi_raw_add_noise (uint8_t * raw,
407 const vbi_sampling_par * sp,
408 unsigned int min_freq,
409 unsigned int max_freq, unsigned int amplitude, unsigned int seed)
410 {
411 double f0, w0, sn, cs, bw, alpha, a0;
412 float a1, a2, b0, b1, z0, z1, z2;
413 unsigned int n_lines;
414 unsigned long samples_per_line;
415 unsigned long padding;
416 uint32_t seed32;
417
418 assert (NULL != raw);
419 assert (NULL != sp);
420
421 if (unlikely (!_vbi_sampling_par_valid_log (sp, /* log */ NULL)))
422 return FALSE;
423
424 switch (sp->sp_sample_format) {
425 case VBI_PIXFMT_YUV420:
426 break;
427
428 default:
429 return FALSE;
430 }
431
432 if (unlikely (sp->sampling_rate <= 0))
433 return FALSE;
434
435 /* Biquad bandpass filter.
436 http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt */
437
438 f0 = ((double) min_freq + max_freq) * 0.5;
439
440 if (f0 <= 0.0)
441 return TRUE;
442
443 w0 = 2 * M_PI * f0 / sp->sampling_rate;
444 vbi_sincos (w0, &sn, &cs);
445 bw = fabs (vbi_log2 (MAX (min_freq, max_freq) / f0));
446 alpha = sn * sinh (log (2) / 2 * bw * w0 / sn);
447 a0 = 1 + alpha;
448 a1 = 2 * cs / a0;
449 a2 = (alpha - 1) / a0;
450 b0 = sn / (2 * a0);
451 b1 = 0;
452
453 if (amplitude > 256)
454 amplitude = 256;
455
456 n_lines = sp->count[0] + sp->count[1];
457
458 if (unlikely (0 == amplitude || 0 == n_lines || 0 == sp->bytes_per_line))
459 return TRUE;
460
461 samples_per_line = sp->bytes_per_line;
462 padding = 0;
463
464 seed32 = seed;
465
466 z1 = 0;
467 z2 = 0;
468
469 do {
470 uint8_t *raw_end = raw + samples_per_line;
471
472 do {
473 int noise;
474
475 /* We use our own simple PRNG to produce
476 predictable results for tests. */
477 seed32 = seed32 * 1103515245u + 12345;
478 noise = ((seed32 / 65536) % (amplitude * 2 + 1))
479 - amplitude;
480
481 z0 = noise + a1 * z1 + a2 * z2;
482 noise = (int) (b0 * (z0 - z2) + b1 * z1);
483 z2 = z1;
484 z1 = z0;
485
486 *raw++ = SATURATE (*raw + noise, 0, 255);
487 } while (raw < raw_end);
488
489 raw += padding;
490 } while (--n_lines > 0);
491
492 return TRUE;
493 }
494
495 static vbi_bool
signal_u8(uint8_t * raw,const vbi_sampling_par * sp,int blank_level,int black_level,int white_level,unsigned int flags,const vbi_sliced * sliced,unsigned int n_sliced_lines,const char * caller)496 signal_u8 (uint8_t * raw,
497 const vbi_sampling_par * sp,
498 int blank_level,
499 int black_level,
500 int white_level,
501 unsigned int flags,
502 const vbi_sliced * sliced, unsigned int n_sliced_lines, const char *caller)
503 {
504 unsigned int n_scan_lines;
505 unsigned int samples_per_line;
506
507 n_scan_lines = sp->count[0] + sp->count[1];
508 samples_per_line = SAMPLES_PER_LINE (sp);
509
510 clear_image (raw,
511 SATURATE (blank_level, 0, 255),
512 samples_per_line, n_scan_lines, sp->bytes_per_line);
513
514 for (; n_sliced_lines-- > 0; ++sliced) {
515 unsigned int row;
516 uint8_t *raw1;
517
518 if (0 == sliced->line) {
519 goto bounds;
520 } else if (0 != sp->start[1]
521 && sliced->line >= (unsigned int) sp->start[1]) {
522 row = sliced->line - sp->start[1];
523 if (row >= (unsigned int) sp->count[1])
524 goto bounds;
525
526 if (sp->interlaced) {
527 row = row * 2 + !(flags & _VBI_RAW_SWAP_FIELDS);
528 } else if (0 == (flags & _VBI_RAW_SWAP_FIELDS)) {
529 row += sp->count[0];
530 }
531 } else if (0 != sp->start[0]
532 && sliced->line >= (unsigned int) sp->start[0]) {
533 row = sliced->line - sp->start[0];
534 if (row >= (unsigned int) sp->count[0])
535 goto bounds;
536
537 if (sp->interlaced) {
538 row *= 2 + ! !(flags & _VBI_RAW_SWAP_FIELDS);
539 } else if (flags & _VBI_RAW_SWAP_FIELDS) {
540 row += sp->count[0];
541 }
542 } else {
543 bounds:
544 warn (caller, "Sliced line %u out of bounds.", sliced->line);
545 return FALSE;
546 }
547
548 raw1 = raw + row * sp->bytes_per_line;
549
550 switch (sliced->id) {
551 case VBI_SLICED_TELETEXT_A: /* ok? */
552 signal_teletext (raw1, sp, black_level,
553 /* amplitude */ .7 * (white_level
554 - black_level),
555 /* bit_rate */ 25 * 625 * 397,
556 /* FRC */ 0xE7,
557 /* payload */ 37,
558 sliced);
559 break;
560
561 case VBI_SLICED_TELETEXT_B_L10_625:
562 case VBI_SLICED_TELETEXT_B_L25_625:
563 case VBI_SLICED_TELETEXT_B:
564 signal_teletext (raw1, sp, black_level,
565 .66 * (white_level - black_level),
566 25 * 625 * 444, 0x27, 42, sliced);
567 break;
568
569 case VBI_SLICED_TELETEXT_C_625:
570 signal_teletext (raw1, sp, black_level,
571 .7 * (white_level - black_level), 25 * 625 * 367, 0xE7, 33, sliced);
572 break;
573
574 case VBI_SLICED_TELETEXT_D_625:
575 signal_teletext (raw1, sp, black_level,
576 .7 * (white_level - black_level), 5642787, 0xA7, 34, sliced);
577 break;
578
579 case VBI_SLICED_CAPTION_625_F1:
580 case VBI_SLICED_CAPTION_625_F2:
581 case VBI_SLICED_CAPTION_625:
582 signal_closed_caption (raw1, sp,
583 blank_level, white_level, flags, 25 * 625 * 32, sliced);
584 break;
585
586 case VBI_SLICED_VPS:
587 case VBI_SLICED_VPS_F2:
588 signal_vps (raw1, sp, black_level, white_level, sliced);
589 break;
590
591 case VBI_SLICED_WSS_625:
592 signal_wss_625 (raw1, sp, black_level, white_level, sliced);
593 break;
594
595 case VBI_SLICED_TELETEXT_B_525:
596 signal_teletext (raw1, sp, black_level,
597 /* amplitude */ .7 * (white_level
598 - black_level),
599 /* bit_rate */ 5727272,
600 /* FRC */ 0x27,
601 /* payload */ 34,
602 sliced);
603 break;
604
605 case VBI_SLICED_TELETEXT_C_525:
606 signal_teletext (raw1, sp, black_level,
607 .7 * (white_level - black_level), 5727272, 0xE7, 33, sliced);
608 break;
609
610 case VBI_SLICED_TELETEXT_D_525:
611 signal_teletext (raw1, sp, black_level,
612 .7 * (white_level - black_level), 5727272, 0xA7, 34, sliced);
613 break;
614
615 case VBI_SLICED_CAPTION_525_F1:
616 case VBI_SLICED_CAPTION_525_F2:
617 case VBI_SLICED_CAPTION_525:
618 signal_closed_caption (raw1, sp,
619 blank_level, white_level, flags, 30000 * 525 * 32 / 1001, sliced);
620 break;
621
622 default:
623 warn (caller,
624 "Service 0x%08x (%s) not supported.",
625 sliced->id, vbi_sliced_name (sliced->id));
626 return FALSE;
627 }
628 }
629
630 return TRUE;
631 }
632
633 vbi_bool
_vbi_raw_vbi_image(uint8_t * raw,unsigned long raw_size,const vbi_sampling_par * sp,int blank_level,int white_level,unsigned int flags,const vbi_sliced * sliced,unsigned int n_sliced_lines)634 _vbi_raw_vbi_image (uint8_t * raw,
635 unsigned long raw_size,
636 const vbi_sampling_par * sp,
637 int blank_level,
638 int white_level,
639 unsigned int flags, const vbi_sliced * sliced, unsigned int n_sliced_lines)
640 {
641 unsigned int n_scan_lines;
642 unsigned int black_level;
643
644 if (unlikely (!_vbi_sampling_par_valid_log (sp, NULL)))
645 return FALSE;
646
647 n_scan_lines = sp->count[0] + sp->count[1];
648 if (unlikely (n_scan_lines * sp->bytes_per_line > raw_size)) {
649 warn (__FUNCTION__,
650 "(%u + %u lines) * %lu bytes_per_line "
651 "> %lu raw_size.",
652 sp->count[0], sp->count[1],
653 (unsigned long) sp->bytes_per_line, raw_size);
654 return FALSE;
655 }
656
657 if (unlikely (0 != white_level && blank_level > white_level)) {
658 warn (__FUNCTION__,
659 "Invalid blanking %d or peak white level %d.",
660 blank_level, white_level);
661 }
662
663 if (SYSTEM_525 (sp)) {
664 /* Observed value. */
665 const unsigned int peak = 200; /* 255 */
666
667 if (0 == white_level) {
668 blank_level = (int) (40.0 * peak / 140);
669 black_level = (int) (47.5 * peak / 140);
670 white_level = peak;
671 } else {
672 black_level = (int) (blank_level + 7.5 * (white_level - blank_level));
673 }
674 } else {
675 const unsigned int peak = 200; /* 255 */
676
677 if (0 == white_level) {
678 blank_level = (int) (43.0 * peak / 140);
679 white_level = peak;
680 }
681
682 black_level = blank_level;
683 }
684
685 return signal_u8 (raw, sp,
686 blank_level, black_level, white_level,
687 flags, sliced, n_sliced_lines, __FUNCTION__);
688 }
689
690 #define RGBA_TO_RGB16(value) \
691 (+(((value) & 0xF8) >> (3 - 0)) \
692 +(((value) & 0xFC00) >> (10 - 5)) \
693 +(((value) & 0xF80000) >> (19 - 11)))
694
695 #define RGBA_TO_RGBA15(value) \
696 (+(((value) & 0xF8) >> (3 - 0)) \
697 +(((value) & 0xF800) >> (11 - 5)) \
698 +(((value) & 0xF80000) >> (19 - 10)) \
699 +(((value) & 0x80000000) >> (31 - 15)))
700
701 #define RGBA_TO_ARGB15(value) \
702 (+(((value) & 0xF8) >> (3 - 1)) \
703 +(((value) & 0xF800) >> (11 - 6)) \
704 +(((value) & 0xF80000) >> (19 - 11)) \
705 +(((value) & 0x80000000) >> (31 - 0)))
706
707 #define RGBA_TO_RGBA12(value) \
708 (+(((value) & 0xF0) >> (4 - 0)) \
709 +(((value) & 0xF000) >> (12 - 4)) \
710 +(((value) & 0xF00000) >> (20 - 8)) \
711 +(((value) & 0xF0000000) >> (28 - 12)))
712
713 #define RGBA_TO_ARGB12(value) \
714 (+(((value) & 0xF0) << -(4 - 12)) \
715 +(((value) & 0xF000) >> (12 - 8)) \
716 +(((value) & 0xF00000) >> (20 - 4)) \
717 +(((value) & 0xF0000000) >> (28 - 0)))
718
719 #define RGBA_TO_RGB8(value) \
720 (+(((value) & 0xE0) >> (5 - 0)) \
721 +(((value) & 0xE000) >> (13 - 3)) \
722 +(((value) & 0xC00000) >> (22 - 6)))
723
724 #define RGBA_TO_BGR8(value) \
725 (+(((value) & 0xE0) >> (5 - 5)) \
726 +(((value) & 0xE000) >> (13 - 2)) \
727 +(((value) & 0xC00000) >> (22 - 0)))
728
729 #define RGBA_TO_RGBA7(value) \
730 (+(((value) & 0xC0) >> (6 - 0)) \
731 +(((value) & 0xE000) >> (13 - 2)) \
732 +(((value) & 0xC00000) >> (22 - 5)) \
733 +(((value) & 0x80000000) >> (31 - 7)))
734
735 #define RGBA_TO_ARGB7(value) \
736 (+(((value) & 0xC0) >> (6 - 6)) \
737 +(((value) & 0xE000) >> (13 - 3)) \
738 +(((value) & 0xC00000) >> (22 - 1)) \
739 +(((value) & 0x80000000) >> (31 - 0)))
740
741 #define MST1(d, val, mask) (d) = ((d) & ~(mask)) | ((val) & (mask))
742 #define MST2(d, val, mask) (d) = ((d) & (mask)) | (val)
743
744 #define SCAN_LINE_TO_N(conv, n) \
745 do { \
746 for (i = 0; i < samples_per_line; ++i) { \
747 uint8_t *dd = d + i * (n); \
748 unsigned int value = s[i] * 0x01010101; \
749 unsigned int mask = ~pixel_mask; \
750 \
751 value = conv (value) & pixel_mask; \
752 MST2 (dd[0], value >> 0, mask >> 0); \
753 if (n >= 2) \
754 MST2 (dd[1], value >> 8, mask >> 8); \
755 if (n >= 3) \
756 MST2 (dd[2], value >> 16, mask >> 16); \
757 if (n >= 4) \
758 MST2 (dd[3], value >> 24, mask >> 24); \
759 } \
760 } while (0)
761
762 #define SCAN_LINE_TO_RGB2(conv, endian) \
763 do { \
764 for (i = 0; i < samples_per_line; ++i) { \
765 uint8_t *dd = d + i * 2; \
766 unsigned int value = s[i] * 0x01010101; \
767 unsigned int mask; \
768 \
769 value = conv (value) & pixel_mask; \
770 mask = ~pixel_mask; \
771 MST2 (dd[0 + endian], value >> 0, mask >> 0); \
772 MST2 (dd[1 - endian], value >> 8, mask >> 8); \
773 } \
774 } while (0)
775
776 vbi_bool
_vbi_raw_video_image(uint8_t * raw,unsigned long raw_size,const vbi_sampling_par * sp,int blank_level,int black_level,int white_level,unsigned int pixel_mask,unsigned int flags,const vbi_sliced * sliced,unsigned int n_sliced_lines)777 _vbi_raw_video_image (uint8_t * raw,
778 unsigned long raw_size,
779 const vbi_sampling_par * sp,
780 int blank_level,
781 int black_level,
782 int white_level,
783 unsigned int pixel_mask,
784 unsigned int flags, const vbi_sliced * sliced, unsigned int n_sliced_lines)
785 {
786 unsigned int n_scan_lines;
787 unsigned int samples_per_line;
788 vbi_sampling_par sp8;
789 unsigned int size;
790 uint8_t *buf;
791 uint8_t *s;
792 uint8_t *d;
793
794 if (unlikely (!_vbi_sampling_par_valid_log (sp, NULL)))
795 return FALSE;
796
797 n_scan_lines = sp->count[0] + sp->count[1];
798 if (unlikely (n_scan_lines * sp->bytes_per_line > raw_size)) {
799 warn (__FUNCTION__,
800 "%u + %u lines * %lu bytes_per_line > %lu raw_size.",
801 sp->count[0], sp->count[1],
802 (unsigned long) sp->bytes_per_line, raw_size);
803 return FALSE;
804 }
805
806 if (unlikely (0 != white_level
807 && (blank_level > black_level || black_level > white_level))) {
808 warn (__FUNCTION__,
809 "Invalid blanking %d, black %d or peak "
810 "white level %d.", blank_level, black_level, white_level);
811 }
812
813 switch (sp->sp_sample_format) {
814 case VBI_PIXFMT_YVYU:
815 case VBI_PIXFMT_VYUY: /* 0xAAUUVVYY */
816 pixel_mask = (+((pixel_mask & 0xFF00) << 8)
817 + ((pixel_mask & 0xFF0000) >> 8)
818 + ((pixel_mask & 0xFF0000FF)));
819 break;
820
821 case VBI_PIXFMT_RGBA24_BE: /* 0xRRGGBBAA */
822 pixel_mask = SWAB32 (pixel_mask);
823 break;
824
825 case VBI_PIXFMT_BGR24_LE: /* 0x00RRGGBB */
826 case VBI_PIXFMT_BGRA15_LE:
827 case VBI_PIXFMT_BGRA15_BE:
828 case VBI_PIXFMT_ABGR15_LE:
829 case VBI_PIXFMT_ABGR15_BE:
830 pixel_mask = (+((pixel_mask & 0xFF) << 16)
831 + ((pixel_mask & 0xFF0000) >> 16)
832 + ((pixel_mask & 0xFF00FF00)));
833 break;
834
835 case VBI_PIXFMT_BGRA24_BE: /* 0xBBGGRRAA */
836 pixel_mask = (+((pixel_mask & 0xFFFFFF) << 8)
837 + ((pixel_mask & 0xFF000000) >> 24));
838 break;
839
840 default:
841 break;
842 }
843
844 switch (sp->sp_sample_format) {
845 case VBI_PIXFMT_RGB16_LE:
846 case VBI_PIXFMT_RGB16_BE:
847 case VBI_PIXFMT_BGR16_LE:
848 case VBI_PIXFMT_BGR16_BE:
849 pixel_mask = RGBA_TO_RGB16 (pixel_mask);
850 break;
851
852 case VBI_PIXFMT_RGBA15_LE:
853 case VBI_PIXFMT_RGBA15_BE:
854 case VBI_PIXFMT_BGRA15_LE:
855 case VBI_PIXFMT_BGRA15_BE:
856 pixel_mask = RGBA_TO_RGBA15 (pixel_mask);
857 break;
858
859 case VBI_PIXFMT_ARGB15_LE:
860 case VBI_PIXFMT_ARGB15_BE:
861 case VBI_PIXFMT_ABGR15_LE:
862 case VBI_PIXFMT_ABGR15_BE:
863 pixel_mask = RGBA_TO_ARGB15 (pixel_mask);
864 break;
865
866 default:
867 break;
868 }
869
870 if (0 == pixel_mask) {
871 /* Done! :-) */
872 return TRUE;
873 }
874
875 /* ITU-R BT.601 sampling assumed. */
876
877 if (SYSTEM_525 (sp)) {
878 if (0 == white_level) {
879 /* Cutting off the bottom of the signal
880 confuses the vbi_bit_slicer (can't adjust
881 the threshold fast enough), probably other
882 decoders as well. */
883 blank_level = 5; /* 16 - 40 * 220 / 100; */
884 black_level = 16;
885 white_level = 16 + 219;
886 }
887 } else {
888 if (0 == white_level) {
889 /* Observed values: 30-30-280 (WSS PAL) -? */
890 blank_level = 5; /* 16 - 43 * 220 / 100; */
891 black_level = 16;
892 white_level = 16 + 219;
893 }
894 }
895
896 sp8 = *sp;
897
898 samples_per_line = SAMPLES_PER_LINE (sp);
899
900 sp8.sampling_format = VBI_PIXFMT_YUV420;
901
902 sp8.bytes_per_line = samples_per_line * 1 /* bpp */ ;
903
904 size = n_scan_lines * samples_per_line;
905 buf = vbi_malloc (size);
906 if (NULL == buf) {
907 error (NULL, "Out of memory.");
908 errno = ENOMEM;
909 return FALSE;
910 }
911
912 if (!signal_u8 (buf, &sp8,
913 blank_level, black_level, white_level,
914 flags, sliced, n_sliced_lines, __FUNCTION__)) {
915 vbi_free (buf);
916 return FALSE;
917 }
918
919 s = buf;
920 d = raw;
921
922 while (n_scan_lines-- > 0) {
923 unsigned int i;
924
925 switch (sp->sp_sample_format) {
926 case VBI_PIXFMT_PAL8:
927 case VBI_PIXFMT_YUV420:
928 for (i = 0; i < samples_per_line; ++i)
929 MST1 (d[i], s[i], pixel_mask);
930 break;
931
932 case VBI_PIXFMT_RGBA24_LE:
933 case VBI_PIXFMT_RGBA24_BE:
934 case VBI_PIXFMT_BGRA24_LE:
935 case VBI_PIXFMT_BGRA24_BE:
936 SCAN_LINE_TO_N (+, 4);
937 break;
938
939 case VBI_PIXFMT_RGB24_LE:
940 case VBI_PIXFMT_BGR24_LE:
941 SCAN_LINE_TO_N (+, 3);
942 break;
943
944 case VBI_PIXFMT_YUYV:
945 case VBI_PIXFMT_YVYU:
946 for (i = 0; i < samples_per_line; i += 2) {
947 uint8_t *dd = d + i * 2;
948 unsigned int uv = (s[i] + s[i + 1] + 1) >> 1;
949
950 MST1 (dd[0], s[i], pixel_mask);
951 MST1 (dd[1], uv, pixel_mask >> 8);
952 MST1 (dd[2], s[i + 1], pixel_mask);
953 MST1 (dd[3], uv, pixel_mask >> 16);
954 }
955 break;
956
957 case VBI_PIXFMT_UYVY:
958 case VBI_PIXFMT_VYUY:
959 for (i = 0; i < samples_per_line; i += 2) {
960 uint8_t *dd = d + i * 2;
961 unsigned int uv = (s[i] + s[i + 1] + 1) >> 1;
962
963 MST1 (dd[0], uv, pixel_mask >> 8);
964 MST1 (dd[1], s[i], pixel_mask);
965 MST1 (dd[2], uv, pixel_mask >> 16);
966 MST1 (dd[3], s[i + 1], pixel_mask);
967 }
968 break;
969
970 case VBI_PIXFMT_RGB16_LE:
971 case VBI_PIXFMT_BGR16_LE:
972 SCAN_LINE_TO_RGB2 (RGBA_TO_RGB16, 0);
973 break;
974
975 case VBI_PIXFMT_RGB16_BE:
976 case VBI_PIXFMT_BGR16_BE:
977 SCAN_LINE_TO_RGB2 (RGBA_TO_RGB16, 1);
978 break;
979
980 case VBI_PIXFMT_RGBA15_LE:
981 case VBI_PIXFMT_BGRA15_LE:
982 SCAN_LINE_TO_RGB2 (RGBA_TO_RGBA15, 0);
983 break;
984
985 case VBI_PIXFMT_RGBA15_BE:
986 case VBI_PIXFMT_BGRA15_BE:
987 SCAN_LINE_TO_RGB2 (RGBA_TO_RGBA15, 1);
988 break;
989
990 case VBI_PIXFMT_ARGB15_LE:
991 case VBI_PIXFMT_ABGR15_LE:
992 SCAN_LINE_TO_RGB2 (RGBA_TO_ARGB15, 0);
993 break;
994
995 case VBI_PIXFMT_ARGB15_BE:
996 case VBI_PIXFMT_ABGR15_BE:
997 SCAN_LINE_TO_RGB2 (RGBA_TO_ARGB15, 1);
998 break;
999
1000 }
1001
1002 s += sp8.bytes_per_line;
1003 d += sp->bytes_per_line;
1004 }
1005
1006 vbi_free (buf);
1007
1008 return TRUE;
1009 }
1010
1011 /*
1012 * @example examples/rawout.c
1013 * Raw VBI output example.
1014 */
1015
1016 /*
1017 * @param raw A raw VBI image will be stored here.
1018 * @param raw_size Size of the @a raw buffer in bytes. The buffer
1019 * must be large enough for @a sp->count[0] + count[1] lines
1020 * of @a sp->bytes_per_line each, with @a sp->samples_per_line
1021 * (in libzvbi 0.2.x @a sp->bytes_per_line) bytes actually written.
1022 * @param sp Describes the raw VBI data to generate. @a sp->sampling_format
1023 * must be @c VBI_PIXFMT_Y8 (@c VBI_PIXFMT_YUV420 with libzvbi 0.2.x).
1024 * @a sp->synchronous is ignored. Note for compatibility in libzvbi
1025 * 0.2.x vbi_sampling_par is a synonym of vbi_raw_decoder, but the
1026 * (private) decoder fields in this structure are ignored.
1027 * @param blank_level The level of the horizontal blanking in the raw
1028 * VBI image. Must be <= @a white_level.
1029 * @param white_level The peak white level in the raw VBI image. Set to
1030 * zero to get the default blanking and white level.
1031 * @param swap_fields If @c TRUE the second field will be stored first
1032 * in the @c raw buffer. Note you can also get an interlaced image
1033 * by setting @a sp->interlaced to @c TRUE. @a sp->synchronous is
1034 * ignored.
1035 * @param sliced Pointer to an array of vbi_sliced containing the
1036 * VBI data to be encoded.
1037 * @param n_sliced_lines Number of elements in the @a sliced array.
1038 *
1039 * This function basically reverses the operation of the vbi_raw_decoder,
1040 * taking sliced VBI data and generating a raw VBI image similar to those
1041 * you would get from raw VBI sampling hardware. The following data services
1042 * are currently supported: All Teletext services, VPS, WSS 625, Closed
1043 * Caption 525 and 625.
1044 *
1045 * The function encodes sliced data as is, e.g. without adding or
1046 * checking parity bits, without checking if the line number is correct
1047 * for the respective data service, or if the signal will fit completely
1048 * in the given space (@a sp->offset and @a sp->samples_per_line at
1049 * @a sp->sampling_rate).
1050 *
1051 * Apart of the payload the generated video signal is invariable and
1052 * attempts to be faithful to related standards. You can only change the
1053 * characteristics of the assumed capture device. Sync pulses and color
1054 * bursts and not generated if the sampling parameters extend to this area.
1055 *
1056 * @note
1057 * This function is mainly intended for testing purposes. It is optimized
1058 * for accuracy, not for speed.
1059 *
1060 * @returns
1061 * @c FALSE if the @a raw_size is too small, if the @a sp sampling
1062 * parameters are invalid, if the signal levels are invalid,
1063 * if the @a sliced array contains unsupported services or line numbers
1064 * outside the @a sp sampling parameters.
1065 *
1066 * @since 0.2.22
1067 */
1068 vbi_bool
vbi_raw_vbi_image(uint8_t * raw,unsigned long raw_size,const vbi_sampling_par * sp,int blank_level,int white_level,vbi_bool swap_fields,const vbi_sliced * sliced,unsigned int n_sliced_lines)1069 vbi_raw_vbi_image (uint8_t * raw,
1070 unsigned long raw_size,
1071 const vbi_sampling_par * sp,
1072 int blank_level,
1073 int white_level,
1074 vbi_bool swap_fields,
1075 const vbi_sliced * sliced, unsigned int n_sliced_lines)
1076 {
1077 return _vbi_raw_vbi_image (raw, raw_size, sp,
1078 blank_level, white_level,
1079 swap_fields ? _VBI_RAW_SWAP_FIELDS : 0, sliced, n_sliced_lines);
1080 }
1081
1082 /*
1083 * @param raw A raw VBI image will be stored here.
1084 * @param raw_size Size of the @a raw buffer in bytes. The buffer
1085 * must be large enough for @a sp->count[0] + count[1] lines
1086 * of @a sp->bytes_per_line each, with @a sp->samples_per_line
1087 * times bytes per pixel (in libzvbi 0.2.x @a sp->bytes_per_line)
1088 * actually written.
1089 * @param sp Describes the raw VBI data to generate. Note for
1090 * compatibility in libzvbi 0.2.x vbi_sampling_par is a synonym of
1091 * vbi_raw_decoder, but the (private) decoder fields in this
1092 * structure are ignored.
1093 * @param blank_level The level of the horizontal blanking in the raw
1094 * VBI image. Must be <= @a black_level.
1095 * @param black_level The black level in the raw VBI image. Must be
1096 * <= @a white_level.
1097 * @param white_level The peak white level in the raw VBI image. Set to
1098 * zero to get the default blanking, black and white level.
1099 * @param pixel_mask This mask selects which color or alpha channel
1100 * shall contain VBI data. Depending on @a sp->sampling_format it is
1101 * interpreted as 0xAABBGGRR or 0xAAVVUUYY. A value of 0x000000FF
1102 * for example writes data in "red bits", not changing other
1103 * bits in the @a raw buffer. When the @a sp->sampling_format is a
1104 * planar YUV the function writes the Y plane only.
1105 * @param swap_fields If @c TRUE the second field will be stored first
1106 * in the @c raw buffer. Note you can also get an interlaced image
1107 * by setting @a sp->interlaced to @c TRUE. @a sp->synchronous is
1108 * ignored.
1109 * @param sliced Pointer to an array of vbi_sliced containing the
1110 * VBI data to be encoded.
1111 * @param n_sliced_lines Number of elements in the @a sliced array.
1112 *
1113 * Generates a raw VBI image similar to those you get from video
1114 * capture hardware. Otherwise identical to vbi_raw_vbi_image().
1115 *
1116 * @returns
1117 * @c FALSE if the @a raw_size is too small, if the @a sp sampling
1118 * parameters are invalid, if the signal levels are invalid,
1119 * if the @a sliced array contains unsupported services or line numbers
1120 * outside the @a sp sampling parameters.
1121 *
1122 * @since 0.2.22
1123 */
1124 vbi_bool
vbi_raw_video_image(uint8_t * raw,unsigned long raw_size,const vbi_sampling_par * sp,int blank_level,int black_level,int white_level,unsigned int pixel_mask,vbi_bool swap_fields,const vbi_sliced * sliced,unsigned int n_sliced_lines)1125 vbi_raw_video_image (uint8_t * raw,
1126 unsigned long raw_size,
1127 const vbi_sampling_par * sp,
1128 int blank_level,
1129 int black_level,
1130 int white_level,
1131 unsigned int pixel_mask,
1132 vbi_bool swap_fields,
1133 const vbi_sliced * sliced, unsigned int n_sliced_lines)
1134 {
1135 return _vbi_raw_video_image (raw, raw_size, sp,
1136 blank_level, black_level,
1137 white_level, pixel_mask,
1138 swap_fields ? _VBI_RAW_SWAP_FIELDS : 0, sliced, n_sliced_lines);
1139 }
1140
1141 /*
1142 Local variables:
1143 c-set-style: K&R
1144 c-basic-offset: 8
1145 End:
1146 */
1147