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

📄 encoder.c

📁 视频压缩编解码标准MPEG4商业级别的VC代码实现标准
💻 C
📖 第 1 页 / 共 4 页
字号:
		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, 0, 0, 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, 0, 0, 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, 0, 0, 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, 0, 0, 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, &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++;	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, 0, 0, stats);		}		else			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 */			call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, 0, 0, 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, 0, 0, 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 voidCodeIntraMB(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 intFrameCodeI(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.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];

⌨️ 快捷键说明

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