diff options
Diffstat (limited to 'src/libffmpeg/libavcodec/h263dec.c')
-rw-r--r-- | src/libffmpeg/libavcodec/h263dec.c | 100 |
1 files changed, 93 insertions, 7 deletions
diff --git a/src/libffmpeg/libavcodec/h263dec.c b/src/libffmpeg/libavcodec/h263dec.c index 4a1c3dcd5..69e161766 100644 --- a/src/libffmpeg/libavcodec/h263dec.c +++ b/src/libffmpeg/libavcodec/h263dec.c @@ -60,7 +60,6 @@ static int h263_decode_init(AVCodecContext *avctx) switch(avctx->codec->id) { case CODEC_ID_H263: s->gob_number = 0; - s->first_slice_line = 0; break; case CODEC_ID_MPEG4: s->time_increment_bits = 4; /* default value for broken headers */ @@ -126,9 +125,14 @@ static int h263_decode_end(AVCodecContext *avctx) */ static int get_consumed_bytes(MpegEncContext *s, int buf_size){ int pos= (get_bits_count(&s->gb)+7)>>3; + if(s->divx_version>=500){ //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 ;) @@ -191,7 +195,7 @@ static int decode_slice(MpegEncContext *s){ } /* DCT & quantize */ - clear_blocks(s->block[0]); + s->dsp.clear_blocks(s->block[0]); s->mv_dir = MV_DIR_FORWARD; s->mv_type = MV_TYPE_16X16; @@ -252,10 +256,10 @@ static int decode_slice(MpegEncContext *s){ if(bits_left==0 || bits_left>8){ s->padding_bug_score++; - } else { + } 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 @@ -300,6 +304,43 @@ static int decode_slice(MpegEncContext *s){ 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 *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; + } + } + } + + 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 -1; +} + static int h263_decode_frame(AVCodecContext *avctx, void *data, int *data_size, UINT8 *buf, int buf_size) @@ -326,6 +367,42 @@ uint64_t time= rdtsc(); if (buf_size == 0) { return 0; } + + if(s->flags&CODEC_FLAG_TRUNCATED){ + int next; + ParseContext *pc= &s->parse_context; + + pc->last_index= pc->index; + + if(s->codec_id==CODEC_ID_MPEG4){ + next= mpeg4_find_frame_end(s, buf, buf_size); + }else{ + fprintf(stderr, "this codec doesnt support truncated bitstreams\n"); + return -1; + } + if(next==-1){ + if(buf_size + FF_INPUT_BUFFER_PADDING_SIZE + pc->index > pc->buffer_size){ + pc->buffer_size= buf_size + pc->index + 10*1024; + pc->buffer= realloc(pc->buffer, pc->buffer_size); + } + + memcpy(&pc->buffer[pc->index], buf, buf_size); + pc->index += buf_size; + return buf_size; + } + + if(pc->index){ + if(next + FF_INPUT_BUFFER_PADDING_SIZE + pc->index > pc->buffer_size){ + pc->buffer_size= next + pc->index + 10*1024; + pc->buffer= realloc(pc->buffer, pc->buffer_size); + } + + memcpy(&pc->buffer[pc->index], buf, next + FF_INPUT_BUFFER_PADDING_SIZE ); + pc->index = 0; + buf= pc->buffer; + buf_size= pc->last_index + next; + } + } retry: @@ -352,6 +429,9 @@ retry: } ret = ff_mpeg4_decode_picture_header(s, &s->gb); + if(s->flags& CODEC_FLAG_LOW_DELAY) + s->low_delay=1; + s->has_b_frames= !s->low_delay; } else if (s->h263_intel) { ret = intel_h263_decode_picture_header(s); @@ -445,10 +525,16 @@ retry: fprintf(stderr, "header damaged\n"); return -1; } + + s->avctx->key_frame = (s->pict_type == I_TYPE); + s->avctx->pict_type = s->pict_type; + /* skip b frames if we dont have reference frames */ if(s->num_available_buffers<2 && s->pict_type==B_TYPE) return get_consumed_bytes(s, buf_size); /* skip b frames if we are in a hurry */ if(s->hurry_up && s->pict_type==B_TYPE) return get_consumed_bytes(s, buf_size); + /* skip everything if we are in a hurry>=5 */ + if(s->hurry_up>=5) return get_consumed_bytes(s, buf_size); if(s->next_p_frame_damaged){ if(s->pict_type==B_TYPE) @@ -479,7 +565,7 @@ retry: decode_slice(s); s->error_status_table[0]|= VP_START; - while(s->mb_y<s->mb_height && s->gb.size*8 - get_bits_count(&s->gb)>32){ + while(s->mb_y<s->mb_height && s->gb.size*8 - get_bits_count(&s->gb)>16){ if(s->msmpeg4_version){ if(s->mb_x!=0 || (s->mb_y%s->slice_height)!=0) break; @@ -545,7 +631,7 @@ retry: num_end_markers--; } if(num_end_markers || error){ -// fprintf(stderr, "concealing errors\n"); + fprintf(stderr, "concealing errors\n"); //printf("type:%d\n", s->pict_type); ff_error_resilience(s); } @@ -625,7 +711,7 @@ AVCodec mpeg4_decoder = { NULL, h263_decode_end, h263_decode_frame, - CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED, }; AVCodec h263_decoder = { |