/* video_on_can_mmap */ static gboolean _video_on_can_mmap(GIOChannel * channel, GIOCondition condition, gpointer data) { VideoPhonePlugin * video = data; PhonePluginHelper * helper = video->helper; struct v4l2_buffer buf; if(channel != video->channel || condition != G_IO_IN) return FALSE; if(_video_ioctl(video, VIDIOC_DQBUF, &buf) == -1) { helper->error(helper->phone, "Could not save picture", 1); return FALSE; } video->raw_buffer = video->buffers[buf.index].start; video->raw_buffer_cnt = buf.bytesused; #if 0 /* FIXME the raw buffer is not meant to be free()'d */ video->source = g_idle_add(_video_on_refresh, video); return FALSE; #else _video_on_refresh(video); video->raw_buffer = NULL; video->raw_buffer_cnt = 0; return TRUE; #endif }
static int _open_setup(VideoPhonePlugin * video) { int ret; struct v4l2_cropcap cropcap; struct v4l2_crop crop; GError * error = NULL; /* check for capabilities */ if(_video_ioctl(video, VIDIOC_QUERYCAP, &video->cap) == -1) return -error_set_code(1, "%s: %s (%s)", video->device, "Could not obtain the capabilities", strerror(errno)); if((video->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) return -error_set_code(1, "%s: %s", video->device, "Not a video capture device"); /* reset cropping */ memset(&cropcap, 0, sizeof(cropcap)); cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(_video_ioctl(video, VIDIOC_CROPCAP, &cropcap) == 0) { /* reset to default */ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = cropcap.defrect; if(_video_ioctl(video, VIDIOC_S_CROP, &crop) == -1 && errno == EINVAL) /* XXX ignore this error for now */ error_set_code(1, "%s: %s", video->device, "Cropping not supported"); } /* obtain the current format */ if(_video_ioctl(video, VIDIOC_G_FMT, &video->format) == -1) return -error_set_code(1, "%s: %s", video->device, "Could not obtain the video capture format"); /* check the current format */ if(video->format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -error_set_code(1, "%s: %s", video->device, "Unsupported video capture type"); if((video->cap.capabilities & V4L2_CAP_STREAMING) != 0) #ifdef NOTYET ret = _open_setup_mmap(video); #else ret = _open_setup_read(video); #endif else if((video->cap.capabilities & V4L2_CAP_READWRITE) != 0)
/* video_init */ static VideoPhonePlugin * _video_init(PhonePluginHelper * helper) { VideoPhonePlugin * video; struct v4l2_capability cap; struct v4l2_cropcap cropcap; struct v4l2_crop crop; struct v4l2_format format; if((video = object_new(sizeof(*video))) == NULL) return NULL; video->helper = helper; /* FIXME let this be configurable */ video->fd = open("/dev/video0", O_RDWR); video->buffer = buffer_new(0, NULL); video->source = 0; video->window = NULL; /* check for errors */ if(video->buffer == NULL || video->fd < 0 || _video_ioctl(video, VIDIOC_QUERYCAP, &cap) == -1 || (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0 /* FIXME also implement mmap() and streaming */ || (cap.capabilities & V4L2_CAP_READWRITE) == 0) { helper->error(helper->phone, "Could not open the video capture device", 1); _video_destroy(video); return NULL; } /* reset cropping */ memset(&cropcap, 0, sizeof(cropcap)); cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(_video_ioctl(video, VIDIOC_CROPCAP, &cropcap) == 0) { /* reset to default */ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = cropcap.defrect; if(_video_ioctl(video, VIDIOC_S_CROP, &crop) == -1 && errno == EINVAL) helper->error(helper->phone, "Cropping not supported", 0); } /* obtain the current format */ if(_video_ioctl(video, VIDIOC_G_FMT, &format) == -1 || buffer_set_size(video->buffer, format.fmt.pix.sizeimage) != 0) { _video_destroy(video); return NULL; } /* create the window */ video->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_resizable(GTK_WINDOW(video->window), FALSE); gtk_window_set_title(GTK_WINDOW(video->window), "Phone - Video"); g_signal_connect_swapped(video->window, "delete-event", G_CALLBACK( _video_on_closex), video); video->area = gtk_drawing_area_new(); gtk_widget_set_size_request(video->area, format.fmt.pix.width, format.fmt.pix.height); gtk_container_add(GTK_CONTAINER(video->window), video->area); gtk_widget_show_all(video->window); if(_video_on_refresh(video) == TRUE) video->source = g_timeout_add(1000, _video_on_refresh, video); return video; }