diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2015-03-09 11:06:27 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2015-04-02 19:55:12 -0400 |
commit | 1f9f23f62fb46d6cef93febe57bf41fb21fd01fa (patch) | |
tree | bfba8aa8d5f56dff9343289e128b0393aacdd56c /drivers/media/platform/vivid | |
parent | ddcaee9dd4c00174db8ddf913c87ddf3773c446e (diff) |
[media] vivid: add downsampling support
Add support in vivid for downsampling. Most of the changes are in
vivid_copy_buffer which needs to know about the right line widths.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/media/platform/vivid')
-rw-r--r-- | drivers/media/platform/vivid/vivid-kthread-cap.c | 68 | ||||
-rw-r--r-- | drivers/media/platform/vivid/vivid-vid-out.c | 7 |
2 files changed, 43 insertions, 32 deletions
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c index 22e17847e67f..1727f5453f0b 100644 --- a/drivers/media/platform/vivid/vivid-kthread-cap.c +++ b/drivers/media/platform/vivid/vivid-kthread-cap.c | |||
@@ -249,8 +249,9 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf, | |||
249 | bool blank = dev->must_blank[vid_cap_buf->vb.v4l2_buf.index]; | 249 | bool blank = dev->must_blank[vid_cap_buf->vb.v4l2_buf.index]; |
250 | struct tpg_data *tpg = &dev->tpg; | 250 | struct tpg_data *tpg = &dev->tpg; |
251 | struct vivid_buffer *vid_out_buf = NULL; | 251 | struct vivid_buffer *vid_out_buf = NULL; |
252 | unsigned pixsize = tpg_g_twopixelsize(tpg, p) / 2; | 252 | unsigned vdiv = dev->fmt_out->vdownsampling[p]; |
253 | unsigned img_width = dev->compose_cap.width; | 253 | unsigned twopixsize = tpg_g_twopixelsize(tpg, p); |
254 | unsigned img_width = tpg_hdiv(tpg, p, dev->compose_cap.width); | ||
254 | unsigned img_height = dev->compose_cap.height; | 255 | unsigned img_height = dev->compose_cap.height; |
255 | unsigned stride_cap = tpg->bytesperline[p]; | 256 | unsigned stride_cap = tpg->bytesperline[p]; |
256 | unsigned stride_out = dev->bytesperline_out[p]; | 257 | unsigned stride_out = dev->bytesperline_out[p]; |
@@ -269,6 +270,7 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf, | |||
269 | unsigned vid_overlay_fract_part = 0; | 270 | unsigned vid_overlay_fract_part = 0; |
270 | unsigned vid_overlay_y = 0; | 271 | unsigned vid_overlay_y = 0; |
271 | unsigned vid_overlay_error = 0; | 272 | unsigned vid_overlay_error = 0; |
273 | unsigned vid_cap_left = tpg_hdiv(tpg, p, dev->loop_vid_cap.left); | ||
272 | unsigned vid_cap_right; | 274 | unsigned vid_cap_right; |
273 | bool quick; | 275 | bool quick; |
274 | 276 | ||
@@ -287,23 +289,25 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf, | |||
287 | dev->bytesperline_out, dev->fmt_out_rect.height); | 289 | dev->bytesperline_out, dev->fmt_out_rect.height); |
288 | if (p < dev->fmt_out->buffers) | 290 | if (p < dev->fmt_out->buffers) |
289 | voutbuf += vid_out_buf->vb.v4l2_planes[p].data_offset; | 291 | voutbuf += vid_out_buf->vb.v4l2_planes[p].data_offset; |
290 | voutbuf += dev->loop_vid_out.left * pixsize + dev->loop_vid_out.top * stride_out; | 292 | voutbuf += tpg_hdiv(tpg, p, dev->loop_vid_out.left) + |
291 | vcapbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride_cap; | 293 | (dev->loop_vid_out.top / vdiv) * stride_out; |
294 | vcapbuf += tpg_hdiv(tpg, p, dev->compose_cap.left) + | ||
295 | (dev->compose_cap.top / vdiv) * stride_cap; | ||
292 | 296 | ||
293 | if (dev->loop_vid_copy.width == 0 || dev->loop_vid_copy.height == 0) { | 297 | if (dev->loop_vid_copy.width == 0 || dev->loop_vid_copy.height == 0) { |
294 | /* | 298 | /* |
295 | * If there is nothing to copy, then just fill the capture window | 299 | * If there is nothing to copy, then just fill the capture window |
296 | * with black. | 300 | * with black. |
297 | */ | 301 | */ |
298 | for (y = 0; y < hmax; y++, vcapbuf += stride_cap) | 302 | for (y = 0; y < hmax / vdiv; y++, vcapbuf += stride_cap) |
299 | memcpy(vcapbuf, tpg->black_line[p], img_width * pixsize); | 303 | memcpy(vcapbuf, tpg->black_line[p], img_width); |
300 | return 0; | 304 | return 0; |
301 | } | 305 | } |
302 | 306 | ||
303 | if (dev->overlay_out_enabled && | 307 | if (dev->overlay_out_enabled && |
304 | dev->loop_vid_overlay.width && dev->loop_vid_overlay.height) { | 308 | dev->loop_vid_overlay.width && dev->loop_vid_overlay.height) { |
305 | vosdbuf = dev->video_vbase; | 309 | vosdbuf = dev->video_vbase; |
306 | vosdbuf += dev->loop_fb_copy.left * pixsize + | 310 | vosdbuf += (dev->loop_fb_copy.left * twopixsize) / 2 + |
307 | dev->loop_fb_copy.top * stride_osd; | 311 | dev->loop_fb_copy.top * stride_osd; |
308 | vid_overlay_int_part = dev->loop_vid_overlay.height / | 312 | vid_overlay_int_part = dev->loop_vid_overlay.height / |
309 | dev->loop_vid_overlay_cap.height; | 313 | dev->loop_vid_overlay_cap.height; |
@@ -311,12 +315,12 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf, | |||
311 | dev->loop_vid_overlay_cap.height; | 315 | dev->loop_vid_overlay_cap.height; |
312 | } | 316 | } |
313 | 317 | ||
314 | vid_cap_right = dev->loop_vid_cap.left + dev->loop_vid_cap.width; | 318 | vid_cap_right = tpg_hdiv(tpg, p, dev->loop_vid_cap.left + dev->loop_vid_cap.width); |
315 | /* quick is true if no video scaling is needed */ | 319 | /* quick is true if no video scaling is needed */ |
316 | quick = dev->loop_vid_out.width == dev->loop_vid_cap.width; | 320 | quick = dev->loop_vid_out.width == dev->loop_vid_cap.width; |
317 | 321 | ||
318 | dev->cur_scaled_line = dev->loop_vid_out.height; | 322 | dev->cur_scaled_line = dev->loop_vid_out.height; |
319 | for (y = 0; y < hmax; y++, vcapbuf += stride_cap) { | 323 | for (y = 0; y < hmax; y += vdiv, vcapbuf += stride_cap) { |
320 | /* osdline is true if this line requires overlay blending */ | 324 | /* osdline is true if this line requires overlay blending */ |
321 | bool osdline = vosdbuf && y >= dev->loop_vid_overlay_cap.top && | 325 | bool osdline = vosdbuf && y >= dev->loop_vid_overlay_cap.top && |
322 | y < dev->loop_vid_overlay_cap.top + dev->loop_vid_overlay_cap.height; | 326 | y < dev->loop_vid_overlay_cap.top + dev->loop_vid_overlay_cap.height; |
@@ -327,34 +331,34 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf, | |||
327 | */ | 331 | */ |
328 | if (y < dev->loop_vid_cap.top || | 332 | if (y < dev->loop_vid_cap.top || |
329 | y >= dev->loop_vid_cap.top + dev->loop_vid_cap.height) { | 333 | y >= dev->loop_vid_cap.top + dev->loop_vid_cap.height) { |
330 | memcpy(vcapbuf, tpg->black_line[p], img_width * pixsize); | 334 | memcpy(vcapbuf, tpg->black_line[p], img_width); |
331 | continue; | 335 | continue; |
332 | } | 336 | } |
333 | 337 | ||
334 | /* fill the left border with black */ | 338 | /* fill the left border with black */ |
335 | if (dev->loop_vid_cap.left) | 339 | if (dev->loop_vid_cap.left) |
336 | memcpy(vcapbuf, tpg->black_line[p], dev->loop_vid_cap.left * pixsize); | 340 | memcpy(vcapbuf, tpg->black_line[p], vid_cap_left); |
337 | 341 | ||
338 | /* fill the right border with black */ | 342 | /* fill the right border with black */ |
339 | if (vid_cap_right < img_width) | 343 | if (vid_cap_right < img_width) |
340 | memcpy(vcapbuf + vid_cap_right * pixsize, | 344 | memcpy(vcapbuf + vid_cap_right, tpg->black_line[p], |
341 | tpg->black_line[p], (img_width - vid_cap_right) * pixsize); | 345 | img_width - vid_cap_right); |
342 | 346 | ||
343 | if (quick && !osdline) { | 347 | if (quick && !osdline) { |
344 | memcpy(vcapbuf + dev->loop_vid_cap.left * pixsize, | 348 | memcpy(vcapbuf + vid_cap_left, |
345 | voutbuf + vid_out_y * stride_out, | 349 | voutbuf + vid_out_y * stride_out, |
346 | dev->loop_vid_cap.width * pixsize); | 350 | tpg_hdiv(tpg, p, dev->loop_vid_cap.width)); |
347 | goto update_vid_out_y; | 351 | goto update_vid_out_y; |
348 | } | 352 | } |
349 | if (dev->cur_scaled_line == vid_out_y) { | 353 | if (dev->cur_scaled_line == vid_out_y) { |
350 | memcpy(vcapbuf + dev->loop_vid_cap.left * pixsize, | 354 | memcpy(vcapbuf + vid_cap_left, dev->scaled_line, |
351 | dev->scaled_line, | 355 | tpg_hdiv(tpg, p, dev->loop_vid_cap.width)); |
352 | dev->loop_vid_cap.width * pixsize); | ||
353 | goto update_vid_out_y; | 356 | goto update_vid_out_y; |
354 | } | 357 | } |
355 | if (!osdline) { | 358 | if (!osdline) { |
356 | scale_line(voutbuf + vid_out_y * stride_out, dev->scaled_line, | 359 | scale_line(voutbuf + vid_out_y * stride_out, dev->scaled_line, |
357 | dev->loop_vid_out.width, dev->loop_vid_cap.width, | 360 | tpg_hdiv(tpg, p, dev->loop_vid_out.width), |
361 | tpg_hdiv(tpg, p, dev->loop_vid_cap.width), | ||
358 | tpg_g_twopixelsize(tpg, p)); | 362 | tpg_g_twopixelsize(tpg, p)); |
359 | } else { | 363 | } else { |
360 | /* | 364 | /* |
@@ -362,7 +366,8 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf, | |||
362 | * loop_vid_overlay rectangle. | 366 | * loop_vid_overlay rectangle. |
363 | */ | 367 | */ |
364 | unsigned offset = | 368 | unsigned offset = |
365 | (dev->loop_vid_overlay.left - dev->loop_vid_copy.left) * pixsize; | 369 | ((dev->loop_vid_overlay.left - dev->loop_vid_copy.left) * |
370 | twopixsize) / 2; | ||
366 | u8 *osd = vosdbuf + vid_overlay_y * stride_osd; | 371 | u8 *osd = vosdbuf + vid_overlay_y * stride_osd; |
367 | 372 | ||
368 | scale_line(voutbuf + vid_out_y * stride_out, dev->blended_line, | 373 | scale_line(voutbuf + vid_out_y * stride_out, dev->blended_line, |
@@ -372,18 +377,17 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf, | |||
372 | blend_line(dev, vid_overlay_y + dev->loop_vid_overlay.top, | 377 | blend_line(dev, vid_overlay_y + dev->loop_vid_overlay.top, |
373 | dev->loop_vid_overlay.left, | 378 | dev->loop_vid_overlay.left, |
374 | dev->blended_line + offset, osd, | 379 | dev->blended_line + offset, osd, |
375 | dev->loop_vid_overlay.width, pixsize); | 380 | dev->loop_vid_overlay.width, twopixsize / 2); |
376 | else | 381 | else |
377 | memcpy(dev->blended_line + offset, | 382 | memcpy(dev->blended_line + offset, |
378 | osd, dev->loop_vid_overlay.width * pixsize); | 383 | osd, (dev->loop_vid_overlay.width * twopixsize) / 2); |
379 | scale_line(dev->blended_line, dev->scaled_line, | 384 | scale_line(dev->blended_line, dev->scaled_line, |
380 | dev->loop_vid_copy.width, dev->loop_vid_cap.width, | 385 | dev->loop_vid_copy.width, dev->loop_vid_cap.width, |
381 | tpg_g_twopixelsize(tpg, p)); | 386 | tpg_g_twopixelsize(tpg, p)); |
382 | } | 387 | } |
383 | dev->cur_scaled_line = vid_out_y; | 388 | dev->cur_scaled_line = vid_out_y; |
384 | memcpy(vcapbuf + dev->loop_vid_cap.left * pixsize, | 389 | memcpy(vcapbuf + vid_cap_left, dev->scaled_line, |
385 | dev->scaled_line, | 390 | tpg_hdiv(tpg, p, dev->loop_vid_cap.width)); |
386 | dev->loop_vid_cap.width * pixsize); | ||
387 | 391 | ||
388 | update_vid_out_y: | 392 | update_vid_out_y: |
389 | if (osdline) { | 393 | if (osdline) { |
@@ -396,16 +400,16 @@ update_vid_out_y: | |||
396 | } | 400 | } |
397 | vid_out_y += vid_out_int_part; | 401 | vid_out_y += vid_out_int_part; |
398 | vid_out_error += vid_out_fract_part; | 402 | vid_out_error += vid_out_fract_part; |
399 | if (vid_out_error >= dev->loop_vid_cap.height) { | 403 | if (vid_out_error >= dev->loop_vid_cap.height / vdiv) { |
400 | vid_out_error -= dev->loop_vid_cap.height; | 404 | vid_out_error -= dev->loop_vid_cap.height / vdiv; |
401 | vid_out_y++; | 405 | vid_out_y++; |
402 | } | 406 | } |
403 | } | 407 | } |
404 | 408 | ||
405 | if (!blank) | 409 | if (!blank) |
406 | return 0; | 410 | return 0; |
407 | for (; y < img_height; y++, vcapbuf += stride_cap) | 411 | for (; y < img_height; y += vdiv, vcapbuf += stride_cap) |
408 | memcpy(vcapbuf, tpg->contrast_line[p], img_width * pixsize); | 412 | memcpy(vcapbuf, tpg->contrast_line[p], img_width); |
409 | return 0; | 413 | return 0; |
410 | } | 414 | } |
411 | 415 | ||
@@ -604,6 +608,12 @@ static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf) | |||
604 | bool quick = dev->bitmap_cap == NULL && dev->clipcount_cap == 0; | 608 | bool quick = dev->bitmap_cap == NULL && dev->clipcount_cap == 0; |
605 | int x, y, w, out_x = 0; | 609 | int x, y, w, out_x = 0; |
606 | 610 | ||
611 | /* | ||
612 | * Overlay support is only supported for formats that have a twopixelsize | ||
613 | * that's >= 2. Warn and bail out if that's not the case. | ||
614 | */ | ||
615 | if (WARN_ON(pixsize == 0)) | ||
616 | return; | ||
607 | if ((dev->overlay_cap_field == V4L2_FIELD_TOP || | 617 | if ((dev->overlay_cap_field == V4L2_FIELD_TOP || |
608 | dev->overlay_cap_field == V4L2_FIELD_BOTTOM) && | 618 | dev->overlay_cap_field == V4L2_FIELD_BOTTOM) && |
609 | dev->overlay_cap_field != buf->vb.v4l2_buf.field) | 619 | dev->overlay_cap_field != buf->vb.v4l2_buf.field) |
diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c index eeafb6c93c64..6c6deef3521c 100644 --- a/drivers/media/platform/vivid/vivid-vid-out.c +++ b/drivers/media/platform/vivid/vivid-vid-out.c | |||
@@ -43,7 +43,7 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f | |||
43 | unsigned p; | 43 | unsigned p; |
44 | 44 | ||
45 | for (p = vfmt->buffers; p < vfmt->planes; p++) | 45 | for (p = vfmt->buffers; p < vfmt->planes; p++) |
46 | size += dev->bytesperline_out[p] * h; | 46 | size += dev->bytesperline_out[p] * h / vfmt->vdownsampling[p]; |
47 | 47 | ||
48 | if (dev->field_out == V4L2_FIELD_ALTERNATE) { | 48 | if (dev->field_out == V4L2_FIELD_ALTERNATE) { |
49 | /* | 49 | /* |
@@ -331,7 +331,8 @@ int vivid_g_fmt_vid_out(struct file *file, void *priv, | |||
331 | for (p = fmt->buffers; p < fmt->planes; p++) { | 331 | for (p = fmt->buffers; p < fmt->planes; p++) { |
332 | unsigned stride = dev->bytesperline_out[p]; | 332 | unsigned stride = dev->bytesperline_out[p]; |
333 | 333 | ||
334 | mp->plane_fmt[0].sizeimage += stride * mp->height; | 334 | mp->plane_fmt[0].sizeimage += |
335 | (stride * mp->height) / fmt->vdownsampling[p]; | ||
335 | } | 336 | } |
336 | return 0; | 337 | return 0; |
337 | } | 338 | } |
@@ -405,7 +406,7 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv, | |||
405 | } | 406 | } |
406 | for (p = fmt->buffers; p < fmt->planes; p++) | 407 | for (p = fmt->buffers; p < fmt->planes; p++) |
407 | pfmt[0].sizeimage += (pfmt[0].bytesperline * fmt->bit_depth[p]) / | 408 | pfmt[0].sizeimage += (pfmt[0].bytesperline * fmt->bit_depth[p]) / |
408 | fmt->bit_depth[0]; | 409 | (fmt->bit_depth[0] * fmt->vdownsampling[p]); |
409 | mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; | 410 | mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; |
410 | mp->quantization = V4L2_QUANTIZATION_DEFAULT; | 411 | mp->quantization = V4L2_QUANTIZATION_DEFAULT; |
411 | if (vivid_is_svid_out(dev)) { | 412 | if (vivid_is_svid_out(dev)) { |