Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
v4l.c
Package: unicap-0.2.19.tar.gz [view]
Upload User: shyika
Upload Date: 2017-11-25
Package Size: 1227k
Code Size: 27k
Category:
Video Capture
Development Platform:
Unix_Linux
- /*
- unicap
- Copyright (C) 2004 Arne Caspari
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program 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 General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include "config.h"
- #include <unicap.h>
- #include <unicap_status.h>
- #include <unicap_cpi.h>
- #include <queue.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/ioctl.h>
- #include <sys/mman.h>
- #include <fcntl.h>
- #include <dirent.h>
- #include <semaphore.h>
- #include <pthread.h>
- #include <errno.h>
- #include <sys/time.h>
- #include <time.h>
- #if V4L_DEBUG
- #define DEBUG
- #endif
- #include <debug.h>
- #include <linux/videodev.h>
- #include <linux/videodev2.h> // for v4l2 checks
- #include "v4l.h"
- unsigned int v4l_palette_array[] =
- {
- VIDEO_PALETTE_GREY,
- VIDEO_PALETTE_HI240,
- VIDEO_PALETTE_RGB565,
- VIDEO_PALETTE_RGB555,
- VIDEO_PALETTE_RGB24,
- VIDEO_PALETTE_RGB32,
- VIDEO_PALETTE_YUV422,
- VIDEO_PALETTE_YUYV,
- VIDEO_PALETTE_UYVY,
- VIDEO_PALETTE_YUV420,
- VIDEO_PALETTE_YUV411,
- VIDEO_PALETTE_RAW,
- VIDEO_PALETTE_YUV422P,
- VIDEO_PALETTE_YUV411P,
- };
- static unicap_status_t v4l_enumerate_devices( unicap_device_t *device, int index );
- static unicap_status_t v4l_open( void **cpi_data, unicap_device_t *device );
- static unicap_status_t v4l_close( void *cpi_data );
- static unicap_status_t v4l_reenumerate_formats( void *cpi_data, int *count );
- static unicap_status_t v4l_enumerate_formats( void *cpi_data, unicap_format_t *format, int index );
- static unicap_status_t v4l_set_format( void *cpi_data, unicap_format_t *format );
- static unicap_status_t v4l_get_format( void *cpi_data, unicap_format_t *format );
- static unicap_status_t v4l_reenumerate_properties( void *cpi_data, int *count );
- static unicap_status_t v4l_enumerate_properties( void *cpi_data, unicap_property_t *property, int index );
- static unicap_status_t v4l_set_property( void *cpi_data, unicap_property_t *property );
- static unicap_status_t v4l_get_property( void *cpi_data, unicap_property_t *property );
- static unicap_status_t v4l_capture_start( void *cpi_data );
- static unicap_status_t v4l_capture_stop( void *cpi_data );
- static unicap_status_t v4l_queue_buffer( void *cpi_data, unicap_data_buffer_t *buffer );
- static unicap_status_t v4l_dequeue_buffer( void *cpi_data, unicap_data_buffer_t **buffer );
- static unicap_status_t v4l_wait_buffer( void *cpi_data, unicap_data_buffer_t **buffer );
- static unicap_status_t v4l_poll_buffer( void *cpi_data, int *count );
- static unicap_status_t v4l_set_event_notify( void *cpi_data,
- unicap_event_callback_t func,
- unicap_handle_t unicap_handle );
- static void v4l_capture_thread( v4l_handle_t handle );
- static int queue_buffer( v4l_handle_t v4lhandle, int b );
- static struct _unicap_cpi cpi_s =
- {
- cpi_version: 1<<16,
- cpi_capabilities: 0x3ffff,
- cpi_enumerate_devices: v4l_enumerate_devices,
- cpi_open: v4l_open,
- cpi_close: v4l_close,
- cpi_reenumerate_formats: v4l_reenumerate_formats,
- cpi_enumerate_formats: v4l_enumerate_formats,
- cpi_set_format: v4l_set_format,
- cpi_get_format: v4l_get_format,
- cpi_reenumerate_properties: v4l_reenumerate_properties,
- cpi_enumerate_properties: v4l_enumerate_properties,
- cpi_set_property: v4l_set_property,
- cpi_get_property: v4l_get_property,
- cpi_capture_start: v4l_capture_start,
- cpi_capture_stop: v4l_capture_stop,
- cpi_queue_buffer: v4l_queue_buffer,
- cpi_dequeue_buffer: v4l_dequeue_buffer,
- cpi_wait_buffer: v4l_wait_buffer,
- cpi_poll_buffer: v4l_poll_buffer,
- cpi_set_event_notify: v4l_set_event_notify,
- };
- #if ENABLE_STATIC_CPI
- void unicap_v4l_register_static_cpi( struct _unicap_cpi **cpi )
- {
- *cpi = &cpi_s;
- }
- #else
- unicap_status_t cpi_register( struct _unicap_cpi *reg_data )
- {
- memcpy( reg_data, &cpi_s, sizeof( struct _unicap_cpi ) );
- /* reg_data->cpi_version = 1<<16; */
- /* reg_data->cpi_capabilities = 0x3ffff; */
- /* reg_data->cpi_enumerate_devices = v4l_enumerate_devices; */
- /* reg_data->cpi_open = v4l_open; */
- /* reg_data->cpi_close = v4l_close; */
- /* reg_data->cpi_reenumerate_formats = v4l_reenumerate_formats; */
- /* reg_data->cpi_enumerate_formats = v4l_enumerate_formats; */
- /* reg_data->cpi_set_format = v4l_set_format; */
- /* reg_data->cpi_get_format = v4l_get_format; */
- /* reg_data->cpi_reenumerate_properties = v4l_reenumerate_properties; */
- /* reg_data->cpi_enumerate_properties = v4l_enumerate_properties; */
- /* reg_data->cpi_set_property = v4l_set_property; */
- /* reg_data->cpi_get_property = v4l_get_property; */
- /* reg_data->cpi_capture_start = v4l_capture_start; */
- /* reg_data->cpi_capture_stop = v4l_capture_stop; */
- /* reg_data->cpi_queue_buffer = v4l_queue_buffer; */
- /* reg_data->cpi_dequeue_buffer = v4l_dequeue_buffer; */
- /* reg_data->cpi_wait_buffer = v4l_wait_buffer; */
- /* reg_data->cpi_poll_buffer = v4l_poll_buffer; */
- /* reg_data->cpi_set_event_notify = v4l_set_event_notify; */
- return STATUS_SUCCESS;
- }
- #endif//ENABLE_STATIC_CPI
- static int file_filter( const struct dirent *a )
- {
- int match = 0;
- // match: 'videoXY' where X = {0..9} and Y = {0..9}
- if( !strncmp( a->d_name, "video", 5 ) )
- {
- if( strlen( a->d_name ) > 5 )
- {
- if( ( a->d_name[5] >= '0' ) && ( a->d_name[5] <= '9' ) ) // match
- // the 'X'
- {
- match = 1;
- }
- if( strlen( a->d_name ) > 6 )
- {
- match = 0;
- if( ( a->d_name[6] >= '0' ) && ( a->d_name[6] <= '9' ) )
- {
- match = 1;
- }
- }
- if( strlen( a->d_name ) > 7 )
- {
- match = 0;
- }
- }
- }
- return match;
- }
- static unicap_status_t v4l_enumerate_devices( unicap_device_t *device, int index )
- {
- int fd;
- char devname[256];
- struct dirent **namelist;
- int n;
- int found = -1;
- int i = 0;
- int dev_index = -1;
- struct video_capability v4lcap;
- struct v4l2_capability v4l2caps;
- TRACE( "*** v4l enumerate devicesn" );
- n = scandir( "/dev", &namelist, file_filter, alphasort );
- if( n < 0 )
- {
- TRACE( "Failed to scan directory '/dev' n" );
- return STATUS_NO_DEVICE;
- }
- while( ( found != index ) && n-- )
- {
- sprintf( devname, "/dev/%s", namelist[n]->d_name );
- /* free( namelist[n]->d_name ); */
- TRACE( "v4l: open %sn", devname );
- if( ( fd = open( devname, O_RDONLY | O_NONBLOCK ) ) == -1 )
- {
- TRACE( "v4l_cpi: open(%s): %sn", devname, strerror( errno ) );
- continue;
- }
- if( ioctl( fd, VIDIOC_QUERYCAP, &v4l2caps ) == 0 )
- {
- TRACE( "v4l2 ioctls succeededn" );
- close( fd );
- continue;
- }
- if( (v4l2caps.capabilities & V4L2_CAP_VIDEO_CAPTURE) )
- {
- // v4l version two device
- close( fd );
- continue;
- }
- if( ioctl( fd, VIDIOCGCAP, &v4lcap ) < 0 )
- {
- TRACE( "VIDIOCGCAP ioctl failed!n" );
- close( fd );
- continue;
- }
- if( !(v4lcap.type & VID_TYPE_CAPTURE ) )
- {
- // no capture to memory capability
- close( fd );
- continue;
- }
- found++;
- close( fd );
- }
- /* free( namelist ); */
- if( found != index )
- {
- return STATUS_NO_DEVICE;
- }
- sprintf( device->identifier, "%s [%d]", v4lcap.name, index );
- strcpy( device->device, devname );
- strcpy( device->model_name, v4lcap.name );
- strcpy( device->vendor_name, "v4l" );
- device->model_id = 1;
- device->vendor_id = 0xffff0000;
- device->flags = UNICAP_CPI_SERIALIZED;
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_open( void **cpi_data, unicap_device_t *device )
- {
- v4l_handle_t v4lhandle;
- *cpi_data = malloc( sizeof( struct _v4l_handle ) );
- if( !cpi_data )
- {
- TRACE( "malloc failedn" );
- return STATUS_FAILURE;
- }
- v4lhandle = *cpi_data;
- memset( v4lhandle, 0x0, sizeof( struct _v4l_handle ) );
- if( sem_init( &v4lhandle->sema, 0, 1 ) )
- {
- TRACE( "sem_init failedn" );
- free( v4lhandle );
- return STATUS_FAILURE;
- }
- if( sem_init( &v4lhandle->out_sema, 0, 0 ) )
- {
- TRACE( "sem_init failed!n" );
- sem_destroy( &v4lhandle->sema );
- free( v4lhandle );
- return STATUS_FAILURE;
- }
- v4lhandle->fd = open( device->device, O_RDWR );
- if( v4lhandle->fd == -1 )
- {
- TRACE( "open failed, device = %sn", device->device );
- TRACE( "error was: %sn", strerror( errno ) );
- return STATUS_FAILURE;
- }
- if( ioctl( v4lhandle->fd, VIDIOCGCAP, &v4lhandle->v4lcap ) )
- {
- // failed v4l ioctl, look for next device
- close( v4lhandle->fd );
- return STATUS_FAILURE;
- }
- v4l_reenumerate_formats( v4lhandle, NULL );
- v4l_reenumerate_properties( v4lhandle, NULL );
- v4lhandle->in_queue = malloc( sizeof( struct _unicap_queue ) );
- v4lhandle->out_queue = malloc( sizeof( struct _unicap_queue ) );
- _init_queue( v4lhandle->in_queue );
- _init_queue( v4lhandle->out_queue );
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_close( void *cpi_data )
- {
- v4l_handle_t v4lhandle = ( v4l_handle_t ) cpi_data;
- close( v4lhandle->fd );
- sem_destroy( &v4lhandle->sema );
- sem_destroy( &v4lhandle->out_sema );
- if( v4lhandle->unicap_handle )
- {
- // handle is a copy!!
- free( v4lhandle->unicap_handle );
- }
- free( v4lhandle );
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_reenumerate_formats( void *cpi_data, int *_pcount )
- {
- v4l_handle_t v4lhandle = ( v4l_handle_t ) cpi_data;
- struct video_picture v4lpict;
- int count = 0;
- int p_count = sizeof( v4l_palette_array ) / sizeof( unsigned int );
- int i;
- if( ioctl( v4lhandle->fd, VIDIOCGPICT, &v4lhandle->v4lpict ) )
- {
- TRACE( "ioctl failedn" );
- return STATUS_FAILURE;
- }
- memset( &v4lhandle->palette, 0x0, 32 * sizeof( unsigned int ) );
- memcpy( &v4lpict, &v4lhandle->v4lpict, sizeof( struct video_picture ) );
- for( i = 0; i < p_count; i++ )
- {
- v4lpict.palette = v4l_palette_array[i];
- TRACE( "try palette: %dn", v4lpict.palette );
- if( !ioctl( v4lhandle->fd, VIDIOCSPICT, &v4lpict ) )
- {
- TRACE( "succeeded palette: %dn", v4lpict.palette );
- v4lhandle->palette[i] = v4lpict.palette;
- count++;
- }
- }
- if( _pcount )
- {
- *_pcount = count;
- }
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_enumerate_formats( void *cpi_data, unicap_format_t *format, int index )
- {
- v4l_handle_t v4lhandle = ( v4l_handle_t ) cpi_data;
- unsigned int p = 0xffffffff;
- int p_count = sizeof( v4l_palette_array ) / sizeof( unsigned int );
- int i, j = -1;
- int tmp;
- if( v4lhandle->v4lpict.palette == 0 )
- {
- v4l_reenumerate_formats( cpi_data, &tmp );
- }
- for( i = 0; i < p_count; i++ )
- {
- if( v4lhandle->palette[i] )
- {
- j++;
- }
- if( j == index )
- {
- p = v4lhandle->palette[i];
- TRACE( "p: %dn", p );
- break;
- }
- }
- if( p == 0xffffffff )
- {
- return STATUS_NO_MATCH;
- }
- switch( p )
- {
- case VIDEO_PALETTE_GREY:
- strcpy( format->identifier, "Grey ( Mono 8pp )" );
- format->fourcc = FOURCC( 'G', 'R', 'E', 'Y' );
- format->bpp = 8;
- break;
- case VIDEO_PALETTE_HI240:
- strcpy( format->identifier, "HI240 Bt848 8Bit color cube" );
- format->fourcc = FOURCC( 'H', '2', '4', '0' );
- format->bpp = 8;
- break;
- case VIDEO_PALETTE_RGB565:
- strcpy( format->identifier, "RGB 16bpp" );
- format->fourcc = FOURCC( 'R', 'G', 'B', '6' );
- format->bpp = 16;
- break;
- case VIDEO_PALETTE_RGB555:
- strcpy( format->identifier, "RGB 15bpp" );
- format->fourcc = FOURCC( 'R', 'G', 'B', '5' );
- format->bpp = 15;
- break;
- case VIDEO_PALETTE_RGB24:
- strcpy( format->identifier, "BGR 24bpp" );
- format->fourcc = FOURCC( 'B', 'G', 'R', '3' );
- format->bpp = 24;
- break;
- case VIDEO_PALETTE_RGB32:
- strcpy( format->identifier, "RGB 32bpp" );
- format->fourcc = FOURCC( 'R', 'G', 'B', '4' );
- format->bpp = 32;
- break;
- case VIDEO_PALETTE_YUV422:
- strcpy( format->identifier, "YUV 4:2:2" );
- format->fourcc = FOURCC( 'Y', '4', '2', '2' );
- format->bpp = 16;
- break;
- case VIDEO_PALETTE_YUYV:
- strcpy( format->identifier, "YUYV" );
- format->fourcc = FOURCC( 'Y', 'U', 'Y', 'V' );
- format->bpp = 16;
- break;
- case VIDEO_PALETTE_UYVY:
- strcpy( format->identifier, "UYVY" );
- format->fourcc = FOURCC( 'U', 'Y', 'V', 'Y' );
- format->bpp = 16;
- break;
- case VIDEO_PALETTE_YUV420:
- strcpy( format->identifier, "Y 4:2:0" );
- format->fourcc = FOURCC( 'Y', '4', '2', '0' );
- format->bpp = 16;
- break;
- case VIDEO_PALETTE_YUV411:
- strcpy( format->identifier, "Y 4:1:1" );
- format->fourcc = FOURCC( 'Y', '4', '1', '1' );
- format->bpp = 12;
- break;
- case VIDEO_PALETTE_RAW:
- strcpy( format->identifier, "Bt848 raw format" );
- format->fourcc = FOURCC( 'R', 'A', 'W', ' ' );
- format->bpp = 8;
- break;
- case VIDEO_PALETTE_YUV422P:
- strcpy( format->identifier, "Y 4:2:2 planar" );
- format->fourcc = FOURCC( 'Y', '4', '2', 'P' );
- format->bpp = 16;
- break;
- case VIDEO_PALETTE_YUV411P:
- strcpy( format->identifier, "Y 4:1:1 planar" );
- format->fourcc = FOURCC( '4', '1', '1', 'P' );
- format->bpp = 12;
- break;
- default:
- TRACE( "unknown format / wrong indexn" );
- return STATUS_FAILURE;
- }
- format->size.width = v4lhandle->v4lcap.maxwidth;
- format->size.height = v4lhandle->v4lcap.maxheight;
- format->min_size.width = v4lhandle->v4lcap.minwidth;
- format->max_size.width = v4lhandle->v4lcap.maxwidth;
- format->min_size.height = v4lhandle->v4lcap.minheight;
- format->max_size.height = v4lhandle->v4lcap.maxheight;
- format->buffer_size = format->size.width * format->size.height * format->bpp / 8;
- format->sizes = 0;
- format->size_count = 0;
- format->h_stepping = 0;
- format->v_stepping = 0;
- #ifdef DEBUG
- TRACE( "bsize: %d, wxhxb: %dx%dx%dn", format->buffer_size, format->size.width, format->size.height, format->bpp );
- {
- char str[1024];
- int s = 1024;
- unicap_describe_format( format, str, &s );
- printf( str );
- }
- #endif
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_set_format( void *cpi_data, unicap_format_t *format )
- {
- v4l_handle_t v4lhandle = ( v4l_handle_t ) cpi_data;
- unsigned int p;
- switch( format->fourcc )
- {
- case FOURCC( 'G', 'R', 'E', 'Y' ):
- p = VIDEO_PALETTE_GREY;
- break;
- case FOURCC( 'H', '2', '4', '0' ):
- p = VIDEO_PALETTE_HI240;
- break;
- case FOURCC( 'R', 'G', 'B', '6' ):
- p = VIDEO_PALETTE_RGB565;
- break;
- case FOURCC( 'R', 'G', 'B', '5' ):
- p = VIDEO_PALETTE_RGB555;
- break;
- case FOURCC( 'B', 'G', 'R', '3' ):
- p = VIDEO_PALETTE_RGB24;
- break;
- case FOURCC( 'R', 'G', 'B', '4' ):
- p = VIDEO_PALETTE_RGB32;
- break;
- case FOURCC( 'Y', '4', '2', '2' ):
- p = VIDEO_PALETTE_YUV422;
- break;
- case FOURCC( 'Y', 'U', 'Y', 'V' ):
- p = VIDEO_PALETTE_YUYV;
- break;
- case FOURCC( 'U', 'Y', 'V', 'Y' ):
- p = VIDEO_PALETTE_UYVY;
- break;
- case FOURCC( 'Y', '4', '2', '0' ):
- p = VIDEO_PALETTE_YUV420;
- break;
- case FOURCC( 'Y', '4', '1', '1' ):
- p = VIDEO_PALETTE_YUV411;
- break;
- case FOURCC( 'R', 'A', 'W', ' ' ):
- p = VIDEO_PALETTE_RAW;
- break;
- case FOURCC( 'Y', '4', '2', 'P' ):
- p = VIDEO_PALETTE_YUV422P;
- break;
- case FOURCC( '4', '1', '1', 'P' ):
- p = VIDEO_PALETTE_YUV411P;
- break;
- default:
- TRACE( "set format with unknown fourccn" );
- return STATUS_FAILURE;
- break;
- }
- // get current settings for brightness etc.
- if( ioctl( v4lhandle->fd, VIDIOCGPICT, &v4lhandle->v4lpict ) )
- {
- TRACE( "ioctl failed: %sn", strerror( errno ) );
- return STATUS_FAILURE;
- }
- v4lhandle->v4lpict.palette = p;
- v4lhandle->v4lpict.depth = format->bpp;
- TRACE( "ioctl VIDIOCSPICTn" );
- if( ioctl( v4lhandle->fd, VIDIOCSPICT, &v4lhandle->v4lpict ) )
- {
- TRACE( "ioctl failed: %sn", strerror( errno ) );
- TRACE( "p: %dn", v4lhandle->v4lpict.palette );
- return STATUS_FAILURE;
- }
- if( ioctl( v4lhandle->fd, VIDIOCGPICT, &v4lhandle->v4lpict ) )
- {
- TRACE( "ioctl failed: %sn", strerror( errno ) );
- TRACE( "p: %dn", v4lhandle->v4lpict.palette );
- return STATUS_FAILURE;
- }
- TRACE( "result: depth: %d palette: %dn", v4lhandle->v4lpict.depth, v4lhandle->v4lpict.palette );
- memset( &v4lhandle->v4lwindow, 0x0, sizeof( struct video_window ) );
- v4lhandle->v4lwindow.width = format->size.width;
- v4lhandle->v4lwindow.height = format->size.height;
- TRACE( "ioctl VIDIOCSWIN size: %dx%dn", v4lhandle->v4lwindow.width, v4lhandle->v4lwindow.height );
- if( ioctl( v4lhandle->fd, VIDIOCSWIN, &v4lhandle->v4lwindow ) )
- {
- TRACE( "ioctl failed: %sn", strerror( errno ) );
- return STATUS_FAILURE;
- }
- if( ioctl( v4lhandle->fd, VIDIOCGWIN, &v4lhandle->v4lwindow ) )
- {
- TRACE( "ioctl failed: %sn", strerror( errno ) );
- return STATUS_FAILURE;
- }
- TRACE( "succeeded: size: %dx%d n", v4lhandle->v4lwindow.x, v4lhandle->v4lwindow.y );
- unicap_copy_format( &v4lhandle->current_format, format );
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_get_format( void *cpi_data, unicap_format_t *format )
- {
- v4l_handle_t v4lhandle = ( v4l_handle_t ) cpi_data;
- memcpy( format, &v4lhandle->current_format, sizeof( unicap_format_t ) );
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_reenumerate_properties( void *cpi_data, int *_pcount )
- {
- v4l_handle_t v4lhandle = ( v4l_handle_t ) cpi_data;
- if( ioctl( v4lhandle->fd, VIDIOCGPICT, &v4lhandle->v4lpict_default ) )
- {
- TRACE( "ioctl failed: %sn", strerror( errno ) );
- return STATUS_FAILURE;
- }
- if( _pcount )
- {
- *_pcount = 5;
- }
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_enumerate_properties( void *cpi_data, unicap_property_t *property, int index )
- {
- v4l_handle_t v4lhandle = ( v4l_handle_t ) cpi_data;
- memset( property, 0x0, sizeof( unicap_property_t ) );
- switch( index )
- {
- case 0:
- strcpy( property->identifier, "brightness" );
- property->value = v4lhandle->v4lpict_default.brightness;
- break;
- case 1:
- strcpy( property->identifier, "hue" );
- property->value = v4lhandle->v4lpict_default.hue;
- break;
- case 2:
- strcpy( property->identifier, "colour" );
- property->value = v4lhandle->v4lpict_default.colour;
- break;
- case 3:
- strcpy( property->identifier, "contrast" );
- property->value = v4lhandle->v4lpict_default.contrast;
- break;
- case 4:
- strcpy( property->identifier, "whiteness" );
- property->value = v4lhandle->v4lpict_default.whiteness;
- break;
- default:
- return STATUS_NO_MATCH;
- }
- property->range.min = 0.0f;
- property->range.max = 1.0f;
- property->value = property->value / 65535.0f;
- property->flags = UNICAP_FLAGS_MANUAL;
- property->flags_mask = UNICAP_FLAGS_MANUAL;
- property->stepping = 1.0f/256.0f;
- strcpy( property->category, "video" );
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_set_property( void *cpi_data, unicap_property_t *property )
- {
- v4l_handle_t v4lhandle = ( v4l_handle_t ) cpi_data;
- int value = property->value * 65535;
- if( !strcmp( property->identifier, "brightness" ) )
- {
- v4lhandle->v4lpict.brightness = value;
- }
- else if( !strcmp( property->identifier, "hue" ) )
- {
- v4lhandle->v4lpict.hue = value;
- }
- else if( !strcmp( property->identifier, "colour" ) )
- {
- v4lhandle->v4lpict.colour = value;
- }
- else if( !strcmp( property->identifier, "contrast" ) )
- {
- v4lhandle->v4lpict.contrast = value;
- }
- else if( !strcmp( property->identifier, "whiteness" ) )
- {
- v4lhandle->v4lpict.whiteness = value;
- }
- else
- {
- return STATUS_FAILURE;
- }
- if( ioctl( v4lhandle->fd, VIDIOCSPICT, &v4lhandle->v4lpict ) )
- {
- TRACE( "ioctl failed: %sn", strerror( errno ) );
- return STATUS_FAILURE;
- }
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_get_property( void *cpi_data, unicap_property_t *property )
- {
- v4l_handle_t v4lhandle = ( v4l_handle_t ) cpi_data;
- double value;
- if( ioctl( v4lhandle->fd, VIDIOCGPICT, &v4lhandle->v4lpict ) )
- {
- TRACE( "ioctl failed: %sn", strerror( errno ) );
- return STATUS_FAILURE;
- }
- if( !strcmp( property->identifier, "brightness" ) )
- {
- value = v4lhandle->v4lpict.brightness;
- }
- else if( !strcmp( property->identifier, "hue" ) )
- {
- value = v4lhandle->v4lpict.hue;
- }
- else if( !strcmp( property->identifier, "colour" ) )
- {
- value = v4lhandle->v4lpict.colour;
- }
- else if( !strcmp( property->identifier, "contrast" ) )
- {
- value = v4lhandle->v4lpict.contrast;
- }
- else if( !strcmp( property->identifier, "whiteness" ) )
- {
- value = v4lhandle->v4lpict.whiteness;
- }
- else
- {
- return STATUS_FAILURE;
- }
- property->range.min = 0.0f;
- property->range.max = 1.0f;
- property->value = value / 65535.0f;
- property->flags = UNICAP_FLAGS_MANUAL;
- property->flags_mask = UNICAP_FLAGS_MANUAL;
- property->stepping = 1.0f/256.0f;
- strcpy( property->category, "video" );
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_capture_start( void *cpi_data )
- {
- v4l_handle_t v4lhandle = ( v4l_handle_t ) cpi_data;
- int i;
- if( ioctl( v4lhandle->fd, VIDIOCGMBUF, &v4lhandle->v4lmbuf ) == -1 )
- {
- TRACE( "ioctl failed: %sn", strerror( errno ) );
- return STATUS_FAILURE;
- }
- TRACE( "mbuf: size: %d, frames: %dn", v4lhandle->v4lmbuf.size, v4lhandle->v4lmbuf.frames );
- for( i = 0; i < v4lhandle->v4lmbuf.frames; i++ )
- {
- TRACE( "offset %d: %xn", i, v4lhandle->v4lmbuf.offsets[i] );
- }
- v4lhandle->map = mmap( 0, v4lhandle->v4lmbuf.size, PROT_WRITE | PROT_READ, MAP_SHARED, v4lhandle->fd, 0 );
- if( v4lhandle->map == MAP_FAILED )
- {
- /* ERROR( "mmap failed: %snCapture can not start!n", strerror( errno ) ); */
- return STATUS_FAILURE;
- }
- TRACE( "map: %pn", v4lhandle->map );
- v4lhandle->ready_buffer = -1;
- for( i = 0; i < v4lhandle->v4lmbuf.frames; i++ )
- {
- queue_buffer( v4lhandle, i );
- }
- v4lhandle->quit_capture_thread = 0;
- pthread_create( &v4lhandle->capture_thread, NULL, v4l_capture_thread, v4lhandle );
- v4lhandle->capture_running = 1;
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_capture_stop( void *cpi_data )
- {
- v4l_handle_t v4lhandle = ( v4l_handle_t ) cpi_data;
- if( v4lhandle->capture_running )
- {
- v4lhandle->quit_capture_thread = 1;
- sem_post( &v4lhandle->out_sema );
- pthread_join( v4lhandle->capture_thread, NULL );
- if( v4lhandle->map )
- {
- munmap( v4lhandle->map, v4lhandle->v4lmbuf.size );
- v4lhandle->map = 0;
- }
- v4lhandle->capture_running = 0;
- }
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_queue_buffer( void *cpi_data, unicap_data_buffer_t *buffer )
- {
- v4l_handle_t v4lhandle = ( v4l_handle_t ) cpi_data;
- struct _unicap_queue *entry;
- entry = malloc( sizeof( struct _unicap_queue ) );
- entry->data = buffer;
- _insert_back_queue( v4lhandle->in_queue, entry );
- return STATUS_SUCCESS;
- }
- static unicap_status_t v4l_dequeue_buffer( void *cpi_data, unicap_data_buffer_t **buffer )
- {
- v4l_handle_t handle = ( v4l_handle_t ) cpi_data;
- unicap_status_t status;
- TRACE( "dequeue buffern" );
- if( handle->capture_running )
- {
- TRACE( "dequeue while capturingn" );
- return STATUS_FAILURE;
- }
- return STATUS_NOT_IMPLEMENTED;
- }
- static unicap_status_t v4l_wait_buffer( void *cpi_data, unicap_data_buffer_t **buffer )
- {
- v4l_handle_t handle = ( v4l_handle_t ) cpi_data;
- unicap_status_t status = STATUS_FAILURE;
- *buffer = NULL;
- if( !handle->out_queue->next &&! handle->capture_running )
- {
- TRACE( "Wait->capture stopped" );
- return STATUS_IS_STOPPED;
- }
- sem_wait( &handle->out_sema );
- if( handle->out_queue->next )
- {
- unicap_data_buffer_t *returned_buffer;
- struct _unicap_queue *entry;
- entry = _get_front_queue( handle->out_queue );
- returned_buffer = ( unicap_data_buffer_t * ) entry->data;
- free( entry );
- *buffer = returned_buffer;
- status = STATUS_SUCCESS;
- }
- return status;
- }
- static unicap_status_t v4l_poll_buffer( void *data, int *count )
- {
- TRACE( "poll buffern" );
- return STATUS_NOT_IMPLEMENTED;
- }
- static unicap_status_t v4l_set_event_notify( void *cpi_data, unicap_event_callback_t func, unicap_handle_t unicap_handle )
- {
- v4l_handle_t handle = ( v4l_handle_t )cpi_data;
- handle->event_callback = func;
- handle->unicap_handle = unicap_handle;
- return STATUS_SUCCESS;
- }
- static int queue_buffer( v4l_handle_t v4lhandle, int buffer )
- {
- struct video_mmap v4lmmap;
- unicap_status_t status;
- int frame;
- frame = buffer;
- TRACE( "queue buffer, frame: %dn", frame );
- v4lmmap.frame = frame;
- v4lmmap.width = v4lhandle->current_format.size.width;
- v4lmmap.height = v4lhandle->current_format.size.height;
- v4lmmap.format = v4lhandle->v4lpict.palette;
- if( ioctl( v4lhandle->fd, VIDIOCMCAPTURE, &v4lmmap ) == -1 )
- {
- TRACE( "ioctl failed: %sn", strerror( errno ) );
- return 0;
- }
- return 1;
- }
- static int wait_buffer( v4l_handle_t v4lhandle, unicap_data_buffer_t *data_buffer )
- {
- int frame;
- struct _unicap_queue *entry;
- v4lhandle->ready_buffer = ( v4lhandle->ready_buffer + 1 ) % v4lhandle->v4lmbuf.frames;
- frame = v4lhandle->ready_buffer;
- TRACE( "wait buffer, frame: %dn", frame );
- if( ioctl( v4lhandle->fd, VIDIOCSYNC, &frame ) == -1 )
- {
- TRACE( "ioctl failed: %sn", strerror( errno ) );
- return 0;
- }
- data_buffer->data = v4lhandle->map + v4lhandle->v4lmbuf.offsets[frame];
- gettimeofday( &data_buffer->fill_time, NULL );
- return 1;
- }
- static void v4l_capture_thread( v4l_handle_t handle )
- {
- unicap_data_buffer_t new_frame_buffer;
- int i = 0;
- unicap_copy_format( &new_frame_buffer.format, &handle->current_format );
- new_frame_buffer.buffer_size = handle->current_format.buffer_size;
- new_frame_buffer.type = UNICAP_BUFFER_TYPE_SYSTEM;
- while( !handle->quit_capture_thread )
- {
- struct _unicap_queue *entry;
- if( sem_wait( &handle->sema ) )
- {
- TRACE( "SEM_WAIT_FAILED" );
- }
- if( !wait_buffer( handle, &new_frame_buffer ) )
- {
- sem_post( &handle->sema );
- continue;
- }
- sem_post( &handle->sema );
- if( handle->event_callback )
- {
- handle->event_callback( handle->unicap_handle, UNICAP_EVENT_NEW_FRAME, &new_frame_buffer );
- }
- entry = _get_front_queue( handle->in_queue );
- if( entry )
- {
- unicap_data_buffer_t *data_buffer = ( unicap_data_buffer_t * ) entry->data;
- struct _unicap_queue *outentry = malloc( sizeof( struct _unicap_queue ) );
- free( entry );
- data_buffer->buffer_size = new_frame_buffer.buffer_size;
- unicap_copy_format( &data_buffer->format, &new_frame_buffer.format );
- if( data_buffer->type == UNICAP_BUFFER_TYPE_SYSTEM )
- {
- data_buffer->data = new_frame_buffer.data;
- }
- else
- {
- memcpy( data_buffer->data, new_frame_buffer.data, new_frame_buffer.buffer_size );
- }
- outentry->data = data_buffer;
- memcpy( &data_buffer->fill_time, &new_frame_buffer.fill_time, sizeof( struct timeval ) );
- _insert_back_queue( handle->out_queue, outentry );
- sem_post( &handle->out_sema );
- }
- if( sem_wait( &handle->sema ) )
- {
- TRACE( "SEM_WAIT_FAILED" );
- }
- queue_buffer( handle, handle->ready_buffer );
- sem_post( &handle->sema );
- }
- }