aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-driver.c
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2009-11-09 21:55:30 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-05 15:41:52 -0500
commit22dce188ef3e1e058ceabe3b3072640d7568f764 (patch)
tree6a5ee29e5b7cdf9125bea7456c8de75ab0861b92 /drivers/media/video/cx18/cx18-driver.c
parent52fcb3ecc6707f52dfe4297f96b7609d4ba517fb (diff)
V4L/DVB (13430): cx18: Fix YUV capture so that encoder passes a single frame per transfer
Fix YUV capture such that the encoder will pass one frame per transfer. This will allow the application to maintain frame alignment when a transfer from the encoder is missed due to high system latency in service the CX23418 IRQ. Also force YUV buffer sizes to be specified in multiples of 33.75 kB, the smalled amount of buffer sizes need to store a complete set of HM12 4:2:0 macroblocks specifying 32 lines of the frame. A full 60Hz/525 line screen requires 15 * 33.75 kB per frame and a full 50Hz/625 line screen requires 18 * 33.75 kB per frame so the default buffer size is 3 * 33.75 kB, requiring exactly 5 or 6 buffers per MDL respectively. The bytes needed per frame and hence MDL need not be the bytes in an integer number of buffers. However, if frame artifacts are seen with scaled screen sizes, the YUV buffer size can be set 34 kB (33.75 kB) to get rid of the artifacts at the cost of more copies between the kernel and userspace. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18/cx18-driver.c')
-rw-r--r--drivers/media/video/cx18/cx18-driver.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index ba4c3ceffbb3..87a735f1ee9e 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -211,7 +211,9 @@ MODULE_PARM_DESC(enc_yuv_buffers,
211 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS)); 211 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS));
212MODULE_PARM_DESC(enc_yuv_bufsize, 212MODULE_PARM_DESC(enc_yuv_bufsize,
213 "Size of an encoder YUV buffer (kB)\n" 213 "Size of an encoder YUV buffer (kB)\n"
214 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFSIZE)); 214 "\t\t\tAllowed values are multiples of 33.75 kB rounded up\n"
215 "\t\t\t(multiples of size required for 32 screen lines)\n"
216 "\t\t\tDefault: 102");
215MODULE_PARM_DESC(enc_yuv_bufs, 217MODULE_PARM_DESC(enc_yuv_bufs,
216 "Number of encoder YUV buffers\n" 218 "Number of encoder YUV buffers\n"
217 "\t\t\tDefault is computed from other enc_yuv_* parameters"); 219 "\t\t\tDefault is computed from other enc_yuv_* parameters");
@@ -499,10 +501,27 @@ static void cx18_process_options(struct cx18 *cx)
499 continue; 501 continue;
500 } 502 }
501 /* 503 /*
504 * YUV is a special case where the stream_buf_size needs to be
505 * an integral multiple of 33.75 kB (storage for 32 screens
506 * lines to maintain alignment in case of lost buffers
507 */
508 if (i == CX18_ENC_STREAM_TYPE_YUV) {
509 cx->stream_buf_size[i] *= 1024;
510 cx->stream_buf_size[i] -=
511 (cx->stream_buf_size[i] % CX18_UNIT_ENC_YUV_BUFSIZE);
512
513 if (cx->stream_buf_size[i] < CX18_UNIT_ENC_YUV_BUFSIZE)
514 cx->stream_buf_size[i] =
515 CX18_UNIT_ENC_YUV_BUFSIZE;
516 }
517 /*
518 * YUV is a special case where the stream_buf_size is
519 * now in bytes.
502 * VBI is a special case where the stream_buf_size is fixed 520 * VBI is a special case where the stream_buf_size is fixed
503 * and already in bytes 521 * and already in bytes
504 */ 522 */
505 if (i == CX18_ENC_STREAM_TYPE_VBI) { 523 if (i == CX18_ENC_STREAM_TYPE_VBI ||
524 i == CX18_ENC_STREAM_TYPE_YUV) {
506 if (cx->stream_buffers[i] < 0) { 525 if (cx->stream_buffers[i] < 0) {
507 cx->stream_buffers[i] = 526 cx->stream_buffers[i] =
508 cx->options.megabytes[i] * 1024 * 1024 527 cx->options.megabytes[i] * 1024 * 1024
@@ -513,18 +532,24 @@ static void cx18_process_options(struct cx18 *cx)
513 cx->stream_buffers[i] 532 cx->stream_buffers[i]
514 * cx->stream_buf_size[i]/(1024 * 1024); 533 * cx->stream_buf_size[i]/(1024 * 1024);
515 } 534 }
516 continue;
517 }
518 /* All other streams have stream_buf_size in kB at this point */
519 if (cx->stream_buffers[i] < 0) {
520 cx->stream_buffers[i] = cx->options.megabytes[i] * 1024
521 / cx->stream_buf_size[i];
522 } else { 535 } else {
523 /* N.B. This might round down to 0 */ 536 /* All other streams have stream_buf_size in kB here */
524 cx->options.megabytes[i] = 537 if (cx->stream_buffers[i] < 0) {
525 cx->stream_buffers[i] * cx->stream_buf_size[i] / 1024; 538 cx->stream_buffers[i] =
539 cx->options.megabytes[i] * 1024
540 / cx->stream_buf_size[i];
541 } else {
542 /* N.B. This might round down to 0 */
543 cx->options.megabytes[i] =
544 cx->stream_buffers[i]
545 * cx->stream_buf_size[i] / 1024;
546 }
547 /* convert from kB to bytes */
548 cx->stream_buf_size[i] *= 1024;
526 } 549 }
527 cx->stream_buf_size[i] *= 1024; /* convert from kB to bytes */ 550 CX18_DEBUG_INFO("Stream type %d options: %d MB, %d buffers, "
551 "%d bytes\n", i, cx->options.megabytes[i],
552 cx->stream_buffers[i], cx->stream_buf_size[i]);
528 } 553 }
529 554
530 cx->options.cardtype = cardtype[cx->instance]; 555 cx->options.cardtype = cardtype[cx->instance];