static bool_t try_format(VfwEngine *s, BITMAPINFO *videoformat, MSPixFmt pixfmt){ MSVideoSize tried_size=s->vsize; bool_t ret; do{ capGetVideoFormat(s->capvideo, videoformat, sizeof(BITMAPINFO)); videoformat->bmiHeader.biSizeImage = 0; videoformat->bmiHeader.biWidth = tried_size.width; videoformat->bmiHeader.biHeight = tried_size.height; switch(pixfmt){ case MS_YUV420P: videoformat->bmiHeader.biBitCount = 12; videoformat->bmiHeader.biCompression=MAKEFOURCC('I','4','2','0'); break; case MS_YUY2: videoformat->bmiHeader.biBitCount = 16; videoformat->bmiHeader.biCompression=MAKEFOURCC('Y','U','Y','2'); break; case MS_RGB24: videoformat->bmiHeader.biBitCount = 24; videoformat->bmiHeader.biCompression=BI_RGB; break; default: return FALSE; } ms_message("Trying video size %ix%i",tried_size.width,tried_size.height); ret=capSetVideoFormat(s->capvideo, videoformat, sizeof(BITMAPINFO)); tried_size=ms_video_size_get_just_lower_than(tried_size); }while(ret==FALSE && tried_size.width!=0); if (ret) { /*recheck video format */ capGetVideoFormat(s->capvideo, videoformat, sizeof(BITMAPINFO)); s->vsize.width=videoformat->bmiHeader.biWidth; s->vsize.height=videoformat->bmiHeader.biHeight; } return ret; }
static int msv4l2_configure(V4l2State *s){ struct v4l2_capability cap; struct v4l2_format fmt; MSVideoSize vsize; if (v4l2_ioctl (s->fd, VIDIOC_QUERYCAP, &cap)<0) { ms_message("Not a v4lv2 driver."); return -1; } if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { ms_error("%s is not a video capture device\n",s->dev); return -1; } if (!(cap.capabilities & V4L2_CAP_STREAMING)) { ms_error("%s does not support streaming i/o\n",s->dev); return -1; } ms_message("Driver is %s",cap.driver); memset(&fmt,0,sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (v4l2_ioctl (s->fd, VIDIOC_G_FMT, &fmt)<0){ ms_error("VIDIOC_G_FMT failed: %s",strerror(errno)); } vsize=s->vsize; do{ fmt.fmt.pix.width = s->vsize.width; fmt.fmt.pix.height = s->vsize.height; ms_message("v4l2: trying %ix%i",s->vsize.width,s->vsize.height); if (v4lv2_try_format(s,&fmt,V4L2_PIX_FMT_YUV420)){ s->pix_fmt=MS_YUV420P; s->int_pix_fmt=V4L2_PIX_FMT_YUV420; ms_message("v4lv2: YUV420P chosen"); break; }else if (v4lv2_try_format(s,&fmt,V4L2_PIX_FMT_YUYV)){ s->pix_fmt=MS_YUYV; s->int_pix_fmt=V4L2_PIX_FMT_YUYV; ms_message("v4lv2: V4L2_PIX_FMT_YUYV chosen"); break; }else if (v4lv2_try_format(s,&fmt,V4L2_PIX_FMT_RGB24)){ s->pix_fmt=MS_RGB24; s->int_pix_fmt=V4L2_PIX_FMT_RGB24; ms_message("v4lv2: RGB24 chosen"); break; }else if (v4lv2_try_format(s,&fmt,V4L2_PIX_FMT_MJPEG)){ s->pix_fmt=MS_MJPEG; s->int_pix_fmt=V4L2_PIX_FMT_MJPEG; ms_message("v4lv2: MJPEG chosen"); break; }else{ ms_error("Could not find supported pixel format for %ix%i", s->vsize.width, s->vsize.height); } s->vsize=ms_video_size_get_just_lower_than(s->vsize); }while(s->vsize.width!=0); if (s->vsize.width==0){ ms_message("Could not find any combination of resolution/pixel-format that works !"); s->vsize=vsize; return -1; } memset(&fmt,0,sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (v4l2_ioctl (s->fd, VIDIOC_G_FMT, &fmt)<0){ ms_error("VIDIOC_G_FMT failed: %s",strerror(errno)); }else{ ms_message("Size of webcam delivered pictures is %ix%i",fmt.fmt.pix.width,fmt.fmt.pix.height); s->vsize.width=fmt.fmt.pix.width; s->vsize.height=fmt.fmt.pix.height; } s->picture_size=get_picture_buffer_size(s->pix_fmt,s->vsize.width,s->vsize.height); s->configured=TRUE; return 0; }