www.pudn.com > xvidcore-0.9.2.zip > odivx_enc_dec.c


/**************************************************************************
 *
 *      XVID MPEG-4 VIDEO CODEC - Example for encoding and decoding
 *
 *      This program 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 of the License, or
 *      (at your option) any later version.
 *
 *      This program 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 this program; if not, write to the Free Software
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *************************************************************************/

/************************************************************************
 *		                    
 *  Test routine for XviD using the OpenDivX/Divx4-API                      
 *  (C) Christoph Lampert, 2002/01/19	              
 *		                    
 *  A sequence of YUV pics in PGM file format is encoded and decoded                     
 *		                   
 *  The program is plain C and needs no libraries except for libxvidcore, 
 *  so with UN*X you simply compile by
 * 
 *  gcc -o odivx_enc_dec odivx_enc_dec.c -lxvidcore 
 *
 *  Run without parameters, then PGM input input is read from stdin.
 *
 *  PGM/xvid-output is saved, if corresponding flags are set 
 * 
 *  input data can be generated e.g. out of MPEG2 with mpeg2dec -o pgmpipe 
 *	
 ************************************************************************/

#include 
#include 

#include "divx4.h"

#define ARG_FRAMERATE 25
#define ARG_BITRATE 900

int QUALITY =5;
int QUANTI = 0;		/* used for fixed-quantizer encoding  */

int XDIM=0;
int YDIM=0;	/* will be set when reading first image */
int filenr = 0;

int save_m4v_flag = 0;		/* save MPEG4-bytestream? */
int save_dec_flag = 0;		/* save decompressed bytestream? */
char filepath[256] = ".";	/* path where to save  */

void *enchandle = NULL;		/* enchandle is a void*, written by encore */
const long dechandle = 0x0815;	/* dechandle is a unique constant!!!  */

/*********************************************************************/
/*	Routines for file input/output, nothing specific to XviD     */
/*********************************************************************/

int read_pgmheader(FILE* handle)
{	int bytes,xsize,ysize,depth;
	char dummy[2];
	
	bytes = fread(dummy,1,2,handle);

	if ( (bytes < 2) || (dummy[0] != 'P') || (dummy[1] != '5' ))
   		return 1;
	fscanf(handle,"%d %d %d",&xsize,&ysize,&depth); 
	if ( (xsize > 1440) || (ysize > 2880 ) || (depth != 255) )
	{
		fprintf(stderr,"%d %d %d\n",XDIM,YDIM,depth);
	   	return 2;
	}
	if ( (XDIM==0) || (YDIM==0) )
	{	XDIM=xsize;
		YDIM=ysize;
	}

	return 0;
}

int read_pgmdata(FILE* handle, unsigned char *image)
{	int i;
	char dummy;
   
	unsigned char* buff1_ptr2 = image + XDIM*YDIM;
	unsigned char* buff1_ptr3 = image + XDIM*YDIM + XDIM/2*YDIM/2; 

	fread(image,XDIM,YDIM,stdin);
 
   	for (i=0;i */
	
	dec_param.time_incr = 20;

	status = decore(dechandle, DEC_OPT_INIT, &dec_param, NULL);
/*      if (status)  */
		printf("Decore INIT return %d\n", status);

/* We don't do any postprocessing here...  */

/*	dec_set.postproc_level = 0;
	status = decore(dechandle, DEC_OPT_SETPP, &dec_set, NULL);
	if (status) 
		printf("Decore POSTPROC %d return %d\n", dec_set.postproc_level, status);
*/

	return status;
} 

int dec_main(unsigned char *m4v_buffer, unsigned char *rgb_buffer, int m4v_size)
{	
	int status;
	
	static DEC_FRAME dec_frame;
	static DEC_FRAME_INFO dec_frame_info;

	dec_frame.length = m4v_size;
	dec_frame.bitstream = m4v_buffer;
	dec_frame.bmp = rgb_buffer;
	dec_frame.render_flag = 1;		/* 0 means: skip this frame */
	dec_frame.stride = XDIM;

	status = decore(dechandle, DEC_OPT_FRAME, &dec_frame, &dec_frame_info);
	if (status)
		printf("Decore Frame status %d!\n", status);

	return status;
}

int dec_stop()
{
	int status;
	status = decore(dechandle, DEC_OPT_RELEASE, NULL, NULL);
/*	if (status)  */
		printf("Decore RELEASE return %d\n", status);
	return status;
}


/*********************************************************************/
/*                          Main program                             */
/*********************************************************************/

int main()
{
  unsigned char *divx_buffer = NULL;
  unsigned char *yuv_buffer = NULL;
  unsigned char *rgb_buffer = NULL;

  int status;
  int m4v_size;
  
  char filename[256];
  
  FILE *filehandle;

/* read YUV in pgm format from stdin */
  if (read_pgmheader(stdin))
    {
      printf("Wrong input format, I want YUV encapsulated in PGM\n");
      return 0;
    }

/* now we know the sizes, so allocate memory */
  yuv_buffer = (unsigned char *) malloc(XDIM*YDIM);	
  if (!yuv_buffer)
    goto free_all_memory;	/* goto is one of the most underestimated instructions in C !!! */
  divx_buffer = (unsigned char *) malloc(XDIM*YDIM*2);	/* this should really be enough! */
  if (!divx_buffer)
    goto free_all_memory;	/* actually, every program should contain a goto  */
    
  YDIM = YDIM*2/3; /* PGM is YUV 4:2:0 format, so height is *3/2 too much */
    
  rgb_buffer = (unsigned char *) malloc(XDIM*YDIM*4);	
  if (!rgb_buffer)
    goto free_all_memory;	/* the more, the better! */

/*********************************************************************/
/*	                   DIVX PART  Start                          */
/*********************************************************************/

  status = enc_init();
/*       if (status)     */
	  printf("Encore INIT return %d, handle=%lx\n", status, enchandle);

  status = dec_init();
/*      if (status)  */
	  printf("Decore INIT return %d\n", status);


/*********************************************************************/
/*	                         Main loop                           */
/*********************************************************************/

  do
    {
      status = read_pgmdata(stdin, yuv_buffer);	/* read PGM data (YUV-format) */
      if (status)
	{
	  fprintf(stderr, "PGM-Data-Error: %d\n", status);	/* this should not happen */
	  continue;
	}

/*********************************************************************/
/*               encode and decode this frame                        */
/*********************************************************************/

	status = enc_main(yuv_buffer, divx_buffer, &m4v_size);

	printf("Frame %5d: encore-ENCODE status %d, m4v-stream length=%7d bytes\n",
		 filenr, status, m4v_size);

      if (save_m4v_flag)
	{
	  sprintf(filename, "%s/frame%05d.m4v", filepath, filenr);
	  filehandle = fopen(filename, "wb");
	  fwrite(divx_buffer, m4v_size, 1, filehandle);
	  fclose(filehandle);
	}

      status = dec_main(divx_buffer, rgb_buffer, m4v_size);
	if (status)
		printf("Frame %5d: decore status %d\n",status);
      
      if (save_dec_flag)
	{
		sprintf(filename, "%s/dec%05d.ppm", filepath, filenr);
 	       	filehandle=fopen(filename,"wb");
		if (filehandle)
	        {
                	fprintf(filehandle,"P6\n");		/* rgb24 in PPM format */
	      		fprintf(filehandle,"%d %d 255\n",XDIM,YDIM);
      			fwrite(rgb_buffer,XDIM,YDIM*3,filehandle);
                	fclose(filehandle);
		}
 	}

      filenr++;
      status = read_pgmheader(stdin);		/* if it was the last PGM, stop after it */
      if (status)
	{
	  fprintf(stderr, "PGM-Header-Error: %d\n", status); /* normally, just end of file */
	}
    }
  while (!status);


/*********************************************************************/
/*	   DIVX PART  Stop                        */
/*********************************************************************/


/* Stop XviD */

  	dec_stop();
/*       if (status)     */
	printf("Encore RELEASE return %d\n", status);

  	enc_stop();
/*       if (status)     */
	printf("Decore RELEASE return %d\n", status);

free_all_memory:

  if (rgb_buffer)
    free(rgb_buffer);
  if (divx_buffer)
    free(divx_buffer);
  if (yuv_buffer)
    free(yuv_buffer);

  return 0;
}