diff options
author | Andy Walls <awalls@radix.net> | 2009-11-09 21:55:30 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 15:41:52 -0500 |
commit | 22dce188ef3e1e058ceabe3b3072640d7568f764 (patch) | |
tree | 6a5ee29e5b7cdf9125bea7456c8de75ab0861b92 /drivers/media/video/cx18/cx18-driver.c | |
parent | 52fcb3ecc6707f52dfe4297f96b7609d4ba517fb (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.c | 49 |
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)); |
212 | MODULE_PARM_DESC(enc_yuv_bufsize, | 212 | MODULE_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"); | ||
215 | MODULE_PARM_DESC(enc_yuv_bufs, | 217 | MODULE_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]; |