📄 fame.c
字号:
exit(1);}static void *audio_callback(void *args){#ifdef HAS_LAME lame_global_flags * lc; input_dsp_context_t * dsp; short int *pcm; unsigned char *buffer; int size; fd_set readfds; struct timeval timeout; pcm = (short int *) malloc(3528*sizeof(short int)); buffer = (unsigned char *) malloc(DEFAULT_BUFFER_SIZE*4); lc = lame_init(); lame_set_out_samplerate(lc, 44100); lame_set_brate(lc, audiobitrate/1000); /* bitrate is in Kbits/s in lame */ lame_init_params(lc); if(!(dsp = dsp_init())) { quit = true; fprintf(stderr, "audio: could not open dsp\n"); pthread_cond_signal(&buffer_cond); return(NULL); } while(!quit) { dsp_read(dsp, pcm, 1764*sizeof(short int)); if (start_frame && (ea_frame < start_frame)) { ea_frame ++; continue; } if (!pause_record || (audio_frame < sync_frame)) { if (pause_record && (audio_frame < sync_frame)) fprintf (stderr, "\rAudio sync\n"); size = lame_encode_buffer(lc, pcm, pcm, 1764, buffer, 0); split_write (audio_fd, buffer, size); audio_frame++; /*fprintf (stderr, "\r frame = %d / %d \r", audio_frame, video_frame);*/ } else ea_frame++; memset (&readfds, 0, sizeof(fd_set)); FD_SET (0, &readfds); timeout.tv_sec = 0L; timeout.tv_usec = 0L; if (select (1, &readfds, (fd_set *) NULL, (fd_set *) NULL, &timeout)) { char qq = fgetc (stdin); if ((qq == 'q') || (qq == 'Q')) quit = true; if (pause_record == true) { pause_record = false; } else pause_record = true; sync_frame = fame_max (audio_frame, video_frame); start_frame = fame_max (ea_frame, ev_frame); } } size = lame_encode_flush(lc, buffer, 0); split_write(audio_fd, buffer, size); lame_close(lc); free(buffer); free(pcm); dsp_close(dsp);#endif}static void *video_callback(void *args){ fame_context_t *fc; fame_object_t *object; fame_yuv_t yuv; input_v4l_context_t * v4l; unsigned char *buffer; int size; fd_set readfds; struct timeval timeout; buffer = (unsigned char *) malloc(DEFAULT_BUFFER_SIZE); yuv.w = fp.width; yuv.h = fp.height; yuv.p = fp.width; yuv.y = (unsigned char *) malloc(fp.width*fp.height*12/8); yuv.u = yuv.y + fp.width*fp.height; yuv.v = yuv.u + fp.width*fp.height/4; if(!(v4l = v4l_init(fp.width, fp.height))) { quit = true; fprintf(stderr, "video: could not open video4linux device\n"); pthread_cond_signal(&buffer_cond); return(NULL); } if(!(fc = fame_open())) { quit = true; fprintf(stderr, "video: error initializing libfame\n"); pthread_cond_signal(&buffer_cond); return(NULL); } object = NULL; if(!strcmp(profile, "mpeg1") || !strcmp(profile, "MPEG1")) object = fame_get_object(fc, "profile/mpeg1"); if(!strcmp(profile, "mpeg4") || !strcmp(profile, "MPEG4")) object = fame_get_object(fc, "profile/mpeg4"); if(!strcmp(profile, "mpeg4_simple") || !strcmp(profile, "MPEG4_SIMPLE")) object = fame_get_object(fc, "profile/mpeg4/simple"); if(!strcmp(profile, "mpeg4_shape") || !strcmp(profile, "MPEG4_SHAPE")) object = fame_get_object(fc, "profile/mpeg4/shape"); if(object) fame_register(fc, "profile", object); else fprintf(stderr, "unknown profile %s\n", profile); object = NULL; if(!strcmp(motion, "none") || !strcmp(motion, "NONE")) object = fame_get_object(fc, "motion/none"); if(!strcmp(motion, "pmvfast") || !strcmp(motion, "PMVFAST")) object = fame_get_object(fc, "motion/pmvfast"); if(!strcmp(motion, "fourstep") || !strcmp(motion, "FOURSTEP")) object = fame_get_object(fc, "motion/fourstep"); if(object) fame_register(fc, "motion", object); else fprintf(stderr, "unknown motion estimation algorithm %s\n", motion); fame_init(fc, &fp, buffer, DEFAULT_BUFFER_SIZE); while(!quit) { v4l_read(v4l, yuv.y, fp.width*fp.height*12/8); if (start_frame && (ev_frame < start_frame)) { ev_frame ++; continue; } if (!pause_record || (video_frame < sync_frame)) { if (pause_record && (video_frame < sync_frame)) fprintf (stderr, "\rVideo sync\n"); if (video_frame % fp.frame_rate_den == 0) { fame_start_frame(fc, &yuv, NULL); while(size = fame_encode_slice(fc)) split_write(video_fd, buffer, size); fame_end_frame(fc, NULL); } video_frame++; } else ev_frame++; memset (&readfds, 0, sizeof(fd_set)); FD_SET (0, &readfds); timeout.tv_sec = 0L; timeout.tv_usec = 0L; if (select (1, &readfds, (fd_set *) NULL, (fd_set *) NULL, &timeout)) { char qq = fgetc (stdin); if ((qq == 'q') || (qq == 'Q')) quit = true; if (pause_record == true) { pause_record = false; } else pause_record = true; sync_frame = fame_max (audio_frame, video_frame); start_frame = fame_max (ea_frame, ev_frame); } } size = fame_close(fc); split_write(video_fd, buffer, size); free(buffer); free(yuv.y); v4l_close(v4l);}/* * write to output by packets of CHUNK_SIZE length */int split_write(int fd, unsigned char *data, unsigned int size){ fd_set set; int r, w; pthread_mutex_lock(&buffer_mutex); w = 0; while(size > CHUNK_SIZE) { r = write(fd, data, CHUNK_SIZE); if(r < 0) { pthread_mutex_unlock(&buffer_mutex); pthread_cond_signal(&buffer_cond); return(r); } w += r; size -= CHUNK_SIZE; data += CHUNK_SIZE; FD_ZERO(&set); FD_SET(fd, &set); if(select(fd+1, NULL, &set, NULL, NULL) <= 0) break; } r = write(fd, data, size); if(r < 0) { pthread_mutex_unlock(&buffer_mutex); pthread_cond_signal(&buffer_cond); return(r); } w += r; pthread_mutex_unlock(&buffer_mutex); pthread_cond_signal(&buffer_cond); return(w);}/* * open UDP socket */int udp_open(char * address, int port){ int enable = 1L; struct sockaddr_in stAddr; struct sockaddr_in stLclAddr; struct hostent * host; int sock; stAddr.sin_family = AF_INET; stAddr.sin_port = htons(port); if((host = gethostbyname(address)) == NULL) return(0); stAddr.sin_addr = *((struct in_addr *) host->h_addr_list[0]); /* Create a UDP socket */ if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return(0); /* Allow multiple instance of the client to share the same address and port */ if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &enable, sizeof(unsigned long int)) < 0) return(0);#ifdef USE_MULTICAST /* If the address is multicast, register to the multicast group */ if(is_address_multicast(stAddr.sin_addr.s_addr)) { struct ip_mreq stMreq; /* Bind the socket to port */ stLclAddr.sin_family = AF_INET; stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); stLclAddr.sin_port = stAddr.sin_port; if(bind(sock, (struct sockaddr*) & stLclAddr, sizeof(stLclAddr)) < 0) return(0); /* Register to a multicast address */ stMreq.imr_multiaddr.s_addr = stAddr.sin_addr.s_addr; stMreq.imr_interface.s_addr = INADDR_ANY; if(setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) & stMreq, sizeof(stMreq)) < 0) return(0); } else#endif { /* Bind the socket to port */ stLclAddr.sin_family = AF_INET; stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); stLclAddr.sin_port = htons(0); if(bind(sock, (struct sockaddr*) & stLclAddr, sizeof(stLclAddr)) < 0) return(0); } connect(sock, (struct sockaddr*) & stAddr, sizeof(stAddr)); return(sock);}fbool_t init(){ quit = false; pause_record = false; /* Hook to the break signal */ signal(SIGINT, break_handler); /* initialize video & audio coders */ pthread_create(&video_thread, NULL, video_callback, NULL); if(audio_fd) pthread_create(&audio_thread, NULL, audio_callback, NULL); video_frame = 0; audio_frame = 0; ea_frame = 0; ev_frame = 0; start_frame = 0; return(true);}fbool_t cleanup(){ /* Ignore further break signals */ signal(SIGINT, SIG_IGN); /* cleanup video & audio coders */ pthread_cond_signal(&buffer_cond); pthread_join(video_thread, NULL); pthread_cond_signal(&buffer_cond); if(audio_fd) pthread_join(audio_thread, NULL); /* close files */ if(audio_fd) close(audio_fd); close(video_fd); return(true);}void break_handler(int signal){ /* Handle the break (Ctrl-C) signal */ if(signal != SIGINT) return; quit = true;}int main(int argc, char * argv[], char *env[]){ if(parse(argc, argv)) { usage(argv[0]); exit(1); } if(!init()) { usage(argv[0]); cleanup(); exit(1); } ioctl (0, TCGETA, &ostate);/* save old state */ ioctl (0, TCGETA, &nstate);/* get base of new state */ nstate.c_lflag &= ~(ISIG | ICANON | ECHO); nstate.c_cc[VEOF] = 1; nstate.c_cc[VEOL] = 1; nstate.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF); nstate.c_oflag &= ~(OPOST); ioctl (0, TCSETA, &nstate);/* set mode */ while(!quit) { /* wait mplex */ pthread_mutex_lock(&buffer_mutex); pthread_cond_wait(&buffer_cond, &buffer_mutex); pthread_mutex_unlock(&buffer_mutex); } ioctl (0, TCSETA, &ostate);/* set mode */ cleanup(); return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -