summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/v4l2/gstv4l2element.c3
-rw-r--r--sys/v4l2/gstv4l2src.c121
2 files changed, 67 insertions, 57 deletions
diff --git a/sys/v4l2/gstv4l2element.c b/sys/v4l2/gstv4l2element.c
index 2ab68a38..01f0fa1c 100644
--- a/sys/v4l2/gstv4l2element.c
+++ b/sys/v4l2/gstv4l2element.c
@@ -23,10 +23,11 @@
#include "v4l2_calls.h"
-
+/* elementfactory details */
static GstElementDetails gst_v4l2element_details = {
"Generic video4linux2 Element",
"None/Video",
+ "LGPL",
"Generic plugin for handling common video4linux2 calls",
VERSION,
"Ronald Bultje <rbultje@ronald.bitfreak.net>",
diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c
index d5ca7106..6ba0ea08 100644
--- a/sys/v4l2/gstv4l2src.c
+++ b/sys/v4l2/gstv4l2src.c
@@ -21,10 +21,11 @@
#include <sys/time.h>
#include "v4l2src_calls.h"
-
+/* elementfactory details */
static GstElementDetails gst_v4l2src_details = {
"Video (video4linux2) Source",
"Source/Video",
+ "LGPL",
"Reads frames (compressed or uncompressed) from a video4linux2 device",
VERSION,
"Ronald Bultje <rbultje@ronald.bitfreak.net>",
@@ -63,6 +64,8 @@ static gboolean gst_v4l2src_srcconvert (GstPad *pad,
gint64 *dest_value);
static GstPadConnectReturn gst_v4l2src_srcconnect (GstPad *pad,
GstCaps *caps);
+static GstCaps * gst_v4l2src_getcaps (GstPad *pad,
+ GstCaps *caps);
static GstBuffer * gst_v4l2src_get (GstPad *pad);
/* get/set params */
@@ -83,9 +86,6 @@ static GstBuffer * gst_v4l2src_buffer_new (GstBufferPool *pool,
guint64 offset,
guint size,
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,
GstBuffer *buf,
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_connect_function(v4l2src->srcpad, gst_v4l2src_srcconnect);
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,
gst_v4l2src_buffer_new,
- gst_v4l2src_buffer_copy,
+ NULL,
gst_v4l2src_buffer_free,
v4l2src);
@@ -562,33 +563,15 @@ gst_v4l2src_srcconnect (GstPad *pad,
/* clean up if we still haven't cleaned up our previous
* capture session */
- if (GST_V4L2_IS_ACTIVE(GST_V4L2ELEMENT(v4l2src)))
- {
+ if (GST_V4L2_IS_ACTIVE(v4l2element)) {
if (!gst_v4l2src_capture_deinit(v4l2src))
return GST_PAD_CONNECT_REFUSED;
- }
- else if (!GST_V4L2_IS_OPEN(GST_V4L2ELEMENT(v4l2src)))
- {
+ } else if (!GST_V4L2_IS_OPEN(v4l2element)) {
return GST_PAD_CONNECT_DELAYED;
}
/* 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);
- }
- }
+ owncapslist = gst_v4l2src_getcaps(pad, NULL);
/* and now, get the caps that we have in common */
if (!(caps = gst_v4l2src_caps_intersect(owncapslist, vscapslist)))
@@ -618,13 +601,10 @@ gst_v4l2src_srcconnect (GstPad *pad,
for (;lastcaps != NULL; lastcaps = lastcaps->next) {
GstPadConnectReturn ret_val;
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))
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;
}
}
@@ -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*
gst_v4l2src_get (GstPad *pad)
{
@@ -660,7 +674,6 @@ gst_v4l2src_get (GstPad *pad)
return NULL;
GST_BUFFER_DATA(buf) = GST_V4L2ELEMENT(v4l2src)->buffer[num];
GST_BUFFER_SIZE(buf) = v4l2src->bufsettings.bytesused;
- GST_BUFFER_MAXSIZE(buf) = v4l2src->bufsettings.length;
if (!v4l2src->first_timestamp)
v4l2src->first_timestamp = v4l2src->bufsettings.timestamp;
GST_BUFFER_TIMESTAMP(buf) = v4l2src->bufsettings.length - v4l2src->first_timestamp;
@@ -834,30 +847,19 @@ gst_v4l2src_buffer_new (GstBufferPool *pool,
gpointer user_data)
{
GstBuffer *buffer;
+ GstV4l2Src *v4l2src = GST_V4L2SRC(user_data);
- buffer = gst_buffer_new();
- if (!buffer) return NULL;
- /* TODO: add interlacing info to buffer as metadata (height>288 or 240 = topfieldfirst, else noninterlaced) */
-
- return buffer;
-}
-
-
-static GstBuffer*
-gst_v4l2src_buffer_copy (GstBufferPool *pool,
- const GstBuffer *srcbuf,
- gpointer user_data)
-{
- GstBuffer *buffer;
+ if (!GST_V4L2_IS_ACTIVE(GST_V4L2ELEMENT(v4l2src)))
+ return NULL;
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);
+ if (!buffer)
+ return NULL;
+
+ /* 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);
return buffer;
}
@@ -871,14 +873,21 @@ gst_v4l2src_buffer_free (GstBufferPool *pool,
GstV4l2Src *v4l2src = GST_V4L2SRC(user_data);
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++)
if (GST_BUFFER_DATA(buf) == GST_V4L2ELEMENT(v4l2src)->buffer[n]) {
gst_v4l2src_requeue_frame(v4l2src, n);
- return;
+ break;
}
- gst_element_error(GST_ELEMENT(v4l2src),
- "Couldn\'t find the buffer");
+ if (n == v4l2src->breq.count)
+ gst_element_error(GST_ELEMENT(v4l2src),
+ "Couldn\'t find the buffer");
+
+ /* free the buffer itself */
+ gst_buffer_default_free(buf);
}