diff options
Diffstat (limited to 'src/libffmpeg/libavcodec/h263dec.c')
-rw-r--r-- | src/libffmpeg/libavcodec/h263dec.c | 297 |
1 files changed, 247 insertions, 50 deletions
diff --git a/src/libffmpeg/libavcodec/h263dec.c b/src/libffmpeg/libavcodec/h263dec.c index e909ac56e..3c90a1e47 100644 --- a/src/libffmpeg/libavcodec/h263dec.c +++ b/src/libffmpeg/libavcodec/h263dec.c @@ -1,53 +1,60 @@ /* * H263 decoder - * Copyright (c) 2001 Gerard Lantau. + * Copyright (c) 2001 Fabrice Bellard. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU 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 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 program is distributed in the hope that it will be useful, + * 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 General Public License for more details. + * 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 General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * 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 */ -#include "config.h" -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "dsputil.h" #include "avcodec.h" +#include "dsputil.h" #include "mpegvideo.h" -#include "xine-utils/xineutils.h" //#define DEBUG +//#define PRINT_FRAME_TIME +#ifdef PRINT_FRAME_TIME +static inline long long rdtsc() +{ + long long l; + asm volatile( "rdtsc\n\t" + : "=A" (l) + ); +// printf("%d\n", int(l/1000)); + return l; +} +#endif static int h263_decode_init(AVCodecContext *avctx) { MpegEncContext *s = avctx->priv_data; - int i; s->avctx = avctx; s->out_format = FMT_H263; s->width = avctx->width; s->height = avctx->height; + s->workaround_bugs= avctx->workaround_bugs; /* select sub codec */ switch(avctx->codec->id) { case CODEC_ID_H263: s->gob_number = 0; - s->first_gob_line = 0; + s->first_slice_line = 0; break; case CODEC_ID_MPEG4: s->time_increment_bits = 4; /* default value for broken headers */ s->h263_pred = 1; - s->has_b_frames = 1; + s->has_b_frames = 1; //default, might be overriden in the vol header during header parsing break; case CODEC_ID_MSMPEG4V1: s->h263_msmpeg4 = 1; @@ -64,23 +71,25 @@ static int h263_decode_init(AVCodecContext *avctx) 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_H263I: s->h263_intel = 1; break; default: return -1; } - + s->codec_id= avctx->codec->id; + avctx->mbskip_table= s->mbskip_table; + /* 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; - /* XXX: suppress this matrix init, only needed because using mpeg1 - dequantize in mmx case */ - for(i=0;i<64;i++) - s->non_intra_matrix[i] = default_non_intra_matrix[i]; - if (s->h263_msmpeg4) msmpeg4_decode_init_vlc(s); else @@ -104,25 +113,37 @@ static int h263_decode_frame(AVCodecContext *avctx, MpegEncContext *s = avctx->priv_data; int ret; AVPicture *pict = data; - +#ifdef PRINT_FRAME_TIME +uint64_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->hurry_up= avctx->hurry_up; + s->error_resilience= avctx->error_resilience; + s->workaround_bugs= avctx->workaround_bugs; + s->flags= avctx->flags; + /* no supplementary picture */ if (buf_size == 0) { *data_size = 0; return 0; } - init_get_bits(&s->gb, buf, buf_size); + if(s->bitstream_buffer_size && buf_size<20){ //divx 5.01+ frame reorder + init_get_bits(&s->gb, s->bitstream_buffer, s->bitstream_buffer_size); + }else + init_get_bits(&s->gb, buf, buf_size); + s->bitstream_buffer_size=0; /* let's go :-) */ if (s->h263_msmpeg4) { ret = msmpeg4_decode_picture_header(s); } else if (s->h263_pred) { ret = mpeg4_decode_picture_header(s); + s->has_b_frames= !s->low_delay; } else if (s->h263_intel) { ret = intel_h263_decode_picture_header(s); } else { @@ -146,8 +167,21 @@ static int h263_decode_frame(AVCodecContext *avctx, return -1; } + if(ret==FRAME_SKIPED) return 0; + /* skip if the header was thrashed */ if (ret < 0) return -1; + /* skip b frames if we dont have reference frames */ + if(s->num_available_buffers<2 && s->pict_type==B_TYPE) return 0; + /* skip b frames if we are in a hurry */ + if(s->hurry_up && s->pict_type==B_TYPE) return 0; + + if(s->next_p_frame_damaged){ + if(s->pict_type==B_TYPE) + return 0; + else + s->next_p_frame_damaged=0; + } MPV_frame_start(s); @@ -155,6 +189,12 @@ static int h263_decode_frame(AVCodecContext *avctx, printf("qscale=%d\n", s->qscale); #endif + /* init resync/ error resilience specific variables */ + s->next_resync_qscale= s->qscale; + s->next_resync_gb= s->gb; + if(s->resync_marker) s->mb_num_left= 0; + else s->mb_num_left= s->mb_num; + /* decode each macroblock */ s->block_wrap[0]= s->block_wrap[1]= @@ -167,7 +207,13 @@ static int h263_decode_frame(AVCodecContext *avctx, /* FIXME: In the future H.263+ will have intra prediction */ /* and we are gonna need another way to detect MPEG4 */ if (s->mb_y && !s->h263_pred) { - s->first_gob_line = h263_decode_gob_header(s); + s->first_slice_line = h263_decode_gob_header(s); + } + + if(s->msmpeg4_version==1){ + s->last_dc[0]= + s->last_dc[1]= + s->last_dc[2]= 128; } s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1; @@ -186,35 +232,95 @@ static int h263_decode_frame(AVCodecContext *avctx, #ifdef DEBUG printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y); #endif + + if(s->resync_marker){ + if(s->mb_num_left<=0){ + /* except the first block */ + if(s->mb_x!=0 || s->mb_y!=0){ + /* did we miss the next resync marker without noticing an error yet */ + if(((get_bits_count(&s->gb)+8)&(~7)) != s->next_resync_pos && s->decoding_error==0){ + fprintf(stderr, "slice end missmatch x:%d y:%d %d %d\n", + s->mb_x, s->mb_y, get_bits_count(&s->gb), s->next_resync_pos); + ff_conceal_past_errors(s, 1); + } + } + s->qscale= s->next_resync_qscale; + s->gb= s->next_resync_gb; + s->resync_mb_x= s->mb_x; //we know that the marker is here cuz mb_num_left was the distance to it + s->resync_mb_y= s->mb_y; + s->first_slice_line=1; + + if(s->codec_id==CODEC_ID_MPEG4){ + ff_mpeg4_clean_buffers(s); + ff_mpeg4_resync(s); + } + } + + if( s->resync_mb_x==s->mb_x + && s->resync_mb_y==s->mb_y && s->decoding_error!=0){ + fprintf(stderr, "resynced at %d %d\n", s->mb_x, s->mb_y); + s->decoding_error= 0; + } + } + //fprintf(stderr,"\nFrame: %d\tMB: %d",avctx->frame_number, (s->mb_y * s->mb_width) + s->mb_x); /* DCT & quantize */ - if (s->h263_msmpeg4) { - msmpeg4_dc_scale(s); - } else if (s->h263_pred) { - h263_dc_scale(s); + if (s->h263_pred && !(s->msmpeg4_version==1 || s->msmpeg4_version==2)) { + /* old ffmpeg encoded msmpeg4v3 workaround */ + if(s->workaround_bugs==1 && s->msmpeg4_version==3) + ff_old_msmpeg4_dc_scale(s); + else + h263_dc_scale(s); } else { /* default quantization values */ s->y_dc_scale = 8; s->c_dc_scale = 8; } - clear_blocks(s->block[0]); + + if(s->decoding_error!=DECODING_DESYNC){ + int last_error= s->decoding_error; + clear_blocks(s->block[0]); - s->mv_dir = MV_DIR_FORWARD; - s->mv_type = MV_TYPE_16X16; - if (s->h263_msmpeg4) { - if (msmpeg4_decode_mb(s, s->block) < 0) { - fprintf(stderr,"\nError at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x); - return -1; - } - } else { - if (h263_decode_mb(s, s->block) < 0) { - fprintf(stderr,"\nError at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x); - return -1; + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + if (s->h263_msmpeg4) { + if (msmpeg4_decode_mb(s, s->block) < 0) { + fprintf(stderr,"Error at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x); + s->decoding_error=DECODING_DESYNC; + } + } else { + if (h263_decode_mb(s, s->block) < 0) { + fprintf(stderr,"Error at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x); + s->decoding_error=DECODING_DESYNC; + } + } + + if(s->decoding_error!=last_error){ + ff_conceal_past_errors(s, 0); } } + + /* conceal errors */ + if( s->decoding_error==DECODING_DESYNC + || (s->decoding_error==DECODING_ACDC_LOST && s->mb_intra)){ + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mb_skiped=0; + s->mb_intra=0; + s->mv[0][0][0]=0; //FIXME this is not optimal + s->mv[0][0][1]=0; + clear_blocks(s->block[0]); + }else if(s->decoding_error && !s->mb_intra){ + clear_blocks(s->block[0]); + } + //FIXME remove AC for intra + MPV_decode_mb(s, s->block); + + s->mb_num_left--; } - if (avctx->draw_horiz_band) { + if ( avctx->draw_horiz_band + && (s->num_available_buffers>=1 || (!s->has_b_frames)) ) { UINT8 *src_ptr[3]; int y, h, offset; y = s->mb_y * 16; @@ -236,11 +342,84 @@ static int h263_decode_frame(AVCodecContext *avctx, } } - if (s->h263_msmpeg4 && s->pict_type==I_TYPE) + if (s->h263_msmpeg4 && s->msmpeg4_version<4 && s->pict_type==I_TYPE) if(msmpeg4_decode_ext_header(s, buf_size) < 0) return -1; + + /* divx 5.01+ bistream reorder stuff */ + if(s->codec_id==CODEC_ID_MPEG4 && s->bitstream_buffer_size==0){ + int current_pos= get_bits_count(&s->gb)>>3; + if( buf_size - current_pos > 5 + && buf_size - current_pos < BITSTREAM_BUFFER_SIZE){ + int i; + int startcode_found=0; + for(i=current_pos; i<buf_size; i++){ + if(buf[i]==0 && buf[i+1]==0 && buf[i+2]==1 && buf[i+3]==0xB6){ + startcode_found=1; + break; + } + } + if(startcode_found){ + memcpy(s->bitstream_buffer, buf + current_pos, buf_size - current_pos); + s->bitstream_buffer_size= buf_size - current_pos; + } + } + } + + if(s->bitstream_buffer_size==0 && s->error_resilience>0){ + int left= s->gb.size*8 - get_bits_count(&s->gb); + int max_extra=8; + + if(s->codec_id==CODEC_ID_MPEG4) max_extra+=32; + + if(left>max_extra){ + fprintf(stderr, "discarding %d junk bits at end, next would be %X\n", left, show_bits(&s->gb, 24)); + if(s->decoding_error==0) + ff_conceal_past_errors(s, 1); + } + if(left<0){ + fprintf(stderr, "overreading %d bits\n", -left); + if(s->decoding_error==0) + ff_conceal_past_errors(s, 1); + } + } + MPV_frame_end(s); - +#if 0 //dirty show MVs, we should export the MV tables and write a filter to show them +{ + int mb_y; + s->has_b_frames=1; + for(mb_y=0; mb_y<s->mb_height; mb_y++){ + int mb_x; + int y= mb_y*16 + 8; + for(mb_x=0; mb_x<s->mb_width; mb_x++){ + int x= mb_x*16 + 8; + uint8_t *ptr= s->last_picture[0]; + int xy= 1 + mb_x*2 + (mb_y*2 + 1)*(s->mb_width*2 + 2); + int mx= (s->motion_val[xy][0]>>1) + x; + int my= (s->motion_val[xy][1]>>1) + y; + int i; + int max; + + if(mx<0) mx=0; + if(my<0) my=0; + if(mx>=s->width) mx= s->width -1; + if(my>=s->height) my= s->height-1; + max= ABS(mx-x); + if(ABS(my-y) > max) max= ABS(my-y); + /* the ugliest linedrawing routine ... */ + for(i=0; i<max; i++){ + int x1= x + (mx-x)*i/max; + int y1= y + (my-y)*i/max; + ptr[y1*s->linesize + x1]+=100; + } + ptr[y*s->linesize + x]+=100; + s->mbskip_table[mb_x + mb_y*s->mb_width]=0; + } + } + +} +#endif if(s->pict_type==B_TYPE || (!s->has_b_frames)){ pict->data[0] = s->current_picture[0]; pict->data[1] = s->current_picture[1]; @@ -260,7 +439,13 @@ static int h263_decode_frame(AVCodecContext *avctx, /* we substract 1 because it is added on utils.c */ avctx->frame_number = s->picture_number - 1; - *data_size = sizeof(AVPicture); + /* dont output the last pic after seeking + note we allready added +1 for the current pix in MPV_frame_end(s) */ + if(s->num_available_buffers>=2 || (!s->has_b_frames)) + *data_size = sizeof(AVPicture); +#ifdef PRINT_FRAME_TIME +printf("%Ld\n", rdtsc()-time); +#endif return buf_size; } @@ -324,6 +509,18 @@ AVCodec msmpeg4v3_decoder = { CODEC_CAP_DRAW_HORIZ_BAND, }; +AVCodec wmv1_decoder = { + "wmv1", + CODEC_TYPE_VIDEO, + CODEC_ID_WMV1, + sizeof(MpegEncContext), + h263_decode_init, + NULL, + h263_decode_end, + h263_decode_frame, + CODEC_CAP_DRAW_HORIZ_BAND, +}; + AVCodec h263i_decoder = { "h263i", CODEC_TYPE_VIDEO, |