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

📄 h263dec.c

📁 现在关于h.264的源码很多
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * H.263 decoder * Copyright (c) 2001 Fabrice Bellard. * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *//** * @file h263dec.c * H.263 decoder. */#include "avcodec.h"#include "dsputil.h"#include "mpegvideo.h"//#define DEBUG//#define PRINT_FRAME_TIMEint ff_h263_decode_init(AVCodecContext *avctx){    MpegEncContext *s = avctx->priv_data;    s->avctx = avctx;    s->out_format = FMT_H263;    s->width  = avctx->coded_width;    s->height = avctx->coded_height;    s->workaround_bugs= avctx->workaround_bugs;    // set defaults    MPV_decode_defaults(s);    s->quant_precision=5;    s->decode_mb= ff_h263_decode_mb;    s->low_delay= 1;    avctx->pix_fmt= PIX_FMT_YUV420P;    s->unrestricted_mv= 1;    /* select sub codec */    switch(avctx->codec->id) {    case CODEC_ID_H263:        s->unrestricted_mv= 0;        break;    case CODEC_ID_MPEG4:        s->decode_mb= ff_mpeg4_decode_mb;        s->time_increment_bits = 4; /* default value for broken headers */        s->h263_pred = 1;        s->low_delay = 0; //default, might be overriden in the vol header during header parsing        break;    case CODEC_ID_MSMPEG4V1:        s->h263_msmpeg4 = 1;        s->h263_pred = 1;        s->msmpeg4_version=1;        break;    case CODEC_ID_MSMPEG4V2:        s->h263_msmpeg4 = 1;        s->h263_pred = 1;        s->msmpeg4_version=2;        break;    case CODEC_ID_MSMPEG4V3:        s->h263_msmpeg4 = 1;        s->h263_pred = 1;        s->msmpeg4_version=3;        break;    case CODEC_ID_WMV1:        s->h263_msmpeg4 = 1;        s->h263_pred = 1;        s->msmpeg4_version=4;        break;    case CODEC_ID_WMV2:        s->h263_msmpeg4 = 1;        s->h263_pred = 1;        s->msmpeg4_version=5;        break;    case CODEC_ID_WMV3:        s->h263_msmpeg4 = 1;        s->h263_pred = 1;        s->msmpeg4_version=6;        break;    case CODEC_ID_H263I:        break;    case CODEC_ID_FLV1:        s->h263_flv = 1;        break;    default:        return -1;    }    s->codec_id= avctx->codec->id;    /* for h263, we allocate the images after having read the header */    if (avctx->codec->id != CODEC_ID_H263 && avctx->codec->id != CODEC_ID_MPEG4)        if (MPV_common_init(s) < 0)            return -1;    if (s->h263_msmpeg4)        ff_msmpeg4_decode_init(s);    else        h263_decode_init_vlc(s);    return 0;}int ff_h263_decode_end(AVCodecContext *avctx){    MpegEncContext *s = avctx->priv_data;    MPV_common_end(s);    return 0;}/** * returns the number of bytes consumed for building the current frame */static int get_consumed_bytes(MpegEncContext *s, int buf_size){    int pos= (get_bits_count(&s->gb)+7)>>3;    if(s->divx_packed){        //we would have to scan through the whole buf to handle the weird reordering ...        return buf_size;    }else if(s->flags&CODEC_FLAG_TRUNCATED){        pos -= s->parse_context.last_index;        if(pos<0) pos=0; // padding is not really read so this might be -1        return pos;    }else{        if(pos==0) pos=1; //avoid infinite loops (i doubt thats needed but ...)        if(pos+10>buf_size) pos=buf_size; // oops ;)        return pos;    }}static int decode_slice(MpegEncContext *s){    const int part_mask= s->partitioned_frame ? (AC_END|AC_ERROR) : 0x7F;    const int mb_size= 16>>s->avctx->lowres;    s->last_resync_gb= s->gb;    s->first_slice_line= 1;    s->resync_mb_x= s->mb_x;    s->resync_mb_y= s->mb_y;    ff_set_qscale(s, s->qscale);    if(s->partitioned_frame){        const int qscale= s->qscale;        if(s->codec_id==CODEC_ID_MPEG4){            if(ff_mpeg4_decode_partitions(s) < 0)                return -1;        }        /* restore variables which were modified */        s->first_slice_line=1;        s->mb_x= s->resync_mb_x;        s->mb_y= s->resync_mb_y;        ff_set_qscale(s, qscale);    }    for(; s->mb_y < s->mb_height; s->mb_y++) {        /* per-row end of slice checks */        if(s->msmpeg4_version){            if(s->resync_mb_y + s->slice_height == s->mb_y){                ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, AC_END|DC_END|MV_END);                return 0;            }        }        if(s->msmpeg4_version==1){            s->last_dc[0]=            s->last_dc[1]=            s->last_dc[2]= 128;        }        ff_init_block_index(s);        for(; s->mb_x < s->mb_width; s->mb_x++) {            int ret;            ff_update_block_index(s);            if(s->resync_mb_x == s->mb_x && s->resync_mb_y+1 == s->mb_y){                s->first_slice_line=0;            }            /* DCT & quantize */            s->mv_dir = MV_DIR_FORWARD;            s->mv_type = MV_TYPE_16X16;//            s->mb_skipped = 0;//printf("%d %d %06X\n", ret, get_bits_count(&s->gb), show_bits(&s->gb, 24));            ret= s->decode_mb(s, s->block);            if (s->pict_type!=B_TYPE)                ff_h263_update_motion_val(s);            if(ret<0){                const int xy= s->mb_x + s->mb_y*s->mb_stride;                if(ret==SLICE_END){                    MPV_decode_mb(s, s->block);                    if(s->loop_filter)                        ff_h263_loop_filter(s);//printf("%d %d %d %06X\n", s->mb_x, s->mb_y, s->gb.size*8 - get_bits_count(&s->gb), show_bits(&s->gb, 24));                    ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);                    s->padding_bug_score--;                    if(++s->mb_x >= s->mb_width){                        s->mb_x=0;                        ff_draw_horiz_band(s, s->mb_y*mb_size, mb_size);                        s->mb_y++;                    }                    return 0;                }else if(ret==SLICE_NOEND){                    av_log(s->avctx, AV_LOG_ERROR, "Slice mismatch at MB: %d\n", xy);                    ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x+1, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);                    return -1;                }                av_log(s->avctx, AV_LOG_ERROR, "Error at MB: %d\n", xy);                ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_ERROR|DC_ERROR|MV_ERROR)&part_mask);                return -1;            }            MPV_decode_mb(s, s->block);            if(s->loop_filter)                ff_h263_loop_filter(s);        }        ff_draw_horiz_band(s, s->mb_y*mb_size, mb_size);        s->mb_x= 0;    }    assert(s->mb_x==0 && s->mb_y==s->mb_height);    /* try to detect the padding bug */    if(      s->codec_id==CODEC_ID_MPEG4       &&   (s->workaround_bugs&FF_BUG_AUTODETECT)       &&    s->gb.size_in_bits - get_bits_count(&s->gb) >=0       &&    s->gb.size_in_bits - get_bits_count(&s->gb) < 48//       &&   !s->resync_marker       &&   !s->data_partitioning){        const int bits_count= get_bits_count(&s->gb);        const int bits_left = s->gb.size_in_bits - bits_count;        if(bits_left==0){            s->padding_bug_score+=16;        } else if(bits_left != 1){            int v= show_bits(&s->gb, 8);            v|= 0x7F >> (7-(bits_count&7));            if(v==0x7F && bits_left<=8)                s->padding_bug_score--;            else if(v==0x7F && ((get_bits_count(&s->gb)+8)&8) && bits_left<=16)                s->padding_bug_score+= 4;            else                s->padding_bug_score++;        }    }    if(s->workaround_bugs&FF_BUG_AUTODETECT){        if(s->padding_bug_score > -2 && !s->data_partitioning /*&& (s->divx_version || !s->resync_marker)*/)            s->workaround_bugs |=  FF_BUG_NO_PADDING;        else            s->workaround_bugs &= ~FF_BUG_NO_PADDING;    }    // handle formats which don't have unique end markers    if(s->msmpeg4_version || (s->workaround_bugs&FF_BUG_NO_PADDING)){ //FIXME perhaps solve this more cleanly        int left= s->gb.size_in_bits - get_bits_count(&s->gb);        int max_extra=7;        /* no markers in M$ crap */        if(s->msmpeg4_version && s->pict_type==I_TYPE)            max_extra+= 17;        /* buggy padding but the frame should still end approximately at the bitstream end */        if((s->workaround_bugs&FF_BUG_NO_PADDING) && s->error_resilience>=3)            max_extra+= 48;        else if((s->workaround_bugs&FF_BUG_NO_PADDING))            max_extra+= 256*256*256*64;        if(left>max_extra){            av_log(s->avctx, AV_LOG_ERROR, "discarding %d junk bits at end, next would be %X\n", left, show_bits(&s->gb, 24));        }        else if(left<0){            av_log(s->avctx, AV_LOG_ERROR, "overreading %d bits\n", -left);        }else            ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, AC_END|DC_END|MV_END);        return 0;    }    av_log(s->avctx, AV_LOG_ERROR, "slice end not reached but screenspace end (%d left %06X, score= %d)\n",            s->gb.size_in_bits - get_bits_count(&s->gb),            show_bits(&s->gb, 24), s->padding_bug_score);    ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);    return -1;}/** * finds the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or -1 */int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){    int vop_found, i;    uint32_t state;    vop_found= pc->frame_start_found;    state= pc->state;    i=0;    if(!vop_found){        for(i=0; i<buf_size; i++){            state= (state<<8) | buf[i];            if(state == 0x1B6){                i++;                vop_found=1;                break;            }        }    }    if(vop_found){        /* EOF considered as end of frame */        if (buf_size == 0)            return 0;        for(; i<buf_size; i++){            state= (state<<8) | buf[i];            if((state&0xFFFFFF00) == 0x100){                pc->frame_start_found=0;                pc->state=-1;                return i-3;            }        }    }    pc->frame_start_found= vop_found;    pc->state= state;    return END_NOT_FOUND;}static int h263_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){    int vop_found, i;    uint32_t state;    vop_found= pc->frame_start_found;    state= pc->state;    i=0;    if(!vop_found){        for(i=0; i<buf_size; i++){            state= (state<<8) | buf[i];            if(state>>(32-22) == 0x20){                i++;                vop_found=1;                break;            }        }    }    if(vop_found){      for(; i<buf_size; i++){        state= (state<<8) | buf[i];        if(state>>(32-22) == 0x20){            pc->frame_start_found=0;            pc->state=-1;            return i-3;        }      }    }    pc->frame_start_found= vop_found;    pc->state= state;    return END_NOT_FOUND;}static int h263_parse(AVCodecParserContext *s,                           AVCodecContext *avctx,                           uint8_t **poutbuf, int *poutbuf_size,                           const uint8_t *buf, int buf_size){    ParseContext *pc = s->priv_data;    int next;    next= h263_find_frame_end(pc, buf, buf_size);    if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) {        *poutbuf = NULL;        *poutbuf_size = 0;        return buf_size;    }    *poutbuf = (uint8_t *)buf;    *poutbuf_size = buf_size;    return next;}int ff_h263_decode_frame(AVCodecContext *avctx,                             void *data, int *data_size,                             uint8_t *buf, int buf_size){    MpegEncContext *s = avctx->priv_data;    int ret;    AVFrame *pict = data;#ifdef PRINT_FRAME_TIMEuint64_t time= rdtsc();#endif#ifdef DEBUG    printf("*****frame %d size=%d\n", avctx->frame_number, buf_size);    printf("bytes=%x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]);#endif    s->flags= avctx->flags;    s->flags2= avctx->flags2;    /* no supplementary picture */    if (buf_size == 0) {        /* special case for last picture */        if (s->low_delay==0 && s->next_picture_ptr) {            *pict= *(AVFrame*)s->next_picture_ptr;            s->next_picture_ptr= NULL;            *data_size = sizeof(AVFrame);        }        return 0;    }    if(s->flags&CODEC_FLAG_TRUNCATED){        int next;        if(s->codec_id==CODEC_ID_MPEG4){

⌨️ 快捷键说明

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