⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 encoder.c

📁 视频压缩编解码标准MPEG4商业级别的VC代码实现标准
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************** * *  XVID MPEG-4 VIDEO CODEC *  - Encoder main module - * *  Copyright(C) 2002	  Michael Militzer <isibaar@xvid.org> *			   2002-2003 Peter Ross <pross@xvid.org> *			   2002	  Daniel Smith <danielsmith@astroboymail.com> * *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * * $Id$ * ****************************************************************************/#include <stdlib.h>#include <stdio.h>#include <math.h>#include <string.h>#include "encoder.h"#include "prediction/mbprediction.h"#include "global.h"#include "utils/timer.h"#include "image/image.h"#include "image/font.h"#include "motion/sad.h"#include "motion/motion.h"#include "motion/gmc.h"#include "bitstream/cbp.h"#include "utils/mbfunctions.h"#include "bitstream/bitstream.h"#include "bitstream/mbcoding.h"#include "utils/emms.h"#include "bitstream/mbcoding.h"#include "quant/quant_matrix.h"#include "utils/mem_align.h"/***************************************************************************** * Local function prototypes ****************************************************************************/static int FrameCodeI(Encoder * pEnc,					  Bitstream * bs);static int FrameCodeP(Encoder * pEnc,					  Bitstream * bs);static void FrameCodeB(Encoder * pEnc,					   FRAMEINFO * frame,					   Bitstream * bs);/***************************************************************************** * Encoder creation * * This function creates an Encoder instance, it allocates all necessary * image buffers (reference, current and bframes) and initialize the internal * xvid encoder paremeters according to the XVID_ENC_PARAM input parameter. * * The code seems to be very long but is very basic, mainly memory allocation * and cleaning code. * * Returned values : *	- 0				- no errors *	- XVID_ERR_MEMORY - the libc could not allocate memory, the function *						cleans the structure before exiting. *						pParam->handle is also set to NULL. * ****************************************************************************//* * Simplify the "fincr/fbase" fraction*/static voidsimplify_time(int *inc, int *base){	/* common factor */	int i = *inc;	while (i > 1) {		if (*inc % i == 0 && *base % i == 0) {			*inc /= i;			*base /= i;			i = *inc;			continue;		}		i--;	}	if (*base > 65535 || *inc > 65535) {		int *biggest;		int *other;		float div;		if (*base > *inc) {			biggest = base;			other = inc;		} else {			biggest = inc;			other = base;		}				div = ((float)*biggest)/((float)65535);		*biggest = (int)(((float)*biggest)/div);		*other = (int)(((float)*other)/div);	}}intenc_create(xvid_enc_create_t * create){	Encoder *pEnc;  int n;	if (XVID_VERSION_MAJOR(create->version) != 1) /* v1.x.x */		return XVID_ERR_VERSION;	if (create->width%2 || create->height%2)		return XVID_ERR_FAIL;	if (create->width<=0 || create->height<=0)		return XVID_ERR_FAIL;	/* allocate encoder struct */	pEnc = (Encoder *) xvid_malloc(sizeof(Encoder), CACHE_LINE);	if (pEnc == NULL)		return XVID_ERR_MEMORY;	memset(pEnc, 0, sizeof(Encoder));	pEnc->mbParam.profile = create->profile;	/* global flags */	pEnc->mbParam.global_flags = create->global;  if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED))    pEnc->mbParam.global_flags |= XVID_GLOBAL_DIVX5_USERDATA;	/* width, height */	pEnc->mbParam.width = create->width;	pEnc->mbParam.height = create->height;	pEnc->mbParam.mb_width = (pEnc->mbParam.width + 15) / 16;	pEnc->mbParam.mb_height = (pEnc->mbParam.height + 15) / 16;	pEnc->mbParam.edged_width = 16 * pEnc->mbParam.mb_width + 2 * EDGE_SIZE;	pEnc->mbParam.edged_height = 16 * pEnc->mbParam.mb_height + 2 * EDGE_SIZE;	/* framerate */	pEnc->mbParam.fincr = MAX(create->fincr, 0);	pEnc->mbParam.fbase = create->fincr <= 0 ? 25 : create->fbase;	if (pEnc->mbParam.fincr>0)		simplify_time(&pEnc->mbParam.fincr, &pEnc->mbParam.fbase);	/* zones */	if(create->num_zones > 0) {		pEnc->num_zones = create->num_zones;		pEnc->zones = xvid_malloc(sizeof(xvid_enc_zone_t) * pEnc->num_zones, CACHE_LINE);		if (pEnc->zones == NULL)			goto xvid_err_memory0;		memcpy(pEnc->zones, create->zones, sizeof(xvid_enc_zone_t) * pEnc->num_zones);	} else {		pEnc->num_zones = 0;		pEnc->zones = NULL;	}	/* plugins */	if(create->num_plugins > 0) {		pEnc->num_plugins = create->num_plugins;		pEnc->plugins = xvid_malloc(sizeof(xvid_enc_plugin_t) * pEnc->num_plugins, CACHE_LINE);		if (pEnc->plugins == NULL)			goto xvid_err_memory0;	} else {		pEnc->num_plugins = 0;		pEnc->plugins = NULL;	}	for (n=0; n<pEnc->num_plugins;n++) {		xvid_plg_create_t pcreate;		xvid_plg_info_t pinfo;		memset(&pinfo, 0, sizeof(xvid_plg_info_t));		pinfo.version = XVID_VERSION;		if (create->plugins[n].func(0, XVID_PLG_INFO, &pinfo, 0) >= 0) {			pEnc->mbParam.plugin_flags |= pinfo.flags;		}		memset(&pcreate, 0, sizeof(xvid_plg_create_t));		pcreate.version = XVID_VERSION;		pcreate.num_zones = pEnc->num_zones;		pcreate.zones = pEnc->zones;		pcreate.width = pEnc->mbParam.width;		pcreate.height = pEnc->mbParam.height;		pcreate.mb_width = pEnc->mbParam.mb_width;		pcreate.mb_height = pEnc->mbParam.mb_height;		pcreate.fincr = pEnc->mbParam.fincr;		pcreate.fbase = pEnc->mbParam.fbase;		pcreate.param = create->plugins[n].param;		pEnc->plugins[n].func = NULL;   /* disable plugins that fail */		if (create->plugins[n].func(0, XVID_PLG_CREATE, &pcreate, &pEnc->plugins[n].param) >= 0) {			pEnc->plugins[n].func = create->plugins[n].func;		}	}	if ((pEnc->mbParam.global_flags & XVID_GLOBAL_EXTRASTATS_ENABLE) ||		(pEnc->mbParam.plugin_flags & XVID_REQPSNR)) {		pEnc->mbParam.plugin_flags |= XVID_REQORIGINAL; /* psnr calculation requires the original */	}	/* temp dquants */	if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) {		pEnc->temp_dquants = (int *) xvid_malloc(pEnc->mbParam.mb_width *						pEnc->mbParam.mb_height * sizeof(int), CACHE_LINE);		if (pEnc->temp_dquants==NULL)			goto xvid_err_memory1a;	}	/* bframes */	pEnc->mbParam.max_bframes = MAX(create->max_bframes, 0);	pEnc->mbParam.bquant_ratio = MAX(create->bquant_ratio, 0);	pEnc->mbParam.bquant_offset = create->bquant_offset;	/* min/max quant */	for (n=0; n<3; n++) {		pEnc->mbParam.min_quant[n] = create->min_quant[n] > 0 ? create->min_quant[n] : 2;		pEnc->mbParam.max_quant[n] = create->max_quant[n] > 0 ? create->max_quant[n] : 31;	}	/* frame drop ratio */	pEnc->mbParam.frame_drop_ratio = MAX(create->frame_drop_ratio, 0);	/* max keyframe interval */	pEnc->mbParam.iMaxKeyInterval = create->max_key_interval <= 0 ? (10 * (int)pEnc->mbParam.fbase) / (int)pEnc->mbParam.fincr : create->max_key_interval;	/* allocate working frame-image memory */	pEnc->current = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);	pEnc->reference = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);	if (pEnc->current == NULL || pEnc->reference == NULL)		goto xvid_err_memory1;	/* allocate macroblock memory */	pEnc->current->mbs =		xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width *					pEnc->mbParam.mb_height, CACHE_LINE);	pEnc->reference->mbs =		xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width *					pEnc->mbParam.mb_height, CACHE_LINE);	if (pEnc->current->mbs == NULL || pEnc->reference->mbs == NULL)		goto xvid_err_memory2;	/* allocate quant matrix memory */	pEnc->mbParam.mpeg_quant_matrices =		xvid_malloc(sizeof(uint16_t) * 64 * 8, CACHE_LINE);	if (pEnc->mbParam.mpeg_quant_matrices == NULL)		goto xvid_err_memory2a;	/* allocate interpolation image memory */	if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {		image_null(&pEnc->sOriginal);		image_null(&pEnc->sOriginal2);	}	image_null(&pEnc->f_refh);	image_null(&pEnc->f_refv);	image_null(&pEnc->f_refhv);	image_null(&pEnc->current->image);	image_null(&pEnc->reference->image);	image_null(&pEnc->vInterH);	image_null(&pEnc->vInterV);	image_null(&pEnc->vInterHV);	if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {		if (image_create			(&pEnc->sOriginal, pEnc->mbParam.edged_width,			 pEnc->mbParam.edged_height) < 0)			goto xvid_err_memory3;		if (image_create			(&pEnc->sOriginal2, pEnc->mbParam.edged_width,			 pEnc->mbParam.edged_height) < 0)			goto xvid_err_memory3;	}	if (image_create		(&pEnc->f_refh, pEnc->mbParam.edged_width,		 pEnc->mbParam.edged_height) < 0)		goto xvid_err_memory3;	if (image_create		(&pEnc->f_refv, pEnc->mbParam.edged_width,		 pEnc->mbParam.edged_height) < 0)		goto xvid_err_memory3;	if (image_create		(&pEnc->f_refhv, pEnc->mbParam.edged_width,		 pEnc->mbParam.edged_height) < 0)		goto xvid_err_memory3;	if (image_create		(&pEnc->current->image, pEnc->mbParam.edged_width,		 pEnc->mbParam.edged_height) < 0)		goto xvid_err_memory3;	if (image_create		(&pEnc->reference->image, pEnc->mbParam.edged_width,		 pEnc->mbParam.edged_height) < 0)		goto xvid_err_memory3;	if (image_create		(&pEnc->vInterH, pEnc->mbParam.edged_width,		 pEnc->mbParam.edged_height) < 0)		goto xvid_err_memory3;	if (image_create		(&pEnc->vInterV, pEnc->mbParam.edged_width,		 pEnc->mbParam.edged_height) < 0)		goto xvid_err_memory3;	if (image_create		(&pEnc->vInterHV, pEnc->mbParam.edged_width,		 pEnc->mbParam.edged_height) < 0)		goto xvid_err_memory3;/* Create full bitplane for GMC, this might be wasteful */	if (image_create		(&pEnc->vGMC, pEnc->mbParam.edged_width,		 pEnc->mbParam.edged_height) < 0)		goto xvid_err_memory3;	/* init bframe image buffers */	pEnc->bframenum_head = 0;	pEnc->bframenum_tail = 0;	pEnc->flush_bframes = 0;	pEnc->closed_bframenum = -1;	/* B Frames specific init */	pEnc->bframes = NULL;	if (pEnc->mbParam.max_bframes > 0) {		pEnc->bframes =			xvid_malloc(pEnc->mbParam.max_bframes * sizeof(FRAMEINFO *),						CACHE_LINE);		if (pEnc->bframes == NULL)			goto xvid_err_memory3;		for (n = 0; n < pEnc->mbParam.max_bframes; n++)			pEnc->bframes[n] = NULL;		for (n = 0; n < pEnc->mbParam.max_bframes; n++) {			pEnc->bframes[n] = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);			if (pEnc->bframes[n] == NULL)				goto xvid_err_memory4;			pEnc->bframes[n]->mbs =				xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width *							pEnc->mbParam.mb_height, CACHE_LINE);			if (pEnc->bframes[n]->mbs == NULL)				goto xvid_err_memory4;			image_null(&pEnc->bframes[n]->image);			if (image_create				(&pEnc->bframes[n]->image, pEnc->mbParam.edged_width,				 pEnc->mbParam.edged_height) < 0)				goto xvid_err_memory4;		}	}	/* init incoming frame queue */	pEnc->queue_head = 0;	pEnc->queue_tail = 0;	pEnc->queue_size = 0;	pEnc->queue =		xvid_malloc((pEnc->mbParam.max_bframes+1) * sizeof(QUEUEINFO),					CACHE_LINE);	if (pEnc->queue == NULL)		goto xvid_err_memory4;	for (n = 0; n < pEnc->mbParam.max_bframes+1; n++)		image_null(&pEnc->queue[n].image);	for (n = 0; n < pEnc->mbParam.max_bframes+1; n++) {		if (image_create			(&pEnc->queue[n].image, pEnc->mbParam.edged_width,			 pEnc->mbParam.edged_height) < 0)			goto xvid_err_memory5;	}	/* timestamp stuff */	pEnc->mbParam.m_stamp = 0;	pEnc->m_framenum = 0;	pEnc->current->stamp = 0;	pEnc->reference->stamp = 0;	/* other stuff */	pEnc->iFrameNum = 0;	pEnc->fMvPrevSigma = -1;	create->handle = (void *) pEnc;	init_timer();	init_mpeg_matrix(pEnc->mbParam.mpeg_quant_matrices);	return 0;   /* ok */	/*	 * We handle all XVID_ERR_MEMORY here, this makes the code lighter	 */  xvid_err_memory5:	for (n = 0; n < pEnc->mbParam.max_bframes+1; n++) {			image_destroy(&pEnc->queue[n].image, pEnc->mbParam.edged_width,						  pEnc->mbParam.edged_height);		}	xvid_free(pEnc->queue);  xvid_err_memory4:	if (pEnc->mbParam.max_bframes > 0) {		int i;		for (i = 0; i < pEnc->mbParam.max_bframes; i++) {			if (pEnc->bframes[i] == NULL)				continue;			image_destroy(&pEnc->bframes[i]->image, pEnc->mbParam.edged_width,						  pEnc->mbParam.edged_height);			xvid_free(pEnc->bframes[i]->mbs);			xvid_free(pEnc->bframes[i]);		}		xvid_free(pEnc->bframes);	}  xvid_err_memory3:	if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {		image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width,					  pEnc->mbParam.edged_height);		image_destroy(&pEnc->sOriginal2, pEnc->mbParam.edged_width,					  pEnc->mbParam.edged_height);	}	image_destroy(&pEnc->f_refh, pEnc->mbParam.edged_width,				  pEnc->mbParam.edged_height);	image_destroy(&pEnc->f_refv, pEnc->mbParam.edged_width,				  pEnc->mbParam.edged_height);	image_destroy(&pEnc->f_refhv, pEnc->mbParam.edged_width,				  pEnc->mbParam.edged_height);	image_destroy(&pEnc->current->image, pEnc->mbParam.edged_width,				  pEnc->mbParam.edged_height);	image_destroy(&pEnc->reference->image, pEnc->mbParam.edged_width,				  pEnc->mbParam.edged_height);	image_destroy(&pEnc->vInterH, pEnc->mbParam.edged_width,				  pEnc->mbParam.edged_height);	image_destroy(&pEnc->vInterV, pEnc->mbParam.edged_width,				  pEnc->mbParam.edged_height);	image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width,				  pEnc->mbParam.edged_height);/* destroy GMC image */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -