使用xvid进行解码

来源:互联网 发布:青岛人工智能发展情况 编辑:程序博客网 时间:2024/04/27 08:18

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#ifndef WIN32
#include <sys/time.h>
#else
#include <time.h>
#endif

#include "xvid.h"

/*****************************************************************************
 *               Global vars in module and constants
 ****************************************************************************/

#define USE_PNM 0
#define USE_TGA 1

static int XDIM = 352;
static int YDIM = 288;
//static int XDIM = 176;
//static int YDIM = 144;
static int ARG_SAVEDECOUTPUT = 0;
static int ARG_SAVEMPEGSTREAM = 0;
static char *ARG_INPUTFILE = "tmp.m4d";
static int CSP = XVID_CSP_I420;
//static int CSP = XVID_CSP_YV12;
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;

#define MIN_USEFUL_BYTES 1

/*****************************************************************************
 *               Local prototypes
 ****************************************************************************/

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_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";
}


/*****************************************************************************
 *               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, " -debug         : debug level (debug=0)/n");
 fprintf(stderr, " -i string      : input filename (default=stdin)/n");
 fprintf(stderr, " -d             : save decoder output/n");
 fprintf(stderr, " -c csp         : choose colorspace output (rgb16, rgb24, rgb32, yv12, i420)/n");
 fprintf(stderr, " -f format      : choose output file format (tga, pnm, pgm)/n");
 fprintf(stderr, " -m             : save mpeg4 raw stream to individual files/n");
 fprintf(stderr, " -help          : This help message/n");
 fprintf(stderr, " (* means default)/n");

}

/*****************************************************************************
 *               "helper" functions
 ****************************************************************************/

/* return the current time in milli seconds */
static double
msecond()

#ifndef WIN32
 struct timeval  tv;
 gettimeofday(&tv, 0);
 return((double)tv.tv_sec*1.0e3 + (double)tv.tv_usec*1.0e-3);
#else
 clock_t clk;
 clk = clock();
 return(clk * 1000.0 / CLOCKS_PER_SEC);
#endif
}
/*****************************************************************************
 * Routines for decoding: init decoder, use, and stop decoder
 ****************************************************************************/
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<YDIM/2;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<XDIM*YDIM*3; i+=3) {
#ifdef ARCH_IS_LITTLE_ENDIAN
   fputc(image[i+2], f);
   fputc(image[i+1], f);
   fputc(image[i+0], f);
#else
   fputc(image[i+0], f);
   fputc(image[i+1], f);
   fputc(image[i+2], f);
#endif
  }
 }

 fclose(f);

 return 0;
}
static int write_yuv(FILE *fp, unsigned char *image)
{
    /* write first plane */
 fwrite(image, 1, XDIM*YDIM*BPP*3/2, fp);
    return 0;
    /*
    char buf[(XDIM*YDIM)/2];
    memset(buf,0,sizeof(buf));
    fwrite(buf,1,(XDIM*YDIM)/2, fp);
    return 0;
    */

 /* Write Y and V planes for YUV formats */
 if (BPP == 1) {
  int i;
  /* Write the two chrominance planes */
  for (i=0; i<YDIM/2; i++) {
   fwrite(image+XDIM*YDIM + i*XDIM/2, 1, XDIM/2, fp);
   fwrite(image+5*XDIM*YDIM/4 + i*XDIM/2, 1, XDIM/2, fp);
  }
 }
 /* Close the file */
    return 0;
}
   
   

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<YDIM/2; 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);
}

/* 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)
#ifdef ARCH_IS_IA64
  xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_IA64;
#else
 xvid_gbl_init.cpu_flags = 0;
#endif
 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);
    //printf("stride[%d][%d][%d][%d]/n",xvid_dec_frame.output.stride[0],xvid_dec_frame.output.stride[1],xvid_dec_frame.output.stride[2],xvid_dec_frame.output.stride[3]);

 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);
}

/*****************************************************************************
 *        Main program
 ****************************************************************************/
#define INPUTFILE  "cif_tmp.m4d"
#define OUTPUTFILE "cif_tmp.yuv"
//#define INPUTFILE  "tmp.m4d"
//#define OUTPUTFILE "tmp.yuv"

typedef struct _m4v_head {
    int magic;
    int size;
}m4v_head;

int main(int argc, char *argv[])
{
    FILE *fp;
    FILE *yuv;
    char stream[BUFFER_SIZE];
    char *image;
    int nbytes, i, frames = 0;
    int yuv_size;
    xvid_dec_stats_t xvid_dec_stats;
    int useful_bytes = BUFFER_SIZE;
    int used_bytes = 0;
    char *mp4_ptr = stream;

    image = (char *)malloc(XDIM*YDIM*4);
   
    dec_init(0,0);
    yuv = fopen(OUTPUTFILE, "wb");
    fp = fopen(INPUTFILE,"rb");
    if (NULL == fp)
    {
        printf("fail to open file to read/n");
        return -1;
    }
#if 1
    /******************************************
     *               main loop                *
     * ****************************************/
    useful_bytes = fread(stream,1,BUFFER_SIZE,fp);
    mp4_ptr = stream;

    do{
        /*adjust buffer and pointer*/
        if (useful_bytes<(BUFFER_SIZE/2) && !feof(fp))
        {
            memcpy(stream, mp4_ptr, useful_bytes);
            nbytes = fread(stream+useful_bytes, 1, (BUFFER_SIZE-useful_bytes), fp);
            mp4_ptr = stream;
            useful_bytes += nbytes;
        }
        do {
            int used_bytes = dec_main(mp4_ptr, image, useful_bytes, &xvid_dec_stats);
            if (XVID_TYPE_VOL == xvid_dec_stats.type)
            {
                XDIM = xvid_dec_stats.data.vol.width;
                YDIM = xvid_dec_stats.data.vol.height;
            }
            mp4_ptr += used_bytes;
            useful_bytes -= used_bytes;
        }while(xvid_dec_stats.type<=0&&useful_bytes>MIN_USEFUL_BYTES);
        //printf("value is %d/n", xvid_dec_stats.type);
        if (useful_bytes<0)//go the way too far
        {
            break;
        }
        frames++;
        //printf("frames is %d/n", frames);
        //write_tga("first.tga", image);
        //write_pnm("first.pgm", image);
        write_yuv(yuv, image);
        //return 0;
    }while(useful_bytes > MIN_USEFUL_BYTES || !feof(fp));
    fclose(fp);
    fclose(yuv);
    useful_bytes = 0;
    return 0;
#endif
}

原创粉丝点击