#include
#include
#include
#include
#ifndef WIN32
#include
#else
#include
#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
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);
#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
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
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
}