xref: /OK3568_Linux_fs/external/mpp/mpp/vproc/mpp_dec_vproc.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 "mpp_dec_vproc"
18 
19 #include <string.h>
20 
21 #include "mpp_env.h"
22 #include "mpp_mem.h"
23 #include "mpp_common.h"
24 
25 #include "mpp_dec_impl.h"
26 
27 #include "mpp_frame_impl.h"
28 #include "mpp_dec_vproc.h"
29 #include "iep_api.h"
30 #include "iep2_api.h"
31 
32 #define DUMP_FILE 1
33 
34 #define dec_vproc_dbg(flag, fmt, ...) \
35     do { \
36         _mpp_dbg(vproc_debug, flag, fmt, ## __VA_ARGS__); \
37     } while (0)
38 
39 #define vproc_dbg_f(flag, fmt, ...) \
40     do { \
41         _mpp_dbg_f(vproc_debug, flag, fmt, ## __VA_ARGS__); \
42     } while (0)
43 
44 #define VPROC_DBG_FUNCTION      (0x00000001)
45 #define VPROC_DBG_STATUS        (0x00000002)
46 #define VPROC_DBG_RESET         (0x00000004)
47 #define VPROC_DBG_DUMP_IN       (0x00000010)
48 #define VPROC_DBG_DUMP_OUT      (0x00000020)
49 
50 #define vproc_dbg_func(fmt, ...)  \
51     vproc_dbg_f(VPROC_DBG_FUNCTION, fmt, ## __VA_ARGS__);
52 #define vproc_dbg_status(fmt, ...)  \
53     vproc_dbg_f(VPROC_DBG_STATUS, fmt, ## __VA_ARGS__);
54 #define vproc_dbg_reset(fmt, ...)  \
55     vproc_dbg_f(VPROC_DBG_RESET, fmt, ## __VA_ARGS__);
56 
57 RK_U32 vproc_debug = 0;
58 
59 typedef union VprocTaskStatus_u {
60     RK_U32          val;
61     struct {
62         RK_U32      task_rdy      : 1;
63         RK_U32      buf_rdy   : 1;
64     };
65 } VprocTaskStatus;
66 
67 typedef union VprocTaskWait_u {
68     RK_U32          val;
69     struct {
70         RK_U32      task_in      : 1;
71         RK_U32      task_buf_in  : 1;
72     };
73 } VprocTaskWait;
74 
75 typedef struct MppDecVprocCtxImpl_t {
76     Mpp                 *mpp;
77     HalTaskGroup        task_group;
78     MppBufSlots         slots;
79 
80     MppThread           *thd;
81     RK_U32              reset;
82     sem_t               reset_sem;
83 
84     IepCtx              iep_ctx;
85     iep_com_ctx         *com_ctx;
86     IepCmdParamDeiCfg   dei_cfg;
87     iep2_api_info       dei_info;
88 
89     VprocTaskStatus     task_status;
90     VprocTaskWait       task_wait;
91 
92     // slot index for previous frame and current frame
93     RK_S32              prev_idx0;
94     MppFrame            prev_frm0;
95     RK_S32              prev_idx1;
96     MppFrame            prev_frm1;
97     RK_U32              detection;
98     RK_U32              pd_mode;
99     MppBuffer           out_buf0;
100     MppBuffer           out_buf1;
101 } MppDecVprocCtxImpl;
102 
dec_vproc_put_frame(Mpp * mpp,MppFrame frame,MppBuffer buf,RK_S64 pts,RK_U32 err)103 static void dec_vproc_put_frame(Mpp *mpp, MppFrame frame, MppBuffer buf, RK_S64 pts, RK_U32 err)
104 {
105     mpp_list *list = mpp->mFrmOut;
106     MppFrame out = NULL;
107     MppFrameImpl *impl = NULL;
108 
109     mpp_frame_init(&out);
110     mpp_frame_copy(out, frame);
111     mpp_frame_set_errinfo(out, err);
112     impl = (MppFrameImpl *)out;
113     if (pts >= 0)
114         impl->pts = pts;
115     if (buf)
116         impl->buffer = buf;
117 
118     list->lock();
119     list->add_at_tail(&out, sizeof(out));
120 
121     mpp_dbg_pts("output frame pts %lld\n", mpp_frame_get_pts(out));
122 
123     mpp->mFramePutCount++;
124     list->signal();
125     list->unlock();
126 
127     if (mpp->mDec)
128         mpp_dec_callback(mpp->mDec, MPP_DEC_EVENT_ON_FRM_READY, out);
129 }
130 
dec_vproc_clr_prev0(MppDecVprocCtxImpl * ctx)131 static void dec_vproc_clr_prev0(MppDecVprocCtxImpl *ctx)
132 {
133     if (vproc_debug & VPROC_DBG_STATUS) {
134         if (ctx->prev_frm0) {
135             MppBuffer buf = mpp_frame_get_buffer(ctx->prev_frm0);
136             RK_S32 fd = (buf) ? (mpp_buffer_get_fd(buf)) : (-1);
137             mpp_log("clearing prev index %d frm %p fd %d\n", ctx->prev_idx0,
138                     ctx->prev_frm0, fd);
139         } else
140             mpp_log("clearing nothing\n");
141     }
142 
143     if (ctx->prev_frm0) {
144         MppBuffer buf = mpp_frame_get_buffer(ctx->prev_frm0);
145         if (buf)
146             mpp_buffer_put(buf);
147     }
148     if (ctx->prev_idx0 >= 0)
149         mpp_buf_slot_clr_flag(ctx->slots, ctx->prev_idx0, SLOT_QUEUE_USE);
150 
151     ctx->prev_idx0 = -1;
152     ctx->prev_frm0 = NULL;
153 }
154 
dec_vproc_clr_prev1(MppDecVprocCtxImpl * ctx)155 static void dec_vproc_clr_prev1(MppDecVprocCtxImpl *ctx)
156 {
157     if (vproc_debug & VPROC_DBG_STATUS) {
158         if (ctx->prev_frm1) {
159             MppBuffer buf = mpp_frame_get_buffer(ctx->prev_frm1);
160             RK_S32 fd = (buf) ? (mpp_buffer_get_fd(buf)) : (-1);
161             mpp_log("clearing prev index %d frm %p fd %d\n", ctx->prev_idx1,
162                     ctx->prev_frm1, fd);
163         } else
164             mpp_log("clearing nothing\n");
165     }
166     if (ctx->prev_frm1) {
167         MppBuffer buf = mpp_frame_get_buffer(ctx->prev_frm1);
168         if (buf)
169             mpp_buffer_put(buf);
170     }
171     if (ctx->prev_idx1 >= 0)
172         mpp_buf_slot_clr_flag(ctx->slots, ctx->prev_idx1, SLOT_QUEUE_USE);
173 
174     ctx->prev_idx1 = -1;
175     ctx->prev_frm1 = NULL;
176 }
177 
dec_vproc_clr_prev(MppDecVprocCtxImpl * ctx)178 static void dec_vproc_clr_prev(MppDecVprocCtxImpl *ctx)
179 {
180     dec_vproc_clr_prev0(ctx);
181     dec_vproc_clr_prev1(ctx);
182     if (ctx->out_buf0) {
183         mpp_buffer_put(ctx->out_buf0);
184         ctx->out_buf0 = NULL;
185     }
186     if (ctx->out_buf1) {
187         mpp_buffer_put(ctx->out_buf1);
188         ctx->out_buf1 = NULL;
189     }
190 }
191 
dec_vproc_set_img_fmt(IepImg * img,MppFrame frm)192 static void dec_vproc_set_img_fmt(IepImg *img, MppFrame frm)
193 {
194     memset(img, 0, sizeof(*img));
195     img->act_w = mpp_frame_get_width(frm);
196     img->act_h = mpp_frame_get_height(frm);
197     img->vir_w = mpp_frame_get_hor_stride(frm);
198     img->vir_h = mpp_frame_get_ver_stride(frm);
199     img->format = IEP_FORMAT_YCbCr_420_SP;
200 }
201 
dec_vproc_set_img(MppDecVprocCtxImpl * ctx,IepImg * img,RK_S32 fd,IepCmd cmd)202 static void dec_vproc_set_img(MppDecVprocCtxImpl *ctx, IepImg *img, RK_S32 fd, IepCmd cmd)
203 {
204     RK_S32 y_size = img->vir_w * img->vir_h;
205     img->mem_addr = fd;
206     img->uv_addr = fd + (y_size << 10);
207     img->v_addr = fd + ((y_size + y_size / 4) << 10);
208 
209     MPP_RET ret = ctx->com_ctx->ops->control(ctx->iep_ctx, cmd, img);
210     if (ret)
211         mpp_log_f("control %08x failed %d\n", cmd, ret);
212 }
213 
214 // start deinterlace hardware
dec_vproc_start_dei(MppDecVprocCtxImpl * ctx,RK_U32 mode)215 static void dec_vproc_start_dei(MppDecVprocCtxImpl *ctx, RK_U32 mode)
216 {
217     MPP_RET ret;
218 
219     if (ctx->com_ctx->ver == 1) {
220         ctx->dei_cfg.dei_field_order =
221             (mode & MPP_FRAME_FLAG_TOP_FIRST) ?
222             (IEP_DEI_FLD_ORDER_TOP_FIRST) :
223             (IEP_DEI_FLD_ORDER_BOT_FIRST);
224 
225         ret = ctx->com_ctx->ops->control(ctx->iep_ctx,
226                                          IEP_CMD_SET_DEI_CFG, &ctx->dei_cfg);
227         if (ret)
228             mpp_log_f("IEP_CMD_SET_DEI_CFG failed %d\n", ret);
229     }
230 
231     ret = ctx->com_ctx->ops->control(ctx->iep_ctx, IEP_CMD_RUN_SYNC, &ctx->dei_info);
232     if (ret)
233         mpp_log_f("IEP_CMD_RUN_SYNC failed %d\n", ret);
234 }
235 
dec_vproc_set_dei_v1(MppDecVprocCtxImpl * ctx,MppFrame frm)236 static void dec_vproc_set_dei_v1(MppDecVprocCtxImpl *ctx, MppFrame frm)
237 {
238     MPP_RET ret = MPP_OK;
239     IepImg img;
240 
241     Mpp *mpp = ctx->mpp;
242     RK_U32 mode = mpp_frame_get_mode(frm);
243     MppBuffer buf = mpp_frame_get_buffer(frm);
244     MppBuffer dst0 = ctx->out_buf0;
245     MppBuffer dst1 = ctx->out_buf1;
246     int fd = -1;
247     RK_U32 frame_err = 0;
248 
249     // setup source IepImg
250     dec_vproc_set_img_fmt(&img, frm);
251 
252     ret = ctx->com_ctx->ops->control(ctx->iep_ctx, IEP_CMD_INIT, NULL);
253     if (ret)
254         mpp_log_f("IEP_CMD_INIT failed %d\n", ret);
255 
256     IepCap_t *cap = NULL;
257     ret = ctx->com_ctx->ops->control(ctx->iep_ctx, IEP_CMD_QUERY_CAP, &cap);
258     if (ret)
259         mpp_log_f("IEP_CMD_QUERY_CAP failed %d\n", ret);
260 
261     // setup destination IepImg with new buffer
262     // NOTE: when deinterlace is enabled parser thread will reserve
263     //       more buffer than normal case
264     if (ctx->prev_frm0 && cap && cap->i4_deinterlace_supported) {
265         // 4 in 2 out case
266         vproc_dbg_status("4 field in and 2 frame out\n");
267         RK_S64 prev_pts = mpp_frame_get_pts(ctx->prev_frm0);
268         RK_S64 curr_pts = mpp_frame_get_pts(frm);
269         RK_S64 first_pts = (prev_pts + curr_pts) / 2;
270 
271         buf = mpp_frame_get_buffer(ctx->prev_frm0);
272         fd = mpp_buffer_get_fd(buf);
273         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC);
274         frame_err = mpp_frame_get_errinfo(ctx->prev_frm0) ||
275                     mpp_frame_get_discard(ctx->prev_frm0);
276         // setup dst 0
277         mpp_assert(dst0);
278         fd = mpp_buffer_get_fd(dst0);
279         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DST);
280 
281         buf = mpp_frame_get_buffer(frm);
282         fd = mpp_buffer_get_fd(buf);
283         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC1);
284         frame_err |= mpp_frame_get_errinfo(frm) ||
285                      mpp_frame_get_discard(frm);
286         // setup dst 1
287         mpp_assert(dst1);
288         fd = mpp_buffer_get_fd(dst1);
289         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_DST1);
290 
291         ctx->dei_cfg.dei_mode = IEP_DEI_MODE_I4O2;
292 
293         mode = mode | MPP_FRAME_FLAG_IEP_DEI_I4O2;
294         mpp_frame_set_mode(frm, mode);
295 
296         // start hardware
297         dec_vproc_start_dei(ctx, mode);
298 
299         // NOTE: we need to process pts here
300         if (mode & MPP_FRAME_FLAG_TOP_FIRST) {
301             dec_vproc_put_frame(mpp, frm, dst0, first_pts, frame_err);
302             dec_vproc_put_frame(mpp, frm, dst1, curr_pts, frame_err);
303         } else {
304             dec_vproc_put_frame(mpp, frm, dst1, first_pts, frame_err);
305             dec_vproc_put_frame(mpp, frm, dst0, curr_pts, frame_err);
306         }
307         ctx->out_buf0 = NULL;
308         ctx->out_buf1 = NULL;
309     } else {
310         // 2 in 1 out case
311         vproc_dbg_status("2 field in and 1 frame out\n");
312         buf = mpp_frame_get_buffer(frm);
313         fd = mpp_buffer_get_fd(buf);
314         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC);
315         frame_err = mpp_frame_get_errinfo(frm) ||
316                     mpp_frame_get_discard(frm);
317 
318         // setup dst 0
319         mpp_assert(dst0);
320         fd = mpp_buffer_get_fd(dst0);
321         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DST);
322 
323         ctx->dei_cfg.dei_mode = IEP_DEI_MODE_I2O1;
324         mode = mode | MPP_FRAME_FLAG_IEP_DEI_I2O1;
325         mpp_frame_set_mode(frm, mode);
326 
327         // start hardware
328         dec_vproc_start_dei(ctx, mode);
329         dec_vproc_put_frame(mpp, frm, dst0, -1, frame_err);
330         ctx->out_buf0 = NULL;
331     }
332 }
333 
334 #if DUMP_FILE
dump_mppbuffer(MppBuffer buf,const char * fname,int stride,int height)335 static void dump_mppbuffer(MppBuffer buf, const char *fname, int stride, int height)
336 {
337     char title[256];
338     void *ptr = mpp_buffer_get_ptr(buf);
339     sprintf(title, "%s.%dx%d.yuv", fname, stride, height);
340     FILE *dump = fopen(title, "ab+");
341 
342     if (dump) {
343         fwrite(ptr, 1, stride * height * 3 / 2, dump);
344         fclose(dump);
345     }
346 }
347 #else
348 #define dump_mppbuffer(...)
349 #endif
350 
dec_vproc_set_dei_v2(MppDecVprocCtxImpl * ctx,MppFrame frm)351 static void dec_vproc_set_dei_v2(MppDecVprocCtxImpl *ctx, MppFrame frm)
352 {
353     IepImg img;
354 
355     Mpp *mpp = ctx->mpp;
356     RK_U32 mode = mpp_frame_get_mode(frm);
357     MppBuffer buf = mpp_frame_get_buffer(frm);
358     MppBuffer dst0 = ctx->out_buf0;
359     MppBuffer dst1 = ctx->out_buf1;
360     RK_U32 hor_stride = mpp_frame_get_hor_stride(frm);
361     RK_U32 ver_stride = mpp_frame_get_ver_stride(frm);
362     int fd = -1;
363     iep_com_ops *ops = ctx->com_ctx->ops;
364     RK_U32 frame_err = 0;
365 
366     // setup source IepImg
367     dec_vproc_set_img_fmt(&img, frm);
368 
369     if (vproc_debug & VPROC_DBG_DUMP_IN)
370         dump_mppbuffer(buf, "/data/dump/dump_in.yuv", hor_stride, ver_stride);
371 
372     if (ctx->prev_frm1 && ctx->prev_frm0) {
373 
374         struct iep2_api_params params;
375 
376         // 5 in 2 out case
377         vproc_dbg_status("5 field in and 2 frame out\n");
378         RK_S64 prev_pts = mpp_frame_get_pts(ctx->prev_frm1);
379         RK_S64 curr_pts = mpp_frame_get_pts(ctx->prev_frm0);
380         RK_S64 first_pts = (prev_pts + curr_pts) / 2;
381 
382         // setup source frames
383         buf = mpp_frame_get_buffer(ctx->prev_frm0);
384         fd = mpp_buffer_get_fd(buf);
385         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC);
386         frame_err = mpp_frame_get_errinfo(ctx->prev_frm0) ||
387                     mpp_frame_get_discard(ctx->prev_frm0);
388 
389         buf = mpp_frame_get_buffer(frm);
390         fd = mpp_buffer_get_fd(buf);
391         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC1);
392         frame_err |= mpp_frame_get_errinfo(frm) ||
393                      mpp_frame_get_discard(frm);
394 
395         buf = mpp_frame_get_buffer(ctx->prev_frm1);
396         fd = mpp_buffer_get_fd(buf);
397         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC2);
398         frame_err |= mpp_frame_get_errinfo(ctx->prev_frm1) ||
399                      mpp_frame_get_discard(ctx->prev_frm0);
400 
401         mpp_assert(dst0);
402         fd = mpp_buffer_get_fd(dst0);
403         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DST);
404 
405         mpp_assert(dst1);
406         fd = mpp_buffer_get_fd(dst1);
407         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_DST1);
408 
409         params.ptype = IEP2_PARAM_TYPE_MODE;
410 
411         if (ctx->detection) {
412             params.param.mode.dil_mode = IEP2_DIL_MODE_DECT;
413         } else if (!ctx->pd_mode) {
414             params.param.mode.dil_mode = IEP2_DIL_MODE_I5O2;
415         } else {
416             params.param.mode.dil_mode = IEP2_DIL_MODE_PD;
417         }
418 
419         params.param.mode.out_mode = IEP2_OUT_MODE_LINE;
420         if ((mode & MPP_FRAME_FLAG_TOP_FIRST) && (mode & MPP_FRAME_FLAG_BOT_FIRST))
421             params.param.mode.dil_order = IEP2_FIELD_ORDER_UND;
422         else if (mode & MPP_FRAME_FLAG_BOT_FIRST)
423             params.param.mode.dil_order = IEP2_FIELD_ORDER_BFF;
424         else
425             params.param.mode.dil_order = IEP2_FIELD_ORDER_TFF;
426 
427         ops->control(ctx->iep_ctx, IEP_CMD_SET_DEI_CFG, &params);
428 
429         params.ptype = IEP2_PARAM_TYPE_COM;
430         params.param.com.sfmt = IEP2_FMT_YUV420;
431         params.param.com.dfmt = IEP2_FMT_YUV420;
432         params.param.com.sswap = IEP2_YUV_SWAP_SP_UV;
433         params.param.com.dswap = IEP2_YUV_SWAP_SP_UV;
434         params.param.com.width = mpp_frame_get_width(frm);//img.act_w;
435         params.param.com.hor_stride = hor_stride;//img.act_w;
436         params.param.com.height = ver_stride;
437 
438         ops->control(ctx->iep_ctx, IEP_CMD_SET_DEI_CFG, &params);
439 
440         if (!ctx->detection) {
441             mode = mode | MPP_FRAME_FLAG_IEP_DEI_I4O2;
442             mpp_frame_set_mode(frm, mode);
443         }
444 
445         // start hardware
446         dec_vproc_start_dei(ctx, mode);
447 
448         // NOTE: we need to process pts here
449         if (!ctx->detection) {
450             if (ctx->pd_mode) {
451                 if (ctx->dei_info.pd_flag != PD_COMP_FLAG_NON && ctx->dei_info.pd_types != PD_TYPES_UNKNOWN) {
452                     dec_vproc_put_frame(mpp, frm, dst0, first_pts, frame_err);
453                     if (vproc_debug & VPROC_DBG_DUMP_OUT)
454                         dump_mppbuffer(dst0, "/data/dump/dump_output.yuv", hor_stride, ver_stride);
455                     ctx->out_buf0 = NULL;
456                 }
457             } else {
458                 RK_U32 fo_from_syntax = (mode & MPP_FRAME_FLAG_TOP_FIRST) ? 1 : 0;
459                 RK_U32 fo_from_iep = (ctx->dei_info.dil_order == IEP2_FIELD_ORDER_TFF);
460                 RK_U32 is_tff = 0;
461 
462                 if (fo_from_iep != fo_from_syntax) {
463                     if (ctx->dei_info.dil_order_confidence_ratio > 30)
464                         is_tff = fo_from_iep;
465                     else
466                         is_tff = fo_from_iep;
467                 } else {
468                     is_tff = fo_from_syntax;
469                 }
470 
471                 if (is_tff) {
472                     dec_vproc_put_frame(mpp, frm, dst0, first_pts, frame_err);
473                     if (vproc_debug & VPROC_DBG_DUMP_OUT)
474                         dump_mppbuffer(dst0, "/data/dump/dump_output.yuv", hor_stride, ver_stride);
475                     dec_vproc_put_frame(mpp, frm, dst1, curr_pts, frame_err);
476                     if (vproc_debug & VPROC_DBG_DUMP_OUT)
477                         dump_mppbuffer(dst1, "/data/dump/dump_output.yuv", hor_stride, ver_stride);
478                 } else {
479                     dec_vproc_put_frame(mpp, frm, dst1, first_pts, frame_err);
480                     if (vproc_debug & VPROC_DBG_DUMP_OUT)
481                         dump_mppbuffer(dst1, "/data/dump/dump_output.yuv", hor_stride, mpp_frame_get_height(frm));
482                     dec_vproc_put_frame(mpp, frm, dst0, curr_pts, frame_err);
483                     if (vproc_debug & VPROC_DBG_DUMP_OUT)
484                         dump_mppbuffer(dst0, "/data/dump/dump_output.yuv", hor_stride, mpp_frame_get_height(frm));
485                 }
486                 ctx->out_buf0 = NULL;
487                 ctx->out_buf1 = NULL;
488             }
489         }
490 
491         if (ctx->dei_info.frm_mode) {
492             ctx->detection = 1;
493         } else if (ctx->dei_info.pd_types == PD_TYPES_UNKNOWN) {
494             ctx->pd_mode = 0;
495             ctx->detection = 0;
496         } else {
497             ctx->pd_mode = 1;
498             ctx->detection = 0;
499         }
500     } else if (ctx->prev_frm0 && ! ctx->prev_frm1) {
501         vproc_dbg_status("Wait for next frame to turn into I5O2");
502 
503         if (ctx->out_buf0) {
504             mpp_buffer_put(ctx->out_buf0);
505             ctx->out_buf0 = NULL;
506         }
507 
508         if (ctx->out_buf1) {
509             mpp_buffer_put(ctx->out_buf1);
510             ctx->out_buf1 = NULL;
511         }
512     } else {
513         struct iep2_api_params params;
514 
515         // 2 in 1 out case
516         vproc_dbg_status("2 field in and 1 frame out\n");
517         buf = mpp_frame_get_buffer(frm);
518         fd = mpp_buffer_get_fd(buf);
519         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC);
520         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC1);
521         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC2);
522 
523         frame_err = mpp_frame_get_errinfo(frm) ||
524                     mpp_frame_get_discard(frm);
525 
526         // setup dst 0
527         fd = mpp_buffer_get_fd(dst0);
528         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DST);
529         dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_DST1);
530 
531         params.ptype = IEP2_PARAM_TYPE_MODE;
532         params.param.mode.dil_mode = IEP2_DIL_MODE_I1O1T;
533         params.param.mode.out_mode = IEP2_OUT_MODE_LINE;
534         ops->control(ctx->iep_ctx, IEP_CMD_SET_DEI_CFG, &params);
535 
536         params.ptype = IEP2_PARAM_TYPE_COM;
537         params.param.com.sfmt = IEP2_FMT_YUV420;
538         params.param.com.dfmt = IEP2_FMT_YUV420;
539         params.param.com.sswap = IEP2_YUV_SWAP_SP_UV;
540         params.param.com.dswap = IEP2_YUV_SWAP_SP_UV;
541         params.param.com.width = hor_stride;
542         params.param.com.height = ver_stride;
543         params.param.com.hor_stride = hor_stride;//img.act_w;
544         ops->control(ctx->iep_ctx, IEP_CMD_SET_DEI_CFG, &params);
545 
546         mode = mode | MPP_FRAME_FLAG_IEP_DEI_I2O1;
547         mpp_frame_set_mode(frm, mode);
548         // start hardware
549         dec_vproc_start_dei(ctx, mode);
550         if (!ctx->detection) {
551             dec_vproc_put_frame(mpp, frm, dst0, -1, frame_err);
552             if (vproc_debug & VPROC_DBG_DUMP_OUT)
553                 dump_mppbuffer(dst0, "/data/dump/dump_output.yuv", hor_stride, mpp_frame_get_height(frm));
554             ctx->out_buf0 = NULL;
555         }
556     }
557 }
558 
dec_vproc_update_ref(MppDecVprocCtxImpl * ctx,MppFrame frm,RK_U32 index,RK_U32 eos)559 static void dec_vproc_update_ref(MppDecVprocCtxImpl *ctx, MppFrame frm, RK_U32 index, RK_U32 eos)
560 {
561     Mpp *mpp = ctx->mpp;
562 
563     if (ctx->com_ctx->ver == 1) {
564         dec_vproc_clr_prev0(ctx);
565         ctx->prev_idx0 = index;
566         ctx->prev_frm0 = frm;
567     } else {
568         if (ctx->detection) {
569             if (ctx->prev_frm1) {
570                 dec_vproc_put_frame(mpp,  ctx->prev_frm1, NULL, -1, 0);
571                 if (ctx->prev_idx1 >= 0)
572                     mpp_buf_slot_clr_flag(ctx->slots, ctx->prev_idx1, SLOT_QUEUE_USE);
573                 ctx->prev_idx1 = -1;
574                 ctx->prev_frm1 = NULL;
575             }
576         } else {
577             dec_vproc_clr_prev1(ctx);
578         }
579 
580         ctx->prev_idx1 = ctx->prev_idx0;
581         ctx->prev_idx0 = index;
582         ctx->prev_frm1 = ctx->prev_frm0;
583         ctx->prev_frm0 = frm;
584     }
585 
586     if (eos) {
587         mpp_frame_init(&frm);
588         mpp_frame_set_eos(frm, eos);
589         dec_vproc_put_frame(mpp, frm, NULL, -1, 0);
590         dec_vproc_clr_prev(ctx);
591         mpp_frame_deinit(&frm);
592     }
593     return;
594 }
595 
dec_vproc_thread(void * data)596 static void *dec_vproc_thread(void *data)
597 {
598     MppDecVprocCtxImpl *ctx = (MppDecVprocCtxImpl *)data;
599     HalTaskGroup tasks = ctx->task_group;
600     MppThread *thd = ctx->thd;
601     Mpp *mpp = ctx->mpp;
602     MppDecImpl *dec = (MppDecImpl *)mpp->mDec;
603     MppBufSlots slots = dec->frame_slots;
604 
605     HalTaskHnd task = NULL;
606     HalTaskInfo task_info;
607     HalDecVprocTask *task_vproc = &task_info.dec_vproc;
608 
609     mpp_dbg_info("mpp_dec_post_proc_thread started\n");
610 
611     while (1) {
612         MPP_RET ret = MPP_OK;
613 
614         {
615             AutoMutex autolock(thd->mutex());
616 
617             if (MPP_THREAD_RUNNING != thd->get_status())
618                 break;
619 
620             if (ctx->task_wait.val && !ctx->reset) {
621                 vproc_dbg_status("vproc thread wait %d", ctx->task_wait.val);
622                 thd->wait();
623             }
624 
625             if (!ctx->task_status.task_rdy) {
626                 if (hal_task_get_hnd(tasks, TASK_PROCESSING, &task)) {
627                     if (ctx->reset) {
628                         /* reset only on all task finished */
629                         vproc_dbg_reset("reset start\n");
630 
631                         dec_vproc_clr_prev(ctx);
632                         ctx->reset = 0;
633                         sem_post(&ctx->reset_sem);
634                         ctx->task_wait.val = 0;
635 
636                         vproc_dbg_reset("reset done\n");
637                         continue;
638                     }
639 
640                     ctx->task_wait.task_in = 1;
641                     continue;
642                 }
643                 ctx->task_status.task_rdy = 1;
644                 ctx->task_wait.task_in = 0;
645             }
646         }
647 
648         if (task) {
649             ret = hal_task_hnd_get_info(task, &task_info);
650 
651             mpp_assert(ret == MPP_OK);
652 
653             RK_S32 index = task_vproc->input;
654             RK_U32 eos = task_vproc->flags.eos;
655             RK_U32 change = task_vproc->flags.info_change;
656             MppFrame frm = NULL;
657 
658             if (eos && index < 0) {
659                 vproc_dbg_status("eos signal\n");
660 
661                 mpp_frame_init(&frm);
662                 mpp_frame_set_eos(frm, eos);
663                 dec_vproc_put_frame(mpp, frm, NULL, -1, 0);
664                 dec_vproc_clr_prev(ctx);
665                 mpp_frame_deinit(&frm);
666 
667                 hal_task_hnd_set_status(task, TASK_IDLE);
668                 ctx->task_status.task_rdy = 0;
669                 continue;
670             }
671 
672             mpp_buf_slot_get_prop(slots, index, SLOT_FRAME_PTR, &frm);
673 
674             if (change) {
675                 vproc_dbg_status("info change\n");
676                 dec_vproc_put_frame(mpp, frm, NULL, -1, 0);
677                 dec_vproc_clr_prev(ctx);
678 
679                 hal_task_hnd_set_status(task, TASK_IDLE);
680                 ctx->task_status.task_rdy = 0;
681                 continue;
682             }
683             vproc_dbg_status("vproc get buf in");
684             if (!ctx->task_status.buf_rdy && !ctx->reset) {
685                 MppBuffer buf = mpp_frame_get_buffer(frm);
686                 size_t buf_size = mpp_buffer_get_size(buf);
687                 if (!ctx->out_buf0) {
688                     mpp_buffer_get(mpp->mFrameGroup, &ctx->out_buf0, buf_size);
689                     if (NULL == ctx->out_buf0) {
690                         ctx->task_wait.task_buf_in = 1;
691                         continue;
692                     }
693                 }
694                 if (!ctx->out_buf1) {
695                     mpp_buffer_get(mpp->mFrameGroup, &ctx->out_buf1, buf_size);
696                     if (NULL == ctx->out_buf1) {
697                         ctx->task_wait.task_buf_in = 1;
698                         continue;
699                     }
700                 }
701                 ctx->task_status.buf_rdy = 1;
702             }
703 
704             RK_S32 tmp = -1;
705             mpp_buf_slot_dequeue(slots, &tmp, QUEUE_DEINTERLACE);
706             mpp_assert(tmp == index);
707 
708             vproc_dbg_status("vproc get buf ready & start process ");
709             if (!ctx->reset && ctx->iep_ctx) {
710                 if (ctx->com_ctx->ver == 1) {
711                     dec_vproc_set_dei_v1(ctx, frm);
712                 } else {
713                     dec_vproc_set_dei_v2(ctx, frm);
714                 }
715             }
716             dec_vproc_update_ref(ctx, frm, index, eos);
717             hal_task_hnd_set_status(task, TASK_IDLE);
718             ctx->task_status.val = 0;
719             ctx->task_wait.val = 0;
720 
721             vproc_dbg_status("vproc task done");
722         }
723     }
724     mpp_dbg_info("mpp_dec_post_proc_thread exited\n");
725 
726     return NULL;
727 }
728 
dec_vproc_init(MppDecVprocCtx * ctx,MppDecVprocCfg * cfg)729 MPP_RET dec_vproc_init(MppDecVprocCtx *ctx, MppDecVprocCfg *cfg)
730 {
731     MPP_RET ret = MPP_OK;
732     if (NULL == ctx || NULL == cfg || NULL == cfg->mpp) {
733         mpp_err_f("found NULL input ctx %p mpp %p\n", ctx, cfg->mpp);
734         return MPP_ERR_NULL_PTR;
735     }
736 
737     vproc_dbg_func("in\n");
738     mpp_env_get_u32("vproc_debug", &vproc_debug, 0);
739 
740     *ctx = NULL;
741 
742     MppDecVprocCtxImpl *p = mpp_calloc(MppDecVprocCtxImpl, 1);
743     if (NULL == p) {
744         mpp_err_f("malloc failed\n");
745         return MPP_ERR_MALLOC;
746     }
747 
748     p->mpp = (Mpp *)cfg->mpp;
749     p->slots = ((MppDecImpl *)p->mpp->mDec)->frame_slots;
750     p->thd = new MppThread(dec_vproc_thread, p, "mpp_dec_vproc");
751     sem_init(&p->reset_sem, 0, 0);
752     ret = hal_task_group_init(&p->task_group, TASK_BUTT, 4, sizeof(HalDecVprocTask));
753     if (ret) {
754         mpp_err_f("create task group failed\n");
755         delete p->thd;
756         MPP_FREE(p);
757         return MPP_ERR_MALLOC;
758     }
759     cfg->task_group = p->task_group;
760 
761     /// TODO, seperate iep1/2 api
762     p->com_ctx = get_iep_ctx();
763     if (!p->com_ctx) {
764         mpp_err("failed to require context\n");
765         delete p->thd;
766 
767         if (p->task_group) {
768             hal_task_group_deinit(p->task_group);
769             p->task_group = NULL;
770         }
771 
772         MPP_FREE(p);
773 
774         return MPP_ERR_MALLOC;
775     }
776 
777     ret = p->com_ctx->ops->init(&p->com_ctx->priv);
778     p->iep_ctx = p->com_ctx->priv;
779     if (!p->thd || ret) {
780         mpp_err("failed to create context\n");
781         if (p->thd) {
782             delete p->thd;
783             p->thd = NULL;
784         }
785 
786         if (p->iep_ctx)
787             p->com_ctx->ops->deinit(p->iep_ctx);
788 
789         if (p->task_group) {
790             hal_task_group_deinit(p->task_group);
791             p->task_group = NULL;
792         }
793 
794         put_iep_ctx(p->com_ctx);
795 
796         MPP_FREE(p);
797     } else {
798         p->dei_cfg.dei_mode = IEP_DEI_MODE_I2O1;
799         p->dei_cfg.dei_field_order = IEP_DEI_FLD_ORDER_BOT_FIRST;
800         /*
801          * We need to turn off this switch to prevent some areas
802          * of the video from flickering.
803          */
804         p->dei_cfg.dei_high_freq_en = 0;
805         p->dei_cfg.dei_high_freq_fct = 64;
806         p->dei_cfg.dei_ei_mode = 0;
807         p->dei_cfg.dei_ei_smooth = 1;
808         p->dei_cfg.dei_ei_sel = 0;
809         p->dei_cfg.dei_ei_radius = 2;
810 
811         p->prev_idx0 = -1;
812         p->prev_frm0 = NULL;
813         p->prev_idx1 = -1;
814         p->prev_frm1 = NULL;
815     }
816 
817     *ctx = p;
818 
819     vproc_dbg_func("out\n");
820     return ret;
821 }
822 
dec_vproc_get_version(MppDecVprocCtx ctx)823 RK_U32 dec_vproc_get_version(MppDecVprocCtx ctx)
824 {
825     if (NULL == ctx) {
826         mpp_err_f("found NULL input\n");
827         return 0;
828     }
829 
830     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
831     return p->com_ctx->ver;
832 }
833 
dec_vproc_enable_detect(MppDecVprocCtx ctx)834 void dec_vproc_enable_detect(MppDecVprocCtx ctx)
835 {
836     if (NULL == ctx) {
837         mpp_err_f("found NULL input\n");
838         return;
839     }
840 
841     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
842     p->detection = 1;
843     return;
844 }
845 
dec_vproc_deinit(MppDecVprocCtx ctx)846 MPP_RET dec_vproc_deinit(MppDecVprocCtx ctx)
847 {
848     if (NULL == ctx) {
849         mpp_err_f("found NULL input\n");
850         return MPP_ERR_NULL_PTR;
851     }
852     vproc_dbg_func("in\n");
853 
854     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
855     if (p->thd) {
856         p->thd->stop();
857         delete p->thd;
858         p->thd = NULL;
859     }
860 
861     if (p->iep_ctx)
862         p->com_ctx->ops->deinit(p->iep_ctx);
863 
864     if (p->task_group) {
865         hal_task_group_deinit(p->task_group);
866         p->task_group = NULL;
867     }
868 
869     if (p->com_ctx) {
870         put_iep_ctx(p->com_ctx);
871         p->com_ctx = NULL;
872     }
873 
874     sem_destroy(&p->reset_sem);
875     mpp_free(p);
876 
877     vproc_dbg_func("out\n");
878     return MPP_OK;
879 }
880 
dec_vproc_start(MppDecVprocCtx ctx)881 MPP_RET dec_vproc_start(MppDecVprocCtx ctx)
882 {
883     if (NULL == ctx) {
884         mpp_err_f("found NULL input\n");
885         return MPP_ERR_NULL_PTR;
886     }
887     vproc_dbg_func("in\n");
888 
889     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
890 
891     if (p->thd)
892         p->thd->start();
893     else
894         mpp_err("failed to start dec vproc thread\n");
895 
896     vproc_dbg_func("out\n");
897     return MPP_OK;
898 }
899 
dec_vproc_stop(MppDecVprocCtx ctx)900 MPP_RET dec_vproc_stop(MppDecVprocCtx ctx)
901 {
902     if (NULL == ctx) {
903         mpp_err_f("found NULL input\n");
904         return MPP_ERR_NULL_PTR;
905     }
906     vproc_dbg_func("in\n");
907 
908     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
909 
910     if (p->thd)
911         p->thd->stop();
912     else
913         mpp_err("failed to stop dec vproc thread\n");
914 
915     vproc_dbg_func("out\n");
916     return MPP_OK;
917 }
918 
dec_vproc_signal(MppDecVprocCtx ctx)919 MPP_RET dec_vproc_signal(MppDecVprocCtx ctx)
920 {
921     if (NULL == ctx) {
922         mpp_err_f("found NULL input\n");
923         return MPP_ERR_NULL_PTR;
924     }
925     vproc_dbg_func("in\n");
926 
927     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
928     if (p->thd) {
929         p->thd->lock();
930         p->thd->signal();
931         p->thd->unlock();
932     }
933 
934     vproc_dbg_func("out\n");
935     return MPP_OK;
936 }
937 
dec_vproc_reset(MppDecVprocCtx ctx)938 MPP_RET dec_vproc_reset(MppDecVprocCtx ctx)
939 {
940     if (NULL == ctx) {
941         mpp_err_f("found NULL input\n");
942         return MPP_ERR_NULL_PTR;
943     }
944     vproc_dbg_func("in\n");
945 
946     MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx;
947     if (p->thd) {
948         MppThread *thd = p->thd;
949 
950         vproc_dbg_reset("reset contorl start\n");
951         // wait reset finished
952         thd->lock();
953         p->reset = 1;
954         thd->signal();
955         thd->unlock();
956 
957         vproc_dbg_reset("reset contorl wait\n");
958         sem_wait(&p->reset_sem);
959         vproc_dbg_reset("reset contorl done\n");
960 
961         mpp_assert(p->reset == 0);
962     }
963 
964     vproc_dbg_func("out\n");
965     return MPP_OK;
966 }
967