/* SPDX-License-Identifier: Apache-2.0 OR MIT */ /* * Copyright (c) 2015 Rockchip Electronics Co., Ltd. */ #define MODULE_TAG "mpp_dec" #include #include "mpp_env.h" #include "mpp_buffer_impl.h" #include "mpp_frame_impl.h" #include "mpp_dec_cfg.h" #include "mpp_dec_debug.h" #include "mpp_dec_vproc.h" #include "mpp_dec_cb_param.h" #include "mpp_dec_normal.h" #include "mpp_dec_no_thread.h" RK_U32 mpp_dec_debug = 0; MPP_RET dec_task_info_init(HalTaskInfo *task) { HalDecTask *p = &task->dec; p->valid = 0; p->flags.val = 0; p->flags.eos = 0; p->input_packet = NULL; p->output = -1; p->input = -1; memset(&task->dec.syntax, 0, sizeof(task->dec.syntax)); memset(task->dec.refer, -1, sizeof(task->dec.refer)); return MPP_OK; } void dec_task_init(DecTask *task) { task->hnd = NULL; task->status.val = 0; task->wait.val = 0; task->status.prev_task_rdy = 1; INIT_LIST_HEAD(&task->ts_cur.link); dec_task_info_init(&task->info); } static MPP_RET mpp_dec_update_cfg(MppDecImpl *p) { MppDecCfgSet *cfg = p->cfg; MppDecBaseCfg *base = &cfg->base; MppDecStatusCfg *status = &cfg->status; if (status->hal_task_count && !status->hal_support_fast_mode) { if (!p->parser_fast_mode && base->fast_parse) { mpp_err("can not enable fast parse while hal not support\n"); base->fast_parse = 0; } } p->parser_fast_mode = base->fast_parse; p->enable_deinterlace = base->enable_vproc; p->disable_error = base->disable_error; p->dis_err_clr_mark = base->dis_err_clr_mark; mpp_env_get_u32("enable_deinterlace", &p->enable_deinterlace, base->enable_vproc); return MPP_OK; } static MPP_RET mpp_dec_check_fbc_cap(MppDecImpl *p) { MppDecBaseCfg *base = &p->cfg->base; if (MPP_FRAME_FMT_IS_FBC(base->out_fmt)) { RK_U32 fbc = (RK_U32)base->out_fmt & MPP_FRAME_FBC_MASK; RK_U32 fmt = base->out_fmt - fbc; if (p->hw_info && p->hw_info->cap_fbc) fmt |= fbc; base->out_fmt = (MppFrameFormat)fmt; } return MPP_OK; } MPP_RET mpp_dec_proc_cfg(MppDecImpl *dec, MpiCmd cmd, void *param) { MPP_RET ret = MPP_OK; mpp_parser_control(dec->parser, cmd, param); ret = mpp_hal_control(dec->hal, cmd, param); if (ret) goto RET; switch (cmd) { case MPP_DEC_SET_FRAME_INFO : { MppFrame frame = (MppFrame)param; /* update output frame format */ dec->cfg->base.out_fmt = mpp_frame_get_fmt(frame); mpp_log_f("found MPP_DEC_SET_FRAME_INFO fmt %x\n", dec->cfg->base.out_fmt); mpp_slots_set_prop(dec->frame_slots, SLOTS_FRAME_INFO, frame); mpp_log("setting default w %4d h %4d h_str %4d v_str %4d\n", mpp_frame_get_width(frame), mpp_frame_get_height(frame), mpp_frame_get_hor_stride(frame), mpp_frame_get_ver_stride(frame)); } break; case MPP_DEC_SET_INFO_CHANGE_READY: { ret = mpp_buf_slot_ready(dec->frame_slots); } break; case MPP_DEC_GET_VPUMEM_USED_COUNT: { RK_S32 *p = (RK_S32 *)param; *p = mpp_slots_get_used_count(dec->frame_slots); dec_dbg_func("used count %d\n", *p); } break; case MPP_DEC_SET_PRESENT_TIME_ORDER : case MPP_DEC_SET_PARSER_SPLIT_MODE : case MPP_DEC_SET_PARSER_FAST_MODE : case MPP_DEC_SET_IMMEDIATE_OUT : case MPP_DEC_SET_OUTPUT_FORMAT : case MPP_DEC_SET_DISABLE_ERROR : case MPP_DEC_SET_DIS_ERR_CLR_MARK : case MPP_DEC_SET_ENABLE_DEINTERLACE : case MPP_DEC_SET_ENABLE_FAST_PLAY : case MPP_DEC_SET_ENABLE_MVC : case MPP_DEC_SET_DISABLE_DPB_CHECK: { ret = mpp_dec_set_cfg_by_cmd(dec->cfg_obj, cmd, param); mpp_dec_update_cfg(dec); mpp_dec_check_fbc_cap(dec); dec->cfg->base.change = 0; } break; case MPP_DEC_QUERY: { MppDecQueryCfg *query = (MppDecQueryCfg *)param; RK_U32 flag = query->query_flag; dec_dbg_func("query %x\n", flag); if (flag & MPP_DEC_QUERY_STATUS) query->rt_status = dec->parser_status_flag; if (flag & MPP_DEC_QUERY_WAIT) query->rt_wait = dec->parser_wait_flag; if (flag & MPP_DEC_QUERY_FPS) query->rt_fps = 0; if (flag & MPP_DEC_QUERY_BPS) query->rt_bps = 0; if (flag & MPP_DEC_QUERY_DEC_IN_PKT) query->dec_in_pkt_cnt = dec->dec_in_pkt_count; if (flag & MPP_DEC_QUERY_DEC_WORK) query->dec_hw_run_cnt = dec->dec_hw_run_count; if (flag & MPP_DEC_QUERY_DEC_OUT_FRM) query->dec_out_frm_cnt = dec->dec_out_frame_count; } break; case MPP_DEC_SET_CFG: { if (param) { kmpp_obj_update(dec->cfg_obj, (KmppObj)param); mpp_dec_update_cfg(dec); mpp_dec_check_fbc_cap(dec); } dec_dbg_func("set dec cfg\n"); } break; case MPP_DEC_GET_CFG: { if (param) ret = (MPP_RET)kmpp_obj_copy_entry(param, dec->cfg_obj); dec_dbg_func("get dec cfg\n"); } break; default : { } break; } RET: return ret; } /* Overall mpp_dec output frame function */ void mpp_dec_put_frame(Mpp *mpp, RK_S32 index, HalDecTaskFlag flags) { MppDecImpl *dec = (MppDecImpl *)mpp->mDec; MppBufSlots slots = dec->frame_slots; MppFrame frame = NULL; RK_U32 eos = flags.eos; RK_U32 change = flags.info_change; RK_U32 error = flags.parse_err || flags.ref_err; RK_U32 refer = flags.used_for_ref; RK_U32 fake_frame = 0; if (index >= 0) { RK_U32 mode = 0; mpp_buf_slot_get_prop(slots, index, SLOT_FRAME_PTR, &frame); mode = mpp_frame_get_mode(frame); if (mode && dec->enable_deinterlace && NULL == dec->vproc) { MppDecVprocCfg cfg = { mpp, NULL }; MPP_RET ret = dec_vproc_init(&dec->vproc, &cfg); if (ret) { // When iep is failed to open disable deinterlace function to // avoid noisy log. dec->enable_deinterlace = 0; dec->vproc = NULL; } else { if (dec_vproc_get_version(dec->vproc) == 1 && mode == MPP_FRAME_FLAG_DEINTERLACED) { mpp_frame_set_mode(frame, MPP_FRAME_FLAG_FRAME); /*iep 1 can't no detect DEINTERLACED, direct disable*/ dec->cfg->base.enable_vproc &= (~MPP_VPROC_MODE_DETECTION); dec->enable_deinterlace = dec->cfg->base.enable_vproc; if (dec->vproc && !dec->enable_deinterlace) { dec_vproc_deinit(dec->vproc); dec->vproc = NULL; } dec->vproc = NULL; } else { /* store current IEP mode */ dec_vproc_set_mode(dec->vproc, (MppVprocMode)dec->enable_deinterlace); dec->vproc_tasks = cfg.task_group; dec_vproc_start(dec->vproc); } } } } else { // when post-process is needed and eos without slot index case // we need to create a slot index for it mpp_assert(eos); mpp_assert(!change); if (dec->vproc) { HalTaskGroup group = dec->vproc_tasks; HalTaskHnd hnd = NULL; HalTaskInfo task; HalDecVprocTask *vproc_task = &task.dec_vproc; MPP_RET ret = MPP_OK; do { ret = hal_task_get_hnd(group, TASK_IDLE, &hnd); if (ret) { if (dec->reset_flag) { return; } else { msleep(10); } } } while (ret); vproc_task->flags.val = 0; vproc_task->flags.eos = eos; vproc_task->input = index; hal_task_hnd_set_info(hnd, &task); hal_task_hnd_set_status(hnd, TASK_PROCESSING); dec_vproc_signal(dec->vproc); return ; } else { mpp_frame_init(&frame); fake_frame = 1; index = 0; } mpp_frame_set_eos(frame, eos); } mpp_assert(index >= 0); mpp_assert(frame); if (dec->cfg->base.disable_error && dec->cfg->base.dis_err_clr_mark) { mpp_frame_set_errinfo(frame, 0); mpp_frame_set_discard(frame, 0); } if (!change) { if (dec->cfg->base.sort_pts) { MppPktTs *pkt_ts; mpp_spinlock_lock(&dec->ts_lock); pkt_ts = list_first_entry_or_null(&dec->ts_link, MppPktTs, link); if (pkt_ts) list_del_init(&pkt_ts->link); mpp_spinlock_unlock(&dec->ts_lock); if (pkt_ts) { mpp_frame_set_dts(frame, pkt_ts->dts); mpp_frame_set_pts(frame, pkt_ts->pts); mpp_mem_pool_put_f(dec->ts_pool, pkt_ts); } } } mpp_frame_set_info_change(frame, change); if (eos) { mpp_frame_set_eos(frame, 1); if (error) { if (refer) mpp_frame_set_errinfo(frame, 1); else mpp_frame_set_discard(frame, 1); } } dec->dec_out_frame_count++; dec_dbg_detail("detail: %p put frm pts %llu fd %d\n", dec, mpp_frame_get_pts(frame), (NULL == mpp_frame_get_buffer(frame)) ? (-1) : mpp_buffer_get_fd(mpp_frame_get_buffer(frame))); if (dec->vproc) { HalTaskGroup group = dec->vproc_tasks; HalTaskHnd hnd = NULL; HalTaskInfo task; HalDecVprocTask *vproc_task = &task.dec_vproc; MPP_RET ret = MPP_OK; do { ret = hal_task_get_hnd(group, TASK_IDLE, &hnd); if (ret) { if (dec->reset_flag) { MppBuffer buffer = NULL; mpp_buf_slot_get_prop(slots, index, SLOT_BUFFER, &buffer); if (buffer) mpp_buffer_put(buffer); return; } else { msleep(10); } } } while (ret); mpp_assert(ret == MPP_OK); vproc_task->flags.eos = eos; vproc_task->flags.info_change = change; vproc_task->input = index; if (!change) { mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE); mpp_buf_slot_enqueue(slots, index, QUEUE_DEINTERLACE); } hal_task_hnd_set_info(hnd, &task); hal_task_hnd_set_status(hnd, TASK_PROCESSING); dec_vproc_signal(dec->vproc); } else { // direct output -> copy a new MppFrame and output MppList *list = mpp->mFrmOut; MppFrame out = NULL; mpp_frame_init(&out); mpp_frame_copy(out, frame); mpp_dbg_pts("output frame pts %lld\n", mpp_frame_get_pts(out)); mpp_mutex_cond_lock(&list->cond_lock); mpp_list_add_at_tail(list, &out, sizeof(out)); mpp->mFramePutCount++; mpp_list_signal(list); mpp_mutex_cond_unlock(&list->cond_lock); if (fake_frame) mpp_frame_deinit(&frame); mpp_dec_callback(dec, MPP_DEC_EVENT_ON_FRM_READY, out); } } RK_S32 mpp_dec_push_display(Mpp *mpp, HalDecTaskFlag flags) { RK_S32 index = -1; MppDecImpl *dec = (MppDecImpl *)mpp->mDec; MppBufSlots frame_slots = dec->frame_slots; RK_U32 eos = flags.eos; HalDecTaskFlag tmp = flags; RK_S32 ret = 0; tmp.eos = 0; /** * After info_change is encountered by parser thread, HalDecTaskFlag will * have this flag set. Although mpp_dec_flush is called there may be some * frames still remaining in display queue and waiting to be output. So * these frames shouldn't have info_change set since their resolution and * bit depth are the same as before. What's more, the info_change flag has * nothing to do with frames being output. */ tmp.info_change = 0; if (dec->thread_hal) mpp_thread_lock(dec->thread_hal, THREAD_OUTPUT); while (MPP_OK == mpp_buf_slot_dequeue(frame_slots, &index, QUEUE_DISPLAY)) { /* deal with current frame */ if (eos && mpp_slots_is_empty(frame_slots, QUEUE_DISPLAY)) tmp.eos = 1; mpp_dec_put_frame(mpp, index, tmp); mpp_buf_slot_clr_flag(frame_slots, index, SLOT_QUEUE_USE); ret++; } if (dec->thread_hal) mpp_thread_unlock(dec->thread_hal, THREAD_OUTPUT); return ret; } MPP_RET update_dec_hal_info(MppDecImpl *dec, MppFrame frame) { HalInfo hal_info = dec->hal_info; MppDevInfoCfg data[DEC_INFO_BUTT]; RK_S32 size = sizeof(data); RK_U64 val = 0; RK_S32 i; hal_info_set(hal_info, DEC_INFO_WIDTH, CODEC_INFO_FLAG_NUMBER, mpp_frame_get_width(frame)); hal_info_set(hal_info, DEC_INFO_HEIGHT, CODEC_INFO_FLAG_NUMBER, mpp_frame_get_height(frame)); val = hal_info_to_string(hal_info, DEC_INFO_FORMAT, &dec->coding); hal_info_set(hal_info, DEC_INFO_FORMAT, CODEC_INFO_FLAG_STRING, val); hal_info_get(hal_info, data, &size); if (size) { size /= sizeof(data[0]); for (i = 0; i < size; i++) mpp_dev_ioctl(dec->dev, MPP_DEV_SET_INFO, &data[i]); } return MPP_OK; } static MppDecModeApi *dec_api[] = { &dec_api_normal, &dec_api_no_thread, }; static const char *timing_str[DEC_TIMING_BUTT] = { "prs thread", "prs wait ", "prs proc ", "prepare ", "parse ", "gen reg ", "hw start ", "hal thread", "hal wait ", "hal proc ", "hw wait ", }; MPP_RET mpp_dec_callback_hal_to_parser(const char *caller, void *ctx, RK_S32 cmd, void *param) { MppDecImpl *p = (MppDecImpl *)ctx; MPP_RET ret = MPP_OK; (void) caller; mpp_assert(cmd == DEC_PARSER_CALLBACK); if (p->parser) ret = mpp_parser_callback(p->parser, param); return ret; } MPP_RET mpp_dec_callback_slot(const char *caller, void *ctx, RK_S32 cmd, void *param) { (void) caller; (void) cmd; (void) param; return mpp_dec_notify((MppDec)ctx, MPP_DEC_NOTIFY_SLOT_VALID); } MPP_RET mpp_dec_init(MppDec *dec, MppDecInitCfg *cfg) { RK_S32 i; MPP_RET ret; MppCodingType coding; MppBufSlots frame_slots = NULL; MppBufSlots packet_slots = NULL; HalTaskGroup tasks = NULL; Parser parser = NULL; MppHal hal = NULL; Mpp *mpp = (Mpp *)cfg->mpp; MppDecImpl *p = NULL; MppDecCfgSet *dec_cfg = NULL; RK_U32 hal_task_count = 2; RK_U32 support_fast_mode = 0; SlotHalFbcAdjCfg hal_fbc_adj_cfg; mpp_env_get_u32("mpp_dec_debug", &mpp_dec_debug, 0); dec_dbg_func("in\n"); if (NULL == dec || NULL == cfg) { mpp_err_f("invalid input dec %p cfg %p\n", dec, cfg); return MPP_ERR_NULL_PTR; } *dec = NULL; p = mpp_calloc(MppDecImpl, 1); if (NULL == p) { mpp_err_f("failed to malloc context\n"); return MPP_ERR_MALLOC; } p->mpp = mpp; mpp_dec_cfg_init(&p->cfg_obj); dec_cfg = (MppDecCfgSet *)kmpp_obj_to_entry(p->cfg_obj); p->cfg = dec_cfg; coding = cfg->coding; mpp_assert(cfg->cfg); kmpp_obj_update(p->cfg_obj, cfg->cfg); mpp_dec_update_cfg(p); p->dec_cb.callBack = mpp_dec_callback_hal_to_parser; p->dec_cb.ctx = p; p->dec_cb.cmd = DEC_PARSER_CALLBACK; do { ret = mpp_buf_slot_init(&frame_slots); if (ret) { mpp_err_f("could not init frame buffer slot\n"); break; } MppCbCtx cb_ctx = { mpp_dec_callback_slot, (void *)p, 0, }; mpp_buf_slot_set_callback(frame_slots, &cb_ctx); ret = mpp_buf_slot_init(&packet_slots); if (ret) { mpp_err_f("could not init packet buffer slot\n"); break; } MppHalCfg hal_cfg = { MPP_CTX_DEC, coding, frame_slots, packet_slots, dec_cfg, &p->dec_cb, NULL, NULL, 0, &hal_fbc_adj_cfg, }; memset(&hal_fbc_adj_cfg, 0, sizeof(hal_fbc_adj_cfg)); ret = mpp_hal_init(&hal, &hal_cfg); if (ret) { mpp_err_f("could not init hal\n"); break; } if (hal_fbc_adj_cfg.func) mpp_slots_set_prop(frame_slots, SLOTS_HAL_FBC_ADJ, &hal_fbc_adj_cfg); support_fast_mode = hal_cfg.support_fast_mode; if (dec_cfg->base.fast_parse && support_fast_mode) { hal_task_count = dec_cfg->status.hal_task_count ? dec_cfg->status.hal_task_count : 3; } else { dec_cfg->base.fast_parse = 0; p->parser_fast_mode = 0; } dec_cfg->status.hal_support_fast_mode = support_fast_mode; dec_cfg->status.hal_task_count = hal_task_count; ret = hal_task_group_init(&tasks, TASK_BUTT, hal_task_count, sizeof(HalDecTask)); if (ret) { mpp_err_f("hal_task_group_init failed ret %d\n", ret); break; } mpp_buf_slot_setup(packet_slots, hal_task_count); mpp_slots_set_prop(packet_slots, SLOTS_CODING_TYPE, &coding); mpp_slots_set_prop(frame_slots, SLOTS_CODING_TYPE, &coding); p->hw_info = hal_cfg.hw_info; p->dev = hal_cfg.dev; /* check fbc cap after hardware info is valid */ mpp_dec_check_fbc_cap(p); ParserCfg parser_cfg = { coding, frame_slots, packet_slots, dec_cfg, p->hw_info, }; ret = mpp_parser_init(&parser, &parser_cfg); if (ret) { mpp_err_f("could not init parser\n"); break; } ret = hal_info_init(&p->hal_info, MPP_CTX_DEC, coding); if (ret) { mpp_err_f("could not init hal info\n"); break; } p->coding = coding; p->parser = parser; p->hal = hal; p->tasks = tasks; p->frame_slots = frame_slots; p->packet_slots = packet_slots; p->statistics_en = (mpp_dec_debug & MPP_DEC_DBG_TIMING) ? 1 : 0; for (i = 0; i < DEC_TIMING_BUTT; i++) { p->clocks[i] = mpp_clock_get(timing_str[i]); mpp_assert(p->clocks[i]); mpp_clock_enable(p->clocks[i], p->statistics_en); } mpp_mutex_cond_init(&p->cmd_lock); sem_init(&p->parser_reset, 0, 0); sem_init(&p->hal_reset, 0, 0); sem_init(&p->cmd_start, 0, 0); sem_init(&p->cmd_done, 0, 0); if (p->cfg->base.disable_thread) { DecTask *task = mpp_calloc(DecTask, 1); mpp_assert(task); p->task_single = task; dec_task_info_init(&task->info); p->mode = MPP_DEC_MODE_NO_THREAD; } p->api = dec_api[p->mode]; // init timestamp for record and sort pts mpp_spinlock_init(&p->ts_lock); INIT_LIST_HEAD(&p->ts_link); p->ts_pool = mpp_mem_pool_init_f("ts_pool", sizeof(MppPktTs)); if (!p->ts_pool) { mpp_err_f("malloc ts pool failed!\n"); break; } *dec = p; dec_dbg_func("%p out\n", p); return MPP_OK; } while (0); mpp_dec_deinit(p); return MPP_NOK; } MPP_RET mpp_dec_deinit(MppDec ctx) { RK_S32 i; MppDecImpl *dec = (MppDecImpl *)ctx; dec_dbg_func("%p in\n", dec); if (NULL == dec) { mpp_err_f("found NULL input\n"); return MPP_ERR_NULL_PTR; } if (dec->statistics_en) { mpp_log("%p work %lu wait %lu\n", dec, dec->parser_work_count, dec->parser_wait_count); for (i = 0; i < DEC_TIMING_BUTT; i++) { MppClock timer = dec->clocks[i]; RK_S32 base = (i < DEC_HAL_TOTAL) ? (DEC_PRS_TOTAL) : (DEC_HAL_TOTAL); RK_S64 time = mpp_clock_get_sum(timer); RK_S64 total = mpp_clock_get_sum(dec->clocks[base]); if (!time || !total) continue; mpp_log("%p %s - %6.2f %-12lld avg %-12lld\n", dec, mpp_clock_get_name(timer), time * 100.0 / total, time, time / mpp_clock_get_count(timer)); } } for (i = 0; i < DEC_TIMING_BUTT; i++) { mpp_clock_put(dec->clocks[i]); dec->clocks[i] = NULL; } if (dec->hal_info) { hal_info_deinit(dec->hal_info); dec->hal_info = NULL; } if (dec->parser) { mpp_parser_deinit(dec->parser); dec->parser = NULL; } if (dec->tasks) { hal_task_group_deinit(dec->tasks); dec->tasks = NULL; } if (dec->hal) { mpp_hal_deinit(dec->hal); dec->hal = NULL; } if (dec->vproc) { dec_vproc_deinit(dec->vproc); dec->vproc = NULL; } if (dec->frame_slots) { mpp_buf_slot_deinit(dec->frame_slots); dec->frame_slots = NULL; } if (dec->packet_slots) { mpp_buf_slot_deinit(dec->packet_slots); dec->packet_slots = NULL; } mpp_mutex_cond_destroy(&dec->cmd_lock); sem_destroy(&dec->parser_reset); sem_destroy(&dec->hal_reset); sem_destroy(&dec->cmd_start); sem_destroy(&dec->cmd_done); if (dec->ts_pool) { mpp_mem_pool_deinit_f(dec->ts_pool); dec->ts_pool = NULL; } if (dec->cfg_obj) { mpp_dec_cfg_deinit(dec->cfg_obj); dec->cfg_obj = NULL; } dec->cfg = NULL; MPP_FREE(dec->task_single); mpp_free(dec); dec_dbg_func("%p out\n", dec); return MPP_OK; } MPP_RET mpp_dec_start(MppDec ctx) { MppDecImpl *dec = (MppDecImpl *)ctx; MPP_RET ret = MPP_OK; dec_dbg_func("%p in\n", dec); if (dec->api && dec->api->start) ret = dec->api->start(dec); dec_dbg_func("%p out ret %d\n", dec, ret); return ret; } MPP_RET mpp_dec_stop(MppDec ctx) { MPP_RET ret = MPP_OK; MppDecImpl *dec = (MppDecImpl *)ctx; dec_dbg_func("%p in\n", dec); if (dec->thread_parser) mpp_thread_stop(dec->thread_parser); if (dec->thread_hal) mpp_thread_stop(dec->thread_hal); if (dec->thread_parser) { mpp_thread_destroy(dec->thread_parser); dec->thread_parser = NULL; } if (dec->thread_hal) { mpp_thread_destroy(dec->thread_hal); dec->thread_hal = NULL; } dec_dbg_func("%p out\n", dec); return ret; } MPP_RET mpp_dec_reset(MppDec ctx) { MppDecImpl *dec = (MppDecImpl *)ctx; MPP_RET ret = MPP_OK; if (NULL == dec) { mpp_err_f("found NULL input dec %p\n", dec); return MPP_ERR_NULL_PTR; } dec_dbg_func("%p in\n", dec); if (dec->api && dec->api->reset) ret = dec->api->reset(dec); dec_dbg_func("%p out ret %d\n", dec, ret); return ret; } MPP_RET mpp_dec_flush(MppDec ctx) { MppDecImpl *dec = (MppDecImpl *)ctx; dec_dbg_func("%p in\n", dec); if (NULL == dec) { mpp_err_f("found NULL input dec %p\n", dec); return MPP_ERR_NULL_PTR; } mpp_parser_flush(dec->parser); mpp_hal_flush(dec->hal); dec_dbg_func("%p out\n", dec); return MPP_OK; } MPP_RET mpp_dec_notify(MppDec ctx, RK_U32 flag) { MppDecImpl *dec = (MppDecImpl *)ctx; MPP_RET ret = MPP_OK; dec_dbg_func("%p in flag %08x\n", dec, flag); if (dec->vproc && (flag & MPP_DEC_NOTIFY_BUFFER_MATCH)) dec_vproc_signal(dec->vproc); if (dec->api && dec->api->notify) ret = dec->api->notify(dec, flag); dec_dbg_func("%p out ret %d\n", dec, ret); return ret; } MPP_RET mpp_dec_callback(MppDec ctx, MppDecEvent event, void *arg) { MppDecImpl *dec = (MppDecImpl *)ctx; MppDecCbCfg *cb = &dec->cfg->cb; Mpp *mpp = (Mpp *)dec->mpp; MPP_RET ret = MPP_OK; switch (event) { case MPP_DEC_EVENT_ON_PKT_RELEASE : { if (cb->pkt_rdy_cb) ret = cb->pkt_rdy_cb(cb->pkt_rdy_ctx, mpp->mCtx, cb->pkt_rdy_cmd, arg); } break; case MPP_DEC_EVENT_ON_FRM_READY : { if (cb->frm_rdy_cb) ret = cb->frm_rdy_cb(cb->frm_rdy_ctx, mpp->mCtx, cb->frm_rdy_cmd, arg); } break; default : { } break; } return ret; } MPP_RET mpp_dec_control(MppDec ctx, MpiCmd cmd, void *param) { MPP_RET ret = MPP_OK; MppDecImpl *dec = (MppDecImpl *)ctx; if (NULL == dec) { mpp_err_f("found NULL input dec %p\n", dec); return MPP_ERR_NULL_PTR; } dec_dbg_func("%p in %08x %p\n", dec, cmd, param); dec_dbg_detail("detail: %p control cmd %08x param %p start\n", dec, cmd, param); if (dec->api && dec->api->control) ret = dec->api->control(dec, cmd, param); dec_dbg_detail("detail: %p control cmd %08x param %p ret %d\n", dec, cmd, param, ret); dec_dbg_func("%p out ret %d\n", dec, ret); return ret; } MPP_RET mpp_dec_set_cfg_by_cmd(MppDecCfg cfg, MpiCmd cmd, void *param) { MppDecCfgSet *dst = (MppDecCfgSet *)kmpp_obj_to_entry(cfg); MppDecBaseCfg *base = &dst->base; MPP_RET ret = MPP_OK; switch (cmd) { case MPP_DEC_SET_PRESENT_TIME_ORDER : { ret = mpp_dec_cfg_set_u32(cfg, "base:sort_pts", (param) ? (*((RK_U32 *)param)) : (1)); dec_dbg_func("sort time order %d\n", base->sort_pts); } break; case MPP_DEC_SET_PARSER_SPLIT_MODE : { ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", (param) ? (*((RK_U32 *)param)) : (0)); dec_dbg_func("split parse mode %d\n", base->split_parse); } break; case MPP_DEC_SET_PARSER_FAST_MODE : { ret = mpp_dec_cfg_set_u32(cfg, "base:fast_parse", (param) ? (*((RK_U32 *)param)) : (0)); dec_dbg_func("fast parse mode %d\n", base->fast_parse); } break; case MPP_DEC_SET_OUTPUT_FORMAT : { ret = mpp_dec_cfg_set_u32(cfg, "base:out_fmt", (param) ? (*((RK_U32 *)param)) : (RK_U32)(MPP_FMT_YUV420SP)); dec_dbg_func("fast out_fmt %d\n", base->out_fmt); } break; case MPP_DEC_SET_DISABLE_ERROR: { ret = mpp_dec_cfg_set_u32(cfg, "base:disable_error", (param) ? (*((RK_U32 *)param)) : (1)); dec_dbg_func("disable error %d\n", base->disable_error); } break; case MPP_DEC_SET_DIS_ERR_CLR_MARK: { ret = mpp_dec_cfg_set_u32(cfg, "base:dis_err_clr_mark", (param) ? (*((RK_U32 *)param)) : (1)); dec_dbg_func("disable error mark %x\n", base->dis_err_clr_mark); } break; case MPP_DEC_SET_IMMEDIATE_OUT : { ret = mpp_dec_cfg_set_u32(cfg, "base:fast_out", (param) ? (*((RK_U32 *)param)) : (0)); dec_dbg_func("fast output mode %d\n", base->fast_out); } break; case MPP_DEC_SET_ENABLE_DEINTERLACE: { ret = mpp_dec_cfg_set_u32(cfg, "base:enable_vproc", (param) ? (*((RK_U32 *)param)) : (MPP_VPROC_MODE_DEINTELACE)); dec_dbg_func("enable dec_vproc %x\n", base->enable_vproc); } break; case MPP_DEC_SET_ENABLE_FAST_PLAY : { ret = mpp_dec_cfg_set_u32(cfg, "base:enable_fast_play", (param) ? (*((RK_U32 *)param)) : (0)); dec_dbg_func("disable idr immediately output %d\n", base->enable_fast_play); } break; case MPP_DEC_SET_ENABLE_MVC : { ret = mpp_dec_cfg_set_u32(cfg, "base:enable_mvc", (param) ? (*((RK_U32 *)param)) : (0)); dec_dbg_func("enable MVC decoder %d\n", base->enable_mvc); } break; case MPP_DEC_SET_DISABLE_DPB_CHECK : { ret = mpp_dec_cfg_set_u32(cfg, "base:disable_dpb_chk", (param) ? (*((RK_U32 *)param)) : (0)); dec_dbg_func("disable dpb discontinuous check %d\n", base->disable_dpb_chk); } break; case MPP_DEC_SET_CODEC_MODE : { ret = mpp_dec_cfg_set_u32(cfg, "base:codec_mode", (param) ? (*((RK_U32 *)param)) : (0)); dec_dbg_func("force use codec device %d\n", base->codec_mode); } break; default : { mpp_err_f("unsupported cfg update cmd %x\n", cmd); ret = MPP_NOK; } break; } return ret; }