📄 grabber-linux.cxx
字号:
/* ========================================================================= Copyright (c) 1997 Regents of Koji OKAMURA, oka@kobe-u.ac.jp All rights reserved. largely rewritten for new bttv/video4linux interface by Gerd Knorr <kraxel@cs.tu-berlin.de> ========================================================================= */#include <ptlib.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h> #include <string.h>#include <signal.h>#include <errno.h>#include <sys/types.h>#include <sys/fcntl.h> #include <sys/ioctl.h>#include <sys/time.h>#include <sys/mman.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/keysym.h>extern "C" {#include <asm/types.h>#include "linux/videodev.h"}#include "grabber-linux.h"/* pass 0/1 by reference */static const int one = 1, zero = 0;VideoGrabber::VideoGrabber(int videoInput, BOOL videoIsPal){ int i; frame=NULL; fd_ = open("/dev/video", O_RDWR); if (fd_ < 0) { operational=0; goto done; } /* ask for capabilities */ if (-1 == ioctl(fd_,VIDIOCGCAP,&capability)) { perror("ioctl VIDIOCGCAP"); exit(1); } //Allocate n_channels*sizeof(one_channel) bytes to hold info on // all channels supported by the video card. card_channels = (struct video_channel*) calloc(capability.channels,sizeof(struct video_channel)); for (i = 0; i < capability.channels; i++) { card_channels[i].channel = i; if (-1 == ioctl(fd_,VIDIOCGCHAN,&card_channels[i])) perror("ioctl VIDIOCGCHAN"); card_channels[i].norm = videoIsPal ? VIDEO_MODE_PAL : VIDEO_MODE_NTSC; } if (-1 == ioctl(fd_,VIDIOCGPICT,&pict)) perror("ioctl VIDIOCGPICT"); operational = 1; port_ = videoInput; done: /* map grab buffer */ gb_buffers.offsets[0] = 0; gb_buffers.offsets[1] = 0x151000; gb_buffers.size = gb_buffers.offsets[1]<<1; frame= new u_char[352*144*3]; //352*144*3==352*288*1.5, if(operational) { if (-1 == ioctl(fd_,VIDIOCGMBUF,&gb_buffers)) perror("ioctl VIDIOCGMBUF"); mem = (char *)mmap(0,gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,fd_,0); if ((char*)-1 == mem) { perror("video grabber: constructor-mmap"); printf("video grabber: Failed to allocate memory map to video driver.\n"); printf("video grabber: YOU NEED mmap support for video functions to work.\n"); printf("video grabber: exiting. \n"); printf("Try again after enabling mmap.\n"); exit(1); } }}VideoGrabber::~VideoGrabber(){ if(operational) { munmap(mem,gb_buffers.size); close(fd_); } if (frame) delete frame; frame=NULL;}void VideoGrabber::Start(){ grab_count = 0; sync_count = 0; if(operational) { if (-1 == ioctl(fd_, VIDIOCMCAPTURE, &gb_even)) perror("ioctl VIDIOCMCAPTURE start even"); else grab_count++; if (-1 == ioctl(fd_, VIDIOCMCAPTURE, &gb_odd)) perror("ioctl VIDIOCMCAPTURE start odd"); else grab_count++; } Grabber::Start(); running = 1;}void VideoGrabber::Stop(){ running = 0; while (operational && (grab_count > sync_count)) { if (-1 == ioctl(fd_, VIDIOCSYNC, (sync_count%2) ? &one:&zero)) { perror("ioctl VIDIOCSYNC stop"); break; } else sync_count++; } Grabber::Stop();}void VideoGrabber::Grab(VideoFrame *vf){ SetSize(vf->width,vf->height); vf->ts= grab_count*33; if (operational) { if (-1 == ioctl(fd_, VIDIOCSYNC, (sync_count%2) ? &one:&zero)) perror("ioctl VIDIOCSYNC grab "); else sync_count++; if (-1 == ioctl(fd_, VIDIOCMCAPTURE, (grab_count % 2) ? &gb_odd : &gb_even)) perror("ioctl VIDIOMCAPTURE grab"); else grab_count++; // Convert to Pixel format YUV420. // Unfortunately, almost all video drivers cannot grab // in VIDEO_PALETTE_YUV420 format. So, we grab in YUV422 and convert. int a,b; char *s, *y,*u,*v; s = (char *)(mem+(gb_buffers.offsets[(sync_count %2)? 1:0])); y = (char *)frame; //frame points to output buffer. u = y + (width * height); v = u + (width * height / 4); for (a = height; a > 0; a -= 2) { for (b = width; b > 0; b -= 2) { *(y++) = *(s++); *(u++) = *(s++); *(y++) = *(s++); *(v++) = *(s++); } for (b = width; b > 0; b -= 2) { *(y++) = *(s++); s++; *(y++) = *(s++); s++; } } vf->frameptr= frame; vf->crvec = 0; } else // Grabber is not operational, so generate fictional image. Grabber::Grab(vf);}void VideoGrabber::SetSize(int _width,int _height){ if((width!=_width)||(height!=_height)) { Grabber::SetSize(_width,_height); Format(); }}void VideoGrabber::Format(){ gb_even.frame = 0; gb_even.format = VIDEO_PALETTE_YUV422;//Ideally, VIDEO_PALETTE_YUV420 gb_even.width = width; gb_even.height = height; gb_odd.frame = 1; gb_odd.format = VIDEO_PALETTE_YUV422;// Ideally, VIDEO_PALETTE_YUV420; gb_odd.width = width; gb_odd.height = height; if ( operational){ if (-1 == ioctl(fd_, VIDIOCSCHAN, &card_channels[port_])) perror("FORMAT:: ioctl VIDIOCSCHAN"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -