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(CONFIG_H264_DECODER && 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(s->codec_id == CODEC_ID_H264){
633 H264Context *h= (void*)s;
634 if(h->ref_count[0] <= 0 || !h->ref_list[0][0].data[0])
638 if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction
640 //prevent dsp.sad() check, that requires access to the image
641 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == FF_I_TYPE)
644 skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 50 MBs
648 for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){
649 for(mb_x= 0; mb_x<s->mb_width; mb_x++){
651 const int mb_xy= mb_x + mb_y*s->mb_stride;
653 error= s->error_status_table[mb_xy];
654 if((error&DC_ERROR) && (error&MV_ERROR))
655 continue; //skip damaged
658 if((j%skip_amount) != 0) continue; //skip a few to speed things up
660 if(s->pict_type==FF_I_TYPE){
661 uint8_t *mb_ptr = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
662 uint8_t *last_mb_ptr= s->last_picture.data [0] + mb_x*16 + mb_y*16*s->linesize;
664 is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr , s->linesize, 16);
665 is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16);
667 if(IS_INTRA(s->current_picture.mb_type[mb_xy]))
674 //printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
675 return is_intra_likely > 0;
678 void ff_er_frame_start(MpegEncContext *s){
679 if(!s->error_recognition) return;
681 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));
682 s->error_count= 3*s->mb_num;
687 * @param endx x component of the last macroblock, can be -1 for the last of the previous line
688 * @param status the status at the end (MV_END, AC_ERROR, ...), it is assumed that no earlier end or
689 * error of the same type occurred
691 void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){
692 const int start_i= av_clip(startx + starty * s->mb_width , 0, s->mb_num-1);
693 const int end_i = av_clip(endx + endy * s->mb_width , 0, s->mb_num);
694 const int start_xy= s->mb_index2xy[start_i];
695 const int end_xy = s->mb_index2xy[end_i];
698 if(s->avctx->hwaccel)
701 if(start_i > end_i || start_xy > end_xy){
702 av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n");
706 if(!s->error_recognition) return;
709 if(status & (AC_ERROR|AC_END)){
710 mask &= ~(AC_ERROR|AC_END);
711 s->error_count -= end_i - start_i + 1;
713 if(status & (DC_ERROR|DC_END)){
714 mask &= ~(DC_ERROR|DC_END);
715 s->error_count -= end_i - start_i + 1;
717 if(status & (MV_ERROR|MV_END)){
718 mask &= ~(MV_ERROR|MV_END);
719 s->error_count -= end_i - start_i + 1;
722 if(status & (AC_ERROR|DC_ERROR|MV_ERROR)) s->error_count= INT_MAX;
725 memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t));
728 for(i=start_xy; i<end_xy; i++){
729 s->error_status_table[ i ] &= mask;
733 if(end_i == s->mb_num)
734 s->error_count= INT_MAX;
736 s->error_status_table[end_xy] &= mask;
737 s->error_status_table[end_xy] |= status;
740 s->error_status_table[start_xy] |= VP_START;
742 if(start_xy > 0 && s->avctx->thread_count <= 1 && s->avctx->skip_top*s->mb_width < start_i){
743 int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ];
745 prev_status &= ~ VP_START;
746 if(prev_status != (MV_END|DC_END|AC_END)) s->error_count= INT_MAX;
750 void ff_er_frame_end(MpegEncContext *s){
751 int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error;
753 int threshold_part[4]= {100,100,100};
756 int size = s->b8_stride * 2 * s->mb_height;
757 Picture *pic= s->current_picture_ptr;
759 if(!s->error_recognition || s->error_count==0 || s->avctx->lowres ||
761 s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
762 s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled
763 s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return;
765 if(s->current_picture.motion_val[0] == NULL){
766 av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
769 pic->ref_index[i]= av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t));
770 pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t));
771 pic->motion_val[i]= pic->motion_val_base[i]+4;
773 pic->motion_subsample_log2= 3;
774 s->current_picture= *s->current_picture_ptr;
777 if(s->avctx->debug&FF_DEBUG_ER){
778 for(mb_y=0; mb_y<s->mb_height; mb_y++){
779 for(mb_x=0; mb_x<s->mb_width; mb_x++){
780 int status= s->error_status_table[mb_x + mb_y*s->mb_stride];
782 av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
784 av_log(s->avctx, AV_LOG_DEBUG, "\n");
789 /* handle overlapping slices */
790 for(error_type=1; error_type<=3; error_type++){
793 for(i=s->mb_num-1; i>=0; i--){
794 const int mb_xy= s->mb_index2xy[i];
795 int error= s->error_status_table[mb_xy];
797 if(error&(1<<error_type))
799 if(error&(8<<error_type))
803 s->error_status_table[mb_xy]|= 1<<error_type;
811 /* handle slices with partitions of different length */
812 if(s->partitioned_frame){
815 for(i=s->mb_num-1; i>=0; i--){
816 const int mb_xy= s->mb_index2xy[i];
817 int error= s->error_status_table[mb_xy];
821 if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
825 s->error_status_table[mb_xy]|= AC_ERROR;
832 /* handle missing slices */
833 if(s->error_recognition>=4){
836 for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
837 const int mb_xy= s->mb_index2xy[i];
838 int error1= s->error_status_table[mb_xy ];
839 int error2= s->error_status_table[s->mb_index2xy[i+1]];
844 if( error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
845 && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
846 && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit
851 s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR;
856 /* backward mark errors */
858 for(error_type=1; error_type<=3; error_type++){
859 for(i=s->mb_num-1; i>=0; i--){
860 const int mb_xy= s->mb_index2xy[i];
861 int error= s->error_status_table[mb_xy];
863 if(!s->mbskip_table[mb_xy]) //FIXME partition specific
865 if(error&(1<<error_type))
868 if(s->partitioned_frame){
869 if(distance < threshold_part[error_type-1])
870 s->error_status_table[mb_xy]|= 1<<error_type;
872 if(distance < threshold)
873 s->error_status_table[mb_xy]|= 1<<error_type;
882 /* forward mark errors */
884 for(i=0; i<s->mb_num; i++){
885 const int mb_xy= s->mb_index2xy[i];
886 int old_error= s->error_status_table[mb_xy];
888 if(old_error&VP_START)
889 error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
891 error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
892 s->error_status_table[mb_xy]|= error;
896 /* handle not partitioned case */
897 if(!s->partitioned_frame){
898 for(i=0; i<s->mb_num; i++){
899 const int mb_xy= s->mb_index2xy[i];
900 error= s->error_status_table[mb_xy];
901 if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
902 error|= AC_ERROR|DC_ERROR|MV_ERROR;
903 s->error_status_table[mb_xy]= error;
908 dc_error= ac_error= mv_error=0;
909 for(i=0; i<s->mb_num; i++){
910 const int mb_xy= s->mb_index2xy[i];
911 error= s->error_status_table[mb_xy];
912 if(error&DC_ERROR) dc_error ++;
913 if(error&AC_ERROR) ac_error ++;
914 if(error&MV_ERROR) mv_error ++;
916 av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
918 is_intra_likely= is_intra_more_likely(s);
920 /* set unknown mb-type to most likely */
921 for(i=0; i<s->mb_num; i++){
922 const int mb_xy= s->mb_index2xy[i];
923 error= s->error_status_table[mb_xy];
924 if(!((error&DC_ERROR) && (error&MV_ERROR)))
928 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
930 s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
933 // change inter to intra blocks if no reference frames are available
934 if (!s->last_picture.data[0] && !s->next_picture.data[0])
935 for(i=0; i<s->mb_num; i++){
936 const int mb_xy= s->mb_index2xy[i];
937 if(!IS_INTRA(s->current_picture.mb_type[mb_xy]))
938 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
941 /* handle inter blocks with damaged AC */
942 for(mb_y=0; mb_y<s->mb_height; mb_y++){
943 for(mb_x=0; mb_x<s->mb_width; mb_x++){
944 const int mb_xy= mb_x + mb_y * s->mb_stride;
945 const int mb_type= s->current_picture.mb_type[mb_xy];
946 int dir = !s->last_picture.data[0];
947 error= s->error_status_table[mb_xy];
949 if(IS_INTRA(mb_type)) continue; //intra
950 if(error&MV_ERROR) continue; //inter with damaged MV
951 if(!(error&AC_ERROR)) continue; //undamaged inter
953 s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
957 int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
959 s->mv_type = MV_TYPE_8X8;
961 s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
962 s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
965 s->mv_type = MV_TYPE_16X16;
966 s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0];
967 s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1];
970 s->dsp.clear_blocks(s->block[0]);
974 decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/);
979 if(s->pict_type==FF_B_TYPE){
980 for(mb_y=0; mb_y<s->mb_height; mb_y++){
981 for(mb_x=0; mb_x<s->mb_width; mb_x++){
982 int xy= mb_x*2 + mb_y*2*s->b8_stride;
983 const int mb_xy= mb_x + mb_y * s->mb_stride;
984 const int mb_type= s->current_picture.mb_type[mb_xy];
985 error= s->error_status_table[mb_xy];
987 if(IS_INTRA(mb_type)) continue;
988 if(!(error&MV_ERROR)) continue; //inter with undamaged MV
989 if(!(error&AC_ERROR)) continue; //undamaged inter
991 s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
992 if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD;
993 if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD;
995 s->mv_type = MV_TYPE_16X16;
999 int time_pp= s->pp_time;
1000 int time_pb= s->pb_time;
1002 s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
1003 s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
1004 s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
1005 s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp;
1013 s->dsp.clear_blocks(s->block[0]);
1022 /* the filters below are not XvMC compatible, skip them */
1023 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
1025 /* fill DC for inter blocks */
1026 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1027 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1028 int dc, dcu, dcv, y, n;
1030 uint8_t *dest_y, *dest_cb, *dest_cr;
1031 const int mb_xy= mb_x + mb_y * s->mb_stride;
1032 const int mb_type= s->current_picture.mb_type[mb_xy];
1034 error= s->error_status_table[mb_xy];
1036 if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
1037 // if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
1039 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1040 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1041 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1043 dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride];
1049 dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
1052 dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3;
1059 dcu+=dest_cb[x + y*(s->uvlinesize)];
1060 dcv+=dest_cr[x + y*(s->uvlinesize)];
1063 s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3;
1064 s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3;
1068 /* guess DC for damaged blocks */
1069 guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1);
1070 guess_dc(s, s->dc_val[1], s->mb_width , s->mb_height , s->mb_stride, 0);
1071 guess_dc(s, s->dc_val[2], s->mb_width , s->mb_height , s->mb_stride, 0);
1073 /* filter luma DC */
1074 filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride);
1077 /* render DC only intra */
1078 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1079 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1080 uint8_t *dest_y, *dest_cb, *dest_cr;
1081 const int mb_xy= mb_x + mb_y * s->mb_stride;
1082 const int mb_type= s->current_picture.mb_type[mb_xy];
1084 error= s->error_status_table[mb_xy];
1086 if(IS_INTER(mb_type)) continue;
1087 if(!(error&AC_ERROR)) continue; //undamaged
1089 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1090 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1091 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1093 put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1098 if(s->avctx->error_concealment&FF_EC_DEBLOCK){
1099 /* filter horizontal block boundaries */
1100 h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
1101 h_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
1102 h_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
1104 /* filter vertical block boundaries */
1105 v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
1106 v_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
1107 v_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
1111 /* clean a few tables */
1112 for(i=0; i<s->mb_num; i++){
1113 const int mb_xy= s->mb_index2xy[i];
1114 int error= s->error_status_table[mb_xy];
1116 if(s->pict_type!=FF_B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
1117 s->mbskip_table[mb_xy]=0;
1119 s->mbintra_table[mb_xy]=1;