2002-09-09 07:14:35 +00:00
/* G-Streamer generic V4L2 element - generic V4L2 calls handling
* Copyright ( C ) 2002 Ronald Bultje < rbultje @ ronald . bitfreak . net >
2006-05-05 20:12:59 +00:00
* Copyright ( C ) 2006 Edgard Lima < edgard . lima @ indt . org . br >
2002-09-09 07:14:35 +00:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the
* Free Software Foundation , Inc . , 59 Temple Place - Suite 330 ,
* Boston , MA 02111 - 1307 , USA .
*/
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <sys/ioctl.h>
# include <sys/mman.h>
# include <string.h>
# include <errno.h>
2003-07-03 15:55:12 +00:00
# include <unistd.h>
2002-09-09 07:14:35 +00:00
# include "v4l2_calls.h"
2003-10-10 12:47:42 +00:00
# include "gstv4l2tuner.h"
# include "gstv4l2xoverlay.h"
# include "gstv4l2colorbalance.h"
2002-09-09 07:14:35 +00:00
2003-11-10 10:25:59 +00:00
# include "gstv4l2src.h"
2006-03-11 22:50:03 +00:00
GST_DEBUG_CATEGORY_EXTERN ( v4l2_debug ) ;
# define GST_CAT_DEFAULT v4l2_debug
2002-09-09 07:14:35 +00:00
/******************************************************
* gst_v4l2_get_capabilities ( ) :
* get the device ' s capturing capabilities
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-03-11 22:50:03 +00:00
gboolean
2006-05-11 17:59:59 +00:00
gst_v4l2_get_capabilities ( GstV4l2Object * v4l2object )
2002-09-09 07:14:35 +00:00
{
2006-05-11 17:59:59 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " getting capabilities " ) ;
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
2006-03-11 22:50:03 +00:00
return FALSE ;
2004-03-14 22:34:33 +00:00
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_QUERYCAP , & ( v4l2object - > vcap ) ) < 0 ) {
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS ,
( _ ( " Error getting capabilities '%s': %d, %s. It isn't a v4l2 driver. Check if it is a v4l1 driver \n " ) , v4l2object - > videodev , errno , strerror ( errno ) ) , GST_ERROR_SYSTEM ) ;
2004-03-14 22:34:33 +00:00
return FALSE ;
}
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
* gst_v4l2_empty_lists ( ) and gst_v4l2_fill_lists ( ) :
* fill / empty the lists of enumerations
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static gboolean
2006-05-11 17:59:59 +00:00
gst_v4l2_fill_lists ( GstV4l2Object * v4l2object )
2002-09-09 07:14:35 +00:00
{
2004-03-14 22:34:33 +00:00
gint n ;
2006-05-05 20:12:59 +00:00
#if 0 /* output not handled by now */
2004-03-14 22:34:33 +00:00
GstPadDirection dir = GST_PAD_UNKNOWN ;
2006-05-05 20:12:59 +00:00
# endif /* #if 0 - output not handled by now */
2004-03-14 22:34:33 +00:00
2006-05-11 17:59:59 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " getting enumerations " ) ;
GST_V4L2_CHECK_OPEN ( v4l2object ) ;
2004-03-14 22:34:33 +00:00
2006-05-05 20:12:59 +00:00
#if 0 /* output not handled by now */
2004-03-14 22:34:33 +00:00
if ( dir ! = GST_PAD_SINK ) {
2006-05-05 20:12:59 +00:00
# endif /* #if 0 - output not handled by now */
2006-08-28 14:59:05 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " inputs " ) ;
2004-03-14 22:34:33 +00:00
/* and now, the inputs */
for ( n = 0 ; ; n + + ) {
struct v4l2_input input ;
GstV4l2TunerChannel * v4l2channel ;
GstTunerChannel * channel ;
input . index = n ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_ENUMINPUT , & input ) < 0 ) {
2004-03-15 19:32:27 +00:00
if ( errno = = EINVAL )
break ; /* end of enumeration */
else {
2006-05-11 17:59:59 +00:00
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS , ( NULL ) ,
2004-03-15 19:32:27 +00:00
( " Failed to get %d in input enumeration for %s: %s " ,
2006-05-11 17:59:59 +00:00
n , v4l2object - > videodev , g_strerror ( errno ) ) ) ;
2004-03-15 19:32:27 +00:00
return FALSE ;
}
2004-03-14 22:34:33 +00:00
}
v4l2channel = g_object_new ( GST_TYPE_V4L2_TUNER_CHANNEL , NULL ) ;
channel = GST_TUNER_CHANNEL ( v4l2channel ) ;
2006-03-11 22:50:03 +00:00
channel - > label = g_strdup ( ( const gchar * ) input . name ) ;
2004-03-14 22:34:33 +00:00
channel - > flags = GST_TUNER_CHANNEL_INPUT ;
v4l2channel - > index = n ;
if ( input . type = = V4L2_INPUT_TYPE_TUNER ) {
2004-03-15 19:32:27 +00:00
struct v4l2_tuner vtun ;
v4l2channel - > tuner = input . tuner ;
channel - > flags | = GST_TUNER_CHANNEL_FREQUENCY ;
vtun . index = input . tuner ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_G_TUNER , & vtun ) < 0 ) {
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS , ( NULL ) ,
2004-03-15 19:32:27 +00:00
( " Failed to get tuner %d settings on %s: %s " ,
2006-05-11 17:59:59 +00:00
input . tuner , v4l2object - > videodev , g_strerror ( errno ) ) ) ;
2004-03-15 19:32:27 +00:00
g_object_unref ( G_OBJECT ( channel ) ) ;
return FALSE ;
}
2004-05-31 14:16:54 +00:00
channel - > freq_multiplicator =
62.5 * ( ( vtun . capability & V4L2_TUNER_CAP_LOW ) ? 1 : 1000 ) ;
channel - > min_frequency = vtun . rangelow * channel - > freq_multiplicator ;
channel - > max_frequency = vtun . rangehigh * channel - > freq_multiplicator ;
2004-03-15 19:32:27 +00:00
channel - > min_signal = 0 ;
channel - > max_signal = 0xffff ;
2004-03-14 22:34:33 +00:00
}
if ( input . audioset ) {
2004-03-15 19:32:27 +00:00
/* we take the first. We don't care for
* the others for now */
while ( ! ( input . audioset & ( 1 < < v4l2channel - > audio ) ) )
v4l2channel - > audio + + ;
channel - > flags | = GST_TUNER_CHANNEL_AUDIO ;
2004-03-14 22:34:33 +00:00
}
2006-05-11 17:59:59 +00:00
v4l2object - > inputs =
g_list_append ( v4l2object - > inputs , ( gpointer ) channel ) ;
2004-03-14 22:34:33 +00:00
}
2006-05-05 20:12:59 +00:00
#if 0 /* output not handled by now */
2004-03-14 22:34:33 +00:00
} else {
/* outputs */
for ( n = 0 ; ; n + + ) {
struct v4l2_output output ;
GstV4l2TunerChannel * v4l2channel ;
GstTunerChannel * channel ;
output . index = n ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_ENUMOUTPUT , & output ) < 0 ) {
2004-03-15 19:32:27 +00:00
if ( errno = = EINVAL )
break ; /* end of enumeration */
else {
2006-05-11 17:59:59 +00:00
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS , ( NULL ) ,
2004-03-15 19:32:27 +00:00
( " Failed to get %d in output enumeration for %s: %s " ,
2006-05-11 17:59:59 +00:00
n , v4l2object - > videodev , g_strerror ( errno ) ) ) ;
2004-03-15 19:32:27 +00:00
return FALSE ;
}
2004-03-14 22:34:33 +00:00
}
v4l2channel = g_object_new ( GST_TYPE_V4L2_TUNER_CHANNEL , NULL ) ;
channel = GST_TUNER_CHANNEL ( v4l2channel ) ;
2006-03-11 22:50:03 +00:00
channel - > label = g_strdup ( ( const gchar * ) output . name ) ;
2004-03-14 22:34:33 +00:00
channel - > flags = GST_TUNER_CHANNEL_OUTPUT ;
v4l2channel - > index = n ;
if ( output . audioset ) {
2004-03-15 19:32:27 +00:00
/* we take the first. We don't care for
* the others for now */
while ( ! ( output . audioset & ( 1 < < v4l2channel - > audio ) ) )
v4l2channel - > audio + + ;
channel - > flags | = GST_TUNER_CHANNEL_AUDIO ;
2004-03-14 22:34:33 +00:00
}
2006-05-11 17:59:59 +00:00
v4l2object - > inputs =
g_list_append ( v4l2object - > inputs , ( gpointer ) channel ) ;
2004-03-14 22:34:33 +00:00
}
}
2006-05-05 20:12:59 +00:00
# endif /* #if 0 - output not handled by now */
2002-09-09 07:14:35 +00:00
2006-08-28 14:59:05 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " norms " ) ;
2004-03-14 22:34:33 +00:00
/* norms... */
for ( n = 0 ; ; n + + ) {
struct v4l2_standard standard ;
GstV4l2TunerNorm * v4l2norm ;
GstTunerNorm * norm ;
standard . index = n ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_ENUMSTD , & standard ) < 0 ) {
2004-03-14 22:34:33 +00:00
if ( errno = = EINVAL )
2004-03-15 19:32:27 +00:00
break ; /* end of enumeration */
2004-03-14 22:34:33 +00:00
else {
2006-05-11 17:59:59 +00:00
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS , ( NULL ) ,
2004-03-15 19:32:27 +00:00
( " Failed to get %d in norm enumeration for %s: %s " ,
2006-05-11 17:59:59 +00:00
n , v4l2object - > videodev , g_strerror ( errno ) ) ) ;
2004-03-15 19:32:27 +00:00
return FALSE ;
2004-03-14 22:34:33 +00:00
}
}
v4l2norm = g_object_new ( GST_TYPE_V4L2_TUNER_NORM , NULL ) ;
norm = GST_TUNER_NORM ( v4l2norm ) ;
2006-03-11 22:50:03 +00:00
norm - > label = g_strdup ( ( const gchar * ) standard . name ) ;
gst_value_set_fraction ( & norm - > framerate ,
standard . frameperiod . denominator , standard . frameperiod . numerator ) ;
2004-03-14 22:34:33 +00:00
v4l2norm - > index = standard . id ;
2006-05-11 17:59:59 +00:00
v4l2object - > stds = g_list_append ( v4l2object - > stds , ( gpointer ) norm ) ;
2004-03-14 22:34:33 +00:00
}
2006-08-28 14:59:05 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " controls+menus " ) ;
2004-03-14 22:34:33 +00:00
/* and lastly, controls+menus (if appropriate) */
for ( n = V4L2_CID_BASE ; ; n + + ) {
struct v4l2_queryctrl control ;
GstV4l2ColorBalanceChannel * v4l2channel ;
GstColorBalanceChannel * channel ;
2006-08-28 14:59:05 +00:00
/* when we reached the last official CID, continue with private CIDs */
if ( n = = V4L2_CID_LASTP1 ) {
GST_DEBUG_OBJECT ( v4l2object - > element , " chhecking private CIDs " ) ;
2004-03-14 22:34:33 +00:00
n = V4L2_CID_PRIVATE_BASE ;
2006-08-28 14:59:05 +00:00
}
2004-03-14 22:34:33 +00:00
control . id = n ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_QUERYCTRL , & control ) < 0 ) {
2004-03-14 22:34:33 +00:00
if ( errno = = EINVAL ) {
2004-03-15 19:32:27 +00:00
if ( n < V4L2_CID_PRIVATE_BASE )
2006-08-28 14:59:05 +00:00
/* continue so that we also check private controls */
2004-03-15 19:32:27 +00:00
continue ;
else
break ;
2004-03-14 22:34:33 +00:00
} else {
2006-05-11 17:59:59 +00:00
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS , ( NULL ) ,
2004-03-15 19:32:27 +00:00
( " Failed to get %d in control enumeration for %s: %s " ,
2006-05-11 17:59:59 +00:00
n , v4l2object - > videodev , g_strerror ( errno ) ) ) ;
2004-03-15 19:32:27 +00:00
return FALSE ;
2004-03-14 22:34:33 +00:00
}
}
if ( control . flags & V4L2_CTRL_FLAG_DISABLED )
continue ;
switch ( n ) {
case V4L2_CID_BRIGHTNESS :
case V4L2_CID_CONTRAST :
case V4L2_CID_SATURATION :
case V4L2_CID_HUE :
case V4L2_CID_BLACK_LEVEL :
case V4L2_CID_AUTO_WHITE_BALANCE :
case V4L2_CID_DO_WHITE_BALANCE :
case V4L2_CID_RED_BALANCE :
case V4L2_CID_BLUE_BALANCE :
case V4L2_CID_GAMMA :
case V4L2_CID_EXPOSURE :
case V4L2_CID_AUTOGAIN :
case V4L2_CID_GAIN :
2006-08-28 14:59:05 +00:00
/* we only handle these for now (why?) */
2004-03-15 19:32:27 +00:00
break ;
2004-03-14 22:34:33 +00:00
default :
2006-05-11 17:59:59 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element ,
2006-08-28 14:59:05 +00:00
" ControlID %s (%x) unhandled, FIXME " , control . name , n ) ;
2004-03-15 19:32:27 +00:00
control . id + + ;
break ;
2004-03-14 22:34:33 +00:00
}
if ( n ! = control . id )
continue ;
2006-08-28 14:59:05 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element ,
" Adding ControlID %s (%x) " , control . name , n ) ;
2004-03-14 22:34:33 +00:00
v4l2channel = g_object_new ( GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL , NULL ) ;
channel = GST_COLOR_BALANCE_CHANNEL ( v4l2channel ) ;
2006-03-11 22:50:03 +00:00
channel - > label = g_strdup ( ( const gchar * ) control . name ) ;
2006-03-25 05:31:28 +00:00
v4l2channel - > id = n ;
2003-10-10 12:47:42 +00:00
#if 0
2004-03-14 22:34:33 +00:00
if ( control . type = = V4L2_CTRL_TYPE_MENU ) {
struct v4l2_querymenu menu , * mptr ;
int i ;
menu . id = n ;
for ( i = 0 ; ; i + + ) {
2004-03-15 19:32:27 +00:00
menu . index = i ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_QUERYMENU , & menu ) < 0 ) {
2004-03-15 19:32:27 +00:00
if ( errno = = EINVAL )
break ; /* end of enumeration */
else {
2006-05-11 17:59:59 +00:00
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , SETTINGS , ( NULL ) ,
2004-03-15 19:32:27 +00:00
( " Failed to get %d in menu enumeration for %s: %s " ,
2006-05-11 17:59:59 +00:00
n , v4l2object - > videodev , g_strerror ( errno ) ) ) ;
2004-03-15 19:32:27 +00:00
return FALSE ;
}
}
mptr = g_malloc ( sizeof ( menu ) ) ;
memcpy ( mptr , & menu , sizeof ( menu ) ) ;
menus = g_list_append ( menus , mptr ) ;
2004-03-14 22:34:33 +00:00
}
}
2006-05-11 17:59:59 +00:00
v4l2object - > menus = g_list_append ( v4l2object - > menus , menus ) ;
2003-10-10 12:47:42 +00:00
# endif
2003-03-02 21:58:52 +00:00
2004-03-14 22:34:33 +00:00
switch ( control . type ) {
case V4L2_CTRL_TYPE_INTEGER :
2004-03-15 19:32:27 +00:00
channel - > min_value = control . minimum ;
channel - > max_value = control . maximum ;
break ;
2004-03-14 22:34:33 +00:00
case V4L2_CTRL_TYPE_BOOLEAN :
2004-03-15 19:32:27 +00:00
channel - > min_value = FALSE ;
channel - > max_value = TRUE ;
break ;
2004-03-14 22:34:33 +00:00
default :
2006-08-28 14:59:05 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element ,
" No range for ControlID %s (%x), type=%d " ,
control . name , n , control . type ) ;
2004-03-15 19:32:27 +00:00
channel - > min_value = channel - > max_value = 0 ;
break ;
2004-03-14 22:34:33 +00:00
}
2002-09-09 07:14:35 +00:00
2006-05-11 17:59:59 +00:00
v4l2object - > colors = g_list_append ( v4l2object - > colors , ( gpointer ) channel ) ;
2004-03-14 22:34:33 +00:00
}
2006-08-28 14:59:05 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " done " ) ;
2004-03-14 22:34:33 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
static void
2006-05-11 17:59:59 +00:00
gst_v4l2_empty_lists ( GstV4l2Object * v4l2object )
2002-09-09 07:14:35 +00:00
{
2006-05-11 17:59:59 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " deleting enumerations " ) ;
2002-09-09 07:14:35 +00:00
2006-05-11 17:59:59 +00:00
g_list_foreach ( v4l2object - > inputs , ( GFunc ) g_object_unref , NULL ) ;
g_list_free ( v4l2object - > inputs ) ;
v4l2object - > inputs = NULL ;
2003-10-10 12:47:42 +00:00
2006-05-11 17:59:59 +00:00
g_list_foreach ( v4l2object - > stds , ( GFunc ) g_object_unref , NULL ) ;
g_list_free ( v4l2object - > stds ) ;
v4l2object - > stds = NULL ;
2003-10-10 12:47:42 +00:00
2006-05-11 17:59:59 +00:00
g_list_foreach ( v4l2object - > colors , ( GFunc ) g_object_unref , NULL ) ;
g_list_free ( v4l2object - > colors ) ;
v4l2object - > colors = NULL ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
* gst_v4l2_open ( ) :
2006-05-11 17:59:59 +00:00
* open the video device ( v4l2object - > videodev )
2002-09-09 07:14:35 +00:00
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2006-05-11 17:59:59 +00:00
gst_v4l2_open ( GstV4l2Object * v4l2object )
2002-09-09 07:14:35 +00:00
{
2006-03-25 05:31:28 +00:00
struct stat st ;
2006-05-11 17:59:59 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " Trying to open device %s " ,
v4l2object - > videodev ) ;
GST_V4L2_CHECK_NOT_OPEN ( v4l2object ) ;
GST_V4L2_CHECK_NOT_ACTIVE ( v4l2object ) ;
2004-03-14 22:34:33 +00:00
/* be sure we have a device */
2006-05-11 17:59:59 +00:00
if ( ! v4l2object - > videodev )
v4l2object - > videodev = g_strdup ( " /dev/video " ) ;
2004-03-14 22:34:33 +00:00
2006-03-25 05:31:28 +00:00
/* check if it is a device */
2006-05-11 17:59:59 +00:00
if ( - 1 = = stat ( v4l2object - > videodev , & st ) ) {
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , NOT_FOUND ,
2006-05-01 21:37:51 +00:00
( _ ( " Cannot identify '%s': %d, %s \n " ) ,
2006-05-11 17:59:59 +00:00
v4l2object - > videodev , errno , strerror ( errno ) ) , GST_ERROR_SYSTEM ) ;
2006-03-25 05:31:28 +00:00
goto error ;
}
if ( ! S_ISCHR ( st . st_mode ) ) {
2006-05-11 17:59:59 +00:00
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , NOT_FOUND ,
2006-05-01 21:37:51 +00:00
( _ ( " It isn't a device '%s': %d, %s \n " ) ,
2006-05-11 17:59:59 +00:00
v4l2object - > videodev , errno , strerror ( errno ) ) , GST_ERROR_SYSTEM ) ;
2006-03-25 05:31:28 +00:00
goto error ;
}
2004-03-14 22:34:33 +00:00
/* open the device */
2006-05-11 17:59:59 +00:00
v4l2object - > video_fd =
open ( v4l2object - > videodev , O_RDWR /* | O_NONBLOCK */ ) ;
2006-03-25 05:31:28 +00:00
2006-05-11 17:59:59 +00:00
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) ) {
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , OPEN_READ_WRITE ,
2004-03-15 19:32:27 +00:00
( _ ( " Could not open device \" %s \" for reading and writing. " ) ,
2006-05-11 17:59:59 +00:00
v4l2object - > videodev ) , GST_ERROR_SYSTEM ) ;
2004-03-14 22:34:33 +00:00
goto error ;
}
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
/* get capabilities */
2006-05-11 17:59:59 +00:00
if ( ! gst_v4l2_get_capabilities ( v4l2object ) ) {
2004-03-14 22:34:33 +00:00
goto error ;
}
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
/* do we need to be a capture device? */
2006-05-11 17:59:59 +00:00
if ( GST_IS_V4L2SRC ( v4l2object ) & &
! ( v4l2object - > vcap . capabilities & V4L2_CAP_VIDEO_CAPTURE ) ) {
GST_ELEMENT_ERROR ( v4l2object - > element , RESOURCE , NOT_FOUND ,
2006-03-25 05:31:28 +00:00
( _ ( " Device \" %s \" is not a capture device. " ) ,
2006-05-11 17:59:59 +00:00
v4l2object - > videodev ) , ( " Capabilities: 0x%x " ,
v4l2object - > vcap . capabilities ) ) ;
2004-03-14 22:34:33 +00:00
goto error ;
}
2003-11-10 10:25:59 +00:00
2004-03-14 22:34:33 +00:00
/* create enumerations */
2006-05-11 17:59:59 +00:00
if ( ! gst_v4l2_fill_lists ( v4l2object ) )
2004-03-14 22:34:33 +00:00
goto error ;
2002-09-09 07:14:35 +00:00
2006-05-11 17:59:59 +00:00
GST_INFO_OBJECT ( v4l2object - > element ,
" Opened device '%s' (%s) successfully \n " , v4l2object - > vcap . card ,
v4l2object - > videodev ) ;
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
error :
2006-05-11 17:59:59 +00:00
if ( GST_V4L2_IS_OPEN ( v4l2object ) ) {
2004-03-14 22:34:33 +00:00
/* close device */
2006-05-11 17:59:59 +00:00
close ( v4l2object - > video_fd ) ;
v4l2object - > video_fd = - 1 ;
2004-03-14 22:34:33 +00:00
}
/* empty lists */
2006-05-11 17:59:59 +00:00
gst_v4l2_empty_lists ( v4l2object ) ;
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
return FALSE ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
* gst_v4l2_close ( ) :
2006-05-11 17:59:59 +00:00
* close the video device ( v4l2object - > video_fd )
2002-09-09 07:14:35 +00:00
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2006-05-11 17:59:59 +00:00
gst_v4l2_close ( GstV4l2Object * v4l2object )
2002-09-09 07:14:35 +00:00
{
2006-05-11 17:59:59 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " Trying to close %s " ,
v4l2object - > videodev ) ;
GST_V4L2_CHECK_OPEN ( v4l2object ) ;
GST_V4L2_CHECK_NOT_ACTIVE ( v4l2object ) ;
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
/* close device */
2006-05-11 17:59:59 +00:00
close ( v4l2object - > video_fd ) ;
v4l2object - > video_fd = - 1 ;
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
/* empty lists */
2006-05-11 17:59:59 +00:00
gst_v4l2_empty_lists ( v4l2object ) ;
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
* gst_v4l2_get_norm ( )
* Get the norm of the current device
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2006-05-11 17:59:59 +00:00
gst_v4l2_get_norm ( GstV4l2Object * v4l2object , v4l2_std_id * norm )
2002-09-09 07:14:35 +00:00
{
2006-05-11 17:59:59 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " getting norm " ) ;
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
2006-03-11 22:50:03 +00:00
return FALSE ;
2004-03-14 22:34:33 +00:00
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_G_STD , norm ) < 0 ) {
GST_WARNING_OBJECT ( v4l2object - > element ,
2006-03-11 22:50:03 +00:00
" Failed to get the current norm for device %s: %s " ,
2006-05-11 17:59:59 +00:00
v4l2object - > videodev , g_strerror ( errno ) ) ;
2004-03-14 22:34:33 +00:00
return FALSE ;
}
2002-09-09 07:14:35 +00:00
2006-05-05 20:12:59 +00:00
2004-03-14 22:34:33 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
* gst_v4l2_set_norm ( )
* Set the norm of the current device
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2006-05-11 17:59:59 +00:00
gst_v4l2_set_norm ( GstV4l2Object * v4l2object , v4l2_std_id norm )
2002-09-09 07:14:35 +00:00
{
2006-05-11 17:59:59 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " trying to set norm to %llx " , norm ) ;
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
2006-03-11 22:50:03 +00:00
return FALSE ;
2004-03-14 22:34:33 +00:00
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_S_STD , & norm ) < 0 ) {
GST_WARNING_OBJECT ( v4l2object - > element ,
2006-03-11 22:50:03 +00:00
" Failed to set norm 0x%llx for device %s: %s " , norm ,
2006-05-11 17:59:59 +00:00
v4l2object - > videodev , g_strerror ( errno ) ) ;
2004-03-14 22:34:33 +00:00
return FALSE ;
}
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
2003-03-02 21:58:52 +00:00
* gst_v4l2_get_frequency ( ) :
2002-09-09 07:14:35 +00:00
* get the current frequency
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2006-05-11 17:59:59 +00:00
gst_v4l2_get_frequency ( GstV4l2Object * v4l2object ,
2004-03-14 22:34:33 +00:00
gint tunernum , gulong * frequency )
2002-09-09 07:14:35 +00:00
{
2004-03-14 22:34:33 +00:00
struct v4l2_frequency freq ;
2004-05-31 14:16:54 +00:00
GstTunerChannel * channel ;
2002-09-09 07:14:35 +00:00
2006-05-11 17:59:59 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " getting current tuner frequency " ) ;
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
2006-03-11 22:50:03 +00:00
return FALSE ;
2002-09-09 07:14:35 +00:00
2006-05-11 17:59:59 +00:00
channel = gst_tuner_get_channel ( GST_TUNER ( v4l2object - > element ) ) ;
2004-05-31 14:16:54 +00:00
2004-03-14 22:34:33 +00:00
freq . tuner = tunernum ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_G_FREQUENCY , & freq ) < 0 ) {
GST_WARNING_OBJECT ( v4l2object - > element ,
2006-03-11 22:50:03 +00:00
" Failed to get current tuner frequency for device %s: %s " ,
2006-05-11 17:59:59 +00:00
v4l2object - > videodev , g_strerror ( errno ) ) ;
2004-03-14 22:34:33 +00:00
return FALSE ;
}
2002-09-09 07:14:35 +00:00
2004-05-31 14:16:54 +00:00
* frequency = freq . frequency * channel - > freq_multiplicator ;
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
2003-03-02 21:58:52 +00:00
* gst_v4l2_set_frequency ( ) :
2002-09-09 07:14:35 +00:00
* set frequency
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2006-05-11 17:59:59 +00:00
gst_v4l2_set_frequency ( GstV4l2Object * v4l2object ,
2004-03-14 22:34:33 +00:00
gint tunernum , gulong frequency )
2002-09-09 07:14:35 +00:00
{
2004-03-14 22:34:33 +00:00
struct v4l2_frequency freq ;
2004-05-31 14:16:54 +00:00
GstTunerChannel * channel ;
2004-03-14 22:34:33 +00:00
2006-05-11 17:59:59 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element ,
" setting current tuner frequency to %lu " , frequency ) ;
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
2006-03-11 22:50:03 +00:00
return FALSE ;
2004-03-14 22:34:33 +00:00
2006-05-11 17:59:59 +00:00
channel = gst_tuner_get_channel ( GST_TUNER ( v4l2object - > element ) ) ;
2004-05-31 14:16:54 +00:00
2004-03-14 22:34:33 +00:00
freq . tuner = tunernum ;
/* fill in type - ignore error */
2006-05-11 17:59:59 +00:00
ioctl ( v4l2object - > video_fd , VIDIOC_G_FREQUENCY , & freq ) ;
2004-05-31 14:16:54 +00:00
freq . frequency = frequency / channel - > freq_multiplicator ;
2004-03-14 22:34:33 +00:00
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_S_FREQUENCY , & freq ) < 0 ) {
GST_WARNING_OBJECT ( v4l2object - > element ,
2006-03-11 22:50:03 +00:00
" Failed to set current tuner frequency for device %s to %lu: %s " ,
2006-05-11 17:59:59 +00:00
v4l2object - > videodev , frequency , g_strerror ( errno ) ) ;
2004-03-14 22:34:33 +00:00
return FALSE ;
}
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
2003-03-02 21:58:52 +00:00
* gst_v4l2_signal_strength ( ) :
2002-09-09 07:14:35 +00:00
* get the strength of the signal on the current input
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2006-05-11 17:59:59 +00:00
gst_v4l2_signal_strength ( GstV4l2Object * v4l2object ,
2004-03-14 22:34:33 +00:00
gint tunernum , gulong * signal_strength )
2002-09-09 07:14:35 +00:00
{
2004-03-14 22:34:33 +00:00
struct v4l2_tuner tuner ;
2002-09-09 07:14:35 +00:00
2006-05-11 17:59:59 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " trying to get signal strength " ) ;
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
2006-03-11 22:50:03 +00:00
return FALSE ;
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
tuner . index = tunernum ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_G_TUNER , & tuner ) < 0 ) {
GST_WARNING_OBJECT ( v4l2object - > element ,
2006-03-11 22:50:03 +00:00
" Failed to get signal strength for device %s: %s " ,
2006-05-11 17:59:59 +00:00
v4l2object - > videodev , g_strerror ( errno ) ) ;
2004-03-14 22:34:33 +00:00
return FALSE ;
}
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
* signal_strength = tuner . signal ;
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
2003-03-02 21:58:52 +00:00
* gst_v4l2_get_attribute ( ) :
2002-09-09 07:14:35 +00:00
* try to get the value of one specific attribute
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2006-05-11 17:59:59 +00:00
gst_v4l2_get_attribute ( GstV4l2Object * v4l2object ,
2004-03-14 22:34:33 +00:00
int attribute_num , int * value )
2002-09-09 07:14:35 +00:00
{
2004-03-14 22:34:33 +00:00
struct v4l2_control control ;
2003-03-02 21:58:52 +00:00
2006-05-11 17:59:59 +00:00
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
2006-03-11 22:50:03 +00:00
return FALSE ;
2002-09-09 07:14:35 +00:00
2006-05-11 17:59:59 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " getting value of attribute %d " ,
2006-05-01 21:37:51 +00:00
attribute_num ) ;
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
control . id = attribute_num ;
2002-09-09 07:14:35 +00:00
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_G_CTRL , & control ) < 0 ) {
GST_WARNING_OBJECT ( v4l2object - > element ,
2006-03-25 05:31:28 +00:00
" Failed to get value for control %d on device %s: %s " ,
2006-05-11 17:59:59 +00:00
attribute_num , v4l2object - > videodev , g_strerror ( errno ) ) ;
2004-03-14 22:34:33 +00:00
return FALSE ;
}
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
* value = control . value ;
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
2003-03-02 21:58:52 +00:00
* gst_v4l2_set_attribute ( ) :
2002-09-09 07:14:35 +00:00
* try to set the value of one specific attribute
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2006-05-11 17:59:59 +00:00
gst_v4l2_set_attribute ( GstV4l2Object * v4l2object ,
2004-03-14 22:34:33 +00:00
int attribute_num , const int value )
2002-09-09 07:14:35 +00:00
{
2004-03-14 22:34:33 +00:00
struct v4l2_control control ;
2002-09-09 07:14:35 +00:00
2006-05-11 17:59:59 +00:00
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
2006-03-11 22:50:03 +00:00
return FALSE ;
2002-09-09 07:14:35 +00:00
2006-05-11 17:59:59 +00:00
GST_DEBUG_OBJECT ( v4l2object - > element , " setting value of attribute %d to %d " ,
2006-05-01 21:37:51 +00:00
attribute_num , value ) ;
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
control . id = attribute_num ;
control . value = value ;
2002-09-09 07:14:35 +00:00
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_S_CTRL , & control ) < 0 ) {
GST_WARNING_OBJECT ( v4l2object - > element ,
2006-03-25 05:31:28 +00:00
" Failed to set value %d for control %d on device %s: %s " ,
2006-05-11 17:59:59 +00:00
value , attribute_num , v4l2object - > videodev , g_strerror ( errno ) ) ;
return FALSE ;
}
return TRUE ;
}
gboolean
gst_v4l2_get_input ( GstV4l2Object * v4l2object , gint * input )
{
gint n ;
GST_DEBUG_OBJECT ( v4l2object - > element , " trying to get input " ) ;
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
return FALSE ;
if ( ioctl ( v4l2object - > video_fd , VIDIOC_G_INPUT , & n ) < 0 ) {
GST_WARNING_OBJECT ( v4l2object - > element ,
" Failed to get current input on device %s: %s " ,
v4l2object - > videodev , g_strerror ( errno ) ) ;
return FALSE ;
}
* input = n ;
return TRUE ;
}
gboolean
gst_v4l2_set_input ( GstV4l2Object * v4l2object , gint input )
{
GST_DEBUG_OBJECT ( v4l2object - > element , " trying to set input to %d " , input ) ;
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
return FALSE ;
if ( ioctl ( v4l2object - > video_fd , VIDIOC_S_INPUT , & input ) < 0 ) {
GST_WARNING_OBJECT ( v4l2object - > element ,
" Failed to set input %d on device %s: %s " , input , v4l2object - > videodev ,
g_strerror ( errno ) ) ;
2004-03-14 22:34:33 +00:00
return FALSE ;
}
2002-09-09 07:14:35 +00:00
2004-03-14 22:34:33 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
2006-05-11 17:59:59 +00:00
#if 0 /* output not handled by now */
gboolean
gst_v4l2_get_output ( GstV4l2Object * v4l2object , gint * output )
{
gint n ;
GST_DEBUG_OBJECT ( v4l2object - > element , " trying to get output " ) ;
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
return FALSE ;
if ( ioctl ( v4l2object - > video_fd , VIDIOC_G_OUTPUT , & n ) < 0 ) {
GST_WARNING_OBJECT ( v4l2object - > element ,
" Failed to get current output on device %s: %s " ,
v4l2object - > videodev , g_strerror ( errno ) ) ;
return FALSE ;
}
* output = n ;
return TRUE ;
}
gboolean
gst_v4l2_set_output ( GstV4l2Object * v4l2object , gint output )
{
GST_DEBUG_OBJECT ( v4l2object - > element , " trying to set output to %d " , output ) ;
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
return FALSE ;
if ( ! GST_V4L2_IS_ACTIVE ( v4l2object ) )
return FALSE ;
if ( ioctl ( v4l2object - > video_fd , VIDIOC_S_OUTPUT , & output ) < 0 ) {
GST_WARNING_OBJECT ( v4l2object - > element ,
" Failed to set current output on device %s to %d: %s " ,
v4l2object - > videodev , output , g_strerror ( errno ) ) ;
return FALSE ;
}
return TRUE ;
}
# endif /* #if 0 - output not handled by now */