mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-10-04 08:46:24 +08:00

1. clear input packet length when packet is copied 2. modify mjpeg advanced decoding path in mpi_dec_test 3. add numerator and denominator set prop function 4. remove extra log on first info change 5. fix eos process and buffer size check in advanced decoding flow 6. fix jpegd stream length config error Change-Id: Id6c26ebda090eb4076f27deaad4d61b4221f2653 Signed-off-by: Herman Chen <herman.chen@rock-chips.com>
656 lines
18 KiB
C
656 lines
18 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.
|
|
*/
|
|
|
|
#if defined(_WIN32)
|
|
#include "vld.h"
|
|
#endif
|
|
|
|
#define MODULE_TAG "mpi_dec_test"
|
|
|
|
#include <string.h>
|
|
#include "rk_mpi.h"
|
|
|
|
#include "mpp_log.h"
|
|
#include "mpp_mem.h"
|
|
#include "mpp_env.h"
|
|
#include "mpp_time.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#define MPI_DEC_LOOP_COUNT 4
|
|
#define MPI_DEC_STREAM_SIZE (SZ_64K)
|
|
#define MAX_FILE_NAME_LENGTH 256
|
|
|
|
typedef struct {
|
|
char file_input[MAX_FILE_NAME_LENGTH];
|
|
char file_output[MAX_FILE_NAME_LENGTH];
|
|
MppCodingType type;
|
|
RK_U32 width;
|
|
RK_U32 height;
|
|
RK_U32 debug;
|
|
|
|
RK_U32 have_input;
|
|
RK_U32 have_output;
|
|
} MpiDecTestCmd;
|
|
|
|
static OptionInfo mpi_dec_cmd[] = {
|
|
{"i", "input_file", "input bitstream file"},
|
|
{"o", "output_file", "output bitstream file, "},
|
|
{"w", "width", "the width of input bitstream"},
|
|
{"h", "height", "the height of input bitstream"},
|
|
{"t", "type", "input stream coding type"},
|
|
{"d", "debug", "debug flag"},
|
|
};
|
|
|
|
int mpi_dec_test_decode_simple(MpiDecTestCmd *cmd)
|
|
{
|
|
MPP_RET ret = MPP_OK;
|
|
RK_U32 pkt_eos = 0;
|
|
RK_U32 frm_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
|
|
char *buf = NULL;
|
|
size_t packet_size = MPI_DEC_STREAM_SIZE;
|
|
size_t read_size = 0;
|
|
RK_U32 frame_count = 0;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
buf = mpp_malloc(char, packet_size);
|
|
if (NULL == buf) {
|
|
mpp_err("mpi_dec_test malloc input stream buffer failed\n");
|
|
goto MPP_TEST_OUT;
|
|
}
|
|
|
|
ret = mpp_packet_init(&packet, buf, packet_size);
|
|
if (ret) {
|
|
mpp_err("mpp_packet_init failed\n");
|
|
goto MPP_TEST_OUT;
|
|
}
|
|
|
|
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) {
|
|
RK_S32 pkt_done = 0;
|
|
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;
|
|
}
|
|
|
|
// write data to packet
|
|
mpp_packet_write(packet, 0, buf, read_size);
|
|
// reset pos
|
|
mpp_packet_set_pos(packet, buf);
|
|
mpp_packet_set_length(packet, read_size);
|
|
// setup eos flag
|
|
if (pkt_eos)
|
|
mpp_packet_set_eos(packet);
|
|
|
|
frame = NULL;
|
|
do {
|
|
// send the packet first if packet is not done
|
|
if (!pkt_done) {
|
|
ret = mpi->decode_put_packet(ctx, packet);
|
|
if (MPP_OK == ret)
|
|
pkt_done = 1;
|
|
}
|
|
|
|
// then get all available frame and release
|
|
do {
|
|
RK_S32 get_frm = 0;
|
|
ret = mpi->decode_get_frame(ctx, &frame);
|
|
if (MPP_OK != ret) {
|
|
mpp_err("decode_get_frame failed ret %d\n", ret);
|
|
goto MPP_TEST_OUT;
|
|
}
|
|
|
|
if (frame) {
|
|
if (mpp_frame_get_info_change(frame)) {
|
|
mpp_log("decode_get_frame get info changed found\n");
|
|
mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
|
|
} else {
|
|
mpp_log("decode_get_frame get frame %d\n", frame_count++);
|
|
if (fp_output)
|
|
dump_mpp_frame_to_file(frame, fp_output);
|
|
}
|
|
frm_eos = mpp_frame_get_eos(frame);
|
|
mpp_frame_deinit(&frame);
|
|
frame = NULL;
|
|
get_frm = 1;
|
|
}
|
|
|
|
// if last packet is send but last frame is not found continue
|
|
if (pkt_eos && pkt_done && !frm_eos)
|
|
continue;
|
|
|
|
if (get_frm)
|
|
continue;
|
|
|
|
break;
|
|
} while (1);
|
|
|
|
if (pkt_done)
|
|
break;
|
|
|
|
msleep(50);
|
|
} 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 (ctx) {
|
|
mpp_destroy(ctx);
|
|
ctx = NULL;
|
|
}
|
|
|
|
if (buf) {
|
|
mpp_free(buf);
|
|
buf = NULL;
|
|
}
|
|
|
|
if (fp_output) {
|
|
fclose(fp_output);
|
|
fp_output = NULL;
|
|
}
|
|
|
|
if (fp_input) {
|
|
fclose(fp_input);
|
|
fp_input = NULL;
|
|
}
|
|
|
|
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;
|
|
size_t file_size = 0;
|
|
RK_U32 frame_count = 0;
|
|
void *buf = NULL;
|
|
|
|
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;
|
|
}
|
|
|
|
// get file size for MJPEG
|
|
fseek(fp_input, 0L, SEEK_END);
|
|
file_size = ftell(fp_input);
|
|
rewind(fp_input);
|
|
mpp_log("input file size %ld\n", file_size);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// NOTE: for mjpeg decoding send the whole file
|
|
if (type == MPP_VIDEO_CodingMJPEG) {
|
|
packet_size = file_size;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// reset pos
|
|
mpp_packet_set_pos(packet, buf);
|
|
mpp_packet_set_length(packet, read_size);
|
|
// setup eos flag
|
|
if (pkt_eos)
|
|
mpp_packet_set_eos(packet);
|
|
|
|
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);
|
|
|
|
if (buf_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("decoded frame %d size %d\n", frame_count, len);
|
|
}
|
|
|
|
if (mpp_frame_get_eos(frame_out))
|
|
mpp_log("found eos frame\n");
|
|
}
|
|
|
|
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 (pkt_buf) {
|
|
mpp_buffer_put(pkt_buf);
|
|
pkt_buf = NULL;
|
|
}
|
|
|
|
if (frm_buf) {
|
|
mpp_buffer_put(frm_buf);
|
|
frm_buf = NULL;
|
|
}
|
|
|
|
if (fp_output) {
|
|
fclose(fp_output);
|
|
fp_output = NULL;
|
|
}
|
|
|
|
if (fp_input) {
|
|
fclose(fp_input);
|
|
fp_input = NULL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void mpi_dec_test_help()
|
|
{
|
|
mpp_log("usage: mpi_dec_test [options]\n");
|
|
show_options(mpi_dec_cmd);
|
|
mpp_show_support_format();
|
|
}
|
|
|
|
static RK_S32 mpi_dec_test_parse_options(int argc, char **argv, MpiDecTestCmd* cmd)
|
|
{
|
|
const char *opt;
|
|
const char *next;
|
|
RK_S32 optindex = 1;
|
|
RK_S32 handleoptions = 1;
|
|
RK_S32 err = MPP_NOK;
|
|
|
|
if ((argc < 2) || (cmd == NULL)) {
|
|
err = 1;
|
|
return err;
|
|
}
|
|
|
|
/* parse options */
|
|
while (optindex < argc) {
|
|
opt = (const char*)argv[optindex++];
|
|
next = (const char*)argv[optindex];
|
|
|
|
if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
|
|
if (opt[1] == '-') {
|
|
if (opt[2] != '\0') {
|
|
opt++;
|
|
} else {
|
|
handleoptions = 0;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
opt++;
|
|
|
|
switch (*opt) {
|
|
case 'i':
|
|
if (next) {
|
|
strncpy(cmd->file_input, next, MAX_FILE_NAME_LENGTH);
|
|
cmd->file_input[strlen(next)] = '\0';
|
|
cmd->have_input = 1;
|
|
} else {
|
|
mpp_err("input file is invalid\n");
|
|
goto PARSE_OPINIONS_OUT;
|
|
}
|
|
break;
|
|
case 'o':
|
|
if (next) {
|
|
strncpy(cmd->file_output, next, MAX_FILE_NAME_LENGTH);
|
|
cmd->file_output[strlen(next)] = '\0';
|
|
cmd->have_output = 1;
|
|
} else {
|
|
mpp_log("output file is invalid\n");
|
|
goto PARSE_OPINIONS_OUT;
|
|
}
|
|
break;
|
|
case 'd':
|
|
if (next) {
|
|
cmd->debug = atoi(next);;
|
|
} else {
|
|
mpp_err("invalid debug flag\n");
|
|
goto PARSE_OPINIONS_OUT;
|
|
}
|
|
break;
|
|
case 'w':
|
|
if (next) {
|
|
cmd->width = atoi(next);
|
|
} else {
|
|
mpp_err("invalid input width\n");
|
|
goto PARSE_OPINIONS_OUT;
|
|
}
|
|
break;
|
|
case 'h':
|
|
if ((*(opt + 1) != '\0') && !strncmp(opt, "help", 4)) {
|
|
mpi_dec_test_help();
|
|
err = 1;
|
|
goto PARSE_OPINIONS_OUT;
|
|
} else if (next) {
|
|
cmd->height = atoi(next);
|
|
} else {
|
|
mpp_log("input height is invalid\n");
|
|
goto PARSE_OPINIONS_OUT;
|
|
}
|
|
break;
|
|
case 't':
|
|
if (next) {
|
|
cmd->type = (MppCodingType)atoi(next);
|
|
err = mpp_check_support_format(MPP_CTX_DEC, cmd->type);
|
|
}
|
|
|
|
if (!next || err) {
|
|
mpp_err("invalid input coding type\n");
|
|
goto PARSE_OPINIONS_OUT;
|
|
}
|
|
break;
|
|
default:
|
|
goto PARSE_OPINIONS_OUT;
|
|
break;
|
|
}
|
|
|
|
optindex++;
|
|
}
|
|
}
|
|
|
|
err = 0;
|
|
|
|
PARSE_OPINIONS_OUT:
|
|
return err;
|
|
}
|
|
|
|
static void mpi_dec_test_show_options(MpiDecTestCmd* cmd)
|
|
{
|
|
mpp_log("cmd parse result:\n");
|
|
mpp_log("input file name: %s\n", cmd->file_input);
|
|
mpp_log("output file name: %s\n", cmd->file_output);
|
|
mpp_log("width : %4d\n", cmd->width);
|
|
mpp_log("height : %4d\n", cmd->height);
|
|
mpp_log("type : %d\n", cmd->type);
|
|
mpp_log("debug flag : %x\n", cmd->debug);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
RK_S32 ret = 0;
|
|
MpiDecTestCmd cmd_ctx;
|
|
MpiDecTestCmd* cmd = &cmd_ctx;
|
|
|
|
memset((void*)cmd, 0, sizeof(*cmd));
|
|
|
|
// parse the cmd option
|
|
ret = mpi_dec_test_parse_options(argc, argv, cmd);
|
|
if (ret) {
|
|
if (ret < 0) {
|
|
mpp_err("mpi_dec_test_parse_options: input parameter invalid\n");
|
|
}
|
|
|
|
mpi_dec_test_help();
|
|
return ret;
|
|
}
|
|
|
|
mpi_dec_test_show_options(cmd);
|
|
|
|
mpp_env_set_u32("mpi_debug", cmd->debug);
|
|
|
|
if (cmd->type != MPP_VIDEO_CodingMJPEG) {
|
|
ret = mpi_dec_test_decode_simple(cmd);
|
|
} else {
|
|
ret = mpi_dec_test_decode_advanced(cmd);
|
|
}
|
|
|
|
if (MPP_OK == ret)
|
|
mpp_log("test success\n");
|
|
else
|
|
mpp_err("test failed ret %d\n", ret);
|
|
|
|
mpp_env_set_u32("mpi_debug", 0x0);
|
|
return 0;
|
|
}
|
|
|