libxvid视频编码代码实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <sys/time.h>

//#include "portab.h" /* for pthread */

#include "xvid.h"

// Equivalent to vfw's pmvfast_presets
static const int motion_presets[] = {
	/* quality 0 */
	0,

	/* quality 1 */
	0,

	/* quality 2 */
	0,

	/* quality 3 */
	0,

	/* quality 4 */
	0 | XVID_ME_HALFPELREFINE16 | 0,

	/* quality 5 */
	0 | XVID_ME_HALFPELREFINE16 | 0 | XVID_ME_ADVANCEDDIAMOND16,

	/* quality 6 */
	XVID_ME_HALFPELREFINE16 | XVID_ME_EXTSEARCH16 |	XVID_ME_HALFPELREFINE8 | 0 | XVID_ME_USESQUARES16

};
#define ME_ELEMENTS (sizeof(motion_presets)/sizeof(motion_presets[0]))

static const int vop_presets[] = {
	/* quality 0 */
	0,

	/* quality 1 */
	0,

	/* quality 2 */
	0,

	/* quality 3 */
	0,

	/* quality 4 */
	0,

	/* quality 5 */
	XVID_VOP_INTER4V,

	/* quality 6 */
	XVID_VOP_INTER4V,

};
#define VOP_ELEMENTS (sizeof(vop_presets)/sizeof(vop_presets[0]))

#define MAX_XDIM 4096
#define MAX_YDIM 4096

#ifndef READ_PNM
#define IMAGE_SIZE(x,y) ((x)*(y)*3/2)
#else
#define IMAGE_SIZE(x,y) ((x)*(y)*3)
#endif

typedef struct 
 {
    void *enc_handle;              /**< Handle for Xvid encoder */
    int xsize;                     /**< Frame x size */
    int ysize;                     /**< Frame y size */
	int bitrate;
	float framerate;
	int me_quality;                /**< Motion estimation quality. 0: fast 6: best. */
    //int vop_flags;                 /**< VOP flags for Xvid encoder */
    //int vol_flags;                 /**< VOL flags for Xvid encoder */
    //int me_flags;                  /**< Motion Estimation flags */
    //int qscale;                    /**< Do we use constant scale? */
    //int quicktime_format;          /**< Are we in a QT-based format? */
    //char *twopassbuffer;           /**< Character buffer for two-pass */
    //char *old_twopassbuffer;       /**< Old character buffer (two-pass) */
    //char *twopassfile;             /**< second pass temp file name */
    //int twopassfd;
    //unsigned char *intra_matrix;   /**< P-Frame Quant Matrix */
    //unsigned char *inter_matrix;   /**< I-Frame Quant Matrix */
    //int lumi_aq;                   /**< Lumi masking as an aq method */
    //int variance_aq;               /**< Variance adaptive quantization */
    //int ssim;                      /**< SSIM information display mode */
    //int ssim_acc;                  /**< SSIM accuracy. 0: accurate. 4: fast. */
    //int gmc;
    //int mpeg_quant;                /**< Quantization type. 0: H.263, 1: MPEG */
} xvid_context;

static 	int ARG_DWRATE = 25;
static 	int ARG_DWSCALE = 1;
static 	int ARG_MAXKEYINTERVAL = 300;

//static 	int ARG_NUM_APP_THREADS = 1;

static 	char *ARG_INPUTFILE = NULL;
static 	char *ARG_OUTPUTFILE = NULL;

static 	int ARG_QUANTS[6] = {2, 31, 2, 31, 2, 31};
const char userdata_start_code[] = "\0\0\x01\xb2";

static double msecond();
int gcd(int a, int b);

static int read_yuvdata(FILE * handle, xvid_context *x, unsigned char *image);
static void enc_gbl(int use_assembler);

static int xvid_encode_init(xvid_context *x);
static int xvid_encode_frame(xvid_context *x, 
                            unsigned char *image, 
							unsigned char *bitstream, 
							int *key, 
							int *stats_type);
static int xvid_encode_close(xvid_context* x);

void removedivxp(char *buf, int size);

static double msecond()
{
#ifndef WIN32
	struct timeval tv;

	gettimeofday(&tv, 0);
	return (tv.tv_sec * 1.0e3 + tv.tv_usec * 1.0e-3);
#else
	clock_t clk;

	clk = clock();
	return (clk * 1000.0 / CLOCKS_PER_SEC);
#endif
}

int gcd(int a, int b)
{
	int r ;

	if (b > a) {
		r = a;
		a = b;
		b = r;
	}

	while ((r = a % b)) {
		a = b;
		b = r;
	}
	return b;
}

static int read_yuvdata(FILE * handle, xvid_context* x, unsigned char *image)
{
	if (fread(image, 1, IMAGE_SIZE(x->xsize, x->ysize), handle) !=
		(unsigned int) IMAGE_SIZE(x->xsize, x->ysize))
		return (1);
	else
		return (0);
}

static void enc_gbl(int use_assembler)
{
	xvid_gbl_init_t xvid_gbl_init;

	/*------------------------------------------------------------------------
	 * 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;//ARG_DEBUG;

    if (use_assembler) 
	    xvid_gbl_init.cpu_flags = 0;
	else 
	    xvid_gbl_init.cpu_flags = XVID_CPU_FORCE;

	/* Initialize Xvid core -- Should be done once per __process__ */
	xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL);
    //ARG_CPU_FLAGS = xvid_gbl_init.cpu_flags;
	----------------------------------------------
	xvid_gbl_info_t xvid_gbl_info;
	int ret;
	memset(&xvid_gbl_info, 0, sizeof(xvid_gbl_info));
	xvid_gbl_info.version = XVID_VERSION;
	ret = xvid_global(NULL, XVID_GBL_INFO, &xvid_gbl_info, NULL);
}

void removedivxp(char *buf, int bufsize) {
	int i;
	char* userdata;

	for (i=0; i <= (int)(bufsize-sizeof(userdata_start_code)); i++) {
		if (memcmp((void*)userdata_start_code, (void*)(buf+i), strlen(userdata_start_code))==0) {
			if ((userdata = strstr(buf+i+4, "DivX"))!=NULL) {
				userdata[strlen(userdata)-1] = '\0';
				return;
			}
		}
	}
}

int main(int argc, char *argv[])
{
    int i;
	int result;
	int key;
	int type;
	int m4v_size;
    FILE *in_file;
	FILE *out_file;

    //memset(framestats, 0, sizeof(framestats));
    xvid_context *x = (xvid_context*)malloc(sizeof(xvid_context));

    for (i = 1; i < argc; i++) 
	{
        if (strcmp("-w", argv[i]) == 0 && i < argc - 1) {
			i++;
			x->xsize = atoi(argv[i]);
		} else if (strcmp("-h", argv[i]) == 0 && i < argc - 1) {
			i++;
			x->ysize = atoi(argv[i]);
		} else if (strcmp("-bitrate", argv[i]) == 0) {
			i++;
			x->bitrate = atoi(argv[i]);
		} else if (strcmp("-framerate", argv[i]) == 0 && i < argc - 1) {
			int exponent;
			i++;
			x->framerate = (float) atof(argv[i]);
			exponent = (int) strcspn(argv[i], ".");
			if (exponent<(int)strlen(argv[i]))
				exponent=(int)pow(10.0, (int)(strlen(argv[i])-1-exponent));
			else
				exponent=1;
			ARG_DWRATE = (int)(atof(argv[i])*exponent);
			ARG_DWSCALE = exponent;
			exponent = gcd(ARG_DWRATE, ARG_DWSCALE);
			ARG_DWRATE /= exponent;
			ARG_DWSCALE /= exponent;
		} else if (strcmp("-i", argv[i]) == 0 && i < argc - 1) {
			i++;
			ARG_INPUTFILE = argv[i];
		} else if (strcmp("-o", argv[i]) == 0 && i < argc - 1) {
			i++;
			ARG_OUTPUTFILE = argv[i];
		}
    }

	fprintf(stdout, "xsize value - ysize value %d - %d \n", x->xsize, x->ysize);

    //---------------------------------------------------------------------------//
	if (ARG_INPUTFILE != NULL) {
		in_file = fopen(ARG_INPUTFILE, "rb");
		if (in_file == NULL) {
			fprintf(stderr, "Error opening input file %s\n", ARG_INPUTFILE);
			return (-1);
		}
	}
	
	if (ARG_OUTPUTFILE != NULL) {
		out_file = fopen(ARG_OUTPUTFILE, "w+b");
		if (out_file == NULL) {
			fprintf(stderr, "Error opening output file %s\n", ARG_OUTPUTFILE);
			return (-1);
		}
	}

	fseek(in_file, 0, SEEK_SET);

	/* now we know the sizes, so allocate memory */
	unsigned char *image = (unsigned char *) malloc(4*x->xsize*x->ysize);
	if (!image)
		goto release_all;

	/* this should really be enough memory ! */
	unsigned char *mp4_buffer = (unsigned char *) malloc(IMAGE_SIZE(x->xsize, x->ysize) * 2);
	if (!mp4_buffer)
		goto release_all;
	
	// ------------------------------------------------------------------------//
	result = xvid_encode_init(x);
	if (result) {
		fprintf(stderr, "Encore INIT problem, return value %d\n", result);
		goto release_all;
	}

	// ------------------------------------------------------------------------//
	i = 0;
	do {
        result = read_yuvdata(in_file, x, image);

	    double enctime = msecond();
		m4v_size = xvid_encode_frame(x, !result ? image : 0, mp4_buffer, &key, &type);
		enctime = msecond() - enctime;

		fprintf(stdout, "frame_num= %d, ", ++i);
		//fprintf(stdout, "m4v_size= %d\n", m4v_size);
	    if (m4v_size < 0)
		    break;

        if (m4v_size > 0) {
        	/* Save ES stream */
            //fprintf(stdout, "type= %d\n", type);

			if (out_file && (type != XVID_TYPE_BVOP) || (m4v_size > 8) ) 
			{
				fwrite(mp4_buffer, 1, m4v_size, out_file);
			}
    	}
		
	} while(1);

	// ----------------------------------------------------------------------------//
	result = xvid_encode_close(x);

	//----------------------------------------------------------//
release_all:
    if (in_file)
	    fclose(in_file);
	if (out_file)
		fclose(out_file);

	if (mp4_buffer)
	    free(mp4_buffer);
	if (image)
	    free(image);

    return (0);
//-------------------------------------------------------------------------------------------//
}

static int xvid_encode_init(xvid_context *x)
{
    /* Init xvidcore */
    enc_gbl(/*use_assembler*/ 1);

    int xerr;
	//xvid_plugin_cbr_t cbr;
    xvid_plugin_single_t single;
	//xvid_plugin_fixed_t rcfixed;
	xvid_enc_plugin_t plugins[8];
	xvid_enc_create_t xvid_enc_create;

	/*------------------------------------------------------------------------
	 * 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 = x->xsize;
	xvid_enc_create.height = x->ysize;
	xvid_enc_create.profile = 0xf5; /* Unrestricted */

	/* init plugins  */

	xvid_enc_create.plugins = plugins;
	xvid_enc_create.num_plugins = 0;

	if (1/*ARG_SINGLE*/) {
		memset(&single, 0, sizeof(xvid_plugin_single_t));
		single.version = XVID_VERSION;
		single.bitrate = x->bitrate;
		single.reaction_delay_factor = 16;//ARG_REACTION;
		single.averaging_period = 100;//ARG_AVERAGING;
		single.buffer = 100;//ARG_SMOOTHER;
		

		plugins[xvid_enc_create.num_plugins].func = xvid_plugin_single;
		plugins[xvid_enc_create.num_plugins].param = &single;
		xvid_enc_create.num_plugins++;
	}

	/* We don't use zones */
    xvid_enc_create.zones     = NULL;
    xvid_enc_create.num_zones = 0;

	xvid_enc_create.num_threads = 1;//ARG_THREADS;
	xvid_enc_create.num_slices  = 1;//ARG_SLICES;

	/* Frame rate  */
	xvid_enc_create.fincr = ARG_DWSCALE;
	xvid_enc_create.fbase = ARG_DWRATE;

	/* Maximum key frame interval */
    if (ARG_MAXKEYINTERVAL > 0) {
        xvid_enc_create.max_key_interval = ARG_MAXKEYINTERVAL;
    }else {
	    xvid_enc_create.max_key_interval = (int) x->framerate *10;
    }

	xvid_enc_create.min_quant[0]=ARG_QUANTS[0];
	xvid_enc_create.min_quant[1]=ARG_QUANTS[2];
	xvid_enc_create.min_quant[2]=ARG_QUANTS[4];
	xvid_enc_create.max_quant[0]=ARG_QUANTS[1];
	xvid_enc_create.max_quant[1]=ARG_QUANTS[3];
	xvid_enc_create.max_quant[2]=ARG_QUANTS[5];

	/* Bframes settings */
	xvid_enc_create.max_bframes = 2;//ARG_MAXBFRAMES;
	xvid_enc_create.bquant_ratio = 150;//ARG_BQRATIO;
	xvid_enc_create.bquant_offset = 100;//ARG_BQOFFSET;

	/* Frame drop ratio */
	xvid_enc_create.frame_drop_ratio = 0;//ARG_FRAMEDROP;

	/* Start frame number */
	xvid_enc_create.start_frame_num = 0;//start_num;

	/* Global encoder options */
	xvid_enc_create.global = 0;

	if (1/*ARG_PACKED*/)
		xvid_enc_create.global |= XVID_GLOBAL_PACKED;

	if (1/*ARG_CLOSED_GOP*/)
		xvid_enc_create.global |= XVID_GLOBAL_CLOSED_GOP;

	/* 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 */
	x->enc_handle = xvid_enc_create.handle;
	x->me_quality = 6;

	free(xvid_enc_create.zones);
	return (xerr);
}

static int xvid_encode_frame(
	xvid_context *x, unsigned char *image, unsigned char *bitstream, int *key, int *stats_type)
 {
    int ret;
    do {
		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] = x->xsize;
		} else {
			xvid_enc_frame.input.csp = XVID_CSP_NULL;
		}

		/* Set up core's general features */
		xvid_enc_frame.vol_flags = 0;

        xvid_enc_frame.par = 1;

		//int div;
		//div = gcd(x->xsize, x->ysize);
		//xvid_enc_frame.par = XVID_PAR_EXT;
		//xvid_enc_frame.par_width = x->xsize/div;
		//xvid_enc_frame.par_height = x->ysize/div;

		// /* Set up core's general features */
		xvid_enc_frame.vop_flags = vop_presets[x->me_quality];

		xvid_enc_frame.vop_flags |= XVID_VOP_HALFPEL;
		xvid_enc_frame.vop_flags |= XVID_VOP_HQACPRED;

		//if (ARG_TRELLIS)
   		xvid_enc_frame.vop_flags |= XVID_VOP_TRELLISQUANT;

		/* Frame type -- taken from function call parameter */
		/* Sometimes we might want to force the last frame to be a P Frame */
		xvid_enc_frame.type = XVID_TYPE_AUTO;

		/* Force the right quantizer -- It is internally managed by RC plugins */
		xvid_enc_frame.quant = 0;

		//if (ARG_CHROMAME)
		xvid_enc_frame.motion |= XVID_ME_CHROMA_PVOP + XVID_ME_CHROMA_BVOP;

		/* Set up motion estimation flags */
		xvid_enc_frame.motion |= motion_presets[x->me_quality];

		// switch (ARG_VHQMODE) /* this is the same code as for vfw */
		// {
		// case 1: /* VHQ_MODE_DECISION */
		 	xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
		// 	break;

		// case 2: /* VHQ_LIMITED_SEARCH */
		// 	xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
		// 	xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE16_RD;
		// 	xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16_RD;
		// 	break;

		// case 3: /* VHQ_MEDIUM_SEARCH */
		// 	xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
		// 	xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE16_RD;
		// 	xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE8_RD;
		// 	xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16_RD;
		// 	xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE8_RD;
		// 	xvid_enc_frame.motion |= XVID_ME_CHECKPREDICTION_RD;
		// 	break;

		//case 4: /* VHQ_WIDE_SEARCH */
			// xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
			// xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE16_RD;
			// xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE8_RD;
			// xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16_RD;
			// xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE8_RD;
			// xvid_enc_frame.motion |= XVID_ME_CHECKPREDICTION_RD;
			// xvid_enc_frame.motion |= XVID_ME_EXTSEARCH_RD;
		//	break;

		//default :
		//	break;
		//}

		/* Not sure what this does */
		// force keyframe spacing in 2-pass 1st pass

		/* frame-based stuff */
		//apply_zone_modifiers(&xvid_enc_frame, framenum);

		/* Encode the frame */
		ret = xvid_encore(x->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;
    } while (0);

	return (ret);
}

static int xvid_encode_close(xvid_context* x)
{
	int xerr;
	/* Destroy the encoder instance */
	xerr = xvid_encore(x->enc_handle, XVID_ENC_DESTROY, NULL, NULL);

	return (xerr);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
h.264视频编解码源代码.rar 详细说明:h.264标准代码,用于视频编码!可以实现各种视频编码和解码,可以在这个代码的基础上进行各种开发,比如算法的优化,转码技术,实现各种分辨了的转码-h.264 standard code, uses in the video frequency code! May realize each kind of video frequency code and the decoding, may carry on each kind of development in this code foundation, for instance the algorithm optimization, transfers the code technology, realizes each kind has distinguished extension code 文件列表: jm73 ....\JM ....\..\bin ....\..\...\decoder.cfg ....\..\...\encoder.cfg ....\..\...\lencod.exe ....\..\...\lencod.map ....\..\...\lencod.pdb ....\..\CHANGES.TXT ....\..\Changes_detail.txt ....\..\copyright.txt ....\..\disclaimer.txt ....\..\doc ....\..\...\coding_style.doc ....\..\...\doxygen.txt ....\..\...\h26l.css ....\..\...\ldecod.dox ....\..\...\lencod.dox ....\..\encoder.cfg ....\..\foreman_part_qcif.yuv ....\..\ldecod ....\..\......\inc ....\..\......\...\annexb.h ....\..\......\...\biaridecod.h ....\..\......\...\block.h ....\..\......\...\cabac.h ....\..\......\...\context_ini.h ....\..\......\...\contributors.h ....\..\......\...\ctx_tables.h ....\..\......\...\defines.h ....\..\......\...\elements.h ....\..\......\...\erc_api.h ....\..\......\...\erc_do.h ....\..\......\...\erc_globals.h ....\..\......\...\errorconcealment.h ....\..\......\...\fmo.h ....\..\......\...\global.h ....\..\......\...\header.h ....\..\......\...\image.h ....\..\......\...\leaky_bucket.h ....\..\......\...\macroblock.h ....\..\......\...\mbuffer.h ....\..\......\...\mb_access.h ....\..\......\...\memalloc.h ....\..\......\...\nalu.h ....\..\......\...\nalucommon.h ....\..\......\...\output.h ....\..\......\...\parset.h ....\..\......\...\parsetcommon.h ....\..\......\...\rtp.h ....\..\......\...\sei.h ....\..\......\...\vlc.h ....\..\......\Makefile ....\..\......\src ....\..\......\...\annexb.c ....\..\......\...\biaridecod.c ....\..\......\...\block.c ....\..\......\...\cabac.c ....\..\......\...\context_ini.c ....\..\......\...\erc_api.c ....\..\......\...\erc_do_i.c ....\..\......\...\erc_do_p.c ....\..\......\...\errorconcealment.c ....\..\......\...\filehandle.c ....\..\......\...\fmo.c ....\..\......\...\header.c ....\..\......\...\image.c ....\..\......\...\ldecod.c ....\..\......\...\leaky_bucket.c ....\..\......\...\loopFilter.c ....\..\......\...\macroblock.c ....\..\......\...\mbuffer.c ....\..\......\...\mb_access.c ....\..\......\...\memalloc.c ....\..\......\...\nal.c ....\..\......\...\nalu.c ....\..\......\...\nalucommon.c ....\..\......\...\nal_part.c ....\..\......\...\output.c ....\..\......\...\parset.c ....\..\......\...\parsetcommon.c ....\..\......\...\rtp.c ....\..\......\...\sei.c ....\..\......\...\vlc.c ....\..\ldecod.dsp ....\..\ldecod.dsw ... ...

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值