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