VIDIOC_REQBUFS: Inappropriate ioctl for device: Streaming USB camera via v4l2rtspserver and/or VLC same error

Hi All,

I am enjoying using Balena, great platform and product. I am currently having a problem with a project I am working on. I am wanting to stream/broadcast a video source from a USB capture card to a program like VLC and later other devices. I have a multicontainer project with a few services. I started with the RaspberryPi Surveillance project (using a Pi4b), did some package modifications, and pulled v4l2rtspserver from MASTER and got it working. From there I built out the project with the other containers, and it was all good. But in the last 2 weeks I started to get the following errors. For all my reading I cannot get it working anymore:

10.11.20 09:24:59 (+0100)  streaming  [INFO] Start RTSP server with -F 25 -W 1920 -H 1080 -P 8555 /dev/video0
10.11.20 09:24:59 (+0100)  streaming  2020-11-10 08:24:59,124 [INFO  ] - /app/v4l2rtspserver/v4l2wrapper/inc/logger.h:44
10.11.20 09:24:59 (+0100)  streaming    level:INFO
10.11.20 09:24:59 (+0100)  streaming  2020-11-10 08:24:59,126 [NOTICE] - /app/v4l2rtspserver/main.cpp:385
10.11.20 09:24:59 (+0100)  streaming    Version: 0.2.1-1-gb3e4c03 live555 version:2020.11.05
10.11.20 09:24:59 (+0100)  streaming  2020-11-10 08:24:59,131 [NOTICE] - /app/v4l2rtspserver/main.cpp:426
10.11.20 09:24:59 (+0100)  streaming    Create V4L2 Source.../dev/video0
10.11.20 09:24:59 (+0100)  streaming  2020-11-10 08:24:59,133 [NOTICE] - /app/v4l2rtspserver/v4l2wrapper/src/V4l2MmapDevice.cpp:49
10.11.20 09:24:59 (+0100)  streaming    Device /dev/video0
10.11.20 09:24:59 (+0100)  streaming  VIDIOC_REQBUFS: Inappropriate ioctl for device
10.11.20 09:24:59 (+0100)  streaming  2020-11-10 08:24:59,135 [NOTICE] - /app/v4l2rtspserver/v4l2wrapper/src/V4l2MmapDevice.cpp:141
10.11.20 09:24:59 (+0100)  streaming    Device /dev/video0
10.11.20 09:24:59 (+0100)  streaming  VIDIOC_STREAMOFF: Inappropriate ioctl for device
10.1

I also see problems with v4l2-ctl command in the run file not working, but I think that is due to not being able to get a video input now. Is there a way to run the v4l2 commands in the host to check the video settings?
Here is my OS video data by running this command ls /dev | grep video

root@25508ea:~# ls /dev | grep video
video0
video1
video10
video11
video12
video13
video14
video15
video16

Here is my Docker file, Docker-compose, and run file for reference.

Docker-compose:

version: "2.1"
services:
  streaming:
    build: ./Streaming
    environment:
      - UDEV=1
    privileged: true
    ports:
        - "8555:8555"
    labels:
      io.balena.features.dbus: '1'
  wifi-repeater:
    build: ./wifi
    privileged: true
    labels:
      io.balena.features.dbus: '1'

Dockerfile.template:

FROM balenalib/%%BALENA_MACHINE_NAME%%-debian:stretch
# Install deps
RUN apt-get update
RUN apt-get install -y apt-utils build-essential git gcc g++ cmake make liblog4cpp5-dev libv4l-dev liblivemedia-dev v4l-utils net-tools
RUN rm -rf /var/lib/apt/lists/*

# Install v4l2rtspserver
RUN git clone https://github.com/mpromonet/v4l2rtspserver.git /app/v4l2rtspserver \
    && ( cd /app/v4l2rtspserver && cmake . && make && make install)
# Source files
COPY ./src/ /app/
# Enable udevd so that plugged dynamic hardware devices show up in our container.
ENV UDEV=1

# Run command
CMD /bin/bash /app/run.sh

Run.sh

#!/bin/bash
set -e
V4L2_KMOD="bcm2835-v4l2"
# Configurable parameters
CAMERA_ROTATE=${CAMERA_ROTATE:-0}
RTSP_PORT=${RTSP_PORT:-8555}
FRAMERATE=${FRAMERATE:-25}
V4L2_W=${V4L2_W:-1920}
V4L2_H=${V4L2_H:-1080}
VIDEO_INPUT=${VIDEO_INPUT:-/dev/video0}
# Get the absolute script location
pushd `dirname $0` > /dev/null 2>&1
SCRIPTPATH=`pwd`
popd > /dev/null 2>&1
. $SCRIPTPATH/helpers.sh
if modprobe -n --first-time $V4L2_KMOD &> /dev/null; then
    log "Load kernel module $V4L2_KMOD..."
    modprobe $V4L2_KMOD
else
    log "Kernel module $V4L2_KMOD already loaded..."
fi
log "Video set to $VIDEO_INPUT..."
log "Rotate to $CAMERA_ROTATE..."
v4l2-ctl --device $VIDEO_INPUT --set-ctrl rotate="$CAMERA_ROTATE"
log "Rotated"
# Did the last run left hanging sockets?
if [ -z "$TIME_WAIT_INTERVAL" ]; then
    if [ -f "/proc/sys/net/ipv4/tcp_fin_timeout" ]; then
        TIME_WAIT_INTERVAL=$(cat /proc/sys/net/ipv4/tcp_fin_timeout)
    else
        TIME_WAIT_INTERVAL=60
    fi
fi
STARTTIME=$(date +%s)
ENDTIME=$(date +%s)
until [ -z "$(netstat | grep $RTSP_PORT | grep TIME_WAIT)" ]; do
    if [ $(($ENDTIME - $STARTTIME)) -le $TIME_WAIT_INTERVAL ]; then
        log WARN "Socket is in TIME_WAIT... Waiting..."
        sleep 5
        ENDTIME=$(date +%s)
    else
        log ERROR "Socket didn't get out of TIME_WAIT even after $TIME_WAIT_INTERVAL seconds. Bailing out."
        exit 1
    fi
done
log "Start RTSP server with -F $FRAMERATE -W $V4L2_W -H $V4L2_H -P $RTSP_PORT $VIDEO_INPUT"
/app/v4l2rtspserver/v4l2rtspserver -v -F $FRAMERATE -W $V4L2_W -H $V4L2_H -P $RTSP_PORT $VIDEO_INPUT

So, after this I tried to get VLC working as an alternative. But I get the same/similar errors. So it could be do to with the drivers (which is weird as it was working??)

Docker-compose:

version: "2.1"
# to get the video input use this command in the host OS: ls /dev | grep video
services:
  Streamer2:
    build: ./Streamer2
    privileged: true
    ports:
      - "8090:8090"
    labels:
      io.balena.features.dbus: '1'
  wifi-repeater:
    build: ./wifi
    privileged: true
    labels:
      io.balena.features.dbus: '1'

Dockerfile.template:

FROM balenalib/%%BALENA_MACHINE_NAME%%-debian:stretch
# Install dependencies
RUN apt-get update
RUN apt-get install build-essential vlc v4l-utils liblog4cpp5-dev libv4l-dev liblivemedia-dev

WORKDIR /usr/src/app
# This will copy all files in our root to the working  directory in the container
COPY . ./
# Enable udevd so that plugged dynamic hardware devices show up in our container.
ENV UDEV=1

# Run command
CMD /bin/bash /usr/src/app/start.sh

Start.sh

#!/bin/bash
VIDEO_INPUT=${VIDEO_INPUT:=0}
RTSP_PORT=${RTSP_PORT:=8090}
# Allow VLC to run as root
sed -i 's/geteuid/getppid/' /usr/bin/vlc
echo "Starting up on port $RTSP_PORT"
cvlc -v v4l2:///dev/video$VIDEO_INPUT --sout '#transcode{vcodec=h264,vb=800,acodec=none}:rtp{sdp=rtsp://:$RTSP_PORT/}'

But I still get the following errors.

10.11.20 10:10:13 (+0100) Starting up on port 8090
10.11.20 10:10:13 (+0100) VLC media player 3.0.11 Vetinari (revision 3.0.11-0-gdc0c5ced72)
10.11.20 10:10:13 (+0100) [0000005562b0c610] vlcpulse audio output error: PulseAudio server connection failure: Connection refused
10.11.20 10:10:13 (+0100) [0000005562b86570] dbus interface error: Failed to connect to the D-Bus session daemon: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11
10.11.20 10:10:13 (+0100) [0000005562b86570] main interface error: no suitable interface module
10.11.20 10:10:13 (+0100) [0000005562a7e8f0] main libvlc error: interface "dbus,none" initialization failed
10.11.20 10:10:13 (+0100) [0000005562b3da40] main interface error: no suitable interface module
10.11.20 10:10:13 (+0100) [0000005562a7e8f0] main libvlc error: interface "globalhotkeys,none" initialization failed
10.11.20 10:10:13 (+0100) [0000005562b3da40] dummy interface: using the dummy interface module...
10.11.20 10:10:13 (+0100) Failed to query video capabilities: Inappropriate ioctl for device
10.11.20 10:10:13 (+0100) libv4l2: error getting capabilities: Inappropriate ioctl for device
10.11.20 10:10:14 (+0100) [0000007f94005bc0] v4l2 demux warning: cannot initialize user-space library: Inappropriate ioctl for device
10.11.20 10:10:14 (+0100) [0000007f94005bc0] v4l2 demux error: cannot get device capabilities: Inappropriate ioctl for device
10.11.20 10:10:14 (+0100) Failed to query video capabilities: Inappropriate ioctl for device
10.11.20 10:10:14 (+0100) libv4l2: error getting capabilities: Inappropriate ioctl for device
10.11.20 10:10:14 (+0100) [0000007f94005bc0] v4l2 demux warning: cannot initialize user-space library: Inappropriate ioctl for device
10.11.20 10:10:14 (+0100) [0000007f94005bc0] v4l2 demux error: cannot get device capabilities: Inappropriate ioctl for device
10.11.20 10:10:14 (+0100) Failed to query video capabilities: Inappropriate ioctl for device
10.11.20 10:10:14 (+0100) libv4l2: error getting capabilities: Inappropriate ioctl for device
10.11.20 10:10:14 (+0100) [0000007f94008ec0] v4l2 stream warning: cannot initialize user-space library: Inappropriate ioctl for device
10.11.20 10:10:14 (+0100) [0000007f94008ec0] v4l2 stream error: cannot get device capabilities: Inappropriate ioctl for device
10.11.20 10:10:14 (+0100) [0000007f9c0009f0] main input error: Your input can't be opened
10.11.20 10:10:14 (+0100) [0000007f9c0009f0] main input error: VLC is unable to open the MRL 'v4l2:///dev/video0'. Check the log for details

Sorry of the long post, does anyone have an idea on how to fix or what could have caused this?

Hi @tjb, thanks for providing so much context. No need to apologize as your verbose message helps with troubleshooting.

So initially did you get camera working totally fine? Were you getting any errors before? Then, what did happen 2 weeks ago that might introduce these errors?

It’d be good to see the changes you introduced. If you have not made any changes, we could look into investigating hardware problems or perhaps a library you use introduced a breaking change in a newer version.

Searching for that error, I found this issue on the library you use. There are other posts in various forums that all point to missing kernel module. I do see the line modprobe $V4L2_KMOD in code that loads the module. Could you check out kernel logs (via dmesg | tail -n 1000) and see if there is any issue with loading this kernel?

Running lsmod | grep v4l2 in your container should also list this kernel module. Can you check that as well?

On a different note, I see that official RPi documentation recommends a different library fswebcam. Could you try it out as well to rule out a hardware issue?
(So if your camera works fine on fswebcam, we could narrow down the issue to the library you use)

Cheers…

Thanks for your reply. An interesting thing happened, I did the command sudo rm /dev/video0 as in your link in the container and it deleted video0, then I tried sudo modprobe bcm2835-v4l2 but the command would not work, and it removed video0. The some searching said to restart the device, so I restarted the systems and then it all started to work! weird.

until… it stopped. I unplugged the USB capture device to try another one and then the error started again. I think that it might delete the

I only could run lsmod | grep v4l2 in one of my containers (the streaming2 using VLC) the other container would not let me spawn a shell for some reason. I got the following:

root@25508ea:~# lsmod | grep v4l2
bcm2835_v4l2           49152  0
v4l2_mem2mem           36864  1 bcm2835_codec
bcm2835_mmal_vchiq     36864  3 bcm2835_codec,bcm2835_v4l2,bcm2835_isp
videobuf2_vmalloc      20480  2 uvcvideo,bcm2835_v4l2
videobuf2_v4l2         32768  5 bcm2835_codec,uvcvideo,bcm2835_v4l2,v4l2_mem2mem,bcm2835_isp
videobuf2_common       61440  6 bcm2835_codec,videobuf2_v4l2,uvcvideo,bcm2835_v4l2,v4l2_mem2mem,bcm2835_isp
videodev              299008  7 bcm2835_codec,videobuf2_v4l2,uvcvideo,bcm2835_v4l2,videobuf2_common,v4l2_mem2mem,bcm2835_isp
mc                     57344  8 videodev,bcm2835_codec,snd_usb_audio,videobuf2_v4l2,uvcvideo,videobuf2_common,v4l2_mem2mem,bcm2835_isp

and then the ls -al /dev/video* command:

root@25508ea:~# ls -al /dev/video*
-rwx------ 1 root root      0 Nov 10 20:24 /dev/video0
crw-rw---- 1 root video 81, 1 Nov 10 20:24 /dev/video10
crw-rw---- 1 root video 81, 4 Nov 10 20:24 /dev/video11
crw-rw---- 1 root video 81, 6 Nov 10 20:24 /dev/video12
crw-rw---- 1 root video 81, 0 Nov 10 20:24 /dev/video13
crw-rw---- 1 root video 81, 2 Nov 10 20:24 /dev/video14
crw-rw---- 1 root video 81, 3 Nov 10 20:24 /dev/video15
crw-rw---- 1 root video 81, 5 Nov 10 20:24 /dev/video16

with my kernel logs, i posted some of it below.

I went through my git history and saw that nothing changed with the original implementation, and it is weird. I would love to see if someone could replicated and see it they get the same thing.

root@25508ea:~# dmesg | tail -n 1000
[  909.297600] IPv6: ADDRCONF(NETDEV_CHANGE): veth322e5a4: link becomes ready
[  909.304757] br-547ddf7a6ad5: port 1(veth322e5a4) entered blocking state
[  909.311489] br-547ddf7a6ad5: port 1(veth322e5a4) entered forwarding state
[  909.625406] systemd-udevd[28]: starting version 232
[  909.751680] systemd-udevd[35]: could not open moddep file '/lib/modules/5.4.58/modules.dep.bin'
[  909.797734] systemd-udevd[35]: could not open moddep file '/lib/modules/5.4.58/modules.dep.bin'
[  910.955081] br-547ddf7a6ad5: port 1(veth322e5a4) entered disabled state
[  910.962085] veth731a003: renamed from eth0
[  911.024887] br-547ddf7a6ad5: port 1(veth322e5a4) entered disabled state
[  911.078523] device veth322e5a4 left promiscuous mode
[  911.083966] br-547ddf7a6ad5: port 1(veth322e5a4) entered disabled state
[  970.845524] br-547ddf7a6ad5: port 1(veth633caf3) entered blocking state
[  970.852271] br-547ddf7a6ad5: port 1(veth633caf3) entered disabled state
[  970.859249] device veth633caf3 entered promiscuous mode
[  971.719150] eth0: renamed from vetha26726b
[  971.742741] IPv6: ADDRCONF(NETDEV_CHANGE): veth633caf3: link becomes ready
[  971.750024] br-547ddf7a6ad5: port 1(veth633caf3) entered blocking state
[  971.756795] br-547ddf7a6ad5: port 1(veth633caf3) entered forwarding state
[  972.071501] systemd-udevd[29]: starting version 232
[  972.195760] systemd-udevd[35]: could not open moddep file '/lib/modules/5.4.58/modules.dep.bin'
[  972.293067] systemd-udevd[35]: could not open moddep file '/lib/modules/5.4.58/modules.dep.bin'
[  973.463117] br-547ddf7a6ad5: port 1(veth633caf3) entered disabled state
[  973.470105] vetha26726b: renamed from eth0
[  973.541483] br-547ddf7a6ad5: port 1(veth633caf3) entered disabled state
[  973.596641] device veth633caf3 left promiscuous mode
[  973.601728] br-547ddf7a6ad5: port 1(veth633caf3) entered disabled state
[ 1033.349144] br-547ddf7a6ad5: port 1(veth63f3d7e) entered blocking state
[ 1033.355909] br-547ddf7a6ad5: port 1(veth63f3d7e) entered disabled state
[ 1033.363052] device veth63f3d7e entered promiscuous mode
[ 1034.276758] eth0: renamed from veth83d6814

Another day, another change. I did some testing and I found something interesting. After deleting /dev/video0, it looks like there is an issue of not recognizing the device. If I do a full restart of the device, the error goes away and the stream starts working. BUT, if I disconnect the device from the USB, the error returns (logical), but if I plug it back in then the error stays. I thought it was a service thing and could go away with a service restart, (the error VIDIOC_REQBUFS: Inappropriate ioctl for device), but it stays until I do a full restart of the device. any thoughts?

Hello @tjb

Looking at the directory listing in your previous message I can see that the /dev/video0 device is an ordinary file and not a device node. I am wondering whether the USB camera is occasionally being registered as a different device on boot or after a USB connection glitch. As far as I can see the video application defaults to using /dev/video0. If this was absent it would explain why the ioctl calls are failing. It looks like your actual video devices are on /dev/video10 to /dev/video16. If the video device does keep changing then it might be possible to assign it as a persistent device using a udev rule.

Thanks @markcorbinuk. As I listed above, after a reboot of the device it works, but if I unplug or swap a device then the system cannot connect to /dev/video0. you could be right that it could change to a difference device. I did run the the ls -al /dev/video* command and /dev/video0 does show up.

How do you assign it as a persistent device using a udev rule? I can try that and report back. Note, i also have other USB devices plugged in for communications, but they just show up as a communication device.

Hi Tim, One approach to get a persistent reference to the device would be to create a symlink with a udev rule.

There’s an example of that with steps here, which should be similar to your case:

The basic steps are:

Identify vendor and product ids for the device (and optionally serial number)
Add udev rule (or edit existing) in /etc/udev/rules.d/ to add symlink (note that the rules are run in alpha-numerial order, so best to start the filename with a high number like 90 or 99) - see the link for the format for that
Reload rules with sudo udevadm control --reload-rules (or restart)

Hi @srlowe, great thanks! Do I do this setup in the dockerfile or the script? for example, in you link you sent, I got the following information. it looks like it if I plug the device in (after the service is running) it goes to /dev/video1, but if I reboot it goes to /dev/video0, so this will really help with the links.

root@25508ea:~# udevadm info --query=all --attribute-walk --name=/dev/video1 | grep -E "idVendor|serial|idProduct"
    ATTRS{serial}=="20150130"
    ATTRS{idProduct}=="0021"
    ATTRS{idVendor}=="534d"
    ATTRS{idVendor}=="2109"
    ATTRS{idProduct}=="3431"
    ATTRS{serial}=="0000:01:00.0"
    ATTRS{idVendor}=="1d6b"
    ATTRS{idProduct}=="0002"

Hi Tim,

You can set the rule in a file in your repository and copy the file to /etc/udev/rules.d. You can see find some more documentation here

And see an example in this repo