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

📄 rc.c

📁 DM642的mpeg4编码
💻 C
字号:
#include"rc.h"

static int CreatRateControl(Encoder* pEncoder, RCData* pRC)
{
	int i;

	pRC->BytesPerSecond = pEncoder->iBitsPerSecoder / 8;
    pRC->TargetFrameSize = pRC->BytesPerSecond / pEncoder->iFrameRate;
    pRC->DelayFactor = 16;
    pRC->AverTime = 100;
    pRC->buffer = 100;

    pRC->time = 0;
    pRC->TotalSize = 0;
    pRC->quant = 4;      

    for (i = 0; i < 31; i++)
    {
       pRC->ErrorQuant[i] = 0.0;
    }

    pRC->AvrageFrameSize = pRC->TargetFrameSize;
	pRC->VideoQuality = 2.0 / (double) pRC->quant;

    pRC->fq_error = 0;

	return (0);
}

static int DestroyRateControl(RCData* rc)
{
	free(rc);
	return (0);
}

static int BeforeRateControl(RCData* rc, DataStruct* pdata)
{	 
	int q = rc->quant;	
	if (q > 31)
	{
		q = 31;
	}
	else if (q < 2)
	{
		q = 2;
	}

	pdata->quant = q;		
	return 0;
}

static int AfterRateControl(RCData* rc, DataStruct* pData)
{
	long deviation;
	int rtn_quant;
	double overflow;
	double averaging_period;
	double reaction_delay_factor;
	double quality_scale;
	double base_quality;
	double target_quality;

	rc->time += (double) pData->fincr / pData->fbase;
	rc->TotalSize += pData->length;

	deviation = rc->TotalSize - rc->BytesPerSecond * rc->time;

	averaging_period = (double) rc->AverTime;

	rc->VideoQuality -= rc->VideoQuality / averaging_period;

	rc->VideoQuality +=	2.0 / (double) pData->quant / averaging_period;

	if (rc->VideoQuality < 0.1)
	{
		rc->VideoQuality = 0.1;
	}
	else if (rc->VideoQuality > 1.0)
	{
		rc->VideoQuality = 1.0;
	}

	if (pData->type != I_VOP) 
	{
		reaction_delay_factor = (double) rc->DelayFactor;
		rc->AvrageFrameSize -= rc->AvrageFrameSize / reaction_delay_factor;
		rc->AvrageFrameSize += pData->length / reaction_delay_factor;
	}

	if (pData->type == B_VOP)
	{
		return (0);
	}

	quality_scale =	rc->TargetFrameSize / rc->AvrageFrameSize * rc->TargetFrameSize / rc->AvrageFrameSize;

	base_quality = rc->VideoQuality;
	if (quality_scale >= 1.0) 
	{
		base_quality = 1.0 - (1.0 - base_quality) / quality_scale;
	} 
	else 
	{
		base_quality = 0.06452 + (base_quality - 0.06452) * quality_scale;
	}

	overflow = -((double) deviation / (double) rc->buffer);

	if (overflow > rc->TargetFrameSize)
	{
		overflow = rc->TargetFrameSize;
	}
	else if (overflow < -rc->TargetFrameSize)
	{
		overflow = -rc->TargetFrameSize;
	}

	target_quality = base_quality + (base_quality - 0.06452) * overflow / rc->TargetFrameSize;

	if (target_quality > 2.0)
	{
		target_quality = 2.0;
	}
	else if (target_quality < 0.06452)
	{
		target_quality = 0.06452;
	}

	rtn_quant = (int) (2.0 / target_quality);

	if (rtn_quant > 0 && rtn_quant < 31)
	{
		rc->ErrorQuant[rtn_quant - 1] += 2.0 / target_quality - rtn_quant;
		if (rc->ErrorQuant[rtn_quant - 1] >= 1.0) 
		{
			rc->ErrorQuant[rtn_quant - 1] -= 1.0;
			rtn_quant++;
			rc->quant++;
		}
	}

	if (rtn_quant > rc->quant + 1)
	{
		if (rtn_quant > rc->quant + 3)
		{
			if (rtn_quant > rc->quant + 5)
			{
				rtn_quant = rc->quant + 3;
			}
			else
			{
				rtn_quant = rc->quant + 2;
			}
		}
		else
		{
			rtn_quant = rc->quant + 1;
		}
	}
	else if (rtn_quant < rc->quant - 1) 
	{
		if (rtn_quant < rc->quant - 3)
		{
			if (rtn_quant < rc->quant - 5)
			{
				rtn_quant = rc->quant - 3;
			}
			else
			{
				rtn_quant = rc->quant - 2;
			}
		}
		else
		{
			rtn_quant = rc->quant - 1;
		}
	}

	rc->quant = rtn_quant;
	return (0);
}

static int RcCall(Encoder* pEncoder, RCData* pRC, int iFlag, void* param1, void* param2)
{
	switch (iFlag)
	{
	case FRAME :
		return 0;

	case CREATE:
		return CreatRateControl(pEncoder, pRC);

	case DESTROY:
		return DestroyRateControl(pRC);

	case BEFORE:
		return BeforeRateControl(pRC, (DataStruct*) param1);

	case AFTER:
		return AfterRateControl(pRC, (DataStruct*) param1);
	}

	return -1;
}

void Rcfunc(Encoder* pEncoder, FrameInfo* frame, RCData* pRC, int iFlag, short* iType, short* quant, EncoderState* pStatic)
{
    unsigned int i, j;
	DataStruct data;

	memset(&data, 0, sizeof(DataStruct));

    data.width = pEncoder->pVol->video_object_layer_width;
	data.height = pEncoder->pVol->video_object_layer_height;
	data.mb_width = pEncoder->pVol->video_object_layer_width/16;
	data.mb_height = pEncoder->pVol->video_object_layer_height/16;
	data.fincr = pEncoder->pVol->fixed_vop_time_increment;
	data.fbase = pEncoder->iFrameRate;

	for (i=0; i<3; i++)
	{
		data.MinQuant[i] = 2;
		data.MaxQuant[i] = 31;
	}

	data.frame_num = pEncoder->iFrameNo;

	if (pEncoder->iFrameNo == 0)
	{
       RcCall(pEncoder, pRC, CREATE, NULL, NULL);
	}

	if (iFlag == BEFORE)
	{
		data.type = *iType;
		data.quant = *quant;
	} 
	else if (iFlag == FRAME) 
	{
		data.type = frame->vop_coding_type;
		data.quant = frame->vop_quant;	
	} 
	else if (iFlag == AFTER)
	{ 

		data.type = frame->vop_coding_type;
		data.quant = frame->vop_quant;

		data.length = frame->length;
		data.IntraMbNum = frame->IntraMbNum;
		data.InterMbNum = frame->InterMbNum;
		data.SkipMbNum = frame->SkipMbNum;
	
		data.stats.type      = frame->vop_coding_type;
		data.stats.quant     = frame->vop_quant;
		data.stats.length    = frame->length;
		data.stats.hlength   = frame->length - (frame->iTextBits / 8);
		
		data.stats.IntraMbNum  = frame->IntraMbNum;
		data.stats.InterMbNum   = frame->InterMbNum;
		data.stats.SkipMbNum   = frame->SkipMbNum;
		data.stats.y     = data.y;
		data.stats.u     = data.u;
		data.stats.v     = data.v;
	
		if (pStatic)
		{
			*pStatic = data.stats;
		}
	}
	
	RcCall(pEncoder, pRC, iFlag, &data, 0);
	
	if (iFlag == BEFORE) 
	{
		*iType = data.type;
		*quant = data.quant > 0 ? data.quant : 2;   /* default */
	} 
	else if (iFlag == FRAME) 
	{		
		for (j = 0; j < (pEncoder->pVol->video_object_layer_height/16); j++)
		{
			for (i = 0; i < (pEncoder->pVol->video_object_layer_width/16); i++)
			{
				frame->pMB[j * (pEncoder->pVol->video_object_layer_width/16) + i].dquant = 0;
			}
		}	
		frame->pMB[0].quant = data.quant; 
	}

}

⌨️ 快捷键说明

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