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

📄 motionest.cc

📁 Motion JPEG编解码器源代码
💻 CC
📖 第 1 页 / 共 4 页
字号:
/* motionest.cc, motion estimation  *//* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. *//* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose.  In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders.  Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * *//* Modifications and enhancements (C) 2000-2004 Andrew Stevens *//* These modifications are free software; you can redistribute it *  and/or modify it under the terms of the GNU General Public License *  as published by the Free Software Foundation; either version 2 of *  the License, or (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *  General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */#include <config.h>#include <stdio.h>#include <stdlib.h>#include <limits.h>#include <cassert>#include <math.h>#include <mpeg2syntaxcodes.h>#include "cpu_accel.h"#include "simd.h"#include "fastintfns.h"#include "motionsearch.h"#include "mjpeg_logging.h"#include "encoderparams.hh"#include "picture.hh"/* See ISO13818-2 7.6.3.5 */int dualprime_m[FieldOrder::dim][Parity::dim /*ref*/][Parity::dim /*pred*/] ={    { { 2, 1 }, { 3, 2 } }, // Botfield first    { { 2, 3 }, { 1, 2 } }  // Topfield first};int dualprime_e[Parity::dim /*ref*/ ][Parity::dim /*pred*/ ] ={     { 0, +1 },     { -1, 0 }};        /* Macro-block Motion estimation results record */struct MotionCand{	Coord pos;        // Half-pel co-ormv[1]dinates of source block	int sad;			// Sum of absolute difference	int var;	uint8_t *blk ;		// Source block data (in luminace data array)	int hx, hy;			// Half-pel offsets	int fieldsel;		// 0 = top 1 = bottom	int fieldoff;       // Offset from start of frame data to first line						// of field.	(top = 0, bottom = width );};struct SubSampledImg{	uint8_t *mb;		// One pel	uint8_t *fmb;		// Two-pel subsampled	uint8_t *qmb;		// Four-pel subsampled	uint8_t *umb; 		// U compoenent one-pel	uint8_t *vmb;       // V component  one-pel};/*  Main field and frame based motion estimation entry points.*/static void field_estimate (const Picture &picture,							uint8_t *toporg,							uint8_t *topref, 							uint8_t *botorg, 							uint8_t *botref,							SubSampledImg *ssmb,							int i, int j, int sx, int sy,							MotionCand *bestfr,							MotionCand *best8u,							MotionCand *best8l,							MotionCand *bestsp);static void mb_me_search (    const EncoderParams &eparams,	uint8_t *org, uint8_t *ref,    int fieldoff,	SubSampledImg *ssblk,	int lx, int i0, int j0, 	int sx, int sy, int h, 	int xmax, int ymax,	MotionCand *motion );inline int mv_coding_penalty( int mv_x, int mv_y ){    return (abs(mv_x) + abs(mv_y))<<3;}/*  *  Compute subsampled images for fast motion compensation search *  N.b. Sub-sampling works correctly if we treat interlaced images *  as two half-height images side-by-side. *//* * Compute the variance of the residual of uni-directionally motion * compensated block. * */static inline int unidir_pred_var( const MotionCand *motion,							uint8_t *mb,  							int lx, 							int h){	return psumsq(motion->blk, mb, lx, motion->hx, motion->hy, h);}/* * Compute the variance of the residual of bi-directionally motion * compensated block. */static inline int bidir_pred_var( const MotionCand *motion_f, 									  const MotionCand *motion_b,									  uint8_t *mb,  									  int lx, int h){	return pbsumsq( motion_f->blk, motion_b->blk,					   mb, lx, 					   motion_f->hx, motion_f->hy,					   motion_b->hx, motion_b->hy,					   h);}/* unidir_var_sum * * Compute the combined variance of luminance and * chrominance information for a particular non-intra macro block * after unidirectional motion estimation... * *  Note: results are scaled to give chrominance equal weight to *  chrominance.  The variance of the luminance portion is computed *  at the time the motion estimation is computed. * *  TODO: Perhaps we should compute the whole thing in mb_mc_search *  not seperate it.  However, that would involve a lot of fiddling *  with field_* and until its thoroughly debugged and tested I think *  I'll leave that alone. Furthermore, it is unclear if its really *  worth * doing these computations for B *and* P frames. * *  TODO: BUG: ONLY works for 420 video... *   */static int unidir_var_sum( MotionCand *lum_mc, 						   uint8_t **ref, 						   SubSampledImg *ssblk,						   int lx, int h ){	int uvlx = (lx>>1);	int uvh = (h>>1);	/* N.b. MC co-ordinates are computed in half-pel units! */	int cblkoffset = (lum_mc->fieldoff>>1) +		(lum_mc->pos.x>>2) + (lum_mc->pos.y>>2)*uvlx;		return 	lum_mc->var +		(psumsq_sub22( ref[1] + cblkoffset, ssblk->umb, uvlx, uvh) +		 psumsq_sub22( ref[2] + cblkoffset, ssblk->vmb, uvlx, uvh));}/* *  bidir_var_sum *  Compute the combined variance of luminance and chrominance information *  for a particular non-intra macro block after bidirectional *  motion estimation...   * *  Note: results are scaled to give chrominance equal weight to *  chrominance.  The variance of the luminance portion is computed *  at the time the motion estimation is computed. * *  Note: results scaled to give chrominance equal weight to chrominance. *  *  TODO: BUG: ONLY works for 420 video... * *  NOTE: Currently unused but may be required if it turns out that taking *  chrominance into account in B frames is needed. * */static int bidir_var_sum( MotionCand *lum_mc_f, 						  MotionCand *lum_mc_b, 						  uint8_t **ref_f, 						  uint8_t **ref_b,						  SubSampledImg *ssblk,						  int lx, int h ){	int uvlx = (lx>>1);	int uvh = (h>>1);	/* N.b. MC co-ordinates are computed in half-pel units! */	int cblkoffset_f = (lum_mc_f->fieldoff>>1) + 		(lum_mc_f->pos.x>>2) + (lum_mc_f->pos.y>>2)*uvlx;	int cblkoffset_b = (lum_mc_b->fieldoff>>1) + 		(lum_mc_b->pos.x>>2) + (lum_mc_b->pos.y>>2)*uvlx;		return 	(		pbsumsq( lum_mc_f->blk, lum_mc_b->blk,					ssblk->mb, lx, 					lum_mc_f->hx, lum_mc_f->hy,					lum_mc_b->hx, lum_mc_b->hy,					h) +		pbsumsq_sub22( ref_f[1] + cblkoffset_f, ref_b[1] + cblkoffset_b,					   ssblk->umb, uvlx, uvh ) +		pbsumsq_sub22( ref_f[2] + cblkoffset_f, ref_b[2] + cblkoffset_b,					   ssblk->vmb, uvlx, uvh ));}/* * Sum of chrominance variance of a block. */static inline int chrom_var_sum( SubSampledImg *ssblk, int h, int lx ){    uint32_t var1, var2, dummy_mean;    assert( (h>>1) == 8 || (h>>1) == 16 );    pvariance(ssblk->umb,(h>>1),(lx>>1), &var1, &dummy_mean);    pvariance(ssblk->vmb,(h>>1),(lx>>1), &var2, &dummy_mean);    	return (var1+var2)*2;}/* * Compute SAD for bi-directionally motion compensated blocks... */static inline int bidir_pred_sad( const MotionCand *motion_f, 									  const MotionCand *motion_b,									  uint8_t *mb,  									  int lx, int h){	return pbsad(motion_f->blk, motion_b->blk, 					 mb, lx, 					 motion_f->hx, motion_f->hy,					 motion_b->hx, motion_b->hy,					 h);}#ifdef DEBUG_MCstatic void display_mb(MotionCand *lum_mc, 				  uint8_t **ref, 				  SubSampledImg *ssblk,				  int lx, int h ){	int x,y;	int sum = 0;	int uvlx = (lx>>1);	int uvh = (h>>1);	/* N.b. MC co-ordinates are computed in half-pel units! */	int lblkoffset = lum_mc->fieldoff +		(lum_mc->pos.x>>1) + (lum_mc->pos.y>>1)*lx;	/*int cblkoffset = (lum_mc->fieldoff>>1) +	  (lum_mc->pos.x>>2) + (lum_mc->pos.y>>2)*uvlx;*/	fprintf(stderr, "ref[0] = %08x (%d,%d) width=%d reconbase = %08x blk =%08x\n", 			(int)ref[0], (lum_mc->pos.x>>1), (lum_mc->pos.y>>1),			lx,			(int)(ref[0]+lblkoffset), (int)(lum_mc->blk) );		for( y = 0; y < 16; ++y )		{			for( x = 0; x< 16; ++x )			{				int diff = *(ref[0]+lblkoffset+x+y*lx)-*(ssblk->mb+x+y*lx);				sum += diff*diff;				fprintf( stderr,"%04d ", diff );			}			fprintf(stderr,"\n");		}		fprintf(stderr, "sumsq = %d [%d] (%d)\n", 				sum, 				lum_mc->var,				unidir_pred_var(lum_mc, ssblk->mb, lx,  h)			);		}#endifvoid FieldMotionCands(    const EncoderParams &eparams,	uint8_t *org,	uint8_t *ref,	SubSampledImg *topssmb,	SubSampledImg *botssmb,	int i, int j, int sx, int sy,	MotionCand *besttop,	MotionCand *bestbot,    MotionCand (&fieldmcs)[2][2]	){	/* predict top field from top field */	mb_me_search( eparams,                  org,ref,0,topssmb,                  eparams.phy_width<<1,i,j>>1,sx,sy>>1,8,                  eparams.enc_width,eparams.enc_height>>1,                  &fieldmcs[Parity::top][Parity::top]);	/* predict top field from bottom field */	mb_me_search( eparams,                  org,ref,eparams.phy_width,topssmb,                   eparams.phy_width<<1,i,j>>1,sx,sy>>1,8,                  eparams.enc_width,eparams.enc_height>>1,                   &fieldmcs[Parity::bot][Parity::top]);    	/* set correct field selectors... */    // TODO fieldset and fieldoff are redundant.  Use only fieldoff    // and derive fieldset as fieldoff != 0	fieldmcs[Parity::top][Parity::top].fieldsel = 0;	fieldmcs[Parity::bot][Parity::top].fieldsel = 1;	fieldmcs[Parity::top][Parity::top].fieldoff = 0;	fieldmcs[Parity::bot][Parity::top].fieldoff = eparams.phy_width;	/* select prediction for top field */	if (fieldmcs[Parity::top][Parity::top].sad<=fieldmcs[Parity::bot][Parity::top].sad)	{		*besttop = fieldmcs[Parity::top][Parity::top];	}	else	{		*besttop = fieldmcs[Parity::bot][Parity::top];	}	/* predict bottom field from top field */	mb_me_search( eparams,                  org,ref,0,botssmb,                  eparams.phy_width<<1,i,j>>1,sx,sy>>1,8,                  eparams.enc_width,eparams.enc_height>>1,                  &fieldmcs[Parity::top][Parity::bot]);	/* predict bottom field from bottom field */	mb_me_search( eparams,                  org,ref,eparams.phy_width,botssmb,                  eparams.phy_width<<1,i,j>>1,sx,sy>>1,8,                  eparams.enc_width,eparams.enc_height>>1,                  &fieldmcs[Parity::bot][Parity::bot]);    	/* set correct field selectors... */	fieldmcs[Parity::top][Parity::bot].fieldsel = 0;	fieldmcs[Parity::bot][Parity::bot].fieldsel = 1;	fieldmcs[Parity::top][Parity::bot].fieldoff = 0;	fieldmcs[Parity::bot][Parity::bot].fieldoff = eparams.phy_width;	/* select prediction for bottom field */	if (fieldmcs[Parity::bot][Parity::bot].sad<=fieldmcs[Parity::top][Parity::bot].sad)	{		*bestbot = fieldmcs[Parity::bot][Parity::bot];	}	else	{		*bestbot = fieldmcs[Parity::top][Parity::bot];	}}typedef int (*DualPrimeMeasure)( uint8_t *sameref,                                 uint8_t *crossref,                                 uint8_t *pred_mb,                                 int field_stride,                                 int same_fx, int same_fy,                                 int cross_fx, int cross_fy,                                 int h    );bool DualPrimeMetric( const Picture &picture,                      DualPrimeMeasure meas,                      const Coord &same,                      const Coord (&crossblks)[Parity::dim], // Cross-field ref                      const MotionVector &dmv,                      uint8_t *ref,                      uint8_t *pred_mb,                      int stride,                      int &measure    ){    bool all_legal = true;    Coord cross;    int part_meas = 0;    // Base MV is out-of-range    if( ! picture.InRangeFieldMVRef( same ) )        return false;    for( int ppred = Parity::top; ppred <= Parity::bot; ++ppred )    {        int same_fieldoff = (ppred == Parity::top ? 0 : stride);        Coord cross(crossblks[Parity::Invert(ppred)],dmv);                int cross_fieldoff = stride - same_fieldoff;

⌨️ 快捷键说明

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