3d47412f7eae0b79989f8e67ca12b28bbc257168
[profile/ivi/libvpx.git] / vp8 / encoder / picklpf.c
1 /*
2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10
11
12 #include "vp8/common/onyxc_int.h"
13 #include "onyx_int.h"
14 #include "quantize.h"
15 #include "vpx_mem/vpx_mem.h"
16 #include "vpx_scale/yv12extend.h"
17 #include "vpx_scale/vpxscale.h"
18 #include "vp8/common/alloccommon.h"
19 #if ARCH_ARM
20 #include "vpx_ports/arm.h"
21 #endif
22
23 extern void vp8_loop_filter_frame(VP8_COMMON *cm,    MACROBLOCKD *mbd,  int filt_val);
24 extern void vp8_loop_filter_frame_yonly(VP8_COMMON *cm,    MACROBLOCKD *mbd,  int filt_val, int sharpness_lvl);
25 extern int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, const vp8_variance_rtcd_vtable_t *rtcd);
26 #if HAVE_ARMV7
27 extern void vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc);
28 #endif
29
30 #if CONFIG_RUNTIME_CPU_DETECT
31 #define IF_RTCD(x) (x)
32 #else
33 #define IF_RTCD(x) NULL
34 #endif
35
36 extern void
37 (*vp8_yv12_copy_partial_frame_ptr)(YV12_BUFFER_CONFIG *src_ybc,
38                                    YV12_BUFFER_CONFIG *dst_ybc,
39                                    int Fraction);
40 void
41 vp8_yv12_copy_partial_frame(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc, int Fraction)
42 {
43     unsigned char *src_y, *dst_y;
44     int yheight;
45     int ystride;
46     int border;
47     int yoffset;
48     int linestocopy;
49
50     border   = src_ybc->border;
51     yheight  = src_ybc->y_height;
52     ystride  = src_ybc->y_stride;
53
54     linestocopy = (yheight >> (Fraction + 4));
55
56     if (linestocopy < 1)
57         linestocopy = 1;
58
59     linestocopy <<= 4;
60
61     yoffset  = ystride * ((yheight >> 5) * 16 - 8);
62     src_y = src_ybc->y_buffer + yoffset;
63     dst_y = dst_ybc->y_buffer + yoffset;
64
65     vpx_memcpy(dst_y, src_y, ystride *(linestocopy + 16));
66 }
67
68 static int vp8_calc_partial_ssl_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, int Fraction, const vp8_variance_rtcd_vtable_t *rtcd)
69 {
70     int i, j;
71     int Total = 0;
72     int srcoffset, dstoffset;
73     unsigned char *src = source->y_buffer;
74     unsigned char *dst = dest->y_buffer;
75
76     int linestocopy = (source->y_height >> (Fraction + 4));
77     (void)rtcd;
78
79     if (linestocopy < 1)
80         linestocopy = 1;
81
82     linestocopy <<= 4;
83
84
85     srcoffset = source->y_stride   * (dest->y_height >> 5) * 16;
86     dstoffset = dest->y_stride     * (dest->y_height >> 5) * 16;
87
88     src += srcoffset;
89     dst += dstoffset;
90
91     // Loop through the Y plane raw and reconstruction data summing (square differences)
92     for (i = 0; i < linestocopy; i += 16)
93     {
94         for (j = 0; j < source->y_width; j += 16)
95         {
96             unsigned int sse;
97             Total += VARIANCE_INVOKE(rtcd, mse16x16)(src + j, source->y_stride, dst + j, dest->y_stride, &sse);
98         }
99
100         src += 16 * source->y_stride;
101         dst += 16 * dest->y_stride;
102     }
103
104     return Total;
105 }
106
107 extern void vp8_loop_filter_partial_frame
108 (
109     VP8_COMMON *cm,
110     MACROBLOCKD *mbd,
111     int default_filt_lvl,
112     int sharpness_lvl,
113     int Fraction
114 );
115
116 // Enforce a minimum filter level based upon baseline Q
117 static int get_min_filter_level(VP8_COMP *cpi, int base_qindex)
118 {
119     int min_filter_level;
120
121     if (cpi->source_alt_ref_active && cpi->common.refresh_golden_frame && !cpi->common.refresh_alt_ref_frame)
122         min_filter_level = 0;
123     else
124     {
125         if (base_qindex <= 6)
126             min_filter_level = 0;
127         else if (base_qindex <= 16)
128             min_filter_level = 1;
129         else
130             min_filter_level = (base_qindex / 8);
131     }
132
133     return min_filter_level;
134 }
135
136 // Enforce a maximum filter level based upon baseline Q
137 static int get_max_filter_level(VP8_COMP *cpi, int base_qindex)
138 {
139     // PGW August 2006: Highest filter values almost always a bad idea
140
141     // jbb chg: 20100118 - not so any more with this overquant stuff allow high values
142     // with lots of intra coming in.
143     int max_filter_level = MAX_LOOP_FILTER ;//* 3 / 4;
144     (void)base_qindex;
145
146     if (cpi->twopass.section_intra_rating > 8)
147         max_filter_level = MAX_LOOP_FILTER * 3 / 4;
148
149     return max_filter_level;
150 }
151
152 void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
153 {
154     VP8_COMMON *cm = &cpi->common;
155
156     int best_err = 0;
157     int filt_err = 0;
158     int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
159     int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
160     int filt_val;
161     int best_filt_val = cm->filter_level;
162
163     //  Make a copy of the unfiltered / processed recon buffer
164     //vp8_yv12_copy_frame_ptr( cm->frame_to_show, &cpi->last_frame_uf  );
165     vp8_yv12_copy_partial_frame_ptr(cm->frame_to_show, &cpi->last_frame_uf, 3);
166
167     if (cm->frame_type == KEY_FRAME)
168         cm->sharpness_level = 0;
169     else
170         cm->sharpness_level = cpi->oxcf.Sharpness;
171
172     // Start the search at the previous frame filter level unless it is now out of range.
173     if (cm->filter_level < min_filter_level)
174         cm->filter_level = min_filter_level;
175     else if (cm->filter_level > max_filter_level)
176         cm->filter_level = max_filter_level;
177
178     filt_val = cm->filter_level;
179     best_filt_val = filt_val;
180
181     // Set up alternate filter values
182
183     // Get the err using the previous frame's filter value.
184     vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val, 0  , 3);
185     cm->last_frame_type = cm->frame_type;
186     cm->last_filter_type = cm->filter_type;
187     cm->last_sharpness_level = cm->sharpness_level;
188
189     best_err = vp8_calc_partial_ssl_err(sd, cm->frame_to_show, 3, IF_RTCD(&cpi->rtcd.variance));
190
191     //  Re-instate the unfiltered frame
192     vp8_yv12_copy_partial_frame_ptr(&cpi->last_frame_uf, cm->frame_to_show, 3);
193
194     filt_val -= (1 + ((filt_val > 10) ? 1 : 0));
195
196     // Search lower filter levels
197     while (filt_val >= min_filter_level)
198     {
199         // Apply the loop filter
200         vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val, 0, 3);
201         cm->last_frame_type = cm->frame_type;
202         cm->last_filter_type = cm->filter_type;
203         cm->last_sharpness_level = cm->sharpness_level;
204
205         // Get the err for filtered frame
206         filt_err = vp8_calc_partial_ssl_err(sd, cm->frame_to_show, 3, IF_RTCD(&cpi->rtcd.variance));
207
208
209         //  Re-instate the unfiltered frame
210         vp8_yv12_copy_partial_frame_ptr(&cpi->last_frame_uf, cm->frame_to_show, 3);
211
212
213         // Update the best case record or exit loop.
214         if (filt_err < best_err)
215         {
216             best_err = filt_err;
217             best_filt_val = filt_val;
218         }
219         else
220             break;
221
222         // Adjust filter level
223         filt_val -= (1 + ((filt_val > 10) ? 1 : 0));
224     }
225
226     // Search up (note that we have already done filt_val = cm->filter_level)
227     filt_val = cm->filter_level + (1 + ((filt_val > 10) ? 1 : 0));
228
229     if (best_filt_val == cm->filter_level)
230     {
231         // Resist raising filter level for very small gains
232         best_err -= (best_err >> 10);
233
234         while (filt_val < max_filter_level)
235         {
236             // Apply the loop filter
237             vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val, 0, 3);
238             cm->last_frame_type = cm->frame_type;
239             cm->last_filter_type = cm->filter_type;
240             cm->last_sharpness_level = cm->sharpness_level;
241
242             // Get the err for filtered frame
243             filt_err = vp8_calc_partial_ssl_err(sd, cm->frame_to_show, 3, IF_RTCD(&cpi->rtcd.variance));
244
245             //  Re-instate the unfiltered frame
246             vp8_yv12_copy_partial_frame_ptr(&cpi->last_frame_uf, cm->frame_to_show, 3);
247
248             // Update the best case record or exit loop.
249             if (filt_err < best_err)
250             {
251                 // Do not raise filter level if improvement is < 1 part in 4096
252                 best_err = filt_err - (filt_err >> 10);
253
254                 best_filt_val = filt_val;
255             }
256             else
257                 break;
258
259             // Adjust filter level
260             filt_val += (1 + ((filt_val > 10) ? 1 : 0));
261         }
262     }
263
264     cm->filter_level = best_filt_val;
265
266     if (cm->filter_level < min_filter_level)
267         cm->filter_level = min_filter_level;
268
269     if (cm->filter_level > max_filter_level)
270         cm->filter_level = max_filter_level;
271 }
272
273 // Stub function for now Alt LF not used
274 void vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val)
275 {
276     MACROBLOCKD *mbd = &cpi->mb.e_mbd;
277     (void) filt_val;
278
279     mbd->segment_feature_data[MB_LVL_ALT_LF][0] = cpi->segment_feature_data[MB_LVL_ALT_LF][0];
280     mbd->segment_feature_data[MB_LVL_ALT_LF][1] = cpi->segment_feature_data[MB_LVL_ALT_LF][1];
281     mbd->segment_feature_data[MB_LVL_ALT_LF][2] = cpi->segment_feature_data[MB_LVL_ALT_LF][2];
282     mbd->segment_feature_data[MB_LVL_ALT_LF][3] = cpi->segment_feature_data[MB_LVL_ALT_LF][3];
283 }
284
285 void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
286 {
287     VP8_COMMON *cm = &cpi->common;
288
289     int best_err = 0;
290     int filt_err = 0;
291     int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
292     int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
293
294     int filter_step;
295     int filt_high = 0;
296     int filt_mid = cm->filter_level;      // Start search at previous frame filter level
297     int filt_low = 0;
298     int filt_best;
299     int filt_direction = 0;
300
301     int Bias = 0;                       // Bias against raising loop filter and in favour of lowering it
302
303     //  Make a copy of the unfiltered / processed recon buffer
304 #if HAVE_ARMV7
305 #if CONFIG_RUNTIME_CPU_DETECT
306     if (cm->rtcd.flags & HAS_NEON)
307 #endif
308     {
309         vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(cm->frame_to_show, &cpi->last_frame_uf);
310     }
311 #if CONFIG_RUNTIME_CPU_DETECT
312     else
313 #endif
314 #endif
315 #if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT
316     {
317         vp8_yv12_copy_frame_ptr(cm->frame_to_show, &cpi->last_frame_uf);
318     }
319 #endif
320
321     if (cm->frame_type == KEY_FRAME)
322         cm->sharpness_level = 0;
323     else
324         cm->sharpness_level = cpi->oxcf.Sharpness;
325
326     // Start the search at the previous frame filter level unless it is now out of range.
327     filt_mid = cm->filter_level;
328
329     if (filt_mid < min_filter_level)
330         filt_mid = min_filter_level;
331     else if (filt_mid > max_filter_level)
332         filt_mid = max_filter_level;
333
334     // Define the initial step size
335     filter_step = (filt_mid < 16) ? 4 : filt_mid / 4;
336
337     // Get baseline error score
338     vp8cx_set_alt_lf_level(cpi, filt_mid);
339     vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_mid, 0);
340     cm->last_frame_type = cm->frame_type;
341     cm->last_filter_type = cm->filter_type;
342     cm->last_sharpness_level = cm->sharpness_level;
343
344     best_err = vp8_calc_ss_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
345     filt_best = filt_mid;
346
347     //  Re-instate the unfiltered frame
348 #if HAVE_ARMV7
349 #if CONFIG_RUNTIME_CPU_DETECT
350     if (cm->rtcd.flags & HAS_NEON)
351 #endif
352     {
353         vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(&cpi->last_frame_uf, cm->frame_to_show);
354     }
355 #if CONFIG_RUNTIME_CPU_DETECT
356     else
357 #endif
358 #endif
359 #if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT
360     {
361         vp8_yv12_copy_frame_yonly_ptr(&cpi->last_frame_uf, cm->frame_to_show);
362     }
363 #endif
364
365     while (filter_step > 0)
366     {
367         Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step; //PGW change 12/12/06 for small images
368
369         // jbb chg: 20100118 - in sections with lots of new material coming in don't bias as much to a low filter value
370         if (cpi->twopass.section_intra_rating < 20)
371             Bias = Bias * cpi->twopass.section_intra_rating / 20;
372
373         filt_high = ((filt_mid + filter_step) > max_filter_level) ? max_filter_level : (filt_mid + filter_step);
374         filt_low = ((filt_mid - filter_step) < min_filter_level) ? min_filter_level : (filt_mid - filter_step);
375
376         if ((filt_direction <= 0) && (filt_low != filt_mid))
377         {
378             // Get Low filter error score
379             vp8cx_set_alt_lf_level(cpi, filt_low);
380             vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_low, 0);
381             cm->last_frame_type = cm->frame_type;
382             cm->last_filter_type = cm->filter_type;
383             cm->last_sharpness_level = cm->sharpness_level;
384
385             filt_err = vp8_calc_ss_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
386
387             //  Re-instate the unfiltered frame
388 #if HAVE_ARMV7
389 #if CONFIG_RUNTIME_CPU_DETECT
390             if (cm->rtcd.flags & HAS_NEON)
391 #endif
392             {
393                 vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(&cpi->last_frame_uf, cm->frame_to_show);
394             }
395 #if CONFIG_RUNTIME_CPU_DETECT
396             else
397 #endif
398 #endif
399 #if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT
400             {
401                 vp8_yv12_copy_frame_yonly_ptr(&cpi->last_frame_uf, cm->frame_to_show);
402             }
403 #endif
404
405             // If value is close to the best so far then bias towards a lower loop filter value.
406             if ((filt_err - Bias) < best_err)
407             {
408                 // Was it actually better than the previous best?
409                 if (filt_err < best_err)
410                     best_err = filt_err;
411
412                 filt_best = filt_low;
413             }
414         }
415
416         // Now look at filt_high
417         if ((filt_direction >= 0) && (filt_high != filt_mid))
418         {
419             vp8cx_set_alt_lf_level(cpi, filt_high);
420             vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_high, 0);
421             cm->last_frame_type = cm->frame_type;
422             cm->last_filter_type = cm->filter_type;
423             cm->last_sharpness_level = cm->sharpness_level;
424
425             filt_err = vp8_calc_ss_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
426
427             //  Re-instate the unfiltered frame
428 #if HAVE_ARMV7
429 #if CONFIG_RUNTIME_CPU_DETECT
430             if (cm->rtcd.flags & HAS_NEON)
431 #endif
432             {
433                 vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(&cpi->last_frame_uf, cm->frame_to_show);
434             }
435 #if CONFIG_RUNTIME_CPU_DETECT
436             else
437 #endif
438 #endif
439 #if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT
440             {
441                 vp8_yv12_copy_frame_yonly_ptr(&cpi->last_frame_uf, cm->frame_to_show);
442             }
443 #endif
444
445             // Was it better than the previous best?
446             if (filt_err < (best_err - Bias))
447             {
448                 best_err = filt_err;
449                 filt_best = filt_high;
450             }
451         }
452
453         // Half the step distance if the best filter value was the same as last time
454         if (filt_best == filt_mid)
455         {
456             filter_step = filter_step / 2;
457             filt_direction = 0;
458         }
459         else
460         {
461             filt_direction = (filt_best < filt_mid) ? -1 : 1;
462             filt_mid = filt_best;
463         }
464     }
465
466     cm->filter_level = filt_best;
467 }