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

📄 encoder.c

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 C
📖 第 1 页 / 共 5 页
字号:
		data.stats.hlength   = frame->length - (frame->sStat.iTextBits / 8);
		data.stats.kblks     = frame->sStat.kblks;
		data.stats.mblks     = frame->sStat.mblks;
		data.stats.ublks     = frame->sStat.ublks;
		data.stats.sse_y     = data.sse_y;
		data.stats.sse_u     = data.sse_u;
		data.stats.sse_v     = data.sse_v;

		if (stats)
			*stats = data.stats;
	}

	/* call plugins */
	for (i=0; i<(unsigned int)pEnc->num_plugins;i++) {
		emms();
		if (pEnc->plugins[i].func) {
			if (pEnc->plugins[i].func(pEnc->plugins[i].param, opt, &data, NULL) < 0) {
				continue;
			}
		}
	}
	emms();

	/* copy modified values back into frame*/
	if (opt == XVID_PLG_BEFORE) {
		*type = data.type;
		*quant = data.quant > 0 ? data.quant : 2;   /* default */

		frame->vol_flags = data.vol_flags;
		frame->vop_flags = data.vop_flags;
		frame->motion_flags = data.motion_flags;
	
	} else if (opt == XVID_PLG_FRAME) {

		if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) {
			for (j=0; j<pEnc->mbParam.mb_height; j++)
			for (i=0; i<pEnc->mbParam.mb_width; i++) {
				frame->mbs[j*pEnc->mbParam.mb_width + i].dquant = data.dquant[j*data.mb_width + i];
			}
		} else {
			for (j=0; j<pEnc->mbParam.mb_height; j++)
			for (i=0; i<pEnc->mbParam.mb_width; i++) {
				frame->mbs[j*pEnc->mbParam.mb_width + i].dquant = 0;
			}
		}

		if (pEnc->mbParam.plugin_flags & XVID_REQLAMBDA) {
			for (j = 0; j < pEnc->mbParam.mb_height; j++)
				for (i = 0; i < pEnc->mbParam.mb_width; i++)
					for (k = 0; k < 6; k++) {
						frame->mbs[j*pEnc->mbParam.mb_width + i].lambda[k] = 
							(int) ((float)(1<<LAMBDA_EXP) * data.lambda[6 * (j * data.mb_width + i) + k]);
			}
		} else {
			for (j = 0; j<pEnc->mbParam.mb_height; j++)
				for (i = 0; i<pEnc->mbParam.mb_width; i++)
					for (k = 0; k < 6; k++) {
						frame->mbs[j*pEnc->mbParam.mb_width + i].lambda[k] = 1<<LAMBDA_EXP;
			}
		}


		frame->mbs[0].quant = data.quant; /* FRAME will not affect the quant in stats */
	}


}


static __inline void inc_frame_num(Encoder * pEnc)
{
	pEnc->current->frame_num = pEnc->m_framenum;
	pEnc->current->stamp = pEnc->mbParam.m_stamp;	/* first frame is zero */

	pEnc->mbParam.m_stamp += pEnc->current->fincr;
	pEnc->m_framenum++;	/* debug ticker */
}

static __inline void dec_frame_num(Encoder * pEnc)
{
	pEnc->mbParam.m_stamp -= pEnc->mbParam.fincr;
	pEnc->m_framenum--;	/* debug ticker */
}

static __inline void 
MBSetDquant(MACROBLOCK * pMB, int x, int y, MBParam * mbParam)
{
	if (pMB->cbp == 0) {
		/* we want to code dquant but the quantizer value will not be used yet
			let's find out if we can postpone dquant to next MB
		*/	
		if (x == mbParam->mb_width-1 && y == mbParam->mb_height-1) {
			pMB->dquant = 0; /* it's the last MB of all, the easiest case */
			return;
		} else {
			MACROBLOCK * next = pMB + 1;
			const MACROBLOCK * prev = pMB - 1;
			if (next->mode != MODE_INTER4V && next->mode != MODE_NOT_CODED)
				/* mode allows dquant change in the future */
				if (abs(next->quant - prev->quant) <= 2) {
					/* quant change is not out of range */
					pMB->quant = prev->quant;
					pMB->dquant = 0;
					next->dquant = next->quant - prev->quant;
					return;
				}
		}		
	}
	/* couldn't skip this dquant */
	pMB->mode = MODE_INTER_Q;
}
			


static __inline void
set_timecodes(FRAMEINFO* pCur,FRAMEINFO *pRef, int32_t time_base)
{

	pCur->ticks = (int32_t)pCur->stamp % time_base;
	pCur->seconds =  ((int32_t)pCur->stamp / time_base)	- ((int32_t)pRef->stamp / time_base) ;

#if 0 	/* HEAVY DEBUG OUTPUT */
	fprintf(stderr,"WriteVop:   %d - %d \n",
			((int32_t)pCur->stamp / time_base), ((int32_t)pRef->stamp / time_base));
	fprintf(stderr,"set_timecodes: VOP %1d   stamp=%lld ref_stamp=%lld  base=%d\n",
			pCur->coding_type, pCur->stamp, pRef->stamp, time_base);
	fprintf(stderr,"set_timecodes: VOP %1d   seconds=%d   ticks=%d   (ref-sec=%d  ref-tick=%d)\n",
			pCur->coding_type, pCur->seconds, pCur->ticks, pRef->seconds, pRef->ticks);
#endif
}

static void
simplify_par(int *par_width, int *par_height)
{

	int _par_width  = (!*par_width)  ? 1 : (*par_width<0)  ? -*par_width:  *par_width;
	int _par_height = (!*par_height) ? 1 : (*par_height<0) ? -*par_height: *par_height;
	int divisor = gcd(_par_width, _par_height);

	_par_width  /= divisor;
	_par_height /= divisor;

	/* 2^8 precision maximum */
	if (_par_width>255 || _par_height>255) {
		float div;
		emms();
		if (_par_width>_par_height)
			div = (float)_par_width/255;
		else
			div = (float)_par_height/255;

		_par_width  = (int)((float)_par_width/div);
		_par_height = (int)((float)_par_height/div);
	}

	*par_width = _par_width;
	*par_height = _par_height;

	return;
}


/*****************************************************************************
 * IPB frame encoder entry point
 *
 * Returned values :
 *	- >0			   - output bytes
 *	- 0				- no output
 *	- XVID_ERR_VERSION - wrong version passed to core
 *	- XVID_ERR_END	 - End of stream reached before end of coding
 *	- XVID_ERR_FORMAT  - the image subsystem reported the image had a wrong
 *						 format
 ****************************************************************************/


int
enc_encode(Encoder * pEnc,
			   xvid_enc_frame_t * xFrame,
			   xvid_enc_stats_t * stats)
{
	xvid_enc_frame_t * frame;
	int type;
	Bitstream bs;

	if (XVID_VERSION_MAJOR(xFrame->version) != 1 || (stats && XVID_VERSION_MAJOR(stats->version) != 1))	/* v1.x.x */
		return XVID_ERR_VERSION;

	xFrame->out_flags = 0;

	start_global_timer();
	BitstreamInit(&bs, xFrame->bitstream, 0);


	/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	 * enqueue image to the encoding-queue
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	if (xFrame->input.csp != XVID_CSP_NULL)
	{
		QUEUEINFO * q = &pEnc->queue[pEnc->queue_tail];

		start_timer();
		if (image_input
			(&q->image, pEnc->mbParam.width, pEnc->mbParam.height,
			pEnc->mbParam.edged_width, (uint8_t**)xFrame->input.plane, xFrame->input.stride,
			xFrame->input.csp, xFrame->vol_flags & XVID_VOL_INTERLACING))
		{
			emms();
			return XVID_ERR_FORMAT;
		}
		stop_conv_timer();

		if ((xFrame->vop_flags & XVID_VOP_CHROMAOPT)) {
			image_chroma_optimize(&q->image,
				pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width);
		}

		q->frame = *xFrame;

		if (xFrame->quant_intra_matrix)
		{
			memcpy(q->quant_intra_matrix, xFrame->quant_intra_matrix, 64*sizeof(unsigned char));
			q->frame.quant_intra_matrix = q->quant_intra_matrix;
		}

		if (xFrame->quant_inter_matrix)
		{
			memcpy(q->quant_inter_matrix, xFrame->quant_inter_matrix, 64*sizeof(unsigned char));
			q->frame.quant_inter_matrix = q->quant_inter_matrix;
		}

		pEnc->queue_tail = (pEnc->queue_tail + 1) % (pEnc->mbParam.max_bframes+1);
		pEnc->queue_size++;
	}


	/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	 * bframe flush code
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

repeat:

	if (pEnc->flush_bframes)
	{
		if (pEnc->bframenum_head < pEnc->bframenum_tail) {

			DPRINTF(XVID_DEBUG_DEBUG,"*** BFRAME (flush) bf: head=%i tail=%i   queue: head=%i tail=%i size=%i\n",
					pEnc->bframenum_head, pEnc->bframenum_tail,
					pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);

			if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
				image_copy(&pEnc->sOriginal2, &pEnc->bframes[pEnc->bframenum_head]->image,
						   pEnc->mbParam.edged_width, pEnc->mbParam.height);
			}

			FrameCodeB(pEnc, pEnc->bframes[pEnc->bframenum_head], &bs);
			call_plugins(pEnc, pEnc->bframes[pEnc->bframenum_head], &pEnc->sOriginal2, XVID_PLG_AFTER, NULL, NULL, stats);
			pEnc->bframenum_head++;

			goto done;
		}

		/* write an empty marker to the bitstream.

		   for divx5 decoder compatibility, this marker must consist
		   of a not-coded p-vop, with a time_base of zero, and time_increment
		   indentical to the future-referece frame.
		*/

		if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED && pEnc->bframenum_tail > 0)) {
			int tmp;
			int bits;

			DPRINTF(XVID_DEBUG_DEBUG,"*** EMPTY bf: head=%i tail=%i   queue: head=%i tail=%i size=%i\n",
				pEnc->bframenum_head, pEnc->bframenum_tail,
				pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);

			bits = BitstreamPos(&bs);

			tmp = pEnc->current->seconds;
			pEnc->current->seconds = 0; /* force time_base = 0 */

			BitstreamWriteVopHeader(&bs, &pEnc->mbParam, pEnc->current, 0, pEnc->current->quant);
			BitstreamPad(&bs);
			pEnc->current->seconds = tmp;

			/* add the not-coded length to the reference frame size */
			pEnc->current->length += (BitstreamPos(&bs) - bits) / 8;
			call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats);

			/* flush complete: reset counters */
			pEnc->flush_bframes = 0;
			pEnc->bframenum_head = pEnc->bframenum_tail = 0;
			goto done;

		}

		/* flush complete: reset counters */
		pEnc->flush_bframes = 0;
		pEnc->bframenum_head = pEnc->bframenum_tail = 0;
	}

	/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	 * dequeue frame from the encoding queue
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	if (pEnc->queue_size == 0)		/* empty */
	{
		if (xFrame->input.csp == XVID_CSP_NULL)	/* no futher input */
		{

			DPRINTF(XVID_DEBUG_DEBUG,"*** FINISH bf: head=%i tail=%i   queue: head=%i tail=%i size=%i\n",
				pEnc->bframenum_head, pEnc->bframenum_tail,
				pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);

			if (!(pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->mbParam.max_bframes > 0) {
				call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats);
			}

			/* if the very last frame is to be b-vop, we must change it to a p-vop */
			if (pEnc->bframenum_tail > 0) {

				SWAP(FRAMEINFO*, pEnc->current, pEnc->reference);
				pEnc->bframenum_tail--;
				SWAP(FRAMEINFO*, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]);

				/* convert B-VOP to P-VOP */
				pEnc->current->quant  = 100*pEnc->current->quant - pEnc->mbParam.bquant_offset;
				pEnc->current->quant += pEnc->mbParam.bquant_ratio - 1; /* to avoid rouding issues */
				pEnc->current->quant /= pEnc->mbParam.bquant_ratio;

				if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
					image_copy(&pEnc->sOriginal, &pEnc->current->image,
						   pEnc->mbParam.edged_width, pEnc->mbParam.height);
				}

				DPRINTF(XVID_DEBUG_DEBUG,"*** PFRAME bf: head=%i tail=%i   queue: head=%i tail=%i size=%i\n",
				pEnc->bframenum_head, pEnc->bframenum_tail,
				pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);
				pEnc->mbParam.frame_drop_ratio = -1; /* it must be a coded vop */

				FrameCodeP(pEnc, &bs);


				if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->bframenum_tail==0) {
					call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats);
				}else{
					pEnc->flush_bframes = 1;
					goto done;
				}
			}
			DPRINTF(XVID_DEBUG_DEBUG, "*** END\n");

			emms();
			return XVID_ERR_END;	/* end of stream reached */
		}
		goto done;	/* nothing to encode yet; encoder lag */
	}

	/* the current FRAME becomes the reference */
	SWAP(FRAMEINFO*, pEnc->current, pEnc->reference);

	/* remove frame from encoding-queue (head), and move it into the current */
	image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head].image);
	frame = &pEnc->queue[pEnc->queue_head].frame;
	pEnc->queue_head = (pEnc->queue_head + 1) % (pEnc->mbParam.max_bframes+1);
	pEnc->queue_size--;


	/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	 * init pEnc->current fields
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	pEnc->current->fincr = pEnc->mbParam.fincr>0 ? pEnc->mbParam.fincr : frame->fincr;
	inc_frame_num(pEnc);
	pEnc->current->vol_flags = frame->vol_flags;
	pEnc->current->vop_flags = frame->vop_flags;
	pEnc->current->motion_flags = frame->motion;
	pEnc->current->fcode = pEnc->mbParam.m_fcode;
	pEnc->current->bcode = pEnc->mbParam.m_fcode;


	if ((xFrame->vop_flags & XVID_VOP_CHROMAOPT)) {
		image_chroma_optimize(&pEnc->current->image,
			pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width);
	}

	/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	 * frame type & quant selection
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	type = frame->type;
	pEnc->current->quant = frame->quant;

	call_plugins(pEnc, pEnc->current, NULL, XVID_PLG_BEFORE, &type, (int*)&pEnc->current->quant, stats);

	if (type > 0){ 	/* XVID_TYPE_?VOP */
		type = type2coding(type);	/* convert XVID_TYPE_?VOP to bitstream coding type */
	} else{		/* XVID_TYPE_AUTO */
		if (pEnc->iFrameNum == 0 || (pEnc->mbParam.iMaxKeyInterval > 0 && pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval)){
			pEnc->iFrameNum = 0;
			type = I_VOP;
		}else{
			type = MEanalysis(&pEnc->reference->image, pEnc->current,
							  &pEnc->mbParam, pEnc->mbParam.iMaxKeyInterval,
							  pEnc->iFrameNum, pEnc->bframenum_tail, xFrame->bframe_threshold,
							  (pEnc->bframes) ? pEnc->bframes[pEnc->bframenum_head]->mbs: NULL);
		}
	}

	if (type != I_VOP) 
		pEnc->current->vol_flags = pEnc->mbParam.vol_flags; /* don't allow VOL changes here */

	/* bframes buffer overflow check */
	if (type == B_VOP && pEnc->bframenum_tail >= pEnc->mbParam.max_bframes) {
		type = P_VOP;
	}

	pEnc->iFrameNum++;

⌨️ 快捷键说明

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