2 * Error resilience / concealment
4 * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
6 * This file is part of FFmpeg.
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * @file libavcodec/error_resilience.c
25 * Error resilience / concealment.
32 #include "mpegvideo.h"
36 * H264 redefines mb_intra so it is not mistakely used (its uninitialized in h264)
37 * but error concealment must support both h264 and h263 thus we must undo this
41 static void decode_mb(MpegEncContext *s, int ref){
42 s->dest[0] = s->current_picture.data[0] + (s->mb_y * 16* s->linesize ) + s->mb_x * 16;
43 s->dest[1] = s->current_picture.data[1] + (s->mb_y * (16>>s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16>>s->chroma_x_shift);
44 s->dest[2] = s->current_picture.data[2] + (s->mb_y * (16>>s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16>>s->chroma_x_shift);
46 if(s->codec_id == CODEC_ID_H264){
47 H264Context *h= (void*)s;
48 h->mb_xy= s->mb_x + s->mb_y*s->mb_stride;
49 memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache));
51 if(ref >= h->ref_count[0]) //FIXME it is posible albeit uncommon that slice references differ between slices, we take the easy approuch and ignore it for now. If this turns out to have any relevance in practice then correct remapping should be added
53 fill_rectangle(&s->current_picture.ref_index[0][4*h->mb_xy], 2, 2, 2, ref, 1);
54 fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);
55 fill_rectangle(h->mv_cache[0][ scan8[0] ], 4, 4, 8, pack16to32(s->mv[0][0][0],s->mv[0][0][1]), 4);
57 ff_h264_hl_decode_mb(h);
60 MPV_decode_mb(s, s->block);
65 * @param stride the number of MVs to get to the next row
66 * @param mv_step the number of MVs per row or column in a macroblock
68 static void set_mv_strides(MpegEncContext *s, int *mv_step, int *stride){
69 if(s->codec_id == CODEC_ID_H264){
70 H264Context *h= (void*)s;
71 assert(s->quarter_sample);
76 *stride= s->b8_stride;
81 * replaces the current MB with a flat dc only version.
83 static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y)
85 int dc, dcu, dcv, y, i;
87 dc= s->dc_val[0][mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*s->b8_stride];
89 else if(dc>2040) dc=2040;
93 dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8;
97 dcu = s->dc_val[1][mb_x + mb_y*s->mb_stride];
98 dcv = s->dc_val[2][mb_x + mb_y*s->mb_stride];
100 else if(dcu>2040) dcu=2040;
102 else if(dcv>2040) dcv=2040;
106 dest_cb[x + y*(s->uvlinesize)]= dcu/8;
107 dest_cr[x + y*(s->uvlinesize)]= dcv/8;
112 static void filter181(int16_t *data, int width, int height, int stride){
115 /* horizontal filter */
116 for(y=1; y<height-1; y++){
117 int prev_dc= data[0 + y*stride];
119 for(x=1; x<width-1; x++){
123 + data[x + y*stride]*8
124 - data[x + 1 + y*stride];
125 dc= (dc*10923 + 32768)>>16;
126 prev_dc= data[x + y*stride];
127 data[x + y*stride]= dc;
131 /* vertical filter */
132 for(x=1; x<width-1; x++){
133 int prev_dc= data[x];
135 for(y=1; y<height-1; y++){
139 + data[x + y *stride]*8
140 - data[x + (y+1)*stride];
141 dc= (dc*10923 + 32768)>>16;
142 prev_dc= data[x + y*stride];
143 data[x + y*stride]= dc;
149 * guess the dc of blocks which do not have an undamaged dc
150 * @param w width in 8 pixel blocks
151 * @param h height in 8 pixel blocks
153 static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, int is_luma){
156 for(b_y=0; b_y<h; b_y++){
157 for(b_x=0; b_x<w; b_x++){
158 int color[4]={1024,1024,1024,1024};
159 int distance[4]={9999,9999,9999,9999};
160 int mb_index, error, j;
161 int64_t guess, weight_sum;
163 mb_index= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
165 error= s->error_status_table[mb_index];
167 if(IS_INTER(s->current_picture.mb_type[mb_index])) continue; //inter
168 if(!(error&DC_ERROR)) continue; //dc-ok
171 for(j=b_x+1; j<w; j++){
172 int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride;
173 int error_j= s->error_status_table[mb_index_j];
174 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
175 if(intra_j==0 || !(error_j&DC_ERROR)){
176 color[0]= dc[j + b_y*stride];
183 for(j=b_x-1; j>=0; j--){
184 int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride;
185 int error_j= s->error_status_table[mb_index_j];
186 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
187 if(intra_j==0 || !(error_j&DC_ERROR)){
188 color[1]= dc[j + b_y*stride];
195 for(j=b_y+1; j<h; j++){
196 int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
197 int error_j= s->error_status_table[mb_index_j];
198 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
199 if(intra_j==0 || !(error_j&DC_ERROR)){
200 color[2]= dc[b_x + j*stride];
207 for(j=b_y-1; j>=0; j--){
208 int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
209 int error_j= s->error_status_table[mb_index_j];
210 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
211 if(intra_j==0 || !(error_j&DC_ERROR)){
212 color[3]= dc[b_x + j*stride];
221 int64_t weight= 256*256*256*16/distance[j];
222 guess+= weight*(int64_t)color[j];
225 guess= (guess + weight_sum/2) / weight_sum;
227 dc[b_x + b_y*stride]= guess;
233 * simple horizontal deblocking filter used for error resilience
234 * @param w width in 8 pixel blocks
235 * @param h height in 8 pixel blocks
237 static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
238 int b_x, b_y, mvx_stride, mvy_stride;
239 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
240 set_mv_strides(s, &mvx_stride, &mvy_stride);
241 mvx_stride >>= is_luma;
242 mvy_stride *= mvx_stride;
244 for(b_y=0; b_y<h; b_y++){
245 for(b_x=0; b_x<w-1; b_x++){
247 int left_status = s->error_status_table[( b_x >>is_luma) + (b_y>>is_luma)*s->mb_stride];
248 int right_status= s->error_status_table[((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride];
249 int left_intra= IS_INTRA(s->current_picture.mb_type [( b_x >>is_luma) + (b_y>>is_luma)*s->mb_stride]);
250 int right_intra= IS_INTRA(s->current_picture.mb_type [((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride]);
251 int left_damage = left_status&(DC_ERROR|AC_ERROR|MV_ERROR);
252 int right_damage= right_status&(DC_ERROR|AC_ERROR|MV_ERROR);
253 int offset= b_x*8 + b_y*stride*8;
254 int16_t *left_mv= s->current_picture.motion_val[0][mvy_stride*b_y + mvx_stride* b_x ];
255 int16_t *right_mv= s->current_picture.motion_val[0][mvy_stride*b_y + mvx_stride*(b_x+1)];
257 if(!(left_damage||right_damage)) continue; // both undamaged
259 if( (!left_intra) && (!right_intra)
260 && FFABS(left_mv[0]-right_mv[0]) + FFABS(left_mv[1]+right_mv[1]) < 2) continue;
265 a= dst[offset + 7 + y*stride] - dst[offset + 6 + y*stride];
266 b= dst[offset + 8 + y*stride] - dst[offset + 7 + y*stride];
267 c= dst[offset + 9 + y*stride] - dst[offset + 8 + y*stride];
269 d= FFABS(b) - ((FFABS(a) + FFABS(c) + 1)>>1);
275 if(!(left_damage && right_damage))
279 dst[offset + 7 + y*stride] = cm[dst[offset + 7 + y*stride] + ((d*7)>>4)];
280 dst[offset + 6 + y*stride] = cm[dst[offset + 6 + y*stride] + ((d*5)>>4)];
281 dst[offset + 5 + y*stride] = cm[dst[offset + 5 + y*stride] + ((d*3)>>4)];
282 dst[offset + 4 + y*stride] = cm[dst[offset + 4 + y*stride] + ((d*1)>>4)];
285 dst[offset + 8 + y*stride] = cm[dst[offset + 8 + y*stride] - ((d*7)>>4)];
286 dst[offset + 9 + y*stride] = cm[dst[offset + 9 + y*stride] - ((d*5)>>4)];
287 dst[offset + 10+ y*stride] = cm[dst[offset +10 + y*stride] - ((d*3)>>4)];
288 dst[offset + 11+ y*stride] = cm[dst[offset +11 + y*stride] - ((d*1)>>4)];
296 * simple vertical deblocking filter used for error resilience
297 * @param w width in 8 pixel blocks
298 * @param h height in 8 pixel blocks
300 static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
301 int b_x, b_y, mvx_stride, mvy_stride;
302 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
303 set_mv_strides(s, &mvx_stride, &mvy_stride);
304 mvx_stride >>= is_luma;
305 mvy_stride *= mvx_stride;
307 for(b_y=0; b_y<h-1; b_y++){
308 for(b_x=0; b_x<w; b_x++){
310 int top_status = s->error_status_table[(b_x>>is_luma) + ( b_y >>is_luma)*s->mb_stride];
311 int bottom_status= s->error_status_table[(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride];
312 int top_intra= IS_INTRA(s->current_picture.mb_type [(b_x>>is_luma) + ( b_y >>is_luma)*s->mb_stride]);
313 int bottom_intra= IS_INTRA(s->current_picture.mb_type [(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride]);
314 int top_damage = top_status&(DC_ERROR|AC_ERROR|MV_ERROR);
315 int bottom_damage= bottom_status&(DC_ERROR|AC_ERROR|MV_ERROR);
316 int offset= b_x*8 + b_y*stride*8;
317 int16_t *top_mv= s->current_picture.motion_val[0][mvy_stride* b_y + mvx_stride*b_x];
318 int16_t *bottom_mv= s->current_picture.motion_val[0][mvy_stride*(b_y+1) + mvx_stride*b_x];
320 if(!(top_damage||bottom_damage)) continue; // both undamaged
322 if( (!top_intra) && (!bottom_intra)
323 && FFABS(top_mv[0]-bottom_mv[0]) + FFABS(top_mv[1]+bottom_mv[1]) < 2) continue;
328 a= dst[offset + x + 7*stride] - dst[offset + x + 6*stride];
329 b= dst[offset + x + 8*stride] - dst[offset + x + 7*stride];
330 c= dst[offset + x + 9*stride] - dst[offset + x + 8*stride];
332 d= FFABS(b) - ((FFABS(a) + FFABS(c)+1)>>1);
338 if(!(top_damage && bottom_damage))
342 dst[offset + x + 7*stride] = cm[dst[offset + x + 7*stride] + ((d*7)>>4)];
343 dst[offset + x + 6*stride] = cm[dst[offset + x + 6*stride] + ((d*5)>>4)];
344 dst[offset + x + 5*stride] = cm[dst[offset + x + 5*stride] + ((d*3)>>4)];
345 dst[offset + x + 4*stride] = cm[dst[offset + x + 4*stride] + ((d*1)>>4)];
348 dst[offset + x + 8*stride] = cm[dst[offset + x + 8*stride] - ((d*7)>>4)];
349 dst[offset + x + 9*stride] = cm[dst[offset + x + 9*stride] - ((d*5)>>4)];
350 dst[offset + x + 10*stride] = cm[dst[offset + x + 10*stride] - ((d*3)>>4)];
351 dst[offset + x + 11*stride] = cm[dst[offset + x + 11*stride] - ((d*1)>>4)];
358 static void guess_mv(MpegEncContext *s){
359 uint8_t fixed[s->mb_stride * s->mb_height];
362 #define MV_UNCHANGED 1
363 const int mb_stride = s->mb_stride;
364 const int mb_width = s->mb_width;
365 const int mb_height= s->mb_height;
366 int i, depth, num_avail;
367 int mb_x, mb_y, mot_step, mot_stride;
369 set_mv_strides(s, &mot_step, &mot_stride);
372 for(i=0; i<s->mb_num; i++){
373 const int mb_xy= s->mb_index2xy[ i ];
375 int error= s->error_status_table[mb_xy];
377 if(IS_INTRA(s->current_picture.mb_type[mb_xy])) f=MV_FROZEN; //intra //FIXME check
378 if(!(error&MV_ERROR)) f=MV_FROZEN; //inter with undamaged MV
385 if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || num_avail <= mb_width/2){
386 for(mb_y=0; mb_y<s->mb_height; mb_y++){
387 for(mb_x=0; mb_x<s->mb_width; mb_x++){
388 const int mb_xy= mb_x + mb_y*s->mb_stride;
390 if(IS_INTRA(s->current_picture.mb_type[mb_xy])) continue;
391 if(!(s->error_status_table[mb_xy]&MV_ERROR)) continue;
393 s->mv_dir = s->last_picture.data[0] ? MV_DIR_FORWARD : MV_DIR_BACKWARD;
395 s->mv_type = MV_TYPE_16X16;
398 s->dsp.clear_blocks(s->block[0]);
410 for(depth=0;; depth++){
411 int changed, pass, none_left;
415 for(pass=0; (changed || pass<2) && pass<10; pass++){
420 for(mb_y=0; mb_y<s->mb_height; mb_y++){
421 for(mb_x=0; mb_x<s->mb_width; mb_x++){
422 const int mb_xy= mb_x + mb_y*s->mb_stride;
423 int mv_predictor[8][2]={{0}};
427 int best_score=256*256*256*64;
429 const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
430 int prev_x= s->current_picture.motion_val[0][mot_index][0];
431 int prev_y= s->current_picture.motion_val[0][mot_index][1];
433 if((mb_x^mb_y^pass)&1) continue;
435 if(fixed[mb_xy]==MV_FROZEN) continue;
436 assert(!IS_INTRA(s->current_picture.mb_type[mb_xy]));
437 assert(s->last_picture_ptr && s->last_picture_ptr->data[0]);
440 if(mb_x>0 && fixed[mb_xy-1 ]==MV_FROZEN) j=1;
441 if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_FROZEN) j=1;
442 if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_FROZEN) j=1;
443 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_FROZEN) j=1;
447 if(mb_x>0 && fixed[mb_xy-1 ]==MV_CHANGED) j=1;
448 if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_CHANGED) j=1;
449 if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_CHANGED) j=1;
450 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_CHANGED) j=1;
451 if(j==0 && pass>1) continue;
455 if(mb_x>0 && fixed[mb_xy-1]){
456 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_step][0];
457 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_step][1];
458 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy-1)];
461 if(mb_x+1<mb_width && fixed[mb_xy+1]){
462 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_step][0];
463 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_step][1];
464 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy+1)];
467 if(mb_y>0 && fixed[mb_xy-mb_stride]){
468 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][0];
469 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][1];
470 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy-s->mb_stride)];
473 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
474 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][0];
475 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][1];
476 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy+s->mb_stride)];
479 if(pred_count==0) continue;
482 int sum_x=0, sum_y=0, sum_r=0;
483 int max_x, max_y, min_x, min_y, max_r, min_r;
485 for(j=0; j<pred_count; j++){
486 sum_x+= mv_predictor[j][0];
487 sum_y+= mv_predictor[j][1];
489 if(j && ref[j] != ref[j-1])
490 goto skip_mean_and_median;
494 mv_predictor[pred_count][0] = sum_x/j;
495 mv_predictor[pred_count][1] = sum_y/j;
496 ref [pred_count] = sum_r/j;
500 min_y= min_x= min_r= 99999;
501 max_y= max_x= max_r=-99999;
503 min_x=min_y=max_x=max_y=min_r=max_r=0;
505 for(j=0; j<pred_count; j++){
506 max_x= FFMAX(max_x, mv_predictor[j][0]);
507 max_y= FFMAX(max_y, mv_predictor[j][1]);
508 max_r= FFMAX(max_r, ref[j]);
509 min_x= FFMIN(min_x, mv_predictor[j][0]);
510 min_y= FFMIN(min_y, mv_predictor[j][1]);
511 min_r= FFMIN(min_r, ref[j]);
513 mv_predictor[pred_count+1][0] = sum_x - max_x - min_x;
514 mv_predictor[pred_count+1][1] = sum_y - max_y - min_y;
515 ref [pred_count+1] = sum_r - max_r - min_r;
518 mv_predictor[pred_count+1][0] /= 2;
519 mv_predictor[pred_count+1][1] /= 2;
520 ref [pred_count+1] /= 2;
524 skip_mean_and_median:
530 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index][0];
531 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index][1];
532 ref [pred_count] = s->current_picture.ref_index[0][4*mb_xy];
535 s->mv_dir = MV_DIR_FORWARD;
537 s->mv_type = MV_TYPE_16X16;
540 s->dsp.clear_blocks(s->block[0]);
545 for(j=0; j<pred_count; j++){
547 uint8_t *src= s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
549 s->current_picture.motion_val[0][mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0];
550 s->current_picture.motion_val[0][mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1];
552 if(ref[j]<0) //predictor intra or otherwise not available
555 decode_mb(s, ref[j]);
557 if(mb_x>0 && fixed[mb_xy-1]){
560 score += FFABS(src[k*s->linesize-1 ]-src[k*s->linesize ]);
562 if(mb_x+1<mb_width && fixed[mb_xy+1]){
565 score += FFABS(src[k*s->linesize+15]-src[k*s->linesize+16]);
567 if(mb_y>0 && fixed[mb_xy-mb_stride]){
570 score += FFABS(src[k-s->linesize ]-src[k ]);
572 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
575 score += FFABS(src[k+s->linesize*15]-src[k+s->linesize*16]);
578 if(score <= best_score){ // <= will favor the last MV
583 score_sum+= best_score;
584 s->mv[0][0][0]= mv_predictor[best_pred][0];
585 s->mv[0][0][1]= mv_predictor[best_pred][1];
587 for(i=0; i<mot_step; i++)
588 for(j=0; j<mot_step; j++){
589 s->current_picture.motion_val[0][mot_index+i+j*mot_stride][0]= s->mv[0][0][0];
590 s->current_picture.motion_val[0][mot_index+i+j*mot_stride][1]= s->mv[0][0][1];
593 decode_mb(s, ref[best_pred]);
596 if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){
597 fixed[mb_xy]=MV_CHANGED;
600 fixed[mb_xy]=MV_UNCHANGED;
604 // printf(".%d/%d", changed, score_sum); fflush(stdout);
610 for(i=0; i<s->mb_num; i++){
611 int mb_xy= s->mb_index2xy[i];
613 fixed[mb_xy]=MV_FROZEN;
615 // printf(":"); fflush(stdout);
619 static int is_intra_more_likely(MpegEncContext *s){
620 int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
622 if(!s->last_picture_ptr || !s->last_picture_ptr->data[0]) return 1; //no previous frame available -> use spatial prediction
625 for(i=0; i<s->mb_num; i++){
626 const int mb_xy= s->mb_index2xy[i];
627 const int error= s->error_status_table[mb_xy];
628 if(!((error&DC_ERROR) && (error&MV_ERROR)))
632 if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction
634 //prevent dsp.sad() check, that requires access to the image
635 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == FF_I_TYPE)
638 skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 50 MBs
642 for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){
643 for(mb_x= 0; mb_x<s->mb_width; mb_x++){
645 const int mb_xy= mb_x + mb_y*s->mb_stride;
647 error= s->error_status_table[mb_xy];
648 if((error&DC_ERROR) && (error&MV_ERROR))
649 continue; //skip damaged
652 if((j%skip_amount) != 0) continue; //skip a few to speed things up
654 if(s->pict_type==FF_I_TYPE){
655 uint8_t *mb_ptr = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
656 uint8_t *last_mb_ptr= s->last_picture.data [0] + mb_x*16 + mb_y*16*s->linesize;
658 is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr , s->linesize, 16);
659 is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16);
661 if(IS_INTRA(s->current_picture.mb_type[mb_xy]))
668 //printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
669 return is_intra_likely > 0;
672 void ff_er_frame_start(MpegEncContext *s){
673 if(!s->error_recognition) return;
675 memset(s->error_status_table, MV_ERROR|AC_ERROR|DC_ERROR|VP_START|AC_END|DC_END|MV_END, s->mb_stride*s->mb_height*sizeof(uint8_t));
676 s->error_count= 3*s->mb_num;
681 * @param endx x component of the last macroblock, can be -1 for the last of the previous line
682 * @param status the status at the end (MV_END, AC_ERROR, ...), it is assumed that no earlier end or
683 * error of the same type occurred
685 void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){
686 const int start_i= av_clip(startx + starty * s->mb_width , 0, s->mb_num-1);
687 const int end_i = av_clip(endx + endy * s->mb_width , 0, s->mb_num);
688 const int start_xy= s->mb_index2xy[start_i];
689 const int end_xy = s->mb_index2xy[end_i];
692 if(s->avctx->hwaccel)
695 if(start_i > end_i || start_xy > end_xy){
696 av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n");
700 if(!s->error_recognition) return;
703 if(status & (AC_ERROR|AC_END)){
704 mask &= ~(AC_ERROR|AC_END);
705 s->error_count -= end_i - start_i + 1;
707 if(status & (DC_ERROR|DC_END)){
708 mask &= ~(DC_ERROR|DC_END);
709 s->error_count -= end_i - start_i + 1;
711 if(status & (MV_ERROR|MV_END)){
712 mask &= ~(MV_ERROR|MV_END);
713 s->error_count -= end_i - start_i + 1;
716 if(status & (AC_ERROR|DC_ERROR|MV_ERROR)) s->error_count= INT_MAX;
719 memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t));
722 for(i=start_xy; i<end_xy; i++){
723 s->error_status_table[ i ] &= mask;
727 if(end_i == s->mb_num)
728 s->error_count= INT_MAX;
730 s->error_status_table[end_xy] &= mask;
731 s->error_status_table[end_xy] |= status;
734 s->error_status_table[start_xy] |= VP_START;
736 if(start_xy > 0 && s->avctx->thread_count <= 1 && s->avctx->skip_top*s->mb_width < start_i){
737 int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ];
739 prev_status &= ~ VP_START;
740 if(prev_status != (MV_END|DC_END|AC_END)) s->error_count= INT_MAX;
744 void ff_er_frame_end(MpegEncContext *s){
745 int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error;
747 int threshold_part[4]= {100,100,100};
750 int size = s->b8_stride * 2 * s->mb_height;
751 Picture *pic= s->current_picture_ptr;
753 if(!s->error_recognition || s->error_count==0 || s->avctx->lowres ||
755 s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
756 s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled
757 s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return;
759 if(s->current_picture.motion_val[0] == NULL){
760 av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
763 pic->ref_index[i]= av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t));
764 pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t));
765 pic->motion_val[i]= pic->motion_val_base[i]+4;
767 pic->motion_subsample_log2= 3;
768 s->current_picture= *s->current_picture_ptr;
771 if(s->avctx->debug&FF_DEBUG_ER){
772 for(mb_y=0; mb_y<s->mb_height; mb_y++){
773 for(mb_x=0; mb_x<s->mb_width; mb_x++){
774 int status= s->error_status_table[mb_x + mb_y*s->mb_stride];
776 av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
778 av_log(s->avctx, AV_LOG_DEBUG, "\n");
783 /* handle overlapping slices */
784 for(error_type=1; error_type<=3; error_type++){
787 for(i=s->mb_num-1; i>=0; i--){
788 const int mb_xy= s->mb_index2xy[i];
789 int error= s->error_status_table[mb_xy];
791 if(error&(1<<error_type))
793 if(error&(8<<error_type))
797 s->error_status_table[mb_xy]|= 1<<error_type;
805 /* handle slices with partitions of different length */
806 if(s->partitioned_frame){
809 for(i=s->mb_num-1; i>=0; i--){
810 const int mb_xy= s->mb_index2xy[i];
811 int error= s->error_status_table[mb_xy];
815 if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
819 s->error_status_table[mb_xy]|= AC_ERROR;
826 /* handle missing slices */
827 if(s->error_recognition>=4){
830 for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
831 const int mb_xy= s->mb_index2xy[i];
832 int error1= s->error_status_table[mb_xy ];
833 int error2= s->error_status_table[s->mb_index2xy[i+1]];
838 if( error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
839 && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
840 && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit
845 s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR;
850 /* backward mark errors */
852 for(error_type=1; error_type<=3; error_type++){
853 for(i=s->mb_num-1; i>=0; i--){
854 const int mb_xy= s->mb_index2xy[i];
855 int error= s->error_status_table[mb_xy];
857 if(!s->mbskip_table[mb_xy]) //FIXME partition specific
859 if(error&(1<<error_type))
862 if(s->partitioned_frame){
863 if(distance < threshold_part[error_type-1])
864 s->error_status_table[mb_xy]|= 1<<error_type;
866 if(distance < threshold)
867 s->error_status_table[mb_xy]|= 1<<error_type;
876 /* forward mark errors */
878 for(i=0; i<s->mb_num; i++){
879 const int mb_xy= s->mb_index2xy[i];
880 int old_error= s->error_status_table[mb_xy];
882 if(old_error&VP_START)
883 error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
885 error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
886 s->error_status_table[mb_xy]|= error;
890 /* handle not partitioned case */
891 if(!s->partitioned_frame){
892 for(i=0; i<s->mb_num; i++){
893 const int mb_xy= s->mb_index2xy[i];
894 error= s->error_status_table[mb_xy];
895 if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
896 error|= AC_ERROR|DC_ERROR|MV_ERROR;
897 s->error_status_table[mb_xy]= error;
902 dc_error= ac_error= mv_error=0;
903 for(i=0; i<s->mb_num; i++){
904 const int mb_xy= s->mb_index2xy[i];
905 error= s->error_status_table[mb_xy];
906 if(error&DC_ERROR) dc_error ++;
907 if(error&AC_ERROR) ac_error ++;
908 if(error&MV_ERROR) mv_error ++;
910 av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
912 is_intra_likely= is_intra_more_likely(s);
914 /* set unknown mb-type to most likely */
915 for(i=0; i<s->mb_num; i++){
916 const int mb_xy= s->mb_index2xy[i];
917 error= s->error_status_table[mb_xy];
918 if(!((error&DC_ERROR) && (error&MV_ERROR)))
922 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
924 s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
927 // change inter to intra blocks if no reference frames are available
928 if (!s->last_picture.data[0] && !s->next_picture.data[0])
929 for(i=0; i<s->mb_num; i++){
930 const int mb_xy= s->mb_index2xy[i];
931 if(!IS_INTRA(s->current_picture.mb_type[mb_xy]))
932 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
935 /* handle inter blocks with damaged AC */
936 for(mb_y=0; mb_y<s->mb_height; mb_y++){
937 for(mb_x=0; mb_x<s->mb_width; mb_x++){
938 const int mb_xy= mb_x + mb_y * s->mb_stride;
939 const int mb_type= s->current_picture.mb_type[mb_xy];
940 int dir = !s->last_picture.data[0];
941 error= s->error_status_table[mb_xy];
943 if(IS_INTRA(mb_type)) continue; //intra
944 if(error&MV_ERROR) continue; //inter with damaged MV
945 if(!(error&AC_ERROR)) continue; //undamaged inter
947 s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
951 int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
953 s->mv_type = MV_TYPE_8X8;
955 s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
956 s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
959 s->mv_type = MV_TYPE_16X16;
960 s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0];
961 s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1];
964 s->dsp.clear_blocks(s->block[0]);
968 decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/);
973 if(s->pict_type==FF_B_TYPE){
974 for(mb_y=0; mb_y<s->mb_height; mb_y++){
975 for(mb_x=0; mb_x<s->mb_width; mb_x++){
976 int xy= mb_x*2 + mb_y*2*s->b8_stride;
977 const int mb_xy= mb_x + mb_y * s->mb_stride;
978 const int mb_type= s->current_picture.mb_type[mb_xy];
979 error= s->error_status_table[mb_xy];
981 if(IS_INTRA(mb_type)) continue;
982 if(!(error&MV_ERROR)) continue; //inter with undamaged MV
983 if(!(error&AC_ERROR)) continue; //undamaged inter
985 s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
986 if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD;
987 if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD;
989 s->mv_type = MV_TYPE_16X16;
993 int time_pp= s->pp_time;
994 int time_pb= s->pb_time;
996 s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
997 s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
998 s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
999 s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp;
1007 s->dsp.clear_blocks(s->block[0]);
1016 /* the filters below are not XvMC compatible, skip them */
1017 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
1019 /* fill DC for inter blocks */
1020 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1021 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1022 int dc, dcu, dcv, y, n;
1024 uint8_t *dest_y, *dest_cb, *dest_cr;
1025 const int mb_xy= mb_x + mb_y * s->mb_stride;
1026 const int mb_type= s->current_picture.mb_type[mb_xy];
1028 error= s->error_status_table[mb_xy];
1030 if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
1031 // if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
1033 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1034 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1035 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1037 dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride];
1043 dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
1046 dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3;
1053 dcu+=dest_cb[x + y*(s->uvlinesize)];
1054 dcv+=dest_cr[x + y*(s->uvlinesize)];
1057 s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3;
1058 s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3;
1062 /* guess DC for damaged blocks */
1063 guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1);
1064 guess_dc(s, s->dc_val[1], s->mb_width , s->mb_height , s->mb_stride, 0);
1065 guess_dc(s, s->dc_val[2], s->mb_width , s->mb_height , s->mb_stride, 0);
1067 /* filter luma DC */
1068 filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride);
1071 /* render DC only intra */
1072 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1073 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1074 uint8_t *dest_y, *dest_cb, *dest_cr;
1075 const int mb_xy= mb_x + mb_y * s->mb_stride;
1076 const int mb_type= s->current_picture.mb_type[mb_xy];
1078 error= s->error_status_table[mb_xy];
1080 if(IS_INTER(mb_type)) continue;
1081 if(!(error&AC_ERROR)) continue; //undamaged
1083 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1084 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1085 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1087 put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1092 if(s->avctx->error_concealment&FF_EC_DEBLOCK){
1093 /* filter horizontal block boundaries */
1094 h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
1095 h_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
1096 h_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
1098 /* filter vertical block boundaries */
1099 v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
1100 v_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
1101 v_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
1105 /* clean a few tables */
1106 for(i=0; i<s->mb_num; i++){
1107 const int mb_xy= s->mb_index2xy[i];
1108 int error= s->error_status_table[mb_xy];
1110 if(s->pict_type!=FF_B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
1111 s->mbskip_table[mb_xy]=0;
1113 s->mbintra_table[mb_xy]=1;