mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
Added basic overlay support to v4l
Original commit message from CVS: Added basic overlay support to v4l
This commit is contained in:
parent
49b26d418b
commit
162086096d
5 changed files with 103 additions and 10 deletions
|
@ -3,7 +3,7 @@ plugindir = $(libdir)/gst
|
||||||
plugin_LTLIBRARIES = libv4lelement.la libv4lsrc.la \
|
plugin_LTLIBRARIES = libv4lelement.la libv4lsrc.la \
|
||||||
libv4lmjpegsrc.la libv4lmjpegsink.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_CFLAGS = $(GST_CFLAGS)
|
||||||
libv4lelement_la_LIBADD = $(GST_LIBS)
|
libv4lelement_la_LIBADD = $(GST_LIBS)
|
||||||
libv4lelement_la_LDFLAGS = @GST_PLUGIN_LDFLAGS@
|
libv4lelement_la_LDFLAGS = @GST_PLUGIN_LDFLAGS@
|
||||||
|
|
|
@ -57,7 +57,11 @@ enum {
|
||||||
ARG_DEVICE_IS_MJPEG_CAPTURE,
|
ARG_DEVICE_IS_MJPEG_CAPTURE,
|
||||||
ARG_DEVICE_IS_MJPEG_PLAYBACK,
|
ARG_DEVICE_IS_MJPEG_PLAYBACK,
|
||||||
ARG_DEVICE_IS_MPEG_CAPTURE,
|
ARG_DEVICE_IS_MPEG_CAPTURE,
|
||||||
ARG_DEVICE_IS_MPEG_PLAYBACK
|
ARG_DEVICE_IS_MPEG_PLAYBACK,
|
||||||
|
ARG_DISPLAY,
|
||||||
|
ARG_VIDEOWINDOW,
|
||||||
|
ARG_CLIPPING,
|
||||||
|
ARG_DO_OVERLAY,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,6 +194,19 @@ gst_v4lelement_class_init (GstV4lElementClass *klass)
|
||||||
g_param_spec_boolean("can_playback_mpeg","can_playback_mpeg","can_playback_mpeg",
|
g_param_spec_boolean("can_playback_mpeg","can_playback_mpeg","can_playback_mpeg",
|
||||||
0,G_PARAM_READABLE));
|
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->set_property = gst_v4lelement_set_property;
|
||||||
gobject_class->get_property = gst_v4lelement_get_property;
|
gobject_class->get_property = gst_v4lelement_get_property;
|
||||||
|
|
||||||
|
@ -204,6 +221,7 @@ gst_v4lelement_init (GstV4lElement *v4lelement)
|
||||||
v4lelement->video_fd = -1;
|
v4lelement->video_fd = -1;
|
||||||
v4lelement->buffer = NULL;
|
v4lelement->buffer = NULL;
|
||||||
v4lelement->videodev = NULL;
|
v4lelement->videodev = NULL;
|
||||||
|
v4lelement->display = NULL;
|
||||||
|
|
||||||
v4lelement->norm = -1;
|
v4lelement->norm = -1;
|
||||||
v4lelement->channel = -1; /* the first channel */
|
v4lelement->channel = -1; /* the first channel */
|
||||||
|
@ -324,12 +342,44 @@ gst_v4lelement_set_property (GObject *object,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ARG_DEVICE:
|
case ARG_DEVICE:
|
||||||
if (GST_V4L_IS_OPEN(v4lelement))
|
|
||||||
break; /* only set when *not* open */
|
|
||||||
if (v4lelement->videodev)
|
if (v4lelement->videodev)
|
||||||
g_free(v4lelement->videodev);
|
g_free(v4lelement->videodev);
|
||||||
v4lelement->videodev = g_strdup(g_value_get_string(value));
|
v4lelement->videodev = g_strdup(g_value_get_string(value));
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -494,6 +544,9 @@ gst_v4lelement_change_state (GstElement *element)
|
||||||
{
|
{
|
||||||
int n, temp;
|
int n, temp;
|
||||||
|
|
||||||
|
if (v4lelement->display)
|
||||||
|
gst_v4l_set_overlay(v4lelement, v4lelement->display);
|
||||||
|
|
||||||
if (!gst_v4l_open(v4lelement))
|
if (!gst_v4l_open(v4lelement))
|
||||||
return GST_STATE_FAILURE;
|
return GST_STATE_FAILURE;
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,10 @@ extern "C" {
|
||||||
typedef struct _GstV4lElement GstV4lElement;
|
typedef struct _GstV4lElement GstV4lElement;
|
||||||
typedef struct _GstV4lElementClass GstV4lElementClass;
|
typedef struct _GstV4lElementClass GstV4lElementClass;
|
||||||
|
|
||||||
|
typedef struct _GstV4lRect {
|
||||||
|
gint x, y, w, h;
|
||||||
|
} GstV4lRect;
|
||||||
|
|
||||||
struct _GstV4lElement {
|
struct _GstV4lElement {
|
||||||
GstElement element;
|
GstElement element;
|
||||||
|
|
||||||
|
@ -61,6 +65,9 @@ struct _GstV4lElement {
|
||||||
/* some more info about the current input's capabilities */
|
/* some more info about the current input's capabilities */
|
||||||
struct video_channel vchan;
|
struct video_channel vchan;
|
||||||
|
|
||||||
|
/* and last but not least, the current video window */
|
||||||
|
struct video_window vwin;
|
||||||
|
|
||||||
/* caching values */
|
/* caching values */
|
||||||
gint channel;
|
gint channel;
|
||||||
gint norm;
|
gint norm;
|
||||||
|
@ -72,6 +79,7 @@ struct _GstV4lElement {
|
||||||
gint hue;
|
gint hue;
|
||||||
gint contrast;
|
gint contrast;
|
||||||
gint saturation;
|
gint saturation;
|
||||||
|
gchar *display;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstV4lElementClass {
|
struct _GstV4lElementClass {
|
||||||
|
|
|
@ -100,6 +100,20 @@ gst_v4l_open (GstV4lElement *v4lelement)
|
||||||
return FALSE;
|
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",
|
gst_info("Opened device \'%s\' (\'%s\') successfully\n",
|
||||||
v4lelement->vcap.name, v4lelement->videodev);
|
v4lelement->vcap.name, v4lelement->videodev);
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,9 @@ extern "C" {
|
||||||
#define GST_V4L_IS_ACTIVE(v4lelement) \
|
#define GST_V4L_IS_ACTIVE(v4lelement) \
|
||||||
(v4lelement->buffer != NULL)
|
(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 */
|
/* checks whether the current v4lelement has already been open()'ed or not */
|
||||||
#define GST_V4L_CHECK_OPEN(v4lelement) \
|
#define GST_V4L_CHECK_OPEN(v4lelement) \
|
||||||
if (v4lelement->video_fd <= 0) \
|
if (v4lelement->video_fd <= 0) \
|
||||||
|
@ -53,6 +56,15 @@ extern "C" {
|
||||||
return FALSE; \
|
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 */
|
/* checks whether we're in capture mode or not */
|
||||||
#define GST_V4L_CHECK_ACTIVE(v4lelement) \
|
#define GST_V4L_CHECK_ACTIVE(v4lelement) \
|
||||||
if (v4lelement->buffer == NULL) \
|
if (v4lelement->buffer == NULL) \
|
||||||
|
@ -98,8 +110,8 @@ gboolean gst_v4l_close (GstV4lElement *v4lelement);
|
||||||
|
|
||||||
/* norm control (norm = VIDEO_MODE_{PAL|NTSC|SECAM|AUTO}) */
|
/* norm control (norm = VIDEO_MODE_{PAL|NTSC|SECAM|AUTO}) */
|
||||||
gint gst_v4l_get_num_chans (GstV4lElement *v4lelement);
|
gint gst_v4l_get_num_chans (GstV4lElement *v4lelement);
|
||||||
gboolean gst_v4l_get_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);
|
gboolean gst_v4l_set_chan_norm (GstV4lElement *v4lelement, gint channel, gint norm);
|
||||||
GList *gst_v4l_get_chan_names (GstV4lElement *v4lelement);
|
GList *gst_v4l_get_chan_names (GstV4lElement *v4lelement);
|
||||||
|
|
||||||
/* frequency control */
|
/* frequency control */
|
||||||
|
@ -108,13 +120,19 @@ gboolean gst_v4l_get_frequency (GstV4lElement *v4lelement, gulong *frequency);
|
||||||
gboolean gst_v4l_set_frequency (GstV4lElement *v4lelement, gulong frequency);
|
gboolean gst_v4l_set_frequency (GstV4lElement *v4lelement, gulong frequency);
|
||||||
|
|
||||||
/* picture control */
|
/* picture control */
|
||||||
gboolean gst_v4l_get_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);
|
gboolean gst_v4l_set_picture (GstV4lElement *v4lelement, GstV4lPictureType type, gint value);
|
||||||
|
|
||||||
/* audio control */
|
/* audio control */
|
||||||
gboolean gst_v4l_has_audio (GstV4lElement *v4lelement);
|
gboolean gst_v4l_has_audio (GstV4lElement *v4lelement);
|
||||||
gboolean gst_v4l_get_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);
|
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
|
#ifdef __cplusplus
|
||||||
|
|
Loading…
Reference in a new issue