mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-26 02:00:33 +00:00
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:
parent
d9d0a69dec
commit
20538dadc9
7 changed files with 205 additions and 76 deletions
14
sys/v4l/TODO
14
sys/v4l/TODO
|
@ -1,24 +1,14 @@
|
||||||
TODO list (short term):
|
TODO list (short term):
|
||||||
=======================
|
=======================
|
||||||
* as soon as we've trashed Gtk-1.2, change 'gint palette'
|
* v4lsrc/v4lmjpegsrc/v4l2src: fix interlacing (not handled at all...)
|
||||||
to 'guint16 palette' in gstv4lsrc.[ch]
|
|
||||||
* v4lsrc: actually try the format out on capsnego
|
|
||||||
* all plugins: on try_set_caps(), loop try_set_caps() per caps
|
|
||||||
instead of using a multi-caps so we know the end-format
|
|
||||||
* all three: fix interlacing (not handled at all...)
|
|
||||||
* add overlay handling in v4lelement
|
|
||||||
* libgstrec
|
|
||||||
* avidemux: add events (seek)
|
|
||||||
* avimux: fps calculations (or make that a set/get_property()?)
|
|
||||||
|
|
||||||
TODO list (long term):
|
TODO list (long term):
|
||||||
======================
|
======================
|
||||||
* v4lmpegsrc (*hint* MPEG card needed *hint*)
|
* v4lmpegsrc (*hint* MPEG card needed *hint*)
|
||||||
* v4l2element && v4l2src
|
* v4l2sink
|
||||||
* BSD-videosrc (meteorsrc?)
|
* BSD-videosrc (meteorsrc?)
|
||||||
* color correction (brightness, hue, etc.)
|
* color correction (brightness, hue, etc.)
|
||||||
* gamma correction
|
* gamma correction
|
||||||
* dxr3sink
|
|
||||||
|
|
||||||
Useful Documentation:
|
Useful Documentation:
|
||||||
=====================
|
=====================
|
||||||
|
|
|
@ -71,6 +71,12 @@ static void gst_v4lmjpegsink_get_property (GObject
|
||||||
static GstElementStateReturn gst_v4lmjpegsink_change_state (GstElement *element);
|
static GstElementStateReturn gst_v4lmjpegsink_change_state (GstElement *element);
|
||||||
static void gst_v4lmjpegsink_set_clock (GstElement *element, GstClock *clock);
|
static void gst_v4lmjpegsink_set_clock (GstElement *element, GstClock *clock);
|
||||||
|
|
||||||
|
/* bufferpool functions */
|
||||||
|
static GstBuffer* gst_v4lmjpegsink_buffer_new (GstBufferPool *pool,
|
||||||
|
guint64 offset,
|
||||||
|
guint size,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
|
||||||
static GstCaps *capslist = NULL;
|
static GstCaps *capslist = NULL;
|
||||||
static GstPadTemplate *sink_template;
|
static GstPadTemplate *sink_template;
|
||||||
|
@ -174,6 +180,14 @@ gst_v4lmjpegsink_init (GstV4lMjpegSink *v4lmjpegsink)
|
||||||
v4lmjpegsink->bufsize = 256;
|
v4lmjpegsink->bufsize = 256;
|
||||||
|
|
||||||
GST_FLAG_SET(v4lmjpegsink, GST_ELEMENT_THREAD_SUGGESTED);
|
GST_FLAG_SET(v4lmjpegsink, GST_ELEMENT_THREAD_SUGGESTED);
|
||||||
|
|
||||||
|
v4lmjpegsink->bufferpool = gst_buffer_pool_new(
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
gst_v4lmjpegsink_buffer_new,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
v4lmjpegsink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -259,6 +273,13 @@ gst_v4lmjpegsink_chain (GstPad *pad,
|
||||||
gst_element_clock_wait(GST_ELEMENT(v4lmjpegsink), v4lmjpegsink->clock, GST_BUFFER_TIMESTAMP(buf), NULL);
|
gst_element_clock_wait(GST_ELEMENT(v4lmjpegsink), v4lmjpegsink->clock, GST_BUFFER_TIMESTAMP(buf), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GST_BUFFER_POOL(buf) == v4lmjpegsink->bufferpool)
|
||||||
|
{
|
||||||
|
num = GPOINTER_TO_INT(GST_BUFFER_POOL_PRIVATE(buf));
|
||||||
|
gst_v4lmjpegsink_play_frame(v4lmjpegsink, num);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* check size */
|
/* check size */
|
||||||
if (GST_BUFFER_SIZE(buf) > v4lmjpegsink->breq.size)
|
if (GST_BUFFER_SIZE(buf) > v4lmjpegsink->breq.size)
|
||||||
{
|
{
|
||||||
|
@ -273,6 +294,7 @@ gst_v4lmjpegsink_chain (GstPad *pad,
|
||||||
memcpy(gst_v4lmjpegsink_get_buffer(v4lmjpegsink, num),
|
memcpy(gst_v4lmjpegsink_get_buffer(v4lmjpegsink, num),
|
||||||
GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf));
|
GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf));
|
||||||
gst_v4lmjpegsink_play_frame(v4lmjpegsink, num);
|
gst_v4lmjpegsink_play_frame(v4lmjpegsink, num);
|
||||||
|
}
|
||||||
|
|
||||||
g_signal_emit(G_OBJECT(v4lmjpegsink),gst_v4lmjpegsink_signals[SIGNAL_FRAME_DISPLAYED],0);
|
g_signal_emit(G_OBJECT(v4lmjpegsink),gst_v4lmjpegsink_signals[SIGNAL_FRAME_DISPLAYED],0);
|
||||||
|
|
||||||
|
@ -280,6 +302,43 @@ gst_v4lmjpegsink_chain (GstPad *pad,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static GstBuffer *
|
||||||
|
gst_v4lmjpegsink_buffer_new (GstBufferPool *pool,
|
||||||
|
guint64 offset,
|
||||||
|
guint size,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GstV4lMjpegSink *v4lmjpegsink = GST_V4LMJPEGSINK(user_data);
|
||||||
|
GstBuffer *buffer = NULL;
|
||||||
|
guint8 *data;
|
||||||
|
gint num;
|
||||||
|
|
||||||
|
if (!GST_V4L_IS_ACTIVE(GST_V4LELEMENT(v4lmjpegsink)))
|
||||||
|
return NULL;
|
||||||
|
if (v4lmjpegsink->breq.size < size) {
|
||||||
|
GST_DEBUG(GST_CAT_PLUGIN_INFO, "Requested buffer size is too large (%d > %ld)",
|
||||||
|
size, v4lmjpegsink->breq.size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!gst_v4lmjpegsink_wait_frame(v4lmjpegsink, &num))
|
||||||
|
return NULL;
|
||||||
|
data = gst_v4lmjpegsink_get_buffer(v4lmjpegsink, num);
|
||||||
|
if (!data)
|
||||||
|
return NULL;
|
||||||
|
buffer = gst_buffer_new();
|
||||||
|
GST_BUFFER_DATA(buffer) = data;
|
||||||
|
GST_BUFFER_MAXSIZE(buffer) = v4lmjpegsink->breq.size;
|
||||||
|
GST_BUFFER_SIZE(buffer) = size;
|
||||||
|
GST_BUFFER_POOL(buffer) = pool;
|
||||||
|
GST_BUFFER_POOL_PRIVATE(buffer) = GINT_TO_POINTER(num);
|
||||||
|
|
||||||
|
/* with this flag set, we don't need our own buffer_free() function */
|
||||||
|
GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_DONTFREE);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4lmjpegsink_set_property (GObject *object,
|
gst_v4lmjpegsink_set_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
|
|
|
@ -68,6 +68,9 @@ struct _GstV4lMjpegSink {
|
||||||
pthread_cond_t *cond_queued_frames;
|
pthread_cond_t *cond_queued_frames;
|
||||||
gint current_frame;
|
gint current_frame;
|
||||||
|
|
||||||
|
/* something to get our buffers from */
|
||||||
|
GstBufferPool *bufferpool;
|
||||||
|
|
||||||
/* width/height/norm of the jpeg stream */
|
/* width/height/norm of the jpeg stream */
|
||||||
gint width;
|
gint width;
|
||||||
gint height;
|
gint height;
|
||||||
|
|
|
@ -86,9 +86,6 @@ static GstBuffer* gst_v4lmjpegsrc_buffer_new (GstBufferPool *pool,
|
||||||
guint64 location,
|
guint64 location,
|
||||||
guint size,
|
guint size,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
static GstBuffer* gst_v4lmjpegsrc_buffer_copy (GstBufferPool *pool,
|
|
||||||
const GstBuffer *srcbuf,
|
|
||||||
gpointer user_data);
|
|
||||||
static void gst_v4lmjpegsrc_buffer_free (GstBufferPool *pool,
|
static void gst_v4lmjpegsrc_buffer_free (GstBufferPool *pool,
|
||||||
GstBuffer *buf,
|
GstBuffer *buf,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
@ -195,7 +192,7 @@ gst_v4lmjpegsrc_init (GstV4lMjpegSrc *v4lmjpegsrc)
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
gst_v4lmjpegsrc_buffer_new,
|
gst_v4lmjpegsrc_buffer_new,
|
||||||
gst_v4lmjpegsrc_buffer_copy,
|
NULL,
|
||||||
gst_v4lmjpegsrc_buffer_free,
|
gst_v4lmjpegsrc_buffer_free,
|
||||||
v4lmjpegsrc);
|
v4lmjpegsrc);
|
||||||
|
|
||||||
|
@ -553,28 +550,18 @@ gst_v4lmjpegsrc_buffer_new (GstBufferPool *pool,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
|
GstV4lMjpegSrc *v4lmjpegsrc = GST_V4LMJPEGSRC(user_data);
|
||||||
|
|
||||||
|
if (!GST_V4L_IS_ACTIVE(GST_V4LELEMENT(v4lmjpegsrc)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
buffer = gst_buffer_new();
|
buffer = gst_buffer_new();
|
||||||
if (!buffer) return NULL;
|
if (!buffer)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* TODO: add interlacing info to buffer as metadata */
|
/* TODO: add interlacing info to buffer as metadata */
|
||||||
|
GST_BUFFER_MAXSIZE(buffer) = v4lmjpegsrc->breq.size;
|
||||||
return buffer;
|
GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_DONTFREE);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static GstBuffer*
|
|
||||||
gst_v4lmjpegsrc_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_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;
|
||||||
}
|
}
|
||||||
|
@ -586,15 +573,22 @@ gst_v4lmjpegsrc_buffer_free (GstBufferPool *pool, GstBuffer *buf, gpointer user_
|
||||||
GstV4lMjpegSrc *v4lmjpegsrc = GST_V4LMJPEGSRC (user_data);
|
GstV4lMjpegSrc *v4lmjpegsrc = GST_V4LMJPEGSRC (user_data);
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
if (gst_element_get_state(GST_ELEMENT(v4lmjpegsrc)) != GST_STATE_PLAYING)
|
||||||
|
return; /* we've already cleaned up ourselves */
|
||||||
|
|
||||||
for (n=0;n<v4lmjpegsrc->breq.count;n++)
|
for (n=0;n<v4lmjpegsrc->breq.count;n++)
|
||||||
if (GST_BUFFER_DATA(buf) == gst_v4lmjpegsrc_get_buffer(v4lmjpegsrc, n))
|
if (GST_BUFFER_DATA(buf) == gst_v4lmjpegsrc_get_buffer(v4lmjpegsrc, n))
|
||||||
{
|
{
|
||||||
gst_v4lmjpegsrc_requeue_frame(v4lmjpegsrc, n);
|
gst_v4lmjpegsrc_requeue_frame(v4lmjpegsrc, n);
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (n == v4lmjpegsrc->breq.count)
|
||||||
gst_element_error(GST_ELEMENT(v4lmjpegsrc),
|
gst_element_error(GST_ELEMENT(v4lmjpegsrc),
|
||||||
"Couldn't find the buffer");
|
"Couldn't find the buffer");
|
||||||
|
|
||||||
|
/* free the buffer struct et all */
|
||||||
|
gst_buffer_default_free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -82,9 +82,6 @@ static GstBuffer* gst_v4lsrc_buffer_new (GstBufferPool *pool,
|
||||||
guint64 offset,
|
guint64 offset,
|
||||||
guint size,
|
guint size,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
static GstBuffer* gst_v4lsrc_buffer_copy (GstBufferPool *pool,
|
|
||||||
const GstBuffer *srcbuf,
|
|
||||||
gpointer user_data);
|
|
||||||
static void gst_v4lsrc_buffer_free (GstBufferPool *pool,
|
static void gst_v4lsrc_buffer_free (GstBufferPool *pool,
|
||||||
GstBuffer *buf,
|
GstBuffer *buf,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
@ -172,7 +169,7 @@ gst_v4lsrc_init (GstV4lSrc *v4lsrc)
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
gst_v4lsrc_buffer_new,
|
gst_v4lsrc_buffer_new,
|
||||||
gst_v4lsrc_buffer_copy,
|
NULL,
|
||||||
gst_v4lsrc_buffer_free,
|
gst_v4lsrc_buffer_free,
|
||||||
v4lsrc);
|
v4lsrc);
|
||||||
|
|
||||||
|
@ -388,9 +385,8 @@ gst_v4lsrc_srcconnect (GstPad *pad,
|
||||||
|
|
||||||
/* if this caps was useful, try it out */
|
/* if this caps was useful, try it out */
|
||||||
try_caps:
|
try_caps:
|
||||||
/* TODO: try the current 'palette' out on the video device */
|
/* try the current 'palette' out on the video device */
|
||||||
|
if (!gst_v4lsrc_try_palette(v4lsrc, palette))
|
||||||
if (!gst_v4lsrc_set_capture(v4lsrc, v4lsrc->width, v4lsrc->height, palette))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* try to connect the pad/caps with the actual width/height */
|
/* try to connect the pad/caps with the actual width/height */
|
||||||
|
@ -428,6 +424,9 @@ gst_v4lsrc_srcconnect (GstPad *pad,
|
||||||
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;
|
||||||
|
|
||||||
|
if (!gst_v4lsrc_set_capture(v4lsrc, v4lsrc->width, v4lsrc->height, palette))
|
||||||
|
return GST_PAD_CONNECT_REFUSED;
|
||||||
|
|
||||||
if (!gst_v4lsrc_capture_init(v4lsrc))
|
if (!gst_v4lsrc_capture_init(v4lsrc))
|
||||||
return GST_PAD_CONNECT_REFUSED;
|
return GST_PAD_CONNECT_REFUSED;
|
||||||
|
|
||||||
|
@ -616,27 +615,19 @@ gst_v4lsrc_buffer_new (GstBufferPool *pool,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
|
GstV4lSrc *v4lsrc = GST_V4LSRC(user_data);
|
||||||
|
|
||||||
|
if (!GST_V4L_IS_ACTIVE(GST_V4LELEMENT(v4lsrc)))
|
||||||
|
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) = v4lsrc->mbuf.size / v4lsrc->mbuf.frames;
|
||||||
|
GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_DONTFREE);
|
||||||
static GstBuffer*
|
|
||||||
gst_v4lsrc_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_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;
|
||||||
}
|
}
|
||||||
|
@ -648,15 +639,22 @@ gst_v4lsrc_buffer_free (GstBufferPool *pool, GstBuffer *buf, gpointer user_data)
|
||||||
GstV4lSrc *v4lsrc = GST_V4LSRC (user_data);
|
GstV4lSrc *v4lsrc = GST_V4LSRC (user_data);
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
if (gst_element_get_state(GST_ELEMENT(v4lsrc)) != GST_STATE_PLAYING)
|
||||||
|
return; /* we've already cleaned up ourselves */
|
||||||
|
|
||||||
for (n=0;n<v4lsrc->mbuf.frames;n++)
|
for (n=0;n<v4lsrc->mbuf.frames;n++)
|
||||||
if (GST_BUFFER_DATA(buf) == gst_v4lsrc_get_buffer(v4lsrc, n))
|
if (GST_BUFFER_DATA(buf) == gst_v4lsrc_get_buffer(v4lsrc, n))
|
||||||
{
|
{
|
||||||
gst_v4lsrc_requeue_frame(v4lsrc, n);
|
gst_v4lsrc_requeue_frame(v4lsrc, n);
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (n == v4lsrc->mbuf.frames)
|
||||||
gst_element_error(GST_ELEMENT(v4lsrc),
|
gst_element_error(GST_ELEMENT(v4lsrc),
|
||||||
"Couldn\'t find the buffer");
|
"Couldn\'t find the buffer");
|
||||||
|
|
||||||
|
/* free struct */
|
||||||
|
gst_buffer_default_free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -493,3 +493,85 @@ gst_v4lsrc_capture_deinit (GstV4lSrc *v4lsrc)
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************
|
||||||
|
* gst_v4lsrc_try_palette():
|
||||||
|
* try out a palette on the device
|
||||||
|
* This has to be done before initializing the
|
||||||
|
* actual capture system, to make sure we don't
|
||||||
|
* mess up anything. So we need to mini-mmap()
|
||||||
|
* a buffer here, queue and sync on one buffer,
|
||||||
|
* and unmap it.
|
||||||
|
* This is ugly, yes, I know - but it's a major
|
||||||
|
* design flaw of v4l1 that you don't know in
|
||||||
|
* advance which formats will be supported...
|
||||||
|
* This is better than "just assuming that it'll
|
||||||
|
* work"...
|
||||||
|
* return value: TRUE on success, FALSE on error
|
||||||
|
******************************************************/
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_v4lsrc_try_palette (GstV4lSrc *v4lsrc,
|
||||||
|
gint palette)
|
||||||
|
{
|
||||||
|
/* so, we need a buffer and some more stuff */
|
||||||
|
int frame = 0;
|
||||||
|
guint8 *buffer;
|
||||||
|
struct video_mbuf vmbuf;
|
||||||
|
struct video_mmap vmmap;
|
||||||
|
|
||||||
|
DEBUG("gonna try out palette format %d (%s)",
|
||||||
|
palette, palette_name[palette]);
|
||||||
|
GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lsrc));
|
||||||
|
GST_V4L_CHECK_NOT_ACTIVE(GST_V4LELEMENT(v4lsrc));
|
||||||
|
|
||||||
|
/* let's start by requesting a buffer and mmap()'ing it */
|
||||||
|
if (ioctl(GST_V4LELEMENT(v4lsrc)->video_fd, VIDIOCGMBUF, &vmbuf) < 0)
|
||||||
|
{
|
||||||
|
gst_element_error(GST_ELEMENT(v4lsrc),
|
||||||
|
"Error getting buffer information: %s",
|
||||||
|
sys_errlist[errno]);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
/* Map the buffers */
|
||||||
|
buffer = mmap(0, vmbuf.size, PROT_READ|PROT_WRITE,
|
||||||
|
MAP_SHARED, GST_V4LELEMENT(v4lsrc)->video_fd, 0);
|
||||||
|
if (buffer == MAP_FAILED)
|
||||||
|
{
|
||||||
|
gst_element_error(GST_ELEMENT(v4lsrc),
|
||||||
|
"Error mapping our try-out buffer: %s",
|
||||||
|
sys_errlist[errno]);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now that we have a buffer, let's try out our format */
|
||||||
|
vmmap.width = GST_V4LELEMENT(v4lsrc)->vcap.minwidth;
|
||||||
|
vmmap.height = GST_V4LELEMENT(v4lsrc)->vcap.minheight;
|
||||||
|
vmmap.format = palette;
|
||||||
|
vmmap.frame = frame;
|
||||||
|
if (ioctl(GST_V4LELEMENT(v4lsrc)->video_fd, VIDIOCMCAPTURE, &vmmap) < 0)
|
||||||
|
{
|
||||||
|
if (errno != EINVAL) /* our format failed! */
|
||||||
|
gst_element_error(GST_ELEMENT(v4lsrc),
|
||||||
|
"Error queueing our try-out buffer: %s",
|
||||||
|
sys_errlist[errno]);
|
||||||
|
munmap(buffer, vmbuf.size);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(GST_V4LELEMENT(v4lsrc)->video_fd, VIDIOCSYNC, &frame) < 0)
|
||||||
|
{
|
||||||
|
gst_element_error(GST_ELEMENT(v4lsrc),
|
||||||
|
"Error syncing on a buffer (%d): %s",
|
||||||
|
frame, sys_errlist[errno]);
|
||||||
|
munmap(buffer, vmbuf.size);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
munmap(buffer, vmbuf.size);
|
||||||
|
|
||||||
|
/* if we got here, it worked! woohoo, the format is supported! */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,9 @@ gboolean gst_v4lsrc_requeue_frame (GstV4lSrc *v4lsrc, gint num);
|
||||||
gboolean gst_v4lsrc_capture_stop (GstV4lSrc *v4lsrc);
|
gboolean gst_v4lsrc_capture_stop (GstV4lSrc *v4lsrc);
|
||||||
gboolean gst_v4lsrc_capture_deinit (GstV4lSrc *v4lsrc);
|
gboolean gst_v4lsrc_capture_deinit (GstV4lSrc *v4lsrc);
|
||||||
|
|
||||||
|
/* "the ugliest hack ever, now available at your local mirror" */
|
||||||
|
gboolean gst_v4lsrc_try_palette (GstV4lSrc *v4lsrc, gint palette);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue