Opened 13 years ago
Closed 13 years ago
#1387 closed defect (fixed)
v4l2 uses wrong (default) parameters
| Reported by: | burek | Owned by: | |
|---|---|---|---|
| Priority: | normal | Component: | undetermined |
| Version: | unspecified | Keywords: | v4l2 |
| Cc: | Blocked By: | ||
| Blocking: | Reproduced by developer: | no | |
| Analyzed by developer: | no |
Description
Using web cameras, usual way of setting web cam parameters is by using v4l2-ctl tool, to set the default width, height, pixel_format, frame_rate, etc. so that when we use:
ffmpeg -f v4l2 -i /dev/video0 ...
FFmpeg should use those defaults (after all, that's the purpose of such tool). But that doesn't happen. For example, I've got a usb web cam that supports input using H264 stream (beside raw and mjpeg), which is confirmed by v4l2-ctl:
$ v4l2-ctl --list-formats
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: 'YUYV'
Name : YUV 4:2:2 (YUYV)
Index : 1
Type : Video Capture
Pixel Format: 'H264' (compressed)
Name : H.264
Index : 2
Type : Video Capture
Pixel Format: 'MJPG' (compressed)
Name : MJPEG
so, setting up some web cam defaults like this:
$ v4l2-ctl --all
Driver Info (not using libv4l2):
Driver name : uvcvideo
Card type : HD Pro Webcam C920
Bus info : usb-0000:00:1d.7-8
Driver version: 3.2.17
Capabilities : 0x04000001
Video Capture
Streaming
Format Video Capture:
Width/Height : 640/480
Pixel Format : 'H264'
Field : None
Bytes per Line: 1280
Size Image : 614400
Colorspace : SRGB
Crop Capability Video Capture:
Bounds : Left 0, Top 0, Width 640, Height 480
Default : Left 0, Top 0, Width 640, Height 480
Pixel Aspect: 1/1
Video input : 0 (Camera 1: ok)
Streaming Parameters Video Capture:
Capabilities : timeperframe
Frames per second: 30.000 (30/1)
Read buffers : 0
should make Ffmpeg's command work in such way that it grabs the input from web cam using frame size of 640x480 and pixel_format of 'H264' (or was it -vcodec in FFmpeg, I'm not sure). But, running the FFmpeg command gives this:
$ ffmpeg -f v4l2 -i /dev/video0 -vcodec copy out.ts
ffmpeg version N-41142-g8f61526 Copyright (c) 2000-2012 the FFmpeg developers
built on May 30 2012 13:40:37 with gcc 4.6.3
configuration: --enable-static --enable-shared --enable-gpl --enable-nonfree --enable-postproc --enable-libx264 --enable-libaacplus --enable-libmp3lame --enable-libopenjpeg --enable-zlib
libavutil 51. 55.100 / 51. 55.100
libavcodec 54. 23.100 / 54. 23.100
libavformat 54. 6.101 / 54. 6.101
libavdevice 54. 0.100 / 54. 0.100
libavfilter 2. 77.100 / 2. 77.100
libswscale 2. 1.100 / 2. 1.100
libswresample 0. 15.100 / 0. 15.100
libpostproc 52. 0.100 / 52. 0.100
[video4linux2,v4l2 @ 0x9fee420] Estimating duration from bitrate, this may be inaccurate
Input #0, video4linux2,v4l2, from '/dev/video0':
Duration: N/A, start: 175879.115402, bitrate: 147456 kb/s
Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 640x480, 147456 kb/s, 30 tbr, 1000k tbn, 30 tbc
[mpegts @ 0x9febaa0] muxrate VBR, pcr every 3 pkts, sdt every 200, pat/pmt every 40 pkts
Output #0, mpegts, to 'out.ts':
Metadata:
encoder : Lavf54.6.101
Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 640x480, q=2-31, 147456 kb/s, 90k tbn, 30 tbc
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
frame= 113 fps= 30 q=-1.0 Lsize= 73103kB time=00:00:03.76 bitrate=158903.9kbits/s
video:67800kB audio:0kB global headers:0kB muxing overhead 7.822064%
As you can see, the input is set to "rawvideo (YUY2 / 0x32595559)" mode (which is wrong) and frame size is set to 640x480 (which is correct). Further testing shows that setting various default frame sizes, using v4l2-ctl, is properly detected in FFmpeg, but input pixel_format of H264/MJPG is not.
P.S.
Using the following command, I can get FFmpeg to "recognize" that I want input format to be mjpeg instead of raw:
$ ffmpeg -f v4l2 -vcodec mjpeg -i /dev/video0 ...
...
Input #0, video4linux2,v4l2, from '/dev/video0':
Duration: N/A, start: 176610.262086, bitrate: N/A
Stream #0:0: Video: mjpeg, yuvj422p, 352x288, -5 kb/s, 30 tbr, 1000k tbn, 30 tbc
but, I can't get the same for H264, because I get error instead:
$ ffmpeg -y -f v4l2 -vcodec h264 -i /dev/video0 ... ... [video4linux2,v4l2 @ 0x8ca24a0] Cannot find a proper format for codec_id 28, pix_fmt -1.
So, this is either some kind of bug in FFmpeg or unimplemented feature or something, so I don't know how to correctly flag this report.
Change History (6)
comment:1 by , 13 years ago
| Keywords: | v4l2 added |
|---|
comment:2 by , 13 years ago
You can close this ticket, the problem was that uvc driver did not support h264 pixel format back then when the ticket was created.
comment:4 by , 13 years ago
I need to get the h264 web cam in my possession again in order to test it on this matter. As soon as I do that, I'll test it and post results here :)
follow-up: 6 comment:5 by , 13 years ago
The bug is still there. h264 is now available, but -pixel_format is needed to set the pixel format again already selected by v4l2-ctl before.
And for the worse, this will in turn reset some other settings done by v4l2-ctl. For example, exposure mode is changed on some cameras. It seems that the format decision is assumed to take place prior to the other settings. The format can only be changed in close state, while the controls can be changed while capturing. So it may be incorrect to change the pixel format by ffmpeg without the ability to reapply the control settings.
I suggest either add a full control interface, or remove the pixel format setup from v4l2.c and just honor what was set by tools like v4l2-ctl before.
Adding an control interface is the issue of https://ffmpeg.org/trac/ffmpeg/ticket/2305 too.
comment:6 by , 13 years ago
| Resolution: | → fixed |
|---|---|
| Status: | new → closed |



Replying to burek:
Do you mean "wrong" in the sense that the output is broken (because the input data is not really yuy2 rawvideo) - I suspect this would indicate a driver bug but I may miss something - or do you mean "wrong" in the sense that you would prefer if the input data were h264? In this case, please test "ffmpeg -vcodec h264 -f v4l2 -i /dev/video0"