1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/*
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan *
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Use of this source code is governed by a BSD-style license
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  that can be found in the LICENSE file in the root of the source
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  tree. An additional intellectual property rights grant can be found
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  in the file PATENTS.  All contributing project authors may
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  be found in the AUTHORS file in the root of the source tree.
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vpx_scale_rtcd.h"
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp8/common/onyxc_int.h"
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "onyx_int.h"
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "quantize.h"
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_mem/vpx_mem.h"
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_scale/vpx_scale.h"
18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp8/common/alloccommon.h"
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp8/common/loopfilter.h"
20233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if ARCH_ARM
21233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_ports/arm.h"
22233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
23233d2500723e5594f3e7c70896ffeeef32b9c950ywan
24233d2500723e5594f3e7c70896ffeeef32b9c950ywanextern int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest);
25233d2500723e5594f3e7c70896ffeeef32b9c950ywan
26233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp8_yv12_copy_partial_frame_c(YV12_BUFFER_CONFIG *src_ybc,
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   YV12_BUFFER_CONFIG *dst_ybc)
28233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
29233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned char *src_y, *dst_y;
30233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int yheight;
31233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int ystride;
32233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int yoffset;
33233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int linestocopy;
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan    yheight  = src_ybc->y_height;
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ystride  = src_ybc->y_stride;
37233d2500723e5594f3e7c70896ffeeef32b9c950ywan
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* number of MB rows to use in partial filtering */
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan    linestocopy = (yheight >> 4) / PARTIAL_FRAME_FRACTION;
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan    linestocopy = linestocopy ? linestocopy << 4 : 16;     /* 16 lines per MB */
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Copy extra 4 so that full filter context is available if filtering done
43233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * on the copied partial frame and not original. Partial filter does mb
44233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * filtering for top row also, which can modify3 pixels above.
45233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan    linestocopy += 4;
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* partial image starts at ~middle of frame (macroblock border)*/
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan    yoffset  = ystride * (((yheight >> 5) * 16) - 4);
49233d2500723e5594f3e7c70896ffeeef32b9c950ywan    src_y = src_ybc->y_buffer + yoffset;
50233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dst_y = dst_ybc->y_buffer + yoffset;
51233d2500723e5594f3e7c70896ffeeef32b9c950ywan
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_memcpy(dst_y, src_y, ystride * linestocopy);
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan
55233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int calc_partial_ssl_err(YV12_BUFFER_CONFIG *source,
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                YV12_BUFFER_CONFIG *dest)
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
58233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int i, j;
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int Total = 0;
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int srcoffset, dstoffset;
61233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned char *src = source->y_buffer;
62233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned char *dst = dest->y_buffer;
63233d2500723e5594f3e7c70896ffeeef32b9c950ywan
64233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int linestocopy;
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* number of MB rows to use in partial filtering */
67233d2500723e5594f3e7c70896ffeeef32b9c950ywan    linestocopy = (source->y_height >> 4) / PARTIAL_FRAME_FRACTION;
68233d2500723e5594f3e7c70896ffeeef32b9c950ywan    linestocopy = linestocopy ? linestocopy << 4 : 16;     /* 16 lines per MB */
69233d2500723e5594f3e7c70896ffeeef32b9c950ywan
70233d2500723e5594f3e7c70896ffeeef32b9c950ywan
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* partial image starts at ~middle of frame (macroblock border)*/
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan    srcoffset = source->y_stride * ((dest->y_height >> 5) * 16);
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dstoffset = dest->y_stride   * ((dest->y_height >> 5) * 16);
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan
75233d2500723e5594f3e7c70896ffeeef32b9c950ywan    src += srcoffset;
76233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dst += dstoffset;
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Loop through the Y plane raw and reconstruction data summing
79233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * (square differences)
80233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < linestocopy; i += 16)
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (j = 0; j < source->y_width; j += 16)
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan            unsigned int sse;
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Total += vp8_mse16x16(src + j, source->y_stride,
87233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                     dst + j, dest->y_stride,
88233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                     &sse);
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
90233d2500723e5594f3e7c70896ffeeef32b9c950ywan
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan        src += 16 * source->y_stride;
92233d2500723e5594f3e7c70896ffeeef32b9c950ywan        dst += 16 * dest->y_stride;
93233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
94233d2500723e5594f3e7c70896ffeeef32b9c950ywan
95233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return Total;
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
97233d2500723e5594f3e7c70896ffeeef32b9c950ywan
98233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Enforce a minimum filter level based upon baseline Q */
99233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int get_min_filter_level(VP8_COMP *cpi, int base_qindex)
100233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int min_filter_level;
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan
103233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->source_alt_ref_active && cpi->common.refresh_golden_frame &&
104233d2500723e5594f3e7c70896ffeeef32b9c950ywan        !cpi->common.refresh_alt_ref_frame)
105233d2500723e5594f3e7c70896ffeeef32b9c950ywan        min_filter_level = 0;
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (base_qindex <= 6)
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan            min_filter_level = 0;
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (base_qindex <= 16)
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan            min_filter_level = 1;
112233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan            min_filter_level = (base_qindex / 8);
114233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return min_filter_level;
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan
119233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Enforce a maximum filter level based upon baseline Q */
120233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int get_max_filter_level(VP8_COMP *cpi, int base_qindex)
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* PGW August 2006: Highest filter values almost always a bad idea */
123233d2500723e5594f3e7c70896ffeeef32b9c950ywan
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* jbb chg: 20100118 - not so any more with this overquant stuff allow
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * high values with lots of intra coming in.
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int max_filter_level = MAX_LOOP_FILTER;
128233d2500723e5594f3e7c70896ffeeef32b9c950ywan    (void)base_qindex;
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan
130233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->twopass.section_intra_rating > 8)
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan        max_filter_level = MAX_LOOP_FILTER * 3 / 4;
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return max_filter_level;
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan
136233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
138233d2500723e5594f3e7c70896ffeeef32b9c950ywan    VP8_COMMON *cm = &cpi->common;
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int best_err = 0;
141233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int filt_err = 0;
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
143233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int filt_val;
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int best_filt_val = cm->filter_level;
146233d2500723e5594f3e7c70896ffeeef32b9c950ywan    YV12_BUFFER_CONFIG * saved_frame = cm->frame_to_show;
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan
148233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Replace unfiltered frame buffer with a new one */
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cm->frame_to_show = &cpi->pick_lf_lvl_frame;
150233d2500723e5594f3e7c70896ffeeef32b9c950ywan
151233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->frame_type == KEY_FRAME)
152233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->sharpness_level = 0;
153233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
154233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->sharpness_level = cpi->oxcf.Sharpness;
155233d2500723e5594f3e7c70896ffeeef32b9c950ywan
156233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->sharpness_level != cm->last_sharpness_level)
157233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
158233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vp8_loop_filter_update_sharpness(&cm->lf_info, cm->sharpness_level);
159233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->last_sharpness_level = cm->sharpness_level;
160233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
161233d2500723e5594f3e7c70896ffeeef32b9c950ywan
162233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Start the search at the previous frame filter level unless it is
163233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * now out of range.
164233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
165233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->filter_level < min_filter_level)
166233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->filter_level = min_filter_level;
167233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (cm->filter_level > max_filter_level)
168233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->filter_level = max_filter_level;
169233d2500723e5594f3e7c70896ffeeef32b9c950ywan
170233d2500723e5594f3e7c70896ffeeef32b9c950ywan    filt_val = cm->filter_level;
171233d2500723e5594f3e7c70896ffeeef32b9c950ywan    best_filt_val = filt_val;
172233d2500723e5594f3e7c70896ffeeef32b9c950ywan
173233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Get the err using the previous frame's filter value. */
174233d2500723e5594f3e7c70896ffeeef32b9c950ywan
175233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Copy the unfiltered / processed recon buffer to the new buffer */
176233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp8_yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
177233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
178233d2500723e5594f3e7c70896ffeeef32b9c950ywan
179233d2500723e5594f3e7c70896ffeeef32b9c950ywan    best_err = calc_partial_ssl_err(sd, cm->frame_to_show);
180233d2500723e5594f3e7c70896ffeeef32b9c950ywan
181233d2500723e5594f3e7c70896ffeeef32b9c950ywan    filt_val -= 1 + (filt_val > 10);
182233d2500723e5594f3e7c70896ffeeef32b9c950ywan
183233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Search lower filter levels */
184233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (filt_val >= min_filter_level)
185233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
186233d2500723e5594f3e7c70896ffeeef32b9c950ywan        /* Apply the loop filter */
187233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vp8_yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
188233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
189233d2500723e5594f3e7c70896ffeeef32b9c950ywan
190233d2500723e5594f3e7c70896ffeeef32b9c950ywan        /* Get the err for filtered frame */
191233d2500723e5594f3e7c70896ffeeef32b9c950ywan        filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
192233d2500723e5594f3e7c70896ffeeef32b9c950ywan
193233d2500723e5594f3e7c70896ffeeef32b9c950ywan        /* Update the best case record or exit loop. */
194233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (filt_err < best_err)
195233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
196233d2500723e5594f3e7c70896ffeeef32b9c950ywan            best_err = filt_err;
197233d2500723e5594f3e7c70896ffeeef32b9c950ywan            best_filt_val = filt_val;
198233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
199233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
200233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
201233d2500723e5594f3e7c70896ffeeef32b9c950ywan
202233d2500723e5594f3e7c70896ffeeef32b9c950ywan        /* Adjust filter level */
203233d2500723e5594f3e7c70896ffeeef32b9c950ywan        filt_val -= 1 + (filt_val > 10);
204233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
205233d2500723e5594f3e7c70896ffeeef32b9c950ywan
206233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Search up (note that we have already done filt_val = cm->filter_level) */
207233d2500723e5594f3e7c70896ffeeef32b9c950ywan    filt_val = cm->filter_level + 1 + (filt_val > 10);
208233d2500723e5594f3e7c70896ffeeef32b9c950ywan
209233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (best_filt_val == cm->filter_level)
210233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
211233d2500723e5594f3e7c70896ffeeef32b9c950ywan        /* Resist raising filter level for very small gains */
212233d2500723e5594f3e7c70896ffeeef32b9c950ywan        best_err -= (best_err >> 10);
213233d2500723e5594f3e7c70896ffeeef32b9c950ywan
214233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (filt_val < max_filter_level)
215233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
216233d2500723e5594f3e7c70896ffeeef32b9c950ywan            /* Apply the loop filter */
217233d2500723e5594f3e7c70896ffeeef32b9c950ywan            vp8_yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
218233d2500723e5594f3e7c70896ffeeef32b9c950ywan
219233d2500723e5594f3e7c70896ffeeef32b9c950ywan            vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
220233d2500723e5594f3e7c70896ffeeef32b9c950ywan
221233d2500723e5594f3e7c70896ffeeef32b9c950ywan            /* Get the err for filtered frame */
222233d2500723e5594f3e7c70896ffeeef32b9c950ywan            filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
223233d2500723e5594f3e7c70896ffeeef32b9c950ywan
224233d2500723e5594f3e7c70896ffeeef32b9c950ywan            /* Update the best case record or exit loop. */
225233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (filt_err < best_err)
226233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
227233d2500723e5594f3e7c70896ffeeef32b9c950ywan                /* Do not raise filter level if improvement is < 1 part
228233d2500723e5594f3e7c70896ffeeef32b9c950ywan                 * in 4096
229233d2500723e5594f3e7c70896ffeeef32b9c950ywan                 */
230233d2500723e5594f3e7c70896ffeeef32b9c950ywan                best_err = filt_err - (filt_err >> 10);
231233d2500723e5594f3e7c70896ffeeef32b9c950ywan
232233d2500723e5594f3e7c70896ffeeef32b9c950ywan                best_filt_val = filt_val;
233233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
234233d2500723e5594f3e7c70896ffeeef32b9c950ywan            else
235233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
236233d2500723e5594f3e7c70896ffeeef32b9c950ywan
237233d2500723e5594f3e7c70896ffeeef32b9c950ywan            /* Adjust filter level */
238233d2500723e5594f3e7c70896ffeeef32b9c950ywan            filt_val += 1 + (filt_val > 10);
239233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
240233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
241233d2500723e5594f3e7c70896ffeeef32b9c950ywan
242233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cm->filter_level = best_filt_val;
243233d2500723e5594f3e7c70896ffeeef32b9c950ywan
244233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->filter_level < min_filter_level)
245233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->filter_level = min_filter_level;
246233d2500723e5594f3e7c70896ffeeef32b9c950ywan
247233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->filter_level > max_filter_level)
248233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->filter_level = max_filter_level;
249233d2500723e5594f3e7c70896ffeeef32b9c950ywan
250233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* restore unfiltered frame pointer */
251233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cm->frame_to_show = saved_frame;
252233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
253233d2500723e5594f3e7c70896ffeeef32b9c950ywan
254233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Stub function for now Alt LF not used */
255233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val)
256233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
257233d2500723e5594f3e7c70896ffeeef32b9c950ywan    MACROBLOCKD *mbd = &cpi->mb.e_mbd;
258233d2500723e5594f3e7c70896ffeeef32b9c950ywan    (void) filt_val;
259233d2500723e5594f3e7c70896ffeeef32b9c950ywan
260233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mbd->segment_feature_data[MB_LVL_ALT_LF][0] = cpi->segment_feature_data[MB_LVL_ALT_LF][0];
261233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mbd->segment_feature_data[MB_LVL_ALT_LF][1] = cpi->segment_feature_data[MB_LVL_ALT_LF][1];
262233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mbd->segment_feature_data[MB_LVL_ALT_LF][2] = cpi->segment_feature_data[MB_LVL_ALT_LF][2];
263233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mbd->segment_feature_data[MB_LVL_ALT_LF][3] = cpi->segment_feature_data[MB_LVL_ALT_LF][3];
264233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
265233d2500723e5594f3e7c70896ffeeef32b9c950ywan
266233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
267233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
268233d2500723e5594f3e7c70896ffeeef32b9c950ywan    VP8_COMMON *cm = &cpi->common;
269233d2500723e5594f3e7c70896ffeeef32b9c950ywan
270233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int best_err = 0;
271233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int filt_err = 0;
272233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
273233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
274233d2500723e5594f3e7c70896ffeeef32b9c950ywan
275233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int filter_step;
276233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int filt_high = 0;
277233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Start search at previous frame filter level */
278233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int filt_mid = cm->filter_level;
279233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int filt_low = 0;
280233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int filt_best;
281233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int filt_direction = 0;
282233d2500723e5594f3e7c70896ffeeef32b9c950ywan
283233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Bias against raising loop filter and in favor of lowering it */
284233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int Bias = 0;
285233d2500723e5594f3e7c70896ffeeef32b9c950ywan
286233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int ss_err[MAX_LOOP_FILTER + 1];
287233d2500723e5594f3e7c70896ffeeef32b9c950ywan
288233d2500723e5594f3e7c70896ffeeef32b9c950ywan    YV12_BUFFER_CONFIG * saved_frame = cm->frame_to_show;
289233d2500723e5594f3e7c70896ffeeef32b9c950ywan
290233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_memset(ss_err, 0, sizeof(ss_err));
291233d2500723e5594f3e7c70896ffeeef32b9c950ywan
292233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Replace unfiltered frame buffer with a new one */
293233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cm->frame_to_show = &cpi->pick_lf_lvl_frame;
294233d2500723e5594f3e7c70896ffeeef32b9c950ywan
295233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->frame_type == KEY_FRAME)
296233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->sharpness_level = 0;
297233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
298233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cm->sharpness_level = cpi->oxcf.Sharpness;
299233d2500723e5594f3e7c70896ffeeef32b9c950ywan
300233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Start the search at the previous frame filter level unless it is
301233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * now out of range.
302233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
303233d2500723e5594f3e7c70896ffeeef32b9c950ywan    filt_mid = cm->filter_level;
304233d2500723e5594f3e7c70896ffeeef32b9c950ywan
305233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (filt_mid < min_filter_level)
306233d2500723e5594f3e7c70896ffeeef32b9c950ywan        filt_mid = min_filter_level;
307233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (filt_mid > max_filter_level)
308233d2500723e5594f3e7c70896ffeeef32b9c950ywan        filt_mid = max_filter_level;
309233d2500723e5594f3e7c70896ffeeef32b9c950ywan
310233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Define the initial step size */
311233d2500723e5594f3e7c70896ffeeef32b9c950ywan    filter_step = (filt_mid < 16) ? 4 : filt_mid / 4;
312233d2500723e5594f3e7c70896ffeeef32b9c950ywan
313233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Get baseline error score */
314233d2500723e5594f3e7c70896ffeeef32b9c950ywan
315233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Copy the unfiltered / processed recon buffer to the new buffer */
316233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
317233d2500723e5594f3e7c70896ffeeef32b9c950ywan
318233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp8cx_set_alt_lf_level(cpi, filt_mid);
319233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_mid);
320233d2500723e5594f3e7c70896ffeeef32b9c950ywan
321233d2500723e5594f3e7c70896ffeeef32b9c950ywan    best_err = vp8_calc_ss_err(sd, cm->frame_to_show);
322233d2500723e5594f3e7c70896ffeeef32b9c950ywan
323233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ss_err[filt_mid] = best_err;
324233d2500723e5594f3e7c70896ffeeef32b9c950ywan
325233d2500723e5594f3e7c70896ffeeef32b9c950ywan    filt_best = filt_mid;
326233d2500723e5594f3e7c70896ffeeef32b9c950ywan
327233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (filter_step > 0)
328233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
329233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step;
330233d2500723e5594f3e7c70896ffeeef32b9c950ywan
331233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (cpi->twopass.section_intra_rating < 20)
332233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Bias = Bias * cpi->twopass.section_intra_rating / 20;
333233d2500723e5594f3e7c70896ffeeef32b9c950ywan
334233d2500723e5594f3e7c70896ffeeef32b9c950ywan        filt_high = ((filt_mid + filter_step) > max_filter_level) ? max_filter_level : (filt_mid + filter_step);
335233d2500723e5594f3e7c70896ffeeef32b9c950ywan        filt_low = ((filt_mid - filter_step) < min_filter_level) ? min_filter_level : (filt_mid - filter_step);
336233d2500723e5594f3e7c70896ffeeef32b9c950ywan
337233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((filt_direction <= 0) && (filt_low != filt_mid))
338233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
339233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if(ss_err[filt_low] == 0)
340233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
341233d2500723e5594f3e7c70896ffeeef32b9c950ywan                /* Get Low filter error score */
342233d2500723e5594f3e7c70896ffeeef32b9c950ywan                vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
343233d2500723e5594f3e7c70896ffeeef32b9c950ywan                vp8cx_set_alt_lf_level(cpi, filt_low);
344233d2500723e5594f3e7c70896ffeeef32b9c950ywan                vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_low);
345233d2500723e5594f3e7c70896ffeeef32b9c950ywan
346233d2500723e5594f3e7c70896ffeeef32b9c950ywan                filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
347233d2500723e5594f3e7c70896ffeeef32b9c950ywan                ss_err[filt_low] = filt_err;
348233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
349233d2500723e5594f3e7c70896ffeeef32b9c950ywan            else
350233d2500723e5594f3e7c70896ffeeef32b9c950ywan                filt_err = ss_err[filt_low];
351233d2500723e5594f3e7c70896ffeeef32b9c950ywan
352233d2500723e5594f3e7c70896ffeeef32b9c950ywan            /* If value is close to the best so far then bias towards a
353233d2500723e5594f3e7c70896ffeeef32b9c950ywan             * lower loop filter value.
354233d2500723e5594f3e7c70896ffeeef32b9c950ywan             */
355233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((filt_err - Bias) < best_err)
356233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
357233d2500723e5594f3e7c70896ffeeef32b9c950ywan                /* Was it actually better than the previous best? */
358233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (filt_err < best_err)
359233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    best_err = filt_err;
360233d2500723e5594f3e7c70896ffeeef32b9c950ywan
361233d2500723e5594f3e7c70896ffeeef32b9c950ywan                filt_best = filt_low;
362233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
363233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
364233d2500723e5594f3e7c70896ffeeef32b9c950ywan
365233d2500723e5594f3e7c70896ffeeef32b9c950ywan        /* Now look at filt_high */
366233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((filt_direction >= 0) && (filt_high != filt_mid))
367233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
368233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if(ss_err[filt_high] == 0)
369233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
370233d2500723e5594f3e7c70896ffeeef32b9c950ywan                vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
371233d2500723e5594f3e7c70896ffeeef32b9c950ywan                vp8cx_set_alt_lf_level(cpi, filt_high);
372233d2500723e5594f3e7c70896ffeeef32b9c950ywan                vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_high);
373233d2500723e5594f3e7c70896ffeeef32b9c950ywan
374233d2500723e5594f3e7c70896ffeeef32b9c950ywan                filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
375233d2500723e5594f3e7c70896ffeeef32b9c950ywan                ss_err[filt_high] = filt_err;
376233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
377233d2500723e5594f3e7c70896ffeeef32b9c950ywan            else
378233d2500723e5594f3e7c70896ffeeef32b9c950ywan                filt_err = ss_err[filt_high];
379233d2500723e5594f3e7c70896ffeeef32b9c950ywan
380233d2500723e5594f3e7c70896ffeeef32b9c950ywan            /* Was it better than the previous best? */
381233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (filt_err < (best_err - Bias))
382233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
383233d2500723e5594f3e7c70896ffeeef32b9c950ywan                best_err = filt_err;
384233d2500723e5594f3e7c70896ffeeef32b9c950ywan                filt_best = filt_high;
385233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
386233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
387233d2500723e5594f3e7c70896ffeeef32b9c950ywan
388233d2500723e5594f3e7c70896ffeeef32b9c950ywan        /* Half the step distance if the best filter value was the same
389233d2500723e5594f3e7c70896ffeeef32b9c950ywan         * as last time
390233d2500723e5594f3e7c70896ffeeef32b9c950ywan         */
391233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (filt_best == filt_mid)
392233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
393233d2500723e5594f3e7c70896ffeeef32b9c950ywan            filter_step = filter_step / 2;
394233d2500723e5594f3e7c70896ffeeef32b9c950ywan            filt_direction = 0;
395233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
396233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
397233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
398233d2500723e5594f3e7c70896ffeeef32b9c950ywan            filt_direction = (filt_best < filt_mid) ? -1 : 1;
399233d2500723e5594f3e7c70896ffeeef32b9c950ywan            filt_mid = filt_best;
400233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
401233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
402233d2500723e5594f3e7c70896ffeeef32b9c950ywan
403233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cm->filter_level = filt_best;
404233d2500723e5594f3e7c70896ffeeef32b9c950ywan
405233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* restore unfiltered frame pointer */
406233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cm->frame_to_show = saved_frame;
407233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
408