mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 05:31:15 +00:00
842 lines
23 KiB
C
842 lines
23 KiB
C
/*
|
|
* libzvbi -- Old raw VBI decoder
|
|
*
|
|
* Copyright (C) 2000, 2001, 2002 Michael H. Schimek
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
/* $Id: decoder.c,v 1.25 2008-02-19 00:35:15 mschimek Exp $ */
|
|
|
|
/* Note this code is only retained for compatibility with older versions
|
|
of libzvbi. vbi_raw_decoder is now just a wrapper for the new raw
|
|
decoder (raw_decoder.c) and bit slicer (bit_slicer.c). We'll drop
|
|
the old API in libzvbi 0.3. Other modules (e.g. io-v4l2k.c) should
|
|
already use the new raw VBI decoder directly. */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <glib.h>
|
|
|
|
#include "misc.h"
|
|
#include "decoder.h"
|
|
#include "raw_decoder.h"
|
|
|
|
/**
|
|
* @addtogroup Rawdec Raw VBI decoder
|
|
* @ingroup Raw
|
|
* @brief Converting raw VBI samples to bits and bytes.
|
|
*
|
|
* The libzvbi already offers hardware interfaces to obtain sliced
|
|
* VBI data for further processing. However if you want to write your own
|
|
* interface or decode data services not covered by libzvbi you can use
|
|
* these lower level functions.
|
|
*/
|
|
|
|
#if 0 /* LEGACY BIT SLICER */
|
|
/*
|
|
* Bit Slicer
|
|
*/
|
|
|
|
#define OVERSAMPLING 4 /* 1, 2, 4, 8 */
|
|
#define THRESH_FRAC 9
|
|
|
|
/*
|
|
* Note this is just a template. The code is inlined,
|
|
* with bpp and endian being const.
|
|
*
|
|
* This function translates from the image format to
|
|
* plain bytes, with linear interpolation of samples.
|
|
* Could be further improved with a lowpass filter.
|
|
*/
|
|
static inline unsigned int
|
|
sample (uint8_t * raw, int offs, int bpp, int endian)
|
|
{
|
|
unsigned char frac = offs;
|
|
int raw0, raw1;
|
|
|
|
switch (bpp) {
|
|
case 14: /* 1:5:5:5 LE/BE */
|
|
raw += (offs >> 8) * 2;
|
|
raw0 = (raw[0 + endian] + raw[1 - endian] * 256) & 0x07C0;
|
|
raw1 = (raw[2 + endian] + raw[3 - endian] * 256) & 0x07C0;
|
|
return (raw1 - raw0) * frac + (raw0 << 8);
|
|
|
|
case 15: /* 5:5:5:1 LE/BE */
|
|
raw += (offs >> 8) * 2;
|
|
raw0 = (raw[0 + endian] + raw[1 - endian] * 256) & 0x03E0;
|
|
raw1 = (raw[2 + endian] + raw[3 - endian] * 256) & 0x03E0;
|
|
return (raw1 - raw0) * frac + (raw0 << 8);
|
|
|
|
case 16: /* 5:6:5 LE/BE */
|
|
raw += (offs >> 8) * 2;
|
|
raw0 = (raw[0 + endian] + raw[1 - endian] * 256) & 0x07E0;
|
|
raw1 = (raw[2 + endian] + raw[3 - endian] * 256) & 0x07E0;
|
|
return (raw1 - raw0) * frac + (raw0 << 8);
|
|
|
|
default: /* 8 (intermediate bytes skipped by caller) */
|
|
raw += (offs >> 8) * bpp;
|
|
return (raw[bpp] - raw[0]) * frac + (raw[0] << 8);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Note this is just a template. The code is inlined,
|
|
* with bpp being const.
|
|
*/
|
|
static inline vbi_bool
|
|
bit_slicer_tmpl (vbi_bit_slicer * d, uint8_t * raw,
|
|
uint8_t * buf, int bpp, int endian)
|
|
{
|
|
unsigned int i, j, k;
|
|
unsigned int cl = 0, thresh0 = d->thresh, tr;
|
|
unsigned int c = 0, t;
|
|
unsigned char b, b1 = 0;
|
|
int raw0, raw1, mask;
|
|
|
|
raw += d->skip;
|
|
|
|
if (bpp == 14)
|
|
mask = 0x07C0;
|
|
else if (bpp == 15)
|
|
mask = 0x03E0;
|
|
else if (bpp == 16)
|
|
mask = 0x07E0;
|
|
|
|
for (i = d->cri_bytes; i > 0; raw += (bpp >= 14 && bpp <= 16) ? 2 : bpp, i--) {
|
|
if (bpp >= 14 && bpp <= 16) {
|
|
raw0 = (raw[0 + endian] + raw[1 - endian] * 256) & mask;
|
|
raw1 = (raw[2 + endian] + raw[3 - endian] * 256) & mask;
|
|
tr = d->thresh >> THRESH_FRAC;
|
|
d->thresh += ((raw0 - tr) * (int) ABS (raw1 - raw0)) >>
|
|
((bpp == 15) ? 2 : 3);
|
|
t = raw0 * OVERSAMPLING;
|
|
} else {
|
|
tr = d->thresh >> THRESH_FRAC;
|
|
d->thresh += ((int) raw[0] - tr) * (int) ABS (raw[bpp] - raw[0]);
|
|
t = raw[0] * OVERSAMPLING;
|
|
}
|
|
|
|
for (j = OVERSAMPLING; j > 0; j--) {
|
|
b = ((t + (OVERSAMPLING / 2)) / OVERSAMPLING >= tr);
|
|
|
|
if (b ^ b1) {
|
|
cl = d->oversampling_rate >> 1;
|
|
} else {
|
|
cl += d->cri_rate;
|
|
|
|
if (cl >= (unsigned int) d->oversampling_rate) {
|
|
cl -= d->oversampling_rate;
|
|
|
|
c = c * 2 + b;
|
|
|
|
if ((c & d->cri_mask) == d->cri) {
|
|
i = d->phase_shift;
|
|
tr *= 256;
|
|
c = 0;
|
|
|
|
for (j = d->frc_bits; j > 0; j--) {
|
|
c = c * 2 + (sample (raw, i, bpp, endian) >= tr);
|
|
i += d->step;
|
|
}
|
|
|
|
if (c ^= d->frc)
|
|
return FALSE;
|
|
|
|
/* CRI/FRC found, now get the
|
|
payload and exit */
|
|
|
|
switch (d->endian) {
|
|
case 3:
|
|
for (j = 0; j < (unsigned int) d->payload; j++) {
|
|
c >>= 1;
|
|
c += (sample (raw, i, bpp, endian) >= tr) << 7;
|
|
i += d->step;
|
|
|
|
if ((j & 7) == 7)
|
|
*buf++ = c;
|
|
}
|
|
|
|
*buf = c >> ((8 - d->payload) & 7);
|
|
break;
|
|
|
|
case 2:
|
|
for (j = 0; j < (unsigned int) d->payload; j++) {
|
|
c = c * 2 + (sample (raw, i, bpp, endian) >= tr);
|
|
i += d->step;
|
|
|
|
if ((j & 7) == 7)
|
|
*buf++ = c;
|
|
}
|
|
|
|
*buf = c & ((1 << (d->payload & 7)) - 1);
|
|
break;
|
|
|
|
case 1:
|
|
for (j = d->payload; j > 0; j--) {
|
|
for (k = 0; k < 8; k++) {
|
|
c >>= 1;
|
|
c += (sample (raw, i, bpp, endian) >= tr) << 7;
|
|
i += d->step;
|
|
}
|
|
|
|
*buf++ = c;
|
|
}
|
|
|
|
break;
|
|
|
|
case 0:
|
|
for (j = d->payload; j > 0; j--) {
|
|
for (k = 0; k < 8; k++) {
|
|
c = c * 2 + (sample (raw, i, bpp, endian) >= tr);
|
|
i += d->step;
|
|
}
|
|
|
|
*buf++ = c;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
b1 = b;
|
|
|
|
if (OVERSAMPLING > 1) {
|
|
if (bpp >= 14 && bpp <= 16) {
|
|
t += raw1;
|
|
t -= raw0;
|
|
} else {
|
|
t += raw[bpp];
|
|
t -= raw[0];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
d->thresh = thresh0;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static vbi_bool
|
|
bit_slicer_1 (vbi_bit_slicer * d, uint8_t * raw, uint8_t * buf)
|
|
{
|
|
return bit_slicer_tmpl (d, raw, buf, 1, 0);
|
|
}
|
|
|
|
static vbi_bool
|
|
bit_slicer_2 (vbi_bit_slicer * d, uint8_t * raw, uint8_t * buf)
|
|
{
|
|
return bit_slicer_tmpl (d, raw, buf, 2, 0);
|
|
}
|
|
|
|
static vbi_bool
|
|
bit_slicer_3 (vbi_bit_slicer * d, uint8_t * raw, uint8_t * buf)
|
|
{
|
|
return bit_slicer_tmpl (d, raw, buf, 3, 0);
|
|
}
|
|
|
|
static vbi_bool
|
|
bit_slicer_4 (vbi_bit_slicer * d, uint8_t * raw, uint8_t * buf)
|
|
{
|
|
return bit_slicer_tmpl (d, raw, buf, 4, 0);
|
|
}
|
|
|
|
static vbi_bool
|
|
bit_slicer_1555_le (vbi_bit_slicer * d, uint8_t * raw, uint8_t * buf)
|
|
{
|
|
return bit_slicer_tmpl (d, raw, buf, 14, 0);
|
|
}
|
|
|
|
static vbi_bool
|
|
bit_slicer_5551_le (vbi_bit_slicer * d, uint8_t * raw, uint8_t * buf)
|
|
{
|
|
return bit_slicer_tmpl (d, raw, buf, 15, 0);
|
|
}
|
|
|
|
static vbi_bool
|
|
bit_slicer_565_le (vbi_bit_slicer * d, uint8_t * raw, uint8_t * buf)
|
|
{
|
|
return bit_slicer_tmpl (d, raw, buf, 16, 0);
|
|
}
|
|
|
|
static vbi_bool
|
|
bit_slicer_1555_be (vbi_bit_slicer * d, uint8_t * raw, uint8_t * buf)
|
|
{
|
|
return bit_slicer_tmpl (d, raw, buf, 14, 1);
|
|
}
|
|
|
|
static vbi_bool
|
|
bit_slicer_5551_be (vbi_bit_slicer * d, uint8_t * raw, uint8_t * buf)
|
|
{
|
|
return bit_slicer_tmpl (d, raw, buf, 15, 1);
|
|
}
|
|
|
|
static vbi_bool
|
|
bit_slicer_565_be (vbi_bit_slicer * d, uint8_t * raw, uint8_t * buf)
|
|
{
|
|
return bit_slicer_tmpl (d, raw, buf, 16, 1);
|
|
}
|
|
|
|
/**
|
|
* @param slicer Pointer to vbi_bit_slicer object to be initialized.
|
|
* @param raw_samples Number of samples or pixels in one raw vbi line
|
|
* later passed to vbi_bit_slice(). This limits the number of
|
|
* bytes read from the sample buffer.
|
|
* @param sampling_rate Raw vbi sampling rate in Hz, that is the number of
|
|
* samples or pixels sampled per second by the hardware.
|
|
* @param cri_rate The Clock Run In is a NRZ modulated
|
|
* sequence of '0' and '1' bits prepending most data transmissions to
|
|
* synchronize data acquisition circuits. This parameter gives the CRI bit
|
|
* rate in Hz, that is the number of CRI bits transmitted per second.
|
|
* @param bit_rate The transmission bit rate of all data bits following the CRI
|
|
* in Hz.
|
|
* @param cri_frc The FRaming Code usually following the CRI is a bit sequence
|
|
* identifying the data service, and per libzvbi definition modulated
|
|
* and transmitted at the same bit rate as the payload (however nothing
|
|
* stops you from counting all nominal CRI and FRC bits as CRI).
|
|
* The bit slicer compares the bits in this word, lsb last transmitted,
|
|
* against the transmitted CRI and FRC. Decoding of payload starts
|
|
* with the next bit after a match.
|
|
* @param cri_mask Of the CRI bits in @c cri_frc, only these bits are
|
|
* actually significant for a match. For instance it is wise
|
|
* not to rely on the very first CRI bits transmitted. Note this
|
|
* mask is not shifted left by @a frc_bits.
|
|
* @param cri_bits
|
|
* @param frc_bits Number of CRI and FRC bits in @a cri_frc, respectively.
|
|
* Their sum is limited to 32.
|
|
* @param payload Number of payload <em>bits</em>. Only this data
|
|
* will be stored in the vbi_bit_slice() output. If this number
|
|
* is no multiple of eight, the most significant bits of the
|
|
* last byte are undefined.
|
|
* @param modulation Modulation of the vbi data, see vbi_modulation.
|
|
* @param fmt Format of the raw data, see vbi_pixfmt.
|
|
*
|
|
* Initializes vbi_bit_slicer object. Usually you will not use this
|
|
* function but vbi_raw_decode(), the vbi image decoder which handles
|
|
* all these details.
|
|
*/
|
|
void
|
|
vbi_bit_slicer_init (vbi_bit_slicer * slicer,
|
|
int raw_samples, int sampling_rate,
|
|
int cri_rate, int bit_rate,
|
|
unsigned int cri_frc, unsigned int cri_mask,
|
|
int cri_bits, int frc_bits, int payload,
|
|
vbi_modulation modulation, vbi_pixfmt fmt)
|
|
{
|
|
unsigned int c_mask = (unsigned int) (-(cri_bits > 0)) >> (32 - cri_bits);
|
|
unsigned int f_mask = (unsigned int) (-(frc_bits > 0)) >> (32 - frc_bits);
|
|
int gsh = 0;
|
|
|
|
slicer->func = bit_slicer_1;
|
|
|
|
switch (fmt) {
|
|
case VBI_PIXFMT_RGB24:
|
|
case VBI_PIXFMT_BGR24:
|
|
slicer->func = bit_slicer_3;
|
|
slicer->skip = 1;
|
|
break;
|
|
|
|
case VBI_PIXFMT_RGBA32_LE:
|
|
case VBI_PIXFMT_BGRA32_LE:
|
|
slicer->func = bit_slicer_4;
|
|
slicer->skip = 1;
|
|
break;
|
|
|
|
case VBI_PIXFMT_RGBA32_BE:
|
|
case VBI_PIXFMT_BGRA32_BE:
|
|
slicer->func = bit_slicer_4;
|
|
slicer->skip = 2;
|
|
break;
|
|
|
|
case VBI_PIXFMT_RGB16_LE:
|
|
case VBI_PIXFMT_BGR16_LE:
|
|
slicer->func = bit_slicer_565_le;
|
|
gsh = 3; /* (green << 3) & 0x07E0 */
|
|
slicer->skip = 0;
|
|
break;
|
|
|
|
case VBI_PIXFMT_RGBA15_LE:
|
|
case VBI_PIXFMT_BGRA15_LE:
|
|
slicer->func = bit_slicer_5551_le;
|
|
gsh = 2; /* (green << 2) & 0x03E0 */
|
|
slicer->skip = 0;
|
|
break;
|
|
|
|
case VBI_PIXFMT_ARGB15_LE:
|
|
case VBI_PIXFMT_ABGR15_LE:
|
|
slicer->func = bit_slicer_1555_le;
|
|
gsh = 3; /* (green << 2) & 0x07C0 */
|
|
slicer->skip = 0;
|
|
break;
|
|
|
|
case VBI_PIXFMT_RGB16_BE:
|
|
case VBI_PIXFMT_BGR16_BE:
|
|
slicer->func = bit_slicer_565_be;
|
|
gsh = 3; /* (green << 3) & 0x07E0 */
|
|
slicer->skip = 0;
|
|
break;
|
|
|
|
case VBI_PIXFMT_RGBA15_BE:
|
|
case VBI_PIXFMT_BGRA15_BE:
|
|
slicer->func = bit_slicer_5551_be;
|
|
gsh = 2; /* (green << 2) & 0x03E0 */
|
|
slicer->skip = 0;
|
|
break;
|
|
|
|
case VBI_PIXFMT_ARGB15_BE:
|
|
case VBI_PIXFMT_ABGR15_BE:
|
|
slicer->func = bit_slicer_1555_be;
|
|
gsh = 3; /* (green << 2) & 0x07C0 */
|
|
slicer->skip = 0;
|
|
break;
|
|
|
|
case VBI_PIXFMT_YUV420:
|
|
slicer->func = bit_slicer_1;
|
|
slicer->skip = 0;
|
|
break;
|
|
|
|
case VBI_PIXFMT_YUYV:
|
|
case VBI_PIXFMT_YVYU:
|
|
slicer->func = bit_slicer_2;
|
|
slicer->skip = 0;
|
|
break;
|
|
|
|
case VBI_PIXFMT_UYVY:
|
|
case VBI_PIXFMT_VYUY:
|
|
slicer->func = bit_slicer_2;
|
|
slicer->skip = 1;
|
|
break;
|
|
|
|
default:
|
|
fprintf (stderr, "vbi_bit_slicer_init: unknown pixfmt %d\n", fmt);
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
slicer->cri_mask = cri_mask & c_mask;
|
|
slicer->cri = (cri_frc >> frc_bits) & slicer->cri_mask;
|
|
/* We stop searching for CRI/FRC when the payload
|
|
cannot possibly fit anymore. */
|
|
slicer->cri_bytes = raw_samples
|
|
- ((long long) sampling_rate * (payload + frc_bits)) / bit_rate;
|
|
slicer->cri_rate = cri_rate;
|
|
/* Raw vbi data is oversampled to account for low sampling rates. */
|
|
slicer->oversampling_rate = sampling_rate * OVERSAMPLING;
|
|
/* 0/1 threshold */
|
|
slicer->thresh = 105 << (THRESH_FRAC + gsh);
|
|
slicer->frc = cri_frc & f_mask;
|
|
slicer->frc_bits = frc_bits;
|
|
/* Payload bit distance in 1/256 raw samples. */
|
|
slicer->step = (int) (sampling_rate * 256.0 / bit_rate);
|
|
|
|
if (payload & 7) {
|
|
slicer->payload = payload;
|
|
slicer->endian = 3;
|
|
} else {
|
|
slicer->payload = payload >> 3;
|
|
slicer->endian = 1;
|
|
}
|
|
|
|
switch (modulation) {
|
|
case VBI_MODULATION_NRZ_MSB:
|
|
slicer->endian--;
|
|
case VBI_MODULATION_NRZ_LSB:
|
|
slicer->phase_shift = (int)
|
|
(sampling_rate * 256.0 / cri_rate * .5
|
|
+ sampling_rate * 256.0 / bit_rate * .5 + 128);
|
|
break;
|
|
|
|
case VBI_MODULATION_BIPHASE_MSB:
|
|
slicer->endian--;
|
|
case VBI_MODULATION_BIPHASE_LSB:
|
|
/* Phase shift between the NRZ modulated CRI and the rest */
|
|
slicer->phase_shift = (int)
|
|
(sampling_rate * 256.0 / cri_rate * .5
|
|
+ sampling_rate * 256.0 / bit_rate * .25 + 128);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/**
|
|
* @example examples/wss.c
|
|
* WSS capture example.
|
|
*/
|
|
|
|
/**
|
|
* @param rd Initialized vbi_raw_decoder structure.
|
|
* @param raw A raw vbi image as defined in the vbi_raw_decoder structure
|
|
* (rd->sampling_format, rd->bytes_per_line, rd->count[0] + rd->count[1]
|
|
* scan lines).
|
|
* @param out Buffer to store the decoded vbi_sliced data. Since every
|
|
* vbi scan line may contain data, this must be an array of vbi_sliced
|
|
* with the same number of entries as scan lines in the raw image
|
|
* (rd->count[0] + rd->count[1]).
|
|
*
|
|
* Decode a raw vbi image, consisting of several scan lines of raw vbi data,
|
|
* into sliced vbi data. The output is sorted by line number.
|
|
*
|
|
* Note this function attempts to learn which lines carry which data
|
|
* service, or none, to speed up decoding. You should avoid using the same
|
|
* vbi_raw_decoder structure for different sources.
|
|
*
|
|
* @return
|
|
* The number of lines decoded, i. e. the number of vbi_sliced records
|
|
* written.
|
|
*/
|
|
int
|
|
vbi_raw_decode (vbi_raw_decoder * rd, uint8_t * raw, vbi_sliced * out)
|
|
{
|
|
vbi3_raw_decoder *rd3;
|
|
unsigned int n_lines;
|
|
|
|
assert (NULL != rd);
|
|
assert (NULL != raw);
|
|
assert (NULL != out);
|
|
|
|
rd3 = (vbi3_raw_decoder *) rd->pattern;
|
|
n_lines = rd->count[0] + rd->count[1];
|
|
|
|
g_mutex_lock (&rd->mutex);
|
|
|
|
{
|
|
n_lines = vbi3_raw_decoder_decode (rd3, out, n_lines, raw);
|
|
}
|
|
|
|
g_mutex_unlock (&rd->mutex);
|
|
|
|
return n_lines;
|
|
}
|
|
|
|
/**
|
|
* @param rd Initialized vbi_raw_decoder structure.
|
|
* @param start Array of start line indices for both fields
|
|
* @param count Array of line counts for both fields
|
|
*
|
|
* Grows or shrinks the internal state arrays for VBI geometry changes
|
|
*/
|
|
void
|
|
vbi_raw_decoder_resize (vbi_raw_decoder * rd, int *start, unsigned int *count)
|
|
{
|
|
#if 0 /* Set but unused */
|
|
vbi_service_set service_set;
|
|
#endif
|
|
vbi3_raw_decoder *rd3;
|
|
|
|
assert (NULL != rd);
|
|
assert (NULL != start);
|
|
assert (NULL != count);
|
|
|
|
rd3 = (vbi3_raw_decoder *) rd->pattern;
|
|
|
|
g_mutex_lock (&rd->mutex);
|
|
|
|
{
|
|
if ((rd->start[0] == start[0])
|
|
&& (rd->start[1] == start[1])
|
|
&& (rd->count[0] == (int) count[0])
|
|
&& (rd->count[1] == (int) count[1])) {
|
|
g_mutex_unlock (&rd->mutex);
|
|
return;
|
|
}
|
|
|
|
rd->start[0] = start[0];
|
|
rd->start[1] = start[1];
|
|
rd->count[0] = count[0];
|
|
rd->count[1] = count[1];
|
|
|
|
#if 0 /* Set but unused */
|
|
service_set = vbi3_raw_decoder_set_sampling_par
|
|
(rd3, (vbi_sampling_par *) rd, /* strict */ 0);
|
|
#else
|
|
vbi3_raw_decoder_set_sampling_par
|
|
(rd3, (vbi_sampling_par *) rd, /* strict */ 0);
|
|
#endif
|
|
}
|
|
|
|
g_mutex_unlock (&rd->mutex);
|
|
}
|
|
|
|
/**
|
|
* @param rd Initialized vbi_raw_decoder structure.
|
|
* @param services Set of @ref VBI_SLICED_ symbols.
|
|
*
|
|
* Removes one or more data services to be decoded from the
|
|
* vbi_raw_decoder structure. This function can be called at any
|
|
* time and does not touch sampling parameters.
|
|
*
|
|
* @return
|
|
* Set of @ref VBI_SLICED_ symbols describing the remaining data
|
|
* services that will be decoded.
|
|
*/
|
|
unsigned int
|
|
vbi_raw_decoder_remove_services (vbi_raw_decoder * rd, unsigned int services)
|
|
{
|
|
vbi_service_set service_set;
|
|
vbi3_raw_decoder *rd3;
|
|
|
|
assert (NULL != rd);
|
|
|
|
rd3 = (vbi3_raw_decoder *) rd->pattern;
|
|
service_set = services;
|
|
|
|
g_mutex_lock (&rd->mutex);
|
|
|
|
{
|
|
service_set = vbi3_raw_decoder_remove_services (rd3, service_set);
|
|
}
|
|
|
|
g_mutex_unlock (&rd->mutex);
|
|
|
|
return service_set;
|
|
}
|
|
|
|
/**
|
|
* @param rd Initialized vbi_raw_decoder structure.
|
|
* @param services Set of @ref VBI_SLICED_ symbols.
|
|
* @param strict See description of vbi_raw_decoder_add_services()
|
|
*
|
|
* Check which of the given services can be decoded with current capture
|
|
* parameters at a given strictness level.
|
|
*
|
|
* @return
|
|
* Subset of services actually decodable.
|
|
*/
|
|
unsigned int
|
|
vbi_raw_decoder_check_services (vbi_raw_decoder * rd,
|
|
unsigned int services, int strict)
|
|
{
|
|
vbi_service_set service_set;
|
|
|
|
assert (NULL != rd);
|
|
|
|
service_set = services;
|
|
|
|
g_mutex_lock (&rd->mutex);
|
|
|
|
{
|
|
service_set = vbi_sampling_par_check_services
|
|
((vbi_sampling_par *) rd, service_set, strict);
|
|
}
|
|
|
|
g_mutex_unlock (&rd->mutex);
|
|
|
|
return (unsigned int) service_set;
|
|
}
|
|
|
|
/**
|
|
* @param rd Initialized vbi_raw_decoder structure.
|
|
* @param services Set of @ref VBI_SLICED_ symbols.
|
|
* @param strict A value of 0, 1 or 2 requests loose, reliable or strict
|
|
* matching of sampling parameters. For example if the data service
|
|
* requires knowledge of line numbers while they are not known, @c 0
|
|
* will accept the service (which may work if the scan lines are
|
|
* populated in a non-confusing way) but @c 1 or @c 2 will not. If the
|
|
* data service <i>may</i> use more lines than are sampled, @c 1 will
|
|
* accept but @c 2 will not. If unsure, set to @c 1.
|
|
*
|
|
* After you initialized the sampling parameters in @a rd (according to
|
|
* the abilities of your raw vbi source), this function adds one or more
|
|
* data services to be decoded. The libzvbi raw vbi decoder can decode up
|
|
* to eight data services in parallel. You can call this function while
|
|
* already decoding, it does not change sampling parameters and you must
|
|
* not change them either after calling this.
|
|
*
|
|
* @return
|
|
* Set of @ref VBI_SLICED_ symbols describing the data services that actually
|
|
* will be decoded. This excludes those services not decodable given
|
|
* the sampling parameters in @a rd.
|
|
*/
|
|
unsigned int
|
|
vbi_raw_decoder_add_services (vbi_raw_decoder * rd,
|
|
unsigned int services, int strict)
|
|
{
|
|
vbi_service_set service_set;
|
|
vbi3_raw_decoder *rd3;
|
|
|
|
assert (NULL != rd);
|
|
|
|
rd3 = (vbi3_raw_decoder *) rd->pattern;
|
|
service_set = services;
|
|
|
|
g_mutex_lock (&rd->mutex);
|
|
|
|
{
|
|
vbi3_raw_decoder_set_sampling_par (rd3, (vbi_sampling_par *) rd, strict);
|
|
|
|
service_set = vbi3_raw_decoder_add_services (rd3, service_set, strict);
|
|
}
|
|
|
|
g_mutex_unlock (&rd->mutex);
|
|
|
|
return service_set;
|
|
}
|
|
|
|
/**
|
|
* @param rd Initialized vbi_raw_decoder structure.
|
|
* @param services Set of VBI_SLICED_ symbols. Here (and only here) you
|
|
* can add @c VBI_SLICED_VBI_625 or @c VBI_SLICED_VBI_525 to include all
|
|
* vbi scan lines in the calculated sampling parameters.
|
|
* @param scanning When 525 accept only NTSC services, when 625
|
|
* only PAL/SECAM services. When scanning is 0, determine the scanning
|
|
* from the requested services, an ambiguous set will pick
|
|
* a 525 or 625 line system at random.
|
|
* @param max_rate If given, the highest data bit rate in Hz of all
|
|
* services requested is stored here. (The sampling rate
|
|
* should be at least twice as high; rd->sampling_rate will
|
|
* be set to a more reasonable value of 27 MHz derived
|
|
* from ITU-R Rec. 601.)
|
|
*
|
|
* Calculate the sampling parameters in @a rd required to receive and
|
|
* decode the requested data @a services. rd->sampling_format will be
|
|
* @c VBI_PIXFMT_YUV420, rd->bytes_per_line set accordingly to a
|
|
* reasonable minimum. This function can be used to initialize hardware
|
|
* prior to calling vbi_raw_decoder_add_service().
|
|
*
|
|
* @return
|
|
* Set of @ref VBI_SLICED_ symbols describing the data services covered
|
|
* by the calculated sampling parameters. This excludes services the libzvbi
|
|
* raw decoder cannot decode.
|
|
*/
|
|
unsigned int
|
|
vbi_raw_decoder_parameters (vbi_raw_decoder * rd,
|
|
unsigned int services, int scanning, int *max_rate)
|
|
{
|
|
vbi_videostd_set videostd_set;
|
|
vbi_service_set service_set;
|
|
|
|
switch (scanning) {
|
|
case 525:
|
|
videostd_set = VBI_VIDEOSTD_SET_525_60;
|
|
break;
|
|
|
|
case 625:
|
|
videostd_set = VBI_VIDEOSTD_SET_625_50;
|
|
break;
|
|
|
|
default:
|
|
videostd_set = 0;
|
|
break;
|
|
}
|
|
|
|
service_set = services;
|
|
|
|
g_mutex_lock (&rd->mutex);
|
|
|
|
{
|
|
service_set = vbi_sampling_par_from_services
|
|
((vbi_sampling_par *) rd,
|
|
(unsigned int *) max_rate, videostd_set, service_set);
|
|
}
|
|
|
|
g_mutex_unlock (&rd->mutex);
|
|
|
|
return (unsigned int) service_set;
|
|
}
|
|
|
|
/**
|
|
* @param rd Initialized vbi_raw_decoder structure.
|
|
*
|
|
* Reset a vbi_raw_decoder structure. This removes
|
|
* all previously added services to be decoded (if any)
|
|
* but does not touch the sampling parameters. You are
|
|
* free to change the sampling parameters after calling this.
|
|
*/
|
|
void
|
|
vbi_raw_decoder_reset (vbi_raw_decoder * rd)
|
|
{
|
|
vbi3_raw_decoder *rd3;
|
|
|
|
if (!rd)
|
|
return; /* compatibility */
|
|
|
|
assert (NULL != rd);
|
|
|
|
rd3 = (vbi3_raw_decoder *) rd->pattern;
|
|
|
|
g_mutex_lock (&rd->mutex);
|
|
|
|
{
|
|
vbi3_raw_decoder_reset (rd3);
|
|
}
|
|
|
|
g_mutex_unlock (&rd->mutex);
|
|
}
|
|
|
|
/**
|
|
* @param rd Pointer to initialized vbi_raw_decoder
|
|
* structure, can be @c NULL.
|
|
*
|
|
* Free all resources associated with @a rd.
|
|
*/
|
|
void
|
|
vbi_raw_decoder_destroy (vbi_raw_decoder * rd)
|
|
{
|
|
vbi3_raw_decoder *rd3;
|
|
|
|
assert (NULL != rd);
|
|
|
|
rd3 = (vbi3_raw_decoder *) rd->pattern;
|
|
|
|
vbi3_raw_decoder_delete (rd3);
|
|
|
|
g_mutex_clear (&rd->mutex);
|
|
|
|
CLEAR (*rd);
|
|
}
|
|
|
|
/**
|
|
* @param rd Pointer to a vbi_raw_decoder structure.
|
|
*
|
|
* Initializes a vbi_raw_decoder structure.
|
|
*/
|
|
void
|
|
vbi_raw_decoder_init (vbi_raw_decoder * rd)
|
|
{
|
|
vbi3_raw_decoder *rd3;
|
|
|
|
assert (NULL != rd);
|
|
|
|
CLEAR (*rd);
|
|
|
|
g_mutex_init (&rd->mutex);
|
|
|
|
rd3 = vbi3_raw_decoder_new ( /* sampling_par */ NULL);
|
|
assert (NULL != rd3);
|
|
|
|
rd->pattern = (int8_t *) rd3;
|
|
}
|
|
|
|
GST_DEBUG_CATEGORY (libzvbi_debug);
|
|
void
|
|
vbi_initialize_gst_debug (void)
|
|
{
|
|
GST_DEBUG_CATEGORY_INIT (libzvbi_debug, "libzvbi", 0, "libzvbi");
|
|
}
|
|
|
|
/*
|
|
Local variables:
|
|
c-set-style: K&R
|
|
c-basic-offset: 8
|
|
End:
|
|
*/
|