Talk:V4L Test Suite

From LinuxTVWiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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 on this page to try to keep the point of the article page from getting buried.


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.

Summary

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

Detail

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:
DEV=/dev/video0

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

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

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

  ((a+=1))

  # 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

done

# 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==
 --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
 (vgPlain_x86_linux_REDIR_FOR_index)
 --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
 (0x4022000)
 ==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==
 ==5166== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 1)
 --5166--
 --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==
 ==5166== searching for pointers to 5 not-freed blocks.
 ==5166== checked 51,772 bytes.
 ==5166==
 ==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
 /home/juser/vga2usb/v4l.org/examples/capture)
 ==5166==    by 0x80498B0: init_device (in
 /home/juser/vga2usb/v4l.org/examples/capture)
 ==5166==    by 0x8049B63: main (in /home/juser/vga2usb/v4l.org/examples/capture)
 ==5166==
 ==5166==
 ==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
 /home/juser/vga2usb/v4l.org/examples/capture)
 ==5166==    by 0x80498B0: init_device (in
 /home/juser/vga2usb/v4l.org/examples/capture)
 ==5166==    by 0x8049B63: main (in /home/juser/vga2usb/v4l.org/examples/capture)
 ==5166==
 ==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