/* V4l2Element signals and args */
enum {
/* FILL ME */
+ SIGNAL_OPEN,
+ SIGNAL_CLOSE,
LAST_SIGNAL
};
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,
static GstElementClass *parent_class = NULL;
-/*static guint gst_v4l2element_signals[LAST_SIGNAL] = { 0 }; */
+static guint gst_v4l2element_signals[LAST_SIGNAL] = { 0 };
GType
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",
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;
v4l2element->frequency = 0;
v4l2element->controls = NULL;
- v4l2element->formats = NULL;
v4l2element->outputs = NULL;
v4l2element->inputs = NULL;
v4l2element->norms = NULL;
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;
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))
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;
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))
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;
}
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 {
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;
struct _GstV4l2ElementClass {
GstElementClass parent_class;
+
+ /* signals */
+ void (*open) (GstElement *element,
+ const gchar *device);
+ void (*close) (GstElement *element,
+ const gchar *device);
};
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,
{
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);
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;
}
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));
}
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:
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);
}
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,
/* 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);
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;
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;
}
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));
/* 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;
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));
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));
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;
/* 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)
}
/* 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);
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);
goto error;
gst_info("Opened device '%s' (%s) successfully\n",
- v4l2element->vcap.name, v4l2element->device);
+ v4l2element->vcap.card, v4l2element->device);
return TRUE;
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));
/* 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;
}
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);
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;
}
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;
* 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;
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;
}
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;
}
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));
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;
}
input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, input_num);
- return (input->capability & V4L2_INPUT_CAP_AUDIO);
+ return (input->audioset != 0);
}
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);
(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"); \
/* 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"); \
/* 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"); \
/* 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"); \
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,
/******************************************************
+ * 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
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",
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),
}
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;
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;
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));
}
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);