Commit 91d410ea authored by Jan Schmidt's avatar Jan Schmidt
Browse files

sys/v4l/: Add new v4ljpegsrc for handling the ov51x hacky "I'll give you jpeg...

sys/v4l/: Add new v4ljpegsrc for handling the ov51x hacky "I'll give you jpeg inside rgb frames" driver.

Original commit message from CVS:
* sys/v4l/gstv4l.c: (plugin_init):
* sys/v4l/gstv4ljpegsrc.c: (gst_v4ljpegsrc_get_type),
(gst_v4ljpegsrc_base_init), (gst_v4ljpegsrc_class_init),
(gst_v4ljpegsrc_init), (gst_v4ljpegsrc_src_link),
(gst_v4ljpegsrc_getcaps), (gst_v4ljpegsrc_get):
* sys/v4l/gstv4ljpegsrc.h:
* sys/v4l/gstv4lsrc.c: (gst_v4lsrc_open), (gst_v4lsrc_src_link):
* sys/v4l/v4l_calls.h:
* sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_palette_name),
(gst_v4lsrc_get_fps):
* sys/v4l/v4lsrc_calls.h:
Add new v4ljpegsrc for handling the ov51x hacky "I'll give
you jpeg inside rgb frames" driver.
Don't error in the v4lsrc link function, just return
REFUSED.
parent 4aa442fc
2005-02-04 Jan Schmidt <thaytan@mad.scientist.com>
* sys/v4l/gstv4l.c: (plugin_init):
* sys/v4l/gstv4ljpegsrc.c: (gst_v4ljpegsrc_get_type),
(gst_v4ljpegsrc_base_init), (gst_v4ljpegsrc_class_init),
(gst_v4ljpegsrc_init), (gst_v4ljpegsrc_src_link),
(gst_v4ljpegsrc_getcaps), (gst_v4ljpegsrc_get):
* sys/v4l/gstv4ljpegsrc.h:
* sys/v4l/gstv4lsrc.c: (gst_v4lsrc_open), (gst_v4lsrc_src_link):
* sys/v4l/v4l_calls.h:
* sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_palette_name),
(gst_v4lsrc_get_fps):
* sys/v4l/v4lsrc_calls.h:
Add new v4ljpegsrc for handling the ov51x hacky "I'll give
you jpeg inside rgb frames" driver.
Don't error in the v4lsrc link function, just return
REFUSED.
2005-02-03 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
 
* sys/qcam/gstqcamsrc.c: (gst_qcamsrc_change_state),
......
......@@ -11,6 +11,7 @@ endif
libgstvideo4linux_la_SOURCES = \
gstv4lelement.c v4l_calls.c \
gstv4lsrc.c v4lsrc_calls.c \
gstv4ljpegsrc.c \
gstv4lmjpegsrc.c v4lmjpegsrc_calls.c \
gstv4lmjpegsink.c v4lmjpegsink_calls.c \
gstv4l.c \
......@@ -26,6 +27,7 @@ libgstvideo4linux_la_LDFLAGS = \
noinst_HEADERS = gstv4lelement.h v4l_calls.h \
gstv4lsrc.h v4lsrc_calls.h \
gstv4ljpegsrc.h \
gstv4lmjpegsrc.h v4lmjpegsrc_calls.h \
gstv4lmjpegsink.h v4lmjpegsink_calls.h \
videodev_mjpeg.h \
......
......@@ -30,6 +30,7 @@
#include "gstv4lelement.h"
#include "gstv4lsrc.h"
#include "gstv4ljpegsrc.h"
#include "gstv4lmjpegsrc.h"
#include "gstv4lmjpegsink.h"
......@@ -44,6 +45,8 @@ plugin_init (GstPlugin * plugin)
GST_RANK_NONE, GST_TYPE_V4LELEMENT) ||
!gst_element_register (plugin, "v4lsrc",
GST_RANK_NONE, GST_TYPE_V4LSRC) ||
!gst_element_register (plugin, "v4ljpegsrc",
GST_RANK_NONE, GST_TYPE_V4LJPEGSRC) ||
!gst_element_register (plugin, "v4lmjpegsrc",
GST_RANK_NONE, GST_TYPE_V4LMJPEGSRC) ||
!gst_element_register (plugin, "v4lmjpegsink",
......
/* GStreamer
*
* gstv4ljpegsrc.c: V4L source element for JPEG cameras
*
* Copyright (C) 2004-2005 Jan Schmidt <thaytan@mad.scientist.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
e Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <sys/time.h>
#include "gstv4ljpegsrc.h"
#include "v4lsrc_calls.h"
/* elementfactory information */
static GstElementDetails gst_v4ljpegsrc_details =
GST_ELEMENT_DETAILS ("Video (video4linux/raw) Jpeg Source",
"Source/Video",
"Reads jpeg frames from a video4linux (eg ov519) device",
"Jan Schmidt <thaytan@mad.scientist.com>");
GST_DEBUG_CATEGORY (v4ljpegsrc_debug);
#define GST_CAT_DEFAULT v4ljpegsrc_debug
/* init functions */
static void gst_v4ljpegsrc_base_init (gpointer g_class);
static void gst_v4ljpegsrc_class_init (GstV4lJpegSrcClass * klass);
static void gst_v4ljpegsrc_init (GstV4lJpegSrc * v4ljpegsrc);
/* buffer functions */
static GstPadLinkReturn gst_v4ljpegsrc_src_link (GstPad * pad,
const GstCaps * caps);
static GstCaps *gst_v4ljpegsrc_getcaps (GstPad * pad);
static GstData *gst_v4ljpegsrc_get (GstPad * pad);
static GstElementClass *parent_class = NULL;
GType
gst_v4ljpegsrc_get_type (void)
{
static GType v4ljpegsrc_type = 0;
if (!v4ljpegsrc_type) {
static const GTypeInfo v4ljpegsrc_info = {
sizeof (GstV4lJpegSrcClass),
gst_v4ljpegsrc_base_init,
NULL,
(GClassInitFunc) gst_v4ljpegsrc_class_init,
NULL,
NULL,
sizeof (GstV4lJpegSrc),
0,
(GInstanceInitFunc) gst_v4ljpegsrc_init,
NULL
};
v4ljpegsrc_type =
g_type_register_static (GST_TYPE_V4LSRC, "GstV4lJpegSrc",
&v4ljpegsrc_info, 0);
GST_DEBUG_CATEGORY_INIT (v4ljpegsrc_debug, "v4ljpegsrc", 0,
"V4L JPEG source element");
}
return v4ljpegsrc_type;
}
static void
gst_v4ljpegsrc_base_init (gpointer g_class)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_set_details (gstelement_class, &gst_v4ljpegsrc_details);
}
static void
gst_v4ljpegsrc_class_init (GstV4lJpegSrcClass * klass)
{
parent_class = g_type_class_ref (GST_TYPE_V4LSRC);
}
static void
gst_v4ljpegsrc_init (GstV4lJpegSrc * v4ljpegsrc)
{
GstV4lSrc *v4lsrc = GST_V4LSRC (v4ljpegsrc);
GstPad *pad = v4lsrc->srcpad;
/*
* Stash away and then replace the getcaps and get functions on the src pad
*/
v4ljpegsrc->getfn = GST_RPAD_GETFUNC (pad);
v4ljpegsrc->getcapsfn = GST_RPAD_GETCAPSFUNC (pad);
gst_pad_set_get_function (v4lsrc->srcpad, gst_v4ljpegsrc_get);
gst_pad_set_getcaps_function (v4lsrc->srcpad, gst_v4ljpegsrc_getcaps);
gst_pad_set_link_function (v4lsrc->srcpad, gst_v4ljpegsrc_src_link);
}
static GstPadLinkReturn
gst_v4ljpegsrc_src_link (GstPad * pad, const GstCaps * vscapslist)
{
GstV4lJpegSrc *v4ljpegsrc;
GstV4lSrc *v4lsrc;
gint w, h, palette = -1;
gdouble fps;
GstStructure *structure;
gboolean was_capturing;
struct video_window *vwin;
v4ljpegsrc = GST_V4LJPEGSRC (gst_pad_get_parent (pad));
v4lsrc = GST_V4LSRC (v4ljpegsrc);
vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
was_capturing = v4lsrc->is_capturing;
/* in case the buffers are active (which means that we already
* did capsnego before and didn't clean up), clean up anyways */
if (GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))) {
if (was_capturing) {
if (!gst_v4lsrc_capture_stop (v4lsrc))
return GST_PAD_LINK_REFUSED;
}
if (!gst_v4lsrc_capture_deinit (v4lsrc))
return GST_PAD_LINK_REFUSED;
} else if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
return GST_PAD_LINK_DELAYED;
}
structure = gst_caps_get_structure (vscapslist, 0);
gst_structure_get_int (structure, "width", &w);
gst_structure_get_int (structure, "height", &h);
gst_structure_get_double (structure, "framerate", &fps);
GST_DEBUG_OBJECT (v4ljpegsrc, "linking with %dx%d at %f fps", w, h, fps);
/* set framerate if it's not already correct */
if (fps != gst_v4lsrc_get_fps (v4lsrc)) {
int fps_index = fps / 15.0 * 16;
GST_DEBUG_OBJECT (v4ljpegsrc, "Trying to set fps index %d", fps_index);
/* set bits 16 to 21 to 0 */
vwin->flags &= (0x3F00 - 1);
/* set bits 16 to 21 to the index */
vwin->flags |= fps_index << 16;
if (!gst_v4l_set_window_properties (GST_V4LELEMENT (v4lsrc))) {
return GST_PAD_LINK_DELAYED;
}
}
/*
* Try to set the camera to capture RGB24
*/
palette = VIDEO_PALETTE_RGB24;
v4lsrc->buffer_size = w * h * 3;
GST_DEBUG_OBJECT (v4ljpegsrc, "trying to set_capture %dx%d, palette %d",
w, h, palette);
/* this only fills in v4lsrc->mmap values */
if (!gst_v4lsrc_set_capture (v4lsrc, w, h, palette)) {
GST_WARNING_OBJECT (v4ljpegsrc, "could not set_capture %dx%d, palette %d",
w, h, palette);
return GST_PAD_LINK_REFUSED;
}
/* first try the negotiated settings using try_capture */
if (!gst_v4lsrc_try_capture (v4lsrc, w, h, palette)) {
GST_DEBUG_OBJECT (v4ljpegsrc, "failed trying palette %d for %dx%d", palette,
w, h);
return GST_PAD_LINK_REFUSED;
}
if (!gst_v4lsrc_capture_init (v4lsrc))
return GST_PAD_LINK_REFUSED;
if (was_capturing || GST_STATE (v4lsrc) == GST_STATE_PLAYING) {
if (!gst_v4lsrc_capture_start (v4lsrc))
return GST_PAD_LINK_REFUSED;
}
return GST_PAD_LINK_OK;
}
static GstCaps *
gst_v4ljpegsrc_getcaps (GstPad * pad)
{
GstCaps *list;
GstV4lJpegSrc *v4ljpegsrc = GST_V4LJPEGSRC (gst_pad_get_parent (pad));
GstV4lSrc *v4lsrc = GST_V4LSRC (v4ljpegsrc);
struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
gfloat fps = 0.0;
if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
return gst_caps_new_any ();
}
if (!v4lsrc->autoprobe) {
/* FIXME: query current caps and return those, with _any appended */
return gst_caps_new_any ();
}
list = gst_caps_new_simple ("image/jpeg", NULL);
GST_DEBUG_OBJECT (v4ljpegsrc,
"Device reports w: %d-%d, h: %d-%d, fps: %f",
vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight, fps);
if (vcap->minwidth < vcap->maxwidth) {
gst_caps_set_simple (list, "width", GST_TYPE_INT_RANGE, vcap->minwidth,
vcap->maxwidth, NULL);
} else {
gst_caps_set_simple (list, "width", G_TYPE_INT, vcap->minwidth, NULL);
}
if (vcap->minheight < vcap->maxheight) {
gst_caps_set_simple (list, "height", GST_TYPE_INT_RANGE, vcap->minheight,
vcap->maxheight, NULL);
} else {
gst_caps_set_simple (list, "height", G_TYPE_INT, vcap->minheight, NULL);
}
if (v4lsrc->fps_list) {
GstStructure *structure = gst_caps_get_structure (list, 0);
gst_structure_set_value (structure, "framerate", v4lsrc->fps_list);
}
GST_DEBUG_OBJECT (v4ljpegsrc, "caps: %" GST_PTR_FORMAT, list);
return list;
}
static GstData *
gst_v4ljpegsrc_get (GstPad * pad)
{
GstV4lJpegSrc *v4ljpegsrc;
GstV4lSrc *v4lsrc;
GstData *data;
GstBuffer *buf;
GstBuffer *outbuf;
int jpeg_size;
g_return_val_if_fail (pad != NULL, NULL);
v4ljpegsrc = GST_V4LJPEGSRC (gst_pad_get_parent (pad));
v4lsrc = GST_V4LSRC (v4ljpegsrc);
/* Fetch from the v4lsrc class get fn. */
data = v4ljpegsrc->getfn (pad);
/* If not a buffer, return it unchanged */
if (!data || (!GST_IS_BUFFER (data)))
return data;
buf = GST_BUFFER (data);
/* Confirm that the buffer contains jpeg data */
/*
* Create a new subbuffer from the jpeg data
* The first 2 bytes in the buffer are the size of the jpeg data
*/
if (GST_BUFFER_SIZE (buf) > 2) {
jpeg_size = (int) (GST_READ_UINT16_LE (GST_BUFFER_DATA (buf))) * 8;
} else
jpeg_size = 0;
/* Check that the size is sensible */
if ((jpeg_size <= 0) || (jpeg_size > GST_BUFFER_SIZE (buf) - 2)) {
GST_ELEMENT_ERROR (v4ljpegsrc, STREAM, FORMAT, (NULL),
("Invalid non-jpeg frame from camera"));
return NULL;
}
GST_DEBUG_OBJECT (v4ljpegsrc, "Creating JPEG subbuffer of size %d",
jpeg_size);
outbuf = gst_buffer_create_sub (buf, 2, jpeg_size);
/* Copy timestamps onto the subbuffer */
gst_buffer_stamp (outbuf, buf);
/* Release the main buffer */
gst_buffer_unref (buf);
return GST_DATA (outbuf);
}
/* GStreamer
*
* gstv4ljpegsrc.h: V4L video source element for JPEG cameras
*
* Copyright (C) 2001-2005 Jan Schmidt <thaytan@mad.scientist.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_V4LJPEGSRC_H__
#define __GST_V4LJPEGSRC_H__
#include <gstv4lsrc.h>
G_BEGIN_DECLS
#define GST_TYPE_V4LJPEGSRC \
(gst_v4ljpegsrc_get_type())
#define GST_V4LJPEGSRC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LJPEGSRC,GstV4lJpegSrc))
#define GST_V4LJPEGSRC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LJPEGSRC,GstV4lJpegSrcClass))
#define GST_IS_V4LJPEGSRC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LJPEGSRC))
#define GST_IS_V4LJPEGSRC_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LJPEGSRC))
typedef struct _GstV4lJpegSrc GstV4lJpegSrc;
typedef struct _GstV4lJpegSrcClass GstV4lJpegSrcClass;
struct _GstV4lJpegSrc
{
GstV4lSrc v4lsrc;
GstPadGetFunction getfn;
GstPadGetCapsFunction getcapsfn;
};
struct _GstV4lJpegSrcClass
{
GstV4lSrcClass parent_class;
};
GType gst_v4ljpegsrc_get_type (void);
G_END_DECLS
#endif /* __GST_V4LJPEGSRC_H__ */
......@@ -29,11 +29,6 @@
#include "v4lsrc_calls.h"
#include <sys/ioctl.h>
/* FIXME: small cheat */
gboolean gst_v4l_set_window_properties (GstV4lElement * v4lelement);
gboolean gst_v4l_get_capabilities (GstV4lElement * v4lelement);
extern const char *v4l_palette_name[];
/* elementfactory information */
static GstElementDetails gst_v4lsrc_details =
GST_ELEMENT_DETAILS ("Video (video4linux/raw) Source",
......@@ -320,7 +315,7 @@ gst_v4lsrc_open (GstElement * element, const gchar * device)
if (!gst_v4lsrc_try_capture (v4lsrc, width, height, palette[i]))
continue;
GST_DEBUG_OBJECT (v4lsrc, "Added palette %d (%s) to supported list",
palette[i], v4l_palette_name[palette[i]]);
palette[i], gst_v4lsrc_palette_name (palette[i]));
v4lsrc->colourspaces = g_list_append (v4lsrc->colourspaces,
GINT_TO_POINTER (palette[i]));
}
......@@ -400,54 +395,6 @@ gst_v4lsrc_get_fps_list (GstV4lSrc * v4lsrc)
return NULL;
}
static gfloat
gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc)
{
gint norm;
gint fps_index;
gfloat fps;
struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
/* check if we have vwin window properties giving a framerate,
* as is done for webcams
* See http://www.smcc.demon.nl/webcam/api.html
* which is used for the Philips and qce-ga drivers */
fps_index = (vwin->flags >> 16) & 0x3F; /* 6 bit index for framerate */
/* webcams have a non-zero fps_index */
if (fps_index != 0) {
gfloat current_fps;
/* index of 16 corresponds to 15 fps */
current_fps = fps_index * 15.0 / 16;
GST_LOG_OBJECT (v4lsrc, "device reports fps of %.4f", current_fps);
return current_fps;
}
if (!(v4lsrc->syncmode == GST_V4LSRC_SYNC_MODE_FIXED_FPS) &&
v4lsrc->clock != NULL && v4lsrc->handled > 0) {
/* try to get time from clock master and calculate fps */
GstClockTime time =
gst_clock_get_time (v4lsrc->clock) - v4lsrc->substract_time;
return v4lsrc->handled * GST_SECOND / time;
}
/* if that failed ... */
if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc)))
return 0.;
if (!gst_v4l_get_chan_norm (GST_V4LELEMENT (v4lsrc), NULL, &norm))
return 0.;
if (norm == VIDEO_MODE_NTSC)
fps = 30000 / 1001;
else
fps = 25.;
return fps;
}
static gboolean
gst_v4lsrc_src_convert (GstPad * pad,
GstFormat src_format,
......@@ -659,8 +606,7 @@ gst_v4lsrc_src_link (GstPad * pad, const GstCaps * vscapslist)
/* set bits 16 to 21 to the index */
vwin->flags |= fps_index << 16;
if (!gst_v4l_set_window_properties (GST_V4LELEMENT (v4lsrc))) {
GST_ELEMENT_ERROR (v4lsrc, RESOURCE, SETTINGS, (NULL),
("Could not set framerate of %f fps", fps));
return GST_PAD_LINK_REFUSED;
}
}
......
......@@ -144,6 +144,10 @@ gboolean gst_v4l_set_audio (GstV4lElement *v4lelement,
GstV4lAudioType type,
gint value);
/* functions that v4lsrc needs */
gboolean gst_v4l_set_window_properties (GstV4lElement * v4lelement);
gboolean gst_v4l_get_capabilities (GstV4lElement * v4lelement);
#ifdef __cplusplus
}
#endif /* __cplusplus */
......
......@@ -511,3 +511,57 @@ gst_v4lsrc_try_capture (GstV4lSrc * v4lsrc, gint width, gint height,
/* if we got here, it worked! woohoo, the format is supported! */
return TRUE;
}
const char *
gst_v4lsrc_palette_name (int i)
{
return v4l_palette_name[i];
}
gfloat
gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc)
{
gint norm;
gint fps_index;
gfloat fps;
struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
/* check if we have vwin window properties giving a framerate,
* as is done for webcams
* See http://www.smcc.demon.nl/webcam/api.html
* which is used for the Philips and qce-ga drivers */
fps_index = (vwin->flags >> 16) & 0x3F; /* 6 bit index for framerate */
/* webcams have a non-zero fps_index */
if (fps_index != 0) {
gfloat current_fps;
/* index of 16 corresponds to 15 fps */
current_fps = fps_index * 15.0 / 16;
GST_LOG_OBJECT (v4lsrc, "device reports fps of %.4f", current_fps);
return current_fps;
}
if (!(v4lsrc->syncmode == GST_V4LSRC_SYNC_MODE_FIXED_FPS) &&
v4lsrc->clock != NULL && v4lsrc->handled > 0) {
/* try to get time from clock master and calculate fps */
GstClockTime time =
gst_clock_get_time (v4lsrc->clock) - v4lsrc->substract_time;
return v4lsrc->handled * GST_SECOND / time;
}
/* if that failed ... */
if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc)))
return 0.;
if (!gst_v4l_get_chan_norm (GST_V4LELEMENT (v4lsrc), NULL, &norm))
return 0.;
if (norm == VIDEO_MODE_NTSC)
fps = 30000 / 1001;
else
fps = 25.;
return fps;
}
......@@ -40,10 +40,13 @@ guint8 * gst_v4lsrc_get_buffer (GstV4lSrc *v4lsrc, gint num);
gboolean gst_v4lsrc_requeue_frame (GstV4lSrc *v4lsrc, gint num);
gboolean gst_v4lsrc_capture_stop (GstV4lSrc *v4lsrc);
gboolean gst_v4lsrc_capture_deinit (GstV4lSrc *v4lsrc);
gfloat gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc);
/* "the ugliest hack ever, now available at your local mirror" */
gboolean gst_v4lsrc_try_capture (GstV4lSrc *v4lsrc, gint width, gint height, gint palette);
/* For debug purposes, share the palette names */
const char *gst_v4lsrc_palette_name (int i);
#ifdef __cplusplus
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment