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] =
173 ivtv_service2vbi(itv->vbi.sliced_data[i].id);
174 memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42);
177 memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
179 /* All lines are used, so there is no space for the linemask
180 (the max size of the VBI data is 36 * 43 + 4 bytes).
181 So in this case we use the magic number 'ITV0'. */
182 memcpy(dst + sd, "ITV0", 4);
183 memcpy(dst + sd + 4, dst + sd + 12, line * 43);
184 size = 4 + ((43 * line + 3) & ~3);
186 memcpy(dst + sd, "itv0", 4);
187 memcpy(dst + sd + 4, &linemask[0], 8);
188 size = 12 + ((43 * line + 3) & ~3);
190 dst[4+16] = (size + 10) >> 8;
191 dst[5+16] = (size + 10) & 0xff;
192 dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
193 dst[10+16] = (pts_stamp >> 22) & 0xff;
194 dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
195 dst[12+16] = (pts_stamp >> 7) & 0xff;
196 dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
197 itv->vbi.sliced_mpeg_size[idx] = sd + size;
200 static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p)
206 if (!memcmp(p, "itv0", 4)) {
207 memcpy(linemask, p + 4, 8);
209 } else if (!memcmp(p, "ITV0", 4)) {
210 linemask[0] = 0xffffffff;
214 /* unknown VBI data, convert to empty VBI frame */
215 linemask[0] = linemask[1] = 0;
217 for (i = 0; i < 36; i++) {
220 if (i < 32 && !(linemask[0] & (1 << i)))
222 if (i >= 32 && !(linemask[1] & (1 << (i - 32))))
226 case IVTV_SLICED_TYPE_TELETEXT_B:
227 id2 = V4L2_SLICED_TELETEXT_B;
229 case IVTV_SLICED_TYPE_CAPTION_525:
230 id2 = V4L2_SLICED_CAPTION_525;
231 err = !odd_parity(p[1]) || !odd_parity(p[2]);
233 case IVTV_SLICED_TYPE_VPS:
234 id2 = V4L2_SLICED_VPS;
236 case IVTV_SLICED_TYPE_WSS_625:
237 id2 = V4L2_SLICED_WSS_625;
244 l = (i < 18) ? i + 6 : i - 18 + 6;
245 itv->vbi.sliced_dec_data[line].line = l;
246 itv->vbi.sliced_dec_data[line].field = i >= 18;
247 itv->vbi.sliced_dec_data[line].id = id2;
248 memcpy(itv->vbi.sliced_dec_data[line].data, p + 1, 42);
254 itv->vbi.sliced_dec_data[line].id = 0;
255 itv->vbi.sliced_dec_data[line].line = 0;
256 itv->vbi.sliced_dec_data[line].field = 0;
259 return line * sizeof(itv->vbi.sliced_dec_data[0]);
262 /* Compress raw VBI format, removes leading SAV codes and surplus space after the
264 Returns new compressed size. */
265 static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size)
267 u32 line_size = itv->vbi.raw_decoder_line_size;
268 u32 lines = itv->vbi.count;
269 u8 sav1 = itv->vbi.raw_decoder_sav_odd_field;
270 u8 sav2 = itv->vbi.raw_decoder_sav_even_field;
275 for (i = 0; i < lines; i++) {
276 p = buf + i * line_size;
278 /* Look for SAV code */
279 if (p[0] != 0xff || p[1] || p[2] || (p[3] != sav1 && p[3] != sav2)) {
282 memcpy(q, p + 4, line_size - 4);
285 return lines * (line_size - 4);
289 /* Compressed VBI format, all found sliced blocks put next to one another
290 Returns new compressed size */
291 static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav)
293 u32 line_size = itv->vbi.sliced_decoder_line_size;
294 struct v4l2_decode_vbi_line vbi;
298 /* find the first valid line */
299 for (i = 0; i < size; i++, buf++) {
300 if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
305 if (size < line_size) {
308 for (i = 0; i < size / line_size; i++) {
309 u8 *p = buf + i * line_size;
311 /* Look for SAV code */
312 if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) {
316 itv->video_dec_func(itv, VIDIOC_INT_DECODE_VBI_LINE, &vbi);
317 if (vbi.type && !(lines & (1 << vbi.line))) {
318 lines |= 1 << vbi.line;
319 itv->vbi.sliced_data[line].id = vbi.type;
320 itv->vbi.sliced_data[line].field = vbi.is_second_field;
321 itv->vbi.sliced_data[line].line = vbi.line;
322 memcpy(itv->vbi.sliced_data[line].data, vbi.p, 42);
329 void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
330 u64 pts_stamp, int streamtype)
332 u8 *p = (u8 *) buf->buf;
333 u32 size = buf->bytesused;
337 if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set == 0) {
344 size = buf->bytesused = compress_raw_buf(itv, p, size);
346 /* second field of the frame? */
347 if (type == itv->vbi.raw_decoder_sav_even_field) {
348 /* Dirty hack needed for backwards
349 compatibility of old VBI software. */
351 memcpy(p, &itv->vbi.frame, 4);
357 /* Sliced VBI data with data insertion */
358 if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) {
364 lines = compress_sliced_buf(itv, 0, p, size / 2,
365 itv->vbi.sliced_decoder_sav_odd_field);
367 /* experimentation shows that the second half does not always begin
368 at the exact address. So start a bit earlier (hence 32). */
369 lines = compress_sliced_buf(itv, lines, p + size / 2 - 32, size / 2 + 32,
370 itv->vbi.sliced_decoder_sav_even_field);
371 /* always return at least one empty line */
373 itv->vbi.sliced_data[0].id = 0;
374 itv->vbi.sliced_data[0].line = 0;
375 itv->vbi.sliced_data[0].field = 0;
378 buf->bytesused = size = lines * sizeof(itv->vbi.sliced_data[0]);
379 memcpy(p, &itv->vbi.sliced_data[0], size);
381 if (itv->vbi.insert_mpeg) {
382 copy_vbi_data(itv, lines, pts_stamp);
388 /* Sliced VBI re-inserted from an MPEG stream */
389 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
390 /* If the size is not 4-byte aligned, then the starting address
391 for the swapping is also shifted. After swapping the data the
392 real start address of the VBI data is exactly 4 bytes after the
393 original start. It's a bit fiddly but it works like a charm.
394 Non-4-byte alignment happens when an lseek is done on the input
395 mpeg file to a non-4-byte aligned position. So on arrival here
396 the VBI data is also non-4-byte aligned. */
397 int offset = size & 3;
404 for (y = 0; y < size; y += 4) {
405 swab32s((u32 *)(p + y));
408 cnt = ivtv_convert_ivtv_vbi(itv, p + offset);
409 memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt);
410 buf->bytesused = cnt;
412 ivtv_write_vbi(itv, itv->vbi.sliced_dec_data,
413 cnt / sizeof(itv->vbi.sliced_dec_data[0]));
418 void ivtv_disable_cc(struct ivtv *itv)
420 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
422 clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
423 ivtv_set_cc(itv, 0, &cc);
424 itv->vbi.cc_payload_idx = 0;
428 void ivtv_vbi_work_handler(struct ivtv *itv)
430 struct vbi_info *vi = &itv->vbi;
431 struct v4l2_sliced_vbi_data data;
432 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
435 if (itv->output_mode == OUT_PASSTHROUGH) {
437 data.id = V4L2_SLICED_WSS_625;
440 if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) {
441 ivtv_set_wss(itv, 1, data.data[0] & 0xf);
442 vi->wss_missing_cnt = 0;
443 } else if (vi->wss_missing_cnt == 4) {
444 ivtv_set_wss(itv, 1, 0x8); /* 4x3 full format */
446 vi->wss_missing_cnt++;
452 data.id = V4L2_SLICED_CAPTION_525;
454 if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) {
456 cc.odd[0] = data.data[0];
457 cc.odd[1] = data.data[1];
460 if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) {
462 cc.even[0] = data.data[0];
463 cc.even[1] = data.data[1];
466 vi->cc_missing_cnt = 0;
467 ivtv_set_cc(itv, mode, &cc);
468 } else if (vi->cc_missing_cnt == 4) {
469 ivtv_set_cc(itv, 0, &cc);
471 vi->cc_missing_cnt++;
477 if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) {
478 ivtv_set_wss(itv, 1, vi->wss_payload & 0xf);
481 if (test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) {
482 if (vi->cc_payload_idx == 0) {
483 clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
484 ivtv_set_cc(itv, 3, &cc);
486 while (vi->cc_payload_idx) {
487 cc = vi->cc_payload[0];
489 memcpy(vi->cc_payload, vi->cc_payload + 1,
490 sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0]));
491 vi->cc_payload_idx--;
492 if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80)
495 ivtv_set_cc(itv, 3, &cc);
500 if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) {
501 ivtv_set_vps(itv, 1);