最近又在搞摄像头的东西。被搞死了。。。上述代码在minigui中是单线程跑的,虽然是在消息空闲的时候进行图像获取的,但实际效果无论是pc还是板子上那些控件都是不能操作的。因此我改了个多线程的。
/*
** $Id: button.c,v 1.7 2003/08/15 11:12:18 weiym Exp $
**
** Listing 7.1
**
** button.c: Sample program for MiniGUI Programming Guide
** Usage of BUTTON control.
**
** Copyright (C) 2003 Feynman Software.
**
** License: GPL
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <memory.h>
#include <pthread.h>
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>
#include "v4l.h"
//#define IDC_STATIC 100
#define IDC_WINMAIN_KAISHIJISHI 101
#define IDC_WINMAIN_DINGSHISHEDING 102
#define IDC_WINMAIN_KAISHIJIANCE 103
#define IDC_WINMAIN_XUANZEKU 104
#define IDC_WINMAIN_NONGDUZHI 105
#define IDC_WINMAIN_KANGSHENGSULEIXING 106
#define IDC_WINMAIN_LEBAL 107
#define IDC_WINMAIN_GUANJI 108
int NumerWin(void);
int TypeWin(void);
void StartTimer(void);
void StopTimer(void);
/* Global Variable */
char gszTypeName[100] = "绿霉素";
int giWaitTime = 12;
bool gbTimerStart = false;
HWND ghWnd = NULL;
/* v4l */
#define V4L_DEV "/dev/video0"
#define VID_W 320
#define VID_H 240
static BITMAP bmp;
static BITMAP small_bmp;
static unsigned char small_buf[240*180*2];
CV4L *cVid; //"/dev/video0"
unsigned char *buf;
pthread_t vid_tid = 0;
char strBuf[100];
static CTRLDATA CtrlYourTaste[] =
{
{
"button",
WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP,
6, 236, 71, 32,
IDC_WINMAIN_KAISHIJISHI,
"开始记时",
0
},
{
"button",
WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP,
85, 236, 71, 32,
IDC_WINMAIN_DINGSHISHEDING,
"定时设定",
0
},
{
"button",
WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP,
162, 236, 71, 32,
IDC_WINMAIN_KAISHIJIANCE,
"开始检测",
0
},
{
"button",
WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP,
6, 273, 71, 32,
IDC_WINMAIN_XUANZEKU,
"选择库",
0
},
{
"button",
WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP,
85, 273, 71, 32,
IDC_WINMAIN_GUANJI,
"结束",
0
},
{
"static",
WS_VISIBLE | WS_TABSTOP,
14, 185, 124, 25,
IDC_WINMAIN_LEBAL,
"检测结果",
0
},
{
"static",
WS_VISIBLE | WS_TABSTOP,
120, 185, 100, 25,
IDC_WINMAIN_NONGDUZHI,
"3.1415",
0
},
{
"static",
WS_VISIBLE | WS_TABSTOP,
14, 211, 150, 25,
IDC_STATIC,
"抗生素类型",
0
},
{
"static",
WS_VISIBLE | WS_TABSTOP,
120, 211, 100, 25,
IDC_WINMAIN_KANGSHENGSULEIXING,
"绿霉素",
0
},
};
static DLGTEMPLATE DlgYourTaste =
{
WS_BORDER | WS_CAPTION,
WS_EX_NONE,
0, -23, 240, 344,
"",
0, 0,
sizeof(CtrlYourTaste)/sizeof(CTRLDATA), NULL,
0
};
void SetTimer(void)
{
NumerWin();
}
void BeginDetect(void)
{
// 停止线程,取得图片
if (vid_tid != 0)
{
pthread_cancel(vid_tid);
vid_tid = 0;
printf("Video Stoped!\n");
}
/* 进行图像检测 */
/* 显示结果 */
SetDlgItemText(ghWnd, IDC_WINMAIN_LEBAL, "检测结果");
sprintf(strBuf, "%f", 3.1415926);
SetDlgItemText(ghWnd, IDC_WINMAIN_NONGDUZHI, strBuf);
}
void ChooseType(void)
{
TypeWin();
}
void FillBitmap(BITMAP *bmp, int w, int h, int bpp, unsigned char *pBuf)
{
bmp->bmType = 0;
bmp->bmBitsPerPixel = 8*bpp;
bmp->bmBytesPerPixel = bpp;
bmp->bmAlpha = 0;
bmp->bmColorKey = 0;
bmp->bmWidth = w;
bmp->bmHeight = h;
bmp->bmPitch = w*2;
bmp->bmBits = pBuf;
bmp->bmAlphaPixelFormat = NULL;
}
void *__VideoThreadProc(void *arg)
{
printf("Thread Start\n");
//////////////////////////////////////////////////////////////
// 3. Read the data from video device.
while (vid_tid != 0)
{
if (buf = cVid->Read ())
{
bmp.bmBits = buf;
SendMessage (ghWnd, MSG_PAINT, 0, 0);
}
}
printf("Thread End\n");
pthread_exit(0);
}
static int DialogBoxProc2 (HWND hDlg, int message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
ghWnd = hDlg;
switch (message) {
case MSG_INITDIALOG:
{
hdc = GetDC(hDlg);
Rectangle (hdc, 0, 0, 100, 100);
//Rectangle (hdc, 0, 0, bmp.bmWidth, bmp.bmHeight);
/*if (LoadBitmap (HDC_SCREEN, &bmp, "save.bmp"))
{
return 0;
}*/
ReleaseDC(hdc);
}
break;
case MSG_PAINT:
hdc = BeginPaint (hDlg);
if (small_bmp.bmBits != NULL)
{
ScaleBitmap (&small_bmp, &bmp);
FillBoxWithBitmap (hdc, 0, 0, small_bmp.bmWidth, small_bmp.bmHeight, &small_bmp);
}
Rectangle (hdc, 0, 0, small_bmp.bmWidth, small_bmp.bmHeight);
EndPaint (hDlg, hdc);
break;
case MSG_USER:
SetDlgItemText(hDlg, IDC_WINMAIN_LEBAL, "剩余时间");
sprintf(strBuf, "%d分%d秒", wParam, lParam);
SetDlgItemText(hDlg, IDC_WINMAIN_NONGDUZHI, strBuf);
printf("剩余时间:%s\n", strBuf);
break;
case MSG_USER+1:
printf("时间到\n", wParam, lParam);
SetDlgItemText(hDlg, IDC_WINMAIN_KAISHIJISHI, "开始记时");
gbTimerStart = false;
EnableWindow(GetDlgItem(hDlg, IDC_WINMAIN_DINGSHISHEDING), true);
EnableWindow(GetDlgItem(hDlg, IDC_WINMAIN_KAISHIJIANCE), true);
if (vid_tid == 0)
{
printf("Video Begin!\n");
pthread_create(&vid_tid, NULL, &__VideoThreadProc, (void *) NULL);
printf("tid = %d\n", vid_tid);
}
break;
case MSG_COMMAND:
switch (wParam) {
case IDC_WINMAIN_KAISHIJISHI:
if (gbTimerStart)
{
SetDlgItemText(hDlg, IDC_WINMAIN_KAISHIJISHI, "开始记时");
EnableWindow(GetDlgItem(hDlg, IDC_WINMAIN_DINGSHISHEDING), true);
EnableWindow(GetDlgItem(hDlg, IDC_WINMAIN_KAISHIJIANCE), true);
gbTimerStart = false;
StopTimer();
}
else
{
SetDlgItemText(hDlg, IDC_WINMAIN_KAISHIJISHI, "停止计时");
EnableWindow(GetDlgItem(hDlg, IDC_WINMAIN_DINGSHISHEDING), false);
EnableWindow(GetDlgItem(hDlg, IDC_WINMAIN_KAISHIJIANCE), false);
gbTimerStart = true;
StartTimer();
}
break;
case IDC_WINMAIN_DINGSHISHEDING:
SetTimer();
break;
case IDC_WINMAIN_KAISHIJIANCE:
BeginDetect();
break;
case IDC_WINMAIN_XUANZEKU:
ChooseType();
SetDlgItemText(hDlg, IDC_WINMAIN_KANGSHENGSULEIXING, gszTypeName);
break;
case IDC_WINMAIN_GUANJI:
if (vid_tid != 0)
{
pthread_cancel(vid_tid);
vid_tid = 0;
printf("Video Stoped!\n");
}
EndDialog (hDlg, wParam);
//exit(0);
break;
}
break;
}
return DefaultDialogProc (hDlg, message, wParam, lParam);
}
void sig_int(int signo)
{
if (vid_tid != 0)
{
pthread_cancel(vid_tid);
vid_tid = 0;
printf("Video Stoped!\n");
}
//cVid->destroy ();
UnloadBitmap (&bmp);
printf("Stoped!\n");
exit(0);
}
int MiniGUIMain (int argc, const char* argv[])
{
#ifdef _LITE_VERSION
SetDesktopRect(0, 0, 1024, 768);
#endif
signal(SIGINT, sig_int);
//////////////////////////////////////////////////////////////
// 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, VID_W, VID_H, 2, NULL);
memset(small_buf, 0xFF, 240*180*2);
FillBitmap(&small_bmp, VID_H, 180, 2, small_buf);
//////////////////////////////////////////////////////////////
// 3. Read the data from video device.
if (buf = cVid->Read ())
{
bmp.bmBits = buf;
}
DlgYourTaste.controls = CtrlYourTaste;
DialogBoxIndirectParam (&DlgYourTaste, HWND_DESKTOP, DialogBoxProc2, 0L);
//cVid->destroy ();
UnloadBitmap (&bmp);
exit(0);
}
#ifndef _LITE_VERSION
#include <minigui/dti.c>
#endif
/*Timer.cpp*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /* UNIX standard function definitions */ /* sleep() */
#include <sys/time.h> /* timeval{} for select() */
#include <time.h> /* timespec{} for pselect() */
#include <pthread.h>
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>
#define IDC_WINMAIN_GUANJI 107
pthread_t timer_tid;
extern HWND ghWnd;
extern int giWaitTime;
void *__TimerThreadProc(void *arg)
{
int i, j;
for (i=giWaitTime-1; i>=0; i--)
{
for (j=59; j>=0; j--)
{
SendMessage(ghWnd, MSG_USER, i, j);
sleep(1);
}
}
SendMessage(ghWnd, MSG_USER+1, i, j);
pthread_exit(0);
return(NULL);
}
void StartTimer(void)
{
pthread_create(&timer_tid, NULL, &__TimerThreadProc, (void *) NULL);
}
void StopTimer(void)
{
pthread_cancel(timer_tid);
}
程序的大致思路是这样的:先开个线程,做定时器(也可以用minigui中MSG_TIMER消息来做),定时到一定时候发送自定义消息,启动图像获取线程。在图像获取线程中获取图像后发送paint消息进行绘制。
但是我发现摄像头在pc上用没有问题,在2410下用有花斑。这个问题有可能是处理器处理能力的问题,也可能是用了多线程以后的问题,因为原先花斑没这么多。
立宇太的工程师不知道有没有遇到这个问题。。。