[分享]基于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