static void gst_v4lsrc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstV4lSrc *v4lsrc = GST_V4LSRC (object); switch (prop_id) { case PROP_AUTOPROBE: g_return_if_fail (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))); v4lsrc->autoprobe = g_value_get_boolean (value); break; case PROP_AUTOPROBE_FPS: g_return_if_fail (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))); v4lsrc->autoprobe_fps = g_value_get_boolean (value); break; case PROP_COPY_MODE: v4lsrc->copy_mode = g_value_get_boolean (value); break; case PROP_TIMESTAMP_OFFSET: v4lsrc->timestamp_offset = g_value_get_int64 (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static GstBuffer * gst_v4lmjpegsink_buffer_new (GstBufferPool * pool, guint64 offset, guint size, gpointer user_data) { GstV4lMjpegSink *v4lmjpegsink = GST_V4LMJPEGSINK (user_data); GstBuffer *buffer = NULL; guint8 *data; gint num; if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lmjpegsink))) return NULL; if (v4lmjpegsink->breq.size < size) { GST_DEBUG ("Requested buffer size is too large (%d > %ld)", size, v4lmjpegsink->breq.size); return NULL; } if (!gst_v4lmjpegsink_wait_frame (v4lmjpegsink, &num)) return NULL; data = gst_v4lmjpegsink_get_buffer (v4lmjpegsink, num); if (!data) return NULL; buffer = gst_buffer_new (); GST_BUFFER_DATA (buffer) = data; GST_BUFFER_MAXSIZE (buffer) = v4lmjpegsink->breq.size; GST_BUFFER_SIZE (buffer) = size; GST_BUFFER_POOL (buffer) = pool; GST_BUFFER_POOL_PRIVATE (buffer) = GINT_TO_POINTER (num); /* with this flag set, we don't need our own buffer_free() function */ GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_DONTFREE); return buffer; }
static GstPadLinkReturn gst_v4lmjpegsink_sinkconnect (GstPad * pad, const GstCaps * vscapslist) { GstV4lMjpegSink *v4lmjpegsink; GstStructure *structure; v4lmjpegsink = GST_V4LMJPEGSINK (gst_pad_get_parent (pad)); /* in case the buffers are active (which means that we already * did capsnego before and didn't clean up), clean up anyways */ if (GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lmjpegsink))) if (!gst_v4lmjpegsink_playback_deinit (v4lmjpegsink)) return GST_PAD_LINK_REFUSED; structure = gst_caps_get_structure (vscapslist, 0); gst_structure_get_int (structure, "width", &v4lmjpegsink->width); gst_structure_get_int (structure, "height", &v4lmjpegsink->height); if (!gst_v4lmjpegsink_set_playback (v4lmjpegsink, v4lmjpegsink->width, v4lmjpegsink->height, v4lmjpegsink->x_offset, v4lmjpegsink->y_offset, GST_V4LELEMENT (v4lmjpegsink)->vchan.norm, 0)) /* TODO: interlacing */ return GST_PAD_LINK_REFUSED; /* set buffer info */ if (!gst_v4lmjpegsink_set_buffer (v4lmjpegsink, v4lmjpegsink->numbufs, v4lmjpegsink->bufsize)) return GST_PAD_LINK_REFUSED; if (!gst_v4lmjpegsink_playback_init (v4lmjpegsink)) return GST_PAD_LINK_REFUSED; return GST_PAD_LINK_OK; }
static gboolean gst_v4lsrc_stop (GstBaseSrc * src) { GstV4lSrc *v4lsrc = GST_V4LSRC (src); if (GST_V4L_IS_ACTIVE (v4lsrc) && !gst_v4lsrc_capture_stop (v4lsrc)) return FALSE; if (GST_V4LELEMENT (v4lsrc)->buffer != NULL) { if (!gst_v4lsrc_capture_deinit (v4lsrc)) return FALSE; } if (!GST_BASE_SRC_CLASS (parent_class)->stop (src)) return FALSE; g_list_free (v4lsrc->colorspaces); v4lsrc->colorspaces = NULL; if (v4lsrc->fps_list) { g_value_unset (v4lsrc->fps_list); g_free (v4lsrc->fps_list); v4lsrc->fps_list = NULL; } return TRUE; }
static gboolean gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps) { GstV4lSrc *v4lsrc; guint32 fourcc; gint bpp, depth, w, h, palette = -1; const GValue *new_fps; gint cur_fps_n, cur_fps_d; GstStructure *structure; struct video_window *vwin; v4lsrc = GST_V4LSRC (src); vwin = &GST_V4LELEMENT (v4lsrc)->vwin; /* if we're not open, punt -- we'll get setcaps'd later via negotiate */ if (!GST_V4L_IS_OPEN (v4lsrc)) return FALSE; /* make sure we stop capturing and dealloc buffers */ if (GST_V4L_IS_ACTIVE (v4lsrc)) { if (!gst_v4lsrc_capture_stop (v4lsrc)) return FALSE; if (!gst_v4lsrc_capture_deinit (v4lsrc)) return FALSE; } /* it's fixed, one struct */ structure = gst_caps_get_structure (caps, 0); if (strcmp (gst_structure_get_name (structure), "video/x-raw-yuv") == 0) gst_structure_get_fourcc (structure, "format", &fourcc); else fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', ' '); gst_structure_get_int (structure, "width", &w); gst_structure_get_int (structure, "height", &h); new_fps = gst_structure_get_value (structure, "framerate"); /* set framerate if it's not already correct */ if (!gst_v4lsrc_get_fps (v4lsrc, &cur_fps_n, &cur_fps_d)) return FALSE; if (new_fps) { GST_DEBUG_OBJECT (v4lsrc, "linking with %dx%d at %d/%d fps", w, h, gst_value_get_fraction_numerator (new_fps), gst_value_get_fraction_denominator (new_fps)); if (gst_value_get_fraction_numerator (new_fps) != cur_fps_n || gst_value_get_fraction_denominator (new_fps) != cur_fps_d) { int fps_index = (gst_value_get_fraction_numerator (new_fps) * 16) / (gst_value_get_fraction_denominator (new_fps) * 15); GST_DEBUG_OBJECT (v4lsrc, "Trying to set fps index %d", fps_index); /* set bits 16 to 21 to 0 */ vwin->flags &= (0x3F00 - 1); /* set bits 16 to 21 to the index */ vwin->flags |= fps_index << 16; if (!gst_v4l_set_window_properties (GST_V4LELEMENT (v4lsrc))) { return FALSE; } } } switch (fourcc) { case GST_MAKE_FOURCC ('I', '4', '2', '0'): palette = VIDEO_PALETTE_YUV420P; v4lsrc->buffer_size = ((w + 1) & ~1) * ((h + 1) & ~1) * 1.5; break; case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): palette = VIDEO_PALETTE_YUV422; v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2; break; case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): palette = VIDEO_PALETTE_UYVY; v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2; break; case GST_MAKE_FOURCC ('Y', '4', '1', 'B'): palette = VIDEO_PALETTE_YUV411P; v4lsrc->buffer_size = ((w + 3) & ~3) * h * 1.5; break; case GST_MAKE_FOURCC ('Y', '4', '1', 'P'): palette = VIDEO_PALETTE_YUV411; v4lsrc->buffer_size = ((w + 3) & ~3) * h * 1.5; break; case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'): palette = VIDEO_PALETTE_YUV410P; v4lsrc->buffer_size = ((w + 3) & ~3) * ((h + 3) & ~3) * 1.125; break; case GST_MAKE_FOURCC ('Y', '4', '2', 'B'): palette = VIDEO_PALETTE_YUV422P; v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2; break; case GST_MAKE_FOURCC ('R', 'G', 'B', ' '): gst_structure_get_int (structure, "depth", &depth); switch (depth) { case 15: palette = VIDEO_PALETTE_RGB555; v4lsrc->buffer_size = w * h * 2; break; case 16: palette = VIDEO_PALETTE_RGB565; v4lsrc->buffer_size = w * h * 2; break; case 24: gst_structure_get_int (structure, "bpp", &bpp); switch (bpp) { case 24: palette = VIDEO_PALETTE_RGB24; v4lsrc->buffer_size = w * h * 3; break; case 32: palette = VIDEO_PALETTE_RGB32; v4lsrc->buffer_size = w * h * 4; break; default: break; } break; default: break; } break; default: break; } if (palette == -1) { GST_WARNING_OBJECT (v4lsrc, "palette for fourcc %" GST_FOURCC_FORMAT " is -1, refusing link", GST_FOURCC_ARGS (fourcc)); return FALSE; } GST_DEBUG_OBJECT (v4lsrc, "trying to set_capture %dx%d, palette %d", w, h, palette); /* this only fills in v4lsrc->mmap values */ if (!gst_v4lsrc_set_capture (v4lsrc, w, h, palette)) { GST_WARNING_OBJECT (v4lsrc, "could not set_capture %dx%d, palette %d", w, h, palette); return FALSE; } /* first try the negotiated settings using try_capture */ if (!gst_v4lsrc_try_capture (v4lsrc, w, h, palette)) { GST_DEBUG_OBJECT (v4lsrc, "failed trying palette %d for %dx%d", palette, w, h); return FALSE; } if (!gst_v4lsrc_capture_init (v4lsrc)) return FALSE; if (!gst_v4lsrc_capture_start (v4lsrc)) return FALSE; return TRUE; }
static GstPadLinkReturn gst_v4ljpegsrc_src_link (GstPad * pad, const GstCaps * vscapslist) { GstV4lJpegSrc *v4ljpegsrc; GstV4lSrc *v4lsrc; gint w, h, palette = -1; const GValue *fps; GstStructure *structure; gboolean was_capturing; struct video_window *vwin; v4ljpegsrc = GST_V4LJPEGSRC (gst_pad_get_parent (pad)); v4lsrc = GST_V4LSRC (v4ljpegsrc); vwin = &GST_V4LELEMENT (v4lsrc)->vwin; was_capturing = v4lsrc->is_capturing; /* in case the buffers are active (which means that we already * did capsnego before and didn't clean up), clean up anyways */ if (GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))) { if (was_capturing) { if (!gst_v4lsrc_capture_stop (v4lsrc)) return GST_PAD_LINK_REFUSED; } if (!gst_v4lsrc_capture_deinit (v4lsrc)) return GST_PAD_LINK_REFUSED; } else if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) { return GST_PAD_LINK_DELAYED; } structure = gst_caps_get_structure (vscapslist, 0); gst_structure_get_int (structure, "width", &w); gst_structure_get_int (structure, "height", &h); fps = gst_structure_get_value (structure, "framerate"); GST_DEBUG_OBJECT (v4ljpegsrc, "linking with %dx%d at %d/%d fps", w, h, gst_value_get_fraction_numerator (fps), gst_value_get_fraction_denominator (fps)); /* set framerate if it's not already correct */ if (fps != gst_v4lsrc_get_fps (v4lsrc)) { int fps_index = fps / 15.0 * 16; GST_DEBUG_OBJECT (v4ljpegsrc, "Trying to set fps index %d", fps_index); /* set bits 16 to 21 to 0 */ vwin->flags &= (0x3F00 - 1); /* set bits 16 to 21 to the index */ vwin->flags |= fps_index << 16; if (!gst_v4l_set_window_properties (GST_V4LELEMENT (v4lsrc))) { return GST_PAD_LINK_DELAYED; } } /* * Try to set the camera to capture RGB24 */ palette = VIDEO_PALETTE_RGB24; v4lsrc->buffer_size = w * h * 3; GST_DEBUG_OBJECT (v4ljpegsrc, "trying to set_capture %dx%d, palette %d", w, h, palette); /* this only fills in v4lsrc->mmap values */ if (!gst_v4lsrc_set_capture (v4lsrc, w, h, palette)) { GST_WARNING_OBJECT (v4ljpegsrc, "could not set_capture %dx%d, palette %d", w, h, palette); return GST_PAD_LINK_REFUSED; } /* first try the negotiated settings using try_capture */ if (!gst_v4lsrc_try_capture (v4lsrc, w, h, palette)) { GST_DEBUG_OBJECT (v4ljpegsrc, "failed trying palette %d for %dx%d", palette, w, h); return GST_PAD_LINK_REFUSED; } if (!gst_v4lsrc_capture_init (v4lsrc)) return GST_PAD_LINK_REFUSED; if (was_capturing || GST_STATE (v4lsrc) == GST_STATE_PLAYING) { if (!gst_v4lsrc_capture_start (v4lsrc)) return GST_PAD_LINK_REFUSED; } return GST_PAD_LINK_OK; }