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
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 == FF_I_TYPE)
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==FF_I_TYPE){
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");
790 /* handle overlapping slices */
791 for(error_type=1; error_type<=3; error_type++){
794 for(i=s->mb_num-1; i>=0; i--){
795 const int mb_xy= s->mb_index2xy[i];
796 int error= s->error_status_table[mb_xy];
798 if(error&(1<<error_type))
800 if(error&(8<<error_type))
804 s->error_status_table[mb_xy]|= 1<<error_type;
812 /* handle slices with partitions of different length */
813 if(s->partitioned_frame){
816 for(i=s->mb_num-1; i>=0; i--){
817 const int mb_xy= s->mb_index2xy[i];
818 int error= s->error_status_table[mb_xy];
822 if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
826 s->error_status_table[mb_xy]|= AC_ERROR;
833 /* handle missing slices */
834 if(s->error_recognition>=4){
837 for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
838 const int mb_xy= s->mb_index2xy[i];
839 int error1= s->error_status_table[mb_xy ];
840 int error2= s->error_status_table[s->mb_index2xy[i+1]];
845 if( error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
846 && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
847 && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit
852 s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR;
857 /* backward mark errors */
859 for(error_type=1; error_type<=3; error_type++){
860 for(i=s->mb_num-1; i>=0; i--){
861 const int mb_xy= s->mb_index2xy[i];
862 int error= s->error_status_table[mb_xy];
864 if(!s->mbskip_table[mb_xy]) //FIXME partition specific
866 if(error&(1<<error_type))
869 if(s->partitioned_frame){
870 if(distance < threshold_part[error_type-1])
871 s->error_status_table[mb_xy]|= 1<<error_type;
873 if(distance < threshold)
874 s->error_status_table[mb_xy]|= 1<<error_type;
883 /* forward mark errors */
885 for(i=0; i<s->mb_num; i++){
886 const int mb_xy= s->mb_index2xy[i];
887 int old_error= s->error_status_table[mb_xy];
889 if(old_error&VP_START)
890 error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
892 error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
893 s->error_status_table[mb_xy]|= error;
897 /* handle not partitioned case */
898 if(!s->partitioned_frame){
899 for(i=0; i<s->mb_num; i++){
900 const int mb_xy= s->mb_index2xy[i];
901 error= s->error_status_table[mb_xy];
902 if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
903 error|= AC_ERROR|DC_ERROR|MV_ERROR;
904 s->error_status_table[mb_xy]= error;
909 dc_error= ac_error= mv_error=0;
910 for(i=0; i<s->mb_num; i++){
911 const int mb_xy= s->mb_index2xy[i];
912 error= s->error_status_table[mb_xy];
913 if(error&DC_ERROR) dc_error ++;
914 if(error&AC_ERROR) ac_error ++;
915 if(error&MV_ERROR) mv_error ++;
917 av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
919 is_intra_likely= is_intra_more_likely(s);
921 /* set unknown mb-type to most likely */
922 for(i=0; i<s->mb_num; i++){
923 const int mb_xy= s->mb_index2xy[i];
924 error= s->error_status_table[mb_xy];
925 if(!((error&DC_ERROR) && (error&MV_ERROR)))
929 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
931 s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
934 // change inter to intra blocks if no reference frames are available
935 if (!s->last_picture.data[0] && !s->next_picture.data[0])
936 for(i=0; i<s->mb_num; i++){
937 const int mb_xy= s->mb_index2xy[i];
938 if(!IS_INTRA(s->current_picture.mb_type[mb_xy]))
939 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
942 /* handle inter blocks with damaged AC */
943 for(mb_y=0; mb_y<s->mb_height; mb_y++){
944 for(mb_x=0; mb_x<s->mb_width; mb_x++){
945 const int mb_xy= mb_x + mb_y * s->mb_stride;
946 const int mb_type= s->current_picture.mb_type[mb_xy];
947 int dir = !s->last_picture.data[0];
948 error= s->error_status_table[mb_xy];
950 if(IS_INTRA(mb_type)) continue; //intra
951 if(error&MV_ERROR) continue; //inter with damaged MV
952 if(!(error&AC_ERROR)) continue; //undamaged inter
954 s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
958 int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
960 s->mv_type = MV_TYPE_8X8;
962 s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
963 s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
966 s->mv_type = MV_TYPE_16X16;
967 s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0];
968 s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1];
971 s->dsp.clear_blocks(s->block[0]);
975 decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/);
980 if(s->pict_type==FF_B_TYPE){
981 for(mb_y=0; mb_y<s->mb_height; mb_y++){
982 for(mb_x=0; mb_x<s->mb_width; mb_x++){
983 int xy= mb_x*2 + mb_y*2*s->b8_stride;
984 const int mb_xy= mb_x + mb_y * s->mb_stride;
985 const int mb_type= s->current_picture.mb_type[mb_xy];
986 error= s->error_status_table[mb_xy];
988 if(IS_INTRA(mb_type)) continue;
989 if(!(error&MV_ERROR)) continue; //inter with undamaged MV
990 if(!(error&AC_ERROR)) continue; //undamaged inter
992 s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
993 if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD;
994 if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD;
996 s->mv_type = MV_TYPE_16X16;
1000 int time_pp= s->pp_time;
1001 int time_pb= s->pb_time;
1003 s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
1004 s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
1005 s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
1006 s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp;
1014 s->dsp.clear_blocks(s->block[0]);
1023 /* the filters below are not XvMC compatible, skip them */
1024 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
1026 /* fill DC for inter blocks */
1027 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1028 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1029 int dc, dcu, dcv, y, n;
1031 uint8_t *dest_y, *dest_cb, *dest_cr;
1032 const int mb_xy= mb_x + mb_y * s->mb_stride;
1033 const int mb_type= s->current_picture.mb_type[mb_xy];
1035 error= s->error_status_table[mb_xy];
1037 if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
1038 // if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
1040 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1041 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1042 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1044 dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride];
1050 dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
1053 dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3;
1060 dcu+=dest_cb[x + y*(s->uvlinesize)];
1061 dcv+=dest_cr[x + y*(s->uvlinesize)];
1064 s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3;
1065 s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3;
1069 /* guess DC for damaged blocks */
1070 guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1);
1071 guess_dc(s, s->dc_val[1], s->mb_width , s->mb_height , s->mb_stride, 0);
1072 guess_dc(s, s->dc_val[2], s->mb_width , s->mb_height , s->mb_stride, 0);
1074 /* filter luma DC */
1075 filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride);
1078 /* render DC only intra */
1079 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1080 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1081 uint8_t *dest_y, *dest_cb, *dest_cr;
1082 const int mb_xy= mb_x + mb_y * s->mb_stride;
1083 const int mb_type= s->current_picture.mb_type[mb_xy];
1085 error= s->error_status_table[mb_xy];
1087 if(IS_INTER(mb_type)) continue;
1088 if(!(error&AC_ERROR)) continue; //undamaged
1090 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1091 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1092 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1094 put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1099 if(s->avctx->error_concealment&FF_EC_DEBLOCK){
1100 /* filter horizontal block boundaries */
1101 h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
1102 h_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
1103 h_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
1105 /* filter vertical block boundaries */
1106 v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
1107 v_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
1108 v_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
1112 /* clean a few tables */
1113 for(i=0; i<s->mb_num; i++){
1114 const int mb_xy= s->mb_index2xy[i];
1115 int error= s->error_status_table[mb_xy];
1117 if(s->pict_type!=FF_B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
1118 s->mbskip_table[mb_xy]=0;
1120 s->mbintra_table[mb_xy]=1;