xref: /rockchip-linux_mpp/mpp/vproc/iep2/iep2_pd.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 #include "iep2_pd.h"
18*437bfbebSnyanmisaka 
19*437bfbebSnyanmisaka #include <stdio.h>
20*437bfbebSnyanmisaka #ifdef SIMULATE
21*437bfbebSnyanmisaka #include <malloc.h>
22*437bfbebSnyanmisaka #endif
23*437bfbebSnyanmisaka #include <string.h>
24*437bfbebSnyanmisaka #include <stdlib.h>
25*437bfbebSnyanmisaka 
26*437bfbebSnyanmisaka #include "mpp_common.h"
27*437bfbebSnyanmisaka #include "iep_common.h"
28*437bfbebSnyanmisaka 
29*437bfbebSnyanmisaka #include "iep2.h"
30*437bfbebSnyanmisaka #include "iep2_api.h"
31*437bfbebSnyanmisaka 
32*437bfbebSnyanmisaka #define RKMIN(a, b)             (((a) < (b)) ? (a) : (b))
33*437bfbebSnyanmisaka #define RKMAX(a, b)             (((a) > (b)) ? (a) : (b))
34*437bfbebSnyanmisaka 
35*437bfbebSnyanmisaka #define PD_TS   1     // Top field unchanged, Bottom field changed
36*437bfbebSnyanmisaka #define PD_BS   2     // Top filed changed, Bottom field unchanged
37*437bfbebSnyanmisaka #define PD_DF   0     // Both fileds changed.
38*437bfbebSnyanmisaka #define PD_ID   3
39*437bfbebSnyanmisaka 
40*437bfbebSnyanmisaka #define PD_FRAME_PERIOD         5
41*437bfbebSnyanmisaka 
42*437bfbebSnyanmisaka #define FIELD_DIFF_SUM_THR      32
43*437bfbebSnyanmisaka 
44*437bfbebSnyanmisaka static int pd_table[][PD_FRAME_PERIOD] = {
45*437bfbebSnyanmisaka     { PD_TS, PD_DF, PD_BS, PD_DF, PD_DF },      // 3:2:3:2
46*437bfbebSnyanmisaka     { PD_DF, PD_BS, PD_DF, PD_TS, PD_DF },      // 2:3:2:3
47*437bfbebSnyanmisaka     { PD_TS, PD_BS, PD_DF, PD_DF, PD_DF },      // 2:3:3:2
48*437bfbebSnyanmisaka     { PD_BS, PD_DF, PD_DF, PD_TS, PD_DF },      // 3:2:2:3
49*437bfbebSnyanmisaka     { PD_DF, PD_DF, PD_DF, PD_DF, PD_DF }       // unknown
50*437bfbebSnyanmisaka };
51*437bfbebSnyanmisaka 
52*437bfbebSnyanmisaka // field intensity table
53*437bfbebSnyanmisaka static int sp_table[][PD_FRAME_PERIOD] = {
54*437bfbebSnyanmisaka     { 0, 1, 1, 0, 0 },
55*437bfbebSnyanmisaka     { 0, 0, 1, 1, 0 },
56*437bfbebSnyanmisaka     { 0, 1, 0, 0, 0 },
57*437bfbebSnyanmisaka     { 0, 1, 1, 1, 0 },
58*437bfbebSnyanmisaka     { 1, 1, 1, 1, 1 }
59*437bfbebSnyanmisaka };
60*437bfbebSnyanmisaka 
61*437bfbebSnyanmisaka static int fp_table[][PD_FRAME_PERIOD] = {
62*437bfbebSnyanmisaka     { 1, 1, 1, 0, 0 },
63*437bfbebSnyanmisaka     { 0, 1, 1, 1, 0 },
64*437bfbebSnyanmisaka     { 0, 1, 1, 0, 0 },
65*437bfbebSnyanmisaka     { 1, 1, 1, 1, 0 },
66*437bfbebSnyanmisaka     { 1, 1, 1, 1, 1 }
67*437bfbebSnyanmisaka };
68*437bfbebSnyanmisaka 
69*437bfbebSnyanmisaka static char* pd_titles[] = {
70*437bfbebSnyanmisaka     "PULLDOWN 3:2:3:2",
71*437bfbebSnyanmisaka     "PULLDOWN 2:3:2:3",
72*437bfbebSnyanmisaka     "PULLDOWN 2:3:3:2",
73*437bfbebSnyanmisaka     "PULLDOWN 3:2:2:3",
74*437bfbebSnyanmisaka     "PULLDOWN UNKNOWN"
75*437bfbebSnyanmisaka };
76*437bfbebSnyanmisaka 
iep2_check_pd(struct iep2_api_ctx * ctx)77*437bfbebSnyanmisaka void iep2_check_pd(struct iep2_api_ctx *ctx)
78*437bfbebSnyanmisaka {
79*437bfbebSnyanmisaka     struct iep2_pd_info *pd_inf = &ctx->pd_inf;
80*437bfbebSnyanmisaka     int tcnt = ctx->output.dect_pd_tcnt;
81*437bfbebSnyanmisaka     int bcnt = ctx->output.dect_pd_bcnt;
82*437bfbebSnyanmisaka     int tdiff = ctx->output.ff_gradt_tcnt + 1;
83*437bfbebSnyanmisaka     int bdiff = ctx->output.ff_gradt_bcnt + 1;
84*437bfbebSnyanmisaka     int idx = pd_inf->i % PD_FRAME_PERIOD;
85*437bfbebSnyanmisaka     int ff00t = (ctx->output.dect_ff_cur_tcnt << 5) / tdiff;
86*437bfbebSnyanmisaka     int ff00b = (ctx->output.dect_ff_cur_bcnt << 5) / bdiff;
87*437bfbebSnyanmisaka     int nz = ctx->output.dect_ff_nz + 1;
88*437bfbebSnyanmisaka     int f = ctx->output.dect_ff_comb_f;
89*437bfbebSnyanmisaka     size_t i, j;
90*437bfbebSnyanmisaka 
91*437bfbebSnyanmisaka     pd_inf->spatial[idx] = RKMIN(ff00t, ff00b);
92*437bfbebSnyanmisaka     pd_inf->temporal[idx] = (tcnt < FIELD_DIFF_SUM_THR) | ((bcnt < FIELD_DIFF_SUM_THR) << 1);
93*437bfbebSnyanmisaka     pd_inf->fcoeff[idx] = f * 100 / nz;
94*437bfbebSnyanmisaka 
95*437bfbebSnyanmisaka     iep_dbg_trace("pd tcnt %d bcnt %d\n", tcnt, bcnt);
96*437bfbebSnyanmisaka     iep_dbg_trace("temporal(%d, %d) %d %d %d %d %d\n",
97*437bfbebSnyanmisaka                   idx, pd_inf->step,
98*437bfbebSnyanmisaka                   pd_inf->temporal[0],
99*437bfbebSnyanmisaka                   pd_inf->temporal[1],
100*437bfbebSnyanmisaka                   pd_inf->temporal[2],
101*437bfbebSnyanmisaka                   pd_inf->temporal[3],
102*437bfbebSnyanmisaka                   pd_inf->temporal[4]);
103*437bfbebSnyanmisaka     iep_dbg_trace("spatial(%d, %d) %d %d %d %d %d\n",
104*437bfbebSnyanmisaka                   idx, pd_inf->step,
105*437bfbebSnyanmisaka                   pd_inf->spatial[0],
106*437bfbebSnyanmisaka                   pd_inf->spatial[1],
107*437bfbebSnyanmisaka                   pd_inf->spatial[2],
108*437bfbebSnyanmisaka                   pd_inf->spatial[3],
109*437bfbebSnyanmisaka                   pd_inf->spatial[4]);
110*437bfbebSnyanmisaka     iep_dbg_trace("fcoeff(%d, %d) %d %d %d %d %d\n",
111*437bfbebSnyanmisaka                   idx, pd_inf->step,
112*437bfbebSnyanmisaka                   pd_inf->fcoeff[0],
113*437bfbebSnyanmisaka                   pd_inf->fcoeff[1],
114*437bfbebSnyanmisaka                   pd_inf->fcoeff[2],
115*437bfbebSnyanmisaka                   pd_inf->fcoeff[3],
116*437bfbebSnyanmisaka                   pd_inf->fcoeff[4]);
117*437bfbebSnyanmisaka 
118*437bfbebSnyanmisaka     if (pd_inf->pdtype != PD_TYPES_UNKNOWN && pd_inf->step != -1) {
119*437bfbebSnyanmisaka         int n = (int)pd_inf->pdtype;
120*437bfbebSnyanmisaka         int type = pd_table[n][(pd_inf->step + 1) % 5];
121*437bfbebSnyanmisaka 
122*437bfbebSnyanmisaka         if ((type == PD_TS && !(tcnt < FIELD_DIFF_SUM_THR)) ||
123*437bfbebSnyanmisaka             (type == PD_BS && !(bcnt < FIELD_DIFF_SUM_THR))) {
124*437bfbebSnyanmisaka             pd_inf->pdtype = PD_TYPES_UNKNOWN;
125*437bfbebSnyanmisaka             pd_inf->step = -1;
126*437bfbebSnyanmisaka         }
127*437bfbebSnyanmisaka     }
128*437bfbebSnyanmisaka 
129*437bfbebSnyanmisaka     pd_inf->step = pd_inf->step != -1 ? (pd_inf->step + 1) % 5 : -1;
130*437bfbebSnyanmisaka 
131*437bfbebSnyanmisaka     if (pd_inf->pdtype != PD_TYPES_UNKNOWN) {
132*437bfbebSnyanmisaka         pd_inf->i++;
133*437bfbebSnyanmisaka         return;
134*437bfbebSnyanmisaka     } else {
135*437bfbebSnyanmisaka         iep_dbg_trace("pulldown recheck start: old type %s\n", pd_titles[pd_inf->pdtype]);
136*437bfbebSnyanmisaka     }
137*437bfbebSnyanmisaka 
138*437bfbebSnyanmisaka     for (i = 0; i < MPP_ARRAY_ELEMS(pd_table); ++i) {
139*437bfbebSnyanmisaka         if (pd_inf->temporal[idx] == pd_table[i][0] &&
140*437bfbebSnyanmisaka             pd_inf->temporal[(idx + 1) % 5] == pd_table[i][1] &&
141*437bfbebSnyanmisaka             pd_inf->temporal[(idx + 2) % 5] == pd_table[i][2] &&
142*437bfbebSnyanmisaka             pd_inf->temporal[(idx + 3) % 5] == pd_table[i][3] &&
143*437bfbebSnyanmisaka             pd_inf->temporal[(idx + 4) % 5] == pd_table[i][4]) {
144*437bfbebSnyanmisaka 
145*437bfbebSnyanmisaka             iep_dbg_trace("[%d] match %s, current idx %d\n", i, pd_titles[i], idx % PD_FRAME_PERIOD);
146*437bfbebSnyanmisaka 
147*437bfbebSnyanmisaka             if (i != PD_TYPES_UNKNOWN) {
148*437bfbebSnyanmisaka                 int vmax = 0x7fffffff;
149*437bfbebSnyanmisaka                 int vmin = 0;
150*437bfbebSnyanmisaka                 int fmax = 0x7fffffff;
151*437bfbebSnyanmisaka                 int fmin = 0;
152*437bfbebSnyanmisaka 
153*437bfbebSnyanmisaka                 iep_dbg_trace("get pulldown type %s\n", pd_titles[i]);
154*437bfbebSnyanmisaka 
155*437bfbebSnyanmisaka                 for (j = 0; j < MPP_ARRAY_ELEMS(sp_table[i]); ++j) {
156*437bfbebSnyanmisaka                     if (sp_table[i][j] == 1) {
157*437bfbebSnyanmisaka                         vmax = RKMIN(vmax, pd_inf->spatial[j]);
158*437bfbebSnyanmisaka                     } else {
159*437bfbebSnyanmisaka                         vmin = RKMAX(vmin, pd_inf->spatial[j]);
160*437bfbebSnyanmisaka                     }
161*437bfbebSnyanmisaka                 }
162*437bfbebSnyanmisaka 
163*437bfbebSnyanmisaka                 for (j = 0; j < MPP_ARRAY_ELEMS(fp_table[i]); ++j) {
164*437bfbebSnyanmisaka                     if (fp_table[i][j] == 1) {
165*437bfbebSnyanmisaka                         fmax = RKMIN(fmax, pd_inf->fcoeff[(idx + j) % 5]);
166*437bfbebSnyanmisaka                     } else {
167*437bfbebSnyanmisaka                         fmin = RKMAX(fmin, pd_inf->fcoeff[(idx + j) % 5]);
168*437bfbebSnyanmisaka                     }
169*437bfbebSnyanmisaka                 }
170*437bfbebSnyanmisaka 
171*437bfbebSnyanmisaka                 if (vmax > vmin || fmax > fmin) {
172*437bfbebSnyanmisaka                     pd_inf->pdtype = i;
173*437bfbebSnyanmisaka 
174*437bfbebSnyanmisaka                     if (i == PD_TYPES_3_2_2_3 && pd_inf->spatial[1] > RKMAX(pd_inf->spatial[0],
175*437bfbebSnyanmisaka                                                                             pd_inf->spatial[4])) {
176*437bfbebSnyanmisaka                         pd_inf->pdtype = PD_TYPES_3_2_3_2;
177*437bfbebSnyanmisaka                     }
178*437bfbebSnyanmisaka 
179*437bfbebSnyanmisaka                     iep_dbg_trace("confirm pulldown type %s\n", pd_titles[i]);
180*437bfbebSnyanmisaka                     pd_inf->step = 0;
181*437bfbebSnyanmisaka                 }
182*437bfbebSnyanmisaka             }
183*437bfbebSnyanmisaka             break;
184*437bfbebSnyanmisaka         }
185*437bfbebSnyanmisaka     }
186*437bfbebSnyanmisaka 
187*437bfbebSnyanmisaka     pd_inf->i++;
188*437bfbebSnyanmisaka }
189*437bfbebSnyanmisaka 
190*437bfbebSnyanmisaka char *PD_COMP_STRING[] = {
191*437bfbebSnyanmisaka     "PD_COMP_CC",
192*437bfbebSnyanmisaka     "PD_COMP_CN",
193*437bfbebSnyanmisaka     "PD_COMP_NC",
194*437bfbebSnyanmisaka     "PD_COMP_NON"
195*437bfbebSnyanmisaka };
196*437bfbebSnyanmisaka 
197*437bfbebSnyanmisaka /**
198*437bfbebSnyanmisaka  * @brief get pulldown compose flag
199*437bfbebSnyanmisaka  *
200*437bfbebSnyanmisaka  * @param pd_inf
201*437bfbebSnyanmisaka  * @return int see @PD_COMP_STRING
202*437bfbebSnyanmisaka  */
iep2_pd_get_output(struct iep2_pd_info * pd_inf)203*437bfbebSnyanmisaka int iep2_pd_get_output(struct iep2_pd_info *pd_inf)
204*437bfbebSnyanmisaka {
205*437bfbebSnyanmisaka     int flag = PD_COMP_FLAG_CC;
206*437bfbebSnyanmisaka     int step = (pd_inf->step + 1) % 5;
207*437bfbebSnyanmisaka 
208*437bfbebSnyanmisaka     switch (pd_inf->pdtype) {
209*437bfbebSnyanmisaka     case PD_TYPES_3_2_3_2:
210*437bfbebSnyanmisaka         switch (step) {
211*437bfbebSnyanmisaka         case 1:
212*437bfbebSnyanmisaka             flag = PD_COMP_FLAG_NC;
213*437bfbebSnyanmisaka             break;
214*437bfbebSnyanmisaka         case 2:
215*437bfbebSnyanmisaka             flag = PD_COMP_FLAG_NON;
216*437bfbebSnyanmisaka             break;
217*437bfbebSnyanmisaka         }
218*437bfbebSnyanmisaka         break;
219*437bfbebSnyanmisaka     case PD_TYPES_2_3_2_3:
220*437bfbebSnyanmisaka         switch (step) {
221*437bfbebSnyanmisaka         case 2:
222*437bfbebSnyanmisaka             flag = PD_COMP_FLAG_CN;
223*437bfbebSnyanmisaka             break;
224*437bfbebSnyanmisaka         case 3:
225*437bfbebSnyanmisaka             flag = PD_COMP_FLAG_NON;
226*437bfbebSnyanmisaka             break;
227*437bfbebSnyanmisaka         }
228*437bfbebSnyanmisaka         break;
229*437bfbebSnyanmisaka     case PD_TYPES_2_3_3_2:
230*437bfbebSnyanmisaka         switch (step) {
231*437bfbebSnyanmisaka         case 2:
232*437bfbebSnyanmisaka             flag = PD_COMP_FLAG_NON;
233*437bfbebSnyanmisaka             break;
234*437bfbebSnyanmisaka         }
235*437bfbebSnyanmisaka         break;
236*437bfbebSnyanmisaka     case PD_TYPES_3_2_2_3:
237*437bfbebSnyanmisaka         switch (step) {
238*437bfbebSnyanmisaka         case 1:
239*437bfbebSnyanmisaka         case 2:
240*437bfbebSnyanmisaka             flag = PD_COMP_FLAG_CN;
241*437bfbebSnyanmisaka             break;
242*437bfbebSnyanmisaka         case 3:
243*437bfbebSnyanmisaka             flag = PD_COMP_FLAG_NON;
244*437bfbebSnyanmisaka             break;
245*437bfbebSnyanmisaka         }
246*437bfbebSnyanmisaka         break;
247*437bfbebSnyanmisaka     default:
248*437bfbebSnyanmisaka         mpp_log("unsupport telecine format %s\n",
249*437bfbebSnyanmisaka                 pd_titles[(int)pd_inf->pdtype]);
250*437bfbebSnyanmisaka         return -1;
251*437bfbebSnyanmisaka     }
252*437bfbebSnyanmisaka 
253*437bfbebSnyanmisaka     iep_dbg_trace("-------------------------------------------------\n");
254*437bfbebSnyanmisaka     iep_dbg_trace("step %d, idx %d, flag %s\n",
255*437bfbebSnyanmisaka                   pd_inf->step, pd_inf->i, PD_COMP_STRING[flag]);
256*437bfbebSnyanmisaka 
257*437bfbebSnyanmisaka     return flag;
258*437bfbebSnyanmisaka }
259