summaryrefslogtreecommitdiffstats
path: root/sys/v4l2
diff options
context:
space:
mode:
Diffstat (limited to 'sys/v4l2')
-rw-r--r--sys/v4l2/gstv4l2element.c55
-rw-r--r--sys/v4l2/gstv4l2element.h21
-rw-r--r--sys/v4l2/gstv4l2src.c56
-rw-r--r--sys/v4l2/gstv4l2src.h5
-rw-r--r--sys/v4l2/v4l2-overlay_calls.c24
-rw-r--r--sys/v4l2/v4l2_calls.c167
-rw-r--r--sys/v4l2/v4l2_calls.h23
-rw-r--r--sys/v4l2/v4l2src_calls.c78
-rw-r--r--sys/v4l2/v4l2src_calls.h2
9 files changed, 274 insertions, 157 deletions
diff --git a/sys/v4l2/gstv4l2element.c b/sys/v4l2/gstv4l2element.c
index 2c3a304d..edff15b1 100644
--- a/sys/v4l2/gstv4l2element.c
+++ b/sys/v4l2/gstv4l2element.c
@@ -37,6 +37,8 @@ static GstElementDetails gst_v4l2element_details = {
/* V4l2Element signals and args */
enum {
/* FILL ME */
+ SIGNAL_OPEN,
+ SIGNAL_CLOSE,
LAST_SIGNAL
};
@@ -58,7 +60,7 @@ enum {
ARG_DEVICE_NAME,
ARG_DEVICE_HAS_CAPTURE,
ARG_DEVICE_HAS_OVERLAY,
- ARG_DEVICE_HAS_CODEC,
+ ARG_DEVICE_HAS_PLAYBACK,
ARG_DISPLAY,
ARG_VIDEOWINDOW,
ARG_DO_OVERLAY,
@@ -79,7 +81,7 @@ static GstElementStateReturn gst_v4l2element_change_state (GstElement *
static GstElementClass *parent_class = NULL;
-/*static guint gst_v4l2element_signals[LAST_SIGNAL] = { 0 }; */
+static guint gst_v4l2element_signals[LAST_SIGNAL] = { 0 };
GType
@@ -168,12 +170,12 @@ gst_v4l2element_class_init (GstV4l2ElementClass *klass)
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_HAS_CAPTURE,
g_param_spec_boolean("can_capture","can_capture","can_capture",
0,G_PARAM_READABLE));
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_HAS_PLAYBACK,
+ g_param_spec_boolean("can_playback","can_playback","can_playback",
+ 0,G_PARAM_READABLE));
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_HAS_OVERLAY,
g_param_spec_boolean("has_overlay","has_overlay","has_overlay",
0,G_PARAM_READABLE));
- g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_HAS_CODEC,
- g_param_spec_boolean("has_compression","has_compression","has_compression",
- 0,G_PARAM_READABLE));
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DISPLAY,
g_param_spec_string("display","display","display",
@@ -185,6 +187,18 @@ gst_v4l2element_class_init (GstV4l2ElementClass *klass)
g_param_spec_pointer("videowindow","videowindow","videowindow",
G_PARAM_WRITABLE));
+ /* signals */
+ gst_v4l2element_signals[SIGNAL_OPEN] =
+ g_signal_new("open", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GstV4l2ElementClass, open),
+ NULL, NULL, g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+ gst_v4l2element_signals[SIGNAL_CLOSE] =
+ g_signal_new("close", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GstV4l2ElementClass, close),
+ NULL, NULL, g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
gobject_class->set_property = gst_v4l2element_set_property;
gobject_class->get_property = gst_v4l2element_get_property;
@@ -206,7 +220,6 @@ gst_v4l2element_init (GstV4l2Element *v4l2element)
v4l2element->frequency = 0;
v4l2element->controls = NULL;
- v4l2element->formats = NULL;
v4l2element->outputs = NULL;
v4l2element->inputs = NULL;
v4l2element->norms = NULL;
@@ -277,7 +290,7 @@ gst_v4l2element_set_property (GObject *object,
GByteArray *array = (GByteArray *) g_value_get_pointer(value);
struct v4l2_clip *clips = (struct v4l2_clip *) array->data;
gst_v4l2_set_window(v4l2element,
- clips->x, clips->y, clips->width, clips->height,
+ clips->c.left, clips->c.top, clips->c.width, clips->c.height,
&clips[1], array->len/sizeof(struct v4l2_clip)-1);
}
break;
@@ -342,8 +355,8 @@ gst_v4l2element_get_property (GObject *object,
break;
case ARG_HAS_TUNER:
if (GST_V4L2_IS_OPEN(v4l2element))
- temp_i = gst_v4l2_has_tuner(v4l2element);
- g_value_set_boolean(value, temp_i>0?TRUE:FALSE);
+ g_value_set_boolean(value,
+ gst_v4l2_has_tuner(v4l2element, &temp_i));
break;
case ARG_FREQUENCY:
if (GST_V4L2_IS_OPEN(v4l2element))
@@ -376,25 +389,25 @@ gst_v4l2element_get_property (GObject *object,
break;
case ARG_DEVICE_NAME:
if (GST_V4L2_IS_OPEN(v4l2element))
- g_value_set_string(value, g_strdup(v4l2element->vcap.name));
+ g_value_set_string(value, g_strdup(v4l2element->vcap.card));
break;
case ARG_DEVICE_HAS_CAPTURE:
if (GST_V4L2_IS_OPEN(v4l2element) &&
- (v4l2element->vcap.type == V4L2_TYPE_CODEC ||
- v4l2element->vcap.type == V4L2_TYPE_CAPTURE) &&
- v4l2element->vcap.flags & V4L2_FLAG_STREAMING)
+ v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE &&
+ v4l2element->vcap.capabilities & V4L2_CAP_STREAMING)
temp_i = 1;
g_value_set_boolean(value, temp_i>0?TRUE:FALSE);
break;
case ARG_DEVICE_HAS_OVERLAY:
if (GST_V4L2_IS_OPEN(v4l2element) &&
- v4l2element->vcap.flags & V4L2_FLAG_PREVIEW)
+ v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
temp_i = 1;
g_value_set_boolean(value, temp_i>0?TRUE:FALSE);
break;
- case ARG_DEVICE_HAS_CODEC:
+ case ARG_DEVICE_HAS_PLAYBACK:
if (GST_V4L2_IS_OPEN(v4l2element) &&
- v4l2element->vcap.type == V4L2_TYPE_CODEC)
+ v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_OUTPUT &&
+ v4l2element->vcap.capabilities & V4L2_CAP_STREAMING)
temp_i = 1;
g_value_set_boolean(value, temp_i>0?TRUE:FALSE);
break;
@@ -422,6 +435,11 @@ gst_v4l2element_change_state (GstElement *element)
if (!gst_v4l2_open(v4l2element))
return GST_STATE_FAILURE;
+ /* emit a signal! whoopie! */
+ g_signal_emit(G_OBJECT(v4l2element),
+ gst_v4l2element_signals[SIGNAL_OPEN], 0,
+ v4l2element->device);
+
/* now, sync options */
if (v4l2element->norm >= 0)
if (!gst_v4l2_set_norm(v4l2element, v4l2element->norm))
@@ -439,6 +457,11 @@ gst_v4l2element_change_state (GstElement *element)
case GST_STATE_READY_TO_NULL:
if (!gst_v4l2_close(v4l2element))
return GST_STATE_FAILURE;
+
+ /* emit yet another signal! wheehee! */
+ g_signal_emit(G_OBJECT(v4l2element),
+ gst_v4l2element_signals[SIGNAL_CLOSE], 0,
+ v4l2element->device);
break;
}
diff --git a/sys/v4l2/gstv4l2element.h b/sys/v4l2/gstv4l2element.h
index b0e9fb7c..87ebaad9 100644
--- a/sys/v4l2/gstv4l2element.h
+++ b/sys/v4l2/gstv4l2element.h
@@ -41,21 +41,17 @@
typedef struct _GstV4l2Element GstV4l2Element;
typedef struct _GstV4l2ElementClass GstV4l2ElementClass;
-typedef struct _GstV4l2Rect {
- gint x, y, w, h;
-} GstV4l2Rect;
-
typedef enum {
- GST_V4L2_ATTRIBUTE_VALUE_TYPE_INT,
- GST_V4L2_ATTRIBUTE_VALUE_TYPE_BOOLEAN,
- GST_V4L2_ATTRIBUTE_VALUE_TYPE_BUTTON,
- GST_V4L2_ATTRIBUTE_VALUE_TYPE_LIST,
+ GST_V4L2_ATTRIBUTE_VALUE_TYPE_INTEGER = V4L2_CTRL_TYPE_INTEGER,
+ GST_V4L2_ATTRIBUTE_VALUE_TYPE_BOOLEAN = V4L2_CTRL_TYPE_BOOLEAN,
+ GST_V4L2_ATTRIBUTE_VALUE_TYPE_MENU = V4L2_CTRL_TYPE_MENU,
+ GST_V4L2_ATTRIBUTE_VALUE_TYPE_BUTTON = V4L2_CTRL_TYPE_BUTTON,
} GstV4l2AttributeValueType;
typedef enum {
GST_V4L2_ATTRIBUTE_TYPE_VIDEO,
GST_V4L2_ATTRIBUTE_TYPE_AUDIO,
- GST_V4L2_ATTRIBUTE_TYPE_EFFECT,
+ GST_V4L2_ATTRIBUTE_TYPE_OTHER,
} GstV4l2AttributeType;
typedef struct _GstV4l2Attribute {
@@ -83,7 +79,6 @@ struct _GstV4l2Element {
struct v4l2_capability vcap;
/* the toys available to us */
- GList /*v4l2_fmtdesc*/ *formats; /* list of available capture formats */
GList /*v4l2_input*/ *inputs;
GList /*v4l2_output*/ *outputs;
GList /*v4l2_enumstd*/ *norms;
@@ -99,6 +94,12 @@ struct _GstV4l2Element {
struct _GstV4l2ElementClass {
GstElementClass parent_class;
+
+ /* signals */
+ void (*open) (GstElement *element,
+ const gchar *device);
+ void (*close) (GstElement *element,
+ const gchar *device);
};
diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c
index 6ba0ea08..52a677d0 100644
--- a/sys/v4l2/gstv4l2src.c
+++ b/sys/v4l2/gstv4l2src.c
@@ -56,6 +56,12 @@ enum {
static void gst_v4l2src_class_init (GstV4l2SrcClass *klass);
static void gst_v4l2src_init (GstV4l2Src *v4l2src);
+/* signal functions */
+static void gst_v4l2src_open (GstElement *element,
+ const gchar *device);
+static void gst_v4l2src_close (GstElement *element,
+ const gchar *device);
+
/* pad/buffer functions */
static gboolean gst_v4l2src_srcconvert (GstPad *pad,
GstFormat src_format,
@@ -127,9 +133,11 @@ gst_v4l2src_class_init (GstV4l2SrcClass *klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
+ GstV4l2ElementClass *v4l2_class;
gobject_class = (GObjectClass*)klass;
gstelement_class = (GstElementClass*)klass;
+ v4l2_class = (GstV4l2ElementClass*)klass;
parent_class = g_type_class_ref(GST_TYPE_V4L2ELEMENT);
@@ -164,6 +172,9 @@ gst_v4l2src_class_init (GstV4l2SrcClass *klass)
gobject_class->get_property = gst_v4l2src_get_property;
gstelement_class->change_state = gst_v4l2src_change_state;
+
+ v4l2_class->open = gst_v4l2src_open;
+ v4l2_class->close = gst_v4l2src_close;
}
@@ -188,6 +199,24 @@ gst_v4l2src_init (GstV4l2Src *v4l2src)
v4l2src->width = 160;
v4l2src->height = 120;
v4l2src->breq.count = 0;
+
+ v4l2src->formats = NULL;
+}
+
+
+static void
+gst_v4l2src_open (GstElement *element,
+ const gchar *device)
+{
+ gst_v4l2src_fill_format_list(GST_V4L2SRC(element));
+}
+
+
+static void
+gst_v4l2src_close (GstElement *element,
+ const gchar *device)
+{
+ gst_v4l2src_empty_format_list(GST_V4L2SRC(element));
}
@@ -211,8 +240,8 @@ gst_v4l2src_srcconvert (GstPad *pad,
if (!gst_v4l2_get_norm(GST_V4L2ELEMENT(v4l2src), &norm))
return FALSE;
- std = &((struct v4l2_enumstd *) g_list_nth_data(GST_V4L2ELEMENT(v4l2src)->norms, norm))->std;
- fps = std->framerate.numerator / std->framerate.denominator;
+ std = ((struct v4l2_standard *) g_list_nth_data(GST_V4L2ELEMENT(v4l2src)->norms, norm));
+ fps = std->frameperiod.numerator / std->frameperiod.denominator;
switch (src_format) {
case GST_FORMAT_TIME:
@@ -453,8 +482,8 @@ gst_v4l2_caps_to_v4l2fourcc (GstV4l2Src *v4l2src,
break; }
}
- for (i=0;i<g_list_length(GST_V4L2ELEMENT(v4l2src)->formats);i++) {
- struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(GST_V4L2ELEMENT(v4l2src)->formats, i);
+ for (i=0;i<g_list_length(v4l2src->formats);i++) {
+ struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2src->formats, i);
if (fmt->pixelformat == fourcc)
fourcclist = g_list_append(fourcclist, (gpointer)fourcc);
}
@@ -585,8 +614,8 @@ gst_v4l2src_srcconnect (GstPad *pad,
for (i=0;i<g_list_length(fourccs);i++) {
guint32 fourcc = (guint32)g_list_nth_data(fourccs, i);
gint n;
- for (n=0;n<g_list_length(v4l2element->formats);n++) {
- struct v4l2_fmtdesc *format = g_list_nth_data(v4l2element->formats, n);
+ for (n=0;n<g_list_length(v4l2src->formats);n++) {
+ struct v4l2_fmtdesc *format = g_list_nth_data(v4l2src->formats, n);
if (format->pixelformat == fourcc) {
/* we found the pixelformat! - try it out */
if (gst_v4l2src_set_capture(v4l2src, format,
@@ -631,15 +660,15 @@ gst_v4l2src_getcaps (GstPad *pad,
/* build our own capslist */
if (v4l2src->palette) {
- struct v4l2_fmtdesc *format = g_list_nth_data(v4l2element->formats, v4l2src->palette);
+ struct v4l2_fmtdesc *format = g_list_nth_data(v4l2src->formats, v4l2src->palette);
owncapslist = gst_v4l2src_v4l2fourcc_to_caps(format->pixelformat,
v4l2src->width, v4l2src->height,
format->flags & V4L2_FMT_FLAG_COMPRESSED);
} else {
gint i;
owncapslist = NULL;
- for (i=0;i<g_list_length(v4l2element->formats);i++) {
- struct v4l2_fmtdesc *format = g_list_nth_data(v4l2element->formats, i);
+ for (i=0;i<g_list_length(v4l2src->formats);i++) {
+ struct v4l2_fmtdesc *format = g_list_nth_data(v4l2src->formats, i);
caps = gst_v4l2src_v4l2fourcc_to_caps(format->pixelformat,
v4l2src->width, v4l2src->height,
format->flags & V4L2_FMT_FLAG_COMPRESSED);
@@ -675,7 +704,8 @@ gst_v4l2src_get (GstPad *pad)
GST_BUFFER_DATA(buf) = GST_V4L2ELEMENT(v4l2src)->buffer[num];
GST_BUFFER_SIZE(buf) = v4l2src->bufsettings.bytesused;
if (!v4l2src->first_timestamp)
- v4l2src->first_timestamp = v4l2src->bufsettings.timestamp;
+ v4l2src->first_timestamp = v4l2src->bufsettings.timestamp.tv_sec * GST_SECOND +
+ v4l2src->bufsettings.timestamp.tv_usec * (GST_SECOND/1000000);
GST_BUFFER_TIMESTAMP(buf) = v4l2src->bufsettings.length - v4l2src->first_timestamp;
return buf;
@@ -717,8 +747,8 @@ gst_v4l2src_set_property (GObject *object,
gint i;
const gchar *formatstr = g_value_get_string(value);
guint32 fourcc = GST_MAKE_FOURCC(formatstr[0],formatstr[1],formatstr[2],formatstr[3]);
- for (i=0;i<g_list_length(GST_V4L2ELEMENT(v4l2src)->formats);i++) {
- struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(GST_V4L2ELEMENT(v4l2src)->formats, i);
+ for (i=0;i<g_list_length(v4l2src->formats);i++) {
+ struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2src->formats, i);
if (fmt->pixelformat == fourcc)
v4l2src->palette = i;
}
@@ -767,7 +797,7 @@ gst_v4l2src_get_property (GObject *object,
break;
case ARG_FOURCC: {
- struct v4l2_fmtdesc *fmt = g_list_nth_data(GST_V4L2ELEMENT(v4l2src)->formats, v4l2src->palette);
+ struct v4l2_fmtdesc *fmt = g_list_nth_data(v4l2src->formats, v4l2src->palette);
guint32 print_format = GUINT32_FROM_LE(fmt->pixelformat);
gchar *print_format_str = (gchar *) &print_format;
g_value_set_string(value, g_strndup(print_format_str, 4));
diff --git a/sys/v4l2/gstv4l2src.h b/sys/v4l2/gstv4l2src.h
index 004347ab..d287076b 100644
--- a/sys/v4l2/gstv4l2src.h
+++ b/sys/v4l2/gstv4l2src.h
@@ -44,11 +44,14 @@ struct _GstV4l2Src {
/* pads */
GstPad *srcpad;
+ /* internal lists */
+ GList /*v4l2_fmtdesc*/ *formats; /* list of available capture formats */
+
/* buffer properties */
struct v4l2_buffer bufsettings;
struct v4l2_requestbuffers breq;
struct v4l2_format format;
- stamp_t first_timestamp;
+ guint64 first_timestamp;
/* bufferpool for the buffers we're gonna use */
GstBufferPool *bufferpool;
diff --git a/sys/v4l2/v4l2-overlay_calls.c b/sys/v4l2/v4l2-overlay_calls.c
index abf11858..ad3ec78a 100644
--- a/sys/v4l2/v4l2-overlay_calls.c
+++ b/sys/v4l2/v4l2-overlay_calls.c
@@ -89,21 +89,23 @@ gst_v4l2_set_window (GstV4l2Element *v4l2element,
struct v4l2_clip *clips,
gint num_clips)
{
- struct v4l2_window vwin;
+ struct v4l2_format fmt;
DEBUG("trying to set video window to %dx%d,%d,%d", x,y,w,h);
GST_V4L2_CHECK_OVERLAY(v4l2element);
GST_V4L2_CHECK_OPEN(v4l2element);
- vwin.clipcount = 0;
- vwin.x = x;
- vwin.y = y;
- vwin.width = w;
- vwin.height = h;
- vwin.clips = clips;
- vwin.clipcount = num_clips;
-
- if (ioctl(v4l2element->video_fd, VIDIOC_S_WIN, &vwin) < 0) {
+ fmt.type = V4L2_CAP_VIDEO_OVERLAY;
+ fmt.fmt.win.clipcount = 0;
+ fmt.fmt.win.w.left = x;
+ fmt.fmt.win.w.top = y;
+ fmt.fmt.win.w.width = w;
+ fmt.fmt.win.w.height = h;
+ fmt.fmt.win.clips = clips;
+ fmt.fmt.win.clipcount = num_clips;
+ fmt.fmt.win.bitmap = NULL;
+
+ if (ioctl(v4l2element->video_fd, VIDIOC_S_FMT, &fmt) < 0) {
gst_element_error(GST_ELEMENT(v4l2element),
"Failed to set the video window on device %s: %s",
v4l2element->device, g_strerror(errno));
@@ -130,7 +132,7 @@ gst_v4l2_enable_overlay (GstV4l2Element *v4l2element,
GST_V4L2_CHECK_OPEN(v4l2element);
GST_V4L2_CHECK_OVERLAY(v4l2element);
- if (ioctl(v4l2element->video_fd, VIDIOC_PREVIEW, &doit) < 0) {
+ if (ioctl(v4l2element->video_fd, VIDIOC_OVERLAY, &doit) < 0) {
gst_element_error(GST_ELEMENT(v4l2element),
"Failed to %s overlay display for device %s: %s",
enable?"enable":"disable", v4l2element->device, g_strerror(errno));
diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c
index e09505c2..cb108416 100644
--- a/sys/v4l2/v4l2_calls.c
+++ b/sys/v4l2/v4l2_calls.c
@@ -73,25 +73,6 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element)
DEBUG("getting enumerations");
GST_V4L2_CHECK_OPEN(v4l2element);
- /* create enumeration lists - let's start with format enumeration */
- for (n=0;;n++) {
- struct v4l2_fmtdesc format, *fmtptr;
- format.index = n;
- if (ioctl(v4l2element->video_fd, VIDIOC_ENUM_PIXFMT, &format) < 0) {
- if (errno == EINVAL)
- break; /* end of enumeration */
- else {
- gst_element_error(GST_ELEMENT(v4l2element),
- "Failed to get no. %d in pixelformat enumeration for %s: %s",
- n, v4l2element->device, g_strerror(errno));
- return FALSE;
- }
- }
- fmtptr = g_malloc(sizeof(format));
- memcpy(fmtptr, &format, sizeof(format));
- v4l2element->formats = g_list_append(v4l2element->formats, fmtptr);
- }
-
/* and now, the inputs */
for (n=0;;n++) {
struct v4l2_input input, *inpptr;
@@ -132,7 +113,7 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element)
/* norms... */
for (n=0;;n++) {
- struct v4l2_enumstd standard, *stdptr;
+ struct v4l2_standard standard, *stdptr;
standard.index = n;
if (ioctl(v4l2element->video_fd, VIDIOC_ENUMSTD, &standard) < 0) {
if (errno == EINVAL)
@@ -150,20 +131,28 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element)
}
/* and lastly, controls+menus (if appropriate) */
- for (n=0;;n++) {
+ for (n=V4L2_CID_BASE;;n++) {
struct v4l2_queryctrl control, *ctrlptr;
GList *menus = NULL;
+ /* hacky... */
+ if (n == V4L2_CID_LASTP1)
+ n = V4L2_CID_PRIVATE_BASE;
control.id = n;
if (ioctl(v4l2element->video_fd, VIDIOC_QUERYCTRL, &control) < 0) {
- if (errno == EINVAL)
- break; /* end of enumeration */
- else {
+ if (errno == EINVAL) {
+ if (n < V4L2_CID_PRIVATE_BASE)
+ continue;
+ else
+ break;
+ } else {
gst_element_error(GST_ELEMENT(v4l2element),
"Failed to get no. %d in control enumeration for %s: %s",
n, v4l2element->device, g_strerror(errno));
return FALSE;
}
}
+ if (control.flags & V4L2_CTRL_FLAG_DISABLED)
+ continue;
ctrlptr = g_malloc(sizeof(control));
memcpy(ctrlptr, &control, sizeof(control));
v4l2element->controls = g_list_append(v4l2element->controls, ctrlptr);
@@ -216,11 +205,6 @@ gst_v4l2_empty_lists (GstV4l2Element *v4l2element)
v4l2element->norms = g_list_remove(v4l2element->norms, data);
g_free(data);
}
- while (g_list_length(v4l2element->formats) > 0) {
- gpointer data = g_list_nth_data(v4l2element->formats, 0);
- v4l2element->formats = g_list_remove(v4l2element->formats, data);
- g_free(data);
- }
while (g_list_length(v4l2element->controls) > 0) {
gpointer data = g_list_nth_data(v4l2element->controls, 0);
v4l2element->controls = g_list_remove(v4l2element->controls, data);
@@ -275,7 +259,7 @@ gst_v4l2_open (GstV4l2Element *v4l2element)
goto error;
gst_info("Opened device '%s' (%s) successfully\n",
- v4l2element->vcap.name, v4l2element->device);
+ v4l2element->vcap.card, v4l2element->device);
return TRUE;
@@ -326,13 +310,13 @@ gboolean
gst_v4l2_get_norm (GstV4l2Element *v4l2element,
gint *norm)
{
- struct v4l2_standard standard;
+ v4l2_std_id std_id;
gint n;
DEBUG("getting norm");
GST_V4L2_CHECK_OPEN(v4l2element);
- if (ioctl(v4l2element->video_fd, VIDIOC_G_STD, &standard) < 0) {
+ if (ioctl(v4l2element->video_fd, VIDIOC_G_STD, &std_id) < 0) {
gst_element_error(GST_ELEMENT(v4l2element),
"Failed to get the current norm for device %s: %s",
v4l2element->device, g_strerror(errno));
@@ -341,16 +325,16 @@ gst_v4l2_get_norm (GstV4l2Element *v4l2element,
/* try to find out what norm number this actually is */
for (n=0;n<g_list_length(v4l2element->norms);n++) {
- struct v4l2_enumstd *stdptr = (struct v4l2_enumstd *) g_list_nth_data(v4l2element->norms, n);
- if (!strcmp(stdptr->std.name, standard.name)) {
+ struct v4l2_standard *stdptr = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, n);
+ if (stdptr->id == std_id) {
*norm = n;
return TRUE;
}
}
gst_element_error(GST_ELEMENT(v4l2element),
- "Failed to find norm '%s' in our list of available norms for device %s",
- standard.name, v4l2element->device);
+ "Failed to find norm '%llu' in our list of available norms for device %s",
+ std_id, v4l2element->device);
return FALSE;
}
@@ -365,7 +349,7 @@ gboolean
gst_v4l2_set_norm (GstV4l2Element *v4l2element,
gint norm)
{
- struct v4l2_enumstd *standard;
+ struct v4l2_standard *standard;
DEBUG("trying to set norm to %d", norm);
GST_V4L2_CHECK_OPEN(v4l2element);
@@ -378,12 +362,12 @@ gst_v4l2_set_norm (GstV4l2Element *v4l2element,
return FALSE;
}
- standard = (struct v4l2_enumstd *) g_list_nth_data(v4l2element->norms, norm);
+ standard = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, norm);
- if (ioctl(v4l2element->video_fd, VIDIOC_S_STD, &standard->std) < 0) {
+ if (ioctl(v4l2element->video_fd, VIDIOC_S_STD, &standard->id) < 0) {
gst_element_error(GST_ELEMENT(v4l2element),
- "Failed to set norm '%s' (%d) for device %s: %s",
- standard->std.name, norm, v4l2element->device, g_strerror(errno));
+ "Failed to set norm '%s' (%llu) for device %s: %s",
+ standard->name, standard->id, v4l2element->device, g_strerror(errno));
return FALSE;
}
@@ -406,8 +390,8 @@ gst_v4l2_get_norm_names (GstV4l2Element *v4l2element)
DEBUG("getting a list of norm names");
for (n=0;n<g_list_length(v4l2element->norms);n++) {
- struct v4l2_enumstd *standard = (struct v4l2_enumstd *) g_list_nth_data(v4l2element->norms, n);
- names = g_list_append(names, g_strdup(standard->std.name));
+ struct v4l2_standard *standard = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, n);
+ names = g_list_append(names, g_strdup(standard->name));
}
return names;
@@ -586,8 +570,9 @@ gst_v4l2_get_output_names (GstV4l2Element *v4l2element)
* return value: TRUE if it has a tuner, else FALSE
******************************************************/
-gboolean
-gst_v4l2_has_tuner (GstV4l2Element *v4l2element)
+gint
+gst_v4l2_has_tuner (GstV4l2Element *v4l2element,
+ gint *tuner_num)
{
gint input_num;
struct v4l2_input *input;
@@ -600,8 +585,12 @@ gst_v4l2_has_tuner (GstV4l2Element *v4l2element)
input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, input_num);
- return (input->type == V4L2_INPUT_TYPE_TUNER &&
- v4l2element->vcap.flags & V4L2_FLAG_TUNER);
+ if (input->type == V4L2_INPUT_TYPE_TUNER &&
+ v4l2element->vcap.capabilities & V4L2_CAP_TUNER) {
+ *tuner_num = input->tuner;
+ return TRUE;
+ }
+ return FALSE;
}
@@ -615,22 +604,24 @@ gboolean
gst_v4l2_get_frequency (GstV4l2Element *v4l2element,
gulong *frequency)
{
- gint n;
+ struct v4l2_frequency freq;
DEBUG("getting current tuner frequency");
GST_V4L2_CHECK_OPEN(v4l2element);
- if (!gst_v4l2_has_tuner(v4l2element))
+ if (!gst_v4l2_has_tuner(v4l2element, &freq.tuner))
return FALSE;
- if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQ, &n) < 0) {
+ freq.type = 0;
+
+ if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) {
gst_element_error(GST_ELEMENT(v4l2element),
"Failed to get current tuner frequency for device %s: %s",
v4l2element->device, g_strerror(errno));
return FALSE;
}
- *frequency = n;
+ *frequency = freq.frequency;
return TRUE;
}
@@ -646,16 +637,19 @@ gboolean
gst_v4l2_set_frequency (GstV4l2Element *v4l2element,
gulong frequency)
{
- gint n = frequency;
+ struct v4l2_frequency freq;
DEBUG("setting current tuner frequency to %lu", frequency);
GST_V4L2_CHECK_OPEN(v4l2element);
GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
- if (!gst_v4l2_has_tuner(v4l2element))
+ if (!gst_v4l2_has_tuner(v4l2element, &freq.tuner))
return FALSE;
- if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQ, &n) < 0) {
+ freq.frequency = frequency;
+ freq.type = 0;
+
+ if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) {
gst_element_error(GST_ELEMENT(v4l2element),
"Failed to set tuner frequency to %lu for device %s: %s",
frequency, v4l2element->device, g_strerror(errno));
@@ -683,7 +677,7 @@ gst_v4l2_signal_strength (GstV4l2Element *v4l2element,
if (ioctl(v4l2element->video_fd, VIDIOC_G_TUNER, &tuner) < 0) {
gst_element_error(GST_ELEMENT(v4l2element),
- "Failed to set signal strength for device %s: %s",
+ "Failed to get signal strength for device %s: %s",
v4l2element->device, g_strerror(errno));
return FALSE;
}
@@ -714,7 +708,7 @@ gst_v4l2_has_audio (GstV4l2Element *v4l2element)
input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, input_num);
- return (input->capability & V4L2_INPUT_CAP_AUDIO);
+ return (input->audioset != 0);
}
@@ -738,36 +732,47 @@ gst_v4l2_get_attributes (GstV4l2Element *v4l2element)
attribute->name = g_strdup(control->name);
attribute->index = i;
attribute->list_items = NULL;
- switch (control->type) {
- case V4L2_CTRL_TYPE_INTEGER:
- attribute->val_type = GST_V4L2_ATTRIBUTE_VALUE_TYPE_INT;
- break;
- case V4L2_CTRL_TYPE_BOOLEAN:
- attribute->val_type = GST_V4L2_ATTRIBUTE_VALUE_TYPE_BOOLEAN;
- break;
- case V4L2_CTRL_TYPE_MENU: {
- /* list items */
- gint n;
- GList *menus = (GList *) g_list_nth_data(v4l2element->menus, i);
- for (n=0;n<g_list_length(menus);n++) {
- struct v4l2_querymenu *menu = g_list_nth_data(menus, n);
- attribute->list_items = g_list_append(attribute->list_items, g_strdup(menu->name));
- }
- attribute->val_type = GST_V4L2_ATTRIBUTE_VALUE_TYPE_LIST;
- break; }
- case V4L2_CTRL_TYPE_BUTTON:
- attribute->val_type = GST_V4L2_ATTRIBUTE_VALUE_TYPE_BUTTON;
- break;
+ attribute->val_type = control->type;
+ if (control->type == V4L2_CTRL_TYPE_MENU) {
+ /* list items */
+ gint n;
+ GList *menus = (GList *) g_list_nth_data(v4l2element->menus, i);
+ for (n=0;n<g_list_length(menus);n++) {
+ struct v4l2_querymenu *menu = g_list_nth_data(menus, n);
+ attribute->list_items = g_list_append(attribute->list_items,
+ g_strdup(menu->name));
+ }
}
- switch (control->category) {
- case V4L2_CTRL_CAT_VIDEO:
+ switch (control->id) {
+ case V4L2_CID_BRIGHTNESS:
+ case V4L2_CID_CONTRAST:
+ case V4L2_CID_SATURATION:
+ case V4L2_CID_HUE:
+ case V4L2_CID_BLACK_LEVEL:
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ case V4L2_CID_DO_WHITE_BALANCE:
+ case V4L2_CID_RED_BALANCE:
+ case V4L2_CID_BLUE_BALANCE:
+ case V4L2_CID_GAMMA:
+ case V4L2_CID_EXPOSURE:
+ case V4L2_CID_AUTOGAIN:
+ case V4L2_CID_GAIN:
+ case V4L2_CID_HFLIP:
+ case V4L2_CID_VFLIP:
+ case V4L2_CID_HCENTER:
+ case V4L2_CID_VCENTER:
attribute->type = GST_V4L2_ATTRIBUTE_TYPE_VIDEO;
break;
- case V4L2_CTRL_CAT_AUDIO:
+ case V4L2_CID_AUDIO_VOLUME:
+ case V4L2_CID_AUDIO_BALANCE:
+ case V4L2_CID_AUDIO_BASS:
+ case V4L2_CID_AUDIO_TREBLE:
+ case V4L2_CID_AUDIO_MUTE:
+ case V4L2_CID_AUDIO_LOUDNESS:
attribute->type = GST_V4L2_ATTRIBUTE_TYPE_AUDIO;
break;
- case V4L2_CTRL_CAT_EFFECT:
- attribute->type = GST_V4L2_ATTRIBUTE_TYPE_EFFECT;
+ default:
+ attribute->type = GST_V4L2_ATTRIBUTE_TYPE_OTHER;
break;
}
gst_v4l2_get_attribute(v4l2element, i, &attribute->value);
diff --git a/sys/v4l2/v4l2_calls.h b/sys/v4l2/v4l2_calls.h
index de0bbc9e..db9adc08 100644
--- a/sys/v4l2/v4l2_calls.h
+++ b/sys/v4l2/v4l2_calls.h
@@ -32,11 +32,11 @@
(v4l2element->buffer != NULL)
#define GST_V4L2_IS_OVERLAY(v4l2element) \
- (v4l2element->vcap.flags & V4L2_FLAG_PREVIEW)
+ (v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
/* checks whether the current v4lelement has already been open()'ed or not */
#define GST_V4L2_CHECK_OPEN(v4l2element) \
- if (v4l2element->video_fd <= 0) \
+ if (!GST_V4L2_IS_OPEN(v4l2element)) \
{ \
gst_element_error(GST_ELEMENT(v4l2element), \
"Device is not open"); \
@@ -45,7 +45,7 @@
/* checks whether the current v4lelement is close()'ed or whether it is still open */
#define GST_V4L2_CHECK_NOT_OPEN(v4l2element) \
- if (v4l2element->video_fd != -1) \
+ if (GST_V4L2_IS_OPEN(v4l2element)) \
{ \
gst_element_error(GST_ELEMENT(v4l2element), \
"Device is open"); \
@@ -54,16 +54,16 @@
/* checks whether the current v4lelement does video overlay */
#define GST_V4L2_CHECK_OVERLAY(v4l2element) \
- if (!(v4l2element->vcap.flags & V4L2_FLAG_PREVIEW)) \
- { \
- gst_element_error(GST_ELEMENT(v4l2element), \
- "Device doesn't do overlay"); \
- return FALSE; \
+ if (!GST_V4L2_IS_OVERLAY(v4l2element)) \
+ { \
+ gst_element_error(GST_ELEMENT(v4l2element), \
+ "Device doesn't do overlay"); \
+ return FALSE; \
}
/* checks whether we're in capture mode or not */
#define GST_V4L2_CHECK_ACTIVE(v4l2element) \
- if (v4l2element->buffer == NULL) \
+ if (!GST_V4L2_IS_ACTIVE(v4l2element)) \
{ \
gst_element_error(GST_ELEMENT(v4l2element), \
"Device is not in streaming mode"); \
@@ -72,7 +72,7 @@
/* checks whether we're out of capture mode or not */
#define GST_V4L2_CHECK_NOT_ACTIVE(v4l2element) \
- if (v4l2element->buffer != NULL) \
+ if (GST_V4L2_IS_ACTIVE(v4l2element)) \
{ \
gst_element_error(GST_ELEMENT(v4l2element), \
"Device is in streaming mode"); \
@@ -102,7 +102,8 @@ gboolean gst_v4l2_set_output (GstV4l2Element *v4l2element,
GList * gst_v4l2_get_output_names (GstV4l2Element *v4l2element);
/* frequency control */
-gboolean gst_v4l2_has_tuner (GstV4l2Element *v4l2element);
+gboolean gst_v4l2_has_tuner (GstV4l2Element *v4l2element,
+ gint *tuner_num);
gboolean gst_v4l2_get_frequency (GstV4l2Element *v4l2element,
gulong *frequency);
gboolean gst_v4l2_set_frequency (GstV4l2Element *v4l2element,
diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c
index 9215de17..a6f244fe 100644
--- a/sys/v4l2/v4l2src_calls.c
+++ b/sys/v4l2/v4l2src_calls.c
@@ -42,6 +42,62 @@
/******************************************************
+ * gst_v4l2src_fill_format_list():
+ * create list of supported capture formats
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+
+gboolean
+gst_v4l2src_fill_format_list (GstV4l2Src *v4l2src)
+{
+ gint n;
+
+ DEBUG("getting src format enumerations");
+
+ /* format enumeration */
+ for (n=0;;n++) {
+ struct v4l2_fmtdesc format, *fmtptr;
+ format.index = n;
+ format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (ioctl(GST_V4L2ELEMENT(v4l2src)->video_fd, VIDIOC_ENUM_FMT, &format) < 0) {
+ if (errno == EINVAL)
+ break; /* end of enumeration */
+ else {
+ gst_element_error(GST_ELEMENT(v4l2src),
+ "Failed to get no. %d in pixelformat enumeration for %s: %s",
+ n, GST_V4L2ELEMENT(v4l2src)->device, g_strerror(errno));
+ return FALSE;
+ }
+ }
+ fmtptr = g_malloc(sizeof(format));
+ memcpy(fmtptr, &format, sizeof(format));
+ v4l2src->formats = g_list_append(v4l2src->formats, fmtptr);
+ }
+
+ return TRUE;
+}
+
+
+/******************************************************
+ * gst_v4l2src_empty_format_list():
+ * free list of supported capture formats
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+
+gboolean
+gst_v4l2src_empty_format_list (GstV4l2Src *v4l2src)
+{
+ while (g_list_length(v4l2src->formats) > 0) {
+ gpointer data = g_list_nth_data(v4l2src->formats, 0);
+ v4l2src->formats = g_list_remove(v4l2src->formats, data);
+ g_free(data);
+ }
+
+ return TRUE;
+}
+
+
+/******************************************************
* gst_v4l2src_queue_frame():
* queue a frame for capturing
* return value: TRUE on success, FALSE on error
@@ -101,6 +157,7 @@ gst_v4l2src_get_capture (GstV4l2Src *v4l2src)
GST_V4L2_CHECK_OPEN(GST_V4L2ELEMENT(v4l2src));
+ v4l2src->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(GST_V4L2ELEMENT(v4l2src)->video_fd, VIDIOC_G_FMT, &v4l2src->format) < 0) {
gst_element_error(GST_ELEMENT(v4l2src),
"Failed to get pixel format for device %s: %s",
@@ -134,12 +191,7 @@ gst_v4l2src_set_capture (GstV4l2Src *v4l2src,
v4l2src->format.fmt.pix.width = width;
v4l2src->format.fmt.pix.height = height;
v4l2src->format.fmt.pix.pixelformat = fmt->pixelformat;
- if (fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
- v4l2src->format.fmt.pix.flags = V4L2_FMT_FLAG_COMPRESSED;
- v4l2src->format.type = V4L2_BUF_TYPE_CODECIN;
- } else {
- v4l2src->format.type = V4L2_BUF_TYPE_CAPTURE;
- }
+ v4l2src->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(GST_V4L2ELEMENT(v4l2src)->video_fd, VIDIOC_S_FMT, &v4l2src->format) < 0) {
gst_element_error(GST_ELEMENT(v4l2src),
@@ -189,8 +241,8 @@ gst_v4l2src_capture_init (GstV4l2Src *v4l2src)
}
v4l2src->bufsettings.type = v4l2src->format.type;
- for (n=0;n<g_list_length(GST_V4L2ELEMENT(v4l2src)->formats);n++) {
- struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(GST_V4L2ELEMENT(v4l2src)->formats, n);
+ for (n=0;n<g_list_length(v4l2src->formats);n++) {
+ struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2src->formats, n);
if (v4l2src->format.fmt.pix.pixelformat == fmt->pixelformat) {
desc = fmt->description;
break;
@@ -359,11 +411,10 @@ GList *
gst_v4l2src_get_fourcc_list (GstV4l2Src *v4l2src)
{
GList *list = NULL;
- GstV4l2Element *v4l2element = GST_V4L2ELEMENT(v4l2src);
gint n;
- for (n=0;n<g_list_length(v4l2element->formats);n++) {
- struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2element->formats, n);
+ for (n=0;n<g_list_length(v4l2src->formats);n++) {
+ struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2src->formats, n);
guint32 print_format = GUINT32_FROM_LE(fmt->pixelformat);
gchar *print_format_str = (gchar *) &print_format;
@@ -384,11 +435,10 @@ GList *
gst_v4l2src_get_format_list (GstV4l2Src *v4l2src)
{
GList *list = NULL;
- GstV4l2Element *v4l2element = GST_V4L2ELEMENT(v4l2src);
gint n;
- for (n=0;n<g_list_length(v4l2element->formats);n++) {
- struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2element->formats, n);
+ for (n=0;n<g_list_length(v4l2src->formats);n++) {
+ struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2src->formats, n);
list = g_list_append(list, g_strdup(fmt->description));
}
diff --git a/sys/v4l2/v4l2src_calls.h b/sys/v4l2/v4l2src_calls.h
index c9a108a7..436f65dc 100644
--- a/sys/v4l2/v4l2src_calls.h
+++ b/sys/v4l2/v4l2src_calls.h
@@ -38,6 +38,8 @@ gboolean gst_v4l2src_requeue_frame (GstV4l2Src *v4l2src,
gboolean gst_v4l2src_capture_stop (GstV4l2Src *v4l2src);
gboolean gst_v4l2src_capture_deinit (GstV4l2Src *v4l2src);
+gboolean gst_v4l2src_fill_format_list (GstV4l2Src *v4l2src);
+gboolean gst_v4l2src_empty_format_list (GstV4l2Src *v4l2src);
GList * gst_v4l2src_get_fourcc_list (GstV4l2Src *v4l2src);
GList * gst_v4l2src_get_format_list (GstV4l2Src *v4l2src);