static gboolean gst_v4l2_video_dec_open (GstVideoDecoder * decoder) { GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder); GST_DEBUG_OBJECT (self, "Opening"); if (!gst_v4l2_object_open (self->v4l2output)) goto failure; if (!gst_v4l2_object_open_shared (self->v4l2capture, self->v4l2output)) goto failure; self->probed_sinkcaps = gst_v4l2_object_get_caps (self->v4l2output, gst_v4l2_object_get_codec_caps ()); if (gst_caps_is_empty (self->probed_sinkcaps)) goto no_encoded_format; self->probed_srccaps = gst_v4l2_object_get_caps (self->v4l2capture, gst_v4l2_object_get_raw_caps ()); if (gst_caps_is_empty (self->probed_srccaps)) goto no_raw_format; return TRUE; no_encoded_format: GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, (_("Encoder on device %s has no supported input format"), self->v4l2output->videodev), (NULL)); goto failure; no_raw_format: GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, (_("Encoder on device %s has no supported output format"), self->v4l2output->videodev), (NULL)); goto failure; failure: if (GST_V4L2_IS_OPEN (self->v4l2output)) gst_v4l2_object_close (self->v4l2output); if (GST_V4L2_IS_OPEN (self->v4l2capture)) gst_v4l2_object_close (self->v4l2capture); gst_caps_replace (&self->probed_srccaps, NULL); gst_caps_replace (&self->probed_sinkcaps, NULL); return FALSE; }
static GstCaps * gst_v4l2src_get_caps (GstBaseSrc * src) { GstV4l2Src *v4l2src = GST_V4L2SRC (src); GstCaps *ret; GSList *walk; GSList *formats; if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object)) { /* FIXME: copy? */ return gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (v4l2src))); } if (v4l2src->probed_caps) return gst_caps_ref (v4l2src->probed_caps); formats = gst_v4l2_object_get_format_list (v4l2src->v4l2object); ret = gst_caps_new_empty (); for (walk = formats; walk; walk = walk->next) { struct v4l2_fmtdesc *format; GstStructure *template;
/****************************************************** * gst_v4l2src_capture_stop(): * stop streaming capture * return value: TRUE on success, FALSE on error ******************************************************/ gboolean gst_v4l2src_capture_stop (GstV4l2Src * v4l2src) { GST_DEBUG_OBJECT (v4l2src, "stopping capturing"); if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object)) { goto done; } if (!GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) { goto done; } if (v4l2src->use_mmap) { /* we actually need to sync on all queued buffers but not * on the non-queued ones */ if (!gst_v4l2_object_stop_streaming (v4l2src->v4l2object)) { return FALSE; } } done: /* make an optional pending wait stop */ v4l2src->quit = TRUE; v4l2src->is_capturing = FALSE; return TRUE; }
static GstCaps * gst_v4l2src_get_caps (GstBaseSrc * src, GstCaps * filter) { GstV4l2Src *v4l2src; GstV4l2Object *obj; GstCaps *ret; GSList *walk; GSList *formats; v4l2src = GST_V4L2SRC (src); obj = v4l2src->v4l2object; if (!GST_V4L2_IS_OPEN (obj)) { return gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (v4l2src)); } if (v4l2src->probed_caps) return gst_caps_ref (v4l2src->probed_caps); formats = gst_v4l2_object_get_format_list (obj); ret = gst_caps_new_empty (); for (walk = formats; walk; walk = walk->next) { struct v4l2_fmtdesc *format; GstStructure *template;
static void gst_v4l2sink_sync_overlay_fields (GstV4l2Sink * v4l2sink) { if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { gint fd = v4l2sink->v4l2object->video_fd; struct v4l2_format format; memset (&format, 0x00, sizeof (struct v4l2_format)); format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; g_return_if_fail (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) >= 0); if (v4l2sink->overlay_fields_set) { if (v4l2sink->overlay_fields_set & OVERLAY_TOP_SET) format.fmt.win.w.top = v4l2sink->overlay.top; if (v4l2sink->overlay_fields_set & OVERLAY_LEFT_SET) format.fmt.win.w.left = v4l2sink->overlay.left; if (v4l2sink->overlay_fields_set & OVERLAY_WIDTH_SET) format.fmt.win.w.width = v4l2sink->overlay.width; if (v4l2sink->overlay_fields_set & OVERLAY_HEIGHT_SET) format.fmt.win.w.height = v4l2sink->overlay.height; g_return_if_fail (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) >= 0); v4l2sink->overlay_fields_set = 0; } v4l2sink->overlay = format.fmt.win.w; } }
gboolean gst_v4l2_tuner_set_frequency (GstV4l2Object * v4l2object, GstTunerChannel * channel, gulong frequency) { GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel); gint chan; /* assert that we're opened and that we're using a known item */ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), FALSE); g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY), FALSE); g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2object, v4l2channel), FALSE); if (v4l2object->get_in_out_func (v4l2object, &chan)) { if (chan == GST_V4L2_TUNER_CHANNEL (channel)->index && GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) { if (gst_v4l2_set_frequency (v4l2object, v4l2channel->tuner, frequency)) { gst_tuner_frequency_changed (GST_TUNER (v4l2object->element), channel, frequency); return TRUE; } } } return FALSE; }
gboolean gst_v4l2_get_input (GstV4l2Object * v4l2object, gint * input) { gint n; GST_DEBUG_OBJECT (v4l2object->element, "trying to get input"); if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_INPUT, &n) < 0) goto input_failed; *input = n; GST_DEBUG_OBJECT (v4l2object->element, "input: %d", n); return TRUE; /* ERRORS */ input_failed: { GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS, (_("Failed to get current input on device '%s'. May be it is a radio device"), v4l2object->videodev), GST_ERROR_SYSTEM); return FALSE; } }
static GstCaps * gst_v4l2sink_get_caps (GstBaseSink * bsink) { GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink); GstCaps *ret; GSList *walk; GSList *formats; if (!GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { /* FIXME: copy? */ GST_DEBUG_OBJECT (v4l2sink, "device is not open"); return gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (v4l2sink))); } if (v4l2sink->probed_caps) { LOG_CAPS (v4l2sink, v4l2sink->probed_caps); return gst_caps_ref (v4l2sink->probed_caps); } formats = gst_v4l2_object_get_format_list (v4l2sink->v4l2object); ret = gst_caps_new_empty (); for (walk = v4l2sink->v4l2object->formats; walk; walk = walk->next) { struct v4l2_fmtdesc *format; GstStructure *template;
/****************************************************** * gst_v4l2_signal_strength(): * get the strength of the signal on the current input * return value: TRUE on success, FALSE on error ******************************************************/ gboolean gst_v4l2_signal_strength (GstV4l2Object * v4l2object, gint tunernum, gulong * signal_strength) { struct v4l2_tuner tuner = { 0, }; GST_DEBUG_OBJECT (v4l2object->element, "trying to get signal strength"); if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; tuner.index = tunernum; if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &tuner) < 0) goto tuner_failed; *signal_strength = tuner.signal; return TRUE; /* ERRORS */ tuner_failed: { GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS, (_("Failed to get signal strength for device '%s'."), v4l2object->videodev), GST_ERROR_SYSTEM); return FALSE; } }
/****************************************************** * gst_v4l2_set_attribute(): * try to set the value of one specific attribute * return value: TRUE on success, FALSE on error ******************************************************/ gboolean gst_v4l2_set_attribute (GstV4l2Object * v4l2object, int attribute_num, const int value) { struct v4l2_control control = { 0, }; GST_DEBUG_OBJECT (v4l2object->element, "setting value of attribute %d to %d", attribute_num, value); if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; control.id = attribute_num; control.value = value; if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) goto ctrl_failed; return TRUE; /* ERRORS */ ctrl_failed: { GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS, (_("Failed to set value %d for control %d on device '%s'."), value, attribute_num, v4l2object->videodev), GST_ERROR_SYSTEM); return FALSE; } }
/****************************************************** * gst_v4l2_get_capabilities(): * get the device's capturing capabilities * return value: TRUE on success, FALSE on error ******************************************************/ gboolean gst_v4l2_get_capabilities (GstV4l2Object * v4l2object) { GstElement *e; e = v4l2object->element; GST_DEBUG_OBJECT (e, "getting capabilities"); if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &v4l2object->vcap) < 0) goto cap_failed; GST_LOG_OBJECT (e, "driver: '%s'", v4l2object->vcap.driver); GST_LOG_OBJECT (e, "card: '%s'", v4l2object->vcap.card); GST_LOG_OBJECT (e, "bus_info: '%s'", v4l2object->vcap.bus_info); GST_LOG_OBJECT (e, "version: %08x", v4l2object->vcap.version); GST_LOG_OBJECT (e, "capabilites: %08x", v4l2object->vcap.capabilities); return TRUE; /* ERRORS */ cap_failed: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS, (_("Error getting capabilities for device '%s': " "It isn't a v4l2 driver. Check if it is a v4l1 driver."), v4l2object->videodev), GST_ERROR_SYSTEM); return FALSE; } }
/****************************************************** * gst_v4l2_set_frequency(): * set frequency * return value: TRUE on success, FALSE on error ******************************************************/ gboolean gst_v4l2_set_frequency (GstV4l2Object * v4l2object, gint tunernum, gulong frequency) { struct v4l2_frequency freq = { 0, }; GstTunerChannel *channel; GST_DEBUG_OBJECT (v4l2object->element, "setting current tuner frequency to %lu", frequency); if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; channel = gst_tuner_get_channel (GST_TUNER (v4l2object->element)); freq.tuner = tunernum; /* fill in type - ignore error */ v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq); freq.frequency = frequency / channel->freq_multiplicator; if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0) goto freq_failed; return TRUE; /* ERRORS */ freq_failed: { GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS, (_("Failed to set current tuner frequency for device '%s' to %lu Hz."), v4l2object->videodev, frequency), GST_ERROR_SYSTEM); return FALSE; } }
gboolean gst_v4l2_set_output (GstV4l2Object * v4l2object, gint output) { GST_DEBUG_OBJECT (v4l2object->element, "trying to set output to %d", output); if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_OUTPUT, &output) < 0) goto output_failed; return TRUE; /* ERRORS */ output_failed: if (v4l2object->vcap.capabilities & V4L2_CAP_TUNER) { /* only give a warning message if driver actually claims to have tuner * support */ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS, (_("Failed to set output %d on device %s."), output, v4l2object->videodev), GST_ERROR_SYSTEM); } return FALSE; }
gboolean gst_v4l2_get_output (GstV4l2Object * v4l2object, gint * output) { gint n; GST_DEBUG_OBJECT (v4l2object->element, "trying to get output"); if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_OUTPUT, &n) < 0) goto output_failed; *output = n; GST_DEBUG_OBJECT (v4l2object->element, "output: %d", n); return TRUE; /* ERRORS */ output_failed: if (v4l2object->vcap.capabilities & V4L2_CAP_TUNER) { /* only give a warning message if driver actually claims to have tuner * support */ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS, (_("Failed to get current output on device '%s'. May be it is a radio device"), v4l2object->videodev), GST_ERROR_SYSTEM); } return FALSE; }
static gboolean gst_v4l2_decoder_cmd (GstV4l2Object * v4l2object, guint cmd, guint flags) { struct v4l2_decoder_cmd dcmd = { 0, }; GST_DEBUG_OBJECT (v4l2object->element, "sending v4l2 decoder command %u with flags %u", cmd, flags); if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; dcmd.cmd = cmd; dcmd.flags = flags; if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_DECODER_CMD, &dcmd) < 0) goto dcmd_failed; return TRUE; dcmd_failed: if (errno == ENOTTY) { GST_INFO_OBJECT (v4l2object->element, "Failed to send decoder command %u with flags %u for '%s'. (%s)", cmd, flags, v4l2object->videodev, g_strerror (errno)); } else { GST_ERROR_OBJECT (v4l2object->element, "Failed to send decoder command %u with flags %u for '%s'. (%s)", cmd, flags, v4l2object->videodev, g_strerror (errno)); } return FALSE; }
/** * gst_v4l2_xoverlay_prepare_xwindow_id: * @v4l2object: the v4l2object * @required: %TRUE if display is required (ie. TRUE for v4l2sink, but * FALSE for any other element with optional overlay capabilities) * * Helper function to create a windo if none is set from the application. */ void gst_v4l2_xoverlay_prepare_xwindow_id (GstV4l2Object * v4l2object, gboolean required) { if (!GST_V4L2_IS_OVERLAY (v4l2object)) return; gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (v4l2object->element)); if (required && !v4l2object->xwindow_id) { GstV4l2Xv *v4l2xv; Window win; int width, height; long event_mask; if (!v4l2object->xv && GST_V4L2_IS_OPEN (v4l2object)) gst_v4l2_xoverlay_open (v4l2object); v4l2xv = v4l2object->xv; /* if xoverlay is not supported, just bail */ if (!v4l2xv) return; /* xoverlay is supported, but we don't have a window.. so create one */ GST_DEBUG_OBJECT (v4l2object->element, "creating window"); g_mutex_lock (v4l2xv->mutex); width = XDisplayWidth (v4l2xv->dpy, DefaultScreen (v4l2xv->dpy)); height = XDisplayHeight (v4l2xv->dpy, DefaultScreen (v4l2xv->dpy)); GST_DEBUG_OBJECT (v4l2object->element, "dpy=%p", v4l2xv->dpy); win = XCreateSimpleWindow (v4l2xv->dpy, DefaultRootWindow (v4l2xv->dpy), 0, 0, width, height, 0, 0, XBlackPixel (v4l2xv->dpy, DefaultScreen (v4l2xv->dpy))); GST_DEBUG_OBJECT (v4l2object->element, "win=%lu", win); event_mask = ExposureMask | StructureNotifyMask; if (GST_IS_NAVIGATION (v4l2object->element)) { event_mask |= PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask; } XSelectInput (v4l2xv->dpy, win, event_mask); v4l2xv->event_id = g_timeout_add (45, event_refresh, v4l2object); XMapRaised (v4l2xv->dpy, win); XSync (v4l2xv->dpy, FALSE); g_mutex_unlock (v4l2xv->mutex); GST_DEBUG_OBJECT (v4l2object->element, "got window"); gst_v4l2_xoverlay_set_window_handle (v4l2object, win); } }
static gboolean gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) { GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink); GstV4l2Object *obj = v4l2sink->v4l2object; LOG_CAPS (v4l2sink, caps); if (!GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { GST_DEBUG_OBJECT (v4l2sink, "device is not open"); return FALSE; } /* make sure the caps changed before doing anything */ if (gst_v4l2_object_caps_equal (obj, caps)) return TRUE; if (!gst_v4l2_object_stop (obj)) goto stop_failed; if (!gst_v4l2_object_set_format (v4l2sink->v4l2object, caps)) goto invalid_format; gst_v4l2sink_sync_overlay_fields (v4l2sink); gst_v4l2sink_sync_crop_fields (v4l2sink); #ifdef HAVE_XVIDEO gst_v4l2_video_overlay_prepare_window_handle (v4l2sink->v4l2object, TRUE); #endif GST_INFO_OBJECT (v4l2sink, "outputting buffers via mmap()"); v4l2sink->video_width = GST_V4L2_WIDTH (v4l2sink->v4l2object); v4l2sink->video_height = GST_V4L2_HEIGHT (v4l2sink->v4l2object); /* TODO: videosink width/height should be scaled according to * pixel-aspect-ratio */ GST_VIDEO_SINK_WIDTH (v4l2sink) = v4l2sink->video_width; GST_VIDEO_SINK_HEIGHT (v4l2sink) = v4l2sink->video_height; return TRUE; /* ERRORS */ stop_failed: { GST_DEBUG_OBJECT (v4l2sink, "failed to stop streaming"); return FALSE; } invalid_format: { /* error already posted */ GST_DEBUG_OBJECT (v4l2sink, "can't set format"); return FALSE; } }
void gst_v4l2_xoverlay_set_xwindow_id (GstV4l2Object * v4l2object, XID xwindow_id) { GstV4l2Xv *v4l2xv; XWindowAttributes attr; gboolean change = (v4l2object->xwindow_id != xwindow_id); GST_LOG_OBJECT (v4l2object->element, "Setting XID to %lx", (gulong) xwindow_id); if (!v4l2object->xv && GST_V4L2_IS_OPEN (v4l2object)) gst_v4l2_xoverlay_open (v4l2object); v4l2xv = v4l2object->xv; if (v4l2xv) g_mutex_lock (v4l2xv->mutex); if (change) { if (v4l2object->xwindow_id && v4l2xv) { GST_DEBUG_OBJECT (v4l2object->element, "Deactivating old port %lx", v4l2object->xwindow_id); XvSelectPortNotify (v4l2xv->dpy, v4l2xv->port, 0); XvSelectVideoNotify (v4l2xv->dpy, v4l2object->xwindow_id, 0); XvStopVideo (v4l2xv->dpy, v4l2xv->port, v4l2object->xwindow_id); } v4l2object->xwindow_id = xwindow_id; } if (!v4l2xv || xwindow_id == 0) { if (v4l2xv) g_mutex_unlock (v4l2xv->mutex); return; } if (change) { GST_DEBUG_OBJECT (v4l2object->element, "Activating new port %lx", xwindow_id); /* draw */ XvSelectPortNotify (v4l2xv->dpy, v4l2xv->port, 1); XvSelectVideoNotify (v4l2xv->dpy, v4l2object->xwindow_id, 1); } XGetWindowAttributes (v4l2xv->dpy, v4l2object->xwindow_id, &attr); XvPutVideo (v4l2xv->dpy, v4l2xv->port, v4l2object->xwindow_id, DefaultGC (v4l2xv->dpy, DefaultScreen (v4l2xv->dpy)), 0, 0, attr.width, attr.height, 0, 0, attr.width, attr.height); if (v4l2xv->idle_id) g_source_remove (v4l2xv->idle_id); v4l2xv->idle_id = g_idle_add (idle_refresh, v4l2object); g_mutex_unlock (v4l2xv->mutex); }
GstTunerNorm * gst_v4l2_tuner_get_norm (GstV4l2Object * v4l2object) { v4l2_std_id norm; /* assert that we're opened and that we're using a known item */ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), NULL); gst_v4l2_get_norm (v4l2object, &norm); return gst_v4l2_tuner_get_norm_by_std_id (v4l2object, norm); }
void gst_v4l2_xoverlay_set_window_handle (GstV4l2Object * v4l2object, guintptr id) { GstV4l2Xv *v4l2xv; XID xwindow_id = id; gboolean change = (v4l2object->xwindow_id != xwindow_id); GST_LOG_OBJECT (v4l2object->element, "Setting XID to %lx", (gulong) xwindow_id); if (!v4l2object->xv && GST_V4L2_IS_OPEN (v4l2object)) gst_v4l2_xoverlay_open (v4l2object); v4l2xv = v4l2object->xv; if (v4l2xv) g_mutex_lock (v4l2xv->mutex); if (change) { if (v4l2object->xwindow_id && v4l2xv) { GST_DEBUG_OBJECT (v4l2object->element, "Deactivating old port %lx", v4l2object->xwindow_id); XvSelectPortNotify (v4l2xv->dpy, v4l2xv->port, 0); XvSelectVideoNotify (v4l2xv->dpy, v4l2object->xwindow_id, 0); XvStopVideo (v4l2xv->dpy, v4l2xv->port, v4l2object->xwindow_id); } v4l2object->xwindow_id = xwindow_id; } if (!v4l2xv || xwindow_id == 0) { if (v4l2xv) g_mutex_unlock (v4l2xv->mutex); return; } if (change) { GST_DEBUG_OBJECT (v4l2object->element, "Activating new port %lx", xwindow_id); /* draw */ XvSelectPortNotify (v4l2xv->dpy, v4l2xv->port, 1); XvSelectVideoNotify (v4l2xv->dpy, v4l2object->xwindow_id, 1); } update_geometry (v4l2object); if (v4l2xv->idle_id) g_source_remove (v4l2xv->idle_id); v4l2xv->idle_id = g_idle_add (idle_refresh, v4l2object); g_mutex_unlock (v4l2xv->mutex); }
/** * gst_v4l2_xoverlay_prepare_xwindow_id: * @v4l2object: the v4l2object * @required: %TRUE if display is required (ie. TRUE for v4l2sink, but * FALSE for any other element with optional overlay capabilities) * * Helper function to create a windo if none is set from the application. */ void gst_v4l2_xoverlay_prepare_xwindow_id (GstV4l2Object * v4l2object, gboolean required) { if (!GST_V4L2_IS_OVERLAY (v4l2object)) return; gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (v4l2object->element)); if (required && !v4l2object->xwindow_id) { GstV4l2Xv *v4l2xv; Window win; int width, height; if (!v4l2object->xv && GST_V4L2_IS_OPEN (v4l2object)) gst_v4l2_xoverlay_open (v4l2object); v4l2xv = v4l2object->xv; /* if xoverlay is not supported, just bail */ if (!v4l2xv) return; /* xoverlay is supported, but we don't have a window.. so create one */ GST_DEBUG_OBJECT (v4l2object->element, "creating window"); g_mutex_lock (v4l2xv->mutex); width = XDisplayWidth (v4l2xv->dpy, DefaultScreen (v4l2xv->dpy)); height = XDisplayHeight (v4l2xv->dpy, DefaultScreen (v4l2xv->dpy)); GST_DEBUG_OBJECT (v4l2object->element, "dpy=%p", v4l2xv->dpy); win = XCreateSimpleWindow (v4l2xv->dpy, DefaultRootWindow (v4l2xv->dpy), 0, 0, width, height, 0, 0, XBlackPixel (v4l2xv->dpy, DefaultScreen (v4l2xv->dpy))); GST_DEBUG_OBJECT (v4l2object->element, "win=%lu", win); XMapRaised (v4l2xv->dpy, win); XSync (v4l2xv->dpy, FALSE); v4l2xv->internal_window = TRUE; g_mutex_unlock (v4l2xv->mutex); GST_DEBUG_OBJECT (v4l2object->element, "got window"); gst_v4l2_xoverlay_set_window_handle (v4l2object, win); } }
static GstCaps * gst_v4l2sink_get_caps (GstBaseSink * bsink, GstCaps * filter) { GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink); if (!GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { /* FIXME: copy? */ GST_DEBUG_OBJECT (v4l2sink, "device is not open"); return gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (v4l2sink)); } return gst_v4l2_object_get_caps (v4l2sink->v4l2object, filter); }
static GstCaps * gst_v4l2src_get_caps (GstBaseSrc * src, GstCaps * filter) { GstV4l2Src *v4l2src; GstV4l2Object *obj; v4l2src = GST_V4L2SRC (src); obj = v4l2src->v4l2object; if (!GST_V4L2_IS_OPEN (obj)) { return gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (v4l2src)); } return gst_v4l2_object_get_caps (obj, filter); }
void gst_v4l2_color_balance_set_value (GstV4l2Object * v4l2object, GstColorBalanceChannel * channel, gint value) { GstV4l2ColorBalanceChannel *v4l2channel = GST_V4L2_COLOR_BALANCE_CHANNEL (channel); /* assert that we're opened and that we're using a known item */ g_return_if_fail (GST_V4L2_IS_OPEN (v4l2object)); g_return_if_fail (gst_v4l2_color_balance_contains_channel (v4l2object, v4l2channel)); gst_v4l2_set_attribute (v4l2object, v4l2channel->id, value); }
gint gst_v4l2_color_balance_get_value (GstV4l2Object * v4l2object, GstColorBalanceChannel * channel) { GstV4l2ColorBalanceChannel *v4l2channel = GST_V4L2_COLOR_BALANCE_CHANNEL (channel); gint value; /* assert that we're opened and that we're using a known item */ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), 0); g_return_val_if_fail (gst_v4l2_color_balance_contains_channel (v4l2object, v4l2channel), 0); if (!gst_v4l2_get_attribute (v4l2object, v4l2channel->id, &value)) return 0; return value; }
static void gst_v4l2sink_sync_overlay_fields (GstV4l2Sink * v4l2sink) { if (!v4l2sink->overlay_fields_set) return; if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { gint fd = v4l2sink->v4l2object->video_fd; struct v4l2_format format; memset (&format, 0x00, sizeof (struct v4l2_format)); format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; if (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) < 0) { GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_FMT failed"); return; } GST_DEBUG_OBJECT (v4l2sink, "setting overlay: overlay_fields_set=0x%02x, top=%d, left=%d, width=%d, height=%d", v4l2sink->overlay_fields_set, v4l2sink->overlay.top, v4l2sink->overlay.left, v4l2sink->overlay.width, v4l2sink->overlay.height); if (v4l2sink->overlay_fields_set & RECT_TOP_SET) format.fmt.win.w.top = v4l2sink->overlay.top; if (v4l2sink->overlay_fields_set & RECT_LEFT_SET) format.fmt.win.w.left = v4l2sink->overlay.left; if (v4l2sink->overlay_fields_set & RECT_WIDTH_SET) format.fmt.win.w.width = v4l2sink->overlay.width; if (v4l2sink->overlay_fields_set & RECT_HEIGHT_SET) format.fmt.win.w.height = v4l2sink->overlay.height; if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0) { GST_WARNING_OBJECT (v4l2sink, "VIDIOC_S_FMT failed"); return; } v4l2sink->overlay_fields_set = 0; v4l2sink->overlay = format.fmt.win.w; } }
static void gst_v4l2sink_sync_crop_fields (GstV4l2Sink * v4l2sink) { if (!v4l2sink->crop_fields_set) return; if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { gint fd = v4l2sink->v4l2object->video_fd; struct v4l2_crop crop; memset (&crop, 0x00, sizeof (struct v4l2_crop)); crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; if (v4l2_ioctl (fd, VIDIOC_G_CROP, &crop) < 0) { GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_CROP failed"); return; } GST_DEBUG_OBJECT (v4l2sink, "setting crop: crop_fields_set=0x%02x, top=%d, left=%d, width=%d, height=%d", v4l2sink->crop_fields_set, v4l2sink->crop.top, v4l2sink->crop.left, v4l2sink->crop.width, v4l2sink->crop.height); if (v4l2sink->crop_fields_set & RECT_TOP_SET) crop.c.top = v4l2sink->crop.top; if (v4l2sink->crop_fields_set & RECT_LEFT_SET) crop.c.left = v4l2sink->crop.left; if (v4l2sink->crop_fields_set & RECT_WIDTH_SET) crop.c.width = v4l2sink->crop.width; if (v4l2sink->crop_fields_set & RECT_HEIGHT_SET) crop.c.height = v4l2sink->crop.height; if (v4l2_ioctl (fd, VIDIOC_S_CROP, &crop) < 0) { GST_WARNING_OBJECT (v4l2sink, "VIDIOC_S_CROP failed"); return; } v4l2sink->crop_fields_set = 0; v4l2sink->crop = crop.c; } }
gboolean gst_v4l2_tuner_set_norm (GstV4l2Object * v4l2object, GstTunerNorm * norm) { GstV4l2TunerNorm *v4l2norm = GST_V4L2_TUNER_NORM (norm); /* assert that we're opened and that we're using a known item */ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), FALSE); g_return_val_if_fail (gst_v4l2_tuner_contains_norm (v4l2object, v4l2norm), FALSE); if (gst_v4l2_set_norm (v4l2object, v4l2norm->index)) { gst_tuner_norm_changed (GST_TUNER (v4l2object->element), norm); if (v4l2object->update_fps_func) v4l2object->update_fps_func (v4l2object); return TRUE; } return FALSE; }
GstTunerChannel * gst_v4l2_tuner_get_channel (GstV4l2Object * v4l2object) { GList *item; gint channel; /* assert that we're opened and that we're using a known item */ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), NULL); if (v4l2object->get_in_out_func (v4l2object, &channel)) { for (item = v4l2object->channels; item != NULL; item = item->next) { if (channel == GST_V4L2_TUNER_CHANNEL (item->data)->index) return (GstTunerChannel *) item->data; } } return NULL; }
gboolean gst_v4l2_tuner_set_channel (GstV4l2Object * v4l2object, GstTunerChannel * channel) { GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel); /* assert that we're opened and that we're using a known item */ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), FALSE); g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2object, v4l2channel), FALSE); if (v4l2object->set_in_out_func (v4l2object, v4l2channel->index)) { gst_tuner_channel_changed (GST_TUNER (v4l2object->element), channel); /* can FPS change here? */ return TRUE; } return FALSE; }