msmpeg4.c

来自「现在关于h.264的源码很多」· C语言 代码 · 共 2,013 行 · 第 1/5 页

C
2,013
字号
            if(s->bit_rate>MBAC_BITRATE)                put_bits(&s->pb, 1, s->per_mb_rl_table);        }        if(s->msmpeg4_version>2){            if(!s->per_mb_rl_table){                code012(&s->pb, s->rl_chroma_table_index);                code012(&s->pb, s->rl_table_index);            }            put_bits(&s->pb, 1, s->dc_table_index);        }    } else {        put_bits(&s->pb, 1, s->use_skip_mb_code);        if(s->msmpeg4_version==4 && s->bit_rate>MBAC_BITRATE)            put_bits(&s->pb, 1, s->per_mb_rl_table);        if(s->msmpeg4_version>2){            if(!s->per_mb_rl_table)                code012(&s->pb, s->rl_table_index);            put_bits(&s->pb, 1, s->dc_table_index);            put_bits(&s->pb, 1, s->mv_table_index);        }    }    s->esc3_level_length= 0;    s->esc3_run_length= 0;#ifdef DEBUG    intra_count = 0;    av_log(s->avctx, AV_LOG_DEBUG, "*****frame %d:\n", frame_count++);#endif}void msmpeg4_encode_ext_header(MpegEncContext * s){        put_bits(&s->pb, 5, s->avctx->time_base.den / s->avctx->time_base.num); //yes 29.97 -> 29        put_bits(&s->pb, 11, FFMIN(s->bit_rate/1024, 2047));        if(s->msmpeg4_version>=3)            put_bits(&s->pb, 1, s->flipflop_rounding);        else            assert(s->flipflop_rounding==0);}#endif //CONFIG_ENCODERS/* predict coded block */static inline int coded_block_pred(MpegEncContext * s, int n, uint8_t **coded_block_ptr){    int xy, wrap, pred, a, b, c;    xy = s->block_index[n];    wrap = s->b8_stride;    /* B C     * A X     */    a = s->coded_block[xy - 1       ];    b = s->coded_block[xy - 1 - wrap];    c = s->coded_block[xy     - wrap];    if (b == c) {        pred = a;    } else {        pred = c;    }    /* store value */    *coded_block_ptr = &s->coded_block[xy];    return pred;}#ifdef CONFIG_ENCODERSstatic void msmpeg4_encode_motion(MpegEncContext * s,                                  int mx, int my){    int code;    MVTable *mv;    /* modulo encoding */    /* WARNING : you cannot reach all the MVs even with the modulo       encoding. This is a somewhat strange compromise they took !!!  */    if (mx <= -64)        mx += 64;    else if (mx >= 64)        mx -= 64;    if (my <= -64)        my += 64;    else if (my >= 64)        my -= 64;    mx += 32;    my += 32;#if 0    if ((unsigned)mx >= 64 ||        (unsigned)my >= 64)        av_log(s->avctx, AV_LOG_ERROR, "error mx=%d my=%d\n", mx, my);#endif    mv = &mv_tables[s->mv_table_index];    code = mv->table_mv_index[(mx << 6) | my];    set_stat(ST_MV);    put_bits(&s->pb,             mv->table_mv_bits[code],             mv->table_mv_code[code]);    if (code == mv->n) {        /* escape : code litterally */        put_bits(&s->pb, 6, mx);        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_t *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);            s->last_bits++;            s->misc_bits++;            s->skip_count++;            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]);            s->misc_bits += get_bits_diff(s);            h263_pred_motion(s, 0, 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]);            s->misc_bits += get_bits_diff(s);            /* motion vector */            h263_pred_motion(s, 0, 0, &pred_x, &pred_y);            msmpeg4_encode_motion(s, motion_x - pred_x,                                  motion_y - pred_y);        }        s->mv_bits += get_bits_diff(s);        for (i = 0; i < 6; i++) {            msmpeg4_encode_block(s, block[i], i);        }        s->p_tex_bits += get_bits_diff(s);    } 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,                         ff_msmp4_mb_i_table[coded_cbp][1], ff_msmp4_mb_i_table[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]);            }        }        s->misc_bits += get_bits_diff(s);        for (i = 0; i < 6; i++) {            msmpeg4_encode_block(s, block[i], i);        }        s->i_tex_bits += get_bits_diff(s);        s->i_count++;    }}#endif //CONFIG_ENCODERSstatic inline int msmpeg4v1_pred_dc(MpegEncContext * s, int n,                                    int32_t **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 FASTDIV((sum + (scale>>1)), scale);}/* dir = 0: left, dir = 1: top prediction */static inline int msmpeg4_pred_dc(MpegEncContext * s, int n,                             uint16_t **dc_val_ptr, int *dir_ptr){    int a, b, c, wrap, pred, scale;    int16_t *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(ARCH_X86_64)) && !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 = FASTDIV((a + (scale >> 1)), scale);        b = FASTDIV((b + (scale >> 1)), scale);        c = FASTDIV((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.data[0] + (((n>>1) + 2*s->mb_y) * 8*  wrap ) + ((n&1) + 2*s->mb_x) * 8;                }else{                    wrap= s->uvlinesize;                    dest= s->current_picture.data[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;                    }

⌨️ 快捷键说明

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