USB Camera (UVC 驱动)
UVC支持YUV和MJPEG的preview,但是奇怪的是上层通过了S_FMT来设置是yuv还是MJPEG,但是并没有找到哪里将MJPEG格式信息通过USB 设置到摄像头这个硬件去了啊。
附 过程:
case VIDIOC_S_FMT:
if ((ret = uvc_acquire_privileges(handle)) < 0)
return ret;
return uvc_v4l2_set_format(stream, arg);
and the uvc_v4l2_set_format call ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);
uvc_v4l2_try_format is defined as :
static int uvc_v4l2_try_format(struct uvc_streaming *stream,
struct v4l2_format *fmt, struct uvc_streaming_control *probe,
struct uvc_format **uvc_format, struct uvc_frame **uvc_frame)
{
struct uvc_format *format = NULL;
struct uvc_frame *frame = NULL;
__u16 rw, rh;
unsigned int d, maxd;
unsigned int i;
__u32 interval;
int ret = 0;
__u8 *fcc;
if (fmt->type != stream->type)
return -EINVAL;
fcc = (__u8 *)&fmt->fmt.pix.pixelformat;
uvc_trace(UVC_TRACE_FORMAT, "Trying format 0x%08x (%c%c%c%c): %ux%u.\n",
fmt->fmt.pix.pixelformat,
fcc[0], fcc[1], fcc[2], fcc[3],
fmt->fmt.pix.width, fmt->fmt.pix.height);
/* Check if the hardware supports the requested format. */
for (i = 0; i < stream->nformats; ++i) {
format = &stream->format[i];
if (format->fcc == fmt->fmt.pix.pixelformat)
break;
}
if (format == NULL || format->fcc != fmt->fmt.pix.pixelformat) {
uvc_trace(UVC_TRACE_FORMAT, "Unsupported format 0x%08x.\n",
fmt->fmt.pix.pixelformat);
return -EINVAL;
}
/* Find the closest image size. The distance between image sizes is
* the size in pixels of the non-overlapping regions between the
* requested size and the frame-specified size.
*/
rw = fmt->fmt.pix.width;
rh = fmt->fmt.pix.height;
maxd = (unsigned int)-1;
for (i = 0; i < format->nframes; ++i) {
__u16 w = format->frame[i].wWidth;
__u16 h = format->frame[i].wHeight;
d = min(w, rw) * min(h, rh);
d = w*h + rw*rh - 2*d;
if (d < maxd) {
maxd = d;
frame = &format->frame[i];
}
if (maxd == 0)
break;
}
if (frame == NULL) {
uvc_trace(UVC_TRACE_FORMAT, "Unsupported size %ux%u.\n",
fmt->fmt.pix.width, fmt->fmt.pix.height);
return -EINVAL;
}
/* Use the default frame interval. */
interval = frame->dwDefaultFrameInterval;
uvc_trace(UVC_TRACE_FORMAT, "Using default frame interval %u.%u us "
"(%u.%u fps).\n", interval/10, interval%10, 10000000/interval,
(100000000/interval)%10);
/* Set the format index, frame index and frame interval. */
memset(probe, 0, sizeof *probe);
probe->bmHint = 1;/* dwFrameInterval */
probe->bFormatIndex = format->index;
probe->bFrameIndex = frame->bFrameIndex;
probe->dwFrameInterval = uvc_try_frame_interval(frame, interval);
/* Some webcams stall the probe control set request when the
* dwMaxVideoFrameSize field is set to zero. The UVC specification
* clearly states that the field is read-only from the host, so this
* is a webcam bug. Set dwMaxVideoFrameSize to the value reported by
* the webcam to work around the problem.
*
* The workaround could probably be enabled for all webcams, so the
* quirk can be removed if needed. It's currently useful to detect
* webcam bugs and fix them before they hit the market (providing
* developers test their webcams with the Linux driver as well as with
* the Windows driver).
*/
mutex_lock(&stream->mutex);
if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)
probe->dwMaxVideoFrameSize =
stream->ctrl.dwMaxVideoFrameSize;
/* Probe the device. */
ret = uvc_probe_video(stream, probe);
mutex_unlock(&stream->mutex);
if (ret < 0)
goto done;
fmt->fmt.pix.width = frame->wWidth;
fmt->fmt.pix.height = frame->wHeight;
fmt->fmt.pix.field = V4L2_FIELD_NONE;
fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8;
fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize;
fmt->fmt.pix.colorspace = format->colorspace;
fmt->fmt.pix.priv = 0;
if (uvc_format != NULL)
*uvc_format = format;
if (uvc_frame != NULL)
*uvc_frame = frame;
done:
return ret;
}
[解决办法]
在ret = uvc_probe_video(stream, probe);中,
调用ret = uvc_set_video_ctrl(stream, probe, 1);
将uvc_streaming_control *probe传给硬件。