summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/cx18/cx18-vbi.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/cx18/cx18-vbi.c')
-rw-r--r--linux/drivers/media/video/cx18/cx18-vbi.c118
1 files changed, 81 insertions, 37 deletions
diff --git a/linux/drivers/media/video/cx18/cx18-vbi.c b/linux/drivers/media/video/cx18/cx18-vbi.c
index fb595bd54..8e6f4d4af 100644
--- a/linux/drivers/media/video/cx18/cx18-vbi.c
+++ b/linux/drivers/media/video/cx18/cx18-vbi.c
@@ -27,6 +27,16 @@
#include "cx18-queue.h"
#include "cx18-av-core.h"
+/*
+ * Raster Reference/Protection (RP) bytes, used in Start/End Active
+ * Video codes emitted from the digitzer in VIP 1.x mode, that flag the start
+ * of VBI sample or VBI ancilliary data regions in the digitial ratser line.
+ *
+ * Task FieldEven VerticalBlank HorizontalBlank 0 0 0 0
+ */
+static const u8 raw_vbi_sav_rp[2] = { 0x20, 0x60 }; /* __V_, _FV_ */
+static const u8 sliced_vbi_eav_rp[2] = { 0xb0, 0xf0 }; /* T_VH, TFVH */
+
static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
{
int line = 0;
@@ -34,10 +44,17 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
u32 linemask[2] = { 0, 0 };
unsigned short size;
static const u8 mpeg_hdr_data[] = {
- 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
- 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
- 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
- 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
+ /* MPEG-2 Program Pack */
+ 0x00, 0x00, 0x01, 0xba, /* Prog Pack start code */
+ 0x44, 0x00, 0x0c, 0x66, 0x24, 0x01, /* SCR, SCR Ext, markers */
+ 0x01, 0xd1, 0xd3, /* Mux Rate, markers */
+ 0xfa, 0xff, 0xff, /* Res, Suff cnt, Stuff */
+ /* MPEG-2 Private Stream 1 PES Packet */
+ 0x00, 0x00, 0x01, 0xbd, /* Priv Stream 1 start */
+ 0x00, 0x1a, /* length */
+ 0x84, 0x80, 0x07, /* flags, hdr data len */
+ 0x21, 0x00, 0x5d, 0x63, 0xa7, /* PTS, markers */
+ 0xff, 0xff /* stuffing */
};
const int sd = sizeof(mpeg_hdr_data); /* start of vbi data */
int idx = cx->vbi.frame % CX18_VBI_FRAMES;
@@ -71,7 +88,7 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
memcpy(dst + sd + 4, dst + sd + 12, line * 43);
size = 4 + ((43 * line + 3) & ~3);
} else {
- memcpy(dst + sd, "cx0", 4);
+ memcpy(dst + sd, "itv0", 4);
memcpy(dst + sd + 4, &linemask[0], 8);
size = 12 + ((43 * line + 3) & ~3);
}
@@ -86,14 +103,13 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
}
/* Compress raw VBI format, removes leading SAV codes and surplus space
- after the field.
- Returns new compressed size. */
+ after the frame. Returns new compressed size. */
static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size)
{
- u32 line_size = cx->vbi.raw_decoder_line_size;
- u32 lines = cx->vbi.count;
- u8 sav1 = cx->vbi.raw_decoder_sav_odd_field;
- u8 sav2 = cx->vbi.raw_decoder_sav_even_field;
+ u32 line_size = vbi_active_samples;
+ u32 lines = cx->vbi.count * 2;
+ u8 sav1 = raw_vbi_sav_rp[0];
+ u8 sav2 = raw_vbi_sav_rp[1];
u8 *q = buf;
u8 *p;
int i;
@@ -115,15 +131,16 @@ static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size)
/* Compressed VBI format, all found sliced blocks put next to one another
Returns new compressed size */
static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf,
- u32 size, u8 sav)
+ u32 size, u8 eav)
{
- u32 line_size = cx->vbi.sliced_decoder_line_size;
struct v4l2_decode_vbi_line vbi;
int i;
+ u32 line_size = cx->is_60hz ? vbi_hblank_samples_60Hz
+ : vbi_hblank_samples_50Hz;
/* find the first valid line */
for (i = 0; i < size; i++, buf++) {
- if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
+ if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == eav)
break;
}
@@ -133,8 +150,8 @@ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf,
for (i = 0; i < size / line_size; i++) {
u8 *p = buf + i * line_size;
- /* Look for SAV code */
- if (p[0] != 0xff || p[1] || p[2] || p[3] != sav)
+ /* Look for EAV code */
+ if (p[0] != 0xff || p[1] || p[2] || p[3] != eav)
continue;
vbi.p = p + 4;
cx18_av_cmd(cx, VIDIOC_INT_DECODE_VBI_LINE, &vbi);
@@ -150,51 +167,78 @@ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf,
}
void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
- u64 pts_stamp, int streamtype)
+ int streamtype)
{
u8 *p = (u8 *) buf->buf;
+ u32 *q = (u32 *) buf->buf;
u32 size = buf->bytesused;
+ u32 pts;
int lines;
if (streamtype != CX18_ENC_STREAM_TYPE_VBI)
return;
+ /*
+ * The CX23418 sends us data that is 32 bit LE swapped, but we want
+ * the raw VBI bytes in the order they were in the raster line
+ */
+ cx18_buf_swap(buf);
+
+ /*
+ * The CX23418 provides a 12 byte header in it's raw VBI buffers to us:
+ * 0x3fffffff [4 bytes of something] [4 byte presentation time stamp?]
+ */
+
/* Raw VBI data */
if (cx18_raw_vbi(cx)) {
u8 type;
- cx18_buf_swap(buf);
-
- /* Skip 12 bytes of header that gets stuffed in */
+ /*
+ * We've set up to get a frame's worth of VBI data at a time.
+ * Skip 12 bytes of header prefixing the first field.
+ */
size -= 12;
memcpy(p, &buf->buf[12], size);
type = p[3];
+ /* Extrapolate the last 12 bytes of the frame's last line */
+ memset(&p[size], (int) p[size - 1], 12);
+ size += 12;
+
size = buf->bytesused = compress_raw_buf(cx, p, size);
- /* second field of the frame? */
- if (type == cx->vbi.raw_decoder_sav_even_field) {
- /* Dirty hack needed for backwards
- compatibility of old VBI software. */
- p += size - 4;
- memcpy(p, &cx->vbi.frame, 4);
- cx->vbi.frame++;
- }
+ /*
+ * Hack needed for compatibility with old VBI software.
+ * Write the frame # at the last 4 bytes of the frame
+ */
+ p += size - 4;
+ memcpy(p, &cx->vbi.frame, 4);
+ cx->vbi.frame++;
return;
}
/* Sliced VBI data with data insertion */
- cx18_buf_swap(buf);
+
+ pts = (be32_to_cpu(q[0] == 0x3fffffff)) ? be32_to_cpu(q[2]) : 0;
+
+ /*
+ * For calls to compress_sliced_buf(), ensure there are an integral
+ * number of lines by shifting the real data up over the 12 bytes header
+ * that got stuffed in.
+ * FIXME - there's a smarter way to do this with pointers, but for some
+ * reason I can't get it to work correctly right now.
+ */
+ memcpy(p, &buf->buf[12], size-12);
/* first field */
- lines = compress_sliced_buf(cx, 0, p, size / 2,
- cx->vbi.sliced_decoder_sav_odd_field);
- /* second field */
- /* experimentation shows that the second half does not always
- begin at the exact address. So start a bit earlier
- (hence 32). */
+ lines = compress_sliced_buf(cx, 0, p, size / 2, sliced_vbi_eav_rp[0]);
+ /*
+ * second field
+ * In case the second half does not always begin at the exact address,
+ * start a bit earlier (hence 32).
+ */
lines = compress_sliced_buf(cx, lines, p + size / 2 - 32,
- size / 2 + 32, cx->vbi.sliced_decoder_sav_even_field);
+ size / 2 + 32, sliced_vbi_eav_rp[1]);
/* always return at least one empty line */
if (lines == 0) {
cx->vbi.sliced_data[0].id = 0;
@@ -206,6 +250,6 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
memcpy(p, &cx->vbi.sliced_data[0], size);
if (cx->vbi.insert_mpeg)
- copy_vbi_data(cx, lines, pts_stamp);
+ copy_vbi_data(cx, lines, pts);
cx->vbi.frame++;
}