一.LINUX DVR源码
static float ARG_FRAMERATE = 25.00f;
static int ARG_QUALITY = 4;
static int ARG_MAXKEYINTERVAL = 250;
static char * ARG_OUTPUTFILE= "out.m4u";
static FILE * fp = NULL;
static int done = 0;
static const int motion_presets[] = {
/* quality 0 */
0,
/* quality 1 */
XVID_ME_ADVANCEDDIAMOND16,
/* quality 2 */
XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16,
/* quality 3 */
XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |
XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8,
/* quality 4 */
XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |
XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 |
XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP,
/* quality 5 */
XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |
XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 |
XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP,
/* quality 6 */
XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 | XVID_ME_EXTSEARCH16 |
XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 | XVID_ME_EXTSEARCH8 |
XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP,
};
static const int vop_presets[] = {
/* quality 0 */
0,
/* quality 1 */
0,
/* quality 2 */
XVID_VOP_HALFPEL,
/* quality 3 */
XVID_VOP_HALFPEL | XVID_VOP_INTER4V,
/* quality 4 */
XVID_VOP_HALFPEL | XVID_VOP_INTER4V,
/* quality 5 */
XVID_VOP_HALFPEL | XVID_VOP_INTER4V |
XVID_VOP_TRELLISQUANT,
/* quality 6 */
XVID_VOP_HALFPEL | XVID_VOP_INTER4V |
XVID_VOP_TRELLISQUANT | XVID_VOP_HQACPRED,
};
static int XDIM=352,YDIM=288;
static use_assembler = 0;
static void *enc_handle = NULL;
static int enc_init(int use_assembler);
static int enc_main(unsigned char *image,
unsigned char *bitstream,
int *key,
int *stats_type,
int *stats_quant,
int *stats_length,
int stats[3]);
static int enc_stop();
//signal act method defination
static void clean(int signum)
{
done=1;
}
int
main(int argc,char *argv[])
{
//register SIGINT action method ,to save the m4u file
signal(SIGINT,clean);
int fd;
struct v4l2_capability cap;
struct v4l2_format format;
struct v4l2_requestbuffers reqbuf;
struct v4l2_buffer buffer;
struct v4l2_input input;
int index=0,i;
for (i=1; i< argc; i++) {
if (strcmp("-asm", argv[i]) == 0 ) {
use_assembler = 1;
}else if(strcmp("-f", argv[i]) == 0 && i < argc -1){
i++;
ARG_OUTPUTFILE = argv[i];
}else if(strcmp("-i", argv[i]) == 0 && i < argc -1){
i++;
index = atoi(argv[i]);
} else if(strcmp("-w", argv[i]) == 0 && i < argc -1){
i++;
XDIM = atoi(argv[i]);
} else if(strcmp("-h", argv[i]) == 0 && i < argc -1){
i++;
YDIM = atoi(argv[i]);
}
}
//init capture card
fd = open(VIDEO,O_RDWR);
if(fd<0)
{
perror("Can't open /dev/video device");
exit(errno);
}
//if card can't support video capture and by means of steamio,exit
IOCTL(fd, VIDIOC_QUERYCAP, &cap);
if ( !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
&&!(cap.capabilities & V4L2_CAP_STREAMING))
{
fprintf(stderr, "Couldn't use the card /n");
exit(3);
}
//query input and select the desired input
IOCTL(fd, VIDIOC_G_INPUT, &index);
input.index = index;
IOCTL(fd, VIDIOC_ENUMINPUT, &input);
printf ("Current input: Index %i,Name %s/n", index,input.name);
for(i=0;;i++)
{
if(i!=index)
{
input.index = i;
if(-1==ioctl(fd, VIDIOC_ENUMINPUT, &input))
break;
else
printf ("Other input: Index %i,Name %s/n",i,input.name);
}
}
IOCTL(fd, VIDIOC_S_INPUT, &index);
//get current video format,set the desired format
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
IOCTL(fd,VIDIOC_G_FMT,&format);
format.fmt.pix.width = XDIM;
format.fmt.pix.height = YDIM;
format.fmt.pix.pixelformat = V4L2_PIX_FMT_YVU420;
format.fmt.pix.field = V4L2_FIELD_ANY;//V4L2_FIELD_INTERLACED
IOCTL(fd,VIDIOC_S_FMT,&format);
XDIM = format.fmt.pix.width;
printf("Gotten width %d/n",XDIM);
YDIM = format.fmt.pix.height;
printf("Gotten height %d/n",YDIM);
//let driver get the buffers
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
reqbuf.count = 4;
IOCTL(fd,VIDIOC_REQBUFS,&reqbuf );
if (reqbuf.count < 4)
{
printf ("Not enough buffer memory for driver/n");
exit (5);
}
//mmap the driver's buffer to application address
//create relative buffers struct to be used by mmap
struct
{
void * start;
size_t length;
} buffers[reqbuf.count];
//mmap the driver's kernel buffer into application
for (i=0;i<reqbuf.count;i++)
{
buffer.type = reqbuf.type;
buffer.index =i ;
//query the status of one buffer ,mmap the driver buffer
IOCTL(fd,VIDIOC_QUERYBUF,&buffer);
buffers[i].length = buffer.length;
buffers[i].start = mmap (NULL,buffer.length,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,buffer.m.offset);
if (buffers[i].start == MAP_FAILED)
{
close(fd);
perror ("mmap");
exit(errno);
}
}
//begin video capture
IOCTL(fd,VIDIOC_STREAMON,&reqbuf.type);
//enqueue all driver buffers
for (i=0;i<reqbuf.count;i++)
{
buffer.type = reqbuf.type;
buffer.index = i;
IOCTL(fd,VIDIOC_QUERYBUF, &buffer);
IOCTL(fd,VIDIOC_QBUF,&buffer);
}
//init xvid
int result;
result = enc_init(1);
if(result!=0)
{
fprintf(stderr, "Encore INIT problem, return value %d/n", result);
goto clean_all;
}
//get mem of mpg4 frame
uint8_t *mp4_buffer = NULL;
mp4_buffer = (unsigned char *) malloc(XDIM*YDIM);
if (mp4_buffer==NULL)
{
fprintf(stderr,"malloc error");
goto clean_all;
}
int key;
int stats_type;
int stats_quant;
int stats_length;
int sse[3];
//create store mp4 file
fp= fopen(ARG_OUTPUTFILE, "rb");
if (fp== NULL) {
perror("Error opening output file.");
exit(-1);
}
//main loop ,frame capture,compressed
i = 0;
int outbytes,m4v_size;
while(!done)
{
//dequeue one frame
buffer.type = reqbuf.type;
buffer.index = i;
IOCTL(fd, VIDIOC_QUERYBUF, &buffer);
IOCTL(fd, VIDIOC_DQBUF, &buffer);
/*debug info
printf("current frame's unix time seconds :%d/n",buffer.timestamp.tv_sec);
printf("current frame's unix time mcicoseconds :%d/n",buffer.timestamp.tv_usec);
*/
//compress a frame
m4v_size = enc_main((uint8_t *)buffers[i].start,
mp4_buffer+16,
&key, &stats_type,&stats_quant, &stats_length, sse);
//store into output file
outbytes = fwrite(mp4_buffer, 1, m4v_size, fp);
if(outbytes != m4v_size)
{
fprintf(stderr,"Error writing the m4u file/n");
exit(7);
}
//enqueue one frame
buffer.type = reqbuf.type;
buffer.index = i;
IOCTL(fd, VIDIOC_QUERYBUF, &buffer );
IOCTL(fd, VIDIOC_QBUF, &buffer );
i++;
if( i >= reqbuf.count )
i = 0;
}
clean_all:
fclose(fp);
enc_stop();
//stop capture
IOCTL(fd, VIDIOC_STREAMOFF, &reqbuf.type );
//unmmap the apllication buffer
for (i=0;i<reqbuf.count;i++)
munmap (buffers[i].start,buffers[i].length);
//release the dynamic mem
close(fd);
return 0;
}
int
enc_init(int use_assembler)
{
int xerr;
//xvid_plugin_cbr_t cbr;
xvid_plugin_single_t single;
xvid_plugin_2pass1_t rc2pass1;
xvid_plugin_2pass2_t rc2pass2;
//xvid_plugin_fixed_t rcfixed;
xvid_enc_plugin_t plugins[7];
xvid_gbl_init_t xvid_gbl_init;
xvid_enc_create_t xvid_enc_create;
/*------------------------------------------------------------------------
* XviD core initialization
*----------------------------------------------------------------------*/
/* Set version -- version checking will done by xvidcore */
memset(&xvid_gbl_init, 0, sizeof(xvid_gbl_init));
xvid_gbl_init.version = XVID_VERSION;
xvid_gbl_init.debug = 0;
/* Do we have to enable ASM optimizations ? */
if (use_assembler) {
xvid_gbl_init.cpu_flags = 0;
}
/* Initialize XviD core -- Should be done once per __process__ */
xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL);
/*------------------------------------------------------------------------
* XviD encoder initialization
*----------------------------------------------------------------------*/
/* Version again */
memset(&xvid_enc_create, 0, sizeof(xvid_enc_create));
xvid_enc_create.version = XVID_VERSION;
/* Width and Height of input frames */
xvid_enc_create.width = XDIM;
xvid_enc_create.height = YDIM;
xvid_enc_create.profile = XVID_PROFILE_S_L3;
/* init plugins */
xvid_enc_create.zones = NULL;
xvid_enc_create.num_zones = 0;
xvid_enc_create.plugins = NULL;
xvid_enc_create.num_plugins = 0;
/* No fancy thread tests */
xvid_enc_create.num_threads = 0;
/* Frame rate - Do some quick float fps = fincr/fbase hack */
if ((ARG_FRAMERATE - (int) ARG_FRAMERATE) < SMALL_EPS) {
xvid_enc_create.fincr = 1;
xvid_enc_create.fbase = (int) ARG_FRAMERATE;
} else {
xvid_enc_create.fincr = FRAMERATE_INCR;
xvid_enc_create.fbase = (int) (FRAMERATE_INCR * ARG_FRAMERATE);
}
/* Maximum key frame interval */
if (ARG_MAXKEYINTERVAL > 0) {
xvid_enc_create.max_key_interval = ARG_MAXKEYINTERVAL;
}else {
xvid_enc_create.max_key_interval = (int) ARG_FRAMERATE *10;
}
/* Bframes settings */
xvid_enc_create.max_bframes = 0;
xvid_enc_create.bquant_ratio = 150;
xvid_enc_create.bquant_offset = 100;
/* Dropping ratio frame -- we don't need that */
xvid_enc_create.frame_drop_ratio = 0;
/* Global encoder options */
xvid_enc_create.global = 0;
/* I use a small value here, since will not encode whole movies, but short clips */
xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL);
/* Retrieve the encoder instance from the structure */
enc_handle = xvid_enc_create.handle;
return (xerr);
}
int
enc_main(unsigned char *image,
unsigned char *bitstream,
int *key,
int *stats_type,
int *stats_quant,
int *stats_length,
int sse[3])
{
int ret;
xvid_enc_frame_t xvid_enc_frame;
xvid_enc_stats_t xvid_enc_stats;
/* Version for the frame and the stats */
memset(&xvid_enc_frame, 0, sizeof(xvid_enc_frame));
xvid_enc_frame.version = XVID_VERSION;
memset(&xvid_enc_stats, 0, sizeof(xvid_enc_stats));
xvid_enc_stats.version = XVID_VERSION;
/* Bind output buffer */
xvid_enc_frame.bitstream = bitstream;
xvid_enc_frame.length = -1;
/* Initialize input image fields */
if (image) {
xvid_enc_frame.input.plane[0] = image;
xvid_enc_frame.input.csp = XVID_CSP_I420;
xvid_enc_frame.input.stride[0] = XDIM;
} else {
xvid_enc_frame.input.csp = XVID_CSP_NULL;
}
/* Set up core's general features */
xvid_enc_frame.vol_flags = 0;
/* Set up core's general features */
xvid_enc_frame.vop_flags = vop_presets[ARG_QUALITY];
/* Frame type -- let core decide for us */
xvid_enc_frame.type = XVID_TYPE_AUTO;
/* Force the right quantizer -- It is internally managed by RC plugins */
xvid_enc_frame.quant = 3;
/* Set up motion estimation flags */
xvid_enc_frame.motion = motion_presets[ARG_QUALITY];
/* We don't use special matrices */
xvid_enc_frame.quant_intra_matrix = NULL;
xvid_enc_frame.quant_inter_matrix = NULL;
/* Encode the frame */
ret = xvid_encore(enc_handle, XVID_ENC_ENCODE, &xvid_enc_frame,
&xvid_enc_stats);
*key = (xvid_enc_frame.out_flags & XVID_KEYFRAME);
*stats_type = xvid_enc_stats.type;
*stats_quant = xvid_enc_stats.quant;
*stats_length = xvid_enc_stats.length;
sse[0] = xvid_enc_stats.sse_y;
sse[1] = xvid_enc_stats.sse_u;
sse[2] = xvid_enc_stats.sse_v;
return (ret);
}
int
enc_stop()
{
int xerr;
/* Destroy the encoder instance */
xerr = xvid_encore(enc_handle, XVID_ENC_DESTROY, NULL, NULL);
return (xerr);
}
下面是基于SDL的跨平台MPEG4播放器源代码,支持硬件YUV加速
#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;
}
}
/*
* 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))
{
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;y<screen->h && y<overlay->h;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;
}
}
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<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);
}
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) {
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);
}