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, ¶ms);
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, ¶ms);
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, ¶ms);
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, ¶ms);
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