It is a requirement that Motion maintains full V4L v.1 compatibility and Motion should try V4L2 first and revert to V4L1 if the driver does not support V4L2. Motion should not be compiled for either or. I (KennethLavrsen) want to be able to make an RPM that can do both.

videodev.h

"Macros and defines specifying V4L2 ioctl requests are located in the videodev.h header file. Applications should use their own copy, not include the version in the kernel sources on the system they compile on."

Motion currently doesn't ship with videodev.h. Any reason it shouldn't?

Discussion

I need your opinions! There is a difference between v4l1 and v4l2 wrt tuners. The old v4l1 spec says "Each video input channel can have one or more tuners associated with it." Also, the tuner is switchable via the VIDIOCSTUNER. In v4l2, however, "Video input devices can have one or more tuners demodulating a RF signal. Each tuner is associated with one or more video inputs, depending on the number of RF connectors on the tuner." Thus, the tuner cannot be set (not even via VIDIOC_S_TUNER - it only changes tuner properties), but is entirely controlled via the input setting.

To summarize:

In v4l1, we can set the tuner number.

In v4l2, we cannot set the tuner number.

So, the question is: should we support setting the tuner number or not? It would only work in v4l1, but most drivers today support v4l2, which will be the first choice for Motion. In other words, it is unlikely that a tuner parameter will work as the user expects it to.

I agree with your suggestion. We do not support tuner number today in Motion and noone has asked for it. I assume that newer capture cards with more tuners will be of a newer kind and with V4L2 support.

Outline

I've been working on the v4l2 code off and on for a while now. Yesterday, I pulled myself together and merged all the code I had lying around. Before creating and submitting a patch, I want to share the details of the new code:

video.c

Most of the functionality in video.c will be moved to other files. The video stub functions ( vid_start etc.) will be kept, as will the vloopback functions. Basically, vid_start will determine which input source to use, based on config options and compile-time flags. It will setup a function pointer struct, which subsequently will be used in vid_next and vid_close. This means that the selection of input path will only happen in one place.

This allows for a future translation into a plugin architecture (see below), in that the vid_* functions are very small and only call other functions.

v4l part

The v4l input source consists of a "frontend" containing the main logic, including roundrobin functionality. It calls a "backend" with is either v4l1 or v4l2, depending on what the driver supports, which talks to the driver. There is an API towards the backend, and my intention is that the FreeBSD v4l code should be moved into a backend as well (see below).

Note that I only use the terms frontend and backend here for clarity (separation of logic and driver-specific code). In a future plugin architecture, the frontend and all backends make up one single plugin.

The palette conversion functions are moved into a separate file and called from the v4l logic part. The conversion functionality will be constructed in a way that makes it very easy to add support for new palettes.

FreeBSD, ffmpeg open and gstreamer

I think the FreeBSD v4l code should be moved into a "backend" of the v4l input source. The selection of FreeBSD backend will then take place in the v4l logic, using an #ifdef. This should eliminate the need for video_freebsd.c, and would simplify the Makefile a bit.

The ffmpeg open functionality is neat, as it enables the use of an arbitrary video file as input source. The selection of this input source should be in vid_start in video.c. It should be configurable, but it could also act as a fallback if neither v4l1 or v4l2 is supported by the driver.

The gstreamer functionality is also useful, and the selection of it as input source should be take place in vid_start. The gstreamer functionality provides v4l2 support, but is more of a complement to the "pure" v4l2 code in the v4l input source.

Plugin architecture

As pointed out above, by moving code our of video.c, and only keeping function calls in the vid_* functions, it should be easy to move to a plugin architecture in the future. In my mind, the plugin loading (for input plugins) takes place in video.c, which means that the interface towards the internals of Motion is kept the same.

I'm with you the way to integrate v4l2 in motion keeping in video.c only the main calls for video ( vid_init, vid_start, vid_next, vid_close ) doing an abstraction layer ( frontend ). So the specific code related to v4l2/v4l and other will be in other/s files , so in.ex will be vid_start_v4l / vid_start_v4l2 ( backend ).

As you said with these 2 layers ( frontend / backend ) is easy to merge bktr ( FreeBSD video interface ) in the backend others as well.

Agree with Plugins , but maybe we need to be aware about netcams because the input plugin is a bit different comes from network ( right now in netcam.c ) and not from video.c .

* caveats: -- it tries V4L1 first, and if that doesn't work, fails over to V4L2, that should probably be changed, -- it really won't work with anything that doesn't produce YUYV (YUV422), -- I had to move things around a bit even for V4L1 code, so that both APIs can coexist, I might have broken things.

My camera 7 is a PWC camera. Reverting back to current code and it works again.

So there is something rotten with either this patch or the pwc driver version I use - and many use.

I also studied the code.

It needs a major clean-up. It is full of printf debug messages. I am changing these to motion_log messages and many of them only at debug level > 5.

The code is also swamped with silly goto messages which are totally not needed. I am eliminating these also. And the tabulation is also not constant and does not follow the code standard. I am fixing this as well. But It will take some time.

I am really concerned that implenting the patch - even cleaned up - will give serious problems many camera devices.

Looking at the code and at the comments above. It is probably the YUV420P and RGB24 cases that are missing. Why the heck did the patch submitter not implement YUV420P? It is just a matter of not converting anything.

My progress in cleaning up the code can be seen in MotionSourceTree. video2.h and video2.c

I have now eliminated all gotos. And I have replaced printf statements with motion_log.

I'm handling the v42l patch , i've removed any dependency with current svn version r142 ( committing a fix that was in the patch but was not related with it ). It seems stable with pwc-v4l2-20061119-042702 on debian sarge with kernel 2.6.18-1.

I have problems when I disconnect (or an other temp. error) a camera then the thread are exiting. I have also tested with v3.2.3 and there it works OK. The log from 3.2.3 there is one row comming all time when disconnected. it is: [1] sync error in proc 6870: Input/output error

Here I see that I get 4 buffers and then get Invalid argument. Tried to set MMAP_BUFFERS to 6 and then I got 6 Input/output before an Invalid argument. Looking at the s->buf.index returned when DQBUF fails it is always 0. This is strange, I think we got buffers from the driver. If I add

I've been looking around and seems that it's a known problem for saa7134 , so your approach is good . I'll improve a bit your patch and add a check for EIO, then clean buffers and reconnect. I think that on this way the issue will be fixed.

It works OK on my SAA7134 installation. My only thoughts about it is that I now have read somewhere in the v4l2 documentation, can't find where just now, that the driver might not return the buffers in the index or in same order that they where queued. The SAA7134 looks like it does it but it is not guarantied. One other thing is that the driver might return us a buffer with a valid index, then we overwrite this index with the lastone + 1.

I might have an idea how to make it more generic. If we get an error when DQBUF, we check if errno is EIO. If true return 1 else return -1. In QBUF, if error try to set index in buf to lastindex + 1. If error loop all index and try. If this also fails we didn't got a "valid" buffer in DQBUF.

I will try to add this code, but I dosn't have time until after 22/7-07.

Main patch for V4L2 has been released for 3.2.8 , although there're some improvements that are in current 3.2.9 svn version. Still there's a pending feature to allow choose between device supported palettes, i've attached a patch. Main problem of patch is not implement that feature but make easy to users to understand what is and how to use it.