[mpi_dec_test]:add advanced decoding path

(1) when decoding mjpeg, switch to mpi_dec_test_decode_advanced
(2) add advanced decoding interface for mjpeg in vpu_api_legacy.cpp

Change-Id: Ib1848d1686c76826385f76405dda81dd0405cb62
Signed-off-by: timkingh.huang <timkingh.huang@rock-chips.com>
This commit is contained in:
timkingh.huang
2016-09-18 11:29:41 +08:00
committed by Herman Chen
parent deb649610c
commit 44852d9696
7 changed files with 615 additions and 23 deletions

View File

@@ -2406,8 +2406,6 @@ MPP_RET jpegd_update_frame(JpegParserContext *ctx)
return MPP_ERR_NULL_PTR;
}
mpp_buf_slot_set_flag(pCtx->frame_slots, pCtx->frame_slot_index, SLOT_QUEUE_USE);
mpp_buf_slot_enqueue(pCtx->frame_slots, pCtx->frame_slot_index, QUEUE_DISPLAY);
mpp_buf_slot_clr_flag(pCtx->frame_slots, pCtx->frame_slot_index, SLOT_CODEC_USE);
pCtx->frame_slot_index = -1;

View File

@@ -63,6 +63,7 @@ extern "C" {
*/
void *mpp_dec_parser_thread(void *data);
void *mpp_dec_hal_thread(void *data);
void *mpp_dec_advanced_thread(void *data);
/*
*

View File

@@ -791,6 +791,149 @@ void *mpp_dec_hal_thread(void *data)
return NULL;
}
static MPP_RET dec_release_task_in_port(MppPort port)
{
MPP_RET ret = MPP_OK;
MppPacket packet = NULL;
MppFrame frame = NULL;
MppTask mpp_task;
do {
ret = mpp_port_dequeue(port, &mpp_task);
if (ret || mpp_task == NULL)
break;
packet = NULL;
frame = NULL;
ret = mpp_task_meta_get_frame(mpp_task, KEY_OUTPUT_FRAME, &frame);
if (frame) {
mpp_frame_deinit(&frame);
frame = NULL;
}
ret = mpp_task_meta_get_packet(mpp_task, KEY_INPUT_PACKET, &packet);
if (packet) {
mpp_packet_deinit(&packet);
packet = NULL;
}
mpp_port_enqueue(port, mpp_task);
mpp_task = NULL;
} while (1);
return ret;
}
void *mpp_dec_advanced_thread(void *data)
{
Mpp *mpp = (Mpp*)data;
MppDec *dec = mpp->mDec;
MppBufSlots frame_slots = dec->frame_slots;
MppBufSlots packet_slots = dec->packet_slots;
MppThread *thd_dec = mpp->mThreadCodec;
DecTask task; /* decoder task */
DecTask *pTask = &task;
dec_task_init(pTask);
HalDecTask *task_dec = &pTask->info.dec;
MppPort input = mpp_task_queue_get_port(mpp->mInputTaskQueue, MPP_PORT_OUTPUT);
MppPort output = mpp_task_queue_get_port(mpp->mOutputTaskQueue, MPP_PORT_INPUT);
MppTask mpp_task = NULL;
MPP_RET ret = MPP_OK;
MppFrame frame = NULL;
MppPacket packet = NULL;
while (MPP_THREAD_RUNNING == thd_dec->get_status()) {
thd_dec->lock();
ret = mpp_port_dequeue(input, &mpp_task);
if (ret || NULL == mpp_task) {
thd_dec->wait();
}
thd_dec->unlock();
if (mpp_task != NULL) {
mpp_task_meta_get_packet(mpp_task, KEY_INPUT_PACKET, &packet);
mpp_task_meta_get_frame (mpp_task, KEY_OUTPUT_FRAME, &frame);
if (NULL == packet) {
mpp_port_enqueue(input, mpp_task);
continue;
}
if (mpp_packet_get_buffer(packet)) {
/*
* if there is available buffer in the input packet do decoding
*/
MppBuffer input_buffer = mpp_packet_get_buffer(packet);
MppBuffer output_buffer = mpp_frame_get_buffer(frame);
parser_prepare(dec->parser, packet, task_dec);
/*
* look for a unused packet slot index
*/
if (task_dec->input < 0) {
mpp_buf_slot_get_unused(packet_slots, &task_dec->input);
}
mpp_buf_slot_set_prop(packet_slots, task_dec->input, SLOT_BUFFER, input_buffer);
mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_CODEC_READY);
mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT);
ret = parser_parse(dec->parser, task_dec);
if (ret != MPP_OK) {
mpp_err_f("something wrong with parser_parse!\n");
mpp_buf_slot_clr_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT);
mpp_frame_init(&frame);
goto DEC_OUT;
}
mpp_buf_slot_set_prop(frame_slots, task_dec->output, SLOT_BUFFER, output_buffer);
// register genertation
mpp_hal_reg_gen(dec->hal, &pTask->info);
mpp_hal_hw_start(dec->hal, &pTask->info);
mpp_hal_hw_wait(dec->hal, &pTask->info);
mpp_buf_slot_clr_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT);
mpp_buf_slot_clr_flag(frame_slots, task_dec->output, SLOT_HAL_OUTPUT);
} else {
/*
* else init a empty frame for output
*/
mpp_log_f("line(%d): Error! Get no buffer from input packet\n", __LINE__);
mpp_frame_init(&frame);
}
/*
* first clear output packet
* then enqueue task back to input port
* final user will release the mpp_frame they had input
*/
DEC_OUT:
mpp_task_meta_set_packet(mpp_task, KEY_INPUT_PACKET, packet);
mpp_port_enqueue(input, mpp_task);
mpp_task = NULL;
// send finished task to output port
mpp_port_dequeue(output, &mpp_task);
mpp_task_meta_set_frame(mpp_task, KEY_OUTPUT_FRAME, frame);
// setup output task here
mpp_port_enqueue(output, mpp_task);
mpp_task = NULL;
packet = NULL;
frame = NULL;
hal_task_info_init(&pTask->info, MPP_CTX_DEC);
}
}
// clear remain task in output port
dec_release_task_in_port(input);
dec_release_task_in_port(mpp->mOutputPort);
return NULL;
}
MPP_RET mpp_dec_init(MppDec **dec, MppDecCfg *cfg)
{
MPP_RET ret;

View File

@@ -130,6 +130,7 @@ typedef struct HalDecTask_t {
// for test purpose
// current tesk output slot index
RK_S32 output;
// current task reference slot index, -1 for unused
RK_S32 refer[MAX_DEC_REF_NUM];
} HalDecTask;

View File

@@ -361,12 +361,205 @@ RK_S32 VpuApiLegacy::flush(VpuCodecContext *ctx)
RK_S32 VpuApiLegacy::decode(VpuCodecContext *ctx, VideoPacket_t *pkt, DecoderOut_t *aDecOut)
{
RK_S32 ret = 0;
MPP_RET ret = MPP_OK;
vpu_api_dbg_func("enter\n");
(void)ctx;
(void)pkt;
(void)aDecOut;
if (ctx->videoCoding == OMX_RK_VIDEO_CodingMJPEG) {
MppTask task = NULL;
if (!init_ok) {
mpp_err("init failed!\n");
return VPU_API_ERR_VPU_CODEC_INIT;
}
/* check input param */
if (!pkt || !aDecOut) {
mpp_err("invalid input %p and output %p\n", pkt, aDecOut);
return VPU_API_ERR_UNKNOW;
}
if (pkt->size <= 0) {
mpp_err("invalid input size %d\n", pkt->size);
return VPU_API_ERR_UNKNOW;
}
/* try import input buffer and output buffer */
RK_S32 fd = -1;
RK_U32 width = ctx->width;
RK_U32 height = ctx->height;
RK_U32 hor_stride = MPP_ALIGN(width, 16);
RK_U32 ver_stride = MPP_ALIGN(height, 16);
MppFrame frame = NULL;
MppPacket packet = NULL;
MppBuffer str_buf = NULL; /* input */
MppBuffer pic_buf = NULL; /* output */
ret = mpp_frame_init(&frame);
if (MPP_OK != ret) {
mpp_err_f("mpp_frame_init failed\n");
goto DECODE_OUT;
}
fd = (RK_S32)(pkt->pts & 0xffffffff);
if (fd_input < 0) {
fd_input = is_valid_dma_fd(fd);
}
if (fd_input) {
MppBufferInfo inputCommit;
memset(&inputCommit, 0, sizeof(inputCommit));
inputCommit.type = MPP_BUFFER_TYPE_ION;
inputCommit.size = pkt->size;
inputCommit.fd = fd;
ret = mpp_buffer_import(&str_buf, &inputCommit);
if (ret) {
mpp_err_f("import input picture buffer failed\n");
goto DECODE_OUT;
}
} else {
if (NULL == pkt->data) {
ret = MPP_ERR_NULL_PTR;
goto DECODE_OUT;
}
ret = mpp_buffer_get(memGroup, &str_buf, pkt->size);
if (ret) {
mpp_err_f("allocate input picture buffer failed\n");
goto DECODE_OUT;
}
memcpy((RK_U8*) mpp_buffer_get_ptr(str_buf), pkt->data, pkt->size);
}
fd = (RK_S32)(aDecOut->timeUs & 0xffffffff);
if (fd_output < 0) {
fd_output = is_valid_dma_fd(fd);
}
if (fd_output) {
MppBufferInfo outputCommit;
memset(&outputCommit, 0, sizeof(outputCommit));
/* in order to avoid interface change use space in output to transmit information */
outputCommit.type = MPP_BUFFER_TYPE_ION;
outputCommit.fd = fd;
outputCommit.size = width * height * 3 / 2;
outputCommit.ptr = (void*)aDecOut->data;
ret = mpp_buffer_import(&pic_buf, &outputCommit);
if (ret) {
mpp_err_f("import output stream buffer failed\n");
goto DECODE_OUT;
}
} else {
ret = mpp_buffer_get(memGroup, &pic_buf, hor_stride * ver_stride * 3 / 2);
if (ret) {
mpp_err_f("allocate output stream buffer failed\n");
goto DECODE_OUT;
}
}
mpp_packet_init_with_buffer(&packet, str_buf); /* input */
mpp_frame_set_buffer(frame, pic_buf); /* output */
vpu_api_dbg_func("mpp import input fd %d output fd %d",
mpp_buffer_get_fd(str_buf), mpp_buffer_get_fd(pic_buf));
do {
ret = mpi->dequeue(mpp_ctx, MPP_PORT_INPUT, &task);
if (ret) {
mpp_err("mpp task input dequeue failed\n");
goto DECODE_OUT;
}
if (task == NULL) {
vpu_api_dbg_func("mpi dequeue from MPP_PORT_INPUT fail, task equal with NULL!");
msleep(3);
} else
break;
} while (1);
mpp_task_meta_set_packet(task, KEY_INPUT_PACKET, packet);
mpp_task_meta_set_frame (task, KEY_OUTPUT_FRAME, frame);
if (mpi != NULL) {
ret = mpi->enqueue(mpp_ctx, MPP_PORT_INPUT, task);
if (ret) {
mpp_err("mpp task input enqueue failed\n");
goto DECODE_OUT;
}
task = NULL;
do {
ret = mpi->dequeue(mpp_ctx, MPP_PORT_OUTPUT, &task);
if (ret) {
mpp_err("ret %d mpp task output dequeue failed\n", ret);
goto DECODE_OUT;
}
if (task) {
MppFrame frame_out = NULL;
mpp_task_meta_get_frame(task, KEY_OUTPUT_FRAME, &frame_out);
mpp_assert(frame_out == frame);
vpu_api_dbg_func("decoded frame %d\n", frame_count);
frame_count++;
ret = mpi->enqueue(mpp_ctx, MPP_PORT_OUTPUT, task);
if (ret) {
mpp_err("mpp task output enqueue failed\n");
goto DECODE_OUT;
}
task = NULL;
break;
}
msleep(3);
} while (1);
} else {
mpp_err("mpi pointer is NULL, failed!");
}
// copy encoded stream into output buffer, and set outpub stream size
if (frame != NULL) {
MppBuffer buf_out = mpp_frame_get_buffer(frame);
size_t len = mpp_buffer_get_size(buf_out);
aDecOut->size = len;
if (!is_valid_dma_fd(fd)) {
mpp_log_f("fd for output is invalid!\n");
if (NULL == aDecOut->data) {
if (NULL == outData)
outData = mpp_malloc(RK_U8, (width * height));
aDecOut->data = outData;
}
memcpy(aDecOut->data, (RK_U8*) mpp_buffer_get_ptr(pic_buf), aDecOut->size);
}
vpu_api_dbg_func("get frame %p size %d\n", frame, len);
mpp_frame_deinit(&frame);
} else {
mpp_log("outputPacket is NULL!");
}
DECODE_OUT:
if (str_buf) {
mpp_buffer_put(str_buf);
str_buf = NULL;
}
if (pic_buf) {
mpp_buffer_put(pic_buf);
pic_buf = NULL;
}
if (frame)
mpp_frame_deinit(&frame);
if (packet)
mpp_packet_deinit(&packet);
}
vpu_api_dbg_func("leave ret %d\n", ret);
return ret;

View File

@@ -93,6 +93,7 @@ MPP_RET Mpp::init(MppCtxType type, MppCodingType coding)
};
mpp_dec_init(&mDec, &cfg);
if (mCoding != MPP_VIDEO_CodingMJPEG) {
mThreadCodec = new MppThread(mpp_dec_parser_thread, this, "mpp_dec_parser");
mThreadHal = new MppThread(mpp_dec_hal_thread, this, "mpp_dec_hal");
@@ -103,6 +104,14 @@ MPP_RET Mpp::init(MppCtxType type, MppCodingType coding)
mpp_task_queue_init(&mOutputTaskQueue);
mpp_task_queue_setup(mInputTaskQueue, 4);
mpp_task_queue_setup(mOutputTaskQueue, 4);
} else {
mThreadCodec = new MppThread(mpp_dec_advanced_thread, this, "mpp_dec_parser");
mpp_task_queue_init(&mInputTaskQueue);
mpp_task_queue_init(&mOutputTaskQueue);
mpp_task_queue_setup(mInputTaskQueue, 1);
mpp_task_queue_setup(mOutputTaskQueue, 1);
}
} break;
case MPP_CTX_ENC : {
mFrames = new mpp_list((node_destructor)NULL);
@@ -129,7 +138,14 @@ MPP_RET Mpp::init(MppCtxType type, MppCodingType coding)
mInputPort = mpp_task_queue_get_port(mInputTaskQueue, MPP_PORT_INPUT);
mOutputPort = mpp_task_queue_get_port(mOutputTaskQueue, MPP_PORT_OUTPUT);
if (mFrames && mPackets &&
if (mCoding == MPP_VIDEO_CodingMJPEG &&
mFrames && mPackets &&
(mDec) &&
mThreadCodec/* &&
mPacketGroup*/) {
mThreadCodec->start();
mInitDone = 1;
} else if (mFrames && mPackets &&
(mDec) &&
mThreadCodec && mThreadHal &&
mPacketGroup) {
@@ -531,10 +547,13 @@ MPP_RET Mpp::reset()
if (mType == MPP_CTX_DEC) {
mpp_dec_reset(mDec);
if (mDec->coding != MPP_VIDEO_CodingMJPEG) {
mThreadCodec->lock();
mThreadCodec->signal();
mThreadCodec->unlock();
mThreadCodec->wait(THREAD_RESET);
}
} else {
mpp_enc_reset(mEnc);
}

View File

@@ -55,7 +55,7 @@ static OptionInfo mpi_dec_cmd[] = {
{"d", "debug", "debug flag"},
};
int mpi_dec_test(MpiDecTestCmd *cmd)
int mpi_dec_test_decode_simple(MpiDecTestCmd *cmd)
{
MPP_RET ret = MPP_OK;
RK_U32 pkt_eos = 0;
@@ -247,6 +247,239 @@ MPP_TEST_OUT:
return ret;
}
int mpi_dec_test_decode_advanced(MpiDecTestCmd *cmd)
{
MPP_RET ret = MPP_OK;
RK_U32 pkt_eos = 0;
FILE *fp_input = NULL;
FILE *fp_output = NULL;
// base flow context
MppCtx ctx = NULL;
MppApi *mpi = NULL;
// input / output
MppPacket packet = NULL;
MppFrame frame = NULL;
MpiCmd mpi_cmd = MPP_CMD_BASE;
MppParam param = NULL;
RK_U32 need_split = 1;
// paramter for resource malloc
RK_U32 width = cmd->width;
RK_U32 height = cmd->height;
MppCodingType type = cmd->type;
// resources
MppBuffer pkt_buf = NULL;
MppBuffer frm_buf = NULL;
size_t packet_size = MPI_DEC_STREAM_SIZE;
size_t read_size = 0;
RK_U32 frame_count = 0;
void *buf = NULL;
(void)read_size;
MppBufferGroup frm_grp = NULL;
MppBufferGroup pkt_grp = NULL;
mpp_log("mpi_dec_test start\n");
if (cmd->have_input) {
fp_input = fopen(cmd->file_input, "rb");
if (NULL == fp_input) {
mpp_err("failed to open input file %s\n", cmd->file_input);
goto MPP_TEST_OUT;
}
}
if (cmd->have_output) {
fp_output = fopen(cmd->file_output, "w+b");
if (NULL == fp_output) {
mpp_err("failed to open output file %s\n", cmd->file_output);
goto MPP_TEST_OUT;
}
}
ret = mpp_buffer_group_get_internal(&frm_grp, MPP_BUFFER_TYPE_ION);
if (ret) {
mpp_err("failed to get buffer group for input frame ret %d\n", ret);
goto MPP_TEST_OUT;
}
ret = mpp_buffer_group_get_internal(&pkt_grp, MPP_BUFFER_TYPE_ION);
if (ret) {
mpp_err("failed to get buffer group for output packet ret %d\n", ret);
goto MPP_TEST_OUT;
}
fseek(fp_input, 0L, SEEK_END);
packet_size = ftell(fp_input);
fseek(fp_input, 0L, SEEK_SET);
RK_U32 frm_size = width * height * 3 / 2;
ret = mpp_frame_init(&frame); /* output frame */
if (MPP_OK != ret) {
mpp_err("mpp_frame_init failed\n");
goto MPP_TEST_OUT;
}
ret = mpp_buffer_get(frm_grp, &frm_buf, frm_size);
if (ret) {
mpp_err("failed to get buffer for input frame ret %d\n", ret);
goto MPP_TEST_OUT;
}
ret = mpp_buffer_get(pkt_grp, &pkt_buf, packet_size);
if (ret) {
mpp_err("failed to get buffer for input frame ret %d\n", ret);
goto MPP_TEST_OUT;
}
mpp_packet_init_with_buffer(&packet, pkt_buf);
buf = mpp_buffer_get_ptr(pkt_buf);
mpp_frame_set_buffer(frame, frm_buf);
mpp_log("mpi_dec_test decoder test start w %d h %d type %d\n", width, height, type);
// decoder demo
ret = mpp_create(&ctx, &mpi);
if (MPP_OK != ret) {
mpp_err("mpp_create failed\n");
goto MPP_TEST_OUT;
}
// NOTE: decoder split mode need to be set before init
mpi_cmd = MPP_DEC_SET_PARSER_SPLIT_MODE;
param = &need_split;
ret = mpi->control(ctx, mpi_cmd, param);
if (MPP_OK != ret) {
mpp_err("mpi->control failed\n");
goto MPP_TEST_OUT;
}
ret = mpp_init(ctx, MPP_CTX_DEC, type);
if (MPP_OK != ret) {
mpp_err("mpp_init failed\n");
goto MPP_TEST_OUT;
}
while (!pkt_eos) {
MppTask task = NULL;
read_size = fread(buf, 1, packet_size, fp_input);
/* if (read_size != packet_size || feof(fp_input)) {
mpp_log("found last packet\n");
pkt_eos = 1;
}*/
pkt_eos = 1;
do {
ret = mpi->dequeue(ctx, MPP_PORT_INPUT, &task); /* input queue */
if (ret) {
mpp_err("mpp task input dequeue failed\n");
goto MPP_TEST_OUT;
}
if (task == NULL) {
mpp_log("mpi dequeue from MPP_PORT_INPUT fail, task equal with NULL!");
msleep(3);
} else {
break;
}
} while (1);
mpp_task_meta_set_packet(task, KEY_INPUT_PACKET, packet);
mpp_task_meta_set_frame (task, KEY_OUTPUT_FRAME, frame);
ret = mpi->enqueue(ctx, MPP_PORT_INPUT, task); /* input queue */
if (ret) {
mpp_err("mpp task input enqueue failed\n");
goto MPP_TEST_OUT;
}
msleep(20);
do {
ret = mpi->dequeue(ctx, MPP_PORT_OUTPUT, &task); /* output queue */
if (ret) {
mpp_err("mpp task output dequeue failed\n");
goto MPP_TEST_OUT;
}
if (task) {
MppFrame frame_out = NULL;
mpp_task_meta_get_frame(task, KEY_OUTPUT_FRAME, &frame_out);
//mpp_assert(packet_out == packet);
if (frame) { /* write frame to file here */
MppBuffer buf_out = mpp_frame_get_buffer(frame_out);
void *ptr = mpp_buffer_get_ptr(buf_out);
size_t len = mpp_buffer_get_size(buf_out);
if (fp_output)
fwrite(ptr, 1, len, fp_output);
mpp_log_f("decoded frame %d size %d\n", frame_count, len);
}
ret = mpi->enqueue(ctx, MPP_PORT_OUTPUT, task); /* output queue */
if (ret) {
mpp_err("mpp task output enqueue failed\n");
goto MPP_TEST_OUT;
}
break;
}
} while (1);
}
ret = mpi->reset(ctx);
if (MPP_OK != ret) {
mpp_err("mpi->reset failed\n");
goto MPP_TEST_OUT;
}
MPP_TEST_OUT:
if (packet) {
mpp_packet_deinit(&packet);
packet = NULL;
}
if (frame) {
mpp_frame_deinit(&frame);
frame = NULL;
}
if (ctx) {
mpp_destroy(ctx);
ctx = NULL;
}
if (buf) {
mpp_free(buf);
buf = NULL;
}
if (frm_buf) {
mpp_free(frm_buf);
frm_buf = NULL;
}
if (fp_output) {
fclose(fp_output);
fp_output = NULL;
}
if (fp_input) {
fclose(fp_input);
fp_input = NULL;
}
if (MPP_OK == ret)
mpp_log_f("success\n");
else
mpp_err_f("failed ret %d\n", ret);
return ret;
}
static void mpi_dec_test_help()
{
@@ -394,7 +627,11 @@ int main(int argc, char **argv)
mpp_env_set_u32("mpi_debug", cmd->debug);
mpi_dec_test(cmd);
if (cmd->type != MPP_VIDEO_CodingMJPEG) {
mpi_dec_test_decode_simple(cmd);
} else {
mpi_dec_test_decode_advanced(cmd);
}
mpp_env_set_u32("mpi_debug", 0x0);
return 0;