Chinaunix首页 | 论坛 | 博客
  • 博客访问: 513833
  • 博文数量: 187
  • 博客积分: 3011
  • 博客等级: 中校
  • 技术积分: 2092
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-28 17:08
文章分类

全部博文(187)

文章存档

2011年(1)

2010年(8)

2009年(178)

我的朋友

分类: LINUX

2009-09-26 15:22:37

/*********************************************************************************************
              gcc -o mpeg4_player mpeg4_player.c `sdl-config --cflags --libs` -lxvidcore
*********************************************************************************************/
#include
#include
#include
#include
#include
#include
#include "xvid.h"
#define USE_PNM 1
#define USE_TGA 0
static int SHXDIM = 0;//display size
static int SHYDIM = 0;
static int XDIM = 352;//real size
static int YDIM = 288;
static int ARG_SAVEDECOUTPUT = 0;
static int ARG_SAVEMPEGSTREAM = 0;
static char *ARG_INPUTFILE = NULL;
static int CSP = XVID_CSP_I420;
static int BPP = 1;
static int FORMAT = USE_PNM;
static char filepath[256] = "./";
static void *dec_handle = NULL;
#define BUFFER_SIZE (2*1024*1024)
static const int display_buffer_bytes = 0;
static SDL_Surface *screen;
static SDL_Overlay *overlay;
static SDL_Rect rect;
static double msecond();
static int dec_init(int use_assembler, int debug_level);
static int dec_main(unsigned char *istream,
     unsigned char *ostream,
     int istream_size,
     xvid_dec_stats_t *xvid_dec_stats);
static int dec_stop();
static void usage();
static int write_image(char *prefix, unsigned char *image);
static int write_pnm(char *filename, unsigned char *image);
static int write_tga(char *filename, unsigned char *image);
const char * type2str(int type)
{
    if (type==XVID_TYPE_IVOP)
        return "I";
    if (type==XVID_TYPE_PVOP)
        return "P";
    if (type==XVID_TYPE_BVOP)
        return "B";
    return "S";
}
static void init_SDL()
{
    if (SDL_Init (SDL_INIT_VIDEO) < 0)
    {
        fprintf (stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
        exit (1);
    }
    atexit (SDL_Quit);
    screen = SDL_SetVideoMode (SHXDIM, SHYDIM, 0, SDL_HWSURFACE
                                          | SDL_DOUBLEBUF
                                          | SDL_ANYFORMAT
                                          | SDL_RESIZABLE);
    if (screen == NULL)
    {
        fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
        exit(2);
    }
    if (0 == screen->flags & SDL_HWSURFACE)
    {
        fprintf(stderr,"Can't get hardware surface\n");
        exit(3);
    }
    SDL_WM_SetCaption ("SDL MultiMedia Application", NULL);      
    overlay = SDL_CreateYUVOverlay(XDIM, YDIM, SDL_YV12_OVERLAY, screen);
    if (!overlay)
    {
        fprintf(stderr, "Couldn't create overlay: %s\n", SDL_GetError());
        exit(4);
    }   
    //show the overlay status
    printf("Created %dx%dx%d %s %s overlay\n",overlay->w,overlay->h,overlay->planes,
           overlay->hw_overlay?"hardware":"software",
           overlay->format==SDL_YV12_OVERLAY?"YV12":
           overlay->format==SDL_IYUV_OVERLAY?"IYUV":
           overlay->format==SDL_YUY2_OVERLAY?"YUY2":
           overlay->format==SDL_UYVY_OVERLAY?"UYVY":
           overlay->format==SDL_YVYU_OVERLAY?"YVYU":
           "Unknown");
    rect.x=0;
    rect.y=0;
    rect.w=SHXDIM;
    rect.h=SHYDIM;
}
int main(int argc, char *argv[])
{
 SDL_Event event;
 uint32_t lastftick;
 unsigned char *mp4_buffer = NULL;
 unsigned char *mp4_ptr    = NULL;
 unsigned char *out_buffer = NULL;
 int useful_bytes;
 xvid_dec_stats_t xvid_dec_stats;
 
 double totaldectime;
 
 long totalsize;
 int status;
 int fps = 25;
     int fpsdelay;
 int paused=0;
     int resized=0; 
 int use_assembler = 1;
 int debug_level = 0;
 
 char filename[256];
 
 FILE *in_file;
 int filenr;
 int i;
 for (i=1; i< argc; i++) {
 
  if (strcmp("-asm", argv[i]) == 0 ) {
   use_assembler = 1;
  } else if (strcmp("-debug", argv[i]) == 0 && i < argc - 1 ) {
   i++;
   if (sscanf(argv[i], "0x%x", &debug_level) != 1) {
    debug_level = atoi(argv[i]);
   }
  } else if (strcmp("-d", argv[i]) == 0) {
   ARG_SAVEDECOUTPUT = 1;
  } else if (strcmp("-i", argv[i]) == 0 && i < argc - 1 ) {
   i++;
   ARG_INPUTFILE = argv[i];
  } else if (strcmp("-c", argv[i]) == 0  && i < argc - 1 ) {
   i++;
   if (strcmp(argv[i], "rgb16") == 0) {
    CSP = XVID_CSP_RGB555;
    BPP = 2;
   } else if (strcmp(argv[i], "rgb24") == 0) {
    CSP = XVID_CSP_BGR;
    BPP = 3;
   } else if (strcmp(argv[i], "rgb32") == 0) {
    CSP = XVID_CSP_BGRA;
    BPP = 4;
   } else if (strcmp(argv[i], "yv12") == 0) {
    CSP = XVID_CSP_YV12;
    BPP = 1;
   } else {
    CSP = XVID_CSP_I420;
    BPP = 1;
   }
  } else if (strcmp("-f", argv[i]) == 0 && i < argc -1) {
   i++;
   if (strcmp(argv[i], "tga") == 0) {
    FORMAT = USE_TGA;
   } else {
    FORMAT = USE_PNM;
   }
  } else if (strcmp("-help", argv[i]) == 0) {
   usage();
   return(0);
  } else if(strcmp("-w", argv[i]) == 0 && i < argc -1){
            i++;
            SHXDIM = atoi(argv[i]);
        } else if(strcmp("-h", argv[i]) == 0 && i < argc -1){
            i++;
            SHYDIM = atoi(argv[i]);
        } else if(strcmp("-fps", argv[i]) == 0 && i < argc -1){
            i++;
            fps = atoi(argv[i]);
        } 
        else {
   usage();
   exit(-1);
  }
 }
 
 if (ARG_INPUTFILE==NULL) {
  fprintf(stderr, "Warning: MSVC build does not read EOF correctly from stdin. Use the -i switch.\n\n");
 }
    in_file = fopen(ARG_INPUTFILE, "rb");
    if (in_file == NULL) {
   fprintf(stderr, "Error opening input file %s\n", ARG_INPUTFILE);
   return(-1);
    }
 /* PNM/PGM format can't handle 16/32 bit data */
 if (BPP != 1 && BPP != 3 && FORMAT == USE_PNM) {
  FORMAT = USE_TGA;
 }
 /* Memory for encoded mp4 stream */
 mp4_buffer = (unsigned char *) malloc(BUFFER_SIZE);
 if (!mp4_buffer)
  goto free_all_memory;
 out_buffer = (unsigned char *)malloc(XDIM*YDIM*3/2);
 if (!out_buffer)
  goto free_all_memory;
/******************************************************************************
*        INIT SDL
*******************************************************************************/       
     init_SDL();   
       
/*****************************************************************************
 *        XviD PART  Start
 ****************************************************************************/
 status = dec_init(use_assembler, debug_level);
 if (status) {
  fprintf(stderr,
    "Decore INIT problem, return value %d\n", status);
  goto release_all;
 }       
/*****************************************************************************
 *                          Main loop
 ****************************************************************************/
 /* Fill the buffer ,create 2M buffer*/
 useful_bytes = fread(mp4_buffer, 1, BUFFER_SIZE, in_file);
 totaldectime = 0;
 totalsize = 0;
 filenr = 0;
 mp4_ptr = mp4_buffer;
     uint8_t  *outy,*outu,*outv,*op[3];
 int y;
    /* set the start frame */
     i=0;
     fpsdelay=1000/fps;
 lastftick=SDL_GetTicks();
 do { 
  int used_bytes = 0;
  double dectime;
  while (SDL_PollEvent(&event)){
              switch (event.type)
              {
                     case SDL_VIDEORESIZE:
                       screen=SDL_SetVideoMode(event.resize.w, event.resize.h, 0, SDL_RESIZABLE | SDL_SWSURFACE);
                       rect.w=event.resize.w;
                       rect.h=event.resize.h;
                       if (paused)
                       {
                           resized=1;
                       }
                       break;
                     case SDL_KEYDOWN:
                       if (event.key.keysym.sym == SDLK_SPACE)
                       {
                           paused=!paused;
                           break;
                       }
                       if (event.key.keysym.sym != SDLK_ESCAPE)
                       {
          goto release_all;
                       }
                            case SDL_QUIT:
                       goto release_all;
              }
         }/* end of while (SDL_PollEvent(&event)) */
  /*
  * If the buffer is half empty or there are no more bytes in it
  * then fill it.
  */
  if (mp4_ptr > mp4_buffer + BUFFER_SIZE/2)
  {
              int already_in_buffer = (mp4_buffer + BUFFER_SIZE - mp4_ptr);
      /* Move data if needed */
       if (already_in_buffer > 0)
                  memcpy(mp4_buffer, mp4_ptr, already_in_buffer);
      /* Update mp4_ptr */
       mp4_ptr = mp4_buffer;
      /* read new data */
       if(feof(in_file))
    break;
              useful_bytes += fread(mp4_buffer + already_in_buffer,1, BUFFER_SIZE - already_in_buffer,in_file);
         }
  if ((!paused)||(resized))  //pause = 0 or resize = 1
  {
          if (((SDL_GetTicks()-lastftick)>fpsdelay)||(resized))
          {
               lastftick=SDL_GetTicks();
    /* This loop is needed to handle VOL/NVOP reading */
    do{
        /* Decode frame */
                dectime = msecond();  
                used_bytes = dec_main(mp4_ptr, out_buffer, useful_bytes, &xvid_dec_stats);
                dectime = msecond() - dectime;
     if(xvid_dec_stats.type==XVID_TYPE_VOL && (xvid_dec_stats.data.vol.width != XDIM
             ||xvid_dec_stats.data.vol.height != YDIM))
          {
       //reallocate bigger out frame
      free(out_buffer);
      XDIM = xvid_dec_stats.data.vol.width;
       YDIM = xvid_dec_stats.data.vol.height;
       out_buffer = (unsigned char *) malloc(XDIM*YDIM*3/2);        
       if (!out_buffer)
               goto free_all_memory;
                     
       //reallocate bigger yuv overlay
                       
           SDL_FreeYUVOverlay(overlay);
              overlay = SDL_CreateYUVOverlay(XDIM, YDIM, SDL_YV12_OVERLAY, screen);
              if (!overlay)
              {
                     fprintf(stderr, "Couldn't create overlay: %s\n", SDL_GetError());
                 exit(4);
                            }    
                     
       }       
     /* Update buffer pointers */
      if(used_bytes > 0) {
          mp4_ptr += used_bytes;
      useful_bytes -= used_bytes;
      /* Total size */
      totalsize += used_bytes;
      }
                  }while (xvid_dec_stats.type <= 0 && useful_bytes > 0);
    /* Check if there is a negative number of useful bytes left in buffer
     * This means we went too far */
           if(useful_bytes < 0)
                    break;
     /* Updated data - Count only usefull decode time */
    totaldectime += dectime;
          //display the decoded frame
           SDL_LockSurface(screen);
           SDL_LockYUVOverlay(overlay);
    outy = out_buffer;
    outu = out_buffer+XDIM*YDIM;
    outv = out_buffer+XDIM*YDIM*5/4;
    for(y=0;yh && yh;y++)
    {
        op[0]=overlay->pixels[0]+overlay->pitches[0]*y;
     op[1]=overlay->pixels[1]+overlay->pitches[1]*(y/2);
     op[2]=overlay->pixels[2]+overlay->pitches[2]*(y/2);  
     memcpy(op[0],outy+y*XDIM,XDIM);
     if(y%2 == 0)
     {
           memcpy(op[1],outu+XDIM/2*y/2,XDIM/2);
      memcpy(op[2],outv+XDIM/2*y/2,XDIM/2);   
             }
    }
           SDL_UnlockYUVOverlay(overlay);
           SDL_UnlockSurface(screen);       
           SDL_DisplayYUVOverlay(overlay, &rect);
    /* Save output frame if required */
    if (ARG_SAVEDECOUTPUT) {
        sprintf(filename, "%sdec%05d", filepath, filenr);
     if(write_image(filename, out_buffer)) {
        fprintf(stderr,
      "Error writing decoded frame %s\n",
      filename);
     }
                  }
                  filenr++;
                  if (resized)
                       resized = 0;
             }/*end of if*/
          }/*end of if*/
          SDL_Delay(10);
 } while (useful_bytes>0 || !feof(in_file));
 useful_bytes = 0; /* Empty buffer */
/*****************************************************************************
 *     Flush decoder buffers
 ****************************************************************************/
 do {
  /* Fake vars */
  int used_bytes;
  double dectime;
         do {
      dectime = msecond();
      used_bytes = dec_main(NULL, out_buffer, -1, &xvid_dec_stats);
      dectime = msecond() - dectime;
          } while(used_bytes>=0 && xvid_dec_stats.type <= 0);
         if (used_bytes < 0) {   /* XVID_ERR_END */
              break;
          }
  /* Updated data - Count only usefull decode time */
  totaldectime += dectime;
  /* Prints some decoding stats */
  if (!display_buffer_bytes) {
   printf("Frame %5d: type = %s, dectime(ms) =%6.1f, length(bytes) =%7d\n",
     filenr, type2str(xvid_dec_stats.type), dectime, used_bytes);
  }
  /* Save output frame if required */
  if (ARG_SAVEDECOUTPUT) {
   sprintf(filename, "%sdec%05d", filepath, filenr);
   if(write_image(filename, out_buffer)) {
    fprintf(stderr,
      "Error writing decoded frame %s\n",
      filename);
   }
  }
  filenr++;
 }while(1);
/*****************************************************************************
 *     Calculate totals and averages for output, print results
 ****************************************************************************/
 if (filenr>0) {
  totalsize    /= filenr;
  totaldectime /= filenr;
  printf("Avg: dectime(ms) =%7.2f, fps =%7.2f, length(bytes) =%7d\n",
      totaldectime, 1000/totaldectime, (int)totalsize);
 }else{
  printf("Nothing was decoded!\n");
 }
 
/*****************************************************************************
 *      XviD PART  Stop
 ****************************************************************************/
 release_all:
    SDL_FreeYUVOverlay(overlay);        
   if (dec_handle) {
    status = dec_stop();
  if (status)   
   fprintf(stderr, "decore RELEASE problem return value %d\n", status);
 }
 free_all_memory:
    free(out_buffer);
 free(mp4_buffer);
 return 0;
}

/*****************************************************************************
 *               Usage function
 ****************************************************************************/
static void usage()
{
 fprintf(stderr, "Usage : xvid_decraw [OPTIONS]\n");
 fprintf(stderr, "Options :\n");
 fprintf(stderr, " -asm           : use assembly optimizations (default=disabled)\n");
 fprintf(stderr, " -i string      : input filename (default=stdin)\n");
 fprintf(stderr, " -d             : save decoder output\n");
 fprintf(stderr, " -f format      : choose output file format (tga, pnm, pgm)\n");
 fprintf(stderr, " -w width       : init window width\n");
 fprintf(stderr, " -h height      : init window height\n");
 fprintf(stderr, " -help          : This help message\n");
 fprintf(stderr, " (* means default)\n");
}
/* return the current time in milli seconds */
static double
msecond()
{
 clock_t clk;
 clk = clock();
 return(clk * 1000 / CLOCKS_PER_SEC);
}
       
static int write_image(char *prefix, unsigned char *image)
{
 char filename[1024];
 char *ext;
 int ret;
 if (FORMAT == USE_PNM && BPP == 1) {
  ext = "pgm";
 } else if (FORMAT == USE_PNM && BPP == 3) {
  ext = "pnm";
 } else if (FORMAT == USE_TGA) {
  ext = "tga";
 } else {
  fprintf(stderr, "Bug: should not reach this path code -- please report to xvid-devel@xvid.org with command line options used");
  exit(-1);
 }
 sprintf(filename, "%s.%s", prefix, ext);
 if (FORMAT == USE_PNM) {
  ret = write_pnm(filename, image);
 } else {
  ret = write_tga(filename, image);
 }
 return(ret);
}
static int write_tga(char *filename, unsigned char *image)
{
 FILE * f;
 char hdr[18];
 f = fopen(filename, "wb");
 if ( f == NULL) {
  return -1;
 }
 hdr[0]  = 0; /* ID length */
 hdr[1]  = 0; /* Color map type */
 hdr[2]  = (BPP>1)?2:3; /* Uncompressed true color (2) or greymap (3) */
 hdr[3]  = 0; /* Color map specification (not used) */
 hdr[4]  = 0; /* Color map specification (not used) */
 hdr[5]  = 0; /* Color map specification (not used) */
 hdr[6]  = 0; /* Color map specification (not used) */
 hdr[7]  = 0; /* Color map specification (not used) */
 hdr[8]  = 0; /* LSB X origin */
 hdr[9]  = 0; /* MSB X origin */
 hdr[10] = 0; /* LSB Y origin */
 hdr[11] = 0; /* MSB Y origin */
 hdr[12] = (XDIM>>0)&0xff; /* LSB Width */
 hdr[13] = (XDIM>>8)&0xff; /* MSB Width */
 if (BPP > 1) {
  hdr[14] = (YDIM>>0)&0xff; /* LSB Height */
  hdr[15] = (YDIM>>8)&0xff; /* MSB Height */
 } else {
  hdr[14] = ((YDIM*3)>>1)&0xff; /* LSB Height */
  hdr[15] = ((YDIM*3)>>9)&0xff; /* MSB Height */
 }
 hdr[16] = BPP*8;
 hdr[17] = 0x00 | (1<<5) /* Up to down */ | (0<<4); /* Image descriptor */
 
 /* Write header */
 fwrite(hdr, 1, sizeof(hdr), f);
 /* write first plane */
 fwrite(image, 1, XDIM*YDIM*BPP, f);
 /* Write Y and V planes for YUV formats */
 if (BPP == 1) {
  int i;
  /* Write the two chrominance planes */
  for (i=0; i   fwrite(image+XDIM*YDIM + i*XDIM/2, 1, XDIM/2, f);
   fwrite(image+5*XDIM*YDIM/4 + i*XDIM/2, 1, XDIM/2, f);
  }
 }

 /* Close the file */
 fclose(f);
 return(0);
}
static int write_pnm(char *filename, unsigned char *image)
{
 FILE * f;
 f = fopen(filename, "wb");
 if ( f == NULL) {
  return -1;
 }
 if (BPP == 1) {
  int i;
  fprintf(f, "P5\n#xvid\n%i %i\n255\n", XDIM, YDIM*3/2);
  fwrite(image, 1, XDIM*YDIM, f);
  for (i=0; i   fwrite(image+XDIM*YDIM + i*XDIM/2, 1, XDIM/2, f);
   fwrite(image+5*XDIM*YDIM/4 + i*XDIM/2, 1, XDIM/2, f);
  }
 } else if (BPP == 3) {
  int i;
  fprintf(f, "P6\n#xvid\n%i %i\n255\n", XDIM, YDIM);
  for (i=0; i   fputc(image[i+2], f);
   fputc(image[i+1], f);
   fputc(image[i+0], f);
  }
 }
 fclose(f);
 return 0;
}
/*****************************************************************************
 * Routines for decoding: init decoder, use, and stop decoder
 ****************************************************************************/
/* init decoder before first run */
static int
dec_init(int use_assembler, int debug_level)
{
 int ret;
 xvid_gbl_init_t   xvid_gbl_init;
 xvid_dec_create_t xvid_dec_create;
 /* Reset the structure with zeros */
 memset(&xvid_gbl_init, 0, sizeof(xvid_gbl_init_t));
 memset(&xvid_dec_create, 0, sizeof(xvid_dec_create_t));
 /*------------------------------------------------------------------------
  * XviD core initialization
  *----------------------------------------------------------------------*/
 /* Version */
 xvid_gbl_init.version = XVID_VERSION;
 /* Assembly setting */
 if(use_assembler)
     xvid_gbl_init.cpu_flags = 0;
 else
  xvid_gbl_init.cpu_flags = XVID_CPU_FORCE;
 xvid_gbl_init.debug = debug_level;
 xvid_global(NULL, 0, &xvid_gbl_init, NULL);
 /*------------------------------------------------------------------------
  * XviD encoder initialization
  *----------------------------------------------------------------------*/
 /* Version */
 xvid_dec_create.version = XVID_VERSION;
 /*
  * Image dimensions -- set to 0, xvidcore will resize when ever it is
  * needed
  */
 xvid_dec_create.width = 0;
 xvid_dec_create.height = 0;
 ret = xvid_decore(NULL, XVID_DEC_CREATE, &xvid_dec_create, NULL);
 dec_handle = xvid_dec_create.handle;
 return(ret);
}
/* decode one frame  */
static int
dec_main(unsigned char *istream,
   unsigned char *ostream,
   int istream_size,
   xvid_dec_stats_t *xvid_dec_stats)
{
 int ret;
 xvid_dec_frame_t xvid_dec_frame;
 /* Reset all structures */
 memset(&xvid_dec_frame, 0, sizeof(xvid_dec_frame_t));
 memset(xvid_dec_stats, 0, sizeof(xvid_dec_stats_t));
 /* Set version */
 xvid_dec_frame.version = XVID_VERSION;
 xvid_dec_stats->version = XVID_VERSION;
 /* No general flags to set */
 xvid_dec_frame.general          = 0;
 /* Input stream */
 xvid_dec_frame.bitstream        = istream;
 xvid_dec_frame.length           = istream_size;
 /* Output frame structure */
 xvid_dec_frame.output.plane[0]  = ostream;
 xvid_dec_frame.output.stride[0] = XDIM*BPP;
 xvid_dec_frame.output.csp = CSP;
 ret = xvid_decore(dec_handle, XVID_DEC_DECODE, &xvid_dec_frame, xvid_dec_stats);
 return(ret);
}
/* close decoder to release resources */
static int
dec_stop()
{
 int ret;
 ret = xvid_decore(dec_handle, XVID_DEC_DESTROY, NULL, NULL);
 return(ret);
}    

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/neohuo/archive/2006/07/10/899772.aspx
阅读(882) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~