Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1427218
  • 博文数量: 430
  • 博客积分: 9995
  • 博客等级: 中将
  • 技术积分: 4388
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-24 18:04
文章存档

2013年(1)

2008年(2)

2007年(14)

2006年(413)

分类:

2006-10-17 08:51:39

基于S3C2410编写摄像头应用程序的参考资料

收集的一些资料,大家共享吧!
========================================================================
用servfox一个小程序做服务端,传出来到你的电脑连续显示,效果不错!

=======================================================================
还有一个类似:spcacat

=======================================================================
德国人做的抓图程序:vgrabbj

=======================================================================
其它的编程经验:

问题1:linux支持的设像头驱动太少,现在我们只找到ov511的驱动,也就是说并不是每一个设像头都能在linux下用.
问题2:以前我们是用v4l一写的,可以正确读取图像,现在2.6内核是v4l二,我们写的程序读出来显现的不正确,源代码大概是这样的:
         Mywidth = 176;
Myheight = 144;
tmp = (uchar *)malloc(Mywidth * Myheight *3);
buffer = (uchar *)malloc(Mywidth * Myheight *4);
device_fd = open("/dev/video0", O_RDONLY);
static struct video_window vidwin;
vidwin.width = Mywidth;
vidwin.height = Myheight;
ioctl(device_fd, VIDIOCSWIN, &vidwin);

read(device_fd, tmp, Mywidth*Myheight*3);
for(int i = 0; i < 176 * 144; ++i)
{
  buffer[4*i] = tmp[3*i];//first bit is blue
  buffer[4*i + 1] = tmp[3*i + 1];//second bit is green
  buffer[4*i + 2] = tmp[3*i + 2] ;//third bit is red
  buffer[4*i + 3] = 130;//forth bit
}
//后面这此是用QT库写的,意思是将buffer的内容转为image再转为pixmap,然后显示出来
QImage img(buffer, Mywidth, Myheight, 32, NULL, 0, QImage::LittleEndian);
QPixmap pic;
pic.convertFromImage(img);
PixmapVideo->setPixmap(pic);


====================================

Content
1.驱动
2.应用程序书写

1.驱动
   Linux-2.4.18默认带有ov511摄像头的驱动,在USB设备中选中,并激活video选项,即可对ov511支持。

2.应用程序书写
   这是一个在MiniGui下的程序,可以用QVFB模拟,可以可以在板子上跑,效果还可以。

v4l.h
/*
* w3v4l.h
*
* Copyright (C) 1998 - 2000 Rasca, Berlin
* EMail:
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef __W3V4L_H__
#define __W3V4L_H__


class CV4L{
public:
CV4L();
CV4L(char *szDevName);
~CV4L();

bool init(int channel, int width, int height);
unsigned char *Read();
void destroy();
private:
char *szDevName;
bool initialized;
unsigned char *m_Buff;
int m_BuffSize;
int fdVideo;
int m_Width, m_Height;
int m_MapSize;
};

#endif

v4l.cpp

/*
* v4l.c
*
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include
#include "v4l.h"

/* v4l_init()
* function: init the video device
* references:
*     dev: device name.
*     input: channel number of video_channel structure.
*     width: width value of video_window structure
*     height: height value of video_window structure
*/
bool CV4L::init(int channel, int width, int height)
{
int fd;
struct video_capability vid_caps;
struct video_mbuf vid_mbuf;
struct video_channel vid_chnl;

// open the video device
fd = open (szDevName, O_RDWR);
if (fd == -1) {
perror (szDevName);
return false;
}
fdVideo = fd;

// get video_capability structrue
if (ioctl (fd, VIDIOCGCAP, &vid_caps) == -1) {
perror ("ioctl (VIDIOCGCAP)");
return false;
}

// get the buffer information in video_mbuf structure
// if can't use mmap()
if (ioctl (fd, VIDIOCGMBUF, &vid_mbuf) == -1) {
struct video_window vid_win;
m_MapSize = 0;

// set video window information
if (ioctl(fd, VIDIOCGWIN, &vid_win) != -1) {
vid_win.width = width;
vid_win.height= height;
ioctl (fd, VIDIOCSWIN, &vid_win);
}
} else {
m_MapSize = vid_mbuf.size;
m_BuffSize = m_MapSize;
}
#ifdef DEBUG
printf ("%s: mbuf.size=%d\n", __FILE__, vid_mbuf.size);
#endif

if (channel > -1) {
vid_chnl.channel = channel;
if (ioctl (fd, VIDIOCGCHAN, &vid_chnl) == -1) {
perror ("ioctl (VIDIOCGCHAN)");
} else {
vid_chnl.channel = channel;
if (ioctl (fd, VIDIOCSCHAN, &vid_chnl) == -1) {
perror ("ioctl (VIDIOCSCHAN)");
}
}
}
if (m_MapSize > 0) {
m_Buff = (unsigned char *)mmap (0,m_MapSize, PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if ((unsigned char *) -1 == (unsigned char *)m_Buff) {
perror ("mmap()");
close (fd);
return false;
}
} else {
m_BuffSize = width * height * 3;
m_Buff = (unsigned char *)malloc (m_BuffSize);
}
m_Width = width;
m_Height = height;

return true;
}

unsigned char
*CV4L::Read()
{
struct video_mmap vid_mmap;

if (m_MapSize == 0) {
printf (__FILE__": reading image .. \n");
if (read (fdVideo, (void *)m_Buff, m_BuffSize) <= 0) {
free (m_Buff);
return (0);
}
} else {
vid_mmap.format = VIDEO_PALETTE_RGB565;   //VIDEO_PALETTE_RGB24;
vid_mmap.frame = 0;
vid_mmap.width = m_Width;
vid_mmap.height= m_Height;
if (ioctl (fdVideo, VIDIOCMCAPTURE, &vid_mmap) == -1) {
perror ("ioctl (VIDIOCMCAPTURE)");
return (0);
}
if (ioctl (fdVideo, VIDIOCSYNC, &vid_mmap) == -1) {
perror ("ioctl (VIDIOCSYNC)");
return (0);
}
}
return m_Buff;
}

void CV4L::destroy()
{
if (fdVideo >= 0) {
if (m_MapSize == 0)
free (m_Buff);
else
munmap (m_Buff, m_MapSize);
close (fdVideo);
}
}

CV4L::CV4L()
{
//
}

CV4L::CV4L(char *_szDevName)
{
szDevName = (char *)malloc(strlen(_szDevName)+1);
strcpy(szDevName, _szDevName);
//init(0, int width, int height);
//
}

CV4L::~CV4L()
{
destroy();
}

video.cpp
/*
** $Id: helloworld.c,v 1.7 2003/06/13 07:15:49 weiym Exp $
**
** Listing 2.1
**
** helloworld.c: Sample program for MiniGUI Programming Guide
**      The first MiniGUI application.
**
** Copyright (C) 2003 Feynman Software.
**
** License: GPL
*/

#include

#include
#include
#include
#include
#include
#include

#include "v4l.h"

#define VID_W 320
#define VID_H 240

static BITMAP bmp;

CV4L *cVid;  //"/dev/video0"
unsigned char *buf;

   static int count = 0;
   static int xdir = -3;
   static int ydir = -3;
   static int x = 1;
   static int y = 11;

/*bool SwitchBuf24ToBmp16(unsigned char *buf24, PBITMAP pBmp)
{
myBmp.bits = buf24;
//ExpandMyBitmap (HDC_SCREEN, &bmp, &myBmp, rgb, 0);

printf ("bmp.bmType = %i\n", bmp.bmType);
printf ("bmp.bmBitsPerPixel = %i\n", bmp.bmBitsPerPixel);
printf ("bmp.bmBytesPerPixel = %i\n", bmp.bmBytesPerPixel);
printf ("bmp.bmAlpha = %i\n", bmp.bmAlpha);
printf ("bmp.bmColorKey = %i\n", bmp.bmColorKey);
printf ("bmp.bmWidth = %i\n", bmp.bmWidth);
printf ("bmp.bmHeight = %i\n", bmp.bmHeight);
printf ("bmp.bmPitch = %i\n", bmp.bmPitch);
printf ("bmp.bmBits = %i\n", bmp.bmBits);
printf ("bmp.bmAlphaPixelFormat = %i\n", bmp.bmAlphaPixelFormat);
return true;
}*/

void FillBitmap(BITMAP *bmp)
{
bmp->bmType = 0;
bmp->bmBitsPerPixel = 16;
bmp->bmBytesPerPixel = 2;
bmp->bmAlpha = 0;
bmp->bmColorKey = 0;
bmp->bmWidth = VID_W;
bmp->bmHeight = VID_H;
bmp->bmPitch = VID_W*2;
bmp->bmBits = NULL;
bmp->bmAlphaPixelFormat = NULL;
}

void FillMyBitmap(PMYBITMAP my_bmp)
{
my_bmp->flags = MYBMP_RGBSIZE_3 | MYBMP_TYPE_BGR | MYBMP_FLOW_DOWN;
my_bmp->frames = 1;
my_bmp->depth = 24;
my_bmp->alpha = 0;
my_bmp->reserved[0] = 0;
my_bmp->reserved[1] = 0;
my_bmp->transparent = 0;
my_bmp->w = 240;
my_bmp->h = 180;
my_bmp->pitch = 240*3;
my_bmp->size = 240*180*3;
my_bmp->bits = NULL;
}

static int HelloWinProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
   HDC hdc;
   RECT rc;

   switch (message) {
       case MSG_PAINT:
           hdc = BeginPaint (hWnd);

           if (bmp.bmBits)
               FillBoxWithBitmap (hdc, 0, 0, bmp.bmWidth, bmp.bmHeight, &bmp);

           SetBkColor (hdc, RGB2Pixel (hdc, 0xFF, 0xFF, 0xFF));
           SetBkMode (hdc, BM_TRANSPARENT);
           SetTextColor (hdc, RGB2Pixel (hdc, 0xFF, 0x00, 0x00));
           rc.left = 0;
           rc.top = 0;
           rc.right = 300;
           rc.bottom = 60;
           TextOut (hdc, 0, 0, "??????");

   if (x >= VID_W || x <=0)
   {
               xdir = 0 - xdir;
   }
   if (y >= VID_W || y <=10)
   {
               ydir = 0 - ydir;
   }
    
   x += xdir;
   y += ydir;
   TextOut (hdc, x, y, "kdf");
           Rectangle (hdc, 0, 0, bmp.bmWidth, bmp.bmHeight);

           /*FillBoxWithBitmap (hdc, 100, 0, 200, 200, &bmp);
           Rectangle (hdc, 100, 0, 300, 200);

           FillBoxWithBitmapPart (hdc, 0, 200, 400, 200, 0, 0, &bmp, 10, 10);
           Rectangle (hdc, 0, 200, 400, 400);*/

           EndPaint (hWnd, hdc);
           return 0;

       case MSG_CREATE:
           /*if (LoadBitmap (HDC_SCREEN, &bmp, "bkgnd.bmp"))
               return -1;*/
           return 0;

       case MSG_CLOSE:
           UnloadBitmap (&bmp);
           DestroyMainWindow (hWnd);
           PostQuitMessage (hWnd);
           return 0;
   }

   return DefaultMainWinProc(hWnd, message, wParam, lParam);
}

int MiniGUIMain (int argc, const char* argv[])
{
   MSG Msg;
   HWND hMainWnd;
   MAINWINCREATE CreateInfo;

#ifdef _LITE_VERSION
   SetDesktopRect(0, 0, 1024, 768);
#endif

   CreateInfo.dwStyle = WS_VISIBLE | WS_BORDER | WS_CAPTION;
   CreateInfo.dwExStyle = WS_EX_NONE;
   CreateInfo.spCaption = "Hello, world";
   CreateInfo.hMenu = 0;
   CreateInfo.hCursor = GetSystemCursor(0);
   CreateInfo.hIcon = 0;
   CreateInfo.MainWindowProc = HelloWinProc;
   CreateInfo.lx = 0;
   CreateInfo.ty = 0;
   CreateInfo.rx = VID_W;
   CreateInfo.by = VID_H;
   CreateInfo.iBkColor = COLOR_lightwhite;
   CreateInfo.dwAddData = 0;
   CreateInfo.hHosting = HWND_DESKTOP;
    
   hMainWnd = CreateMainWindow (&CreateInfo);
    
   if (hMainWnd == HWND_INVALID)
       return -1;

   ShowWindow(hMainWnd, SW_SHOWNORMAL);

   //////////////////////////////////////////////////////////////
   // 1. Create my video class CV4L.
   cVid = new CV4L("/dev/video0");
    
   //////////////////////////////////////////////////////////////
   // 2. Init the video device with channel and map size.
   if (cVid->init(0, VID_W, VID_H) == false)
       return -1;

   //FillMyBitmap(&myBmp);
   FillBitmap(&bmp);
   //////////////////////////////////////////////////////////////
   // 3. Read the data from video device.
   if (buf = cVid->Read ())
   {
       bmp.bmBits = buf;
       //InvalidateRect ();
       SendMessage (hMainWnd, MSG_PAINT, 0, 0);
   }

   while (true)
   {
       if (!HavePendingMessage (hMainWnd))
       {
           if (!GetMessage (&Msg, hMainWnd))
               break;
           TranslateMessage (&Msg);
           DispatchMessage (&Msg);
       } else {
           //////////////////////////////////////////////////////////////
           // 3. Read the data from video device.
           if (buf = cVid->Read ())
           {
               bmp.bmBits = buf;
               SendMessage (hMainWnd, MSG_PAINT, 0, 0);
           } else {
               // if Buffer is Null, vedeo device have pluged out.
               PostQuitMessage (hMainWnd);
           } /* end of read video buffer */
       } /* end of HavePendingMessage() */
   } /* end of while */

   //////////////////////////////////////////////////////////////
   // 4. destroy the CV4L class, and release resources.
   cVid->destroy ();
   UnloadBitmap (&bmp);
   //free (bmp.bmBits);

   MainWindowThreadCleanup (hMainWnd);

   return 0;
}

#ifndef _LITE_VERSION
#include
#endif

把这些代码添加到miniugi-1.3.3的helloworld程序中去编译一下就可以了,也可以用如下命令
g++ -o video -I/minigui/include -L/minigui/lib video.cpp v4l.cpp
阅读(3410) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~