⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 videocaptureview.cpp

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 CPP
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS.  All rights reserved.**** This file is part of the Qtopia Environment.** ** 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.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** 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.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "videocaptureview.h"#include <qimage.h>#include <qpainter.h>#ifdef Q_WS_QWS#include <qgfx_qws.h>#include <qdirectpainter_qws.h>#endif#ifdef __linux__#define	HAVE_VIDEO4LINUX 1#endif#ifdef HAVE_VIDEO4LINUX#include <sys/types.h>#include <sys/ioctl.h>#include <unistd.h>#include <fcntl.h>#include <linux/videodev.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include <sys/mman.h>#endif /* HAVE_VIDEO4LINUX */class VideoCapture{public:    VideoCapture();    ~VideoCapture();    bool hasCamera() const;    void getCameraImage( QImage& img, bool copy=FALSE );    QValueList<QSize> photoSizes() const;    QValueList<QSize> videoSizes() const;    QSize recommendedPhotoSize() const;    QSize recommendedVideoSize() const;    QSize recommendedPreviewSize() const;    QSize captureSize() const;    void setCaptureSize( QSize size );    uint refocusDelay() const;    int minimumFramePeriod() const;private:#ifdef HAVE_VIDEO4LINUX    int fd;    int width, height;    struct video_capability caps;    struct video_mbuf mbuf;    unsigned char *frames;    int currentFrame;    void setupCamera( QSize size );    void shutdown();#endif};#ifdef HAVE_VIDEO4LINUX#define	VIDEO_DEVICE	    "/dev/video"bool VideoCapture::hasCamera() const{    return ( fd != -1 );}QSize VideoCapture::captureSize() const{    return QSize( width, height );}uint VideoCapture::refocusDelay() const{    return 250;}int VideoCapture::minimumFramePeriod() const{    return 40; // milliseconds}VideoCapture::VideoCapture(){    setupCamera( QSize( 0, 0 ) );}VideoCapture::~VideoCapture(){    shutdown();}void VideoCapture::setupCamera( QSize size ){    // Clear important variables.    frames = 0;    currentFrame = 0;    width = 640;    height = 480;    caps.minwidth = width;    caps.minheight = height;    caps.maxwidth = width;    caps.maxheight = height;    // Open the video device.    fd = open( VIDEO_DEVICE, O_RDWR );    if ( fd == -1 ) {	qDebug( "%s: %s", VIDEO_DEVICE, strerror( errno ) );	return;    }    // Get the device's current capabilities.    memset( &caps, 0, sizeof( caps ) );    if ( ioctl( fd, VIDIOCGCAP, &caps ) < 0 ) {	qDebug( "%s: could not retrieve the video capabilities",		VIDEO_DEVICE );	close( fd );	fd = -1;	return;    }    // Change the channel to the first-connected camera, skipping TV inputs.    // If there are multiple cameras, this may need to be modified.    int chan;    struct video_channel chanInfo;    qDebug( "available video capture inputs:" );    for ( chan = 0; chan < caps.channels; ++chan ) {	chanInfo.channel = chan;	if ( ioctl( fd, VIDIOCGCHAN, &chanInfo ) >= 0 ) {	    if ( chanInfo.type == VIDEO_TYPE_CAMERA )		qDebug( "    %s (camera)", chanInfo.name );	    else if ( chanInfo.type == VIDEO_TYPE_TV )		qDebug( "    %s (tv)", chanInfo.name );	    else		qDebug( "    %s (unknown)", chanInfo.name );	}    }    for ( chan = 0; chan < caps.channels; ++chan ) {	chanInfo.channel = chan;	if ( ioctl( fd, VIDIOCGCHAN, &chanInfo ) >= 0 ) {	    if ( chanInfo.type == VIDEO_TYPE_CAMERA ) {		qDebug( "selecting camera on input %s", chanInfo.name );		if ( ioctl( fd, VIDIOCSCHAN, &chan ) < 0 ) {		    qDebug( "%s: could not set the channel", VIDEO_DEVICE );		}		break;	    }	}    }    // Set the desired picture mode to RGB32.    struct video_picture pict;    memset( &pict, 0, sizeof( pict ) );    ioctl( fd, VIDIOCGPICT, &pict );    pict.palette = VIDEO_PALETTE_RGB32;    if ( ioctl( fd, VIDIOCSPICT, &pict ) < 0 ) {	qDebug( "%s: could not set the picture mode", VIDEO_DEVICE );	close( fd );	fd = -1;	return;    }    // Determine the capture size to use.  Zero indicates "preview mode".    if ( size.width() == 0 ) {	size = QSize( caps.minwidth, caps.minheight );    }    // Get the current capture window.    struct video_window wind;    memset( &wind, 0, sizeof( wind ) );    ioctl( fd, VIDIOCGWIN, &wind );    // Adjust the capture size to match the camera's aspect ratio.    if ( caps.maxwidth > 0 && caps.maxheight > 0 ) {	if ( size.width() > size.height() ) {	    size = QSize( size.height() * caps.maxwidth / caps.maxheight,			  size.height() );	} else {	    size = QSize( size.width(),			  size.width() * caps.maxheight / caps.maxwidth );	}    }    // Set the new capture window.    wind.x = 0;    wind.y = 0;    wind.width = size.width();    wind.height = size.height();    if ( ioctl( fd, VIDIOCSWIN, &wind ) < 0 ) {	qDebug( "%s: could not set the capture window", VIDEO_DEVICE );    }    // Re-read the capture window, to see what it was adjusted to.    ioctl( fd, VIDIOCGWIN, &wind );    width = wind.width;    height = wind.height;    // Enable mmap-based access to the camera.    memset( &mbuf, 0, sizeof( mbuf ) );    if ( ioctl( fd, VIDIOCGMBUF, &mbuf ) < 0 ) {	qDebug( "%s: mmap-based camera access is not available", VIDEO_DEVICE );	close( fd );	fd = -1;	return;    }    // Mmap the designated memory region.    frames = (unsigned char *)mmap( 0, mbuf.size, PROT_READ | PROT_WRITE,				    MAP_SHARED, fd, 0 );    if ( !frames || frames == (unsigned char *)(long)(-1) ) {	qDebug( "%s: could not mmap the device", VIDEO_DEVICE );	close( fd );	fd = -1;	return;    }    // Start capturing of the first frame.    struct video_mmap capture;    currentFrame = 0;    capture.frame = currentFrame;    capture.width = width;    capture.height = height;    capture.format = VIDEO_PALETTE_RGB32;    ioctl( fd, VIDIOCMCAPTURE, &capture );}void VideoCapture::shutdown(){    if ( frames != 0 ) {	munmap( frames, mbuf.size );	frames = 0;    }    if ( fd != -1 ) {	int flag = 0;	ioctl( fd, VIDIOCSYNC, 0);	ioctl( fd, VIDIOCCAPTURE, &flag );	close( fd );	fd = -1;    }}void VideoCapture::getCameraImage( QImage& img, bool copy ){    if ( fd == -1 ) {	if ( img.isNull() ) {	    img.create( width, height, 32 );	}	return;    }    // Start capturing the next frame (we alternate between 0 and 1).    int frame = currentFrame;    struct video_mmap capture;    if ( mbuf.frames > 1 ) {	currentFrame = !currentFrame;	capture.frame = currentFrame;	capture.width = width;	capture.height = height;	capture.format = VIDEO_PALETTE_RGB32;	ioctl( fd, VIDIOCMCAPTURE, &capture );    }    // Wait for the current frame to complete.    ioctl( fd, VIDIOCSYNC, &frame );    // Create an image that refers directly to the kernel's    // frame buffer, to avoid having to copy the data.    if ( !copy ) {        img = QImage( frames + mbuf.offsets[frame], width, height, 32, 0, 0,		      QImage::IgnoreEndian );    } else {	img.create( width, height, 32 );	memcpy( img.bits(), frames + mbuf.offsets[frame], width * height * 4 );    }    // Queue up another frame if the device only supports one at a time.    if ( mbuf.frames <= 1 ) {	capture.frame = currentFrame;	capture.width = width;	capture.height = height;	capture.format = VIDEO_PALETTE_RGB32;	ioctl( fd, VIDIOCMCAPTURE, &capture );    }}QValueList<QSize> VideoCapture::photoSizes() const{    QValueList<QSize> list;    list.append( QSize( caps.maxwidth, caps.maxheight ) );    if ( caps.maxwidth != caps.minwidth || caps.maxheight != caps.minheight )	list.append( QSize( caps.minwidth, caps.minheight ) );    return list;}QValueList<QSize> VideoCapture::videoSizes() const{    // We use the same sizes for both.    return photoSizes();}QSize VideoCapture::recommendedPhotoSize() const{    return QSize( caps.maxwidth, caps.maxheight );}QSize VideoCapture::recommendedVideoSize() const{    return QSize( caps.minwidth, caps.minheight );}QSize VideoCapture::recommendedPreviewSize() const{    return QSize( caps.minwidth, caps.minheight );}void VideoCapture::setCaptureSize( QSize size ){    if ( size.width() != width || size.height() != height ) {	shutdown();	setupCamera( size );    }}#else /* !HAVE_VIDEO4LINUX */// Dummy implementation for systems without video.VideoCapture::VideoCapture(){}VideoCapture::~VideoCapture(){}bool VideoCapture::hasCamera() const{    return TRUE;}QSize VideoCapture::captureSize() const{    return QSize( 640, 480 );}uint VideoCapture::refocusDelay() const{    return 0;}int VideoCapture::minimumFramePeriod() const{    return 100;}static unsigned int nextrand(){#define A 16807#define M 2147483647#define Q 127773#define R 2836    static unsigned int rnd=1;    unsigned long hi = rnd / Q;    unsigned long lo = rnd % Q;    unsigned long test = A*lo - R*hi;    if (test>0)	    rnd = test;    else	    rnd = test + M;    return rnd;}void VideoCapture::getCameraImage(QImage& img, bool){    // Just generate something dynamic (rectangles)    static QImage cimg;    int x,y,w,h;    if ( cimg.isNull() ) {	x = y = 0;	w = 640; h = 480;	cimg.create(w,h,32);    } else {	w = nextrand()%(cimg.width()-10)+10;	h = nextrand()%(cimg.height()-10)+10;	x = nextrand()%(cimg.width()-w);	y = nextrand()%(cimg.height()-h);    }    QRgb c = qRgb(nextrand()%255,nextrand()%255,nextrand()%255);    for (int j=0; j<h; j++) {	QRgb* l = (QRgb*)cimg.scanLine(y+j)+x;	for (int i=0; i<w; i++)	    l[i] = c;    }    img = cimg;}QValueList<QSize> VideoCapture::photoSizes() const{    QValueList<QSize> list;    list.append( QSize( 640, 480 ) );    list.append( QSize( 320, 240 ) );    return list;}QValueList<QSize> VideoCapture::videoSizes() const{    QValueList<QSize> list;    list.append( QSize( 640, 480 ) );    list.append( QSize( 320, 240 ) );    return list;}QSize VideoCapture::recommendedPhotoSize() const{    return QSize( 640, 480 );}QSize VideoCapture::recommendedVideoSize() const{    return QSize( 320, 240 );}QSize VideoCapture::recommendedPreviewSize() const{    return QSize( 320, 240 );}void VideoCapture::setCaptureSize( QSize size ){}#endif /* !HAVE_VIDEO4LINUX */VideoCaptureView::VideoCaptureView( QWidget *parent, const char *name, WFlags fl ) :    QWidget(parent,name,fl){    capture = new VideoCapture();    QSizePolicy sp(QSizePolicy::Expanding,QSizePolicy::Expanding);    setSizePolicy(sp);    tid_update = 0;    setLive();}VideoCaptureView::~VideoCaptureView(){    delete capture;}void VideoCaptureView::setLive(int period){    if ( tid_update )	killTimer(tid_update);    if ( period == 0 )	tid_update = startTimer(capture->minimumFramePeriod());    else if ( period > 0 )	tid_update = startTimer(period);    else	tid_update = 0;}void VideoCaptureView::setStill(const QImage& i){    setLive(-1);    img = i;    repaint(TRUE);}QValueList<QSize> VideoCaptureView::photoSizes() const{    return capture->photoSizes();}QValueList<QSize> VideoCaptureView::videoSizes() const{    return capture->videoSizes();}QSize VideoCaptureView::recommendedPhotoSize() const{    return capture->recommendedPhotoSize();}QSize VideoCaptureView::recommendedVideoSize() const{    return capture->recommendedVideoSize();}QSize VideoCaptureView::recommendedPreviewSize() const{    return capture->recommendedPreviewSize();}QSize VideoCaptureView::captureSize() const{    return capture->captureSize();}void VideoCaptureView::setCaptureSize( QSize size ){    capture->setCaptureSize( size );}uint VideoCaptureView::refocusDelay() const{    return capture->refocusDelay();}bool VideoCaptureView::available() const{    return capture->hasCamera();}void VideoCaptureView::paintEvent(QPaintEvent*){    if ( tid_update && !capture->hasCamera() ) {	QPainter p(this);	p.drawText(rect(),AlignCenter,tr("No Camera"));	return;    }    if ( tid_update )	capture->getCameraImage(img);    int w = img.width();    int h = img.height();    if ( !w || !h )	return;    if ( width()*w > height()*h ) {	w = w * height() / h;	h = height();    } else {	h = h * width() / w;	w = width();    }    if ( qt_screen->transformOrientation() == 0 ) {        // Stretch and draw the image.	QDirectPainter p(this);	QGfx *gfx = p.internalGfx();	if ( gfx ) {	    gfx->setSource( &img );	    gfx->setAlphaType( QGfx::IgnoreAlpha );	    gfx->stretchBlt( (width() - w) / 2, (height() - h) / 2, w, h,			     img.width(), img.height() );	}    } else {	// This code is nowhere near efficient enough (hence the above).	// TODO - handle rotations during direct painting.	QImage scimg = img.smoothScale(w,h);	QPainter p(this);	p.drawImage((width()-w)/2,(height()-h)/2,scimg);    }}void VideoCaptureView::timerEvent(QTimerEvent*){    repaint(FALSE);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -