plugin_LTLIBRARIES = libv4lelement.la libv4lsrc.la \
libv4lmjpegsrc.la libv4lmjpegsink.la
-libv4lelement_la_SOURCES = gstv4lelement.c v4l_calls.c
+libv4lelement_la_SOURCES = gstv4lelement.c v4l_calls.c v4l-overlay_calls.c
libv4lelement_la_CFLAGS = $(GST_CFLAGS)
libv4lelement_la_LIBADD = $(GST_LIBS)
libv4lelement_la_LDFLAGS = @GST_PLUGIN_LDFLAGS@
ARG_DEVICE_IS_MJPEG_CAPTURE,
ARG_DEVICE_IS_MJPEG_PLAYBACK,
ARG_DEVICE_IS_MPEG_CAPTURE,
- ARG_DEVICE_IS_MPEG_PLAYBACK
+ ARG_DEVICE_IS_MPEG_PLAYBACK,
+ ARG_DISPLAY,
+ ARG_VIDEOWINDOW,
+ ARG_CLIPPING,
+ ARG_DO_OVERLAY,
};
g_param_spec_boolean("can_playback_mpeg","can_playback_mpeg","can_playback_mpeg",
0,G_PARAM_READABLE));
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DISPLAY,
+ g_param_spec_string("display","display","display",
+ NULL, G_PARAM_WRITABLE));
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DO_OVERLAY,
+ g_param_spec_boolean("do_overlay","do_overlay","do_overlay",
+ 0,G_PARAM_WRITABLE));
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VIDEOWINDOW,
+ g_param_spec_pointer("videowindow","videowindow","videowindow",
+ G_PARAM_WRITABLE));
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CLIPPING,
+ g_param_spec_pointer("videowindowclip","videowindowclip","videowindowclip",
+ G_PARAM_WRITABLE));
+
gobject_class->set_property = gst_v4lelement_set_property;
gobject_class->get_property = gst_v4lelement_get_property;
v4lelement->video_fd = -1;
v4lelement->buffer = NULL;
v4lelement->videodev = NULL;
+ v4lelement->display = NULL;
v4lelement->norm = -1;
v4lelement->channel = -1; /* the first channel */
}
break;
case ARG_DEVICE:
- if (GST_V4L_IS_OPEN(v4lelement))
- break; /* only set when *not* open */
if (v4lelement->videodev)
g_free(v4lelement->videodev);
v4lelement->videodev = g_strdup(g_value_get_string(value));
break;
+ case ARG_DO_OVERLAY:
+ if (GST_V4L_IS_OPEN(v4lelement))
+ gst_v4l_enable_overlay(v4lelement, g_value_get_boolean(value));
+ break;
+ case ARG_DISPLAY:
+ if (v4lelement->display) g_free(v4lelement->display);
+ v4lelement->display = g_strdup(g_value_get_string(value));
+ break;
+ case ARG_VIDEOWINDOW:
+ if (GST_V4L_IS_OPEN(v4lelement))
+ gst_v4l_set_window(v4lelement,
+ ((GstV4lRect*)g_value_get_pointer(value))->x,
+ ((GstV4lRect*)g_value_get_pointer(value))->y,
+ ((GstV4lRect*)g_value_get_pointer(value))->w,
+ ((GstV4lRect*)g_value_get_pointer(value))->h);
+ break;
+ case ARG_CLIPPING:
+ if (GST_V4L_IS_OPEN(v4lelement))
+ {
+ gint i;
+ struct video_clip *clips;
+ GList *list = (GList*)g_value_get_pointer(value);
+ clips = g_malloc(sizeof(struct video_clip) * g_list_length(list));
+ for (i=0;i<g_list_length(list);i++)
+ {
+ clips[i].x = ((GstV4lRect*)g_list_nth_data(list, i))->x;
+ clips[i].y = ((GstV4lRect*)g_list_nth_data(list, i))->y;
+ clips[i].width = ((GstV4lRect*)g_list_nth_data(list, i))->w;
+ clips[i].height = ((GstV4lRect*)g_list_nth_data(list, i))->h;
+ }
+ gst_v4l_set_clips(v4lelement, clips, g_list_length(list));
+ g_free(clips);
+ }
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
{
int n, temp;
+ if (v4lelement->display)
+ gst_v4l_set_overlay(v4lelement, v4lelement->display);
+
if (!gst_v4l_open(v4lelement))
return GST_STATE_FAILURE;
typedef struct _GstV4lElement GstV4lElement;
typedef struct _GstV4lElementClass GstV4lElementClass;
+typedef struct _GstV4lRect {
+ gint x, y, w, h;
+} GstV4lRect;
+
struct _GstV4lElement {
GstElement element;
/* some more info about the current input's capabilities */
struct video_channel vchan;
+ /* and last but not least, the current video window */
+ struct video_window vwin;
+
/* caching values */
gint channel;
gint norm;
gint hue;
gint contrast;
gint saturation;
+ gchar *display;
};
struct _GstV4lElementClass {
return FALSE;
}
+ /* and get the video window */
+ if (GST_V4L_IS_OVERLAY(v4lelement))
+ {
+ if (ioctl(v4lelement->video_fd, VIDIOCGWIN, &(v4lelement->vwin)) < 0)
+ {
+ close(v4lelement->video_fd);
+ v4lelement->video_fd = -1;
+ gst_element_error(GST_ELEMENT(v4lelement),
+ "Failed to get video window properties of \'%s\': %s",
+ v4lelement->videodev, sys_errlist[errno]);
+ return FALSE;
+ }
+ }
+
gst_info("Opened device \'%s\' (\'%s\') successfully\n",
v4lelement->vcap.name, v4lelement->videodev);
#define GST_V4L_IS_ACTIVE(v4lelement) \
(v4lelement->buffer != NULL)
+#define GST_V4L_IS_OVERLAY(v4lelement) \
+ (v4lelement->vcap.type & VID_TYPE_OVERLAY)
+
/* checks whether the current v4lelement has already been open()'ed or not */
#define GST_V4L_CHECK_OPEN(v4lelement) \
if (v4lelement->video_fd <= 0) \
return FALSE; \
}
+/* checks whether the current v4lelement does video overlay */
+#define GST_V4L_CHECK_OVERLAY(v4lelement) \
+ if (!(v4lelement->vcap.type & VID_TYPE_OVERLAY)) \
+ { \
+ gst_element_error(GST_ELEMENT(v4lelement), \
+ "Device doesn';t do overlay"); \
+ return FALSE; \
+ }
+
/* checks whether we're in capture mode or not */
#define GST_V4L_CHECK_ACTIVE(v4lelement) \
if (v4lelement->buffer == NULL) \
/* norm control (norm = VIDEO_MODE_{PAL|NTSC|SECAM|AUTO}) */
gint gst_v4l_get_num_chans (GstV4lElement *v4lelement);
-gboolean gst_v4l_get_chan_norm (GstV4lElement *v4lelement, gint *channel, gint *norm);
-gboolean gst_v4l_set_chan_norm (GstV4lElement *v4lelement, gint channel, gint norm);
+gboolean gst_v4l_get_chan_norm (GstV4lElement *v4lelement, gint *channel, gint *norm);
+gboolean gst_v4l_set_chan_norm (GstV4lElement *v4lelement, gint channel, gint norm);
GList *gst_v4l_get_chan_names (GstV4lElement *v4lelement);
/* frequency control */
gboolean gst_v4l_set_frequency (GstV4lElement *v4lelement, gulong frequency);
/* picture control */
-gboolean gst_v4l_get_picture (GstV4lElement *v4lelement, GstV4lPictureType type, gint *value);
-gboolean gst_v4l_set_picture (GstV4lElement *v4lelement, GstV4lPictureType type, gint value);
+gboolean gst_v4l_get_picture (GstV4lElement *v4lelement, GstV4lPictureType type, gint *value);
+gboolean gst_v4l_set_picture (GstV4lElement *v4lelement, GstV4lPictureType type, gint value);
/* audio control */
gboolean gst_v4l_has_audio (GstV4lElement *v4lelement);
-gboolean gst_v4l_get_audio (GstV4lElement *v4lelement, GstV4lAudioType type, gint *value);
-gboolean gst_v4l_set_audio (GstV4lElement *v4lelement, GstV4lAudioType type, gint value);
+gboolean gst_v4l_get_audio (GstV4lElement *v4lelement, GstV4lAudioType type, gint *value);
+gboolean gst_v4l_set_audio (GstV4lElement *v4lelement, GstV4lAudioType type, gint value);
+
+/* overlay */
+gboolean gst_v4l_set_overlay (GstV4lElement *v4lelement, gchar *display);
+gboolean gst_v4l_set_window (GstV4lElement *v4lelement, gint x, gint y, gint w, gint h);
+gboolean gst_v4l_set_clips (GstV4lElement *v4lelement, struct video_clip *clips, gint num_clips);
+gboolean gst_v4l_enable_overlay (GstV4lElement *v4lelement, gboolean enable);
#ifdef __cplusplus