aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/vivid
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2015-03-09 11:06:27 -0400
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-04-02 19:55:12 -0400
commit1f9f23f62fb46d6cef93febe57bf41fb21fd01fa (patch)
treebfba8aa8d5f56dff9343289e128b0393aacdd56c /drivers/media/platform/vivid
parentddcaee9dd4c00174db8ddf913c87ddf3773c446e (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.c68
-rw-r--r--drivers/media/platform/vivid/vivid-vid-out.c7
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
388update_vid_out_y: 392update_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)) {