xref: /rockchip-linux_mpp/mpp/vproc/iep2/iep2_ff.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1*437bfbebSnyanmisaka /*
2*437bfbebSnyanmisaka  * Copyright 2020 Rockchip Electronics Co. LTD
3*437bfbebSnyanmisaka  *
4*437bfbebSnyanmisaka  * Licensed under the Apache License, Version 2.0 (the "License");
5*437bfbebSnyanmisaka  * you may not use this file except in compliance with the License.
6*437bfbebSnyanmisaka  * You may obtain a copy of the License at
7*437bfbebSnyanmisaka  *
8*437bfbebSnyanmisaka  *      http://www.apache.org/licenses/LICENSE-2.0
9*437bfbebSnyanmisaka  *
10*437bfbebSnyanmisaka  * Unless required by applicable law or agreed to in writing, software
11*437bfbebSnyanmisaka  * distributed under the License is distributed on an "AS IS" BASIS,
12*437bfbebSnyanmisaka  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*437bfbebSnyanmisaka  * See the License for the specific language governing permissions and
14*437bfbebSnyanmisaka  * limitations under the License.
15*437bfbebSnyanmisaka  */
16*437bfbebSnyanmisaka 
17*437bfbebSnyanmisaka #define MODULE_TAG "iep2"
18*437bfbebSnyanmisaka 
19*437bfbebSnyanmisaka #include <stdio.h>
20*437bfbebSnyanmisaka #include <string.h>
21*437bfbebSnyanmisaka #include <stdlib.h>
22*437bfbebSnyanmisaka 
23*437bfbebSnyanmisaka #include "mpp_common.h"
24*437bfbebSnyanmisaka 
25*437bfbebSnyanmisaka #include "iep2.h"
26*437bfbebSnyanmisaka #include "iep2_api.h"
27*437bfbebSnyanmisaka #include "iep2_ff.h"
28*437bfbebSnyanmisaka 
iep2_check_ffo(struct iep2_api_ctx * ctx)29*437bfbebSnyanmisaka void iep2_check_ffo(struct iep2_api_ctx *ctx)
30*437bfbebSnyanmisaka {
31*437bfbebSnyanmisaka     RK_S32 tcnt = ctx->output.dect_pd_tcnt;
32*437bfbebSnyanmisaka     RK_S32 bcnt = ctx->output.dect_pd_bcnt;
33*437bfbebSnyanmisaka     RK_U32 tdiff = ctx->output.ff_gradt_tcnt + 1;
34*437bfbebSnyanmisaka     RK_U32 bdiff = ctx->output.ff_gradt_bcnt + 1;
35*437bfbebSnyanmisaka     RK_U32 ff00t  = (ctx->output.dect_ff_cur_tcnt << 5) / tdiff;
36*437bfbebSnyanmisaka     RK_U32 ff00b  = (ctx->output.dect_ff_cur_bcnt << 5) / bdiff;
37*437bfbebSnyanmisaka     RK_U32 ff11t  = (ctx->output.dect_ff_nxt_tcnt << 5) / tdiff;
38*437bfbebSnyanmisaka     RK_U32 ff11b  = (ctx->output.dect_ff_nxt_bcnt << 5) / bdiff;
39*437bfbebSnyanmisaka     RK_S32 ff0t1b = (ctx->output.dect_ff_ble_tcnt << 5) / bdiff;
40*437bfbebSnyanmisaka     RK_S32 ff0b1t = (ctx->output.dect_ff_ble_bcnt << 5) / bdiff;
41*437bfbebSnyanmisaka 
42*437bfbebSnyanmisaka     RK_U32 ff00 = RKMIN(ff00t, ff00b);
43*437bfbebSnyanmisaka     RK_U32 ff11 = RKMIN(ff11t, ff11b);
44*437bfbebSnyanmisaka     RK_U32 ffx = RKMIN(ff0t1b, ff0b1t);
45*437bfbebSnyanmisaka     RK_U32 ffi = RKMAX(ff00, ff11);
46*437bfbebSnyanmisaka     RK_U32 thr = ffx / 10;
47*437bfbebSnyanmisaka     RK_U32 field_diff_ratio = 0;
48*437bfbebSnyanmisaka 
49*437bfbebSnyanmisaka     iep_dbg_trace("deinterlace pd_cnt %d : %d, gradt cnt %d : %d, cur cnt %d : %d, nxt cnt %d : %d, ble 01:%d 10:%d",
50*437bfbebSnyanmisaka                   tcnt, bcnt, tdiff, bdiff, ctx->output.ff_gradt_tcnt, ctx->output.ff_gradt_bcnt,
51*437bfbebSnyanmisaka                   ctx->output.dect_ff_cur_tcnt, ctx->output.dect_ff_cur_bcnt,
52*437bfbebSnyanmisaka                   ctx->output.dect_ff_nxt_tcnt, ctx->output.dect_ff_nxt_bcnt,
53*437bfbebSnyanmisaka                   ctx->output.dect_ff_ble_tcnt, ctx->output.dect_ff_ble_bcnt);
54*437bfbebSnyanmisaka 
55*437bfbebSnyanmisaka     iep_dbg_trace("deinterlace tdiff %u, bdiff %u, ff00t %u, ff00b %u, ff11t %u ff11b %u ff0t1b %u ff0b1t %u, ff00 %d, ff11 %d, ffx %d, ffi %d thr %d\n",
56*437bfbebSnyanmisaka                   tdiff, bdiff, ff00t, ff00b, ff11t, ff11b, ff0t1b, ff0b1t, ff00, ff11, ffx, ffi, thr);
57*437bfbebSnyanmisaka 
58*437bfbebSnyanmisaka     RK_S32 tff_score = 0;
59*437bfbebSnyanmisaka     RK_S32 bff_score = 0;
60*437bfbebSnyanmisaka     RK_S32 coef = 0;
61*437bfbebSnyanmisaka     RK_S32 frm_score = 0;
62*437bfbebSnyanmisaka     RK_S32 fie_score = 0;
63*437bfbebSnyanmisaka 
64*437bfbebSnyanmisaka     iep_dbg_trace("deinterlace cur %u, %u, nxt %u, %u, ble %u, %u, diff %u, %u, nz %u, f %u, comb %u\n",
65*437bfbebSnyanmisaka                   ctx->output.dect_ff_cur_tcnt, ctx->output.dect_ff_cur_bcnt,
66*437bfbebSnyanmisaka                   ctx->output.dect_ff_nxt_tcnt, ctx->output.dect_ff_nxt_bcnt,
67*437bfbebSnyanmisaka                   ctx->output.dect_ff_ble_tcnt, ctx->output.dect_ff_ble_bcnt,
68*437bfbebSnyanmisaka                   tdiff, bdiff,
69*437bfbebSnyanmisaka                   ctx->output.dect_ff_nz, ctx->output.dect_ff_comb_f,
70*437bfbebSnyanmisaka                   ctx->output.out_comb_cnt);
71*437bfbebSnyanmisaka 
72*437bfbebSnyanmisaka     if (ff00t > 120 || ff00b > 120) {
73*437bfbebSnyanmisaka         iep_dbg_trace("deinterlace check ffo abort at %d\n", __LINE__);
74*437bfbebSnyanmisaka         return;
75*437bfbebSnyanmisaka     }
76*437bfbebSnyanmisaka 
77*437bfbebSnyanmisaka     iep_dbg_trace("deinterlace ffi %u ffx %u\n", ffi, ffx);
78*437bfbebSnyanmisaka 
79*437bfbebSnyanmisaka     if (ffi <= 3 && ffx <= 3) {
80*437bfbebSnyanmisaka         iep_dbg_trace("deinterlace check ffo abort at %d\n", __LINE__);
81*437bfbebSnyanmisaka         return;
82*437bfbebSnyanmisaka     }
83*437bfbebSnyanmisaka 
84*437bfbebSnyanmisaka     coef = 2;
85*437bfbebSnyanmisaka 
86*437bfbebSnyanmisaka     if ((ffi * coef <= ffx) && (ffx - ffi * coef) > 2 * ffx / 10) {
87*437bfbebSnyanmisaka         ctx->ff_inf.frm_score = RKCLIP(ctx->ff_inf.frm_score + 1, 0, 20);
88*437bfbebSnyanmisaka         ctx->ff_inf.fie_score = RKCLIP(ctx->ff_inf.fie_score - 1, 0, 20);
89*437bfbebSnyanmisaka     } else {
90*437bfbebSnyanmisaka         ctx->ff_inf.frm_score = RKCLIP(ctx->ff_inf.frm_score - 1, 0, 20);
91*437bfbebSnyanmisaka         ctx->ff_inf.fie_score = RKCLIP(ctx->ff_inf.fie_score + 1, 0, 20);
92*437bfbebSnyanmisaka     }
93*437bfbebSnyanmisaka 
94*437bfbebSnyanmisaka     iep_dbg_trace("deinterlace (frm,fie) offset %d, %d, score %d, %d\n",
95*437bfbebSnyanmisaka                   ctx->ff_inf.frm_offset, ctx->ff_inf.fie_offset,
96*437bfbebSnyanmisaka                   ctx->ff_inf.frm_score, ctx->ff_inf.fie_score);
97*437bfbebSnyanmisaka 
98*437bfbebSnyanmisaka     frm_score = ctx->ff_inf.frm_score + ctx->ff_inf.frm_offset;
99*437bfbebSnyanmisaka     fie_score = ctx->ff_inf.fie_score + ctx->ff_inf.fie_offset;
100*437bfbebSnyanmisaka 
101*437bfbebSnyanmisaka 
102*437bfbebSnyanmisaka     if (RKABS(frm_score - fie_score) > 10) {
103*437bfbebSnyanmisaka         if (frm_score > fie_score) {
104*437bfbebSnyanmisaka             ctx->ff_inf.frm_mode = IEP2_FF_MODE_FRAME;
105*437bfbebSnyanmisaka             iep_dbg_trace("deinterlace frame mode\n");
106*437bfbebSnyanmisaka         } else {
107*437bfbebSnyanmisaka             ctx->ff_inf.frm_mode = IEP2_FF_MODE_FIELD;
108*437bfbebSnyanmisaka             iep_dbg_trace("deinterlace field mode\n");
109*437bfbebSnyanmisaka         }
110*437bfbebSnyanmisaka     } else {
111*437bfbebSnyanmisaka         ctx->ff_inf.frm_mode = IEP2_FF_MODE_UND;
112*437bfbebSnyanmisaka         iep_dbg_trace("deinterlace mode unknown\n");
113*437bfbebSnyanmisaka     }
114*437bfbebSnyanmisaka 
115*437bfbebSnyanmisaka     if (tcnt <= 3 && bcnt <= 3) {
116*437bfbebSnyanmisaka         iep_dbg_trace("deinterlace check ffo abort at %d\n", __LINE__);
117*437bfbebSnyanmisaka         return;
118*437bfbebSnyanmisaka     }
119*437bfbebSnyanmisaka 
120*437bfbebSnyanmisaka     thr = (thr == 0) ? 1 : thr;
121*437bfbebSnyanmisaka 
122*437bfbebSnyanmisaka     // field order detection
123*437bfbebSnyanmisaka     field_diff_ratio = RKABS(ff0t1b - ff0b1t) / thr * 10;
124*437bfbebSnyanmisaka     ctx->ff_inf.fo_ratio_sum = ctx->ff_inf.fo_ratio_sum + field_diff_ratio - ctx->ff_inf.fo_ratio[ctx->ff_inf.fo_ratio_idx];
125*437bfbebSnyanmisaka     ctx->ff_inf.fo_ratio[ctx->ff_inf.fo_ratio_idx] = field_diff_ratio;
126*437bfbebSnyanmisaka     ctx->ff_inf.fo_ratio_idx = (ctx->ff_inf.fo_ratio_idx + 1) % FIELD_ORDER_RATIO_SIZE;
127*437bfbebSnyanmisaka 
128*437bfbebSnyanmisaka     ctx->ff_inf.fo_ratio_cnt++;
129*437bfbebSnyanmisaka     ctx->ff_inf.fo_ratio_cnt = RKMIN(ctx->ff_inf.fo_ratio_cnt, FIELD_ORDER_RATIO_SIZE);
130*437bfbebSnyanmisaka     ctx->ff_inf.fo_ratio_avg = ctx->ff_inf.fo_ratio_sum / ctx->ff_inf.fo_ratio_cnt;
131*437bfbebSnyanmisaka 
132*437bfbebSnyanmisaka     if (field_diff_ratio > 10) {
133*437bfbebSnyanmisaka         if (ff0t1b > ff0b1t) {
134*437bfbebSnyanmisaka             ctx->ff_inf.tff_score = RKCLIP(ctx->ff_inf.tff_score + 1, 0, 10);
135*437bfbebSnyanmisaka             ctx->ff_inf.bff_score = RKCLIP(ctx->ff_inf.bff_score - 1, 0, 10);
136*437bfbebSnyanmisaka         } else {
137*437bfbebSnyanmisaka             ctx->ff_inf.tff_score = RKCLIP(ctx->ff_inf.tff_score - 1, 0, 10);
138*437bfbebSnyanmisaka             ctx->ff_inf.bff_score = RKCLIP(ctx->ff_inf.bff_score + 1, 0, 10);
139*437bfbebSnyanmisaka         }
140*437bfbebSnyanmisaka     }
141*437bfbebSnyanmisaka 
142*437bfbebSnyanmisaka     tff_score = ctx->ff_inf.tff_score + ctx->ff_inf.tff_offset;
143*437bfbebSnyanmisaka     bff_score = ctx->ff_inf.bff_score + ctx->ff_inf.bff_offset;
144*437bfbebSnyanmisaka     iep_dbg_trace("deinterlace ff score %d : %d, offset %d : %d\n", tff_score, bff_score, ctx->ff_inf.tff_offset, ctx->ff_inf.bff_offset);
145*437bfbebSnyanmisaka 
146*437bfbebSnyanmisaka     if (RKABS(tff_score - bff_score) > 5) {
147*437bfbebSnyanmisaka         if (tff_score > bff_score) {
148*437bfbebSnyanmisaka             iep_dbg_trace("deinterlace field order tff\n");
149*437bfbebSnyanmisaka             ctx->ff_inf.field_order = IEP2_FIELD_ORDER_TFF;
150*437bfbebSnyanmisaka         } else {
151*437bfbebSnyanmisaka             iep_dbg_trace("deinterlace field order bff\n");
152*437bfbebSnyanmisaka             ctx->ff_inf.field_order = IEP2_FIELD_ORDER_BFF;
153*437bfbebSnyanmisaka         }
154*437bfbebSnyanmisaka     } else {
155*437bfbebSnyanmisaka         iep_dbg_trace("deinterlace field order unknown\n");
156*437bfbebSnyanmisaka         ctx->ff_inf.field_order = IEP2_FIELD_ORDER_UND;
157*437bfbebSnyanmisaka     }
158*437bfbebSnyanmisaka 
159*437bfbebSnyanmisaka }
160