V4L Test Suite

From LinuxTVWiki
Revision as of 23:44, 22 November 2008 by CityK (talk | contribs) (Test Suite moved to V4L Test Suite: name)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Code to test other code.

If you need a test, look here.

If you create a new test, add it here.

If you know of a test that is not listed, please add it.

Stable Starting Point

It seems the 2 V4L2 examples (capture.c and vivi.c) don't play well with each other. I am not really sure where to post about this, so I will start here and move it to the appropriate place once I find it. so far http://bugzilla.kernel.org seems the most likely. I am dumping my notes at the bottom of this page to try to keep the point of this page from getting buried.

Test Driver

VIVI - Virtual Video Driver

A real v4l2 device driver with no physical hardware. This means anyone can use it (it is part of the Linux kernel: modprobe vivi).

If your application has problems with a specific device driver, try using vivi instead. If you still have a problem, it is much more likely to be a problem with the application than with the driver. Knowing where to look is a big help in fixing problems.

However, vivi is not

  • perfect. Not surprising given it doesn't get the amount of real world use that real drivers do.
  • feature complete. It does not implement every interface of the v4l2 spec.

But it is something anyone can run, so it makes reproducing some problems possible that would otherwise be impossible without the specific hardware.

Test applications

Simple programs that test various functionality of a driver.

There are many small test apps that seem to have been written to help isolate an existing problem, as opposed to actively looking for problems. This means the tests make assumptions about what is/isn't supported, which can cause false problems when someone else uses them in a different environment. For instance, a test should not be run unless the driver advertises suppport for it. This means all tests should first xioctl(fd, VIDIOC_QUERYCAP, &cap) and test cap.capabilities to see if the rest of the test is applicable. (note I said 'should' - This does not mean you shouldn't post your test code it it does not comply - something is better than nothing.)



The utilities in the test/ directory of the zvbi tarball, available on zvbi's project page;

http://code.google.com/p/python-video4linux2/ - starting to build a tester using that.

http://v4l2spec.bytesex.org/spec/a16706.htm Appendix B. Video Capture Example - not exactly a tester, but worth listing. latest: http://linuxtv.org/hg/~hverkuil/v4l-dvb-media2/file/7ff930a1268f/v4l2-apps/test/capture_example.c


Bugs in Examples

capture.c and vivi.c are V4L2 examples:

capture: "Video for Linux Two API Specification: Revision 0.24 Appendix B. Video Capture Example"

vivi: "It is intended to be a working example code for current V4L2 Driver and Stub driver to facilitate the implementation of new video drivers.

They don't play well with each other. There is a memory leak, and I think vivi is telling capture to use a buffer mode that isn't valid - I call this "capabilities mismatch" but I am not really sure what the problem is.


detailed report: "vivi memory leak = kernel panic" https://bugs.launchpad.net/ubuntu/+source/linux/+bug/294951

memory leak
sudo modprobe vivi
gcc capture.c -g -o capture
valgrind ./capture --userp -d /dev/video1
==17153== malloc/free: in use at exit: 2,457,632 bytes in 5 blocks.
capabilities mismatch
./capture --userp -d /dev/video1
VIDIOC_QBUF error 22, Invalid argument


setup for both: (capture.c is the original, same problem with capture_example.c, see URL above)

wget http://www.linuxtv.org/downloads/video4linux/API/V4L2_API/v4l2spec/capture.c
gcc capture.c -g -o capture
sudo modprobe vivi
dmesg | grep /dev/video1
[ 1015.491550] vivi: V4L2 device registered as /dev/video1
memory leak
# memleak.sh
# runs capture to cause "Cannot allocate memory"
# and logs /proc/meminfo along the way

set -x

sudo modprobe vivi
dmesg|grep vivi

# make sure the above grep matchs:

if [ -d proc ]; then
  # wipe out previous run
  rm -f proc/meminfo*
  # make a place to log proc/meminfo
  mkdir proc

# 0.0 = start
let a=0
cp /proc/meminfo proc/meminfo$a.0.txt

# loop until "Cannot allocate memory"
while true; do


  # run using valid params, therefore should not error.
  ./capture --read -d $DEV
  # unless something has sucked all the memory from somewhere.
  if [ "0" != "$?" ]; then break; fi
  # shouldn't be anything interesting, but log the state, just to be sure.
  cp /proc/meminfo proc/meminfo$a.1.txt
  # run with unsupported buffer mode
  ./capture --userp -d $DEV
  # which didn't release memory from who knows where, so log the state:
  cp /proc/meminfo proc/meminfo$a.2.txt


# x.3 = final state.  should be about the same as x.2
cp /proc/meminfo proc/meminfo$a.3.txt

resulting data: http://spreadsheets.google.com/ccc?key=pIfz0wOzPtW1-oZkXXbvcLA&hl=en

The runaways: HighFree go from 72608 to 252 VmallocUsed from 6440 to 109724 VmallocChunk from 103620 to 336

Using valgrind (a suite of tools for debugging and profiling programs)

 valgrind -v --leak-check=full --show-reachable=yes ./capture --userp -d /dev/video1
 ==5166== Memcheck, a memory error detector.
 ==5166== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
 ==5166== Using LibVEX rev 1854, a library for dynamic binary translation.
 ==5166== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
 ==5166== Using valgrind-3.3.1-Debian, a dynamic binary instrumentation framework.
 ==5166== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
 --5166-- Command line
 --5166--    ./capture
 --5166--    --userp
 --5166--    -d
 --5166--    /dev/video1
 --5166-- Startup, with flags:
 --5166--    --suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp
 --5166--    -v
 --5166--    --leak-check=full
 --5166--    --show-reachable=yes
 --5166-- Contents of /proc/version:
 --5166--   Linux version 2.6.27-7-generic (buildd@palmer) (gcc version 4.3.2
 (Ubuntu 4.3.2-1ubuntu11) ) #1 SMP Thu Oct 30 04:18:38 UTC 2008
 --5166-- Arch and hwcaps: X86, x86-sse1-sse2
 --5166-- Page sizes: currently 4096, max supported 4096
 --5166-- Valgrind library directory: /usr/lib/valgrind
 --5166-- Reading syms from /lib/ld-2.8.90.so (0x4000000)
 --5166-- Reading debug info from /lib/ld-2.8.90.so...
 --5166-- ... CRC mismatch (computed 371b8ee6 wanted cc0a418a)
 --5166-- Reading debug info from /usr/lib/debug/lib/ld-2.8.90.so...
 --5166-- Reading syms from /home/juser/vga2usb/v4l.org/examples/capture (0x8048000)
 --5166-- Reading syms from /usr/lib/valgrind/x86-linux/memcheck (0x38000000)
 --5166--    object doesn't have a dynamic symbol table
 --5166-- Reading suppressions file: /usr/lib/valgrind/debian-libc6-dbg.supp
 --5166-- Reading suppressions file: /usr/lib/valgrind/default.supp
 --5166-- REDIR: 0x40155d0 (index) redirected to 0x3802cf63
 --5166-- Reading syms from /usr/lib/valgrind/x86-linux/vgpreload_core.so (0x401F000)
 --5166-- Reading syms from /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so
 ==5166== WARNING: new redirection conflicts with existing -- ignoring it
 --5166--     new: 0x040155d0 (index               ) R-> 0x040261a0 index
 --5166-- REDIR: 0x40157c0 (strlen) redirected to 0x4026450 (strlen)
 --5166-- Reading syms from /usr/lib/debug/libc-2.8.90.so (0x402A000)
 --5166-- REDIR: 0x409d2f0 (rindex) redirected to 0x4026080 (rindex)
 --5166-- REDIR: 0x409cf00 (strlen) redirected to 0x4026430 (strlen)
 --5166-- REDIR: 0x409d110 (strncmp) redirected to 0x40266a0 (strncmp)
 --5166-- REDIR: 0x409c7e0 (index) redirected to 0x4026170 (index)
 --5166-- REDIR: 0x409df70 (memset) redirected to 0x4027340 (memset)
 --5166-- REDIR: 0x4099c50 (calloc) redirected to 0x4023d20 (calloc)
 --5166-- REDIR: 0x409a190 (memalign) redirected to 0x4023b80 (memalign)
 --5166-- REDIR: 0x409e490 (memcpy) redirected to 0x40268a0 (memcpy)
 --5166-- REDIR: 0x409e180 (stpcpy) redirected to 0x40270d0 (stpcpy)
 --5166-- REDIR: 0x409dfd0 (mempcpy) redirected to 0x4027470 (mempcpy)
 --5166-- REDIR: 0x409f010 (strchrnul) redirected to 0x4027410 (strchrnul)
 VIDIOC_QBUF error 22, Invalid argument
 --5166-- REDIR: 0x4097730 (free) redirected to 0x4024a90 (free)
 ==5166== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 1)
 --5166-- supp:     11 dl-hack3-cond-1
 ==5166== malloc/free: in use at exit: 2,457,632 bytes in 5 blocks.
 ==5166== malloc/free: 5 allocs, 0 frees, 2,457,632 bytes allocated.
 ==5166== searching for pointers to 5 not-freed blocks.
 ==5166== checked 51,772 bytes.
 ==5166== 32 bytes in 1 blocks are still reachable in loss record 1 of 2
 ==5166==    at 0x4023DE2: calloc (vg_replace_malloc.c:397)
 ==5166==    by 0x80494AF: init_userp (in
 ==5166==    by 0x80498B0: init_device (in
 ==5166==    by 0x8049B63: main (in /home/juser/vga2usb/v4l.org/examples/capture)
 ==5166== 2,457,600 bytes in 4 blocks are still reachable in loss record 2 of 2
 ==5166==    at 0x4023C4A: memalign (vg_replace_malloc.c:460)
 ==5166==    by 0x8049536: init_userp (in
 ==5166==    by 0x80498B0: init_device (in
 ==5166==    by 0x8049B63: main (in /home/juser/vga2usb/v4l.org/examples/capture)
 ==5166== LEAK SUMMARY:
 ==5166==    definitely lost: 0 bytes in 0 blocks.
 ==5166==      possibly lost: 0 bytes in 0 blocks.
 ==5166==    still reachable: 2,457,632 bytes in 5 blocks.
 ==5166==         suppressed: 0 bytes in 0 blocks.
 --5166--  memcheck: sanity checks: 0 cheap, 1 expensive
 --5166--  memcheck: auxmaps: 0 auxmap entries (0k, 0M) in use
 --5166--  memcheck: auxmaps_L1: 0 searches, 0 cmps, ratio 0:10
 --5166--  memcheck: auxmaps_L2: 0 searches, 0 nodes
 --5166--  memcheck: SMs: n_issued      = 10 (160k, 0M)
 --5166--  memcheck: SMs: n_deissued    = 0 (0k, 0M)
 --5166--  memcheck: SMs: max_noaccess  = 65535 (1048560k, 1023M)
 --5166--  memcheck: SMs: max_undefined = 34 (544k, 0M)
 --5166--  memcheck: SMs: max_defined   = 20 (320k, 0M)
 --5166--  memcheck: SMs: max_non_DSM   = 10 (160k, 0M)
 --5166--  memcheck: max sec V bit nodes:    0 (0k, 0M)
 --5166--  memcheck: set_sec_vbits8 calls: 0 (new: 0, updates: 0)
 --5166--  memcheck: max shadow mem size:   464k, 0M
 --5166-- translate:            fast SP updates identified: 1,933 ( 89.4%)
 --5166-- translate:   generic_known SP updates identified: 128 (  5.9%)
 --5166-- translate: generic_unknown SP updates identified: 100 (  4.6%)
 --5166--     tt/tc: 4,312 tt lookups requiring 4,351 probes
 --5166--     tt/tc: 4,312 fast-cache updates, 3 flushes
 --5166--  transtab: new        2,035 (43,121 -> 617,673; ratio 143:10) [0 scs]
 --5166--  transtab: dumped     0 (0 -> ??)
 --5166--  transtab: discarded  8 (200 -> ??)
 --5166-- scheduler: 25,512 jumps (bb entries).
 --5166-- scheduler: 0/2,355 major/minor sched events.
 --5166--    sanity: 1 cheap, 1 expensive checks.
 --5166--    exectx: 769 lists, 8 contexts (avg 0 per list)
 --5166--    exectx: 16 searches, 8 full compares (500 per 1000)
 --5166--    exectx: 4 cmp2, 26 cmp4, 0 cmpAll
 --5166--  errormgr: 8 supplist searches, 271 comparisons during search
 --5166--  errormgr: 11 errlist searches, 26 comparisons during search

from v4l list Andy Walls:

It looks like init_userp() allocated a bunch of "buffers", which has to happen for a program to use user pointer mode of v4l2. The function errno_exit() doesn't bother to clean up when the VIDIOC_QBUF ioctl() call fails. free() is only called by uninit_device(). Since the alternate flow of the program through errno_exit() to termination doesn't call free() on "buffers", you should have a process heap memory leak on error exit.

program didn't close it's file descriptors with the driver on errno_exit()

capabilities mismatch

Looking at the source, capture.c should have reported "does not support user pointer" by:

411 init_userp                      (unsigned int           buffer_size)
421     req.count               = 4;
       req.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
       req.memory              = V4L2_MEMORY_USERPTR;
427        if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) {
               if (EINVAL == errno) {
                       fprintf (stderr, "%s does not support "
                                "user pointer i/o\n", dev_name);
                       exit (EXIT_FAILURE);

But instead it errors here:

250 start_capturing                 (void)
260        case IO_METHOD_USERPTR:
                       if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
                               errno_exit ("VIDIOC_QBUF");

Canonical source of capture and vivi