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
2012-11-04 00:07:18 +00:00
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 ,
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"
# 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>
2009-08-04 07:14:20 +00:00
GST_DEBUG_CATEGORY_EXTERN ( v4l2_debug ) ;
# define GST_CAT_DEFAULT v4l2_debug
2013-05-29 19:57:09 +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
2013-12-12 17:18:45 +00:00
# define ENCODED_BUFFER_SIZE (1 * 1024 * 1024)
2006-05-18 19:34:47 +00:00
enum
{
PROP_0 ,
V4L2_STD_OBJECT_PROPS ,
} ;
2014-03-13 17:21:41 +00:00
/*
* common format / caps utilities :
*/
typedef enum
{
GST_V4L2_RAW = 1 < < 0 ,
GST_V4L2_CODEC = 1 < < 1 ,
GST_V4L2_TRANSPORT = 1 < < 2 ,
GST_V4L2_NO_PARSE = 1 < < 3 ,
GST_V4L2_ALL = 0xffff
} GstV4L2FormatFlags ;
typedef struct
{
guint32 format ;
gboolean dimensions ;
GstV4L2FormatFlags flags ;
} GstV4L2FormatDesc ;
static const GstV4L2FormatDesc gst_v4l2_formats [ ] = {
/* from Linux 2.6.15 videodev2.h */
{ V4L2_PIX_FMT_RGB332 , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_RGB555 , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_RGB565 , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_RGB555X , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_RGB565X , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_BGR24 , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_RGB24 , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_BGR32 , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_RGB32 , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_GREY , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_YVU410 , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_YVU420 , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_YUYV , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_UYVY , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_YUV422P , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_YUV411P , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_Y41P , TRUE , GST_V4L2_RAW } ,
/* two planes -- one Y, one Cr + Cb interleaved */
{ V4L2_PIX_FMT_NV12 , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_NV12M , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_NV12MT , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_NV21 , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_NV21M , TRUE , GST_V4L2_RAW } ,
/* The following formats are not defined in the V4L2 specification */
{ V4L2_PIX_FMT_YUV410 , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_YUV420 , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_YYUV , TRUE , GST_V4L2_RAW } ,
{ V4L2_PIX_FMT_HI240 , TRUE , GST_V4L2_RAW } ,
/* see http://www.siliconimaging.com/RGB%20Bayer.htm */
{ V4L2_PIX_FMT_SBGGR8 , TRUE , GST_V4L2_CODEC } ,
/* compressed formats */
{ V4L2_PIX_FMT_MJPEG , FALSE , GST_V4L2_CODEC } ,
{ V4L2_PIX_FMT_JPEG , FALSE , GST_V4L2_CODEC } ,
{ V4L2_PIX_FMT_PJPG , FALSE , GST_V4L2_CODEC } ,
{ V4L2_PIX_FMT_DV , FALSE , GST_V4L2_TRANSPORT } ,
{ V4L2_PIX_FMT_MPEG , FALSE , GST_V4L2_TRANSPORT } ,
{ V4L2_PIX_FMT_MPEG1 , FALSE , GST_V4L2_CODEC } ,
{ V4L2_PIX_FMT_MPEG2 , FALSE , GST_V4L2_CODEC } ,
{ V4L2_PIX_FMT_MPEG4 , FALSE , GST_V4L2_CODEC } ,
{ V4L2_PIX_FMT_H263 , FALSE , GST_V4L2_CODEC } ,
{ V4L2_PIX_FMT_H264 , FALSE , GST_V4L2_CODEC } ,
/* VP8 not parseable */
{ V4L2_PIX_FMT_VP8 , FALSE , GST_V4L2_CODEC | GST_V4L2_NO_PARSE } ,
/* Vendor-specific formats */
{ V4L2_PIX_FMT_WNVA , TRUE , GST_V4L2_CODEC } ,
{ V4L2_PIX_FMT_SN9C10X , TRUE , GST_V4L2_CODEC } ,
{ V4L2_PIX_FMT_PWC1 , TRUE , GST_V4L2_CODEC } ,
{ V4L2_PIX_FMT_PWC2 , TRUE , GST_V4L2_CODEC } ,
{ V4L2_PIX_FMT_YVYU , TRUE , GST_V4L2_RAW } ,
} ;
# define GST_V4L2_FORMAT_COUNT (G_N_ELEMENTS (gst_v4l2_formats))
2013-08-19 17:19:42 +00:00
static GSList * gst_v4l2_object_get_format_list ( GstV4l2Object * v4l2object ) ;
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 ;
}
2013-11-28 21:59:59 +00:00
GType
2011-07-18 16:54:49 +00:00
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 " } ,
2013-02-19 10:47:20 +00:00
{ GST_V4L2_IO_DMABUF , " GST_V4L2_IO_DMABUF " , " dmabuf " } ,
2014-04-14 16:19:39 +00:00
{ GST_V4L2_IO_DMABUF_IMPORT , " GST_V4L2_IO_DMABUF_IMPORT " ,
" dmabuf-import " } ,
2011-07-18 16:54:49 +00:00
{ 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
/**
2013-11-18 14:44:36 +00:00
* GstV4l2Src : brightness :
2010-09-15 16:02:57 +00:00
*
* Picture brightness , or more precisely , the black level
*/
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
/**
2013-11-18 14:44:36 +00:00
* GstV4l2Src : contrast :
2010-09-15 16:02:57 +00:00
*
* Picture contrast or luma gain
*/
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
/**
2013-11-18 14:44:36 +00:00
* GstV4l2Src : saturation :
2010-09-15 16:02:57 +00:00
*
* Picture color saturation or chroma gain
*/
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
/**
2013-11-18 14:44:36 +00:00
* GstV4l2Src : hue :
2010-09-15 16:02:57 +00:00
*
* Hue or color balance
*/
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
/**
2013-11-18 14:44:36 +00:00
* GstV4l2Src : norm :
2010-04-04 11:43:41 +00:00
*
* TV norm
*/
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
/**
2013-11-18 14:44:36 +00:00
* GstV4l2Src : io - mode :
2011-07-18 16:54:49 +00:00
*
* 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 ) ) ;
2013-05-20 14:45:37 +00:00
/**
2013-11-18 14:44:36 +00:00
* GstV4l2Src : extra - controls :
2013-05-20 14:45:37 +00:00
*
* Additional v4l2 controls for the device . The controls are identified
* by the control name ( lowercase with ' _ ' for any non - alphanumeric
* characters ) .
*
* Since : 1.2
*/
g_object_class_install_property ( gobject_class , PROP_EXTRA_CONTROLS ,
g_param_spec_boxed ( " extra-controls " , " Extra Controls " ,
" Extra v4l2 controls (CIDs) for the device " ,
GST_TYPE_STRUCTURE , G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ) ) ;
2013-06-04 06:26:33 +00:00
/**
2013-11-18 14:44:36 +00:00
* GstV4l2Src : pixel - aspect - ratio :
2013-06-04 06:26:33 +00:00
*
* The pixel aspect ratio of the device . This overwrites the pixel aspect
* ratio queried from the device .
*
* Since : 1.2
*/
g_object_class_install_property ( gobject_class , PROP_PIXEL_ASPECT_RATIO ,
g_param_spec_string ( " pixel-aspect-ratio " , " Pixel Aspect Ratio " ,
" Overwrite the pixel aspect ratio of the device " , " 1/1 " ,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ) ) ;
/**
2013-11-18 14:44:36 +00:00
* GstV4l2Src : force - aspect - ratio :
2013-06-04 06:26:33 +00:00
*
* When enabled , the pixel aspect ratio queried from the device or set
* with the pixel - aspect - ratio property will be enforced .
*
* Since : 1.2
*/
g_object_class_install_property ( gobject_class , PROP_FORCE_ASPECT_RATIO ,
g_param_spec_boolean ( " force-aspect-ratio " , " Force aspect ratio " ,
" When enabled, the pixel aspect ratio will be enforced " , TRUE ,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ) ) ;
2006-05-11 17:59:59 +00:00
}
2014-05-15 22:08:53 +00:00
void
gst_v4l2_object_install_m2m_properties_helper ( GObjectClass * gobject_class )
{
g_object_class_install_property ( gobject_class , PROP_DEVICE ,
g_param_spec_string ( " device " , " Device " , " Device location " ,
NULL , G_PARAM_READABLE | G_PARAM_STATIC_STRINGS ) ) ;
g_object_class_install_property ( gobject_class , PROP_DEVICE_NAME ,
g_param_spec_string ( " device-name " , " Device name " ,
" Name of the device " , DEFAULT_PROP_DEVICE_NAME ,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS ) ) ;
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 ,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS ) ) ;
g_object_class_install_property ( gobject_class , PROP_OUTPUT_IO_MODE ,
g_param_spec_enum ( " output-io-mode " , " Output IO mode " ,
" Output side I/O mode (matches sink pad) " ,
GST_TYPE_V4L2_IO_MODE , DEFAULT_PROP_IO_MODE ,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ) ) ;
g_object_class_install_property ( gobject_class , PROP_CAPTURE_IO_MODE ,
g_param_spec_enum ( " capture-io-mode " , " Capture IO mode " ,
" Capture I/O mode (matches src pad) " ,
GST_TYPE_V4L2_IO_MODE , DEFAULT_PROP_IO_MODE ,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ) ) ;
g_object_class_install_property ( gobject_class , PROP_EXTRA_CONTROLS ,
g_param_spec_boxed ( " extra-controls " , " Extra Controls " ,
" Extra v4l2 controls (CIDs) for the device " ,
GST_TYPE_STRUCTURE , 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 ;
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 ;
2013-06-04 06:26:33 +00:00
v4l2object - > keep_aspect = TRUE ;
2013-11-13 12:05:40 +00:00
v4l2object - > n_v4l2_planes = 0 ;
2013-11-28 22:10:29 +00:00
v4l2object - > no_initial_format = FALSE ;
2006-05-11 17:59:59 +00:00
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 ) ;
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 ) ;
}
2012-10-22 21:58:07 +00:00
if ( v4l2object - > probed_caps ) {
gst_caps_unref ( v4l2object - > probed_caps ) ;
}
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
2014-05-15 22:08:53 +00:00
2011-07-18 16:54:49 +00:00
case PROP_IO_MODE :
v4l2object - > req_mode = g_value_get_enum ( value ) ;
break ;
2014-05-15 22:08:53 +00:00
case PROP_CAPTURE_IO_MODE :
g_return_val_if_fail ( ! V4L2_TYPE_IS_OUTPUT ( v4l2object - > type ) , FALSE ) ;
v4l2object - > req_mode = g_value_get_enum ( value ) ;
break ;
case PROP_OUTPUT_IO_MODE :
g_return_val_if_fail ( V4L2_TYPE_IS_OUTPUT ( v4l2object - > type ) , FALSE ) ;
v4l2object - > req_mode = g_value_get_enum ( value ) ;
break ;
2013-05-20 14:45:37 +00:00
case PROP_EXTRA_CONTROLS : {
const GstStructure * s = gst_value_get_structure ( value ) ;
if ( v4l2object - > extra_controls )
gst_structure_free ( v4l2object - > extra_controls ) ;
v4l2object - > extra_controls = s ? gst_structure_copy ( s ) : NULL ;
if ( GST_V4L2_IS_OPEN ( v4l2object ) )
gst_v4l2_set_controls ( v4l2object , v4l2object - > extra_controls ) ;
break ;
}
2013-06-04 06:26:33 +00:00
case PROP_PIXEL_ASPECT_RATIO :
g_free ( v4l2object - > par ) ;
v4l2object - > par = g_new0 ( GValue , 1 ) ;
g_value_init ( v4l2object - > par , GST_TYPE_FRACTION ) ;
if ( ! g_value_transform ( value , v4l2object - > par ) ) {
g_warning ( " Could not transform string to aspect ratio " ) ;
gst_value_set_fraction ( v4l2object - > par , 1 , 1 ) ;
}
GST_DEBUG_OBJECT ( v4l2object - > element , " set PAR to %d/%d " ,
gst_value_get_fraction_numerator ( v4l2object - > par ) ,
gst_value_get_fraction_denominator ( v4l2object - > par ) ) ;
break ;
case PROP_FORCE_ASPECT_RATIO :
v4l2object - > keep_aspect = g_value_get_boolean ( 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 ) ;
2013-11-13 12:05:40 +00:00
if ( v4l2object - > vcap . capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE )
flags | = V4L2_CAP_VIDEO_CAPTURE ;
if ( v4l2object - > vcap . capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE )
flags | = V4L2_CAP_VIDEO_OUTPUT ;
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 ;
2014-05-15 22:08:53 +00:00
case PROP_CAPTURE_IO_MODE :
g_return_val_if_fail ( ! V4L2_TYPE_IS_OUTPUT ( v4l2object - > type ) , FALSE ) ;
g_value_set_enum ( value , v4l2object - > req_mode ) ;
break ;
case PROP_OUTPUT_IO_MODE :
g_return_val_if_fail ( V4L2_TYPE_IS_OUTPUT ( v4l2object - > type ) , FALSE ) ;
g_value_set_enum ( value , v4l2object - > req_mode ) ;
break ;
2013-05-20 14:45:37 +00:00
case PROP_EXTRA_CONTROLS :
gst_value_set_structure ( value , v4l2object - > extra_controls ) ;
break ;
2013-06-04 06:26:33 +00:00
case PROP_PIXEL_ASPECT_RATIO :
if ( v4l2object - > par )
g_value_transform ( v4l2object - > par , value ) ;
break ;
case PROP_FORCE_ASPECT_RATIO :
g_value_set_boolean ( value , v4l2object - > keep_aspect ) ;
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 ;
return TRUE ;
}
2013-11-28 22:09:26 +00:00
gboolean
gst_v4l2_object_open_shared ( GstV4l2Object * v4l2object , GstV4l2Object * other )
{
gboolean ret ;
ret = gst_v4l2_dup ( v4l2object , other ) ;
return ret ;
}
2006-05-11 17:59:59 +00:00
gboolean
2011-07-13 14:33:58 +00:00
gst_v4l2_object_close ( GstV4l2Object * v4l2object )
2006-05-11 17:59:59 +00:00
{
if ( ! gst_v4l2_close ( v4l2object ) )
return FALSE ;
2013-11-18 13:27:48 +00:00
gst_caps_replace ( & v4l2object - > probed_caps , NULL ) ;
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
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 | |
2014-03-15 10:13:05 +00:00
fmt - > pixelformat = = V4L2_PIX_FMT_JPEG | |
fmt - > pixelformat = = V4L2_PIX_FMT_PJPG ) {
if ( fourcc = = V4L2_PIX_FMT_JPEG | | fourcc = = V4L2_PIX_FMT_MJPEG | |
fourcc = = V4L2_PIX_FMT_PJPG ) {
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
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-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 ;
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 */
2013-11-13 12:05:40 +00:00
case V4L2_PIX_FMT_NV12M : /* Same as NV12 */
2013-12-10 19:29:55 +00:00
case V4L2_PIX_FMT_NV12MT : /* NV12 64x32 tile */
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_NV21 : /* 12 Y/CrCb 4:2:0 */
2013-11-13 12:05:40 +00:00
case V4L2_PIX_FMT_NV21M : /* Same as NV21 */
2009-08-04 07:14:20 +00:00
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
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
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
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
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
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
2013-11-13 12:05:40 +00:00
gst_v4l2_object_fill_format_list ( GstV4l2Object * v4l2object ,
enum v4l2_buf_type type )
2009-08-04 07:14:20 +00:00
{
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 ;
2013-11-13 12:05:40 +00:00
format - > type = type ;
2009-08-04 07:14:20 +00:00
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
/*
2013-11-13 12:05:40 +00:00
* Get the list of supported capture formats , a list of
* < code > struct v4l2_fmtdesc < / code > .
*/
2012-10-22 21:58:07 +00:00
static GSList *
2009-08-04 07:14:20 +00:00
gst_v4l2_object_get_format_list ( GstV4l2Object * v4l2object )
{
2013-11-13 12:05:40 +00:00
if ( ! v4l2object - > formats ) {
/* check usual way */
gst_v4l2_object_fill_format_list ( v4l2object , v4l2object - > type ) ;
/* if our driver supports multi-planar
* and if formats are still empty then we can workaround driver bug
* by also looking up formats as if our device was not supporting
* multiplanar */
if ( ! v4l2object - > formats ) {
switch ( v4l2object - > type ) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
gst_v4l2_object_fill_format_list ( v4l2object ,
V4L2_BUF_TYPE_VIDEO_CAPTURE ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
gst_v4l2_object_fill_format_list ( v4l2object ,
V4L2_BUF_TYPE_VIDEO_OUTPUT ) ;
break ;
default :
break ;
}
}
}
2009-08-04 07:14:20 +00:00
return v4l2object - > formats ;
}
2013-12-03 23:27:47 +00:00
static GstVideoFormat
gst_v4l2_object_v4l2fourcc_to_video_format ( guint32 fourcc )
{
GstVideoFormat format ;
switch ( fourcc ) {
case V4L2_PIX_FMT_GREY : /* 8 Greyscale */
format = GST_VIDEO_FORMAT_GRAY8 ;
break ;
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 :
2014-03-07 22:31:29 +00:00
format = GST_VIDEO_FORMAT_xRGB ;
2013-12-03 23:27:47 +00:00
break ;
case V4L2_PIX_FMT_BGR32 :
format = GST_VIDEO_FORMAT_BGRx ;
break ;
case V4L2_PIX_FMT_NV12 :
case V4L2_PIX_FMT_NV12M :
format = GST_VIDEO_FORMAT_NV12 ;
break ;
2013-12-10 19:29:55 +00:00
case V4L2_PIX_FMT_NV12MT :
format = GST_VIDEO_FORMAT_NV12_64Z32 ;
break ;
2013-12-03 23:27:47 +00:00
case V4L2_PIX_FMT_NV21 :
case V4L2_PIX_FMT_NV21M :
format = GST_VIDEO_FORMAT_NV21 ;
break ;
case V4L2_PIX_FMT_YVU410 :
format = GST_VIDEO_FORMAT_YVU9 ;
break ;
case V4L2_PIX_FMT_YUV410 :
format = GST_VIDEO_FORMAT_YUV9 ;
break ;
case V4L2_PIX_FMT_YUV420 :
format = GST_VIDEO_FORMAT_I420 ;
break ;
case V4L2_PIX_FMT_YUYV :
format = GST_VIDEO_FORMAT_YUY2 ;
break ;
case V4L2_PIX_FMT_YVU420 :
format = GST_VIDEO_FORMAT_YV12 ;
break ;
case V4L2_PIX_FMT_UYVY :
format = GST_VIDEO_FORMAT_UYVY ;
break ;
#if 0
case V4L2_PIX_FMT_Y41P :
format = GST_VIDEO_FORMAT_Y41P ;
break ;
# endif
case V4L2_PIX_FMT_YUV411P :
format = GST_VIDEO_FORMAT_Y41B ;
break ;
case V4L2_PIX_FMT_YUV422P :
format = GST_VIDEO_FORMAT_Y42B ;
break ;
case V4L2_PIX_FMT_YVYU :
format = GST_VIDEO_FORMAT_YVYU ;
break ;
default :
format = GST_VIDEO_FORMAT_UNKNOWN ;
break ;
}
return format ;
}
2009-08-04 07:14:20 +00:00
2014-05-03 01:38:30 +00:00
static GstStructure *
gst_v4l2_object_v4l2fourcc_to_bare_struct ( guint32 fourcc )
2009-08-04 07:14:20 +00:00
{
GstStructure * structure = NULL ;
switch ( fourcc ) {
case V4L2_PIX_FMT_MJPEG : /* Motion-JPEG */
2011-02-15 18:59:32 +00:00
case V4L2_PIX_FMT_PJPG : /* Progressive-JPEG */
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 ;
2013-12-12 19:22:26 +00:00
case V4L2_PIX_FMT_MPEG1 :
structure = gst_structure_new ( " video/mpeg " ,
" mpegversion " , G_TYPE_INT , 2 , NULL ) ;
break ;
case V4L2_PIX_FMT_MPEG2 :
structure = gst_structure_new ( " video/mpeg " ,
" mpegversion " , G_TYPE_INT , 2 , NULL ) ;
break ;
2012-07-10 13:29:40 +00:00
case V4L2_PIX_FMT_MPEG4 :
structure = gst_structure_new ( " video/mpeg " ,
" mpegversion " , G_TYPE_INT , 4 , " systemstream " ,
G_TYPE_BOOLEAN , FALSE , NULL ) ;
break ;
case V4L2_PIX_FMT_H263 :
structure = gst_structure_new ( " video/x-h263 " ,
" variant " , G_TYPE_STRING , " itu " , NULL ) ;
break ;
2012-04-16 22:08:21 +00:00
case V4L2_PIX_FMT_H264 : /* H.264 */
2013-06-05 03:34:04 +00:00
structure = gst_structure_new ( " video/x-h264 " ,
" stream-format " , G_TYPE_STRING , " byte-stream " , " alignment " ,
G_TYPE_STRING , " au " , NULL ) ;
2012-04-16 22:08:21 +00:00
break ;
2013-12-16 22:29:30 +00:00
case V4L2_PIX_FMT_VP8 :
structure = gst_structure_new_empty ( " video/x-vp8 " ) ;
break ;
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 */
2013-11-13 12:05:40 +00:00
case V4L2_PIX_FMT_NV12M :
2013-12-10 19:29:55 +00:00
case V4L2_PIX_FMT_NV12MT :
2009-08-04 07:14:20 +00:00
case V4L2_PIX_FMT_NV21 : /* 12 Y/CrCb 4:2:0 */
2013-11-13 12:05:40 +00:00
case V4L2_PIX_FMT_NV21M :
2009-08-04 07:14:20 +00:00
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 :
case V4L2_PIX_FMT_YVYU :
case V4L2_PIX_FMT_YUV411P : {
2011-07-08 12:34:40 +00:00
GstVideoFormat format ;
2013-12-03 23:27:47 +00:00
format = gst_v4l2_object_v4l2fourcc_to_video_format ( fourcc ) ;
2013-11-13 12:05:40 +00:00
if ( format ! = GST_VIDEO_FORMAT_UNKNOWN )
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 */
2014-03-29 21:21:17 +00:00
structure = gst_structure_new ( " video/mpegts " ,
" systemstream " , G_TYPE_BOOLEAN , TRUE , NULL ) ;
2009-08-04 07:14:20 +00:00
break ;
case V4L2_PIX_FMT_WNVA : /* Winnov hw compres */
break ;
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 ;
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 ;
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 ;
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 ;
default :
GST_DEBUG ( " Unknown fourcc 0x%08x % " GST_FOURCC_FORMAT ,
fourcc , GST_FOURCC_ARGS ( fourcc ) ) ;
break ;
}
return structure ;
}
2014-05-03 01:38:30 +00:00
GstStructure *
gst_v4l2_object_v4l2fourcc_to_structure ( guint32 fourcc )
{
GstStructure * template ;
gint i ;
template = gst_v4l2_object_v4l2fourcc_to_bare_struct ( fourcc ) ;
if ( template = = NULL )
goto done ;
for ( i = 0 ; i < GST_V4L2_FORMAT_COUNT ; i + + ) {
if ( gst_v4l2_formats [ i ] . format ! = fourcc )
continue ;
if ( gst_v4l2_formats [ i ] . dimensions ) {
gst_structure_set ( template ,
" 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 ) ;
}
break ;
}
done :
return template ;
}
2009-08-04 07:14:20 +00:00
2013-12-06 19:44:51 +00:00
static GstCaps *
gst_v4l2_object_get_caps_helper ( GstV4L2FormatFlags flags )
{
GstStructure * structure ;
GstCaps * caps ;
guint i ;
caps = gst_caps_new_empty ( ) ;
for ( i = 0 ; i < GST_V4L2_FORMAT_COUNT ; i + + ) {
if ( ( gst_v4l2_formats [ i ] . flags & flags ) = = 0 )
continue ;
structure =
2014-05-03 01:38:30 +00:00
gst_v4l2_object_v4l2fourcc_to_bare_struct ( gst_v4l2_formats [ i ] . format ) ;
2014-03-19 21:00:56 +00:00
2013-12-06 19:44:51 +00:00
if ( structure ) {
2014-03-19 21:00:56 +00:00
GstStructure * alt_s = NULL ;
2013-12-06 19:44: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 ) ;
}
2014-03-19 21:00:56 +00:00
switch ( gst_v4l2_formats [ i ] . format ) {
case V4L2_PIX_FMT_RGB32 :
alt_s = gst_structure_copy ( structure ) ;
gst_structure_set ( alt_s , " format " , G_TYPE_STRING , " ARGB " , NULL ) ;
break ;
case V4L2_PIX_FMT_BGR32 :
alt_s = gst_structure_copy ( structure ) ;
gst_structure_set ( alt_s , " format " , G_TYPE_STRING , " BGRA " , NULL ) ;
default :
break ;
}
2013-12-06 19:44:51 +00:00
gst_caps_append_structure ( caps , structure ) ;
2014-03-19 21:00:56 +00:00
if ( alt_s )
gst_caps_append_structure ( caps , alt_s ) ;
2013-12-06 19:44:51 +00:00
}
}
return gst_caps_simplify ( caps ) ;
}
2009-08-04 07:14:20 +00:00
GstCaps *
gst_v4l2_object_get_all_caps ( void )
{
static GstCaps * caps = NULL ;
2013-12-06 19:44:51 +00:00
if ( caps = = NULL )
caps = gst_v4l2_object_get_caps_helper ( GST_V4L2_ALL ) ;
2009-08-04 07:14:20 +00:00
2013-12-06 19:44:51 +00:00
return gst_caps_ref ( caps ) ;
}
2009-08-04 07:14:20 +00:00
2013-12-06 19:44:51 +00:00
GstCaps *
gst_v4l2_object_get_raw_caps ( void )
{
static GstCaps * caps = NULL ;
if ( caps = = NULL )
caps = gst_v4l2_object_get_caps_helper ( GST_V4L2_RAW ) ;
2009-08-04 07:14:20 +00:00
return gst_caps_ref ( caps ) ;
}
2013-12-06 19:44:51 +00:00
GstCaps *
gst_v4l2_object_get_codec_caps ( void )
{
static GstCaps * caps = NULL ;
if ( caps = = NULL )
caps = gst_v4l2_object_get_caps_helper ( GST_V4L2_CODEC ) ;
return gst_caps_ref ( caps ) ;
}
2009-08-04 07:14:20 +00:00
/* 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 ;
2014-03-07 21:39:29 +00:00
guint32 fourcc = 0 , fourcc_nc = 0 ;
2009-08-04 07:14:20 +00:00
const gchar * mimetype ;
2014-03-07 21:39:29 +00:00
struct v4l2_fmtdesc * fmt = NULL ;
2009-08-04 07:14:20 +00:00
structure = gst_caps_get_structure ( caps , 0 ) ;
2009-09-07 16:28:51 +00:00
mimetype = gst_structure_get_name ( structure ) ;
2013-05-03 10:46:37 +00:00
if ( ! gst_video_info_from_caps ( info , caps ) )
goto invalid_format ;
2009-08-04 07:14:20 +00:00
2013-05-03 10:46:37 +00:00
if ( g_str_equal ( mimetype , " video/x-raw " ) ) {
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 :
2014-03-07 21:39:29 +00:00
fourcc = V4L2_PIX_FMT_NV12 ;
fourcc_nc = V4L2_PIX_FMT_NV12M ;
2009-08-04 07:14:20 +00:00
break ;
2013-12-10 19:29:55 +00:00
case GST_VIDEO_FORMAT_NV12_64Z32 :
2014-03-07 21:39:29 +00:00
fourcc_nc = V4L2_PIX_FMT_NV12MT ;
2013-12-10 19:29:55 +00:00
break ;
2011-07-08 12:34:40 +00:00
case GST_VIDEO_FORMAT_NV21 :
2014-03-07 21:39:29 +00:00
fourcc = V4L2_PIX_FMT_NV21 ;
fourcc_nc = V4L2_PIX_FMT_NV21M ;
2009-08-04 07:14:20 +00:00
break ;
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 ;
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 ;
2014-03-07 22:31:29 +00:00
case GST_VIDEO_FORMAT_xRGB :
case GST_VIDEO_FORMAT_ARGB :
2011-07-08 12:34:40 +00:00
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 {
if ( g_str_equal ( mimetype , " video/mpegts " ) ) {
fourcc = V4L2_PIX_FMT_MPEG ;
} 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-07-10 13:29:40 +00:00
} else if ( g_str_equal ( mimetype , " video/mpeg " ) ) {
2013-12-12 19:22:26 +00:00
gint version ;
if ( gst_structure_get_int ( structure , " mpegversion " , & version ) ) {
switch ( version ) {
case 1 :
fourcc = V4L2_PIX_FMT_MPEG1 ;
break ;
case 2 :
fourcc = V4L2_PIX_FMT_MPEG2 ;
break ;
case 4 :
fourcc = V4L2_PIX_FMT_MPEG4 ;
break ;
default :
break ;
}
}
2012-07-10 13:29:40 +00:00
} else if ( g_str_equal ( mimetype , " video/x-h263 " ) ) {
fourcc = V4L2_PIX_FMT_H263 ;
2012-04-16 22:08:21 +00:00
} else if ( g_str_equal ( mimetype , " video/x-h264 " ) ) {
fourcc = V4L2_PIX_FMT_H264 ;
2013-12-16 22:29:30 +00:00
} else if ( g_str_equal ( mimetype , " video/x-vp8 " ) ) {
fourcc = V4L2_PIX_FMT_VP8 ;
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 ;
} else if ( g_str_equal ( mimetype , " video/x-sonix " ) ) {
fourcc = V4L2_PIX_FMT_SN9C10X ;
} else if ( g_str_equal ( mimetype , " video/x-pwc1 " ) ) {
fourcc = V4L2_PIX_FMT_PWC1 ;
} else if ( g_str_equal ( mimetype , " video/x-pwc2 " ) ) {
fourcc = V4L2_PIX_FMT_PWC2 ;
}
}
2009-08-04 07:14:20 +00:00
2014-03-07 21:39:29 +00:00
/* Prefer the non-contiguous if supported */
v4l2object - > prefered_non_contiguous = TRUE ;
if ( fourcc_nc )
fmt = gst_v4l2_object_get_format_from_fourcc ( v4l2object , fourcc_nc ) ;
else if ( fourcc = = 0 )
goto unhandled_format ;
2013-12-04 20:09:10 +00:00
2014-03-07 21:39:29 +00:00
if ( fmt = = NULL ) {
fmt = gst_v4l2_object_get_format_from_fourcc ( v4l2object , fourcc ) ;
v4l2object - > prefered_non_contiguous = FALSE ;
2013-12-04 20:09:10 +00:00
}
2011-07-19 17:20:43 +00:00
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 */
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 ) ;
2013-06-04 06:26:33 +00:00
static void
gst_v4l2_object_add_aspect_ratio ( GstV4l2Object * v4l2object , GstStructure * s )
{
struct v4l2_cropcap cropcap ;
int num = 1 , den = 1 ;
if ( ! v4l2object - > keep_aspect )
return ;
if ( v4l2object - > par ) {
num = gst_value_get_fraction_numerator ( v4l2object - > par ) ;
den = gst_value_get_fraction_denominator ( v4l2object - > par ) ;
goto done ;
}
memset ( & cropcap , 0 , sizeof ( cropcap ) ) ;
cropcap . type = v4l2object - > type ;
if ( v4l2_ioctl ( v4l2object - > video_fd , VIDIOC_CROPCAP , & cropcap ) < 0 )
goto cropcap_failed ;
num = cropcap . pixelaspect . numerator ;
den = cropcap . pixelaspect . denominator ;
2014-03-04 23:31:27 +00:00
/* Ignore PAR that are 0/0 */
if ( den = = 0 )
return ;
2013-06-04 06:26:33 +00:00
done :
gst_structure_set ( s , " pixel-aspect-ratio " , GST_TYPE_FRACTION , num , den ,
NULL ) ;
return ;
cropcap_failed :
if ( errno ! = ENOTTY )
GST_WARNING_OBJECT ( v4l2object - > element ,
" Failed to probe pixel aspect ratio with VIDIOC_CROPCAP: %s " ,
g_strerror ( errno ) ) ;
goto done ;
}
2014-05-12 16:20:14 +00:00
/* returns TRUE if the value was changed in place, otherwise FALSE */
static gboolean
gst_v4l2src_value_simplify ( GValue * val )
{
/* simplify list of one value to one value */
if ( GST_VALUE_HOLDS_LIST ( val ) & & gst_value_list_get_size ( val ) = = 1 ) {
const GValue * list_val ;
GValue new_val = G_VALUE_INIT ;
list_val = gst_value_list_get_value ( val , 0 ) ;
g_value_init ( & new_val , G_VALUE_TYPE ( list_val ) ) ;
g_value_copy ( list_val , & new_val ) ;
g_value_unset ( val ) ;
* val = new_val ;
return TRUE ;
}
return FALSE ;
}
2009-08-04 07:14:20 +00:00
/* The frame interval enumeration code first appeared in Linux 2.6.19. */
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 ;
2013-06-05 03:42:24 +00:00
if ( v4l2object - > never_interlaced ) {
2012-08-08 10:31:59 +00:00
interlaced = FALSE ;
2012-06-08 18:38:34 +00:00
} else {
/* 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 ,
2013-06-04 06:26:33 +00:00
" height " , G_TYPE_INT , ( gint ) height , NULL ) ;
gst_v4l2_object_add_aspect_ratio ( v4l2object , s ) ;
2013-05-14 08:52:19 +00:00
if ( g_str_equal ( gst_structure_get_name ( s ) , " video/x-raw " ) )
gst_structure_set ( s , " interlace-mode " , G_TYPE_STRING ,
( interlaced ? " mixed " : " progressive " ) , NULL ) ;
2009-08-04 07:14:20 +00:00
if ( G_IS_VALUE ( & rates ) ) {
2014-05-12 16:20:14 +00:00
gst_v4l2src_value_simplify ( & rates ) ;
2009-08-04 07:14:20 +00:00
/* only change the framerate on the template when we have a valid probed new
* value */
2014-05-12 16:23:19 +00:00
gst_structure_take_value ( s , " framerate " , & rates ) ;
2013-12-12 21:46:09 +00:00
} else if ( v4l2object - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE | |
v4l2object - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) {
2009-08-04 07:14:20 +00:00
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 ;
}
}
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 ) ) ;
}
2014-01-10 17:40:31 +00:00
static void
gst_v4l2_object_update_and_append ( GstV4l2Object * v4l2object ,
guint32 format , GstCaps * caps , GstStructure * s )
{
2014-03-19 21:00:56 +00:00
GstStructure * alt_s = NULL ;
2014-01-10 17:40:31 +00:00
/* Encoded stream on output buffer need to be parsed */
if ( v4l2object - > type = = V4L2_BUF_TYPE_VIDEO_OUTPUT | |
v4l2object - > type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ) {
gint i = 0 ;
for ( ; i < GST_V4L2_FORMAT_COUNT ; i + + ) {
if ( format = = gst_v4l2_formats [ i ] . format & &
2014-02-25 21:10:54 +00:00
gst_v4l2_formats [ i ] . flags & GST_V4L2_CODEC & &
! ( gst_v4l2_formats [ i ] . flags & GST_V4L2_NO_PARSE ) ) {
2014-01-10 17:40:31 +00:00
gst_structure_set ( s , " parsed " , G_TYPE_BOOLEAN , TRUE , NULL ) ;
break ;
}
}
}
2014-03-19 21:00:56 +00:00
if ( v4l2object - > has_alpha_component & &
( v4l2object - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE | |
v4l2object - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) ) {
switch ( format ) {
case V4L2_PIX_FMT_RGB32 :
alt_s = gst_structure_copy ( s ) ;
gst_structure_set ( alt_s , " format " , G_TYPE_STRING , " ARGB " , NULL ) ;
break ;
case V4L2_PIX_FMT_BGR32 :
alt_s = gst_structure_copy ( s ) ;
gst_structure_set ( alt_s , " format " , G_TYPE_STRING , " BGRA " , NULL ) ;
break ;
default :
break ;
}
}
2014-01-10 17:40:31 +00:00
gst_caps_append_structure ( caps , s ) ;
2014-03-19 21:00:56 +00:00
if ( alt_s )
gst_caps_append_structure ( caps , alt_s ) ;
2014-01-10 17:40:31 +00:00
}
2012-10-22 21:58:07 +00:00
static GstCaps *
2009-08-04 07:14:20 +00:00
gst_v4l2_object_probe_caps_for_format ( GstV4l2Object * v4l2object ,
guint32 pixelformat , const GstStructure * template )
{
GstCaps * ret = gst_caps_new_empty ( ) ;
GstStructure * tmp ;
gint fd = v4l2object - > video_fd ;
struct v4l2_frmsizeenum size ;
GList * results = NULL ;
guint32 w , h ;
2014-01-10 17:39:16 +00:00
if ( pixelformat = = GST_MAKE_FOURCC ( ' M ' , ' P ' , ' E ' , ' G ' ) ) {
gst_caps_append_structure ( ret , gst_structure_copy ( template ) ) ;
return ret ;
}
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 ;
2013-11-13 10:42:21 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element ,
" Enumerating frame sizes for % " GST_FOURCC_FORMAT ,
GST_FOURCC_ARGS ( pixelformat ) ) ;
2009-08-04 07:14:20 +00:00
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 */
2014-01-10 17:40:31 +00:00
gst_v4l2_object_update_and_append ( v4l2object , pixelformat , ret , tmp ) ;
2009-08-04 07:14:20 +00:00
}
} 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 ) {
2014-01-10 17:40:31 +00:00
gst_v4l2_object_update_and_append ( v4l2object , pixelformat , ret ,
results - > data ) ;
2009-08-04 07:14:20 +00:00
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 ;
}
2014-03-15 10:13:05 +00:00
2009-08-04 07:14:20 +00:00
default_frame_sizes :
{
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 ) ;
2013-12-12 21:46:09 +00:00
} else if ( v4l2object - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE | |
v4l2object - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) {
2009-08-04 07:14:20 +00:00
/* 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 ) ;
2013-05-14 08:52:19 +00:00
if ( g_str_equal ( gst_structure_get_name ( tmp ) , " video/x-raw " ) )
gst_structure_set ( tmp , " interlace-mode " , G_TYPE_STRING ,
( interlaced ? " mixed " : " progressive " ) , NULL ) ;
2013-06-04 06:26:33 +00:00
gst_v4l2_object_add_aspect_ratio ( v4l2object , tmp ) ;
2010-11-04 17:36:09 +00:00
2014-01-10 17:40:31 +00:00
gst_v4l2_object_update_and_append ( v4l2object , pixelformat , ret , tmp ) ;
2009-08-04 07:14:20 +00:00
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 ;
2013-11-28 22:10:29 +00:00
int prevfmt_valid = FALSE ;
2013-12-31 12:31:52 +00:00
gboolean ret = FALSE ;
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 ;
2013-12-03 23:27:47 +00:00
memset ( & fmt , 0 , sizeof ( struct v4l2_format ) ) ;
memset ( & prevfmt , 0 , sizeof ( struct v4l2_format ) ) ;
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 . */
2013-11-28 22:10:29 +00:00
if ( ! v4l2object - > no_initial_format ) {
prevfmt . type = v4l2object - > type ;
prevfmt_valid = ( v4l2_ioctl ( fd , VIDIOC_G_FMT , & prevfmt ) > = 0 ) ;
}
2011-08-08 09:54:26 +00:00
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
}
2013-12-31 12:31:52 +00:00
ret = TRUE ;
2011-08-08 09:54:26 +00:00
error :
2013-12-31 12:31:52 +00:00
if ( ! ret ) {
GST_WARNING_OBJECT ( v4l2object - > element ,
" Unable to try format: %s " , g_strerror ( errno ) ) ;
}
2011-08-08 09:54:26 +00:00
if ( prevfmt_valid )
2013-12-31 12:31:52 +00:00
if ( v4l2_ioctl ( fd , VIDIOC_S_FMT , & prevfmt ) < 0 ) {
GST_WARNING_OBJECT ( v4l2object - > element ,
" Unable to restore format after trying format: %s " ,
g_strerror ( errno ) ) ;
}
return ret ;
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 ;
}
}
2014-03-25 14:49:39 +00:00
static void
2014-05-06 16:58:59 +00:00
gst_v4l2_object_set_stride ( GstVideoInfo * info , GstVideoAlignment * align ,
gint plane , gint stride )
2014-03-25 14:49:39 +00:00
{
2014-05-06 16:58:59 +00:00
const GstVideoFormatInfo * finfo = info - > finfo ;
if ( GST_VIDEO_FORMAT_INFO_IS_TILED ( finfo ) ) {
gint x_tiles , y_tiles , ws , hs , tile_height , padded_height ;
ws = GST_VIDEO_FORMAT_INFO_TILE_WS ( finfo ) ;
hs = GST_VIDEO_FORMAT_INFO_TILE_HS ( finfo ) ;
tile_height = 1 < < hs ;
padded_height = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT ( finfo , plane ,
info - > height + align - > padding_top + align - > padding_bottom ) ;
padded_height = GST_ROUND_UP_N ( padded_height , tile_height ) ;
x_tiles = stride > > ws ;
y_tiles = padded_height > > hs ;
info - > stride [ plane ] = GST_VIDEO_TILE_MAKE_STRIDE ( x_tiles , y_tiles ) ;
} else {
info - > stride [ plane ] = stride ;
}
}
static void
gst_v4l2_object_extrapolate_info ( GstV4l2Object * v4l2object ,
GstVideoInfo * info , GstVideoAlignment * align , gint stride )
{
const GstVideoFormatInfo * finfo = info - > finfo ;
gint i , estride , padded_height ;
gsize offs = 0 ;
2014-03-25 14:49:39 +00:00
g_return_if_fail ( v4l2object - > n_v4l2_planes = = 1 ) ;
2014-05-06 16:58:59 +00:00
padded_height = info - > height + align - > padding_top + align - > padding_bottom ;
2014-03-25 14:49:39 +00:00
for ( i = 0 ; i < finfo - > n_planes ; i + + ) {
switch ( finfo - > format ) {
case GST_VIDEO_FORMAT_NV12 :
2014-05-06 16:58:59 +00:00
case GST_VIDEO_FORMAT_NV12_64Z32 :
2014-03-25 14:49:39 +00:00
case GST_VIDEO_FORMAT_NV21 :
case GST_VIDEO_FORMAT_NV16 :
case GST_VIDEO_FORMAT_NV24 :
2014-05-06 16:58:59 +00:00
estride = ( i = = 0 ? 1 : 2 ) *
2014-03-25 14:49:39 +00:00
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH ( finfo , i , stride ) ;
break ;
default :
2014-05-06 16:58:59 +00:00
estride = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH ( finfo , i , stride ) ;
2014-03-25 14:49:39 +00:00
break ;
}
2014-05-06 16:58:59 +00:00
gst_v4l2_object_set_stride ( info , align , i , estride ) ;
info - > offset [ i ] = offs ;
2014-05-13 17:44:20 +00:00
offs + = estride *
2014-05-06 16:58:59 +00:00
GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT ( finfo , i , padded_height ) ;
2014-03-25 14:49:39 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element ,
2014-05-06 16:58:59 +00:00
" Extrapolated for plane %d with base stride %d: "
" stride %d, offset % " G_GSIZE_FORMAT , i , stride , info - > stride [ i ] ,
info - > offset [ i ] ) ;
2014-03-25 14:49:39 +00:00
}
}
2013-12-10 19:34:17 +00:00
static void
gst_v4l2_object_save_format ( GstV4l2Object * v4l2object ,
struct v4l2_fmtdesc * fmtdesc , struct v4l2_format * format ,
2014-04-15 19:07:23 +00:00
GstVideoInfo * info , GstVideoAlignment * align )
2013-12-10 19:34:17 +00:00
{
const GstVideoFormatInfo * finfo = info - > finfo ;
2014-05-06 16:58:59 +00:00
gboolean standard_stride = TRUE ;
gint stride , padded_width , padded_height , i ;
if ( GST_VIDEO_INFO_FORMAT ( info ) = = GST_VIDEO_FORMAT_ENCODED ) {
v4l2object - > n_v4l2_planes = 1 ;
info - > size = format - > fmt . pix . sizeimage ;
goto store_info ;
}
/* adjust right padding */
if ( V4L2_TYPE_IS_MULTIPLANAR ( v4l2object - > type ) )
stride = format - > fmt . pix_mp . plane_fmt [ 0 ] . bytesperline ;
else
stride = format - > fmt . pix . bytesperline ;
padded_width = stride / GST_VIDEO_FORMAT_INFO_PSTRIDE ( finfo , 0 ) ;
if ( padded_width < format - > fmt . pix . width )
GST_WARNING_OBJECT ( v4l2object - > element ,
" Driver bug detected, stride is too small for the width " ) ;
align - > padding_right = padded_width - info - > width - align - > padding_left ;
/* adjust bottom padding */
padded_height = format - > fmt . pix . height ;
if ( GST_VIDEO_FORMAT_INFO_IS_TILED ( finfo ) ) {
guint hs , tile_height ;
hs = GST_VIDEO_FORMAT_INFO_TILE_HS ( finfo ) ;
tile_height = 1 < < hs ;
2013-12-10 19:34:17 +00:00
2014-05-06 16:58:59 +00:00
padded_height = GST_ROUND_UP_N ( padded_height , tile_height ) ;
}
align - > padding_bottom = padded_height - info - > height - align - > padding_top ;
/* setup the strides and offset */
2013-12-10 19:34:17 +00:00
if ( V4L2_TYPE_IS_MULTIPLANAR ( v4l2object - > type ) ) {
2014-05-06 16:58:59 +00:00
struct v4l2_pix_format_mplane * pix_mp = & format - > fmt . pix_mp ;
2013-12-10 19:34:17 +00:00
/* figure out the frame layout */
2014-05-06 16:58:59 +00:00
v4l2object - > n_v4l2_planes = MAX ( 1 , pix_mp - > num_planes ) ;
info - > size = 0 ;
2014-04-08 22:17:31 +00:00
for ( i = 0 ; i < v4l2object - > n_v4l2_planes ; i + + ) {
2014-05-06 16:58:59 +00:00
stride = pix_mp - > plane_fmt [ i ] . bytesperline ;
if ( info - > stride [ i ] ! = stride )
standard_stride = FALSE ;
gst_v4l2_object_set_stride ( info , align , i , stride ) ;
info - > offset [ i ] = info - > size ;
info - > size + = pix_mp - > plane_fmt [ i ] . sizeimage ;
2013-12-10 19:34:17 +00:00
}
2014-03-25 14:49:39 +00:00
/* Extrapolate stride if planar format are being set in 1 v4l2 plane */
if ( v4l2object - > n_v4l2_planes < finfo - > n_planes ) {
stride = format - > fmt . pix_mp . plane_fmt [ 0 ] . bytesperline ;
2014-05-06 16:58:59 +00:00
gst_v4l2_object_extrapolate_info ( v4l2object , info , align , stride ) ;
2014-03-25 14:49:39 +00:00
}
2013-12-10 19:34:17 +00:00
} else {
/* only one plane in non-MPLANE mode */
v4l2object - > n_v4l2_planes = 1 ;
2014-05-06 16:58:59 +00:00
info - > size = format - > fmt . pix . sizeimage ;
2014-03-25 14:49:39 +00:00
stride = format - > fmt . pix . bytesperline ;
2013-12-10 19:34:17 +00:00
2014-05-06 16:58:59 +00:00
if ( info - > stride [ 0 ] ! = stride )
standard_stride = FALSE ;
2013-12-10 19:34:17 +00:00
2014-05-06 16:58:59 +00:00
gst_v4l2_object_extrapolate_info ( v4l2object , info , align , stride ) ;
}
2014-04-15 19:07:23 +00:00
2014-05-06 16:58:59 +00:00
/* adjust the offset to take into account left and top */
if ( GST_VIDEO_FORMAT_INFO_IS_TILED ( finfo ) ) {
if ( ( align - > padding_left + align - > padding_top ) > 0 )
GST_WARNING_OBJECT ( v4l2object - > element ,
" Left and top padding is not permitted for tiled formats " ) ;
} else {
for ( i = 0 ; i < finfo - > n_planes ; i + + ) {
gint vedge , hedge ;
2014-04-15 19:07:23 +00:00
2014-05-06 16:58:59 +00:00
/* FIXME we assume plane as component as this is true for all supported
* format we support . */
2014-03-18 19:49:49 +00:00
2014-05-06 16:58:59 +00:00
hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH ( finfo , i , align - > padding_left ) ;
vedge = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT ( finfo , i , align - > padding_top ) ;
2014-03-18 19:49:49 +00:00
2014-05-06 16:58:59 +00:00
info - > offset [ i ] + = ( vedge * info - > stride [ i ] ) +
( hedge * GST_VIDEO_INFO_COMP_PSTRIDE ( info , i ) ) ;
}
2014-03-18 19:49:49 +00:00
}
2014-04-15 19:07:23 +00:00
2014-05-06 16:58:59 +00:00
store_info :
GST_DEBUG_OBJECT ( v4l2object - > element , " Got sizeimage % " G_GSIZE_FORMAT ,
info - > size ) ;
/* to avoid copies we need video meta if top or left padding */
v4l2object - > need_video_meta =
( ( align - > padding_top + align - > padding_left ) ! = 0 ) ;
/* ... or if stride is non "standard" */
if ( ! standard_stride )
v4l2object - > need_video_meta = TRUE ;
2014-04-15 19:07:23 +00:00
/* ... or also video meta if we use multiple, non-contiguous, planes */
if ( v4l2object - > n_v4l2_planes > 1 )
v4l2object - > need_video_meta = TRUE ;
2013-12-10 19:34:17 +00:00
v4l2object - > info = * info ;
2014-04-15 19:07:23 +00:00
v4l2object - > align = * align ;
2014-03-27 22:41:07 +00:00
v4l2object - > format = * format ;
2013-12-10 19:34:17 +00:00
v4l2object - > fmtdesc = fmtdesc ;
/* if we have a framerate pre-calculate duration */
if ( info - > fps_n > 0 & & info - > fps_d > 0 ) {
v4l2object - > duration = gst_util_uint64_scale_int ( GST_SECOND , info - > fps_d ,
info - > fps_n ) ;
} else {
v4l2object - > duration = GST_CLOCK_TIME_NONE ;
}
}
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 ;
2014-04-15 19:07:23 +00:00
GstVideoAlignment align ;
2013-12-04 21:23:18 +00:00
gint width , height , fps_n , fps_d ;
2014-04-15 19:07:23 +00:00
gint n_v4l_planes ;
2013-11-13 12:05:40 +00:00
gint i = 0 ;
2014-04-15 19:07:23 +00:00
gboolean is_mplane , format_changed ;
2013-11-13 12:05:40 +00:00
2013-12-04 20:09:44 +00:00
GST_V4L2_CHECK_OPEN ( v4l2object ) ;
GST_V4L2_CHECK_NOT_ACTIVE ( v4l2object ) ;
2014-04-15 19:07:23 +00:00
is_mplane = V4L2_TYPE_IS_MULTIPLANAR ( v4l2object - > type ) ;
gst_video_info_init ( & info ) ;
gst_video_alignment_reset ( & align ) ;
2013-12-04 20:09:10 +00:00
if ( ! gst_v4l2_object_get_caps_info ( v4l2object , caps , & fmtdesc , & info ) )
goto invalid_caps ;
2011-07-12 18:03:32 +00:00
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 ) ;
2010-12-04 19:43:11 +00:00
2014-04-15 19:07:23 +00:00
/* if encoded format (GST_VIDEO_INFO_N_PLANES return 0)
* or if contiguous is prefered */
n_v4l_planes = GST_VIDEO_INFO_N_PLANES ( & info ) ;
if ( ! n_v4l_planes | | ! v4l2object - > prefered_non_contiguous )
n_v4l_planes = 1 ;
2013-11-13 12:05:40 +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 ,
2014-04-15 19:07:23 +00:00
GST_FOURCC_ARGS ( pixelformat ) , GST_VIDEO_INFO_PLANE_STRIDE ( & info , 0 ) ) ;
2009-08-04 07:14:20 +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
2014-04-15 19:07:23 +00:00
if ( v4l2object - > no_initial_format ) {
format_changed = TRUE ;
} else {
2013-11-28 22:10:29 +00:00
if ( v4l2_ioctl ( fd , VIDIOC_G_FMT , & format ) < 0 )
goto get_fmt_failed ;
2009-08-04 07:14:20 +00:00
2014-04-15 19:07:23 +00:00
/* Note that four first fields are the same between v4l2_pix_format and
* v4l2_pix_format_mplane , so we don ' t need to duplicate he checks */
2013-11-13 12:05:40 +00:00
2014-03-29 23:13:06 +00:00
/* If no size in caps, use configured size */
if ( width = = 0 & & height = = 0 ) {
width = format . fmt . pix_mp . width ;
height = format . fmt . pix_mp . height ;
}
2014-04-15 19:07:23 +00:00
format_changed = format . type ! = v4l2object - > type | |
2013-11-13 12:05:40 +00:00
format . fmt . pix_mp . width ! = width | |
format . fmt . pix_mp . height ! = height | |
format . fmt . pix_mp . pixelformat ! = pixelformat | |
2014-04-15 19:07:23 +00:00
format . fmt . pix_mp . field ! = field ;
}
2011-07-13 09:19:28 +00:00
2013-11-13 12:05:40 +00:00
# ifndef GST_DISABLE_GST_DEBUG
2014-04-15 19:07:23 +00:00
if ( is_mplane ) {
GST_DEBUG_OBJECT ( v4l2object - > element , " Current size is %dx%d, format "
" % " GST_FOURCC_FORMAT " colorspace %d, nb planes %d " ,
format . fmt . pix_mp . width , format . fmt . pix_mp . height ,
GST_FOURCC_ARGS ( format . fmt . pix . pixelformat ) ,
format . fmt . pix_mp . colorspace , format . fmt . pix_mp . num_planes ) ;
2013-11-13 12:05:40 +00:00
2014-04-15 19:07:23 +00:00
for ( i = 0 ; i < format . fmt . pix_mp . num_planes ; i + + )
GST_DEBUG_OBJECT ( v4l2object - > element , " stride %d " ,
format . fmt . pix_mp . plane_fmt [ i ] . bytesperline ) ;
2013-11-13 12:05:40 +00:00
} else {
2014-04-15 19:07:23 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " Current size is %dx%d, format "
" % " GST_FOURCC_FORMAT " stride %d, colorspace %d " ,
2013-11-13 12:05:40 +00:00
format . fmt . pix . width , format . fmt . pix . height ,
GST_FOURCC_ARGS ( format . fmt . pix . pixelformat ) ,
format . fmt . pix . bytesperline , format . fmt . pix . colorspace ) ;
2014-04-15 19:07:23 +00:00
}
# endif
2013-11-13 12:05:40 +00:00
2014-04-15 19:07:23 +00:00
/* If nothing changed, we are done */
if ( ! format_changed )
goto done ;
2014-03-29 23:13:06 +00:00
2014-04-15 19:07:23 +00:00
/* something different, set the format */
GST_DEBUG_OBJECT ( v4l2object - > element , " Setting format to %dx%d, format "
" % " GST_FOURCC_FORMAT , width , height , GST_FOURCC_ARGS ( pixelformat ) ) ;
if ( is_mplane ) {
format . type = v4l2object - > type ;
format . fmt . pix_mp . pixelformat = pixelformat ;
format . fmt . pix_mp . width = width ;
format . fmt . pix_mp . height = height ;
format . fmt . pix_mp . field = field ;
format . fmt . pix_mp . num_planes = n_v4l_planes ;
2014-03-18 19:45:18 +00:00
/* try to ask our prefered stride but it's not a failure if not
* accepted */
for ( i = 0 ; i < n_v4l_planes ; i + + ) {
gint stride = GST_VIDEO_INFO_PLANE_STRIDE ( & info , i ) ;
if ( GST_VIDEO_FORMAT_INFO_IS_TILED ( info . finfo ) )
stride = GST_VIDEO_TILE_X_TILES ( stride ) < <
GST_VIDEO_FORMAT_INFO_TILE_WS ( info . finfo ) ;
format . fmt . pix_mp . plane_fmt [ i ] . bytesperline = stride ;
}
2014-04-15 19:07:23 +00:00
if ( GST_VIDEO_INFO_FORMAT ( & info ) = = GST_VIDEO_FORMAT_ENCODED )
format . fmt . pix_mp . plane_fmt [ 0 ] . sizeimage = ENCODED_BUFFER_SIZE ;
} else {
2014-03-18 19:45:18 +00:00
gint stride = GST_VIDEO_INFO_PLANE_STRIDE ( & info , 0 ) ;
2014-04-15 19:07:23 +00:00
format . type = v4l2object - > type ;
format . fmt . pix . width = width ;
format . fmt . pix . height = height ;
format . fmt . pix . pixelformat = pixelformat ;
format . fmt . pix . field = field ;
2014-03-18 19:45:18 +00:00
if ( GST_VIDEO_FORMAT_INFO_IS_TILED ( info . finfo ) )
stride = GST_VIDEO_TILE_X_TILES ( stride ) < <
GST_VIDEO_FORMAT_INFO_TILE_WS ( info . finfo ) ;
2014-04-15 19:07:23 +00:00
/* try to ask our prefered stride */
2014-03-18 19:45:18 +00:00
format . fmt . pix . bytesperline = stride ;
2013-12-12 17:18:45 +00:00
2014-04-15 19:07:23 +00:00
if ( GST_VIDEO_INFO_FORMAT ( & info ) = = GST_VIDEO_FORMAT_ENCODED )
format . fmt . pix . sizeimage = ENCODED_BUFFER_SIZE ;
}
2013-11-13 12:05:40 +00:00
2014-03-18 19:45:18 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " Desired format is %dx%d, format "
" % " GST_FOURCC_FORMAT " , nb planes %d " , format . fmt . pix . width ,
format . fmt . pix_mp . height ,
GST_FOURCC_ARGS ( format . fmt . pix . pixelformat ) ,
is_mplane ? format . fmt . pix_mp . num_planes : 1 ) ;
# ifndef GST_DISABLE_GST_DEBUG
if ( is_mplane ) {
for ( i = 0 ; i < format . fmt . pix_mp . num_planes ; i + + )
GST_DEBUG_OBJECT ( v4l2object - > element , " stride %d " ,
format . fmt . pix_mp . plane_fmt [ i ] . bytesperline ) ;
} else {
GST_DEBUG_OBJECT ( v4l2object - > element , " stride %d " ,
format . fmt . pix . bytesperline ) ;
}
# endif
2014-04-15 19:07:23 +00:00
if ( v4l2_ioctl ( fd , VIDIOC_S_FMT , & format ) < 0 )
goto set_fmt_failed ;
2013-11-13 12:05:40 +00:00
2014-03-18 19:45:18 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " Got format of %dx%d, format "
2014-04-15 19:07:23 +00:00
" % " GST_FOURCC_FORMAT " , nb planes %d " , format . fmt . pix . width ,
format . fmt . pix_mp . height ,
GST_FOURCC_ARGS ( format . fmt . pix . pixelformat ) ,
is_mplane ? format . fmt . pix_mp . num_planes : 1 ) ;
2013-11-13 12:05:40 +00:00
2014-04-15 19:07:23 +00:00
# ifndef GST_DISABLE_GST_DEBUG
if ( is_mplane ) {
for ( i = 0 ; i < format . fmt . pix_mp . num_planes ; i + + )
2014-03-18 19:45:18 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " stride %d, sizeimage %d " ,
format . fmt . pix_mp . plane_fmt [ i ] . bytesperline ,
format . fmt . pix_mp . plane_fmt [ i ] . sizeimage ) ;
} else {
GST_DEBUG_OBJECT ( v4l2object - > element , " stride %d, sizeimage %d " ,
format . fmt . pix . bytesperline , format . fmt . pix . sizeimage ) ;
2013-11-13 12:05:40 +00:00
}
2014-04-15 19:07:23 +00:00
# endif
if ( format . fmt . pix . pixelformat ! = pixelformat )
goto invalid_pixelformat ;
/* Only negotiate size with raw data.
* For some codecs the dimensions are * not * in the bitstream , IIRC VC1
* in ASF mode for example , there is also not reason for a driver to
* change the size . */
if ( info . finfo - > format ! = GST_VIDEO_FORMAT_ENCODED ) {
/* We can crop larger images */
if ( format . fmt . pix . width < width | | format . fmt . pix . height < height )
goto invalid_dimensions ;
/* Note, this will be adjusted if upstream has non-centered cropping. */
align . padding_top = 0 ;
align . padding_bottom = format . fmt . pix . height - height ;
align . padding_left = 0 ;
align . padding_right = format . fmt . pix . width - width ;
}
if ( is_mplane & & format . fmt . pix_mp . num_planes ! = n_v4l_planes )
goto invalid_planes ;
2011-07-26 14:15:05 +00:00
2014-03-19 21:00:56 +00:00
if ( GST_VIDEO_INFO_HAS_ALPHA ( & info ) ) {
struct v4l2_control ctl = { 0 , } ;
ctl . id = V4L2_CID_ALPHA_COMPONENT ;
ctl . value = 0xff ;
if ( v4l2_ioctl ( fd , VIDIOC_S_CTRL , & ctl ) < 0 )
GST_WARNING_OBJECT ( v4l2object - > element ,
" Failed to set alpha component value " ) ;
}
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 ;
2013-11-13 12:05:40 +00:00
if ( v4l2object - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE
| | v4l2object - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) {
2011-07-13 09:29:26 +00:00
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 :
2014-05-06 16:58:59 +00:00
/* add boolean return, so we can fail on drivers bugs */
2014-04-15 19:07:23 +00:00
gst_v4l2_object_save_format ( v4l2object , fmtdesc , & format , & info , & align ) ;
2009-08-04 07:14:20 +00:00
2014-04-15 19:07:23 +00:00
/* now configure the pool */
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 ;
}
2013-11-13 12:05:40 +00:00
invalid_planes :
{
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS ,
( _ ( " Device '%s' does support non-contiguous planes " ) ,
v4l2object - > videodev ) ,
( " Device wants %d planes " , format . fmt . pix_mp . num_planes ) ) ;
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 */
2012-07-05 16:02:27 +00:00
if ( errno ! = EINVAL & & errno ! = ENOTTY ) {
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 :
{
2014-04-08 22:18:57 +00:00
/* setup_pool already send the error */
2011-07-13 14:33:58 +00:00
return FALSE ;
}
2009-08-04 07:14:20 +00:00
}
2013-12-05 18:51:13 +00:00
/**
2014-03-13 18:24:51 +00:00
* gst_v4l2_object_acquire_format :
2013-12-05 18:51:13 +00:00
* @ v4l2object the object
* @ info a GstVideoInfo to be filled
*
2014-03-13 18:24:51 +00:00
* Acquire the driver choosen format . This is useful in decoder or encoder elements where
* the output format is choosen by the HW .
2013-12-05 18:51:13 +00:00
*
* Returns : % TRUE on success , % FALSE on failure .
*/
gboolean
2014-04-15 19:07:23 +00:00
gst_v4l2_object_acquire_format ( GstV4l2Object * v4l2object , GstVideoInfo * info )
2013-12-05 18:51:13 +00:00
{
struct v4l2_fmtdesc * fmtdesc ;
struct v4l2_format fmt ;
struct v4l2_crop crop ;
GstVideoFormat format ;
guint width , height ;
2014-04-15 19:07:23 +00:00
GstVideoAlignment align ;
2013-12-05 18:51:13 +00:00
gst_video_info_init ( info ) ;
2014-04-15 19:07:23 +00:00
gst_video_alignment_reset ( & align ) ;
2013-12-05 18:51:13 +00:00
memset ( & fmt , 0x00 , sizeof ( struct v4l2_format ) ) ;
fmt . type = v4l2object - > type ;
if ( v4l2_ioctl ( v4l2object - > video_fd , VIDIOC_G_FMT , & fmt ) < 0 )
goto get_fmt_failed ;
fmtdesc = gst_v4l2_object_get_format_from_fourcc ( v4l2object ,
fmt . fmt . pix . pixelformat ) ;
if ( fmtdesc = = NULL )
goto unsupported_format ;
/* No need to care about mplane, the four first params are the same */
format = gst_v4l2_object_v4l2fourcc_to_video_format ( fmt . fmt . pix . pixelformat ) ;
2013-12-31 16:38:09 +00:00
/* fails if we do no translate the fmt.pix.pixelformat to GstVideoFormat */
if ( format = = GST_VIDEO_FORMAT_UNKNOWN )
goto unsupported_format ;
if ( fmt . fmt . pix . width = = 0 | | fmt . fmt . pix . height = = 0 )
goto invalid_dimensions ;
2013-12-05 18:51:13 +00:00
width = fmt . fmt . pix . width ;
height = fmt . fmt . pix . height ;
memset ( & crop , 0 , sizeof ( struct v4l2_crop ) ) ;
crop . type = v4l2object - > type ;
if ( v4l2_ioctl ( v4l2object - > video_fd , VIDIOC_G_CROP , & crop ) > = 0 ) {
2014-04-15 19:07:23 +00:00
align . padding_left = crop . c . left ;
align . padding_top = crop . c . top ;
align . padding_right = width - crop . c . width - crop . c . left ;
align . padding_bottom = height - crop . c . height - crop . c . top ;
2013-12-05 18:51:13 +00:00
width = crop . c . width ;
height = crop . c . height ;
}
gst_video_info_set_format ( info , format , width , height ) ;
switch ( fmt . fmt . pix . field ) {
case V4L2_FIELD_ANY :
case V4L2_FIELD_NONE :
info - > interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE ;
break ;
case V4L2_FIELD_INTERLACED :
case V4L2_FIELD_INTERLACED_TB :
case V4L2_FIELD_INTERLACED_BT :
info - > interlace_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED ;
break ;
default :
goto unsupported_field ;
}
2014-04-15 19:07:23 +00:00
gst_v4l2_object_save_format ( v4l2object , fmtdesc , & fmt , info , & align ) ;
2013-12-05 18:51:13 +00:00
/* Shall we setup the pool ? */
return TRUE ;
get_fmt_failed :
{
GST_ELEMENT_WARNING ( v4l2object - > element , RESOURCE , SETTINGS ,
( _ ( " Video device did not provide output format. " ) ) , GST_ERROR_SYSTEM ) ;
return FALSE ;
}
2013-12-07 15:31:15 +00:00
invalid_dimensions :
{
GST_ELEMENT_WARNING ( v4l2object - > element , RESOURCE , SETTINGS ,
( _ ( " Video device returned invalid dimensions. " ) ) ,
( " Expected non 0 dimensions, got %dx%d " , fmt . fmt . pix . width ,
fmt . fmt . pix . height ) ) ;
return FALSE ;
}
2013-12-05 18:51:13 +00:00
unsupported_field :
{
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS ,
( _ ( " Video devices uses an unsupported interlacing method. " ) ) ,
( " V4L2 field type %d not supported " , fmt . fmt . pix . field ) ) ;
return FALSE ;
}
unsupported_format :
{
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS ,
( _ ( " Video devices uses an unsupported pixel format. " ) ) ,
( " V4L2 format % " GST_FOURCC_FORMAT " not supported " ,
GST_FOURCC_ARGS ( fmt . fmt . pix . pixelformat ) ) ) ;
return FALSE ;
}
}
2014-03-20 19:31:22 +00:00
gboolean
gst_v4l2_object_set_crop ( GstV4l2Object * obj )
{
struct v4l2_crop crop = { 0 } ;
crop . type = obj - > type ;
crop . c . left = obj - > align . padding_left ;
crop . c . top = obj - > align . padding_top ;
crop . c . width = obj - > info . width ;
crop . c . height = obj - > info . height ;
if ( obj - > align . padding_left + obj - > align . padding_top +
obj - > align . padding_right + obj - > align . padding_bottom = = 0 ) {
GST_DEBUG_OBJECT ( obj - > element , " no cropping needed " ) ;
return TRUE ;
}
GST_DEBUG_OBJECT ( obj - > element ,
" Desired cropping left %u, top %u, size %ux%u " , crop . c . left , crop . c . top ,
crop . c . width , crop . c . height ) ;
if ( v4l2_ioctl ( obj - > video_fd , VIDIOC_S_CROP , & crop ) < 0 ) {
GST_WARNING_OBJECT ( obj - > element , " VIDIOC_S_CROP failed " ) ;
return FALSE ;
}
GST_DEBUG_OBJECT ( obj - > element ,
" Got cropping left %u, top %u, size %ux%u " , crop . c . left , crop . c . top ,
crop . c . width , crop . c . height ) ;
return TRUE ;
}
2013-05-17 08:16:48 +00:00
gboolean
gst_v4l2_object_caps_equal ( GstV4l2Object * v4l2object , GstCaps * caps )
{
2014-05-09 16:10:04 +00:00
GstStructure * config ;
2013-05-17 08:16:48 +00:00
GstCaps * oldcaps ;
2014-05-09 16:10:04 +00:00
gboolean ret ;
2013-05-17 08:16:48 +00:00
if ( ! v4l2object - > pool )
return FALSE ;
2014-05-09 16:10:04 +00:00
config = gst_buffer_pool_get_config ( v4l2object - > pool ) ;
gst_buffer_pool_config_get_params ( config , & oldcaps , NULL , NULL , NULL ) ;
ret = oldcaps & & gst_caps_is_equal ( caps , oldcaps ) ;
2013-05-17 08:16:48 +00:00
2014-05-09 16:10:04 +00:00
gst_structure_free ( config ) ;
return ret ;
2013-05-17 08:16:48 +00:00
}
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
{
2014-05-23 18:12:10 +00:00
gboolean ret = TRUE ;
2011-07-13 14:33:58 +00:00
2014-05-23 18:12:10 +00:00
GST_LOG_OBJECT ( v4l2object - > element , " start flushing " ) ;
if ( v4l2object - > pool & & gst_buffer_pool_is_active ( v4l2object - > pool ) )
gst_buffer_pool_set_flushing ( v4l2object - > pool , TRUE ) ;
return ret ;
2011-07-18 16:54:49 +00:00
}
2011-07-13 14:33:58 +00:00
2011-07-18 16:54:49 +00:00
gboolean
gst_v4l2_object_unlock_stop ( GstV4l2Object * v4l2object )
{
2014-05-23 18:12:10 +00:00
gboolean ret = TRUE ;
2011-07-15 09:27:18 +00:00
2014-05-23 18:12:10 +00:00
GST_LOG_OBJECT ( v4l2object - > element , " stop flushing " ) ;
if ( v4l2object - > pool & & gst_buffer_pool_is_active ( v4l2object - > pool ) )
gst_buffer_pool_set_flushing ( v4l2object - > pool , FALSE ) ;
return ret ;
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 " ) ;
2014-05-09 16:08:11 +00:00
gst_buffer_pool_set_active ( 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
}
2012-10-22 21:58:07 +00:00
GstCaps *
gst_v4l2_object_get_caps ( GstV4l2Object * v4l2object , GstCaps * filter )
{
GstCaps * ret ;
GSList * walk ;
GSList * formats ;
if ( v4l2object - > probed_caps = = NULL ) {
formats = gst_v4l2_object_get_format_list ( v4l2object ) ;
ret = gst_caps_new_empty ( ) ;
for ( walk = formats ; walk ; walk = walk - > next ) {
struct v4l2_fmtdesc * format ;
GstStructure * template ;
format = ( struct v4l2_fmtdesc * ) walk - > data ;
2014-05-03 01:38:30 +00:00
template =
gst_v4l2_object_v4l2fourcc_to_bare_struct ( format - > pixelformat ) ;
2012-10-22 21:58:07 +00:00
if ( template ) {
GstCaps * tmp ;
tmp = gst_v4l2_object_probe_caps_for_format ( v4l2object ,
format - > pixelformat , template ) ;
if ( tmp )
gst_caps_append ( ret , tmp ) ;
gst_structure_free ( template ) ;
} else {
GST_DEBUG_OBJECT ( v4l2object - > element , " unknown format %u " ,
format - > pixelformat ) ;
}
}
v4l2object - > probed_caps = ret ;
}
if ( filter ) {
ret = gst_caps_intersect_full ( filter , v4l2object - > probed_caps ,
GST_CAPS_INTERSECT_FIRST ) ;
} else {
ret = gst_caps_ref ( v4l2object - > probed_caps ) ;
}
2013-10-03 17:33:01 +00:00
GST_INFO_OBJECT ( v4l2object - > element , " probed caps: % " GST_PTR_FORMAT , ret ) ;
2012-10-22 21:58:07 +00:00
LOG_CAPS ( v4l2object - > element , ret ) ;
return ret ;
}
2013-12-05 23:48:15 +00:00
gboolean
gst_v4l2_object_decide_allocation ( GstV4l2Object * obj , GstQuery * query )
{
2014-03-16 11:44:14 +00:00
GstCaps * caps ;
2014-05-09 15:51:26 +00:00
GstBufferPool * pool = NULL , * other_pool = NULL ;
2014-04-08 22:20:25 +00:00
GstStructure * config ;
2014-04-18 18:45:00 +00:00
guint size , min , max , own_min = 0 ;
2013-12-05 23:48:15 +00:00
gboolean update ;
2014-05-06 16:58:59 +00:00
gboolean has_video_meta ;
2014-04-11 21:10:11 +00:00
gboolean can_share_own_pool , pushing_from_our_pool = FALSE ;
2013-12-05 23:49:19 +00:00
struct v4l2_control ctl = { 0 , } ;
2013-12-05 23:48:15 +00:00
GST_DEBUG_OBJECT ( obj - > element , " decide allocation " ) ;
g_return_val_if_fail ( obj - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE | |
obj - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE , FALSE ) ;
2014-03-16 11:44:14 +00:00
gst_query_parse_allocation ( query , & caps , NULL ) ;
2013-12-05 23:48:44 +00:00
2014-03-16 11:44:14 +00:00
if ( obj - > pool = = NULL ) {
2013-12-05 23:48:44 +00:00
if ( ! gst_v4l2_object_setup_pool ( obj , caps ) )
goto pool_failed ;
}
2013-12-05 23:48:15 +00:00
if ( gst_query_get_n_allocation_pools ( query ) > 0 ) {
gst_query_parse_nth_allocation_pool ( query , 0 , & pool , & size , & min , & max ) ;
update = TRUE ;
} else {
pool = NULL ;
min = max = 0 ;
size = 0 ;
update = FALSE ;
}
GST_DEBUG_OBJECT ( obj - > element , " allocation: size:%u min:%u max:%u pool:% "
GST_PTR_FORMAT , size , min , max , pool ) ;
2014-04-15 19:07:23 +00:00
has_video_meta =
gst_query_find_allocation_meta ( query , GST_VIDEO_META_API_TYPE , NULL ) ;
2014-05-06 16:58:59 +00:00
can_share_own_pool = ( has_video_meta | | ! obj - > need_video_meta ) ;
2014-04-15 19:07:23 +00:00
2013-12-05 23:48:15 +00:00
/* select a pool */
switch ( obj - > mode ) {
case GST_V4L2_IO_RW :
2014-04-15 19:07:23 +00:00
if ( pool ) {
2013-12-05 23:48:15 +00:00
/* in READ/WRITE mode, prefer a downstream pool because our own pool
* doesn ' t help much , we have to write to it as well */
GST_DEBUG_OBJECT ( obj - > element ,
" read/write mode: using downstream pool " ) ;
/* use the bigest size, when we use our own pool we can't really do any
* other size than what the hardware gives us but for downstream pools
* we can try */
2014-05-06 16:58:59 +00:00
size = MAX ( size , obj - > info . size ) ;
2014-04-11 21:10:11 +00:00
} else if ( can_share_own_pool ) {
2014-04-15 19:07:23 +00:00
/* no downstream pool, use our own then */
GST_DEBUG_OBJECT ( obj - > element ,
" read/write mode: no downstream pool, using our own " ) ;
2014-04-16 21:04:42 +00:00
pool = gst_object_ref ( obj - > pool ) ;
2014-05-06 16:58:59 +00:00
size = obj - > info . size ;
2014-04-11 21:10:11 +00:00
pushing_from_our_pool = TRUE ;
2013-12-05 23:48:15 +00:00
}
break ;
2014-04-11 21:10:11 +00:00
2014-04-14 16:19:39 +00:00
case GST_V4L2_IO_USERPTR :
case GST_V4L2_IO_DMABUF_IMPORT :
2014-04-11 21:10:11 +00:00
/* in importing mode, prefer our own pool, and pass the other pool to
* our own , so it can serve itself */
if ( pool = = NULL )
goto no_downstream_pool ;
gst_v4l2_buffer_pool_set_other_pool ( GST_V4L2_BUFFER_POOL ( obj - > pool ) ,
pool ) ;
other_pool = pool ;
gst_object_unref ( pool ) ;
pool = gst_object_ref ( obj - > pool ) ;
2014-05-06 16:58:59 +00:00
size = obj - > info . size ;
2014-04-11 21:10:11 +00:00
break ;
case GST_V4L2_IO_MMAP :
case GST_V4L2_IO_DMABUF :
2013-12-05 23:48:15 +00:00
/* in streaming mode, prefer our own pool */
2014-04-15 19:07:23 +00:00
/* Check if we can use it ... */
2014-04-11 21:10:11 +00:00
if ( can_share_own_pool ) {
2014-04-15 19:07:23 +00:00
if ( pool )
gst_object_unref ( pool ) ;
2014-04-16 21:04:42 +00:00
pool = gst_object_ref ( obj - > pool ) ;
2014-05-06 16:58:59 +00:00
size = obj - > info . size ;
2014-04-15 19:07:23 +00:00
GST_DEBUG_OBJECT ( obj - > element ,
" streaming mode: using our own pool % " GST_PTR_FORMAT , pool ) ;
2014-04-11 21:10:11 +00:00
pushing_from_our_pool = TRUE ;
2014-04-15 19:07:23 +00:00
} else if ( pool ) {
GST_DEBUG_OBJECT ( obj - > element ,
" streaming mode: copying to downstream pool % " GST_PTR_FORMAT ,
pool ) ;
2014-04-08 22:54:09 +00:00
} else {
GST_DEBUG_OBJECT ( obj - > element ,
" streaming mode: no usable pool, copying to generic pool " ) ;
2014-05-06 16:58:59 +00:00
size = MAX ( size , obj - > info . size ) ;
2014-04-15 19:07:23 +00:00
}
2013-12-05 23:48:15 +00:00
break ;
case GST_V4L2_IO_AUTO :
default :
GST_WARNING_OBJECT ( obj - > element , " unhandled mode " ) ;
break ;
}
2014-04-08 22:20:25 +00:00
if ( size = = 0 )
goto no_size ;
2014-04-18 18:45:00 +00:00
/* Certain driver may expose a minimum through controls */
ctl . id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE ;
if ( v4l2_ioctl ( obj - > video_fd , VIDIOC_G_CTRL , & ctl ) > = 0 ) {
GST_DEBUG_OBJECT ( obj - > element , " driver require a minimum of %d buffers " ,
ctl . value ) ;
obj - > min_buffers_for_capture = ctl . value ;
} else {
obj - > min_buffers_for_capture = 0 ;
}
/* If pushing from our own pool, configure it with queried minimum,
* otherwise use the minimum required */
if ( pushing_from_our_pool ) {
/* When pushing from our own pool, we need what downstream one, to be able
* to fill the pipeline , the minimum required to decoder according to the
* driver and 1 more , so we don ' t endup up with everything downstream or
* held by the decoder . */
own_min = min + obj - > min_buffers_for_capture + 1 ;
/* Update min/max so the base class does not reset our settings */
min = own_min ;
max = 0 ;
} else {
/* In this case we'll have to configure two buffer pool. For our buffer
* pool , we ' ll need what the driver one , and one more , so we can dequeu */
own_min = obj - > min_buffers_for_capture + 1 ;
/* for the downstream pool, we keep what downstream wants, though ensure
* at least a minimum if downstream didn ' t suggest anything ( we are
* expecting the base class to create a default one for the context ) */
min = MAX ( min , GST_V4L2_MIN_BUFFERS ) ;
}
2014-04-08 22:20:25 +00:00
/* Request a bigger max, if one was suggested but it's too small */
if ( max ! = 0 )
max = MAX ( min , max ) ;
/* First step, configure our own pool */
2014-05-06 17:37:47 +00:00
config = gst_buffer_pool_get_config ( obj - > pool ) ;
2014-04-08 22:20:25 +00:00
/* If already configured/active, skip it */
/* FIXME not entirely correct, See bug 728268 */
2014-05-06 17:37:47 +00:00
if ( gst_buffer_pool_is_active ( obj - > pool ) ) {
gst_buffer_pool_config_get_params ( config , NULL , & size , & min , & max ) ;
2014-05-23 19:17:27 +00:00
gst_structure_free ( config ) ;
2014-04-08 22:20:25 +00:00
goto setup_other_pool ;
2014-05-06 17:37:47 +00:00
}
2014-04-08 21:34:19 +00:00
2014-04-08 22:20:25 +00:00
if ( obj - > need_video_meta ) {
2014-04-18 18:45:00 +00:00
GST_DEBUG_OBJECT ( obj - > element , " activate Video Meta " ) ;
2014-04-08 22:20:25 +00:00
gst_buffer_pool_config_add_option ( config ,
GST_BUFFER_POOL_OPTION_VIDEO_META ) ;
2014-04-08 21:34:19 +00:00
}
2014-04-18 18:45:00 +00:00
gst_buffer_pool_config_set_params ( config , caps , size , own_min , 0 ) ;
2014-04-08 22:20:25 +00:00
2014-04-18 18:45:00 +00:00
GST_DEBUG_OBJECT ( obj - > element , " setting own pool config to % "
GST_PTR_FORMAT , config ) ;
2014-04-08 22:20:25 +00:00
/* Our pool often need to adjust the value */
if ( ! gst_buffer_pool_set_config ( obj - > pool , config ) ) {
config = gst_buffer_pool_get_config ( obj - > pool ) ;
2014-04-18 18:45:00 +00:00
GST_DEBUG_OBJECT ( obj - > element , " own pool config changed to % "
GST_PTR_FORMAT , config ) ;
2014-04-08 22:20:25 +00:00
/* our pool will adjust the maximum buffer, which we are fine with */
2014-05-06 17:37:47 +00:00
if ( obj - > pool = = pool )
gst_buffer_pool_config_get_params ( config , NULL , & size , & min , & max ) ;
2014-04-08 22:20:25 +00:00
if ( ! gst_buffer_pool_set_config ( obj - > pool , config ) )
goto config_failed ;
}
setup_other_pool :
2014-04-11 21:10:11 +00:00
2014-04-08 22:20:25 +00:00
/* Now configure the other pool if different */
2014-04-11 21:10:11 +00:00
if ( obj - > pool ! = pool )
other_pool = pool ;
if ( other_pool ) {
2014-04-08 22:20:25 +00:00
if ( gst_buffer_pool_is_active ( obj - > pool ) )
goto done ;
2013-12-05 23:48:15 +00:00
config = gst_buffer_pool_get_config ( pool ) ;
gst_buffer_pool_config_set_params ( config , caps , size , min , max ) ;
2014-04-18 18:45:00 +00:00
GST_DEBUG_OBJECT ( obj - > element , " setting other pool config to % "
GST_PTR_FORMAT , config ) ;
2013-12-05 23:48:15 +00:00
/* if downstream supports video metadata, add this to the pool config */
2014-04-15 19:07:23 +00:00
if ( has_video_meta ) {
2014-04-18 18:45:00 +00:00
GST_DEBUG_OBJECT ( obj - > element , " activate Video Meta " ) ;
2013-12-05 23:48:15 +00:00
gst_buffer_pool_config_add_option ( config ,
GST_BUFFER_POOL_OPTION_VIDEO_META ) ;
}
2014-04-08 22:20:25 +00:00
/* TODO check return value, validate changes and confirm */
2013-12-05 23:48:15 +00:00
gst_buffer_pool_set_config ( pool , config ) ;
}
2014-04-08 22:20:25 +00:00
done :
2013-12-05 23:48:15 +00:00
if ( update )
gst_query_set_nth_allocation_pool ( query , 0 , pool , size , min , max ) ;
else
gst_query_add_allocation_pool ( query , pool , size , min , max ) ;
2014-04-16 21:04:42 +00:00
if ( pool )
gst_object_unref ( pool ) ;
2013-12-05 23:48:15 +00:00
return TRUE ;
pool_failed :
2014-04-08 22:20:25 +00:00
{
/* setup_pool already send the error */
2014-04-16 21:04:42 +00:00
goto cleanup ;
2014-04-08 22:20:25 +00:00
}
config_failed :
{
GST_ELEMENT_ERROR ( obj - > element , RESOURCE , SETTINGS ,
( _ ( " Failed to configure internal buffer pool. " ) ) , ( NULL ) ) ;
2014-04-16 21:04:42 +00:00
goto cleanup ;
2014-04-08 22:20:25 +00:00
}
no_size :
2013-12-05 23:48:15 +00:00
{
GST_ELEMENT_ERROR ( obj - > element , RESOURCE , SETTINGS ,
2014-04-08 22:20:25 +00:00
( _ ( " Video device did not suggest any buffer size. " ) ) , ( NULL ) ) ;
2014-04-16 21:04:42 +00:00
goto cleanup ;
}
cleanup :
{
if ( pool )
gst_object_unref ( pool ) ;
2013-12-05 23:48:15 +00:00
return FALSE ;
}
2014-04-11 21:10:11 +00:00
no_downstream_pool :
{
GST_ELEMENT_ERROR ( obj - > element , RESOURCE , SETTINGS ,
( _ ( " No downstream pool to import from. " ) ) ,
( " When importing DMABUF or USERPTR, we need a pool to import from " ) ) ;
return FALSE ;
}
2013-12-05 23:48:15 +00:00
}
2014-03-27 17:20:53 +00:00
gboolean
gst_v4l2_object_propose_allocation ( GstV4l2Object * obj , GstQuery * query )
{
GstBufferPool * pool ;
2014-04-05 02:36:37 +00:00
/* we need at least 2 buffers to operate */
guint size , min , max ;
2014-03-27 17:20:53 +00:00
GstCaps * caps ;
gboolean need_pool ;
2014-04-05 02:36:37 +00:00
/* Set defaults allocation parameters */
2014-05-06 16:58:59 +00:00
size = obj - > info . size ;
2014-04-05 02:36:37 +00:00
min = GST_V4L2_MIN_BUFFERS ;
max = VIDEO_MAX_FRAME ;
2014-03-27 17:20:53 +00:00
gst_query_parse_allocation ( query , & caps , & need_pool ) ;
if ( caps = = NULL )
goto no_caps ;
if ( ( pool = obj - > pool ) )
gst_object_ref ( pool ) ;
if ( pool ! = NULL ) {
GstCaps * pcaps ;
GstStructure * config ;
/* we had a pool, check caps */
config = gst_buffer_pool_get_config ( pool ) ;
2014-04-05 02:36:37 +00:00
gst_buffer_pool_config_get_params ( config , & pcaps , NULL , NULL , NULL ) ;
2014-03-27 17:20:53 +00:00
GST_DEBUG_OBJECT ( obj - > element ,
" we had a pool with caps % " GST_PTR_FORMAT , pcaps ) ;
if ( ! gst_caps_is_equal ( caps , pcaps ) ) {
gst_structure_free ( config ) ;
gst_object_unref ( pool ) ;
goto different_caps ;
}
gst_structure_free ( config ) ;
}
2014-04-05 02:36:37 +00:00
gst_query_add_allocation_pool ( query , pool , size , min , max ) ;
2014-03-27 17:20:53 +00:00
/* we also support various metadata */
gst_query_add_allocation_meta ( query , GST_VIDEO_META_API_TYPE , NULL ) ;
if ( pool )
gst_object_unref ( pool ) ;
return TRUE ;
/* ERRORS */
no_caps :
{
GST_DEBUG_OBJECT ( obj - > element , " no caps specified " ) ;
return FALSE ;
}
different_caps :
{
/* different caps, we can't use this pool */
GST_DEBUG_OBJECT ( obj - > element , " pool has different caps " ) ;
return FALSE ;
}
}