msmpeg4.c

来自「Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3」· C语言 代码 · 共 1,993 行 · 第 1/4 页

C
1,993
字号
        put_bits(&s->pb, 6, my);    }}static inline void handle_slices(MpegEncContext *s){    if (s->mb_x == 0) {        if (s->slice_height && (s->mb_y % s->slice_height) == 0) {            if(s->msmpeg4_version != 4){                ff_mpeg4_clean_buffers(s);            }            s->first_slice_line = 1;        } else {            s->first_slice_line = 0;         }    }}void msmpeg4_encode_mb(MpegEncContext * s,                        DCTELEM block[6][64],                       int motion_x, int motion_y){    int cbp, coded_cbp, i;    int pred_x, pred_y;    UINT8 *coded_block;    handle_slices(s);        if (!s->mb_intra) {	/* compute cbp */        set_stat(ST_INTER_MB);	cbp = 0;	for (i = 0; i < 6; i++) {	    if (s->block_last_index[i] >= 0)		cbp |= 1 << (5 - i);	}	if (s->use_skip_mb_code && (cbp | motion_x | motion_y) == 0) {	    /* skip macroblock */	    put_bits(&s->pb, 1, 1);	    return;	}        if (s->use_skip_mb_code)            put_bits(&s->pb, 1, 0);	/* mb coded */                if(s->msmpeg4_version<=2){            put_bits(&s->pb,                      v2_mb_type[cbp&3][1],                      v2_mb_type[cbp&3][0]);            if((cbp&3) != 3) coded_cbp= cbp ^ 0x3C;            else             coded_cbp= cbp;            put_bits(&s->pb,                      cbpy_tab[coded_cbp>>2][1],                      cbpy_tab[coded_cbp>>2][0]);                                    h263_pred_motion(s, 0, &pred_x, &pred_y);            msmpeg4v2_encode_motion(s, motion_x - pred_x);            msmpeg4v2_encode_motion(s, motion_y - pred_y);        }else{            put_bits(&s->pb,                      table_mb_non_intra[cbp + 64][1],                      table_mb_non_intra[cbp + 64][0]);            /* motion vector */            h263_pred_motion(s, 0, &pred_x, &pred_y);            msmpeg4_encode_motion(s, motion_x - pred_x,                                   motion_y - pred_y);        }    } else {	/* compute cbp */	cbp = 0;        coded_cbp = 0;	for (i = 0; i < 6; i++) {            int val, pred;            val = (s->block_last_index[i] >= 1);            cbp |= val << (5 - i);            if (i < 4) {                /* predict value for close blocks only for luma */                pred = coded_block_pred(s, i, &coded_block);                *coded_block = val;                val = val ^ pred;            }            coded_cbp |= val << (5 - i);	}#if 0        if (coded_cbp)            printf("cbp=%x %x\n", cbp, coded_cbp);#endif        if(s->msmpeg4_version<=2){            if (s->pict_type == I_TYPE) {                put_bits(&s->pb,                          v2_intra_cbpc[cbp&3][1], v2_intra_cbpc[cbp&3][0]);            } else {                if (s->use_skip_mb_code)                    put_bits(&s->pb, 1, 0);	/* mb coded */                put_bits(&s->pb,                          v2_mb_type[(cbp&3) + 4][1],                          v2_mb_type[(cbp&3) + 4][0]);            }            put_bits(&s->pb, 1, 0);	/* no AC prediction yet */            put_bits(&s->pb,                      cbpy_tab[cbp>>2][1],                      cbpy_tab[cbp>>2][0]);        }else{            if (s->pict_type == I_TYPE) {                set_stat(ST_INTRA_MB);                put_bits(&s->pb,                          table_mb_intra[coded_cbp][1], table_mb_intra[coded_cbp][0]);            } else {                if (s->use_skip_mb_code)                    put_bits(&s->pb, 1, 0);	/* mb coded */                put_bits(&s->pb,                          table_mb_non_intra[cbp][1],                          table_mb_non_intra[cbp][0]);            }            set_stat(ST_INTRA_MB);            put_bits(&s->pb, 1, 0);	/* no AC prediction yet */            if(s->inter_intra_pred){                s->h263_aic_dir=0;                put_bits(&s->pb, table_inter_intra[s->h263_aic_dir][1], table_inter_intra[s->h263_aic_dir][0]);            }        }    }    for (i = 0; i < 6; i++) {        msmpeg4_encode_block(s, block[i], i);    }}/* old ffmpeg msmpeg4v3 mode */void ff_old_msmpeg4_dc_scale(MpegEncContext * s){    if (s->qscale < 5){        s->y_dc_scale = 8;        s->c_dc_scale = 8;    }else if (s->qscale < 9){        s->y_dc_scale = 2 * s->qscale;        s->c_dc_scale = (s->qscale + 13)>>1;    }else{        s->y_dc_scale = s->qscale + 8;        s->c_dc_scale = (s->qscale + 13)>>1;    }}static inline int msmpeg4v1_pred_dc(MpegEncContext * s, int n,                                     INT32 **dc_val_ptr){    int i;    if (n < 4) {        i= 0;    } else {        i= n-3;    }        *dc_val_ptr= &s->last_dc[i];    return s->last_dc[i]; }static int get_dc(uint8_t *src, int stride, int scale){    int y;    int sum=0;    for(y=0; y<8; y++){        int x;        for(x=0; x<8; x++){            sum+=src[x + y*stride];        }    }    return (sum + (scale>>1))/scale;}/* dir = 0: left, dir = 1: top prediction */static inline int msmpeg4_pred_dc(MpegEncContext * s, int n,                              UINT16 **dc_val_ptr, int *dir_ptr){    int a, b, c, wrap, pred, scale;    INT16 *dc_val;    /* find prediction */    if (n < 4) {	scale = s->y_dc_scale;    } else {	scale = s->c_dc_scale;    }        wrap = s->block_wrap[n];    dc_val= s->dc_val[0] + s->block_index[n];    /* B C     * A X      */    a = dc_val[ - 1];    b = dc_val[ - 1 - wrap];    c = dc_val[ - wrap];        if(s->first_slice_line && (n&2)==0 && s->msmpeg4_version!=4){        b=c=1024;    }    /* XXX: the following solution consumes divisions, but it does not       necessitate to modify mpegvideo.c. The problem comes from the       fact they decided to store the quantized DC (which would lead       to problems if Q could vary !) */#if defined ARCH_X86 && !defined PIC    asm volatile(        "movl %3, %%eax		\n\t"	"shrl $1, %%eax		\n\t"	"addl %%eax, %2		\n\t"	"addl %%eax, %1		\n\t"	"addl %0, %%eax		\n\t"	"mull %4		\n\t"	"movl %%edx, %0		\n\t"	"movl %1, %%eax		\n\t"	"mull %4		\n\t"	"movl %%edx, %1		\n\t"	"movl %2, %%eax		\n\t"	"mull %4		\n\t"	"movl %%edx, %2		\n\t"	: "+b" (a), "+c" (b), "+D" (c)	: "g" (scale), "S" (inverse[scale])	: "%eax", "%edx"    );#else    /* #elif defined (ARCH_ALPHA) */    /* Divisions are extremely costly on Alpha; optimize the most       common case. But they are costly everywhere...     */    if (scale == 8) {	a = (a + (8 >> 1)) / 8;	b = (b + (8 >> 1)) / 8;	c = (c + (8 >> 1)) / 8;    } else {	a = (a + (scale >> 1)) / scale;	b = (b + (scale >> 1)) / scale;	c = (c + (scale >> 1)) / scale;    }#endif    /* XXX: WARNING: they did not choose the same test as MPEG4. This       is very important ! */    if(s->msmpeg4_version>3){        if(s->inter_intra_pred){            uint8_t *dest;            int wrap;                        if(n==1){                pred=a;                *dir_ptr = 0;            }else if(n==2){                pred=c;                *dir_ptr = 1;            }else if(n==3){                if (abs(a - b) < abs(b - c)) {                    pred = c;                    *dir_ptr = 1;                } else {                    pred = a;                    *dir_ptr = 0;                }            }else{                if(n<4){                    wrap= s->linesize;                    dest= s->current_picture[0] + (((n>>1) + 2*s->mb_y) * 8*  wrap ) + ((n&1) + 2*s->mb_x) * 8;                }else{                    wrap= s->uvlinesize;                    dest= s->current_picture[n-3] + (s->mb_y * 8 * wrap) + s->mb_x * 8;                }                if(s->mb_x==0) a= (1024 + (scale>>1))/scale;                else           a= get_dc(dest-8, wrap, scale*8);                if(s->mb_y==0) c= (1024 + (scale>>1))/scale;                else           c= get_dc(dest-8*wrap, wrap, scale*8);                                if (s->h263_aic_dir==0) {                    pred= a;                    *dir_ptr = 0;                }else if (s->h263_aic_dir==1) {                    if(n==0){                        pred= c;                        *dir_ptr = 1;                    }else{                        pred= a;                        *dir_ptr = 0;                    }                }else if (s->h263_aic_dir==2) {                    if(n==0){                        pred= a;                        *dir_ptr = 0;                    }else{                        pred= c;                        *dir_ptr = 1;                    }                } else {                    pred= c;                    *dir_ptr = 1;                }            }        }else{            if (abs(a - b) < abs(b - c)) {                pred = c;                *dir_ptr = 1;            } else {                pred = a;                *dir_ptr = 0;            }        }    }else{        if (abs(a - b) <= abs(b - c)) {            pred = c;            *dir_ptr = 1;        } else {            pred = a;            *dir_ptr = 0;        }    }    /* update predictor */    *dc_val_ptr = &dc_val[0];    return pred;}#define DC_MAX 119static void msmpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr){    int sign, code;    int pred;    if(s->msmpeg4_version==1){        INT32 *dc_val;        pred = msmpeg4v1_pred_dc(s, n, &dc_val);                /* update predictor */        *dc_val= level;    }else{        UINT16 *dc_val;        pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);        /* update predictor */        if (n < 4) {            *dc_val = level * s->y_dc_scale;        } else {            *dc_val = level * s->c_dc_scale;        }    }    /* do the prediction */    level -= pred;    if(s->msmpeg4_version<=2){        if (n < 4) {            put_bits(&s->pb,                      v2_dc_lum_table[level+256][1],                     v2_dc_lum_table[level+256][0]);        }else{            put_bits(&s->pb,                      v2_dc_chroma_table[level+256][1],                     v2_dc_chroma_table[level+256][0]);        }    }else{        sign = 0;        if (level < 0) {            level = -level;            sign = 1;        }        code = level;        if (code > DC_MAX)             code = DC_MAX;        if (s->dc_table_index == 0) {            if (n < 4) {                put_bits(&s->pb, table0_dc_lum[code][1], table0_dc_lum[code][0]);            } else {                put_bits(&s->pb, table0_dc_chroma[code][1], table0_dc_chroma[code][0]);            }        } else {            if (n < 4) {                put_bits(&s->pb, table1_dc_lum[code][1], table1_dc_lum[code][0]);            } else {                put_bits(&s->pb, table1_dc_chroma[code][1], table1_dc_chroma[code][0]);            }        }                    if (code == DC_MAX)            put_bits(&s->pb, 8, level);                    if (level != 0) {            put_bits(&s->pb, 1, sign);        }    }}/* Encoding of a block. Very similar to MPEG4 except for a different   escape coding (same as H263) and more vlc tables. */static inline void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n){    int level, run, last, i, j, last_index;    int last_non_zero, sign, slevel;    int code, run_diff, dc_pred_dir;    const RLTable *rl;    const UINT8 *scantable;    if (s->mb_intra) {        set_stat(ST_DC);        msmpeg4_encode_dc(s, block[0], n, &dc_pred_dir);        i = 1;        if (n < 4) {            rl = &rl_table[s->rl_table_index];        } else {            rl = &rl_table[3 + s->rl_chroma_table_index];        }        run_diff = 0;        scantable= s->intra_scantable.permutated;        set_stat(ST_INTRA_AC);    } else {        i = 0;        rl = &rl_table[3 + s->rl_table_index];        if(s->msmpeg4_version<=2)            run_diff = 0;        else            run_diff = 1;        scantable= s->inter_scantable.permutated;        set_stat(ST_INTER_AC);    }    /* recalculate block_last_index for M$ wmv1 */    if(s->msmpeg4_version==4 && s->block_last_index[n]>0){        for(last_index=63; last_index>=0; last_index--){            if(block[scantable[last_index]]) break;        }        s->block_last_index[n]= last_index;    }else        last_index = s->block_last_index[n];    /* AC coefs */    last_non_zero = i - 1;    for (; i <= last_index; i++) {	j = scantable[i];	level = block[j];	if (level) {	    run = i - last_non_zero - 1;	    last = (i == last_index);	    sign = 0;	    slevel = level;	    if (level < 0) {		sign = 1;		level = -level;	    }            if(level<=MAX_LEVEL && run<=MAX_RUN){                s->ac_stats[s->mb_intra][n>3][level][run][last]++;            }#if 0else    s->ac_stats[s->mb_intra][n>3][40][63][0]++; //esc3 like#endif            code = get_rl_index(rl, last, run, level);            put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);            if (code == rl->n) {                int level1, run1;                level1 = level - rl->max_level[last][run];                if (level1 < 1)                     goto esc2;                code = get_rl_index(rl, last, run, level1);                if (code == rl->n) {                esc2:                    put_bits(&s->pb, 1, 0);                    if (level > MAX_LEVEL)                        goto esc3;                    run1 = run - rl->max_run[last][level] - run_diff;                    if (run1 < 0)                        goto esc3;                    code = get_rl_index(rl, last, run1, level);                    if (code == rl->n) {                    esc3:                        /* third escape */                        put_bits(&s->pb, 1, 0);                        put_bits(&s->pb, 1, last);                        if(s->msmpeg4_version==4){                            if(s->esc3_level_length==0){                                s->esc3_level_length=8;                                s->esc3_run_length= 6;                                if(s->qscale<8)                                    put_bits(&s->pb, 6, 3);                                else                                    put_bits(&s->pb, 8, 3);                            }                            put_bits(&s->pb, s->esc3_run_length, run);                            put_bits(&s->pb, 1, sign);                            put_bits(&s->pb, s->esc3_level_length, level);                        }else{                            put_bits(&s->pb, 6, run);                            put_bits(&s->pb, 8, slevel & 0xff);                        }                    } else {                        /* second escape */                        put_bits(&s->pb, 1, 1);                        put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);                        put_bits(&s->pb, 1, sign);

⌨️ 快捷键说明

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