Commit | Line | Data |
---|---|---|
4d2858de MN |
1 | /* |
2 | * Error resilience / concealment | |
3 | * | |
8f2ab833 | 4 | * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> |
4d2858de | 5 | * |
2912e87a | 6 | * This file is part of Libav. |
b78e7197 | 7 | * |
2912e87a | 8 | * Libav is free software; you can redistribute it and/or |
4d2858de MN |
9 | * modify it under the terms of the GNU Lesser General Public |
10 | * License as published by the Free Software Foundation; either | |
b78e7197 | 11 | * version 2.1 of the License, or (at your option) any later version. |
4d2858de | 12 | * |
2912e87a | 13 | * Libav is distributed in the hope that it will be useful, |
4d2858de MN |
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. | |
17 | * | |
18 | * You should have received a copy of the GNU Lesser General Public | |
2912e87a | 19 | * License along with Libav; if not, write to the Free Software |
5509bffa | 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
4d2858de | 21 | */ |
115329f1 | 22 | |
983e3246 | 23 | /** |
ba87f080 | 24 | * @file |
983e3246 MN |
25 | * Error resilience / concealment. |
26 | */ | |
4d2858de | 27 | |
7bc9090a | 28 | #include <limits.h> |
115329f1 | 29 | |
4d2858de MN |
30 | #include "avcodec.h" |
31 | #include "dsputil.h" | |
32 | #include "mpegvideo.h" | |
2c4bc23e | 33 | #include "h264.h" |
e5d2bdec | 34 | #include "rectangle.h" |
6a9c8594 | 35 | #include "thread.h" |
2c4bc23e MN |
36 | |
37 | /* | |
38 | * H264 redefines mb_intra so it is not mistakely used (its uninitialized in h264) | |
39 | * but error concealment must support both h264 and h263 thus we must undo this | |
40 | */ | |
41 | #undef mb_intra | |
4d2858de | 42 | |
673fc638 | 43 | static void decode_mb(MpegEncContext *s, int ref){ |
657ccb5a DB |
44 | s->dest[0] = s->current_picture.f.data[0] + (s->mb_y * 16 * s->linesize) + s->mb_x * 16; |
45 | s->dest[1] = s->current_picture.f.data[1] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift); | |
46 | s->dest[2] = s->current_picture.f.data[2] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift); | |
7d1c3fc1 | 47 | |
3546fa8d | 48 | if(CONFIG_H264_DECODER && s->codec_id == CODEC_ID_H264){ |
68f0bc7e MN |
49 | H264Context *h= (void*)s; |
50 | h->mb_xy= s->mb_x + s->mb_y*s->mb_stride; | |
51 | memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache)); | |
673fc638 | 52 | assert(ref>=0); |
5ea20630 | 53 | /* FIXME: It is possible albeit uncommon that slice references |
8fd35b1a DB |
54 | * differ between slices. We take the easy approach and ignore |
55 | * it for now. If this turns out to have any relevance in | |
56 | * practice then correct remapping should be added. */ | |
57 | if (ref >= h->ref_count[0]) | |
673fc638 | 58 | ref=0; |
657ccb5a | 59 | fill_rectangle(&s->current_picture.f.ref_index[0][4*h->mb_xy], 2, 2, 2, ref, 1); |
673fc638 | 60 | fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1); |
68f0bc7e | 61 | fill_rectangle(h->mv_cache[0][ scan8[0] ], 4, 4, 8, pack16to32(s->mv[0][0][0],s->mv[0][0][1]), 4); |
68f0bc7e MN |
62 | assert(!FRAME_MBAFF); |
63 | ff_h264_hl_decode_mb(h); | |
64 | }else{ | |
673fc638 | 65 | assert(ref==0); |
115329f1 | 66 | MPV_decode_mb(s, s->block); |
68f0bc7e | 67 | } |
7d1c3fc1 MN |
68 | } |
69 | ||
4d2858de | 70 | /** |
2c4bc23e MN |
71 | * @param stride the number of MVs to get to the next row |
72 | * @param mv_step the number of MVs per row or column in a macroblock | |
73 | */ | |
74 | static void set_mv_strides(MpegEncContext *s, int *mv_step, int *stride){ | |
75 | if(s->codec_id == CODEC_ID_H264){ | |
76 | H264Context *h= (void*)s; | |
77 | assert(s->quarter_sample); | |
78 | *mv_step= 4; | |
79 | *stride= h->b_stride; | |
80 | }else{ | |
81 | *mv_step= 2; | |
82 | *stride= s->b8_stride; | |
83 | } | |
84 | } | |
85 | ||
86 | /** | |
58c42af7 | 87 | * Replace the current MB with a flat dc-only version. |
4d2858de MN |
88 | */ |
89 | static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y) | |
90 | { | |
91 | int dc, dcu, dcv, y, i; | |
92 | for(i=0; i<4; i++){ | |
137c8468 | 93 | dc= s->dc_val[0][mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*s->b8_stride]; |
4d2858de MN |
94 | if(dc<0) dc=0; |
95 | else if(dc>2040) dc=2040; | |
96 | for(y=0; y<8; y++){ | |
97 | int x; | |
98 | for(x=0; x<8; x++){ | |
99 | dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8; | |
100 | } | |
101 | } | |
102 | } | |
137c8468 MN |
103 | dcu = s->dc_val[1][mb_x + mb_y*s->mb_stride]; |
104 | dcv = s->dc_val[2][mb_x + mb_y*s->mb_stride]; | |
4d2858de MN |
105 | if (dcu<0 ) dcu=0; |
106 | else if(dcu>2040) dcu=2040; | |
107 | if (dcv<0 ) dcv=0; | |
108 | else if(dcv>2040) dcv=2040; | |
109 | for(y=0; y<8; y++){ | |
110 | int x; | |
111 | for(x=0; x<8; x++){ | |
3dc99a18 DB |
112 | dest_cb[x + y * s->uvlinesize] = dcu / 8; |
113 | dest_cr[x + y * s->uvlinesize] = dcv / 8; | |
4d2858de MN |
114 | } |
115 | } | |
116 | } | |
117 | ||
b86216de | 118 | static void filter181(int16_t *data, int width, int height, int stride){ |
4d2858de MN |
119 | int x,y; |
120 | ||
121 | /* horizontal filter */ | |
122 | for(y=1; y<height-1; y++){ | |
123 | int prev_dc= data[0 + y*stride]; | |
124 | ||
125 | for(x=1; x<width-1; x++){ | |
126 | int dc; | |
115329f1 DB |
127 | |
128 | dc= - prev_dc | |
4d2858de MN |
129 | + data[x + y*stride]*8 |
130 | - data[x + 1 + y*stride]; | |
131 | dc= (dc*10923 + 32768)>>16; | |
132 | prev_dc= data[x + y*stride]; | |
133 | data[x + y*stride]= dc; | |
134 | } | |
135 | } | |
115329f1 | 136 | |
4d2858de MN |
137 | /* vertical filter */ |
138 | for(x=1; x<width-1; x++){ | |
139 | int prev_dc= data[x]; | |
140 | ||
141 | for(y=1; y<height-1; y++){ | |
142 | int dc; | |
115329f1 DB |
143 | |
144 | dc= - prev_dc | |
4d2858de MN |
145 | + data[x + y *stride]*8 |
146 | - data[x + (y+1)*stride]; | |
147 | dc= (dc*10923 + 32768)>>16; | |
148 | prev_dc= data[x + y*stride]; | |
149 | data[x + y*stride]= dc; | |
150 | } | |
151 | } | |
152 | } | |
153 | ||
154 | /** | |
755bfeab | 155 | * guess the dc of blocks which do not have an undamaged dc |
bb270c08 DB |
156 | * @param w width in 8 pixel blocks |
157 | * @param h height in 8 pixel blocks | |
4d2858de | 158 | */ |
b86216de | 159 | static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, int is_luma){ |
4d2858de MN |
160 | int b_x, b_y; |
161 | ||
162 | for(b_y=0; b_y<h; b_y++){ | |
163 | for(b_x=0; b_x<w; b_x++){ | |
164 | int color[4]={1024,1024,1024,1024}; | |
165 | int distance[4]={9999,9999,9999,9999}; | |
166 | int mb_index, error, j; | |
0c1a9eda | 167 | int64_t guess, weight_sum; |
115329f1 | 168 | |
7bc9090a | 169 | mb_index= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride; |
115329f1 | 170 | |
4d2858de | 171 | error= s->error_status_table[mb_index]; |
115329f1 | 172 | |
657ccb5a | 173 | if(IS_INTER(s->current_picture.f.mb_type[mb_index])) continue; //inter |
5bf2ac2b | 174 | if(!(error&ER_DC_ERROR)) continue; //dc-ok |
115329f1 | 175 | |
4d2858de MN |
176 | /* right block */ |
177 | for(j=b_x+1; j<w; j++){ | |
7bc9090a | 178 | int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride; |
4d2858de | 179 | int error_j= s->error_status_table[mb_index_j]; |
657ccb5a | 180 | int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]); |
5bf2ac2b | 181 | if(intra_j==0 || !(error_j&ER_DC_ERROR)){ |
4d2858de MN |
182 | color[0]= dc[j + b_y*stride]; |
183 | distance[0]= j-b_x; | |
184 | break; | |
185 | } | |
186 | } | |
115329f1 | 187 | |
4d2858de MN |
188 | /* left block */ |
189 | for(j=b_x-1; j>=0; j--){ | |
7bc9090a | 190 | int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride; |
4d2858de | 191 | int error_j= s->error_status_table[mb_index_j]; |
657ccb5a | 192 | int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]); |
5bf2ac2b | 193 | if(intra_j==0 || !(error_j&ER_DC_ERROR)){ |
4d2858de MN |
194 | color[1]= dc[j + b_y*stride]; |
195 | distance[1]= b_x-j; | |
196 | break; | |
197 | } | |
198 | } | |
199 | ||
200 | /* bottom block */ | |
201 | for(j=b_y+1; j<h; j++){ | |
7bc9090a | 202 | int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride; |
4d2858de | 203 | int error_j= s->error_status_table[mb_index_j]; |
657ccb5a | 204 | int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]); |
5bf2ac2b | 205 | if(intra_j==0 || !(error_j&ER_DC_ERROR)){ |
4d2858de MN |
206 | color[2]= dc[b_x + j*stride]; |
207 | distance[2]= j-b_y; | |
208 | break; | |
209 | } | |
210 | } | |
211 | ||
212 | /* top block */ | |
213 | for(j=b_y-1; j>=0; j--){ | |
7bc9090a | 214 | int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride; |
4d2858de | 215 | int error_j= s->error_status_table[mb_index_j]; |
657ccb5a | 216 | int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]); |
5bf2ac2b | 217 | if(intra_j==0 || !(error_j&ER_DC_ERROR)){ |
4d2858de MN |
218 | color[3]= dc[b_x + j*stride]; |
219 | distance[3]= b_y-j; | |
220 | break; | |
221 | } | |
222 | } | |
115329f1 | 223 | |
4d2858de MN |
224 | weight_sum=0; |
225 | guess=0; | |
226 | for(j=0; j<4; j++){ | |
0c1a9eda ZK |
227 | int64_t weight= 256*256*256*16/distance[j]; |
228 | guess+= weight*(int64_t)color[j]; | |
4d2858de MN |
229 | weight_sum+= weight; |
230 | } | |
231 | guess= (guess + weight_sum/2) / weight_sum; | |
232 | ||
233 | dc[b_x + b_y*stride]= guess; | |
234 | } | |
235 | } | |
236 | } | |
237 | ||
238 | /** | |
239 | * simple horizontal deblocking filter used for error resilience | |
bb270c08 DB |
240 | * @param w width in 8 pixel blocks |
241 | * @param h height in 8 pixel blocks | |
4d2858de | 242 | */ |
0c1a9eda | 243 | static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){ |
bb4fcfa3 | 244 | int b_x, b_y, mvx_stride, mvy_stride; |
55fde95e | 245 | uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; |
bb4fcfa3 MN |
246 | set_mv_strides(s, &mvx_stride, &mvy_stride); |
247 | mvx_stride >>= is_luma; | |
248 | mvy_stride *= mvx_stride; | |
4d2858de MN |
249 | |
250 | for(b_y=0; b_y<h; b_y++){ | |
251 | for(b_x=0; b_x<w-1; b_x++){ | |
252 | int y; | |
7bc9090a MN |
253 | int left_status = s->error_status_table[( b_x >>is_luma) + (b_y>>is_luma)*s->mb_stride]; |
254 | int right_status= s->error_status_table[((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride]; | |
657ccb5a DB |
255 | int left_intra = IS_INTRA(s->current_picture.f.mb_type[( b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride]); |
256 | int right_intra = IS_INTRA(s->current_picture.f.mb_type[((b_x + 1) >> is_luma) + (b_y >> is_luma) * s->mb_stride]); | |
63ccd466 LB |
257 | int left_damage = left_status&ER_MB_ERROR; |
258 | int right_damage= right_status&ER_MB_ERROR; | |
4d2858de | 259 | int offset= b_x*8 + b_y*stride*8; |
657ccb5a DB |
260 | int16_t *left_mv= s->current_picture.f.motion_val[0][mvy_stride*b_y + mvx_stride* b_x ]; |
261 | int16_t *right_mv= s->current_picture.f.motion_val[0][mvy_stride*b_y + mvx_stride*(b_x+1)]; | |
115329f1 | 262 | |
4d2858de | 263 | if(!(left_damage||right_damage)) continue; // both undamaged |
115329f1 DB |
264 | |
265 | if( (!left_intra) && (!right_intra) | |
c26abfa5 | 266 | && FFABS(left_mv[0]-right_mv[0]) + FFABS(left_mv[1]+right_mv[1]) < 2) continue; |
115329f1 | 267 | |
4d2858de MN |
268 | for(y=0; y<8; y++){ |
269 | int a,b,c,d; | |
115329f1 | 270 | |
4d2858de MN |
271 | a= dst[offset + 7 + y*stride] - dst[offset + 6 + y*stride]; |
272 | b= dst[offset + 8 + y*stride] - dst[offset + 7 + y*stride]; | |
273 | c= dst[offset + 9 + y*stride] - dst[offset + 8 + y*stride]; | |
115329f1 | 274 | |
c26abfa5 | 275 | d= FFABS(b) - ((FFABS(a) + FFABS(c) + 1)>>1); |
b8a78f41 | 276 | d= FFMAX(d, 0); |
4d2858de | 277 | if(b<0) d= -d; |
115329f1 | 278 | |
4d2858de MN |
279 | if(d==0) continue; |
280 | ||
281 | if(!(left_damage && right_damage)) | |
282 | d= d*16/9; | |
115329f1 | 283 | |
4d2858de MN |
284 | if(left_damage){ |
285 | dst[offset + 7 + y*stride] = cm[dst[offset + 7 + y*stride] + ((d*7)>>4)]; | |
286 | dst[offset + 6 + y*stride] = cm[dst[offset + 6 + y*stride] + ((d*5)>>4)]; | |
287 | dst[offset + 5 + y*stride] = cm[dst[offset + 5 + y*stride] + ((d*3)>>4)]; | |
288 | dst[offset + 4 + y*stride] = cm[dst[offset + 4 + y*stride] + ((d*1)>>4)]; | |
289 | } | |
290 | if(right_damage){ | |
291 | dst[offset + 8 + y*stride] = cm[dst[offset + 8 + y*stride] - ((d*7)>>4)]; | |
292 | dst[offset + 9 + y*stride] = cm[dst[offset + 9 + y*stride] - ((d*5)>>4)]; | |
293 | dst[offset + 10+ y*stride] = cm[dst[offset +10 + y*stride] - ((d*3)>>4)]; | |
294 | dst[offset + 11+ y*stride] = cm[dst[offset +11 + y*stride] - ((d*1)>>4)]; | |
295 | } | |
296 | } | |
297 | } | |
298 | } | |
299 | } | |
300 | ||
301 | /** | |
302 | * simple vertical deblocking filter used for error resilience | |
bb270c08 DB |
303 | * @param w width in 8 pixel blocks |
304 | * @param h height in 8 pixel blocks | |
4d2858de | 305 | */ |
0c1a9eda | 306 | static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){ |
bb4fcfa3 | 307 | int b_x, b_y, mvx_stride, mvy_stride; |
55fde95e | 308 | uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; |
bb4fcfa3 MN |
309 | set_mv_strides(s, &mvx_stride, &mvy_stride); |
310 | mvx_stride >>= is_luma; | |
311 | mvy_stride *= mvx_stride; | |
4d2858de MN |
312 | |
313 | for(b_y=0; b_y<h-1; b_y++){ | |
314 | for(b_x=0; b_x<w; b_x++){ | |
315 | int x; | |
7bc9090a MN |
316 | int top_status = s->error_status_table[(b_x>>is_luma) + ( b_y >>is_luma)*s->mb_stride]; |
317 | int bottom_status= s->error_status_table[(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride]; | |
657ccb5a DB |
318 | int top_intra = IS_INTRA(s->current_picture.f.mb_type[(b_x >> is_luma) + ( b_y >> is_luma) * s->mb_stride]); |
319 | int bottom_intra = IS_INTRA(s->current_picture.f.mb_type[(b_x >> is_luma) + ((b_y + 1) >> is_luma) * s->mb_stride]); | |
63ccd466 LB |
320 | int top_damage = top_status&ER_MB_ERROR; |
321 | int bottom_damage= bottom_status&ER_MB_ERROR; | |
4d2858de | 322 | int offset= b_x*8 + b_y*stride*8; |
657ccb5a DB |
323 | int16_t *top_mv = s->current_picture.f.motion_val[0][mvy_stride * b_y + mvx_stride * b_x]; |
324 | int16_t *bottom_mv = s->current_picture.f.motion_val[0][mvy_stride * (b_y + 1) + mvx_stride * b_x]; | |
115329f1 | 325 | |
4d2858de | 326 | if(!(top_damage||bottom_damage)) continue; // both undamaged |
115329f1 DB |
327 | |
328 | if( (!top_intra) && (!bottom_intra) | |
c26abfa5 | 329 | && FFABS(top_mv[0]-bottom_mv[0]) + FFABS(top_mv[1]+bottom_mv[1]) < 2) continue; |
115329f1 | 330 | |
4d2858de MN |
331 | for(x=0; x<8; x++){ |
332 | int a,b,c,d; | |
115329f1 | 333 | |
4d2858de MN |
334 | a= dst[offset + x + 7*stride] - dst[offset + x + 6*stride]; |
335 | b= dst[offset + x + 8*stride] - dst[offset + x + 7*stride]; | |
336 | c= dst[offset + x + 9*stride] - dst[offset + x + 8*stride]; | |
115329f1 | 337 | |
c26abfa5 | 338 | d= FFABS(b) - ((FFABS(a) + FFABS(c)+1)>>1); |
b8a78f41 | 339 | d= FFMAX(d, 0); |
4d2858de | 340 | if(b<0) d= -d; |
115329f1 | 341 | |
4d2858de MN |
342 | if(d==0) continue; |
343 | ||
344 | if(!(top_damage && bottom_damage)) | |
345 | d= d*16/9; | |
115329f1 | 346 | |
4d2858de MN |
347 | if(top_damage){ |
348 | dst[offset + x + 7*stride] = cm[dst[offset + x + 7*stride] + ((d*7)>>4)]; | |
349 | dst[offset + x + 6*stride] = cm[dst[offset + x + 6*stride] + ((d*5)>>4)]; | |
350 | dst[offset + x + 5*stride] = cm[dst[offset + x + 5*stride] + ((d*3)>>4)]; | |
351 | dst[offset + x + 4*stride] = cm[dst[offset + x + 4*stride] + ((d*1)>>4)]; | |
352 | } | |
353 | if(bottom_damage){ | |
354 | dst[offset + x + 8*stride] = cm[dst[offset + x + 8*stride] - ((d*7)>>4)]; | |
355 | dst[offset + x + 9*stride] = cm[dst[offset + x + 9*stride] - ((d*5)>>4)]; | |
356 | dst[offset + x + 10*stride] = cm[dst[offset + x + 10*stride] - ((d*3)>>4)]; | |
357 | dst[offset + x + 11*stride] = cm[dst[offset + x + 11*stride] - ((d*1)>>4)]; | |
358 | } | |
359 | } | |
360 | } | |
361 | } | |
362 | } | |
363 | ||
364 | static void guess_mv(MpegEncContext *s){ | |
7bc9090a | 365 | uint8_t fixed[s->mb_stride * s->mb_height]; |
4d2858de MN |
366 | #define MV_FROZEN 3 |
367 | #define MV_CHANGED 2 | |
368 | #define MV_UNCHANGED 1 | |
7bc9090a | 369 | const int mb_stride = s->mb_stride; |
4d2858de MN |
370 | const int mb_width = s->mb_width; |
371 | const int mb_height= s->mb_height; | |
372 | int i, depth, num_avail; | |
2c4bc23e MN |
373 | int mb_x, mb_y, mot_step, mot_stride; |
374 | ||
375 | set_mv_strides(s, &mot_step, &mot_stride); | |
115329f1 | 376 | |
4d2858de MN |
377 | num_avail=0; |
378 | for(i=0; i<s->mb_num; i++){ | |
7bc9090a | 379 | const int mb_xy= s->mb_index2xy[ i ]; |
4d2858de | 380 | int f=0; |
7bc9090a | 381 | int error= s->error_status_table[mb_xy]; |
4d2858de | 382 | |
657ccb5a | 383 | if(IS_INTRA(s->current_picture.f.mb_type[mb_xy])) f=MV_FROZEN; //intra //FIXME check |
5bf2ac2b | 384 | if(!(error&ER_MV_ERROR)) f=MV_FROZEN; //inter with undamaged MV |
115329f1 | 385 | |
7bc9090a | 386 | fixed[mb_xy]= f; |
4d2858de MN |
387 | if(f==MV_FROZEN) |
388 | num_avail++; | |
389 | } | |
115329f1 | 390 | |
4d2858de | 391 | if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || num_avail <= mb_width/2){ |
4d2858de MN |
392 | for(mb_y=0; mb_y<s->mb_height; mb_y++){ |
393 | for(mb_x=0; mb_x<s->mb_width; mb_x++){ | |
7bc9090a | 394 | const int mb_xy= mb_x + mb_y*s->mb_stride; |
115329f1 | 395 | |
657ccb5a | 396 | if(IS_INTRA(s->current_picture.f.mb_type[mb_xy])) continue; |
5bf2ac2b | 397 | if(!(s->error_status_table[mb_xy]&ER_MV_ERROR)) continue; |
4d2858de | 398 | |
657ccb5a | 399 | s->mv_dir = s->last_picture.f.data[0] ? MV_DIR_FORWARD : MV_DIR_BACKWARD; |
4d2858de MN |
400 | s->mb_intra=0; |
401 | s->mv_type = MV_TYPE_16X16; | |
160d679c | 402 | s->mb_skipped=0; |
4d2858de | 403 | |
bb270c08 | 404 | s->dsp.clear_blocks(s->block[0]); |
4d2858de MN |
405 | |
406 | s->mb_x= mb_x; | |
407 | s->mb_y= mb_y; | |
408 | s->mv[0][0][0]= 0; | |
409 | s->mv[0][0][1]= 0; | |
673fc638 | 410 | decode_mb(s, 0); |
4d2858de MN |
411 | } |
412 | } | |
413 | return; | |
414 | } | |
115329f1 | 415 | |
4d2858de MN |
416 | for(depth=0;; depth++){ |
417 | int changed, pass, none_left; | |
418 | ||
419 | none_left=1; | |
420 | changed=1; | |
421 | for(pass=0; (changed || pass<2) && pass<10; pass++){ | |
7bc9090a | 422 | int mb_x, mb_y; |
4d2858de | 423 | int score_sum=0; |
115329f1 | 424 | |
4d2858de | 425 | changed=0; |
4d2858de MN |
426 | for(mb_y=0; mb_y<s->mb_height; mb_y++){ |
427 | for(mb_x=0; mb_x<s->mb_width; mb_x++){ | |
7bc9090a | 428 | const int mb_xy= mb_x + mb_y*s->mb_stride; |
4d2858de | 429 | int mv_predictor[8][2]={{0}}; |
673fc638 | 430 | int ref[8]={0}; |
4d2858de MN |
431 | int pred_count=0; |
432 | int j; | |
433 | int best_score=256*256*256*64; | |
434 | int best_pred=0; | |
2c4bc23e | 435 | const int mot_index= (mb_x + mb_y*mot_stride) * mot_step; |
6a9c8594 | 436 | int prev_x, prev_y, prev_ref; |
4d2858de | 437 | |
4d2858de | 438 | if((mb_x^mb_y^pass)&1) continue; |
115329f1 | 439 | |
7bc9090a | 440 | if(fixed[mb_xy]==MV_FROZEN) continue; |
657ccb5a DB |
441 | assert(!IS_INTRA(s->current_picture.f.mb_type[mb_xy])); |
442 | assert(s->last_picture_ptr && s->last_picture_ptr->f.data[0]); | |
115329f1 | 443 | |
4d2858de | 444 | j=0; |
7bc9090a MN |
445 | if(mb_x>0 && fixed[mb_xy-1 ]==MV_FROZEN) j=1; |
446 | if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_FROZEN) j=1; | |
447 | if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_FROZEN) j=1; | |
448 | if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_FROZEN) j=1; | |
4d2858de MN |
449 | if(j==0) continue; |
450 | ||
451 | j=0; | |
7bc9090a MN |
452 | if(mb_x>0 && fixed[mb_xy-1 ]==MV_CHANGED) j=1; |
453 | if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_CHANGED) j=1; | |
454 | if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_CHANGED) j=1; | |
455 | if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_CHANGED) j=1; | |
4d2858de | 456 | if(j==0 && pass>1) continue; |
115329f1 | 457 | |
4d2858de | 458 | none_left=0; |
115329f1 | 459 | |
7bc9090a | 460 | if(mb_x>0 && fixed[mb_xy-1]){ |
657ccb5a DB |
461 | mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index - mot_step][0]; |
462 | mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index - mot_step][1]; | |
463 | ref [pred_count] = s->current_picture.f.ref_index[0][4*(mb_xy-1)]; | |
4d2858de MN |
464 | pred_count++; |
465 | } | |
7bc9090a | 466 | if(mb_x+1<mb_width && fixed[mb_xy+1]){ |
657ccb5a DB |
467 | mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index + mot_step][0]; |
468 | mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index + mot_step][1]; | |
469 | ref [pred_count] = s->current_picture.f.ref_index[0][4*(mb_xy+1)]; | |
4d2858de MN |
470 | pred_count++; |
471 | } | |
7bc9090a | 472 | if(mb_y>0 && fixed[mb_xy-mb_stride]){ |
657ccb5a DB |
473 | mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index - mot_stride*mot_step][0]; |
474 | mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index - mot_stride*mot_step][1]; | |
475 | ref [pred_count] = s->current_picture.f.ref_index[0][4*(mb_xy-s->mb_stride)]; | |
4d2858de MN |
476 | pred_count++; |
477 | } | |
7bc9090a | 478 | if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){ |
657ccb5a DB |
479 | mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index + mot_stride*mot_step][0]; |
480 | mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index + mot_stride*mot_step][1]; | |
481 | ref [pred_count] = s->current_picture.f.ref_index[0][4*(mb_xy+s->mb_stride)]; | |
4d2858de MN |
482 | pred_count++; |
483 | } | |
484 | if(pred_count==0) continue; | |
115329f1 | 485 | |
4d2858de | 486 | if(pred_count>1){ |
673fc638 MN |
487 | int sum_x=0, sum_y=0, sum_r=0; |
488 | int max_x, max_y, min_x, min_y, max_r, min_r; | |
4d2858de MN |
489 | |
490 | for(j=0; j<pred_count; j++){ | |
491 | sum_x+= mv_predictor[j][0]; | |
492 | sum_y+= mv_predictor[j][1]; | |
673fc638 | 493 | sum_r+= ref[j]; |
fc4a2d1e | 494 | if(j && ref[j] != ref[j-1]) |
673fc638 | 495 | goto skip_mean_and_median; |
4d2858de | 496 | } |
115329f1 | 497 | |
4d2858de MN |
498 | /* mean */ |
499 | mv_predictor[pred_count][0] = sum_x/j; | |
500 | mv_predictor[pred_count][1] = sum_y/j; | |
673fc638 | 501 | ref [pred_count] = sum_r/j; |
115329f1 | 502 | |
4d2858de MN |
503 | /* median */ |
504 | if(pred_count>=3){ | |
673fc638 MN |
505 | min_y= min_x= min_r= 99999; |
506 | max_y= max_x= max_r=-99999; | |
4d2858de | 507 | }else{ |
673fc638 | 508 | min_x=min_y=max_x=max_y=min_r=max_r=0; |
4d2858de MN |
509 | } |
510 | for(j=0; j<pred_count; j++){ | |
b8a78f41 MN |
511 | max_x= FFMAX(max_x, mv_predictor[j][0]); |
512 | max_y= FFMAX(max_y, mv_predictor[j][1]); | |
673fc638 | 513 | max_r= FFMAX(max_r, ref[j]); |
b8a78f41 MN |
514 | min_x= FFMIN(min_x, mv_predictor[j][0]); |
515 | min_y= FFMIN(min_y, mv_predictor[j][1]); | |
673fc638 | 516 | min_r= FFMIN(min_r, ref[j]); |
4d2858de MN |
517 | } |
518 | mv_predictor[pred_count+1][0] = sum_x - max_x - min_x; | |
519 | mv_predictor[pred_count+1][1] = sum_y - max_y - min_y; | |
673fc638 | 520 | ref [pred_count+1] = sum_r - max_r - min_r; |
115329f1 | 521 | |
4d2858de MN |
522 | if(pred_count==4){ |
523 | mv_predictor[pred_count+1][0] /= 2; | |
524 | mv_predictor[pred_count+1][1] /= 2; | |
673fc638 | 525 | ref [pred_count+1] /= 2; |
4d2858de MN |
526 | } |
527 | pred_count+=2; | |
528 | } | |
673fc638 | 529 | skip_mean_and_median: |
115329f1 | 530 | |
4d2858de MN |
531 | /* zero MV */ |
532 | pred_count++; | |
533 | ||
6a9c8594 AS |
534 | if (!fixed[mb_xy]) { |
535 | if (s->avctx->codec_id == CODEC_ID_H264) { | |
536 | // FIXME | |
537 | } else { | |
538 | ff_thread_await_progress((AVFrame *) s->last_picture_ptr, | |
539 | mb_y, 0); | |
540 | } | |
657ccb5a DB |
541 | if (!s->last_picture.f.motion_val[0] || |
542 | !s->last_picture.f.ref_index[0]) | |
20153fb8 | 543 | goto skip_last_mv; |
657ccb5a DB |
544 | prev_x = s->last_picture.f.motion_val[0][mot_index][0]; |
545 | prev_y = s->last_picture.f.motion_val[0][mot_index][1]; | |
546 | prev_ref = s->last_picture.f.ref_index[0][4*mb_xy]; | |
6a9c8594 | 547 | } else { |
657ccb5a DB |
548 | prev_x = s->current_picture.f.motion_val[0][mot_index][0]; |
549 | prev_y = s->current_picture.f.motion_val[0][mot_index][1]; | |
550 | prev_ref = s->current_picture.f.ref_index[0][4*mb_xy]; | |
6a9c8594 AS |
551 | } |
552 | ||
4d2858de | 553 | /* last MV */ |
6a9c8594 AS |
554 | mv_predictor[pred_count][0]= prev_x; |
555 | mv_predictor[pred_count][1]= prev_y; | |
556 | ref [pred_count] = prev_ref; | |
d42aaa80 | 557 | pred_count++; |
20153fb8 | 558 | skip_last_mv: |
115329f1 | 559 | |
4d2858de MN |
560 | s->mv_dir = MV_DIR_FORWARD; |
561 | s->mb_intra=0; | |
562 | s->mv_type = MV_TYPE_16X16; | |
160d679c | 563 | s->mb_skipped=0; |
4d2858de | 564 | |
bb270c08 | 565 | s->dsp.clear_blocks(s->block[0]); |
4d2858de MN |
566 | |
567 | s->mb_x= mb_x; | |
568 | s->mb_y= mb_y; | |
7bc9090a | 569 | |
4d2858de MN |
570 | for(j=0; j<pred_count; j++){ |
571 | int score=0; | |
657ccb5a | 572 | uint8_t *src = s->current_picture.f.data[0] + mb_x*16 + mb_y*16*s->linesize; |
4d2858de | 573 | |
657ccb5a DB |
574 | s->current_picture.f.motion_val[0][mot_index][0] = s->mv[0][0][0] = mv_predictor[j][0]; |
575 | s->current_picture.f.motion_val[0][mot_index][1] = s->mv[0][0][1] = mv_predictor[j][1]; | |
7bc9090a | 576 | |
fc4a2d1e | 577 | if(ref[j]<0) //predictor intra or otherwise not available |
673fc638 MN |
578 | continue; |
579 | ||
580 | decode_mb(s, ref[j]); | |
115329f1 | 581 | |
7bc9090a | 582 | if(mb_x>0 && fixed[mb_xy-1]){ |
4d2858de MN |
583 | int k; |
584 | for(k=0; k<16; k++) | |
c26abfa5 | 585 | score += FFABS(src[k*s->linesize-1 ]-src[k*s->linesize ]); |
4d2858de | 586 | } |
7bc9090a | 587 | if(mb_x+1<mb_width && fixed[mb_xy+1]){ |
4d2858de MN |
588 | int k; |
589 | for(k=0; k<16; k++) | |
c26abfa5 | 590 | score += FFABS(src[k*s->linesize+15]-src[k*s->linesize+16]); |
4d2858de | 591 | } |
7bc9090a | 592 | if(mb_y>0 && fixed[mb_xy-mb_stride]){ |
4d2858de MN |
593 | int k; |
594 | for(k=0; k<16; k++) | |
c26abfa5 | 595 | score += FFABS(src[k-s->linesize ]-src[k ]); |
4d2858de | 596 | } |
7bc9090a | 597 | if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){ |
4d2858de MN |
598 | int k; |
599 | for(k=0; k<16; k++) | |
c26abfa5 | 600 | score += FFABS(src[k+s->linesize*15]-src[k+s->linesize*16]); |
4d2858de | 601 | } |
115329f1 | 602 | |
4d2858de MN |
603 | if(score <= best_score){ // <= will favor the last MV |
604 | best_score= score; | |
605 | best_pred= j; | |
606 | } | |
607 | } | |
608 | score_sum+= best_score; | |
686c7817 MN |
609 | s->mv[0][0][0]= mv_predictor[best_pred][0]; |
610 | s->mv[0][0][1]= mv_predictor[best_pred][1]; | |
611 | ||
612 | for(i=0; i<mot_step; i++) | |
613 | for(j=0; j<mot_step; j++){ | |
657ccb5a DB |
614 | s->current_picture.f.motion_val[0][mot_index + i + j * mot_stride][0] = s->mv[0][0][0]; |
615 | s->current_picture.f.motion_val[0][mot_index + i + j * mot_stride][1] = s->mv[0][0][1]; | |
686c7817 | 616 | } |
4d2858de | 617 | |
673fc638 | 618 | decode_mb(s, ref[best_pred]); |
4d2858de | 619 | |
115329f1 | 620 | |
4d2858de | 621 | if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){ |
7bc9090a | 622 | fixed[mb_xy]=MV_CHANGED; |
4d2858de MN |
623 | changed++; |
624 | }else | |
7bc9090a | 625 | fixed[mb_xy]=MV_UNCHANGED; |
4d2858de MN |
626 | } |
627 | } | |
628 | ||
629 | // printf(".%d/%d", changed, score_sum); fflush(stdout); | |
630 | } | |
115329f1 DB |
631 | |
632 | if(none_left) | |
4d2858de | 633 | return; |
115329f1 | 634 | |
4d2858de | 635 | for(i=0; i<s->mb_num; i++){ |
7bc9090a MN |
636 | int mb_xy= s->mb_index2xy[i]; |
637 | if(fixed[mb_xy]) | |
638 | fixed[mb_xy]=MV_FROZEN; | |
4d2858de MN |
639 | } |
640 | // printf(":"); fflush(stdout); | |
641 | } | |
642 | } | |
115329f1 | 643 | |
4d2858de MN |
644 | static int is_intra_more_likely(MpegEncContext *s){ |
645 | int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y; | |
115329f1 | 646 | |
657ccb5a | 647 | if (!s->last_picture_ptr || !s->last_picture_ptr->f.data[0]) return 1; //no previous frame available -> use spatial prediction |
4d2858de MN |
648 | |
649 | undamaged_count=0; | |
650 | for(i=0; i<s->mb_num; i++){ | |
7bc9090a MN |
651 | const int mb_xy= s->mb_index2xy[i]; |
652 | const int error= s->error_status_table[mb_xy]; | |
5bf2ac2b | 653 | if(!((error&ER_DC_ERROR) && (error&ER_MV_ERROR))) |
4d2858de MN |
654 | undamaged_count++; |
655 | } | |
115329f1 | 656 | |
c28112fa MN |
657 | if(s->codec_id == CODEC_ID_H264){ |
658 | H264Context *h= (void*)s; | |
e8ac80fb | 659 | if (h->list_count <= 0 || h->ref_count[0] <= 0 || !h->ref_list[0][0].f.data[0]) |
c28112fa MN |
660 | return 1; |
661 | } | |
662 | ||
04932b0d | 663 | if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction |
115329f1 | 664 | |
551109d4 | 665 | //prevent dsp.sad() check, that requires access to the image |
975a1447 | 666 | if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == AV_PICTURE_TYPE_I) |
83344066 | 667 | return 1; |
551109d4 | 668 | |
8fd35b1a | 669 | skip_amount = FFMAX(undamaged_count / 50, 1); // check only up to 50 MBs |
4d2858de MN |
670 | is_intra_likely=0; |
671 | ||
672 | j=0; | |
4d2858de MN |
673 | for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){ |
674 | for(mb_x= 0; mb_x<s->mb_width; mb_x++){ | |
675 | int error; | |
7bc9090a | 676 | const int mb_xy= mb_x + mb_y*s->mb_stride; |
4d2858de | 677 | |
7bc9090a | 678 | error= s->error_status_table[mb_xy]; |
5bf2ac2b | 679 | if((error&ER_DC_ERROR) && (error&ER_MV_ERROR)) |
4d2858de | 680 | continue; //skip damaged |
115329f1 DB |
681 | |
682 | j++; | |
4d2858de | 683 | if((j%skip_amount) != 0) continue; //skip a few to speed things up |
115329f1 | 684 | |
975a1447 | 685 | if(s->pict_type==AV_PICTURE_TYPE_I){ |
657ccb5a DB |
686 | uint8_t *mb_ptr = s->current_picture.f.data[0] + mb_x*16 + mb_y*16*s->linesize; |
687 | uint8_t *last_mb_ptr= s->last_picture.f.data [0] + mb_x*16 + mb_y*16*s->linesize; | |
115329f1 | 688 | |
6a9c8594 AS |
689 | if (s->avctx->codec_id == CODEC_ID_H264) { |
690 | // FIXME | |
691 | } else { | |
692 | ff_thread_await_progress((AVFrame *) s->last_picture_ptr, | |
693 | mb_y, 0); | |
694 | } | |
bb270c08 | 695 | is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr , s->linesize, 16); |
bb198e19 | 696 | is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16); |
4d2858de | 697 | }else{ |
657ccb5a | 698 | if (IS_INTRA(s->current_picture.f.mb_type[mb_xy])) |
4d2858de MN |
699 | is_intra_likely++; |
700 | else | |
701 | is_intra_likely--; | |
702 | } | |
703 | } | |
704 | } | |
705 | //printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type); | |
115329f1 | 706 | return is_intra_likely > 0; |
4d2858de MN |
707 | } |
708 | ||
46b4feec | 709 | void ff_er_frame_start(MpegEncContext *s){ |
5b22d6e1 | 710 | if(!s->err_recognition) return; |
46b4feec | 711 | |
63ccd466 | 712 | memset(s->error_status_table, ER_MB_ERROR|VP_START|ER_MB_END, s->mb_stride*s->mb_height*sizeof(uint8_t)); |
7bc9090a | 713 | s->error_count= 3*s->mb_num; |
6a9c8594 | 714 | s->error_occurred = 0; |
46b4feec MN |
715 | } |
716 | ||
717 | /** | |
58c42af7 | 718 | * Add a slice. |
46b4feec | 719 | * @param endx x component of the last macroblock, can be -1 for the last of the previous line |
5bf2ac2b | 720 | * @param status the status at the end (ER_MV_END, ER_AC_ERROR, ...), it is assumed that no earlier end or |
d9526386 | 721 | * error of the same type occurred |
46b4feec MN |
722 | */ |
723 | void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){ | |
f66e4f5f RD |
724 | const int start_i= av_clip(startx + starty * s->mb_width , 0, s->mb_num-1); |
725 | const int end_i = av_clip(endx + endy * s->mb_width , 0, s->mb_num); | |
7bc9090a MN |
726 | const int start_xy= s->mb_index2xy[start_i]; |
727 | const int end_xy = s->mb_index2xy[end_i]; | |
46b4feec | 728 | int mask= -1; |
04cfef21 | 729 | |
11647a9f GB |
730 | if(s->avctx->hwaccel) |
731 | return; | |
732 | ||
04cfef21 MN |
733 | if(start_i > end_i || start_xy > end_xy){ |
734 | av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n"); | |
735 | return; | |
736 | } | |
115329f1 | 737 | |
5b22d6e1 | 738 | if(!s->err_recognition) return; |
46b4feec MN |
739 | |
740 | mask &= ~VP_START; | |
5bf2ac2b LB |
741 | if(status & (ER_AC_ERROR|ER_AC_END)){ |
742 | mask &= ~(ER_AC_ERROR|ER_AC_END); | |
7bc9090a MN |
743 | s->error_count -= end_i - start_i + 1; |
744 | } | |
5bf2ac2b LB |
745 | if(status & (ER_DC_ERROR|ER_DC_END)){ |
746 | mask &= ~(ER_DC_ERROR|ER_DC_END); | |
7bc9090a MN |
747 | s->error_count -= end_i - start_i + 1; |
748 | } | |
5bf2ac2b LB |
749 | if(status & (ER_MV_ERROR|ER_MV_END)){ |
750 | mask &= ~(ER_MV_ERROR|ER_MV_END); | |
7bc9090a MN |
751 | s->error_count -= end_i - start_i + 1; |
752 | } | |
753 | ||
63ccd466 | 754 | if(status & ER_MB_ERROR) { |
6a9c8594 AS |
755 | s->error_occurred = 1; |
756 | s->error_count= INT_MAX; | |
757 | } | |
46b4feec MN |
758 | |
759 | if(mask == ~0x7F){ | |
7bc9090a | 760 | memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t)); |
46b4feec MN |
761 | }else{ |
762 | int i; | |
763 | for(i=start_xy; i<end_xy; i++){ | |
7bc9090a | 764 | s->error_status_table[ i ] &= mask; |
46b4feec MN |
765 | } |
766 | } | |
7bc9090a | 767 | |
115329f1 | 768 | if(end_i == s->mb_num) |
7bc9090a MN |
769 | s->error_count= INT_MAX; |
770 | else{ | |
46b4feec MN |
771 | s->error_status_table[end_xy] &= mask; |
772 | s->error_status_table[end_xy] |= status; | |
773 | } | |
115329f1 | 774 | |
0aae3f43 | 775 | s->error_status_table[start_xy] |= VP_START; |
7bc9090a | 776 | |
0dfd33c3 | 777 | if(start_xy > 0 && s->avctx->thread_count <= 1 && s->avctx->skip_top*s->mb_width < start_i){ |
7bc9090a | 778 | int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ]; |
115329f1 | 779 | |
7bc9090a | 780 | prev_status &= ~ VP_START; |
5bf2ac2b | 781 | if(prev_status != (ER_MV_END|ER_DC_END|ER_AC_END)) s->error_count= INT_MAX; |
7bc9090a | 782 | } |
46b4feec MN |
783 | } |
784 | ||
785 | void ff_er_frame_end(MpegEncContext *s){ | |
4cfbbbde | 786 | int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error; |
4d2858de MN |
787 | int distance; |
788 | int threshold_part[4]= {100,100,100}; | |
789 | int threshold= 50; | |
790 | int is_intra_likely; | |
ec892563 MN |
791 | int size = s->b8_stride * 2 * s->mb_height; |
792 | Picture *pic= s->current_picture_ptr; | |
115329f1 | 793 | |
5b22d6e1 | 794 | if(!s->err_recognition || s->error_count==0 || s->avctx->lowres || |
40e5d31b | 795 | s->avctx->hwaccel || |
7eb6ed78 | 796 | s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU || |
da9cea77 | 797 | s->picture_structure != PICT_FRAME || // we do not support ER of field pictures yet, though it should not crash if enabled |
0dfd33c3 | 798 | s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return; |
46b4feec | 799 | |
657ccb5a | 800 | if (s->current_picture.f.motion_val[0] == NULL) { |
9b879566 | 801 | av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n"); |
115329f1 | 802 | |
967be700 | 803 | for(i=0; i<2; i++){ |
657ccb5a | 804 | pic->f.ref_index[i] = av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t)); |
02dc8983 | 805 | pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t)); |
657ccb5a | 806 | pic->f.motion_val[i] = pic->motion_val_base[i] + 4; |
967be700 | 807 | } |
657ccb5a | 808 | pic->f.motion_subsample_log2 = 3; |
967be700 | 809 | s->current_picture= *s->current_picture_ptr; |
46b4feec | 810 | } |
115329f1 | 811 | |
7bc9090a MN |
812 | if(s->avctx->debug&FF_DEBUG_ER){ |
813 | for(mb_y=0; mb_y<s->mb_height; mb_y++){ | |
814 | for(mb_x=0; mb_x<s->mb_width; mb_x++){ | |
815 | int status= s->error_status_table[mb_x + mb_y*s->mb_stride]; | |
115329f1 DB |
816 | |
817 | av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status); | |
7bc9090a | 818 | } |
9b879566 | 819 | av_log(s->avctx, AV_LOG_DEBUG, "\n"); |
46b4feec MN |
820 | } |
821 | } | |
115329f1 | 822 | |
4d2858de MN |
823 | /* handle overlapping slices */ |
824 | for(error_type=1; error_type<=3; error_type++){ | |
825 | int end_ok=0; | |
826 | ||
827 | for(i=s->mb_num-1; i>=0; i--){ | |
7bc9090a MN |
828 | const int mb_xy= s->mb_index2xy[i]; |
829 | int error= s->error_status_table[mb_xy]; | |
115329f1 | 830 | |
4d2858de MN |
831 | if(error&(1<<error_type)) |
832 | end_ok=1; | |
833 | if(error&(8<<error_type)) | |
834 | end_ok=1; | |
835 | ||
836 | if(!end_ok) | |
7bc9090a | 837 | s->error_status_table[mb_xy]|= 1<<error_type; |
4d2858de MN |
838 | |
839 | if(error&VP_START) | |
840 | end_ok=0; | |
841 | } | |
842 | } | |
e6ff0648 | 843 | |
4d2858de MN |
844 | /* handle slices with partitions of different length */ |
845 | if(s->partitioned_frame){ | |
846 | int end_ok=0; | |
847 | ||
848 | for(i=s->mb_num-1; i>=0; i--){ | |
7bc9090a MN |
849 | const int mb_xy= s->mb_index2xy[i]; |
850 | int error= s->error_status_table[mb_xy]; | |
115329f1 | 851 | |
5bf2ac2b | 852 | if(error&ER_AC_END) |
4d2858de | 853 | end_ok=0; |
5bf2ac2b | 854 | if((error&ER_MV_END) || (error&ER_DC_END) || (error&ER_AC_ERROR)) |
4d2858de MN |
855 | end_ok=1; |
856 | ||
857 | if(!end_ok) | |
5bf2ac2b | 858 | s->error_status_table[mb_xy]|= ER_AC_ERROR; |
4d2858de MN |
859 | |
860 | if(error&VP_START) | |
861 | end_ok=0; | |
862 | } | |
863 | } | |
e6ff0648 | 864 | |
4d2858de | 865 | /* handle missing slices */ |
5b22d6e1 | 866 | if(s->err_recognition&AV_EF_EXPLODE){ |
4d2858de | 867 | int end_ok=1; |
115329f1 | 868 | |
4d2858de | 869 | for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack |
7bc9090a MN |
870 | const int mb_xy= s->mb_index2xy[i]; |
871 | int error1= s->error_status_table[mb_xy ]; | |
db6e7795 | 872 | int error2= s->error_status_table[s->mb_index2xy[i+1]]; |
115329f1 | 873 | |
4d2858de MN |
874 | if(error1&VP_START) |
875 | end_ok=1; | |
115329f1 | 876 | |
63ccd466 LB |
877 | if( error2==(VP_START|ER_MB_ERROR|ER_MB_END) |
878 | && error1!=(VP_START|ER_MB_ERROR|ER_MB_END) | |
5bf2ac2b | 879 | && ((error1&ER_AC_END) || (error1&ER_DC_END) || (error1&ER_MV_END))){ //end & uninit |
4d2858de MN |
880 | end_ok=0; |
881 | } | |
115329f1 | 882 | |
4d2858de | 883 | if(!end_ok) |
63ccd466 | 884 | s->error_status_table[mb_xy]|= ER_MB_ERROR; |
4d2858de MN |
885 | } |
886 | } | |
115329f1 | 887 | |
4d2858de MN |
888 | /* backward mark errors */ |
889 | distance=9999999; | |
890 | for(error_type=1; error_type<=3; error_type++){ | |
891 | for(i=s->mb_num-1; i>=0; i--){ | |
7bc9090a MN |
892 | const int mb_xy= s->mb_index2xy[i]; |
893 | int error= s->error_status_table[mb_xy]; | |
115329f1 | 894 | |
7bc9090a | 895 | if(!s->mbskip_table[mb_xy]) //FIXME partition specific |
115329f1 | 896 | distance++; |
4d2858de MN |
897 | if(error&(1<<error_type)) |
898 | distance= 0; | |
899 | ||
900 | if(s->partitioned_frame){ | |
901 | if(distance < threshold_part[error_type-1]) | |
7bc9090a | 902 | s->error_status_table[mb_xy]|= 1<<error_type; |
4d2858de MN |
903 | }else{ |
904 | if(distance < threshold) | |
7bc9090a | 905 | s->error_status_table[mb_xy]|= 1<<error_type; |
4d2858de MN |
906 | } |
907 | ||
908 | if(error&VP_START) | |
909 | distance= 9999999; | |
910 | } | |
911 | } | |
4d2858de MN |
912 | |
913 | /* forward mark errors */ | |
914 | error=0; | |
915 | for(i=0; i<s->mb_num; i++){ | |
7bc9090a MN |
916 | const int mb_xy= s->mb_index2xy[i]; |
917 | int old_error= s->error_status_table[mb_xy]; | |
115329f1 | 918 | |
4d2858de | 919 | if(old_error&VP_START) |
63ccd466 | 920 | error= old_error& ER_MB_ERROR; |
4d2858de | 921 | else{ |
63ccd466 | 922 | error|= old_error& ER_MB_ERROR; |
7bc9090a | 923 | s->error_status_table[mb_xy]|= error; |
4d2858de MN |
924 | } |
925 | } | |
e6ff0648 | 926 | |
4d2858de MN |
927 | /* handle not partitioned case */ |
928 | if(!s->partitioned_frame){ | |
929 | for(i=0; i<s->mb_num; i++){ | |
7bc9090a MN |
930 | const int mb_xy= s->mb_index2xy[i]; |
931 | error= s->error_status_table[mb_xy]; | |
63ccd466 LB |
932 | if(error&ER_MB_ERROR) |
933 | error|= ER_MB_ERROR; | |
7bc9090a | 934 | s->error_status_table[mb_xy]= error; |
4d2858de MN |
935 | } |
936 | } | |
4cfbbbde MN |
937 | |
938 | dc_error= ac_error= mv_error=0; | |
939 | for(i=0; i<s->mb_num; i++){ | |
940 | const int mb_xy= s->mb_index2xy[i]; | |
941 | error= s->error_status_table[mb_xy]; | |
5bf2ac2b LB |
942 | if(error&ER_DC_ERROR) dc_error ++; |
943 | if(error&ER_AC_ERROR) ac_error ++; | |
944 | if(error&ER_MV_ERROR) mv_error ++; | |
4cfbbbde MN |
945 | } |
946 | av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error); | |
947 | ||
4d2858de MN |
948 | is_intra_likely= is_intra_more_likely(s); |
949 | ||
950 | /* set unknown mb-type to most likely */ | |
951 | for(i=0; i<s->mb_num; i++){ | |
7bc9090a MN |
952 | const int mb_xy= s->mb_index2xy[i]; |
953 | error= s->error_status_table[mb_xy]; | |
5bf2ac2b | 954 | if(!((error&ER_DC_ERROR) && (error&ER_MV_ERROR))) |
7bc9090a | 955 | continue; |
4d2858de | 956 | |
7bc9090a | 957 | if(is_intra_likely) |
657ccb5a | 958 | s->current_picture.f.mb_type[mb_xy] = MB_TYPE_INTRA4x4; |
4d2858de | 959 | else |
657ccb5a | 960 | s->current_picture.f.mb_type[mb_xy] = MB_TYPE_16x16 | MB_TYPE_L0; |
4d2858de | 961 | } |
115329f1 | 962 | |
b6b66760 | 963 | // change inter to intra blocks if no reference frames are available |
657ccb5a | 964 | if (!s->last_picture.f.data[0] && !s->next_picture.f.data[0]) |
b6b66760 RD |
965 | for(i=0; i<s->mb_num; i++){ |
966 | const int mb_xy= s->mb_index2xy[i]; | |
657ccb5a DB |
967 | if (!IS_INTRA(s->current_picture.f.mb_type[mb_xy])) |
968 | s->current_picture.f.mb_type[mb_xy] = MB_TYPE_INTRA4x4; | |
b6b66760 RD |
969 | } |
970 | ||
4d2858de | 971 | /* handle inter blocks with damaged AC */ |
4d2858de MN |
972 | for(mb_y=0; mb_y<s->mb_height; mb_y++){ |
973 | for(mb_x=0; mb_x<s->mb_width; mb_x++){ | |
7bc9090a | 974 | const int mb_xy= mb_x + mb_y * s->mb_stride; |
657ccb5a DB |
975 | const int mb_type= s->current_picture.f.mb_type[mb_xy]; |
976 | int dir = !s->last_picture.f.data[0]; | |
7bc9090a | 977 | error= s->error_status_table[mb_xy]; |
4d2858de | 978 | |
7bc9090a | 979 | if(IS_INTRA(mb_type)) continue; //intra |
5bf2ac2b LB |
980 | if(error&ER_MV_ERROR) continue; //inter with damaged MV |
981 | if(!(error&ER_AC_ERROR)) continue; //undamaged inter | |
115329f1 | 982 | |
b6b66760 | 983 | s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD; |
4d2858de | 984 | s->mb_intra=0; |
160d679c | 985 | s->mb_skipped=0; |
7bc9090a | 986 | if(IS_8X8(mb_type)){ |
137c8468 | 987 | int mb_index= mb_x*2 + mb_y*2*s->b8_stride; |
4d2858de MN |
988 | int j; |
989 | s->mv_type = MV_TYPE_8X8; | |
990 | for(j=0; j<4; j++){ | |
657ccb5a DB |
991 | s->mv[0][j][0] = s->current_picture.f.motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][0]; |
992 | s->mv[0][j][1] = s->current_picture.f.motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][1]; | |
4d2858de MN |
993 | } |
994 | }else{ | |
995 | s->mv_type = MV_TYPE_16X16; | |
657ccb5a DB |
996 | s->mv[0][0][0] = s->current_picture.f.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0]; |
997 | s->mv[0][0][1] = s->current_picture.f.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1]; | |
4d2858de | 998 | } |
115329f1 | 999 | |
bb270c08 | 1000 | s->dsp.clear_blocks(s->block[0]); |
4d2858de MN |
1001 | |
1002 | s->mb_x= mb_x; | |
1003 | s->mb_y= mb_y; | |
673fc638 | 1004 | decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/); |
4d2858de MN |
1005 | } |
1006 | } | |
1007 | ||
1008 | /* guess MVs */ | |
975a1447 | 1009 | if(s->pict_type==AV_PICTURE_TYPE_B){ |
4d2858de MN |
1010 | for(mb_y=0; mb_y<s->mb_height; mb_y++){ |
1011 | for(mb_x=0; mb_x<s->mb_width; mb_x++){ | |
137c8468 | 1012 | int xy= mb_x*2 + mb_y*2*s->b8_stride; |
7bc9090a | 1013 | const int mb_xy= mb_x + mb_y * s->mb_stride; |
657ccb5a | 1014 | const int mb_type= s->current_picture.f.mb_type[mb_xy]; |
7bc9090a | 1015 | error= s->error_status_table[mb_xy]; |
4d2858de | 1016 | |
7bc9090a | 1017 | if(IS_INTRA(mb_type)) continue; |
5bf2ac2b LB |
1018 | if(!(error&ER_MV_ERROR)) continue; //inter with undamaged MV |
1019 | if(!(error&ER_AC_ERROR)) continue; //undamaged inter | |
115329f1 | 1020 | |
4d2858de | 1021 | s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD; |
657ccb5a DB |
1022 | if(!s->last_picture.f.data[0]) s->mv_dir &= ~MV_DIR_FORWARD; |
1023 | if(!s->next_picture.f.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD; | |
4d2858de MN |
1024 | s->mb_intra=0; |
1025 | s->mv_type = MV_TYPE_16X16; | |
160d679c | 1026 | s->mb_skipped=0; |
115329f1 | 1027 | |
4d2858de MN |
1028 | if(s->pp_time){ |
1029 | int time_pp= s->pp_time; | |
1030 | int time_pb= s->pb_time; | |
115329f1 | 1031 | |
6a9c8594 AS |
1032 | if (s->avctx->codec_id == CODEC_ID_H264) { |
1033 | //FIXME | |
1034 | } else { | |
1035 | ff_thread_await_progress((AVFrame *) s->next_picture_ptr, | |
1036 | mb_y, 0); | |
1037 | } | |
657ccb5a DB |
1038 | s->mv[0][0][0] = s->next_picture.f.motion_val[0][xy][0] * time_pb / time_pp; |
1039 | s->mv[0][0][1] = s->next_picture.f.motion_val[0][xy][1] * time_pb / time_pp; | |
1040 | s->mv[1][0][0] = s->next_picture.f.motion_val[0][xy][0] * (time_pb - time_pp) / time_pp; | |
1041 | s->mv[1][0][1] = s->next_picture.f.motion_val[0][xy][1] * (time_pb - time_pp) / time_pp; | |
4d2858de MN |
1042 | }else{ |
1043 | s->mv[0][0][0]= 0; | |
1044 | s->mv[0][0][1]= 0; | |
1045 | s->mv[1][0][0]= 0; | |
1046 | s->mv[1][0][1]= 0; | |
1047 | } | |
eb4b3dd3 ZK |
1048 | |
1049 | s->dsp.clear_blocks(s->block[0]); | |
4d2858de MN |
1050 | s->mb_x= mb_x; |
1051 | s->mb_y= mb_y; | |
673fc638 | 1052 | decode_mb(s, 0); |
4d2858de MN |
1053 | } |
1054 | } | |
1055 | }else | |
1056 | guess_mv(s); | |
1057 | ||
2e7b4c84 | 1058 | /* the filters below are not XvMC compatible, skip them */ |
83344066 DB |
1059 | if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) |
1060 | goto ec_clean; | |
4d2858de | 1061 | /* fill DC for inter blocks */ |
4d2858de MN |
1062 | for(mb_y=0; mb_y<s->mb_height; mb_y++){ |
1063 | for(mb_x=0; mb_x<s->mb_width; mb_x++){ | |
1064 | int dc, dcu, dcv, y, n; | |
b86216de | 1065 | int16_t *dc_ptr; |
0c1a9eda | 1066 | uint8_t *dest_y, *dest_cb, *dest_cr; |
7bc9090a | 1067 | const int mb_xy= mb_x + mb_y * s->mb_stride; |
657ccb5a | 1068 | const int mb_type = s->current_picture.f.mb_type[mb_xy]; |
115329f1 | 1069 | |
7bc9090a | 1070 | error= s->error_status_table[mb_xy]; |
4d2858de | 1071 | |
7bc9090a | 1072 | if(IS_INTRA(mb_type) && s->partitioned_frame) continue; |
5bf2ac2b | 1073 | // if(error&ER_MV_ERROR) continue; //inter data damaged FIXME is this good? |
115329f1 | 1074 | |
657ccb5a DB |
1075 | dest_y = s->current_picture.f.data[0] + mb_x * 16 + mb_y * 16 * s->linesize; |
1076 | dest_cb = s->current_picture.f.data[1] + mb_x * 8 + mb_y * 8 * s->uvlinesize; | |
1077 | dest_cr = s->current_picture.f.data[2] + mb_x * 8 + mb_y * 8 * s->uvlinesize; | |
115329f1 | 1078 | |
137c8468 | 1079 | dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride]; |
4d2858de MN |
1080 | for(n=0; n<4; n++){ |
1081 | dc=0; | |
1082 | for(y=0; y<8; y++){ | |
1083 | int x; | |
1084 | for(x=0; x<8; x++){ | |
1085 | dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize]; | |
1086 | } | |
1087 | } | |
137c8468 | 1088 | dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3; |
4d2858de MN |
1089 | } |
1090 | ||
1091 | dcu=dcv=0; | |
1092 | for(y=0; y<8; y++){ | |
1093 | int x; | |
1094 | for(x=0; x<8; x++){ | |
3dc99a18 DB |
1095 | dcu += dest_cb[x + y * s->uvlinesize]; |
1096 | dcv += dest_cr[x + y * s->uvlinesize]; | |
4d2858de MN |
1097 | } |
1098 | } | |
137c8468 | 1099 | s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3; |
115329f1 | 1100 | s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3; |
4d2858de MN |
1101 | } |
1102 | } | |
e6ff0648 | 1103 | |
4d2858de | 1104 | /* guess DC for damaged blocks */ |
137c8468 MN |
1105 | guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1); |
1106 | guess_dc(s, s->dc_val[1], s->mb_width , s->mb_height , s->mb_stride, 0); | |
1107 | guess_dc(s, s->dc_val[2], s->mb_width , s->mb_height , s->mb_stride, 0); | |
e6ff0648 | 1108 | |
4d2858de | 1109 | /* filter luma DC */ |
137c8468 | 1110 | filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride); |
115329f1 | 1111 | |
4d2858de | 1112 | /* render DC only intra */ |
4d2858de MN |
1113 | for(mb_y=0; mb_y<s->mb_height; mb_y++){ |
1114 | for(mb_x=0; mb_x<s->mb_width; mb_x++){ | |
0c1a9eda | 1115 | uint8_t *dest_y, *dest_cb, *dest_cr; |
7bc9090a | 1116 | const int mb_xy= mb_x + mb_y * s->mb_stride; |
657ccb5a | 1117 | const int mb_type = s->current_picture.f.mb_type[mb_xy]; |
7bc9090a MN |
1118 | |
1119 | error= s->error_status_table[mb_xy]; | |
4d2858de | 1120 | |
7bc9090a | 1121 | if(IS_INTER(mb_type)) continue; |
5bf2ac2b | 1122 | if(!(error&ER_AC_ERROR)) continue; //undamaged |
115329f1 | 1123 | |
657ccb5a DB |
1124 | dest_y = s->current_picture.f.data[0] + mb_x * 16 + mb_y * 16 * s->linesize; |
1125 | dest_cb = s->current_picture.f.data[1] + mb_x * 8 + mb_y * 8 * s->uvlinesize; | |
1126 | dest_cr = s->current_picture.f.data[2] + mb_x * 8 + mb_y * 8 * s->uvlinesize; | |
115329f1 | 1127 | |
4d2858de MN |
1128 | put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y); |
1129 | } | |
1130 | } | |
115329f1 | 1131 | |
4d2858de MN |
1132 | if(s->avctx->error_concealment&FF_EC_DEBLOCK){ |
1133 | /* filter horizontal block boundaries */ | |
657ccb5a DB |
1134 | h_block_filter(s, s->current_picture.f.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1); |
1135 | h_block_filter(s, s->current_picture.f.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0); | |
1136 | h_block_filter(s, s->current_picture.f.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0); | |
4d2858de MN |
1137 | |
1138 | /* filter vertical block boundaries */ | |
657ccb5a DB |
1139 | v_block_filter(s, s->current_picture.f.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1); |
1140 | v_block_filter(s, s->current_picture.f.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0); | |
1141 | v_block_filter(s, s->current_picture.f.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0); | |
4d2858de MN |
1142 | } |
1143 | ||
2e7b4c84 | 1144 | ec_clean: |
4d2858de MN |
1145 | /* clean a few tables */ |
1146 | for(i=0; i<s->mb_num; i++){ | |
7bc9090a MN |
1147 | const int mb_xy= s->mb_index2xy[i]; |
1148 | int error= s->error_status_table[mb_xy]; | |
115329f1 | 1149 | |
5bf2ac2b | 1150 | if(s->pict_type!=AV_PICTURE_TYPE_B && (error&(ER_DC_ERROR|ER_MV_ERROR|ER_AC_ERROR))){ |
7bc9090a | 1151 | s->mbskip_table[mb_xy]=0; |
4d2858de | 1152 | } |
7bc9090a | 1153 | s->mbintra_table[mb_xy]=1; |
115329f1 | 1154 | } |
4d2858de | 1155 | } |