2 Vertical Blank Interval support functions
3 Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "ivtv-driver.h"
22 #include "ivtv-ioctl.h"
23 #include "ivtv-queue.h"
26 static void ivtv_set_vps(struct ivtv *itv, int enabled)
28 struct v4l2_sliced_vbi_data data;
30 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
32 data.id = V4L2_SLICED_VPS;
34 data.line = enabled ? 16 : 0;
35 data.data[2] = itv->vbi.vps_payload.data[0];
36 data.data[8] = itv->vbi.vps_payload.data[1];
37 data.data[9] = itv->vbi.vps_payload.data[2];
38 data.data[10] = itv->vbi.vps_payload.data[3];
39 data.data[11] = itv->vbi.vps_payload.data[4];
40 ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data);
43 static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
45 struct v4l2_sliced_vbi_data data;
47 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
49 data.id = V4L2_SLICED_CAPTION_525;
51 data.line = (mode & 1) ? 21 : 0;
52 data.data[0] = cc->odd[0];
53 data.data[1] = cc->odd[1];
54 ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data);
56 data.line = (mode & 2) ? 21 : 0;
57 data.data[0] = cc->even[0];
58 data.data[1] = cc->even[1];
59 ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data);
62 static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
64 struct v4l2_sliced_vbi_data data;
66 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
68 /* When using a 50 Hz system, always turn on the
69 wide screen signal with 4x3 ratio as the default.
70 Turning this signal on and off can confuse certain
71 TVs. As far as I can tell there is no reason not to
72 transmit this signal. */
73 if ((itv->std & V4L2_STD_625_50) && !enabled) {
75 mode = 0x08; /* 4x3 full format */
77 data.id = V4L2_SLICED_WSS_625;
79 data.line = enabled ? 23 : 0;
80 data.data[0] = mode & 0xff;
81 data.data[1] = (mode >> 8) & 0xff;
82 ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data);
85 static int odd_parity(u8 c)
94 void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t cnt)
96 struct vbi_info *vi = &itv->vbi;
97 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
101 for (i = 0; i < cnt; i++) {
102 const struct v4l2_sliced_vbi_data *d = sliced + i;
104 if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) {
106 cc.even[0] = d->data[0];
107 cc.even[1] = d->data[1];
109 cc.odd[0] = d->data[0];
110 cc.odd[1] = d->data[1];
114 else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) {
117 vps.data[0] = d->data[2];
118 vps.data[1] = d->data[8];
119 vps.data[2] = d->data[9];
120 vps.data[3] = d->data[10];
121 vps.data[4] = d->data[11];
122 if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) {
123 vi->vps_payload = vps;
124 set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
127 else if (d->id == V4L2_SLICED_WSS_625 && d->line == 23 && d->field == 0) {
128 int wss = d->data[0] | d->data[1] << 8;
130 if (vi->wss_payload != wss) {
131 vi->wss_payload = wss;
132 set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
136 if (found_cc && vi->cc_payload_idx < sizeof(vi->cc_payload)) {
137 vi->cc_payload[vi->cc_payload_idx++] = cc;
138 set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
142 static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
146 u32 linemask[2] = { 0, 0 };
148 static const u8 mpeg_hdr_data[] = {
149 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
150 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
151 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
152 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
154 const int sd = sizeof(mpeg_hdr_data); /* start of vbi data */
155 int idx = itv->vbi.frame % IVTV_VBI_FRAMES;
156 u8 *dst = &itv->vbi.sliced_mpeg_data[idx][0];
158 for (i = 0; i < lines; i++) {
161 if (itv->vbi.sliced_data[i].id == 0)
164 l = itv->vbi.sliced_data[i].line - 6;
165 f = itv->vbi.sliced_data[i].field;
169 linemask[0] |= (1 << l);
171 linemask[1] |= (1 << (l - 32));
172 dst[sd + 12 + line * 43] = service2vbi(itv->vbi.sliced_data[i].id);
173 memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42);
176 memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
178 /* All lines are used, so there is no space for the linemask
179 (the max size of the VBI data is 36 * 43 + 4 bytes).
180 So in this case we use the magic number 'ITV0'. */
181 memcpy(dst + sd, "ITV0", 4);
182 memcpy(dst + sd + 4, dst + sd + 12, line * 43);
183 size = 4 + ((43 * line + 3) & ~3);
185 memcpy(dst + sd, "itv0", 4);
186 memcpy(dst + sd + 4, &linemask[0], 8);
187 size = 12 + ((43 * line + 3) & ~3);
189 dst[4+16] = (size + 10) >> 8;
190 dst[5+16] = (size + 10) & 0xff;
191 dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
192 dst[10+16] = (pts_stamp >> 22) & 0xff;
193 dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
194 dst[12+16] = (pts_stamp >> 7) & 0xff;
195 dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
196 itv->vbi.sliced_mpeg_size[idx] = sd + size;
199 static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p)
205 if (!memcmp(p, "itv0", 4)) {
206 memcpy(linemask, p + 4, 8);
208 } else if (!memcmp(p, "ITV0", 4)) {
209 linemask[0] = 0xffffffff;
213 /* unknown VBI data, convert to empty VBI frame */
214 linemask[0] = linemask[1] = 0;
216 for (i = 0; i < 36; i++) {
219 if (i < 32 && !(linemask[0] & (1 << i)))
221 if (i >= 32 && !(linemask[1] & (1 << (i - 32))))
225 case IVTV_SLICED_TYPE_TELETEXT_B:
226 id2 = V4L2_SLICED_TELETEXT_B;
228 case IVTV_SLICED_TYPE_CAPTION_525:
229 id2 = V4L2_SLICED_CAPTION_525;
230 err = !odd_parity(p[1]) || !odd_parity(p[2]);
232 case IVTV_SLICED_TYPE_VPS:
233 id2 = V4L2_SLICED_VPS;
235 case IVTV_SLICED_TYPE_WSS_625:
236 id2 = V4L2_SLICED_WSS_625;
243 l = (i < 18) ? i + 6 : i - 18 + 6;
244 itv->vbi.sliced_dec_data[line].line = l;
245 itv->vbi.sliced_dec_data[line].field = i >= 18;
246 itv->vbi.sliced_dec_data[line].id = id2;
247 memcpy(itv->vbi.sliced_dec_data[line].data, p + 1, 42);
253 itv->vbi.sliced_dec_data[line].id = 0;
254 itv->vbi.sliced_dec_data[line].line = 0;
255 itv->vbi.sliced_dec_data[line].field = 0;
258 return line * sizeof(itv->vbi.sliced_dec_data[0]);
261 /* Compress raw VBI format, removes leading SAV codes and surplus space after the
263 Returns new compressed size. */
264 static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size)
266 u32 line_size = itv->vbi.raw_decoder_line_size;
267 u32 lines = itv->vbi.count;
268 u8 sav1 = itv->vbi.raw_decoder_sav_odd_field;
269 u8 sav2 = itv->vbi.raw_decoder_sav_even_field;
274 for (i = 0; i < lines; i++) {
275 p = buf + i * line_size;
277 /* Look for SAV code */
278 if (p[0] != 0xff || p[1] || p[2] || (p[3] != sav1 && p[3] != sav2)) {
281 memcpy(q, p + 4, line_size - 4);
284 return lines * (line_size - 4);
288 /* Compressed VBI format, all found sliced blocks put next to one another
289 Returns new compressed size */
290 static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav)
292 u32 line_size = itv->vbi.sliced_decoder_line_size;
293 struct v4l2_decode_vbi_line vbi;
296 /* find the first valid line */
297 for (i = 0; i < size; i++, buf++) {
298 if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
303 if (size < line_size) {
306 for (i = 0; i < size / line_size; i++) {
307 u8 *p = buf + i * line_size;
309 /* Look for SAV code */
310 if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) {
314 itv->video_dec_func(itv, VIDIOC_INT_DECODE_VBI_LINE, &vbi);
316 itv->vbi.sliced_data[line].id = vbi.type;
317 itv->vbi.sliced_data[line].field = vbi.is_second_field;
318 itv->vbi.sliced_data[line].line = vbi.line;
319 memcpy(itv->vbi.sliced_data[line].data, vbi.p, 42);
326 void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
327 u64 pts_stamp, int streamtype)
329 u8 *p = (u8 *) buf->buf;
330 u32 size = buf->bytesused;
334 if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set == 0) {
341 size = buf->bytesused = compress_raw_buf(itv, p, size);
343 /* second field of the frame? */
344 if (type == itv->vbi.raw_decoder_sav_even_field) {
345 /* Dirty hack needed for backwards
346 compatibility of old VBI software. */
348 memcpy(p, &itv->vbi.frame, 4);
354 /* Sliced VBI data with data insertion */
355 if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) {
361 lines = compress_sliced_buf(itv, 0, p, size / 2,
362 itv->vbi.sliced_decoder_sav_odd_field);
364 /* experimentation shows that the second half does not always begin
365 at the exact address. So start a bit earlier (hence 32). */
366 lines = compress_sliced_buf(itv, lines, p + size / 2 - 32, size / 2 + 32,
367 itv->vbi.sliced_decoder_sav_even_field);
368 /* always return at least one empty line */
370 itv->vbi.sliced_data[0].id = 0;
371 itv->vbi.sliced_data[0].line = 0;
372 itv->vbi.sliced_data[0].field = 0;
375 buf->bytesused = size = lines * sizeof(itv->vbi.sliced_data[0]);
376 memcpy(p, &itv->vbi.sliced_data[0], size);
378 if (itv->vbi.insert_mpeg) {
379 copy_vbi_data(itv, lines, pts_stamp);
385 /* Sliced VBI re-inserted from an MPEG stream */
386 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
387 /* If the size is not 4-byte aligned, then the starting address
388 for the swapping is also shifted. After swapping the data the
389 real start address of the VBI data is exactly 4 bytes after the
390 original start. It's a bit fiddly but it works like a charm.
391 Non-4-byte alignment happens when an lseek is done on the input
392 mpeg file to a non-4-byte aligned position. So on arrival here
393 the VBI data is also non-4-byte aligned. */
394 int offset = size & 3;
401 for (y = 0; y < size; y += 4) {
402 swab32s((u32 *)(p + y));
405 cnt = ivtv_convert_ivtv_vbi(itv, p + offset);
406 memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt);
407 buf->bytesused = cnt;
409 ivtv_write_vbi(itv, itv->vbi.sliced_dec_data,
410 cnt / sizeof(itv->vbi.sliced_dec_data[0]));
415 void ivtv_disable_cc(struct ivtv *itv)
417 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
419 clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
420 ivtv_set_cc(itv, 0, &cc);
421 itv->vbi.cc_payload_idx = 0;
425 void ivtv_vbi_work_handler(struct ivtv *itv)
427 struct vbi_info *vi = &itv->vbi;
428 struct v4l2_sliced_vbi_data data;
429 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
432 if (itv->output_mode == OUT_PASSTHROUGH) {
434 data.id = V4L2_SLICED_WSS_625;
437 if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) {
438 ivtv_set_wss(itv, 1, data.data[0] & 0xf);
439 vi->wss_missing_cnt = 0;
440 } else if (vi->wss_missing_cnt == 4) {
441 ivtv_set_wss(itv, 1, 0x8); /* 4x3 full format */
443 vi->wss_missing_cnt++;
449 data.id = V4L2_SLICED_CAPTION_525;
451 if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) {
453 cc.odd[0] = data.data[0];
454 cc.odd[1] = data.data[1];
457 if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) {
459 cc.even[0] = data.data[0];
460 cc.even[1] = data.data[1];
463 vi->cc_missing_cnt = 0;
464 ivtv_set_cc(itv, mode, &cc);
465 } else if (vi->cc_missing_cnt == 4) {
466 ivtv_set_cc(itv, 0, &cc);
468 vi->cc_missing_cnt++;
474 if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) {
475 ivtv_set_wss(itv, 1, vi->wss_payload & 0xf);
478 if (test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) {
479 if (vi->cc_payload_idx == 0) {
480 clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
481 ivtv_set_cc(itv, 3, &cc);
483 while (vi->cc_payload_idx) {
484 cc = vi->cc_payload[0];
486 memcpy(vi->cc_payload, vi->cc_payload + 1,
487 sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0]));
488 vi->cc_payload_idx--;
489 if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80)
492 ivtv_set_cc(itv, 3, &cc);
497 if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) {
498 ivtv_set_vps(itv, 1);