📄 v4lcapture.c
字号:
//==========================================================================//// Project: libfg - Frame Grabber interface for Linux//// Module: Capture client implementation//// Description: Provides a high-level C interface for controlling frame// grabber and TV tuner cards. Uses the Video 4 Linux API// (currently v1) and thus supports any V4L supported// device.//// Author: Gavin Baker <gavinb@antonym.org>//// Homepage: http://www.antonym.org/libfg////--------------------------------------------------------------------------//// libfg - Frame Grabber interface for Linux// Copyright (c) 2002 Gavin Baker//// This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public// License as published by the Free Software Foundation; either// version 2.1 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// Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser 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// or obtain a copy from the GNU website at http://www.gnu.org/////==========================================================================#include "v4lcapture.h"#include <string.h>//--------------------------------------------------------------------------//// Function: fg_open//// Description: Opens and initialises the frame grabber device with// some reasonable default values, and queries for all// capabilities.//// Requires: 1. The Video4Linux subsystem to be properly initialised// 2. Either a valid device name (such as "/dev/bttv") or// NULL to use the default.// // Promises: 1. To open the video device// 2. Initialise the video device to reasonable defaults// 3. To not leak any memory by freeing upon any error// 4. To return NULL if any initialisation fails// 5. To return a valid FRAMEGRABBER instance that can// be used immediately for grabbing////--------------------------------------------------------------------------FRAMEGRABBER* fg_open( const char* dev ){ FRAMEGRABBER* fg = malloc( sizeof( FRAMEGRABBER ) ); int i; // Use default device if none specified if ( dev != NULL ) { fg->device = strdup( dev ); } else { fg->device = strdup( FG_DEFAULT_DEVICE ); } // Open the video device fg->fd = open( fg->device, O_RDWR ); if ( fg->fd == -1 ) { perror( "fg_open(): open video device failed" ); free( fg->device ); free( fg ); return NULL; } // Make sure child processes don't inherit video (close on exec) fcntl( fg->fd, F_SETFD, FD_CLOEXEC ); // For n-ary buffering fg->cur_frame = -1; // Get the device capabilities if( ioctl( fg->fd, VIDIOCGCAP, &(fg->caps) ) < 0 ) { perror( "fg_open(): query capabilities failed" ); free( fg->device ); free( fg ); return NULL; } // Read info for all input sources fg->source = 0; fg->sources = malloc( sizeof( struct video_channel )*fg->caps.channels ); for ( i = 0; i < fg->caps.channels; i++ ) { fg->sources[i].channel = i; ioctl( fg->fd, VIDIOCGCHAN, &(fg->sources[i]) ); // Read info about tuner // TODO: multiple tuners? if (fg->sources[i].tuners > 0) { fg->tuner.tuner = 0; if ( ioctl( fg->fd, VIDIOCGTUNER, &(fg->tuner) ) < 0 ) { perror( "fg_open(): warning: cannot get tuner info (not present?)" ); } } } /* MOVE or REMOVE; we may not know the valid palette yet // Set default picture attributes (50%) fg->picture.brightness = FG_50PC; fg->picture.hue = FG_50PC; fg->picture.colour = FG_50PC; fg->picture.contrast = FG_50PC; fg->picture.whiteness = FG_50PC; fg->picture.depth = 32; fg->picture.palette = VIDEO_PALETTE_RGB32; if ( ioctl( fg->fd, VIDIOCSPICT, &(fg->picture) ) < 0 ) { perror( "fg_open(): warning: set picture attributes failed" ); free( fg->device ); free( fg->sources ); free( fg ); return NULL; } */ // Get frame buffer info if ( ioctl( fg->fd, VIDIOCGFBUF, &(fg->fbuffer) ) < 0 ) { perror( "fg_open(): get framebuffer failed; ignoring" ); /* VIDIOCGBUF ioctl fails on some webcams, this can be safely ignored free( fg->device ); free( fg->sources ); free( fg ); return NULL; */ } // Get the memory buffer info if ( ioctl( fg->fd, VIDIOCGMBUF, &(fg->mbuf) ) < 0 ) { perror( "fg_open(): get memory buffer" ); free( fg->device ); free( fg->sources ); free( fg ); return NULL; } // set the default max_buffer fg->max_buffer = fg->mbuf.frames; // Memory map the video buffer fg->mb_map = mmap( NULL, // Start addr fg->mbuf.size, // Buffer length PROT_READ | PROT_WRITE, // Protections MAP_SHARED, // Mapping flags fg->fd, // File handle 0 ); // Offset if ( MAP_FAILED == fg->mb_map ) { perror( "fg_open(): mmap buffer" ); free( fg->device ); free( fg->sources ); free( fg ); return NULL; } return fg;}//--------------------------------------------------------------------------void fg_close(FRAMEGRABBER* fg){ munmap( fg->mb_map, fg->mbuf.size); close( fg->fd ); // Make sure we free all memory (backwards!) free( fg->device ); free( fg->sources ); free( fg );}//--------------------------------------------------------------------------int fg_set_capture_window( FRAMEGRABBER* fg, int x, int y, int width, int height ){ // Read default fields value if ( ioctl( fg->fd, VIDIOCGWIN, &(fg->window) ) < 0 ) { perror( "fg_set_capture_window(): get window failed" ); return -1; } // Set user's desired window fg->window.x = x; fg->window.y = y; fg->window.width = width; fg->window.height = height;/* // Try setting the values if ( ioctl( fg->fd, VIDIOCSWIN, &(fg->window) ) < 0 ) { perror( "fg_set_capture_window(): set window failed" ); return -1; } // Read back the real values set if ( ioctl( fg->fd, VIDIOCGWIN, &(fg->window) ) < 0 ) { perror( "fg_set_capture_window(): get window failed" ); return -1; }*/ return 0;}//--------------------------------------------------------------------------int fg_enable_capture( FRAMEGRABBER* fg, int flag ){ if ( ioctl( fg->fd, VIDIOCCAPTURE, (flag>0) ) < 0 ) { perror( "fg_enable_capture(): capture control failed" ); return -1; } return 0;}//--------------------------------------------------------------------------int fg_set_format( FRAMEGRABBER* fg, int fmt ){ // This is only meaningful when we actually do a capture fg->picture.palette = fmt; return 0;}//--------------------------------------------------------------------------int fg_set_source( FRAMEGRABBER* fg, int ch ){ if ( ch > fg->caps.channels ) { fprintf( stderr, "fg_set_source(): Invalid channel number!\n" ); return -1; } fg->source = ch; if ( ioctl( fg->fd, VIDIOCSCHAN, &(fg->sources[fg->source]) ) < 0 ) { perror( "fg_set_source(): set channel failed" ); return -1; } return 0;}//--------------------------------------------------------------------------int fg_set_source_norm( FRAMEGRABBER* fg, int norm ){ fg->sources[fg->source].norm = norm; if ( ioctl( fg->fd, VIDIOCSCHAN, &(fg->sources[fg->source]) ) < 0 ) { perror( "fg_set_source_norm(): set channel/norm failed" ); return -1; } return 0;}//--------------------------------------------------------------------------int fg_get_source_count( FRAMEGRABBER* fg ){ return fg->caps.channels;}//--------------------------------------------------------------------------char* fg_get_source_name( FRAMEGRABBER* fg, int ch ){ if ( ch > fg->caps.channels ) { fprintf( stderr, "fg_get_source_name(): Invalid channel number!\n" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -