2 * Error resilience / concealment
4 * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
6 * This file is part of Libav.
8 * Libav 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 * Libav 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 Libav; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * Error resilience / concealment.
32 #include "mpegvideo.h"
34 #include "rectangle.h"
37 * H264 redefines mb_intra so it is not mistakely used (its uninitialized in h264)
38 * but error concealment must support both h264 and h263 thus we must undo this
42 static void decode_mb(MpegEncContext *s, int ref){
43 s->dest[0] = s->current_picture.data[0] + (s->mb_y * 16* s->linesize ) + s->mb_x * 16;
44 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);
45 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);
47 if(CONFIG_H264_DECODER && s->codec_id == CODEC_ID_H264){
48 H264Context *h= (void*)s;
49 h->mb_xy= s->mb_x + s->mb_y*s->mb_stride;
50 memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache));
52 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
54 fill_rectangle(&s->current_picture.ref_index[0][4*h->mb_xy], 2, 2, 2, ref, 1);
55 fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);
56 fill_rectangle(h->mv_cache[0][ scan8[0] ], 4, 4, 8, pack16to32(s->mv[0][0][0],s->mv[0][0][1]), 4);
58 ff_h264_hl_decode_mb(h);
61 MPV_decode_mb(s, s->block);
66 * @param stride the number of MVs to get to the next row
67 * @param mv_step the number of MVs per row or column in a macroblock
69 static void set_mv_strides(MpegEncContext *s, int *mv_step, int *stride){
70 if(s->codec_id == CODEC_ID_H264){
71 H264Context *h= (void*)s;
72 assert(s->quarter_sample);
77 *stride= s->b8_stride;
82 * replaces the current MB with a flat dc only version.
84 static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y)
86 int dc, dcu, dcv, y, i;
88 dc= s->dc_val[0][mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*s->b8_stride];
90 else if(dc>2040) dc=2040;
94 dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8;
98 dcu = s->dc_val[1][mb_x + mb_y*s->mb_stride];
99 dcv = s->dc_val[2][mb_x + mb_y*s->mb_stride];
101 else if(dcu>2040) dcu=2040;
103 else if(dcv>2040) dcv=2040;
107 dest_cb[x + y*(s->uvlinesize)]= dcu/8;
108 dest_cr[x + y*(s->uvlinesize)]= dcv/8;
113 static void filter181(int16_t *data, int width, int height, int stride){
116 /* horizontal filter */
117 for(y=1; y<height-1; y++){
118 int prev_dc= data[0 + y*stride];
120 for(x=1; x<width-1; x++){
124 + data[x + y*stride]*8
125 - data[x + 1 + y*stride];
126 dc= (dc*10923 + 32768)>>16;
127 prev_dc= data[x + y*stride];
128 data[x + y*stride]= dc;
132 /* vertical filter */
133 for(x=1; x<width-1; x++){
134 int prev_dc= data[x];
136 for(y=1; y<height-1; y++){
140 + data[x + y *stride]*8
141 - data[x + (y+1)*stride];
142 dc= (dc*10923 + 32768)>>16;
143 prev_dc= data[x + y*stride];
144 data[x + y*stride]= dc;
150 * guess the dc of blocks which do not have an undamaged dc
151 * @param w width in 8 pixel blocks
152 * @param h height in 8 pixel blocks
154 static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, int is_luma){
157 for(b_y=0; b_y<h; b_y++){
158 for(b_x=0; b_x<w; b_x++){
159 int color[4]={1024,1024,1024,1024};
160 int distance[4]={9999,9999,9999,9999};
161 int mb_index, error, j;
162 int64_t guess, weight_sum;
164 mb_index= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
166 error= s->error_status_table[mb_index];
168 if(IS_INTER(s->current_picture.mb_type[mb_index])) continue; //inter
169 if(!(error&DC_ERROR)) continue; //dc-ok
172 for(j=b_x+1; j<w; j++){
173 int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride;
174 int error_j= s->error_status_table[mb_index_j];
175 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
176 if(intra_j==0 || !(error_j&DC_ERROR)){
177 color[0]= dc[j + b_y*stride];
184 for(j=b_x-1; j>=0; j--){
185 int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride;
186 int error_j= s->error_status_table[mb_index_j];
187 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
188 if(intra_j==0 || !(error_j&DC_ERROR)){
189 color[1]= dc[j + b_y*stride];
196 for(j=b_y+1; j<h; j++){
197 int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
198 int error_j= s->error_status_table[mb_index_j];
199 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
200 if(intra_j==0 || !(error_j&DC_ERROR)){
201 color[2]= dc[b_x + j*stride];
208 for(j=b_y-1; j>=0; j--){
209 int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
210 int error_j= s->error_status_table[mb_index_j];
211 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
212 if(intra_j==0 || !(error_j&DC_ERROR)){
213 color[3]= dc[b_x + j*stride];
222 int64_t weight= 256*256*256*16/distance[j];
223 guess+= weight*(int64_t)color[j];
226 guess= (guess + weight_sum/2) / weight_sum;
228 dc[b_x + b_y*stride]= guess;
234 * simple horizontal deblocking filter used for error resilience
235 * @param w width in 8 pixel blocks
236 * @param h height in 8 pixel blocks
238 static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
239 int b_x, b_y, mvx_stride, mvy_stride;
240 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
241 set_mv_strides(s, &mvx_stride, &mvy_stride);
242 mvx_stride >>= is_luma;
243 mvy_stride *= mvx_stride;
245 for(b_y=0; b_y<h; b_y++){
246 for(b_x=0; b_x<w-1; b_x++){
248 int left_status = s->error_status_table[( b_x >>is_luma) + (b_y>>is_luma)*s->mb_stride];
249 int right_status= s->error_status_table[((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride];
250 int left_intra= IS_INTRA(s->current_picture.mb_type [( b_x >>is_luma) + (b_y>>is_luma)*s->mb_stride]);
251 int right_intra= IS_INTRA(s->current_picture.mb_type [((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride]);
252 int left_damage = left_status&(DC_ERROR|AC_ERROR|MV_ERROR);
253 int right_damage= right_status&(DC_ERROR|AC_ERROR|MV_ERROR);
254 int offset= b_x*8 + b_y*stride*8;
255 int16_t *left_mv= s->current_picture.motion_val[0][mvy_stride*b_y + mvx_stride* b_x ];
256 int16_t *right_mv= s->current_picture.motion_val[0][mvy_stride*b_y + mvx_stride*(b_x+1)];
258 if(!(left_damage||right_damage)) continue; // both undamaged
260 if( (!left_intra) && (!right_intra)
261 && FFABS(left_mv[0]-right_mv[0]) + FFABS(left_mv[1]+right_mv[1]) < 2) continue;
266 a= dst[offset + 7 + y*stride] - dst[offset + 6 + y*stride];
267 b= dst[offset + 8 + y*stride] - dst[offset + 7 + y*stride];
268 c= dst[offset + 9 + y*stride] - dst[offset + 8 + y*stride];
270 d= FFABS(b) - ((FFABS(a) + FFABS(c) + 1)>>1);
276 if(!(left_damage && right_damage))
280 dst[offset + 7 + y*stride] = cm[dst[offset + 7 + y*stride] + ((d*7)>>4)];
281 dst[offset + 6 + y*stride] = cm[dst[offset + 6 + y*stride] + ((d*5)>>4)];
282 dst[offset + 5 + y*stride] = cm[dst[offset + 5 + y*stride] + ((d*3)>>4)];
283 dst[offset + 4 + y*stride] = cm[dst[offset + 4 + y*stride] + ((d*1)>>4)];
286 dst[offset + 8 + y*stride] = cm[dst[offset + 8 + y*stride] - ((d*7)>>4)];
287 dst[offset + 9 + y*stride] = cm[dst[offset + 9 + y*stride] - ((d*5)>>4)];
288 dst[offset + 10+ y*stride] = cm[dst[offset +10 + y*stride] - ((d*3)>>4)];
289 dst[offset + 11+ y*stride] = cm[dst[offset +11 + y*stride] - ((d*1)>>4)];
297 * simple vertical deblocking filter used for error resilience
298 * @param w width in 8 pixel blocks
299 * @param h height in 8 pixel blocks
301 static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
302 int b_x, b_y, mvx_stride, mvy_stride;
303 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
304 set_mv_strides(s, &mvx_stride, &mvy_stride);
305 mvx_stride >>= is_luma;
306 mvy_stride *= mvx_stride;
308 for(b_y=0; b_y<h-1; b_y++){
309 for(b_x=0; b_x<w; b_x++){
311 int top_status = s->error_status_table[(b_x>>is_luma) + ( b_y >>is_luma)*s->mb_stride];
312 int bottom_status= s->error_status_table[(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride];
313 int top_intra= IS_INTRA(s->current_picture.mb_type [(b_x>>is_luma) + ( b_y >>is_luma)*s->mb_stride]);
314 int bottom_intra= IS_INTRA(s->current_picture.mb_type [(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride]);
315 int top_damage = top_status&(DC_ERROR|AC_ERROR|MV_ERROR);
316 int bottom_damage= bottom_status&(DC_ERROR|AC_ERROR|MV_ERROR);
317 int offset= b_x*8 + b_y*stride*8;
318 int16_t *top_mv= s->current_picture.motion_val[0][mvy_stride* b_y + mvx_stride*b_x];
319 int16_t *bottom_mv= s->current_picture.motion_val[0][mvy_stride*(b_y+1) + mvx_stride*b_x];
321 if(!(top_damage||bottom_damage)) continue; // both undamaged
323 if( (!top_intra) && (!bottom_intra)
324 && FFABS(top_mv[0]-bottom_mv[0]) + FFABS(top_mv[1]+bottom_mv[1]) < 2) continue;
329 a= dst[offset + x + 7*stride] - dst[offset + x + 6*stride];
330 b= dst[offset + x + 8*stride] - dst[offset + x + 7*stride];
331 c= dst[offset + x + 9*stride] - dst[offset + x + 8*stride];
333 d= FFABS(b) - ((FFABS(a) + FFABS(c)+1)>>1);
339 if(!(top_damage && bottom_damage))
343 dst[offset + x + 7*stride] = cm[dst[offset + x + 7*stride] + ((d*7)>>4)];
344 dst[offset + x + 6*stride] = cm[dst[offset + x + 6*stride] + ((d*5)>>4)];
345 dst[offset + x + 5*stride] = cm[dst[offset + x + 5*stride] + ((d*3)>>4)];
346 dst[offset + x + 4*stride] = cm[dst[offset + x + 4*stride] + ((d*1)>>4)];
349 dst[offset + x + 8*stride] = cm[dst[offset + x + 8*stride] - ((d*7)>>4)];
350 dst[offset + x + 9*stride] = cm[dst[offset + x + 9*stride] - ((d*5)>>4)];
351 dst[offset + x + 10*stride] = cm[dst[offset + x + 10*stride] - ((d*3)>>4)];
352 dst[offset + x + 11*stride] = cm[dst[offset + x + 11*stride] - ((d*1)>>4)];
359 static void guess_mv(MpegEncContext *s){
360 uint8_t fixed[s->mb_stride * s->mb_height];
363 #define MV_UNCHANGED 1
364 const int mb_stride = s->mb_stride;
365 const int mb_width = s->mb_width;
366 const int mb_height= s->mb_height;
367 int i, depth, num_avail;
368 int mb_x, mb_y, mot_step, mot_stride;
370 set_mv_strides(s, &mot_step, &mot_stride);
373 for(i=0; i<s->mb_num; i++){
374 const int mb_xy= s->mb_index2xy[ i ];
376 int error= s->error_status_table[mb_xy];
378 if(IS_INTRA(s->current_picture.mb_type[mb_xy])) f=MV_FROZEN; //intra //FIXME check
379 if(!(error&MV_ERROR)) f=MV_FROZEN; //inter with undamaged MV
386 if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || num_avail <= mb_width/2){
387 for(mb_y=0; mb_y<s->mb_height; mb_y++){
388 for(mb_x=0; mb_x<s->mb_width; mb_x++){
389 const int mb_xy= mb_x + mb_y*s->mb_stride;
391 if(IS_INTRA(s->current_picture.mb_type[mb_xy])) continue;
392 if(!(s->error_status_table[mb_xy]&MV_ERROR)) continue;
394 s->mv_dir = s->last_picture.data[0] ? MV_DIR_FORWARD : MV_DIR_BACKWARD;
396 s->mv_type = MV_TYPE_16X16;
399 s->dsp.clear_blocks(s->block[0]);
411 for(depth=0;; depth++){
412 int changed, pass, none_left;
416 for(pass=0; (changed || pass<2) && pass<10; pass++){
421 for(mb_y=0; mb_y<s->mb_height; mb_y++){
422 for(mb_x=0; mb_x<s->mb_width; mb_x++){
423 const int mb_xy= mb_x + mb_y*s->mb_stride;
424 int mv_predictor[8][2]={{0}};
428 int best_score=256*256*256*64;
430 const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
431 int prev_x= s->current_picture.motion_val[0][mot_index][0];
432 int prev_y= s->current_picture.motion_val[0][mot_index][1];
434 if((mb_x^mb_y^pass)&1) continue;
436 if(fixed[mb_xy]==MV_FROZEN) continue;
437 assert(!IS_INTRA(s->current_picture.mb_type[mb_xy]));
438 assert(s->last_picture_ptr && s->last_picture_ptr->data[0]);
441 if(mb_x>0 && fixed[mb_xy-1 ]==MV_FROZEN) j=1;
442 if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_FROZEN) j=1;
443 if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_FROZEN) j=1;
444 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_FROZEN) j=1;
448 if(mb_x>0 && fixed[mb_xy-1 ]==MV_CHANGED) j=1;
449 if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_CHANGED) j=1;
450 if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_CHANGED) j=1;
451 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_CHANGED) j=1;
452 if(j==0 && pass>1) continue;
456 if(mb_x>0 && fixed[mb_xy-1]){
457 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_step][0];
458 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_step][1];
459 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy-1)];
462 if(mb_x+1<mb_width && fixed[mb_xy+1]){
463 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_step][0];
464 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_step][1];
465 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy+1)];
468 if(mb_y>0 && fixed[mb_xy-mb_stride]){
469 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][0];
470 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][1];
471 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy-s->mb_stride)];
474 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
475 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][0];
476 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][1];
477 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy+s->mb_stride)];
480 if(pred_count==0) continue;
483 int sum_x=0, sum_y=0, sum_r=0;
484 int max_x, max_y, min_x, min_y, max_r, min_r;
486 for(j=0; j<pred_count; j++){
487 sum_x+= mv_predictor[j][0];
488 sum_y+= mv_predictor[j][1];
490 if(j && ref[j] != ref[j-1])
491 goto skip_mean_and_median;
495 mv_predictor[pred_count][0] = sum_x/j;
496 mv_predictor[pred_count][1] = sum_y/j;
497 ref [pred_count] = sum_r/j;
501 min_y= min_x= min_r= 99999;
502 max_y= max_x= max_r=-99999;
504 min_x=min_y=max_x=max_y=min_r=max_r=0;
506 for(j=0; j<pred_count; j++){
507 max_x= FFMAX(max_x, mv_predictor[j][0]);
508 max_y= FFMAX(max_y, mv_predictor[j][1]);
509 max_r= FFMAX(max_r, ref[j]);
510 min_x= FFMIN(min_x, mv_predictor[j][0]);
511 min_y= FFMIN(min_y, mv_predictor[j][1]);
512 min_r= FFMIN(min_r, ref[j]);
514 mv_predictor[pred_count+1][0] = sum_x - max_x - min_x;
515 mv_predictor[pred_count+1][1] = sum_y - max_y - min_y;
516 ref [pred_count+1] = sum_r - max_r - min_r;
519 mv_predictor[pred_count+1][0] /= 2;
520 mv_predictor[pred_count+1][1] /= 2;
521 ref [pred_count+1] /= 2;
525 skip_mean_and_median:
531 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index][0];
532 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index][1];
533 ref [pred_count] = s->current_picture.ref_index[0][4*mb_xy];
536 s->mv_dir = MV_DIR_FORWARD;
538 s->mv_type = MV_TYPE_16X16;
541 s->dsp.clear_blocks(s->block[0]);
546 for(j=0; j<pred_count; j++){
548 uint8_t *src= s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
550 s->current_picture.motion_val[0][mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0];
551 s->current_picture.motion_val[0][mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1];
553 if(ref[j]<0) //predictor intra or otherwise not available
556 decode_mb(s, ref[j]);
558 if(mb_x>0 && fixed[mb_xy-1]){
561 score += FFABS(src[k*s->linesize-1 ]-src[k*s->linesize ]);
563 if(mb_x+1<mb_width && fixed[mb_xy+1]){
566 score += FFABS(src[k*s->linesize+15]-src[k*s->linesize+16]);
568 if(mb_y>0 && fixed[mb_xy-mb_stride]){
571 score += FFABS(src[k-s->linesize ]-src[k ]);
573 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
576 score += FFABS(src[k+s->linesize*15]-src[k+s->linesize*16]);
579 if(score <= best_score){ // <= will favor the last MV
584 score_sum+= best_score;
585 s->mv[0][0][0]= mv_predictor[best_pred][0];
586 s->mv[0][0][1]= mv_predictor[best_pred][1];
588 for(i=0; i<mot_step; i++)
589 for(j=0; j<mot_step; j++){
590 s->current_picture.motion_val[0][mot_index+i+j*mot_stride][0]= s->mv[0][0][0];
591 s->current_picture.motion_val[0][mot_index+i+j*mot_stride][1]= s->mv[0][0][1];
594 decode_mb(s, ref[best_pred]);
597 if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){
598 fixed[mb_xy]=MV_CHANGED;
601 fixed[mb_xy]=MV_UNCHANGED;
605 // printf(".%d/%d", changed, score_sum); fflush(stdout);
611 for(i=0; i<s->mb_num; i++){
612 int mb_xy= s->mb_index2xy[i];
614 fixed[mb_xy]=MV_FROZEN;
616 // printf(":"); fflush(stdout);
620 static int is_intra_more_likely(MpegEncContext *s){
621 int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
623 if(!s->last_picture_ptr || !s->last_picture_ptr->data[0]) return 1; //no previous frame available -> use spatial prediction
626 for(i=0; i<s->mb_num; i++){
627 const int mb_xy= s->mb_index2xy[i];
628 const int error= s->error_status_table[mb_xy];
629 if(!((error&DC_ERROR) && (error&MV_ERROR)))
633 if(s->codec_id == CODEC_ID_H264){
634 H264Context *h= (void*)s;
635 if(h->ref_count[0] <= 0 || !h->ref_list[0][0].data[0])
639 if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction
641 //prevent dsp.sad() check, that requires access to the image
642 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == AV_PICTURE_TYPE_I)
645 skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 50 MBs
649 for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){
650 for(mb_x= 0; mb_x<s->mb_width; mb_x++){
652 const int mb_xy= mb_x + mb_y*s->mb_stride;
654 error= s->error_status_table[mb_xy];
655 if((error&DC_ERROR) && (error&MV_ERROR))
656 continue; //skip damaged
659 if((j%skip_amount) != 0) continue; //skip a few to speed things up
661 if(s->pict_type==AV_PICTURE_TYPE_I){
662 uint8_t *mb_ptr = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
663 uint8_t *last_mb_ptr= s->last_picture.data [0] + mb_x*16 + mb_y*16*s->linesize;
665 is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr , s->linesize, 16);
666 is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16);
668 if(IS_INTRA(s->current_picture.mb_type[mb_xy]))
675 //printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
676 return is_intra_likely > 0;
679 void ff_er_frame_start(MpegEncContext *s){
680 if(!s->error_recognition) return;
682 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));
683 s->error_count= 3*s->mb_num;
688 * @param endx x component of the last macroblock, can be -1 for the last of the previous line
689 * @param status the status at the end (MV_END, AC_ERROR, ...), it is assumed that no earlier end or
690 * error of the same type occurred
692 void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){
693 const int start_i= av_clip(startx + starty * s->mb_width , 0, s->mb_num-1);
694 const int end_i = av_clip(endx + endy * s->mb_width , 0, s->mb_num);
695 const int start_xy= s->mb_index2xy[start_i];
696 const int end_xy = s->mb_index2xy[end_i];
699 if(s->avctx->hwaccel)
702 if(start_i > end_i || start_xy > end_xy){
703 av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n");
707 if(!s->error_recognition) return;
710 if(status & (AC_ERROR|AC_END)){
711 mask &= ~(AC_ERROR|AC_END);
712 s->error_count -= end_i - start_i + 1;
714 if(status & (DC_ERROR|DC_END)){
715 mask &= ~(DC_ERROR|DC_END);
716 s->error_count -= end_i - start_i + 1;
718 if(status & (MV_ERROR|MV_END)){
719 mask &= ~(MV_ERROR|MV_END);
720 s->error_count -= end_i - start_i + 1;
723 if(status & (AC_ERROR|DC_ERROR|MV_ERROR)) s->error_count= INT_MAX;
726 memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t));
729 for(i=start_xy; i<end_xy; i++){
730 s->error_status_table[ i ] &= mask;
734 if(end_i == s->mb_num)
735 s->error_count= INT_MAX;
737 s->error_status_table[end_xy] &= mask;
738 s->error_status_table[end_xy] |= status;
741 s->error_status_table[start_xy] |= VP_START;
743 if(start_xy > 0 && s->avctx->thread_count <= 1 && s->avctx->skip_top*s->mb_width < start_i){
744 int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ];
746 prev_status &= ~ VP_START;
747 if(prev_status != (MV_END|DC_END|AC_END)) s->error_count= INT_MAX;
751 void ff_er_frame_end(MpegEncContext *s){
752 int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error;
754 int threshold_part[4]= {100,100,100};
757 int size = s->b8_stride * 2 * s->mb_height;
758 Picture *pic= s->current_picture_ptr;
760 if(!s->error_recognition || s->error_count==0 || s->avctx->lowres ||
762 s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
763 s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled
764 s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return;
766 if(s->current_picture.motion_val[0] == NULL){
767 av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
770 pic->ref_index[i]= av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t));
771 pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t));
772 pic->motion_val[i]= pic->motion_val_base[i]+4;
774 pic->motion_subsample_log2= 3;
775 s->current_picture= *s->current_picture_ptr;
778 if(s->avctx->debug&FF_DEBUG_ER){
779 for(mb_y=0; mb_y<s->mb_height; mb_y++){
780 for(mb_x=0; mb_x<s->mb_width; mb_x++){
781 int status= s->error_status_table[mb_x + mb_y*s->mb_stride];
783 av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
785 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;
810 /* handle slices with partitions of different length */
811 if(s->partitioned_frame){
814 for(i=s->mb_num-1; i>=0; i--){
815 const int mb_xy= s->mb_index2xy[i];
816 int error= s->error_status_table[mb_xy];
820 if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
824 s->error_status_table[mb_xy]|= AC_ERROR;
831 /* handle missing slices */
832 if(s->error_recognition>=4){
835 for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
836 const int mb_xy= s->mb_index2xy[i];
837 int error1= s->error_status_table[mb_xy ];
838 int error2= s->error_status_table[s->mb_index2xy[i+1]];
843 if( error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
844 && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
845 && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit
850 s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR;
854 /* backward mark errors */
856 for(error_type=1; error_type<=3; error_type++){
857 for(i=s->mb_num-1; i>=0; i--){
858 const int mb_xy= s->mb_index2xy[i];
859 int error= s->error_status_table[mb_xy];
861 if(!s->mbskip_table[mb_xy]) //FIXME partition specific
863 if(error&(1<<error_type))
866 if(s->partitioned_frame){
867 if(distance < threshold_part[error_type-1])
868 s->error_status_table[mb_xy]|= 1<<error_type;
870 if(distance < threshold)
871 s->error_status_table[mb_xy]|= 1<<error_type;
879 /* forward mark errors */
881 for(i=0; i<s->mb_num; i++){
882 const int mb_xy= s->mb_index2xy[i];
883 int old_error= s->error_status_table[mb_xy];
885 if(old_error&VP_START)
886 error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
888 error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
889 s->error_status_table[mb_xy]|= error;
893 /* handle not partitioned case */
894 if(!s->partitioned_frame){
895 for(i=0; i<s->mb_num; i++){
896 const int mb_xy= s->mb_index2xy[i];
897 error= s->error_status_table[mb_xy];
898 if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
899 error|= AC_ERROR|DC_ERROR|MV_ERROR;
900 s->error_status_table[mb_xy]= error;
904 dc_error= ac_error= mv_error=0;
905 for(i=0; i<s->mb_num; i++){
906 const int mb_xy= s->mb_index2xy[i];
907 error= s->error_status_table[mb_xy];
908 if(error&DC_ERROR) dc_error ++;
909 if(error&AC_ERROR) ac_error ++;
910 if(error&MV_ERROR) mv_error ++;
912 av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
914 is_intra_likely= is_intra_more_likely(s);
916 /* set unknown mb-type to most likely */
917 for(i=0; i<s->mb_num; i++){
918 const int mb_xy= s->mb_index2xy[i];
919 error= s->error_status_table[mb_xy];
920 if(!((error&DC_ERROR) && (error&MV_ERROR)))
924 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
926 s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
929 // change inter to intra blocks if no reference frames are available
930 if (!s->last_picture.data[0] && !s->next_picture.data[0])
931 for(i=0; i<s->mb_num; i++){
932 const int mb_xy= s->mb_index2xy[i];
933 if(!IS_INTRA(s->current_picture.mb_type[mb_xy]))
934 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
937 /* handle inter blocks with damaged AC */
938 for(mb_y=0; mb_y<s->mb_height; mb_y++){
939 for(mb_x=0; mb_x<s->mb_width; mb_x++){
940 const int mb_xy= mb_x + mb_y * s->mb_stride;
941 const int mb_type= s->current_picture.mb_type[mb_xy];
942 int dir = !s->last_picture.data[0];
943 error= s->error_status_table[mb_xy];
945 if(IS_INTRA(mb_type)) continue; //intra
946 if(error&MV_ERROR) continue; //inter with damaged MV
947 if(!(error&AC_ERROR)) continue; //undamaged inter
949 s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
953 int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
955 s->mv_type = MV_TYPE_8X8;
957 s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
958 s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
961 s->mv_type = MV_TYPE_16X16;
962 s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0];
963 s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1];
966 s->dsp.clear_blocks(s->block[0]);
970 decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/);
975 if(s->pict_type==AV_PICTURE_TYPE_B){
976 for(mb_y=0; mb_y<s->mb_height; mb_y++){
977 for(mb_x=0; mb_x<s->mb_width; mb_x++){
978 int xy= mb_x*2 + mb_y*2*s->b8_stride;
979 const int mb_xy= mb_x + mb_y * s->mb_stride;
980 const int mb_type= s->current_picture.mb_type[mb_xy];
981 error= s->error_status_table[mb_xy];
983 if(IS_INTRA(mb_type)) continue;
984 if(!(error&MV_ERROR)) continue; //inter with undamaged MV
985 if(!(error&AC_ERROR)) continue; //undamaged inter
987 s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
988 if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD;
989 if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD;
991 s->mv_type = MV_TYPE_16X16;
995 int time_pp= s->pp_time;
996 int time_pb= s->pb_time;
998 s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
999 s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
1000 s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
1001 s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp;
1009 s->dsp.clear_blocks(s->block[0]);
1018 /* the filters below are not XvMC compatible, skip them */
1019 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
1021 /* fill DC for inter blocks */
1022 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1023 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1024 int dc, dcu, dcv, y, n;
1026 uint8_t *dest_y, *dest_cb, *dest_cr;
1027 const int mb_xy= mb_x + mb_y * s->mb_stride;
1028 const int mb_type= s->current_picture.mb_type[mb_xy];
1030 error= s->error_status_table[mb_xy];
1032 if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
1033 // if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
1035 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1036 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1037 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1039 dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride];
1045 dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
1048 dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3;
1055 dcu+=dest_cb[x + y*(s->uvlinesize)];
1056 dcv+=dest_cr[x + y*(s->uvlinesize)];
1059 s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3;
1060 s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3;
1064 /* guess DC for damaged blocks */
1065 guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1);
1066 guess_dc(s, s->dc_val[1], s->mb_width , s->mb_height , s->mb_stride, 0);
1067 guess_dc(s, s->dc_val[2], s->mb_width , s->mb_height , s->mb_stride, 0);
1069 /* filter luma DC */
1070 filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride);
1072 /* render DC only intra */
1073 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1074 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1075 uint8_t *dest_y, *dest_cb, *dest_cr;
1076 const int mb_xy= mb_x + mb_y * s->mb_stride;
1077 const int mb_type= s->current_picture.mb_type[mb_xy];
1079 error= s->error_status_table[mb_xy];
1081 if(IS_INTER(mb_type)) continue;
1082 if(!(error&AC_ERROR)) continue; //undamaged
1084 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1085 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1086 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1088 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!=AV_PICTURE_TYPE_B && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
1111 s->mbskip_table[mb_xy]=0;
1113 s->mbintra_table[mb_xy]=1;