The patch number 14269 was added via h...@rhel5-devel.localdomain to http://linuxtv.org/hg/v4l-dvb master development tree.
Kernel patches in this development tree may be modified to be backward compatible with older kernels. Compatibility modifications will be removed before inclusion into the mainstream Kernel If anyone has any objections, please let us know by sending a message to: Linux Media Mailing List <linux-me...@vger.kernel.org> ------ From: Hans de Goede <hdego...@redhat.com> libv4l: Add error checking to mr97310a decompression Add error checking to mr97310a decompression, and upon receival of 3 consecutive short frames, tell the driver (through the custom minimum clockdiv control) to increase the minimum clockdiv and thus lower the framerate as the cams compression engine is not keeping up with the data. Priority: normal Signed-off-by: Hans de Goede <hdego...@redhat.com> --- v4l2-apps/libv4l/ChangeLog | 2 v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h | 6 + v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 7 +- v4l2-apps/libv4l/libv4lconvert/mr97310a.c | 42 ++++++++++-- 4 files changed, 51 insertions(+), 6 deletions(-) diff -r e0e01333ecc5 -r 400a00849bdb v4l2-apps/libv4l/ChangeLog --- a/v4l2-apps/libv4l/ChangeLog Mon Oct 26 09:45:43 2009 +0100 +++ b/v4l2-apps/libv4l/ChangeLog Fri Oct 30 09:17:01 2009 +0100 @@ -1,6 +1,8 @@ libv4l-0.6.4 ------------ * Add more laptop models to the upside down devices table +* Add error checking to mr97310a decompression +* Increase mr97310a minimum clockdiv upon 3 consecutive decoding errors libv4l-0.6.3 ------------ diff -r e0e01333ecc5 -r 400a00849bdb v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h Mon Oct 26 09:45:43 2009 +0100 +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h Fri Oct 30 09:17:01 2009 +0100 @@ -149,6 +149,9 @@ pid_t decompress_pid; int decompress_in_pipe[2]; /* Data from helper to us */ int decompress_out_pipe[2]; /* Data from us to helper */ + + /* For mr97310a decoder */ + int frames_dropped; }; struct v4lconvert_pixfmt { @@ -228,7 +231,8 @@ const unsigned char *inp, int src_size, unsigned char *outp, int width, int height); -void v4lconvert_decode_mr97310a(const unsigned char *src, unsigned char *dst, +int v4lconvert_decode_mr97310a(struct v4lconvert_data *data, + const unsigned char *src, int src_size, unsigned char *dst, int width, int height); void v4lconvert_decode_sn9c2028(const unsigned char *src, unsigned char *dst, diff -r e0e01333ecc5 -r 400a00849bdb v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c Mon Oct 26 09:45:43 2009 +0100 +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c Fri Oct 30 09:17:01 2009 +0100 @@ -762,7 +762,12 @@ tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8; break; case V4L2_PIX_FMT_MR97310A: - v4lconvert_decode_mr97310a(src, tmpbuf, width, height); + if (v4lconvert_decode_mr97310a(data, src, src_size, tmpbuf, + width, height)) { + /* Corrupt frame, better get another one */ + errno = EAGAIN; + return -1; + } tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8; break; case V4L2_PIX_FMT_SN9C2028: diff -r e0e01333ecc5 -r 400a00849bdb v4l2-apps/libv4l/libv4lconvert/mr97310a.c --- a/v4l2-apps/libv4l/libv4lconvert/mr97310a.c Mon Oct 26 09:45:43 2009 +0100 +++ b/v4l2-apps/libv4l/libv4lconvert/mr97310a.c Fri Oct 30 09:17:01 2009 +0100 @@ -19,10 +19,14 @@ * Boston, MA 02111-1307, USA. */ +#include <unistd.h> #include "libv4lconvert-priv.h" +#include "libv4lsyscall-priv.h" #define CLIP(x) ((x)<0?0:((x)>0xff)?0xff:(x)) +#define MIN_CLOCKDIV_CID V4L2_CID_PRIVATE_BASE + /* FIXME not threadsafe */ static int decoder_initialized = 0; @@ -90,20 +94,22 @@ return (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); } -void v4lconvert_decode_mr97310a(const unsigned char *inp, unsigned char *outp, - int width, int height) +int v4lconvert_decode_mr97310a(struct v4lconvert_data *data, + const unsigned char *inp, int src_size, + unsigned char *outp, int width, int height) { int row, col; int val; int bitpos; unsigned char code; unsigned char lp, tp, tlp, trp; + struct v4l2_control min_clockdiv = { .id = MIN_CLOCKDIV_CID }; if (!decoder_initialized) init_mr97310a_decoder(); /* remove the header */ - inp += 12; + inp += 12; bitpos = 0; @@ -169,6 +175,34 @@ *outp++ = CLIP(val); ++col; } + + /* src_size - 12 because of 12 byte footer */ + if (((bitpos - 1) / 8) >= (src_size - 12)) { + data->frames_dropped++; + if (data->frames_dropped == 3) { + /* Tell the driver to go slower as + the compression engine is not able to + compress the image enough, we may + fail to do this because older + drivers don't support this */ + SYS_IOCTL(data->fd, VIDIOC_G_CTRL, + &min_clockdiv); + min_clockdiv.value++; + SYS_IOCTL(data->fd, VIDIOC_S_CTRL, + &min_clockdiv); + /* We return success here, because if we + return failure for too many frames in a row + libv4l2 will return an error to the + application and some applications abort + on the first error received. */ + data->frames_dropped = 0; + return 0; + } + V4LCONVERT_ERR("incomplete mr97310a frame\n"); + return -1; + } } - return; + + data->frames_dropped = 0; + return 0; } --- Patch is available at: http://linuxtv.org/hg/v4l-dvb/rev/400a00849bdb4274791ab40b48552101cf7cc8a9 _______________________________________________ linuxtv-commits mailing list linuxtv-commits@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits