xref: /rockchip-linux_mpp/mpp/vproc/mpp_dec_vproc.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3  * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
4  */
5 
6 #define MODULE_TAG "mpp_dec_vproc"
7 
8 #include <string.h>
9 
10 #include "mpp_env.h"
11 #include "mpp_mem.h"
12 #include "mpp_common.h"
13 
14 #include "mpp_dec_impl.h"
15 
16 #include "mpp_meta_impl.h"
17 #include "mpp_frame_impl.h"
18 #include "mpp_dec_vproc.h"
19 #include "iep_api.h"
20 #include "iep2_api.h"
21 
22 #define DUMP_FILE 1
23 
24 #define dec_vproc_dbg(flag, fmt, ...) \
25     do { \
26         _mpp_dbg(vproc_debug, flag, fmt, ## __VA_ARGS__); \
27     } while (0)
28 
29 #define vproc_dbg_f(flag, fmt, ...) \
30     do { \
31         _mpp_dbg_f(vproc_debug, flag, fmt, ## __VA_ARGS__); \
32     } while (0)
33 
34 #define VPROC_DBG_FUNCTION      (0x00000001)
35 #define VPROC_DBG_STATUS        (0x00000002)
36 #define VPROC_DBG_RESET         (0x00000004)
37 #define VPROC_DBG_DUMP_IN       (0x00000010)
38 #define VPROC_DBG_DUMP_OUT      (0x00000020)
39 #define VPROC_DBG_IN            (0x00000040)
40 #define VPROC_DBG_OUT           (0x00000080)
41 
42 #define vproc_dbg_func(fmt, ...)  \
43     vproc_dbg_f(VPROC_DBG_FUNCTION, fmt, ## __VA_ARGS__);
44 #define vproc_dbg_status(fmt, ...)  \
45     vproc_dbg_f(VPROC_DBG_STATUS, fmt, ## __VA_ARGS__);
46 #define vproc_dbg_reset(fmt, ...)  \
47     vproc_dbg_f(VPROC_DBG_RESET, fmt, ## __VA_ARGS__);
48 #define vproc_dbg_in(fmt, ...)  \
49     vproc_dbg_f(VPROC_DBG_IN, fmt, ## __VA_ARGS__);
50 #define vproc_dbg_out(fmt, ...)  \
51     vproc_dbg_f(VPROC_DBG_OUT, fmt, ## __VA_ARGS__);
52 
53 RK_U32 vproc_debug = 0;
54 
55 typedef union VprocTaskStatus_u {
56     RK_U32          val;
57     struct {
58         RK_U32      task_rdy      : 1;
59         RK_U32      buf_rdy   : 1;
60     };
61 } VprocTaskStatus;
62 
63 typedef union VprocTaskWait_u {
64     RK_U32          val;
65     struct {
66         RK_U32      task_in      : 1;
67         RK_U32      task_buf_in  : 1;
68     };
69 } VprocTaskWait;
70 
71 typedef struct MppDecVprocCtxImpl_t {
72     Mpp                 *mpp;
73     HalTaskGroup        task_group;
74     MppBufSlots         slots;
75 
76     MppThread           *thd;
77     RK_U32              reset;
78     sem_t               reset_sem;
79 
80     IepCtx              iep_ctx;
81     iep_com_ctx         *com_ctx;
82     IepCmdParamDeiCfg   dei_cfg;
83     struct iep2_api_info  dei_info;
84 
85     VprocTaskStatus     task_status;
86     VprocTaskWait       task_wait;
87 
88     // slot index for previous frame and current frame
89     RK_S32              prev_idx0;
90     MppFrame            prev_frm0;
91     RK_S32              prev_idx1;
92     MppFrame            prev_frm1;
93     enum IEP2_FF_MODE   pre_ff_mode;
94     RK_U32              pd_mode;
95     MppBuffer           out_buf0;
96     MppBuffer           out_buf1;
97     MppVprocMode        vproc_mode;
98 
99     MPP_RET (*set_dei)(MppDecVprocCtx *vproc_ctx, MppFrame frm);
100     MPP_RET (*start_dei)(MppDecVprocCtx *vproc_ctx, RK_U32 mode);
101     MPP_RET (*update_ref)(MppDecVprocCtx *vproc_ctx, MppFrame frm, RK_U32 index);
102 } MppDecVprocCtxImpl;
103 
dec_vproc_put_frame(Mpp * mpp,MppFrame frame,MppBuffer buf,RK_S64 pts,RK_U32 err)104 static void dec_vproc_put_frame(Mpp *mpp, MppFrame frame, MppBuffer buf, RK_S64 pts, RK_U32 err)
105 {
106     MppList *list = mpp->mFrmOut;
107     MppFrame out = mpp_frame_dup(frame);
108     MppFrameImpl *impl = (MppFrameImpl *)out;
109     MppBuffer src_buf = mpp_frame_get_buffer(frame);
110 
111     if (pts >= 0)
112         impl->pts = pts;
113 
114     if (buf)
115         impl->buffer = buf;
116 
117     /* check and copy hdr info */
118     if (impl->meta && src_buf != buf) {
119         RK_S32 hdr_offset = 0;
120         RK_S32 hdr_size = 0;
121 
122         mpp_meta_s32_read(impl->meta, meta_hdr_offset_index, &hdr_offset);
123         mpp_meta_s32_read(impl->meta, meta_hdr_size_index, &hdr_size);
124 
125         if (hdr_offset && hdr_size) {
126             RK_U8 *src = (RK_U8 *)mpp_buffer_get_ptr(src_buf) + hdr_offset;
127             RK_U8 *dst = (RK_U8 *)mpp_buffer_get_ptr(buf) + hdr_offset;
128 
129             mpp_buffer_sync_ro_partial_begin(src_buf, hdr_offset, hdr_size);
130             memcpy(dst, src, hdr_size);
131             mpp_buffer_sync_partial_end(buf, hdr_offset, hdr_size);
132         }
133     }
134 
135     impl->errinfo |= err;
136 
137     mpp_mutex_cond_lock(&list->cond_lock);
138     mpp_list_add_at_tail(list, &out, sizeof(out));
139 
140     mpp->mFramePutCount++;
141     vproc_dbg_out("Output frame[%d]:poc %d, pts %lld, err 0x%x, dis %x, buf ptr %p\n",
142                   mpp->mFramePutCount, mpp_frame_get_poc(out), mpp_frame_get_pts(out),
143                   mpp_frame_get_errinfo(frame), mpp_frame_get_discard(frame),
144                   mpp_buffer_get_ptr(impl->buffer));
145     mpp_mutex_cond_signal(&list->cond_lock);
146     mpp_mutex_cond_unlock(&list->cond_lock);
147 
148     if (mpp->mDec)
149         mpp_dec_callback(mpp->mDec, MPP_DEC_EVENT_ON_FRM_READY, out);
150 }
151 
dec_vproc_clr_prev0(MppDecVprocCtxImpl * ctx)152 static void dec_vproc_clr_prev0(MppDecVprocCtxImpl *ctx)
153 {
154     if (vproc_debug & VPROC_DBG_STATUS) {
155         if (ctx->prev_frm0) {
156             MppBuffer buf = mpp_frame_get_buffer(ctx->prev_frm0);
157             RK_S32 fd = (buf) ? (mpp_buffer_get_fd(buf)) : (-1);
158             mpp_log("clearing prev index %d frm %p fd %d, poc%d\n", ctx->prev_idx0,
159                     ctx->prev_frm0, fd, mpp_frame_get_poc(ctx->prev_frm0));
160         } else
161             mpp_log("clearing nothing\n");
162     }
163 
164     if (ctx->prev_frm0) {
165         MppBuffer buf = mpp_frame_get_buffer(ctx->prev_frm0);
166         if (buf)
167             mpp_buffer_put(buf);
168     }
169     if (ctx->prev_idx0 >= 0)
170         mpp_buf_slot_clr_flag(ctx->slots, ctx->prev_idx0, SLOT_QUEUE_USE);
171 
172     ctx->prev_idx0 = -1;
173     ctx->prev_frm0 = NULL;
174 }
175 
dec_vproc_clr_prev1(MppDecVprocCtxImpl * ctx)176 static void dec_vproc_clr_prev1(MppDecVprocCtxImpl *ctx)
177 {
178     if (vproc_debug & VPROC_DBG_STATUS) {
179         if (ctx->prev_frm1) {
180             MppBuffer buf = mpp_frame_get_buffer(ctx->prev_frm1);
181             RK_S32 fd = (buf) ? (mpp_buffer_get_fd(buf)) : (-1);
182             mpp_log("clearing prev index %d frm %p fd %d, poc %d\n", ctx->prev_idx1,
183                     ctx->prev_frm1, fd, mpp_frame_get_poc(ctx->prev_frm1));
184         } else
185             mpp_log("clearing nothing\n");
186     }
187     if (ctx->prev_frm1) {
188         MppBuffer buf = mpp_frame_get_buffer(ctx->prev_frm1);
189         if (buf)
190             mpp_buffer_put(buf);
191     }
192     if (ctx->prev_idx1 >= 0)
193         mpp_buf_slot_clr_flag(ctx->slots, ctx->prev_idx1, SLOT_QUEUE_USE);
194 
195     ctx->prev_idx1 = -1;
196     ctx->prev_frm1 = NULL;
197 }
198 
dec_vproc_clr_prev(MppDecVprocCtxImpl * ctx)199 static void dec_vproc_clr_prev(MppDecVprocCtxImpl *ctx)
200 {
201     dec_vproc_clr_prev0(ctx);
202     dec_vproc_clr_prev1(ctx);
203     if (ctx->out_buf0) {
204         mpp_buffer_put(ctx->out_buf0);
205         ctx->out_buf0 = NULL;
206     }
207     if (ctx->out_buf1) {
208         mpp_buffer_put(ctx->out_buf1);
209         ctx->out_buf1 = NULL;
210     }
211 }
212 
dec_vproc_set_img_fmt(IepImg * img,MppFrame frm)213 static void dec_vproc_set_img_fmt(IepImg *img, MppFrame frm)
214 {
215     memset(img, 0, sizeof(*img));
216     img->act_w = mpp_frame_get_width(frm);
217     img->act_h = mpp_frame_get_height(frm);
218     img->vir_w = mpp_frame_get_hor_stride(frm);
219     img->vir_h = mpp_frame_get_ver_stride(frm);
220     img->format = IEP_FORMAT_YCbCr_420_SP;
221 }
222 
dec_vproc_set_img(MppDecVprocCtxImpl * ctx,IepImg * img,RK_S32 fd,IepCmd cmd)223 static void dec_vproc_set_img(MppDecVprocCtxImpl *ctx, IepImg *img, RK_S32 fd, IepCmd cmd)
224 {
225     RK_S32 y_size = img->vir_w * img->vir_h;
226     img->mem_addr = fd;
227     img->uv_addr = fd + (y_size << 10);
228     img->v_addr = fd + ((y_size + y_size / 4) << 10);
229 
230     MPP_RET ret = ctx->com_ctx->ops->control(ctx->iep_ctx, cmd, img);
231     if (ret)
232         mpp_log_f("control %08x failed %d\n", cmd, ret);
233 }
234 
dec_vproc_start_dei_v1(MppDecVprocCtx * vproc_ctx,RK_U32 mode)235 static MPP_RET dec_vproc_start_dei_v1(MppDecVprocCtx *vproc_ctx, RK_U32 mode)
236 {
237     MPP_RET ret = MPP_OK;
238     MppDecVprocCtxImpl *impl = (MppDecVprocCtxImpl *) vproc_ctx;
239     impl->dei_cfg.dei_field_order = (mode & MPP_FRAME_FLAG_TOP_FIRST) ?
240                                     (IEP_DEI_FLD_ORDER_TOP_FIRST) :
241                                     (IEP_DEI_FLD_ORDER_BOT_FIRST);
242     ret = impl->com_ctx->ops->control(impl->iep_ctx,
243                                       IEP_CMD_SET_DEI_CFG, &impl->dei_cfg);
244     if (ret)
245         mpp_err_f("IEP_CMD_SET_DEI_CFG failed %d\n", ret);
246 
247     ret = impl->com_ctx->ops->control(impl->iep_ctx, IEP_CMD_RUN_SYNC, &impl->dei_info);
248     if (ret)
249         mpp_err_f("IEP_CMD_RUN_SYNC failed %d\n", ret);
250 
251     return ret;
252 }
253 
dec_vproc_start_dei_v2(MppDecVprocCtx * vproc_ctx,RK_U32 mode)254 static MPP_RET dec_vproc_start_dei_v2(MppDecVprocCtx *vproc_ctx, RK_U32 mode)
255 {
256     MPP_RET ret = MPP_OK;
257     MppDecVprocCtxImpl *impl = (MppDecVprocCtxImpl *) vproc_ctx;
258     (void)mode;
259 
260     ret = impl->com_ctx->ops->control(impl->iep_ctx, IEP_CMD_RUN_SYNC, &impl->dei_info);
261     if (ret)
262         mpp_log_f("IEP_CMD_RUN_SYNC failed %d\n", ret);
263 
264     return ret;
265 }
266 
dec_vproc_set_dei_v1(MppDecVprocCtx * vproc_ctx,MppFrame frm)267 static MPP_RET dec_vproc_set_dei_v1(MppDecVprocCtx *vproc_ctx, MppFrame frm)
268 {
269     MPP_RET ret = MPP_OK;
270     IepImg img;
271     MppDecVprocCtxImpl *ctx = (MppDecVprocCtxImpl *)vproc_ctx;
272 
273     Mpp *mpp = ctx->mpp;
274     RK_U32 mode = mpp_frame_get_mode(frm);
275     MppBuffer buf = mpp_frame_get_buffer(frm);
276     MppBuffer dst0 = ctx->out_buf0;
277     MppBuffer dst1 = ctx->out_buf1;
278     int fd = -1;
279     RK_U32 frame_err = 0;
280 
281     // setup source IepImg
282     dec_vproc_set_img_fmt(&img, frm);
283 
284     ret = ctx->com_ctx->ops->control(ctx->iep_ctx, IEP_CMD_INIT, NULL);
285     if (ret)
286         mpp_log_f("IEP_CMD_INIT failed %d\n", ret);
287 
288     struct IepCap_t *cap = NULL;
289     ret = ctx->com_ctx->ops->control(ctx->iep_ctx, IEP_CMD_QUERY_CAP, &cap);
290     if (ret)
291         mpp_log_f("IEP_CMD_QUERY_CAP failed %d\n", ret);
292 
293     // setup destination IepImg with new buffer
294     // NOTE: when deinterlace is enabled parser thread will reserve
295     //       more buffer than normal case
296     if (ctx->prev_frm0 && cap && cap->i4_deinterlace_supported) {
297         // 4 in 2 out case
298         vproc_dbg_status("4 field in and 2 frame out\n");
299         RK_S64 prev_pts = mpp_frame_get_pts(ctx->prev_frm0);
300         RK_S64 curr_pts = mpp_frame_get_pts(frm);
301         RK_S64 first_pts = (prev_pts + curr_pts) / 2;
302 
303         buf = mpp_frame_get_buffer(ctx->prev_frm0);
304         fd = mpp_buffer_get_fd(buf);
305         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC);
306         frame_err = mpp_frame_get_errinfo(ctx->prev_frm0) ||
307                     mpp_frame_get_discard(ctx->prev_frm0);
308         // setup dst 0
309         mpp_assert(dst0);
310         fd = mpp_buffer_get_fd(dst0);
311         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DST);
312 
313         buf = mpp_frame_get_buffer(frm);
314         fd = mpp_buffer_get_fd(buf);
315         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC1);
316         frame_err |= mpp_frame_get_errinfo(frm) ||
317                      mpp_frame_get_discard(frm);
318         // setup dst 1
319         mpp_assert(dst1);
320         fd = mpp_buffer_get_fd(dst1);
321         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_DST1);
322 
323         ctx->dei_cfg.dei_mode = IEP_DEI_MODE_I4O2;
324 
325         mode = mode | MPP_FRAME_FLAG_IEP_DEI_I4O2;
326         mpp_frame_set_mode(frm, mode);
327 
328         // start hardware
329         ctx->start_dei((MppDecVprocCtx *)ctx, mode);
330 
331         // NOTE: we need to process pts here
332         if (mode & MPP_FRAME_FLAG_TOP_FIRST) {
333             dec_vproc_put_frame(mpp, frm, dst0, first_pts, frame_err);
334             dec_vproc_put_frame(mpp, frm, dst1, curr_pts, frame_err);
335         } else {
336             dec_vproc_put_frame(mpp, frm, dst1, first_pts, frame_err);
337             dec_vproc_put_frame(mpp, frm, dst0, curr_pts, frame_err);
338         }
339         ctx->out_buf0 = NULL;
340         ctx->out_buf1 = NULL;
341     } else {
342         // 2 in 1 out case
343         vproc_dbg_status("2 field in and 1 frame out\n");
344         buf = mpp_frame_get_buffer(frm);
345         fd = mpp_buffer_get_fd(buf);
346         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC);
347         frame_err = mpp_frame_get_errinfo(frm) ||
348                     mpp_frame_get_discard(frm);
349 
350         // setup dst 0
351         mpp_assert(dst0);
352         fd = mpp_buffer_get_fd(dst0);
353         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DST);
354 
355         ctx->dei_cfg.dei_mode = IEP_DEI_MODE_I2O1;
356         mode = mode | MPP_FRAME_FLAG_IEP_DEI_I2O1;
357         mpp_frame_set_mode(frm, mode);
358 
359         // start hardware
360         ctx->start_dei((MppDecVprocCtx *)ctx, mode);
361         dec_vproc_put_frame(mpp, frm, dst0, -1, frame_err);
362         ctx->out_buf0 = NULL;
363     }
364 
365     return ret;
366 }
367 
368 #if DUMP_FILE
dump_mppbuffer(MppBuffer buf,const char * fname,int stride,int height)369 static void dump_mppbuffer(MppBuffer buf, const char *fname, int stride, int height)
370 {
371     char title[256];
372     void *ptr = mpp_buffer_get_ptr(buf);
373     sprintf(title, "%s.%dx%d.yuv", fname, stride, height);
374     FILE *dump = fopen(title, "ab+");
375 
376     if (dump) {
377         fwrite(ptr, 1, stride * height * 3 / 2, dump);
378         fclose(dump);
379     }
380 }
381 #else
382 #define dump_mppbuffer(...)
383 #endif
384 
dec_vproc_config_dei_v2(MppDecVprocCtxImpl * ctx,MppFrame frm,enum IEP2_DIL_MODE dil_mode)385 static MPP_RET dec_vproc_config_dei_v2(MppDecVprocCtxImpl *ctx, MppFrame frm,
386                                        enum IEP2_DIL_MODE dil_mode)
387 {
388     MPP_RET ret = MPP_OK;
389     MppBuffer buf = NULL;
390     RK_S32 fd = -1;
391     IepImg img;
392     struct iep2_api_params params;
393     iep_com_ops *ops = ctx->com_ctx->ops;
394 
395     if (!frm) {
396         mpp_err("found NULL pointer frm\n");
397         ret = MPP_ERR_NULL_PTR;
398         return ret;
399     }
400 
401     /* default alloc 2 out buffer for IEP */
402     if (!ctx->out_buf0 || !ctx->out_buf1) {
403         mpp_err("found NULL pointer out_buf0 %p out_buf1 %p\n", ctx->out_buf0, ctx->out_buf1);
404         ret = MPP_ERR_NULL_PTR;
405         return ret;
406     }
407 
408     // setup source IepImg
409     dec_vproc_set_img_fmt(&img, frm);
410 
411     if (vproc_debug & VPROC_DBG_DUMP_IN)
412         dump_mppbuffer(buf, "/data/dump/dump_in.yuv", img.vir_w, img.vir_h);
413 
414     vproc_dbg_status("set dil_mode %d\n", dil_mode);
415     // TODO: check the input frame
416     switch (dil_mode) {
417     case IEP2_DIL_MODE_I5O2:
418     case IEP2_DIL_MODE_I5O1T:
419     case IEP2_DIL_MODE_I5O1B:
420     case IEP2_DIL_MODE_DECT: {
421         // require 3 frames
422         buf = mpp_frame_get_buffer(ctx->prev_frm0);
423         fd = mpp_buffer_get_fd(buf);
424         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC);
425 
426         buf = mpp_frame_get_buffer(frm);
427         fd = mpp_buffer_get_fd(buf);
428         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC1);
429 
430         buf = mpp_frame_get_buffer(ctx->prev_frm1);
431         fd = mpp_buffer_get_fd(buf);
432         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC2);
433     } break;
434     case IEP2_DIL_MODE_PD: {
435         // require 2 frame
436         buf = mpp_frame_get_buffer(frm);
437         fd = mpp_buffer_get_fd(buf);
438         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC1);
439 
440         if (ctx->prev_frm0) {
441             buf = mpp_frame_get_buffer(ctx->prev_frm0);
442             fd = mpp_buffer_get_fd(buf);
443         } else if (ctx->prev_frm1) {
444             buf = mpp_frame_get_buffer(ctx->prev_frm1);
445             fd = mpp_buffer_get_fd(buf);
446         }
447 
448         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC);
449         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC2);
450     } break;
451     case IEP2_DIL_MODE_I2O2:
452     case IEP2_DIL_MODE_I1O1T:
453     case IEP2_DIL_MODE_I1O1B:
454     case IEP2_DIL_MODE_BYPASS:
455     default: {
456         buf = mpp_frame_get_buffer(frm);
457         fd = mpp_buffer_get_fd(buf);
458         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC);
459         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC1);
460         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC2);
461     } break;
462     }
463 
464     // setup output
465     fd = mpp_buffer_get_fd(ctx->out_buf0);
466     dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DST);
467     fd = mpp_buffer_get_fd(ctx->out_buf1);
468     dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_DST1);
469 
470     memset(&params, 0, sizeof(params));
471     params.ptype = IEP2_PARAM_TYPE_MODE;
472     params.param.mode.dil_mode = dil_mode;
473     params.param.mode.out_mode = IEP2_OUT_MODE_LINE;
474     {
475         RK_U32 mode = mpp_frame_get_mode(frm);
476         RK_U32 fo_from_syntax = (mode & MPP_FRAME_FLAG_TOP_FIRST) ? 1 : 0;
477 
478         /* refer to syntax */
479         if ((mode & MPP_FRAME_FLAG_TOP_FIRST) && (mode & MPP_FRAME_FLAG_BOT_FIRST))
480             params.param.mode.dil_order = IEP2_FIELD_ORDER_UND;
481         else if (fo_from_syntax)
482             params.param.mode.dil_order = IEP2_FIELD_ORDER_TFF;
483         else
484             params.param.mode.dil_order = IEP2_FIELD_ORDER_BFF;
485 
486         /* refer to IEP */
487         if (ctx->pre_ff_mode == IEP2_FF_MODE_FIELD) {
488             RK_U32 fo_from_iep = (ctx->dei_info.dil_order == IEP2_FIELD_ORDER_UND) ?
489                                  fo_from_syntax : (ctx->dei_info.dil_order == IEP2_FIELD_ORDER_TFF);
490             RK_U32 is_tff = 0;
491 
492             if (fo_from_iep != fo_from_syntax) {
493                 if (ctx->dei_info.dil_order_confidence_ratio > 30)
494                     is_tff = fo_from_iep;
495                 else
496                     is_tff = fo_from_syntax;
497             } else {
498                 is_tff = fo_from_syntax;
499             }
500 
501             if (is_tff)
502                 params.param.mode.dil_order = IEP2_FIELD_ORDER_TFF;
503             else
504                 params.param.mode.dil_order = IEP2_FIELD_ORDER_BFF;
505 
506             vproc_dbg_status("Config field order: is TFF %d, syn %d vs iep %d\n",
507                              is_tff, fo_from_syntax, fo_from_iep);
508         }
509     }
510     ops->control(ctx->iep_ctx, IEP_CMD_SET_DEI_CFG, &params);
511 
512     memset(&params, 0, sizeof(params));
513     params.ptype = IEP2_PARAM_TYPE_COM;
514     params.param.com.sfmt = IEP2_FMT_YUV420;
515     params.param.com.dfmt = IEP2_FMT_YUV420;
516     params.param.com.sswap = IEP2_YUV_SWAP_SP_UV;
517     params.param.com.dswap = IEP2_YUV_SWAP_SP_UV;
518     params.param.com.width = img.act_w;
519     params.param.com.height = img.act_h;
520     params.param.com.hor_stride = img.vir_w;//img.act_w;
521     ops->control(ctx->iep_ctx, IEP_CMD_SET_DEI_CFG, &params);
522 
523     return MPP_OK;
524 }
525 
dec_vproc_output_dei_v2(MppDecVprocCtxImpl * ctx,MppFrame frm,RK_U32 is_frm)526 MPP_RET dec_vproc_output_dei_v2(MppDecVprocCtxImpl *ctx, MppFrame frm, RK_U32 is_frm)
527 {
528     MPP_RET ret = MPP_OK;
529     Mpp *mpp = ctx->mpp;
530     RK_U32 hor_stride = mpp_frame_get_hor_stride(frm);
531     RK_U32 ver_stride = mpp_frame_get_ver_stride(frm);
532     RK_U32 mode = mpp_frame_get_mode(frm);
533     RK_U32 dei_mode = mode & MPP_FRAME_FLAG_IEP_DEI_MASK;
534     MppBuffer dst0 = ctx->out_buf0;
535     MppBuffer dst1 = ctx->out_buf1;
536     RK_U32 frame_err = 0;
537 
538     vproc_dbg_status("is_frm %d frm %p, dei_mode %d field0 %p field1 %p",
539                      is_frm, ctx->prev_frm1, dei_mode, dst0, dst1);
540     if (is_frm) {
541         if (ctx->prev_frm1) {
542             vproc_dbg_out("output frame prev1 poc %d\n", mpp_frame_get_poc(ctx->prev_frm1));
543             dec_vproc_put_frame(mpp,  ctx->prev_frm1, NULL, -1, 0);
544             if (ctx->prev_idx1 >= 0)
545                 mpp_buf_slot_clr_flag(ctx->slots, ctx->prev_idx1, SLOT_QUEUE_USE);
546             ctx->prev_idx1 = -1;
547             ctx->prev_frm1 = NULL;
548         }
549         return ret;
550     }
551 
552     switch (dei_mode) {
553     case MPP_FRAME_FLAG_IEP_DEI_I4O2: {
554         RK_S64 prev_pts = mpp_frame_get_pts(ctx->prev_frm1);
555         RK_S64 curr_pts = mpp_frame_get_pts(ctx->prev_frm0);
556         RK_S64 first_pts = (prev_pts + curr_pts) / 2;
557 
558         frame_err |= mpp_frame_get_errinfo(ctx->prev_frm0) + mpp_frame_get_discard(ctx->prev_frm0);
559         frame_err |= mpp_frame_get_errinfo(ctx->prev_frm1) + mpp_frame_get_discard(ctx->prev_frm1);
560 
561         if (ctx->pd_mode) {
562             // NOTE: we need to process pts here if PD mode
563             if (ctx->dei_info.pd_flag != PD_COMP_FLAG_NON &&
564                 ctx->dei_info.pd_types != PD_TYPES_UNKNOWN) {
565                 vproc_dbg_out("output at pd mode, frame poc %d\n", mpp_frame_get_poc(frm));
566                 dec_vproc_put_frame(mpp, frm, dst0, first_pts, frame_err);
567                 if (vproc_debug & VPROC_DBG_DUMP_OUT)
568                     dump_mppbuffer(dst0, "/data/dump/dump_output.yuv", hor_stride, ver_stride);
569                 ctx->out_buf0 = NULL;
570             }
571         } else {
572             RK_U32 fo_from_syntax = (mode & MPP_FRAME_FLAG_TOP_FIRST) ? 1 : 0;
573             RK_U32 fo_from_iep = (ctx->dei_info.dil_order == IEP2_FIELD_ORDER_UND) ?
574                                  fo_from_syntax : (ctx->dei_info.dil_order == IEP2_FIELD_ORDER_TFF);
575             RK_U32 is_tff = 0;
576 
577             if (fo_from_iep != fo_from_syntax) {
578                 if (ctx->dei_info.dil_order_confidence_ratio > 30)
579                     is_tff = fo_from_iep;
580                 else
581                     is_tff = fo_from_syntax;
582             } else {
583                 is_tff = fo_from_syntax;
584             }
585 
586             vproc_dbg_status("Output field order: is TFF %d, syn %d vs iep %d\n",
587                              is_tff, fo_from_syntax, fo_from_iep);
588 
589             if (is_tff) {
590                 vproc_dbg_out("output at I4O2 for tff, frame poc %d\n", mpp_frame_get_poc(frm));
591                 dec_vproc_put_frame(mpp, frm, dst0, first_pts, frame_err);
592                 if (vproc_debug & VPROC_DBG_DUMP_OUT)
593                     dump_mppbuffer(dst0, "/data/dump/dump_output.yuv", hor_stride, ver_stride);
594                 vproc_dbg_out("output at I4O2 for bff, frame poc %d\n", mpp_frame_get_poc(frm));
595                 dec_vproc_put_frame(mpp, frm, dst1, curr_pts, frame_err);
596                 if (vproc_debug & VPROC_DBG_DUMP_OUT)
597                     dump_mppbuffer(dst1, "/data/dump/dump_output.yuv", hor_stride, ver_stride);
598             } else {
599                 vproc_dbg_out("output at I4O2 for bff, frame poc %d\n", mpp_frame_get_poc(frm));
600                 dec_vproc_put_frame(mpp, frm, dst1, first_pts, frame_err);
601                 if (vproc_debug & VPROC_DBG_DUMP_OUT)
602                     dump_mppbuffer(dst1, "/data/dump/dump_output.yuv", hor_stride, mpp_frame_get_height(frm));
603                 vproc_dbg_out("output at I4O2 for tff, frame poc %d\n", mpp_frame_get_poc(frm));
604                 dec_vproc_put_frame(mpp, frm, dst0, curr_pts, frame_err);
605                 if (vproc_debug & VPROC_DBG_DUMP_OUT)
606                     dump_mppbuffer(dst0, "/data/dump/dump_output.yuv", hor_stride, mpp_frame_get_height(frm));
607             }
608 
609             ctx->out_buf0 = NULL;
610             ctx->out_buf1 = NULL;
611         }
612     } break;
613     case MPP_FRAME_FLAG_IEP_DEI_I2O1:
614     case MPP_FRAME_FLAG_IEP_DEI_I4O1: {
615         vproc_dbg_out("output at I2O1, frame poc %d\n", mpp_frame_get_poc(frm));
616         dec_vproc_put_frame(mpp, frm, dst0, -1, frame_err);
617         if (vproc_debug & VPROC_DBG_DUMP_OUT)
618             dump_mppbuffer(dst0, "/data/dump/dump_output.yuv", hor_stride, mpp_frame_get_height(frm));
619         ctx->out_buf0 = NULL;
620     }
621     default:
622         break;
623     }
624 
625     return ret;
626 }
627 
dec_vproc_dei_v2_deinterlace(MppDecVprocCtxImpl * ctx,MppFrame frm)628 static MPP_RET dec_vproc_dei_v2_deinterlace(MppDecVprocCtxImpl *ctx, MppFrame frm)
629 {
630     MPP_RET ret = MPP_OK;
631     RK_U32 mode = mpp_frame_get_mode(frm);
632     enum IEP2_DIL_MODE dil_mode = IEP2_DIL_MODE_DISABLE;
633 
634     /* refer to syntax */
635     if (((mode & MPP_FRAME_FLAG_PAIRED_FIELD) == MPP_FRAME_FLAG_FRAME) &&
636         !(mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK))
637         return dec_vproc_output_dei_v2(ctx, frm, 1);
638 
639     if (ctx->prev_frm1 && ctx->prev_frm0) {
640         // 5 in 2 out case
641         vproc_dbg_status("5 field in and 2 frame out\n");
642 
643         if (!ctx->pd_mode)
644             dil_mode = IEP2_DIL_MODE_I5O2;
645         else
646             dil_mode = IEP2_DIL_MODE_PD;
647 
648         dec_vproc_config_dei_v2(ctx, frm, dil_mode);
649 
650         mode = mode | MPP_FRAME_FLAG_IEP_DEI_I4O2;
651         mpp_frame_set_mode(frm, mode);
652         // start hardware
653         ctx->start_dei((MppDecVprocCtx *)ctx, mode);
654 
655         dec_vproc_output_dei_v2(ctx, frm, 0);
656 
657         if (ctx->dei_info.pd_types == PD_TYPES_UNKNOWN)
658             ctx->pd_mode = 0;
659         else
660             ctx->pd_mode = 1;
661 
662     } else if (ctx->prev_frm0 && ! ctx->prev_frm1) {
663         vproc_dbg_status("Wait for next frame to turn into I5O2");
664 
665         if (ctx->out_buf0) {
666             mpp_buffer_put(ctx->out_buf0);
667             ctx->out_buf0 = NULL;
668         }
669 
670         if (ctx->out_buf1) {
671             mpp_buffer_put(ctx->out_buf1);
672             ctx->out_buf1 = NULL;
673         }
674     } else {
675         // 2 in 1 out case
676         vproc_dbg_status("2 field in and 1 frame out\n");
677         dil_mode = IEP2_DIL_MODE_I1O1T;
678 
679         dec_vproc_config_dei_v2(ctx, frm, dil_mode);
680 
681         mode = mode | MPP_FRAME_FLAG_IEP_DEI_I2O1;
682         mpp_frame_set_mode(frm, mode);
683         // start hardware
684         ctx->start_dei((MppDecVprocCtx *)ctx, mode);
685 
686         dec_vproc_output_dei_v2(ctx, frm, 0);
687     }
688 
689     return ret;
690 }
691 
dec_vproc_dei_v2_detection(MppDecVprocCtxImpl * ctx,MppFrame frm)692 static MPP_RET dec_vproc_dei_v2_detection(MppDecVprocCtxImpl *ctx, MppFrame frm)
693 {
694     MPP_RET ret = MPP_OK;
695     RK_U32 mode = mpp_frame_get_mode(frm);
696     enum IEP2_DIL_MODE dil_mode = IEP2_DIL_MODE_DISABLE;
697     RK_U32 is_frame = 0;
698 
699     if (ctx->pre_ff_mode == IEP2_FF_MODE_UND) {
700         if (((mode & MPP_FRAME_FLAG_PAIRED_FIELD) == MPP_FRAME_FLAG_FRAME) &&
701             !(mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK))
702             is_frame = 1;
703         else
704             is_frame = 0;
705     } else {
706         is_frame = ctx->pre_ff_mode == IEP2_FF_MODE_FRAME ? 1 : 0;
707     }
708 
709     /* TODO: diff detection strategy */
710     if (ctx->prev_frm1 && ctx->prev_frm0) {
711         // 5 in 2 out case
712         vproc_dbg_status("5 field in and 2 frame out\n");
713 
714         if (!ctx->pd_mode)
715             dil_mode = IEP2_DIL_MODE_I5O2;
716         else
717             dil_mode = IEP2_DIL_MODE_PD;
718 
719         dec_vproc_config_dei_v2(ctx, frm, dil_mode);
720 
721         // start hardware
722         ctx->start_dei((MppDecVprocCtx *)ctx, mode);
723 
724         if (ctx->dei_info.frm_mode == IEP2_FF_MODE_FRAME) {
725             is_frame = 1;
726         } else if (ctx->dei_info.pd_types == PD_TYPES_UNKNOWN) {
727             ctx->pd_mode = 0;
728             is_frame = 0;
729         } else {
730             ctx->pd_mode = 1;
731             is_frame = 0;
732         }
733 
734         if (!is_frame) {
735             mode = mode | MPP_FRAME_FLAG_IEP_DEI_I4O2;
736             mpp_frame_set_mode(frm, mode);
737         }
738     } else if (ctx->prev_frm0 && ! ctx->prev_frm1) {
739         vproc_dbg_status("Wait for next frame to turn into I5O2");
740 
741         if (ctx->out_buf0) {
742             mpp_buffer_put(ctx->out_buf0);
743             ctx->out_buf0 = NULL;
744         }
745 
746         if (ctx->out_buf1) {
747             mpp_buffer_put(ctx->out_buf1);
748             ctx->out_buf1 = NULL;
749         }
750     } else {
751         // 2 in 1 out case
752         vproc_dbg_status("2 field in and 1 frame out\n");
753         dil_mode = IEP2_DIL_MODE_I1O1T;
754 
755         dec_vproc_config_dei_v2(ctx, frm, dil_mode);
756 
757         mode = mode | MPP_FRAME_FLAG_IEP_DEI_I2O1;
758         mpp_frame_set_mode(frm, mode);
759         // start hardware
760         ctx->start_dei((MppDecVprocCtx *)ctx, mode);
761     }
762 
763     ret = dec_vproc_output_dei_v2(ctx, frm, is_frame);
764     ctx->pre_ff_mode = ctx->dei_info.frm_mode;
765 
766     return ret;
767 }
768 
dec_vproc_set_dei_v2(MppDecVprocCtx * vproc_ctx,MppFrame frm)769 static MPP_RET dec_vproc_set_dei_v2(MppDecVprocCtx *vproc_ctx, MppFrame frm)
770 {
771     MPP_RET ret = MPP_OK;
772     MppDecVprocCtxImpl *ctx = (MppDecVprocCtxImpl *)vproc_ctx;
773     /*     RK_U32 mode = mpp_frame_get_mode(frm);
774         enum IEP2_DIL_MODE dil_mode = IEP2_DIL_MODE_DISABLE; */
775     MppVprocMode vproc_mode = ctx->vproc_mode;
776 
777     switch (vproc_mode) {
778     case MPP_VPROC_MODE_DETECTION: {
779         dec_vproc_dei_v2_detection(ctx, frm);
780     } break;
781     case MPP_VPROC_MODE_DEINTELACE: {
782         dec_vproc_dei_v2_deinterlace(ctx, frm);
783     } break;
784     default: {
785         mpp_err("warning: vproc mode unknown!\n");
786         ret = MPP_NOK;
787     } break;
788     }
789 
790     return ret;
791 }
792 
dec_vproc_update_ref_v1(MppDecVprocCtx * vproc_ctx,MppFrame frm,RK_U32 index)793 MPP_RET dec_vproc_update_ref_v1(MppDecVprocCtx *vproc_ctx, MppFrame frm, RK_U32 index)
794 {
795     MPP_RET ret = MPP_OK;
796     MppDecVprocCtxImpl *ctx = (MppDecVprocCtxImpl *)vproc_ctx;
797     dec_vproc_clr_prev0(ctx);
798     ctx->prev_idx0 = index;
799     ctx->prev_frm0 = frm;
800 
801     return ret;
802 }
803 
dec_vproc_update_ref_v2(MppDecVprocCtx * vproc_ctx,MppFrame frm,RK_U32 index)804 MPP_RET dec_vproc_update_ref_v2(MppDecVprocCtx *vproc_ctx, MppFrame frm, RK_U32 index)
805 {
806     MPP_RET ret = MPP_OK;
807     MppDecVprocCtxImpl *ctx = (MppDecVprocCtxImpl *)vproc_ctx;
808 
809     dec_vproc_clr_prev1(ctx);
810 
811     ctx->prev_idx1 = ctx->prev_idx0;
812     ctx->prev_idx0 = index;
813     ctx->prev_frm1 = ctx->prev_frm0;
814     ctx->prev_frm0 = frm;
815     return ret;
816 }
817 
dec_vproc_update_ref(MppDecVprocCtxImpl * ctx,MppFrame frm,RK_U32 index,RK_U32 eos)818 static MPP_RET dec_vproc_update_ref(MppDecVprocCtxImpl *ctx, MppFrame frm, RK_U32 index, RK_U32 eos)
819 {
820     MPP_RET ret = MPP_OK;
821     Mpp *mpp = ctx->mpp;
822 
823     ret = ctx->update_ref((MppDecVprocCtx *)ctx, frm, index);
824 
825     if (eos) {
826         mpp_frame_init(&frm);
827         mpp_frame_set_eos(frm, eos);
828         vproc_dbg_out("output at update ref, frame poc %d\n", mpp_frame_get_poc(frm));
829         dec_vproc_put_frame(mpp, frm, NULL, -1, 0);
830         dec_vproc_clr_prev(ctx);
831         mpp_frame_deinit(&frm);
832     }
833     return ret;
834 }
835 
dec_vproc_thread(void * data)836 static void *dec_vproc_thread(void *data)
837 {
838     MppDecVprocCtxImpl *ctx = (MppDecVprocCtxImpl *)data;
839     HalTaskGroup tasks = ctx->task_group;
840     MppThread *thd = ctx->thd;
841     Mpp *mpp = ctx->mpp;
842     MppDecImpl *dec = (MppDecImpl *)mpp->mDec;
843     MppBufSlots slots = dec->frame_slots;
844 
845     HalTaskHnd task = NULL;
846     HalTaskInfo task_info;
847     HalDecVprocTask *task_vproc = &task_info.dec_vproc;
848 
849     mpp_dbg_info("mpp_dec_post_proc_thread started\n");
850 
851     while (1) {
852         MPP_RET ret = MPP_OK;
853 
854         mpp_thread_lock(thd, THREAD_WORK);
855         if (MPP_THREAD_RUNNING != mpp_thread_get_status(thd, THREAD_WORK)) {
856             mpp_thread_unlock(thd, THREAD_WORK);
857             break;
858         }
859 
860         if (ctx->task_wait.val && !ctx->reset) {
861             vproc_dbg_status("vproc thread wait %d", ctx->task_wait.val);
862             mpp_thread_wait(thd, THREAD_WORK);
863         }
864         mpp_thread_unlock(thd, THREAD_WORK);
865 
866         if (!ctx->task_status.task_rdy) {
867             if (hal_task_get_hnd(tasks, TASK_PROCESSING, &task)) {
868                 if (ctx->reset) {
869                     /* reset only on all task finished */
870                     vproc_dbg_reset("reset start\n");
871 
872                     dec_vproc_clr_prev(ctx);
873 
874                     mpp_thread_lock(thd, THREAD_CONTROL);
875                     ctx->reset = 0;
876                     mpp_thread_unlock(thd, THREAD_CONTROL);
877                     sem_post(&ctx->reset_sem);
878                     ctx->task_wait.val = 0;
879 
880                     vproc_dbg_reset("reset done\n");
881                     continue;
882                 }
883 
884                 ctx->task_wait.task_in = 1;
885                 continue;
886             }
887             ctx->task_status.task_rdy = 1;
888             ctx->task_wait.task_in = 0;
889         }
890 
891         if (task) {
892             ret = hal_task_hnd_get_info(task, &task_info);
893 
894             mpp_assert(ret == MPP_OK);
895 
896             RK_S32 index = task_vproc->input;
897             RK_U32 eos = task_vproc->flags.eos;
898             RK_U32 change = task_vproc->flags.info_change;
899             MppFrame frm = NULL;
900 
901             if (eos && index < 0) {
902                 vproc_dbg_status("eos signal\n");
903 
904                 mpp_frame_init(&frm);
905                 mpp_frame_set_eos(frm, eos);
906                 vproc_dbg_out("output at eos, frame poc %d\n", mpp_frame_get_poc(frm));
907                 dec_vproc_put_frame(mpp, frm, NULL, -1, 0);
908                 dec_vproc_clr_prev(ctx);
909                 mpp_frame_deinit(&frm);
910 
911                 hal_task_hnd_set_status(task, TASK_IDLE);
912                 ctx->task_status.task_rdy = 0;
913                 continue;
914             }
915 
916             mpp_buf_slot_get_prop(slots, index, SLOT_FRAME_PTR, &frm);
917 
918             if (change) {
919                 vproc_dbg_status("info change\n");
920                 vproc_dbg_out("output at info change, frame poc %d\n", mpp_frame_get_poc(frm));
921                 dec_vproc_put_frame(mpp, frm, NULL, -1, 0);
922                 dec_vproc_clr_prev(ctx);
923 
924                 if (ctx->com_ctx->ops->reset)
925                     ctx->com_ctx->ops->reset(ctx->iep_ctx);
926 
927                 hal_task_hnd_set_status(task, TASK_IDLE);
928                 ctx->task_status.task_rdy = 0;
929                 continue;
930             }
931             vproc_dbg_status("vproc get buf in");
932             if (!ctx->task_status.buf_rdy && !ctx->reset) {
933                 MppBuffer buf = mpp_frame_get_buffer(frm);
934                 size_t buf_size = mpp_buffer_get_size(buf);
935 
936                 if (!ctx->out_buf0) {
937                     mpp_buffer_get(mpp->mFrameGroup, &ctx->out_buf0, buf_size);
938                     vproc_dbg_out("get out buf0 ptr %p\n", mpp_buffer_get_ptr(ctx->out_buf0));
939                     if (NULL == ctx->out_buf0) {
940                         ctx->task_wait.task_buf_in = 1;
941                         continue;
942                     }
943                 }
944                 if (!ctx->out_buf1) {
945                     mpp_buffer_get(mpp->mFrameGroup, &ctx->out_buf1, buf_size);
946                     vproc_dbg_out("get out buf1 ptr %p\n", mpp_buffer_get_ptr(ctx->out_buf1));
947                     if (NULL == ctx->out_buf1) {
948                         ctx->task_wait.task_buf_in = 1;
949                         continue;
950                     }
951                 }
952                 ctx->task_status.buf_rdy = 1;
953             }
954 
955             RK_S32 tmp = -1;
956             mpp_buf_slot_dequeue(slots, &tmp, QUEUE_DEINTERLACE);
957             mpp_assert(tmp == index);
958 
959             vproc_dbg_status("vproc get buf ready & start process ");
960             if (!ctx->reset && ctx->iep_ctx) {
961                 vproc_dbg_in("processing frame poc %d, mode 0x%x, err %x vs %x, buf slot %x, ptr %p\n",
962                              mpp_frame_get_poc(frm), mpp_frame_get_mode(frm), mpp_frame_get_errinfo(frm),
963                              mpp_frame_get_discard(frm), index, mpp_buffer_get_ptr(mpp_frame_get_buffer(frm)));
964                 ctx->set_dei((MppDecVprocCtx *)ctx, frm);
965             }
966 
967             dec_vproc_update_ref(ctx, frm, index, eos);
968             hal_task_hnd_set_status(task, TASK_IDLE);
969             ctx->task_status.val = 0;
970             ctx->task_wait.val = 0;
971 
972             vproc_dbg_status("vproc task done");
973         }
974     }
975     mpp_dbg_info("mpp_dec_post_proc_thread exited\n");
976 
977     return NULL;
978 }
979 
dec_vproc_init(MppDecVprocCtx * ctx,MppDecVprocCfg * cfg)980 MPP_RET dec_vproc_init(MppDecVprocCtx *ctx, MppDecVprocCfg *cfg)
981 {
982     MPP_RET ret = MPP_OK;
983     if (NULL == ctx || NULL == cfg || NULL == cfg->mpp) {
984         mpp_err_f("found NULL input ctx %p mpp %p\n", ctx, cfg->mpp);
985         return MPP_ERR_NULL_PTR;
986     }
987 
988     vproc_dbg_func("in\n");
989     mpp_env_get_u32("vproc_debug", &vproc_debug, 0);
990 
991     *ctx = NULL;
992 
993     MppDecVprocCtxImpl *p = mpp_calloc(MppDecVprocCtxImpl, 1);
994     if (NULL == p) {
995         mpp_err_f("malloc failed\n");
996         return MPP_ERR_MALLOC;
997     }
998 
999     p->pre_ff_mode = IEP2_FF_MODE_UND;
1000     p->mpp = (Mpp *)cfg->mpp;
1001     p->slots = ((MppDecImpl *)p->mpp->mDec)->frame_slots;
1002     p->thd = mpp_thread_create(dec_vproc_thread, p, "mpp_dec_vproc");
1003     sem_init(&p->reset_sem, 0, 0);
1004     ret = hal_task_group_init(&p->task_group, TASK_BUTT, 4, sizeof(HalDecVprocTask));
1005     if (ret) {
1006         mpp_err_f("create task group failed\n");
1007         mpp_thread_destroy(p->thd);
1008         MPP_FREE(p);
1009         return MPP_ERR_MALLOC;
1010     }
1011     cfg->task_group = p->task_group;
1012 
1013     p->com_ctx = get_iep_ctx();
1014     if (!p->com_ctx) {
1015         mpp_err("failed to require context\n");
1016         mpp_thread_destroy(p->thd);
1017 
1018         if (p->task_group) {
1019             hal_task_group_deinit(p->task_group);
1020             p->task_group = NULL;
1021         }
1022 
1023         MPP_FREE(p);
1024 
1025         return MPP_ERR_MALLOC;
1026     }
1027 
1028     if (p->com_ctx->ver == 1) {
1029         p->start_dei = dec_vproc_start_dei_v1;
1030         p->set_dei = dec_vproc_set_dei_v1;
1031         p->update_ref = dec_vproc_update_ref_v1;
1032     } else {
1033         p->start_dei = dec_vproc_start_dei_v2;
1034         p->set_dei = dec_vproc_set_dei_v2;
1035         p->update_ref = dec_vproc_update_ref_v2;
1036     }
1037 
1038     ret = p->com_ctx->ops->init(&p->com_ctx->priv);
1039     p->iep_ctx = p->com_ctx->priv;
1040     if (!p->thd || ret) {
1041         mpp_err("failed to create context\n");
1042         if (p->thd) {
1043             mpp_thread_destroy(p->thd);
1044             p->thd = NULL;
1045         }
1046 
1047         if (p->iep_ctx)
1048             p->com_ctx->ops->deinit(p->iep_ctx);
1049 
1050         if (p->task_group) {
1051             hal_task_group_deinit(p->task_group);
1052             p->task_group = NULL;
1053         }
1054 
1055         put_iep_ctx(p->com_ctx);
1056 
1057         MPP_FREE(p);
1058     } else {
1059         p->dei_cfg.dei_mode = IEP_DEI_MODE_I2O1;
1060         p->dei_cfg.dei_field_order = IEP_DEI_FLD_ORDER_BOT_FIRST;
1061         /*
1062          * We need to turn off this switch to prevent some areas
1063          * of the video from flickering.
1064          */
1065         p->dei_cfg.dei_high_freq_en = 0;
1066         p->dei_cfg.dei_high_freq_fct = 64;
1067         p->dei_cfg.dei_ei_mode = 0;
1068         p->dei_cfg.dei_ei_smooth = 1;
1069         p->dei_cfg.dei_ei_sel = 0;
1070         p->dei_cfg.dei_ei_radius = 2;
1071 
1072         p->prev_idx0 = -1;
1073         p->prev_frm0 = NULL;
1074         p->prev_idx1 = -1;
1075         p->prev_frm1 = NULL;
1076     }
1077 
1078     *ctx = p;
1079 
1080     vproc_dbg_func("out\n");
1081     return ret;
1082 }
1083 
dec_vproc_get_version(MppDecVprocCtx ctx)1084 RK_U32 dec_vproc_get_version(MppDecVprocCtx ctx)
1085 {
1086     if (NULL == ctx) {
1087         mpp_err_f("found NULL input\n");
1088         return 0;
1089     }
1090 
1091     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
1092     return p->com_ctx->ver;
1093 }
1094 
dec_vproc_set_mode(MppDecVprocCtx ctx,MppVprocMode mode)1095 MPP_RET dec_vproc_set_mode(MppDecVprocCtx ctx, MppVprocMode mode)
1096 {
1097     if (NULL == ctx) {
1098         mpp_err_f("found NULL input\n");
1099         return MPP_ERR_NULL_PTR;
1100     }
1101 
1102     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
1103     p->vproc_mode = mode;
1104     return MPP_OK;
1105 }
1106 
dec_vproc_deinit(MppDecVprocCtx ctx)1107 MPP_RET dec_vproc_deinit(MppDecVprocCtx ctx)
1108 {
1109     if (NULL == ctx) {
1110         mpp_err_f("found NULL input\n");
1111         return MPP_ERR_NULL_PTR;
1112     }
1113     vproc_dbg_func("in\n");
1114 
1115     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
1116     if (p->thd) {
1117         mpp_thread_destroy(p->thd);
1118         p->thd = NULL;
1119     }
1120 
1121     if (p->iep_ctx)
1122         p->com_ctx->ops->deinit(p->iep_ctx);
1123 
1124     if (p->task_group) {
1125         hal_task_group_deinit(p->task_group);
1126         p->task_group = NULL;
1127     }
1128 
1129     if (p->com_ctx) {
1130         put_iep_ctx(p->com_ctx);
1131         p->com_ctx = NULL;
1132     }
1133 
1134     sem_destroy(&p->reset_sem);
1135     mpp_free(p);
1136 
1137     vproc_dbg_func("out\n");
1138     return MPP_OK;
1139 }
1140 
dec_vproc_start(MppDecVprocCtx ctx)1141 MPP_RET dec_vproc_start(MppDecVprocCtx ctx)
1142 {
1143     if (NULL == ctx) {
1144         mpp_err_f("found NULL input\n");
1145         return MPP_ERR_NULL_PTR;
1146     }
1147     vproc_dbg_func("in\n");
1148 
1149     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
1150 
1151     if (p->thd)
1152         mpp_thread_start(p->thd);
1153     else
1154         mpp_err("failed to start dec vproc thread\n");
1155 
1156     vproc_dbg_func("out\n");
1157     return MPP_OK;
1158 }
1159 
dec_vproc_stop(MppDecVprocCtx ctx)1160 MPP_RET dec_vproc_stop(MppDecVprocCtx ctx)
1161 {
1162     if (NULL == ctx) {
1163         mpp_err_f("found NULL input\n");
1164         return MPP_ERR_NULL_PTR;
1165     }
1166     vproc_dbg_func("in\n");
1167 
1168     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
1169 
1170     if (p->thd)
1171         mpp_thread_stop(p->thd);
1172     else
1173         mpp_err("failed to stop dec vproc thread\n");
1174 
1175     vproc_dbg_func("out\n");
1176     return MPP_OK;
1177 }
1178 
dec_vproc_signal(MppDecVprocCtx ctx)1179 MPP_RET dec_vproc_signal(MppDecVprocCtx ctx)
1180 {
1181     if (NULL == ctx) {
1182         mpp_err_f("found NULL input\n");
1183         return MPP_ERR_NULL_PTR;
1184     }
1185     vproc_dbg_func("in\n");
1186 
1187     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
1188     if (p->thd) {
1189         mpp_thread_lock(p->thd, THREAD_WORK);
1190         mpp_thread_signal(p->thd, THREAD_WORK);
1191         mpp_thread_unlock(p->thd, THREAD_WORK);
1192     }
1193 
1194     vproc_dbg_func("out\n");
1195     return MPP_OK;
1196 }
1197 
dec_vproc_reset(MppDecVprocCtx ctx)1198 MPP_RET dec_vproc_reset(MppDecVprocCtx ctx)
1199 {
1200     if (NULL == ctx) {
1201         mpp_err_f("found NULL input\n");
1202         return MPP_ERR_NULL_PTR;
1203     }
1204     vproc_dbg_func("in\n");
1205 
1206     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
1207     if (p->thd) {
1208         MppThread *thd = p->thd;
1209 
1210         vproc_dbg_reset("reset contorl start\n");
1211         // wait reset finished
1212         mpp_thread_lock(thd, THREAD_WORK);
1213         mpp_thread_lock(thd, THREAD_CONTROL);
1214         p->reset = 1;
1215         mpp_thread_signal(thd, THREAD_WORK);
1216         mpp_thread_unlock(thd, THREAD_CONTROL);
1217         mpp_thread_unlock(thd, THREAD_WORK);
1218 
1219         vproc_dbg_reset("reset contorl wait\n");
1220         sem_wait(&p->reset_sem);
1221         vproc_dbg_reset("reset contorl done\n");
1222 
1223         mpp_assert(p->reset == 0);
1224     }
1225 
1226     vproc_dbg_func("out\n");
1227     return MPP_OK;
1228 }
1229