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