2 * Error resilience / concealment
4 * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "mpegvideo.h"
26 * replaces the current MB with a flat dc only version.
28 static void put_dc(MpegEncContext
*s
, uint8_t *dest_y
, uint8_t *dest_cb
, uint8_t *dest_cr
, int mb_x
, int mb_y
)
30 int dc
, dcu
, dcv
, y
, i
;
32 dc
= s
->dc_val
[0][mb_x
*2+1 + (i
&1) + (mb_y
*2+1 + (i
>>1))*(s
->mb_width
*2+2)];
34 else if(dc
>2040) dc
=2040;
38 dest_y
[x
+ (i
&1)*8 + (y
+ (i
>>1)*8)*s
->linesize
]= dc
/8;
42 dcu
= s
->dc_val
[1][mb_x
+1 + (mb_y
+1)*(s
->mb_width
+2)];
43 dcv
= s
->dc_val
[2][mb_x
+1 + (mb_y
+1)*(s
->mb_width
+2)];
45 else if(dcu
>2040) dcu
=2040;
47 else if(dcv
>2040) dcv
=2040;
51 dest_cb
[x
+ y
*(s
->uvlinesize
)]= dcu
/8;
52 dest_cr
[x
+ y
*(s
->uvlinesize
)]= dcv
/8;
57 static void filter181(INT16
*data
, int width
, int height
, int stride
){
60 /* horizontal filter */
61 for(y
=1; y
<height
-1; y
++){
62 int prev_dc
= data
[0 + y
*stride
];
64 for(x
=1; x
<width
-1; x
++){
68 + data
[x
+ y
*stride
]*8
69 - data
[x
+ 1 + y
*stride
];
70 dc
= (dc
*10923 + 32768)>>16;
71 prev_dc
= data
[x
+ y
*stride
];
72 data
[x
+ y
*stride
]= dc
;
77 for(x
=1; x
<width
-1; x
++){
80 for(y
=1; y
<height
-1; y
++){
84 + data
[x
+ y
*stride
]*8
85 - data
[x
+ (y
+1)*stride
];
86 dc
= (dc
*10923 + 32768)>>16;
87 prev_dc
= data
[x
+ y
*stride
];
88 data
[x
+ y
*stride
]= dc
;
94 * guess the dc of blocks which dont have a undamaged dc
95 * @param w width in 8 pixel blocks
96 * @param h height in 8 pixel blocks
98 static void guess_dc(MpegEncContext
*s
, INT16
*dc
, int w
, int h
, int stride
, int is_luma
){
101 for(b_y
=0; b_y
<h
; b_y
++){
102 for(b_x
=0; b_x
<w
; b_x
++){
103 int color
[4]={1024,1024,1024,1024};
104 int distance
[4]={9999,9999,9999,9999};
105 int mb_index
, error
, j
;
106 INT64 guess
, weight_sum
;
108 mb_index
= (b_x
>>is_luma
) + (b_y
>>is_luma
)*s
->mb_width
;
110 error
= s
->error_status_table
[mb_index
];
112 if(!(s
->mb_type
[mb_index
]&MB_TYPE_INTRA
)) continue; //inter
113 if(!(error
&DC_ERROR
)) continue; //dc-ok
116 for(j
=b_x
+1; j
<w
; j
++){
117 int mb_index_j
= (j
>>is_luma
) + (b_y
>>is_luma
)*s
->mb_width
;
118 int error_j
= s
->error_status_table
[mb_index_j
];
119 int intra_j
= s
->mb_type
[mb_index_j
]&MB_TYPE_INTRA
;
120 if(intra_j
==0 || !(error_j
&DC_ERROR
)){
121 color
[0]= dc
[j
+ b_y
*stride
];
128 for(j
=b_x
-1; j
>=0; j
--){
129 int mb_index_j
= (j
>>is_luma
) + (b_y
>>is_luma
)*s
->mb_width
;
130 int error_j
= s
->error_status_table
[mb_index_j
];
131 int intra_j
= s
->mb_type
[mb_index_j
]&MB_TYPE_INTRA
;
132 if(intra_j
==0 || !(error_j
&DC_ERROR
)){
133 color
[1]= dc
[j
+ b_y
*stride
];
140 for(j
=b_y
+1; j
<h
; j
++){
141 int mb_index_j
= (b_x
>>is_luma
) + (j
>>is_luma
)*s
->mb_width
;
142 int error_j
= s
->error_status_table
[mb_index_j
];
143 int intra_j
= s
->mb_type
[mb_index_j
]&MB_TYPE_INTRA
;
144 if(intra_j
==0 || !(error_j
&DC_ERROR
)){
145 color
[2]= dc
[b_x
+ j
*stride
];
152 for(j
=b_y
-1; j
>=0; j
--){
153 int mb_index_j
= (b_x
>>is_luma
) + (j
>>is_luma
)*s
->mb_width
;
154 int error_j
= s
->error_status_table
[mb_index_j
];
155 int intra_j
= s
->mb_type
[mb_index_j
]&MB_TYPE_INTRA
;
156 if(intra_j
==0 || !(error_j
&DC_ERROR
)){
157 color
[3]= dc
[b_x
+ j
*stride
];
166 INT64 weight
= 256*256*256*16/distance
[j
];
167 guess
+= weight
*(INT64
)color
[j
];
170 guess
= (guess
+ weight_sum
/2) / weight_sum
;
172 dc
[b_x
+ b_y
*stride
]= guess
;
178 * simple horizontal deblocking filter used for error resilience
179 * @param w width in 8 pixel blocks
180 * @param h height in 8 pixel blocks
182 static void h_block_filter(MpegEncContext
*s
, UINT8
*dst
, int w
, int h
, int stride
, int is_luma
){
184 UINT8
*cm
= cropTbl
+ MAX_NEG_CROP
;
186 for(b_y
=0; b_y
<h
; b_y
++){
187 for(b_x
=0; b_x
<w
-1; b_x
++){
189 int left_status
= s
->error_status_table
[( b_x
>>is_luma
) + (b_y
>>is_luma
)*s
->mb_width
];
190 int right_status
= s
->error_status_table
[((b_x
+1)>>is_luma
) + (b_y
>>is_luma
)*s
->mb_width
];
191 int left_intra
= s
->mb_type
[( b_x
>>is_luma
) + (b_y
>>is_luma
)*s
->mb_width
]&MB_TYPE_INTRA
;
192 int right_intra
= s
->mb_type
[((b_x
+1)>>is_luma
) + (b_y
>>is_luma
)*s
->mb_width
]&MB_TYPE_INTRA
;
193 int left_damage
= left_status
&(DC_ERROR
|AC_ERROR
|MV_ERROR
);
194 int right_damage
= right_status
&(DC_ERROR
|AC_ERROR
|MV_ERROR
);
195 int offset
= b_x
*8 + b_y
*stride
*8;
196 INT16
*left_mv
= s
->motion_val
[s
->block_wrap
[0]*((b_y
<<(1-is_luma
)) + 1) + ( b_x
<<(1-is_luma
))];
197 INT16
*right_mv
= s
->motion_val
[s
->block_wrap
[0]*((b_y
<<(1-is_luma
)) + 1) + ((b_x
+1)<<(1-is_luma
))];
199 if(!(left_damage
||right_damage
)) continue; // both undamaged
201 if( (!left_intra
) && (!right_intra
)
202 && ABS(left_mv
[0]-right_mv
[0]) + ABS(left_mv
[1]+right_mv
[1]) < 2) continue;
207 a
= dst
[offset
+ 7 + y
*stride
] - dst
[offset
+ 6 + y
*stride
];
208 b
= dst
[offset
+ 8 + y
*stride
] - dst
[offset
+ 7 + y
*stride
];
209 c
= dst
[offset
+ 9 + y
*stride
] - dst
[offset
+ 8 + y
*stride
];
211 d
= ABS(b
) - ((ABS(a
) + ABS(c
) + 1)>>1);
217 if(!(left_damage
&& right_damage
))
221 dst
[offset
+ 7 + y
*stride
] = cm
[dst
[offset
+ 7 + y
*stride
] + ((d
*7)>>4)];
222 dst
[offset
+ 6 + y
*stride
] = cm
[dst
[offset
+ 6 + y
*stride
] + ((d
*5)>>4)];
223 dst
[offset
+ 5 + y
*stride
] = cm
[dst
[offset
+ 5 + y
*stride
] + ((d
*3)>>4)];
224 dst
[offset
+ 4 + y
*stride
] = cm
[dst
[offset
+ 4 + y
*stride
] + ((d
*1)>>4)];
227 dst
[offset
+ 8 + y
*stride
] = cm
[dst
[offset
+ 8 + y
*stride
] - ((d
*7)>>4)];
228 dst
[offset
+ 9 + y
*stride
] = cm
[dst
[offset
+ 9 + y
*stride
] - ((d
*5)>>4)];
229 dst
[offset
+ 10+ y
*stride
] = cm
[dst
[offset
+10 + y
*stride
] - ((d
*3)>>4)];
230 dst
[offset
+ 11+ y
*stride
] = cm
[dst
[offset
+11 + y
*stride
] - ((d
*1)>>4)];
238 * simple vertical deblocking filter used for error resilience
239 * @param w width in 8 pixel blocks
240 * @param h height in 8 pixel blocks
242 static void v_block_filter(MpegEncContext
*s
, UINT8
*dst
, int w
, int h
, int stride
, int is_luma
){
244 UINT8
*cm
= cropTbl
+ MAX_NEG_CROP
;
246 for(b_y
=0; b_y
<h
-1; b_y
++){
247 for(b_x
=0; b_x
<w
; b_x
++){
249 int top_status
= s
->error_status_table
[(b_x
>>is_luma
) + ( b_y
>>is_luma
)*s
->mb_width
];
250 int bottom_status
= s
->error_status_table
[(b_x
>>is_luma
) + ((b_y
+1)>>is_luma
)*s
->mb_width
];
251 int top_intra
= s
->mb_type
[(b_x
>>is_luma
) + ( b_y
>>is_luma
)*s
->mb_width
]&MB_TYPE_INTRA
;
252 int bottom_intra
= s
->mb_type
[(b_x
>>is_luma
) + ((b_y
+1)>>is_luma
)*s
->mb_width
]&MB_TYPE_INTRA
;
253 int top_damage
= top_status
&(DC_ERROR
|AC_ERROR
|MV_ERROR
);
254 int bottom_damage
= bottom_status
&(DC_ERROR
|AC_ERROR
|MV_ERROR
);
255 int offset
= b_x
*8 + b_y
*stride
*8;
256 INT16
*top_mv
= s
->motion_val
[s
->block_wrap
[0]*(( b_y
<<(1-is_luma
)) + 1) + (b_x
<<(1-is_luma
))];
257 INT16
*bottom_mv
= s
->motion_val
[s
->block_wrap
[0]*(((b_y
+1)<<(1-is_luma
)) + 1) + (b_x
<<(1-is_luma
))];
259 if(!(top_damage
||bottom_damage
)) continue; // both undamaged
261 if( (!top_intra
) && (!bottom_intra
)
262 && ABS(top_mv
[0]-bottom_mv
[0]) + ABS(top_mv
[1]+bottom_mv
[1]) < 2) continue;
267 a
= dst
[offset
+ x
+ 7*stride
] - dst
[offset
+ x
+ 6*stride
];
268 b
= dst
[offset
+ x
+ 8*stride
] - dst
[offset
+ x
+ 7*stride
];
269 c
= dst
[offset
+ x
+ 9*stride
] - dst
[offset
+ x
+ 8*stride
];
271 d
= ABS(b
) - ((ABS(a
) + ABS(c
)+1)>>1);
277 if(!(top_damage
&& bottom_damage
))
281 dst
[offset
+ x
+ 7*stride
] = cm
[dst
[offset
+ x
+ 7*stride
] + ((d
*7)>>4)];
282 dst
[offset
+ x
+ 6*stride
] = cm
[dst
[offset
+ x
+ 6*stride
] + ((d
*5)>>4)];
283 dst
[offset
+ x
+ 5*stride
] = cm
[dst
[offset
+ x
+ 5*stride
] + ((d
*3)>>4)];
284 dst
[offset
+ x
+ 4*stride
] = cm
[dst
[offset
+ x
+ 4*stride
] + ((d
*1)>>4)];
287 dst
[offset
+ x
+ 8*stride
] = cm
[dst
[offset
+ x
+ 8*stride
] - ((d
*7)>>4)];
288 dst
[offset
+ x
+ 9*stride
] = cm
[dst
[offset
+ x
+ 9*stride
] - ((d
*5)>>4)];
289 dst
[offset
+ x
+ 10*stride
] = cm
[dst
[offset
+ x
+ 10*stride
] - ((d
*3)>>4)];
290 dst
[offset
+ x
+ 11*stride
] = cm
[dst
[offset
+ x
+ 11*stride
] - ((d
*1)>>4)];
297 static void guess_mv(MpegEncContext
*s
){
298 UINT8 fixed
[s
->mb_num
];
301 #define MV_UNCHANGED 1
302 const int mb_width
= s
->mb_width
;
303 const int mb_height
= s
->mb_height
;
304 int i
, depth
, num_avail
;
307 for(i
=0; i
<s
->mb_num
; i
++){
309 int error
= s
->error_status_table
[i
];
311 if(s
->mb_type
[i
]&MB_TYPE_INTRA
) f
=MV_FROZEN
; //intra //FIXME check
312 if(!(error
&MV_ERROR
)) f
=MV_FROZEN
; //inter with undamaged MV
319 if((!(s
->avctx
->error_concealment
&FF_EC_GUESS_MVS
)) || num_avail
<= mb_width
/2){
322 for(mb_y
=0; mb_y
<s
->mb_height
; mb_y
++){
323 for(mb_x
=0; mb_x
<s
->mb_width
; mb_x
++){
326 if(s
->mb_type
[i
]&MB_TYPE_INTRA
) continue;
327 if(!(s
->error_status_table
[i
]&MV_ERROR
)) continue;
329 s
->mv_dir
= MV_DIR_FORWARD
;
331 s
->mv_type
= MV_TYPE_16X16
;
334 s
->dsp
.clear_blocks(s
->block
[0]);
340 MPV_decode_mb(s
, s
->block
);
346 for(depth
=0;; depth
++){
347 int changed
, pass
, none_left
;
351 for(pass
=0; (changed
|| pass
<2) && pass
<10; pass
++){
357 for(mb_y
=0; mb_y
<s
->mb_height
; mb_y
++){
358 for(mb_x
=0; mb_x
<s
->mb_width
; mb_x
++){
359 int mv_predictor
[8][2]={{0}};
362 int best_score
=256*256*256*64;
364 const int mot_stride
= mb_width
*2+2;
365 const int mot_index
= mb_x
*2 + 1 + (mb_y
*2+1)*mot_stride
;
366 int prev_x
= s
->motion_val
[mot_index
][0];
367 int prev_y
= s
->motion_val
[mot_index
][1];
370 if((mb_x
^mb_y
^pass
)&1) continue;
372 if(fixed
[i
]==MV_FROZEN
) continue;
375 if(mb_x
>0 && fixed
[i
-1 ]==MV_FROZEN
) j
=1;
376 if(mb_x
+1<mb_width
&& fixed
[i
+1 ]==MV_FROZEN
) j
=1;
377 if(mb_y
>0 && fixed
[i
-mb_width
]==MV_FROZEN
) j
=1;
378 if(mb_y
+1<mb_height
&& fixed
[i
+mb_width
]==MV_FROZEN
) j
=1;
382 if(mb_x
>0 && fixed
[i
-1 ]==MV_CHANGED
) j
=1;
383 if(mb_x
+1<mb_width
&& fixed
[i
+1 ]==MV_CHANGED
) j
=1;
384 if(mb_y
>0 && fixed
[i
-mb_width
]==MV_CHANGED
) j
=1;
385 if(mb_y
+1<mb_height
&& fixed
[i
+mb_width
]==MV_CHANGED
) j
=1;
386 if(j
==0 && pass
>1) continue;
390 if(mb_x
>0 && fixed
[i
-1]){
391 mv_predictor
[pred_count
][0]= s
->motion_val
[mot_index
- 2][0];
392 mv_predictor
[pred_count
][1]= s
->motion_val
[mot_index
- 2][1];
395 if(mb_x
+1<mb_width
&& fixed
[i
+1]){
396 mv_predictor
[pred_count
][0]= s
->motion_val
[mot_index
+ 2][0];
397 mv_predictor
[pred_count
][1]= s
->motion_val
[mot_index
+ 2][1];
400 if(mb_y
>0 && fixed
[i
-mb_width
]){
401 mv_predictor
[pred_count
][0]= s
->motion_val
[mot_index
- mot_stride
*2][0];
402 mv_predictor
[pred_count
][1]= s
->motion_val
[mot_index
- mot_stride
*2][1];
405 if(mb_y
+1<mb_height
&& fixed
[i
+mb_width
]){
406 mv_predictor
[pred_count
][0]= s
->motion_val
[mot_index
+ mot_stride
*2][0];
407 mv_predictor
[pred_count
][1]= s
->motion_val
[mot_index
+ mot_stride
*2][1];
410 if(pred_count
==0) continue;
413 int sum_x
=0, sum_y
=0;
414 int max_x
, max_y
, min_x
, min_y
;
416 for(j
=0; j
<pred_count
; j
++){
417 sum_x
+= mv_predictor
[j
][0];
418 sum_y
+= mv_predictor
[j
][1];
422 mv_predictor
[pred_count
][0] = sum_x
/j
;
423 mv_predictor
[pred_count
][1] = sum_y
/j
;
430 min_x
=min_y
=max_x
=max_y
=0;
432 for(j
=0; j
<pred_count
; j
++){
433 max_x
= FFMAX(max_x
, mv_predictor
[j
][0]);
434 max_y
= FFMAX(max_y
, mv_predictor
[j
][1]);
435 min_x
= FFMIN(min_x
, mv_predictor
[j
][0]);
436 min_y
= FFMIN(min_y
, mv_predictor
[j
][1]);
438 mv_predictor
[pred_count
+1][0] = sum_x
- max_x
- min_x
;
439 mv_predictor
[pred_count
+1][1] = sum_y
- max_y
- min_y
;
442 mv_predictor
[pred_count
+1][0] /= 2;
443 mv_predictor
[pred_count
+1][1] /= 2;
452 mv_predictor
[pred_count
][0]= s
->motion_val
[mot_index
][0];
453 mv_predictor
[pred_count
][1]= s
->motion_val
[mot_index
][1];
456 s
->mv_dir
= MV_DIR_FORWARD
;
458 s
->mv_type
= MV_TYPE_16X16
;
461 s
->dsp
.clear_blocks(s
->block
[0]);
465 for(j
=0; j
<pred_count
; j
++){
467 UINT8
*src
= s
->current_picture
.data
[0] + mb_x
*16 + mb_y
*16*s
->linesize
;
469 s
->motion_val
[mot_index
][0]= s
->mv
[0][0][0]= mv_predictor
[j
][0];
470 s
->motion_val
[mot_index
][1]= s
->mv
[0][0][1]= mv_predictor
[j
][1];
471 MPV_decode_mb(s
, s
->block
);
473 if(mb_x
>0 && fixed
[i
-1]){
476 score
+= ABS(src
[k
*s
->linesize
-1 ]-src
[k
*s
->linesize
]);
478 if(mb_x
+1<mb_width
&& fixed
[i
+1]){
481 score
+= ABS(src
[k
*s
->linesize
+15]-src
[k
*s
->linesize
+16]);
483 if(mb_y
>0 && fixed
[i
-mb_width
]){
486 score
+= ABS(src
[k
-s
->linesize
]-src
[k
]);
488 if(mb_y
+1<mb_height
&& fixed
[i
+mb_width
]){
491 score
+= ABS(src
[k
+s
->linesize
*15]-src
[k
+s
->linesize
*16]);
494 if(score
<= best_score
){ // <= will favor the last MV
499 score_sum
+= best_score
;
500 //FIXME no need to set s->motion_val[mot_index][0] explicit
501 s
->motion_val
[mot_index
][0]= s
->mv
[0][0][0]= mv_predictor
[best_pred
][0];
502 s
->motion_val
[mot_index
][1]= s
->mv
[0][0][1]= mv_predictor
[best_pred
][1];
504 MPV_decode_mb(s
, s
->block
);
507 if(s
->mv
[0][0][0] != prev_x
|| s
->mv
[0][0][1] != prev_y
){
511 fixed
[i
]=MV_UNCHANGED
;
515 // printf(".%d/%d", changed, score_sum); fflush(stdout);
521 for(i
=0; i
<s
->mb_num
; i
++){
525 // printf(":"); fflush(stdout);
529 static int is_intra_more_likely(MpegEncContext
*s
){
530 int is_intra_likely
, i
, j
, undamaged_count
, skip_amount
, mb_x
, mb_y
;
532 if(s
->last_picture
.data
[0]==NULL
) return 1; //no previous frame available -> use spatial prediction
535 for(i
=0; i
<s
->mb_num
; i
++){
536 int error
= s
->error_status_table
[i
];
537 if(!((error
&DC_ERROR
) && (error
&MV_ERROR
)))
541 if(undamaged_count
< 5) return 0; //allmost all MBs damaged -> use temporal prediction
543 skip_amount
= FFMAX(undamaged_count
/50, 1); //check only upto 50 MBs
548 for(mb_y
= 0; mb_y
<s
->mb_height
-1; mb_y
++){
549 for(mb_x
= 0; mb_x
<s
->mb_width
; mb_x
++){
553 error
= s
->error_status_table
[i
];
554 if((error
&DC_ERROR
) && (error
&MV_ERROR
))
555 continue; //skip damaged
558 if((j
%skip_amount
) != 0) continue; //skip a few to speed things up
560 if(s
->pict_type
==I_TYPE
){
561 UINT8
*mb_ptr
= s
->current_picture
.data
[0] + mb_x
*16 + mb_y
*16*s
->linesize
;
562 UINT8
*last_mb_ptr
= s
->last_picture
.data
[0] + mb_x
*16 + mb_y
*16*s
->linesize
;
564 is_intra_likely
+= s
->dsp
.pix_abs16x16(last_mb_ptr
, mb_ptr
, s
->linesize
);
565 is_intra_likely
-= s
->dsp
.pix_abs16x16(last_mb_ptr
, last_mb_ptr
+s
->linesize
*16, s
->linesize
);
567 if(s
->mbintra_table
[i
]) //HACK (this is allways inited but we should use mb_type[])
574 //printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
575 return is_intra_likely
> 0;
578 void ff_error_resilience(MpegEncContext
*s
){
579 int i
, mb_x
, mb_y
, error
, error_type
;
581 int threshold_part
[4]= {100,100,100};
586 /* handle overlapping slices */
587 for(error_type
=1; error_type
<=3; error_type
++){
590 for(i
=s
->mb_num
-1; i
>=0; i
--){
591 int error
= s
->error_status_table
[i
];
593 if(error
&(1<<error_type
))
595 if(error
&(8<<error_type
))
599 s
->error_status_table
[i
]|= 1<<error_type
;
607 /* handle slices with partitions of different length */
608 if(s
->partitioned_frame
){
611 for(i
=s
->mb_num
-1; i
>=0; i
--){
612 int error
= s
->error_status_table
[i
];
616 if((error
&MV_END
) || (error
&DC_END
) || (error
&AC_ERROR
))
620 s
->error_status_table
[i
]|= AC_ERROR
;
627 /* handle missing slices */
628 if(s
->error_resilience
>=4){
631 for(i
=s
->mb_num
-2; i
>=s
->mb_width
+100; i
--){ //FIXME +100 hack
632 int error1
= s
->error_status_table
[i
];
633 int error2
= s
->error_status_table
[i
+1];
638 if( error2
==(VP_START
|DC_ERROR
|AC_ERROR
|MV_ERROR
|AC_END
|DC_END
|MV_END
)
639 && error1
!=(VP_START
|DC_ERROR
|AC_ERROR
|MV_ERROR
|AC_END
|DC_END
|MV_END
)
640 && ((error1
&AC_END
) || (error1
&DC_END
) || (error1
&MV_END
))){ //end & uninited
645 s
->error_status_table
[i
]|= DC_ERROR
|AC_ERROR
|MV_ERROR
;
650 /* backward mark errors */
652 for(error_type
=1; error_type
<=3; error_type
++){
653 for(i
=s
->mb_num
-1; i
>=0; i
--){
654 int error
= s
->error_status_table
[i
];
656 if(!s
->mbskip_table
[i
]) //FIXME partition specific
658 if(error
&(1<<error_type
))
661 if(s
->partitioned_frame
){
662 if(distance
< threshold_part
[error_type
-1])
663 s
->error_status_table
[i
]|= 1<<error_type
;
665 if(distance
< threshold
)
666 s
->error_status_table
[i
]|= 1<<error_type
;
675 /* forward mark errors */
677 for(i
=0; i
<s
->mb_num
; i
++){
678 int old_error
= s
->error_status_table
[i
];
680 if(old_error
&VP_START
)
681 error
= old_error
& (DC_ERROR
|AC_ERROR
|MV_ERROR
);
683 error
|= old_error
& (DC_ERROR
|AC_ERROR
|MV_ERROR
);
684 s
->error_status_table
[i
]|= error
;
688 /* handle not partitioned case */
689 if(!s
->partitioned_frame
){
690 for(i
=0; i
<s
->mb_num
; i
++){
691 error
= s
->error_status_table
[i
];
692 if(error
&(AC_ERROR
|DC_ERROR
|MV_ERROR
))
693 error
|= AC_ERROR
|DC_ERROR
|MV_ERROR
;
694 s
->error_status_table
[i
]= error
;
698 is_intra_likely
= is_intra_more_likely(s
);
700 /* set unknown mb-type to most likely */
701 for(i
=0; i
<s
->mb_num
; i
++){
703 error
= s
->error_status_table
[i
];
704 if((error
&DC_ERROR
) && (error
&MV_ERROR
))
705 intra
= is_intra_likely
;
707 intra
= s
->mbintra_table
[i
];
710 s
->mb_type
[i
]|= MB_TYPE_INTRA
;
712 s
->mb_type
[i
]&= ~MB_TYPE_INTRA
;
715 /* handle inter blocks with damaged AC */
717 for(mb_y
=0; mb_y
<s
->mb_height
; mb_y
++){
718 for(mb_x
=0; mb_x
<s
->mb_width
; mb_x
++){
720 error
= s
->error_status_table
[i
];
722 if(s
->mb_type
[i
]&MB_TYPE_INTRA
) continue; //intra
723 if(error
&MV_ERROR
) continue; //inter with damaged MV
724 if(!(error
&AC_ERROR
)) continue; //undamaged inter
726 s
->mv_dir
= MV_DIR_FORWARD
;
729 if(s
->mb_type
[i
]&MB_TYPE_INTER4V
){
730 int mb_index
= mb_x
*2+1 + (mb_y
*2+1)*s
->block_wrap
[0];
732 s
->mv_type
= MV_TYPE_8X8
;
734 s
->mv
[0][j
][0] = s
->motion_val
[ mb_index
+ (j
&1) + (j
>>1)*s
->block_wrap
[0] ][0];
735 s
->mv
[0][j
][1] = s
->motion_val
[ mb_index
+ (j
&1) + (j
>>1)*s
->block_wrap
[0] ][1];
738 s
->mv_type
= MV_TYPE_16X16
;
739 s
->mv
[0][0][0] = s
->motion_val
[ mb_x
*2+1 + (mb_y
*2+1)*s
->block_wrap
[0] ][0];
740 s
->mv
[0][0][1] = s
->motion_val
[ mb_x
*2+1 + (mb_y
*2+1)*s
->block_wrap
[0] ][1];
743 s
->dsp
.clear_blocks(s
->block
[0]);
747 MPV_decode_mb(s
, s
->block
);
752 if(s
->pict_type
==B_TYPE
){
754 for(mb_y
=0; mb_y
<s
->mb_height
; mb_y
++){
755 for(mb_x
=0; mb_x
<s
->mb_width
; mb_x
++){
756 int xy
= mb_x
*2+1 + (mb_y
*2+1)*s
->block_wrap
[0];
758 error
= s
->error_status_table
[i
];
760 if(s
->mb_type
[i
]&MB_TYPE_INTRA
) continue; //intra
761 if(!(error
&MV_ERROR
)) continue; //inter with undamaged MV
762 if(!(error
&AC_ERROR
)) continue; //undamaged inter
764 s
->mv_dir
= MV_DIR_FORWARD
|MV_DIR_BACKWARD
;
766 s
->mv_type
= MV_TYPE_16X16
;
770 int time_pp
= s
->pp_time
;
771 int time_pb
= s
->pb_time
;
773 s
->mv
[0][0][0] = s
->motion_val
[xy
][0]*time_pb
/time_pp
;
774 s
->mv
[0][0][1] = s
->motion_val
[xy
][1]*time_pb
/time_pp
;
775 s
->mv
[1][0][0] = s
->motion_val
[xy
][0]*(time_pb
- time_pp
)/time_pp
;
776 s
->mv
[1][0][1] = s
->motion_val
[xy
][1]*(time_pb
- time_pp
)/time_pp
;
784 s
->dsp
.clear_blocks(s
->block
[0]);
787 MPV_decode_mb(s
, s
->block
);
793 /* fill DC for inter blocks */
795 for(mb_y
=0; mb_y
<s
->mb_height
; mb_y
++){
796 for(mb_x
=0; mb_x
<s
->mb_width
; mb_x
++){
797 int dc
, dcu
, dcv
, y
, n
;
799 UINT8
*dest_y
, *dest_cb
, *dest_cr
;
802 error
= s
->error_status_table
[i
];
804 if(s
->mb_type
[i
]&MB_TYPE_INTRA
) continue; //intra
805 // if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
807 dest_y
= s
->current_picture
.data
[0] + mb_x
*16 + mb_y
*16*s
->linesize
;
808 dest_cb
= s
->current_picture
.data
[1] + mb_x
*8 + mb_y
*8 *s
->uvlinesize
;
809 dest_cr
= s
->current_picture
.data
[2] + mb_x
*8 + mb_y
*8 *s
->uvlinesize
;
811 dc_ptr
= &s
->dc_val
[0][mb_x
*2+1 + (mb_y
*2+1)*(s
->mb_width
*2+2)];
817 dc
+= dest_y
[x
+ (n
&1)*8 + (y
+ (n
>>1)*8)*s
->linesize
];
820 dc_ptr
[(n
&1) + (n
>>1)*(s
->mb_width
*2+2)]= (dc
+4)>>3;
827 dcu
+=dest_cb
[x
+ y
*(s
->uvlinesize
)];
828 dcv
+=dest_cr
[x
+ y
*(s
->uvlinesize
)];
831 s
->dc_val
[1][mb_x
+1 + (mb_y
+1)*(s
->mb_width
+2)]= (dcu
+4)>>3;
832 s
->dc_val
[2][mb_x
+1 + (mb_y
+1)*(s
->mb_width
+2)]= (dcv
+4)>>3;
836 /* guess DC for damaged blocks */
837 guess_dc(s
, s
->dc_val
[0] + s
->mb_width
*2+3, s
->mb_width
*2, s
->mb_height
*2, s
->mb_width
*2+2, 1);
838 guess_dc(s
, s
->dc_val
[1] + s
->mb_width
+3, s
->mb_width
, s
->mb_height
, s
->mb_width
+2, 0);
839 guess_dc(s
, s
->dc_val
[2] + s
->mb_width
+3, s
->mb_width
, s
->mb_height
, s
->mb_width
+2, 0);
842 filter181(s
->dc_val
[0] + s
->mb_width
*2+3, s
->mb_width
*2, s
->mb_height
*2, s
->mb_width
*2+2);
845 /* render DC only intra */
847 for(mb_y
=0; mb_y
<s
->mb_height
; mb_y
++){
848 for(mb_x
=0; mb_x
<s
->mb_width
; mb_x
++){
849 UINT8
*dest_y
, *dest_cb
, *dest_cr
;
852 error
= s
->error_status_table
[i
];
854 if(!(s
->mb_type
[i
]&MB_TYPE_INTRA
)) continue; //inter
855 if(!(error
&AC_ERROR
)) continue; //undamaged
857 dest_y
= s
->current_picture
.data
[0] + mb_x
*16 + mb_y
*16*s
->linesize
;
858 dest_cb
= s
->current_picture
.data
[1] + mb_x
*8 + mb_y
*8 *s
->uvlinesize
;
859 dest_cr
= s
->current_picture
.data
[2] + mb_x
*8 + mb_y
*8 *s
->uvlinesize
;
861 put_dc(s
, dest_y
, dest_cb
, dest_cr
, mb_x
, mb_y
);
866 if(s
->avctx
->error_concealment
&FF_EC_DEBLOCK
){
867 /* filter horizontal block boundaries */
868 h_block_filter(s
, s
->current_picture
.data
[0], s
->mb_width
*2, s
->mb_height
*2, s
->linesize
, 1);
869 h_block_filter(s
, s
->current_picture
.data
[1], s
->mb_width
, s
->mb_height
, s
->uvlinesize
, 0);
870 h_block_filter(s
, s
->current_picture
.data
[2], s
->mb_width
, s
->mb_height
, s
->uvlinesize
, 0);
872 /* filter vertical block boundaries */
873 v_block_filter(s
, s
->current_picture
.data
[0], s
->mb_width
*2, s
->mb_height
*2, s
->linesize
, 1);
874 v_block_filter(s
, s
->current_picture
.data
[1], s
->mb_width
, s
->mb_height
, s
->uvlinesize
, 0);
875 v_block_filter(s
, s
->current_picture
.data
[2], s
->mb_width
, s
->mb_height
, s
->uvlinesize
, 0);
878 /* clean a few tables */
879 for(i
=0; i
<s
->mb_num
; i
++){
880 int error
= s
->error_status_table
[i
];
882 if(s
->pict_type
!=B_TYPE
&& (error
&(DC_ERROR
|MV_ERROR
|AC_ERROR
))){
883 s
->mbskip_table
[i
]=0;
885 s
->mbintra_table
[i
]=1;