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

📄 h261.c

📁 tcpmp播放器的flv插件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * H261 decoder * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> * Copyright (c) 2004 Maarten Daniels * * 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 *//** * @file h261.c * h261codec. */#include "common.h"#include "dsputil.h"#include "avcodec.h"#include "mpegvideo.h"#include "h261data.h"#define H261_MBA_VLC_BITS 9#define H261_MTYPE_VLC_BITS 6#define H261_MV_VLC_BITS 7#define H261_CBP_VLC_BITS 9#define TCOEFF_VLC_BITS 9#define MBA_STUFFING 33#define MBA_STARTCODE 34#define IS_FIL(a)    ((a)&MB_TYPE_H261_FIL)/** * H261Context */typedef struct H261Context{    MpegEncContext s;    int current_mba;    int previous_mba;    int mba_diff;    int mtype;    int current_mv_x;    int current_mv_y;    int gob_number;    int gob_start_code_skipped; // 1 if gob start code is already read before gob header is read}H261Context;void ff_h261_loop_filter(MpegEncContext *s){    H261Context * h= (H261Context*)s;    const int linesize  = s->linesize;    const int uvlinesize= s->uvlinesize;    uint8_t *dest_y = s->dest[0];    uint8_t *dest_cb= s->dest[1];    uint8_t *dest_cr= s->dest[2];    if(!(IS_FIL (h->mtype)))        return;    s->dsp.h261_loop_filter(dest_y                   , linesize);    s->dsp.h261_loop_filter(dest_y                + 8, linesize);    s->dsp.h261_loop_filter(dest_y + 8 * linesize    , linesize);    s->dsp.h261_loop_filter(dest_y + 8 * linesize + 8, linesize);    s->dsp.h261_loop_filter(dest_cb, uvlinesize);    s->dsp.h261_loop_filter(dest_cr, uvlinesize);}static int ff_h261_get_picture_format(int width, int height){    // QCIF    if (width == 176 && height == 144)        return 0;    // CIF    else if (width == 352 && height == 288)        return 1;    // ERROR    else        return -1;}static void h261_encode_block(H261Context * h, DCTELEM * block,                              int n);static int h261_decode_block(H261Context *h, DCTELEM *block,                             int n, int coded);void ff_h261_encode_picture_header(MpegEncContext * s, int picture_number){    H261Context * h = (H261Context *) s;    int format, temp_ref;    align_put_bits(&s->pb);    /* Update the pointer to last GOB */    s->ptr_lastgob = pbBufPtr(&s->pb);    put_bits(&s->pb, 20, 0x10); /* PSC */    temp_ref= s->picture_number * (int64_t)30000 * s->avctx->time_base.num /                          (1001 * (int64_t)s->avctx->time_base.den); //FIXME maybe this should use a timestamp    put_bits(&s->pb, 5, temp_ref & 0x1f); /* TemporalReference */    put_bits(&s->pb, 1, 0); /* split screen off */    put_bits(&s->pb, 1, 0); /* camera  off */    put_bits(&s->pb, 1, 0); /* freeze picture release off */        format = ff_h261_get_picture_format(s->width, s->height);        put_bits(&s->pb, 1, format); /* 0 == QCIF, 1 == CIF */    put_bits(&s->pb, 1, 0); /* still image mode */    put_bits(&s->pb, 1, 0); /* reserved */    put_bits(&s->pb, 1, 0); /* no PEI */        if(format == 0)        h->gob_number = -1;    else        h->gob_number = 0;    h->current_mba = 0;}/** * Encodes a group of blocks header. */static void h261_encode_gob_header(MpegEncContext * s, int mb_line){    H261Context * h = (H261Context *)s;    if(ff_h261_get_picture_format(s->width, s->height) == 0){        h->gob_number+=2; // QCIF    }    else{        h->gob_number++; // CIF    }    put_bits(&s->pb, 16, 1); /* GBSC */    put_bits(&s->pb, 4, h->gob_number); /* GN */    put_bits(&s->pb, 5, s->qscale); /* GQUANT */    put_bits(&s->pb, 1, 0); /* no GEI */    h->current_mba = 0;    h->previous_mba = 0;    h->current_mv_x=0;    h->current_mv_y=0;}void ff_h261_reorder_mb_index(MpegEncContext* s){    int index= s->mb_x + s->mb_y*s->mb_width;    if(index % 33 == 0)        h261_encode_gob_header(s,0);    /* for CIF the GOB's are fragmented in the middle of a scanline       that's why we need to adjust the x and y index of the macroblocks */    if(ff_h261_get_picture_format(s->width,s->height) == 1){ // CIF        s->mb_x =     index % 11 ; index /= 11;        s->mb_y =     index %  3 ; index /=  3;        s->mb_x+= 11*(index %  2); index /=  2;        s->mb_y+=  3*index;                ff_init_block_index(s);        ff_update_block_index(s);    }}static void h261_encode_motion(H261Context * h, int val){    MpegEncContext * const s = &h->s;    int sign, code;    if(val==0){        code = 0;        put_bits(&s->pb,h261_mv_tab[code][1],h261_mv_tab[code][0]);    }     else{        if(val > 15)            val -=32;        if(val < -16)            val+=32;        sign = val < 0;        code = sign ? -val : val;         put_bits(&s->pb,h261_mv_tab[code][1],h261_mv_tab[code][0]);        put_bits(&s->pb,1,sign);    }}static inline int get_cbp(MpegEncContext * s,                      DCTELEM block[6][64]){    int i, cbp;    cbp= 0;    for (i = 0; i < 6; i++) {        if (s->block_last_index[i] >= 0)            cbp |= 1 << (5 - i);    }    return cbp;}void ff_h261_encode_mb(MpegEncContext * s,         DCTELEM block[6][64],         int motion_x, int motion_y){    H261Context * h = (H261Context *)s;    int mvd, mv_diff_x, mv_diff_y, i, cbp;    cbp = 63; // avoid warning    mvd = 0;     h->current_mba++;    h->mtype = 0;     if (!s->mb_intra){        /* compute cbp */        cbp= get_cbp(s, block);           /* mvd indicates if this block is motion compensated */        mvd = motion_x | motion_y;        if((cbp | mvd | s->dquant ) == 0) {            /* skip macroblock */            s->skip_count++;            h->current_mv_x=0;            h->current_mv_y=0;            return;        }    }    /* MB is not skipped, encode MBA */    put_bits(&s->pb, h261_mba_bits[(h->current_mba-h->previous_mba)-1], h261_mba_code[(h->current_mba-h->previous_mba)-1]);     /* calculate MTYPE */    if(!s->mb_intra){        h->mtype++;                if(mvd || s->loop_filter)            h->mtype+=3;        if(s->loop_filter)            h->mtype+=3;        if(cbp || s->dquant)            h->mtype++;        assert(h->mtype > 1);    }    if(s->dquant)         h->mtype++;    put_bits(&s->pb, h261_mtype_bits[h->mtype], h261_mtype_code[h->mtype]);     h->mtype = h261_mtype_map[h->mtype];     if(IS_QUANT(h->mtype)){        ff_set_qscale(s,s->qscale+s->dquant);        put_bits(&s->pb, 5, s->qscale);    }     if(IS_16X16(h->mtype)){        mv_diff_x = (motion_x >> 1) - h->current_mv_x;        mv_diff_y = (motion_y >> 1) - h->current_mv_y;        h->current_mv_x = (motion_x >> 1);        h->current_mv_y = (motion_y >> 1);        h261_encode_motion(h,mv_diff_x);        h261_encode_motion(h,mv_diff_y);    }     h->previous_mba = h->current_mba;     if(HAS_CBP(h->mtype)){        put_bits(&s->pb,h261_cbp_tab[cbp-1][1],h261_cbp_tab[cbp-1][0]);     }    for(i=0; i<6; i++) {        /* encode each block */        h261_encode_block(h, block[i], i);    }    if ( ( h->current_mba == 11 ) || ( h->current_mba == 22 ) || ( h->current_mba == 33 ) || ( !IS_16X16 ( h->mtype ) )){        h->current_mv_x=0;        h->current_mv_y=0;    }}void ff_h261_encode_init(MpegEncContext *s){    static int done = 0;        if (!done) {        done = 1;        init_rl(&h261_rl_tcoeff, 1);    }    s->min_qcoeff= -127;    s->max_qcoeff=  127;    s->y_dc_scale_table=    s->c_dc_scale_table= ff_mpeg1_dc_scale_table;}/** * encodes a 8x8 block. * @param block the 8x8 block * @param n block index (0-3 are luma, 4-5 are chroma) */static void h261_encode_block(H261Context * h, DCTELEM * block, int n){    MpegEncContext * const s = &h->s;    int level, run, last, i, j, last_index, last_non_zero, sign, slevel, code;    RLTable *rl;    rl = &h261_rl_tcoeff;    if (s->mb_intra) {        /* DC coef */        level = block[0];        /* 255 cannot be represented, so we clamp */        if (level > 254) {            level = 254;            block[0] = 254;        }        /* 0 cannot be represented also */        else if (level < 1) {            level = 1;            block[0] = 1;        }        if (level == 128)            put_bits(&s->pb, 8, 0xff);        else            put_bits(&s->pb, 8, level);        i = 1;    } else if((block[0]==1 || block[0] == -1) && (s->block_last_index[n] > -1)){        //special case        put_bits(&s->pb,2,block[0]>0 ? 2 : 3 );        i = 1;    } else {        i = 0;    }       /* AC coefs */    last_index = s->block_last_index[n];    last_non_zero = i - 1;    for (; i <= last_index; i++) {        j = s->intra_scantable.permutated[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;            }            code = get_rl_index(rl, 0 /*no last in H.261, EOB is used*/, run, level);            if(run==0 && level < 16)            code+=1;            put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);            if (code == rl->n) {                put_bits(&s->pb, 6, run);                assert(slevel != 0);                assert(level <= 127);                put_bits(&s->pb, 8, slevel & 0xff);            } else {                put_bits(&s->pb, 1, sign);            }            last_non_zero = i;        }    }    if(last_index > -1){        put_bits(&s->pb, rl->table_vlc[0][1], rl->table_vlc[0][0]);// END OF BLOCK    }}/***********************************************//* decoding */static VLC h261_mba_vlc;static VLC h261_mtype_vlc;static VLC h261_mv_vlc;static VLC h261_cbp_vlc;void init_vlc_rl(RLTable *rl, int use_static);static void h261_decode_init_vlc(H261Context *h){    static int done = 0;    if(!done){        done = 1;        init_vlc(&h261_mba_vlc, H261_MBA_VLC_BITS, 35,                 h261_mba_bits, 1, 1,                 h261_mba_code, 1, 1, 1);        init_vlc(&h261_mtype_vlc, H261_MTYPE_VLC_BITS, 10,                 h261_mtype_bits, 1, 1,                 h261_mtype_code, 1, 1, 1);        init_vlc(&h261_mv_vlc, H261_MV_VLC_BITS, 17,                 &h261_mv_tab[0][1], 2, 1,                 &h261_mv_tab[0][0], 2, 1, 1);        init_vlc(&h261_cbp_vlc, H261_CBP_VLC_BITS, 63,                 &h261_cbp_tab[0][1], 2, 1,                 &h261_cbp_tab[0][0], 2, 1, 1);        init_rl(&h261_rl_tcoeff, 1);        init_vlc_rl(&h261_rl_tcoeff, 1);    }}static int h261_decode_init(AVCodecContext *avctx){    H261Context *h= avctx->priv_data;    MpegEncContext * const s = &h->s;    // set defaults    MPV_decode_defaults(s);    s->avctx = avctx;    s->width  = s->avctx->coded_width;    s->height = s->avctx->coded_height;    s->codec_id = s->avctx->codec->id;    s->out_format = FMT_H261;    s->low_delay= 1;    avctx->pix_fmt= PIX_FMT_YUV420P;    s->codec_id= avctx->codec->id;    h261_decode_init_vlc(h);    h->gob_start_code_skipped = 0;        return 0;}/** * decodes the group of blocks header or slice header. * @return <0 if an error occured */static int h261_decode_gob_header(H261Context *h){    unsigned int val;    MpegEncContext * const s = &h->s;        if ( !h->gob_start_code_skipped ){        /* Check for GOB Start Code */        val = show_bits(&s->gb, 15);        if(val)            return -1;        /* We have a GBSC */        skip_bits(&s->gb, 16);    }    h->gob_start_code_skipped = 0;    h->gob_number = get_bits(&s->gb, 4); /* GN */    s->qscale = get_bits(&s->gb, 5); /* GQUANT */    /* Check if gob_number is valid */    if (s->mb_height==18){ //cif        if ((h->gob_number<=0) || (h->gob_number>12))            return -1;    }    else{ //qcif        if ((h->gob_number!=1) && (h->gob_number!=3) && (h->gob_number!=5))            return -1;    }    /* GEI */    while (get_bits1(&s->gb) != 0) {        skip_bits(&s->gb, 8);    }    if(s->qscale==0)        return -1;    // For the first transmitted macroblock in a GOB, MBA is the absolute address. For    // subsequent macroblocks, MBA is the difference between the absolute addresses of    // the macroblock and the last transmitted macroblock.    h->current_mba = 0;    h->mba_diff = 0;    return 0;}/** * decodes the group of blocks / video packet header. * @return <0 if no resync found */static int ff_h261_resync(H261Context *h){    MpegEncContext * const s = &h->s;    int left, ret;    if ( h->gob_start_code_skipped ){        ret= h261_decode_gob_header(h);        if(ret>=0)            return 0;    }    else{        if(show_bits(&s->gb, 15)==0){            ret= h261_decode_gob_header(h);            if(ret>=0)                return 0;        }        //ok, its not where its supposed to be ...        s->gb= s->last_resync_gb;        align_get_bits(&s->gb);        left= s->gb.size_in_bits - get_bits_count(&s->gb);        for(;left>15+1+4+5; left-=8){            if(show_bits(&s->gb, 15)==0){                GetBitContext bak= s->gb;                ret= h261_decode_gob_header(h);                if(ret>=0)                    return 0;                s->gb= bak;            }            skip_bits(&s->gb, 8);        }    }    return -1;}/** * decodes skipped macroblocks * @return 0 */static int h261_decode_mb_skipped(H261Context *h, int mba1, int mba2 ){    MpegEncContext * const s = &h->s;    int i;        s->mb_intra = 0;

⌨️ 快捷键说明

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