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

📄 encoder.c

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 C
📖 第 1 页 / 共 5 页
字号:

	if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) {
		image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 5,
			"%d  st:%lld  if:%d", pEnc->current->frame_num, pEnc->current->stamp, pEnc->iFrameNum);
	}

	/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	 * encode this frame as a b-vop
	 * (we dont encode here, rather we store the frame in the bframes queue, to be encoded later)
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
	if (type == B_VOP) {
		if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) {
			image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "BVOP");
		}

		if (frame->quant < 1) {
			pEnc->current->quant = ((((pEnc->reference->quant + pEnc->current->quant) *
				pEnc->mbParam.bquant_ratio) / 2) + pEnc->mbParam.bquant_offset)/100;

		} else {
			pEnc->current->quant = frame->quant;
		}

		if (pEnc->current->quant < 1)
			pEnc->current->quant = 1;
		else if (pEnc->current->quant > 31)
			pEnc->current->quant = 31;

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

		/* store frame into bframe buffer & swap ref back to current */
		SWAP(FRAMEINFO*, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]);
		SWAP(FRAMEINFO*, pEnc->current, pEnc->reference);

		pEnc->bframenum_tail++;

		goto repeat;
	}


		DPRINTF(XVID_DEBUG_DEBUG,"*** XXXXXX 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);

	/* for unpacked bframes, output the stats for the last encoded frame */
	if (!(pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->mbParam.max_bframes > 0)
	{
		if (pEnc->current->stamp > 0) {
			call_plugins(pEnc, pEnc->reference, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats);
		}
        else if (stats) {
            stats->type = XVID_TYPE_NOTHING;
        }
	}

	/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	 * closed-gop
	 * if the frame prior to an iframe is scheduled as a bframe, we must change it to a pframe
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	if (type == I_VOP && (pEnc->mbParam.global_flags & XVID_GLOBAL_CLOSED_GOP) && pEnc->bframenum_tail > 0) {

		/* place this frame back on the encoding-queue (head) */
		/* we will deal with it next time */
		dec_frame_num(pEnc);
		pEnc->iFrameNum--;

		pEnc->queue_head = (pEnc->queue_head + (pEnc->mbParam.max_bframes+1) - 1) % (pEnc->mbParam.max_bframes+1);
		pEnc->queue_size++;
		image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head].image);

		/* grab the last frame from the bframe-queue */

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

		if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) {
			image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "CLOSED GOP BVOP->PVOP");
		}

		/* convert B-VOP quant 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;
		type = P_VOP;
	}


	/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	 * encode this frame as an i-vop
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	if (type == I_VOP) {

		DPRINTF(XVID_DEBUG_DEBUG,"*** IFRAME 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->current->vop_flags & XVID_VOP_DEBUG)) {
			image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "IVOP");
		}

		pEnc->iFrameNum = 1;

		/* ---- update vol flags at IVOP ----------- */
		pEnc->mbParam.vol_flags = pEnc->current->vol_flags;

		/* Aspect ratio */
		switch(frame->par) {
		case XVID_PAR_11_VGA:
		case XVID_PAR_43_PAL:
		case XVID_PAR_43_NTSC:
		case XVID_PAR_169_PAL:
		case XVID_PAR_169_NTSC:
		case XVID_PAR_EXT:
			pEnc->mbParam.par = frame->par;
			break;
		default:
			pEnc->mbParam.par = XVID_PAR_11_VGA;
			break;
		}

		/* For extended PAR only, we try to sanityse/simplify par values */
		if (pEnc->mbParam.par == XVID_PAR_EXT) {
			pEnc->mbParam.par_width  = frame->par_width;
			pEnc->mbParam.par_height = frame->par_height;
			simplify_par(&pEnc->mbParam.par_width, &pEnc->mbParam.par_height);
		}

		if ((pEnc->mbParam.vol_flags & XVID_VOL_MPEGQUANT)) {
			if (frame->quant_intra_matrix != NULL)
				set_intra_matrix(pEnc->mbParam.mpeg_quant_matrices, frame->quant_intra_matrix);
			if (frame->quant_inter_matrix != NULL)
				set_inter_matrix(pEnc->mbParam.mpeg_quant_matrices, frame->quant_inter_matrix);
		}

		/* prevent vol/vop misuse */

		if (!(pEnc->current->vol_flags & XVID_VOL_INTERLACING))
			pEnc->current->vop_flags &= ~(XVID_VOP_TOPFIELDFIRST|XVID_VOP_ALTERNATESCAN);

		/* ^^^------------------------ */

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

		FrameCodeI(pEnc, &bs);
		xFrame->out_flags |= XVID_KEYFRAME;

	/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	 * encode this frame as an p-vop
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	} else { /* (type == P_VOP || type == S_VOP) */

		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);

		if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) {
			image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "PVOP");
		}

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

		if ( FrameCodeP(pEnc, &bs) == 0 ) {
			/* N-VOP, we mustn't code b-frames yet */
			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);
			goto done;
		}
	}


	/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	 * on next enc_encode call we must flush bframes
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

/*done_flush:*/

	pEnc->flush_bframes = 1;

	/* packed & queued_bframes: dont bother outputting stats here, we do so after the flush */
	if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->bframenum_tail > 0) {
		goto repeat;
	}

	/* packed or no-bframes or no-bframes-queued: output stats */
	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);
	}

	/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	 * done; return number of bytes consumed
	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

done:

	stop_global_timer();
	write_timer();

	emms();
	return BitstreamLength(&bs);
}


static void SetMacroblockQuants(MBParam * const pParam, FRAMEINFO * frame)
{
	unsigned int i;
	MACROBLOCK * pMB = frame->mbs;
	int quant = frame->mbs[0].quant; /* set by XVID_PLG_FRAME */
	if (quant > 31)
		frame->quant = quant = 31;
	else if (quant < 1)
		frame->quant = quant = 1;

	for (i = 0; i < pParam->mb_height * pParam->mb_width; i++) {
		quant += pMB->dquant;
		if (quant > 31)
			quant = 31;
		else if (quant < 1)
			quant = 1;
		pMB->quant = quant;
		pMB++;
	}
}


static __inline void
CodeIntraMB(Encoder * pEnc,
			MACROBLOCK * pMB)
{

	pMB->mode = MODE_INTRA;

	/* zero mv statistics */
	pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
	pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
	pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;
	pMB->sad16 = 0;

	if (pMB->dquant != 0) {
		pMB->mode = MODE_INTRA_Q;
	}
}



static int
FrameCodeI(Encoder * pEnc,
		   Bitstream * bs)
{
	int bits = BitstreamPos(bs);
	int mb_width = pEnc->mbParam.mb_width;
	int mb_height = pEnc->mbParam.mb_height;

	DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE);
	DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE);

	uint16_t x, y;

	pEnc->mbParam.m_rounding_type = 1;
	pEnc->current->rounding_type = pEnc->mbParam.m_rounding_type;
	pEnc->current->coding_type = I_VOP;

	call_plugins(pEnc, pEnc->current, NULL, XVID_PLG_FRAME, NULL, NULL, NULL);

	SetMacroblockQuants(&pEnc->mbParam, pEnc->current);

	BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current);

	set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase);

	BitstreamPad(bs);

	BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 1, pEnc->current->mbs[0].quant);

	pEnc->current->sStat.iTextBits = 0;
	pEnc->current->sStat.iMVBits = 0;
	pEnc->current->sStat.kblks = mb_width * mb_height;
	pEnc->current->sStat.mblks = pEnc->current->sStat.ublks = 0;

	for (y = 0; y < mb_height; y++)
		for (x = 0; x < mb_width; x++) {
			MACROBLOCK *pMB =
				&pEnc->current->mbs[x + y * pEnc->mbParam.mb_width];

			CodeIntraMB(pEnc, pMB);

			MBTransQuantIntra(&pEnc->mbParam, pEnc->current, pMB, x, y,
							  dct_codes, qcoeff);

			start_timer();
			MBPrediction(pEnc->current, x, y, pEnc->mbParam.mb_width, qcoeff);
			stop_prediction_timer();

			start_timer();
			MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat);
			stop_coding_timer();
		}

	emms();

	BitstreamPadAlways(bs); /* next_start_code() at the end of VideoObjectPlane() */

	pEnc->current->length = (BitstreamPos(bs) - bits) / 8;

	pEnc->fMvPrevSigma = -1;
	pEnc->mbParam.m_fcode = 2;

	pEnc->current->is_edged = 0; /* not edged */
	pEnc->current->is_interpolated = -1; /* not interpolated (fake rounding -1) */

	return 1;					/* intra */
}

static __inline void
updateFcode(Statistics * sStat, Encoder * pEnc)
{
	float fSigma;
	int iSearchRange;

	if (sStat->iMvCount == 0)
		sStat->iMvCount = 1;

	fSigma = (float) sqrt((float) sStat->iMvSum / sStat->iMvCount);

	iSearchRange = 16 << pEnc->mbParam.m_fcode;

	if ((3.0 * fSigma > iSearchRange) && (pEnc->mbParam.m_fcode <= 5) )
		pEnc->mbParam.m_fcode++;

	else if ((5.0 * fSigma < iSearchRange)
			   && (4.0 * pEnc->fMvPrevSigma < iSearchRange)
			   && (pEnc->mbParam.m_fcode >= 2) )
		pEnc->mbParam.m_fcode--;

	pEnc->fMvPrevSigma = fSigma;
}

#define BFRAME_SKIP_THRESHHOLD 30

/* FrameCodeP also handles S(GMC)-VOPs */
static int
FrameCodeP(Encoder * pEnc,
		   Bitstream * bs)
{
	int bits = BitstreamPos(bs);

	DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE);
	DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE);

	int x, y, k;
	FRAMEINFO *const current = pEnc->current;
	FRAMEINFO *const reference = pEnc->reference;
	MBParam * const pParam = &pEnc->mbParam;
	int mb_width = pParam->mb_width;
	int mb_height = pParam->mb_height;
	int coded = 1;

	IMAGE *pRef = &reference->image;

	if (!reference->is_edged) {	
		start_timer();
		image_setedges(pRef, pParam->edged_width, pParam->edged_height,
					   pParam->width, pParam->height, 0);
		stop_edges_timer();
		reference->is_edged = 1;
	}

	pParam->m_rounding_type = 1 - pParam->m_rounding_type;
	current->rounding_type = pParam->m_rounding_type;
	current->fcode = pParam->m_fcode;

	if ((current->vop_flags & XVID_VOP_HALFPEL)) {
		if (reference->is_interpolated != current->rounding_type) {
			start_timer();
			image_interpolate(pRef->y, pEnc->vInterH.y, pEnc->vInterV.y,
							  pEnc->vInterHV.y, pParam->edged_width,
							  pParam->edged_height,
							  (pParam->vol_flags & XVID_VOL_QUARTERPEL),
							  current->rounding_type);
			stop_inter_timer();
			reference->is_interpolated = current->rounding_type;
		}
	}

	current->sStat.iTextBits = current->sStat.iMvSum = current->sStat.iMvCount =
		current->sStat.kblks = current->sStat.mblks = current->sStat.ublks = 
		current->sStat.iMVBits = 0;

	current->coding_type = P_VOP;

	call_plugins(pEnc, pEnc->current, NULL, XVID_PLG_FRAME, NULL, NULL, NULL);

	SetMacroblockQuants(&pEnc->mbParam, current);

	start_timer();
	if (current->vol_flags & XVID_VOL_GMC )	/* GMC only for S(GMC)-VOPs */
	{	int gmcval;
		current->warp = GlobalMotionEst( current->mbs, pParam, current, reference,
								 &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV);

		if (current->motion_flags & XVID_ME_GME_REFINE) {
			gmcval = GlobalMotionEstRefine(&current->warp,
										   current->mbs, pParam,
										   current, reference,
										   &current->image,
										   &reference->image,
										   &pEnc->vInterH,
										   &pEnc->vInterV,

⌨️ 快捷键说明

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