📄 thread_v4l.c
字号:
/* * Copyright (C) 2000-2004 Damien Douxchamps <ddouxchamps@users.sf.net> * Dan Dennedy <dan@dennedy.org> * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "coriander.h"gintV4lStartThread(camera_t* cam){ chain_t* v4l_service=NULL; v4lthread_info_t *info=NULL; char *stemp; stemp=(char*)malloc(STRING_SIZE*sizeof(char)); v4l_service=GetService(camera, SERVICE_V4L); if (v4l_service==NULL) { // if no V4L service running... v4l_service=(chain_t*)malloc(sizeof(chain_t)); v4l_service->current_buffer=NULL; v4l_service->next_buffer=NULL; v4l_service->data=(void*)malloc(sizeof(v4lthread_info_t)); info=(v4lthread_info_t*)v4l_service->data; pthread_mutex_init(&v4l_service->mutex_data, NULL); pthread_mutex_init(&v4l_service->mutex_struct, NULL); pthread_mutex_init(&info->mutex_cancel, NULL); /* if you want a clean-interrupt thread:*/ pthread_mutex_lock(&info->mutex_cancel); info->cancel_req=0; pthread_mutex_unlock(&info->mutex_cancel); /* setup v4l_thread: handles, ...*/ pthread_mutex_lock(&v4l_service->mutex_data); info->period=cam->prefs.v4l_period; CommonChainSetup(cam, v4l_service,SERVICE_V4L); info->v4l_buffer=NULL; //info->counter=0; // COPY CAM->PREFS HERE strcpy(info->v4l_dev_name,cam->prefs.v4l_dev_name); // open V4L device info->v4l_dev=-1; info->v4l_dev = open(info->v4l_dev_name, O_RDWR); if (info->v4l_dev < 0) { sprintf(stemp,"Failed to open V4L device %s",info->v4l_dev_name); MainError(stemp); free(stemp); FreeChain(v4l_service); return(-1); } /* Insert chain and start service*/ pthread_mutex_lock(&v4l_service->mutex_struct); InsertChain(cam, v4l_service); if (pthread_create(&v4l_service->thread, NULL, V4lThread,(void*) v4l_service)) { /* error starting thread. You should cleanup here (free, unset global vars,...):*/ /* Mendatory cleanups:*/ RemoveChain(cam, v4l_service); pthread_mutex_unlock(&v4l_service->mutex_struct); pthread_mutex_unlock(&v4l_service->mutex_data); free(info->v4l_buffer); free(stemp); FreeChain(v4l_service); return(-1); } pthread_mutex_unlock(&v4l_service->mutex_struct); pthread_mutex_unlock(&v4l_service->mutex_data); } free(stemp); return (1);}void*V4lCleanupThread(void* arg) { chain_t* v4l_service; v4lthread_info_t *info; v4l_service=(chain_t*)arg; info=(v4lthread_info_t*)v4l_service->data; /* Specific cleanups: */ /* Mendatory cleanups: */ pthread_mutex_unlock(&v4l_service->mutex_data); return(NULL);}void*V4lThread(void* arg){ chain_t* v4l_service=NULL; v4lthread_info_t *info=NULL; long int skip_counter; float tmp; v4l_service=(chain_t*)arg; pthread_mutex_lock(&v4l_service->mutex_data); info=(v4lthread_info_t*)v4l_service->data; skip_counter=0; v4l_service->processed_frames=0; /* These settings depend on the thread. For 100% safe deferred-cancel threads, I advise you use a custom thread cancel flag. See display thread.*/ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL); pthread_mutex_unlock(&v4l_service->mutex_data); // time inits: v4l_service->prev_time = times(&v4l_service->tms_buf); v4l_service->fps_frames=0; while (1) { /* Clean cancel handlers */ pthread_mutex_lock(&info->mutex_cancel); if (info->cancel_req>0) { break; } else { pthread_mutex_unlock(&info->mutex_cancel); pthread_mutex_lock(&v4l_service->mutex_data); if(RollBuffers(v4l_service)) { // have buffers been rolled? // check params V4lThreadCheckParams(v4l_service); convert_to_rgb(v4l_service->current_buffer, info->v4l_buffer); swap_rb(info->v4l_buffer, v4l_service->current_buffer->width*v4l_service->current_buffer->height*3); if (v4l_service->current_buffer->width!=-1) { if (skip_counter>=(info->period-1)) { skip_counter=0; write(info->v4l_dev,info->v4l_buffer,v4l_service->current_buffer->width*v4l_service->current_buffer->height*3); v4l_service->fps_frames++; v4l_service->processed_frames++; } else skip_counter++; // FPS display v4l_service->current_time=times(&v4l_service->tms_buf); tmp=(float)(v4l_service->current_time-v4l_service->prev_time)/sysconf(_SC_CLK_TCK); if (tmp==0) v4l_service->fps=fabs(0.0); else v4l_service->fps=fabs((float)v4l_service->fps_frames/tmp); } pthread_mutex_unlock(&v4l_service->mutex_data); } else { pthread_mutex_unlock(&v4l_service->mutex_data); } } usleep(0); } pthread_mutex_unlock(&info->mutex_cancel); return ((void*)1);}gintV4lStopThread(camera_t* cam){ v4lthread_info_t *info; chain_t *v4l_service; v4l_service=GetService(cam,SERVICE_V4L); if (v4l_service!=NULL) { // if V4L service running... info=(v4lthread_info_t*)v4l_service->data; /* Clean cancel handler: */ pthread_mutex_lock(&info->mutex_cancel); info->cancel_req=1; pthread_mutex_unlock(&info->mutex_cancel); /* common handlers...*/ pthread_join(v4l_service->thread, NULL); pthread_mutex_lock(&v4l_service->mutex_data); pthread_mutex_lock(&v4l_service->mutex_struct); RemoveChain(cam,v4l_service); /* Do custom cleanups here...*/ if (info->v4l_buffer!=NULL) { free(info->v4l_buffer); info->v4l_buffer=NULL; } close(info->v4l_dev); /* Mendatory cleanups: */ pthread_mutex_unlock(&v4l_service->mutex_struct); pthread_mutex_unlock(&v4l_service->mutex_data); FreeChain(v4l_service); } return (1);}voidV4lThreadCheckParams(chain_t *v4l_service){ v4lthread_info_t *info; int buffer_size_change=0; info=(v4lthread_info_t*)v4l_service->data; // copy harmless parameters anyway: v4l_service->local_param_copy.bpp=v4l_service->current_buffer->bpp; v4l_service->local_param_copy.bayer_pattern=v4l_service->current_buffer->bayer_pattern; // if some parameters changed, we need to re-allocate the local buffers and restart the v4l if ((v4l_service->current_buffer->width!=v4l_service->local_param_copy.width)|| (v4l_service->current_buffer->height!=v4l_service->local_param_copy.height)|| (v4l_service->current_buffer->bytes_per_frame!=v4l_service->local_param_copy.bytes_per_frame)|| (v4l_service->current_buffer->mode!=v4l_service->local_param_copy.mode)|| (v4l_service->current_buffer->format!=v4l_service->local_param_copy.format)|| // check F7 color mode change ((v4l_service->current_buffer->format==FORMAT_SCALABLE_IMAGE_SIZE)&& (v4l_service->current_buffer->format7_color_mode!=v4l_service->local_param_copy.format7_color_mode) ) || // check bayer and stereo decoding (v4l_service->current_buffer->stereo_decoding!=v4l_service->local_param_copy.stereo_decoding)|| (v4l_service->current_buffer->bayer!=v4l_service->local_param_copy.bayer) ) { if (v4l_service->current_buffer->width*v4l_service->current_buffer->height!= v4l_service->local_param_copy.width*v4l_service->local_param_copy.height) { buffer_size_change=1; } else { buffer_size_change=0; } // copy all new parameters: v4l_service->local_param_copy.width=v4l_service->current_buffer->width; v4l_service->local_param_copy.height=v4l_service->current_buffer->height; v4l_service->local_param_copy.bytes_per_frame=v4l_service->current_buffer->bytes_per_frame; v4l_service->local_param_copy.mode=v4l_service->current_buffer->mode; v4l_service->local_param_copy.format=v4l_service->current_buffer->format; v4l_service->local_param_copy.format7_color_mode=v4l_service->current_buffer->format7_color_mode; v4l_service->local_param_copy.stereo_decoding=v4l_service->current_buffer->stereo_decoding; v4l_service->local_param_copy.bayer=v4l_service->current_buffer->bayer; v4l_service->local_param_copy.buffer_image_bytes=v4l_service->current_buffer->buffer_image_bytes; // DO SOMETHING if (buffer_size_change!=0) { // clear buffer if (info->v4l_buffer!=NULL) { free(info->v4l_buffer); info->v4l_buffer=NULL; } // create buffer info->v4l_buffer=(unsigned char*)malloc(v4l_service->current_buffer->width*v4l_service->current_buffer->height *3*sizeof(unsigned char)); if (info->v4l_buffer==NULL) { fprintf(stderr,"Can't allocate buffer! Aiiieee!\n"); } // STOPING THE PIPE MIGHT BE NECESSARY HERE // "start pipe" if (ioctl (info->v4l_dev, VIDIOCGCAP, &info->vid_caps) == -1) { perror ("ioctl (VIDIOCGCAP)"); } if (ioctl (info->v4l_dev, VIDIOCGPICT, &info->vid_pic)== -1) { perror ("ioctl VIDIOCGPICT"); } info->vid_pic.palette = VIDEO_PALETTE_RGB24; if (ioctl (info->v4l_dev, VIDIOCSPICT, &info->vid_pic)== -1) { perror ("ioctl VIDIOCSPICT"); } if (ioctl (info->v4l_dev, VIDIOCGWIN, &info->vid_win)== -1) { perror ("ioctl VIDIOCGWIN"); } info->vid_win.width=v4l_service->current_buffer->width; info->vid_win.height=v4l_service->current_buffer->height; if (ioctl (info->v4l_dev, VIDIOCSWIN, &info->vid_win)== -1) { perror ("ioctl VIDIOCSWIN"); } } }}voidswap_rb(unsigned char *image, int i) { unsigned char t; i--; while (i>0) { t=image[i]; image[i]=image[i-2]; image[i-2]=t; i-=3; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -