📄 gtk_cam.c
字号:
#include <strings.h>#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/mman.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include <time.h>#include <gtk/gtk.h>#include <errno.h>#include <stdlib.h>#include "grab-ng.h"#include "dh-ioctl.h"//#define __YUV422_CAP__ //采用YUV格式采集int TOP = 0, LEFT = 0; //窗体起始坐标int COLS = 768, ROWS = 288; //采集窗体的大小int frame = 0;int send_num = 0;int bt8x8_handle = 0; //设备句柄unsigned char *card0_buf = NULL; //硬件采集到的原始图像数据指针unsigned char *card0_dest_buf = NULL; //经过格式转换后的图像数据指针char title[256];int g_err_num = 0;int global_frames = 0; //用来计算FPSint capture_flag = 0; //preview采集控制参数int overlay_flag = 0; //overlay采集控制参数int b_current = 0, c_current = 0, s_current = 0, h_current = 0; //用来存取图像亮度对比度等参数GtkObject *b_adj, *c_adj, *s_adj, *h_adj;time_t stTime;GtkWidget *main_win;GtkWidget *status;GtkWidget *darea;GtkWidget *label;gdouble gtk_adjustment_get_value (GtkAdjustment * adjustment);int send_expose (void);void on_darea_expose (GtkWidget * widget);gint configure_event (GtkWidget * widget);static void overlay_display (void);//打开设备void open_dev (void){ int rc; card0_dest_buf = (unsigned char *) malloc (768 * 576 * 3); //申请存放处理后图像数据的内存空间 bt8x8_handle = dh_OpenVideo (0); //打开设备 if (bt8x8_handle < 0) { printf (dh_GetErrInfo ()); free (card0_dest_buf); exit (-1); }#ifdef __YUV422_CAP__ rc = dh_MSetCaptureNorm (bt8x8_handle, COLS, ROWS, VIDEO_YUYV); //YUV格式采集#else rc = dh_MSetCaptureNorm (bt8x8_handle, COLS, ROWS, VIDEO_BGR24); //BGR格式采集#endif if (rc < 0) { printf (dh_GetErrInfo ()); } if (dh_SetVideoSource (bt8x8_handle, VIDEO_SOURCE_COMPOSITE0) < 0) //设置源路为复合视频1 { printf (dh_GetErrInfo ()); } if (dh_SetVideoStandard (bt8x8_handle, VIDEO_MODE_PAL) < 0) //设置源路制式为PAL制 { printf (dh_GetErrInfo ()); }//default value dh_SetBrightness (bt8x8_handle, 65535 / 2); dh_SetContrast (bt8x8_handle, 65535 / 2); dh_SetSaturation (bt8x8_handle, 65535 / 2); dh_SetHue (bt8x8_handle, 65535 / 2);}/*---------------------------菜单要调用的函数(callback)---------------------------------*///菜单项preview要调用的函数static void preview_display (void){ time (&stTime); g_err_num = 0; //采集之前判断是否有视频信号输入 if (!dh_IsVideoOn (bt8x8_handle)) { printf ("Video source not ready.\n"); return; } //如果正在overlay采集,先停止overlay采集 if (overlay_flag) overlay_display (); //由capture_flag判断开始采集还是停止采集 if (capture_flag == 0) { capture_flag = 1; //如果窗体大小变化,每次采集前得重新设置采集参数#ifdef __YUV422_CAP__ dh_MSetCaptureNorm (bt8x8_handle, COLS, ROWS, VIDEO_YUYV);#else dh_MSetCaptureNorm (bt8x8_handle, COLS, ROWS, VIDEO_BGR24);#endif dh_MStartCapture (bt8x8_handle, 4); //发往内存循环采集命令,使用4个缓冲区 gtk_timeout_add (10, (GtkFunction) send_expose, NULL); //每10秒调用一次函数send_expose() } else { capture_flag = 0; dh_MStopCapture (bt8x8_handle); //停止往内存循环采集 }}//定时器调用的函数,实现连续采集显示int send_expose (void){ if (capture_flag == 1) { //返回采集完成当前帧的指针,同时发出采集下帧的命令 card0_buf = dh_MGetNextFrame (bt8x8_handle); if (NULL == card0_buf) { printf ("card0_buf is NULL.\n"); //如果采集错误,重启采集 dh_MStopCapture (bt8x8_handle); dh_MStartCapture (bt8x8_handle, 4); g_err_num++; } else { on_darea_expose (darea); //调用此函数实现图像显示 //释放内存,否则循环采集无法进行下去 if (dh_MReleaseBuf (bt8x8_handle) < 0) { printf (dh_GetErrInfo ()); } } } return 1;}//菜单项overlay调用的函数:往屏幕采集static voidoverlay_display (void){ int wx, wy; wx = TOP + 4; wy = LEFT + 56; //采集之前判断是否有视频信号输入 if (!dh_IsVideoOn (bt8x8_handle)) { printf ("Video source not ready.\n"); return; } gtk_widget_set_uposition (main_win, TOP, LEFT); if (overlay_flag == 0) { //如果正在preview采集,先停下来 if(capture_flag) { capture_flag = 0; dh_MStopCapture (bt8x8_handle); } //开始overlay采集 dh_OStartCapture (bt8x8_handle, COLS, ROWS, wx, wy); overlay_flag = 1; } else { //停止overlay采集 dh_OStopCapture (bt8x8_handle); overlay_flag = 0; }}//菜单项grab调用的的函数抓单帧static void grab_one_display (void){ int i; time (&stTime); g_err_num = 0; //如果正在preview采集,先停下来 if (capture_flag == 1) preview_display (); //stop capture //如果正在overlay采集,先停下来 if (overlay_flag) overlay_display (); //采集之前判断是否有视频信号输入 if (!dh_IsVideoOn (bt8x8_handle)) { printf ("Video source not ready.\n"); return; }//for(;;) //死循环抓单帧采集,用来测试性能 { card0_buf = dh_MCaptureOne (bt8x8_handle); //正常抓单帧或单场采集,FPS最高8帧/秒 //card0_buf = dh_MFastCaptureOne(bt8x8_handle); //快速抓单帧或单场采集,FPS可达到16帧/秒 //dh_MSnapOne(bt8x8_handle); //card0_buf = dh_MGetSnapOneStatus(bt8x8_handle); if (NULL == card0_buf) { printf (dh_GetErrInfo ()); g_err_num++; } else { on_darea_expose (darea); //调用此函数实现图像显示 //释放内存,否则循环采集无法进行下去,如果是快速采集则无需调用此函数 if (dh_MReleaseBuf (bt8x8_handle) < 0) { printf (dh_GetErrInfo ()); } } } gtk_statusbar_push (GTK_STATUSBAR (status), 1, "Grab a picture"); g_message ("Grab a picture!\n");}//此函数用来显示图像和计算FPSvoid on_darea_expose (GtkWidget * widget){ static time_t init, end; static int frames; if (!frames) { time (&init); } if (!card0_buf) { return; } gdk_threads_enter (); //转换成24位RGB#ifdef __YUV422_CAP__ yuv422_to_rgb24 (card0_dest_buf, card0_buf, COLS * ROWS);#else redblue_swap (card0_dest_buf, card0_buf, COLS * ROWS);#endif //显示图像 gdk_draw_rgb_image (widget->window, widget->style->white_gc, 0, 0, COLS, ROWS, GDK_RGB_DITHER_NORMAL, card0_dest_buf, COLS * 3); gdk_threads_leave (); frames++; time (&end); if (end - init >= 1) { global_frames = frames; frames = 0; sprintf (title, "RTime=%d,FPS %d,Err=%d", (int) (end - stTime), global_frames, g_err_num); gtk_statusbar_push (GTK_STATUSBAR (status), 1, title); fprintf (stderr, "%s\n", title); }}//退出程序static void exit_program (void){ int rc = 0; capture_flag = 0; //退出程序前先释放buf if (NULL != card0_buf) { rc = dh_MReleaseBuf (bt8x8_handle); if (rc == 0) card0_buf = NULL; } free (card0_dest_buf); dh_CloseVideo (bt8x8_handle);//关闭设备句柄 gtk_main_quit ();}//菜单项option->SourceInput调用下列函数static void set_ch_video0 (){ dh_SetVideoSource (bt8x8_handle, VIDEO_SOURCE_COMPOSITE0); g_message ("use VIDEO_SOURCE_COMPOSITE0.\n");}static voidset_ch_video1 (void){ dh_SetVideoSource (bt8x8_handle, VIDEO_SOURCE_COMPOSITE1); g_message ("use VIDEO_SOURCE_COMPOSITE1.\n");}static voidset_ch_video2 (void){ dh_SetVideoSource (bt8x8_handle, VIDEO_SOURCE_COMPOSITE2); g_message ("use VIDEO_SOURCE_COMPOSITE2.\n");}static voidset_ch_video3 (void){ dh_SetVideoSource (bt8x8_handle, VIDEO_SOURCE_SVIDEO); g_message ("use VIDEO_SOURCE_SVIDEO.\n");}//菜单项option->SourceNorm调用下列函数static voidset_norm_pal (void){ dh_SetVideoStandard (bt8x8_handle, VIDEO_MODE_PAL); g_message ("change source norm to PAL.\n");}static voidset_norm_ntsc (void){ dh_SetVideoStandard (bt8x8_handle, VIDEO_MODE_NTSC); g_message ("change source norm to NTSC.\n");}static voidset_norm_secam (void){ dh_SetVideoStandard (bt8x8_handle, VIDEO_MODE_SECAM); g_message ("change source norm to SECAM.\n");}static voidclick_ok (GtkWidget * widget, gpointer window){ dh_GetBrightness (bt8x8_handle, &b_current); dh_GetContrast (bt8x8_handle, &c_current); dh_GetSaturation (bt8x8_handle, &s_current);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -