• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "vpx_ports/config.h"
13 #include "loopfilter.h"
14 #include "onyxc_int.h"
15 
16 typedef unsigned char uc;
17 
18 
19 prototype_loopfilter(vp8_loop_filter_horizontal_edge_c);
20 prototype_loopfilter(vp8_loop_filter_vertical_edge_c);
21 prototype_loopfilter(vp8_mbloop_filter_horizontal_edge_c);
22 prototype_loopfilter(vp8_mbloop_filter_vertical_edge_c);
23 prototype_loopfilter(vp8_loop_filter_simple_horizontal_edge_c);
24 prototype_loopfilter(vp8_loop_filter_simple_vertical_edge_c);
25 
26 /* Horizontal MB filtering */
vp8_loop_filter_mbh_c(unsigned char * y_ptr,unsigned char * u_ptr,unsigned char * v_ptr,int y_stride,int uv_stride,loop_filter_info * lfi,int simpler_lpf)27 void vp8_loop_filter_mbh_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
28                            int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
29 {
30     (void) simpler_lpf;
31     vp8_mbloop_filter_horizontal_edge_c(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->thr, 2);
32 
33     if (u_ptr)
34         vp8_mbloop_filter_horizontal_edge_c(u_ptr, uv_stride, lfi->mbflim, lfi->lim, lfi->thr, 1);
35 
36     if (v_ptr)
37         vp8_mbloop_filter_horizontal_edge_c(v_ptr, uv_stride, lfi->mbflim, lfi->lim, lfi->thr, 1);
38 }
39 
vp8_loop_filter_mbhs_c(unsigned char * y_ptr,unsigned char * u_ptr,unsigned char * v_ptr,int y_stride,int uv_stride,loop_filter_info * lfi,int simpler_lpf)40 void vp8_loop_filter_mbhs_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
41                             int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
42 {
43     (void) u_ptr;
44     (void) v_ptr;
45     (void) uv_stride;
46     (void) simpler_lpf;
47     vp8_loop_filter_simple_horizontal_edge_c(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->thr, 2);
48 }
49 
50 /* Vertical MB Filtering */
vp8_loop_filter_mbv_c(unsigned char * y_ptr,unsigned char * u_ptr,unsigned char * v_ptr,int y_stride,int uv_stride,loop_filter_info * lfi,int simpler_lpf)51 void vp8_loop_filter_mbv_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
52                            int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
53 {
54     (void) simpler_lpf;
55     vp8_mbloop_filter_vertical_edge_c(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->thr, 2);
56 
57     if (u_ptr)
58         vp8_mbloop_filter_vertical_edge_c(u_ptr, uv_stride, lfi->mbflim, lfi->lim, lfi->thr, 1);
59 
60     if (v_ptr)
61         vp8_mbloop_filter_vertical_edge_c(v_ptr, uv_stride, lfi->mbflim, lfi->lim, lfi->thr, 1);
62 }
63 
vp8_loop_filter_mbvs_c(unsigned char * y_ptr,unsigned char * u_ptr,unsigned char * v_ptr,int y_stride,int uv_stride,loop_filter_info * lfi,int simpler_lpf)64 void vp8_loop_filter_mbvs_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
65                             int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
66 {
67     (void) u_ptr;
68     (void) v_ptr;
69     (void) uv_stride;
70     (void) simpler_lpf;
71     vp8_loop_filter_simple_vertical_edge_c(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->thr, 2);
72 }
73 
74 /* Horizontal B Filtering */
vp8_loop_filter_bh_c(unsigned char * y_ptr,unsigned char * u_ptr,unsigned char * v_ptr,int y_stride,int uv_stride,loop_filter_info * lfi,int simpler_lpf)75 void vp8_loop_filter_bh_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
76                           int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
77 {
78     (void) simpler_lpf;
79     vp8_loop_filter_horizontal_edge_c(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
80     vp8_loop_filter_horizontal_edge_c(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
81     vp8_loop_filter_horizontal_edge_c(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
82 
83     if (u_ptr)
84         vp8_loop_filter_horizontal_edge_c(u_ptr + 4 * uv_stride, uv_stride, lfi->flim, lfi->lim, lfi->thr, 1);
85 
86     if (v_ptr)
87         vp8_loop_filter_horizontal_edge_c(v_ptr + 4 * uv_stride, uv_stride, lfi->flim, lfi->lim, lfi->thr, 1);
88 }
89 
vp8_loop_filter_bhs_c(unsigned char * y_ptr,unsigned char * u_ptr,unsigned char * v_ptr,int y_stride,int uv_stride,loop_filter_info * lfi,int simpler_lpf)90 void vp8_loop_filter_bhs_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
91                            int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
92 {
93     (void) u_ptr;
94     (void) v_ptr;
95     (void) uv_stride;
96     (void) simpler_lpf;
97     vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
98     vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
99     vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
100 }
101 
102 /* Vertical B Filtering */
vp8_loop_filter_bv_c(unsigned char * y_ptr,unsigned char * u_ptr,unsigned char * v_ptr,int y_stride,int uv_stride,loop_filter_info * lfi,int simpler_lpf)103 void vp8_loop_filter_bv_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
104                           int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
105 {
106     (void) simpler_lpf;
107     vp8_loop_filter_vertical_edge_c(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
108     vp8_loop_filter_vertical_edge_c(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
109     vp8_loop_filter_vertical_edge_c(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
110 
111     if (u_ptr)
112         vp8_loop_filter_vertical_edge_c(u_ptr + 4, uv_stride, lfi->flim, lfi->lim, lfi->thr, 1);
113 
114     if (v_ptr)
115         vp8_loop_filter_vertical_edge_c(v_ptr + 4, uv_stride, lfi->flim, lfi->lim, lfi->thr, 1);
116 }
117 
vp8_loop_filter_bvs_c(unsigned char * y_ptr,unsigned char * u_ptr,unsigned char * v_ptr,int y_stride,int uv_stride,loop_filter_info * lfi,int simpler_lpf)118 void vp8_loop_filter_bvs_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
119                            int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
120 {
121     (void) u_ptr;
122     (void) v_ptr;
123     (void) uv_stride;
124     (void) simpler_lpf;
125     vp8_loop_filter_simple_vertical_edge_c(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
126     vp8_loop_filter_simple_vertical_edge_c(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
127     vp8_loop_filter_simple_vertical_edge_c(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
128 }
129 
vp8_init_loop_filter(VP8_COMMON * cm)130 void vp8_init_loop_filter(VP8_COMMON *cm)
131 {
132     loop_filter_info *lfi = cm->lf_info;
133     LOOPFILTERTYPE lft = cm->filter_type;
134     int sharpness_lvl = cm->sharpness_level;
135     int frame_type = cm->frame_type;
136     int i, j;
137 
138     int block_inside_limit = 0;
139     int HEVThresh;
140 
141     /* For each possible value for the loop filter fill out a "loop_filter_info" entry. */
142     for (i = 0; i <= MAX_LOOP_FILTER; i++)
143     {
144         int filt_lvl = i;
145 
146         if (frame_type == KEY_FRAME)
147         {
148             if (filt_lvl >= 40)
149                 HEVThresh = 2;
150             else if (filt_lvl >= 15)
151                 HEVThresh = 1;
152             else
153                 HEVThresh = 0;
154         }
155         else
156         {
157             if (filt_lvl >= 40)
158                 HEVThresh = 3;
159             else if (filt_lvl >= 20)
160                 HEVThresh = 2;
161             else if (filt_lvl >= 15)
162                 HEVThresh = 1;
163             else
164                 HEVThresh = 0;
165         }
166 
167         /* Set loop filter paramaeters that control sharpness. */
168         block_inside_limit = filt_lvl >> (sharpness_lvl > 0);
169         block_inside_limit = block_inside_limit >> (sharpness_lvl > 4);
170 
171         if (sharpness_lvl > 0)
172         {
173             if (block_inside_limit > (9 - sharpness_lvl))
174                 block_inside_limit = (9 - sharpness_lvl);
175         }
176 
177         if (block_inside_limit < 1)
178             block_inside_limit = 1;
179 
180         for (j = 0; j < 16; j++)
181         {
182             lfi[i].lim[j] = block_inside_limit;
183             lfi[i].mbflim[j] = filt_lvl + 2;
184             lfi[i].flim[j] = filt_lvl;
185             lfi[i].thr[j] = HEVThresh;
186         }
187 
188     }
189 
190     /* Set up the function pointers depending on the type of loop filtering selected */
191     if (lft == NORMAL_LOOPFILTER)
192     {
193         cm->lf_mbv = LF_INVOKE(&cm->rtcd.loopfilter, normal_mb_v);
194         cm->lf_bv  = LF_INVOKE(&cm->rtcd.loopfilter, normal_b_v);
195         cm->lf_mbh = LF_INVOKE(&cm->rtcd.loopfilter, normal_mb_h);
196         cm->lf_bh  = LF_INVOKE(&cm->rtcd.loopfilter, normal_b_h);
197     }
198     else
199     {
200         cm->lf_mbv = LF_INVOKE(&cm->rtcd.loopfilter, simple_mb_v);
201         cm->lf_bv  = LF_INVOKE(&cm->rtcd.loopfilter, simple_b_v);
202         cm->lf_mbh = LF_INVOKE(&cm->rtcd.loopfilter, simple_mb_h);
203         cm->lf_bh  = LF_INVOKE(&cm->rtcd.loopfilter, simple_b_h);
204     }
205 }
206 
207 /* Put vp8_init_loop_filter() in vp8dx_create_decompressor(). Only call vp8_frame_init_loop_filter() while decoding
208  * each frame. Check last_frame_type to skip the function most of times.
209  */
vp8_frame_init_loop_filter(loop_filter_info * lfi,int frame_type)210 void vp8_frame_init_loop_filter(loop_filter_info *lfi, int frame_type)
211 {
212     int HEVThresh;
213     int i, j;
214 
215     /* For each possible value for the loop filter fill out a "loop_filter_info" entry. */
216     for (i = 0; i <= MAX_LOOP_FILTER; i++)
217     {
218         int filt_lvl = i;
219 
220         if (frame_type == KEY_FRAME)
221         {
222             if (filt_lvl >= 40)
223                 HEVThresh = 2;
224             else if (filt_lvl >= 15)
225                 HEVThresh = 1;
226             else
227                 HEVThresh = 0;
228         }
229         else
230         {
231             if (filt_lvl >= 40)
232                 HEVThresh = 3;
233             else if (filt_lvl >= 20)
234                 HEVThresh = 2;
235             else if (filt_lvl >= 15)
236                 HEVThresh = 1;
237             else
238                 HEVThresh = 0;
239         }
240 
241         for (j = 0; j < 16; j++)
242         {
243             /*lfi[i].lim[j] = block_inside_limit;
244             lfi[i].mbflim[j] = filt_lvl+2;*/
245             /*lfi[i].flim[j] = filt_lvl;*/
246             lfi[i].thr[j] = HEVThresh;
247         }
248     }
249 }
250 
251 
vp8_adjust_mb_lf_value(MACROBLOCKD * mbd,int filter_level)252 int vp8_adjust_mb_lf_value(MACROBLOCKD *mbd, int filter_level)
253 {
254     MB_MODE_INFO *mbmi = &mbd->mode_info_context->mbmi;
255 
256     if (mbd->mode_ref_lf_delta_enabled)
257     {
258         /* Apply delta for reference frame */
259         filter_level += mbd->ref_lf_deltas[mbmi->ref_frame];
260 
261         /* Apply delta for mode */
262         if (mbmi->ref_frame == INTRA_FRAME)
263         {
264             /* Only the split mode BPRED has a further special case */
265             if (mbmi->mode == B_PRED)
266                 filter_level +=  mbd->mode_lf_deltas[0];
267         }
268         else
269         {
270             /* Zero motion mode */
271             if (mbmi->mode == ZEROMV)
272                 filter_level +=  mbd->mode_lf_deltas[1];
273 
274             /* Split MB motion mode */
275             else if (mbmi->mode == SPLITMV)
276                 filter_level +=  mbd->mode_lf_deltas[3];
277 
278             /* All other inter motion modes (Nearest, Near, New) */
279             else
280                 filter_level +=  mbd->mode_lf_deltas[2];
281         }
282 
283         /* Range check */
284         if (filter_level > MAX_LOOP_FILTER)
285             filter_level = MAX_LOOP_FILTER;
286         else if (filter_level < 0)
287             filter_level = 0;
288     }
289     return filter_level;
290 }
291 
292 
vp8_loop_filter_frame(VP8_COMMON * cm,MACROBLOCKD * mbd,int default_filt_lvl)293 void vp8_loop_filter_frame
294 (
295     VP8_COMMON *cm,
296     MACROBLOCKD *mbd,
297     int default_filt_lvl
298 )
299 {
300     YV12_BUFFER_CONFIG *post = cm->frame_to_show;
301     loop_filter_info *lfi = cm->lf_info;
302     FRAME_TYPE frame_type = cm->frame_type;
303 
304     int mb_row;
305     int mb_col;
306 
307 
308     int baseline_filter_level[MAX_MB_SEGMENTS];
309     int filter_level;
310     int alt_flt_enabled = mbd->segmentation_enabled;
311 
312     int i;
313     unsigned char *y_ptr, *u_ptr, *v_ptr;
314 
315     mbd->mode_info_context = cm->mi;          /* Point at base of Mb MODE_INFO list */
316 
317     /* Note the baseline filter values for each segment */
318     if (alt_flt_enabled)
319     {
320         for (i = 0; i < MAX_MB_SEGMENTS; i++)
321         {
322             /* Abs value */
323             if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
324                 baseline_filter_level[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
325             /* Delta Value */
326             else
327             {
328                 baseline_filter_level[i] = default_filt_lvl + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
329                 baseline_filter_level[i] = (baseline_filter_level[i] >= 0) ? ((baseline_filter_level[i] <= MAX_LOOP_FILTER) ? baseline_filter_level[i] : MAX_LOOP_FILTER) : 0;  /* Clamp to valid range */
330             }
331         }
332     }
333     else
334     {
335         for (i = 0; i < MAX_MB_SEGMENTS; i++)
336             baseline_filter_level[i] = default_filt_lvl;
337     }
338 
339     /* Initialize the loop filter for this frame. */
340     if ((cm->last_filter_type != cm->filter_type) || (cm->last_sharpness_level != cm->sharpness_level))
341         vp8_init_loop_filter(cm);
342     else if (frame_type != cm->last_frame_type)
343         vp8_frame_init_loop_filter(lfi, frame_type);
344 
345     /* Set up the buffer pointers */
346     y_ptr = post->y_buffer;
347     u_ptr = post->u_buffer;
348     v_ptr = post->v_buffer;
349 
350     /* vp8_filter each macro block */
351     for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
352     {
353         for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
354         {
355             int Segment = (alt_flt_enabled) ? mbd->mode_info_context->mbmi.segment_id : 0;
356 
357             filter_level = baseline_filter_level[Segment];
358 
359             /* Distance of Mb to the various image edges.
360              * These specified to 8th pel as they are always compared to values that are in 1/8th pel units
361              * Apply any context driven MB level adjustment
362              */
363             filter_level = vp8_adjust_mb_lf_value(mbd, filter_level);
364 
365             if (filter_level)
366             {
367                 if (mb_col > 0)
368                     cm->lf_mbv(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
369 
370                 if (mbd->mode_info_context->mbmi.dc_diff > 0)
371                     cm->lf_bv(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
372 
373                 /* don't apply across umv border */
374                 if (mb_row > 0)
375                     cm->lf_mbh(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
376 
377                 if (mbd->mode_info_context->mbmi.dc_diff > 0)
378                     cm->lf_bh(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
379             }
380 
381             y_ptr += 16;
382             u_ptr += 8;
383             v_ptr += 8;
384 
385             mbd->mode_info_context++;     /* step to next MB */
386         }
387 
388         y_ptr += post->y_stride  * 16 - post->y_width;
389         u_ptr += post->uv_stride *  8 - post->uv_width;
390         v_ptr += post->uv_stride *  8 - post->uv_width;
391 
392         mbd->mode_info_context++;         /* Skip border mb */
393     }
394 }
395 
396 
vp8_loop_filter_frame_yonly(VP8_COMMON * cm,MACROBLOCKD * mbd,int default_filt_lvl,int sharpness_lvl)397 void vp8_loop_filter_frame_yonly
398 (
399     VP8_COMMON *cm,
400     MACROBLOCKD *mbd,
401     int default_filt_lvl,
402     int sharpness_lvl
403 )
404 {
405     YV12_BUFFER_CONFIG *post = cm->frame_to_show;
406 
407     int i;
408     unsigned char *y_ptr;
409     int mb_row;
410     int mb_col;
411 
412     loop_filter_info *lfi = cm->lf_info;
413     int baseline_filter_level[MAX_MB_SEGMENTS];
414     int filter_level;
415     int alt_flt_enabled = mbd->segmentation_enabled;
416     FRAME_TYPE frame_type = cm->frame_type;
417 
418     (void) sharpness_lvl;
419 
420     /*MODE_INFO * this_mb_mode_info = cm->mi;*/ /* Point at base of Mb MODE_INFO list */
421     mbd->mode_info_context = cm->mi;          /* Point at base of Mb MODE_INFO list */
422 
423     /* Note the baseline filter values for each segment */
424     if (alt_flt_enabled)
425     {
426         for (i = 0; i < MAX_MB_SEGMENTS; i++)
427         {
428             /* Abs value */
429             if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
430                 baseline_filter_level[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
431             /* Delta Value */
432             else
433             {
434                 baseline_filter_level[i] = default_filt_lvl + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
435                 baseline_filter_level[i] = (baseline_filter_level[i] >= 0) ? ((baseline_filter_level[i] <= MAX_LOOP_FILTER) ? baseline_filter_level[i] : MAX_LOOP_FILTER) : 0;  /* Clamp to valid range */
436             }
437         }
438     }
439     else
440     {
441         for (i = 0; i < MAX_MB_SEGMENTS; i++)
442             baseline_filter_level[i] = default_filt_lvl;
443     }
444 
445     /* Initialize the loop filter for this frame. */
446     if ((cm->last_filter_type != cm->filter_type) || (cm->last_sharpness_level != cm->sharpness_level))
447         vp8_init_loop_filter(cm);
448     else if (frame_type != cm->last_frame_type)
449         vp8_frame_init_loop_filter(lfi, frame_type);
450 
451     /* Set up the buffer pointers */
452     y_ptr = post->y_buffer;
453 
454     /* vp8_filter each macro block */
455     for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
456     {
457         for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
458         {
459             int Segment = (alt_flt_enabled) ? mbd->mode_info_context->mbmi.segment_id : 0;
460             filter_level = baseline_filter_level[Segment];
461 
462             /* Apply any context driven MB level adjustment */
463             filter_level = vp8_adjust_mb_lf_value(mbd, filter_level);
464 
465             if (filter_level)
466             {
467                 if (mb_col > 0)
468                     cm->lf_mbv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
469 
470                 if (mbd->mode_info_context->mbmi.dc_diff > 0)
471                     cm->lf_bv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
472 
473                 /* don't apply across umv border */
474                 if (mb_row > 0)
475                     cm->lf_mbh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
476 
477                 if (mbd->mode_info_context->mbmi.dc_diff > 0)
478                     cm->lf_bh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
479             }
480 
481             y_ptr += 16;
482             mbd->mode_info_context ++;        /* step to next MB */
483 
484         }
485 
486         y_ptr += post->y_stride  * 16 - post->y_width;
487         mbd->mode_info_context ++;            /* Skip border mb */
488     }
489 
490 }
491 
492 
vp8_loop_filter_partial_frame(VP8_COMMON * cm,MACROBLOCKD * mbd,int default_filt_lvl,int sharpness_lvl,int Fraction)493 void vp8_loop_filter_partial_frame
494 (
495     VP8_COMMON *cm,
496     MACROBLOCKD *mbd,
497     int default_filt_lvl,
498     int sharpness_lvl,
499     int Fraction
500 )
501 {
502     YV12_BUFFER_CONFIG *post = cm->frame_to_show;
503 
504     int i;
505     unsigned char *y_ptr;
506     int mb_row;
507     int mb_col;
508     /*int mb_rows = post->y_height >> 4;*/
509     int mb_cols = post->y_width  >> 4;
510 
511     int linestocopy;
512 
513     loop_filter_info *lfi = cm->lf_info;
514     int baseline_filter_level[MAX_MB_SEGMENTS];
515     int filter_level;
516     int alt_flt_enabled = mbd->segmentation_enabled;
517     FRAME_TYPE frame_type = cm->frame_type;
518 
519     (void) sharpness_lvl;
520 
521     /*MODE_INFO * this_mb_mode_info = cm->mi + (post->y_height>>5) * (mb_cols + 1);*/ /* Point at base of Mb MODE_INFO list */
522     mbd->mode_info_context = cm->mi + (post->y_height >> 5) * (mb_cols + 1);        /* Point at base of Mb MODE_INFO list */
523 
524     linestocopy = (post->y_height >> (4 + Fraction));
525 
526     if (linestocopy < 1)
527         linestocopy = 1;
528 
529     linestocopy <<= 4;
530 
531     /* Note the baseline filter values for each segment */
532     if (alt_flt_enabled)
533     {
534         for (i = 0; i < MAX_MB_SEGMENTS; i++)
535         {
536             /* Abs value */
537             if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
538                 baseline_filter_level[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
539             /* Delta Value */
540             else
541             {
542                 baseline_filter_level[i] = default_filt_lvl + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
543                 baseline_filter_level[i] = (baseline_filter_level[i] >= 0) ? ((baseline_filter_level[i] <= MAX_LOOP_FILTER) ? baseline_filter_level[i] : MAX_LOOP_FILTER) : 0;  /* Clamp to valid range */
544             }
545         }
546     }
547     else
548     {
549         for (i = 0; i < MAX_MB_SEGMENTS; i++)
550             baseline_filter_level[i] = default_filt_lvl;
551     }
552 
553     /* Initialize the loop filter for this frame. */
554     if ((cm->last_filter_type != cm->filter_type) || (cm->last_sharpness_level != cm->sharpness_level))
555         vp8_init_loop_filter(cm);
556     else if (frame_type != cm->last_frame_type)
557         vp8_frame_init_loop_filter(lfi, frame_type);
558 
559     /* Set up the buffer pointers */
560     y_ptr = post->y_buffer + (post->y_height >> 5) * 16 * post->y_stride;
561 
562     /* vp8_filter each macro block */
563     for (mb_row = 0; mb_row<(linestocopy >> 4); mb_row++)
564     {
565         for (mb_col = 0; mb_col < mb_cols; mb_col++)
566         {
567             int Segment = (alt_flt_enabled) ? mbd->mode_info_context->mbmi.segment_id : 0;
568             filter_level = baseline_filter_level[Segment];
569 
570             if (filter_level)
571             {
572                 if (mb_col > 0)
573                     cm->lf_mbv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
574 
575                 if (mbd->mode_info_context->mbmi.dc_diff > 0)
576                     cm->lf_bv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
577 
578                 cm->lf_mbh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
579 
580                 if (mbd->mode_info_context->mbmi.dc_diff > 0)
581                     cm->lf_bh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
582             }
583 
584             y_ptr += 16;
585             mbd->mode_info_context += 1;      /* step to next MB */
586         }
587 
588         y_ptr += post->y_stride  * 16 - post->y_width;
589         mbd->mode_info_context += 1;          /* Skip border mb */
590     }
591 }
592