From 91d410ea195a43182561ac54f79f0f411fb5f84e Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 3 Feb 2005 18:23:17 +0000 Subject: [PATCH] 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. --- ChangeLog | 17 +++ sys/v4l/Makefile.am | 2 + sys/v4l/gstv4l.c | 3 + sys/v4l/gstv4ljpegsrc.c | 295 ++++++++++++++++++++++++++++++++++++++++ sys/v4l/gstv4ljpegsrc.h | 57 ++++++++ sys/v4l/gstv4lsrc.c | 58 +------- sys/v4l/v4l_calls.h | 4 + sys/v4l/v4lsrc_calls.c | 54 ++++++++ sys/v4l/v4lsrc_calls.h | 3 + 9 files changed, 437 insertions(+), 56 deletions(-) create mode 100644 sys/v4l/gstv4ljpegsrc.c create mode 100644 sys/v4l/gstv4ljpegsrc.h diff --git a/ChangeLog b/ChangeLog index f5804edb39..e1c002ae35 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2005-02-04 Jan Schmidt + * 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 * sys/qcam/gstqcamsrc.c: (gst_qcamsrc_change_state), diff --git a/sys/v4l/Makefile.am b/sys/v4l/Makefile.am index 947c73875d..441a07c600 100644 --- a/sys/v4l/Makefile.am +++ b/sys/v4l/Makefile.am @@ -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 \ diff --git a/sys/v4l/gstv4l.c b/sys/v4l/gstv4l.c index bed2272448..5d641437b9 100644 --- a/sys/v4l/gstv4l.c +++ b/sys/v4l/gstv4l.c @@ -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", diff --git a/sys/v4l/gstv4ljpegsrc.c b/sys/v4l/gstv4ljpegsrc.c new file mode 100644 index 0000000000..1c34fcc111 --- /dev/null +++ b/sys/v4l/gstv4ljpegsrc.c @@ -0,0 +1,295 @@ +/* GStreamer + * + * gstv4ljpegsrc.c: V4L source element for JPEG cameras + * + * Copyright (C) 2004-2005 Jan Schmidt + * + * 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 +#endif + +#include +#include +#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 "); + +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); +} diff --git a/sys/v4l/gstv4ljpegsrc.h b/sys/v4l/gstv4ljpegsrc.h new file mode 100644 index 0000000000..0561ebf2fe --- /dev/null +++ b/sys/v4l/gstv4ljpegsrc.h @@ -0,0 +1,57 @@ +/* GStreamer + * + * gstv4ljpegsrc.h: V4L video source element for JPEG cameras + * + * Copyright (C) 2001-2005 Jan Schmidt + * + * 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 + +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__ */ diff --git a/sys/v4l/gstv4lsrc.c b/sys/v4l/gstv4lsrc.c index 30ba1992f2..31ee5ee0e2 100644 --- a/sys/v4l/gstv4lsrc.c +++ b/sys/v4l/gstv4lsrc.c @@ -29,11 +29,6 @@ #include "v4lsrc_calls.h" #include -/* 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; } } diff --git a/sys/v4l/v4l_calls.h b/sys/v4l/v4l_calls.h index 58240f77c6..5af7f90e37 100644 --- a/sys/v4l/v4l_calls.h +++ b/sys/v4l/v4l_calls.h @@ -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 */ diff --git a/sys/v4l/v4lsrc_calls.c b/sys/v4l/v4lsrc_calls.c index c816fe691f..91feeeb3aa 100644 --- a/sys/v4l/v4lsrc_calls.c +++ b/sys/v4l/v4lsrc_calls.c @@ -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; +} diff --git a/sys/v4l/v4lsrc_calls.h b/sys/v4l/v4lsrc_calls.h index 8ff1d7787c..f26eb55f6a 100644 --- a/sys/v4l/v4lsrc_calls.h +++ b/sys/v4l/v4lsrc_calls.h @@ -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 }