⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 recmpeg.c

📁 一个很好用的MPEG1/4的开源编码器的应用程序
💻 C
字号:
/*  *    recmpeg.c * *	Copyright (C) Vivien Chappelier - 2001 * *  This file is part of recmpeg, a free MPEG encoder based on libfame. *	 *  recmpeg 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, or (at your option) *  any later version. *    *  recmpeg 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 GNU Make; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <string.h>#include <fame.h>#ifdef HAS_GETOPT_H#include <getopt.h>#endif#ifndef WIN32#define O_BINARY 0#endif#define DEFAULT_BUFFER_SIZE 1024*1024#define CHUNK_SIZE 2048#ifdef USE_UDP#include <netinet/in.h>#include <netdb.h>#include <sys/socket.h>#include <arpa/inet.h>int is_address_multicast(unsigned long address){  if((address & 255) >= 224 && (address & 255) <= 239) return(1);  return(0);}/* * 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);}#endif/* * write to output by packets of CHUNK_SIZE length */int split_write(int fd, unsigned char *buffer, unsigned int size){    fd_set set;    int r, w;    w = 0;    while(size > CHUNK_SIZE) {        r = write(fd, buffer, CHUNK_SIZE);	if(r < 0) return(r);	w += r;        size -= CHUNK_SIZE;        buffer += CHUNK_SIZE;              FD_ZERO(&set);        FD_SET(fd, &set);        if(select(fd+1, NULL, &set, NULL, NULL) <= 0) break;    }    r = write(fd, buffer, size);    if(r < 0) return(r);    w += r;    return(w);}/* * parse command line */int parse(int argc, char *argv[],	  fame_context_t *fc,	  fame_parameters_t *p,	  int *number,	  int *buffer_size,	  int *ofile,	  int *ifile,	  int *sfile){  int index = -1;  int c;  /* options */#ifdef _GNU_SOURCE  const struct option longopts[]={    {"number",1,0,'n'},  /* number of pictures to code: number or 0 (all) */    {"picture",1,0,'p'}, /* picture size: widthxheight or CIF,SIF,QCIF */    {"coding",1,0,'c'},  /* coding sequence: for example "IBBPBBPBB"   */    {"quality",1,0,'q'}, /* quality: percentage of video quality */    {"bitrate",1,0,'b'}, /* bitrate: in bits/s, K for kilo, M for mega */    {"buffer",1,0,'B'},  /* buffer size: in bytes, K for kilo, M for mega */    {"alpha",1,0,'a'},   /* shape quality: percentage of shape accuracy */    {"search",1,0,'s'},  /* search range: motion estimation range */    {"slices",1,0,'S'},  /* slices: number of slices per frame */    {"fps",1,0,'f'},     /* framerate: fractional number of frames/sec */    {"refresh",1,0,'r'}, /* refresh: number of frames before a new sequence */    {"options",1,0,'o'}, /* options: intra_only, lossless_shape */    {"profile",1,0,'P'}, /* profile: name of the profile to use */    {"motion",1,0,'M'},  /* motion: motion estimation algorithm */    {"verbose",0,0,'v'}, /* verbose: when set, print messages */    {"help",0,0,'h'},    /* help: display help message */    {0,0,0,0}  };#endif  const char * shortopts = "n:p:c:q:b:B:a:s:S:f:r:o:P:M:vh";#ifdef _GNU_SOURCE  while((c = getopt_long(argc,argv,shortopts,longopts,&index)) != -1)#else  while((c = getopt(argc,argv,shortopts)) != -1)#endif  {    switch(c)     {      case 'n':	*number = atoi(optarg);      break;      case 'p':	/* picture size: widthxheight or CIF,SIF,QCIF,QSIF */	if(!strcmp("CIF", optarg)) {	  p->width = 352;	  p->height = 288;	} else 	if(!strcmp("SIF", optarg)) {	  p->width = 352;	  p->height = 240;	} else	if(!strcmp("QCIF", optarg)) {	  p->width = 176;	  p->height = 144;	} else 	if(strchr(optarg, 'x')) {	  p->width = atoi(optarg);	  p->height = atoi(strchr(optarg, 'x')+1);	} else {	  return(index);	}      break;      /* coding sequence: for example "IBBPBBPBB"   */      case 'c':	p->coding = optarg;      break;      /* quality percentage */      case 'q':	p->quality = atoi(optarg);      break;      /* bitrate: in bits/s, K for kilo, M for mega */      case 'b':	p->bitrate = atoi(optarg);	if(optarg[strlen(optarg)-1] == 'K' ||	   optarg[strlen(optarg)-1] == 'k')	  p->bitrate *= 1024;	if(optarg[strlen(optarg)-1] == 'M' ||	   optarg[strlen(optarg)-1] == 'm')	  p->bitrate *= 1024*1024;      break;      /* buffer size: in bytes, K for kilo, M for mega */      case 'B':	*buffer_size = atoi(optarg);	if(optarg[strlen(optarg)-1] == 'K' ||	   optarg[strlen(optarg)-1] == 'k')	  *buffer_size *= 1024;	if(optarg[strlen(optarg)-1] == 'M' ||	   optarg[strlen(optarg)-1] == 'm')	  *buffer_size *= 1024*1024;      break;      /* shape quality percentage */      case 'a':	p->shape_quality = atoi(optarg);      break;      /* search range: motion estimation range */      case 's':	p->search_range = atoi(optarg);      break;      /* slices: number of slices per frame */      case 'S':	p->slices_per_frame = atoi(optarg);      break;      /* framerate: fractional number of frames/sec */      case 'f':	p->frame_rate_num = atoi(optarg);	if(strchr(optarg, '/') != NULL)	  p->frame_rate_den = atoi(strchr(optarg, '/') + 1);	else	  p->frame_rate_den = 1;      break;      /* refresh: number of frames before a new sequence */      case 'r':	p->frames_per_sequence = atoi(optarg);      break;      /* motion: motion estimation algorithm */      case 'M':      {	fame_object_t *object;		object = NULL;	if(!strcmp(optarg, "none") || !strcmp(optarg, "NONE"))	  object = fame_get_object(fc, "motion/none");	if(!strcmp(optarg, "pmvfast") || !strcmp(optarg, "PMVFAST"))	  object = fame_get_object(fc, "motion/pmvfast");	if(!strcmp(optarg, "fourstep") || !strcmp(optarg, "FOURSTEP")) 	  object = fame_get_object(fc, "motion/fourstep");	if(object)	  fame_register(fc, "motion", object);	else 	  fprintf(stderr, "unknown motion estimation algorithm %s\n", optarg);      }      break;      /* profile: name of the default profile to use */      case 'P':      {	fame_object_t *object;		object = NULL;	if(!strcmp(optarg, "stats") || !strcmp(optarg, "STATS"))	  object = fame_get_object(fc, "profile/stats");	if(!strcmp(optarg, "mpeg1") || !strcmp(optarg, "MPEG1"))	  object = fame_get_object(fc, "profile/mpeg1");	if(!strcmp(optarg, "mpeg4") || !strcmp(optarg, "MPEG4"))	  object = fame_get_object(fc, "profile/mpeg4");	if(!strcmp(optarg, "mpeg4_simple") || !strcmp(optarg, "MPEG4_SIMPLE")) 	  object = fame_get_object(fc, "profile/mpeg4/simple");	if(!strcmp(optarg, "mpeg4_shape") || !strcmp(optarg, "MPEG4_SHAPE")) 	  object = fame_get_object(fc, "profile/mpeg4/shape");	if(object)	  fame_register(fc, "profile", object);	else	  fprintf(stderr, "unknown profile %s\n", optarg);      }      break;      /* verbose: when set, print messages */      case 'v':	p->verbose = 1;      break;      /* help */      case 'h':	return(-1);      break;      default: 	return(index);    }  }  /* output file */  if(argc >= optind+1) {#ifdef USE_UDP    if(!strncmp(argv[optind+0], "udp://", strlen("udp://")))    {      char * host;      int port;      int sock;            port = 10000; /* default port */      host = argv[optind+0] + strlen("udp://");      if(strchr(host, ':') != NULL)      {	/* port is specified */	port = atoi(strchr(host, ':') + 1);	*strchr(host, ':') = 0;      }      /* open udp socket */      *ofile = udp_open(host, port);    } else#endif    {      *ofile = open(argv[optind+0], O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, 0666);    }    if(*ofile < 0) {      char error[256];      sprintf(error, "Error opening %s for writing", argv[optind+0]);      perror(error);      exit(1);    }  }  /* input file */  if(argc >= optind+2) {    *ifile = open(argv[optind+1], O_BINARY | O_RDONLY);    if(*ifile < 0) {      char error[256];      sprintf(error, "Error opening %s for reading", argv[optind+1]);      perror(error);      exit(1);    }  }  /* shape file */  if(argc >= optind+3) {    *sfile = open(argv[optind+2], O_BINARY | O_RDONLY);    if(*sfile < 0) {      char error[256];      sprintf(error, "Error opening %s for reading", argv[optind+2]);      perror(error);      exit(1);    }  }  return(0);}void usage(char const *name){  fprintf(stderr, "usage: %s options [output [input [mask]]]\n", name);  fprintf(stderr, "options are\n");  fprintf(stderr, "\t%s\t%s\n",	  "-n --number",	  "number of pictures to code: number or 0 (all)");  fprintf(stderr, "\t%s\t%s\n",	  "-p --picture",	  "picture size: widthxheight or CIF,SIF,QCIF");  fprintf(stderr, "\t%s\t%s\n",	  "-c --coding",	  "coding sequence: for example \"IBBPBBPBB\"");  fprintf(stderr, "\t%s\t%s\n",	  "-q --quality",	  "quality: percentage of video quality");  fprintf(stderr, "\t%s\t%s\n",          "-b --bitrate",	  "bitrate: in bits/s, K for kilo, M for mega");  fprintf(stderr, "\t%s\t%s\n",          "-B --buffer",	  "buffer size: in bytes, K for kilo, M for mega");  fprintf(stderr, "\t%s\t%s\n",          "-a --alpha",	  "shape quality: percentage of shape accuracy");  fprintf(stderr, "\t%s\t%s\n",	  "-s --search",	  "search range: motion estimation range");  fprintf(stderr, "\t%s\t%s\n",	  "-S --slices",	  "slices: number of slices per frame");  fprintf(stderr, "\t%s\t%s\n",	  "-f --fps",	  "framerate: fractional number of frames/sec");  fprintf(stderr, "\t%s\t%s\n",	  "-r --refresh",	  "number of frames before a new sequence");  fprintf(stderr, "\t%s\t%s\n",	  "-P --profile",	  "profile: name of the profile to use");  fprintf(stderr, "\t%s\t%s\n",	  "-M --motion",	  "motion: motion estimation algorithm");  fprintf(stderr, "\t%s\t%s\n",	  "-v --verbose",	  "verbose: when set, print messages");  fprintf(stderr, "\t%s\t%s\n",	  "-h --help",	  "display this message");  exit(1);}int main(int argc, char *argv[]){  fame_parameters_t fp = FAME_PARAMETERS_INITIALIZER;  fame_context_t *fc;  fame_yuv_t yuv;  unsigned char *buffer;  unsigned char *shape;  int width, height;  int length, size;  int ifile, ofile, sfile;  FILE *bifile, *bsfile;  int frame = 0;  int number = 0;  fc = fame_open();  /* default to CIF */  fp.width = 352;  fp.height = 288;  /* default files */  ifile = 0;  ofile = 1;  sfile = 0;  /* default buffer size */  size = DEFAULT_BUFFER_SIZE;  /* turn off verbose mode */  fp.verbose = 0;  /* parse command line */  if(parse(argc, argv, fc, &fp, &number, &size, &ofile, &ifile, &sfile))    usage(argv[0]);  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;  shape = (unsigned char *) malloc(fp.width*fp.height);  buffer = (unsigned char *) malloc(size);  fame_init(fc, &fp, buffer, size);  /* buffered input (thx Eric Maffre) */  bifile = fdopen(ifile, "r");  if(sfile)    bsfile = fdopen(sfile, "r");  do {    if(fread(yuv.y, fp.width*fp.height, 1, bifile) <= 0) break;    if(fread(yuv.u, fp.width*fp.height/4, 1, bifile) <= 0) break;    if(fread(yuv.v, fp.width*fp.height/4, 1, bifile) <= 0) break;    if(sfile) {      if(fread(shape, fp.width*fp.height, 1, bsfile) <= 0) break;      fame_start_frame(fc, &yuv, shape);    } else      fame_start_frame(fc, &yuv, NULL);    /* TODO: would buffered output help? */    while(length = fame_encode_slice(fc)) {      // TEMP      //      printf("%d\n", length*8);	split_write(ofile, buffer, length);    }    fame_end_frame(fc, NULL);    frame++;  } while(!number || frame < number);  length = fame_close(fc);  split_write(ofile, buffer, length);  free(yuv.y);  free(buffer);  fclose(bifile);  if(sfile)    fclose(bsfile);    if(ifile != 0) close(ifile);  if(ofile != 1) close(ofile);  if(sfile != 0) close(sfile);  fprintf(stderr, "encoded %d frames\n", frame);  return(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -