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

📄 encoder.c

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 C
📖 第 1 页 / 共 5 页
字号:
/*****************************************************************************
 *
 *  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: encoder.c,v 1.130 2007/02/08 13:10:24 Isibaar Exp $
 *
 ****************************************************************************/

#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"

# include "motion/motion_smp.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 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 void
simplify_time(int *inc, int *base)
{
	/* common factor */
	const int s = gcd(*inc, *base);
  *inc  /= s;
  *base /= s;

	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 = (unsigned int)(((float)*biggest)/div);
		*other = (unsigned int)(((float)*other)/div);
	}
}


int
enc_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((int*)&pEnc->mbParam.fincr, (int*)&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(NULL, XVID_PLG_INFO, &pinfo, NULL) >= 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(NULL, 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;
	}

	/* temp lambdas */
	if (pEnc->mbParam.plugin_flags & XVID_REQLAMBDA) {
		pEnc->temp_lambda = (float *) xvid_malloc(pEnc->mbParam.mb_width *
						pEnc->mbParam.mb_height * 6 * sizeof(float), CACHE_LINE);
		if (pEnc->temp_lambda == 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);

⌨️ 快捷键说明

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