2006-09-02 14:28:55 +00:00
/* GStreamer
*
2002-09-09 07:14:35 +00:00
* Copyright ( C ) 2002 Ronald Bultje < rbultje @ ronald . bitfreak . net >
2006-09-02 14:28:55 +00:00
* 2006 Edgard Lima < edgard . lima @ indt . org . br >
*
* v4l2src . c - system calls
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 .
*/
2003-11-07 12:47:02 +00:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
2002-09-09 07:14:35 +00:00
# include <stdlib.h>
# 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>
# include "v4l2src_calls.h"
# include <sys/time.h>
2004-01-12 02:19:57 +00:00
# include <unistd.h>
2006-03-11 22:50:03 +00:00
# include "gstv4l2tuner.h"
GST_DEBUG_CATEGORY_EXTERN ( v4l2src_debug ) ;
2004-01-12 02:19:57 +00:00
# define GST_CAT_DEFAULT v4l2src_debug
/* lalala... */
# define GST_V4L2_SET_ACTIVE(element) (element)->buffer = GINT_TO_POINTER (-1)
# define GST_V4L2_SET_INACTIVE(element) (element)->buffer = NULL
2002-09-09 07:14:35 +00:00
# define DEBUG(format, args...) \
2006-03-11 22:50:03 +00:00
GST_CAT_DEBUG_OBJECT ( \
v4l2src_debug , v4l2src , \
" V4L2SRC: " format , # # args )
2002-09-09 07:14:35 +00:00
/* On some systems MAP_FAILED seems to be missing */
# ifndef MAP_FAILED
# define MAP_FAILED ( (caddr_t) -1 )
# endif
2002-11-13 12:35:56 +00:00
/******************************************************
* gst_v4l2src_fill_format_list ( ) :
* create list of supported capture formats
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2004-03-14 22:34:33 +00:00
gst_v4l2src_fill_format_list ( GstV4l2Src * v4l2src )
2002-11-13 12:35:56 +00:00
{
2004-01-12 02:19:57 +00:00
gint n ;
struct v4l2_fmtdesc * format ;
GST_DEBUG_OBJECT ( v4l2src , " getting src format enumerations " ) ;
/* format enumeration */
2004-03-14 22:34:33 +00:00
for ( n = 0 ; ; n + + ) {
2004-01-12 02:19:57 +00:00
format = g_new ( struct v4l2_fmtdesc , 1 ) ;
2004-03-14 22:34:33 +00:00
2004-01-12 02:19:57 +00:00
format - > index = n ;
format - > type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2src - > v4l2object - > video_fd , VIDIOC_ENUM_FMT , format ) < 0 ) {
2004-01-12 02:19:57 +00:00
if ( errno = = EINVAL ) {
2004-03-15 19:32:27 +00:00
break ; /* end of enumeration */
2004-01-12 02:19:57 +00:00
} else {
2006-09-15 19:11:00 +00:00
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , SETTINGS ,
( _ ( " failed to get number %d in pixelformat enumeration for %s: %s " ) ,
n , v4l2src - > v4l2object - > videodev ) , GST_ERROR_SYSTEM ) ;
2004-03-15 19:32:27 +00:00
g_free ( format ) ;
return FALSE ;
2004-01-12 02:19:57 +00:00
}
}
2006-05-08 19:21:18 +00:00
GST_LOG_OBJECT ( v4l2src , " got format % " GST_FOURCC_FORMAT ,
2004-03-15 19:32:27 +00:00
GST_FOURCC_ARGS ( format - > pixelformat ) ) ;
2004-01-12 02:19:57 +00:00
v4l2src - > formats = g_slist_prepend ( v4l2src - > formats , format ) ;
}
return TRUE ;
2002-11-13 12:35:56 +00:00
}
/******************************************************
2004-01-12 02:19:57 +00:00
* gst_v4l2src_clear_format_list ( ) :
2002-11-13 12:35:56 +00:00
* free list of supported capture formats
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2004-03-14 22:34:33 +00:00
gst_v4l2src_clear_format_list ( GstV4l2Src * v4l2src )
2002-11-13 12:35:56 +00:00
{
2004-01-12 02:19:57 +00:00
g_slist_foreach ( v4l2src - > formats , ( GFunc ) g_free , NULL ) ;
g_slist_free ( v4l2src - > formats ) ;
2004-10-24 18:15:23 +00:00
v4l2src - > formats = NULL ;
2002-11-13 12:35:56 +00:00
2004-01-12 02:19:57 +00:00
return TRUE ;
2002-11-13 12:35:56 +00:00
}
2002-09-09 07:14:35 +00:00
/******************************************************
* gst_v4l2src_queue_frame ( ) :
* queue a frame for capturing
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-01-12 02:19:57 +00:00
gboolean
2004-03-14 22:34:33 +00:00
gst_v4l2src_queue_frame ( GstV4l2Src * v4l2src , guint i )
2002-09-09 07:14:35 +00:00
{
2004-01-12 02:19:57 +00:00
GST_LOG_OBJECT ( v4l2src , " queueing frame %u " , i ) ;
2002-09-09 07:14:35 +00:00
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2src - > v4l2object - > video_fd , VIDIOC_QBUF ,
2004-03-15 19:32:27 +00:00
& v4l2src - > pool - > buffers [ i ] . buffer ) < 0 ) {
2004-01-29 23:20:45 +00:00
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , WRITE ,
2006-09-02 14:28:55 +00:00
( _ ( " Could not write to device '%s'. " ) ,
2006-05-11 17:59:59 +00:00
v4l2src - > v4l2object - > videodev ) ,
2006-09-15 19:11:00 +00:00
( " Error queueing buffer %u on device %s. system error: %s " , i ,
v4l2src - > v4l2object - > videodev , g_strerror ( errno ) ) ) ;
2004-01-12 02:19:57 +00:00
return FALSE ;
}
2003-05-21 06:33:18 +00:00
2004-01-12 02:19:57 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
2004-01-12 02:19:57 +00:00
* gst_v4l2src_grab_frame ( ) :
* grab a frame for capturing
2002-09-09 07:14:35 +00:00
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-01-12 02:19:57 +00:00
gint
2004-03-14 22:34:33 +00:00
gst_v4l2src_grab_frame ( GstV4l2Src * v4l2src )
2002-09-09 07:14:35 +00:00
{
2004-01-12 02:19:57 +00:00
struct v4l2_buffer buffer ;
2006-03-25 05:31:28 +00:00
gint32 trials = 100 ;
2004-03-14 22:34:33 +00:00
2006-03-25 05:31:28 +00:00
memset ( & buffer , 0x00 , sizeof ( buffer ) ) ;
2004-01-12 02:19:57 +00:00
buffer . type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
2006-03-25 05:31:28 +00:00
buffer . memory = v4l2src - > breq . memory ;
2006-05-11 17:59:59 +00:00
while ( ioctl ( v4l2src - > v4l2object - > video_fd , VIDIOC_DQBUF , & buffer ) < 0 ) {
2004-01-12 02:19:57 +00:00
/* if the sync() got interrupted, we can retry */
2006-03-11 22:50:03 +00:00
switch ( errno ) {
case EAGAIN :
2006-09-15 19:11:00 +00:00
GST_DEBUG_OBJECT ( v4l2src ,
" Non-blocking I/O has been selected using O_NONBLOCK and "
" no buffer was in the outgoing queue. device %s " ,
v4l2src - > v4l2object - > videodev ) ;
2006-03-11 22:50:03 +00:00
break ;
case EINVAL :
2006-09-15 19:11:00 +00:00
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , FAILED ,
( _ ( " Failed trying to get frames from device %s " ) ,
v4l2src - > v4l2object - > videodev ) ,
( _ ( " The buffer type is not supported, or the index is out of bounds, " " or no buffers have been allocated yet, or the userptr " " or length are invalid. device %s " ) , v4l2src - > v4l2object - > videodev ) ) ;
2006-03-11 22:50:03 +00:00
break ;
case ENOMEM :
2006-09-15 19:11:00 +00:00
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , FAILED ,
( _ ( " Failed trying to get frames from device %s. Not enough memory " ) ,
v4l2src - > v4l2object - > videodev ) ,
( _ ( " isufficient memory to enqueue a user pointer buffer. device %s " ) , v4l2src - > v4l2object - > videodev ) ) ;
2006-03-11 22:50:03 +00:00
break ;
case EIO :
2006-09-15 19:11:00 +00:00
GST_DEBUG_OBJECT ( v4l2src ,
2006-03-25 05:31:28 +00:00
" VIDIOC_DQBUF failed due to an internal error. "
" Can also indicate temporary problems like signal loss. "
" Note the driver might dequeue an (empty) buffer despite "
" returning an error, or even stop capturing. "
2006-09-15 19:11:00 +00:00
" device %s " , v4l2src - > v4l2object - > videodev ) ;
2006-03-11 22:50:03 +00:00
break ;
case EINTR :
2006-09-15 19:11:00 +00:00
GST_DEBUG_OBJECT ( v4l2src ,
" could not sync on a buffer on device %s " ,
v4l2src - > v4l2object - > videodev ) ;
2006-03-11 22:50:03 +00:00
break ;
default :
2006-09-15 19:11:00 +00:00
GST_ELEMENT_WARNING ( v4l2src , RESOURCE , FAILED ,
( _ ( " Grabbing frame got interrupted on %s. No expected reason " ) ,
v4l2src - > v4l2object - > videodev ) , GST_ERROR_SYSTEM ) ;
2006-03-11 22:50:03 +00:00
break ;
2004-01-12 02:19:57 +00:00
}
2006-03-11 22:50:03 +00:00
2006-03-25 05:31:28 +00:00
if ( - - trials = = - 1 ) {
return - 1 ;
} else {
2006-05-11 17:59:59 +00:00
ioctl ( v4l2src - > v4l2object - > video_fd , VIDIOC_QBUF , & buffer ) ;
2006-03-25 05:31:28 +00:00
memset ( & buffer , 0x00 , sizeof ( buffer ) ) ;
buffer . type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
buffer . memory = v4l2src - > breq . memory ;
}
2006-03-11 22:50:03 +00:00
2004-01-12 02:19:57 +00:00
}
GST_LOG_OBJECT ( v4l2src , " grabbed frame %d " , buffer . index ) ;
return buffer . index ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
* gst_v4l2src_get_capture ( ) :
* get capture parameters
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2004-03-14 22:34:33 +00:00
gst_v4l2src_get_capture ( GstV4l2Src * v4l2src )
2002-09-09 07:14:35 +00:00
{
2004-03-14 22:34:33 +00:00
DEBUG ( " Getting capture format " ) ;
2002-09-09 07:14:35 +00:00
2006-05-11 17:59:59 +00:00
GST_V4L2_CHECK_OPEN ( v4l2src - > v4l2object ) ;
2002-09-09 07:14:35 +00:00
2006-08-24 00:40:07 +00:00
memset ( & v4l2src - > format , 0 , sizeof ( struct v4l2_format ) ) ;
2004-03-14 22:34:33 +00:00
v4l2src - > format . type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2src - > v4l2object - > video_fd , VIDIOC_G_FMT , & v4l2src - > format ) < 0 ) {
2006-09-15 19:11:00 +00:00
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , SETTINGS ,
( _ ( " failed to get pixelformat for device %s " ) ,
v4l2src - > v4l2object - > videodev ) , 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_v4l2src_set_capture ( ) :
* set capture parameters
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2004-03-14 22:34:33 +00:00
gst_v4l2src_set_capture ( GstV4l2Src * v4l2src ,
2006-08-29 20:59:47 +00:00
struct v4l2_fmtdesc * fmt , gint * width , gint * height ,
guint * fps_n , guint * fps_d )
2002-09-09 07:14:35 +00:00
{
2006-08-29 20:59:47 +00:00
guint new_fps_n = * fps_n ;
guint new_fps_d = * fps_d ;
2004-03-14 22:34:33 +00:00
DEBUG ( " Setting capture format to %dx%d, format %s " ,
2006-08-24 00:40:07 +00:00
* width , * height , fmt - > description ) ;
2004-03-14 22:34:33 +00:00
2006-05-11 17:59:59 +00:00
GST_V4L2_CHECK_OPEN ( v4l2src - > v4l2object ) ;
GST_V4L2_CHECK_NOT_ACTIVE ( v4l2src - > v4l2object ) ;
2004-03-14 22:34:33 +00:00
2006-08-24 00:40:07 +00:00
if ( ! gst_v4l2src_get_capture ( v4l2src ) ) {
goto fail ;
}
v4l2src - > format . fmt . pix . width = * width ;
v4l2src - > format . fmt . pix . height = * height ;
2004-03-14 22:34:33 +00:00
v4l2src - > format . fmt . pix . pixelformat = fmt - > pixelformat ;
v4l2src - > format . fmt . pix . field = V4L2_FIELD_INTERLACED ;
v4l2src - > format . type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2src - > v4l2object - > video_fd , VIDIOC_S_FMT , & v4l2src - > format ) < 0 ) {
2006-09-15 19:11:00 +00:00
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , SETTINGS ,
( _ ( " failed to set pixelformat to %s @ %dx%d for device %s: %s " ) ,
fmt - > description , * width , * height , v4l2src - > v4l2object - > videodev ) ,
GST_ERROR_SYSTEM ) ;
2006-08-24 00:40:07 +00:00
goto fail ;
}
if ( * width ! = v4l2src - > format . fmt . pix . width | |
* height ! = v4l2src - > format . fmt . pix . height ) {
DEBUG ( " Updating size from %dx%d to %dx%d, format %s " ,
* width , * height , v4l2src - > format . fmt . pix . width ,
v4l2src - > format . fmt . pix . height , fmt - > description ) ;
2004-03-14 22:34:33 +00:00
}
/* update internal info */
2006-08-24 00:40:07 +00:00
if ( ! gst_v4l2src_get_capture ( v4l2src ) ) {
goto fail ;
}
if ( fmt - > pixelformat ! = v4l2src - > format . fmt . pix . pixelformat ) {
2006-09-15 19:11:00 +00:00
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , SETTINGS ,
( _ ( " failed to set pixelformat to %s @ %dx%d for device %s: %s " ) ,
fmt - > description , * width , * height , v4l2src - > v4l2object - > videodev ) ,
GST_ERROR_SYSTEM ) ;
2006-08-24 00:40:07 +00:00
goto fail ;
}
2006-08-29 20:59:47 +00:00
if ( * fps_n ) {
if ( gst_v4l2src_set_fps ( v4l2src , & new_fps_n , & new_fps_d ) ) {
if ( new_fps_n ! = * fps_n | | new_fps_d ! = * fps_d ) {
DEBUG ( " Updating framerate from %u/%u to %u%u " ,
* fps_n , * fps_d , new_fps_n , new_fps_d ) ;
* fps_n = new_fps_n ;
* fps_d = new_fps_d ;
}
}
} else {
if ( gst_v4l2src_get_fps ( v4l2src , & new_fps_n , & new_fps_d ) ) {
DEBUG ( " framerate is %u/%u " , new_fps_n , new_fps_d ) ;
* fps_n = new_fps_n ;
* fps_d = new_fps_d ;
}
}
2006-08-24 00:40:07 +00:00
* width = v4l2src - > format . fmt . pix . width ;
* height = v4l2src - > format . fmt . pix . height ;
return TRUE ;
fail :
return FALSE ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
* gst_v4l2src_capture_init ( ) :
* initialize the capture system
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2004-03-14 22:34:33 +00:00
gst_v4l2src_capture_init ( GstV4l2Src * v4l2src )
2002-09-09 07:14:35 +00:00
{
2004-01-12 02:19:57 +00:00
gint n ;
guint buffers ;
GST_DEBUG_OBJECT ( v4l2src , " initting the capture system " ) ;
2006-05-11 17:59:59 +00:00
GST_V4L2_CHECK_OPEN ( v4l2src - > v4l2object ) ;
GST_V4L2_CHECK_NOT_ACTIVE ( v4l2src - > v4l2object ) ;
2004-01-12 02:19:57 +00:00
/* request buffer info */
buffers = v4l2src - > breq . count ;
if ( v4l2src - > breq . count > GST_V4L2_MAX_BUFFERS ) {
v4l2src - > breq . count = GST_V4L2_MAX_BUFFERS ;
}
if ( v4l2src - > breq . count < GST_V4L2_MIN_BUFFERS ) {
v4l2src - > breq . count = GST_V4L2_MIN_BUFFERS ;
}
v4l2src - > breq . type = v4l2src - > format . type ;
2006-05-11 17:59:59 +00:00
if ( v4l2src - > v4l2object - > vcap . capabilities & V4L2_CAP_STREAMING ) {
2006-03-11 22:50:03 +00:00
v4l2src - > breq . memory = V4L2_MEMORY_MMAP ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2src - > v4l2object - > video_fd , VIDIOC_REQBUFS ,
2006-03-11 22:50:03 +00:00
& v4l2src - > breq ) < 0 ) {
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , READ ,
2006-09-02 14:28:55 +00:00
( _ ( " Could not get buffers from device '%s'. " ) ,
2006-05-11 17:59:59 +00:00
v4l2src - > v4l2object - > videodev ) ,
2006-09-15 19:11:00 +00:00
( " error requesting %d buffers. system error: %s " ,
2006-03-25 05:31:28 +00:00
v4l2src - > breq . count , g_strerror ( errno ) ) ) ;
2006-03-11 22:50:03 +00:00
return FALSE ;
}
GST_LOG_OBJECT ( v4l2src , " using default mmap method " ) ;
2006-05-11 17:59:59 +00:00
} else if ( v4l2src - > v4l2object - > vcap . capabilities & V4L2_CAP_READWRITE ) {
2006-03-11 22:50:03 +00:00
v4l2src - > breq . memory = 0 ;
GST_INFO_OBJECT ( v4l2src , " using fallback read method " ) ;
} else {
2004-01-29 23:20:45 +00:00
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , READ ,
2006-09-02 14:28:55 +00:00
( _ ( " the driver of device '%s' is broken. " ) ,
2006-05-11 17:59:59 +00:00
v4l2src - > v4l2object - > videodev ) ,
2006-03-11 22:50:03 +00:00
( " no supported read capability from %s " ,
2006-05-11 17:59:59 +00:00
v4l2src - > v4l2object - > videodev ) ) ;
2004-01-12 02:19:57 +00:00
return FALSE ;
}
2006-05-05 20:12:59 +00:00
/* Determine the device's framerate */
2006-05-11 17:59:59 +00:00
if ( ! gst_v4l2src_update_fps ( v4l2src - > v4l2object ) ) {
2006-05-05 20:12:59 +00:00
GST_DEBUG_OBJECT ( v4l2src , " frame rate is unknown. " ) ;
v4l2src - > fps_d = 1 ;
v4l2src - > fps_n = 0 ;
}
2006-03-11 22:50:03 +00:00
if ( v4l2src - > breq . memory > 0 ) {
if ( v4l2src - > breq . count < GST_V4L2_MIN_BUFFERS ) {
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , READ ,
2006-09-02 14:28:55 +00:00
( _ ( " Could not get enough buffers from device '%s'. " ) ,
2006-05-11 17:59:59 +00:00
v4l2src - > v4l2object - > videodev ) ,
2006-03-25 05:31:28 +00:00
( " we received %d, we want at least %d " ,
v4l2src - > breq . count , GST_V4L2_MIN_BUFFERS ) ) ;
2006-03-11 22:50:03 +00:00
v4l2src - > breq . count = buffers ;
2004-01-12 02:19:57 +00:00
return FALSE ;
}
2006-03-11 22:50:03 +00:00
if ( v4l2src - > breq . count ! = buffers )
g_object_notify ( G_OBJECT ( v4l2src ) , " num_buffers " ) ;
GST_INFO_OBJECT ( v4l2src ,
2006-09-15 19:11:00 +00:00
" Got %d buffers (% " GST_FOURCC_FORMAT " ) of size %d KB " ,
2006-03-11 22:50:03 +00:00
v4l2src - > breq . count ,
GST_FOURCC_ARGS ( v4l2src - > format . fmt . pix . pixelformat ) ,
v4l2src - > format . fmt . pix . sizeimage / 1024 ) ;
/* Map the buffers */
GST_LOG_OBJECT ( v4l2src , " initiating buffer pool " ) ;
v4l2src - > pool = g_new ( GstV4l2BufferPool , 1 ) ;
2006-03-12 15:33:00 +00:00
gst_atomic_int_set ( & v4l2src - > pool - > refcount , 1 ) ;
2006-05-11 17:59:59 +00:00
v4l2src - > pool - > video_fd = v4l2src - > v4l2object - > video_fd ;
2006-03-11 22:50:03 +00:00
v4l2src - > pool - > buffer_count = v4l2src - > breq . count ;
v4l2src - > pool - > buffers = g_new0 ( GstV4l2Buffer , v4l2src - > breq . count ) ;
for ( n = 0 ; n < v4l2src - > breq . count ; n + + ) {
GstV4l2Buffer * buffer = & v4l2src - > pool - > buffers [ n ] ;
2006-03-12 15:33:00 +00:00
gst_atomic_int_set ( & buffer - > refcount , 1 ) ;
2006-03-11 22:50:03 +00:00
buffer - > pool = v4l2src - > pool ;
2006-03-27 17:06:45 +00:00
memset ( & buffer - > buffer , 0x00 , sizeof ( buffer - > buffer ) ) ;
2006-03-11 22:50:03 +00:00
buffer - > buffer . index = n ;
2006-03-27 17:06:45 +00:00
buffer - > buffer . type = v4l2src - > breq . type ;
buffer - > buffer . memory = v4l2src - > breq . memory ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2src - > v4l2object - > video_fd , VIDIOC_QUERYBUF ,
2006-03-11 22:50:03 +00:00
& buffer - > buffer ) < 0 ) {
2006-09-15 19:11:00 +00:00
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , READ ,
( _ ( " Could not get buffer properties of buffer %d " ) , n ) ,
GST_ERROR_SYSTEM ) ;
2006-03-11 22:50:03 +00:00
gst_v4l2src_capture_deinit ( v4l2src ) ;
return FALSE ;
}
buffer - > start =
mmap ( 0 , buffer - > buffer . length , PROT_READ | PROT_WRITE , MAP_SHARED ,
2006-05-11 17:59:59 +00:00
v4l2src - > v4l2object - > video_fd , buffer - > buffer . m . offset ) ;
2006-03-11 22:50:03 +00:00
if ( buffer - > start = = MAP_FAILED ) {
2006-09-15 19:11:00 +00:00
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , READ ,
( _ ( " Could not mmap video buffer %d: %s " ) , n ) , GST_ERROR_SYSTEM ) ;
2006-03-11 22:50:03 +00:00
buffer - > start = 0 ;
gst_v4l2src_capture_deinit ( v4l2src ) ;
return FALSE ;
}
buffer - > length = buffer - > buffer . length ;
if ( ! gst_v4l2src_queue_frame ( v4l2src , n ) ) {
gst_v4l2src_capture_deinit ( v4l2src ) ;
return FALSE ;
}
2004-01-12 02:19:57 +00:00
}
2006-03-11 22:50:03 +00:00
} else {
GST_LOG_OBJECT ( v4l2src , " no buffer pool used " ) ;
v4l2src - > pool = NULL ;
2004-01-12 02:19:57 +00:00
}
2006-05-11 17:59:59 +00:00
GST_V4L2_SET_ACTIVE ( v4l2src - > v4l2object ) ;
2004-10-24 15:47:40 +00:00
2004-01-12 02:19:57 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
* gst_v4l2src_capture_start ( ) :
* start streaming capture
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2004-03-14 22:34:33 +00:00
gst_v4l2src_capture_start ( GstV4l2Src * v4l2src )
2002-09-09 07:14:35 +00:00
{
2004-01-12 02:19:57 +00:00
gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
2002-09-09 07:14:35 +00:00
2004-01-12 02:19:57 +00:00
GST_DEBUG_OBJECT ( v4l2src , " starting the capturing " ) ;
2004-03-14 22:34:33 +00:00
2006-05-11 17:59:59 +00:00
GST_V4L2_CHECK_OPEN ( v4l2src - > v4l2object ) ;
if ( ! GST_V4L2_IS_ACTIVE ( v4l2src - > v4l2object ) ) {
2006-03-11 22:50:03 +00:00
/* gst_pad_renegotiate (v4l2src->srcpad); FIX: is it still required in 0.10 */
2004-01-12 02:19:57 +00:00
}
2006-05-11 17:59:59 +00:00
GST_V4L2_CHECK_ACTIVE ( v4l2src - > v4l2object ) ;
2003-05-21 06:33:18 +00:00
2004-01-12 02:19:57 +00:00
v4l2src - > quit = FALSE ;
2003-05-21 06:33:18 +00:00
2006-03-11 22:50:03 +00:00
if ( v4l2src - > breq . memory ! = 0 ) {
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2src - > v4l2object - > video_fd , VIDIOC_STREAMON , & type ) < 0 ) {
2006-09-15 19:11:00 +00:00
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , OPEN_READ ,
( _ ( " Error starting streaming capture from device %s " ) ,
v4l2src - > v4l2object - > videodev ) , GST_ERROR_SYSTEM ) ;
2006-03-11 22:50:03 +00:00
return FALSE ;
}
2004-01-12 02:19:57 +00:00
}
2002-09-09 07:14:35 +00:00
2004-10-24 15:47:40 +00:00
v4l2src - > is_capturing = TRUE ;
2004-01-12 02:19:57 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
/******************************************************
* gst_v4l2src_capture_stop ( ) :
* stop streaming capture
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2004-03-14 22:34:33 +00:00
gst_v4l2src_capture_stop ( GstV4l2Src * v4l2src )
2002-09-09 07:14:35 +00:00
{
2004-01-12 02:19:57 +00:00
gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
GST_DEBUG_OBJECT ( v4l2src , " stopping capturing " ) ;
2006-05-11 17:59:59 +00:00
GST_V4L2_CHECK_OPEN ( v4l2src - > v4l2object ) ;
GST_V4L2_CHECK_ACTIVE ( v4l2src - > v4l2object ) ;
2004-01-12 02:19:57 +00:00
2006-03-11 22:50:03 +00:00
if ( v4l2src - > breq . memory ! = 0 ) {
/* we actually need to sync on all queued buffers but not
* on the non - queued ones */
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2src - > v4l2object - > video_fd , VIDIOC_STREAMOFF , & type ) < 0 ) {
2006-09-15 19:11:00 +00:00
GST_ELEMENT_ERROR ( v4l2src , RESOURCE , CLOSE ,
( _ ( " Error stopping streaming capture from device %s: %s " ) ,
v4l2src - > v4l2object - > videodev ) , GST_ERROR_SYSTEM ) ;
2006-03-11 22:50:03 +00:00
return FALSE ;
}
2004-01-12 02:19:57 +00:00
}
/* make an optional pending wait stop */
v4l2src - > quit = TRUE ;
2004-10-24 15:47:40 +00:00
v4l2src - > is_capturing = FALSE ;
2004-03-14 22:34:33 +00:00
2004-01-12 02:19:57 +00:00
return TRUE ;
}
2003-05-21 06:33:18 +00:00
2004-01-12 02:19:57 +00:00
static void
2004-03-14 22:34:33 +00:00
gst_v4l2src_buffer_pool_free ( GstV4l2BufferPool * pool , gboolean do_close )
2004-01-12 02:19:57 +00:00
{
guint i ;
for ( i = 0 ; i < pool - > buffer_count ; i + + ) {
2006-03-12 15:33:00 +00:00
gst_atomic_int_set ( & pool - > buffers [ i ] . refcount , 0 ) ;
2004-01-12 02:19:57 +00:00
munmap ( pool - > buffers [ i ] . start , pool - > buffers [ i ] . length ) ;
}
g_free ( pool - > buffers ) ;
2006-03-12 15:33:00 +00:00
gst_atomic_int_set ( & pool - > refcount , 0 ) ;
2004-01-12 02:19:57 +00:00
if ( do_close )
close ( pool - > video_fd ) ;
g_free ( pool ) ;
2002-09-09 07:14:35 +00:00
}
2006-03-11 22:50:03 +00:00
#if 0
2004-01-12 02:19:57 +00:00
void
2004-03-14 22:34:33 +00:00
gst_v4l2src_free_buffer ( GstBuffer * buffer )
2004-01-12 02:19:57 +00:00
{
GstV4l2Buffer * buf = ( GstV4l2Buffer * ) GST_BUFFER_PRIVATE ( buffer ) ;
2004-03-14 22:34:33 +00:00
2004-01-12 02:19:57 +00:00
GST_LOG ( " freeing buffer %p (nr. %d) " , buffer , buf - > buffer . index ) ;
2004-03-14 22:34:33 +00:00
2006-03-11 22:50:03 +00:00
if ( ! g_atomic_int_dec_and_test ( & buf - > refcount ) ) {
2004-01-12 02:19:57 +00:00
/* we're still in use, add to queue again
note : this might fail because the device is already stopped ( race ) */
2004-03-14 22:34:33 +00:00
if ( ioctl ( buf - > pool - > video_fd , VIDIOC_QBUF , & buf - > buffer ) < 0 )
2004-01-12 02:19:57 +00:00
GST_INFO ( " readding to queue failed, assuming video device is stopped " ) ;
}
2006-03-11 22:50:03 +00:00
if ( g_atomic_int_dec_and_test ( & buf - > pool - > refcount ) ) {
2004-01-12 02:19:57 +00:00
/* we're last thing that used all this */
gst_v4l2src_buffer_pool_free ( buf - > pool , TRUE ) ;
}
}
2002-09-09 07:14:35 +00:00
2006-03-11 22:50:03 +00:00
# endif
2002-09-09 07:14:35 +00:00
/******************************************************
* gst_v4l2src_capture_deinit ( ) :
* deinitialize the capture system
* return value : TRUE on success , FALSE on error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
gboolean
2004-03-14 22:34:33 +00:00
gst_v4l2src_capture_deinit ( GstV4l2Src * v4l2src )
2002-09-09 07:14:35 +00:00
{
2006-03-11 22:50:03 +00:00
gint i ;
gboolean try_reinit = FALSE ;
2004-03-14 22:34:33 +00:00
2004-01-12 02:19:57 +00:00
GST_DEBUG_OBJECT ( v4l2src , " deinitting capture system " ) ;
2004-03-14 22:34:33 +00:00
2006-05-11 17:59:59 +00:00
GST_V4L2_CHECK_OPEN ( v4l2src - > v4l2object ) ;
GST_V4L2_CHECK_ACTIVE ( v4l2src - > v4l2object ) ;
2004-01-12 02:19:57 +00:00
2006-03-11 22:50:03 +00:00
if ( v4l2src - > pool ) {
/* free the buffers */
for ( i = 0 ; i < v4l2src - > breq . count ; i + + ) {
if ( g_atomic_int_dec_and_test ( & v4l2src - > pool - > buffers [ i ] . refcount ) ) {
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2src - > v4l2object - > video_fd , VIDIOC_DQBUF ,
2006-03-11 22:50:03 +00:00
& v4l2src - > pool - > buffers [ i ] . buffer ) < 0 )
2006-09-15 19:11:00 +00:00
GST_DEBUG_OBJECT ( v4l2src ,
" Could not dequeue buffer on uninitialization. "
" system error: %s. Will try reinit instead " , g_strerror ( errno ) ) ;
2006-03-11 22:50:03 +00:00
try_reinit = TRUE ;
}
}
if ( g_atomic_int_dec_and_test ( & v4l2src - > pool - > refcount ) ) {
/* we're last thing that used all this */
gst_v4l2src_buffer_pool_free ( v4l2src - > pool , FALSE ) ;
}
v4l2src - > pool = NULL ;
/* This is our second try to get the buffers dequeued.
* Since buffers are normally dequeued automatically when capturing is
* stopped , but may be enqueued before capturing has started , you get
* a problem when you abort before capturing started but have enqueued
* the buffers . We avoid that by starting / stopping capturing once so
* they get auto - dequeued .
*/
if ( try_reinit ) {
if ( ! gst_v4l2src_capture_start ( v4l2src ) | |
! gst_v4l2src_capture_stop ( v4l2src ) )
return FALSE ;
}
2004-01-12 02:19:57 +00:00
}
2004-03-14 22:34:33 +00:00
2006-05-11 17:59:59 +00:00
GST_V4L2_SET_INACTIVE ( v4l2src - > v4l2object ) ;
2004-01-12 02:19:57 +00:00
return TRUE ;
2002-09-09 07:14:35 +00:00
}
2003-05-10 14:36:34 +00:00
/*
*/
gboolean
2004-03-14 22:34:33 +00:00
gst_v4l2src_get_size_limits ( GstV4l2Src * v4l2src ,
struct v4l2_fmtdesc * format ,
gint * min_w , gint * max_w , gint * min_h , gint * max_h )
2003-05-10 14:36:34 +00:00
{
2006-08-24 00:40:07 +00:00
2004-03-14 22:34:33 +00:00
struct v4l2_format fmt ;
2006-05-08 19:21:18 +00:00
GST_LOG_OBJECT ( v4l2src ,
" getting size limits with format % " GST_FOURCC_FORMAT ,
2004-03-14 22:34:33 +00:00
GST_FOURCC_ARGS ( format - > pixelformat ) ) ;
/* get size delimiters */
memset ( & fmt , 0 , sizeof ( fmt ) ) ;
fmt . type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
fmt . fmt . pix . width = 0 ;
fmt . fmt . pix . height = 0 ;
fmt . fmt . pix . pixelformat = format - > pixelformat ;
fmt . fmt . pix . field = V4L2_FIELD_INTERLACED ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2src - > v4l2object - > video_fd , VIDIOC_TRY_FMT , & fmt ) < 0 ) {
2004-03-14 22:34:33 +00:00
return FALSE ;
}
if ( min_w )
* min_w = fmt . fmt . pix . width ;
if ( min_h )
* min_h = fmt . fmt . pix . height ;
2006-09-15 19:11:00 +00:00
GST_LOG_OBJECT ( v4l2src ,
" got min size %dx%d " , fmt . fmt . pix . width , fmt . fmt . pix . height ) ;
2004-03-14 22:34:33 +00:00
2006-08-22 20:39:26 +00:00
fmt . fmt . pix . width = 4096 ;
fmt . fmt . pix . height = 4096 ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2src - > v4l2object - > video_fd , VIDIOC_TRY_FMT , & fmt ) < 0 ) {
2004-03-14 22:34:33 +00:00
return FALSE ;
}
if ( max_w )
* max_w = fmt . fmt . pix . width ;
if ( max_h )
* max_h = fmt . fmt . pix . height ;
2006-09-15 19:11:00 +00:00
GST_LOG_OBJECT ( v4l2src ,
" got max size %dx%d " , fmt . fmt . pix . width , fmt . fmt . pix . height ) ;
2004-03-14 22:34:33 +00:00
return TRUE ;
2003-05-10 14:36:34 +00:00
}
2006-03-11 22:50:03 +00:00
2006-05-11 17:59:59 +00:00
gboolean
gst_v4l2src_update_fps ( GstV4l2Object * v4l2object )
{
GstV4l2Src * v4l2src = GST_V4L2SRC ( v4l2object - > element ) ;
return gst_v4l2src_get_fps ( v4l2src , & v4l2src - > fps_n , & v4l2src - > fps_d ) ;
}
2006-08-29 20:59:47 +00:00
gboolean
gst_v4l2src_set_fps ( GstV4l2Src * v4l2src , guint * fps_n , guint * fps_d )
{
GstV4l2Object * v4l2object = v4l2src - > v4l2object ;
struct v4l2_streamparm stream ;
memset ( & stream , 0x00 , sizeof ( struct v4l2_streamparm ) ) ;
stream . type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
if ( ioctl ( v4l2object - > video_fd , VIDIOC_G_PARM , & stream ) = = 0 & &
stream . parm . capture . capability & V4L2_CAP_TIMEPERFRAME ) {
stream . parm . capture . timeperframe . denominator = * fps_n ;
stream . parm . capture . timeperframe . numerator = * fps_d ;
if ( ioctl ( v4l2object - > video_fd , VIDIOC_S_PARM , & stream ) = = 0 ) {
* fps_n = stream . parm . capture . timeperframe . denominator ;
* fps_d = stream . parm . capture . timeperframe . numerator ;
return TRUE ;
}
}
return FALSE ;
}
2006-03-11 22:50:03 +00:00
gboolean
2006-05-05 20:12:59 +00:00
gst_v4l2src_get_fps ( GstV4l2Src * v4l2src , guint * fps_n , guint * fps_d )
2006-03-11 22:50:03 +00:00
{
2006-05-11 17:59:59 +00:00
GstV4l2Object * v4l2object = v4l2src - > v4l2object ;
2006-03-11 22:50:03 +00:00
v4l2_std_id std ;
2006-05-05 20:12:59 +00:00
struct v4l2_streamparm stream ;
2006-03-11 22:50:03 +00:00
const GList * item ;
2006-05-11 17:59:59 +00:00
if ( ! GST_V4L2_IS_OPEN ( v4l2object ) )
2006-03-11 22:50:03 +00:00
return FALSE ;
2006-05-05 20:12:59 +00:00
/* Try to get the frame rate directly from the device using VIDIOC_G_PARM */
2006-08-29 20:59:47 +00:00
memset ( & stream , 0x00 , sizeof ( struct v4l2_streamparm ) ) ;
2006-05-05 20:12:59 +00:00
stream . type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
2006-05-11 17:59:59 +00:00
if ( ioctl ( v4l2object - > video_fd , VIDIOC_G_PARM , & stream ) = = 0 & &
stream . parm . capture . capability & V4L2_CAP_TIMEPERFRAME ) {
2006-05-05 20:12:59 +00:00
/* Note: V4L2 gives us the frame interval, we need the frame rate */
* fps_n = stream . parm . capture . timeperframe . denominator ;
* fps_d = stream . parm . capture . timeperframe . numerator ;
2006-09-15 19:11:00 +00:00
GST_DEBUG_OBJECT ( v4l2src ,
" frame rate returned by G_PARM: %d/%d fps " , * fps_n , * fps_d ) ;
2006-05-05 20:12:59 +00:00
return TRUE ;
}
/* If G_PARM failed, try to get the same information from the video standard */
2006-05-11 17:59:59 +00:00
if ( ! gst_v4l2_get_norm ( v4l2object , & std ) )
2006-03-11 22:50:03 +00:00
return FALSE ;
2006-05-11 17:59:59 +00:00
for ( item = v4l2object - > stds ; item ! = NULL ; item = item - > next ) {
2006-03-11 22:50:03 +00:00
GstV4l2TunerNorm * v4l2norm = item - > data ;
if ( v4l2norm - > index = = std ) {
* fps_n =
gst_value_get_fraction_numerator ( & GST_TUNER_NORM ( v4l2norm ) - >
framerate ) ;
* fps_d =
gst_value_get_fraction_denominator ( & GST_TUNER_NORM ( v4l2norm ) - >
framerate ) ;
2006-09-15 19:11:00 +00:00
GST_DEBUG_OBJECT ( v4l2src ,
" frame rate returned by get_norm: %d/%d fps " , * fps_n , * fps_d ) ;
2006-03-11 22:50:03 +00:00
return TRUE ;
}
}
return FALSE ;
}
# define GST_TYPE_V4L2SRC_BUFFER (gst_v4l2src_buffer_get_type())
# define GST_IS_V4L2SRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2SRC_BUFFER))
# define GST_V4L2SRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2SRC_BUFFER, GstV4l2SrcBuffer))
typedef struct _GstV4l2SrcBuffer
{
GstBuffer buffer ;
GstV4l2Buffer * buf ;
} GstV4l2SrcBuffer ;
static void gst_v4l2src_buffer_class_init ( gpointer g_class ,
gpointer class_data ) ;
static void gst_v4l2src_buffer_init ( GTypeInstance * instance ,
gpointer g_class ) ;
static void gst_v4l2src_buffer_finalize ( GstV4l2SrcBuffer * v4l2src_buffer ) ;
GType
gst_v4l2src_buffer_get_type ( void )
{
static GType _gst_v4l2src_buffer_type ;
if ( G_UNLIKELY ( _gst_v4l2src_buffer_type = = 0 ) ) {
static const GTypeInfo v4l2src_buffer_info = {
sizeof ( GstBufferClass ) ,
NULL ,
NULL ,
gst_v4l2src_buffer_class_init ,
NULL ,
NULL ,
sizeof ( GstV4l2SrcBuffer ) ,
0 ,
gst_v4l2src_buffer_init ,
NULL
} ;
_gst_v4l2src_buffer_type = g_type_register_static ( GST_TYPE_BUFFER ,
" GstV4l2SrcBuffer " , & v4l2src_buffer_info , 0 ) ;
}
return _gst_v4l2src_buffer_type ;
}
static void
gst_v4l2src_buffer_class_init ( gpointer g_class , gpointer class_data )
{
GstMiniObjectClass * mini_object_class = GST_MINI_OBJECT_CLASS ( g_class ) ;
mini_object_class - > finalize = ( GstMiniObjectFinalizeFunction )
gst_v4l2src_buffer_finalize ;
}
static void
gst_v4l2src_buffer_init ( GTypeInstance * instance , gpointer g_class )
{
}
static void
gst_v4l2src_buffer_finalize ( GstV4l2SrcBuffer * v4l2src_buffer )
{
GstV4l2Buffer * buf = v4l2src_buffer - > buf ;
if ( buf ) {
GST_LOG ( " freeing buffer %p (nr. %d) " , buf , buf - > buffer . index ) ;
if ( ! g_atomic_int_dec_and_test ( & buf - > refcount ) ) {
/* we're still in use, add to queue again
note : this might fail because the device is already stopped ( race ) */
if ( ioctl ( buf - > pool - > video_fd , VIDIOC_QBUF , & buf - > buffer ) < 0 )
GST_INFO ( " readding to queue failed, assuming video device is stopped " ) ;
}
if ( g_atomic_int_dec_and_test ( & buf - > pool - > refcount ) ) {
/* we're last thing that used all this */
gst_v4l2src_buffer_pool_free ( buf - > pool , TRUE ) ;
}
}
}
/* Create a V4l2Src buffer from our mmap'd data area */
GstBuffer *
gst_v4l2src_buffer_new ( GstV4l2Src * v4l2src , guint size , guint8 * data ,
GstV4l2Buffer * srcbuf )
{
GstBuffer * buf ;
if ( data = = NULL ) {
2006-04-13 21:45:57 +00:00
buf = gst_buffer_new_and_alloc ( size ) ;
2006-03-11 22:50:03 +00:00
} else {
2006-04-13 21:45:57 +00:00
buf = ( GstBuffer * ) gst_mini_object_new ( GST_TYPE_V4L2SRC_BUFFER ) ;
2006-03-11 22:50:03 +00:00
GST_BUFFER_DATA ( buf ) = data ;
2006-04-13 21:45:57 +00:00
GST_V4L2SRC_BUFFER ( buf ) - > buf = srcbuf ;
2006-09-15 19:11:00 +00:00
GST_LOG_OBJECT ( v4l2src ,
" creating buffer %p (nr. %d) " , srcbuf , srcbuf - > buffer . index ) ;
2006-03-11 22:50:03 +00:00
}
2006-04-13 21:45:57 +00:00
2006-05-08 19:21:18 +00:00
2006-03-11 22:50:03 +00:00
GST_BUFFER_SIZE ( buf ) = size ;
GST_BUFFER_TIMESTAMP ( buf ) =
gst_clock_get_time ( GST_ELEMENT ( v4l2src ) - > clock ) ;
GST_BUFFER_TIMESTAMP ( buf ) - = GST_ELEMENT ( v4l2src ) - > base_time ;
2006-09-15 19:11:00 +00:00
GST_BUFFER_OFFSET ( buf ) = v4l2src - > offset + + ;
2006-03-11 22:50:03 +00:00
GST_BUFFER_FLAG_SET ( buf , GST_BUFFER_FLAG_READONLY ) ;
2006-05-05 20:12:59 +00:00
if ( v4l2src - > fps_n > 0 ) {
GST_BUFFER_DURATION ( buf ) =
2006-09-18 15:36:14 +00:00
gst_util_uint64_scale_int ( GST_SECOND , v4l2src - > fps_d , v4l2src - > fps_n ) ;
2006-03-25 05:31:28 +00:00
} else {
GST_BUFFER_DURATION ( buf ) = GST_CLOCK_TIME_NONE ;
}
2006-03-11 22:50:03 +00:00
/* the negotiate() method already set caps on the source pad */
gst_buffer_set_caps ( buf , GST_PAD_CAPS ( GST_BASE_SRC_PAD ( v4l2src ) ) ) ;
return buf ;
}