diff options
author | Andy Walls <awalls@radix.net> | 2009-03-14 22:20:49 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:43:28 -0400 |
commit | 4ab9b256b5908afbdc030a8c3184ce243f5aca39 (patch) | |
tree | 25f604c5794dbae544a6a42c90e4c37ac77082c5 /drivers/media/video/cx18 | |
parent | 6e1a63720228ef7fc3bd00b04dfb608064fbab4e (diff) |
V4L/DVB (11092): cx18: Optimize processing of VBI buffers from the capture unit
Removed some unnecessary memcpy()'s by reworking the compress_*_vbi_buf()
functions.
Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18')
-rw-r--r-- | drivers/media/video/cx18/cx18-vbi.c | 103 |
1 files changed, 49 insertions, 54 deletions
diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index 99f9b2c86b0c..c2aef4add31d 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c | |||
@@ -105,54 +105,72 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) | |||
105 | 105 | ||
106 | /* Compress raw VBI format, removes leading SAV codes and surplus space | 106 | /* Compress raw VBI format, removes leading SAV codes and surplus space |
107 | after the frame. Returns new compressed size. */ | 107 | after the frame. Returns new compressed size. */ |
108 | static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size) | 108 | static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size, u32 hdr_size) |
109 | { | 109 | { |
110 | u32 line_size = vbi_active_samples; | 110 | u32 line_size = vbi_active_samples; |
111 | u32 lines = cx->vbi.count * 2; | 111 | u32 lines = cx->vbi.count * 2; |
112 | u8 sav1 = raw_vbi_sav_rp[0]; | ||
113 | u8 sav2 = raw_vbi_sav_rp[1]; | ||
114 | u8 *q = buf; | 112 | u8 *q = buf; |
115 | u8 *p; | 113 | u8 *p; |
116 | int i; | 114 | int i; |
117 | 115 | ||
116 | /* Skip the header */ | ||
117 | buf += hdr_size; | ||
118 | |||
118 | for (i = 0; i < lines; i++) { | 119 | for (i = 0; i < lines; i++) { |
119 | p = buf + i * line_size; | 120 | p = buf + i * line_size; |
120 | 121 | ||
121 | /* Look for SAV code */ | 122 | /* Look for SAV code */ |
122 | if (p[0] != 0xff || p[1] || p[2] || | 123 | if (p[0] != 0xff || p[1] || p[2] || |
123 | (p[3] != sav1 && p[3] != sav2)) | 124 | (p[3] != raw_vbi_sav_rp[0] && |
125 | p[3] != raw_vbi_sav_rp[1])) | ||
124 | break; | 126 | break; |
125 | memcpy(q, p + 4, line_size - 4); | 127 | if (i == lines - 1) { |
126 | q += line_size - 4; | 128 | /* last line is hdr_size bytes short - extrapolate it */ |
129 | memcpy(q, p + 4, line_size - 4 - hdr_size); | ||
130 | q += line_size - 4 - hdr_size; | ||
131 | p += line_size - hdr_size - 1; | ||
132 | memset(q, (int) *p, hdr_size); | ||
133 | } else { | ||
134 | memcpy(q, p + 4, line_size - 4); | ||
135 | q += line_size - 4; | ||
136 | } | ||
127 | } | 137 | } |
128 | return lines * (line_size - 4); | 138 | return lines * (line_size - 4); |
129 | } | 139 | } |
130 | 140 | ||
131 | 141 | static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size, | |
132 | /* Compressed VBI format, all found sliced blocks put next to one another | 142 | const u32 hdr_size) |
133 | Returns new compressed size */ | ||
134 | static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, | ||
135 | u32 size, u8 eav) | ||
136 | { | 143 | { |
137 | struct v4l2_decode_vbi_line vbi; | 144 | struct v4l2_decode_vbi_line vbi; |
138 | int i; | 145 | int i; |
146 | u32 line = 0; | ||
139 | u32 line_size = cx->is_60hz ? vbi_hblank_samples_60Hz | 147 | u32 line_size = cx->is_60hz ? vbi_hblank_samples_60Hz |
140 | : vbi_hblank_samples_50Hz; | 148 | : vbi_hblank_samples_50Hz; |
141 | 149 | ||
142 | /* find the first valid line */ | 150 | /* find the first valid line */ |
143 | for (i = 0; i < size; i++, buf++) { | 151 | for (i = hdr_size, buf += hdr_size; i < size; i++, buf++) { |
144 | if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == eav) | 152 | if (buf[0] == 0xff && !buf[1] && !buf[2] && |
153 | (buf[3] == sliced_vbi_eav_rp[0] || | ||
154 | buf[3] == sliced_vbi_eav_rp[1])) | ||
145 | break; | 155 | break; |
146 | } | 156 | } |
147 | 157 | ||
148 | size -= i; | 158 | /* |
159 | * The last line is short by hdr_size bytes, but for the remaining | ||
160 | * checks against size, we pretend that it is not, by counting the | ||
161 | * header bytes we knowingly skipped | ||
162 | */ | ||
163 | size -= (i - hdr_size); | ||
149 | if (size < line_size) | 164 | if (size < line_size) |
150 | return line; | 165 | return line; |
166 | |||
151 | for (i = 0; i < size / line_size; i++) { | 167 | for (i = 0; i < size / line_size; i++) { |
152 | u8 *p = buf + i * line_size; | 168 | u8 *p = buf + i * line_size; |
153 | 169 | ||
154 | /* Look for EAV code */ | 170 | /* Look for EAV code */ |
155 | if (p[0] != 0xff || p[1] || p[2] || p[3] != eav) | 171 | if (p[0] != 0xff || p[1] || p[2] || |
172 | (p[3] != sliced_vbi_eav_rp[0] && | ||
173 | p[3] != sliced_vbi_eav_rp[1])) | ||
156 | continue; | 174 | continue; |
157 | vbi.p = p + 4; | 175 | vbi.p = p + 4; |
158 | v4l2_subdev_call(cx->sd_av, video, decode_vbi_line, &vbi); | 176 | v4l2_subdev_call(cx->sd_av, video, decode_vbi_line, &vbi); |
@@ -170,8 +188,17 @@ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, | |||
170 | void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, | 188 | void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, |
171 | int streamtype) | 189 | int streamtype) |
172 | { | 190 | { |
191 | /* | ||
192 | * The CX23418 provides a 12 byte header in its raw VBI buffers to us: | ||
193 | * 0x3fffffff [4 bytes of something] [4 byte presentation time stamp] | ||
194 | */ | ||
195 | struct vbi_data_hdr { | ||
196 | __be32 magic; | ||
197 | __be32 unknown; | ||
198 | __be32 pts; | ||
199 | } *hdr = (struct vbi_data_hdr *) buf->buf; | ||
200 | |||
173 | u8 *p = (u8 *) buf->buf; | 201 | u8 *p = (u8 *) buf->buf; |
174 | __be32 *q = (__be32 *) buf->buf; | ||
175 | u32 size = buf->bytesused; | 202 | u32 size = buf->bytesused; |
176 | u32 pts; | 203 | u32 pts; |
177 | int lines; | 204 | int lines; |
@@ -182,32 +209,15 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, | |||
182 | /* | 209 | /* |
183 | * The CX23418 sends us data that is 32 bit little-endian swapped, | 210 | * The CX23418 sends us data that is 32 bit little-endian swapped, |
184 | * but we want the raw VBI bytes in the order they were in the raster | 211 | * but we want the raw VBI bytes in the order they were in the raster |
185 | * line. This has a side effect of making the 12 byte header big endian | 212 | * line. This has a side effect of making the header big endian |
186 | */ | 213 | */ |
187 | cx18_buf_swap(buf); | 214 | cx18_buf_swap(buf); |
188 | 215 | ||
189 | /* | ||
190 | * The CX23418 provides a 12 byte header in it's raw VBI buffers to us: | ||
191 | * 0x3fffffff [4 bytes of something] [4 byte presentation time stamp?] | ||
192 | */ | ||
193 | |||
194 | /* Raw VBI data */ | 216 | /* Raw VBI data */ |
195 | if (cx18_raw_vbi(cx)) { | 217 | if (cx18_raw_vbi(cx)) { |
196 | u8 type; | ||
197 | |||
198 | /* | ||
199 | * We've set up to get a frame's worth of VBI data at a time. | ||
200 | * Skip 12 bytes of header prefixing the first field. | ||
201 | */ | ||
202 | size -= 12; | ||
203 | memcpy(p, &buf->buf[12], size); | ||
204 | type = p[3]; | ||
205 | 218 | ||
206 | /* Extrapolate the last 12 bytes of the frame's last line */ | 219 | size = buf->bytesused = |
207 | memset(&p[size], (int) p[size - 1], 12); | 220 | compress_raw_buf(cx, p, size, sizeof(struct vbi_data_hdr)); |
208 | size += 12; | ||
209 | |||
210 | size = buf->bytesused = compress_raw_buf(cx, p, size); | ||
211 | 221 | ||
212 | /* | 222 | /* |
213 | * Hack needed for compatibility with old VBI software. | 223 | * Hack needed for compatibility with old VBI software. |
@@ -221,26 +231,11 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, | |||
221 | 231 | ||
222 | /* Sliced VBI data with data insertion */ | 232 | /* Sliced VBI data with data insertion */ |
223 | 233 | ||
224 | pts = (be32_to_cpu(q[0]) == 0x3fffffff) ? be32_to_cpu(q[2]) : 0; | 234 | pts = (be32_to_cpu(hdr->magic) == 0x3fffffff) ? be32_to_cpu(hdr->pts) |
235 | : 0; | ||
225 | 236 | ||
226 | /* | 237 | lines = compress_sliced_buf(cx, p, size, sizeof(struct vbi_data_hdr)); |
227 | * For calls to compress_sliced_buf(), ensure there are an integral | ||
228 | * number of lines by shifting the real data up over the 12 bytes header | ||
229 | * that got stuffed in. | ||
230 | * FIXME - there's a smarter way to do this with pointers, but for some | ||
231 | * reason I can't get it to work correctly right now. | ||
232 | */ | ||
233 | memcpy(p, &buf->buf[12], size-12); | ||
234 | 238 | ||
235 | /* first field */ | ||
236 | lines = compress_sliced_buf(cx, 0, p, size / 2, sliced_vbi_eav_rp[0]); | ||
237 | /* | ||
238 | * second field | ||
239 | * In case the second half does not always begin at the exact address, | ||
240 | * start a bit earlier (hence 32). | ||
241 | */ | ||
242 | lines = compress_sliced_buf(cx, lines, p + size / 2 - 32, | ||
243 | size / 2 + 32, sliced_vbi_eav_rp[1]); | ||
244 | /* always return at least one empty line */ | 239 | /* always return at least one empty line */ |
245 | if (lines == 0) { | 240 | if (lines == 0) { |
246 | cx->vbi.sliced_data[0].id = 0; | 241 | cx->vbi.sliced_data[0].id = 0; |