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

📄 motion_est.c

📁 tcpmp播放器的flv插件
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Motion estimation  * Copyright (c) 2000,2001 Fabrice Bellard. * Copyright (c) 2002-2004 Michael Niedermayer *  * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * new Motion Estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at> */ /** * @file motion_est.c * Motion estimation. */ #include <stdlib.h>#include <stdio.h>#include <limits.h>#include "avcodec.h"#include "dsputil.h"#include "mpegvideo.h"#undef NDEBUG#include <assert.h>#define SQ(a) ((a)*(a))#define P_LEFT P[1]#define P_TOP P[2]#define P_TOPRIGHT P[3]#define P_MEDIAN P[4]#define P_MV1 P[9]static inline int sad_hpel_motion_search(MpegEncContext * s,				  int *mx_ptr, int *my_ptr, int dmin,                                  int src_index, int ref_index,                                  int size, int h);static inline int update_map_generation(MotionEstContext *c){    c->map_generation+= 1<<(ME_MAP_MV_BITS*2);    if(c->map_generation==0){        c->map_generation= 1<<(ME_MAP_MV_BITS*2);        memset(c->map, 0, sizeof(uint32_t)*ME_MAP_SIZE);    }    return c->map_generation;}/* shape adaptive search stuff */typedef struct Minima{    int height;    int x, y;    int checked;}Minima;static int minima_cmp(const void *a, const void *b){    const Minima *da = (const Minima *) a;    const Minima *db = (const Minima *) b;        return da->height - db->height;}#define FLAG_QPEL   1 //must be 1#define FLAG_CHROMA 2#define FLAG_DIRECT 4static inline void init_ref(MotionEstContext *c, uint8_t *src[3], uint8_t *ref[3], uint8_t *ref2[3], int x, int y, int ref_index){    const int offset[3]= {          y*c->  stride + x,        ((y*c->uvstride + x)>>1),        ((y*c->uvstride + x)>>1),    };    int i;    for(i=0; i<3; i++){        c->src[0][i]= src [i] + offset[i];        c->ref[0][i]= ref [i] + offset[i];    }    if(ref_index){        for(i=0; i<3; i++){            c->ref[ref_index][i]= ref2[i] + offset[i];        }    }}static int get_flags(MotionEstContext *c, int direct, int chroma){    return   ((c->avctx->flags&CODEC_FLAG_QPEL) ? FLAG_QPEL : 0)           + (direct ? FLAG_DIRECT : 0)            + (chroma ? FLAG_CHROMA : 0);}static always_inline int cmp(MpegEncContext *s, const int x, const int y, const int subx, const int suby,                      const int size, const int h, int ref_index, int src_index,                      me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){    MotionEstContext * const c= &s->me;    const int stride= c->stride;    const int uvstride= c->uvstride;    const int qpel= flags&FLAG_QPEL;    const int chroma= flags&FLAG_CHROMA;    const int dxy= subx + (suby<<(1+qpel)); //FIXME log2_subpel?    const int hx= subx + (x<<(1+qpel));    const int hy= suby + (y<<(1+qpel));    uint8_t * const * const ref= c->ref[ref_index];    uint8_t * const * const src= c->src[src_index];    int d;    //FIXME check chroma 4mv, (no crashes ...)    if(flags&FLAG_DIRECT){        if(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1)){            const int time_pp= s->pp_time;            const int time_pb= s->pb_time;            const int mask= 2*qpel+1;            if(s->mv_type==MV_TYPE_8X8){                int i;                for(i=0; i<4; i++){                    int fx = c->direct_basis_mv[i][0] + hx;                    int fy = c->direct_basis_mv[i][1] + hy;                    int bx = hx ? fx - c->co_located_mv[i][0] : c->co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(qpel+4));                    int by = hy ? fy - c->co_located_mv[i][1] : c->co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(qpel+4));                    int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));                    int bxy= (bx&mask) + ((by&mask)<<(qpel+1));                            uint8_t *dst= c->temp + 8*(i&1) + 8*stride*(i>>1);                    if(qpel){                        c->qpel_put[1][fxy](dst, ref[0] + (fx>>2) + (fy>>2)*stride, stride);                        c->qpel_avg[1][bxy](dst, ref[8] + (bx>>2) + (by>>2)*stride, stride);                    }else{                        c->hpel_put[1][fxy](dst, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 8);                        c->hpel_avg[1][bxy](dst, ref[8] + (bx>>1) + (by>>1)*stride, stride, 8);                    }                }            }else{                int fx = c->direct_basis_mv[0][0] + hx;                int fy = c->direct_basis_mv[0][1] + hy;                int bx = hx ? fx - c->co_located_mv[0][0] : (c->co_located_mv[0][0]*(time_pb - time_pp)/time_pp);                int by = hy ? fy - c->co_located_mv[0][1] : (c->co_located_mv[0][1]*(time_pb - time_pp)/time_pp);                int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));                int bxy= (bx&mask) + ((by&mask)<<(qpel+1));                                if(qpel){                    c->qpel_put[1][fxy](c->temp               , ref[0] + (fx>>2) + (fy>>2)*stride               , stride);                    c->qpel_put[1][fxy](c->temp + 8           , ref[0] + (fx>>2) + (fy>>2)*stride + 8           , stride);                    c->qpel_put[1][fxy](c->temp     + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride     + 8*stride, stride);                    c->qpel_put[1][fxy](c->temp + 8 + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride + 8 + 8*stride, stride);                    c->qpel_avg[1][bxy](c->temp               , ref[8] + (bx>>2) + (by>>2)*stride               , stride);                    c->qpel_avg[1][bxy](c->temp + 8           , ref[8] + (bx>>2) + (by>>2)*stride + 8           , stride);                    c->qpel_avg[1][bxy](c->temp     + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride     + 8*stride, stride);                    c->qpel_avg[1][bxy](c->temp + 8 + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride + 8 + 8*stride, stride);                }else{                                assert((fx>>1) + 16*s->mb_x >= -16);                    assert((fy>>1) + 16*s->mb_y >= -16);                    assert((fx>>1) + 16*s->mb_x <= s->width);                    assert((fy>>1) + 16*s->mb_y <= s->height);                    assert((bx>>1) + 16*s->mb_x >= -16);                    assert((by>>1) + 16*s->mb_y >= -16);                    assert((bx>>1) + 16*s->mb_x <= s->width);                    assert((by>>1) + 16*s->mb_y <= s->height);                    c->hpel_put[0][fxy](c->temp, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 16);                    c->hpel_avg[0][bxy](c->temp, ref[8] + (bx>>1) + (by>>1)*stride, stride, 16);                }            }            d = cmp_func(s, c->temp, src[0], stride, 16);        }else            d= 256*256*256*32;    }else{        int uvdxy;              /* no, it might not be used uninitialized */        if(dxy){            if(qpel){                c->qpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride); //FIXME prototype (add h)                if(chroma){                    int cx= hx/2;                    int cy= hy/2;                    cx= (cx>>1)|(cx&1);                    cy= (cy>>1)|(cy&1);                    uvdxy= (cx&1) + 2*(cy&1);                    //FIXME x/y wrong, but mpeg4 qpel is sick anyway, we should drop as much of it as possible in favor for h264                }            }else{                c->hpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride, h);                if(chroma)                    uvdxy= dxy | (x&1) | (2*(y&1));            }            d = cmp_func(s, c->temp, src[0], stride, h);         }else{            d = cmp_func(s, src[0], ref[0] + x + y*stride, stride, h);             if(chroma)                uvdxy= (x&1) + 2*(y&1);        }        if(chroma){            uint8_t * const uvtemp= c->temp + 16*stride;            c->hpel_put[size+1][uvdxy](uvtemp  , ref[1] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);            c->hpel_put[size+1][uvdxy](uvtemp+8, ref[2] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);            d += chroma_cmp_func(s, uvtemp  , src[1], uvstride, h>>1);             d += chroma_cmp_func(s, uvtemp+8, src[2], uvstride, h>>1);         }    }#if 0    if(full_pel){        const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);        score_map[index]= d;    }    d += (c->mv_penalty[hx - c->pred_x] + c->mv_penalty[hy - c->pred_y])*c->penalty_factor;#endif    return d;}#include "motion_est_template.c"static int zero_cmp(void *s, uint8_t *a, uint8_t *b, int stride, int h){    return 0;}static void zero_hpel(uint8_t *a, const uint8_t *b, int stride, int h){}void ff_init_me(MpegEncContext *s){    MotionEstContext * const c= &s->me;    c->avctx= s->avctx;    ff_set_cmp(&s->dsp, s->dsp.me_pre_cmp, c->avctx->me_pre_cmp);    ff_set_cmp(&s->dsp, s->dsp.me_cmp, c->avctx->me_cmp);    ff_set_cmp(&s->dsp, s->dsp.me_sub_cmp, c->avctx->me_sub_cmp);    ff_set_cmp(&s->dsp, s->dsp.mb_cmp, c->avctx->mb_cmp);        c->flags    = get_flags(c, 0, c->avctx->me_cmp    &FF_CMP_CHROMA);    c->sub_flags= get_flags(c, 0, c->avctx->me_sub_cmp&FF_CMP_CHROMA);    c->mb_flags = get_flags(c, 0, c->avctx->mb_cmp    &FF_CMP_CHROMA);/*FIXME s->no_rounding b_type*/    if(s->flags&CODEC_FLAG_QPEL){        c->sub_motion_search= qpel_motion_search;        c->qpel_avg= s->dsp.avg_qpel_pixels_tab;        if(s->no_rounding) c->qpel_put= s->dsp.put_no_rnd_qpel_pixels_tab;        else               c->qpel_put= s->dsp.put_qpel_pixels_tab;    }else{        if(c->avctx->me_sub_cmp&FF_CMP_CHROMA)            c->sub_motion_search= hpel_motion_search;        else if(   c->avctx->me_sub_cmp == FF_CMP_SAD                 && c->avctx->    me_cmp == FF_CMP_SAD                 && c->avctx->    mb_cmp == FF_CMP_SAD)            c->sub_motion_search= sad_hpel_motion_search; // 2050 vs. 2450 cycles        else            c->sub_motion_search= hpel_motion_search;    }    c->hpel_avg= s->dsp.avg_pixels_tab;    if(s->no_rounding) c->hpel_put= s->dsp.put_no_rnd_pixels_tab;    else               c->hpel_put= s->dsp.put_pixels_tab;    if(s->linesize){        c->stride  = s->linesize;         c->uvstride= s->uvlinesize;    }else{        c->stride  = 16*s->mb_width + 32;        c->uvstride=  8*s->mb_width + 16;    }    // 8x8 fullpel search would need a 4x4 chroma compare, which we dont have yet, and even if we had the motion estimation code doesnt expect it    if(s->codec_id != CODEC_ID_SNOW){        if((c->avctx->me_cmp&FF_CMP_CHROMA)/* && !s->dsp.me_cmp[2]*/){            s->dsp.me_cmp[2]= zero_cmp;        }        if((c->avctx->me_sub_cmp&FF_CMP_CHROMA) && !s->dsp.me_sub_cmp[2]){            s->dsp.me_sub_cmp[2]= zero_cmp;        }        c->hpel_put[2][0]= c->hpel_put[2][1]=        c->hpel_put[2][2]= c->hpel_put[2][3]= zero_hpel;    }    if(s->codec_id == CODEC_ID_H261){        c->sub_motion_search= no_sub_motion_search;    }    c->temp= c->scratchpad;}      #if 0static int pix_dev(uint8_t * pix, int line_size, int mean){    int s, i, j;    s = 0;    for (i = 0; i < 16; i++) {	for (j = 0; j < 16; j += 8) {	    s += ABS(pix[0]-mean);	    s += ABS(pix[1]-mean);	    s += ABS(pix[2]-mean);	    s += ABS(pix[3]-mean);	    s += ABS(pix[4]-mean);	    s += ABS(pix[5]-mean);	    s += ABS(pix[6]-mean);	    s += ABS(pix[7]-mean);	    pix += 8;	}	pix += line_size - 16;    }    return s;}#endifstatic inline void no_motion_search(MpegEncContext * s,				    int *mx_ptr, int *my_ptr){    *mx_ptr = 16 * s->mb_x;    *my_ptr = 16 * s->mb_y;}#if 0  /* the use of these functions is inside #if 0 */static int full_motion_search(MpegEncContext * s,                              int *mx_ptr, int *my_ptr, int range,                              int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture){    int x1, y1, x2, y2, xx, yy, x, y;    int mx, my, dmin, d;    uint8_t *pix;    xx = 16 * s->mb_x;    yy = 16 * s->mb_y;    x1 = xx - range + 1;	/* we loose one pixel to avoid boundary pb with half pixel pred */    if (x1 < xmin)	x1 = xmin;    x2 = xx + range - 1;    if (x2 > xmax)	x2 = xmax;    y1 = yy - range + 1;    if (y1 < ymin)	y1 = ymin;    y2 = yy + range - 1;    if (y2 > ymax)	y2 = ymax;    pix = s->new_picture.data[0] + (yy * s->linesize) + xx;    dmin = 0x7fffffff;    mx = 0;    my = 0;    for (y = y1; y <= y2; y++) {	for (x = x1; x <= x2; x++) {	    d = s->dsp.pix_abs[0][0](NULL, pix, ref_picture + (y * s->linesize) + x,			     s->linesize, 16);	    if (d < dmin ||		(d == dmin &&		 (abs(x - xx) + abs(y - yy)) <		 (abs(mx - xx) + abs(my - yy)))) {		dmin = d;		mx = x;		my = y;	    }	}    }    *mx_ptr = mx;    *my_ptr = my;#if 0    if (*mx_ptr < -(2 * range) || *mx_ptr >= (2 * range) ||

⌨️ 快捷键说明

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