📄 thread_display.c
字号:
/* * Copyright (C) 2000-2004 Damien Douxchamps <ddouxchamps@users.sf.net> * * 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"gintDisplayStartThread(camera_t* cam){ chain_t *display_service=NULL; displaythread_info_t *info=NULL; display_service=GetService(camera,SERVICE_DISPLAY); if (display_service==NULL) {// if no display service running... display_service=(chain_t*)malloc(sizeof(chain_t)); display_service->current_buffer=NULL; display_service->next_buffer=NULL; display_service->data=(void*)malloc(sizeof(displaythread_info_t)); info=(displaythread_info_t*)display_service->data; pthread_mutex_init(&display_service->mutex_struct, NULL); pthread_mutex_init(&display_service->mutex_data, NULL); pthread_mutex_init(&info->mutex_cancel, NULL); pthread_mutex_lock(&info->mutex_cancel); info->cancel_req=0; pthread_mutex_unlock(&info->mutex_cancel); pthread_mutex_lock(&display_service->mutex_data); info->period=cam->prefs.display_period; CommonChainSetup(cam, display_service,SERVICE_DISPLAY); pthread_mutex_lock(&display_service->mutex_struct); InsertChain(cam, display_service); if (pthread_create(&display_service->thread, NULL, DisplayThread, (void*)display_service)) { RemoveChain(cam, display_service); pthread_mutex_unlock(&display_service->mutex_struct); pthread_mutex_unlock(&display_service->mutex_data); FreeChain(display_service); return(-1); } pthread_mutex_unlock(&display_service->mutex_struct); pthread_mutex_unlock(&display_service->mutex_data); } return (1);}void*DisplayCleanupThread(void* arg){ chain_t* display_service; displaythread_info_t *info; display_service=(chain_t*)arg; info=(displaythread_info_t*)display_service->data; pthread_mutex_unlock(&display_service->mutex_data); return(NULL);}void*DisplayThread(void* arg){ chain_t* display_service=NULL; displaythread_info_t *info=NULL; long int skip_counter; float tmp; // we should only use mutex_data in this function display_service=(chain_t*)arg; pthread_mutex_lock(&display_service->mutex_data); info=(displaythread_info_t*)display_service->data; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL); pthread_mutex_unlock(&display_service->mutex_data); skip_counter=0; // time inits: display_service->prev_time = times(&display_service->tms_buf); display_service->fps_frames=0; display_service->processed_frames=0; while (1) { pthread_mutex_lock(&info->mutex_cancel); if (info->cancel_req>0) { break; } else { pthread_mutex_unlock(&info->mutex_cancel); pthread_mutex_lock(&display_service->mutex_data); if(RollBuffers(display_service)) { // have buffers been rolled?#ifdef HAVE_SDLLIB // check params DisplayThreadCheckParams(display_service);#endif if (display_service->current_buffer->width!=-1) { if (skip_counter>=(info->period-1)) { skip_counter=0;#ifdef HAVE_SDLLIB if (info->sdloverlay!=NULL) { if (SDL_LockYUVOverlay(info->sdloverlay) == 0) { convert_to_yuv_for_SDL(display_service->current_buffer, info->sdloverlay, preferences.overlay_byte_order); // informative overlays SDLDisplayArea(display_service); SDLDisplayPattern(display_service); SDL_UnlockYUVOverlay(info->sdloverlay); SDL_DisplayYUVOverlay(info->sdloverlay, &info->sdlvideorect); info->redraw_prev_time=times(&info->redraw_tms_buf); } }#endif display_service->fps_frames++; display_service->processed_frames++; } else { // if (display_service->camera->prefs.display_redraw==DISPLAY_REDRAW_ON) { ConditionalTimeoutRedraw(display_service); } skip_counter++; } // FPS display: display_service->current_time=times(&display_service->tms_buf); tmp=(float)(display_service->current_time-display_service->prev_time)/sysconf(_SC_CLK_TCK); if (tmp==0) display_service->fps=fabs(0.0); else display_service->fps=fabs((float)display_service->fps_frames/tmp); } pthread_mutex_unlock(&display_service->mutex_data); } else { // if (display_service->camera->prefs.display_redraw==DISPLAY_REDRAW_ON) { ConditionalTimeoutRedraw(display_service); } pthread_mutex_unlock(&display_service->mutex_data); } } usleep(0); } pthread_mutex_unlock(&info->mutex_cancel); return ((void*)1);}// the goal of the following function is to redraw the SDL display twice a second so that the image follows the screen// during window movement or if another window comes momentarily on top of the display while no images are coming. voidConditionalTimeoutRedraw(chain_t* service){ displaythread_info_t *info=NULL; float interval; info=(displaythread_info_t*)service->data; if (service->current_buffer->width!=-1) { info->redraw_current_time=times(&info->redraw_tms_buf); interval=fabs((float)(info->redraw_current_time-info->redraw_prev_time)/sysconf(_SC_CLK_TCK)); if (interval>(1.0/service->camera->prefs.display_redraw_rate)) { // redraw e.g. 4 times per second#ifdef HAVE_SDLLIB if (SDL_LockYUVOverlay(info->sdloverlay) == 0) { //MainStatus("Conditional display redraw"); convert_to_yuv_for_SDL(service->current_buffer, info->sdloverlay, preferences.overlay_byte_order); SDLDisplayArea(service); SDL_UnlockYUVOverlay(info->sdloverlay); SDL_DisplayYUVOverlay(info->sdloverlay, &info->sdlvideorect); }#endif info->redraw_prev_time=times(&info->redraw_tms_buf); } }}gintDisplayStopThread(camera_t* cam){ displaythread_info_t *info; chain_t *display_service; display_service=GetService(cam,SERVICE_DISPLAY); if (display_service!=NULL) { // if display service running... info=(displaythread_info_t*)display_service->data; // send request for cancellation: pthread_mutex_lock(&info->mutex_cancel); info->cancel_req=1; pthread_mutex_unlock(&info->mutex_cancel); // when cancellation occured, join: pthread_join(display_service->thread, NULL); pthread_mutex_lock(&display_service->mutex_data); pthread_mutex_lock(&display_service->mutex_struct); RemoveChain(cam,display_service);#ifdef HAVE_SDLLIB SDLQuit(display_service);#endif pthread_mutex_unlock(&display_service->mutex_struct); pthread_mutex_unlock(&display_service->mutex_data); FreeChain(display_service); } return (1);}#ifdef HAVE_SDLLIBintSDLInit(chain_t *display_service){ displaythread_info_t *info; const SDL_VideoInfo *sdl_videoinfo; SDL_Rect** modes; info=(displaythread_info_t*)display_service->data; //SDL_Surface *icon_surface; info->sdlbpp=16; info->sdlflags=SDL_ANYFORMAT | SDL_RESIZABLE; // Initialize the SDL library (video subsystem) if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) == -1) { fprintf(stderr,"Couldn't initialize SDL video subsystem\n"); return(0); } sdl_videoinfo = SDL_GetVideoInfo(); if ((xvinfo.max_width!=-1)&&(xvinfo.max_height!=-1)) { // if the XV area is too small, we use software accelleration if ((xvinfo.max_width<display_service->current_buffer->width)|| (xvinfo.max_height<display_service->current_buffer->height)) { //fprintf(stderr,"Using SW surface\n"); info->sdlflags|= SDL_SWSURFACE; info->sdlflags&= ~SDL_HWSURFACE; info->sdlflags&= ~SDL_HWACCEL; } else { //fprintf(stderr,"Using HW surface\n"); info->sdlflags|= SDL_HWSURFACE; info->sdlflags|= SDL_HWACCEL; info->sdlflags&= ~SDL_SWSURFACE; } } else { // try HW accel and pray... info->sdlflags|= SDL_SWSURFACE; info->sdlflags&= ~SDL_HWSURFACE; info->sdlflags&= ~SDL_HWACCEL; } modes=SDL_ListModes(NULL,info->sdlflags); if (modes!=(SDL_Rect**)-1) { // not all resolutions are OK for this video card. For safety we switch to software accel fprintf(stderr,"No SDL mode available with hardware accel. Trying without HWSURFACE\n"); info->sdlflags&= ~SDL_HWSURFACE; info->sdlflags&= ~SDL_HWACCEL; modes=SDL_ListModes(NULL,info->sdlflags); if (modes!=(SDL_Rect**)-1) { fprintf(stderr,"Still no modes available. Can't start SDL!\n"); SDL_Quit(); return(0); } } /* // set coriander icon icon_surface=SDL_CreateRGBSurfaceFrom((void*)coriander_logo_xpm) SDL_WM_SetIcon(icon_surface,NULL); */ info->sdlvideorect.x=0; info->sdlvideorect.y=0; info->sdlvideorect.w=display_service->current_buffer->width; info->sdlvideorect.h=display_service->current_buffer->height; // maximize display size to XV size if necessary if ((xvinfo.max_width!=-1)&&(xvinfo.max_height!=-1)) { if (info->sdlvideorect.w>xvinfo.max_width) { info->sdlvideorect.w=xvinfo.max_width; } if (info->sdlvideorect.h>xvinfo.max_height) { info->sdlvideorect.h=xvinfo.max_height; } } // Set requested video mode info->sdlbpp = SDL_VideoModeOK(info->sdlvideorect.w, info->sdlvideorect.h, info->sdlbpp, info->sdlflags); info->sdlvideo = SDL_SetVideoMode(info->sdlvideorect.w, info->sdlvideorect.h, info->sdlbpp, info->sdlflags); if (info->sdlvideo == NULL) { MainError(SDL_GetError()); SDL_Quit(); return(0); } if (SDL_SetColorKey( info->sdlvideo, SDL_SRCCOLORKEY, 0x0) < 0 ) { MainError(SDL_GetError()); } // Show cursor SDL_ShowCursor(1); // set window title: SDL_WM_SetCaption(camera->prefs.name,camera->prefs.name); // this line broke everything for unknown reasons so I just remove it. //info->sdlvideo->format->BytesPerPixel=2; // Create YUV Overlay switch(preferences.overlay_byte_order) { case OVERLAY_BYTE_ORDER_YUYV: info->sdloverlay = SDL_CreateYUVOverlay(display_service->current_buffer->width, display_service->current_buffer->height, SDL_YUY2_OVERLAY,info->sdlvideo); break; case OVERLAY_BYTE_ORDER_UYVY: info->sdloverlay = SDL_CreateYUVOverlay(display_service->current_buffer->width, display_service->current_buffer->height, SDL_UYVY_OVERLAY,info->sdlvideo); break; default: fprintf(stderr,"Invalid overlay byte order\n"); break; } if (info->sdloverlay==NULL) { MainError(SDL_GetError()); SDL_Quit(); return(0); } SDLEventStartThread(display_service); return(1);}// we should optimize this for RGB too: RGB modes could use RGB-SDL instead of YUV overlayvoidconvert_to_yuv_for_SDL(buffer_t *buffer, SDL_Overlay *sdloverlay, int overlay_byte_order){ unsigned char *dest=sdloverlay->pixels[0]; switch(buffer->buffer_color_mode) { case COLOR_FORMAT7_MONO8: y2uyvy(buffer->image, dest, buffer->width, buffer->height, sdloverlay->pitches[0], overlay_byte_order); break; case COLOR_FORMAT7_YUV411:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -