Updated all plugins to new capsnego format and added some small usability enhancements to v4lelement

Original commit message from CVS:
Updated all plugins to new capsnego format and added some small usability enhancements to v4lelement
This commit is contained in:
Ronald S. Bultje 2002-01-15 15:52:09 +00:00
parent 3333429a0d
commit 6dd1750d19
9 changed files with 464 additions and 323 deletions

View file

@ -39,7 +39,9 @@ enum {
enum {
ARG_0,
ARG_CHANNEL,
ARG_CHANNEL_NAME,
ARG_NORM,
ARG_NORM_NAME,
ARG_HAS_TUNER,
ARG_FREQUENCY,
ARG_HAS_AUDIO,
@ -119,9 +121,15 @@ gst_v4lelement_class_init (GstV4lElementClass *klass)
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CHANNEL,
g_param_spec_int("channel","channel","channel",
G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CHANNEL_NAME,
g_param_spec_string("channel_name","channel_name","channel_name",
NULL, G_PARAM_READABLE));
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NORM,
g_param_spec_int("norm","norm","norm",
G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NORM_NAME,
g_param_spec_string("norm_name","norm_name","norm_name",
NULL, G_PARAM_READABLE));
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HAS_TUNER,
g_param_spec_boolean("has_tuner","has_tuner","has_tuner",
@ -159,10 +167,9 @@ gst_v4lelement_class_init (GstV4lElementClass *klass)
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE,
g_param_spec_string("device","device","device",
NULL, G_PARAM_READWRITE));
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_NAME,
g_param_spec_string("device_name","device_name","device_name",
NULL, G_PARAM_READWRITE));
NULL, G_PARAM_READABLE));
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_IS_CAPTURE,
g_param_spec_boolean("can_capture","can_capture","can_capture",
@ -326,7 +333,7 @@ gst_v4lelement_set_property (GObject *object,
v4lelement->videodev = g_strdup(g_value_get_string(value));
break;
default:
//G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
@ -353,11 +360,26 @@ gst_v4lelement_get_property (GObject *object,
gst_v4l_get_chan_norm(v4lelement, &temp_i, NULL);
g_value_set_int(value, temp_i);
break;
case ARG_CHANNEL_NAME:
if (GST_V4L_IS_OPEN(v4lelement))
g_value_set_string(value, g_strdup(v4lelement->vchan.name));
else
g_value_set_string(value, g_strdup("Unknown"));
break;
case ARG_NORM:
if (GST_V4L_IS_OPEN(v4lelement))
gst_v4l_get_chan_norm(v4lelement, NULL, &temp_i);
g_value_set_int(value, temp_i);
break;
case ARG_NORM_NAME:
if (GST_V4L_IS_OPEN(v4lelement))
{
gst_v4l_get_chan_norm(v4lelement, NULL, &temp_i);
g_value_set_string(value, g_strdup(norm_name[temp_i]));
}
else
g_value_set_string(value, g_strdup("Unknwon"));
break;
case ARG_HAS_TUNER:
g_value_set_boolean(value, FALSE);
if (GST_V4L_IS_OPEN(v4lelement))
@ -454,7 +476,7 @@ gst_v4lelement_get_property (GObject *object,
g_value_set_boolean(value, v4lelement->vcap.type & VID_TYPE_MPEG_DECODER);
break;
default:
//G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}

View file

@ -58,6 +58,9 @@ struct _GstV4lElement {
/* the video-device's capabilities */
struct video_capability vcap;
/* some more info about the current input's capabilities */
struct video_channel vchan;
/* caching values */
gint channel;
gint norm;

View file

@ -46,24 +46,14 @@ enum {
ARG_FRAME_TIME,
};
GST_PADTEMPLATE_FACTORY (sink_template,
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"v4lmjpegsink_caps",
"video/jpeg",
"width", GST_PROPS_INT_RANGE (0, G_MAXINT),
"height", GST_PROPS_INT_RANGE (0, G_MAXINT)
)
)
/* init functions */
static void gst_v4lmjpegsink_class_init (GstV4lMjpegSinkClass *klass);
static void gst_v4lmjpegsink_init (GstV4lMjpegSink *v4lmjpegsink);
/* the chain of buffers */
static GstPadConnectReturn gst_v4lmjpegsink_sinkconnect (GstPad *pad,
GstCaps *vscapslist);
static void gst_v4lmjpegsink_chain (GstPad *pad,
GstBuffer *buf);
@ -79,6 +69,10 @@ static void gst_v4lmjpegsink_get_property (GObject
static void gst_v4lmjpegsink_close (GstV4lMjpegSink *v4lmjpegsink);
static GstElementStateReturn gst_v4lmjpegsink_change_state (GstElement *element);
static GstCaps *capslist = NULL;
static GstPadTemplate *sink_template;
static GstElementClass *parent_class = NULL;
static guint gst_v4lmjpegsink_signals[LAST_SIGNAL] = { 0 };
@ -155,37 +149,13 @@ gst_v4lmjpegsink_class_init (GstV4lMjpegSinkClass *klass)
gstelement_class->change_state = gst_v4lmjpegsink_change_state;
}
static GstPadConnectReturn
gst_v4lmjpegsink_sinkconnect (GstPad *pad,
GstCaps *caps)
{
GstV4lMjpegSink *v4lmjpegsink;
v4lmjpegsink = GST_V4LMJPEGSINK (gst_pad_get_parent (pad));
if (!GST_CAPS_IS_FIXED (caps))
return GST_PAD_CONNECT_DELAYED;
v4lmjpegsink->width = gst_caps_get_int (caps, "width");
v4lmjpegsink->height = gst_caps_get_int (caps, "height");
gst_v4lmjpegsink_set_playback(v4lmjpegsink,
v4lmjpegsink->width, v4lmjpegsink->height,
v4lmjpegsink->x_offset, v4lmjpegsink->y_offset,
GST_V4LELEMENT(v4lmjpegsink)->norm, 0); /* TODO: interlacing */
g_signal_emit (G_OBJECT (v4lmjpegsink), gst_v4lmjpegsink_signals[SIGNAL_HAVE_SIZE], 0,
v4lmjpegsink->width, v4lmjpegsink->height);
return GST_PAD_CONNECT_OK;
}
static void
gst_v4lmjpegsink_init (GstV4lMjpegSink *v4lmjpegsink)
{
v4lmjpegsink->sinkpad = gst_pad_new_from_template(GST_PADTEMPLATE_GET (sink_template), "sink");
v4lmjpegsink->sinkpad = gst_pad_new_from_template (sink_template, "sink");
gst_element_add_pad (GST_ELEMENT (v4lmjpegsink), v4lmjpegsink->sinkpad);
gst_pad_set_chain_function (v4lmjpegsink->sinkpad, gst_v4lmjpegsink_chain);
gst_pad_set_connect_function (v4lmjpegsink->sinkpad, gst_v4lmjpegsink_sinkconnect);
@ -205,6 +175,39 @@ gst_v4lmjpegsink_init (GstV4lMjpegSink *v4lmjpegsink)
}
static GstPadConnectReturn
gst_v4lmjpegsink_sinkconnect (GstPad *pad,
GstCaps *vscapslist)
{
GstV4lMjpegSink *v4lmjpegsink;
GstCaps *caps;
v4lmjpegsink = GST_V4LMJPEGSINK (gst_pad_get_parent (pad));
for (caps = capslist; caps != NULL; caps = vscapslist = vscapslist->next)
{
v4lmjpegsink->width = gst_caps_get_int (caps, "width");
v4lmjpegsink->height = gst_caps_get_int (caps, "height");
if (!gst_v4lmjpegsink_set_playback(v4lmjpegsink,
v4lmjpegsink->width, v4lmjpegsink->height,
v4lmjpegsink->x_offset, v4lmjpegsink->y_offset,
GST_V4LELEMENT(v4lmjpegsink)->norm, 0)) /* TODO: interlacing */
continue;
g_signal_emit (G_OBJECT (v4lmjpegsink), gst_v4lmjpegsink_signals[SIGNAL_HAVE_SIZE], 0,
v4lmjpegsink->width, v4lmjpegsink->height);
return GST_PAD_CONNECT_OK;
}
/* if we got here - it's not good */
gst_element_error(GST_ELEMENT(v4lmjpegsink),
"Failed to find acceptable caps");
return GST_PAD_CONNECT_REFUSED;
}
static void
gst_v4lmjpegsink_chain (GstPad *pad,
GstBuffer *buf)
@ -281,7 +284,7 @@ gst_v4lmjpegsink_set_property (GObject *object,
v4lmjpegsink->y_offset = g_value_get_int(value);
break;
default:
/*parent_class->set_property(object, prop_id, value, pspec);*/
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
@ -312,7 +315,7 @@ gst_v4lmjpegsink_get_property (GObject *object,
g_value_set_int (value, v4lmjpegsink->bufsize);
break;
default:
/*parent_class->get_property(object, prop_id, value, pspec);*/
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
@ -379,14 +382,29 @@ plugin_init (GModule *module,
GstPlugin *plugin)
{
GstElementFactory *factory;
GstCaps *caps;
/* create an elementfactory for the v4lmjpegsink element */
factory = gst_elementfactory_new("v4lmjpegsink",GST_TYPE_V4LMJPEGSINK,
&gst_v4lmjpegsink_details);
g_return_val_if_fail(factory != NULL, FALSE);
gst_elementfactory_add_padtemplate (factory,
GST_PADTEMPLATE_GET (sink_template));
caps = gst_caps_new ("v4lmjpegsink_caps",
"video/jpeg",
gst_props_new (
"width", GST_PROPS_INT_RANGE (0, G_MAXINT),
"height", GST_PROPS_INT_RANGE (0, G_MAXINT),
NULL )
);
capslist = gst_caps_append(capslist, caps);
sink_template = gst_padtemplate_new (
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
capslist, NULL);
gst_elementfactory_add_padtemplate (factory, sink_template);
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));

View file

@ -57,12 +57,8 @@ static void gst_v4lmjpegsrc_class_init (GstV4lMjpegSrcClass *
static void gst_v4lmjpegsrc_init (GstV4lMjpegSrc *v4lmjpegsrc);
/* pad/buffer functions */
/*
static GstPadNegotiateReturn gst_v4lmjpegsrc_negotiate (GstPad *pad,
GstCaps **caps,
gpointer *user_data);
*/
static GstCaps* gst_v4lmjpegsrc_create_caps (GstV4lMjpegSrc *v4lmjpegsrc);
static GstPadConnectReturn gst_v4lmjpegsrc_srcconnect (GstPad *pad,
GstCaps *caps);
static GstBuffer* gst_v4lmjpegsrc_get (GstPad *pad);
/* get/set params */
@ -87,6 +83,9 @@ static GstBuffer* gst_v4lmjpegsrc_buffer_copy (GstBuffer *srcbu
static void gst_v4lmjpegsrc_buffer_free (GstBuffer *buf);
static GstCaps *capslist = NULL;
static GstPadTemplate *src_template;
static GstElementClass *parent_class = NULL;
//static guint gst_v4lmjpegsrc_signals[LAST_SIGNAL] = { 0 };
@ -174,11 +173,11 @@ gst_v4lmjpegsrc_class_init (GstV4lMjpegSrcClass *klass)
static void
gst_v4lmjpegsrc_init (GstV4lMjpegSrc *v4lmjpegsrc)
{
v4lmjpegsrc->srcpad = gst_pad_new("src", GST_PAD_SRC);
v4lmjpegsrc->srcpad = gst_pad_new_from_template (src_template, "src");
gst_element_add_pad(GST_ELEMENT(v4lmjpegsrc), v4lmjpegsrc->srcpad);
gst_pad_set_get_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_get);
//gst_pad_set_negotiate_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_negotiate);
gst_pad_set_connect_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_srcconnect);
v4lmjpegsrc->bufferpool = gst_buffer_pool_new();
gst_buffer_pool_set_buffer_new_function(v4lmjpegsrc->bufferpool, gst_v4lmjpegsrc_buffer_new);
@ -202,46 +201,21 @@ gst_v4lmjpegsrc_init (GstV4lMjpegSrc *v4lmjpegsrc)
v4lmjpegsrc->numbufs = 64;
v4lmjpegsrc->bufsize = 256;
v4lmjpegsrc->init = TRUE;
v4lmjpegsrc->capslist = capslist;
}
/*
static GstPadNegotiateReturn
gst_v4lmjpegsrc_negotiate (GstPad *pad,
GstCaps **caps,
gpointer *user_data)
static GstPadConnectReturn
gst_v4lmjpegsrc_srcconnect (GstPad *pad,
GstCaps *caps)
{
GstV4lMjpegSrc *v4lmjpegsrc;
v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad));
if (!*caps) {
return GST_PAD_NEGOTIATE_FAIL;
}
else {
return GST_PAD_NEGOTIATE_AGREE;
}
/* we will try_set_caps() with the actual size (wxh) when we know it */
return GST_PAD_NEGOTIATE_FAIL;
}
*/
static GstCaps*
gst_v4lmjpegsrc_create_caps (GstV4lMjpegSrc *v4lmjpegsrc)
{
GstCaps *caps;
caps = GST_CAPS_NEW (
"v4lmjpegsrc_caps",
"video/jpeg",
"width", GST_PROPS_INT(v4lmjpegsrc->end_width),
"height", GST_PROPS_INT(v4lmjpegsrc->end_height)
);
return caps;
return GST_PAD_CONNECT_OK;
}
@ -256,17 +230,6 @@ gst_v4lmjpegsrc_get (GstPad *pad)
v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad));
if (v4lmjpegsrc->init) {
gst_pad_try_set_caps (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_create_caps (v4lmjpegsrc));
v4lmjpegsrc->init = FALSE;
}
else {
if (!gst_pad_get_caps (v4lmjpegsrc->srcpad) &&
!gst_pad_renegotiate (v4lmjpegsrc->srcpad)) {
return NULL;
}
}
buf = gst_buffer_new_from_pool(v4lmjpegsrc->bufferpool, 0, 0);
if (!buf)
{
@ -326,7 +289,7 @@ gst_v4lmjpegsrc_set_property (GObject *object,
v4lmjpegsrc->bufsize = g_value_get_int(value);
break;
default:
/*parent_class->set_property(object, prop_id, value, pspec);*/
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
@ -357,7 +320,7 @@ gst_v4lmjpegsrc_get_property (GObject *object,
g_value_set_int(value, v4lmjpegsrc->breq.size);
break;
default:
/*parent_class->get_property(object, prop_id, value, pspec);*/
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
@ -368,6 +331,7 @@ gst_v4lmjpegsrc_change_state (GstElement *element)
{
GstV4lMjpegSrc *v4lmjpegsrc;
GstElementStateReturn parent_value;
GstCaps *caps;
g_return_val_if_fail(GST_IS_V4LMJPEGSRC(element), GST_STATE_FAILURE);
@ -396,7 +360,19 @@ gst_v4lmjpegsrc_change_state (GstElement *element)
v4lmjpegsrc->quality))
return GST_STATE_FAILURE;
}
v4lmjpegsrc->init = TRUE;
/* we now have an actual width/height - *set it* */
caps = gst_caps_new("v4lmjpegsrc_caps",
"video/jpeg",
gst_props_new(
"width", GST_PROPS_INT(v4lmjpegsrc->end_width),
"height", GST_PROPS_INT(v4lmjpegsrc->end_height),
NULL ) );
if (!gst_pad_try_set_caps(v4lmjpegsrc->srcpad, caps))
{
gst_element_error(GST_ELEMENT(v4lmjpegsrc),
"Failed to set new caps");
return GST_STATE_FAILURE;
}
if (!gst_v4lmjpegsrc_capture_init(v4lmjpegsrc))
return GST_STATE_FAILURE;
break;
@ -509,11 +485,30 @@ static gboolean
plugin_init (GModule *module, GstPlugin *plugin)
{
GstElementFactory *factory;
GstCaps *caps;
/* create an elementfactory for the v4lmjpegsrcparse element */
factory = gst_elementfactory_new("v4lmjpegsrc",GST_TYPE_V4LMJPEGSRC,
&gst_v4lmjpegsrc_details);
g_return_val_if_fail(factory != NULL, FALSE);
caps = gst_caps_new ("v4lmjpegsrc_caps",
"video/jpeg",
gst_props_new (
"width", GST_PROPS_INT_RANGE (0, G_MAXINT),
"height", GST_PROPS_INT_RANGE (0, G_MAXINT),
NULL )
);
capslist = gst_caps_append(capslist, caps);
src_template = gst_padtemplate_new (
"src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
capslist, NULL);
gst_elementfactory_add_padtemplate (factory, src_template);
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
return TRUE;

View file

@ -55,6 +55,9 @@ struct _GstV4lMjpegSrc {
struct mjpeg_sync bsync;
struct mjpeg_requestbuffers breq;
/* list of available caps */
GstCaps *capslist;
/* caching values */
gint x_offset;
gint y_offset;
@ -69,8 +72,6 @@ struct _GstV4lMjpegSrc {
gint quality;
gint numbufs;
gint bufsize; /* in KB */
gboolean init;
};
struct _GstV4lMjpegSrcClass {

View file

@ -54,11 +54,8 @@ static void gst_v4lsrc_class_init (GstV4lSrcClass *klass);
static void gst_v4lsrc_init (GstV4lSrc *v4lsrc);
/* pad/buffer functions */
/*static GstPadNegotiateReturn gst_v4lsrc_negotiate (GstPad *pad,
GstCaps **caps,
gpointer *user_data);
*/
static GstCaps* gst_v4lsrc_create_caps (GstV4lSrc *v4lsrc);
static GstPadConnectReturn gst_v4lsrc_srcconnect (GstPad *pad,
GstCaps *caps);
static GstBuffer* gst_v4lsrc_get (GstPad *pad);
/* get/set params */
@ -83,6 +80,9 @@ static GstBuffer* gst_v4lsrc_buffer_copy (GstBuffer *srcbuf);
static void gst_v4lsrc_buffer_free (GstBuffer *buf);
static GstCaps *capslist = NULL;
static GstPadTemplate *src_template;
static GstElementClass *parent_class = NULL;\
//static guint gst_v4lsrc_signals[LAST_SIGNAL] = { 0 };
@ -151,11 +151,11 @@ gst_v4lsrc_class_init (GstV4lSrcClass *klass)
static void
gst_v4lsrc_init (GstV4lSrc *v4lsrc)
{
v4lsrc->srcpad = gst_pad_new("src", GST_PAD_SRC);
v4lsrc->srcpad = gst_pad_new_from_template (src_template, "src");
gst_element_add_pad(GST_ELEMENT(v4lsrc), v4lsrc->srcpad);
gst_pad_set_get_function (v4lsrc->srcpad, gst_v4lsrc_get);
//gst_pad_set_negotiate_function (v4lsrc->srcpad, gst_v4lsrc_negotiate);
gst_pad_set_connect_function (v4lsrc->srcpad, gst_v4lsrc_srcconnect);
v4lsrc->bufferpool = gst_buffer_pool_new();
gst_buffer_pool_set_buffer_new_function(v4lsrc->bufferpool, gst_v4lsrc_buffer_new);
@ -163,192 +163,155 @@ gst_v4lsrc_init (GstV4lSrc *v4lsrc)
gst_buffer_pool_set_buffer_free_function(v4lsrc->bufferpool, gst_v4lsrc_buffer_free);
gst_buffer_pool_set_user_data(v4lsrc->bufferpool, v4lsrc);
v4lsrc->palette = VIDEO_PALETTE_YUV420P;
v4lsrc->palette = 0; /* means 'any' - user can specify a specific palette */
v4lsrc->width = 160;
v4lsrc->height = 120;
v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 1.5;
v4lsrc->init = TRUE;
v4lsrc->capslist = capslist;
}
#if 0
static GstPadNegotiateReturn
gst_v4lsrc_negotiate (GstPad *pad,
GstCaps **caps,
gpointer *user_data)
static GstPadConnectReturn
gst_v4lsrc_srcconnect (GstPad *pad,
GstCaps *vscapslist)
{
GstV4lSrc *v4lsrc;
GstCaps *caps, *newcaps;
gint palette = v4lsrc->palette;
v4lsrc = GST_V4LSRC (gst_pad_get_parent (pad));
if (!*caps) {
return GST_PAD_NEGOTIATE_FAIL;
}
else {
gint width, height;
gulong format;
width = gst_caps_get_int (*caps, "width");
height = gst_caps_get_int (*caps, "height");
format = gst_caps_get_fourcc_int (*caps, "format");
switch (format) {
case GST_MAKE_FOURCC ('R','G','B',' '):
/* TODO: caps = gst_caps_normalize(capslist); */
for (caps = vscapslist ; caps != NULL ; caps = vscapslist = vscapslist->next)
{
if (v4lsrc->palette > 0)
{
switch (v4lsrc->palette)
{
gint depth;
depth = gst_caps_get_int (*caps, "depth");
switch (depth) {
case 15:
v4lsrc->palette = VIDEO_PALETTE_RGB555;
v4lsrc->buffer_size = width * height * 2;
break;
case 16:
v4lsrc->palette = VIDEO_PALETTE_RGB565;
v4lsrc->buffer_size = width * height * 2;
break;
case 24:
v4lsrc->palette = VIDEO_PALETTE_RGB24;
v4lsrc->buffer_size = width * height * 3;
break;
case 32:
v4lsrc->palette = VIDEO_PALETTE_RGB32;
v4lsrc->buffer_size = width * height * 4;
break;
default:
*caps = NULL;
return GST_PAD_NEGOTIATE_TRY;
}
break;
}
case GST_MAKE_FOURCC ('I','4','2','0'):
v4lsrc->palette = VIDEO_PALETTE_YUV420P;
v4lsrc->buffer_size = width * height * 1.5;
break;
case GST_MAKE_FOURCC ('U','Y','V','Y'):
v4lsrc->palette = VIDEO_PALETTE_UYVY; //YUV422?;
v4lsrc->buffer_size = width * height * 2;
break;
case GST_MAKE_FOURCC ('Y','U','Y','2'):
v4lsrc->palette = VIDEO_PALETTE_YUYV; //YUV422?;
v4lsrc->buffer_size = width * height * 2;
break;
/* TODO: add YUV4:2:2 planar and YUV4:2:0 packed, maybe also YUV4:1:1? */
default:
*caps = NULL;
return GST_PAD_NEGOTIATE_TRY;
}
/* if we get here, it's okay */
v4lsrc->width = width;
v4lsrc->height = height;
return GST_PAD_NEGOTIATE_AGREE;
}
return GST_PAD_NEGOTIATE_FAIL;
}
#endif
static GstCaps*
gst_v4lsrc_create_caps (GstV4lSrc *v4lsrc)
{
GstCaps *caps = NULL;
gulong fourcc = 0;
switch (v4lsrc->palette) {
case VIDEO_PALETTE_RGB555:
case VIDEO_PALETTE_RGB565:
case VIDEO_PALETTE_RGB24:
case VIDEO_PALETTE_RGB32:
{
int depth=0, bpp=0;
fourcc = GST_STR_FOURCC ("RGB ");
switch (v4lsrc->palette) {
case VIDEO_PALETTE_RGB555:
depth = 15;
bpp = 2;
break;
case VIDEO_PALETTE_RGB565:
depth = 16;
bpp = 2;
break;
case VIDEO_PALETTE_RGB24:
depth = 24;
bpp = 3;
break;
case VIDEO_PALETTE_RGB32:
depth = 32;
bpp = 4;
break;
}
caps = GST_CAPS_NEW (
"v4lsrc_caps",
"video/raw",
"format", GST_PROPS_FOURCC (fourcc),
"width", GST_PROPS_INT (v4lsrc->width),
"height", GST_PROPS_INT (v4lsrc->height),
"bpp", GST_PROPS_INT (bpp),
"depth", GST_PROPS_INT (depth)
);
v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * bpp;
break;
}
case VIDEO_PALETTE_YUV422:
case VIDEO_PALETTE_YUV420P:
{
switch (v4lsrc->palette) {
case VIDEO_PALETTE_YUV422:
fourcc = (G_BYTE_ORDER == G_BIG_ENDIAN) ?
GST_STR_FOURCC("UYVY") : GST_STR_FOURCC("YUY2");
v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
break;
case VIDEO_PALETTE_YUYV:
fourcc = GST_STR_FOURCC("YUY2");
v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
break;
case VIDEO_PALETTE_UYVY:
fourcc = GST_STR_FOURCC("UYVY");
v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
break;
case VIDEO_PALETTE_YUV420P:
fourcc = GST_STR_FOURCC("I420");
v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 1.5;
break;
if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('I','4','2','0') &&
gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('I','Y','U','V'))
goto try_next;
goto try_caps;
case VIDEO_PALETTE_YUV422:
case VIDEO_PALETTE_YUYV:
if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('Y','U','Y','2'))
goto try_next;
goto try_caps;
case VIDEO_PALETTE_UYVY:
if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('U','Y','V','Y'))
goto try_next;
goto try_caps;
case VIDEO_PALETTE_YUV411:
if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('Y','4','1','P'))
goto try_next;
goto try_caps;
case VIDEO_PALETTE_RGB555:
if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('R','G','B',' ') ||
gst_caps_get_int(caps, "depth") != 15)
goto try_next;
goto try_caps;
case VIDEO_PALETTE_RGB565:
if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('R','G','B',' ') ||
gst_caps_get_int(caps, "depth") != 16)
goto try_next;
goto try_caps;
case VIDEO_PALETTE_RGB24:
if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('R','G','B',' ') ||
gst_caps_get_int(caps, "depth") != 24)
goto try_next;
goto try_caps;
case VIDEO_PALETTE_RGB32:
if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('R','G','B',' ') ||
gst_caps_get_int(caps, "depth") != 32)
goto try_next;
goto try_caps;
default:
goto try_next;
}
}
else
{
switch (gst_caps_get_fourcc_int(caps, "format"))
{
case GST_MAKE_FOURCC('I','4','2','0'):
case GST_MAKE_FOURCC('I','Y','U','V'):
palette = VIDEO_PALETTE_YUV420P;
goto try_caps;
case GST_MAKE_FOURCC('Y','U','Y','2'):
palette = VIDEO_PALETTE_YUV422;
goto try_caps;
case GST_MAKE_FOURCC('U','Y','V','Y'):
palette = VIDEO_PALETTE_UYVY;
goto try_caps;
case GST_MAKE_FOURCC('Y','4','1','P'):
palette = VIDEO_PALETTE_YUV411;
goto try_caps;
case GST_MAKE_FOURCC('R','G','B',' '):
switch (gst_caps_get_int(caps, "depth"))
{
case 15:
palette = VIDEO_PALETTE_RGB555;
goto try_caps;
case 16:
palette = VIDEO_PALETTE_RGB565;
goto try_caps;
case 24:
palette = VIDEO_PALETTE_RGB24;
goto try_caps;
case 32:
palette = VIDEO_PALETTE_RGB32;
goto try_caps;
default:
goto try_next;
}
default:
goto try_next;
}
caps = GST_CAPS_NEW (
"v4lsrc_caps",
"video/raw",
"format", GST_PROPS_FOURCC (fourcc),
"width", GST_PROPS_INT (v4lsrc->width),
"height", GST_PROPS_INT (v4lsrc->height)
);
break;
}
default:
return NULL;
/* if this caps wasn't useful, try the next one */
try_next:
continue;
/* if this caps was useful, try it out */
try_caps:
/* TODO: try the current 'palette' out on the video device */
if (!gst_v4lsrc_set_capture(v4lsrc, v4lsrc->width, v4lsrc->height, palette))
continue;
/* try to connect the pad/caps with the actual width/height */
if (palette >= VIDEO_PALETTE_RGB565 && palette <= VIDEO_PALETTE_RGB555)
newcaps = gst_caps_new("v4lsrc_caps",
"video/raw",
gst_props_new(
"format", GST_PROPS_FOURCC(gst_caps_get_fourcc_int(caps, "format")),
"width", GST_PROPS_INT(v4lsrc->width),
"width", GST_PROPS_INT(v4lsrc->height),
"bpp", GST_PROPS_INT(gst_caps_get_int(caps, "bpp")),
"depth", GST_PROPS_INT(gst_caps_get_int(caps, "depth")),
NULL ) );
else
newcaps = gst_caps_new("v4lsrc_caps",
"video/raw",
gst_props_new(
"format", GST_PROPS_FOURCC(gst_caps_get_fourcc_int(caps, "format")),
"width", GST_PROPS_INT(v4lsrc->width),
"height", GST_PROPS_INT(v4lsrc->height),
NULL ) );
if (!gst_pad_try_set_caps(v4lsrc->srcpad, newcaps))
continue;
else
return GST_PAD_CONNECT_DONE;
}
return caps;
/* still nothing - no good caps */
gst_element_error(GST_ELEMENT(v4lsrc),
"Failed to find acceptable caps");
return GST_PAD_CONNECT_REFUSED;
}
@ -363,17 +326,6 @@ gst_v4lsrc_get (GstPad *pad)
v4lsrc = GST_V4LSRC (gst_pad_get_parent (pad));
if (v4lsrc->init) {
gst_pad_try_set_caps (v4lsrc->srcpad, gst_v4lsrc_create_caps (v4lsrc));
v4lsrc->init = FALSE;
}
else {
if (!gst_pad_get_caps (v4lsrc->srcpad) &&
!gst_pad_renegotiate (v4lsrc->srcpad)) {
return NULL;
}
}
buf = gst_buffer_new_from_pool(v4lsrc->bufferpool, 0, 0);
if (!buf)
{
@ -419,7 +371,7 @@ gst_v4lsrc_set_property (GObject *object,
break;
default:
/*parent_class->set_property(object, prop_id, value, pspec);*/
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
@ -462,7 +414,7 @@ gst_v4lsrc_get_property (GObject *object,
break;
default:
/*parent_class->get_property(object, prop_id, value, pspec);*/
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
@ -473,6 +425,7 @@ gst_v4lsrc_change_state (GstElement *element)
{
GstV4lSrc *v4lsrc;
GstElementStateReturn parent_value;
GstCaps *caps;
g_return_val_if_fail(GST_IS_V4LSRC(element), GST_STATE_FAILURE);
@ -481,9 +434,120 @@ gst_v4lsrc_change_state (GstElement *element)
switch (GST_STATE_TRANSITION(element)) {
case GST_STATE_READY_TO_PAUSED:
/* set capture parameters and mmap the buffers */
if (!gst_v4lsrc_set_capture(v4lsrc, v4lsrc->width, v4lsrc->height, v4lsrc->palette))
if (!gst_v4lsrc_set_capture(v4lsrc, v4lsrc->width, v4lsrc->height,
v4lsrc->palette>0 ? v4lsrc->palette : v4lsrc->mmap.format))
return GST_STATE_FAILURE;
v4lsrc->init = TRUE;
/* retry setting the video-palette */
if (v4lsrc->palette > 0)
{
switch (v4lsrc->palette)
{
case VIDEO_PALETTE_YUYV:
case VIDEO_PALETTE_UYVY:
case VIDEO_PALETTE_YUV422:
case VIDEO_PALETTE_YUV420P:
case VIDEO_PALETTE_YUV411:
{
gulong format;
switch (v4lsrc->palette)
{
case VIDEO_PALETTE_YUYV:
format = GST_MAKE_FOURCC('Y','U','Y','2');
break;
case VIDEO_PALETTE_UYVY:
format = GST_MAKE_FOURCC('U','Y','V','Y');
break;
case VIDEO_PALETTE_YUV422:
format = GST_MAKE_FOURCC('Y','U','Y','2');
break;
case VIDEO_PALETTE_YUV420P:
format = GST_MAKE_FOURCC('I','4','2','0');
break;
case VIDEO_PALETTE_YUV411:
format = GST_MAKE_FOURCC('Y','4','1','P');
break;
}
caps = gst_caps_new("v4lsrc_caps",
"video/raw",
gst_props_new(
"format", GST_PROPS_FOURCC(format),
"width", GST_PROPS_INT(v4lsrc->width),
"height", GST_PROPS_INT(v4lsrc->height),
NULL ) );
break;
}
case VIDEO_PALETTE_RGB555:
case VIDEO_PALETTE_RGB565:
case VIDEO_PALETTE_RGB24:
case VIDEO_PALETTE_RGB32:
{
gint depth, bpp;
switch (v4lsrc->palette)
{
case VIDEO_PALETTE_RGB555:
bpp = 2;
depth = 15;
break;
case VIDEO_PALETTE_RGB565:
bpp = 2;
depth = 16;
break;
case VIDEO_PALETTE_RGB24:
bpp = 3;
depth = 24;
break;
case VIDEO_PALETTE_RGB32:
bpp = 4;
depth = 32;
break;
}
caps = gst_caps_new("v4lsrc_caps",
"video/raw",
gst_props_new(
"format", GST_PROPS_FOURCC(GST_MAKE_FOURCC('R','G','B',' ')),
"width", GST_PROPS_INT(v4lsrc->width),
"height", GST_PROPS_INT(v4lsrc->height),
"bpp", GST_PROPS_INT(bpp),
"depth", GST_PROPS_INT(depth),
NULL ) );
break;
}
default:
gst_element_error(GST_ELEMENT(v4lsrc),
"Failed to find a fourcc code for palette %d (\'%s\')",
v4lsrc->palette, palette_name[v4lsrc->palette]);
return GST_STATE_FAILURE;
}
}
else
{
GstCaps *oldcaps = gst_pad_get_caps(v4lsrc->srcpad);
if (gst_caps_get_fourcc_int(oldcaps, "format") == GST_MAKE_FOURCC('R','G','B',' '))
caps = gst_caps_new("v4lsrc_caps",
"video/raw",
gst_props_new(
"format", GST_PROPS_FOURCC(GST_MAKE_FOURCC('R','G','B',' ')),
"width", GST_PROPS_INT(v4lsrc->width),
"height", GST_PROPS_INT(v4lsrc->height),
"bpp", GST_PROPS_INT(gst_caps_get_int(oldcaps, "bpp")),
"depth", GST_PROPS_INT(gst_caps_get_int(oldcaps, "depth")),
NULL) );
else
caps = gst_caps_new("v4lsrc_caps",
"video/raw",
gst_props_new(
"format", GST_PROPS_FOURCC(gst_caps_get_fourcc_int(oldcaps, "format")),
"width", GST_PROPS_INT(v4lsrc->width),
"height", GST_PROPS_INT(v4lsrc->height),
NULL) );
}
if (!gst_pad_try_set_caps(v4lsrc->srcpad, caps))
{
gst_element_error(GST_ELEMENT(v4lsrc),
"Failed to set new caps");
return GST_STATE_FAILURE;
}
if (!gst_v4lsrc_capture_init(v4lsrc))
return GST_STATE_FAILURE;
break;
@ -573,7 +637,7 @@ gst_v4lsrc_buffer_free (GstBuffer *buf)
}
gst_element_error(GST_ELEMENT(v4lsrc),
"Couldn't find the buffer");
"Couldn\'t find the buffer");
}
@ -582,11 +646,60 @@ plugin_init (GModule *module,
GstPlugin *plugin)
{
GstElementFactory *factory;
GstCaps *caps;
gint i;
gulong format[5] = { GST_MAKE_FOURCC('Y','U','Y','2'), /* VIDEO_PALETTE_YUV422/_YUYV */
GST_MAKE_FOURCC('I','4','2','0'), /* VIDEO_PALETTE_YUV420P */
GST_MAKE_FOURCC('I','Y','U','V'), /* VIDEO_PALETTE_YUV420P */
GST_MAKE_FOURCC('U','Y','V','Y'), /* VIDEO_PALETTE_UYVY */
GST_MAKE_FOURCC('Y','4','1','P') /* VIDEO_PALETTE_YUV411 */
};
gint rgb_bpp[4] = { 2, 2, 3, 4 };
gint rgb_depth[4] = { 15, 16, 24, 32 };
/* create an elementfactory for the v4lsrc */
factory = gst_elementfactory_new("v4lsrc",GST_TYPE_V4LSRC,
&gst_v4lsrc_details);
g_return_val_if_fail(factory != NULL, FALSE);
/* make a list of all available caps - first the YUV formats */
for (i=0;i<5;i++)
{
caps = gst_caps_new ("v4lsrc_caps",
"video/raw",
gst_props_new (
"format", GST_PROPS_FOURCC(format[i]),
"width", GST_PROPS_INT_RANGE (0, G_MAXINT),
"height", GST_PROPS_INT_RANGE (0, G_MAXINT),
NULL )
);
capslist = gst_caps_append(capslist, caps);
}
/* now all the RGB formats */
for (i=0;i<4;i++)
{
caps = gst_caps_new ("v4lsrc_caps",
"video/raw",
gst_props_new (
"format", GST_PROPS_FOURCC(GST_MAKE_FOURCC('R','G','B',' ')),
"width", GST_PROPS_INT_RANGE (0, G_MAXINT),
"height", GST_PROPS_INT_RANGE (0, G_MAXINT),
"bpp", GST_PROPS_INT(rgb_bpp[i]),
"depth", GST_PROPS_INT(rgb_depth[i]),
NULL )
);
capslist = gst_caps_append(capslist, caps);
}
src_template = gst_padtemplate_new (
"src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
capslist, NULL);
gst_elementfactory_add_padtemplate (factory, src_template);
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
return TRUE;

View file

@ -49,9 +49,6 @@ struct _GstV4lSrc {
/* bufferpool for the buffers we're gonna use */
GstBufferPool *bufferpool;
/* whether we need to reset the GstPad */
gboolean init;
/* capture/buffer info */
struct video_mmap mmap;
struct video_mbuf mbuf;
@ -71,6 +68,9 @@ struct _GstV4lSrc {
pthread_mutex_t mutex_queued_frames;
pthread_cond_t cond_queued_frames;
/* list of available caps */
GstCaps *capslist;
/* caching values */
gint width;
gint height;

View file

@ -161,26 +161,16 @@ gst_v4l_get_chan_norm (GstV4lElement *v4lelement,
gint *channel,
gint *norm)
{
struct video_channel vchan;
#ifdef DEBUG
fprintf(stderr, "V4L: gst_v4l_get_chan_norm()\n");
#endif
GST_V4L_CHECK_OPEN(v4lelement);
if (ioctl(v4lelement->video_fd, VIDIOCGCHAN, &vchan) < 0)
{
gst_element_error(GST_ELEMENT(v4lelement),
"Error getting the channel/norm settings: %s",
sys_errlist[errno]);
return FALSE;
}
if (channel)
*channel = vchan.channel;
*channel = v4lelement->vchan.channel;
if (norm)
*norm = vchan.norm;
*norm = v4lelement->vchan.norm;
return TRUE;
}
@ -198,8 +188,6 @@ gst_v4l_set_chan_norm (GstV4lElement *v4lelement,
gint channel,
gint norm)
{
struct video_channel vchan;
#ifdef DEBUG
fprintf(stderr, "V4L: gst_v4l_set_chan_norm(), channel = %d, norm = %d (%s)\n",
channel, norm, norm_name[norm]);
@ -208,19 +196,10 @@ gst_v4l_set_chan_norm (GstV4lElement *v4lelement,
GST_V4L_CHECK_OPEN(v4lelement);
GST_V4L_CHECK_NOT_ACTIVE(v4lelement);
#if 0
if (ioctl(v4lelement->video_fd, VIDIOCGCHAN, &vchan) < 0)
{
gst_error("V4lElement - Error getting the channel/norm settings: %s",
sys_errlist[errno]);
return FALSE;
}
#endif
v4lelement->vchan.channel = channel;
v4lelement->vchan.norm = norm;
vchan.channel = channel;
vchan.norm = norm;
if (ioctl(v4lelement->video_fd, VIDIOCSCHAN, &vchan) < 0)
if (ioctl(v4lelement->video_fd, VIDIOCSCHAN, &(v4lelement->vchan)) < 0)
{
gst_element_error(GST_ELEMENT(v4lelement),
"Error setting the channel/norm settings: %s",
@ -228,6 +207,14 @@ gst_v4l_set_chan_norm (GstV4lElement *v4lelement,
return FALSE;
}
if (ioctl(v4lelement->video_fd, VIDIOCGCHAN, &(v4lelement->vchan)) < 0)
{
gst_element_error(GST_ELEMENT(v4lelement),
"Error getting the channel/norm settings: %s",
sys_errlist[errno]);
return FALSE;
}
return TRUE;
}
@ -246,7 +233,8 @@ gst_v4l_has_tuner (GstV4lElement *v4lelement)
GST_V4L_CHECK_OPEN(v4lelement);
return (v4lelement->vcap.type & VID_TYPE_TUNER);
return (v4lelement->vcap.type & VID_TYPE_TUNER &&
v4lelement->vchan.flags & VIDEO_VC_TUNER);
}
@ -442,7 +430,8 @@ gst_v4l_has_audio (GstV4lElement *v4lelement)
GST_V4L_CHECK_OPEN(v4lelement);
return (v4lelement->vcap.audios > 0);
return (v4lelement->vcap.audios > 0 &&
v4lelement->vchan.flags & VIDEO_VC_AUDIO);
}

View file

@ -240,7 +240,7 @@ gst_v4lsrc_set_capture (GstV4lSrc *v4lsrc,
width, height, palette);
#endif
GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lsrc));
/*GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lsrc));*/
GST_V4L_CHECK_NOT_ACTIVE(GST_V4LELEMENT(v4lsrc));
v4lsrc->mmap.width = width;