1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "mpp_dec"
7
8 #include <string.h>
9
10 #include "mpp_env.h"
11
12 #include "mpp_buffer_impl.h"
13 #include "mpp_frame_impl.h"
14 #include "mpp_dec_cfg.h"
15
16 #include "mpp_dec_debug.h"
17 #include "mpp_dec_vproc.h"
18 #include "mpp_dec_cb_param.h"
19 #include "mpp_dec_normal.h"
20 #include "mpp_dec_no_thread.h"
21
22 RK_U32 mpp_dec_debug = 0;
23
dec_task_info_init(HalTaskInfo * task)24 MPP_RET dec_task_info_init(HalTaskInfo *task)
25 {
26 HalDecTask *p = &task->dec;
27
28 p->valid = 0;
29 p->flags.val = 0;
30 p->flags.eos = 0;
31 p->input_packet = NULL;
32 p->output = -1;
33 p->input = -1;
34 memset(&task->dec.syntax, 0, sizeof(task->dec.syntax));
35 memset(task->dec.refer, -1, sizeof(task->dec.refer));
36
37 return MPP_OK;
38 }
39
dec_task_init(DecTask * task)40 void dec_task_init(DecTask *task)
41 {
42 task->hnd = NULL;
43 task->status.val = 0;
44 task->wait.val = 0;
45 task->status.prev_task_rdy = 1;
46 INIT_LIST_HEAD(&task->ts_cur.link);
47
48 dec_task_info_init(&task->info);
49 }
50
mpp_dec_update_cfg(MppDecImpl * p)51 static MPP_RET mpp_dec_update_cfg(MppDecImpl *p)
52 {
53 MppDecCfgSet *cfg = p->cfg;
54 MppDecBaseCfg *base = &cfg->base;
55 MppDecStatusCfg *status = &cfg->status;
56
57 if (status->hal_task_count && !status->hal_support_fast_mode) {
58 if (!p->parser_fast_mode && base->fast_parse) {
59 mpp_err("can not enable fast parse while hal not support\n");
60 base->fast_parse = 0;
61 }
62 }
63
64 p->parser_fast_mode = base->fast_parse;
65 p->enable_deinterlace = base->enable_vproc;
66 p->disable_error = base->disable_error;
67 p->dis_err_clr_mark = base->dis_err_clr_mark;
68
69 mpp_env_get_u32("enable_deinterlace", &p->enable_deinterlace, base->enable_vproc);
70
71 return MPP_OK;
72 }
73
mpp_dec_check_fbc_cap(MppDecImpl * p)74 static MPP_RET mpp_dec_check_fbc_cap(MppDecImpl *p)
75 {
76 MppDecBaseCfg *base = &p->cfg->base;
77
78 if (MPP_FRAME_FMT_IS_FBC(base->out_fmt)) {
79 RK_U32 fbc = (RK_U32)base->out_fmt & MPP_FRAME_FBC_MASK;
80 RK_U32 fmt = base->out_fmt - fbc;
81
82 if (p->hw_info && p->hw_info->cap_fbc)
83 fmt |= fbc;
84
85 base->out_fmt = (MppFrameFormat)fmt;
86 }
87
88 return MPP_OK;
89 }
90
mpp_dec_proc_cfg(MppDecImpl * dec,MpiCmd cmd,void * param)91 MPP_RET mpp_dec_proc_cfg(MppDecImpl *dec, MpiCmd cmd, void *param)
92 {
93 MPP_RET ret = MPP_OK;
94
95 mpp_parser_control(dec->parser, cmd, param);
96
97 ret = mpp_hal_control(dec->hal, cmd, param);
98
99 if (ret)
100 goto RET;
101
102 switch (cmd) {
103 case MPP_DEC_SET_FRAME_INFO : {
104 MppFrame frame = (MppFrame)param;
105
106 /* update output frame format */
107 dec->cfg->base.out_fmt = mpp_frame_get_fmt(frame);
108 mpp_log_f("found MPP_DEC_SET_FRAME_INFO fmt %x\n", dec->cfg->base.out_fmt);
109
110 mpp_slots_set_prop(dec->frame_slots, SLOTS_FRAME_INFO, frame);
111
112 mpp_log("setting default w %4d h %4d h_str %4d v_str %4d\n",
113 mpp_frame_get_width(frame),
114 mpp_frame_get_height(frame),
115 mpp_frame_get_hor_stride(frame),
116 mpp_frame_get_ver_stride(frame));
117
118 } break;
119 case MPP_DEC_SET_INFO_CHANGE_READY: {
120 ret = mpp_buf_slot_ready(dec->frame_slots);
121 } break;
122 case MPP_DEC_GET_VPUMEM_USED_COUNT: {
123 RK_S32 *p = (RK_S32 *)param;
124 *p = mpp_slots_get_used_count(dec->frame_slots);
125 dec_dbg_func("used count %d\n", *p);
126 } break;
127 case MPP_DEC_SET_PRESENT_TIME_ORDER :
128 case MPP_DEC_SET_PARSER_SPLIT_MODE :
129 case MPP_DEC_SET_PARSER_FAST_MODE :
130 case MPP_DEC_SET_IMMEDIATE_OUT :
131 case MPP_DEC_SET_OUTPUT_FORMAT :
132 case MPP_DEC_SET_DISABLE_ERROR :
133 case MPP_DEC_SET_DIS_ERR_CLR_MARK :
134 case MPP_DEC_SET_ENABLE_DEINTERLACE :
135 case MPP_DEC_SET_ENABLE_FAST_PLAY :
136 case MPP_DEC_SET_ENABLE_MVC :
137 case MPP_DEC_SET_DISABLE_DPB_CHECK: {
138 ret = mpp_dec_set_cfg_by_cmd(dec->cfg_obj, cmd, param);
139 mpp_dec_update_cfg(dec);
140 mpp_dec_check_fbc_cap(dec);
141 dec->cfg->base.change = 0;
142 } break;
143 case MPP_DEC_QUERY: {
144 MppDecQueryCfg *query = (MppDecQueryCfg *)param;
145 RK_U32 flag = query->query_flag;
146
147 dec_dbg_func("query %x\n", flag);
148
149 if (flag & MPP_DEC_QUERY_STATUS)
150 query->rt_status = dec->parser_status_flag;
151
152 if (flag & MPP_DEC_QUERY_WAIT)
153 query->rt_wait = dec->parser_wait_flag;
154
155 if (flag & MPP_DEC_QUERY_FPS)
156 query->rt_fps = 0;
157
158 if (flag & MPP_DEC_QUERY_BPS)
159 query->rt_bps = 0;
160
161 if (flag & MPP_DEC_QUERY_DEC_IN_PKT)
162 query->dec_in_pkt_cnt = dec->dec_in_pkt_count;
163
164 if (flag & MPP_DEC_QUERY_DEC_WORK)
165 query->dec_hw_run_cnt = dec->dec_hw_run_count;
166
167 if (flag & MPP_DEC_QUERY_DEC_OUT_FRM)
168 query->dec_out_frm_cnt = dec->dec_out_frame_count;
169 } break;
170 case MPP_DEC_SET_CFG: {
171 if (param) {
172 kmpp_obj_update(dec->cfg_obj, (KmppObj)param);
173 mpp_dec_update_cfg(dec);
174 mpp_dec_check_fbc_cap(dec);
175 }
176
177 dec_dbg_func("set dec cfg\n");
178 } break;
179 case MPP_DEC_GET_CFG: {
180 if (param)
181 ret = (MPP_RET)kmpp_obj_copy_entry(param, dec->cfg_obj);
182
183 dec_dbg_func("get dec cfg\n");
184 } break;
185 default : {
186 } break;
187 }
188
189 RET:
190 return ret;
191 }
192
193 /* Overall mpp_dec output frame function */
mpp_dec_put_frame(Mpp * mpp,RK_S32 index,HalDecTaskFlag flags)194 void mpp_dec_put_frame(Mpp *mpp, RK_S32 index, HalDecTaskFlag flags)
195 {
196 MppDecImpl *dec = (MppDecImpl *)mpp->mDec;
197 MppBufSlots slots = dec->frame_slots;
198 MppFrame frame = NULL;
199 RK_U32 eos = flags.eos;
200 RK_U32 change = flags.info_change;
201 RK_U32 error = flags.parse_err || flags.ref_err;
202 RK_U32 refer = flags.used_for_ref;
203 RK_U32 fake_frame = 0;
204
205 if (index >= 0) {
206 RK_U32 mode = 0;
207
208 mpp_buf_slot_get_prop(slots, index, SLOT_FRAME_PTR, &frame);
209
210 mode = mpp_frame_get_mode(frame);
211 if (mode && dec->enable_deinterlace && NULL == dec->vproc) {
212 MppDecVprocCfg cfg = { mpp, NULL };
213 MPP_RET ret = dec_vproc_init(&dec->vproc, &cfg);
214 if (ret) {
215 // When iep is failed to open disable deinterlace function to
216 // avoid noisy log.
217 dec->enable_deinterlace = 0;
218 dec->vproc = NULL;
219 } else {
220 if (dec_vproc_get_version(dec->vproc) == 1 && mode == MPP_FRAME_FLAG_DEINTERLACED) {
221 mpp_frame_set_mode(frame, MPP_FRAME_FLAG_FRAME);
222 /*iep 1 can't no detect DEINTERLACED, direct disable*/
223 dec->cfg->base.enable_vproc &= (~MPP_VPROC_MODE_DETECTION);
224 dec->enable_deinterlace = dec->cfg->base.enable_vproc;
225 if (dec->vproc && !dec->enable_deinterlace) {
226 dec_vproc_deinit(dec->vproc);
227 dec->vproc = NULL;
228 }
229 dec->vproc = NULL;
230 } else {
231 /* store current IEP mode */
232 dec_vproc_set_mode(dec->vproc, (MppVprocMode)dec->enable_deinterlace);
233
234 dec->vproc_tasks = cfg.task_group;
235 dec_vproc_start(dec->vproc);
236 }
237 }
238 }
239 } else {
240 // when post-process is needed and eos without slot index case
241 // we need to create a slot index for it
242 mpp_assert(eos);
243 mpp_assert(!change);
244
245 if (dec->vproc) {
246 HalTaskGroup group = dec->vproc_tasks;
247 HalTaskHnd hnd = NULL;
248 HalTaskInfo task;
249 HalDecVprocTask *vproc_task = &task.dec_vproc;
250 MPP_RET ret = MPP_OK;
251
252 do {
253 ret = hal_task_get_hnd(group, TASK_IDLE, &hnd);
254 if (ret) {
255 if (dec->reset_flag) {
256 return;
257 } else {
258 msleep(10);
259 }
260 }
261 } while (ret);
262 vproc_task->flags.val = 0;
263 vproc_task->flags.eos = eos;
264 vproc_task->input = index;
265
266 hal_task_hnd_set_info(hnd, &task);
267 hal_task_hnd_set_status(hnd, TASK_PROCESSING);
268 dec_vproc_signal(dec->vproc);
269
270 return ;
271 } else {
272 mpp_frame_init(&frame);
273 fake_frame = 1;
274 index = 0;
275 }
276
277 mpp_frame_set_eos(frame, eos);
278 }
279
280 mpp_assert(index >= 0);
281 mpp_assert(frame);
282
283 if (dec->cfg->base.disable_error && dec->cfg->base.dis_err_clr_mark) {
284 mpp_frame_set_errinfo(frame, 0);
285 mpp_frame_set_discard(frame, 0);
286 }
287
288 if (!change) {
289 if (dec->cfg->base.sort_pts) {
290 MppPktTs *pkt_ts;
291
292 mpp_spinlock_lock(&dec->ts_lock);
293 pkt_ts = list_first_entry_or_null(&dec->ts_link, MppPktTs, link);
294 if (pkt_ts)
295 list_del_init(&pkt_ts->link);
296 mpp_spinlock_unlock(&dec->ts_lock);
297 if (pkt_ts) {
298 mpp_frame_set_dts(frame, pkt_ts->dts);
299 mpp_frame_set_pts(frame, pkt_ts->pts);
300 mpp_mem_pool_put_f(dec->ts_pool, pkt_ts);
301 }
302 }
303 }
304 mpp_frame_set_info_change(frame, change);
305
306 if (eos) {
307 mpp_frame_set_eos(frame, 1);
308 if (error) {
309 if (refer)
310 mpp_frame_set_errinfo(frame, 1);
311 else
312 mpp_frame_set_discard(frame, 1);
313 }
314 }
315
316 dec->dec_out_frame_count++;
317 dec_dbg_detail("detail: %p put frm pts %llu fd %d\n", dec,
318 mpp_frame_get_pts(frame),
319 (NULL == mpp_frame_get_buffer(frame)) ? (-1) :
320 mpp_buffer_get_fd(mpp_frame_get_buffer(frame)));
321
322 if (dec->vproc) {
323 HalTaskGroup group = dec->vproc_tasks;
324 HalTaskHnd hnd = NULL;
325 HalTaskInfo task;
326 HalDecVprocTask *vproc_task = &task.dec_vproc;
327 MPP_RET ret = MPP_OK;
328
329 do {
330 ret = hal_task_get_hnd(group, TASK_IDLE, &hnd);
331 if (ret) {
332 if (dec->reset_flag) {
333 MppBuffer buffer = NULL;
334 mpp_buf_slot_get_prop(slots, index, SLOT_BUFFER, &buffer);
335 if (buffer)
336 mpp_buffer_put(buffer);
337 return;
338 } else {
339 msleep(10);
340 }
341 }
342 } while (ret);
343
344 mpp_assert(ret == MPP_OK);
345
346 vproc_task->flags.eos = eos;
347 vproc_task->flags.info_change = change;
348 vproc_task->input = index;
349
350 if (!change) {
351 mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE);
352 mpp_buf_slot_enqueue(slots, index, QUEUE_DEINTERLACE);
353 }
354
355 hal_task_hnd_set_info(hnd, &task);
356 hal_task_hnd_set_status(hnd, TASK_PROCESSING);
357
358 dec_vproc_signal(dec->vproc);
359 } else {
360 // direct output -> copy a new MppFrame and output
361 MppList *list = mpp->mFrmOut;
362 MppFrame out = NULL;
363
364 mpp_frame_init(&out);
365 mpp_frame_copy(out, frame);
366
367 mpp_dbg_pts("output frame pts %lld\n", mpp_frame_get_pts(out));
368
369 mpp_mutex_cond_lock(&list->cond_lock);
370 mpp_list_add_at_tail(list, &out, sizeof(out));
371 mpp->mFramePutCount++;
372 mpp_list_signal(list);
373 mpp_mutex_cond_unlock(&list->cond_lock);
374
375 if (fake_frame)
376 mpp_frame_deinit(&frame);
377
378 mpp_dec_callback(dec, MPP_DEC_EVENT_ON_FRM_READY, out);
379 }
380 }
381
mpp_dec_push_display(Mpp * mpp,HalDecTaskFlag flags)382 RK_S32 mpp_dec_push_display(Mpp *mpp, HalDecTaskFlag flags)
383 {
384 RK_S32 index = -1;
385 MppDecImpl *dec = (MppDecImpl *)mpp->mDec;
386 MppBufSlots frame_slots = dec->frame_slots;
387 RK_U32 eos = flags.eos;
388 HalDecTaskFlag tmp = flags;
389 RK_S32 ret = 0;
390
391 tmp.eos = 0;
392 /**
393 * After info_change is encountered by parser thread, HalDecTaskFlag will
394 * have this flag set. Although mpp_dec_flush is called there may be some
395 * frames still remaining in display queue and waiting to be output. So
396 * these frames shouldn't have info_change set since their resolution and
397 * bit depth are the same as before. What's more, the info_change flag has
398 * nothing to do with frames being output.
399 */
400 tmp.info_change = 0;
401
402 if (dec->thread_hal)
403 mpp_thread_lock(dec->thread_hal, THREAD_OUTPUT);
404
405 while (MPP_OK == mpp_buf_slot_dequeue(frame_slots, &index, QUEUE_DISPLAY)) {
406 /* deal with current frame */
407 if (eos && mpp_slots_is_empty(frame_slots, QUEUE_DISPLAY))
408 tmp.eos = 1;
409
410 mpp_dec_put_frame(mpp, index, tmp);
411 mpp_buf_slot_clr_flag(frame_slots, index, SLOT_QUEUE_USE);
412 ret++;
413 }
414
415 if (dec->thread_hal)
416 mpp_thread_unlock(dec->thread_hal, THREAD_OUTPUT);
417
418 return ret;
419 }
420
update_dec_hal_info(MppDecImpl * dec,MppFrame frame)421 MPP_RET update_dec_hal_info(MppDecImpl *dec, MppFrame frame)
422 {
423 HalInfo hal_info = dec->hal_info;
424 MppDevInfoCfg data[DEC_INFO_BUTT];
425 RK_S32 size = sizeof(data);
426 RK_U64 val = 0;
427 RK_S32 i;
428
429 hal_info_set(hal_info, DEC_INFO_WIDTH, CODEC_INFO_FLAG_NUMBER,
430 mpp_frame_get_width(frame));
431
432 hal_info_set(hal_info, DEC_INFO_HEIGHT, CODEC_INFO_FLAG_NUMBER,
433 mpp_frame_get_height(frame));
434
435 val = hal_info_to_string(hal_info, DEC_INFO_FORMAT, &dec->coding);
436 hal_info_set(hal_info, DEC_INFO_FORMAT, CODEC_INFO_FLAG_STRING, val);
437
438 hal_info_get(hal_info, data, &size);
439
440 if (size) {
441 size /= sizeof(data[0]);
442 for (i = 0; i < size; i++)
443 mpp_dev_ioctl(dec->dev, MPP_DEV_SET_INFO, &data[i]);
444 }
445
446 return MPP_OK;
447 }
448
449 static MppDecModeApi *dec_api[] = {
450 &dec_api_normal,
451 &dec_api_no_thread,
452 };
453
454 static const char *timing_str[DEC_TIMING_BUTT] = {
455 "prs thread",
456 "prs wait ",
457 "prs proc ",
458 "prepare ",
459 "parse ",
460 "gen reg ",
461 "hw start ",
462
463 "hal thread",
464 "hal wait ",
465 "hal proc ",
466 "hw wait ",
467 };
468
mpp_dec_callback_hal_to_parser(const char * caller,void * ctx,RK_S32 cmd,void * param)469 MPP_RET mpp_dec_callback_hal_to_parser(const char *caller, void *ctx,
470 RK_S32 cmd, void *param)
471 {
472 MppDecImpl *p = (MppDecImpl *)ctx;
473 MPP_RET ret = MPP_OK;
474 (void) caller;
475
476 mpp_assert(cmd == DEC_PARSER_CALLBACK);
477
478 if (p->parser)
479 ret = mpp_parser_callback(p->parser, param);
480
481 return ret;
482 }
483
mpp_dec_callback_slot(const char * caller,void * ctx,RK_S32 cmd,void * param)484 MPP_RET mpp_dec_callback_slot(const char *caller, void *ctx, RK_S32 cmd, void *param)
485 {
486 (void) caller;
487 (void) cmd;
488 (void) param;
489 return mpp_dec_notify((MppDec)ctx, MPP_DEC_NOTIFY_SLOT_VALID);
490 }
491
mpp_dec_init(MppDec * dec,MppDecInitCfg * cfg)492 MPP_RET mpp_dec_init(MppDec *dec, MppDecInitCfg *cfg)
493 {
494 RK_S32 i;
495 MPP_RET ret;
496 MppCodingType coding;
497 MppBufSlots frame_slots = NULL;
498 MppBufSlots packet_slots = NULL;
499 HalTaskGroup tasks = NULL;
500 Parser parser = NULL;
501 MppHal hal = NULL;
502 Mpp *mpp = (Mpp *)cfg->mpp;
503 MppDecImpl *p = NULL;
504 MppDecCfgSet *dec_cfg = NULL;
505 RK_U32 hal_task_count = 2;
506 RK_U32 support_fast_mode = 0;
507 SlotHalFbcAdjCfg hal_fbc_adj_cfg;
508
509 mpp_env_get_u32("mpp_dec_debug", &mpp_dec_debug, 0);
510
511 dec_dbg_func("in\n");
512
513 if (NULL == dec || NULL == cfg) {
514 mpp_err_f("invalid input dec %p cfg %p\n", dec, cfg);
515 return MPP_ERR_NULL_PTR;
516 }
517
518 *dec = NULL;
519
520 p = mpp_calloc(MppDecImpl, 1);
521 if (NULL == p) {
522 mpp_err_f("failed to malloc context\n");
523 return MPP_ERR_MALLOC;
524 }
525
526 p->mpp = mpp;
527 mpp_dec_cfg_init(&p->cfg_obj);
528 dec_cfg = (MppDecCfgSet *)kmpp_obj_to_entry(p->cfg_obj);
529 p->cfg = dec_cfg;
530 coding = cfg->coding;
531
532 mpp_assert(cfg->cfg);
533 kmpp_obj_update(p->cfg_obj, cfg->cfg);
534 mpp_dec_update_cfg(p);
535
536 p->dec_cb.callBack = mpp_dec_callback_hal_to_parser;
537 p->dec_cb.ctx = p;
538 p->dec_cb.cmd = DEC_PARSER_CALLBACK;
539
540 do {
541 ret = mpp_buf_slot_init(&frame_slots);
542 if (ret) {
543 mpp_err_f("could not init frame buffer slot\n");
544 break;
545 }
546
547 MppCbCtx cb_ctx = {
548 mpp_dec_callback_slot,
549 (void *)p,
550 0,
551 };
552
553 mpp_buf_slot_set_callback(frame_slots, &cb_ctx);
554
555 ret = mpp_buf_slot_init(&packet_slots);
556 if (ret) {
557 mpp_err_f("could not init packet buffer slot\n");
558 break;
559 }
560
561 MppHalCfg hal_cfg = {
562 MPP_CTX_DEC,
563 coding,
564 frame_slots,
565 packet_slots,
566 dec_cfg,
567 &p->dec_cb,
568 NULL,
569 NULL,
570 0,
571 &hal_fbc_adj_cfg,
572 };
573
574 memset(&hal_fbc_adj_cfg, 0, sizeof(hal_fbc_adj_cfg));
575
576 ret = mpp_hal_init(&hal, &hal_cfg);
577 if (ret) {
578 mpp_err_f("could not init hal\n");
579 break;
580 }
581
582 if (hal_fbc_adj_cfg.func)
583 mpp_slots_set_prop(frame_slots, SLOTS_HAL_FBC_ADJ, &hal_fbc_adj_cfg);
584
585 support_fast_mode = hal_cfg.support_fast_mode;
586
587 if (dec_cfg->base.fast_parse && support_fast_mode) {
588 hal_task_count = dec_cfg->status.hal_task_count ?
589 dec_cfg->status.hal_task_count : 3;
590 } else {
591 dec_cfg->base.fast_parse = 0;
592 p->parser_fast_mode = 0;
593 }
594 dec_cfg->status.hal_support_fast_mode = support_fast_mode;
595 dec_cfg->status.hal_task_count = hal_task_count;
596
597 ret = hal_task_group_init(&tasks, TASK_BUTT, hal_task_count, sizeof(HalDecTask));
598 if (ret) {
599 mpp_err_f("hal_task_group_init failed ret %d\n", ret);
600 break;
601 }
602
603 mpp_buf_slot_setup(packet_slots, hal_task_count);
604 mpp_slots_set_prop(packet_slots, SLOTS_CODING_TYPE, &coding);
605 mpp_slots_set_prop(frame_slots, SLOTS_CODING_TYPE, &coding);
606
607 p->hw_info = hal_cfg.hw_info;
608 p->dev = hal_cfg.dev;
609 /* check fbc cap after hardware info is valid */
610 mpp_dec_check_fbc_cap(p);
611
612 ParserCfg parser_cfg = {
613 coding,
614 frame_slots,
615 packet_slots,
616 dec_cfg,
617 p->hw_info,
618 };
619
620 ret = mpp_parser_init(&parser, &parser_cfg);
621 if (ret) {
622 mpp_err_f("could not init parser\n");
623 break;
624 }
625
626 ret = hal_info_init(&p->hal_info, MPP_CTX_DEC, coding);
627 if (ret) {
628 mpp_err_f("could not init hal info\n");
629 break;
630 }
631
632 p->coding = coding;
633 p->parser = parser;
634 p->hal = hal;
635 p->tasks = tasks;
636 p->frame_slots = frame_slots;
637 p->packet_slots = packet_slots;
638
639 p->statistics_en = (mpp_dec_debug & MPP_DEC_DBG_TIMING) ? 1 : 0;
640
641 for (i = 0; i < DEC_TIMING_BUTT; i++) {
642 p->clocks[i] = mpp_clock_get(timing_str[i]);
643 mpp_assert(p->clocks[i]);
644 mpp_clock_enable(p->clocks[i], p->statistics_en);
645 }
646
647 mpp_mutex_cond_init(&p->cmd_lock);
648 sem_init(&p->parser_reset, 0, 0);
649 sem_init(&p->hal_reset, 0, 0);
650 sem_init(&p->cmd_start, 0, 0);
651 sem_init(&p->cmd_done, 0, 0);
652
653 if (p->cfg->base.disable_thread) {
654 DecTask *task = mpp_calloc(DecTask, 1);
655
656 mpp_assert(task);
657
658 p->task_single = task;
659 dec_task_info_init(&task->info);
660
661 p->mode = MPP_DEC_MODE_NO_THREAD;
662 }
663
664 p->api = dec_api[p->mode];
665
666 // init timestamp for record and sort pts
667 mpp_spinlock_init(&p->ts_lock);
668 INIT_LIST_HEAD(&p->ts_link);
669 p->ts_pool = mpp_mem_pool_init_f("ts_pool", sizeof(MppPktTs));
670 if (!p->ts_pool) {
671 mpp_err_f("malloc ts pool failed!\n");
672 break;
673 }
674
675 *dec = p;
676 dec_dbg_func("%p out\n", p);
677 return MPP_OK;
678 } while (0);
679
680 mpp_dec_deinit(p);
681 return MPP_NOK;
682 }
683
mpp_dec_deinit(MppDec ctx)684 MPP_RET mpp_dec_deinit(MppDec ctx)
685 {
686 RK_S32 i;
687 MppDecImpl *dec = (MppDecImpl *)ctx;
688
689 dec_dbg_func("%p in\n", dec);
690 if (NULL == dec) {
691 mpp_err_f("found NULL input\n");
692 return MPP_ERR_NULL_PTR;
693 }
694
695 if (dec->statistics_en) {
696 mpp_log("%p work %lu wait %lu\n", dec,
697 dec->parser_work_count, dec->parser_wait_count);
698
699 for (i = 0; i < DEC_TIMING_BUTT; i++) {
700 MppClock timer = dec->clocks[i];
701 RK_S32 base = (i < DEC_HAL_TOTAL) ? (DEC_PRS_TOTAL) : (DEC_HAL_TOTAL);
702 RK_S64 time = mpp_clock_get_sum(timer);
703 RK_S64 total = mpp_clock_get_sum(dec->clocks[base]);
704
705 if (!time || !total)
706 continue;
707
708 mpp_log("%p %s - %6.2f %-12lld avg %-12lld\n", dec,
709 mpp_clock_get_name(timer), time * 100.0 / total, time,
710 time / mpp_clock_get_count(timer));
711 }
712 }
713
714 for (i = 0; i < DEC_TIMING_BUTT; i++) {
715 mpp_clock_put(dec->clocks[i]);
716 dec->clocks[i] = NULL;
717 }
718
719 if (dec->hal_info) {
720 hal_info_deinit(dec->hal_info);
721 dec->hal_info = NULL;
722 }
723
724 if (dec->parser) {
725 mpp_parser_deinit(dec->parser);
726 dec->parser = NULL;
727 }
728
729 if (dec->tasks) {
730 hal_task_group_deinit(dec->tasks);
731 dec->tasks = NULL;
732 }
733
734 if (dec->hal) {
735 mpp_hal_deinit(dec->hal);
736 dec->hal = NULL;
737 }
738
739 if (dec->vproc) {
740 dec_vproc_deinit(dec->vproc);
741 dec->vproc = NULL;
742 }
743
744 if (dec->frame_slots) {
745 mpp_buf_slot_deinit(dec->frame_slots);
746 dec->frame_slots = NULL;
747 }
748
749 if (dec->packet_slots) {
750 mpp_buf_slot_deinit(dec->packet_slots);
751 dec->packet_slots = NULL;
752 }
753
754 mpp_mutex_cond_destroy(&dec->cmd_lock);
755
756 sem_destroy(&dec->parser_reset);
757 sem_destroy(&dec->hal_reset);
758 sem_destroy(&dec->cmd_start);
759 sem_destroy(&dec->cmd_done);
760
761 if (dec->ts_pool) {
762 mpp_mem_pool_deinit_f(dec->ts_pool);
763 dec->ts_pool = NULL;
764 }
765
766 if (dec->cfg_obj) {
767 mpp_dec_cfg_deinit(dec->cfg_obj);
768 dec->cfg_obj = NULL;
769 }
770 dec->cfg = NULL;
771
772 MPP_FREE(dec->task_single);
773 mpp_free(dec);
774 dec_dbg_func("%p out\n", dec);
775 return MPP_OK;
776 }
777
mpp_dec_start(MppDec ctx)778 MPP_RET mpp_dec_start(MppDec ctx)
779 {
780 MppDecImpl *dec = (MppDecImpl *)ctx;
781 MPP_RET ret = MPP_OK;
782
783 dec_dbg_func("%p in\n", dec);
784
785 if (dec->api && dec->api->start)
786 ret = dec->api->start(dec);
787
788 dec_dbg_func("%p out ret %d\n", dec, ret);
789 return ret;
790 }
791
mpp_dec_stop(MppDec ctx)792 MPP_RET mpp_dec_stop(MppDec ctx)
793 {
794 MPP_RET ret = MPP_OK;
795 MppDecImpl *dec = (MppDecImpl *)ctx;
796
797 dec_dbg_func("%p in\n", dec);
798
799 if (dec->thread_parser)
800 mpp_thread_stop(dec->thread_parser);
801
802 if (dec->thread_hal)
803 mpp_thread_stop(dec->thread_hal);
804
805 if (dec->thread_parser) {
806 mpp_thread_destroy(dec->thread_parser);
807 dec->thread_parser = NULL;
808 }
809
810 if (dec->thread_hal) {
811 mpp_thread_destroy(dec->thread_hal);
812 dec->thread_hal = NULL;
813 }
814
815 dec_dbg_func("%p out\n", dec);
816 return ret;
817 }
818
mpp_dec_reset(MppDec ctx)819 MPP_RET mpp_dec_reset(MppDec ctx)
820 {
821 MppDecImpl *dec = (MppDecImpl *)ctx;
822 MPP_RET ret = MPP_OK;
823
824 if (NULL == dec) {
825 mpp_err_f("found NULL input dec %p\n", dec);
826 return MPP_ERR_NULL_PTR;
827 }
828
829 dec_dbg_func("%p in\n", dec);
830
831 if (dec->api && dec->api->reset)
832 ret = dec->api->reset(dec);
833
834 dec_dbg_func("%p out ret %d\n", dec, ret);
835
836 return ret;
837 }
838
mpp_dec_flush(MppDec ctx)839 MPP_RET mpp_dec_flush(MppDec ctx)
840 {
841 MppDecImpl *dec = (MppDecImpl *)ctx;
842
843 dec_dbg_func("%p in\n", dec);
844 if (NULL == dec) {
845 mpp_err_f("found NULL input dec %p\n", dec);
846 return MPP_ERR_NULL_PTR;
847 }
848
849 mpp_parser_flush(dec->parser);
850 mpp_hal_flush(dec->hal);
851
852 dec_dbg_func("%p out\n", dec);
853 return MPP_OK;
854 }
855
mpp_dec_notify(MppDec ctx,RK_U32 flag)856 MPP_RET mpp_dec_notify(MppDec ctx, RK_U32 flag)
857 {
858 MppDecImpl *dec = (MppDecImpl *)ctx;
859 MPP_RET ret = MPP_OK;
860
861 dec_dbg_func("%p in flag %08x\n", dec, flag);
862
863 if (dec->vproc && (flag & MPP_DEC_NOTIFY_BUFFER_MATCH))
864 dec_vproc_signal(dec->vproc);
865
866 if (dec->api && dec->api->notify)
867 ret = dec->api->notify(dec, flag);
868
869 dec_dbg_func("%p out ret %d\n", dec, ret);
870
871 return ret;
872 }
873
mpp_dec_callback(MppDec ctx,MppDecEvent event,void * arg)874 MPP_RET mpp_dec_callback(MppDec ctx, MppDecEvent event, void *arg)
875 {
876 MppDecImpl *dec = (MppDecImpl *)ctx;
877 MppDecCbCfg *cb = &dec->cfg->cb;
878 Mpp *mpp = (Mpp *)dec->mpp;
879 MPP_RET ret = MPP_OK;
880
881 switch (event) {
882 case MPP_DEC_EVENT_ON_PKT_RELEASE : {
883 if (cb->pkt_rdy_cb)
884 ret = cb->pkt_rdy_cb(cb->pkt_rdy_ctx, mpp->mCtx, cb->pkt_rdy_cmd, arg);
885 } break;
886 case MPP_DEC_EVENT_ON_FRM_READY : {
887 if (cb->frm_rdy_cb)
888 ret = cb->frm_rdy_cb(cb->frm_rdy_ctx, mpp->mCtx, cb->frm_rdy_cmd, arg);
889 } break;
890 default : {
891 } break;
892 }
893
894 return ret;
895 }
896
mpp_dec_control(MppDec ctx,MpiCmd cmd,void * param)897 MPP_RET mpp_dec_control(MppDec ctx, MpiCmd cmd, void *param)
898 {
899 MPP_RET ret = MPP_OK;
900 MppDecImpl *dec = (MppDecImpl *)ctx;
901
902 if (NULL == dec) {
903 mpp_err_f("found NULL input dec %p\n", dec);
904 return MPP_ERR_NULL_PTR;
905 }
906
907 dec_dbg_func("%p in %08x %p\n", dec, cmd, param);
908 dec_dbg_detail("detail: %p control cmd %08x param %p start\n", dec, cmd, param);
909
910 if (dec->api && dec->api->control)
911 ret = dec->api->control(dec, cmd, param);
912
913 dec_dbg_detail("detail: %p control cmd %08x param %p ret %d\n", dec, cmd, param, ret);
914 dec_dbg_func("%p out ret %d\n", dec, ret);
915
916 return ret;
917 }
918
mpp_dec_set_cfg_by_cmd(MppDecCfg cfg,MpiCmd cmd,void * param)919 MPP_RET mpp_dec_set_cfg_by_cmd(MppDecCfg cfg, MpiCmd cmd, void *param)
920 {
921 MppDecCfgSet *dst = (MppDecCfgSet *)kmpp_obj_to_entry(cfg);
922 MppDecBaseCfg *base = &dst->base;
923 MPP_RET ret = MPP_OK;
924
925 switch (cmd) {
926 case MPP_DEC_SET_PRESENT_TIME_ORDER : {
927 ret = mpp_dec_cfg_set_u32(cfg, "base:sort_pts", (param) ? (*((RK_U32 *)param)) : (1));
928 dec_dbg_func("sort time order %d\n", base->sort_pts);
929 } break;
930 case MPP_DEC_SET_PARSER_SPLIT_MODE : {
931 ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", (param) ? (*((RK_U32 *)param)) : (0));
932 dec_dbg_func("split parse mode %d\n", base->split_parse);
933 } break;
934 case MPP_DEC_SET_PARSER_FAST_MODE : {
935 ret = mpp_dec_cfg_set_u32(cfg, "base:fast_parse", (param) ? (*((RK_U32 *)param)) : (0));
936 dec_dbg_func("fast parse mode %d\n", base->fast_parse);
937 } break;
938 case MPP_DEC_SET_OUTPUT_FORMAT : {
939 ret = mpp_dec_cfg_set_u32(cfg, "base:out_fmt", (param) ? (*((RK_U32 *)param)) : (RK_U32)(MPP_FMT_YUV420SP));
940 dec_dbg_func("fast out_fmt %d\n", base->out_fmt);
941 } break;
942 case MPP_DEC_SET_DISABLE_ERROR: {
943 ret = mpp_dec_cfg_set_u32(cfg, "base:disable_error", (param) ? (*((RK_U32 *)param)) : (1));
944 dec_dbg_func("disable error %d\n", base->disable_error);
945 } break;
946 case MPP_DEC_SET_DIS_ERR_CLR_MARK: {
947 ret = mpp_dec_cfg_set_u32(cfg, "base:dis_err_clr_mark", (param) ? (*((RK_U32 *)param)) : (1));
948 dec_dbg_func("disable error mark %x\n", base->dis_err_clr_mark);
949 } break;
950 case MPP_DEC_SET_IMMEDIATE_OUT : {
951 ret = mpp_dec_cfg_set_u32(cfg, "base:fast_out", (param) ? (*((RK_U32 *)param)) : (0));
952 dec_dbg_func("fast output mode %d\n", base->fast_out);
953 } break;
954 case MPP_DEC_SET_ENABLE_DEINTERLACE: {
955 ret = mpp_dec_cfg_set_u32(cfg, "base:enable_vproc", (param) ? (*((RK_U32 *)param)) : (MPP_VPROC_MODE_DEINTELACE));
956 dec_dbg_func("enable dec_vproc %x\n", base->enable_vproc);
957 } break;
958 case MPP_DEC_SET_ENABLE_FAST_PLAY : {
959 ret = mpp_dec_cfg_set_u32(cfg, "base:enable_fast_play", (param) ? (*((RK_U32 *)param)) : (0));
960 dec_dbg_func("disable idr immediately output %d\n", base->enable_fast_play);
961 } break;
962 case MPP_DEC_SET_ENABLE_MVC : {
963 ret = mpp_dec_cfg_set_u32(cfg, "base:enable_mvc", (param) ? (*((RK_U32 *)param)) : (0));
964 dec_dbg_func("enable MVC decoder %d\n", base->enable_mvc);
965 } break;
966 case MPP_DEC_SET_DISABLE_DPB_CHECK : {
967 ret = mpp_dec_cfg_set_u32(cfg, "base:disable_dpb_chk", (param) ? (*((RK_U32 *)param)) : (0));
968 dec_dbg_func("disable dpb discontinuous check %d\n", base->disable_dpb_chk);
969 } break;
970 case MPP_DEC_SET_CODEC_MODE : {
971 ret = mpp_dec_cfg_set_u32(cfg, "base:codec_mode", (param) ? (*((RK_U32 *)param)) : (0));
972 dec_dbg_func("force use codec device %d\n", base->codec_mode);
973 } break;
974 default : {
975 mpp_err_f("unsupported cfg update cmd %x\n", cmd);
976 ret = MPP_NOK;
977 } break;
978 }
979
980 return ret;
981 }
982