📄 h261.c
字号:
/* * 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 + -