📄 capture.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, 2003 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 "capture.h"#include <string.h>//--------------------------------------------------------------------------FRAMEGRABBER* fg_open( const char* dev ){ FRAMEGRABBER* fg; int i; fg = malloc( sizeof( FRAMEGRABBER ) ); if ( fg == NULL ) { perror( "fg_open(): failed to alloc FRAMEGRABBER" ); return NULL; } memset( fg, 0, sizeof( FRAMEGRABBER ) ); // 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_RDONLY ); if ( fg->fd == -1 ) { //perror( "fg_open(): open video device failed" ); goto bail; } // 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" ); goto bail; } // Read info for all input sources fg->source = 0; fg->sources = malloc( sizeof( struct video_channel )*fg->caps.channels ); if ( fg->sources == NULL ) { perror( "fg_open(): failed to alloc sources" ); goto bail; } for ( i = 0; i < fg->caps.channels; i++ ) { fg->sources[i].channel = i; ioctl( fg->fd, VIDIOCGCHAN, &(fg->sources[i]) ); } // Read info about tuner fg->tuner.tuner = 0; if ( ( fg->caps.type & VID_TYPE_TUNER ) && ( ioctl( fg->fd, VIDIOCGTUNER, &(fg->tuner) ) < 0 ) ) { perror( "fg_open(): warning: cannot get tuner info (not present?)" ); } // Set default window to max size fg->window.x = 0; fg->window.y = 0; fg->window.width = fg->caps.maxwidth; fg->window.height = fg->caps.maxheight; fg->window.chromakey = 0; fg->window.flags = 0; fg->window.clips = NULL; fg->window.clipcount = 0; if ( ioctl( fg->fd, VIDIOCSWIN, &(fg->window) ) < 0 ) { perror( "fg_open(): set default window attrs failed" ); goto bail; } // 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 = 24; fg->picture.palette = VIDEO_PALETTE_YUV420P; //RGB24; if ( ioctl( fg->fd, VIDIOCSPICT, &(fg->picture) ) < 0 ) { perror( "fg_open(): set picture attributes failed" ); goto bail; } // Get frame buffer info if ( ioctl( fg->fd, VIDIOCGFBUF, &(fg->fbuffer) ) < 0 ) { perror( "fg_open(): get framebuffer failed" ); goto bail; } // Get the memory buffer info if ( ioctl( fg->fd, VIDIOCGMBUF, &(fg->mbuf) ) < 0 ) { perror( "fg_open(): get memory buffer" ); goto bail; } // Memory map the video buffer fg->mb_map = mmap( 0, // Start addr fg->mbuf.size, // Buffer length PROT_READ, // Protections MAP_SHARED, // Mapping flags fg->fd, // File handle 0 ); // Offset if ( fg->mb_map == (void *) -1 ) { perror( "fg_open(): mmap failed" ); goto bail; } return fg;bail: if ( fg->device ) { free( fg->device ); } if ( fg->sources ) { free( fg->sources ); } free( fg ); return NULL;}//--------------------------------------------------------------------------void fg_close(FRAMEGRABBER* fg){ if ( munmap(fg->mb_map, fg->mbuf.size) == -1 ) { perror( "fg_close(): failed to unmap mmap" ); } if ( close( fg->fd ) == -1 ) { perror( "fg_close(): failed to close 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 ){ // Set user's desired window fg->window.x = x; fg->window.y = y; fg->window.width = width; fg->window.height = height; // Default other fields fg->window.chromakey = 0; fg->window.flags = 0; fg->window.clips = NULL; fg->window.clipcount = 0; // 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" ); return NULL; } return fg->sources[ch].name;}//--------------------------------------------------------------------------int fg_get_source_type( FRAMEGRABBER* fg, int ch ){ if ( ch > fg->caps.channels ) { fprintf( stderr, "fg_get_source_type(): Invalid channel number!\n" ); return -1; } return fg->sources[ch].type;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -