Files
mpp/mpp/codec/mpp_dec.cpp
sayon.chen 38fc8aada8 [mpp_dec]: Support no thread decode
1. Use cmd MPP_SET_DISABLE_THREAD to disable thread, cmd set must be
after mpp_create before mpp_init.
2. When thread disabled put_packet & get_frame MUST not be used.
3. Separate normal flow and no thread flow.

Change-Id: Icf189d312ff39aacf6ca0afe7f345ff4d1cbfb67
Signed-off-by: sayon.chen <sayon.chen@rock-chips.com>
2022-11-29 11:20:06 +08:00

1027 lines
29 KiB
C++

/*
* Copyright 2015 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define MODULE_TAG "mpp_dec"
#include <string.h>
#include "mpp_env.h"
#include "mpp_buffer_impl.h"
#include "mpp_frame_impl.h"
#include "mpp_dec_cfg_impl.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;
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;
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_ENABLE_DEINTERLACE :
case MPP_DEC_SET_ENABLE_FAST_PLAY : {
ret = mpp_dec_set_cfg_by_cmd(&dec->cfg, cmd, param);
mpp_dec_update_cfg(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: {
MppDecCfgImpl *dec_cfg = (MppDecCfgImpl *)param;
if (dec_cfg) {
mpp_dec_set_cfg(&dec->cfg, &dec_cfg->cfg);
mpp_dec_update_cfg(dec);
mpp_dec_check_fbc_cap(dec);
}
dec_dbg_func("set dec cfg\n");
} break;
case MPP_DEC_GET_CFG: {
MppDecCfgImpl *dec_cfg = (MppDecCfgImpl *)param;
if (dec_cfg)
memcpy(&dec_cfg->cfg, &dec->cfg, sizeof(dec->cfg));
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 {
if (mode == MPP_FRAME_FLAG_DEINTERLACED)
dec_vproc_enable_detect(dec->vproc);
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) {
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);
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) {
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(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
mpp_list *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));
list->lock();
list->add_at_tail(&out, sizeof(out));
mpp->mFramePutCount++;
list->signal();
list->unlock();
if (fake_frame)
mpp_frame_deinit(&frame);
mpp_dec_callback(dec, MPP_DEC_EVENT_ON_FRM_READY, out);
}
}
void 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;
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)
dec->thread_hal->lock(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);
}
if (dec->thread_hal)
dec->thread_hal->unlock(THREAD_OUTPUT);
}
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_set_cfg(MppDecCfgSet *dst, MppDecCfgSet *src)
{
MppDecBaseCfg *src_base = &src->base;
MppDecCbCfg *src_cb = &src->cb;
if (src_base->change) {
MppDecBaseCfg *dst_base = &dst->base;
RK_U32 change = src_base->change;
if (change & MPP_DEC_CFG_CHANGE_TYPE)
dst_base->type = src_base->type;
if (change & MPP_DEC_CFG_CHANGE_CODING)
dst_base->coding = src_base->coding;
if (change & MPP_DEC_CFG_CHANGE_HW_TYPE)
dst_base->hw_type = src_base->hw_type;
if (change & MPP_DEC_CFG_CHANGE_BATCH_MODE)
dst_base->batch_mode = src_base->batch_mode;
if (change & MPP_DEC_CFG_CHANGE_OUTPUT_FORMAT)
dst_base->out_fmt = src_base->out_fmt;
if (change & MPP_DEC_CFG_CHANGE_FAST_OUT)
dst_base->fast_out = src_base->fast_out;
if (change & MPP_DEC_CFG_CHANGE_FAST_PARSE)
dst_base->fast_parse = src_base->fast_parse;
if (change & MPP_DEC_CFG_CHANGE_SPLIT_PARSE)
dst_base->split_parse = src_base->split_parse;
if (change & MPP_DEC_CFG_CHANGE_INTERNAL_PTS)
dst_base->internal_pts = src_base->internal_pts;
if (change & MPP_DEC_CFG_CHANGE_SORT_PTS)
dst_base->sort_pts = src_base->sort_pts;
if (change & MPP_DEC_CFG_CHANGE_DISABLE_ERROR)
dst_base->disable_error = src_base->disable_error;
if (change & MPP_DEC_CFG_CHANGE_ENABLE_VPROC)
dst_base->enable_vproc = src_base->enable_vproc;
if (change & MPP_DEC_CFG_CHANGE_ENABLE_FAST_PLAY)
dst_base->enable_fast_play = src_base->enable_fast_play;
if (change & MPP_DEC_CFG_CHANGE_ENABLE_HDR_META)
dst_base->enable_hdr_meta = src_base->enable_hdr_meta;
if (change & MPP_DEC_CFG_CHANGE_ENABLE_THUMBNAIL)
dst_base->enable_thumbnail = src_base->enable_thumbnail;
if (change & MPP_DEC_CFG_CHANGE_DISABLE_THREAD)
dst_base->disable_thread = src_base->disable_thread;
dst_base->change = change;
src_base->change = 0;
}
if (src_cb->change) {
MppDecCbCfg *dst_cb = &dst->cb;
RK_U32 change = src_cb->change;
if (change & MPP_DEC_CB_CFG_CHANGE_PKT_RDY) {
dst_cb->pkt_rdy_cb = src_cb->pkt_rdy_cb;
dst_cb->pkt_rdy_ctx = src_cb->pkt_rdy_ctx;
dst_cb->pkt_rdy_cmd = src_cb->pkt_rdy_cmd;
}
if (change & MPP_DEC_CB_CFG_CHANGE_FRM_RDY) {
dst_cb->frm_rdy_cb = src_cb->frm_rdy_cb;
dst_cb->frm_rdy_ctx = src_cb->frm_rdy_ctx;
dst_cb->frm_rdy_cmd = src_cb->frm_rdy_cmd;
}
dst_cb->change = change;
src_cb->change = 0;
}
return MPP_OK;
}
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_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;
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;
coding = cfg->coding;
dec_cfg = &p->cfg;
mpp_assert(cfg->cfg);
mpp_dec_cfg_set_default(dec_cfg);
mpp_dec_set_cfg(dec_cfg, 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;
}
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,
};
ret = mpp_hal_init(&hal, &hal_cfg);
if (ret) {
mpp_err_f("could not init hal\n");
break;
}
support_fast_mode = hal_cfg.support_fast_mode;
if (dec_cfg->base.fast_parse && support_fast_mode) {
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);
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);
}
p->cmd_lock = new MppMutexCond();
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(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;
}
if (dec->cmd_lock) {
delete dec->cmd_lock;
dec->cmd_lock = NULL;
}
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(dec->ts_pool);
dec->ts_pool = 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)
dec->thread_parser->stop();
if (dec->thread_hal)
dec->thread_hal->stop();
if (dec->thread_parser) {
delete dec->thread_parser;
dec->thread_parser = NULL;
}
if (dec->thread_hal) {
delete 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(MppDecCfgSet *set, MpiCmd cmd, void *param)
{
MppDecBaseCfg *cfg = &set->base;
MPP_RET ret = MPP_OK;
switch (cmd) {
case MPP_DEC_SET_PRESENT_TIME_ORDER : {
cfg->sort_pts = (param) ? (*((RK_U32 *)param)) : (1);
cfg->change |= MPP_DEC_CFG_CHANGE_SORT_PTS;
dec_dbg_func("sort time order %d\n", cfg->sort_pts);
} break;
case MPP_DEC_SET_PARSER_SPLIT_MODE : {
cfg->split_parse = (param) ? (*((RK_U32 *)param)) : (0);
cfg->change |= MPP_DEC_CFG_CHANGE_SPLIT_PARSE;
dec_dbg_func("split parse mode %d\n", cfg->split_parse);
} break;
case MPP_DEC_SET_PARSER_FAST_MODE : {
cfg->fast_parse = (param) ? (*((RK_U32 *)param)) : (0);
cfg->change |= MPP_DEC_CFG_CHANGE_FAST_PARSE;
dec_dbg_func("fast parse mode %d\n", cfg->fast_parse);
} break;
case MPP_DEC_SET_OUTPUT_FORMAT : {
cfg->out_fmt = (param) ? (*((MppFrameFormat *)param)) : (MPP_FMT_YUV420SP);
cfg->change |= MPP_DEC_CFG_CHANGE_OUTPUT_FORMAT;
} break;
case MPP_DEC_SET_DISABLE_ERROR: {
cfg->disable_error = (param) ? (*((RK_U32 *)param)) : (1);
cfg->change |= MPP_DEC_CFG_CHANGE_DISABLE_ERROR;
dec_dbg_func("disable error %d\n", cfg->disable_error);
} break;
case MPP_DEC_SET_IMMEDIATE_OUT : {
cfg->fast_out = (param) ? (*((RK_U32 *)param)) : (0);
cfg->change |= MPP_DEC_CFG_CHANGE_FAST_OUT;
dec_dbg_func("fast output mode %d\n", cfg->fast_out);
} break;
case MPP_DEC_SET_ENABLE_DEINTERLACE: {
cfg->enable_vproc = (param) ? (*((RK_U32 *)param)) : MPP_VPROC_MODE_DEINTELACE;
cfg->change |= MPP_DEC_CFG_CHANGE_ENABLE_VPROC;
dec_dbg_func("enable dec_vproc %x\n", cfg->enable_vproc);
} break;
case MPP_DEC_SET_ENABLE_FAST_PLAY : {
cfg->enable_fast_play = (param) ? (*((RK_U32 *)param)) : (0);
cfg->change |= MPP_DEC_CFG_CHANGE_ENABLE_FAST_PLAY;
dec_dbg_func("disable idr immediately output %d\n", cfg->enable_fast_play);
} break;
default : {
mpp_err_f("unsupported cfg update cmd %x\n", cmd);
ret = MPP_NOK;
} break;
}
return ret;
}