2006-09-02 14:28:55 +00:00
/* GStreamer
*
2006-05-11 17:59:59 +00:00
* Copyright ( C ) 2001 - 2002 Ronald Bultje < rbultje @ ronald . bitfreak . net >
2006-09-02 14:28:55 +00:00
* 2006 Edgard Lima < edgard . lima @ indt . org . br >
*
* gstv4l2object . c : base class for V4L2 elements
2006-05-11 17:59:59 +00:00
*
* 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 ,
2009-08-04 07:14:20 +00:00
* USA .
2006-05-11 17:59:59 +00:00
*/
2012-02-27 13:47:25 +00:00
/* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
* with newer GLib versions ( > = 2.31 .0 ) */
# define GLIB_DISABLE_DEPRECATION_WARNINGS
2006-05-11 17:59:59 +00:00
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
# include <sys/stat.h>
# include <fcntl.h>
# include <errno.h>
# include <unistd.h>
# include <string.h>
2009-07-03 06:38:43 +00:00
# ifdef HAVE_GUDEV
# include <gudev/gudev.h>
# endif
2006-05-11 17:59:59 +00:00
# include "v4l2_calls.h"
# include "gstv4l2tuner.h"
2010-04-04 11:37:16 +00:00
# ifdef HAVE_XVIDEO
2011-08-08 14:25:31 +00:00
# include "gstv4l2videooverlay.h"
2006-05-11 17:59:59 +00:00
# endif
# include "gstv4l2colorbalance.h"
2009-08-04 07:14:20 +00:00
# include "gst/gst-i18n-plugin.h"
2011-07-08 12:34:40 +00:00
# include <gst/video/video.h>
2011-01-12 20:38:59 +00:00
/* videodev2.h is not versioned and we can't easily check for the presence
* of enum values at compile time , but the V4L2_CAP_VIDEO_OUTPUT_OVERLAY define
* was added in the same commit as V4L2_FIELD_INTERLACED_ { TB , BT } ( b2787845 ) */
# ifndef V4L2_CAP_VIDEO_OUTPUT_OVERLAY
# define V4L2_FIELD_INTERLACED_TB 8
# define V4L2_FIELD_INTERLACED_BT 9
# endif
2009-08-04 07:14:20 +00:00
GST_DEBUG_CATEGORY_EXTERN ( v4l2_debug ) ;
2011-07-13 16:32:00 +00:00
GST_DEBUG_CATEGORY_EXTERN ( GST_CAT_PERFORMANCE ) ;
2009-08-04 07:14:20 +00:00
# define GST_CAT_DEFAULT v4l2_debug
2006-09-26 13:18:06 +00:00
# define DEFAULT_PROP_DEVICE_NAME NULL
2008-03-26 15:10:08 +00:00
# define DEFAULT_PROP_DEVICE_FD -1
2006-09-26 13:18:06 +00:00
# define DEFAULT_PROP_FLAGS 0
2010-04-04 11:43:41 +00:00
# define DEFAULT_PROP_TV_NORM 0
sys/v4l2/: Renamed some properties to match the tuner interface naming.
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c:
(gst_v4l2_object_install_properties_helper), (gst_v4l2_object_new),
(gst_v4l2_object_set_property_helper),
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_create):
* sys/v4l2/gstv4l2tuner.c: (gst_v4l2_tuner_contains_channel),
(gst_v4l2_tuner_list_channels),
(gst_v4l2_tuner_set_channel_and_notify),
(gst_v4l2_tuner_get_channel), (gst_v4l2_tuner_contains_norm),
(gst_v4l2_tuner_list_norms), (gst_v4l2_tuner_set_norm_and_notify),
(gst_v4l2_tuner_get_norm):
* sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
(gst_v4l2_fill_lists), (gst_v4l2_empty_lists):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_get_fps):
Renamed some properties to match the tuner interface naming.
2006-09-27 17:04:22 +00:00
# define DEFAULT_PROP_CHANNEL NULL
2006-09-26 13:18:06 +00:00
# define DEFAULT_PROP_FREQUENCY 0
2011-07-18 16:54:49 +00:00
# define DEFAULT_PROP_IO_MODE GST_V4L2_IO_AUTO
2006-09-26 13:18:06 +00:00
2006-05-18 19:34:47 +00:00
enum
{
PROP_0 ,
V4L2_STD_OBJECT_PROPS ,
} ;
2011-12-21 10:59:46 +00:00
#if 0
2010-12-07 10:40:58 +00:00
G_LOCK_DEFINE_STATIC ( probe_lock ) ;
2006-05-18 19:34:47 +00:00
const GList *
2006-05-11 17:59:59 +00:00
gst_v4l2_probe_get_properties ( GstPropertyProbe * probe )
{
GObjectClass * klass = G_OBJECT_GET_CLASS ( probe ) ;
static GList * list = NULL ;
2010-12-07 10:40:58 +00:00
G_LOCK ( probe_lock ) ;
2006-05-11 17:59:59 +00:00
if ( ! list ) {
list = g_list_append ( NULL , g_object_class_find_property ( klass , " device " ) ) ;
}
2010-12-07 10:40:58 +00:00
G_UNLOCK ( probe_lock ) ;
2006-05-11 17:59:59 +00:00
return list ;
}
2009-07-03 06:38:43 +00:00
static gboolean init = FALSE ;
static GList * devices = NULL ;
# ifdef HAVE_GUDEV
2006-05-11 17:59:59 +00:00
static gboolean
2009-07-03 06:38:43 +00:00
gst_v4l2_class_probe_devices_with_udev ( GstElementClass * klass , gboolean check ,
2006-05-11 17:59:59 +00:00
GList * * klass_devices )
{
2009-11-10 10:52:24 +00:00
GUdevClient * client = NULL ;
2009-07-03 06:38:43 +00:00
GList * item ;
if ( ! check ) {
while ( devices ) {
gchar * device = devices - > data ;
devices = g_list_remove ( devices , device ) ;
g_free ( device ) ;
}
GST_INFO ( " Enumerating video4linux devices from udev " ) ;
client = g_udev_client_new ( NULL ) ;
if ( ! client ) {
GST_WARNING ( " Failed to initialize gudev client " ) ;
goto finish ;
}
item = g_udev_client_query_by_subsystem ( client , " video4linux " ) ;
while ( item ) {
GUdevDevice * device = item - > data ;
gchar * devnode = g_strdup ( g_udev_device_get_device_file ( device ) ) ;
gint api = g_udev_device_get_property_as_int ( device , " ID_V4L_VERSION " ) ;
GST_INFO ( " Found new device: %s, API: %d " , devnode , api ) ;
/* Append v4l2 devices only. If api is 0 probably v4l_id has
been stripped out of the current udev installation , append
anyway */
if ( api = = 0 ) {
GST_WARNING
( " Couldn't retrieve ID_V4L_VERSION, silly udev installation? " ) ;
}
if ( ( api = = 2 | | api = = 0 ) ) {
devices = g_list_append ( devices , devnode ) ;
} else {
g_free ( devnode ) ;
}
g_object_unref ( device ) ;
item = item - > next ;
}
g_list_free ( item ) ;
init = TRUE ;
}
finish :
if ( client ) {
g_object_unref ( client ) ;
}
* klass_devices = devices ;
2006-05-11 17:59:59 +00:00
2009-07-03 06:38:43 +00:00
return init ;
}
# endif /* HAVE_GUDEV */
static gboolean
gst_v4l2_class_probe_devices ( GstElementClass * klass , gboolean check ,
GList * * klass_devices )
{
2008-08-23 15:33:49 +00:00
if ( ! check ) {
2006-05-18 19:34:47 +00:00
const gchar * dev_base [ ] = { " /dev/video " , " /dev/v4l2/video " , NULL } ;
2006-05-11 17:59:59 +00:00
gint base , n , fd ;
while ( devices ) {
2009-07-03 06:38:43 +00:00
gchar * device = devices - > data ;
2008-08-23 15:33:49 +00:00
devices = g_list_remove ( devices , device ) ;
2006-05-11 17:59:59 +00:00
g_free ( device ) ;
}
/*
2009-08-04 07:14:20 +00:00
* detect / dev entries
2006-05-11 17:59:59 +00:00
*/
for ( n = 0 ; n < 64 ; n + + ) {
for ( base = 0 ; dev_base [ base ] ! = NULL ; base + + ) {
struct stat s ;
gchar * device = g_strdup_printf ( " %s%d " ,
dev_base [ base ] ,
n ) ;
/*
2009-08-04 07:14:20 +00:00
* does the / dev / entry exist at all ?
2006-05-11 17:59:59 +00:00
*/
if ( stat ( device , & s ) = = 0 ) {
/*
2009-08-04 07:14:20 +00:00
* yes : is a device attached ?
2006-05-11 17:59:59 +00:00
*/
if ( S_ISCHR ( s . st_mode ) ) {
if ( ( fd = open ( device , O_RDWR | O_NONBLOCK ) ) > 0 | | errno = = EBUSY ) {
if ( fd > 0 )
close ( fd ) ;
devices = g_list_append ( devices , device ) ;
break ;
}
}
}
g_free ( device ) ;
}
}
init = TRUE ;
}
* klass_devices = devices ;
return init ;
}
void
gst_v4l2_probe_probe_property ( GstPropertyProbe * probe ,
guint prop_id , const GParamSpec * pspec , GList * * klass_devices )
{
GstElementClass * klass = GST_ELEMENT_GET_CLASS ( probe ) ;
switch ( prop_id ) {
case PROP_DEVICE :
2009-07-03 06:38:43 +00:00
# ifdef HAVE_GUDEV
if ( ! gst_v4l2_class_probe_devices_with_udev ( klass , FALSE , klass_devices ) )
gst_v4l2_class_probe_devices ( klass , FALSE , klass_devices ) ;
# else /* !HAVE_GUDEV */
2006-05-11 17:59:59 +00:00
gst_v4l2_class_probe_devices ( klass , FALSE , klass_devices ) ;
2009-07-03 06:38:43 +00:00
# endif /* HAVE_GUDEV */
2006-05-11 17:59:59 +00:00
break ;
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID ( probe , prop_id , pspec ) ;
break ;
}
}
gboolean
gst_v4l2_probe_needs_probe ( GstPropertyProbe * probe ,
guint prop_id , const GParamSpec * pspec , GList * * klass_devices )
{
GstElementClass * klass = GST_ELEMENT_GET_CLASS ( probe ) ;
gboolean ret = FALSE ;
switch ( prop_id ) {
case PROP_DEVICE :
2009-07-03 06:38:43 +00:00
# ifdef HAVE_GUDEV
ret =
! gst_v4l2_class_probe_devices_with_udev ( klass , FALSE , klass_devices ) ;
# else /* !HAVE_GUDEV */
2006-05-11 17:59:59 +00:00
ret = ! gst_v4l2_class_probe_devices ( klass , TRUE , klass_devices ) ;
2009-07-03 06:38:43 +00:00
# endif /* HAVE_GUDEV */
2006-05-11 17:59:59 +00:00
break ;
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID ( probe , prop_id , pspec ) ;
break ;
}
return ret ;
}
static GValueArray *
gst_v4l2_class_list_devices ( GstElementClass * klass , GList * * klass_devices )
{
GValueArray * array ;
GValue value = { 0 } ;
GList * item ;
if ( ! * klass_devices )
return NULL ;
array = g_value_array_new ( g_list_length ( * klass_devices ) ) ;
item = * klass_devices ;
g_value_init ( & value , G_TYPE_STRING ) ;
while ( item ) {
gchar * device = item - > data ;
g_value_set_string ( & value , device ) ;
g_value_array_append ( array , & value ) ;
item = item - > next ;
}
g_value_unset ( & value ) ;
return array ;
}
GValueArray *
gst_v4l2_probe_get_values ( GstPropertyProbe * probe ,
guint prop_id , const GParamSpec * pspec , GList * * klass_devices )
{
GstElementClass * klass = GST_ELEMENT_GET_CLASS ( probe ) ;
GValueArray * array = NULL ;
switch ( prop_id ) {
case PROP_DEVICE :
array = gst_v4l2_class_list_devices ( klass , klass_devices ) ;
break ;
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID ( probe , prop_id , pspec ) ;
break ;
}
return array ;
}
2011-12-21 10:59:46 +00:00
# endif
2006-05-11 17:59:59 +00:00
# define GST_TYPE_V4L2_DEVICE_FLAGS (gst_v4l2_device_get_type ())
2010-03-17 17:23:00 +00:00
static GType
2006-05-11 17:59:59 +00:00
gst_v4l2_device_get_type ( void )
{
static GType v4l2_device_type = 0 ;
if ( v4l2_device_type = = 0 ) {
static const GFlagsValue values [ ] = {
2006-09-26 13:18:06 +00:00
{ V4L2_CAP_VIDEO_CAPTURE , " Device supports video capture " , " capture " } ,
{ V4L2_CAP_VIDEO_OUTPUT , " Device supports video playback " , " output " } ,
{ V4L2_CAP_VIDEO_OVERLAY , " Device supports video overlay " , " overlay " } ,
{ V4L2_CAP_VBI_CAPTURE , " Device supports the VBI capture " , " vbi-capture " } ,
{ V4L2_CAP_VBI_OUTPUT , " Device supports the VBI output " , " vbi-output " } ,
{ V4L2_CAP_TUNER , " Device has a tuner or modulator " , " tuner " } ,
{ V4L2_CAP_AUDIO , " Device has audio inputs or outputs " , " audio " } ,
2006-05-11 17:59:59 +00:00
{ 0 , NULL , NULL }
} ;
v4l2_device_type =
g_flags_register_static ( " GstV4l2DeviceTypeFlags " , values ) ;
}
return v4l2_device_type ;
}
2010-04-04 11:43:41 +00:00
# define GST_TYPE_V4L2_TV_NORM (gst_v4l2_tv_norm_get_type ())
static GType
gst_v4l2_tv_norm_get_type ( void )
{
static GType v4l2_tv_norm = 0 ;
if ( ! v4l2_tv_norm ) {
static const GEnumValue tv_norms [ ] = {
{ 0 , " none " , " none " } ,
{ V4L2_STD_NTSC , " NTSC " , " NTSC " } ,
{ V4L2_STD_NTSC_M , " NTSC-M " , " NTSC-M " } ,
{ V4L2_STD_NTSC_M_JP , " NTSC-M-JP " , " NTSC-M-JP " } ,
{ V4L2_STD_NTSC_M_KR , " NTSC-M-KR " , " NTSC-M-KR " } ,
{ V4L2_STD_NTSC_443 , " NTSC-443 " , " NTSC-443 " } ,
{ V4L2_STD_PAL , " PAL " , " PAL " } ,
{ V4L2_STD_PAL_BG , " PAL-BG " , " PAL-BG " } ,
{ V4L2_STD_PAL_B , " PAL-B " , " PAL-B " } ,
{ V4L2_STD_PAL_B1 , " PAL-B1 " , " PAL-B1 " } ,
{ V4L2_STD_PAL_G , " PAL-G " , " PAL-G " } ,
{ V4L2_STD_PAL_H , " PAL-H " , " PAL-H " } ,
{ V4L2_STD_PAL_I , " PAL-I " , " PAL-I " } ,
{ V4L2_STD_PAL_DK , " PAL-DK " , " PAL-DK " } ,
{ V4L2_STD_PAL_D , " PAL-D " , " PAL-D " } ,
{ V4L2_STD_PAL_D1 , " PAL-D1 " , " PAL-D1 " } ,
{ V4L2_STD_PAL_K , " PAL-K " , " PAL-K " } ,
{ V4L2_STD_PAL_M , " PAL-M " , " PAL-M " } ,
{ V4L2_STD_PAL_N , " PAL-N " , " PAL-N " } ,
{ V4L2_STD_PAL_Nc , " PAL-Nc " , " PAL-Nc " } ,
{ V4L2_STD_PAL_60 , " PAL-60 " , " PAL-60 " } ,
{ V4L2_STD_SECAM , " SECAM " , " SECAM " } ,
{ V4L2_STD_SECAM_B , " SECAM-B " , " SECAM-B " } ,
{ V4L2_STD_SECAM_G , " SECAM-G " , " SECAM-G " } ,
{ V4L2_STD_SECAM_H , " SECAM-H " , " SECAM-H " } ,
{ V4L2_STD_SECAM_DK , " SECAM-DK " , " SECAM-DK " } ,
{ V4L2_STD_SECAM_D , " SECAM-D " , " SECAM-D " } ,
{ V4L2_STD_SECAM_K , " SECAM-K " , " SECAM-K " } ,
{ V4L2_STD_SECAM_K1 , " SECAM-K1 " , " SECAM-K1 " } ,
{ V4L2_STD_SECAM_L , " SECAM-L " , " SECAM-L " } ,
{ V4L2_STD_SECAM_LC , " SECAM-Lc " , " SECAM-Lc " } ,
{ 0 , NULL , NULL }
} ;
v4l2_tv_norm = g_enum_register_static ( " V4L2_TV_norms " , tv_norms ) ;
}
return v4l2_tv_norm ;
}
2011-07-18 16:54:49 +00:00
# define GST_TYPE_V4L2_IO_MODE (gst_v4l2_io_mode_get_type ())
static GType
gst_v4l2_io_mode_get_type ( void )
{
static GType v4l2_io_mode = 0 ;
if ( ! v4l2_io_mode ) {
static const GEnumValue io_modes [ ] = {
{ GST_V4L2_IO_AUTO , " GST_V4L2_IO_AUTO " , " auto " } ,
{ GST_V4L2_IO_RW , " GST_V4L2_IO_RW " , " rw " } ,
{ GST_V4L2_IO_MMAP , " GST_V4L2_IO_MMAP " , " mmap " } ,
{ GST_V4L2_IO_USERPTR , " GST_V4L2_IO_USERPTR " , " userptr " } ,
{ 0 , NULL , NULL }
} ;
v4l2_io_mode = g_enum_register_static ( " GstV4l2IOMode " , io_modes ) ;
}
return v4l2_io_mode ;
}
2006-05-11 17:59:59 +00:00
void
2009-08-04 07:14:20 +00:00
gst_v4l2_object_install_properties_helper ( GObjectClass * gobject_class ,
const char * default_device )
2006-05-11 17:59:59 +00:00
{
2006-09-26 13:18:06 +00:00
g_object_class_install_property ( gobject_class , PROP_DEVICE ,
g_param_spec_string ( " device " , " Device " , " Device location " ,
2010-06-21 09:15:14 +00:00
default_device , G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ) ) ;
2006-09-26 13:18:06 +00:00
g_object_class_install_property ( gobject_class , PROP_DEVICE_NAME ,
g_param_spec_string ( " device-name " , " Device name " ,
2010-06-21 09:15:14 +00:00
" Name of the device " , DEFAULT_PROP_DEVICE_NAME ,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS ) ) ;
2008-03-26 15:10:08 +00:00
g_object_class_install_property ( gobject_class , PROP_DEVICE_FD ,
g_param_spec_int ( " device-fd " , " File descriptor " ,
" File descriptor of the device " , - 1 , G_MAXINT , DEFAULT_PROP_DEVICE_FD ,
2010-06-21 09:15:14 +00:00
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS ) ) ;
2006-09-26 13:18:06 +00:00
g_object_class_install_property ( gobject_class , PROP_FLAGS ,
g_param_spec_flags ( " flags " , " Flags " , " Device type flags " ,
2010-06-21 09:15:14 +00:00
GST_TYPE_V4L2_DEVICE_FLAGS , DEFAULT_PROP_FLAGS ,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS ) ) ;
2010-06-22 12:48:04 +00:00
2010-09-15 16:02:57 +00:00
/**
* GstV4l2Src : brightness
*
* Picture brightness , or more precisely , the black level
*
* Since : 0.10 .26
*/
2010-06-22 12:48:04 +00:00
g_object_class_install_property ( gobject_class , PROP_BRIGHTNESS ,
g_param_spec_int ( " brightness " , " Brightness " ,
" Picture brightness, or more precisely, the black level " , G_MININT ,
G_MAXINT , 0 ,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE ) ) ;
2010-09-15 16:02:57 +00:00
/**
* GstV4l2Src : contrast
*
* Picture contrast or luma gain
*
* Since : 0.10 .26
*/
2010-06-22 12:48:04 +00:00
g_object_class_install_property ( gobject_class , PROP_CONTRAST ,
g_param_spec_int ( " contrast " , " Contrast " ,
" Picture contrast or luma gain " , G_MININT ,
G_MAXINT , 0 ,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE ) ) ;
2010-09-15 16:02:57 +00:00
/**
* GstV4l2Src : saturation
*
* Picture color saturation or chroma gain
*
* Since : 0.10 .26
*/
2010-06-22 12:48:04 +00:00
g_object_class_install_property ( gobject_class , PROP_SATURATION ,
g_param_spec_int ( " saturation " , " Saturation " ,
" Picture color saturation or chroma gain " , G_MININT ,
G_MAXINT , 0 ,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE ) ) ;
2010-09-15 16:02:57 +00:00
/**
* GstV4l2Src : hue
*
* Hue or color balance
*
* Since : 0.10 .26
*/
2010-06-22 12:48:04 +00:00
g_object_class_install_property ( gobject_class , PROP_HUE ,
g_param_spec_int ( " hue " , " Hue " ,
" Hue or color balance " , G_MININT ,
G_MAXINT , 0 ,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE ) ) ;
2010-04-04 11:43:41 +00:00
/**
* GstV4l2Src : norm
*
* TV norm
*
2011-08-02 22:42:58 +00:00
* Since : 0.10 .31
2010-04-04 11:43:41 +00:00
*/
g_object_class_install_property ( gobject_class , PROP_TV_NORM ,
g_param_spec_enum ( " norm " , " TV norm " ,
" video standard " ,
GST_TYPE_V4L2_TV_NORM , DEFAULT_PROP_TV_NORM ,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ) ) ;
2011-07-18 16:54:49 +00:00
/**
* GstV4l2Src : io - mode
*
* IO Mode
*/
g_object_class_install_property ( gobject_class , PROP_IO_MODE ,
g_param_spec_enum ( " io-mode " , " IO mode " ,
" I/O mode " ,
GST_TYPE_V4L2_IO_MODE , DEFAULT_PROP_IO_MODE ,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ) ) ;
2006-05-11 17:59:59 +00:00
}
GstV4l2Object *
2006-05-19 18:31:25 +00:00
gst_v4l2_object_new ( GstElement * element ,
2009-08-04 07:14:20 +00:00
enum v4l2_buf_type type ,
2010-03-19 23:54:14 +00:00
const char * default_device ,
2006-05-11 17:59:59 +00:00
GstV4l2GetInOutFunction get_in_out_func ,
2007-05-30 14:57:44 +00:00
GstV4l2SetInOutFunction set_in_out_func ,
GstV4l2UpdateFpsFunction update_fps_func )
2006-05-11 17:59:59 +00:00
{
GstV4l2Object * v4l2object ;
/*
2009-08-04 07:14:20 +00:00
* some default values
2006-05-11 17:59:59 +00:00
*/
v4l2object = g_new0 ( GstV4l2Object , 1 ) ;
2009-08-04 07:14:20 +00:00
v4l2object - > type = type ;
v4l2object - > formats = NULL ;
2006-05-11 17:59:59 +00:00
v4l2object - > element = element ;
v4l2object - > get_in_out_func = get_in_out_func ;
v4l2object - > set_in_out_func = set_in_out_func ;
2007-05-30 14:57:44 +00:00
v4l2object - > update_fps_func = update_fps_func ;
2006-05-11 17:59:59 +00:00
v4l2object - > video_fd = - 1 ;
2009-03-01 18:55:26 +00:00
v4l2object - > poll = gst_poll_new ( TRUE ) ;
2011-07-13 09:19:28 +00:00
v4l2object - > active = FALSE ;
2009-08-04 07:14:20 +00:00
v4l2object - > videodev = g_strdup ( default_device ) ;
2006-05-11 17:59:59 +00:00
sys/v4l2/: Renamed some properties to match the tuner interface naming.
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c:
(gst_v4l2_object_install_properties_helper), (gst_v4l2_object_new),
(gst_v4l2_object_set_property_helper),
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_create):
* sys/v4l2/gstv4l2tuner.c: (gst_v4l2_tuner_contains_channel),
(gst_v4l2_tuner_list_channels),
(gst_v4l2_tuner_set_channel_and_notify),
(gst_v4l2_tuner_get_channel), (gst_v4l2_tuner_contains_norm),
(gst_v4l2_tuner_list_norms), (gst_v4l2_tuner_set_norm_and_notify),
(gst_v4l2_tuner_get_norm):
* sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
(gst_v4l2_fill_lists), (gst_v4l2_empty_lists):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_get_fps):
Renamed some properties to match the tuner interface naming.
2006-09-27 17:04:22 +00:00
v4l2object - > norms = NULL ;
v4l2object - > channels = NULL ;
2006-05-11 17:59:59 +00:00
v4l2object - > colors = NULL ;
v4l2object - > xwindow_id = 0 ;
return v4l2object ;
}
2009-08-04 07:14:20 +00:00
static gboolean gst_v4l2_object_clear_format_list ( GstV4l2Object * v4l2object ) ;
2006-05-11 17:59:59 +00:00
void
Fix a bunch of leaks shown by the newly-added states test.
Original commit message from CVS:
* ext/flac/gstflacenc.c: (gst_flac_enc_finalize):
* ext/gconf/gstgconfaudiosink.c: (gst_gconf_audio_sink_class_init),
(gst_gconf_audio_sink_dispose), (gst_gconf_audio_sink_finalize):
* ext/gconf/gstgconfaudiosrc.c: (gst_gconf_audio_src_base_init),
(gst_gconf_audio_src_class_init), (gst_gconf_audio_src_dispose),
(gst_gconf_audio_src_finalize), (do_toggle_element):
* ext/gconf/gstgconfvideosink.c: (gst_gconf_video_sink_base_init),
(gst_gconf_video_sink_class_init), (gst_gconf_video_sink_finalize),
(do_toggle_element):
* ext/gconf/gstgconfvideosrc.c: (gst_gconf_video_src_base_init),
(gst_gconf_video_src_class_init), (gst_gconf_video_src_dispose),
(gst_gconf_video_src_finalize), (do_toggle_element):
* ext/gconf/gstswitchsink.c: (gst_switch_sink_class_init),
(gst_switch_sink_reset), (gst_switch_sink_set_child):
* ext/hal/gsthalaudiosink.c: (gst_hal_audio_sink_base_init):
* ext/hal/gsthalaudiosrc.c: (gst_hal_audio_src_base_init):
* ext/shout2/gstshout2.c: (gst_shout2send_class_init),
(gst_shout2send_init), (gst_shout2send_finalize):
* gst/debug/testplugin.c: (gst_test_class_init),
(gst_test_finalize):
* gst/flx/gstflxdec.c: (gst_flxdec_class_init),
(gst_flxdec_dispose):
* gst/multipart/multipartmux.c: (gst_multipart_mux_finalize):
* gst/rtp/gstrtpmp4gpay.c: (gst_rtp_mp4g_pay_finalize):
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_init),
(gst_rtspsrc_finalize):
* gst/rtsp/rtspextwms.c: (rtsp_ext_wms_free_context):
* gst/rtsp/rtspextwms.h:
* gst/smpte/gstsmpte.c: (gst_smpte_class_init),
(gst_smpte_finalize):
* gst/udp/gstmultiudpsink.c: (gst_multiudpsink_finalize):
* gst/udp/gstudpsink.c: (gst_udpsink_class_init),
(gst_udpsink_finalize):
* gst/wavparse/gstwavparse.c: (gst_wavparse_dispose),
(gst_wavparse_sink_activate):
* sys/oss/gstosssink.c: (gst_oss_sink_finalise):
* sys/oss/gstosssrc.c: (gst_oss_src_class_init),
(gst_oss_src_finalize):
* sys/v4l2/gstv4l2object.c: (gst_v4l2_object_destroy):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_finalize):
* sys/ximage/gstximagesrc.c: (gst_ximage_src_ximage_get):
Fix a bunch of leaks shown by the newly-added states test.
2007-03-04 13:52:03 +00:00
gst_v4l2_object_destroy ( GstV4l2Object * v4l2object )
2006-05-11 17:59:59 +00:00
{
Fix a bunch of leaks shown by the newly-added states test.
Original commit message from CVS:
* ext/flac/gstflacenc.c: (gst_flac_enc_finalize):
* ext/gconf/gstgconfaudiosink.c: (gst_gconf_audio_sink_class_init),
(gst_gconf_audio_sink_dispose), (gst_gconf_audio_sink_finalize):
* ext/gconf/gstgconfaudiosrc.c: (gst_gconf_audio_src_base_init),
(gst_gconf_audio_src_class_init), (gst_gconf_audio_src_dispose),
(gst_gconf_audio_src_finalize), (do_toggle_element):
* ext/gconf/gstgconfvideosink.c: (gst_gconf_video_sink_base_init),
(gst_gconf_video_sink_class_init), (gst_gconf_video_sink_finalize),
(do_toggle_element):
* ext/gconf/gstgconfvideosrc.c: (gst_gconf_video_src_base_init),
(gst_gconf_video_src_class_init), (gst_gconf_video_src_dispose),
(gst_gconf_video_src_finalize), (do_toggle_element):
* ext/gconf/gstswitchsink.c: (gst_switch_sink_class_init),
(gst_switch_sink_reset), (gst_switch_sink_set_child):
* ext/hal/gsthalaudiosink.c: (gst_hal_audio_sink_base_init):
* ext/hal/gsthalaudiosrc.c: (gst_hal_audio_src_base_init):
* ext/shout2/gstshout2.c: (gst_shout2send_class_init),
(gst_shout2send_init), (gst_shout2send_finalize):
* gst/debug/testplugin.c: (gst_test_class_init),
(gst_test_finalize):
* gst/flx/gstflxdec.c: (gst_flxdec_class_init),
(gst_flxdec_dispose):
* gst/multipart/multipartmux.c: (gst_multipart_mux_finalize):
* gst/rtp/gstrtpmp4gpay.c: (gst_rtp_mp4g_pay_finalize):
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_init),
(gst_rtspsrc_finalize):
* gst/rtsp/rtspextwms.c: (rtsp_ext_wms_free_context):
* gst/rtsp/rtspextwms.h:
* gst/smpte/gstsmpte.c: (gst_smpte_class_init),
(gst_smpte_finalize):
* gst/udp/gstmultiudpsink.c: (gst_multiudpsink_finalize):
* gst/udp/gstudpsink.c: (gst_udpsink_class_init),
(gst_udpsink_finalize):
* gst/wavparse/gstwavparse.c: (gst_wavparse_dispose),
(gst_wavparse_sink_activate):
* sys/oss/gstosssink.c: (gst_oss_sink_finalise):
* sys/oss/gstosssrc.c: (gst_oss_src_class_init),
(gst_oss_src_finalize):
* sys/v4l2/gstv4l2object.c: (gst_v4l2_object_destroy):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_finalize):
* sys/ximage/gstximagesrc.c: (gst_ximage_src_ximage_get):
Fix a bunch of leaks shown by the newly-added states test.
2007-03-04 13:52:03 +00:00
g_return_if_fail ( v4l2object ! = NULL ) ;
2006-05-11 17:59:59 +00:00
Fix a bunch of leaks shown by the newly-added states test.
Original commit message from CVS:
* ext/flac/gstflacenc.c: (gst_flac_enc_finalize):
* ext/gconf/gstgconfaudiosink.c: (gst_gconf_audio_sink_class_init),
(gst_gconf_audio_sink_dispose), (gst_gconf_audio_sink_finalize):
* ext/gconf/gstgconfaudiosrc.c: (gst_gconf_audio_src_base_init),
(gst_gconf_audio_src_class_init), (gst_gconf_audio_src_dispose),
(gst_gconf_audio_src_finalize), (do_toggle_element):
* ext/gconf/gstgconfvideosink.c: (gst_gconf_video_sink_base_init),
(gst_gconf_video_sink_class_init), (gst_gconf_video_sink_finalize),
(do_toggle_element):
* ext/gconf/gstgconfvideosrc.c: (gst_gconf_video_src_base_init),
(gst_gconf_video_src_class_init), (gst_gconf_video_src_dispose),
(gst_gconf_video_src_finalize), (do_toggle_element):
* ext/gconf/gstswitchsink.c: (gst_switch_sink_class_init),
(gst_switch_sink_reset), (gst_switch_sink_set_child):
* ext/hal/gsthalaudiosink.c: (gst_hal_audio_sink_base_init):
* ext/hal/gsthalaudiosrc.c: (gst_hal_audio_src_base_init):
* ext/shout2/gstshout2.c: (gst_shout2send_class_init),
(gst_shout2send_init), (gst_shout2send_finalize):
* gst/debug/testplugin.c: (gst_test_class_init),
(gst_test_finalize):
* gst/flx/gstflxdec.c: (gst_flxdec_class_init),
(gst_flxdec_dispose):
* gst/multipart/multipartmux.c: (gst_multipart_mux_finalize):
* gst/rtp/gstrtpmp4gpay.c: (gst_rtp_mp4g_pay_finalize):
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_init),
(gst_rtspsrc_finalize):
* gst/rtsp/rtspextwms.c: (rtsp_ext_wms_free_context):
* gst/rtsp/rtspextwms.h:
* gst/smpte/gstsmpte.c: (gst_smpte_class_init),
(gst_smpte_finalize):
* gst/udp/gstmultiudpsink.c: (gst_multiudpsink_finalize):
* gst/udp/gstudpsink.c: (gst_udpsink_class_init),
(gst_udpsink_finalize):
* gst/wavparse/gstwavparse.c: (gst_wavparse_dispose),
(gst_wavparse_sink_activate):
* sys/oss/gstosssink.c: (gst_oss_sink_finalise):
* sys/oss/gstosssrc.c: (gst_oss_src_class_init),
(gst_oss_src_finalize):
* sys/v4l2/gstv4l2object.c: (gst_v4l2_object_destroy):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_finalize):
* sys/ximage/gstximagesrc.c: (gst_ximage_src_ximage_get):
Fix a bunch of leaks shown by the newly-added states test.
2007-03-04 13:52:03 +00:00
if ( v4l2object - > videodev )
g_free ( v4l2object - > videodev ) ;
2009-03-01 18:55:26 +00:00
if ( v4l2object - > poll )
gst_poll_free ( v4l2object - > poll ) ;
2008-08-26 12:27:11 +00:00
if ( v4l2object - > channel )
g_free ( v4l2object - > channel ) ;
2009-08-04 07:14:20 +00:00
if ( v4l2object - > formats ) {
gst_v4l2_object_clear_format_list ( v4l2object ) ;
}
Fix a bunch of leaks shown by the newly-added states test.
Original commit message from CVS:
* ext/flac/gstflacenc.c: (gst_flac_enc_finalize):
* ext/gconf/gstgconfaudiosink.c: (gst_gconf_audio_sink_class_init),
(gst_gconf_audio_sink_dispose), (gst_gconf_audio_sink_finalize):
* ext/gconf/gstgconfaudiosrc.c: (gst_gconf_audio_src_base_init),
(gst_gconf_audio_src_class_init), (gst_gconf_audio_src_dispose),
(gst_gconf_audio_src_finalize), (do_toggle_element):
* ext/gconf/gstgconfvideosink.c: (gst_gconf_video_sink_base_init),
(gst_gconf_video_sink_class_init), (gst_gconf_video_sink_finalize),
(do_toggle_element):
* ext/gconf/gstgconfvideosrc.c: (gst_gconf_video_src_base_init),
(gst_gconf_video_src_class_init), (gst_gconf_video_src_dispose),
(gst_gconf_video_src_finalize), (do_toggle_element):
* ext/gconf/gstswitchsink.c: (gst_switch_sink_class_init),
(gst_switch_sink_reset), (gst_switch_sink_set_child):
* ext/hal/gsthalaudiosink.c: (gst_hal_audio_sink_base_init):
* ext/hal/gsthalaudiosrc.c: (gst_hal_audio_src_base_init):
* ext/shout2/gstshout2.c: (gst_shout2send_class_init),
(gst_shout2send_init), (gst_shout2send_finalize):
* gst/debug/testplugin.c: (gst_test_class_init),
(gst_test_finalize):
* gst/flx/gstflxdec.c: (gst_flxdec_class_init),
(gst_flxdec_dispose):
* gst/multipart/multipartmux.c: (gst_multipart_mux_finalize):
* gst/rtp/gstrtpmp4gpay.c: (gst_rtp_mp4g_pay_finalize):
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_init),
(gst_rtspsrc_finalize):
* gst/rtsp/rtspextwms.c: (rtsp_ext_wms_free_context):
* gst/rtsp/rtspextwms.h:
* gst/smpte/gstsmpte.c: (gst_smpte_class_init),
(gst_smpte_finalize):
* gst/udp/gstmultiudpsink.c: (gst_multiudpsink_finalize):
* gst/udp/gstudpsink.c: (gst_udpsink_class_init),
(gst_udpsink_finalize):
* gst/wavparse/gstwavparse.c: (gst_wavparse_dispose),
(gst_wavparse_sink_activate):
* sys/oss/gstosssink.c: (gst_oss_sink_finalise):
* sys/oss/gstosssrc.c: (gst_oss_src_class_init),
(gst_oss_src_finalize):
* sys/v4l2/gstv4l2object.c: (gst_v4l2_object_destroy):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_finalize):
* sys/ximage/gstximagesrc.c: (gst_ximage_src_ximage_get):
Fix a bunch of leaks shown by the newly-added states test.
2007-03-04 13:52:03 +00:00
g_free ( v4l2object ) ;
2006-05-11 17:59:59 +00:00
}
2009-08-04 07:14:20 +00:00
static gboolean
gst_v4l2_object_clear_format_list ( GstV4l2Object * v4l2object )
{
g_slist_foreach ( v4l2object - > formats , ( GFunc ) g_free , NULL ) ;
g_slist_free ( v4l2object - > formats ) ;
v4l2object - > formats = NULL ;
return TRUE ;
}
2010-06-22 12:48:04 +00:00
static gint
gst_v4l2_object_prop_to_cid ( guint prop_id )
{
gint cid = - 1 ;
switch ( prop_id ) {
case PROP_BRIGHTNESS :
cid = V4L2_CID_BRIGHTNESS ;
break ;
case PROP_CONTRAST :
cid = V4L2_CID_CONTRAST ;
break ;
case PROP_SATURATION :
cid = V4L2_CID_SATURATION ;
break ;
case PROP_HUE :
cid = V4L2_CID_HUE ;
break ;
default :
GST_WARNING ( " unmapped property id: %d " , prop_id ) ;
}
return cid ;
}
2009-08-04 07:14:20 +00:00
2006-05-11 17:59:59 +00:00
gboolean
2006-05-19 18:31:25 +00:00
gst_v4l2_object_set_property_helper ( GstV4l2Object * v4l2object ,
2006-05-11 17:59:59 +00:00
guint prop_id , const GValue * value , GParamSpec * pspec )
{
switch ( prop_id ) {
case PROP_DEVICE :
Small cleanups.
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c: (gst_v4l2_object_set_property_helper),
(gst_v4l2_set_defaults):
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_get_read),
(gst_v4l2src_create):
* sys/v4l2/gstv4l2xoverlay.c: (gst_v4l2_xoverlay_open):
* sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
(gst_v4l2_fill_lists), (gst_v4l2_open), (gst_v4l2_set_norm),
(gst_v4l2_get_frequency), (gst_v4l2_set_frequency),
(gst_v4l2_signal_strength), (gst_v4l2_get_attribute),
(gst_v4l2_set_attribute), (gst_v4l2_get_input),
(gst_v4l2_set_input):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list),
(gst_v4l2src_grab_frame), (gst_v4l2src_get_capture),
(gst_v4l2src_set_capture), (gst_v4l2src_capture_init),
(gst_v4l2src_capture_start), (gst_v4l2src_capture_stop),
(gst_v4l2src_buffer_new):
* tests/icles/v4l2src-test.c: (my_bus_callback), (main):
Small cleanups.
Fix error messages.
Use locks when getting timestamps.
Fix leaks in test.
Add licensing header to tests.
2006-09-27 16:14:18 +00:00
g_free ( v4l2object - > videodev ) ;
sys/v4l2/: Fix pass at code cleanups, move errors cases out of the normal flow for additional code clarity.
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c: (gst_v4l2_class_probe_devices),
(gst_v4l2_probe_needs_probe),
(gst_v4l2_object_install_properties_helper), (gst_v4l2_object_new),
(gst_v4l2_object_destroy), (gst_v4l2_object_set_property_helper),
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults),
(gst_v4l2_object_start), (gst_v4l2_object_stop):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_init), (gst_v4l2src_dispose),
(gst_v4l2src_set_property), (gst_v4l2src_get_property),
(gst_v4l2src_fixate), (gst_v4l2src_get_caps),
(gst_v4l2src_set_caps), (gst_v4l2src_get_read),
(gst_v4l2src_get_mmap), (gst_v4l2src_create):
* sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
(gst_v4l2_open), (gst_v4l2_close), (gst_v4l2_get_norm),
(gst_v4l2_set_norm), (gst_v4l2_get_frequency),
(gst_v4l2_set_frequency), (gst_v4l2_signal_strength),
(gst_v4l2_get_attribute), (gst_v4l2_set_attribute),
(gst_v4l2_get_input), (gst_v4l2_set_input):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list),
(gst_v4l2src_queue_frame), (gst_v4l2src_grab_frame),
(gst_v4l2src_get_capture), (gst_v4l2src_set_capture),
(gst_v4l2src_capture_init), (gst_v4l2src_capture_start),
(gst_v4l2src_capture_stop), (gst_v4l2src_capture_deinit),
(gst_v4l2src_get_size_limits), (gst_v4l2src_set_fps),
(gst_v4l2src_get_fps), (gst_v4l2src_buffer_finalize),
(gst_v4l2src_buffer_new):
Fix pass at code cleanups, move errors cases out of the normal
flow for additional code clarity.
2006-09-26 11:06:17 +00:00
v4l2object - > videodev = g_value_dup_string ( value ) ;
2006-05-11 17:59:59 +00:00
break ;
2010-06-22 12:48:04 +00:00
case PROP_BRIGHTNESS :
case PROP_CONTRAST :
case PROP_SATURATION :
case PROP_HUE :
{
gint cid = gst_v4l2_object_prop_to_cid ( prop_id ) ;
if ( cid ! = - 1 ) {
if ( GST_V4L2_IS_OPEN ( v4l2object ) ) {
gst_v4l2_set_attribute ( v4l2object , cid , g_value_get_int ( value ) ) ;
}
}
return TRUE ;
}
break ;
2010-04-04 11:43:41 +00:00
case PROP_TV_NORM :
v4l2object - > tv_norm = g_value_get_enum ( value ) ;
2006-05-11 17:59:59 +00:00
break ;
2010-04-04 11:43:41 +00:00
#if 0
sys/v4l2/: Renamed some properties to match the tuner interface naming.
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c:
(gst_v4l2_object_install_properties_helper), (gst_v4l2_object_new),
(gst_v4l2_object_set_property_helper),
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_create):
* sys/v4l2/gstv4l2tuner.c: (gst_v4l2_tuner_contains_channel),
(gst_v4l2_tuner_list_channels),
(gst_v4l2_tuner_set_channel_and_notify),
(gst_v4l2_tuner_get_channel), (gst_v4l2_tuner_contains_norm),
(gst_v4l2_tuner_list_norms), (gst_v4l2_tuner_set_norm_and_notify),
(gst_v4l2_tuner_get_norm):
* sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
(gst_v4l2_fill_lists), (gst_v4l2_empty_lists):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_get_fps):
Renamed some properties to match the tuner interface naming.
2006-09-27 17:04:22 +00:00
case PROP_CHANNEL :
2006-05-11 17:59:59 +00:00
if ( GST_V4L2_IS_OPEN ( v4l2object ) ) {
GstTuner * tuner = GST_TUNER ( v4l2object - > element ) ;
GstTunerChannel * channel = gst_tuner_find_channel_by_name ( tuner ,
sys/v4l2/: Fix pass at code cleanups, move errors cases out of the normal flow for additional code clarity.
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c: (gst_v4l2_class_probe_devices),
(gst_v4l2_probe_needs_probe),
(gst_v4l2_object_install_properties_helper), (gst_v4l2_object_new),
(gst_v4l2_object_destroy), (gst_v4l2_object_set_property_helper),
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults),
(gst_v4l2_object_start), (gst_v4l2_object_stop):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_init), (gst_v4l2src_dispose),
(gst_v4l2src_set_property), (gst_v4l2src_get_property),
(gst_v4l2src_fixate), (gst_v4l2src_get_caps),
(gst_v4l2src_set_caps), (gst_v4l2src_get_read),
(gst_v4l2src_get_mmap), (gst_v4l2src_create):
* sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
(gst_v4l2_open), (gst_v4l2_close), (gst_v4l2_get_norm),
(gst_v4l2_set_norm), (gst_v4l2_get_frequency),
(gst_v4l2_set_frequency), (gst_v4l2_signal_strength),
(gst_v4l2_get_attribute), (gst_v4l2_set_attribute),
(gst_v4l2_get_input), (gst_v4l2_set_input):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list),
(gst_v4l2src_queue_frame), (gst_v4l2src_grab_frame),
(gst_v4l2src_get_capture), (gst_v4l2src_set_capture),
(gst_v4l2src_capture_init), (gst_v4l2src_capture_start),
(gst_v4l2src_capture_stop), (gst_v4l2src_capture_deinit),
(gst_v4l2src_get_size_limits), (gst_v4l2src_set_fps),
(gst_v4l2src_get_fps), (gst_v4l2src_buffer_finalize),
(gst_v4l2src_buffer_new):
Fix pass at code cleanups, move errors cases out of the normal
flow for additional code clarity.
2006-09-26 11:06:17 +00:00
( gchar * ) g_value_get_string ( value ) ) ;
2006-05-11 17:59:59 +00:00
if ( channel ) {
/* like gst_tuner_set_channel (tuner, channel)
without g_object_notify */
gst_v4l2_tuner_set_channel ( v4l2object , channel ) ;
}
} else {
sys/v4l2/: Renamed some properties to match the tuner interface naming.
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c:
(gst_v4l2_object_install_properties_helper), (gst_v4l2_object_new),
(gst_v4l2_object_set_property_helper),
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_create):
* sys/v4l2/gstv4l2tuner.c: (gst_v4l2_tuner_contains_channel),
(gst_v4l2_tuner_list_channels),
(gst_v4l2_tuner_set_channel_and_notify),
(gst_v4l2_tuner_get_channel), (gst_v4l2_tuner_contains_norm),
(gst_v4l2_tuner_list_norms), (gst_v4l2_tuner_set_norm_and_notify),
(gst_v4l2_tuner_get_norm):
* sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
(gst_v4l2_fill_lists), (gst_v4l2_empty_lists):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_get_fps):
Renamed some properties to match the tuner interface naming.
2006-09-27 17:04:22 +00:00
g_free ( v4l2object - > channel ) ;
v4l2object - > channel = g_value_dup_string ( value ) ;
2006-05-11 17:59:59 +00:00
}
break ;
case PROP_FREQUENCY :
if ( GST_V4L2_IS_OPEN ( v4l2object ) ) {
GstTuner * tuner = GST_TUNER ( v4l2object - > element ) ;
GstTunerChannel * channel = gst_tuner_get_channel ( tuner ) ;
if ( channel & &
GST_TUNER_CHANNEL_HAS_FLAG ( channel , GST_TUNER_CHANNEL_FREQUENCY ) ) {
/* like
gst_tuner_set_frequency ( tuner , channel , g_value_get_ulong ( value ) )
without g_object_notify */
gst_v4l2_tuner_set_frequency ( v4l2object , channel ,
g_value_get_ulong ( value ) ) ;
}
} else {
v4l2object - > frequency = g_value_get_ulong ( value ) ;
}
break ;
sys/v4l2/: Fix EIO handing when capturing. Add new property to specify the number of buffers to enque (and remove the...
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c:
(gst_v4l2_object_install_properties_helper),
(gst_v4l2_object_set_property_helper),
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_init), (gst_v4l2src_set_property),
(gst_v4l2src_get_property), (gst_v4l2src_set_caps):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list),
(gst_v4l2src_grab_frame), (gst_v4l2src_set_capture),
(gst_v4l2src_capture_init), (gst_v4l2src_capture_start),
(gst_v4l2src_capture_deinit):
Fix EIO handing when capturing. Add new property to specify the number of
buffers to enque (and remove the borked num-buffers usage).
2007-01-17 14:30:50 +00:00
# endif
2011-07-18 16:54:49 +00:00
case PROP_IO_MODE :
v4l2object - > req_mode = g_value_get_enum ( value ) ;
break ;
2006-05-11 17:59:59 +00:00
default :
return FALSE ;
break ;
}
return TRUE ;
}
gboolean
2006-05-19 18:31:25 +00:00
gst_v4l2_object_get_property_helper ( GstV4l2Object * v4l2object ,
2006-05-11 17:59:59 +00:00
guint prop_id , GValue * value , GParamSpec * pspec )
{
switch ( prop_id ) {
case PROP_DEVICE :
g_value_set_string ( value , v4l2object - > videodev ) ;
break ;
case PROP_DEVICE_NAME :
{
sys/v4l2/: Fix pass at code cleanups, move errors cases out of the normal flow for additional code clarity.
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c: (gst_v4l2_class_probe_devices),
(gst_v4l2_probe_needs_probe),
(gst_v4l2_object_install_properties_helper), (gst_v4l2_object_new),
(gst_v4l2_object_destroy), (gst_v4l2_object_set_property_helper),
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults),
(gst_v4l2_object_start), (gst_v4l2_object_stop):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_init), (gst_v4l2src_dispose),
(gst_v4l2src_set_property), (gst_v4l2src_get_property),
(gst_v4l2src_fixate), (gst_v4l2src_get_caps),
(gst_v4l2src_set_caps), (gst_v4l2src_get_read),
(gst_v4l2src_get_mmap), (gst_v4l2src_create):
* sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
(gst_v4l2_open), (gst_v4l2_close), (gst_v4l2_get_norm),
(gst_v4l2_set_norm), (gst_v4l2_get_frequency),
(gst_v4l2_set_frequency), (gst_v4l2_signal_strength),
(gst_v4l2_get_attribute), (gst_v4l2_set_attribute),
(gst_v4l2_get_input), (gst_v4l2_set_input):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list),
(gst_v4l2src_queue_frame), (gst_v4l2src_grab_frame),
(gst_v4l2src_get_capture), (gst_v4l2src_set_capture),
(gst_v4l2src_capture_init), (gst_v4l2src_capture_start),
(gst_v4l2src_capture_stop), (gst_v4l2src_capture_deinit),
(gst_v4l2src_get_size_limits), (gst_v4l2src_set_fps),
(gst_v4l2src_get_fps), (gst_v4l2src_buffer_finalize),
(gst_v4l2src_buffer_new):
Fix pass at code cleanups, move errors cases out of the normal
flow for additional code clarity.
2006-09-26 11:06:17 +00:00
const guchar * new = NULL ;
2006-05-11 17:59:59 +00:00
2006-07-19 14:36:00 +00:00
if ( GST_V4L2_IS_OPEN ( v4l2object ) ) {
sys/v4l2/: Fix pass at code cleanups, move errors cases out of the normal flow for additional code clarity.
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c: (gst_v4l2_class_probe_devices),
(gst_v4l2_probe_needs_probe),
(gst_v4l2_object_install_properties_helper), (gst_v4l2_object_new),
(gst_v4l2_object_destroy), (gst_v4l2_object_set_property_helper),
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults),
(gst_v4l2_object_start), (gst_v4l2_object_stop):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_init), (gst_v4l2src_dispose),
(gst_v4l2src_set_property), (gst_v4l2src_get_property),
(gst_v4l2src_fixate), (gst_v4l2src_get_caps),
(gst_v4l2src_set_caps), (gst_v4l2src_get_read),
(gst_v4l2src_get_mmap), (gst_v4l2src_create):
* sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
(gst_v4l2_open), (gst_v4l2_close), (gst_v4l2_get_norm),
(gst_v4l2_set_norm), (gst_v4l2_get_frequency),
(gst_v4l2_set_frequency), (gst_v4l2_signal_strength),
(gst_v4l2_get_attribute), (gst_v4l2_set_attribute),
(gst_v4l2_get_input), (gst_v4l2_set_input):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list),
(gst_v4l2src_queue_frame), (gst_v4l2src_grab_frame),
(gst_v4l2src_get_capture), (gst_v4l2src_set_capture),
(gst_v4l2src_capture_init), (gst_v4l2src_capture_start),
(gst_v4l2src_capture_stop), (gst_v4l2src_capture_deinit),
(gst_v4l2src_get_size_limits), (gst_v4l2src_set_fps),
(gst_v4l2src_get_fps), (gst_v4l2src_buffer_finalize),
(gst_v4l2src_buffer_new):
Fix pass at code cleanups, move errors cases out of the normal
flow for additional code clarity.
2006-09-26 11:06:17 +00:00
new = v4l2object - > vcap . card ;
2006-07-19 14:36:00 +00:00
} else if ( gst_v4l2_open ( v4l2object ) ) {
sys/v4l2/: Fix pass at code cleanups, move errors cases out of the normal flow for additional code clarity.
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c: (gst_v4l2_class_probe_devices),
(gst_v4l2_probe_needs_probe),
(gst_v4l2_object_install_properties_helper), (gst_v4l2_object_new),
(gst_v4l2_object_destroy), (gst_v4l2_object_set_property_helper),
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults),
(gst_v4l2_object_start), (gst_v4l2_object_stop):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_init), (gst_v4l2src_dispose),
(gst_v4l2src_set_property), (gst_v4l2src_get_property),
(gst_v4l2src_fixate), (gst_v4l2src_get_caps),
(gst_v4l2src_set_caps), (gst_v4l2src_get_read),
(gst_v4l2src_get_mmap), (gst_v4l2src_create):
* sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
(gst_v4l2_open), (gst_v4l2_close), (gst_v4l2_get_norm),
(gst_v4l2_set_norm), (gst_v4l2_get_frequency),
(gst_v4l2_set_frequency), (gst_v4l2_signal_strength),
(gst_v4l2_get_attribute), (gst_v4l2_set_attribute),
(gst_v4l2_get_input), (gst_v4l2_set_input):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list),
(gst_v4l2src_queue_frame), (gst_v4l2src_grab_frame),
(gst_v4l2src_get_capture), (gst_v4l2src_set_capture),
(gst_v4l2src_capture_init), (gst_v4l2src_capture_start),
(gst_v4l2src_capture_stop), (gst_v4l2src_capture_deinit),
(gst_v4l2src_get_size_limits), (gst_v4l2src_set_fps),
(gst_v4l2src_get_fps), (gst_v4l2src_buffer_finalize),
(gst_v4l2src_buffer_new):
Fix pass at code cleanups, move errors cases out of the normal
flow for additional code clarity.
2006-09-26 11:06:17 +00:00
new = v4l2object - > vcap . card ;
2006-07-19 14:36:00 +00:00
gst_v4l2_close ( v4l2object ) ;
}
sys/v4l2/: Fix pass at code cleanups, move errors cases out of the normal flow for additional code clarity.
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c: (gst_v4l2_class_probe_devices),
(gst_v4l2_probe_needs_probe),
(gst_v4l2_object_install_properties_helper), (gst_v4l2_object_new),
(gst_v4l2_object_destroy), (gst_v4l2_object_set_property_helper),
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults),
(gst_v4l2_object_start), (gst_v4l2_object_stop):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_init), (gst_v4l2src_dispose),
(gst_v4l2src_set_property), (gst_v4l2src_get_property),
(gst_v4l2src_fixate), (gst_v4l2src_get_caps),
(gst_v4l2src_set_caps), (gst_v4l2src_get_read),
(gst_v4l2src_get_mmap), (gst_v4l2src_create):
* sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
(gst_v4l2_open), (gst_v4l2_close), (gst_v4l2_get_norm),
(gst_v4l2_set_norm), (gst_v4l2_get_frequency),
(gst_v4l2_set_frequency), (gst_v4l2_signal_strength),
(gst_v4l2_get_attribute), (gst_v4l2_set_attribute),
(gst_v4l2_get_input), (gst_v4l2_set_input):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list),
(gst_v4l2src_queue_frame), (gst_v4l2src_grab_frame),
(gst_v4l2src_get_capture), (gst_v4l2src_set_capture),
(gst_v4l2src_capture_init), (gst_v4l2src_capture_start),
(gst_v4l2src_capture_stop), (gst_v4l2src_capture_deinit),
(gst_v4l2src_get_size_limits), (gst_v4l2src_set_fps),
(gst_v4l2src_get_fps), (gst_v4l2src_buffer_finalize),
(gst_v4l2src_buffer_new):
Fix pass at code cleanups, move errors cases out of the normal
flow for additional code clarity.
2006-09-26 11:06:17 +00:00
g_value_set_string ( value , ( gchar * ) new ) ;
2006-05-11 17:59:59 +00:00
break ;
}
2008-03-26 15:10:08 +00:00
case PROP_DEVICE_FD :
{
if ( GST_V4L2_IS_OPEN ( v4l2object ) )
g_value_set_int ( value , v4l2object - > video_fd ) ;
else
g_value_set_int ( value , DEFAULT_PROP_DEVICE_FD ) ;
break ;
}
2006-05-11 17:59:59 +00:00
case PROP_FLAGS :
{
guint flags = 0 ;
if ( GST_V4L2_IS_OPEN ( v4l2object ) ) {
flags | = v4l2object - > vcap . capabilities &
( V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_VIDEO_OUTPUT |
2006-09-27 15:14:07 +00:00
V4L2_CAP_VIDEO_OVERLAY |
V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_VBI_OUTPUT | V4L2_CAP_TUNER | V4L2_CAP_AUDIO ) ;
2006-05-11 17:59:59 +00:00
}
g_value_set_flags ( value , flags ) ;
break ;
}
2010-06-22 12:48:04 +00:00
case PROP_BRIGHTNESS :
case PROP_CONTRAST :
case PROP_SATURATION :
case PROP_HUE :
{
gint cid = gst_v4l2_object_prop_to_cid ( prop_id ) ;
if ( cid ! = - 1 ) {
if ( GST_V4L2_IS_OPEN ( v4l2object ) ) {
gint v ;
if ( gst_v4l2_get_attribute ( v4l2object , cid , & v ) ) {
g_value_set_int ( value , v ) ;
}
}
}
return TRUE ;
}
break ;
2010-04-04 11:43:41 +00:00
case PROP_TV_NORM :
g_value_set_enum ( value , v4l2object - > tv_norm ) ;
break ;
2011-07-18 16:54:49 +00:00
case PROP_IO_MODE :
g_value_set_enum ( value , v4l2object - > req_mode ) ;
break ;
2006-05-11 17:59:59 +00:00
default :
return FALSE ;
break ;
}
return TRUE ;
}
static void
gst_v4l2_set_defaults ( GstV4l2Object * v4l2object )
{
GstTunerNorm * norm = NULL ;
GstTunerChannel * channel = NULL ;
2009-08-04 07:14:20 +00:00
GstTuner * tuner ;
if ( ! GST_IS_TUNER ( v4l2object - > element ) )
return ;
tuner = GST_TUNER ( v4l2object - > element ) ;
2006-05-11 17:59:59 +00:00
2010-04-04 11:43:41 +00:00
if ( v4l2object - > tv_norm )
norm = gst_v4l2_tuner_get_norm_by_std_id ( v4l2object , v4l2object - > tv_norm ) ;
2011-09-29 14:41:53 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " tv_norm=0x% " G_GINT64_MODIFIER " x, "
" norm=%p " , ( guint64 ) v4l2object - > tv_norm , norm ) ;
2006-05-11 17:59:59 +00:00
if ( norm ) {
gst_tuner_set_norm ( tuner , norm ) ;
} else {
norm =
GST_TUNER_NORM ( gst_tuner_get_norm ( GST_TUNER ( v4l2object - > element ) ) ) ;
if ( norm ) {
2010-04-04 11:43:41 +00:00
v4l2object - > tv_norm =
gst_v4l2_tuner_get_std_id_by_norm ( v4l2object , norm ) ;
2006-05-11 17:59:59 +00:00
gst_tuner_norm_changed ( tuner , norm ) ;
}
}
sys/v4l2/: Renamed some properties to match the tuner interface naming.
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c:
(gst_v4l2_object_install_properties_helper), (gst_v4l2_object_new),
(gst_v4l2_object_set_property_helper),
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_create):
* sys/v4l2/gstv4l2tuner.c: (gst_v4l2_tuner_contains_channel),
(gst_v4l2_tuner_list_channels),
(gst_v4l2_tuner_set_channel_and_notify),
(gst_v4l2_tuner_get_channel), (gst_v4l2_tuner_contains_norm),
(gst_v4l2_tuner_list_norms), (gst_v4l2_tuner_set_norm_and_notify),
(gst_v4l2_tuner_get_norm):
* sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
(gst_v4l2_fill_lists), (gst_v4l2_empty_lists):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_get_fps):
Renamed some properties to match the tuner interface naming.
2006-09-27 17:04:22 +00:00
if ( v4l2object - > channel )
channel = gst_tuner_find_channel_by_name ( tuner , v4l2object - > channel ) ;
2006-05-11 17:59:59 +00:00
if ( channel ) {
gst_tuner_set_channel ( tuner , channel ) ;
} else {
channel =
2008-08-23 15:33:49 +00:00
GST_TUNER_CHANNEL ( gst_tuner_get_channel ( GST_TUNER
( v4l2object - > element ) ) ) ;
2007-02-22 17:53:26 +00:00
if ( channel ) {
g_free ( v4l2object - > channel ) ;
v4l2object - > channel = g_strdup ( channel - > label ) ;
gst_tuner_channel_changed ( tuner , channel ) ;
}
2006-05-11 17:59:59 +00:00
}
2007-02-22 17:53:26 +00:00
if ( channel
& & GST_TUNER_CHANNEL_HAS_FLAG ( channel , GST_TUNER_CHANNEL_FREQUENCY ) ) {
2006-05-11 17:59:59 +00:00
if ( v4l2object - > frequency ! = 0 ) {
gst_tuner_set_frequency ( tuner , channel , v4l2object - > frequency ) ;
} else {
v4l2object - > frequency = gst_tuner_get_frequency ( tuner , channel ) ;
if ( v4l2object - > frequency = = 0 ) {
/* guess */
gst_tuner_set_frequency ( tuner , channel , 1000 ) ;
} else {
}
}
}
}
gboolean
2011-07-13 14:33:58 +00:00
gst_v4l2_object_open ( GstV4l2Object * v4l2object )
2006-05-11 17:59:59 +00:00
{
if ( gst_v4l2_open ( v4l2object ) )
gst_v4l2_set_defaults ( v4l2object ) ;
else
return FALSE ;
2010-04-04 11:37:16 +00:00
# ifdef HAVE_XVIDEO
2011-08-08 14:25:31 +00:00
gst_v4l2_video_overlay_start ( v4l2object ) ;
2006-05-11 17:59:59 +00:00
# endif
return TRUE ;
}
gboolean
2011-07-13 14:33:58 +00:00
gst_v4l2_object_close ( GstV4l2Object * v4l2object )
2006-05-11 17:59:59 +00:00
{
2010-04-04 11:37:16 +00:00
# ifdef HAVE_XVIDEO
2011-08-08 14:25:31 +00:00
gst_v4l2_video_overlay_stop ( v4l2object ) ;
2006-05-11 17:59:59 +00:00
# endif
if ( ! gst_v4l2_close ( v4l2object ) )
return FALSE ;
2009-08-14 08:11:25 +00:00
if ( v4l2object - > formats ) {
gst_v4l2_object_clear_format_list ( v4l2object ) ;
}
2006-05-11 17:59:59 +00:00
return TRUE ;
}
2009-08-04 07:14:20 +00:00
/*
* common format / caps utilities :
*/
2009-09-07 16:28:51 +00:00
typedef struct
{
guint32 format ;
gboolean dimensions ;
} GstV4L2FormatDesc ;
2009-08-04 07:14:20 +00:00
2009-09-07 16:28:51 +00:00
static const GstV4L2FormatDesc gst_v4l2_formats [ ] = {
2009-08-04 07:14:20 +00:00
/* from Linux 2.6.15 videodev2.h */
2009-09-07 16:28:51 +00:00
{ V4L2_PIX_FMT_RGB332 , TRUE } ,
{ V4L2_PIX_FMT_RGB555 , TRUE } ,
{ V4L2_PIX_FMT_RGB565 , TRUE } ,
{ V4L2_PIX_FMT_RGB555X , TRUE } ,
{ V4L2_PIX_FMT_RGB565X , TRUE } ,
{ V4L2_PIX_FMT_BGR24 , TRUE } ,
{ V4L2_PIX_FMT_RGB24 , TRUE } ,
{ V4L2_PIX_FMT_BGR32 , TRUE } ,
{ V4L2_PIX_FMT_RGB32 , TRUE } ,
{ V4L2_PIX_FMT_GREY , TRUE } ,
{ V4L2_PIX_FMT_YVU410 , TRUE } ,
{ V4L2_PIX_FMT_YVU420 , TRUE } ,
{ V4L2_PIX_FMT_YUYV , TRUE } ,
{ V4L2_PIX_FMT_UYVY , TRUE } ,
{ V4L2_PIX_FMT_YUV422P , TRUE } ,
{ V4L2_PIX_FMT_YUV411P , TRUE } ,
{ V4L2_PIX_FMT_Y41P , TRUE } ,
2009-08-04 07:14:20 +00:00
/* two planes -- one Y, one Cr + Cb interleaved */
2009-09-07 16:28:51 +00:00
{ V4L2_PIX_FMT_NV12 , TRUE } ,
{ V4L2_PIX_FMT_NV21 , TRUE } ,
2009-08-04 07:14:20 +00:00
/* The following formats are not defined in the V4L2 specification */
2009-09-07 16:28:51 +00:00
{ V4L2_PIX_FMT_YUV410 , TRUE } ,
{ V4L2_PIX_FMT_YUV420 , TRUE } ,
{ V4L2_PIX_FMT_YYUV , TRUE } ,
{ V4L2_PIX_FMT_HI240 , TRUE } ,
2009-08-04 07:14:20 +00:00
/* see http://www.siliconimaging.com/RGB%20Bayer.htm */
# ifdef V4L2_PIX_FMT_SBGGR8
2009-09-07 16:28:51 +00:00
{ V4L2_PIX_FMT_SBGGR8 , TRUE } ,
2009-08-04 07:14:20 +00:00
# endif
/* compressed formats */
2009-09-07 16:28:51 +00:00
{ V4L2_PIX_FMT_MJPEG , TRUE } ,
{ V4L2_PIX_FMT_JPEG , TRUE } ,
2011-03-05 02:37:38 +00:00
# ifdef V4L2_PIX_FMT_PJPG
2011-02-15 18:59:32 +00:00
{ V4L2_PIX_FMT_PJPG , TRUE } ,
2011-03-05 02:37:38 +00:00
# endif
2009-09-07 16:28:51 +00:00
{ V4L2_PIX_FMT_DV , TRUE } ,
{ V4L2_PIX_FMT_MPEG , FALSE } ,
2009-08-04 07:14:20 +00:00
2012-04-19 10:38:58 +00:00
# ifdef V4L2_PIX_FMT_H264
2012-04-16 22:08:21 +00:00
{ V4L2_PIX_FMT_H264 , TRUE } ,
2012-04-19 10:38:58 +00:00
# endif
2012-04-16 22:08:21 +00:00
2009-08-04 07:14:20 +00:00
/* Vendor-specific formats */
2009-09-07 16:28:51 +00:00
{ V4L2_PIX_FMT_WNVA , TRUE } ,
2009-08-04 07:14:20 +00:00
# ifdef V4L2_PIX_FMT_SN9C10X
2009-09-07 16:28:51 +00:00
{ V4L2_PIX_FMT_SN9C10X , TRUE } ,
2009-08-04 07:14:20 +00:00
# endif
# ifdef V4L2_PIX_FMT_PWC1
2009-09-07 16:28:51 +00:00
{ V4L2_PIX_FMT_PWC1 , TRUE } ,
2009-08-04 07:14:20 +00:00
# endif
# ifdef V4L2_PIX_FMT_PWC2
2009-09-07 16:28:51 +00:00
{ V4L2_PIX_FMT_PWC2 , TRUE } ,
2009-08-04 07:14:20 +00:00
# endif
# ifdef V4L2_PIX_FMT_YVYU
2009-09-07 16:28:51 +00:00
{ V4L2_PIX_FMT_YVYU , TRUE } ,
2009-08-04 07:14:20 +00:00
# endif
} ;
# define GST_V4L2_FORMAT_COUNT (G_N_ELEMENTS (gst_v4l2_formats))
static struct v4l2_fmtdesc *
gst_v4l2_object_get_format_from_fourcc ( GstV4l2Object * v4l2object ,
guint32 fourcc )
{
struct v4l2_fmtdesc * fmt ;
GSList * walk ;
if ( fourcc = = 0 )
return NULL ;
walk = gst_v4l2_object_get_format_list ( v4l2object ) ;
while ( walk ) {
fmt = ( struct v4l2_fmtdesc * ) walk - > data ;
if ( fmt - > pixelformat = = fourcc )
return fmt ;
/* special case for jpeg */
2011-02-15 18:59:32 +00:00
if ( fmt - > pixelformat = = V4L2_PIX_FMT_MJPEG | |
2011-03-05 02:37:38 +00:00
fmt - > pixelformat = = V4L2_PIX_FMT_JPEG
# ifdef V4L2_PIX_FMT_PJPG
| | fmt - > pixelformat = = V4L2_PIX_FMT_PJPG
# endif
) {
if ( fourcc = = V4L2_PIX_FMT_JPEG | | fourcc = = V4L2_PIX_FMT_MJPEG
# ifdef V4L2_PIX_FMT_PJPG
| | fourcc = = V4L2_PIX_FMT_PJPG
# endif
) {
2011-02-15 18:59:32 +00:00
return fmt ;
}
2009-08-04 07:14:20 +00:00
}
walk = g_slist_next ( walk ) ;
}
return NULL ;
}
/* complete made up ranking, the values themselves are meaningless */
2011-12-02 12:01:22 +00:00
/* These ranks MUST be X such that X<<15 fits on a signed int - see
the comment at the end of gst_v4l2_object_format_get_rank . */
2009-08-04 07:14:20 +00:00
# define YUV_BASE_RANK 1000
# define JPEG_BASE_RANK 500
# define DV_BASE_RANK 200
# define RGB_BASE_RANK 100
# define YUV_ODD_BASE_RANK 50
# define RGB_ODD_BASE_RANK 25
# define BAYER_BASE_RANK 15
# define S910_BASE_RANK 10
# define GREY_BASE_RANK 5
# define PWC_BASE_RANK 1
2009-09-04 07:32:42 +00:00
/* This flag is already used by libv4l2 although
* it was added to the Linux kernel in 2.6 .32
*/
# ifndef V4L2_FMT_FLAG_EMULATED
# define V4L2_FMT_FLAG_EMULATED 0x0002
# endif
2009-08-04 07:14:20 +00:00
static gint
2009-09-03 18:38:50 +00:00
gst_v4l2_object_format_get_rank ( const struct v4l2_fmtdesc * fmt )
2009-08-04 07:14:20 +00:00
{
2009-09-03 18:38:50 +00:00
guint32 fourcc = fmt - > pixelformat ;
2009-09-03 18:40:17 +00:00
gboolean emulated = ( ( fmt - > flags & V4L2_FMT_FLAG_EMULATED ) ! = 0 ) ;
2009-09-03 18:38:50 +00:00
gint rank = 0 ;
2009-08-04 07:14:20 +00:00
switch ( fourcc ) {
case V4L2_PIX_FMT_MJPEG :
2011-03-05 02:37:38 +00:00
# ifdef V4L2_PIX_FMT_PJPG
2011-02-15 18:59:32 +00:00
case V4L2_PIX_FMT_PJPG :
2009-09-03 18:38:50 +00:00
rank = JPEG_BASE_RANK ;
break ;
2011-03-05 02:37:38 +00:00
# endif
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_JPEG :
2009-09-03 18:38:50 +00:00
rank = JPEG_BASE_RANK + 1 ;
break ;
2009-09-07 16:28:51 +00:00
case V4L2_PIX_FMT_MPEG : /* MPEG */
rank = JPEG_BASE_RANK + 2 ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_RGB332 :
case V4L2_PIX_FMT_RGB555 :
case V4L2_PIX_FMT_RGB555X :
case V4L2_PIX_FMT_RGB565 :
case V4L2_PIX_FMT_RGB565X :
2009-09-03 18:38:50 +00:00
rank = RGB_ODD_BASE_RANK ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_RGB24 :
case V4L2_PIX_FMT_BGR24 :
2009-09-03 18:38:50 +00:00
rank = RGB_BASE_RANK - 1 ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_RGB32 :
case V4L2_PIX_FMT_BGR32 :
2009-09-03 18:38:50 +00:00
rank = RGB_BASE_RANK ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_GREY : /* 8 Greyscale */
2009-09-03 18:38:50 +00:00
rank = GREY_BASE_RANK ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_NV12 : /* 12 Y/CbCr 4:2:0 */
case V4L2_PIX_FMT_NV21 : /* 12 Y/CrCb 4:2:0 */
case V4L2_PIX_FMT_YYUV : /* 16 YUV 4:2:2 */
case V4L2_PIX_FMT_HI240 : /* 8 8-bit color */
2009-09-03 18:38:50 +00:00
rank = YUV_ODD_BASE_RANK ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_YVU410 : /* YVU9, 9 bits per pixel */
2009-09-03 18:38:50 +00:00
rank = YUV_BASE_RANK + 3 ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_YUV410 : /* YUV9, 9 bits per pixel */
2009-09-03 18:38:50 +00:00
rank = YUV_BASE_RANK + 2 ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_YUV420 : /* I420, 12 bits per pixel */
2009-09-03 18:38:50 +00:00
rank = YUV_BASE_RANK + 7 ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_YUYV : /* YUY2, 16 bits per pixel */
2009-09-03 18:38:50 +00:00
rank = YUV_BASE_RANK + 10 ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_YVU420 : /* YV12, 12 bits per pixel */
2009-09-03 18:38:50 +00:00
rank = YUV_BASE_RANK + 6 ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_UYVY : /* UYVY, 16 bits per pixel */
2009-09-03 18:38:50 +00:00
rank = YUV_BASE_RANK + 9 ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_Y41P : /* Y41P, 12 bits per pixel */
2009-09-03 18:38:50 +00:00
rank = YUV_BASE_RANK + 5 ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_YUV411P : /* Y41B, 12 bits per pixel */
2009-09-03 18:38:50 +00:00
rank = YUV_BASE_RANK + 4 ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_YUV422P : /* Y42B, 16 bits per pixel */
2009-09-03 18:38:50 +00:00
rank = YUV_BASE_RANK + 8 ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_DV :
2009-09-03 18:38:50 +00:00
rank = DV_BASE_RANK ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_WNVA : /* Winnov hw compres */
2009-09-03 18:38:50 +00:00
rank = 0 ;
break ;
2009-08-04 07:14:20 +00:00
# ifdef V4L2_PIX_FMT_SBGGR8
case V4L2_PIX_FMT_SBGGR8 :
2009-09-03 18:38:50 +00:00
rank = BAYER_BASE_RANK ;
break ;
2009-08-04 07:14:20 +00:00
# endif
# ifdef V4L2_PIX_FMT_SN9C10X
case V4L2_PIX_FMT_SN9C10X :
2009-09-03 18:38:50 +00:00
rank = S910_BASE_RANK ;
break ;
2009-08-04 07:14:20 +00:00
# endif
# ifdef V4L2_PIX_FMT_PWC1
case V4L2_PIX_FMT_PWC1 :
2009-09-03 18:38:50 +00:00
rank = PWC_BASE_RANK ;
break ;
2009-08-04 07:14:20 +00:00
# endif
# ifdef V4L2_PIX_FMT_PWC2
case V4L2_PIX_FMT_PWC2 :
2009-09-03 18:38:50 +00:00
rank = PWC_BASE_RANK ;
break ;
2009-08-04 07:14:20 +00:00
# endif
default :
2009-09-03 18:38:50 +00:00
rank = 0 ;
2009-08-04 07:14:20 +00:00
break ;
}
2009-09-03 18:38:50 +00:00
/* All ranks are below 1<<15 so a shift by 15
* will a ) make all non - emulated formats larger
* than emulated and b ) will not overflow
*/
if ( ! emulated )
rank < < = 15 ;
return rank ;
2009-08-04 07:14:20 +00:00
}
static gint
format_cmp_func ( gconstpointer a , gconstpointer b )
{
2009-09-03 18:38:50 +00:00
const struct v4l2_fmtdesc * fa = a ;
const struct v4l2_fmtdesc * fb = b ;
2009-08-04 07:14:20 +00:00
2009-09-03 18:38:50 +00:00
if ( fa - > pixelformat = = fb - > pixelformat )
2009-08-04 07:14:20 +00:00
return 0 ;
2010-08-06 17:07:46 +00:00
return gst_v4l2_object_format_get_rank ( fb ) -
gst_v4l2_object_format_get_rank ( fa ) ;
2009-08-04 07:14:20 +00:00
}
/******************************************************
* gst_v4l2_object_fill_format_list ( ) :
* create list of supported capture formats
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static gboolean
gst_v4l2_object_fill_format_list ( GstV4l2Object * v4l2object )
{
gint n ;
struct v4l2_fmtdesc * format ;
GST_DEBUG_OBJECT ( v4l2object - > element , " getting src format enumerations " ) ;
/* format enumeration */
for ( n = 0 ; ; n + + ) {
format = g_new0 ( struct v4l2_fmtdesc , 1 ) ;
format - > index = n ;
format - > type = v4l2object - > type ;
if ( v4l2_ioctl ( v4l2object - > video_fd , VIDIOC_ENUM_FMT , format ) < 0 ) {
if ( errno = = EINVAL ) {
g_free ( format ) ;
break ; /* end of enumeration */
} else {
goto failed ;
}
}
GST_LOG_OBJECT ( v4l2object - > element , " index: %u " , format - > index ) ;
GST_LOG_OBJECT ( v4l2object - > element , " type: %d " , format - > type ) ;
GST_LOG_OBJECT ( v4l2object - > element , " flags: %08x " , format - > flags ) ;
GST_LOG_OBJECT ( v4l2object - > element , " description: '%s' " ,
format - > description ) ;
GST_LOG_OBJECT ( v4l2object - > element , " pixelformat: % " GST_FOURCC_FORMAT ,
GST_FOURCC_ARGS ( format - > pixelformat ) ) ;
/* sort formats according to our preference; we do this, because caps
* are probed in the order the formats are in the list , and the order of
* formats in the final probed caps matters for things like fixation */
v4l2object - > formats = g_slist_insert_sorted ( v4l2object - > formats , format ,
( GCompareFunc ) format_cmp_func ) ;
}
2010-08-06 19:04:59 +00:00
# ifndef GST_DISABLE_GST_DEBUG
{
GSList * l ;
GST_INFO_OBJECT ( v4l2object - > element , " got %d format(s): " , n ) ;
for ( l = v4l2object - > formats ; l ! = NULL ; l = l - > next ) {
format = l - > data ;
GST_INFO_OBJECT ( v4l2object - > element ,
" % " GST_FOURCC_FORMAT " %s " , GST_FOURCC_ARGS ( format - > pixelformat ) ,
( ( format - > flags & V4L2_FMT_FLAG_EMULATED ) ) ? " (emulated) " : " " ) ;
}
}
# endif
2009-08-04 07:14:20 +00:00
return TRUE ;
/* ERRORS */
failed :
{
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS ,
( _ ( " Failed to enumerate possible video formats device '%s' can work with " ) , v4l2object - > videodev ) , ( " Failed to get number %d in pixelformat enumeration for %s. (%d - %s) " , n , v4l2object - > videodev , errno , g_strerror ( errno ) ) ) ;
g_free ( format ) ;
return FALSE ;
}
}
2009-09-10 07:26:23 +00:00
/*
2009-08-04 07:14:20 +00:00
* Get the list of supported capture formats , a list of
* < code > struct v4l2_fmtdesc < / code > .
*/
GSList *
gst_v4l2_object_get_format_list ( GstV4l2Object * v4l2object )
{
if ( ! v4l2object - > formats )
gst_v4l2_object_fill_format_list ( v4l2object ) ;
return v4l2object - > formats ;
}
GstStructure *
gst_v4l2_object_v4l2fourcc_to_structure ( guint32 fourcc )
{
GstStructure * structure = NULL ;
switch ( fourcc ) {
case V4L2_PIX_FMT_MJPEG : /* Motion-JPEG */
2011-03-05 02:37:38 +00:00
# ifdef V4L2_PIX_FMT_PJPG
2011-02-15 18:59:32 +00:00
case V4L2_PIX_FMT_PJPG : /* Progressive-JPEG */
2011-03-05 02:37:38 +00:00
# endif
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_JPEG : /* JFIF JPEG */
2011-10-29 07:09:45 +00:00
structure = gst_structure_new_empty ( " image/jpeg " ) ;
2009-08-04 07:14:20 +00:00
break ;
case V4L2_PIX_FMT_YYUV : /* 16 YUV 4:2:2 */
case V4L2_PIX_FMT_HI240 : /* 8 8-bit color */
/* FIXME: get correct fourccs here */
break ;
2012-04-19 10:38:58 +00:00
# ifdef V4L2_PIX_FMT_H264
2012-04-16 22:08:21 +00:00
case V4L2_PIX_FMT_H264 : /* H.264 */
2012-04-19 07:50:25 +00:00
structure = gst_structure_new_empty ( " video/x-h264 " ) ;
2012-04-16 22:08:21 +00:00
break ;
2012-04-19 10:38:58 +00:00
# endif
2011-07-08 12:34:40 +00:00
case V4L2_PIX_FMT_RGB332 :
case V4L2_PIX_FMT_RGB555X :
case V4L2_PIX_FMT_RGB565X :
/* FIXME: get correct fourccs here */
break ;
2011-07-08 14:37:11 +00:00
case V4L2_PIX_FMT_GREY : /* 8 Greyscale */
2011-07-08 12:34:40 +00:00
case V4L2_PIX_FMT_RGB555 :
case V4L2_PIX_FMT_RGB565 :
case V4L2_PIX_FMT_RGB24 :
case V4L2_PIX_FMT_BGR24 :
case V4L2_PIX_FMT_RGB32 :
case V4L2_PIX_FMT_BGR32 :
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_NV12 : /* 12 Y/CbCr 4:2:0 */
case V4L2_PIX_FMT_NV21 : /* 12 Y/CrCb 4:2:0 */
case V4L2_PIX_FMT_YVU410 :
case V4L2_PIX_FMT_YUV410 :
case V4L2_PIX_FMT_YUV420 : /* I420/IYUV */
case V4L2_PIX_FMT_YUYV :
case V4L2_PIX_FMT_YVU420 :
case V4L2_PIX_FMT_UYVY :
2011-07-08 12:34:40 +00:00
#if 0
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_Y41P :
2011-07-08 12:34:40 +00:00
# endif
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_YUV422P :
# ifdef V4L2_PIX_FMT_YVYU
case V4L2_PIX_FMT_YVYU :
# endif
case V4L2_PIX_FMT_YUV411P : {
2011-07-08 12:34:40 +00:00
GstVideoFormat format ;
2009-08-04 07:14:20 +00:00
switch ( fourcc ) {
2011-07-08 14:37:11 +00:00
case V4L2_PIX_FMT_GREY : /* 8 Greyscale */
format = GST_VIDEO_FORMAT_GRAY8 ;
break ;
2011-07-08 12:34:40 +00:00
case V4L2_PIX_FMT_RGB555 :
format = GST_VIDEO_FORMAT_RGB15 ;
break ;
case V4L2_PIX_FMT_RGB565 :
format = GST_VIDEO_FORMAT_RGB16 ;
break ;
case V4L2_PIX_FMT_RGB24 :
format = GST_VIDEO_FORMAT_RGB ;
break ;
case V4L2_PIX_FMT_BGR24 :
format = GST_VIDEO_FORMAT_BGR ;
break ;
case V4L2_PIX_FMT_RGB32 :
format = GST_VIDEO_FORMAT_RGBx ;
break ;
case V4L2_PIX_FMT_BGR32 :
format = GST_VIDEO_FORMAT_BGRx ;
break ;
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_NV12 :
2011-07-08 12:34:40 +00:00
format = GST_VIDEO_FORMAT_NV12 ;
2009-08-04 07:14:20 +00:00
break ;
case V4L2_PIX_FMT_NV21 :
2011-07-08 12:34:40 +00:00
format = GST_VIDEO_FORMAT_NV21 ;
2009-08-04 07:14:20 +00:00
break ;
case V4L2_PIX_FMT_YVU410 :
2011-07-08 12:34:40 +00:00
format = GST_VIDEO_FORMAT_YVU9 ;
2009-08-04 07:14:20 +00:00
break ;
case V4L2_PIX_FMT_YUV410 :
2011-07-08 12:34:40 +00:00
format = GST_VIDEO_FORMAT_YUV9 ;
2009-08-04 07:14:20 +00:00
break ;
case V4L2_PIX_FMT_YUV420 :
2011-07-08 12:34:40 +00:00
format = GST_VIDEO_FORMAT_I420 ;
2009-08-04 07:14:20 +00:00
break ;
case V4L2_PIX_FMT_YUYV :
2011-07-08 12:34:40 +00:00
format = GST_VIDEO_FORMAT_YUY2 ;
2009-08-04 07:14:20 +00:00
break ;
case V4L2_PIX_FMT_YVU420 :
2011-07-08 12:34:40 +00:00
format = GST_VIDEO_FORMAT_YV12 ;
2009-08-04 07:14:20 +00:00
break ;
case V4L2_PIX_FMT_UYVY :
2011-07-08 12:34:40 +00:00
format = GST_VIDEO_FORMAT_UYVY ;
2009-08-04 07:14:20 +00:00
break ;
2011-07-08 12:34:40 +00:00
#if 0
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_Y41P :
2011-07-08 12:34:40 +00:00
format = GST_VIDEO_FORMAT_Y41P ;
2009-08-04 07:14:20 +00:00
break ;
2011-07-08 12:34:40 +00:00
# endif
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_YUV411P :
2011-07-08 12:34:40 +00:00
format = GST_VIDEO_FORMAT_Y41B ;
2009-08-04 07:14:20 +00:00
break ;
case V4L2_PIX_FMT_YUV422P :
2011-07-08 12:34:40 +00:00
format = GST_VIDEO_FORMAT_Y42B ;
2009-08-04 07:14:20 +00:00
break ;
# ifdef V4L2_PIX_FMT_YVYU
case V4L2_PIX_FMT_YVYU :
2011-07-08 12:34:40 +00:00
format = GST_VIDEO_FORMAT_YVYU ;
2009-08-04 07:14:20 +00:00
break ;
# endif
default :
g_assert_not_reached ( ) ;
break ;
}
2011-07-08 12:34:40 +00:00
structure = gst_structure_new ( " video/x-raw " ,
" format " , G_TYPE_STRING , gst_video_format_to_string ( format ) , NULL ) ;
2009-08-04 07:14:20 +00:00
break ;
}
case V4L2_PIX_FMT_DV :
structure =
gst_structure_new ( " video/x-dv " , " systemstream " , G_TYPE_BOOLEAN , TRUE ,
NULL ) ;
break ;
case V4L2_PIX_FMT_MPEG : /* MPEG */
2011-10-29 07:09:45 +00:00
structure = gst_structure_new_empty ( " video/mpegts " ) ;
2009-08-04 07:14:20 +00:00
break ;
case V4L2_PIX_FMT_WNVA : /* Winnov hw compres */
break ;
# ifdef V4L2_PIX_FMT_SBGGR8
case V4L2_PIX_FMT_SBGGR8 :
2012-03-05 11:43:17 +00:00
structure = gst_structure_new_empty ( " video/x-bayer " ) ;
2009-08-04 07:14:20 +00:00
break ;
# endif
# ifdef V4L2_PIX_FMT_SN9C10X
case V4L2_PIX_FMT_SN9C10X :
2011-10-29 07:09:45 +00:00
structure = gst_structure_new_empty ( " video/x-sonix " ) ;
2009-08-04 07:14:20 +00:00
break ;
# endif
# ifdef V4L2_PIX_FMT_PWC1
case V4L2_PIX_FMT_PWC1 :
2011-10-29 07:09:45 +00:00
structure = gst_structure_new_empty ( " video/x-pwc1 " ) ;
2009-08-04 07:14:20 +00:00
break ;
# endif
# ifdef V4L2_PIX_FMT_PWC2
case V4L2_PIX_FMT_PWC2 :
2011-10-29 07:09:45 +00:00
structure = gst_structure_new_empty ( " video/x-pwc2 " ) ;
2009-08-04 07:14:20 +00:00
break ;
# endif
default :
GST_DEBUG ( " Unknown fourcc 0x%08x % " GST_FOURCC_FORMAT ,
fourcc , GST_FOURCC_ARGS ( fourcc ) ) ;
break ;
}
return structure ;
}
GstCaps *
gst_v4l2_object_get_all_caps ( void )
{
static GstCaps * caps = NULL ;
if ( caps = = NULL ) {
GstStructure * structure ;
guint i ;
caps = gst_caps_new_empty ( ) ;
for ( i = 0 ; i < GST_V4L2_FORMAT_COUNT ; i + + ) {
2009-09-07 16:28:51 +00:00
structure =
gst_v4l2_object_v4l2fourcc_to_structure ( gst_v4l2_formats [ i ] . format ) ;
2009-08-04 07:14:20 +00:00
if ( structure ) {
2009-09-07 16:28:51 +00:00
if ( gst_v4l2_formats [ i ] . dimensions ) {
gst_structure_set ( structure ,
" width " , GST_TYPE_INT_RANGE , 1 , GST_V4L2_MAX_SIZE ,
" height " , GST_TYPE_INT_RANGE , 1 , GST_V4L2_MAX_SIZE ,
" framerate " , GST_TYPE_FRACTION_RANGE , 0 , 1 , 100 , 1 , NULL ) ;
}
2009-08-04 07:14:20 +00:00
gst_caps_append_structure ( caps , structure ) ;
}
}
}
return gst_caps_ref ( caps ) ;
}
/* collect data for the given caps
* @ caps : given input caps
* @ format : location for the v4l format
* @ w / @ h : location for width and height
* @ fps_n / @ fps_d : location for framerate
* @ size : location for expected size of the frame or 0 if unknown
*/
2011-07-12 18:03:32 +00:00
static gboolean
2009-08-04 07:14:20 +00:00
gst_v4l2_object_get_caps_info ( GstV4l2Object * v4l2object , GstCaps * caps ,
2011-07-13 11:00:42 +00:00
struct v4l2_fmtdesc * * format , GstVideoInfo * info )
2009-08-04 07:14:20 +00:00
{
GstStructure * structure ;
guint32 fourcc ;
const gchar * mimetype ;
2011-07-19 17:20:43 +00:00
struct v4l2_fmtdesc * fmt ;
2009-08-04 07:14:20 +00:00
/* default unknown values */
fourcc = 0 ;
structure = gst_caps_get_structure ( caps , 0 ) ;
2009-09-07 16:28:51 +00:00
mimetype = gst_structure_get_name ( structure ) ;
2011-07-13 11:00:42 +00:00
if ( g_str_equal ( mimetype , " video/x-raw " ) ) {
/* raw caps, parse into video info */
if ( ! gst_video_info_from_caps ( info , caps ) )
2011-07-08 12:34:40 +00:00
goto invalid_format ;
2009-08-04 07:14:20 +00:00
2011-07-13 11:00:42 +00:00
switch ( GST_VIDEO_INFO_FORMAT ( info ) ) {
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_I420 :
2009-08-04 07:14:20 +00:00
fourcc = V4L2_PIX_FMT_YUV420 ;
break ;
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_YUY2 :
2009-08-04 07:14:20 +00:00
fourcc = V4L2_PIX_FMT_YUYV ;
break ;
2011-07-08 12:34:40 +00:00
#if 0
case GST_VIDEO_FORMAT_Y41P :
2009-08-04 07:14:20 +00:00
fourcc = V4L2_PIX_FMT_Y41P ;
break ;
2011-07-08 12:34:40 +00:00
# endif
case GST_VIDEO_FORMAT_UYVY :
2009-08-04 07:14:20 +00:00
fourcc = V4L2_PIX_FMT_UYVY ;
break ;
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_YV12 :
2009-08-04 07:14:20 +00:00
fourcc = V4L2_PIX_FMT_YVU420 ;
break ;
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_Y41B :
2009-08-04 07:14:20 +00:00
fourcc = V4L2_PIX_FMT_YUV411P ;
break ;
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_Y42B :
2009-08-04 07:14:20 +00:00
fourcc = V4L2_PIX_FMT_YUV422P ;
break ;
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_NV12 :
2009-08-04 07:14:20 +00:00
fourcc = V4L2_PIX_FMT_NV12 ;
break ;
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_NV21 :
2009-08-04 07:14:20 +00:00
fourcc = V4L2_PIX_FMT_NV21 ;
break ;
# ifdef V4L2_PIX_FMT_YVYU
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_YVYU :
2009-08-04 07:14:20 +00:00
fourcc = V4L2_PIX_FMT_YVYU ;
break ;
# endif
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_RGB15 :
fourcc = V4L2_PIX_FMT_RGB555 ;
break ;
case GST_VIDEO_FORMAT_RGB16 :
fourcc = V4L2_PIX_FMT_RGB565 ;
2009-08-04 07:14:20 +00:00
break ;
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_RGB :
fourcc = V4L2_PIX_FMT_RGB24 ;
2009-08-04 07:14:20 +00:00
break ;
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_BGR :
fourcc = V4L2_PIX_FMT_BGR24 ;
2009-08-04 07:14:20 +00:00
break ;
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_RGBx :
case GST_VIDEO_FORMAT_RGBA :
fourcc = V4L2_PIX_FMT_RGB32 ;
2009-08-04 07:14:20 +00:00
break ;
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_BGRx :
case GST_VIDEO_FORMAT_BGRA :
fourcc = V4L2_PIX_FMT_BGR32 ;
break ;
2011-07-08 14:37:11 +00:00
case GST_VIDEO_FORMAT_GRAY8 :
fourcc = V4L2_PIX_FMT_GREY ;
2011-07-08 12:34:40 +00:00
default :
2009-08-04 07:14:20 +00:00
break ;
}
2011-07-13 11:00:42 +00:00
} else {
gboolean dimensions = TRUE ;
/* no video caps, construct videoinfo ourselves */
gst_video_info_init ( info ) ;
if ( g_str_equal ( mimetype , " video/mpegts " ) ) {
fourcc = V4L2_PIX_FMT_MPEG ;
dimensions = FALSE ;
} else if ( g_str_equal ( mimetype , " video/x-dv " ) ) {
fourcc = V4L2_PIX_FMT_DV ;
} else if ( g_str_equal ( mimetype , " image/jpeg " ) ) {
fourcc = V4L2_PIX_FMT_JPEG ;
2012-04-19 10:38:58 +00:00
# ifdef V4L2_PIX_FMT_H264
2012-04-16 22:08:21 +00:00
} else if ( g_str_equal ( mimetype , " video/x-h264 " ) ) {
fourcc = V4L2_PIX_FMT_H264 ;
2012-04-19 10:38:58 +00:00
# endif
2009-08-04 07:14:20 +00:00
# ifdef V4L2_PIX_FMT_SBGGR8
2012-03-05 11:43:17 +00:00
} else if ( g_str_equal ( mimetype , " video/x-bayer " ) ) {
2011-07-13 11:00:42 +00:00
fourcc = V4L2_PIX_FMT_SBGGR8 ;
2009-08-04 07:14:20 +00:00
# endif
# ifdef V4L2_PIX_FMT_SN9C10X
2011-07-13 11:00:42 +00:00
} else if ( g_str_equal ( mimetype , " video/x-sonix " ) ) {
fourcc = V4L2_PIX_FMT_SN9C10X ;
2009-08-04 07:14:20 +00:00
# endif
# ifdef V4L2_PIX_FMT_PWC1
2011-07-13 11:00:42 +00:00
} else if ( g_str_equal ( mimetype , " video/x-pwc1 " ) ) {
fourcc = V4L2_PIX_FMT_PWC1 ;
2009-08-04 07:14:20 +00:00
# endif
# ifdef V4L2_PIX_FMT_PWC2
2011-07-13 11:00:42 +00:00
} else if ( g_str_equal ( mimetype , " video/x-pwc2 " ) ) {
fourcc = V4L2_PIX_FMT_PWC2 ;
}
2011-07-08 14:37:11 +00:00
# endif
2009-08-04 07:14:20 +00:00
2011-07-13 11:00:42 +00:00
if ( dimensions ) {
2011-12-19 18:03:52 +00:00
const gchar * interlace_mode ;
2011-07-13 11:00:42 +00:00
if ( ! gst_structure_get_int ( structure , " width " , & info - > width ) )
goto no_width ;
if ( ! gst_structure_get_int ( structure , " height " , & info - > height ) )
goto no_height ;
2011-12-19 18:03:52 +00:00
interlace_mode = gst_structure_get_string ( structure , " interlace-mode " ) ;
if ( g_str_equal ( interlace_mode , " progressive " ) ) {
info - > interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE ;
} else {
info - > interlace_mode = GST_VIDEO_INTERLACE_MODE_MIXED ;
}
2011-07-13 11:00:42 +00:00
if ( ! gst_structure_get_fraction ( structure , " framerate " , & info - > fps_n ,
& info - > fps_d ) )
goto no_framerate ;
}
}
2009-08-04 07:14:20 +00:00
if ( fourcc = = 0 )
2011-07-08 12:34:40 +00:00
goto unhandled_format ;
2009-08-04 07:14:20 +00:00
2011-07-19 17:20:43 +00:00
fmt = gst_v4l2_object_get_format_from_fourcc ( v4l2object , fourcc ) ;
if ( fmt = = NULL )
goto unsupported_format ;
* format = fmt ;
2009-08-04 07:14:20 +00:00
return TRUE ;
2011-07-08 12:34:40 +00:00
/* ERRORS */
no_width :
{
GST_DEBUG_OBJECT ( v4l2object , " no width " ) ;
return FALSE ;
}
no_height :
{
GST_DEBUG_OBJECT ( v4l2object , " no height " ) ;
return FALSE ;
}
no_framerate :
{
GST_DEBUG_OBJECT ( v4l2object , " no framerate " ) ;
return FALSE ;
}
invalid_format :
{
GST_DEBUG_OBJECT ( v4l2object , " invalid format " ) ;
return FALSE ;
}
unhandled_format :
{
GST_DEBUG_OBJECT ( v4l2object , " unhandled format " ) ;
return FALSE ;
}
2011-07-19 17:20:43 +00:00
unsupported_format :
{
GST_DEBUG_OBJECT ( v4l2object , " unsupported format " ) ;
return FALSE ;
}
2009-08-04 07:14:20 +00:00
}
2010-11-04 17:36:09 +00:00
static gboolean
gst_v4l2_object_get_nearest_size ( GstV4l2Object * v4l2object ,
guint32 pixelformat , gint * width , gint * height , gboolean * interlaced ) ;
2009-08-04 07:14:20 +00:00
/* The frame interval enumeration code first appeared in Linux 2.6.19. */
# ifdef VIDIOC_ENUM_FRAMEINTERVALS
static GstStructure *
gst_v4l2_object_probe_caps_for_format_and_size ( GstV4l2Object * v4l2object ,
guint32 pixelformat ,
guint32 width , guint32 height , const GstStructure * template )
{
gint fd = v4l2object - > video_fd ;
struct v4l2_frmivalenum ival ;
guint32 num , denom ;
GstStructure * s ;
GValue rates = { 0 , } ;
2010-11-04 17:36:09 +00:00
gboolean interlaced ;
gint int_width = width ;
gint int_height = height ;
/* interlaced detection using VIDIOC_TRY/S_FMT */
if ( ! gst_v4l2_object_get_nearest_size ( v4l2object , pixelformat ,
& int_width , & int_height , & interlaced ) )
return NULL ;
2009-08-04 07:14:20 +00:00
memset ( & ival , 0 , sizeof ( struct v4l2_frmivalenum ) ) ;
ival . index = 0 ;
ival . pixel_format = pixelformat ;
ival . width = width ;
ival . height = height ;
GST_LOG_OBJECT ( v4l2object - > element ,
" get frame interval for %ux%u, % " GST_FOURCC_FORMAT , width , height ,
GST_FOURCC_ARGS ( pixelformat ) ) ;
/* keep in mind that v4l2 gives us frame intervals (durations); we invert the
* fraction to get framerate */
if ( v4l2_ioctl ( fd , VIDIOC_ENUM_FRAMEINTERVALS , & ival ) < 0 )
goto enum_frameintervals_failed ;
if ( ival . type = = V4L2_FRMIVAL_TYPE_DISCRETE ) {
GValue rate = { 0 , } ;
g_value_init ( & rates , GST_TYPE_LIST ) ;
g_value_init ( & rate , GST_TYPE_FRACTION ) ;
do {
num = ival . discrete . numerator ;
denom = ival . discrete . denominator ;
if ( num > G_MAXINT | | denom > G_MAXINT ) {
/* let us hope we don't get here... */
num > > = 1 ;
denom > > = 1 ;
}
GST_LOG_OBJECT ( v4l2object - > element , " adding discrete framerate: %d/%d " ,
denom , num ) ;
/* swap to get the framerate */
gst_value_set_fraction ( & rate , denom , num ) ;
gst_value_list_append_value ( & rates , & rate ) ;
ival . index + + ;
} while ( v4l2_ioctl ( fd , VIDIOC_ENUM_FRAMEINTERVALS , & ival ) > = 0 ) ;
} else if ( ival . type = = V4L2_FRMIVAL_TYPE_STEPWISE ) {
GValue min = { 0 , } ;
GValue step = { 0 , } ;
GValue max = { 0 , } ;
gboolean added = FALSE ;
guint32 minnum , mindenom ;
guint32 maxnum , maxdenom ;
g_value_init ( & rates , GST_TYPE_LIST ) ;
g_value_init ( & min , GST_TYPE_FRACTION ) ;
g_value_init ( & step , GST_TYPE_FRACTION ) ;
g_value_init ( & max , GST_TYPE_FRACTION ) ;
/* get the min */
minnum = ival . stepwise . min . numerator ;
mindenom = ival . stepwise . min . denominator ;
if ( minnum > G_MAXINT | | mindenom > G_MAXINT ) {
minnum > > = 1 ;
mindenom > > = 1 ;
}
GST_LOG_OBJECT ( v4l2object - > element , " stepwise min frame interval: %d/%d " ,
minnum , mindenom ) ;
gst_value_set_fraction ( & min , minnum , mindenom ) ;
/* get the max */
maxnum = ival . stepwise . max . numerator ;
maxdenom = ival . stepwise . max . denominator ;
if ( maxnum > G_MAXINT | | maxdenom > G_MAXINT ) {
maxnum > > = 1 ;
maxdenom > > = 1 ;
}
GST_LOG_OBJECT ( v4l2object - > element , " stepwise max frame interval: %d/%d " ,
maxnum , maxdenom ) ;
gst_value_set_fraction ( & max , maxnum , maxdenom ) ;
/* get the step */
num = ival . stepwise . step . numerator ;
denom = ival . stepwise . step . denominator ;
if ( num > G_MAXINT | | denom > G_MAXINT ) {
num > > = 1 ;
denom > > = 1 ;
}
if ( num = = 0 | | denom = = 0 ) {
/* in this case we have a wrong fraction or no step, set the step to max
* so that we only add the min value in the loop below */
num = maxnum ;
denom = maxdenom ;
}
/* since we only have gst_value_fraction_subtract and not add, negate the
* numerator */
GST_LOG_OBJECT ( v4l2object - > element , " stepwise step frame interval: %d/%d " ,
num , denom ) ;
gst_value_set_fraction ( & step , - num , denom ) ;
2011-12-02 12:07:24 +00:00
while ( gst_value_compare ( & min , & max ) ! = GST_VALUE_GREATER_THAN ) {
2009-08-04 07:14:20 +00:00
GValue rate = { 0 , } ;
num = gst_value_get_fraction_numerator ( & min ) ;
denom = gst_value_get_fraction_denominator ( & min ) ;
GST_LOG_OBJECT ( v4l2object - > element , " adding stepwise framerate: %d/%d " ,
denom , num ) ;
/* invert to get the framerate */
g_value_init ( & rate , GST_TYPE_FRACTION ) ;
gst_value_set_fraction ( & rate , denom , num ) ;
gst_value_list_append_value ( & rates , & rate ) ;
added = TRUE ;
/* we're actually adding because step was negated above. This is because
* there is no _add function . . . */
if ( ! gst_value_fraction_subtract ( & min , & min , & step ) ) {
GST_WARNING_OBJECT ( v4l2object - > element , " could not step fraction! " ) ;
break ;
}
}
if ( ! added ) {
/* no range was added, leave the default range from the template */
GST_WARNING_OBJECT ( v4l2object - > element ,
" no range added, leaving default " ) ;
g_value_unset ( & rates ) ;
}
} else if ( ival . type = = V4L2_FRMIVAL_TYPE_CONTINUOUS ) {
guint32 maxnum , maxdenom ;
g_value_init ( & rates , GST_TYPE_FRACTION_RANGE ) ;
num = ival . stepwise . min . numerator ;
denom = ival . stepwise . min . denominator ;
if ( num > G_MAXINT | | denom > G_MAXINT ) {
num > > = 1 ;
denom > > = 1 ;
}
maxnum = ival . stepwise . max . numerator ;
maxdenom = ival . stepwise . max . denominator ;
if ( maxnum > G_MAXINT | | maxdenom > G_MAXINT ) {
maxnum > > = 1 ;
maxdenom > > = 1 ;
}
GST_LOG_OBJECT ( v4l2object - > element ,
" continuous frame interval %d/%d to %d/%d " , maxdenom , maxnum , denom ,
num ) ;
gst_value_set_fraction_range_full ( & rates , maxdenom , maxnum , denom , num ) ;
} else {
goto unknown_type ;
}
return_data :
s = gst_structure_copy ( template ) ;
gst_structure_set ( s , " width " , G_TYPE_INT , ( gint ) width ,
2010-11-04 17:36:09 +00:00
" height " , G_TYPE_INT , ( gint ) height ,
2011-12-19 18:03:52 +00:00
" interlace-mode " , G_TYPE_STRING , ( interlaced ? " mixed " : " progressive " ) ,
2011-11-07 18:43:26 +00:00
" pixel-aspect-ratio " , GST_TYPE_FRACTION , 1 , 1 , NULL ) ;
2009-08-04 07:14:20 +00:00
if ( G_IS_VALUE ( & rates ) ) {
/* only change the framerate on the template when we have a valid probed new
* value */
gst_structure_set_value ( s , " framerate " , & rates ) ;
g_value_unset ( & rates ) ;
} else {
gst_structure_set ( s , " framerate " , GST_TYPE_FRACTION_RANGE , 0 , 1 , 100 , 1 ,
NULL ) ;
}
return s ;
/* ERRORS */
enum_frameintervals_failed :
{
GST_DEBUG_OBJECT ( v4l2object - > element ,
" Unable to enumerate intervals for % " GST_FOURCC_FORMAT " @%ux%u " ,
GST_FOURCC_ARGS ( pixelformat ) , width , height ) ;
goto return_data ;
}
unknown_type :
{
/* I don't see how this is actually an error, we ignore the format then */
GST_WARNING_OBJECT ( v4l2object - > element ,
" Unknown frame interval type at % " GST_FOURCC_FORMAT " @%ux%u: %u " ,
GST_FOURCC_ARGS ( pixelformat ) , width , height , ival . type ) ;
return NULL ;
}
}
# endif /* defined VIDIOC_ENUM_FRAMEINTERVALS */
# ifdef VIDIOC_ENUM_FRAMESIZES
static gint
sort_by_frame_size ( GstStructure * s1 , GstStructure * s2 )
{
int w1 , h1 , w2 , h2 ;
gst_structure_get_int ( s1 , " width " , & w1 ) ;
gst_structure_get_int ( s1 , " height " , & h1 ) ;
gst_structure_get_int ( s2 , " width " , & w2 ) ;
gst_structure_get_int ( s2 , " height " , & h2 ) ;
/* I think it's safe to assume that this won't overflow for a while */
return ( ( w2 * h2 ) - ( w1 * h1 ) ) ;
}
# endif
GstCaps *
gst_v4l2_object_probe_caps_for_format ( GstV4l2Object * v4l2object ,
guint32 pixelformat , const GstStructure * template )
{
GstCaps * ret = gst_caps_new_empty ( ) ;
GstStructure * tmp ;
# ifdef VIDIOC_ENUM_FRAMESIZES
gint fd = v4l2object - > video_fd ;
struct v4l2_frmsizeenum size ;
GList * results = NULL ;
guint32 w , h ;
2009-09-07 16:28:51 +00:00
if ( pixelformat = = GST_MAKE_FOURCC ( ' M ' , ' P ' , ' E ' , ' G ' ) )
2011-10-28 08:05:27 +00:00
return gst_caps_new_empty_simple ( " video/mpegts " ) ;
2009-09-07 16:28:51 +00:00
2009-08-04 07:14:20 +00:00
memset ( & size , 0 , sizeof ( struct v4l2_frmsizeenum ) ) ;
size . index = 0 ;
size . pixel_format = pixelformat ;
GST_DEBUG_OBJECT ( v4l2object - > element , " Enumerating frame sizes " ) ;
if ( v4l2_ioctl ( fd , VIDIOC_ENUM_FRAMESIZES , & size ) < 0 )
goto enum_framesizes_failed ;
if ( size . type = = V4L2_FRMSIZE_TYPE_DISCRETE ) {
do {
GST_LOG_OBJECT ( v4l2object - > element , " got discrete frame size %dx%d " ,
size . discrete . width , size . discrete . height ) ;
w = MIN ( size . discrete . width , G_MAXINT ) ;
h = MIN ( size . discrete . height , G_MAXINT ) ;
if ( w & & h ) {
tmp =
gst_v4l2_object_probe_caps_for_format_and_size ( v4l2object ,
pixelformat , w , h , template ) ;
if ( tmp )
results = g_list_prepend ( results , tmp ) ;
}
size . index + + ;
} while ( v4l2_ioctl ( fd , VIDIOC_ENUM_FRAMESIZES , & size ) > = 0 ) ;
GST_DEBUG_OBJECT ( v4l2object - > element ,
" done iterating discrete frame sizes " ) ;
} else if ( size . type = = V4L2_FRMSIZE_TYPE_STEPWISE ) {
GST_DEBUG_OBJECT ( v4l2object - > element , " we have stepwise frame sizes: " ) ;
GST_DEBUG_OBJECT ( v4l2object - > element , " min width: %d " ,
size . stepwise . min_width ) ;
GST_DEBUG_OBJECT ( v4l2object - > element , " min height: %d " ,
size . stepwise . min_height ) ;
GST_DEBUG_OBJECT ( v4l2object - > element , " max width: %d " ,
size . stepwise . max_width ) ;
GST_DEBUG_OBJECT ( v4l2object - > element , " min height: %d " ,
size . stepwise . max_height ) ;
GST_DEBUG_OBJECT ( v4l2object - > element , " step width: %d " ,
size . stepwise . step_width ) ;
GST_DEBUG_OBJECT ( v4l2object - > element , " step height: %d " ,
size . stepwise . step_height ) ;
for ( w = size . stepwise . min_width , h = size . stepwise . min_height ;
2011-12-02 11:59:03 +00:00
w < = size . stepwise . max_width & & h < = size . stepwise . max_height ;
2009-08-04 07:14:20 +00:00
w + = size . stepwise . step_width , h + = size . stepwise . step_height ) {
if ( w = = 0 | | h = = 0 )
continue ;
tmp =
gst_v4l2_object_probe_caps_for_format_and_size ( v4l2object ,
pixelformat , w , h , template ) ;
if ( tmp )
results = g_list_prepend ( results , tmp ) ;
}
GST_DEBUG_OBJECT ( v4l2object - > element ,
" done iterating stepwise frame sizes " ) ;
} else if ( size . type = = V4L2_FRMSIZE_TYPE_CONTINUOUS ) {
guint32 maxw , maxh ;
GST_DEBUG_OBJECT ( v4l2object - > element , " we have continuous frame sizes: " ) ;
GST_DEBUG_OBJECT ( v4l2object - > element , " min width: %d " ,
size . stepwise . min_width ) ;
GST_DEBUG_OBJECT ( v4l2object - > element , " min height: %d " ,
size . stepwise . min_height ) ;
GST_DEBUG_OBJECT ( v4l2object - > element , " max width: %d " ,
size . stepwise . max_width ) ;
GST_DEBUG_OBJECT ( v4l2object - > element , " min height: %d " ,
size . stepwise . max_height ) ;
w = MAX ( size . stepwise . min_width , 1 ) ;
h = MAX ( size . stepwise . min_height , 1 ) ;
maxw = MIN ( size . stepwise . max_width , G_MAXINT ) ;
maxh = MIN ( size . stepwise . max_height , G_MAXINT ) ;
tmp =
gst_v4l2_object_probe_caps_for_format_and_size ( v4l2object , pixelformat ,
w , h , template ) ;
if ( tmp ) {
gst_structure_set ( tmp , " width " , GST_TYPE_INT_RANGE , ( gint ) w ,
( gint ) maxw , " height " , GST_TYPE_INT_RANGE , ( gint ) h , ( gint ) maxh ,
NULL ) ;
/* no point using the results list here, since there's only one struct */
gst_caps_append_structure ( ret , tmp ) ;
}
} else {
goto unknown_type ;
}
/* we use an intermediary list to store and then sort the results of the
* probing because we can ' t make any assumptions about the order in which
* the driver will give us the sizes , but we want the final caps to contain
* the results starting with the highest resolution and having the lowest
* resolution last , since order in caps matters for things like fixation . */
results = g_list_sort ( results , ( GCompareFunc ) sort_by_frame_size ) ;
while ( results ! = NULL ) {
gst_caps_append_structure ( ret , GST_STRUCTURE ( results - > data ) ) ;
results = g_list_delete_link ( results , results ) ;
}
if ( gst_caps_is_empty ( ret ) )
goto enum_framesizes_no_results ;
return ret ;
/* ERRORS */
enum_framesizes_failed :
{
/* I don't see how this is actually an error */
GST_DEBUG_OBJECT ( v4l2object - > element ,
" Failed to enumerate frame sizes for pixelformat % " GST_FOURCC_FORMAT
" (%s) " , GST_FOURCC_ARGS ( pixelformat ) , g_strerror ( errno ) ) ;
goto default_frame_sizes ;
}
enum_framesizes_no_results :
{
/* it's possible that VIDIOC_ENUM_FRAMESIZES is defined but the driver in
* question doesn ' t actually support it yet */
GST_DEBUG_OBJECT ( v4l2object - > element ,
" No results for pixelformat % " GST_FOURCC_FORMAT
" enumerating frame sizes, trying fallback " ,
GST_FOURCC_ARGS ( pixelformat ) ) ;
goto default_frame_sizes ;
}
unknown_type :
{
GST_WARNING_OBJECT ( v4l2object - > element ,
" Unknown frame sizeenum type for pixelformat % " GST_FOURCC_FORMAT
" : %u " , GST_FOURCC_ARGS ( pixelformat ) , size . type ) ;
goto default_frame_sizes ;
}
default_frame_sizes :
# endif /* defined VIDIOC_ENUM_FRAMESIZES */
{
gint min_w , max_w , min_h , max_h , fix_num = 0 , fix_denom = 0 ;
2010-11-04 17:36:09 +00:00
gboolean interlaced ;
2009-08-04 07:14:20 +00:00
/* This code is for Linux < 2.6.19 */
min_w = min_h = 1 ;
max_w = max_h = GST_V4L2_MAX_SIZE ;
if ( ! gst_v4l2_object_get_nearest_size ( v4l2object , pixelformat , & min_w ,
2010-11-04 17:36:09 +00:00
& min_h , & interlaced ) ) {
2009-08-04 07:14:20 +00:00
GST_WARNING_OBJECT ( v4l2object - > element ,
" Could not probe minimum capture size for pixelformat % "
GST_FOURCC_FORMAT , GST_FOURCC_ARGS ( pixelformat ) ) ;
}
if ( ! gst_v4l2_object_get_nearest_size ( v4l2object , pixelformat , & max_w ,
2010-11-04 17:36:09 +00:00
& max_h , & interlaced ) ) {
2009-08-04 07:14:20 +00:00
GST_WARNING_OBJECT ( v4l2object - > element ,
" Could not probe maximum capture size for pixelformat % "
GST_FOURCC_FORMAT , GST_FOURCC_ARGS ( pixelformat ) ) ;
}
/* Since we can't get framerate directly, try to use the current norm */
2010-04-04 11:43:41 +00:00
if ( v4l2object - > tv_norm & & v4l2object - > norms ) {
2009-08-04 07:14:20 +00:00
GList * norms ;
2010-06-15 17:47:16 +00:00
GstTunerNorm * norm = NULL ;
2010-04-04 11:43:41 +00:00
GstTunerNorm * current =
gst_v4l2_tuner_get_norm_by_std_id ( v4l2object , v4l2object - > tv_norm ) ;
2009-08-04 07:14:20 +00:00
for ( norms = v4l2object - > norms ; norms ! = NULL ; norms = norms - > next ) {
norm = ( GstTunerNorm * ) norms - > data ;
2010-04-04 11:43:41 +00:00
if ( ! strcmp ( norm - > label , current - > label ) )
2009-08-04 07:14:20 +00:00
break ;
}
/* If it's possible, set framerate to that (discrete) value */
if ( norm ) {
fix_num = gst_value_get_fraction_numerator ( & norm - > framerate ) ;
fix_denom = gst_value_get_fraction_denominator ( & norm - > framerate ) ;
}
}
tmp = gst_structure_copy ( template ) ;
if ( fix_num ) {
2009-08-09 13:19:42 +00:00
gst_structure_set ( tmp , " framerate " , GST_TYPE_FRACTION , fix_num ,
fix_denom , NULL ) ;
2009-08-04 07:14:20 +00:00
} else {
/* if norm can't be used, copy the template framerate */
2009-08-09 13:19:42 +00:00
gst_structure_set ( tmp , " framerate " , GST_TYPE_FRACTION_RANGE , 0 , 1 ,
100 , 1 , NULL ) ;
2009-08-04 07:14:20 +00:00
}
2009-08-09 13:19:42 +00:00
if ( min_w = = max_w )
gst_structure_set ( tmp , " width " , G_TYPE_INT , max_w , NULL ) ;
else
gst_structure_set ( tmp , " width " , GST_TYPE_INT_RANGE , min_w , max_w , NULL ) ;
if ( min_h = = max_h )
gst_structure_set ( tmp , " height " , G_TYPE_INT , max_h , NULL ) ;
else
gst_structure_set ( tmp , " height " , GST_TYPE_INT_RANGE , min_h , max_h , NULL ) ;
2011-12-19 18:03:52 +00:00
gst_structure_set ( tmp , " interlace-mode " , G_TYPE_STRING ,
( interlaced ? " mixed " : " progressive " ) , NULL ) ;
gst_structure_set ( tmp , " pixel-aspect-ratio " , GST_TYPE_FRACTION , 1 , 1 ,
NULL ) ;
2010-11-04 17:36:09 +00:00
2009-08-04 07:14:20 +00:00
gst_caps_append_structure ( ret , tmp ) ;
return ret ;
}
}
static gboolean
gst_v4l2_object_get_nearest_size ( GstV4l2Object * v4l2object ,
2010-11-04 17:36:09 +00:00
guint32 pixelformat , gint * width , gint * height , gboolean * interlaced )
2009-08-04 07:14:20 +00:00
{
2011-08-08 09:54:26 +00:00
struct v4l2_format fmt , prevfmt ;
2009-08-04 07:14:20 +00:00
int fd ;
int r ;
2011-08-08 09:54:26 +00:00
int prevfmt_valid ;
2009-08-04 07:14:20 +00:00
g_return_val_if_fail ( width ! = NULL , FALSE ) ;
g_return_val_if_fail ( height ! = NULL , FALSE ) ;
GST_LOG_OBJECT ( v4l2object - > element ,
" getting nearest size to %dx%d with format % " GST_FOURCC_FORMAT ,
* width , * height , GST_FOURCC_ARGS ( pixelformat ) ) ;
fd = v4l2object - > video_fd ;
2011-08-08 09:54:26 +00:00
/* Some drivers are buggy and will modify the currently set format
when processing VIDIOC_TRY_FMT , so we remember what is set at the
minute , and will reset it when done . */
prevfmt_valid = ( v4l2_ioctl ( fd , VIDIOC_G_FMT , & prevfmt ) > = 0 ) ;
2009-08-04 07:14:20 +00:00
/* get size delimiters */
memset ( & fmt , 0 , sizeof ( fmt ) ) ;
fmt . type = v4l2object - > type ;
fmt . fmt . pix . width = * width ;
fmt . fmt . pix . height = * height ;
fmt . fmt . pix . pixelformat = pixelformat ;
2010-12-04 19:43:11 +00:00
fmt . fmt . pix . field = V4L2_FIELD_NONE ;
2009-08-04 07:14:20 +00:00
r = v4l2_ioctl ( fd , VIDIOC_TRY_FMT , & fmt ) ;
if ( r < 0 & & errno = = EINVAL ) {
2010-12-04 19:43:11 +00:00
/* try again with interlaced video */
2009-08-04 07:14:20 +00:00
fmt . fmt . pix . width = * width ;
fmt . fmt . pix . height = * height ;
fmt . fmt . pix . pixelformat = pixelformat ;
2010-12-04 19:43:11 +00:00
fmt . fmt . pix . field = V4L2_FIELD_INTERLACED ;
2009-08-04 07:14:20 +00:00
r = v4l2_ioctl ( fd , VIDIOC_TRY_FMT , & fmt ) ;
}
if ( r < 0 ) {
/* The driver might not implement TRY_FMT, in which case we will try
S_FMT to probe */
if ( errno ! = ENOTTY )
2011-08-08 09:54:26 +00:00
goto error ;
2009-08-04 07:14:20 +00:00
/* Only try S_FMT if we're not actively capturing yet, which we shouldn't
be , because we ' re still probing */
if ( GST_V4L2_IS_ACTIVE ( v4l2object ) )
2011-08-08 09:54:26 +00:00
goto error ;
2009-08-04 07:14:20 +00:00
GST_LOG_OBJECT ( v4l2object - > element ,
" Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT " ) ;
fmt . fmt . pix . width = * width ;
fmt . fmt . pix . height = * height ;
r = v4l2_ioctl ( fd , VIDIOC_S_FMT , & fmt ) ;
if ( r < 0 & & errno = = EINVAL ) {
/* try again with progressive video */
fmt . fmt . pix . width = * width ;
fmt . fmt . pix . height = * height ;
fmt . fmt . pix . pixelformat = pixelformat ;
fmt . fmt . pix . field = V4L2_FIELD_NONE ;
r = v4l2_ioctl ( fd , VIDIOC_S_FMT , & fmt ) ;
}
if ( r < 0 )
2011-08-08 09:54:26 +00:00
goto error ;
2009-08-04 07:14:20 +00:00
}
GST_LOG_OBJECT ( v4l2object - > element ,
" got nearest size %dx%d " , fmt . fmt . pix . width , fmt . fmt . pix . height ) ;
* width = fmt . fmt . pix . width ;
* height = fmt . fmt . pix . height ;
2010-11-04 17:36:09 +00:00
switch ( fmt . fmt . pix . field ) {
2010-12-04 19:43:11 +00:00
case V4L2_FIELD_ANY :
2010-11-04 17:36:09 +00:00
case V4L2_FIELD_NONE :
* interlaced = FALSE ;
break ;
case V4L2_FIELD_INTERLACED :
case V4L2_FIELD_INTERLACED_TB :
case V4L2_FIELD_INTERLACED_BT :
* interlaced = TRUE ;
break ;
default :
GST_WARNING_OBJECT ( v4l2object - > element ,
" Unsupported field type for % " GST_FOURCC_FORMAT " @%ux%u " ,
2010-12-18 01:19:35 +00:00
GST_FOURCC_ARGS ( pixelformat ) , * width , * height ) ;
2011-08-08 09:54:26 +00:00
goto error ;
2010-11-04 17:36:09 +00:00
}
2011-08-08 09:54:26 +00:00
if ( prevfmt_valid )
v4l2_ioctl ( fd , VIDIOC_S_FMT , & prevfmt ) ;
2009-08-04 07:14:20 +00:00
return TRUE ;
2011-08-08 09:54:26 +00:00
error :
if ( prevfmt_valid )
v4l2_ioctl ( fd , VIDIOC_S_FMT , & prevfmt ) ;
return FALSE ;
2009-08-04 07:14:20 +00:00
}
2011-07-13 14:33:58 +00:00
static gboolean
2011-07-15 15:26:06 +00:00
gst_v4l2_object_setup_pool ( GstV4l2Object * v4l2object , GstCaps * caps )
2011-07-13 14:33:58 +00:00
{
2011-07-26 09:54:23 +00:00
GstV4l2IOMode mode ;
2011-07-18 16:54:49 +00:00
2011-07-13 14:33:58 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " initializing the capture system " ) ;
GST_V4L2_CHECK_OPEN ( v4l2object ) ;
GST_V4L2_CHECK_NOT_ACTIVE ( v4l2object ) ;
2011-07-26 09:54:23 +00:00
/* find transport */
mode = v4l2object - > req_mode ;
if ( v4l2object - > vcap . capabilities & V4L2_CAP_READWRITE ) {
if ( v4l2object - > req_mode = = GST_V4L2_IO_AUTO )
mode = GST_V4L2_IO_RW ;
} else if ( v4l2object - > req_mode = = GST_V4L2_IO_RW )
goto method_not_supported ;
if ( v4l2object - > vcap . capabilities & V4L2_CAP_STREAMING ) {
if ( v4l2object - > req_mode = = GST_V4L2_IO_AUTO )
mode = GST_V4L2_IO_MMAP ;
} else if ( v4l2object - > req_mode = = GST_V4L2_IO_MMAP )
goto method_not_supported ;
2011-07-13 14:33:58 +00:00
2011-07-18 16:54:49 +00:00
/* if still no transport selected, error out */
2011-07-26 09:54:23 +00:00
if ( mode = = GST_V4L2_IO_AUTO )
2011-07-18 16:54:49 +00:00
goto no_supported_capture_method ;
2011-07-13 14:33:58 +00:00
2011-07-26 09:54:23 +00:00
GST_INFO_OBJECT ( v4l2object - > element , " accessing buffers via mode %d " , mode ) ;
v4l2object - > mode = mode ;
2011-07-18 16:54:49 +00:00
/* Map the buffers */
GST_LOG_OBJECT ( v4l2object - > element , " initiating buffer pool " ) ;
2011-07-13 14:33:58 +00:00
2011-08-04 11:50:01 +00:00
if ( ! ( v4l2object - > pool = gst_v4l2_buffer_pool_new ( v4l2object , caps ) ) )
2011-07-18 16:54:49 +00:00
goto buffer_pool_new_failed ;
2011-07-13 14:33:58 +00:00
GST_V4L2_SET_ACTIVE ( v4l2object ) ;
return TRUE ;
/* ERRORS */
buffer_pool_new_failed :
{
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , READ ,
( _ ( " Could not map buffers from device '%s' " ) ,
v4l2object - > videodev ) ,
( " Failed to create buffer pool: %s " , g_strerror ( errno ) ) ) ;
return FALSE ;
}
2011-07-26 09:54:23 +00:00
method_not_supported :
{
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , READ ,
( _ ( " The driver of device '%s' does not support the IO method %d " ) ,
v4l2object - > videodev , mode ) , ( NULL ) ) ;
return FALSE ;
}
2011-07-13 14:33:58 +00:00
no_supported_capture_method :
{
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , READ ,
2011-07-26 09:54:23 +00:00
( _ ( " The driver of device '%s' does not support any known IO "
2011-07-13 14:33:58 +00:00
" method. " ) , v4l2object - > videodev ) , ( NULL ) ) ;
return FALSE ;
}
}
2011-07-13 09:19:28 +00:00
/* Note about fraction simplification
* * n1 / d1 = = n2 / d2 is also written as n1 = = ( n2 * d1 ) / d2
* */
# define fractions_are_equal(n1,d1,n2,d2) ((n1) == gst_util_uint64_scale_int((n2), (d1), (d2)))
2009-08-04 07:14:20 +00:00
gboolean
2011-07-12 18:03:32 +00:00
gst_v4l2_object_set_format ( GstV4l2Object * v4l2object , GstCaps * caps )
2009-08-04 07:14:20 +00:00
{
gint fd = v4l2object - > video_fd ;
2011-07-13 11:00:42 +00:00
struct v4l2_format format ;
struct v4l2_streamparm streamparm ;
2010-12-04 19:43:11 +00:00
enum v4l2_field field ;
2011-07-12 18:03:32 +00:00
guint32 pixelformat ;
struct v4l2_fmtdesc * fmtdesc ;
2011-07-13 11:00:42 +00:00
GstVideoInfo info ;
gint width , height , fps_n , fps_d , stride ;
2011-07-12 18:03:32 +00:00
2011-07-13 11:00:42 +00:00
if ( ! gst_v4l2_object_get_caps_info ( v4l2object , caps , & fmtdesc , & info ) )
2011-07-12 18:03:32 +00:00
goto invalid_caps ;
pixelformat = fmtdesc - > pixelformat ;
2011-07-13 11:00:42 +00:00
width = GST_VIDEO_INFO_WIDTH ( & info ) ;
height = GST_VIDEO_INFO_HEIGHT ( & info ) ;
fps_n = GST_VIDEO_INFO_FPS_N ( & info ) ;
fps_d = GST_VIDEO_INFO_FPS_D ( & info ) ;
stride = GST_VIDEO_INFO_PLANE_STRIDE ( & info , 0 ) ;
2010-12-04 19:43:11 +00:00
2012-04-19 10:20:59 +00:00
if ( GST_VIDEO_INFO_IS_INTERLACED ( & info ) ) {
2010-12-04 19:43:11 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " interlaced video " ) ;
/* ideally we would differentiate between types of interlaced video
* but there is not sufficient information in the caps . .
*/
2011-02-03 22:42:59 +00:00
field = V4L2_FIELD_INTERLACED ;
2010-12-04 19:43:11 +00:00
} else {
GST_DEBUG_OBJECT ( v4l2object - > element , " progressive video " ) ;
field = V4L2_FIELD_NONE ;
}
2009-08-04 07:14:20 +00:00
2011-07-13 09:19:28 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " Desired format %dx%d, format "
2011-07-18 16:54:49 +00:00
" % " GST_FOURCC_FORMAT " stride: %d " , width , height ,
GST_FOURCC_ARGS ( pixelformat ) , stride ) ;
2009-08-04 07:14:20 +00:00
GST_V4L2_CHECK_OPEN ( v4l2object ) ;
GST_V4L2_CHECK_NOT_ACTIVE ( v4l2object ) ;
2012-04-19 08:27:01 +00:00
/* MPEG-TS source cameras don't get their format set for some reason.
* It looks wrong and we weren ' t able to track down the reason for that code
* so it is disabled until someone who has an mpeg - ts camera complains . . .
*/
#if 0
2011-04-28 13:57:04 +00:00
/* Only unconditionally accept mpegts for sources */
if ( ( v4l2object - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE ) & &
( pixelformat = = GST_MAKE_FOURCC ( ' M ' , ' P ' , ' E ' , ' G ' ) ) )
2011-07-13 09:19:28 +00:00
goto done ;
2012-04-19 08:27:01 +00:00
# endif
2009-09-07 16:28:51 +00:00
2011-07-13 11:00:42 +00:00
memset ( & format , 0x00 , sizeof ( struct v4l2_format ) ) ;
format . type = v4l2object - > type ;
2011-07-12 16:13:42 +00:00
2011-07-13 11:00:42 +00:00
if ( v4l2_ioctl ( fd , VIDIOC_G_FMT , & format ) < 0 )
2009-08-04 07:14:20 +00:00
goto get_fmt_failed ;
2011-07-12 15:46:21 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " Got format to %dx%d, format "
2011-07-27 11:41:33 +00:00
" % " GST_FOURCC_FORMAT " bytesperline %d, colorspace %d " ,
format . fmt . pix . width , format . fmt . pix . height ,
GST_FOURCC_ARGS ( format . fmt . pix . pixelformat ) , format . fmt . pix . bytesperline ,
format . fmt . pix . colorspace ) ;
2011-07-13 09:19:28 +00:00
2011-07-13 11:00:42 +00:00
if ( format . type ! = v4l2object - > type | |
format . fmt . pix . width ! = width | |
format . fmt . pix . height ! = height | |
format . fmt . pix . pixelformat ! = pixelformat | |
2011-07-13 12:52:30 +00:00
format . fmt . pix . field ! = field | | format . fmt . pix . bytesperline ! = stride ) {
2011-07-13 11:00:42 +00:00
/* something different, set the format */
GST_DEBUG_OBJECT ( v4l2object - > element , " Setting format to %dx%d, format "
" % " GST_FOURCC_FORMAT " bytesperline %d " , width , height ,
GST_FOURCC_ARGS ( pixelformat ) , stride ) ;
format . type = v4l2object - > type ;
format . fmt . pix . width = width ;
format . fmt . pix . height = height ;
format . fmt . pix . pixelformat = pixelformat ;
format . fmt . pix . field = field ;
/* try to ask our prefered stride */
format . fmt . pix . bytesperline = stride ;
if ( v4l2_ioctl ( fd , VIDIOC_S_FMT , & format ) < 0 )
2011-07-13 09:19:28 +00:00
goto set_fmt_failed ;
GST_DEBUG_OBJECT ( v4l2object - > element , " Got format to %dx%d, format "
2011-07-13 11:00:42 +00:00
" % " GST_FOURCC_FORMAT " stride %d " , format . fmt . pix . width ,
format . fmt . pix . height , GST_FOURCC_ARGS ( format . fmt . pix . pixelformat ) ,
format . fmt . pix . bytesperline ) ;
2011-07-13 09:19:28 +00:00
2011-07-13 11:00:42 +00:00
if ( format . fmt . pix . width ! = width | | format . fmt . pix . height ! = height )
2011-07-13 09:19:28 +00:00
goto invalid_dimensions ;
2011-07-13 11:00:42 +00:00
if ( format . fmt . pix . pixelformat ! = pixelformat )
2011-07-13 09:19:28 +00:00
goto invalid_pixelformat ;
2010-06-16 15:21:35 +00:00
}
2011-07-26 14:15:05 +00:00
/* figure out the frame layout */
2011-07-18 16:54:49 +00:00
v4l2object - > bytesperline = format . fmt . pix . bytesperline ;
2011-07-26 14:15:05 +00:00
v4l2object - > sizeimage = format . fmt . pix . sizeimage ;
2011-07-27 14:46:46 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " Got sizeimage %u " ,
v4l2object - > sizeimage ) ;
2010-06-16 15:21:35 +00:00
2011-07-13 09:19:28 +00:00
/* Is there a reason we require the caller to always specify a framerate? */
GST_DEBUG_OBJECT ( v4l2object - > element , " Desired framerate: %u/%u " , fps_n ,
fps_d ) ;
2011-07-13 11:00:42 +00:00
memset ( & streamparm , 0x00 , sizeof ( struct v4l2_streamparm ) ) ;
streamparm . type = v4l2object - > type ;
2011-07-13 09:19:28 +00:00
2011-07-13 11:00:42 +00:00
if ( v4l2_ioctl ( fd , VIDIOC_G_PARM , & streamparm ) < 0 )
2011-07-13 09:19:28 +00:00
goto get_parm_failed ;
2011-07-13 11:00:42 +00:00
GST_VIDEO_INFO_FPS_N ( & info ) =
streamparm . parm . capture . timeperframe . denominator ;
GST_VIDEO_INFO_FPS_D ( & info ) = streamparm . parm . capture . timeperframe . numerator ;
2011-07-13 09:29:26 +00:00
if ( v4l2object - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE ) {
GST_DEBUG_OBJECT ( v4l2object - > element , " Got framerate: %u/%u " ,
2011-07-13 11:00:42 +00:00
streamparm . parm . capture . timeperframe . denominator ,
streamparm . parm . capture . timeperframe . numerator ) ;
2011-07-13 09:29:26 +00:00
2011-08-29 11:43:59 +00:00
/* We used to skip frame rate setup if the camera was already setup
* with the requested frame rate . This breaks some cameras though ,
* causing them to not output data ( several models of Thinkpad cameras
* have this problem at least ) .
* So , don ' t skip . */
GST_LOG_OBJECT ( v4l2object - > element , " Setting framerate to %u/%u " , fps_n ,
fps_d ) ;
/* We want to change the frame rate, so check whether we can. Some cheap USB
* cameras don ' t have the capability */
if ( ( streamparm . parm . capture . capability & V4L2_CAP_TIMEPERFRAME ) = = 0 ) {
GST_DEBUG_OBJECT ( v4l2object - > element ,
" Not setting framerate (not supported) " ) ;
goto done ;
}
2011-07-12 15:46:21 +00:00
2011-08-29 11:43:59 +00:00
/* Note: V4L2 wants the frame interval, we have the frame rate */
streamparm . parm . capture . timeperframe . numerator = fps_d ;
streamparm . parm . capture . timeperframe . denominator = fps_n ;
2009-08-04 07:14:20 +00:00
2011-08-29 11:43:59 +00:00
/* some cheap USB cam's won't accept any change */
if ( v4l2_ioctl ( fd , VIDIOC_S_PARM , & streamparm ) < 0 )
goto set_parm_failed ;
2011-07-12 15:46:21 +00:00
2011-08-29 11:43:59 +00:00
/* get new values */
fps_d = streamparm . parm . capture . timeperframe . numerator ;
fps_n = streamparm . parm . capture . timeperframe . denominator ;
2009-08-04 07:14:20 +00:00
2011-08-29 11:43:59 +00:00
GST_INFO_OBJECT ( v4l2object - > element , " Set framerate to %u/%u " , fps_n ,
fps_d ) ;
2011-07-13 11:00:42 +00:00
2011-08-29 11:43:59 +00:00
GST_VIDEO_INFO_FPS_N ( & info ) = fps_n ;
GST_VIDEO_INFO_FPS_D ( & info ) = fps_d ;
2011-07-13 09:19:28 +00:00
}
2009-08-04 07:14:20 +00:00
2011-07-13 09:19:28 +00:00
done :
/* if we have a framerate pre-calculate duration */
if ( fps_n > 0 & & fps_d > 0 ) {
v4l2object - > duration = gst_util_uint64_scale_int ( GST_SECOND , fps_d , fps_n ) ;
} else {
v4l2object - > duration = GST_CLOCK_TIME_NONE ;
}
2011-07-13 11:00:42 +00:00
v4l2object - > info = info ;
v4l2object - > fmtdesc = fmtdesc ;
2009-08-04 07:14:20 +00:00
2011-07-13 14:33:58 +00:00
/* now configure ther pools */
2011-07-15 15:26:06 +00:00
if ( ! gst_v4l2_object_setup_pool ( v4l2object , caps ) )
2011-07-13 14:33:58 +00:00
goto pool_failed ;
2009-08-04 07:14:20 +00:00
return TRUE ;
/* ERRORS */
2011-07-12 18:03:32 +00:00
invalid_caps :
{
GST_DEBUG_OBJECT ( v4l2object - > element , " can't parse caps % " GST_PTR_FORMAT ,
caps ) ;
return FALSE ;
}
2009-08-04 07:14:20 +00:00
get_fmt_failed :
{
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS ,
( _ ( " Device '%s' does not support video capture " ) ,
v4l2object - > videodev ) ,
( " Call to G_FMT failed: (%s) " , g_strerror ( errno ) ) ) ;
return FALSE ;
}
set_fmt_failed :
{
2011-09-08 11:28:24 +00:00
if ( errno = = EBUSY ) {
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , BUSY ,
( _ ( " Device '%s' is busy " ) , v4l2object - > videodev ) ,
( " Call to S_FMT failed for % " GST_FOURCC_FORMAT " @ %dx%d: %s " ,
GST_FOURCC_ARGS ( pixelformat ) , width , height ,
g_strerror ( errno ) ) ) ;
} else {
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS ,
( _ ( " Device '%s' cannot capture at %dx%d " ) ,
v4l2object - > videodev , width , height ) ,
( " Call to S_FMT failed for % " GST_FOURCC_FORMAT " @ %dx%d: %s " ,
GST_FOURCC_ARGS ( pixelformat ) , width , height ,
g_strerror ( errno ) ) ) ;
}
2009-08-04 07:14:20 +00:00
return FALSE ;
}
invalid_dimensions :
{
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS ,
( _ ( " Device '%s' cannot capture at %dx%d " ) ,
v4l2object - > videodev , width , height ) ,
( " Tried to capture at %dx%d, but device returned size %dx%d " ,
2011-07-13 11:00:42 +00:00
width , height , format . fmt . pix . width , format . fmt . pix . height ) ) ;
2009-08-04 07:14:20 +00:00
return FALSE ;
}
invalid_pixelformat :
{
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS ,
( _ ( " Device '%s' cannot capture in the specified format " ) ,
v4l2object - > videodev ) ,
( " Tried to capture in % " GST_FOURCC_FORMAT
" , but device returned format " " % " GST_FOURCC_FORMAT ,
GST_FOURCC_ARGS ( pixelformat ) ,
2011-07-13 11:00:42 +00:00
GST_FOURCC_ARGS ( format . fmt . pix . pixelformat ) ) ) ;
2009-08-04 07:14:20 +00:00
return FALSE ;
}
2011-07-13 09:19:28 +00:00
get_parm_failed :
{
2011-07-13 09:36:54 +00:00
/* it's possible that this call is not supported */
2011-07-13 10:40:11 +00:00
if ( errno ! = EINVAL ) {
2011-07-13 09:36:54 +00:00
GST_ELEMENT_WARNING ( v4l2object - > element , RESOURCE , SETTINGS ,
( _ ( " Could not get parameters on device '%s' " ) ,
v4l2object - > videodev ) , GST_ERROR_SYSTEM ) ;
}
2011-07-13 09:19:28 +00:00
goto done ;
}
set_parm_failed :
{
GST_ELEMENT_WARNING ( v4l2object - > element , RESOURCE , SETTINGS ,
2011-07-13 14:33:58 +00:00
( _ ( " Video device did not accept new frame rate setting. " ) ) ,
2011-07-13 09:19:28 +00:00
GST_ERROR_SYSTEM ) ;
goto done ;
}
2011-07-13 14:33:58 +00:00
pool_failed :
{
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS ,
( _ ( " Video device could not create buffer pool. " ) ) , GST_ERROR_SYSTEM ) ;
return FALSE ;
}
2009-08-04 07:14:20 +00:00
}
gboolean
2011-07-18 16:54:49 +00:00
gst_v4l2_object_unlock ( GstV4l2Object * v4l2object )
2009-08-04 07:14:20 +00:00
{
2011-07-18 16:54:49 +00:00
GST_LOG_OBJECT ( v4l2object - > element , " flush poll " ) ;
gst_poll_set_flushing ( v4l2object - > poll , TRUE ) ;
2011-07-13 14:33:58 +00:00
2011-07-18 16:54:49 +00:00
return TRUE ;
}
2011-07-13 14:33:58 +00:00
2011-07-18 16:54:49 +00:00
gboolean
gst_v4l2_object_unlock_stop ( GstV4l2Object * v4l2object )
{
GST_LOG_OBJECT ( v4l2object - > element , " flush stop poll " ) ;
gst_poll_set_flushing ( v4l2object - > poll , FALSE ) ;
2011-07-15 09:27:18 +00:00
2011-07-12 17:29:35 +00:00
return TRUE ;
2009-08-04 07:14:20 +00:00
}
gboolean
2011-07-13 14:33:58 +00:00
gst_v4l2_object_stop ( GstV4l2Object * v4l2object )
2009-08-04 07:14:20 +00:00
{
2011-07-13 14:33:58 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " stopping " ) ;
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
goto done ;
if ( ! GST_V4L2_IS_ACTIVE ( v4l2object ) )
goto done ;
if ( v4l2object - > pool ) {
2011-07-15 09:27:18 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " deactivating pool " ) ;
2011-07-27 14:46:46 +00:00
gst_buffer_pool_set_active ( GST_BUFFER_POOL_CAST ( v4l2object - > pool ) , FALSE ) ;
2011-07-15 09:27:18 +00:00
gst_object_unref ( v4l2object - > pool ) ;
2011-07-13 14:33:58 +00:00
v4l2object - > pool = NULL ;
}
GST_V4L2_SET_INACTIVE ( v4l2object ) ;
done :
2011-07-12 17:13:45 +00:00
return TRUE ;
2011-07-13 16:32:00 +00:00
}
2011-07-18 16:54:49 +00:00
#if 0
2011-07-13 16:32:00 +00:00
static GstFlowReturn
2011-07-14 14:21:36 +00:00
gst_v4l2_object_get_mmap ( GstV4l2Object * v4l2object , GstBuffer * * buf )
2011-07-13 16:32:00 +00:00
{
2011-07-15 09:27:18 +00:00
GstFlowReturn res ;
2011-07-13 16:32:00 +00:00
# define NUM_TRIALS 50
2011-07-15 09:27:18 +00:00
GstBufferPool * pool ;
2011-07-13 16:32:00 +00:00
gint32 trials = NUM_TRIALS ;
GstBuffer * pool_buffer ;
gboolean need_copy ;
pool = v4l2object - > pool ;
if ( ! pool )
goto no_buffer_pool ;
GST_DEBUG_OBJECT ( v4l2object - > element , " grab frame " ) ;
for ( ; ; ) {
2011-07-18 16:54:49 +00:00
if ( ( res = gst_v4l2_object_poll ( v4l2object ) ) ! = GST_FLOW_OK )
goto poll_error ;
2011-07-13 16:32:00 +00:00
2011-07-15 09:27:18 +00:00
res = gst_buffer_pool_acquire_buffer ( pool , & pool_buffer , NULL ) ;
if ( res ! = GST_FLOW_OK )
2011-07-14 14:21:36 +00:00
goto no_buffer ;
if ( v4l2object - > size > 0 ) {
gsize size = gst_buffer_get_size ( pool_buffer ) ;
/* if size does not match what we expected, try again */
if ( size ! = v4l2object - > size ) {
GST_ELEMENT_WARNING ( v4l2object - > element , RESOURCE , READ ,
( _ ( " Got unexpected frame size of %u instead of %u. " ) ,
size , v4l2object - > size ) , ( NULL ) ) ;
gst_buffer_unref ( pool_buffer ) ;
goto no_buffer ;
}
}
/* when we get here all is fine */
break ;
2011-07-13 16:32:00 +00:00
2011-07-14 14:21:36 +00:00
no_buffer :
2011-07-13 16:32:00 +00:00
GST_WARNING_OBJECT ( v4l2object - > element , " trials=%d " , trials ) ;
/* if the sync() got interrupted, we can retry */
switch ( errno ) {
case EINVAL :
case ENOMEM :
/* fatal */
return GST_FLOW_ERROR ;
case EAGAIN :
case EIO :
case EINTR :
default :
/* try again, until too many trials */
break ;
}
/* check nr. of attempts to capture */
if ( - - trials = = - 1 ) {
goto too_many_trials ;
}
}
2011-07-14 14:21:36 +00:00
2011-07-13 16:32:00 +00:00
/* if we are handing out the last buffer in the pool, we need to make a
* copy and bring the buffer back in the pool . */
need_copy = v4l2object - > always_copy
| | ! gst_v4l2_buffer_pool_available_buffers ( pool ) ;
if ( G_UNLIKELY ( need_copy ) ) {
if ( ! v4l2object - > always_copy ) {
GST_CAT_LOG_OBJECT ( GST_CAT_PERFORMANCE , v4l2object - > element ,
" running out of buffers, making a copy to reuse current one " ) ;
}
* buf = gst_buffer_copy ( pool_buffer ) ;
/* this will requeue */
gst_buffer_unref ( pool_buffer ) ;
} else {
* buf = pool_buffer ;
}
return GST_FLOW_OK ;
/* ERRORS */
no_buffer_pool :
{
GST_DEBUG_OBJECT ( v4l2object - > element , " no buffer pool " ) ;
2012-02-08 15:34:00 +00:00
return GST_FLOW_FLUSHING ;
2011-07-13 16:32:00 +00:00
}
2011-07-18 16:54:49 +00:00
poll_error :
2011-07-13 16:32:00 +00:00
{
2011-07-18 16:54:49 +00:00
return res ;
2011-07-13 16:32:00 +00:00
}
too_many_trials :
{
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , FAILED ,
( _ ( " Failed trying to get video frames from device '%s'. " ) ,
v4l2object - > videodev ) ,
( _ ( " Failed after %d tries. device %s. system error: %s " ) ,
NUM_TRIALS , v4l2object - > videodev , g_strerror ( errno ) ) ) ;
return GST_FLOW_ERROR ;
}
}
2011-07-18 16:54:49 +00:00
# endif
2011-07-13 16:32:00 +00:00
2011-07-18 16:54:49 +00:00
gboolean
gst_v4l2_object_copy ( GstV4l2Object * v4l2object , GstBuffer * dest ,
GstBuffer * src )
2011-07-13 16:32:00 +00:00
{
2011-07-18 16:54:49 +00:00
if ( v4l2object - > info . finfo ) {
GstVideoFrame src_frame , dest_frame ;
GST_DEBUG_OBJECT ( v4l2object - > element , " copy video frame " ) ;
/* we have raw video, use videoframe copy to get strides right */
if ( ! gst_video_frame_map ( & src_frame , & v4l2object - > info , src , GST_MAP_READ ) )
goto invalid_buffer ;
if ( ! gst_video_frame_map ( & dest_frame , & v4l2object - > info , dest ,
GST_MAP_WRITE ) ) {
gst_video_frame_unmap ( & src_frame ) ;
goto invalid_buffer ;
}
gst_video_frame_copy ( & dest_frame , & src_frame ) ;
gst_video_frame_unmap ( & src_frame ) ;
gst_video_frame_unmap ( & dest_frame ) ;
} else {
2012-01-24 13:38:58 +00:00
GstMapInfo map ;
2011-07-18 16:54:49 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " copy raw bytes " ) ;
2012-01-24 13:38:58 +00:00
gst_buffer_map ( src , & map , GST_MAP_READ ) ;
gst_buffer_fill ( dest , 0 , map . data , map . size ) ;
gst_buffer_unmap ( src , & map ) ;
2011-07-18 16:54:49 +00:00
}
GST_CAT_LOG_OBJECT ( GST_CAT_PERFORMANCE , v4l2object - > element ,
" slow copy into buffer %p " , dest ) ;
return TRUE ;
/* ERRORS */
invalid_buffer :
{
/* No Window available to put our image into */
GST_WARNING_OBJECT ( v4l2object - > element , " could not map image " ) ;
return FALSE ;
2011-07-13 16:32:00 +00:00
}
}