This patch fixes some issues caused by design issues in video4linux, adds some nicety to video4linux2 plugins and doe...

Original commit message from CVS:
This patch fixes some issues caused by design issues in video4linux, adds
some nicety to video4linux2 plugins and does some more evil stuff:
* video4linux doesn't tell us which formats are supported by a card, so
the only way to know this is by simply trying it out. This patch adds that.
* v4lmjpegsink didnt have a bufferpool yet - is integrated now.
* all copy() bufferpool functions have been removed since they're not needed.
* v4lmjpegsink doesnt have a free() function, because hen playing the frames,
all this is already handled. When the frame is not played, nothing has to
be done. In total, the function is not needed.
* adds a get_caps() function to v4l2src
* some minor crap
This commit is contained in:
Ronald S. Bultje 2002-09-20 09:28:46 +00:00
parent 91b9c6c9c6
commit ab8fe8ba0b
2 changed files with 67 additions and 57 deletions

View file

@ -23,10 +23,11 @@
#include "v4l2_calls.h" #include "v4l2_calls.h"
/* elementfactory details */
static GstElementDetails gst_v4l2element_details = { static GstElementDetails gst_v4l2element_details = {
"Generic video4linux2 Element", "Generic video4linux2 Element",
"None/Video", "None/Video",
"LGPL",
"Generic plugin for handling common video4linux2 calls", "Generic plugin for handling common video4linux2 calls",
VERSION, VERSION,
"Ronald Bultje <rbultje@ronald.bitfreak.net>", "Ronald Bultje <rbultje@ronald.bitfreak.net>",

View file

@ -21,10 +21,11 @@
#include <sys/time.h> #include <sys/time.h>
#include "v4l2src_calls.h" #include "v4l2src_calls.h"
/* elementfactory details */
static GstElementDetails gst_v4l2src_details = { static GstElementDetails gst_v4l2src_details = {
"Video (video4linux2) Source", "Video (video4linux2) Source",
"Source/Video", "Source/Video",
"LGPL",
"Reads frames (compressed or uncompressed) from a video4linux2 device", "Reads frames (compressed or uncompressed) from a video4linux2 device",
VERSION, VERSION,
"Ronald Bultje <rbultje@ronald.bitfreak.net>", "Ronald Bultje <rbultje@ronald.bitfreak.net>",
@ -63,6 +64,8 @@ static gboolean gst_v4l2src_srcconvert (GstPad *pad,
gint64 *dest_value); gint64 *dest_value);
static GstPadConnectReturn gst_v4l2src_srcconnect (GstPad *pad, static GstPadConnectReturn gst_v4l2src_srcconnect (GstPad *pad,
GstCaps *caps); GstCaps *caps);
static GstCaps * gst_v4l2src_getcaps (GstPad *pad,
GstCaps *caps);
static GstBuffer * gst_v4l2src_get (GstPad *pad); static GstBuffer * gst_v4l2src_get (GstPad *pad);
/* get/set params */ /* get/set params */
@ -83,9 +86,6 @@ static GstBuffer * gst_v4l2src_buffer_new (GstBufferPool *pool,
guint64 offset, guint64 offset,
guint size, guint size,
gpointer user_data); gpointer user_data);
static GstBuffer * gst_v4l2src_buffer_copy (GstBufferPool *pool,
const GstBuffer *srcbuf,
gpointer user_data);
static void gst_v4l2src_buffer_free (GstBufferPool *pool, static void gst_v4l2src_buffer_free (GstBufferPool *pool,
GstBuffer *buf, GstBuffer *buf,
gpointer user_data); gpointer user_data);
@ -176,10 +176,11 @@ gst_v4l2src_init (GstV4l2Src *v4l2src)
gst_pad_set_get_function(v4l2src->srcpad, gst_v4l2src_get); gst_pad_set_get_function(v4l2src->srcpad, gst_v4l2src_get);
gst_pad_set_connect_function(v4l2src->srcpad, gst_v4l2src_srcconnect); gst_pad_set_connect_function(v4l2src->srcpad, gst_v4l2src_srcconnect);
gst_pad_set_convert_function (v4l2src->srcpad, gst_v4l2src_srcconvert); gst_pad_set_convert_function (v4l2src->srcpad, gst_v4l2src_srcconvert);
gst_pad_set_getcaps_function (v4l2src->srcpad, gst_v4l2src_getcaps);
v4l2src->bufferpool = gst_buffer_pool_new(NULL, NULL, v4l2src->bufferpool = gst_buffer_pool_new(NULL, NULL,
gst_v4l2src_buffer_new, gst_v4l2src_buffer_new,
gst_v4l2src_buffer_copy, NULL,
gst_v4l2src_buffer_free, gst_v4l2src_buffer_free,
v4l2src); v4l2src);
@ -562,33 +563,15 @@ gst_v4l2src_srcconnect (GstPad *pad,
/* clean up if we still haven't cleaned up our previous /* clean up if we still haven't cleaned up our previous
* capture session */ * capture session */
if (GST_V4L2_IS_ACTIVE(GST_V4L2ELEMENT(v4l2src))) if (GST_V4L2_IS_ACTIVE(v4l2element)) {
{
if (!gst_v4l2src_capture_deinit(v4l2src)) if (!gst_v4l2src_capture_deinit(v4l2src))
return GST_PAD_CONNECT_REFUSED; return GST_PAD_CONNECT_REFUSED;
} } else if (!GST_V4L2_IS_OPEN(v4l2element)) {
else if (!GST_V4L2_IS_OPEN(GST_V4L2ELEMENT(v4l2src)))
{
return GST_PAD_CONNECT_DELAYED; return GST_PAD_CONNECT_DELAYED;
} }
/* build our own capslist */ /* build our own capslist */
if (v4l2src->palette) { owncapslist = gst_v4l2src_getcaps(pad, NULL);
struct v4l2_fmtdesc *format = g_list_nth_data(v4l2element->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);
caps = gst_v4l2src_v4l2fourcc_to_caps(format->pixelformat,
v4l2src->width, v4l2src->height,
format->flags & V4L2_FMT_FLAG_COMPRESSED);
owncapslist = gst_caps_append(owncapslist, caps);
}
}
/* and now, get the caps that we have in common */ /* and now, get the caps that we have in common */
if (!(caps = gst_v4l2src_caps_intersect(owncapslist, vscapslist))) if (!(caps = gst_v4l2src_caps_intersect(owncapslist, vscapslist)))
@ -618,13 +601,10 @@ gst_v4l2src_srcconnect (GstPad *pad,
for (;lastcaps != NULL; lastcaps = lastcaps->next) { for (;lastcaps != NULL; lastcaps = lastcaps->next) {
GstPadConnectReturn ret_val; GstPadConnectReturn ret_val;
onecaps = gst_caps_copy_1(lastcaps); onecaps = gst_caps_copy_1(lastcaps);
if ((ret_val = gst_pad_try_set_caps(v4l2src->srcpad, onecaps)) > 0) if ((ret_val = gst_pad_try_set_caps(v4l2src->srcpad, onecaps)) > 0) {
{
if (gst_v4l2src_capture_init(v4l2src)) if (gst_v4l2src_capture_init(v4l2src))
return GST_PAD_CONNECT_DONE; return GST_PAD_CONNECT_DONE;
} } else if (ret_val == GST_PAD_CONNECT_DELAYED) {
else if (ret_val == GST_PAD_CONNECT_DELAYED)
{
return GST_PAD_CONNECT_DELAYED; return GST_PAD_CONNECT_DELAYED;
} }
} }
@ -637,6 +617,40 @@ gst_v4l2src_srcconnect (GstPad *pad,
} }
static GstCaps *
gst_v4l2src_getcaps (GstPad *pad,
GstCaps *caps)
{
GstV4l2Src *v4l2src = GST_V4L2SRC(gst_pad_get_parent (pad));
GstV4l2Element *v4l2element = GST_V4L2ELEMENT(v4l2src);
GstCaps *owncapslist;
if (!GST_V4L2_IS_OPEN(v4l2element)) {
return NULL;
}
/* build our own capslist */
if (v4l2src->palette) {
struct v4l2_fmtdesc *format = g_list_nth_data(v4l2element->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);
caps = gst_v4l2src_v4l2fourcc_to_caps(format->pixelformat,
v4l2src->width, v4l2src->height,
format->flags & V4L2_FMT_FLAG_COMPRESSED);
owncapslist = gst_caps_append(owncapslist, caps);
}
}
return owncapslist;
}
static GstBuffer* static GstBuffer*
gst_v4l2src_get (GstPad *pad) gst_v4l2src_get (GstPad *pad)
{ {
@ -660,7 +674,6 @@ gst_v4l2src_get (GstPad *pad)
return NULL; return NULL;
GST_BUFFER_DATA(buf) = GST_V4L2ELEMENT(v4l2src)->buffer[num]; GST_BUFFER_DATA(buf) = GST_V4L2ELEMENT(v4l2src)->buffer[num];
GST_BUFFER_SIZE(buf) = v4l2src->bufsettings.bytesused; GST_BUFFER_SIZE(buf) = v4l2src->bufsettings.bytesused;
GST_BUFFER_MAXSIZE(buf) = v4l2src->bufsettings.length;
if (!v4l2src->first_timestamp) if (!v4l2src->first_timestamp)
v4l2src->first_timestamp = v4l2src->bufsettings.timestamp; v4l2src->first_timestamp = v4l2src->bufsettings.timestamp;
GST_BUFFER_TIMESTAMP(buf) = v4l2src->bufsettings.length - v4l2src->first_timestamp; GST_BUFFER_TIMESTAMP(buf) = v4l2src->bufsettings.length - v4l2src->first_timestamp;
@ -834,30 +847,19 @@ gst_v4l2src_buffer_new (GstBufferPool *pool,
gpointer user_data) gpointer user_data)
{ {
GstBuffer *buffer; GstBuffer *buffer;
GstV4l2Src *v4l2src = GST_V4L2SRC(user_data);
if (!GST_V4L2_IS_ACTIVE(GST_V4L2ELEMENT(v4l2src)))
return NULL;
buffer = gst_buffer_new(); buffer = gst_buffer_new();
if (!buffer) return NULL; if (!buffer)
/* TODO: add interlacing info to buffer as metadata (height>288 or 240 = topfieldfirst, else noninterlaced) */ return NULL;
return buffer; /* TODO: add interlacing info to buffer as metadata
} * (height>288 or 240 = topfieldfirst, else noninterlaced) */
GST_BUFFER_MAXSIZE(buffer) = v4l2src->bufsettings.length;
GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_DONTFREE);
static GstBuffer*
gst_v4l2src_buffer_copy (GstBufferPool *pool,
const GstBuffer *srcbuf,
gpointer user_data)
{
GstBuffer *buffer;
buffer = gst_buffer_new();
if (!buffer) return NULL;
GST_BUFFER_DATA(buffer) = g_malloc(GST_BUFFER_SIZE(srcbuf));
if (!GST_BUFFER_DATA(buffer)) return NULL;
GST_BUFFER_MAXSIZE(buffer) = GST_BUFFER_SIZE(srcbuf);
GST_BUFFER_SIZE(buffer) = GST_BUFFER_SIZE(srcbuf);
memcpy(GST_BUFFER_DATA(buffer), GST_BUFFER_DATA(srcbuf), GST_BUFFER_SIZE(srcbuf));
GST_BUFFER_TIMESTAMP(buffer) = GST_BUFFER_TIMESTAMP(srcbuf);
return buffer; return buffer;
} }
@ -871,14 +873,21 @@ gst_v4l2src_buffer_free (GstBufferPool *pool,
GstV4l2Src *v4l2src = GST_V4L2SRC(user_data); GstV4l2Src *v4l2src = GST_V4L2SRC(user_data);
int n; int n;
if (gst_element_get_state(GST_ELEMENT(v4l2src)) != GST_STATE_PLAYING)
return; /* we've already cleaned up ourselves */
for (n=0;n<v4l2src->breq.count;n++) for (n=0;n<v4l2src->breq.count;n++)
if (GST_BUFFER_DATA(buf) == GST_V4L2ELEMENT(v4l2src)->buffer[n]) { if (GST_BUFFER_DATA(buf) == GST_V4L2ELEMENT(v4l2src)->buffer[n]) {
gst_v4l2src_requeue_frame(v4l2src, n); gst_v4l2src_requeue_frame(v4l2src, n);
return; break;
} }
gst_element_error(GST_ELEMENT(v4l2src), if (n == v4l2src->breq.count)
"Couldn\'t find the buffer"); gst_element_error(GST_ELEMENT(v4l2src),
"Couldn\'t find the buffer");
/* free the buffer itself */
gst_buffer_default_free(buf);
} }