aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@kernellabs.com>2009-11-28 00:53:23 (GMT)
committerDevin Heitmueller <dheitmueller@kernellabs.com>2009-11-28 00:53:23 (GMT)
commit5f979b263120e12afc47e5b78be8cdd10794aba4 (patch)
tree222e2ebf3cb14f24574dcdaf040f7227adb540e7 /src
parent547c5c9576412f93b6ac81d15359b0eec93db395 (diff)
djh - Add support for more generic VBI handling. Currently only tested with the HVR-950 (em28xx based), so there may need to be additional changes required for other boards).
Diffstat (limited to 'src')
-rw-r--r--src/vbidata.c91
1 files changed, 59 insertions, 32 deletions
diff --git a/src/vbidata.c b/src/vbidata.c
index c7ed87f..548bb27 100644
--- a/src/vbidata.c
+++ b/src/vbidata.c
@@ -30,12 +30,15 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/ioctl.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <unistd.h>
+#include <math.h>
#include <errno.h>
#include "vbidata.h"
+#include <linux/videodev.h>
struct vbidata_s
{
@@ -49,6 +52,11 @@ struct vbidata_s
int usexds;
+ /* VBI parameters negotiated by the hardware */
+ unsigned int linewidth;
+ unsigned int numlines;
+ unsigned int vbi_clkin;
+
unsigned int colour;
int row, ital;
int indent, ul;
@@ -128,27 +136,16 @@ int parityok( int n )
return 1;
}
-#define VBI_LINELEN 2048
-/* clock-in period = 2x bit period at the initial VBI frequency, actually
- * 28.64*2/1.006976 = ~56.88
- * for PAL:
- * 35.47*2/1.006976 = ~70.45 */
-#ifndef PAL_DECODE
-#define VBI_CLKIN 57
-#else
-#define VBI_CLKIN 71
-#endif
-
/* use an average to handle noisy cases; assume proper input.
* the avg is taken over slightly less than one sampled cycle at the
* initial frequency */
-int decodebit( uint8_t *data, int threshold )
+int decodebit( vbidata_t *vbi, uint8_t *data, int threshold )
{
int sum = 0, i;
- for (i = 0; i < (VBI_CLKIN - 1)/2; i++) {
+ for (i = 0; i < (vbi->vbi_clkin - 1)/2; i++) {
sum += data[i];
}
- return (sum > threshold*(VBI_CLKIN - 1)/2);
+ return (sum > threshold*(vbi->vbi_clkin - 1)/2);
}
/* Return index relative to start of ary of the next local maximum.
@@ -186,7 +183,7 @@ int find_next_min(uint8_t *ary, int range)
return mini;
}
-int ccdecode( uint8_t *vbiline )
+int ccdecode( vbidata_t *vbi, uint8_t *vbiline )
{
int max[7], min[7], x_start, x_end;
int i = 0, clk = 0, tmp = 0;
@@ -195,12 +192,12 @@ int ccdecode( uint8_t *vbiline )
/* set starting point of captured data by skipping 0's
* avoid diz' filter effects at start
*/
- for (x_start = 1; x_start < VBI_LINELEN; x_start++) {
+ for (x_start = 1; x_start < vbi->linewidth; x_start++) {
if (vbiline[x_start] != 0)
break;
}
/* set end-point */
- for (x_end = VBI_LINELEN - 1; x_end > x_start ; x_end--) {
+ for (x_end = vbi->linewidth - 1; x_end > x_start ; x_end--) {
if (vbiline[x_end] != 0)
break;
}
@@ -221,10 +218,10 @@ int ccdecode( uint8_t *vbiline )
* [x_start, (x_end - x_start)/13] */
max[0] = x_start + find_next_max(vbiline + x_start, (x_end - x_start)/13);
for (i = 1; i < 7; i++) {
- min[i-1] = max[i-1] + find_next_min(vbiline + max[i-1], VBI_CLKIN);
- max[i] = min[i-1] + find_next_max(vbiline + min[i-1], VBI_CLKIN);
+ min[i-1] = max[i-1] + find_next_min(vbiline + max[i-1], vbi->vbi_clkin);
+ max[i] = min[i-1] + find_next_max(vbiline + min[i-1], vbi->vbi_clkin);
}
- min[6] = max[6] + find_next_min(vbiline + max[6], VBI_CLKIN);
+ min[6] = max[6] + find_next_min(vbiline + max[6], vbi->vbi_clkin);
/* determine sample threshold by averaging; using multiple points helps
* for noisy channels */
@@ -241,14 +238,14 @@ int ccdecode( uint8_t *vbiline )
*/
for (i = min[6]; i < x_end && vbiline[i] < sample; i++);
- if (!decodebit(&vbiline[i], sample))
+ if (!decodebit(vbi, &vbiline[i], sample))
return 0;
- tmp = i + VBI_CLKIN; /* tmp = data bit zero, and frequency now halves */
+ tmp = i + vbi->vbi_clkin; /* tmp = data bit zero, and frequency now halves */
for (i = 0; i < 16; i++) {
- clk = tmp + i * VBI_CLKIN;
- if (decodebit(&vbiline[clk], sample)) {
+ clk = tmp + i * vbi->vbi_clkin;
+ if (decodebit(vbi, &vbiline[clk], sample)) {
packedbits |= 1 << i;
}
}
@@ -592,7 +589,7 @@ int ProcessLine( vbidata_t *vbi, uint8_t *s, int bottom )
{
int w1, b1, b2;
- w1 = ccdecode( s );
+ w1 = ccdecode( vbi, s );
b1 = w1 & 0x7f;
b2 = (w1 >> 8) & 0x7f;
@@ -990,6 +987,10 @@ vbidata_t *vbidata_new( const char *filename, vbiscreen_t *vs, int verbose )
static void vbidata_open_device( vbidata_t *vbi )
{
+ struct v4l2_format vfmt;
+ double frame_rate;
+ int result;
+
vbi->fd = open( vbi->filename, O_RDONLY );
if( vbi->fd < 0 ) {
fprintf( stderr, "vbidata: Can't open %s: %s\n",
@@ -997,6 +998,28 @@ static void vbidata_open_device( vbidata_t *vbi )
} else {
vbi->open = 1;
}
+
+ /* Determine the VBI parameters based on the hardware config */
+ memset(&vfmt, 0, sizeof(vfmt));
+ vfmt.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+
+ result = ioctl (vbi->fd, VIDIOC_G_FMT, &vfmt);
+ if (result < 0) {
+ fprintf( stderr, "vbidata: Could not retrieve VBI format info [%s]\n",
+ strerror( errno ) );
+ close(vbi->fd);
+ vbi->open = 0;
+ return;
+ }
+
+ vbi->linewidth = vfmt.fmt.vbi.samples_per_line;
+ vbi->numlines = vfmt.fmt.vbi.count[0];
+
+ frame_rate = vfmt.fmt.vbi.sampling_rate * 2 / 1.006976 / 1000 / 1000;
+ vbi->vbi_clkin = round(frame_rate);
+
+ printf("linewidth=%d numlines=%d clkin=%d\n", vbi->vbi_clkin,
+ vbi->linewidth, vbi->numlines);
}
static void vbidata_close_device( vbidata_t *vbi )
@@ -1152,36 +1175,40 @@ void vbidata_capture_xds( vbidata_t *vbi, int xds )
void vbidata_process_frame( vbidata_t *vbi, int printdebug )
{
if( vbi->open ) {
- if( read( vbi->fd, vbi->buf, 65536 ) < 65536 ) {
+ unsigned int frame_size = vbi->linewidth * vbi->numlines * 2;
+ if( read( vbi->fd, vbi->buf, frame_size ) < frame_size ) {
if( vbi->verbose ) {
fprintf( stderr, "vbidata: Can't read vbi data: %s\n",
strerror( errno ) );
}
} else {
int scanline = 11; /* Process line 21. */
+#ifdef DJH_DEBUG
int k;
-
/* Apply diz' new filter. */
for( k = 1; k < 7; k++ ) {
- int j = scanline * 2048;
+ int j = scanline * vbi->linewidth;
int i;
for( i = 1600; i > 0; i-- ) {
vbi->buf[i + j] = (vbi->buf[i + j + k] + vbi->buf[i + j]) / 2;
}
}
- ProcessLine( vbi, &vbi->buf[ scanline * 2048 ], 0 );
-
+#endif
+ ProcessLine( vbi, &vbi->buf[ scanline * vbi->linewidth ], 0 );
+#ifdef DJH_DEBUG
/* Apply diz' new filter. */
for( k = 1; k < 7; k++ ) {
- int j = ( 16 + scanline )*2048;
+ int j = ( vbi->numlines + scanline ) * vbi->linewidth;
int i;
for( i = 1600; i > 0; i-- ) {
vbi->buf[i + j] = (vbi->buf[i + j + k] + vbi->buf[i + j]) / 2;
}
}
- ProcessLine( vbi, &vbi->buf[ ( 16 + scanline ) * 2048 ], 1 );
+#endif
+
+ ProcessLine( vbi, &vbi->buf[ ( vbi->numlines + scanline ) * vbi->linewidth ], 1 );
}
}
}

Privacy Policy