📄 spcaview.c
字号:
/****************************************************************************# spcaview: Sdl video recorder and viewer with sound. ##This package work with the spca5xx based webcam with the raw jpeg feature. ##All the decoding is in user space with the help of libjpeg. ##. ## Copyright (C) 2003 2004 2005 Michel Xhaard ## ## 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 <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>
#include <winsock2.h>
#include <SDL.h>#include <SDL_thread.h>#include <SDL_audio.h>#include <SDL_timer.h>#include <errno.h>#include <fcntl.h>#include <time.h>#include <signal.h>#include "SDL_audioin.h"#include "jconfig.h"#include "dpsh.h"// 整理之后必须的#include "utils.h"#include "tcputils.h"#include "spcaframe.h"#include "version.h"#include "picture.h"#include "videodev.h"#include "avilib.h"#define WAVE_AUDIO_PCM 1#define CHANNELS 1#define AUDIO_SAMPLERATE 22050 // 44100 // 11025 // 8000 // 22050#define AUDIO_SAMPLES 512 // 1024#define AUDIO_FORMAT AUDIO_S16#define AUDIOSIZE 2#define NUM_CHUNCK 64 // 256 a large ring buffer #define MAXBUFFERSIZE (AUDIO_SAMPLES*AUDIOSIZE*NUM_CHUNCK)#define HELPBUFFERSIZE (AUDIO_SAMPLES*AUDIOSIZE)// INIT_BRIGHT is the initial brightness level// BRIGHTMEAN is the goal mean brightness for the // auto adjustment.// SPRING_CONSTANT determines the restoring force// for the auto adjust// BRIGHT_WINDOW is the window around the goal mean// in which no adjustment is to occur#define V4L_BRIGHT_MIN 0#define V4L_BRIGHT_MAX 50000 //65000#define BRIGHTMEAN 128 //145#define SPRING_CONSTANT 25#define BRIGHTWINDOW 10/* pictFlag should be set by the hardware or the timer *//* call_back function need to reset the flag *//* picture structure */typedef struct pictstruct{ unsigned char *data; int sizeIn; int width; int height; int formatIn; int mode; avi_t *out_fd; // pthread_mutex_t mutex; // pthread_cond_t cond;} pictstruct;static int totmean;
int interval = 0;
volatile int pictFlag = 0;
static int Oneshoot = 1;
static int numshoot = 0;
static int modshoot = 0;
static videoOk = 0;
/* sound buffer */struct Rbuffer { Uint8 buffer[MAXBUFFERSIZE]; Uint8 helpbuffer[HELPBUFFERSIZE]; int ptread ; int ptwrite;};#ifdef __cplusplusextern "C" {#endif/*__cplusplus*/ Uint32 GetVideoBpp (void); void callback_record(void *userdata, Uint8 *stream, int len);void callback_play(void *userdata, Uint8 *stream, int len);static int clip_to(int x, int low, int high);//void equalize (unsigned char *src, int width, int height, int format);static int get_pic_mean ( int width, int height, const unsigned char *buffer, int is_rgb,int startx, int starty, int endx, int endy );static int isSpcaChip (const char *BridgeName);/* return Bridge otherwhise -1 */static int getStreamId (const char * BridgeName);/* return Stream_id otherwhise -1 */static int probeSize (const char *BridgeName, int *width, int *height); /* return 1->ok otherwhise -1 */void resize (unsigned char *dst,unsigned char *src, int Wd,int Hd,int Ws,int Hs) ;static void refresh_screen (unsigned char *src, unsigned char *pict, int format, int width, int height,int owidth ,int oheight, int size, int autobright);int spcaClient (char *Ip, short port,int owidth, int oheight ,int statOn);void init_callbackmessage(struct client_t* callback);void reset_callbackmessage(struct client_t* callback);void init_sdlall(void);void init_sdlvideo(void);void close_sdlvideo(void);int readjpeg(int sock, unsigned char **buf,struct frame_t *headerframe,struct client_t *message,int statOn);
#ifdef __cplusplus}#endif/*__cplusplus*/
static Uint32 callback_timer (Uint32 interval){ pictFlag = 1; //printf("TIMER ON !!!!\n"); return interval;}void callback_record(void *userdata, Uint8 *stream, int len){ int part1 =0; int part2 =0; struct Rbuffer *mybuf=(struct Rbuffer*) userdata; if ((mybuf->ptwrite + len) > MAXBUFFERSIZE){ part1=MAXBUFFERSIZE-mybuf->ptwrite; part2 = len-part1; memcpy (mybuf->buffer+mybuf->ptwrite,stream,part1); memcpy (mybuf->buffer,stream+part1,part2); } else { memcpy(mybuf->buffer+mybuf->ptwrite,stream,len); } mybuf->ptwrite = (mybuf->ptwrite +len) % MAXBUFFERSIZE; //fprintf(stderr,"callback_record(%p,%d,%d %d)\n",userdata,mybuf->ptwrite,part1,part2); }void callback_play(void *userdata, Uint8 *stream, int len){ struct Rbuffer *mybuf=(struct Rbuffer*) userdata; int ptwrite=mybuf->ptwrite ; int ptread =mybuf->ptread; int part1 =0; int part2 =0; int delta =0; delta = ptwrite-ptread; if(delta < 0){ if (((MAXBUFFERSIZE + delta) >= len)){ part1=MAXBUFFERSIZE-ptread; if (part1 >=len){ part1 = len; part2 = 0 ; } else { part2 = len-part1; } //fprintf(stderr,"callback_playT part1 %d part2 %d \n",part1,part2); memcpy (mybuf->helpbuffer,mybuf->buffer+ptread,part1); if (part2) memcpy (mybuf->helpbuffer+part1,mybuf->buffer,part2); SDL_MixAudio(stream,mybuf->helpbuffer, len, SDL_MIX_MAXVOLUME); mybuf->ptread = (mybuf->ptread +len) % MAXBUFFERSIZE; //fprintf(stderr,"callback_playT ptread %d ptwrite %d \n",ptread,ptwrite); } else { //fprintf(stderr,"Waiting for dataT to Play Ptread %dPtwrite %d !! \n",ptread,ptwrite); } } else { if (delta >= len){ memcpy (mybuf->helpbuffer,mybuf->buffer+ptread,len); SDL_MixAudio(stream,mybuf->helpbuffer, len, SDL_MIX_MAXVOLUME); mybuf->ptread = (mybuf->ptread +len) % MAXBUFFERSIZE; //fprintf(stderr,"callback_playF ptread %d ptwrite %d \n",ptread,ptwrite); } else { //fprintf(stderr,"Waiting for dataF to Play Ptread %d Ptwrite %d !! \n",ptread,ptwrite); } }} void init_callbackmessage(struct client_t* callback){ char key[4] ={'O','K','\0','\0'} ; int x = 128; int y = 128; unsigned char sleepon=0; unsigned char bright=0; unsigned char contrast =0; unsigned char exposure = 0; unsigned char colors = 0; unsigned char size = 0; unsigned char fps = 0; memcpy(callback->message,key,4); callback->x = x; callback->y = y; callback->updobright=bright; callback->updocontrast=contrast; callback->updoexposure = exposure; callback->updocolors = colors; callback->sleepon=sleepon; callback->updosize = size; callback->fps = fps; }/* callback spec updobright = 1 increase bright updobright = 0 nothing todo updobright = 2 decrease bright same for all updocontrast updosize fps number of frame to skip 1 mean 1 frame every 2 2 mean 1 frame send 2 skipped 0 all frame are send sleepon =1 ask the server for no frame on wakeup sleepon is cleared server will send frame and client should display sleepon =2 ask the server to send a 100ms pulse on pin 14 pin 14 is inverted always 1 pulse 0*/void reset_callbackmessage(struct client_t* callback){ callback->updobright= 0; callback->updocontrast= 0; callback->updoexposure = 0; callback->updocolors = 0; callback->sleepon= 0; callback->updosize = 0; //callback->fps = 0; } int readjpeg(int sock, unsigned char **buf,struct frame_t *headerframe,struct client_t *message,int statOn){ int byteread,bytewrite; bytewrite = write_sock(sock,(unsigned char*)message,sizeof(struct client_t)); // is sleeping ? if ((byteread= read_sock(sock,(unsigned char*)headerframe,sizeof(struct frame_t))) < 0){ printf("Seem server is gone !! try later \n"); goto error; } if(statOn)
{ printf (" key %s nb %d width %d height %d times %dms size %d \n",headerframe->header, headerframe->nbframe,headerframe->w,headerframe->h,headerframe->deltatimes,headerframe->size); }
if(headerframe->size && !headerframe->wakeup)
{ *buf=(unsigned char*) realloc(*buf,headerframe->size); if((byteread = read_sock(sock,*buf,headerframe->size)) < 0)
{ printf("Seem server is gone !! try later \n"); goto error;
}
} //printf("buf read %d \n",byteread); if(headerframe->acknowledge) reset_callbackmessage(message);// usleep(5000); return ((headerframe->wakeup)?0:(headerframe->size));//return (headerframe->size);error:return -1;}void init_sdlall(void){ /* Initialize defaults, Video and Audio */ if ((SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER ) == -1)) { printf ("Could not initialize SDL: %s.\n", SDL_GetError ()); exit (-1); } videoOk =1; atexit (SDL_Quit); }void init_sdlvideo(void){ /* Initialize defaults, Video and Audio */ if ((SDL_InitSubSystem (SDL_INIT_VIDEO ) == -1)) { printf ("Could not initialize SDL: %s.\n", SDL_GetError ()); exit (-1); } videoOk = 1;}void close_sdlvideo(void){ SDL_QuitSubSystem (SDL_INIT_VIDEO ) ; videoOk = 0;}int spcaClient (char *Ip, short port,int owidth, int oheight, int statOn){ struct frame_t *headerframe; struct client_t *messcallback; unsigned char *buf = NULL; int width,height; int jpegsize; int sock_client; int run = 1; int quit =1; int keypressed =0; int bpp = 3; SDL_Surface *pscreen; SDL_Event sdlevent; unsigned char* p= NULL; unsigned char *picture = NULL; struct tm *tdate; time_t curdate; char titre[21];
WORD wVersion=MAKEWORD(2,0);
WSADATA wsData;
int nResult= WSAStartup(wVersion,&wsData);
if(nResult !=0)
{
printf("初始化 ws2_32.dll 出错!\n");
exit(0);
}
init_sdlall(); sock_client = open_clientsock(Ip,port); headerframe=(struct frame_t*)malloc(sizeof(struct frame_t)); messcallback=(struct client_t*)malloc(sizeof(struct client_t)); init_callbackmessage(messcallback); if ((jpegsize = readjpeg(sock_client,&buf,headerframe,messcallback,statOn)) < 0)
{ printf("got size = 0 \n"); goto error; } width = headerframe->w; height = headerframe->h; if(!owidth || !oheight)
{ owidth = width; oheight = height; } if(videoOk)
{ pscreen = SDL_SetVideoMode (owidth, oheight, bpp * 8, SDL_DOUBLEBUF | SDL_HWSURFACE); p = (unsigned char *)(pscreen->pixels); }
do
{ if((jpegsize = readjpeg(sock_client,&buf,headerframe,messcallback,statOn)) < 0)
{ // printf(" No size !!! exit fatal \n"); goto error; }/* mode sleep off */ if(!jpegsize && videoOk) {
close_sdlvideo(); }
if( !videoOk && jpegsize)
{ init_sdlvideo(); pscreen = SDL_SetVideoMode (owidth, oheight, bpp * 8, SDL_DOUBLEBUF | SDL_SWSURFACE); p=(unsigned char *)(pscreen->pixels); }// curdate = (time_t) (headerframe->seqtimes / 1000);
curdate = time(NULL); tdate = localtime(&curdate); _snprintf (titre,21,"%02d/%02d/%04d-%02d:%02d:%02d\0", tdate->tm_mday, tdate->tm_mon + 1, tdate->tm_year + 1900, tdate->tm_hour, tdate->tm_min, tdate->tm_sec); if(jpegsize && videoOk)
{ jpeg_decode(&picture,buf,&width,&height); resize (p,picture,owidth,oheight,width,height) ; SDL_WM_SetCaption (titre, NULL); SDL_Flip (pscreen); } printf("bright %05d contrast %05d \r",headerframe->bright,headerframe->contrast); fflush (stdout); switch (run)
{ case 1: if (SDL_PollEvent (&sdlevent) == 1)
{ switch (sdlevent.type)
{ case SDL_KEYDOWN: switch (sdlevent.key.keysym.sym)
{ case SDLK_s: //getPicture(buf,jpegsize); getJpegPicture(buf,width,height, VIDEO_PALETTE_JPEG,jpegsize,PICTURE,NULL); break;
case SDLK_w: messcallback->updocontrast =2; break;
case SDLK_x: messcallback->updocontrast =1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -