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

📄 encoder.c

📁 网络MPEG4IP流媒体开发源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <stdlib.h>#include <stdio.h>#include <math.h>#include "encoder.h"#include "prediction/mbprediction.h"#include "global.h"#include "utils/timer.h"#include "image/image.h"#include "bitstream/cbp.h"#include "utils/mbfunctions.h"#include "bitstream/bitstream.h"#include "bitstream/mbcoding.h"#include "utils/ratecontrol.h"#include "utils/emms.h"#include "bitstream/mbcoding.h"#include "quant/adapt_quant.h"#include "quant/quant_matrix.h"#include "utils/mem_align.h"#define ENC_CHECK(X) if(!(X)) return XVID_ERR_FORMAT#ifdef MPEG4IPstatic int FrameCodeI(Encoder * pEnc, Bitstream * bs, uint32_t *pBits, bool vol_header);#elsestatic int FrameCodeI(Encoder * pEnc, Bitstream * bs, uint32_t *pBits);#endifstatic int FrameCodeP(Encoder * pEnc, Bitstream * bs, uint32_t *pBits, bool force_inter, bool vol_header);static int DQtab[4] = {	-1, -2, 1, 2};static int iDQtab[5] = {	1, 0, NO_CHANGE, 2, 3};int encoder_create(XVID_ENC_PARAM * pParam){	Encoder *pEnc;	uint32_t i;	pParam->handle = NULL;	ENC_CHECK(pParam);	ENC_CHECK(pParam->width > 0 && pParam->width <= 1920);	ENC_CHECK(pParam->height > 0 && pParam->height <= 1280);	ENC_CHECK(!(pParam->width % 2));	ENC_CHECK(!(pParam->height % 2));	if (pParam->fincr <= 0 || pParam->fbase <= 0)	{		pParam->fincr = 1;		pParam->fbase = 25;	}	// simplify the "fincr/fbase" fraction	// (neccessary, since windows supplies us with huge numbers)	if (pParam->dont_simplify_fincr == 0) {	  i = pParam->fincr;	  while (i > 1)	    {	      if (pParam->fincr % i == 0 && pParam->fbase % i == 0)		{		  pParam->fincr /= i;		  pParam->fbase /= i;		  i = pParam->fincr;		  continue;		}	      i--;	    }	}	if (pParam->fbase > 65535)	{		float div = (float)pParam->fbase / 65535;		pParam->fbase = (int)(pParam->fbase / div);		pParam->fincr = (int)(pParam->fincr / div);	}	if (pParam->bitrate <= 0)		pParam->bitrate = 900000;	if (pParam->rc_buffersize <= 0)		pParam->rc_buffersize = 16;	if ((pParam->min_quantizer <= 0) || (pParam->min_quantizer > 31))		pParam->min_quantizer = 1;	if ((pParam->max_quantizer <= 0) || (pParam->max_quantizer > 31))		pParam->max_quantizer = 31;	if (pParam->max_key_interval == 0)		/* 1 keyframe each 10 seconds */ 		pParam->max_key_interval = 10 * pParam->fincr / pParam->fbase;						if (pParam->max_quantizer < pParam->min_quantizer)		pParam->max_quantizer = pParam->min_quantizer;	if ((pEnc = (Encoder *) xvid_malloc(sizeof(Encoder), CACHE_LINE)) == NULL)		return XVID_ERR_MEMORY;	/* Fill members of Encoder structure */	pEnc->mbParam.width = pParam->width;	pEnc->mbParam.height = pParam->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;#ifdef MPEG4IP	pEnc->mbParam.fincr = pParam->fincr;	pEnc->mbParam.fbase = pParam->fbase;	pEnc->mbParam.time_inc_bits = 1;	while (pParam->fbase > (1 << pEnc->mbParam.time_inc_bits)) {		pEnc->mbParam.time_inc_bits++;	}#endif	pEnc->sStat.fMvPrevSigma = -1;	/* Fill rate control parameters */	pEnc->mbParam.quant = 4;	pEnc->bitrate = pParam->bitrate;	pEnc->iFrameNum = 0;	pEnc->iMaxKeyInterval = pParam->max_key_interval;	/* try to allocate memory */	pEnc->sCurrent.y	=	pEnc->sCurrent.u	=	pEnc->sCurrent.v	= NULL;	pEnc->sReference.y	=	pEnc->sReference.u	=	pEnc->sReference.v	= NULL;	pEnc->vInterH.y		=	pEnc->vInterH.u		=	pEnc->vInterH.v		= NULL;	pEnc->vInterV.y		=	pEnc->vInterV.u		=	pEnc->vInterV.v		= NULL;	pEnc->vInterVf.y	=	pEnc->vInterVf.u	=	pEnc->vInterVf.v	= NULL;	pEnc->vInterHV.y	=	pEnc->vInterHV.u	=	pEnc->vInterHV.v	= NULL;	pEnc->vInterHVf.y	=	pEnc->vInterHVf.u	=	pEnc->vInterHVf.v	= NULL;	pEnc->pMBs = NULL;	if (image_create(&pEnc->sCurrent, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height) < 0 ||		image_create(&pEnc->sReference, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height) < 0 ||		image_create(&pEnc->vInterH, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height) < 0 ||		image_create(&pEnc->vInterV, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height) < 0 ||		image_create(&pEnc->vInterVf, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height) < 0 ||		image_create(&pEnc->vInterHV, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height) < 0 ||		image_create(&pEnc->vInterHVf, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height) < 0 ||#ifdef _DEBUG		image_create(&pEnc->sOriginal, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height) < 0 ||#endif		(pEnc->pMBs = xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width * pEnc->mbParam.mb_height, CACHE_LINE)) == NULL)	{		image_destroy(&pEnc->sCurrent, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height);		image_destroy(&pEnc->sReference, 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->vInterVf, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height);		image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height);		image_destroy(&pEnc->vInterHVf, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height);#ifdef _DEBUG		image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height);#endif		if (pEnc)		{			xvid_free(pEnc);		}		return XVID_ERR_MEMORY;	}	// init macroblock array	for (i = 0; i < pEnc->mbParam.mb_width * pEnc->mbParam.mb_height; i++)	{		pEnc->pMBs[i].dquant = NO_CHANGE;	}	pParam->handle = (void *)pEnc;	if (pParam->bitrate)	{		RateControlInit(pParam->bitrate, pParam->rc_buffersize, pParam->fbase * 1000 / pParam->fincr,				pParam->max_quantizer, pParam->min_quantizer);	}	init_timer();	return XVID_ERR_OK;}int encoder_destroy(Encoder * pEnc){	ENC_CHECK(pEnc);	ENC_CHECK(pEnc->sCurrent.y);	ENC_CHECK(pEnc->sReference.y);	xvid_free(pEnc->pMBs);	image_destroy(&pEnc->sCurrent, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height);	image_destroy(&pEnc->sReference, 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->vInterVf, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height);	image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height);	image_destroy(&pEnc->vInterHVf, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height);#ifdef _DEBUG		image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height);#endif	xvid_free(pEnc);	return XVID_ERR_OK;}int encoder_encode(Encoder * pEnc, XVID_ENC_FRAME * pFrame, XVID_ENC_STATS * pResult){	uint16_t x, y;	Bitstream bs;	uint32_t bits;	uint16_t write_vol_header = 0;#ifdef _DEBUG	float psnr;	uint8_t temp[100];#endif	start_global_timer();	ENC_CHECK(pEnc);	ENC_CHECK(pFrame);	ENC_CHECK(pFrame->bitstream);#ifndef MPEG4IP	ENC_CHECK(pFrame->image);#endif	pEnc->mbParam.global_flags = pFrame->general;	pEnc->mbParam.motion_flags = pFrame->motion;	pEnc->mbParam.hint = &pFrame->hint;	start_timer();#ifdef MPEG4IP	if (pFrame->image == NULL 	  && pFrame->colorspace == XVID_CSP_I420) {		ENC_CHECK(pFrame->image_y);		ENC_CHECK(pFrame->image_u);		ENC_CHECK(pFrame->image_v);		ENC_CHECK(pFrame->stride >= pEnc->mbParam.width);		if (yuv_input(&pEnc->sCurrent, 		  pEnc->mbParam.width, 		  pEnc->mbParam.height,		  pEnc->mbParam.edged_width, 		  pFrame->image_y, pFrame->image_u, pFrame->image_v,		  pFrame->stride,		  pFrame->colorspace)) {			return XVID_ERR_FORMAT;		}	} else {#endif	if (image_input(&pEnc->sCurrent, pEnc->mbParam.width, pEnc->mbParam.height,		pEnc->mbParam.edged_width, pFrame->image, pFrame->colorspace))	{		return XVID_ERR_FORMAT;	}#ifdef MPEG4IP	}#endif	stop_conv_timer();	EMMS();#ifdef _DEBUG	image_copy(&pEnc->sOriginal, &pEnc->sCurrent, pEnc->mbParam.edged_width, pEnc->mbParam.height);#endif	BitstreamInit(&bs, pFrame->bitstream, 0);	if (pFrame->quant == 0)	{		pEnc->mbParam.quant = RateControlGetQ(0);	}	else	{		pEnc->mbParam.quant = pFrame->quant;	}	if ((pEnc->mbParam.global_flags & XVID_LUMIMASKING) > 0)	{		int * temp_dquants = (int *) xvid_malloc(pEnc->mbParam.mb_width * pEnc->mbParam.mb_height * sizeof(int), CACHE_LINE);				pEnc->mbParam.quant = adaptive_quantization(pEnc->sCurrent.y,							    pEnc->mbParam.width,							    temp_dquants,							    pEnc->mbParam.quant,							    pEnc->mbParam.quant,							    2*pEnc->mbParam.quant,							    pEnc->mbParam.mb_width,							    pEnc->mbParam.mb_height);					for (y = 0; y < pEnc->mbParam.mb_height; y++)			for (x = 0; x < pEnc->mbParam.mb_width; x++)			{				MACROBLOCK *pMB = &pEnc->pMBs[x + y * pEnc->mbParam.mb_width];				pMB->dquant = iDQtab[(temp_dquants[y * pEnc->mbParam.mb_width + x] + 2)];			}		xvid_free(temp_dquants);	}	if(pEnc->mbParam.global_flags & XVID_H263QUANT) {		if(pEnc->mbParam.quant_type != H263_QUANT)			write_vol_header = 1;		pEnc->mbParam.quant_type = H263_QUANT;	}	else if(pEnc->mbParam.global_flags & XVID_MPEGQUANT) {		int ret1, ret2;		ret1 = ret2 = 0;		if(pEnc->mbParam.quant_type != MPEG4_QUANT)			write_vol_header = 1;				pEnc->mbParam.quant_type = MPEG4_QUANT;				if ((pEnc->mbParam.global_flags & XVID_CUSTOM_QMATRIX) > 0) {			if(pFrame->quant_intra_matrix != NULL)				ret1 = set_intra_matrix(pFrame->quant_intra_matrix);			if(pFrame->quant_inter_matrix != NULL)				ret2 = set_inter_matrix(pFrame->quant_inter_matrix);		}		else {			ret1 = set_intra_matrix(get_default_intra_matrix());			ret2 = set_inter_matrix(get_default_inter_matrix());		}		if(write_vol_header == 0)			write_vol_header = ret1 | ret2;	}#ifdef MPEG4IP	if (pEnc->iFrameNum == 0 && (pEnc->mbParam.global_flags & XVID_SHORT_HEADERS) == 0) {		BitstreamWriteVoshHeader(&bs);		write_vol_header = 1;	}#endif	if (pFrame->intra < 0)	{		if ((pEnc->iFrameNum == 0) || ((pEnc->iMaxKeyInterval > 0) 					       && (pEnc->iFrameNum >= pEnc->iMaxKeyInterval)))#ifdef MPEG4IP			pFrame->intra = FrameCodeI(pEnc, &bs, &bits, write_vol_header);#else			pFrame->intra = FrameCodeI(pEnc, &bs, &bits);#endif		else			pFrame->intra = FrameCodeP(pEnc, &bs, &bits, 0, write_vol_header);	}	else	{		if (pFrame->intra == 1)#ifdef MPEG4IP			pFrame->intra = FrameCodeI(pEnc, &bs, &bits, write_vol_header);#else			pFrame->intra = FrameCodeI(pEnc, &bs, &bits);#endif		else			pFrame->intra = FrameCodeP(pEnc, &bs, &bits, 1, write_vol_header);	}	BitstreamPutBits(&bs, 0xFFFF, 16);	BitstreamPutBits(&bs, 0xFFFF, 16);	BitstreamPad(&bs);	pFrame->length = BitstreamLength(&bs);	if (pResult)	{		pResult->quant = pEnc->mbParam.quant;		pResult->hlength = pFrame->length - (pEnc->sStat.iTextBits / 8);		pResult->kblks = pEnc->sStat.kblks;		pResult->mblks = pEnc->sStat.mblks;		pResult->ublks = pEnc->sStat.ublks;#ifdef MPEG4IP		pResult->image_y = pEnc->sCurrent.y;		pResult->image_u = pEnc->sCurrent.u;		pResult->image_v = pEnc->sCurrent.v;		pResult->stride_y = pEnc->mbParam.edged_width;		pResult->stride_uv = pResult->stride_y / 2;#endif	}   	EMMS();	if (pFrame->quant == 0)	{		RateControlUpdate(pEnc->mbParam.quant, pFrame->length, pFrame->intra);	}#ifdef _DEBUG	psnr = image_psnr(&pEnc->sOriginal, &pEnc->sCurrent, pEnc->mbParam.edged_width,				pEnc->mbParam.width, pEnc->mbParam.height);	sprintf(temp, "PSNR: %f\n", psnr);	DEBUG(temp);#endif	pEnc->iFrameNum++;	image_swap(&pEnc->sCurrent, &pEnc->sReference);		stop_global_timer();	write_timer();	return XVID_ERR_OK;}static __inline void CodeIntraMB(Encoder *pEnc, MACROBLOCK *pMB) {	pMB->mode = MODE_INTRA;	if ((pEnc->mbParam.global_flags & XVID_LUMIMASKING) > 0) {		if(pMB->dquant != NO_CHANGE)		{			pMB->mode = MODE_INTRA_Q;			pEnc->mbParam.quant += DQtab[pMB->dquant];					if (pEnc->mbParam.quant > 31) pEnc->mbParam.quant = 31;			if (pEnc->mbParam.quant < 1) pEnc->mbParam.quant = 1;		}	}	pMB->quant = pEnc->mbParam.quant;}#define FCODEBITS	3#define MODEBITS	5staticvoid HintedMESet(Encoder * pEnc, int * intra){	HINTINFO * hint;	Bitstream bs;	int length, high;	uint32_t x, y;	hint = pEnc->mbParam.hint;	if (hint->rawhints)	{		*intra = hint->mvhint.intra;	}	else	{		BitstreamInit(&bs, hint->hintstream, hint->hintlength);		*intra = BitstreamGetBit(&bs);	}

⌨️ 快捷键说明

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