/src/ffmpeg/libavcodec/error_resilience.c
Line | Count | Source |
1 | | /* |
2 | | * Error resilience / concealment |
3 | | * |
4 | | * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> |
5 | | * |
6 | | * This file is part of FFmpeg. |
7 | | * |
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. |
12 | | * |
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. |
17 | | * |
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 |
21 | | */ |
22 | | |
23 | | /** |
24 | | * @file |
25 | | * Error resilience / concealment. |
26 | | */ |
27 | | |
28 | | #include <limits.h> |
29 | | |
30 | | #include "libavutil/avassert.h" |
31 | | #include "libavutil/attributes.h" |
32 | | #include "libavutil/mem.h" |
33 | | #include "avcodec.h" |
34 | | #include "error_resilience.h" |
35 | | #include "mathops.h" |
36 | | #include "me_cmp.h" |
37 | | #include "mpegutils.h" |
38 | | #include "mpegvideo.h" |
39 | | #include "threadframe.h" |
40 | | #include "threadprogress.h" |
41 | | |
42 | | av_cold int ff_er_init(ERContext *const s) |
43 | 906k | { |
44 | 906k | MECmpContext mecc; |
45 | 906k | unsigned mb_array_size = s->mb_height * s->mb_stride; |
46 | | |
47 | 906k | s->error_status_table = av_mallocz(mb_array_size); |
48 | 906k | if (!s->error_status_table) |
49 | 0 | return AVERROR(ENOMEM); |
50 | 906k | s->er_temp_buffer = av_malloc_array(mb_array_size, 4*sizeof(int) + 1); |
51 | 906k | if (!s->er_temp_buffer) |
52 | 0 | return AVERROR(ENOMEM); |
53 | | |
54 | 906k | ff_me_cmp_init(&mecc, s->avctx); |
55 | 906k | s->sad = mecc.sad[0]; |
56 | | |
57 | 906k | return 0; |
58 | 906k | } |
59 | | |
60 | | /** |
61 | | * @param stride the number of MVs to get to the next row |
62 | | * @param mv_step the number of MVs per row or column in a macroblock |
63 | | */ |
64 | | static void set_mv_strides(ERContext *s, ptrdiff_t *mv_step, ptrdiff_t *stride) |
65 | 3.08M | { |
66 | 3.08M | if (s->avctx->codec_id == AV_CODEC_ID_H264) { |
67 | 1.41M | av_assert0(s->quarter_sample); |
68 | 1.41M | *mv_step = 4; |
69 | 1.41M | *stride = s->mb_width * 4; |
70 | 1.67M | } else { |
71 | 1.67M | *mv_step = 2; |
72 | 1.67M | *stride = s->b8_stride; |
73 | 1.67M | } |
74 | 3.08M | } |
75 | | |
76 | | /** |
77 | | * Replace the current MB with a flat dc-only version. |
78 | | */ |
79 | | static void put_dc(ERContext *s, uint8_t *dest_y, uint8_t *dest_cb, |
80 | | uint8_t *dest_cr, int mb_x, int mb_y) |
81 | 135M | { |
82 | 135M | int *linesize = s->cur_pic.f->linesize; |
83 | 135M | int dc, dcu, dcv, y, i; |
84 | 678M | for (i = 0; i < 4; i++) { |
85 | 543M | dc = s->dc_val[0][mb_x * 2 + (i & 1) + (mb_y * 2 + (i >> 1)) * s->b8_stride]; |
86 | 543M | if (dc < 0) |
87 | 3.40M | dc = 0; |
88 | 539M | else if (dc > 2040) |
89 | 1.66M | dc = 2040; |
90 | 4.88G | for (y = 0; y < 8; y++) { |
91 | 4.34G | int x; |
92 | 39.1G | for (x = 0; x < 8; x++) |
93 | 34.7G | dest_y[x + (i & 1) * 8 + (y + (i >> 1) * 8) * linesize[0]] = dc / 8; |
94 | 4.34G | } |
95 | 543M | } |
96 | 135M | dcu = s->dc_val[1][mb_x + mb_y * s->mb_stride]; |
97 | 135M | dcv = s->dc_val[2][mb_x + mb_y * s->mb_stride]; |
98 | 135M | if (dcu < 0) |
99 | 0 | dcu = 0; |
100 | 135M | else if (dcu > 2040) |
101 | 4.18k | dcu = 2040; |
102 | 135M | if (dcv < 0) |
103 | 0 | dcv = 0; |
104 | 135M | else if (dcv > 2040) |
105 | 3.79k | dcv = 2040; |
106 | | |
107 | 135M | if (dest_cr) |
108 | 1.22G | for (y = 0; y < 8; y++) { |
109 | 1.08G | int x; |
110 | 9.77G | for (x = 0; x < 8; x++) { |
111 | 8.69G | dest_cb[x + y * linesize[1]] = dcu / 8; |
112 | 8.69G | dest_cr[x + y * linesize[2]] = dcv / 8; |
113 | 8.69G | } |
114 | 1.08G | } |
115 | 135M | } |
116 | | |
117 | | static void filter181(int16_t *data, int width, int height, ptrdiff_t stride) |
118 | 450k | { |
119 | 450k | int x, y; |
120 | | |
121 | | /* horizontal filter */ |
122 | 75.4M | for (y = 1; y < height - 1; y++) { |
123 | 74.9M | int prev_dc = data[0 + y * stride]; |
124 | | |
125 | 1.67G | for (x = 1; x < width - 1; x++) { |
126 | 1.60G | int dc; |
127 | 1.60G | dc = -prev_dc + |
128 | 1.60G | data[x + y * stride] * 8 - |
129 | 1.60G | data[x + 1 + y * stride]; |
130 | 1.60G | dc = (av_clip(dc, INT_MIN/10923, INT_MAX/10923 - 32768) * 10923 + 32768) >> 16; |
131 | 1.60G | prev_dc = data[x + y * stride]; |
132 | 1.60G | data[x + y * stride] = dc; |
133 | 1.60G | } |
134 | 74.9M | } |
135 | | |
136 | | /* vertical filter */ |
137 | 55.8M | for (x = 1; x < width - 1; x++) { |
138 | 55.4M | int prev_dc = data[x]; |
139 | | |
140 | 1.65G | for (y = 1; y < height - 1; y++) { |
141 | 1.60G | int dc; |
142 | | |
143 | 1.60G | dc = -prev_dc + |
144 | 1.60G | data[x + y * stride] * 8 - |
145 | 1.60G | data[x + (y + 1) * stride]; |
146 | 1.60G | dc = (av_clip(dc, INT_MIN/10923, INT_MAX/10923 - 32768) * 10923 + 32768) >> 16; |
147 | 1.60G | prev_dc = data[x + y * stride]; |
148 | 1.60G | data[x + y * stride] = dc; |
149 | 1.60G | } |
150 | 55.4M | } |
151 | 450k | } |
152 | | |
153 | | /** |
154 | | * guess the dc of blocks which do not have an undamaged dc |
155 | | * @param w width in 8 pixel blocks |
156 | | * @param h height in 8 pixel blocks |
157 | | */ |
158 | | static void guess_dc(ERContext *s, int16_t *dc, int w, |
159 | | int h, ptrdiff_t stride, int is_luma) |
160 | 1.35M | { |
161 | 1.35M | int b_x, b_y; |
162 | 1.35M | int16_t (*col )[4] = av_malloc_array(stride, h*sizeof( int16_t)*4); |
163 | 1.35M | uint32_t (*dist)[4] = av_malloc_array(stride, h*sizeof(uint32_t)*4); |
164 | | |
165 | 1.35M | if(!col || !dist) { |
166 | 0 | av_log(s->avctx, AV_LOG_ERROR, "guess_dc() is out of memory\n"); |
167 | 0 | goto fail; |
168 | 0 | } |
169 | | |
170 | 153M | for(b_y=0; b_y<h; b_y++){ |
171 | 151M | int color= 1024; |
172 | 151M | int distance= -1; |
173 | 2.94G | for(b_x=0; b_x<w; b_x++){ |
174 | 2.79G | int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride; |
175 | 2.79G | int error_j= s->error_status_table[mb_index_j]; |
176 | 2.79G | int intra_j = IS_INTRA(s->cur_pic.mb_type[mb_index_j]); |
177 | 2.79G | if(intra_j==0 || !(error_j&ER_DC_ERROR)){ |
178 | 1.98G | color= dc[b_x + b_y*stride]; |
179 | 1.98G | distance= b_x; |
180 | 1.98G | } |
181 | 2.79G | col [b_x + b_y*stride][1]= color; |
182 | 2.79G | dist[b_x + b_y*stride][1]= distance >= 0 ? b_x-distance : 9999; |
183 | 2.79G | } |
184 | 151M | color= 1024; |
185 | 151M | distance= -1; |
186 | 2.94G | for(b_x=w-1; b_x>=0; b_x--){ |
187 | 2.79G | int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride; |
188 | 2.79G | int error_j= s->error_status_table[mb_index_j]; |
189 | 2.79G | int intra_j = IS_INTRA(s->cur_pic.mb_type[mb_index_j]); |
190 | 2.79G | if(intra_j==0 || !(error_j&ER_DC_ERROR)){ |
191 | 1.98G | color= dc[b_x + b_y*stride]; |
192 | 1.98G | distance= b_x; |
193 | 1.98G | } |
194 | 2.79G | col [b_x + b_y*stride][0]= color; |
195 | 2.79G | dist[b_x + b_y*stride][0]= distance >= 0 ? distance-b_x : 9999; |
196 | 2.79G | } |
197 | 151M | } |
198 | 113M | for(b_x=0; b_x<w; b_x++){ |
199 | 112M | int color= 1024; |
200 | 112M | int distance= -1; |
201 | 2.90G | for(b_y=0; b_y<h; b_y++){ |
202 | 2.79G | int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride; |
203 | 2.79G | int error_j= s->error_status_table[mb_index_j]; |
204 | 2.79G | int intra_j = IS_INTRA(s->cur_pic.mb_type[mb_index_j]); |
205 | 2.79G | if(intra_j==0 || !(error_j&ER_DC_ERROR)){ |
206 | 1.98G | color= dc[b_x + b_y*stride]; |
207 | 1.98G | distance= b_y; |
208 | 1.98G | } |
209 | 2.79G | col [b_x + b_y*stride][3]= color; |
210 | 2.79G | dist[b_x + b_y*stride][3]= distance >= 0 ? b_y-distance : 9999; |
211 | 2.79G | } |
212 | 112M | color= 1024; |
213 | 112M | distance= -1; |
214 | 2.90G | for(b_y=h-1; b_y>=0; b_y--){ |
215 | 2.79G | int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride; |
216 | 2.79G | int error_j= s->error_status_table[mb_index_j]; |
217 | 2.79G | int intra_j = IS_INTRA(s->cur_pic.mb_type[mb_index_j]); |
218 | 2.79G | if(intra_j==0 || !(error_j&ER_DC_ERROR)){ |
219 | 1.98G | color= dc[b_x + b_y*stride]; |
220 | 1.98G | distance= b_y; |
221 | 1.98G | } |
222 | 2.79G | col [b_x + b_y*stride][2]= color; |
223 | 2.79G | dist[b_x + b_y*stride][2]= distance >= 0 ? distance-b_y : 9999; |
224 | 2.79G | } |
225 | 112M | } |
226 | | |
227 | 153M | for (b_y = 0; b_y < h; b_y++) { |
228 | 2.94G | for (b_x = 0; b_x < w; b_x++) { |
229 | 2.79G | int mb_index, error, j; |
230 | 2.79G | int64_t guess, weight_sum; |
231 | 2.79G | mb_index = (b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride; |
232 | 2.79G | error = s->error_status_table[mb_index]; |
233 | | |
234 | 2.79G | if (IS_INTER(s->cur_pic.mb_type[mb_index])) |
235 | 1.86G | continue; // inter |
236 | 927M | if (!(error & ER_DC_ERROR)) |
237 | 113M | continue; // dc-ok |
238 | | |
239 | 814M | weight_sum = 0; |
240 | 814M | guess = 0; |
241 | 4.07G | for (j = 0; j < 4; j++) { |
242 | 3.25G | int64_t weight = 256 * 256 * 256 * 16 / FFMAX(dist[b_x + b_y*stride][j], 1); |
243 | 3.25G | guess += weight*(int64_t)col[b_x + b_y*stride][j]; |
244 | 3.25G | weight_sum += weight; |
245 | 3.25G | } |
246 | 814M | guess = (guess + weight_sum / 2) / weight_sum; |
247 | 814M | dc[b_x + b_y * stride] = guess; |
248 | 814M | } |
249 | 151M | } |
250 | | |
251 | 1.35M | fail: |
252 | 1.35M | av_freep(&col); |
253 | 1.35M | av_freep(&dist); |
254 | 1.35M | } |
255 | | |
256 | | /** |
257 | | * simple horizontal deblocking filter used for error resilience |
258 | | * @param w width in 8 pixel blocks |
259 | | * @param h height in 8 pixel blocks |
260 | | */ |
261 | | static void h_block_filter(ERContext *s, uint8_t *dst, int w, |
262 | | int h, ptrdiff_t stride, int is_luma) |
263 | 1.35M | { |
264 | 1.35M | int b_x, b_y; |
265 | 1.35M | ptrdiff_t mvx_stride, mvy_stride; |
266 | 1.35M | const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; |
267 | 1.35M | set_mv_strides(s, &mvx_stride, &mvy_stride); |
268 | 1.35M | mvx_stride >>= is_luma; |
269 | 1.35M | mvy_stride *= mvx_stride; |
270 | | |
271 | 153M | for (b_y = 0; b_y < h; b_y++) { |
272 | 2.79G | for (b_x = 0; b_x < w - 1; b_x++) { |
273 | 2.64G | int y; |
274 | 2.64G | int left_status = s->error_status_table[( b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride]; |
275 | 2.64G | int right_status = s->error_status_table[((b_x + 1) >> is_luma) + (b_y >> is_luma) * s->mb_stride]; |
276 | 2.64G | int left_intra = IS_INTRA(s->cur_pic.mb_type[( b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride]); |
277 | 2.64G | int right_intra = IS_INTRA(s->cur_pic.mb_type[((b_x + 1) >> is_luma) + (b_y >> is_luma) * s->mb_stride]); |
278 | 2.64G | int left_damage = left_status & ER_MB_ERROR; |
279 | 2.64G | int right_damage = right_status & ER_MB_ERROR; |
280 | 2.64G | int offset = b_x * 8 + b_y * stride * 8; |
281 | 2.64G | int16_t *left_mv = s->cur_pic.motion_val[0][mvy_stride * b_y + mvx_stride * b_x]; |
282 | 2.64G | int16_t *right_mv = s->cur_pic.motion_val[0][mvy_stride * b_y + mvx_stride * (b_x + 1)]; |
283 | 2.64G | if (!(left_damage || right_damage)) |
284 | 200M | continue; // both undamaged |
285 | 2.44G | if ((!left_intra) && (!right_intra) && |
286 | 1.66G | FFABS(left_mv[0] - right_mv[0]) + |
287 | 1.66G | FFABS(left_mv[1] + right_mv[1]) < 2) |
288 | 1.62G | continue; |
289 | | |
290 | 7.34G | for (y = 0; y < 8; y++) { |
291 | 6.52G | int a, b, c, d; |
292 | | |
293 | 6.52G | a = dst[offset + 7 + y * stride] - dst[offset + 6 + y * stride]; |
294 | 6.52G | b = dst[offset + 8 + y * stride] - dst[offset + 7 + y * stride]; |
295 | 6.52G | c = dst[offset + 9 + y * stride] - dst[offset + 8 + y * stride]; |
296 | | |
297 | 6.52G | d = FFABS(b) - ((FFABS(a) + FFABS(c) + 1) >> 1); |
298 | 6.52G | d = FFMAX(d, 0); |
299 | 6.52G | if (b < 0) |
300 | 414M | d = -d; |
301 | | |
302 | 6.52G | if (d == 0) |
303 | 5.70G | continue; |
304 | | |
305 | 827M | if (!(left_damage && right_damage)) |
306 | 743k | d = d * 16 / 9; |
307 | | |
308 | 827M | if (left_damage) { |
309 | 826M | dst[offset + 7 + y * stride] = cm[dst[offset + 7 + y * stride] + ((d * 7) >> 4)]; |
310 | 826M | dst[offset + 6 + y * stride] = cm[dst[offset + 6 + y * stride] + ((d * 5) >> 4)]; |
311 | 826M | dst[offset + 5 + y * stride] = cm[dst[offset + 5 + y * stride] + ((d * 3) >> 4)]; |
312 | 826M | dst[offset + 4 + y * stride] = cm[dst[offset + 4 + y * stride] + ((d * 1) >> 4)]; |
313 | 826M | } |
314 | 827M | if (right_damage) { |
315 | 826M | dst[offset + 8 + y * stride] = cm[dst[offset + 8 + y * stride] - ((d * 7) >> 4)]; |
316 | 826M | dst[offset + 9 + y * stride] = cm[dst[offset + 9 + y * stride] - ((d * 5) >> 4)]; |
317 | 826M | dst[offset + 10+ y * stride] = cm[dst[offset + 10 + y * stride] - ((d * 3) >> 4)]; |
318 | 826M | dst[offset + 11+ y * stride] = cm[dst[offset + 11 + y * stride] - ((d * 1) >> 4)]; |
319 | 826M | } |
320 | 827M | } |
321 | 815M | } |
322 | 151M | } |
323 | 1.35M | } |
324 | | |
325 | | /** |
326 | | * simple vertical deblocking filter used for error resilience |
327 | | * @param w width in 8 pixel blocks |
328 | | * @param h height in 8 pixel blocks |
329 | | */ |
330 | | static void v_block_filter(ERContext *s, uint8_t *dst, int w, int h, |
331 | | ptrdiff_t stride, int is_luma) |
332 | 1.35M | { |
333 | 1.35M | int b_x, b_y; |
334 | 1.35M | ptrdiff_t mvx_stride, mvy_stride; |
335 | 1.35M | const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; |
336 | 1.35M | set_mv_strides(s, &mvx_stride, &mvy_stride); |
337 | 1.35M | mvx_stride >>= is_luma; |
338 | 1.35M | mvy_stride *= mvx_stride; |
339 | | |
340 | 151M | for (b_y = 0; b_y < h - 1; b_y++) { |
341 | 2.83G | for (b_x = 0; b_x < w; b_x++) { |
342 | 2.68G | int x; |
343 | 2.68G | int top_status = s->error_status_table[(b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride]; |
344 | 2.68G | int bottom_status = s->error_status_table[(b_x >> is_luma) + ((b_y + 1) >> is_luma) * s->mb_stride]; |
345 | 2.68G | int top_intra = IS_INTRA(s->cur_pic.mb_type[(b_x >> is_luma) + ( b_y >> is_luma) * s->mb_stride]); |
346 | 2.68G | int bottom_intra = IS_INTRA(s->cur_pic.mb_type[(b_x >> is_luma) + ((b_y + 1) >> is_luma) * s->mb_stride]); |
347 | 2.68G | int top_damage = top_status & ER_MB_ERROR; |
348 | 2.68G | int bottom_damage = bottom_status & ER_MB_ERROR; |
349 | 2.68G | int offset = b_x * 8 + b_y * stride * 8; |
350 | | |
351 | 2.68G | int16_t *top_mv = s->cur_pic.motion_val[0][mvy_stride * b_y + mvx_stride * b_x]; |
352 | 2.68G | int16_t *bottom_mv = s->cur_pic.motion_val[0][mvy_stride * (b_y + 1) + mvx_stride * b_x]; |
353 | | |
354 | 2.68G | if (!(top_damage || bottom_damage)) |
355 | 194M | continue; // both undamaged |
356 | | |
357 | 2.48G | if ((!top_intra) && (!bottom_intra) && |
358 | 1.70G | FFABS(top_mv[0] - bottom_mv[0]) + |
359 | 1.70G | FFABS(top_mv[1] + bottom_mv[1]) < 2) |
360 | 1.66G | continue; |
361 | | |
362 | 7.43G | for (x = 0; x < 8; x++) { |
363 | 6.61G | int a, b, c, d; |
364 | | |
365 | 6.61G | a = dst[offset + x + 7 * stride] - dst[offset + x + 6 * stride]; |
366 | 6.61G | b = dst[offset + x + 8 * stride] - dst[offset + x + 7 * stride]; |
367 | 6.61G | c = dst[offset + x + 9 * stride] - dst[offset + x + 8 * stride]; |
368 | | |
369 | 6.61G | d = FFABS(b) - ((FFABS(a) + FFABS(c) + 1) >> 1); |
370 | 6.61G | d = FFMAX(d, 0); |
371 | 6.61G | if (b < 0) |
372 | 90.3M | d = -d; |
373 | | |
374 | 6.61G | if (d == 0) |
375 | 6.43G | continue; |
376 | | |
377 | 181M | if (!(top_damage && bottom_damage)) |
378 | 30.4M | d = d * 16 / 9; |
379 | | |
380 | 181M | if (top_damage) { |
381 | 152M | dst[offset + x + 7 * stride] = cm[dst[offset + x + 7 * stride] + ((d * 7) >> 4)]; |
382 | 152M | dst[offset + x + 6 * stride] = cm[dst[offset + x + 6 * stride] + ((d * 5) >> 4)]; |
383 | 152M | dst[offset + x + 5 * stride] = cm[dst[offset + x + 5 * stride] + ((d * 3) >> 4)]; |
384 | 152M | dst[offset + x + 4 * stride] = cm[dst[offset + x + 4 * stride] + ((d * 1) >> 4)]; |
385 | 152M | } |
386 | 181M | if (bottom_damage) { |
387 | 179M | dst[offset + x + 8 * stride] = cm[dst[offset + x + 8 * stride] - ((d * 7) >> 4)]; |
388 | 179M | dst[offset + x + 9 * stride] = cm[dst[offset + x + 9 * stride] - ((d * 5) >> 4)]; |
389 | 179M | dst[offset + x + 10 * stride] = cm[dst[offset + x + 10 * stride] - ((d * 3) >> 4)]; |
390 | 179M | dst[offset + x + 11 * stride] = cm[dst[offset + x + 11 * stride] - ((d * 1) >> 4)]; |
391 | 179M | } |
392 | 181M | } |
393 | 826M | } |
394 | 150M | } |
395 | 1.35M | } |
396 | | |
397 | 918M | #define MV_FROZEN 8 |
398 | 112M | #define MV_CHANGED 4 |
399 | 103M | #define MV_UNCHANGED 2 |
400 | 52.0M | #define MV_LISTED 1 |
401 | | static av_always_inline void add_blocklist(int (*blocklist)[2], int *blocklist_length, uint8_t *fixed, int mb_x, int mb_y, int mb_xy) |
402 | 814M | { |
403 | 814M | if (fixed[mb_xy]) |
404 | 762M | return; |
405 | 52.0M | fixed[mb_xy] = MV_LISTED; |
406 | 52.0M | blocklist[ *blocklist_length ][0] = mb_x; |
407 | 52.0M | blocklist[(*blocklist_length)++][1] = mb_y; |
408 | 52.0M | } |
409 | | |
410 | | static void guess_mv(ERContext *s) |
411 | 381k | { |
412 | 381k | int (*blocklist)[2], (*next_blocklist)[2]; |
413 | 381k | uint8_t *fixed; |
414 | 381k | const ptrdiff_t mb_stride = s->mb_stride; |
415 | 381k | const int mb_width = s->mb_width; |
416 | 381k | int mb_height = s->mb_height; |
417 | 381k | int i, num_avail; |
418 | 381k | int mb_x, mb_y; |
419 | 381k | ptrdiff_t mot_step, mot_stride; |
420 | 381k | int blocklist_length, next_blocklist_length; |
421 | | |
422 | 381k | if (s->last_pic.f && s->last_pic.f->data[0]) |
423 | 272k | mb_height = FFMIN(mb_height, (s->last_pic.f->height+15)>>4); |
424 | 381k | if (s->next_pic.f && s->next_pic.f->data[0]) |
425 | 250k | mb_height = FFMIN(mb_height, (s->next_pic.f->height+15)>>4); |
426 | | |
427 | 381k | blocklist = (int (*)[2])s->er_temp_buffer; |
428 | 381k | next_blocklist = blocklist + s->mb_stride * s->mb_height; |
429 | 381k | fixed = (uint8_t *)(next_blocklist + s->mb_stride * s->mb_height); |
430 | | |
431 | 381k | set_mv_strides(s, &mot_step, &mot_stride); |
432 | | |
433 | 381k | num_avail = 0; |
434 | 381k | if (s->last_pic.motion_val[0]) { |
435 | 260k | if (s->last_pic.tf) |
436 | 88.7k | ff_thread_await_progress(s->last_pic.tf, mb_height-1, 0); |
437 | 171k | else |
438 | 171k | ff_thread_progress_await(s->last_pic.progress, mb_height - 1); |
439 | 260k | } |
440 | 426M | for (i = 0; i < mb_width * mb_height; i++) { |
441 | 426M | const int mb_xy = s->mb_index2xy[i]; |
442 | 426M | int f = 0; |
443 | 426M | int error = s->error_status_table[mb_xy]; |
444 | | |
445 | 426M | if (IS_INTRA(s->cur_pic.mb_type[mb_xy])) |
446 | 139M | f = MV_FROZEN; // intra // FIXME check |
447 | 426M | if (!(error & ER_MV_ERROR)) |
448 | 32.3M | f = MV_FROZEN; // inter with undamaged MV |
449 | | |
450 | 426M | fixed[mb_xy] = f; |
451 | 426M | if (f == MV_FROZEN) |
452 | 164M | num_avail++; |
453 | 262M | else if(s->last_pic.f->data[0] && s->last_pic.motion_val[0]){ |
454 | 254M | const int mb_y= mb_xy / s->mb_stride; |
455 | 254M | const int mb_x= mb_xy % s->mb_stride; |
456 | 254M | const int mot_index= (mb_x + mb_y*mot_stride) * mot_step; |
457 | 254M | s->cur_pic.motion_val[0][mot_index][0]= s->last_pic.motion_val[0][mot_index][0]; |
458 | 254M | s->cur_pic.motion_val[0][mot_index][1]= s->last_pic.motion_val[0][mot_index][1]; |
459 | 254M | s->cur_pic.ref_index[0][4*mb_xy] = s->last_pic.ref_index[0][4*mb_xy]; |
460 | 254M | } |
461 | 426M | } |
462 | | |
463 | 381k | if ((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || |
464 | 381k | num_avail <= FFMAX(mb_width, mb_height) / 2) { |
465 | 21.5M | for (mb_y = 0; mb_y < mb_height; mb_y++) { |
466 | 232M | for (mb_x = 0; mb_x < s->mb_width; mb_x++) { |
467 | 211M | const int mb_xy = mb_x + mb_y * s->mb_stride; |
468 | 211M | int mv_dir = (s->last_pic.f && s->last_pic.f->data[0]) ? MV_DIR_FORWARD : MV_DIR_BACKWARD; |
469 | | |
470 | 211M | if (IS_INTRA(s->cur_pic.mb_type[mb_xy])) |
471 | 41.4k | continue; |
472 | 211M | if (!(s->error_status_table[mb_xy] & ER_MV_ERROR)) |
473 | 1.17M | continue; |
474 | | |
475 | 210M | s->mv[0][0][0] = 0; |
476 | 210M | s->mv[0][0][1] = 0; |
477 | 210M | s->decode_mb(s->opaque, 0, mv_dir, MV_TYPE_16X16, &s->mv, |
478 | 210M | mb_x, mb_y, 0, 0); |
479 | 210M | } |
480 | 21.3M | } |
481 | 221k | return; |
482 | 221k | } |
483 | | |
484 | 159k | blocklist_length = 0; |
485 | 12.9M | for (mb_y = 0; mb_y < mb_height; mb_y++) { |
486 | 228M | for (mb_x = 0; mb_x < mb_width; mb_x++) { |
487 | 215M | const int mb_xy = mb_x + mb_y * mb_stride; |
488 | 215M | if (fixed[mb_xy] == MV_FROZEN) { |
489 | 163M | if (mb_x) add_blocklist(blocklist, &blocklist_length, fixed, mb_x - 1, mb_y, mb_xy - 1); |
490 | 163M | if (mb_y) add_blocklist(blocklist, &blocklist_length, fixed, mb_x, mb_y - 1, mb_xy - mb_stride); |
491 | 163M | if (mb_x+1 < mb_width) add_blocklist(blocklist, &blocklist_length, fixed, mb_x + 1, mb_y, mb_xy + 1); |
492 | 163M | if (mb_y+1 < mb_height) add_blocklist(blocklist, &blocklist_length, fixed, mb_x, mb_y + 1, mb_xy + mb_stride); |
493 | 163M | } |
494 | 215M | } |
495 | 12.8M | } |
496 | | |
497 | 3.09M | for (;;) { |
498 | 3.09M | int changed, pass, none_left; |
499 | 3.09M | int blocklist_index; |
500 | | |
501 | 3.09M | none_left = 1; |
502 | 3.09M | changed = 1; |
503 | 9.74M | for (pass = 0; (changed || pass < 2) && pass < 10; pass++) { |
504 | 6.65M | changed = 0; |
505 | 123M | for (blocklist_index = 0; blocklist_index < blocklist_length; blocklist_index++) { |
506 | 116M | const int mb_x = blocklist[blocklist_index][0]; |
507 | 116M | const int mb_y = blocklist[blocklist_index][1]; |
508 | 116M | const int mb_xy = mb_x + mb_y * mb_stride; |
509 | 116M | int mv_predictor[8][2]; |
510 | 116M | int ref[8]; |
511 | 116M | int pred_count; |
512 | 116M | int j; |
513 | 116M | int best_score; |
514 | 116M | int best_pred; |
515 | 116M | int mot_index; |
516 | 116M | int prev_x, prev_y, prev_ref; |
517 | | |
518 | 116M | if ((mb_x ^ mb_y ^ pass) & 1) |
519 | 58.6M | continue; |
520 | 58.3M | av_assert2(fixed[mb_xy] != MV_FROZEN); |
521 | | |
522 | | |
523 | 58.3M | av_assert1(!IS_INTRA(s->cur_pic.mb_type[mb_xy])); |
524 | 58.3M | av_assert1(s->last_pic.f && s->last_pic.f->data[0]); |
525 | | |
526 | 58.3M | j = 0; |
527 | 58.3M | if (mb_x > 0) |
528 | 55.4M | j |= fixed[mb_xy - 1]; |
529 | 58.3M | if (mb_x + 1 < mb_width) |
530 | 55.5M | j |= fixed[mb_xy + 1]; |
531 | 58.3M | if (mb_y > 0) |
532 | 57.7M | j |= fixed[mb_xy - mb_stride]; |
533 | 58.3M | if (mb_y + 1 < mb_height) |
534 | 55.0M | j |= fixed[mb_xy + mb_stride]; |
535 | | |
536 | 58.3M | av_assert2(j & MV_FROZEN); |
537 | | |
538 | 58.3M | if (!(j & MV_CHANGED) && pass > 1) |
539 | 4.94M | continue; |
540 | | |
541 | 53.3M | none_left = 0; |
542 | 53.3M | pred_count = 0; |
543 | 53.3M | mot_index = (mb_x + mb_y * mot_stride) * mot_step; |
544 | | |
545 | 53.3M | if (mb_x > 0 && fixed[mb_xy - 1] > 1) { |
546 | 28.5M | mv_predictor[pred_count][0] = |
547 | 28.5M | s->cur_pic.motion_val[0][mot_index - mot_step][0]; |
548 | 28.5M | mv_predictor[pred_count][1] = |
549 | 28.5M | s->cur_pic.motion_val[0][mot_index - mot_step][1]; |
550 | 28.5M | ref[pred_count] = |
551 | 28.5M | s->cur_pic.ref_index[0][4 * (mb_xy - 1)]; |
552 | 28.5M | pred_count++; |
553 | 28.5M | } |
554 | 53.3M | if (mb_x + 1 < mb_width && fixed[mb_xy + 1] > 1) { |
555 | 23.3M | mv_predictor[pred_count][0] = |
556 | 23.3M | s->cur_pic.motion_val[0][mot_index + mot_step][0]; |
557 | 23.3M | mv_predictor[pred_count][1] = |
558 | 23.3M | s->cur_pic.motion_val[0][mot_index + mot_step][1]; |
559 | 23.3M | ref[pred_count] = |
560 | 23.3M | s->cur_pic.ref_index[0][4 * (mb_xy + 1)]; |
561 | 23.3M | pred_count++; |
562 | 23.3M | } |
563 | 53.3M | if (mb_y > 0 && fixed[mb_xy - mb_stride] > 1) { |
564 | 50.6M | mv_predictor[pred_count][0] = |
565 | 50.6M | s->cur_pic.motion_val[0][mot_index - mot_stride * mot_step][0]; |
566 | 50.6M | mv_predictor[pred_count][1] = |
567 | 50.6M | s->cur_pic.motion_val[0][mot_index - mot_stride * mot_step][1]; |
568 | 50.6M | ref[pred_count] = |
569 | 50.6M | s->cur_pic.ref_index[0][4 * (mb_xy - s->mb_stride)]; |
570 | 50.6M | pred_count++; |
571 | 50.6M | } |
572 | 53.3M | if (mb_y + 1<mb_height && fixed[mb_xy + mb_stride] > 1) { |
573 | 2.40M | mv_predictor[pred_count][0] = |
574 | 2.40M | s->cur_pic.motion_val[0][mot_index + mot_stride * mot_step][0]; |
575 | 2.40M | mv_predictor[pred_count][1] = |
576 | 2.40M | s->cur_pic.motion_val[0][mot_index + mot_stride * mot_step][1]; |
577 | 2.40M | ref[pred_count] = |
578 | 2.40M | s->cur_pic.ref_index[0][4 * (mb_xy + s->mb_stride)]; |
579 | 2.40M | pred_count++; |
580 | 2.40M | } |
581 | 53.3M | if (pred_count == 0) |
582 | 0 | continue; |
583 | | |
584 | 53.3M | if (pred_count > 1) { |
585 | 29.4M | int sum_x = 0, sum_y = 0, sum_r = 0; |
586 | 29.4M | int max_x, max_y, min_x, min_y, max_r, min_r; |
587 | | |
588 | 110M | for (j = 0; j < pred_count; j++) { |
589 | 80.9M | sum_x += mv_predictor[j][0]; |
590 | 80.9M | sum_y += mv_predictor[j][1]; |
591 | 80.9M | sum_r += ref[j]; |
592 | 80.9M | if (j && ref[j] != ref[j - 1]) |
593 | 135k | goto skip_mean_and_median; |
594 | 80.9M | } |
595 | | |
596 | | /* mean */ |
597 | 29.3M | mv_predictor[pred_count][0] = sum_x / j; |
598 | 29.3M | mv_predictor[pred_count][1] = sum_y / j; |
599 | 29.3M | ref[pred_count] = sum_r / j; |
600 | | |
601 | | /* median */ |
602 | 29.3M | if (pred_count >= 3) { |
603 | 21.9M | min_y = min_x = min_r = 99999; |
604 | 21.9M | max_y = max_x = max_r = -99999; |
605 | 21.9M | } else { |
606 | 7.37M | min_x = min_y = max_x = max_y = min_r = max_r = 0; |
607 | 7.37M | } |
608 | 110M | for (j = 0; j < pred_count; j++) { |
609 | 80.6M | max_x = FFMAX(max_x, mv_predictor[j][0]); |
610 | 80.6M | max_y = FFMAX(max_y, mv_predictor[j][1]); |
611 | 80.6M | max_r = FFMAX(max_r, ref[j]); |
612 | 80.6M | min_x = FFMIN(min_x, mv_predictor[j][0]); |
613 | 80.6M | min_y = FFMIN(min_y, mv_predictor[j][1]); |
614 | 80.6M | min_r = FFMIN(min_r, ref[j]); |
615 | 80.6M | } |
616 | 29.3M | mv_predictor[pred_count + 1][0] = sum_x - max_x - min_x; |
617 | 29.3M | mv_predictor[pred_count + 1][1] = sum_y - max_y - min_y; |
618 | 29.3M | ref[pred_count + 1] = sum_r - max_r - min_r; |
619 | | |
620 | 29.3M | if (pred_count == 4) { |
621 | 31.2k | mv_predictor[pred_count + 1][0] /= 2; |
622 | 31.2k | mv_predictor[pred_count + 1][1] /= 2; |
623 | 31.2k | ref[pred_count + 1] /= 2; |
624 | 31.2k | } |
625 | 29.3M | pred_count += 2; |
626 | 29.3M | } |
627 | | |
628 | 53.3M | skip_mean_and_median: |
629 | | /* zero MV */ |
630 | 53.3M | mv_predictor[pred_count][0] = |
631 | 53.3M | mv_predictor[pred_count][1] = |
632 | 53.3M | ref[pred_count] = 0; |
633 | 53.3M | pred_count++; |
634 | | |
635 | 53.3M | prev_x = s->cur_pic.motion_val[0][mot_index][0]; |
636 | 53.3M | prev_y = s->cur_pic.motion_val[0][mot_index][1]; |
637 | 53.3M | prev_ref = s->cur_pic.ref_index[0][4 * mb_xy]; |
638 | | |
639 | | /* last MV */ |
640 | 53.3M | mv_predictor[pred_count][0] = prev_x; |
641 | 53.3M | mv_predictor[pred_count][1] = prev_y; |
642 | 53.3M | ref[pred_count] = prev_ref; |
643 | 53.3M | pred_count++; |
644 | | |
645 | 53.3M | best_pred = 0; |
646 | 53.3M | best_score = 256 * 256 * 256 * 64; |
647 | 323M | for (j = 0; j < pred_count; j++) { |
648 | 270M | int *linesize = s->cur_pic.f->linesize; |
649 | 270M | int score = 0; |
650 | 270M | uint8_t *src = s->cur_pic.f->data[0] + |
651 | 270M | mb_x * 16 + mb_y * 16 * linesize[0]; |
652 | | |
653 | 270M | s->cur_pic.motion_val[0][mot_index][0] = |
654 | 270M | s->mv[0][0][0] = mv_predictor[j][0]; |
655 | 270M | s->cur_pic.motion_val[0][mot_index][1] = |
656 | 270M | s->mv[0][0][1] = mv_predictor[j][1]; |
657 | | |
658 | | // predictor intra or otherwise not available |
659 | 270M | if (ref[j] < 0) |
660 | 28.3k | continue; |
661 | | |
662 | 270M | s->decode_mb(s->opaque, ref[j], MV_DIR_FORWARD, |
663 | 270M | MV_TYPE_16X16, &s->mv, mb_x, mb_y, 0, 0); |
664 | | |
665 | 270M | if (mb_x > 0 && fixed[mb_xy - 1] > 1) { |
666 | 191M | int k; |
667 | 3.26G | for (k = 0; k < 16; k++) |
668 | 3.07G | score += FFABS(src[k * linesize[0] - 1] - |
669 | 191M | src[k * linesize[0]]); |
670 | 191M | } |
671 | 270M | if (mb_x + 1 < mb_width && fixed[mb_xy + 1] > 1) { |
672 | 162M | int k; |
673 | 2.75G | for (k = 0; k < 16; k++) |
674 | 2.59G | score += FFABS(src[k * linesize[0] + 15] - |
675 | 162M | src[k * linesize[0] + 16]); |
676 | 162M | } |
677 | 270M | if (mb_y > 0 && fixed[mb_xy - mb_stride] > 1) { |
678 | 257M | int k; |
679 | 4.36G | for (k = 0; k < 16; k++) |
680 | 4.11G | score += FFABS(src[k - linesize[0]] - src[k]); |
681 | 257M | } |
682 | 270M | if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride] > 1) { |
683 | 12.6M | int k; |
684 | 215M | for (k = 0; k < 16; k++) |
685 | 202M | score += FFABS(src[k + linesize[0] * 15] - |
686 | 12.6M | src[k + linesize[0] * 16]); |
687 | 12.6M | } |
688 | | |
689 | 270M | if (score <= best_score) { // <= will favor the last MV |
690 | 263M | best_score = score; |
691 | 263M | best_pred = j; |
692 | 263M | } |
693 | 270M | } |
694 | 53.3M | s->mv[0][0][0] = mv_predictor[best_pred][0]; |
695 | 53.3M | s->mv[0][0][1] = mv_predictor[best_pred][1]; |
696 | | |
697 | 171M | for (i = 0; i < mot_step; i++) |
698 | 398M | for (j = 0; j < mot_step; j++) { |
699 | 280M | s->cur_pic.motion_val[0][mot_index + i + j * mot_stride][0] = s->mv[0][0][0]; |
700 | 280M | s->cur_pic.motion_val[0][mot_index + i + j * mot_stride][1] = s->mv[0][0][1]; |
701 | 280M | } |
702 | | |
703 | 53.3M | s->decode_mb(s->opaque, ref[best_pred], MV_DIR_FORWARD, |
704 | 53.3M | MV_TYPE_16X16, &s->mv, mb_x, mb_y, 0, 0); |
705 | | |
706 | | |
707 | 53.3M | if (s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y) { |
708 | 1.80M | fixed[mb_xy] = MV_CHANGED; |
709 | 1.80M | changed++; |
710 | 1.80M | } else |
711 | 51.5M | fixed[mb_xy] = MV_UNCHANGED; |
712 | 53.3M | } |
713 | 6.65M | } |
714 | | |
715 | 3.09M | if (none_left) |
716 | 159k | return; |
717 | | |
718 | 2.93M | next_blocklist_length = 0; |
719 | | |
720 | 55.0M | for (blocklist_index = 0; blocklist_index < blocklist_length; blocklist_index++) { |
721 | 52.0M | const int mb_x = blocklist[blocklist_index][0]; |
722 | 52.0M | const int mb_y = blocklist[blocklist_index][1]; |
723 | 52.0M | const int mb_xy = mb_x + mb_y * mb_stride; |
724 | | |
725 | 52.0M | if (fixed[mb_xy] & (MV_CHANGED|MV_UNCHANGED|MV_FROZEN)) { |
726 | 52.0M | fixed[mb_xy] = MV_FROZEN; |
727 | 52.0M | if (mb_x > 0) |
728 | 49.4M | add_blocklist(next_blocklist, &next_blocklist_length, fixed, mb_x - 1, mb_y, mb_xy - 1); |
729 | 52.0M | if (mb_y > 0) |
730 | 51.5M | add_blocklist(next_blocklist, &next_blocklist_length, fixed, mb_x, mb_y - 1, mb_xy - mb_stride); |
731 | 52.0M | if (mb_x + 1 < mb_width) |
732 | 49.4M | add_blocklist(next_blocklist, &next_blocklist_length, fixed, mb_x + 1, mb_y, mb_xy + 1); |
733 | 52.0M | if (mb_y + 1 < mb_height) |
734 | 49.2M | add_blocklist(next_blocklist, &next_blocklist_length, fixed, mb_x, mb_y + 1, mb_xy + mb_stride); |
735 | 52.0M | } |
736 | 52.0M | } |
737 | 2.93M | av_assert0(next_blocklist_length <= mb_height * mb_width); |
738 | 2.93M | FFSWAP(int , blocklist_length, next_blocklist_length); |
739 | 2.93M | FFSWAP(void*, blocklist, next_blocklist); |
740 | 2.93M | } |
741 | 159k | } |
742 | | |
743 | | static int is_intra_more_likely(ERContext *s) |
744 | 450k | { |
745 | 450k | int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y; |
746 | | |
747 | 450k | if (!s->last_pic.f || !s->last_pic.f->data[0]) |
748 | 115k | return 1; // no previous frame available -> use spatial prediction |
749 | | |
750 | 334k | if (s->avctx->error_concealment & FF_EC_FAVOR_INTER) |
751 | 0 | return 0; |
752 | | |
753 | 334k | undamaged_count = 0; |
754 | 334M | for (i = 0; i < s->mb_num; i++) { |
755 | 334M | const int mb_xy = s->mb_index2xy[i]; |
756 | 334M | const int error = s->error_status_table[mb_xy]; |
757 | 334M | if (!((error & ER_DC_ERROR) && (error & ER_MV_ERROR))) |
758 | 26.9M | undamaged_count++; |
759 | 334M | } |
760 | | |
761 | 334k | if (undamaged_count < 5) |
762 | 254k | return 0; // almost all MBs damaged -> use temporal prediction |
763 | | |
764 | 79.9k | skip_amount = FFMAX(undamaged_count / 50, 1); // check only up to 50 MBs |
765 | 79.9k | is_intra_likely = 0; |
766 | | |
767 | 79.9k | j = 0; |
768 | 12.4M | for (mb_y = 0; mb_y < s->mb_height - 1; mb_y++) { |
769 | 160M | for (mb_x = 0; mb_x < s->mb_width; mb_x++) { |
770 | 148M | int error; |
771 | 148M | const int mb_xy = mb_x + mb_y * s->mb_stride; |
772 | | |
773 | 148M | error = s->error_status_table[mb_xy]; |
774 | 148M | if ((error & ER_DC_ERROR) && (error & ER_MV_ERROR)) |
775 | 122M | continue; // skip damaged |
776 | | |
777 | 26.1M | j++; |
778 | | // skip a few to speed things up |
779 | 26.1M | if ((j % skip_amount) != 0) |
780 | 23.3M | continue; |
781 | | |
782 | 2.82M | if (s->cur_pic.f->pict_type == AV_PICTURE_TYPE_I) { |
783 | 130k | int *linesize = s->cur_pic.f->linesize; |
784 | 130k | uint8_t *mb_ptr = s->cur_pic.f->data[0] + |
785 | 130k | mb_x * 16 + mb_y * 16 * linesize[0]; |
786 | 130k | uint8_t *last_mb_ptr = s->last_pic.f->data[0] + |
787 | 130k | mb_x * 16 + mb_y * 16 * linesize[0]; |
788 | | |
789 | 130k | if (s->avctx->codec_id == AV_CODEC_ID_H264) { |
790 | | // FIXME |
791 | 117k | } else { |
792 | 117k | ff_thread_progress_await(s->last_pic.progress, mb_y); |
793 | 117k | } |
794 | 130k | is_intra_likely += s->sad(NULL, last_mb_ptr, mb_ptr, |
795 | 130k | linesize[0], 16); |
796 | | // FIXME need await_progress() here |
797 | 130k | is_intra_likely -= s->sad(NULL, last_mb_ptr, |
798 | 130k | last_mb_ptr + linesize[0] * 16, |
799 | 130k | linesize[0], 16); |
800 | 2.68M | } else { |
801 | 2.68M | if (IS_INTRA(s->cur_pic.mb_type[mb_xy])) |
802 | 65.1k | is_intra_likely++; |
803 | 2.62M | else |
804 | 2.62M | is_intra_likely--; |
805 | 2.68M | } |
806 | 2.82M | } |
807 | 12.3M | } |
808 | | // av_log(NULL, AV_LOG_ERROR, "is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type); |
809 | 79.9k | return is_intra_likely > 0; |
810 | 334k | } |
811 | | |
812 | | void ff_er_frame_start(ERContext *s) |
813 | 6.51M | { |
814 | 6.51M | if (!s->avctx->error_concealment) |
815 | 4.43M | return; |
816 | | |
817 | 2.08M | memset(s->error_status_table, ER_MB_ERROR | VP_START | ER_MB_END, |
818 | 2.08M | s->mb_stride * s->mb_height * sizeof(uint8_t)); |
819 | 2.08M | atomic_init(&s->error_count, 3 * s->mb_num); |
820 | 2.08M | s->error_occurred = 0; |
821 | 2.08M | } |
822 | | |
823 | | static int er_supported(ERContext *s) |
824 | 1.50M | { |
825 | 1.50M | if (s->avctx->hwaccel || |
826 | 1.50M | !s->cur_pic.f || |
827 | 1.28M | s->cur_pic.field_picture |
828 | 1.50M | ) |
829 | 245k | return 0; |
830 | 1.26M | return 1; |
831 | 1.50M | } |
832 | | |
833 | | /** |
834 | | * Add a slice. |
835 | | * @param endx x component of the last macroblock, can be -1 |
836 | | * for the last of the previous line |
837 | | * @param status the status at the end (ER_MV_END, ER_AC_ERROR, ...), it is |
838 | | * assumed that no earlier end or error of the same type occurred |
839 | | */ |
840 | | void ff_er_add_slice(ERContext *s, int startx, int starty, |
841 | | int endx, int endy, int status) |
842 | 6.20M | { |
843 | 6.20M | const int start_i = av_clip(startx + starty * s->mb_width, 0, s->mb_num - 1); |
844 | 6.20M | const int end_i = av_clip(endx + endy * s->mb_width, 0, s->mb_num); |
845 | 6.20M | const int start_xy = s->mb_index2xy[start_i]; |
846 | 6.20M | const int end_xy = s->mb_index2xy[end_i]; |
847 | 6.20M | int mask = -1; |
848 | | |
849 | 6.20M | if (s->avctx->hwaccel) |
850 | 0 | return; |
851 | | |
852 | 6.20M | if (start_i > end_i || start_xy > end_xy) { |
853 | 14.3k | av_log(s->avctx, AV_LOG_ERROR, |
854 | 14.3k | "internal error, slice end before start\n"); |
855 | 14.3k | return; |
856 | 14.3k | } |
857 | | |
858 | 6.18M | if (!s->avctx->error_concealment) |
859 | 2.98M | return; |
860 | | |
861 | 3.20M | mask &= ~VP_START; |
862 | 3.20M | if (status & (ER_AC_ERROR | ER_AC_END)) { |
863 | 3.17M | mask &= ~(ER_AC_ERROR | ER_AC_END); |
864 | 3.17M | atomic_fetch_add(&s->error_count, start_i - end_i - 1); |
865 | 3.17M | } |
866 | 3.20M | if (status & (ER_DC_ERROR | ER_DC_END)) { |
867 | 3.18M | mask &= ~(ER_DC_ERROR | ER_DC_END); |
868 | 3.18M | atomic_fetch_add(&s->error_count, start_i - end_i - 1); |
869 | 3.18M | } |
870 | 3.20M | if (status & (ER_MV_ERROR | ER_MV_END)) { |
871 | 3.19M | mask &= ~(ER_MV_ERROR | ER_MV_END); |
872 | 3.19M | atomic_fetch_add(&s->error_count, start_i - end_i - 1); |
873 | 3.19M | } |
874 | | |
875 | 3.20M | if (status & ER_MB_ERROR) { |
876 | 2.31M | s->error_occurred = 1; |
877 | 2.31M | atomic_store(&s->error_count, INT_MAX); |
878 | 2.31M | } |
879 | | |
880 | 3.20M | if (mask == ~0x7F) { |
881 | 3.17M | memset(&s->error_status_table[start_xy], 0, |
882 | 3.17M | (end_xy - start_xy) * sizeof(uint8_t)); |
883 | 3.17M | } else { |
884 | 32.0k | int i; |
885 | 651k | for (i = start_xy; i < end_xy; i++) |
886 | 619k | s->error_status_table[i] &= mask; |
887 | 32.0k | } |
888 | | |
889 | 3.20M | if (end_i == s->mb_num) |
890 | 3.20M | atomic_store(&s->error_count, INT_MAX); |
891 | 2.99M | else { |
892 | 2.99M | s->error_status_table[end_xy] &= mask; |
893 | 2.99M | s->error_status_table[end_xy] |= status; |
894 | 2.99M | } |
895 | | |
896 | 3.20M | s->error_status_table[start_xy] |= VP_START; |
897 | | |
898 | 3.20M | if (start_xy > 0 && !(s->avctx->active_thread_type & FF_THREAD_SLICE) && |
899 | 1.05M | er_supported(s) && s->avctx->skip_top * s->mb_width < start_i) { |
900 | 811k | int prev_status = s->error_status_table[s->mb_index2xy[start_i - 1]]; |
901 | | |
902 | 811k | prev_status &= ~ VP_START; |
903 | 811k | if (prev_status != (ER_MV_END | ER_DC_END | ER_AC_END)) { |
904 | 480k | s->error_occurred = 1; |
905 | 480k | atomic_store(&s->error_count, INT_MAX); |
906 | 480k | } |
907 | 811k | } |
908 | 3.20M | } |
909 | | |
910 | | void ff_er_frame_end(ERContext *s, int *decode_error_flags) |
911 | 2.92M | { |
912 | 2.92M | int *linesize = NULL; |
913 | 2.92M | int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error; |
914 | 2.92M | int distance; |
915 | 2.92M | int threshold_part[4] = { 100, 100, 100 }; |
916 | 2.92M | int threshold = 50; |
917 | 2.92M | int is_intra_likely; |
918 | 2.92M | int size = s->b8_stride * 2 * s->mb_height; |
919 | 2.92M | int guessed_mb_type; |
920 | | |
921 | | /* We do not support ER of field pictures yet, |
922 | | * though it should not crash if enabled. */ |
923 | 2.92M | if (!s->avctx->error_concealment || !atomic_load(&s->error_count) || |
924 | 511k | s->avctx->lowres || |
925 | 453k | !er_supported(s) || |
926 | 2.92M | atomic_load(&s->error_count) == 3 * s->mb_width * |
927 | 2.47M | (s->avctx->skip_top + s->avctx->skip_bottom)) { |
928 | 2.47M | return; |
929 | 2.47M | } |
930 | 451k | linesize = s->cur_pic.f->linesize; |
931 | | |
932 | 451k | if ( s->avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO |
933 | 11.4k | && (FFALIGN(s->avctx->height, 16)&16) |
934 | 451k | && atomic_load(&s->error_count) == 3 * s->mb_width * (s->avctx->skip_top + s->avctx->skip_bottom + 1)) { |
935 | 281k | for (mb_x = 0; mb_x < s->mb_width; mb_x++) { |
936 | 280k | int status = s->error_status_table[mb_x + (s->mb_height - 1) * s->mb_stride]; |
937 | 280k | if (status != 0x7F) |
938 | 0 | break; |
939 | 280k | } |
940 | | |
941 | 943 | if (mb_x == s->mb_width) { |
942 | 943 | av_log(s->avctx, AV_LOG_DEBUG, "ignoring last missing slice\n"); |
943 | 943 | return; |
944 | 943 | } |
945 | 943 | } |
946 | | |
947 | 450k | if (s->last_pic.f) { |
948 | 334k | if (s->last_pic.f->width != s->cur_pic.f->width || |
949 | 334k | s->last_pic.f->height != s->cur_pic.f->height || |
950 | 334k | s->last_pic.f->format != s->cur_pic.f->format) { |
951 | 0 | av_log(s->avctx, AV_LOG_WARNING, "Cannot use previous picture in error concealment\n"); |
952 | 0 | memset(&s->last_pic, 0, sizeof(s->last_pic)); |
953 | 0 | } |
954 | 334k | } |
955 | 450k | if (s->next_pic.f) { |
956 | 310k | if (s->next_pic.f->width != s->cur_pic.f->width || |
957 | 307k | s->next_pic.f->height != s->cur_pic.f->height || |
958 | 307k | s->next_pic.f->format != s->cur_pic.f->format) { |
959 | 3.07k | av_log(s->avctx, AV_LOG_WARNING, "Cannot use next picture in error concealment\n"); |
960 | 3.07k | memset(&s->next_pic, 0, sizeof(s->next_pic)); |
961 | 3.07k | } |
962 | 310k | } |
963 | | |
964 | 450k | if (!s->cur_pic.motion_val[0] || !s->cur_pic.ref_index[0]) { |
965 | 20.5k | av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n"); |
966 | | |
967 | 61.6k | for (i = 0; i < 2; i++) { |
968 | 41.0k | s->ref_index[i] = av_calloc(s->mb_stride * s->mb_height, 4 * sizeof(uint8_t)); |
969 | 41.0k | s->motion_val_base[i] = av_calloc(size + 4, 2 * sizeof(uint16_t)); |
970 | 41.0k | if (!s->ref_index[i] || !s->motion_val_base[i]) |
971 | 0 | goto cleanup; |
972 | 41.0k | s->cur_pic.ref_index[i] = s->ref_index[i]; |
973 | 41.0k | s->cur_pic.motion_val[i] = s->motion_val_base[i] + 4; |
974 | 41.0k | } |
975 | 20.5k | } |
976 | | |
977 | 450k | if (s->avctx->debug & FF_DEBUG_ER) { |
978 | 0 | for (mb_y = 0; mb_y < s->mb_height; mb_y++) { |
979 | 0 | for (mb_x = 0; mb_x < s->mb_width; mb_x++) { |
980 | 0 | int status = s->error_status_table[mb_x + mb_y * s->mb_stride]; |
981 | |
|
982 | 0 | av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status); |
983 | 0 | } |
984 | 0 | av_log(s->avctx, AV_LOG_DEBUG, "\n"); |
985 | 0 | } |
986 | 0 | } |
987 | | |
988 | 450k | #if 1 |
989 | | /* handle overlapping slices */ |
990 | 1.80M | for (error_type = 1; error_type <= 3; error_type++) { |
991 | 1.35M | int end_ok = 0; |
992 | | |
993 | 1.39G | for (i = s->mb_num - 1; i >= 0; i--) { |
994 | 1.39G | const int mb_xy = s->mb_index2xy[i]; |
995 | 1.39G | int error = s->error_status_table[mb_xy]; |
996 | | |
997 | 1.39G | if (error & (1 << error_type)) |
998 | 1.27G | end_ok = 1; |
999 | 1.39G | if (error & (8 << error_type)) |
1000 | 1.27G | end_ok = 1; |
1001 | | |
1002 | 1.39G | if (!end_ok) |
1003 | 394k | s->error_status_table[mb_xy] |= 1 << error_type; |
1004 | | |
1005 | 1.39G | if (error & VP_START) |
1006 | 1.27G | end_ok = 0; |
1007 | 1.39G | } |
1008 | 1.35M | } |
1009 | 450k | #endif |
1010 | 450k | #if 1 |
1011 | | /* handle slices with partitions of different length */ |
1012 | 450k | if (s->partitioned_frame) { |
1013 | 5.05k | int end_ok = 0; |
1014 | | |
1015 | 1.92M | for (i = s->mb_num - 1; i >= 0; i--) { |
1016 | 1.92M | const int mb_xy = s->mb_index2xy[i]; |
1017 | 1.92M | int error = s->error_status_table[mb_xy]; |
1018 | | |
1019 | 1.92M | if (error & ER_AC_END) |
1020 | 1.90M | end_ok = 0; |
1021 | 1.92M | if ((error & ER_MV_END) || |
1022 | 297k | (error & ER_DC_END) || |
1023 | 20.0k | (error & ER_AC_ERROR)) |
1024 | 1.91M | end_ok = 1; |
1025 | | |
1026 | 1.92M | if (!end_ok) |
1027 | 911 | s->error_status_table[mb_xy]|= ER_AC_ERROR; |
1028 | | |
1029 | 1.92M | if (error & VP_START) |
1030 | 1.63M | end_ok = 0; |
1031 | 1.92M | } |
1032 | 5.05k | } |
1033 | 450k | #endif |
1034 | | /* handle missing slices */ |
1035 | 450k | if (s->avctx->err_recognition & AV_EF_EXPLODE) { |
1036 | 101k | int end_ok = 1; |
1037 | | |
1038 | | // FIXME + 100 hack |
1039 | 76.2M | for (i = s->mb_num - 2; i >= s->mb_width + 100; i--) { |
1040 | 76.1M | const int mb_xy = s->mb_index2xy[i]; |
1041 | 76.1M | int error1 = s->error_status_table[mb_xy]; |
1042 | 76.1M | int error2 = s->error_status_table[s->mb_index2xy[i + 1]]; |
1043 | | |
1044 | 76.1M | if (error1 & VP_START) |
1045 | 71.2M | end_ok = 1; |
1046 | | |
1047 | 76.1M | if (error2 == (VP_START | ER_MB_ERROR | ER_MB_END) && |
1048 | 71.2M | error1 != (VP_START | ER_MB_ERROR | ER_MB_END) && |
1049 | 11.8k | ((error1 & ER_AC_END) || (error1 & ER_DC_END) || |
1050 | 8.22k | (error1 & ER_MV_END))) { |
1051 | | // end & uninit |
1052 | 3.63k | end_ok = 0; |
1053 | 3.63k | } |
1054 | | |
1055 | 76.1M | if (!end_ok) |
1056 | 369k | s->error_status_table[mb_xy] |= ER_MB_ERROR; |
1057 | 76.1M | } |
1058 | 101k | } |
1059 | | |
1060 | 450k | #if 1 |
1061 | | /* backward mark errors */ |
1062 | 450k | distance = 9999999; |
1063 | 1.80M | for (error_type = 1; error_type <= 3; error_type++) { |
1064 | 1.39G | for (i = s->mb_num - 1; i >= 0; i--) { |
1065 | 1.39G | const int mb_xy = s->mb_index2xy[i]; |
1066 | 1.39G | int error = s->error_status_table[mb_xy]; |
1067 | | |
1068 | 1.39G | if (!s->mbskip_table || !s->mbskip_table[mb_xy]) // FIXME partition specific |
1069 | 1.31G | distance++; |
1070 | 1.39G | if (error & (1 << error_type)) |
1071 | 1.27G | distance = 0; |
1072 | | |
1073 | 1.39G | if (s->partitioned_frame) { |
1074 | 5.77M | if (distance < threshold_part[error_type - 1]) |
1075 | 5.60M | s->error_status_table[mb_xy] |= 1 << error_type; |
1076 | 1.39G | } else { |
1077 | 1.39G | if (distance < threshold) |
1078 | 1.28G | s->error_status_table[mb_xy] |= 1 << error_type; |
1079 | 1.39G | } |
1080 | | |
1081 | 1.39G | if (error & VP_START) |
1082 | 1.27G | distance = 9999999; |
1083 | 1.39G | } |
1084 | 1.35M | } |
1085 | 450k | #endif |
1086 | | |
1087 | | /* forward mark errors */ |
1088 | 450k | error = 0; |
1089 | 466M | for (i = 0; i < s->mb_num; i++) { |
1090 | 466M | const int mb_xy = s->mb_index2xy[i]; |
1091 | 466M | int old_error = s->error_status_table[mb_xy]; |
1092 | | |
1093 | 466M | if (old_error & VP_START) { |
1094 | 424M | error = old_error & ER_MB_ERROR; |
1095 | 424M | } else { |
1096 | 41.3M | error |= old_error & ER_MB_ERROR; |
1097 | 41.3M | s->error_status_table[mb_xy] |= error; |
1098 | 41.3M | } |
1099 | 466M | } |
1100 | 450k | #if 1 |
1101 | | /* handle not partitioned case */ |
1102 | 450k | if (!s->partitioned_frame) { |
1103 | 464M | for (i = 0; i < s->mb_num; i++) { |
1104 | 464M | const int mb_xy = s->mb_index2xy[i]; |
1105 | 464M | int error = s->error_status_table[mb_xy]; |
1106 | 464M | if (error & ER_MB_ERROR) |
1107 | 428M | error |= ER_MB_ERROR; |
1108 | 464M | s->error_status_table[mb_xy] = error; |
1109 | 464M | } |
1110 | 445k | } |
1111 | 450k | #endif |
1112 | | |
1113 | 450k | dc_error = ac_error = mv_error = 0; |
1114 | 466M | for (i = 0; i < s->mb_num; i++) { |
1115 | 466M | const int mb_xy = s->mb_index2xy[i]; |
1116 | 466M | int error = s->error_status_table[mb_xy]; |
1117 | 466M | if (error & ER_DC_ERROR) |
1118 | 430M | dc_error++; |
1119 | 466M | if (error & ER_AC_ERROR) |
1120 | 430M | ac_error++; |
1121 | 466M | if (error & ER_MV_ERROR) |
1122 | 430M | mv_error++; |
1123 | 466M | } |
1124 | 450k | av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors in %c frame\n", |
1125 | 450k | dc_error, ac_error, mv_error, av_get_picture_type_char(s->cur_pic.f->pict_type)); |
1126 | | |
1127 | 450k | if (decode_error_flags) |
1128 | 209k | *decode_error_flags |= FF_DECODE_ERROR_CONCEALMENT_ACTIVE; |
1129 | 240k | else |
1130 | 240k | s->cur_pic.f->decode_error_flags |= FF_DECODE_ERROR_CONCEALMENT_ACTIVE; |
1131 | | |
1132 | 450k | is_intra_likely = is_intra_more_likely(s); |
1133 | | |
1134 | | /* set unknown mb-type to most likely */ |
1135 | 450k | guessed_mb_type = is_intra_likely ? MB_TYPE_INTRA4x4 : |
1136 | 450k | (MB_TYPE_16x16 | (s->avctx->codec_id == AV_CODEC_ID_H264 ? MB_TYPE_L0 : MB_TYPE_FORWARD_MV)); |
1137 | 466M | for (i = 0; i < s->mb_num; i++) { |
1138 | 466M | const int mb_xy = s->mb_index2xy[i]; |
1139 | 466M | int error = s->error_status_table[mb_xy]; |
1140 | 466M | if (!((error & ER_DC_ERROR) && (error & ER_MV_ERROR))) |
1141 | 35.7M | continue; |
1142 | | |
1143 | 430M | s->cur_pic.mb_type[mb_xy] = guessed_mb_type; |
1144 | 430M | } |
1145 | | |
1146 | | // change inter to intra blocks if no reference frames are available |
1147 | 450k | if (!(s->last_pic.f && s->last_pic.f->data[0]) && |
1148 | 115k | !(s->next_pic.f && s->next_pic.f->data[0])) |
1149 | 22.9M | for (i = 0; i < s->mb_num; i++) { |
1150 | 22.8M | const int mb_xy = s->mb_index2xy[i]; |
1151 | 22.8M | if (!IS_INTRA(s->cur_pic.mb_type[mb_xy])) |
1152 | 771k | s->cur_pic.mb_type[mb_xy] = MB_TYPE_INTRA4x4; |
1153 | 22.8M | } |
1154 | | |
1155 | | /* handle inter blocks with damaged AC */ |
1156 | 38.3M | for (mb_y = 0; mb_y < s->mb_height; mb_y++) { |
1157 | 504M | for (mb_x = 0; mb_x < s->mb_width; mb_x++) { |
1158 | 466M | const int mb_xy = mb_x + mb_y * s->mb_stride; |
1159 | 466M | const int mb_type = s->cur_pic.mb_type[mb_xy]; |
1160 | 466M | const int dir = !(s->last_pic.f && s->last_pic.f->data[0]); |
1161 | 466M | const int mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD; |
1162 | 466M | int mv_type; |
1163 | | |
1164 | 466M | int error = s->error_status_table[mb_xy]; |
1165 | | |
1166 | 466M | if (IS_INTRA(mb_type)) |
1167 | 143M | continue; // intra |
1168 | 322M | if (error & ER_MV_ERROR) |
1169 | 294M | continue; // inter with damaged MV |
1170 | 27.5M | if (!(error & ER_AC_ERROR)) |
1171 | 27.4M | continue; // undamaged inter |
1172 | | |
1173 | 145k | if (IS_8X8(mb_type)) { |
1174 | 8.87k | int mb_index = mb_x * 2 + mb_y * 2 * s->b8_stride; |
1175 | 8.87k | int j; |
1176 | 8.87k | mv_type = MV_TYPE_8X8; |
1177 | 44.3k | for (j = 0; j < 4; j++) { |
1178 | 35.5k | s->mv[0][j][0] = s->cur_pic.motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][0]; |
1179 | 35.5k | s->mv[0][j][1] = s->cur_pic.motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][1]; |
1180 | 35.5k | } |
1181 | 136k | } else { |
1182 | 136k | mv_type = MV_TYPE_16X16; |
1183 | 136k | s->mv[0][0][0] = s->cur_pic.motion_val[dir][mb_x * 2 + mb_y * 2 * s->b8_stride][0]; |
1184 | 136k | s->mv[0][0][1] = s->cur_pic.motion_val[dir][mb_x * 2 + mb_y * 2 * s->b8_stride][1]; |
1185 | 136k | } |
1186 | | |
1187 | 145k | s->decode_mb(s->opaque, 0 /* FIXME H.264 partitioned slices need this set */, |
1188 | 145k | mv_dir, mv_type, &s->mv, mb_x, mb_y, 0, 0); |
1189 | 145k | } |
1190 | 37.9M | } |
1191 | | |
1192 | | /* guess MVs */ |
1193 | 450k | if (s->cur_pic.f->pict_type == AV_PICTURE_TYPE_B) { |
1194 | 3.81M | for (mb_y = 0; mb_y < s->mb_height; mb_y++) { |
1195 | 42.7M | for (mb_x = 0; mb_x < s->mb_width; mb_x++) { |
1196 | 39.0M | int xy = mb_x * 2 + mb_y * 2 * s->b8_stride; |
1197 | 39.0M | const int mb_xy = mb_x + mb_y * s->mb_stride; |
1198 | 39.0M | const int mb_type = s->cur_pic.mb_type[mb_xy]; |
1199 | 39.0M | int mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD; |
1200 | | |
1201 | 39.0M | int error = s->error_status_table[mb_xy]; |
1202 | | |
1203 | 39.0M | if (IS_INTRA(mb_type)) |
1204 | 4.13M | continue; |
1205 | 34.8M | if (!(error & ER_MV_ERROR)) |
1206 | 2.90M | continue; // inter with undamaged MV |
1207 | 31.9M | if (!(error & ER_AC_ERROR)) |
1208 | 0 | continue; // undamaged inter |
1209 | | |
1210 | 31.9M | if (!(s->last_pic.f && s->last_pic.f->data[0])) |
1211 | 0 | mv_dir &= ~MV_DIR_FORWARD; |
1212 | 31.9M | if (!(s->next_pic.f && s->next_pic.f->data[0])) |
1213 | 2.31M | mv_dir &= ~MV_DIR_BACKWARD; |
1214 | | |
1215 | 31.9M | if (s->pp_time) { |
1216 | 1.33M | int time_pp = s->pp_time; |
1217 | 1.33M | int time_pb = s->pb_time; |
1218 | | |
1219 | 1.33M | av_assert0(s->avctx->codec_id != AV_CODEC_ID_H264); |
1220 | 1.33M | ff_thread_progress_await(s->next_pic.progress, mb_y); |
1221 | | |
1222 | 1.33M | s->mv[0][0][0] = s->next_pic.motion_val[0][xy][0] * time_pb / time_pp; |
1223 | 1.33M | s->mv[0][0][1] = s->next_pic.motion_val[0][xy][1] * time_pb / time_pp; |
1224 | 1.33M | s->mv[1][0][0] = s->next_pic.motion_val[0][xy][0] * (time_pb - time_pp) / time_pp; |
1225 | 1.33M | s->mv[1][0][1] = s->next_pic.motion_val[0][xy][1] * (time_pb - time_pp) / time_pp; |
1226 | 30.6M | } else { |
1227 | 30.6M | s->mv[0][0][0] = 0; |
1228 | 30.6M | s->mv[0][0][1] = 0; |
1229 | 30.6M | s->mv[1][0][0] = 0; |
1230 | 30.6M | s->mv[1][0][1] = 0; |
1231 | 30.6M | } |
1232 | | |
1233 | 31.9M | s->decode_mb(s->opaque, 0, mv_dir, MV_TYPE_16X16, &s->mv, |
1234 | 31.9M | mb_x, mb_y, 0, 0); |
1235 | 31.9M | } |
1236 | 3.74M | } |
1237 | 68.7k | } else |
1238 | 381k | guess_mv(s); |
1239 | | |
1240 | | /* fill DC for inter blocks */ |
1241 | 38.3M | for (mb_y = 0; mb_y < s->mb_height; mb_y++) { |
1242 | 504M | for (mb_x = 0; mb_x < s->mb_width; mb_x++) { |
1243 | 466M | int dc, dcu, dcv, y, n; |
1244 | 466M | int16_t *dc_ptr; |
1245 | 466M | uint8_t *dest_y, *dest_cb, *dest_cr; |
1246 | 466M | const int mb_xy = mb_x + mb_y * s->mb_stride; |
1247 | 466M | const int mb_type = s->cur_pic.mb_type[mb_xy]; |
1248 | | |
1249 | | // error = s->error_status_table[mb_xy]; |
1250 | | |
1251 | 466M | if (IS_INTRA(mb_type) && s->partitioned_frame) |
1252 | 171k | continue; |
1253 | | // if (error & ER_MV_ERROR) |
1254 | | // continue; // inter data damaged FIXME is this good? |
1255 | | |
1256 | 465M | dest_y = s->cur_pic.f->data[0] + mb_x * 16 + mb_y * 16 * linesize[0]; |
1257 | 465M | dest_cb = s->cur_pic.f->data[1] + mb_x * 8 + mb_y * 8 * linesize[1]; |
1258 | 465M | dest_cr = s->cur_pic.f->data[2] + mb_x * 8 + mb_y * 8 * linesize[2]; |
1259 | | |
1260 | 465M | dc_ptr = &s->dc_val[0][mb_x * 2 + mb_y * 2 * s->b8_stride]; |
1261 | 2.32G | for (n = 0; n < 4; n++) { |
1262 | 1.86G | dc = 0; |
1263 | 16.7G | for (y = 0; y < 8; y++) { |
1264 | 14.9G | int x; |
1265 | 134G | for (x = 0; x < 8; x++) |
1266 | 119G | dc += dest_y[x + (n & 1) * 8 + |
1267 | 119G | (y + (n >> 1) * 8) * linesize[0]]; |
1268 | 14.9G | } |
1269 | 1.86G | dc_ptr[(n & 1) + (n >> 1) * s->b8_stride] = (dc + 4) >> 3; |
1270 | 1.86G | } |
1271 | | |
1272 | 465M | if (!s->cur_pic.f->data[2]) |
1273 | 0 | continue; |
1274 | | |
1275 | 465M | dcu = dcv = 0; |
1276 | 4.19G | for (y = 0; y < 8; y++) { |
1277 | 3.72G | int x; |
1278 | 33.5G | for (x = 0; x < 8; x++) { |
1279 | 29.8G | dcu += dest_cb[x + y * linesize[1]]; |
1280 | 29.8G | dcv += dest_cr[x + y * linesize[2]]; |
1281 | 29.8G | } |
1282 | 3.72G | } |
1283 | 465M | s->dc_val[1][mb_x + mb_y * s->mb_stride] = (dcu + 4) >> 3; |
1284 | 465M | s->dc_val[2][mb_x + mb_y * s->mb_stride] = (dcv + 4) >> 3; |
1285 | 465M | } |
1286 | 37.9M | } |
1287 | 450k | #if 1 |
1288 | | /* guess DC for damaged blocks */ |
1289 | 450k | guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1); |
1290 | 450k | guess_dc(s, s->dc_val[1], s->mb_width , s->mb_height , s->mb_stride, 0); |
1291 | 450k | guess_dc(s, s->dc_val[2], s->mb_width , s->mb_height , s->mb_stride, 0); |
1292 | 450k | #endif |
1293 | | |
1294 | | /* filter luma DC */ |
1295 | 450k | filter181(s->dc_val[0], s->mb_width * 2, s->mb_height * 2, s->b8_stride); |
1296 | | |
1297 | 450k | #if 1 |
1298 | | /* render DC only intra */ |
1299 | 38.3M | for (mb_y = 0; mb_y < s->mb_height; mb_y++) { |
1300 | 504M | for (mb_x = 0; mb_x < s->mb_width; mb_x++) { |
1301 | 466M | uint8_t *dest_y, *dest_cb, *dest_cr; |
1302 | 466M | const int mb_xy = mb_x + mb_y * s->mb_stride; |
1303 | 466M | const int mb_type = s->cur_pic.mb_type[mb_xy]; |
1304 | | |
1305 | 466M | int error = s->error_status_table[mb_xy]; |
1306 | | |
1307 | 466M | if (IS_INTER(mb_type)) |
1308 | 311M | continue; |
1309 | 154M | if (!(error & ER_AC_ERROR)) |
1310 | 18.8M | continue; // undamaged |
1311 | | |
1312 | 135M | dest_y = s->cur_pic.f->data[0] + mb_x * 16 + mb_y * 16 * linesize[0]; |
1313 | 135M | dest_cb = s->cur_pic.f->data[1] + mb_x * 8 + mb_y * 8 * linesize[1]; |
1314 | 135M | dest_cr = s->cur_pic.f->data[2] + mb_x * 8 + mb_y * 8 * linesize[2]; |
1315 | 135M | if (!s->cur_pic.f->data[2]) |
1316 | 0 | dest_cb = dest_cr = NULL; |
1317 | | |
1318 | 135M | put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y); |
1319 | 135M | } |
1320 | 37.9M | } |
1321 | 450k | #endif |
1322 | | |
1323 | 450k | if (s->avctx->error_concealment & FF_EC_DEBLOCK) { |
1324 | | /* filter horizontal block boundaries */ |
1325 | 450k | h_block_filter(s, s->cur_pic.f->data[0], s->mb_width * 2, |
1326 | 450k | s->mb_height * 2, linesize[0], 1); |
1327 | | |
1328 | | /* filter vertical block boundaries */ |
1329 | 450k | v_block_filter(s, s->cur_pic.f->data[0], s->mb_width * 2, |
1330 | 450k | s->mb_height * 2, linesize[0], 1); |
1331 | | |
1332 | 450k | if (s->cur_pic.f->data[2]) { |
1333 | 450k | h_block_filter(s, s->cur_pic.f->data[1], s->mb_width, |
1334 | 450k | s->mb_height, linesize[1], 0); |
1335 | 450k | h_block_filter(s, s->cur_pic.f->data[2], s->mb_width, |
1336 | 450k | s->mb_height, linesize[2], 0); |
1337 | 450k | v_block_filter(s, s->cur_pic.f->data[1], s->mb_width, |
1338 | 450k | s->mb_height, linesize[1], 0); |
1339 | 450k | v_block_filter(s, s->cur_pic.f->data[2], s->mb_width, |
1340 | 450k | s->mb_height, linesize[2], 0); |
1341 | 450k | } |
1342 | 450k | } |
1343 | | |
1344 | | /* clean a few tables */ |
1345 | 466M | for (i = 0; i < s->mb_num; i++) { |
1346 | 466M | const int mb_xy = s->mb_index2xy[i]; |
1347 | 466M | int error = s->error_status_table[mb_xy]; |
1348 | | |
1349 | 466M | if (s->mbskip_table && s->cur_pic.f->pict_type != AV_PICTURE_TYPE_B && |
1350 | 379M | (error & (ER_DC_ERROR | ER_MV_ERROR | ER_AC_ERROR))) { |
1351 | 350M | s->mbskip_table[mb_xy] = 0; |
1352 | 350M | } |
1353 | 466M | if (s->mbintra_table) |
1354 | 398M | s->mbintra_table[mb_xy] = 1; |
1355 | 466M | } |
1356 | | |
1357 | 450k | memset(&s->cur_pic, 0, sizeof(ERPicture)); |
1358 | 450k | memset(&s->last_pic, 0, sizeof(ERPicture)); |
1359 | 450k | memset(&s->next_pic, 0, sizeof(ERPicture)); |
1360 | | |
1361 | 450k | cleanup: |
1362 | 1.35M | for (i = 0; i < 2; i++) { |
1363 | 900k | av_freep(&s->ref_index[i]); |
1364 | 900k | av_freep(&s->motion_val_base[i]); |
1365 | 900k | s->cur_pic.ref_index[i] = NULL; |
1366 | | s->cur_pic.motion_val[i] = NULL; |
1367 | 900k | } |
1368 | 450k | } |