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(¶ms, 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, ¶ms);
511
512 memset(¶ms, 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, ¶ms);
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