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

📄 h263dec.c

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * H.263 decoder * Copyright (c) 2001 Fabrice Bellard. * * 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 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->width;    s->height = avctx->height;    s->workaround_bugs= avctx->workaround_bugs;    // set defaults    s->quant_precision=5;    s->progressive_sequence=1;    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->gob_number = 0;        break;    case CODEC_ID_MPEG4:        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_H263I:        s->h263_intel = 1;        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;}/** * retunrs 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;    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;    s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];    s->c_dc_scale= s->c_dc_scale_table[ 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;        s->qscale= qscale;        s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];        s->c_dc_scale= s->c_dc_scale_table[ 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->dsp.clear_blocks(s->block[0]);                        s->mv_dir = MV_DIR_FORWARD;            s->mv_type = MV_TYPE_16X16;//            s->mb_skiped = 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);//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*16, 16);                        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);        }                ff_draw_horiz_band(s, s->mb_y*16, 16);                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>8){            s->padding_bug_score++;        } else if(bits_left != 1){            int v= show_bits(&s->gb, 8);            v|= 0x7F >> (7-(bits_count&7));            if(v==0x7F)                s->padding_bug_score--;            else                s->padding_bug_score++;                    }                              }    // handle formats which dont 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 */static int mpeg4_find_frame_end(MpegEncContext *s, uint8_t *buf, int buf_size){    ParseContext *pc= &s->parse_context;    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){          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(MpegEncContext *s, uint8_t *buf, int buf_size){    ParseContext *pc= &s->parse_context;    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;}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;    *data_size = 0;    /* 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){            next= mpeg4_find_frame_end(s, buf, buf_size);        }else if(s->codec_id==CODEC_ID_H263){            next= h263_find_frame_end(s, buf, buf_size);        }else{

⌨️ 快捷键说明

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