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

📄 encoder.c

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 C
📖 第 1 页 / 共 5 页
字号:
										   &pEnc->vInterHV);
		} else {
			gmcval = globalSAD(&current->warp, pParam, current->mbs,
							   current,
							   &reference->image,
							   &current->image,
							   pEnc->vGMC.y);
		}

		gmcval += /*current->quant*/ 2 * (int)(pParam->mb_width*pParam->mb_height);

		/* 1st '3': 3 warpoints, 2nd '3': 16th pel res (2<<3) */
		generate_GMCparameters(	3, 3, &current->warp,
				pParam->width, pParam->height,
				&current->new_gmc_data);

		if ( (gmcval<0) && ( (current->warp.duv[1].x != 0) || (current->warp.duv[1].y != 0) ||
			 (current->warp.duv[2].x != 0) || (current->warp.duv[2].y != 0) ) )
		{
			current->coding_type = S_VOP;

			generate_GMCimage(&current->new_gmc_data, &reference->image,
				pParam->mb_width, pParam->mb_height,
				pParam->edged_width, pParam->edged_width/2,
				pParam->m_fcode, ((pParam->vol_flags & XVID_VOL_QUARTERPEL)?1:0), 0,
				current->rounding_type, current->mbs, &pEnc->vGMC);

		} else {

			generate_GMCimage(&current->new_gmc_data, &reference->image,
				pParam->mb_width, pParam->mb_height,
				pParam->edged_width, pParam->edged_width/2,
				pParam->m_fcode, ((pParam->vol_flags & XVID_VOL_QUARTERPEL)?1:0), 0,
				current->rounding_type, current->mbs, NULL);	/* no warping, just AMV */
		}
	}


	if (pEnc->num_threads > 0) {
		/* multithreaded motion estimation - dispatch threads */

		void * status;
		int rows_per_thread = (pParam->mb_height + pEnc->num_threads - 1)/pEnc->num_threads;

		for (k = 0; k < pEnc->num_threads; k++) {
			memset(pEnc->motionData[k].complete_count_self, 0, rows_per_thread * sizeof(int));
			pEnc->motionData[k].pParam = &pEnc->mbParam;
			pEnc->motionData[k].current = current;
			pEnc->motionData[k].reference = reference;
			pEnc->motionData[k].pRefH = &pEnc->vInterH;
			pEnc->motionData[k].pRefV = &pEnc->vInterV;
			pEnc->motionData[k].pRefHV = &pEnc->vInterHV;
			pEnc->motionData[k].pGMC = &pEnc->vGMC;
			pEnc->motionData[k].y_step = pEnc->num_threads;
			pEnc->motionData[k].start_y = k;
			/* todo: sort out temp space once and for all */
			pEnc->motionData[k].RefQ = pEnc->vInterH.u + 16*k*pParam->edged_width;
		}

		for (k = 1; k < pEnc->num_threads; k++) {
			pthread_create(&pEnc->motionData[k].handle, NULL, 
				(void*)MotionEstimateSMP, (void*)&pEnc->motionData[k]);
		}

		MotionEstimateSMP(&pEnc->motionData[0]);

		for (k = 1; k < pEnc->num_threads; k++) {
			pthread_join(pEnc->motionData[k].handle, &status);
		}

		current->fcode = 0;
		for (k = 0; k < pEnc->num_threads; k++) {
			current->sStat.iMvSum += pEnc->motionData[k].mvSum;
			current->sStat.iMvCount += pEnc->motionData[k].mvCount;
			if (pEnc->motionData[k].minfcode > current->fcode)
				current->fcode = pEnc->motionData[k].minfcode;
		}

	} else {
		/* regular ME */

		MotionEstimation(&pEnc->mbParam, current, reference,
						 &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV,
						 &pEnc->vGMC, 256*4096);
	}

	stop_motion_timer();

	set_timecodes(current,reference,pParam->fbase);

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

	for (y = 0; y < mb_height; y++) {
		for (x = 0; x < mb_width; x++) {
			MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
			int skip_possible;

			if (pMB->mode == MODE_INTRA || pMB->mode == MODE_INTRA_Q) {
				CodeIntraMB(pEnc, pMB);
				MBTransQuantIntra(&pEnc->mbParam, current, pMB, x, y,
								  dct_codes, qcoeff);

				start_timer();
				MBPrediction(current, x, y, pParam->mb_width, qcoeff);
				stop_prediction_timer();

				current->sStat.kblks++;

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

			start_timer();
			MBMotionCompensation(pMB, x, y, &reference->image,
								 &pEnc->vInterH, &pEnc->vInterV,
								 &pEnc->vInterHV, &pEnc->vGMC,
								 &current->image,
								 dct_codes, pParam->width,
								 pParam->height,
								 pParam->edged_width,
								 (current->vol_flags & XVID_VOL_QUARTERPEL),
								 current->rounding_type);

			stop_comp_timer();

			pMB->field_pred = 0;

			if (pMB->cbp != 0) {
				pMB->cbp = MBTransQuantInter(&pEnc->mbParam, current, pMB, x, y,
									  dct_codes, qcoeff);
			}

			if (pMB->dquant != 0)
				MBSetDquant(pMB, x, y, &pEnc->mbParam);


			if (pMB->cbp || pMB->mvs[0].x || pMB->mvs[0].y ||
				   pMB->mvs[1].x || pMB->mvs[1].y || pMB->mvs[2].x ||
				   pMB->mvs[2].y || pMB->mvs[3].x || pMB->mvs[3].y) {
				current->sStat.mblks++;
			}  else {
				current->sStat.ublks++;
			}

			start_timer();

			/* Finished processing the MB, now check if to CODE or SKIP */

			skip_possible = (pMB->cbp == 0) && (pMB->mode == MODE_INTER);

			if (current->coding_type == S_VOP)
				skip_possible &= (pMB->mcsel == 1);
			else { /* PVOP */
				const VECTOR * const mv = (pParam->vol_flags & XVID_VOL_QUARTERPEL) ?
										pMB->qmvs : pMB->mvs;
				skip_possible &= ((mv->x|mv->y) == 0);
			}

			if ((pMB->mode == MODE_NOT_CODED) || (skip_possible)) {
				/* This is a candidate for SKIPping, but for P-VOPs check intermediate B-frames first */
				int bSkip = 1;

				if (current->coding_type == P_VOP) {	/* special rule for P-VOP's SKIP */

					for (k = pEnc->bframenum_head; k < pEnc->bframenum_tail; k++) {
						int iSAD;
						iSAD = sad16(reference->image.y + 16*y*pParam->edged_width + 16*x,
										pEnc->bframes[k]->image.y + 16*y*pParam->edged_width + 16*x,
										pParam->edged_width, BFRAME_SKIP_THRESHHOLD * pMB->quant);
						if (iSAD >= BFRAME_SKIP_THRESHHOLD * pMB->quant) {
							bSkip = 0; /* could not SKIP */
							if (pParam->vol_flags & XVID_VOL_QUARTERPEL) {
								VECTOR predMV = get_qpmv2(current->mbs, pParam->mb_width, 0, x, y, 0);
								pMB->pmvs[0].x = - predMV.x;
								pMB->pmvs[0].y = - predMV.y;
							} else {
								VECTOR predMV = get_pmv2(current->mbs, pParam->mb_width, 0, x, y, 0);
								pMB->pmvs[0].x = - predMV.x;
								pMB->pmvs[0].y = - predMV.y;
							}
							pMB->mode = MODE_INTER;
							pMB->cbp = 0;
							break;
						}
					}
				}

				if (bSkip) {
					/* do SKIP */
					pMB->mode = MODE_NOT_CODED;
					MBSkip(bs);
					stop_coding_timer();
					continue;	/* next MB */
				}
			}

			/* ordinary case: normal coded INTER/INTER4V block */
			MBCoding(current, pMB, qcoeff, bs, &pEnc->current->sStat);
			stop_coding_timer();
		}
	}

	emms();
	updateFcode(&current->sStat, pEnc);

	/* frame drop code */
#if 0
	DPRINTF(XVID_DEBUG_DEBUG, "kmu %i %i %i\n", current->sStat.kblks, current->sStat.mblks, current->sStat.ublks);
#endif
	if (current->sStat.kblks + current->sStat.mblks <=
		(pParam->frame_drop_ratio * mb_width * mb_height) / 100 &&
		( (pEnc->bframenum_head >= pEnc->bframenum_tail) || !(pEnc->mbParam.global_flags & XVID_GLOBAL_CLOSED_GOP)) )
	{
		current->sStat.kblks = current->sStat.mblks = current->sStat.iTextBits = 0;
		current->sStat.ublks = mb_width * mb_height;

		BitstreamReset(bs);

		set_timecodes(current,reference,pParam->fbase);
		BitstreamWriteVopHeader(bs, &pEnc->mbParam, current, 0, current->mbs[0].quant);

		/* copy reference frame details into the current frame */
		current->quant = reference->quant;
		current->motion_flags = reference->motion_flags;
		current->rounding_type = reference->rounding_type;
		current->fcode = reference->fcode;
		current->bcode = reference->bcode;
		current->stamp = reference->stamp;
		image_copy(&current->image, &reference->image, pParam->edged_width, pParam->height);
		memcpy(current->mbs, reference->mbs, sizeof(MACROBLOCK) * mb_width * mb_height);
		coded = 0;
	
	} else {

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

		/* what was this frame's interpolated reference will become 
			forward (past) reference in b-frame coding */

		image_swap(&pEnc->vInterH, &pEnc->f_refh);
		image_swap(&pEnc->vInterV, &pEnc->f_refv);
		image_swap(&pEnc->vInterHV, &pEnc->f_refhv);
	}

	/* XXX: debug
	{
		char s[100];
		sprintf(s, "\\%05i_cur.pgm", pEnc->m_framenum);
		image_dump_yuvpgm(&current->image,
			pParam->edged_width,
			pParam->width, pParam->height, s);

		sprintf(s, "\\%05i_ref.pgm", pEnc->m_framenum);
		image_dump_yuvpgm(&reference->image,
			pParam->edged_width,
			pParam->width, pParam->height, s);
	}
	*/

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

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

	return coded;
}


static void
FrameCodeB(Encoder * pEnc,
		   FRAMEINFO * frame,
		   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);
	uint32_t x, y;

	IMAGE *f_ref = &pEnc->reference->image;
	IMAGE *b_ref = &pEnc->current->image;

	#ifdef BFRAMES_DEC_DEBUG
	FILE *fp;
	static char first=0;
#define BFRAME_DEBUG  	if (!first && fp){ \
		fprintf(fp,"Y=%3d   X=%3d   MB=%2d   CBP=%02X\n",y,x,mb->mode,mb->cbp); \
	}

	if (!first){
		fp=fopen("C:\\XVIDDBGE.TXT","w");
	}
#endif

	/* forward  */
	if (!pEnc->reference->is_edged) {
		image_setedges(f_ref, pEnc->mbParam.edged_width,
					   pEnc->mbParam.edged_height, pEnc->mbParam.width,
					   pEnc->mbParam.height, 0);
		pEnc->current->is_edged = 1;	
	}

	if (pEnc->reference->is_interpolated != 0) {
		start_timer();
		image_interpolate(f_ref->y, pEnc->f_refh.y, pEnc->f_refv.y, pEnc->f_refhv.y,
						  pEnc->mbParam.edged_width, pEnc->mbParam.edged_height,
						  (pEnc->mbParam.vol_flags & XVID_VOL_QUARTERPEL), 0);
		stop_inter_timer();
		pEnc->reference->is_interpolated = 0;
	}

	/* backward */
	if (!pEnc->current->is_edged) {
		image_setedges(b_ref, pEnc->mbParam.edged_width,
					   pEnc->mbParam.edged_height, pEnc->mbParam.width,
					   pEnc->mbParam.height, 0);
		pEnc->current->is_edged = 1;
	}

	if (pEnc->current->is_interpolated != 0) {
		start_timer();
		image_interpolate(b_ref->y, pEnc->vInterH.y, pEnc->vInterV.y, pEnc->vInterHV.y,
						pEnc->mbParam.edged_width, pEnc->mbParam.edged_height,
						(pEnc->mbParam.vol_flags & XVID_VOL_QUARTERPEL), 0);
		stop_inter_timer();
		pEnc->current->is_interpolated = 0;
	}

	frame->coding_type = B_VOP;
	call_plugins(pEnc, frame, NULL, XVID_PLG_FRAME, NULL, NULL, NULL);

	frame->fcode = frame->bcode = pEnc->current->fcode;

	start_timer();
	if (pEnc->num_threads > 0) {
		void * status;
		int k;
		/* multithreaded motion estimation - dispatch threads */
		int rows_per_thread = (pEnc->mbParam.mb_height + pEnc->num_threads - 1)/pEnc->num_threads;

		for (k = 0; k < pEnc->num_threads; k++) {
			memset(pEnc->motionData[k].complete_count_self, 0, rows_per_thread * sizeof(int));
			pEnc->motionData[k].pParam = &pEnc->mbParam;
			pEnc->motionData[k].current = frame;
			pEnc->motionData[k].reference = pEnc->current;
			pEnc->motionData[k].fRef = f_ref;
			pEnc->motionData[k].fRefH = &pEnc->f_refh;
			pEnc->motionData[k].fRefV = &pEnc->f_refv;
			pEnc->motionData[k].fRefHV = &pEnc->f_refhv;
			pEnc->motionData[k].pRef = b_ref;
			pEnc->motionData[k].pRefH = &pEnc->vInterH;
			pEnc->motionData[k].pRefV = &pEnc->vInterV;
			pEnc->motionData[k].pRefHV = &pEnc->vInterHV;
			pEnc->motionData[k].time_bp = (int32_t)(pEnc->current->stamp - frame->stamp);
			pEnc->motionData[k].time_pp = (int32_t)(pEnc->current->stamp - pEnc->reference->stamp);
			pEnc->motionData[k].y_step = pEnc->num_threads;
			pEnc->motionData[k].start_y = k;
			/* todo: sort out temp space once and for all */
			pEnc->motionData[k].RefQ = pEnc->vInterH.u + 16*k*pEnc->mbParam.edged_width;
		}

		for (k = 1; k < pEnc->num_threads; k++) {
			pthread_create(&pEnc->motionData[k].handle, NULL, 
				(void*)SMPMotionEstimationBVOP, (void*)&pEnc->motionData[k]);
		}

		SMPMotionEstimationBVOP(&pEnc->motionData[0]);

		for (k = 1; k < pEnc->num_threads; k++) {
			pthread_join(pEnc->motionData[k].handle, &status);
		}

		frame->fcode = frame->bcode = 0;
		for (k = 0; k < pEnc->num_threads; k++) {
			if (pEnc->motionData[k].minfcode > frame->fcode)
				frame->fcode = pEnc->motionData[k].minfcode;
			if (pEnc->motionData[k].minbcode > frame->bcode)
				frame->bcode = pEnc->motionData[k].minbcode;
		}
	} else {
		MotionEstimationBVOP(&pEnc->mbParam, frame,
							 ((int32_t)(pEnc->current->stamp - frame->stamp)),				/* time_bp */
							 ((int32_t)(pEnc->current->stamp - pEnc->reference->stamp)), 	/* time_pp */
							 pEnc->reference->mbs, f_ref,
							 &pEnc->f_refh, &pEnc->f_refv, &pEnc->f_refhv,
							 pEnc->current, b_ref, &pEnc->vInterH,
							 &pEnc->vInterV, &pEnc->vInterHV);
	}
	stop_motion_timer();

	set_timecodes(frame, pEnc->reference,pEnc->mbParam.fbase);
	BitstreamWriteVopHeader(bs, &pEnc->mbParam, frame, 1, frame->quant);

	frame->sStat.iTextBits = 0;
	frame->sStat.iMVBits = 0;
	frame->sStat.iMvSum = 0;
	frame->sStat.iMvCount = 0;
	frame->sStat.kblks = frame->sStat.mblks = frame->sStat.ublks = 0;
	frame->sStat.mblks = pEnc->mbParam.mb_width * pEnc->mbParam.mb_height;
	frame->sStat.kblks = frame->sStat.ublks = 0;

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

			/* decoder ignores mb when refence block is INTER(0,0), CBP=0 */
			if (mb->mode == MODE_NOT_CODED) {
				if (pEnc->mbParam.plugin_flags & XVID_REQORIGINAL) {
					MBMotionCompensation(mb, x, y, f_ref, NULL, f_ref, NULL, NULL, &frame->image,
											NULL, 0, 0, pEnc->mbParam.edged_width, 0, 0);
				}
				continue;
			}

			mb->quant = frame->quant;

			if (mb->cbp != 0 || pEnc->mbParam.plugin_flags & XVID_REQORIGINA

⌨️ 快捷键说明

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