xref: /OK3568_Linux_fs/external/mpp/mpp/codec/mpp_dec.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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