Actually I've succeed with streaming of h264 video with ffmpeg.
I was able to do this with help from ffmpeg-user list, especially from Carl Eugen Hoyos, author of this patch:
diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
index cd6aeb2..c3f813d 100644
--- a/libavdevice/v4l2.c
+++ b/libavdevice/v4l2.c
@@ -150,6 +150,7 @@ static struct fmt_map fmt_conversion_table[] = {
{ AV_PIX_FMT_NV12, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_NV12 },
{ AV_PIX_FMT_NONE, AV_CODEC_ID_MJPEG, V4L2_PIX_FMT_MJPEG },
{ AV_PIX_FMT_NONE, AV_CODEC_ID_MJPEG, V4L2_PIX_FMT_JPEG },
+ { AV_PIX_FMT_NONE, AV_CODEC_ID_H264, V4L2_PIX_FMT_H264 },
#ifdef V4L2_PIX_FMT_CPIA1
{ AV_PIX_FMT_NONE, AV_CODEC_ID_CPIA, V4L2_PIX_FMT_CPIA1 },
#endif
Actual command I've used:
./ffmpeg -f video4linux2 -s 640x480 -r 15 -vcodec h264 -i /dev/video0 -an http://localhost:8099/feed1.ffm
But I wasn't able to get rid of transcoding, so I switched to vlc (and succeed).
It's by design. First, let it be said that multiple processes can open the /dev/video0 device, but only one of them will be able to issue certain controls (ioctl()) until streaming starts.
Those V4L2 controls define things like bitrate. After you start streaming, the kernel will not let you change them and returns EBUSY
(Device or resource busy) if you try. See this note in the kernel source. That effectively blocks other consumers, since you should set those before you start streaming.
What does v4l2loopback do differently? It adds logic and data structures for multiple openers and by default will not try to apply new controls by provinding its own setter.
Note that v4l2loopback needs to have multiple openers, at least two to be useful. One reader and one writer.
Best Answer
Based on this AU Q&A titled: Is there any way ffmpeg send video to /dev/video0 on Ubuntu? you can do the following: