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

📄 motionest.cc

📁 Motion JPEG编解码器源代码
💻 CC
📖 第 1 页 / 共 4 页
字号:
        if( ! picture.InRangeFieldMVRef( cross ) )            return false;        uint8_t *sameref = ref + same_fieldoff            + (same.x>>1) + (stride<<1)*(same.y>>1);        uint8_t *crossref = ref + cross_fieldoff            + (cross.x>>1) + (stride<<1)*(cross.y>>1);        /* compute prediction error */        part_meas += meas( sameref, crossref,                           pred_mb,                           stride<<1,                           same.x&1,                           same.y&1,                           cross.x&1,                           cross.y&1,                           8            );    }    measure = part_meas;    return true; // All vectors legal...}bool MacroBlock::FrameDualPrimeCand (uint8_t *ref,                                const SubSampledImg &ssmb,                                const MotionCand (&best_fieldmcs)[Parity::dim][Parity::dim],                                 MotionCand &best_mc,                                MotionVector &min_dpmv){	int local_dist;    int stride = picture->encparams.phy_width;    bool dpmvfound = false;    // Tricky here we need half-pel field co-ordinates so hpel won't do!    const Coord mb( Coord::HalfPel(Coord::Field(pel)) );	/* Calculate Dual Prime distortions for 9 delta candidates	 * for each of the four minimum field vectors	 * Note: only for P pictures!	 */	/* initialize minimum dual prime distortion to maximum     * macroblockvariance value. Ensure estimate won't be used if     * no legal one can be found...     */    int best_sad = 256*16*16;        int (&m)[Parity::dim /*ref*/][Parity::dim /*pred*/] =        dualprime_m[picture->topfirst];    Coord min_cross[Parity::dim];    Coord min_same;    // Iterate over the different suggestions corresponding to the    // different possible combinations of reference/prediction    // field parity 	for ( int psugref=Parity::top; psugref<=Parity::bot; psugref++) 	{        // Iterate of over parity predicted MB suggestion		for ( int psugpred=Parity::top; psugpred<=Parity::top; psugpred++)		{			/* convert Cartesian absolute to relative motion vector			 * values (wrt current macroblock address (i,j)			 */            MotionVector suggestion =                 MotionVector::Frame(best_fieldmcs[psugref][psugpred].pos, mb );            /* If the candidate base vector is between opposite polarity               fields we have to convert it to a corresponding dual-prime               base-vector.  N.b. this may *increase* its magnitude outside the               legal range so we have to check for this...            */            MotionVector base;            base[Dim::X] = suggestion[Dim::X]*2/m[psugref][psugpred];            base[Dim::Y] = (suggestion[Dim::Y] - dualprime_e[psugref][psugpred])*2/m[psugref][psugpred];            if( ! picture->Legal( base ) )                continue;            /* We use (legal) base motion vectors for the same               polarity prediction and to derive the base motion               vectors for the cross-polarity predictions */                        Coord same( mb, base );            Coord cross[Parity::dim /* ref polarity */];            for( int pref = Parity::top; pref < Parity::dim; ++pref )            {                int ppred = Parity::Invert(pref);                cross[pref].x = rnddiv2(base[Dim::X] * m[pref][ppred])                     + mb.x;                cross[pref].y = rnddiv2(base[Dim::Y] * m[pref][ppred])                    +dualprime_e[pref][ppred]+mb.y;            }                              			/* Now find the best differential motion vector for the               cross-polarity predictions             */            MotionVector dmv;            for (dmv[Dim::Y]=-1; dmv[Dim::Y]<=1; ++dmv[Dim::Y])            {                for (dmv[Dim::X]=-1; dmv[Dim::X]<=1; ++dmv[Dim::X])                {                    local_dist = 0;                    bool legal =                        DualPrimeMetric( *picture, pbsad,                                         same, cross,                                         dmv,                                         ref,                                         ssmb.mb,                                         stride,                                         local_dist );                    /* update best legal MV with smallest distortion                     * distortion */                                        if ( local_dist < best_sad && legal )                    {                        dpmvfound = true;                        min_dpmv = dmv;                        best_sad = local_dist;                        min_same = same;                        min_cross[Parity::top] = cross[Parity::top];                        min_cross[Parity::bot] = cross[Parity::bot];                    }                }  /* end delta x loop */            } /* end delta y loop */		}	}        if( dpmvfound )    {        DualPrimeMetric( *picture, pbsumsq,                         min_same, min_cross, min_dpmv,                         ref,                         ssmb.mb,                         stride,                         best_mc.var );        best_mc.sad = best_sad + mv_coding_penalty( min_same.x-mb.x,                                                     min_same.y-mb.y );        best_mc.pos = min_same;    }    return dpmvfound;}static void dpfield_estimate(	const Picture &picture,	uint8_t *topref,	uint8_t *botref, 	uint8_t *mb,	int i, int j, 	MotionCand *bestsp_mc,	MotionCand *bestdp_mc,	int *vmcp	){    const EncoderParams &eparams = picture.encparams;	uint8_t *sameref, *oppref;	int io0,jo0,io,jo,delta_x,delta_y,mvxs,mvys,mvxo0,mvyo0;	int imino = 0;	int jmino = 0;	int imindmv = 0;	int jmindmv = 0;	int vmc_dp,local_dist;	int imins = 0;	int jmins = 0;	/* Calculate Dual Prime distortions for 9 delta candidates */	/* Note: only for P pictures! */	/* Assign opposite and same reference pointer */	if (picture.pict_struct==TOP_FIELD)	{		sameref = topref;    		oppref = botref;	}	else 	{		sameref = botref;		oppref = topref;	}	/* convert Cartesian absolute to relative motion vector	 * values (wrt current macroblock address (i,j)	 */	mvxs = imins - (i<<1);	mvys = jmins - (j<<1);	/* vector for prediction from field of opposite 'parity' */	mvxo0 = (mvxs+(mvxs>0)) >> 1;  /* mvxs / / */	mvyo0 = (mvys+(mvys>0)) >> 1;  /* mvys / / 2*/			/* vertical field shift correction */	if (picture.pict_struct==TOP_FIELD)		mvyo0--;	else		mvyo0++;			/* convert back to absolute coordinates */	io0 = mvxo0 + (i<<1);	jo0 = mvyo0 + (j<<1);			/* initialize minimum dual prime distortion to maximum             * macroblock variance value */	vmc_dp = 256*256*16*16;	for (delta_y = -1; delta_y <= 1; delta_y++)	{		for (delta_x = -1; delta_x <=1; delta_x++)		{			/* opposite field coordinates */			io = io0 + delta_x;			jo = jo0 + delta_y;			if (io >= 0 && io <= (eparams.enc_width-16)<<1 &&				jo >= 0 && jo <= (eparams.enc_height2-16)<<1)			{				/* compute prediction error */				local_dist = pbsumsq(					sameref + (imins>>1) + eparams.phy_width2*(jmins>>1),					oppref  + (io>>1)    + eparams.phy_width2*(jo>>1),					mb,             /* current mb location */					eparams.phy_width2,         /* adjacent line distance */					imins&1, jmins&1, io&1, jo&1, /* half-pel flags */					16);            /* block height */				/* update delta with least distortion vector */				if (local_dist < vmc_dp)				{					imino = io;					jmino = jo;					imindmv = delta_x;					jmindmv = delta_y;					vmc_dp = local_dist;				}			}		}  /* end delta x loop */	} /* end delta y loop */	/* Compute L1 error for decision purposes */	bestdp_mc->sad =		pbsad(			sameref + (imins>>1) + eparams.phy_width2*(jmins>>1),			oppref  + (imino>>1) + eparams.phy_width2*(jmino>>1),			mb,             /* current mb location */			eparams.phy_width2,         /* adjacent line distance */			imins&1, jmins&1, imino&1, jmino&1, /* half-pel flags */			16);            /* block height */	bestdp_mc->pos.x = imindmv;	bestdp_mc->pos.x = jmindmv;	*vmcp = vmc_dp;}/* * Collection motion estimates for the different modes for frame pictures * picture: picture object for which MC is to be computed. * * results: a vector of 'plausible' motion estimates.  This function * which is a refined version of the original MSSE reference encoder * only every puts a single, heuristically 'best', estimate into the vector * * TODO: MC_DMV should trigger on the current (dynamically selected) * bigroup length and not the fixed Maximum bi-group length M. */#ifdef DEBUG_MOTION_ESTconst static bool trace_me = false;#endifvoid MacroBlock::FrameMEs(){    const Picture &picture = ParentPicture();    const EncoderParams &eparams = picture.encparams;    int i = TopleftX();    int j = TopleftY();    //    // Motion info for the various possible motion modes...    //	MotionCand framef_mc;	MotionCand frameb_mc;	MotionCand dualpf_mc;	MotionCand topfldf_mc;	MotionCand botfldf_mc;	MotionCand topfldb_mc;	MotionCand botfldb_mc;	MotionCand zeromot_mc;    // Pointers to macroblock's contents in YUV and half and quad    // subsampled planes, and for FIELD modes, the bottom field    // variants...	SubSampledImg ssmb;	SubSampledImg  botssmb;	MotionCand best_fieldmcs[2][2];    MotionVector min_dpmv;    int mb_row_start = j*eparams.phy_width;	    MotionEst me;    best_of_kind_me.erase(best_of_kind_me.begin(),best_of_kind_me.end());	/* A.Stevens fast motion estimation data is appended to actual	   luminance information. 	   TODO: The append thing made sense before we had	   a nice tidy compression record for each picture but now 	   it should really be replaced by additional pointers to	   seperate buffers.	*/	ssmb.mb = picture.org_img[0] + mb_row_start + i;	ssmb.umb = (uint8_t*)(picture.org_img[1] + (i>>1) + (mb_row_start>>2));	ssmb.vmb = (uint8_t*)(picture.org_img[2] + (i>>1) + (mb_row_start>>2));	ssmb.fmb = (uint8_t*)(picture.org_img[0] + eparams.fsubsample_offset + 						  ((i>>1) + (mb_row_start>>2)));	ssmb.qmb = (uint8_t*)(picture.org_img[0] + eparams.qsubsample_offset + 						  (i>>2) + (mb_row_start>>4));	/* Zero motion vector - useful for some optimisations	 */	zeromot_mc.pos.x = (i<<1);	/* Damn but its messy carrying doubled */	zeromot_mc.pos.y = (j<<1);	/* absolute Co-ordinates for M/C */	zeromot_mc.fieldsel = 0;	zeromot_mc.fieldoff = 0;	zeromot_mc.blk = picture.fwd_rec[0]+mb_row_start+i;    zeromot_mc.hx = zeromot_mc.hy = 0;	/* Compute variance MB as a measure of Intra-coding complexity	   We include chrominance information here, scaled to compensate	   for sub-sampling.  Silly MPEG forcing chrom/lum to have same	   quantisations... ;-)	 */    pvariance(ssmb.mb,16,eparams.phy_width, &lum_variance, &lum_mean );	int intravar = lum_variance + chrom_var_sum(&ssmb,16,eparams.phy_width);    /* We always have the possibility of INTRA coding */    me.mb_type = MB_INTRA;    me.motion_type = 0;    me.var = intravar;    me.MV[0][0].Zero();    best_of_kind_me.push_back( me );	if (picture.pict_type==P_TYPE)	{        /* FRAME mode non-intra coding 0 MV and estimated MVs is           always possible */        zeromot_mc.var = unidir_pred_var(&zeromot_mc, ssmb.mb,                                          eparams.phy_width, 16 );        me.mb_type = 0;        me.motion_type = MC_FRAME;        me.var =  unidir_var_sum(&zeromot_mc, picture.fwd_rec, &ssmb,                                 eparams.phy_width, 16 );        best_of_kind_me.push_back( me );        mb_me_search( eparams,                      picture.fwd_org[0],picture.fwd_rec[0],                      0,                      &ssmb, eparams.phy_width,                      i,j,picture.sxf,picture.syf,16,                      eparams.enc_width,eparams.enc_height, &framef_mc);        framef_mc.fieldoff = 0;        me.mb_type = MB_FORWARD;        me.motion_type=MC_FRAME;        me.var = unidir_var_sum( &framef_mc, picture.fwd_rec, &ssmb,                                 eparams.phy_width, 16 );        me.MV[0][0] = MotionVector::Frame( framef_mc.pos, hpel );        best_of_kind_me.push_back( me );                /* FIELD modes only possible if appropriate picture type is legal */		if (!picture.frame_pred_dct )		{			botssmb.mb = ssmb.mb+eparams.phy_width;			botssmb.fmb = ssmb.fmb+(eparams.phy_width>>1);			botssmb.qmb = ssmb.qmb+(eparams.phy_width>>2);			botssmb.umb = ssmb.umb+(eparams.phy_width>>1);			botssmb.vmb = ssmb.vmb+(eparams.phy_width>>1);			FieldMotionCands( eparams,                               picture.fwd_org[0],picture.fwd_rec[0],                               &ssmb, &botssmb,                               i,j,picture.sxf,picture.syf,                               &topfldf_mc,                               &botfldf_mc,                               best_fieldmcs);            me.mb_type = MB_FORWARD;            me.motion_type = MC_FIELD;            me.var =                 unidir_var_sum( &topfldf_mc, picture.fwd_rec, &ssmb,                                (eparams.phy_width<<1), 8 )				+ unidir_var_sum( &botfldf_mc, picture.fwd_rec, &botssmb,                                  (eparams.phy_width<<1), 8 );            me.MV[0][0] = MotionVector::Field(topfldf_mc.pos, hpel);            me.MV[1][0] = MotionVector::Field(botfldf_mc.pos, hpel);            me.field_sel[0][0] = topfldf_mc.fieldsel;            me.field_sel[1][0] = botfldf_mc.fieldsel;            best_of_kind_me.push_back( me );			if ( eparams.dualprime                  && FrameDualPrimeCand(picture.fwd_rec[0], ssmb,                                       best_fieldmcs, dualpf_mc, min_dpmv )                 )            {                    me.mb_type = MB_FORWARD;                    me.motion_type = MC_DMV;                    me.MV[0][0] = MotionVector::Field(dualpf_mc.pos, hpel);                    me.dualprimeMV = min_dpmv;                    // TODO: No actual calculation of chroma variances                    // just assumed identical per block as luma.                    me.var = dualpf_mc.var + dualpf_mc.var/2;                    best_of_kind_me.push_back( me );            }        }	}	else if (picture.pict_type==B_TYPE)	{        /*  FRAME modes: always possible */        // Forward motion estimates        mb_me_search( eparams,                      picture.fwd_org[0],picture.fwd_rec[0],0,&ssmb,                      eparams.phy_width,i,j,picture.sxf,picture.syf,                      16,eparams.enc_width,eparams.enc_height,                      &framef_mc					   );        framef_mc.fieldoff = 0;                // Backword motion estimates...        mb_me_search( eparams,                      picture.bwd_org[0],picture.bwd_rec[0],0,&ssmb,                      eparams.phy_width, i,j,picture.sxb,picture.syb,                      16, eparams.enc_width, eparams.enc_height,                      &frameb_mc);        frameb_mc.fieldoff = 0;        me.motion_type = MC_FRAME;        me.MV[0][0][0] = framef_mc.pos.x - (i<<1);        me.MV[0][0][1] = framef_mc.pos.y - (j<<1);

⌨️ 快捷键说明

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