mirror of
https://git.videolan.org/git/ffmpeg.git
synced 2024-08-18 07:15:04 +02:00
error concealment / error resilience
merging s->first_gob_line & s->first_slice_line Originally committed as revision 640 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
92073d01ca
commit
6733417a5f
@ -49,7 +49,7 @@ static int h263_decode_init(AVCodecContext *avctx)
|
||||
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 */
|
||||
@ -122,7 +122,9 @@ uint64_t time= rdtsc();
|
||||
#endif
|
||||
|
||||
s->hurry_up= avctx->hurry_up;
|
||||
|
||||
s->error_resilience= avctx->error_resilience;
|
||||
s->workaround_bugs= avctx->workaround_bugs;
|
||||
|
||||
/* no supplementary picture */
|
||||
if (buf_size == 0) {
|
||||
*data_size = 0;
|
||||
@ -165,19 +167,33 @@ uint64_t time= rdtsc();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
#ifdef DEBUG
|
||||
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]=
|
||||
@ -190,7 +206,13 @@ uint64_t time= rdtsc();
|
||||
/* 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;
|
||||
@ -209,9 +231,40 @@ uint64_t time= rdtsc();
|
||||
#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_pred && s->msmpeg4_version!=2) {
|
||||
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);
|
||||
@ -222,22 +275,48 @@ uint64_t time= rdtsc();
|
||||
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
|
||||
&& (s->num_available_buffers>=1 || (!s->has_b_frames)) ) {
|
||||
@ -267,11 +346,40 @@ uint64_t time= rdtsc();
|
||||
|
||||
/* 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)/8;
|
||||
int current_pos= get_bits_count(&s->gb)>>3;
|
||||
|
||||
if( buf_size - current_pos > 5
|
||||
&& buf_size - current_pos < BITSTREAM_BUFFER_SIZE){
|
||||
memcpy(s->bitstream_buffer, buf + current_pos, buf_size - current_pos);
|
||||
s->bitstream_buffer_size= buf_size - current_pos;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user