2 * cx18 Vertical Blank Interval support functions
4 * Derived from ivtv-vbi.c
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 #include "cx18-driver.h"
26 #include "cx18-ioctl.h"
27 #include "cx18-queue.h"
28 #include "cx18-av-core.h"
30 static void copy_vbi_data(struct cx18
*cx
, int lines
, u32 pts_stamp
)
34 u32 linemask
[2] = { 0, 0 };
36 static const u8 mpeg_hdr_data
[] = {
37 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
38 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
39 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
40 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
42 const int sd
= sizeof(mpeg_hdr_data
); /* start of vbi data */
43 int idx
= cx
->vbi
.frame
% CX18_VBI_FRAMES
;
44 u8
*dst
= &cx
->vbi
.sliced_mpeg_data
[idx
][0];
46 for (i
= 0; i
< lines
; i
++) {
47 struct v4l2_sliced_vbi_data
*sdata
= cx
->vbi
.sliced_data
+ i
;
58 linemask
[0] |= (1 << l
);
60 linemask
[1] |= (1 << (l
- 32));
61 dst
[sd
+ 12 + line
* 43] = cx18_service2vbi(sdata
->id
);
62 memcpy(dst
+ sd
+ 12 + line
* 43 + 1, sdata
->data
, 42);
65 memcpy(dst
, mpeg_hdr_data
, sizeof(mpeg_hdr_data
));
67 /* All lines are used, so there is no space for the linemask
68 (the max size of the VBI data is 36 * 43 + 4 bytes).
69 So in this case we use the magic number 'ITV0'. */
70 memcpy(dst
+ sd
, "ITV0", 4);
71 memcpy(dst
+ sd
+ 4, dst
+ sd
+ 12, line
* 43);
72 size
= 4 + ((43 * line
+ 3) & ~3);
74 memcpy(dst
+ sd
, "cx0", 4);
75 memcpy(dst
+ sd
+ 4, &linemask
[0], 8);
76 size
= 12 + ((43 * line
+ 3) & ~3);
78 dst
[4+16] = (size
+ 10) >> 8;
79 dst
[5+16] = (size
+ 10) & 0xff;
80 dst
[9+16] = 0x21 | ((pts_stamp
>> 29) & 0x6);
81 dst
[10+16] = (pts_stamp
>> 22) & 0xff;
82 dst
[11+16] = 1 | ((pts_stamp
>> 14) & 0xff);
83 dst
[12+16] = (pts_stamp
>> 7) & 0xff;
84 dst
[13+16] = 1 | ((pts_stamp
& 0x7f) << 1);
85 cx
->vbi
.sliced_mpeg_size
[idx
] = sd
+ size
;
88 /* Compress raw VBI format, removes leading SAV codes and surplus space
90 Returns new compressed size. */
91 static u32
compress_raw_buf(struct cx18
*cx
, u8
*buf
, u32 size
)
93 u32 line_size
= cx
->vbi
.raw_decoder_line_size
;
94 u32 lines
= cx
->vbi
.count
;
95 u8 sav1
= cx
->vbi
.raw_decoder_sav_odd_field
;
96 u8 sav2
= cx
->vbi
.raw_decoder_sav_even_field
;
101 for (i
= 0; i
< lines
; i
++) {
102 p
= buf
+ i
* line_size
;
104 /* Look for SAV code */
105 if (p
[0] != 0xff || p
[1] || p
[2] ||
106 (p
[3] != sav1
&& p
[3] != sav2
))
108 memcpy(q
, p
+ 4, line_size
- 4);
111 return lines
* (line_size
- 4);
115 /* Compressed VBI format, all found sliced blocks put next to one another
116 Returns new compressed size */
117 static u32
compress_sliced_buf(struct cx18
*cx
, u32 line
, u8
*buf
,
120 u32 line_size
= cx
->vbi
.sliced_decoder_line_size
;
121 struct v4l2_decode_vbi_line vbi
;
124 /* find the first valid line */
125 for (i
= 0; i
< size
; i
++, buf
++) {
126 if (buf
[0] == 0xff && !buf
[1] && !buf
[2] && buf
[3] == sav
)
131 if (size
< line_size
)
133 for (i
= 0; i
< size
/ line_size
; i
++) {
134 u8
*p
= buf
+ i
* line_size
;
136 /* Look for SAV code */
137 if (p
[0] != 0xff || p
[1] || p
[2] || p
[3] != sav
)
140 cx18_av_cmd(cx
, VIDIOC_INT_DECODE_VBI_LINE
, &vbi
);
142 cx
->vbi
.sliced_data
[line
].id
= vbi
.type
;
143 cx
->vbi
.sliced_data
[line
].field
= vbi
.is_second_field
;
144 cx
->vbi
.sliced_data
[line
].line
= vbi
.line
;
145 memcpy(cx
->vbi
.sliced_data
[line
].data
, vbi
.p
, 42);
152 void cx18_process_vbi_data(struct cx18
*cx
, struct cx18_buffer
*buf
,
153 u64 pts_stamp
, int streamtype
)
155 u8
*p
= (u8
*) buf
->buf
;
156 u32 size
= buf
->bytesused
;
159 if (streamtype
!= CX18_ENC_STREAM_TYPE_VBI
)
163 if (cx18_raw_vbi(cx
)) {
170 size
= buf
->bytesused
= compress_raw_buf(cx
, p
, size
);
172 /* second field of the frame? */
173 if (type
== cx
->vbi
.raw_decoder_sav_even_field
) {
174 /* Dirty hack needed for backwards
175 compatibility of old VBI software. */
177 memcpy(p
, &cx
->vbi
.frame
, 4);
183 /* Sliced VBI data with data insertion */
187 lines
= compress_sliced_buf(cx
, 0, p
, size
/ 2,
188 cx
->vbi
.sliced_decoder_sav_odd_field
);
190 /* experimentation shows that the second half does not always
191 begin at the exact address. So start a bit earlier
193 lines
= compress_sliced_buf(cx
, lines
, p
+ size
/ 2 - 32,
194 size
/ 2 + 32, cx
->vbi
.sliced_decoder_sav_even_field
);
195 /* always return at least one empty line */
197 cx
->vbi
.sliced_data
[0].id
= 0;
198 cx
->vbi
.sliced_data
[0].line
= 0;
199 cx
->vbi
.sliced_data
[0].field
= 0;
202 buf
->bytesused
= size
= lines
* sizeof(cx
->vbi
.sliced_data
[0]);
203 memcpy(p
, &cx
->vbi
.sliced_data
[0], size
);
205 if (cx
->vbi
.insert_mpeg
)
206 copy_vbi_data(cx
, lines
, pts_stamp
);