mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-10-06 01:26:49 +08:00
[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>
This commit is contained in:
@@ -7,6 +7,8 @@ add_library(mpp_codec STATIC
|
|||||||
mpp_enc_impl.cpp
|
mpp_enc_impl.cpp
|
||||||
mpp_enc_v2.cpp
|
mpp_enc_v2.cpp
|
||||||
enc_impl.cpp
|
enc_impl.cpp
|
||||||
|
mpp_dec_no_thread.cpp
|
||||||
|
mpp_dec_normal.cpp
|
||||||
mpp_dec.cpp
|
mpp_dec.cpp
|
||||||
mpp_parser.cpp
|
mpp_parser.cpp
|
||||||
)
|
)
|
||||||
|
@@ -58,6 +58,8 @@ MPP_RET mpp_dec_callback(MppDec ctx, MppDecEvent event, void *arg);
|
|||||||
MPP_RET mpp_dec_set_cfg_by_cmd(MppDecCfgSet *set, MpiCmd cmd, void *param);
|
MPP_RET mpp_dec_set_cfg_by_cmd(MppDecCfgSet *set, MpiCmd cmd, void *param);
|
||||||
MPP_RET mpp_dec_set_cfg(MppDecCfgSet *dst, MppDecCfgSet *src);
|
MPP_RET mpp_dec_set_cfg(MppDecCfgSet *dst, MppDecCfgSet *src);
|
||||||
|
|
||||||
|
MPP_RET mpp_dec_decode(MppDec ctx, MppPacket packet, MppFrame *frame);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -46,9 +46,30 @@ typedef enum MppDecTimingType_e {
|
|||||||
DEC_TIMING_BUTT,
|
DEC_TIMING_BUTT,
|
||||||
} MppDecTimingType;
|
} MppDecTimingType;
|
||||||
|
|
||||||
typedef struct MppDecImpl_t {
|
|
||||||
|
typedef enum MppDecMode_e {
|
||||||
|
MPP_DEC_MODE_DEFAULT,
|
||||||
|
MPP_DEC_MODE_NO_THREAD,
|
||||||
|
|
||||||
|
MPP_DEC_MODE_BUTT,
|
||||||
|
} MppDecMode;
|
||||||
|
|
||||||
|
typedef struct MppDecImpl_t MppDecImpl;
|
||||||
|
|
||||||
|
typedef struct MppDecModeApi_t {
|
||||||
|
MPP_RET (*start)(MppDecImpl *dec);
|
||||||
|
MPP_RET (*stop)(MppDecImpl *dec);
|
||||||
|
MPP_RET (*reset)(MppDecImpl *dec);
|
||||||
|
MPP_RET (*notify)(MppDecImpl *dec, RK_U32 flag);
|
||||||
|
MPP_RET (*control)(MppDecImpl *dec, MpiCmd cmd, void *param);
|
||||||
|
} MppDecModeApi;
|
||||||
|
|
||||||
|
struct MppDecImpl_t {
|
||||||
MppCodingType coding;
|
MppCodingType coding;
|
||||||
|
|
||||||
|
MppDecMode mode;
|
||||||
|
MppDecModeApi *api;
|
||||||
|
|
||||||
Parser parser;
|
Parser parser;
|
||||||
MppHal hal;
|
MppHal hal;
|
||||||
|
|
||||||
@@ -72,7 +93,7 @@ typedef struct MppDecImpl_t {
|
|||||||
MppDecCfgSet cfg;
|
MppDecCfgSet cfg;
|
||||||
|
|
||||||
/* control process */
|
/* control process */
|
||||||
Mutex *cmd_lock;
|
MppMutexCond *cmd_lock;
|
||||||
RK_U32 cmd_send;
|
RK_U32 cmd_send;
|
||||||
RK_U32 cmd_recv;
|
RK_U32 cmd_recv;
|
||||||
MpiCmd cmd;
|
MpiCmd cmd;
|
||||||
@@ -127,12 +148,98 @@ typedef struct MppDecImpl_t {
|
|||||||
MppMemPool ts_pool;
|
MppMemPool ts_pool;
|
||||||
struct list_head ts_link;
|
struct list_head ts_link;
|
||||||
spinlock_t ts_lock;
|
spinlock_t ts_lock;
|
||||||
} MppDecImpl;
|
void *task_single;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* external wait state */
|
||||||
|
#define MPP_DEC_WAIT_PKT_IN (0x00000001) /* input packet not ready */
|
||||||
|
#define MPP_DEC_WAIT_FRM_OUT (0x00000002) /* frame output queue full */
|
||||||
|
|
||||||
|
#define MPP_DEC_WAIT_INFO_CHG (0x00000020) /* wait info change ready */
|
||||||
|
#define MPP_DEC_WAIT_BUF_RDY (0x00000040) /* wait valid frame buffer */
|
||||||
|
#define MPP_DEC_WAIT_TSK_ALL_DONE (0x00000080) /* wait all task done */
|
||||||
|
|
||||||
|
#define MPP_DEC_WAIT_TSK_HND_RDY (0x00000100) /* wait task handle ready */
|
||||||
|
#define MPP_DEC_WAIT_TSK_PREV_DONE (0x00000200) /* wait previous task done */
|
||||||
|
#define MPP_DEC_WAIT_BUF_GRP_RDY (0x00000200) /* wait buffer group change ready */
|
||||||
|
|
||||||
|
/* internal wait state */
|
||||||
|
#define MPP_DEC_WAIT_BUF_SLOT_RDY (0x00001000) /* wait buffer slot ready */
|
||||||
|
#define MPP_DEC_WAIT_PKT_BUF_RDY (0x00002000) /* wait packet buffer ready */
|
||||||
|
#define MPP_DEC_WAIT_BUF_SLOT_KEEP (0x00004000) /* wait buffer slot reservation */
|
||||||
|
|
||||||
|
typedef union PaserTaskWait_u {
|
||||||
|
RK_U32 val;
|
||||||
|
struct {
|
||||||
|
RK_U32 dec_pkt_in : 1; // 0x0001 MPP_DEC_NOTIFY_PACKET_ENQUEUE
|
||||||
|
RK_U32 dis_que_full : 1; // 0x0002 MPP_DEC_NOTIFY_FRAME_DEQUEUE
|
||||||
|
RK_U32 reserv0004 : 1; // 0x0004
|
||||||
|
RK_U32 reserv0008 : 1; // 0x0008
|
||||||
|
|
||||||
|
RK_U32 ext_buf_grp : 1; // 0x0010 MPP_DEC_NOTIFY_EXT_BUF_GRP_READY
|
||||||
|
RK_U32 info_change : 1; // 0x0020 MPP_DEC_NOTIFY_INFO_CHG_DONE
|
||||||
|
RK_U32 dec_pic_unusd : 1; // 0x0040 MPP_DEC_NOTIFY_BUFFER_VALID
|
||||||
|
RK_U32 dec_all_done : 1; // 0x0080 MPP_DEC_NOTIFY_TASK_ALL_DONE
|
||||||
|
|
||||||
|
RK_U32 task_hnd : 1; // 0x0100 MPP_DEC_NOTIFY_TASK_HND_VALID
|
||||||
|
RK_U32 prev_task : 1; // 0x0200 MPP_DEC_NOTIFY_TASK_PREV_DONE
|
||||||
|
RK_U32 dec_pic_match : 1; // 0x0400 MPP_DEC_NOTIFY_BUFFER_MATCH
|
||||||
|
RK_U32 reserv0800 : 1; // 0x0800
|
||||||
|
|
||||||
|
RK_U32 dec_pkt_idx : 1; // 0x1000
|
||||||
|
RK_U32 dec_pkt_buf : 1; // 0x2000
|
||||||
|
RK_U32 dec_slot_idx : 1; // 0x4000
|
||||||
|
};
|
||||||
|
} PaserTaskWait;
|
||||||
|
|
||||||
|
typedef union DecTaskStatus_u {
|
||||||
|
RK_U32 val;
|
||||||
|
struct {
|
||||||
|
RK_U32 task_hnd_rdy : 1;
|
||||||
|
RK_U32 mpp_pkt_in_rdy : 1;
|
||||||
|
RK_U32 dec_pkt_idx_rdy : 1;
|
||||||
|
RK_U32 dec_pkt_buf_rdy : 1;
|
||||||
|
RK_U32 task_valid_rdy : 1;
|
||||||
|
RK_U32 dec_pkt_copy_rdy : 1;
|
||||||
|
RK_U32 prev_task_rdy : 1;
|
||||||
|
RK_U32 info_task_gen_rdy : 1;
|
||||||
|
RK_U32 curr_task_rdy : 1;
|
||||||
|
RK_U32 task_parsed_rdy : 1;
|
||||||
|
};
|
||||||
|
} DecTaskStatus;
|
||||||
|
|
||||||
|
typedef struct MppPktTimestamp_t {
|
||||||
|
struct list_head link;
|
||||||
|
RK_S64 pts;
|
||||||
|
RK_S64 dts;
|
||||||
|
} MppPktTs;
|
||||||
|
|
||||||
|
typedef struct DecTask_t {
|
||||||
|
HalTaskHnd hnd;
|
||||||
|
|
||||||
|
DecTaskStatus status;
|
||||||
|
PaserTaskWait wait;
|
||||||
|
|
||||||
|
HalTaskInfo info;
|
||||||
|
MppPktTs ts_cur;
|
||||||
|
|
||||||
|
MppBuffer hal_pkt_buf_in;
|
||||||
|
RK_S32 hal_pkt_idx_in;
|
||||||
|
MppBuffer hal_frm_buf_out;
|
||||||
|
} DecTask;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
MPP_RET dec_task_info_init(HalTaskInfo *task);
|
||||||
|
void dec_task_init(DecTask *task);
|
||||||
|
|
||||||
|
MPP_RET mpp_dec_proc_cfg(MppDecImpl *dec, MpiCmd cmd, void *param);
|
||||||
|
|
||||||
|
MPP_RET update_dec_hal_info(MppDecImpl *dec, MppFrame frame);
|
||||||
|
void mpp_dec_put_frame(Mpp *mpp, RK_S32 index, HalDecTaskFlag flags);
|
||||||
|
void mpp_dec_push_display(Mpp *mpp, HalDecTaskFlag flags);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
32
mpp/codec/inc/mpp_dec_no_thread.h
Normal file
32
mpp/codec/inc/mpp_dec_no_thread.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MPP_DEC_NO_THREAD_H__
|
||||||
|
#define __MPP_DEC_NO_THREAD_H__
|
||||||
|
|
||||||
|
#include "mpp_dec_impl.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern MppDecModeApi dec_api_no_thread;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*__MPP_DEC_NO_THREAD_H__*/
|
32
mpp/codec/inc/mpp_dec_normal.h
Normal file
32
mpp/codec/inc/mpp_dec_normal.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MPP_DEC_NORMAL_H__
|
||||||
|
#define __MPP_DEC_NORMAL_H__
|
||||||
|
|
||||||
|
#include "mpp_dec_impl.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern MppDecModeApi dec_api_normal;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*__MPP_DEC_NORMAL_H__*/
|
File diff suppressed because it is too large
Load Diff
40
mpp/codec/mpp_dec_debug.h
Normal file
40
mpp/codec/mpp_dec_debug.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MPP_DEC_DEBUG_H__
|
||||||
|
#define __MPP_DEC_DEBUG_H__
|
||||||
|
|
||||||
|
#include "mpp_debug.h"
|
||||||
|
|
||||||
|
#define MPP_DEC_DBG_FUNCTION (0x00000001)
|
||||||
|
#define MPP_DEC_DBG_TIMING (0x00000002)
|
||||||
|
#define MPP_DEC_DBG_STATUS (0x00000010)
|
||||||
|
#define MPP_DEC_DBG_DETAIL (0x00000020)
|
||||||
|
#define MPP_DEC_DBG_RESET (0x00000040)
|
||||||
|
#define MPP_DEC_DBG_NOTIFY (0x00000080)
|
||||||
|
|
||||||
|
#define mpp_dec_dbg(flag, fmt, ...) _mpp_dbg(mpp_dec_debug, flag, fmt, ## __VA_ARGS__)
|
||||||
|
#define mpp_dec_dbg_f(flag, fmt, ...) _mpp_dbg_f(mpp_dec_debug, flag, fmt, ## __VA_ARGS__)
|
||||||
|
|
||||||
|
#define dec_dbg_func(fmt, ...) mpp_dec_dbg_f(MPP_DEC_DBG_FUNCTION, fmt, ## __VA_ARGS__)
|
||||||
|
#define dec_dbg_status(fmt, ...) mpp_dec_dbg_f(MPP_DEC_DBG_STATUS, fmt, ## __VA_ARGS__)
|
||||||
|
#define dec_dbg_detail(fmt, ...) mpp_dec_dbg(MPP_DEC_DBG_DETAIL, fmt, ## __VA_ARGS__)
|
||||||
|
#define dec_dbg_reset(fmt, ...) mpp_dec_dbg(MPP_DEC_DBG_RESET, fmt, ## __VA_ARGS__)
|
||||||
|
#define dec_dbg_notify(fmt, ...) mpp_dec_dbg_f(MPP_DEC_DBG_NOTIFY, fmt, ## __VA_ARGS__)
|
||||||
|
|
||||||
|
extern RK_U32 mpp_dec_debug;
|
||||||
|
|
||||||
|
#endif /* __MPP_DEC_DEBUG_H__ */
|
343
mpp/codec/mpp_dec_no_thread.cpp
Normal file
343
mpp/codec/mpp_dec_no_thread.cpp
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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_nt"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "mpp_buffer_impl.h"
|
||||||
|
|
||||||
|
#include "mpp_dec_debug.h"
|
||||||
|
#include "mpp_dec_vproc.h"
|
||||||
|
#include "mpp_dec_no_thread.h"
|
||||||
|
|
||||||
|
MPP_RET mpp_dec_decode(MppDec ctx, MppPacket packet, MppFrame *frame)
|
||||||
|
{
|
||||||
|
MppDecImpl *dec = (MppDecImpl *)ctx;
|
||||||
|
Mpp *mpp = (Mpp *)dec->mpp;
|
||||||
|
DecTask *task = (DecTask *)dec->task_single;
|
||||||
|
MppBufSlots frame_slots = dec->frame_slots;
|
||||||
|
MppBufSlots packet_slots = dec->packet_slots;
|
||||||
|
HalDecTask *task_dec = &task->info.dec;
|
||||||
|
MppMutexCond *cmd_lock = dec->cmd_lock;
|
||||||
|
MppBuffer hal_buf_in = NULL;
|
||||||
|
MppBuffer hal_buf_out = NULL;
|
||||||
|
size_t stream_size = 0;
|
||||||
|
RK_S32 output = 0;
|
||||||
|
|
||||||
|
AutoMutex auto_lock(cmd_lock->mutex());
|
||||||
|
|
||||||
|
if (dec->mpp_pkt_in == NULL && !task->status.curr_task_rdy)
|
||||||
|
dec->mpp_pkt_in = packet;
|
||||||
|
|
||||||
|
if (!task->status.curr_task_rdy) {
|
||||||
|
if (dec->mpp_pkt_in == NULL)
|
||||||
|
return MPP_OK;
|
||||||
|
|
||||||
|
mpp_parser_prepare(dec->parser, dec->mpp_pkt_in, task_dec);
|
||||||
|
|
||||||
|
if (0 == mpp_packet_get_length(dec->mpp_pkt_in)) {
|
||||||
|
// mpp_packet_deinit(&dec->mpp_pkt_in);
|
||||||
|
dec->mpp_pkt_in = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!task_dec->valid) {
|
||||||
|
if (task_dec->flags.eos) {
|
||||||
|
mpp_dec_flush(dec);
|
||||||
|
mpp_dec_push_display(mpp, task_dec->flags);
|
||||||
|
/*
|
||||||
|
* Use -1 as invalid buffer slot index.
|
||||||
|
* Reason: the last task maybe is a empty task with eos flag
|
||||||
|
* only but this task may go through vproc process also. We need
|
||||||
|
* create a buffer slot index for it.
|
||||||
|
*/
|
||||||
|
mpp_dec_put_frame(mpp, -1, task_dec->flags);
|
||||||
|
}
|
||||||
|
return MPP_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task->status.curr_task_rdy = task_dec->valid;
|
||||||
|
|
||||||
|
// NOTE: packet in task should be ready now
|
||||||
|
mpp_assert(task_dec->input_packet);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 4. look for a unused packet slot index
|
||||||
|
*/
|
||||||
|
if (task_dec->input < 0) {
|
||||||
|
mpp_buf_slot_get_unused(packet_slots, &task_dec->input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 5. malloc hardware buffer for the packet slot index
|
||||||
|
*/
|
||||||
|
task->hal_pkt_idx_in = task_dec->input;
|
||||||
|
stream_size = mpp_packet_get_size(task_dec->input_packet);
|
||||||
|
|
||||||
|
mpp_buf_slot_get_prop(packet_slots, task->hal_pkt_idx_in, SLOT_BUFFER, &hal_buf_in);
|
||||||
|
if (NULL == hal_buf_in) {
|
||||||
|
mpp_buffer_get(mpp->mPacketGroup, &hal_buf_in, stream_size);
|
||||||
|
if (hal_buf_in) {
|
||||||
|
mpp_buf_slot_set_prop(packet_slots, task->hal_pkt_idx_in, SLOT_BUFFER, hal_buf_in);
|
||||||
|
mpp_buffer_put(hal_buf_in);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MppBufferImpl *buf = (MppBufferImpl *)hal_buf_in;
|
||||||
|
mpp_assert(buf->info.size >= stream_size);
|
||||||
|
}
|
||||||
|
task->hal_pkt_buf_in = hal_buf_in;
|
||||||
|
if (!task->status.dec_pkt_copy_rdy) {
|
||||||
|
void *dst = mpp_buffer_get_ptr(task->hal_pkt_buf_in);
|
||||||
|
void *src = mpp_packet_get_data(task_dec->input_packet);
|
||||||
|
size_t length = mpp_packet_get_length(task_dec->input_packet);
|
||||||
|
memcpy(dst, src, length);
|
||||||
|
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);
|
||||||
|
task->status.dec_pkt_copy_rdy = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!task->status.task_parsed_rdy) {
|
||||||
|
mpp_clock_start(dec->clocks[DEC_PRS_PARSE]);
|
||||||
|
mpp_parser_parse(dec->parser, task_dec);
|
||||||
|
mpp_clock_pause(dec->clocks[DEC_PRS_PARSE]);
|
||||||
|
task->status.task_parsed_rdy = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task_dec->output < 0 || !task_dec->valid) {
|
||||||
|
/*
|
||||||
|
* We may meet an eos in parser step and there will be no anymore vaild
|
||||||
|
* task generated. So here we try push eos task to hal, hal will push
|
||||||
|
* all frame(s) to display, a frame of them with a eos flag will be
|
||||||
|
* used to inform that all frame have decoded
|
||||||
|
*/
|
||||||
|
if (task_dec->flags.eos) {
|
||||||
|
mpp_dec_flush(dec);
|
||||||
|
mpp_dec_push_display(mpp, task_dec->flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task->status.dec_pkt_copy_rdy) {
|
||||||
|
mpp_buf_slot_clr_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT);
|
||||||
|
task->status.dec_pkt_copy_rdy = 0;
|
||||||
|
}
|
||||||
|
task->status.curr_task_rdy = 0;
|
||||||
|
task->status.task_parsed_rdy = 0;
|
||||||
|
dec_task_info_init(&task->info);
|
||||||
|
return MPP_NOK;
|
||||||
|
}
|
||||||
|
dec_dbg_detail("detail: %p check output index pass\n", dec);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 9. parse local task and slot to check whether new buffer or info change is needed.
|
||||||
|
*
|
||||||
|
* detect info change from frame slot
|
||||||
|
*/
|
||||||
|
if (mpp_buf_slot_is_changed(frame_slots)) {
|
||||||
|
if (!task->status.info_task_gen_rdy) {
|
||||||
|
RK_U32 eos = task_dec->flags.eos;
|
||||||
|
// NOTE: info change should not go with eos flag
|
||||||
|
task_dec->flags.info_change = 1;
|
||||||
|
task_dec->flags.eos = 0;
|
||||||
|
mpp_dec_flush(dec);
|
||||||
|
mpp_dec_push_display(mpp, task_dec->flags);
|
||||||
|
mpp_dec_put_frame(mpp, task_dec->output, task_dec->flags);
|
||||||
|
task_dec->flags.eos = eos;
|
||||||
|
task->status.info_task_gen_rdy = 1;
|
||||||
|
return MPP_OK;
|
||||||
|
}
|
||||||
|
dec->info_updated = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
task->wait.info_change = mpp_buf_slot_is_changed(frame_slots);
|
||||||
|
if (task->wait.info_change) {
|
||||||
|
return MPP_OK;
|
||||||
|
} else {
|
||||||
|
task->status.info_task_gen_rdy = 0;
|
||||||
|
task_dec->flags.info_change = 0;
|
||||||
|
// NOTE: check the task must be ready
|
||||||
|
// mpp_assert(task->hnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 10. whether the frame buffer group is internal or external */
|
||||||
|
if (NULL == mpp->mFrameGroup) {
|
||||||
|
mpp_log("mpp_dec use internal frame buffer group\n");
|
||||||
|
mpp_buffer_group_get_internal(&mpp->mFrameGroup, MPP_BUFFER_TYPE_ION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 10.1 look for a unused hardware buffer for output */
|
||||||
|
if (mpp->mFrameGroup) {
|
||||||
|
RK_S32 unused = mpp_buffer_group_unused(mpp->mFrameGroup);
|
||||||
|
|
||||||
|
// NOTE: When dec post-process is enabled reserve 2 buffer for it.
|
||||||
|
task->wait.dec_pic_unusd = (dec->vproc) ? (unused < 3) : (unused < 1);
|
||||||
|
if (task->wait.dec_pic_unusd)
|
||||||
|
cmd_lock->wait();
|
||||||
|
}
|
||||||
|
dec_dbg_detail("detail: %p check frame group count pass\n", dec);
|
||||||
|
|
||||||
|
output = task_dec->output;
|
||||||
|
mpp_buf_slot_get_prop(frame_slots, output, SLOT_BUFFER, &hal_buf_out);
|
||||||
|
if (NULL == hal_buf_out) {
|
||||||
|
size_t size = mpp_buf_slot_get_size(frame_slots);
|
||||||
|
mpp_buffer_get(mpp->mFrameGroup, &hal_buf_out, size);
|
||||||
|
if (hal_buf_out)
|
||||||
|
mpp_buf_slot_set_prop(frame_slots, output, SLOT_BUFFER,
|
||||||
|
hal_buf_out);
|
||||||
|
}
|
||||||
|
if (!dec->info_updated && dec->dev) {
|
||||||
|
MppFrame slot_frm = NULL;
|
||||||
|
|
||||||
|
mpp_buf_slot_get_prop(frame_slots, output, SLOT_FRAME_PTR, &slot_frm);
|
||||||
|
update_dec_hal_info(dec, slot_frm);
|
||||||
|
dec->info_updated = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
task->hal_frm_buf_out = hal_buf_out;
|
||||||
|
task->wait.dec_pic_match = (NULL == hal_buf_out);
|
||||||
|
if (task->wait.dec_pic_match)
|
||||||
|
return MPP_NOK;
|
||||||
|
|
||||||
|
mpp_hal_reg_gen(dec->hal, &task->info);
|
||||||
|
mpp_hal_hw_start(dec->hal, &task->info);
|
||||||
|
mpp_hal_hw_wait(dec->hal, &task->info);
|
||||||
|
dec->dec_hw_run_count++;
|
||||||
|
/*
|
||||||
|
* when hardware decoding is done:
|
||||||
|
* 1. clear decoding flag (mark buffer is ready)
|
||||||
|
* 2. use get_display to get a new frame with buffer
|
||||||
|
* 3. add frame to output list
|
||||||
|
* repeat 2 and 3 until not frame can be output
|
||||||
|
*/
|
||||||
|
mpp_buf_slot_clr_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT);
|
||||||
|
|
||||||
|
if (task_dec->output >= 0)
|
||||||
|
mpp_buf_slot_clr_flag(frame_slots, task_dec->output, SLOT_HAL_OUTPUT);
|
||||||
|
|
||||||
|
for (RK_U32 i = 0; i < MPP_ARRAY_ELEMS(task_dec->refer); i++) {
|
||||||
|
RK_S32 index = task_dec->refer[i];
|
||||||
|
if (index >= 0)
|
||||||
|
mpp_buf_slot_clr_flag(frame_slots, index, SLOT_HAL_INPUT);
|
||||||
|
}
|
||||||
|
if (task_dec->flags.eos)
|
||||||
|
mpp_dec_flush(dec);
|
||||||
|
|
||||||
|
mpp_dec_push_display(mpp, task_dec->flags);
|
||||||
|
|
||||||
|
(void)frame;
|
||||||
|
|
||||||
|
task->status.dec_pkt_copy_rdy = 0;
|
||||||
|
task->status.curr_task_rdy = 0;
|
||||||
|
task->status.task_parsed_rdy = 0;
|
||||||
|
task->status.prev_task_rdy = 0;
|
||||||
|
dec_task_info_init(&task->info);
|
||||||
|
return MPP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MPP_RET mpp_dec_reset_no_thread(MppDecImpl *dec)
|
||||||
|
{
|
||||||
|
DecTask *task = (DecTask *)dec->task_single;
|
||||||
|
MppBufSlots frame_slots = dec->frame_slots;
|
||||||
|
MppMutexCond *cmd_lock = dec->cmd_lock;
|
||||||
|
HalDecTask *task_dec = &task->info.dec;
|
||||||
|
RK_S32 index;
|
||||||
|
|
||||||
|
AutoMutex auto_lock(cmd_lock->mutex());
|
||||||
|
|
||||||
|
task->status.curr_task_rdy = 0;
|
||||||
|
task->status.prev_task_rdy = 1;
|
||||||
|
task_dec->valid = 0;
|
||||||
|
mpp_parser_reset(dec->parser);
|
||||||
|
mpp_hal_reset(dec->hal);
|
||||||
|
if (dec->vproc) {
|
||||||
|
dec_dbg_reset("reset: vproc reset start\n");
|
||||||
|
dec_vproc_reset(dec->vproc);
|
||||||
|
dec_dbg_reset("reset: vproc reset done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait hal thread reset ready
|
||||||
|
if (task->wait.info_change) {
|
||||||
|
mpp_log("reset at info change status\n");
|
||||||
|
mpp_buf_slot_reset(frame_slots, task_dec->output);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task->status.task_parsed_rdy) {
|
||||||
|
mpp_log("task no send to hal que must clr current frame hal status\n");
|
||||||
|
mpp_buf_slot_clr_flag(frame_slots, task_dec->output, SLOT_HAL_OUTPUT);
|
||||||
|
for (RK_U32 i = 0; i < MPP_ARRAY_ELEMS(task_dec->refer); i++) {
|
||||||
|
index = task_dec->refer[i];
|
||||||
|
if (index >= 0)
|
||||||
|
mpp_buf_slot_clr_flag(frame_slots, index, SLOT_HAL_INPUT);
|
||||||
|
}
|
||||||
|
task->status.task_parsed_rdy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (MPP_OK == mpp_buf_slot_dequeue(frame_slots, &index, QUEUE_DISPLAY)) {
|
||||||
|
/* release extra ref in slot's MppBuffer */
|
||||||
|
MppBuffer buffer = NULL;
|
||||||
|
mpp_buf_slot_get_prop(frame_slots, index, SLOT_BUFFER, &buffer);
|
||||||
|
if (buffer)
|
||||||
|
mpp_buffer_put(buffer);
|
||||||
|
mpp_buf_slot_clr_flag(frame_slots, index, SLOT_QUEUE_USE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task->status.dec_pkt_copy_rdy) {
|
||||||
|
mpp_buf_slot_clr_flag(dec->packet_slots, task_dec->input, SLOT_HAL_INPUT);
|
||||||
|
task->status.dec_pkt_copy_rdy = 0;
|
||||||
|
task_dec->input = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
task->status.task_parsed_rdy = 0;
|
||||||
|
dec_task_init(task);
|
||||||
|
|
||||||
|
dec_dbg_reset("reset: parser reset all done\n");
|
||||||
|
|
||||||
|
dec->dec_in_pkt_count = 0;
|
||||||
|
dec->dec_hw_run_count = 0;
|
||||||
|
dec->dec_out_frame_count = 0;
|
||||||
|
dec->info_updated = 0;
|
||||||
|
|
||||||
|
cmd_lock->signal();
|
||||||
|
|
||||||
|
return MPP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MPP_RET mpp_dec_notify_no_thread(MppDecImpl *dec, RK_U32 flag)
|
||||||
|
{
|
||||||
|
// Only notify buffer group control
|
||||||
|
if (flag == (MPP_DEC_NOTIFY_BUFFER_VALID | MPP_DEC_NOTIFY_BUFFER_MATCH)) {
|
||||||
|
dec->cmd_lock->signal();
|
||||||
|
return MPP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MPP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MPP_RET mpp_dec_control_no_thread(MppDecImpl *dec, MpiCmd cmd, void *param)
|
||||||
|
{
|
||||||
|
// cmd_lock is used to sync all async operations
|
||||||
|
AutoMutex auto_lock(dec->cmd_lock->mutex());
|
||||||
|
|
||||||
|
dec->cmd_send++;
|
||||||
|
return mpp_dec_proc_cfg(dec, cmd, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
MppDecModeApi dec_api_no_thread = {
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
mpp_dec_reset_no_thread,
|
||||||
|
mpp_dec_notify_no_thread,
|
||||||
|
mpp_dec_control_no_thread,
|
||||||
|
};
|
1179
mpp/codec/mpp_dec_normal.cpp
Normal file
1179
mpp/codec/mpp_dec_normal.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -115,6 +115,7 @@ public:
|
|||||||
|
|
||||||
MPP_RET put_packet(MppPacket packet);
|
MPP_RET put_packet(MppPacket packet);
|
||||||
MPP_RET get_frame(MppFrame *frame);
|
MPP_RET get_frame(MppFrame *frame);
|
||||||
|
MPP_RET get_frame_noblock(MppFrame *frame);
|
||||||
|
|
||||||
MPP_RET put_frame(MppFrame frame);
|
MPP_RET put_frame(MppFrame frame);
|
||||||
MPP_RET get_packet(MppPacket *packet);
|
MPP_RET get_packet(MppPacket *packet);
|
||||||
@@ -123,6 +124,8 @@ public:
|
|||||||
MPP_RET dequeue(MppPortType type, MppTask *task);
|
MPP_RET dequeue(MppPortType type, MppTask *task);
|
||||||
MPP_RET enqueue(MppPortType type, MppTask task);
|
MPP_RET enqueue(MppPortType type, MppTask task);
|
||||||
|
|
||||||
|
MPP_RET decode(MppPacket packet, MppFrame *frame);
|
||||||
|
|
||||||
MPP_RET reset();
|
MPP_RET reset();
|
||||||
MPP_RET control(MpiCmd cmd, MppParam param);
|
MPP_RET control(MpiCmd cmd, MppParam param);
|
||||||
|
|
||||||
@@ -188,6 +191,7 @@ public:
|
|||||||
RK_U32 mEncAyncIo;
|
RK_U32 mEncAyncIo;
|
||||||
RK_U32 mEncAyncProc;
|
RK_U32 mEncAyncProc;
|
||||||
MppIoMode mIoMode;
|
MppIoMode mIoMode;
|
||||||
|
RK_U32 mDisableThread;
|
||||||
|
|
||||||
/* dump info for debug */
|
/* dump info for debug */
|
||||||
MppDump mDump;
|
MppDump mDump;
|
||||||
|
42
mpp/mpi.cpp
42
mpp/mpi.cpp
@@ -103,47 +103,23 @@ static MPP_RET mpi_decode(MppCtx ctx, MppPacket packet, MppFrame *frame)
|
|||||||
MpiImpl *p = (MpiImpl *)ctx;
|
MpiImpl *p = (MpiImpl *)ctx;
|
||||||
|
|
||||||
mpi_dbg_func("enter ctx %p packet %p frame %p\n", ctx, packet, frame);
|
mpi_dbg_func("enter ctx %p packet %p frame %p\n", ctx, packet, frame);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
RK_U32 packet_done = 0;
|
|
||||||
Mpp *mpp = p->ctx;
|
|
||||||
ret = check_mpp_ctx(p);
|
ret = check_mpp_ctx(p);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (NULL == frame || NULL == packet) {
|
/*
|
||||||
mpp_err_f("found NULL input packet %p frame %p\n", packet, frame);
|
* NOTE: packet and frame could be NULL
|
||||||
ret = MPP_ERR_NULL_PTR;
|
* If packet is NULL then it is equal to get_frame
|
||||||
break;
|
* If frame is NULL then it is equal to put_packet
|
||||||
}
|
*/
|
||||||
|
if (frame)
|
||||||
|
*frame = NULL;
|
||||||
|
|
||||||
*frame = NULL;
|
ret = p->ctx->decode(packet, frame);
|
||||||
|
|
||||||
do {
|
|
||||||
/*
|
|
||||||
* If there is frame to return get the frame first
|
|
||||||
* But if the output mode is block then we need to send packet first
|
|
||||||
*/
|
|
||||||
if (!mpp->mOutputTimeout || packet_done) {
|
|
||||||
ret = mpp->get_frame(frame);
|
|
||||||
if (ret || *frame)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* when packet is send do one more get frame here */
|
|
||||||
if (packet_done)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* then send input stream with timeout mode
|
|
||||||
*/
|
|
||||||
ret = mpp->put_packet(packet);
|
|
||||||
if (MPP_OK == ret)
|
|
||||||
packet_done = 1;
|
|
||||||
} while (1);
|
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
mpp_assert(0 == mpp_packet_get_length(packet));
|
|
||||||
|
|
||||||
mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
|
mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
71
mpp/mpp.cpp
71
mpp/mpp.cpp
@@ -41,8 +41,6 @@
|
|||||||
#define MPP_TEST_FRAME_SIZE SZ_1M
|
#define MPP_TEST_FRAME_SIZE SZ_1M
|
||||||
#define MPP_TEST_PACKET_SIZE SZ_512K
|
#define MPP_TEST_PACKET_SIZE SZ_512K
|
||||||
|
|
||||||
typedef MPP_RET (*QueueFunc)(Mpp* mpp, MppPortType type, MppTask *task);
|
|
||||||
|
|
||||||
static void mpp_notify_by_buffer_group(void *arg, void *group)
|
static void mpp_notify_by_buffer_group(void *arg, void *group)
|
||||||
{
|
{
|
||||||
Mpp *mpp = (Mpp *)arg;
|
Mpp *mpp = (Mpp *)arg;
|
||||||
@@ -103,6 +101,7 @@ Mpp::Mpp(MppCtx ctx)
|
|||||||
mEncAyncIo(0),
|
mEncAyncIo(0),
|
||||||
mEncAyncProc(0),
|
mEncAyncProc(0),
|
||||||
mIoMode(MPP_IO_MODE_DEFAULT),
|
mIoMode(MPP_IO_MODE_DEFAULT),
|
||||||
|
mDisableThread(0),
|
||||||
mDump(NULL),
|
mDump(NULL),
|
||||||
mType(MPP_CTX_BUTT),
|
mType(MPP_CTX_BUTT),
|
||||||
mCoding(MPP_VIDEO_CodingUnused),
|
mCoding(MPP_VIDEO_CodingUnused),
|
||||||
@@ -172,6 +171,9 @@ MPP_RET Mpp::init(MppCtxType type, MppCodingType coding)
|
|||||||
mMppInPort = mpp_task_queue_get_port(mInputTaskQueue, MPP_PORT_OUTPUT);
|
mMppInPort = mpp_task_queue_get_port(mInputTaskQueue, MPP_PORT_OUTPUT);
|
||||||
mMppOutPort = mpp_task_queue_get_port(mOutputTaskQueue, MPP_PORT_INPUT);
|
mMppOutPort = mpp_task_queue_get_port(mOutputTaskQueue, MPP_PORT_INPUT);
|
||||||
|
|
||||||
|
mDecInitcfg.base.disable_thread = mDisableThread;
|
||||||
|
mDecInitcfg.base.change |= MPP_DEC_CFG_CHANGE_DISABLE_THREAD;
|
||||||
|
|
||||||
MppDecInitCfg cfg = {
|
MppDecInitCfg cfg = {
|
||||||
coding,
|
coding,
|
||||||
this,
|
this,
|
||||||
@@ -316,6 +318,7 @@ void Mpp::clear()
|
|||||||
mpp_buffer_group_put(mPacketGroup);
|
mpp_buffer_group_put(mPacketGroup);
|
||||||
mPacketGroup = NULL;
|
mPacketGroup = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFrameGroup && !mExternalFrameGroup) {
|
if (mFrameGroup && !mExternalFrameGroup) {
|
||||||
mpp_buffer_group_put(mFrameGroup);
|
mpp_buffer_group_put(mFrameGroup);
|
||||||
mFrameGroup = NULL;
|
mFrameGroup = NULL;
|
||||||
@@ -354,6 +357,11 @@ MPP_RET Mpp::put_packet(MppPacket packet)
|
|||||||
MppTask task_dequeue = NULL;
|
MppTask task_dequeue = NULL;
|
||||||
RK_U32 pkt_copy = 0;
|
RK_U32 pkt_copy = 0;
|
||||||
|
|
||||||
|
if (mDisableThread) {
|
||||||
|
mpp_err_f("no thread decoding case MUST use mpi_decode interface\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (mExtraPacket) {
|
if (mExtraPacket) {
|
||||||
MppPacket extra = mExtraPacket;
|
MppPacket extra = mExtraPacket;
|
||||||
|
|
||||||
@@ -504,6 +512,61 @@ MPP_RET Mpp::get_frame(MppFrame *frame)
|
|||||||
return MPP_OK;
|
return MPP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MPP_RET Mpp::get_frame_noblock(MppFrame *frame)
|
||||||
|
{
|
||||||
|
MppFrame first = NULL;
|
||||||
|
|
||||||
|
if (!mInitDone)
|
||||||
|
return MPP_ERR_INIT;
|
||||||
|
|
||||||
|
mFrmOut->lock();
|
||||||
|
if (mFrmOut->list_size()) {
|
||||||
|
mFrmOut->del_at_head(&first, sizeof(frame));
|
||||||
|
mFrameGetCount++;
|
||||||
|
}
|
||||||
|
mFrmOut->unlock();
|
||||||
|
*frame = first;
|
||||||
|
|
||||||
|
return MPP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MPP_RET Mpp::decode(MppPacket packet, MppFrame *frame)
|
||||||
|
{
|
||||||
|
RK_U32 packet_done = 0;
|
||||||
|
MPP_RET ret = MPP_NOK;
|
||||||
|
|
||||||
|
if (!mDec)
|
||||||
|
return MPP_NOK;
|
||||||
|
|
||||||
|
do {
|
||||||
|
/*
|
||||||
|
* If there is frame to return get the frame first
|
||||||
|
* But if the output mode is block then we need to send packet first
|
||||||
|
*/
|
||||||
|
if (!mOutputTimeout || packet_done) {
|
||||||
|
ret = get_frame_noblock(frame);
|
||||||
|
if (ret || *frame)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* when packet is send do one more get frame here */
|
||||||
|
if (packet_done)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = mpp_dec_decode(mDec, packet, frame);
|
||||||
|
if (!ret)
|
||||||
|
packet_done = 1;
|
||||||
|
|
||||||
|
if (!mOutputTimeout || packet_done) {
|
||||||
|
ret = get_frame_noblock(frame);
|
||||||
|
if (ret || *frame)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
MPP_RET Mpp::put_frame(MppFrame frame)
|
MPP_RET Mpp::put_frame(MppFrame frame)
|
||||||
{
|
{
|
||||||
if (!mInitDone)
|
if (!mInitDone)
|
||||||
@@ -979,6 +1042,10 @@ MPP_RET Mpp::control_mpp(MpiCmd cmd, MppParam param)
|
|||||||
mpp_log("deprecated block control, use timeout control instead\n");
|
mpp_log("deprecated block control, use timeout control instead\n");
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case MPP_SET_DISABLE_THREAD: {
|
||||||
|
mDisableThread = 1;
|
||||||
|
} break;
|
||||||
|
|
||||||
case MPP_SET_INPUT_TIMEOUT:
|
case MPP_SET_INPUT_TIMEOUT:
|
||||||
case MPP_SET_OUTPUT_TIMEOUT: {
|
case MPP_SET_OUTPUT_TIMEOUT: {
|
||||||
MppPollType timeout = (param) ? *((MppPollType *)param) : MPP_POLL_NON_BLOCK;
|
MppPollType timeout = (param) ? *((MppPollType *)param) : MPP_POLL_NON_BLOCK;
|
||||||
|
@@ -30,6 +30,9 @@ add_mpp_test(mpi_dec c)
|
|||||||
# mpi decoder multi-thread input / output unit test
|
# mpi decoder multi-thread input / output unit test
|
||||||
add_mpp_test(mpi_dec_mt c)
|
add_mpp_test(mpi_dec_mt c)
|
||||||
|
|
||||||
|
# mpi decoder no-thread input / output unit test
|
||||||
|
add_mpp_test(mpi_dec_nt c)
|
||||||
|
|
||||||
# mpi encoder unit test
|
# mpi encoder unit test
|
||||||
add_mpp_test(mpi_enc c)
|
add_mpp_test(mpi_enc c)
|
||||||
|
|
||||||
|
602
test/mpi_dec_nt_test.c
Normal file
602
test/mpi_dec_nt_test.c
Normal file
@@ -0,0 +1,602 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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_nt_test"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "rk_mpi.h"
|
||||||
|
|
||||||
|
#include "mpp_mem.h"
|
||||||
|
#include "mpp_env.h"
|
||||||
|
#include "mpp_time.h"
|
||||||
|
#include "mpp_common.h"
|
||||||
|
#include "mpi_dec_utils.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
MpiDecTestCmd *cmd;
|
||||||
|
MppCtx ctx;
|
||||||
|
MppApi *mpi;
|
||||||
|
RK_U32 quiet;
|
||||||
|
|
||||||
|
/* end of stream flag when set quit the loop */
|
||||||
|
RK_U32 loop_end;
|
||||||
|
|
||||||
|
/* input and output */
|
||||||
|
MppBufferGroup frm_grp;
|
||||||
|
MppPacket packet;
|
||||||
|
MppFrame frame;
|
||||||
|
|
||||||
|
FILE *fp_output;
|
||||||
|
RK_S32 frame_count;
|
||||||
|
RK_S32 frame_num;
|
||||||
|
|
||||||
|
RK_S64 first_pkt;
|
||||||
|
RK_S64 first_frm;
|
||||||
|
|
||||||
|
size_t max_usage;
|
||||||
|
float frame_rate;
|
||||||
|
RK_S64 elapsed_time;
|
||||||
|
RK_S64 delay;
|
||||||
|
FILE *fp_verify;
|
||||||
|
FrmCrc checkcrc;
|
||||||
|
} MpiDecLoopData;
|
||||||
|
|
||||||
|
static int dec_loop(MpiDecLoopData *data)
|
||||||
|
{
|
||||||
|
RK_U32 pkt_done = 0;
|
||||||
|
RK_U32 pkt_eos = 0;
|
||||||
|
MPP_RET ret = MPP_OK;
|
||||||
|
MpiDecTestCmd *cmd = data->cmd;
|
||||||
|
MppCtx ctx = data->ctx;
|
||||||
|
MppApi *mpi = data->mpi;
|
||||||
|
MppPacket packet = data->packet;
|
||||||
|
FileBufSlot *slot = NULL;
|
||||||
|
RK_U32 quiet = data->quiet;
|
||||||
|
FrmCrc *checkcrc = &data->checkcrc;
|
||||||
|
|
||||||
|
// when packet size is valid read the input binary file
|
||||||
|
ret = reader_read(cmd->reader, &slot);
|
||||||
|
|
||||||
|
mpp_assert(ret == MPP_OK);
|
||||||
|
mpp_assert(slot);
|
||||||
|
|
||||||
|
pkt_eos = slot->eos;
|
||||||
|
|
||||||
|
if (pkt_eos) {
|
||||||
|
if (data->frame_num < 0 || data->frame_num > data->frame_count) {
|
||||||
|
mpp_log_q(quiet, "%p loop again\n", ctx);
|
||||||
|
reader_rewind(cmd->reader);
|
||||||
|
pkt_eos = 0;
|
||||||
|
} else {
|
||||||
|
mpp_log_q(quiet, "%p found last packet\n", ctx);
|
||||||
|
data->loop_end = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mpp_packet_set_data(packet, slot->data);
|
||||||
|
mpp_packet_set_size(packet, slot->size);
|
||||||
|
mpp_packet_set_pos(packet, slot->data);
|
||||||
|
mpp_packet_set_length(packet, slot->size);
|
||||||
|
// setup eos flag
|
||||||
|
if (pkt_eos)
|
||||||
|
mpp_packet_set_eos(packet);
|
||||||
|
|
||||||
|
do {
|
||||||
|
RK_U32 frm_eos = 0;
|
||||||
|
RK_S32 get_frm = 0;
|
||||||
|
MppFrame frame = NULL;
|
||||||
|
|
||||||
|
// send the packet first if packet is not done
|
||||||
|
ret = mpi->decode(ctx, packet, &frame);
|
||||||
|
if (ret)
|
||||||
|
mpp_err("decode failed ret %d\n", ret);
|
||||||
|
|
||||||
|
// then get all available frame and release
|
||||||
|
if (frame) {
|
||||||
|
if (mpp_frame_get_info_change(frame)) {
|
||||||
|
RK_U32 width = mpp_frame_get_width(frame);
|
||||||
|
RK_U32 height = mpp_frame_get_height(frame);
|
||||||
|
RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
|
||||||
|
RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
|
||||||
|
RK_U32 buf_size = mpp_frame_get_buf_size(frame);
|
||||||
|
|
||||||
|
mpp_log_q(quiet, "%p decode_get_frame get info changed found\n", ctx);
|
||||||
|
mpp_log_q(quiet, "%p decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d",
|
||||||
|
ctx, width, height, hor_stride, ver_stride, buf_size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: We can choose decoder's buffer mode here.
|
||||||
|
* There are three mode that decoder can support:
|
||||||
|
*
|
||||||
|
* Mode 1: Pure internal mode
|
||||||
|
* In the mode user will NOT call MPP_DEC_SET_EXT_BUF_GROUP
|
||||||
|
* control to decoder. Only call MPP_DEC_SET_INFO_CHANGE_READY
|
||||||
|
* to let decoder go on. Then decoder will use create buffer
|
||||||
|
* internally and user need to release each frame they get.
|
||||||
|
*
|
||||||
|
* Advantage:
|
||||||
|
* Easy to use and get a demo quickly
|
||||||
|
* Disadvantage:
|
||||||
|
* 1. The buffer from decoder may not be return before
|
||||||
|
* decoder is close. So memroy leak or crash may happen.
|
||||||
|
* 2. The decoder memory usage can not be control. Decoder
|
||||||
|
* is on a free-to-run status and consume all memory it can
|
||||||
|
* get.
|
||||||
|
* 3. Difficult to implement zero-copy display path.
|
||||||
|
*
|
||||||
|
* Mode 2: Half internal mode
|
||||||
|
* This is the mode current test code using. User need to
|
||||||
|
* create MppBufferGroup according to the returned info
|
||||||
|
* change MppFrame. User can use mpp_buffer_group_limit_config
|
||||||
|
* function to limit decoder memory usage.
|
||||||
|
*
|
||||||
|
* Advantage:
|
||||||
|
* 1. Easy to use
|
||||||
|
* 2. User can release MppBufferGroup after decoder is closed.
|
||||||
|
* So memory can stay longer safely.
|
||||||
|
* 3. Can limit the memory usage by mpp_buffer_group_limit_config
|
||||||
|
* Disadvantage:
|
||||||
|
* 1. The buffer limitation is still not accurate. Memory usage
|
||||||
|
* is 100% fixed.
|
||||||
|
* 2. Also difficult to implement zero-copy display path.
|
||||||
|
*
|
||||||
|
* Mode 3: Pure external mode
|
||||||
|
* In this mode use need to create empty MppBufferGroup and
|
||||||
|
* import memory from external allocator by file handle.
|
||||||
|
* On Android surfaceflinger will create buffer. Then
|
||||||
|
* mediaserver get the file handle from surfaceflinger and
|
||||||
|
* commit to decoder's MppBufferGroup.
|
||||||
|
*
|
||||||
|
* Advantage:
|
||||||
|
* 1. Most efficient way for zero-copy display
|
||||||
|
* Disadvantage:
|
||||||
|
* 1. Difficult to learn and use.
|
||||||
|
* 2. Player work flow may limit this usage.
|
||||||
|
* 3. May need a external parser to get the correct buffer
|
||||||
|
* size for the external allocator.
|
||||||
|
*
|
||||||
|
* The required buffer size caculation:
|
||||||
|
* hor_stride * ver_stride * 3 / 2 for pixel data
|
||||||
|
* hor_stride * ver_stride / 2 for extra info
|
||||||
|
* Total hor_stride * ver_stride * 2 will be enough.
|
||||||
|
*
|
||||||
|
* For H.264/H.265 20+ buffers will be enough.
|
||||||
|
* For other codec 10 buffers will be enough.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (NULL == data->frm_grp) {
|
||||||
|
/* If buffer group is not set create one and limit it */
|
||||||
|
ret = mpp_buffer_group_get_internal(&data->frm_grp, MPP_BUFFER_TYPE_ION);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("%p get mpp buffer group failed ret %d\n", ctx, ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set buffer to mpp decoder */
|
||||||
|
ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, data->frm_grp);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("%p set buffer group failed ret %d\n", ctx, ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* If old buffer group exist clear it */
|
||||||
|
ret = mpp_buffer_group_clear(data->frm_grp);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("%p clear buffer group failed ret %d\n", ctx, ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use limit config to limit buffer count to 24 with buf_size */
|
||||||
|
ret = mpp_buffer_group_limit_config(data->frm_grp, buf_size, 24);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("%p limit buffer group failed ret %d\n", ctx, ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All buffer group config done. Set info change ready to let
|
||||||
|
* decoder continue decoding
|
||||||
|
*/
|
||||||
|
ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("%p info change ready failed ret %d\n", ctx, ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
char log_buf[256];
|
||||||
|
RK_S32 log_size = sizeof(log_buf) - 1;
|
||||||
|
RK_S32 log_len = 0;
|
||||||
|
RK_U32 err_info = mpp_frame_get_errinfo(frame);
|
||||||
|
RK_U32 discard = mpp_frame_get_discard(frame);
|
||||||
|
|
||||||
|
if (!data->first_frm)
|
||||||
|
data->first_frm = mpp_time();
|
||||||
|
|
||||||
|
log_len += snprintf(log_buf + log_len, log_size - log_len,
|
||||||
|
"decode get frame %d", data->frame_count);
|
||||||
|
|
||||||
|
if (mpp_frame_has_meta(frame)) {
|
||||||
|
MppMeta meta = mpp_frame_get_meta(frame);
|
||||||
|
RK_S32 temporal_id = 0;
|
||||||
|
|
||||||
|
mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id);
|
||||||
|
|
||||||
|
log_len += snprintf(log_buf + log_len, log_size - log_len,
|
||||||
|
" tid %d", temporal_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err_info || discard) {
|
||||||
|
log_len += snprintf(log_buf + log_len, log_size - log_len,
|
||||||
|
" err %x discard %x", err_info, discard);
|
||||||
|
}
|
||||||
|
mpp_log_q(quiet, "%p %s\n", ctx, log_buf);
|
||||||
|
|
||||||
|
data->frame_count++;
|
||||||
|
if (data->fp_output && !err_info)
|
||||||
|
dump_mpp_frame_to_file(frame, data->fp_output);
|
||||||
|
|
||||||
|
if (data->fp_verify) {
|
||||||
|
calc_frm_crc(frame, checkcrc);
|
||||||
|
write_frm_crc(data->fp_verify, checkcrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
fps_calc_inc(cmd->fps);
|
||||||
|
}
|
||||||
|
frm_eos = mpp_frame_get_eos(frame);
|
||||||
|
mpp_frame_deinit(&frame);
|
||||||
|
get_frm = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try get runtime frame memory usage
|
||||||
|
if (data->frm_grp) {
|
||||||
|
size_t usage = mpp_buffer_group_usage(data->frm_grp);
|
||||||
|
if (usage > data->max_usage)
|
||||||
|
data->max_usage = usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// when get one output frame check the output frame count limit
|
||||||
|
if (get_frm) {
|
||||||
|
if (data->frame_num > 0) {
|
||||||
|
// when get enough frame quit
|
||||||
|
if (data->frame_count >= data->frame_num) {
|
||||||
|
data->loop_end = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// when get last frame quit
|
||||||
|
if (frm_eos) {
|
||||||
|
mpp_log_q(quiet, "%p found last packet\n", ctx);
|
||||||
|
data->loop_end = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet) {
|
||||||
|
if (mpp_packet_get_length(packet)) {
|
||||||
|
msleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data->first_pkt)
|
||||||
|
data->first_pkt = mpp_time();
|
||||||
|
|
||||||
|
packet = NULL;
|
||||||
|
pkt_done = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpp_assert(pkt_done);
|
||||||
|
|
||||||
|
// if last packet is send but last frame is not found continue
|
||||||
|
if (pkt_eos && !frm_eos) {
|
||||||
|
msleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pkt_done)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* why sleep here:
|
||||||
|
* mpi->decode_put_packet will failed when packet in internal queue is
|
||||||
|
* full,waiting the package is consumed .Usually hardware decode one
|
||||||
|
* frame which resolution is 1080p needs 2 ms,so here we sleep 1ms
|
||||||
|
* * is enough.
|
||||||
|
*/
|
||||||
|
msleep(1);
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *thread_decode(void *arg)
|
||||||
|
{
|
||||||
|
MpiDecLoopData *data = (MpiDecLoopData *)arg;
|
||||||
|
RK_S64 t_s, t_e;
|
||||||
|
|
||||||
|
memset(&data->checkcrc, 0, sizeof(data->checkcrc));
|
||||||
|
data->checkcrc.luma.sum = mpp_malloc(RK_ULONG, 512);
|
||||||
|
data->checkcrc.chroma.sum = mpp_malloc(RK_ULONG, 512);
|
||||||
|
|
||||||
|
t_s = mpp_time();
|
||||||
|
|
||||||
|
while (!data->loop_end)
|
||||||
|
dec_loop(data);
|
||||||
|
|
||||||
|
t_e = mpp_time();
|
||||||
|
data->elapsed_time = t_e - t_s;
|
||||||
|
data->frame_count = data->frame_count;
|
||||||
|
data->frame_rate = (float)data->frame_count * 1000000 / data->elapsed_time;
|
||||||
|
data->delay = data->first_frm - data->first_pkt;
|
||||||
|
|
||||||
|
mpp_log("decode %d frames time %lld ms delay %3d ms fps %3.2f\n",
|
||||||
|
data->frame_count, (RK_S64)(data->elapsed_time / 1000),
|
||||||
|
(RK_S32)(data->delay / 1000), data->frame_rate);
|
||||||
|
|
||||||
|
MPP_FREE(data->checkcrc.luma.sum);
|
||||||
|
MPP_FREE(data->checkcrc.chroma.sum);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dec_nt_decode(MpiDecTestCmd *cmd)
|
||||||
|
{
|
||||||
|
// base flow context
|
||||||
|
MppCtx ctx = NULL;
|
||||||
|
MppApi *mpi = NULL;
|
||||||
|
|
||||||
|
// input / output
|
||||||
|
MppPacket packet = NULL;
|
||||||
|
MppFrame frame = NULL;
|
||||||
|
|
||||||
|
// paramter for resource malloc
|
||||||
|
RK_U32 width = cmd->width;
|
||||||
|
RK_U32 height = cmd->height;
|
||||||
|
MppCodingType type = cmd->type;
|
||||||
|
|
||||||
|
// config for runtime mode
|
||||||
|
MppDecCfg cfg = NULL;
|
||||||
|
RK_U32 need_split = 1;
|
||||||
|
|
||||||
|
// resources
|
||||||
|
MppBuffer frm_buf = NULL;
|
||||||
|
pthread_t thd;
|
||||||
|
pthread_attr_t attr;
|
||||||
|
MpiDecLoopData data;
|
||||||
|
MPP_RET ret = MPP_OK;
|
||||||
|
|
||||||
|
mpp_log("mpi_dec_test start\n");
|
||||||
|
memset(&data, 0, sizeof(data));
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
|
||||||
|
cmd->simple = (cmd->type != MPP_VIDEO_CodingMJPEG) ? (1) : (0);
|
||||||
|
|
||||||
|
if (cmd->have_output) {
|
||||||
|
data.fp_output = fopen(cmd->file_output, "w+b");
|
||||||
|
if (NULL == data.fp_output) {
|
||||||
|
mpp_err("failed to open output file %s\n", cmd->file_output);
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->file_slt) {
|
||||||
|
data.fp_verify = fopen(cmd->file_slt, "wt");
|
||||||
|
if (!data.fp_verify)
|
||||||
|
mpp_err("failed to open verify file %s\n", cmd->file_slt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->simple) {
|
||||||
|
ret = mpp_packet_init(&packet, NULL, 0);
|
||||||
|
mpp_err_f("mpp_packet_init get %p\n", packet);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("mpp_packet_init failed\n");
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RK_U32 hor_stride = MPP_ALIGN(width, 16);
|
||||||
|
RK_U32 ver_stride = MPP_ALIGN(height, 16);
|
||||||
|
|
||||||
|
ret = mpp_buffer_group_get_internal(&data.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_frame_init(&frame); /* output frame */
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("mpp_frame_init failed\n");
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: For jpeg could have YUV420 and YUV422 the buffer should be
|
||||||
|
* larger for output. And the buffer dimension should align to 16.
|
||||||
|
* YUV420 buffer is 3/2 times of w*h.
|
||||||
|
* YUV422 buffer is 2 times of w*h.
|
||||||
|
* So create larger buffer with 2 times w*h.
|
||||||
|
*/
|
||||||
|
ret = mpp_buffer_get(data.frm_grp, &frm_buf, hor_stride * ver_stride * 4);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("failed to get buffer for input frame ret %d\n", ret);
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpp_frame_set_buffer(frame, frm_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// decoder demo
|
||||||
|
ret = mpp_create(&ctx, &mpi);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("mpp_create failed\n");
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpp_log("%p mpi_dec_test decoder test start w %d h %d type %d\n",
|
||||||
|
ctx, width, height, type);
|
||||||
|
|
||||||
|
ret = mpi->control(ctx, MPP_SET_DISABLE_THREAD, NULL);
|
||||||
|
|
||||||
|
ret = mpp_init(ctx, MPP_CTX_DEC, type);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("%p mpp_init failed\n", ctx);
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpp_dec_cfg_init(&cfg);
|
||||||
|
|
||||||
|
/* get default config from decoder context */
|
||||||
|
ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("%p failed to get decoder cfg ret %d\n", ctx, ret);
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* split_parse is to enable mpp internal frame spliter when the input
|
||||||
|
* packet is not aplited into frames.
|
||||||
|
*/
|
||||||
|
ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("%p failed to set split_parse ret %d\n", ctx, ret);
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mpi->control(ctx, MPP_DEC_SET_CFG, cfg);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("%p failed to set cfg %p ret %d\n", ctx, cfg, ret);
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.cmd = cmd;
|
||||||
|
data.ctx = ctx;
|
||||||
|
data.mpi = mpi;
|
||||||
|
data.loop_end = 0;
|
||||||
|
data.packet = packet;
|
||||||
|
data.frame = frame;
|
||||||
|
data.frame_count = 0;
|
||||||
|
data.frame_num = cmd->frame_num;
|
||||||
|
data.quiet = cmd->quiet;
|
||||||
|
|
||||||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||||
|
|
||||||
|
ret = pthread_create(&thd, &attr, thread_decode, &data);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("failed to create thread for input ret %d\n", ret);
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->frame_num < 0) {
|
||||||
|
// wait for input then quit decoding
|
||||||
|
mpp_log("*******************************************\n");
|
||||||
|
mpp_log("**** Press Enter to stop loop decoding ****\n");
|
||||||
|
mpp_log("*******************************************\n");
|
||||||
|
|
||||||
|
getc(stdin);
|
||||||
|
data.loop_end = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_join(thd, NULL);
|
||||||
|
|
||||||
|
cmd->max_usage = data.max_usage;
|
||||||
|
|
||||||
|
ret = mpi->reset(ctx);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("%p mpi->reset failed\n", ctx);
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
MPP_TEST_OUT:
|
||||||
|
if (data.packet) {
|
||||||
|
mpp_packet_deinit(&data.packet);
|
||||||
|
data.packet = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame) {
|
||||||
|
mpp_frame_deinit(&frame);
|
||||||
|
frame = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx) {
|
||||||
|
mpp_destroy(ctx);
|
||||||
|
ctx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cmd->simple) {
|
||||||
|
if (frm_buf) {
|
||||||
|
mpp_buffer_put(frm_buf);
|
||||||
|
frm_buf = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.frm_grp) {
|
||||||
|
mpp_buffer_group_put(data.frm_grp);
|
||||||
|
data.frm_grp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.fp_output) {
|
||||||
|
fclose(data.fp_output);
|
||||||
|
data.fp_output = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.fp_verify) {
|
||||||
|
fclose(data.fp_verify);
|
||||||
|
data.fp_verify = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfg) {
|
||||||
|
mpp_dec_cfg_deinit(cfg);
|
||||||
|
cfg = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_attr_destroy(&attr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
RK_S32 ret = 0;
|
||||||
|
MpiDecTestCmd cmd_ctx;
|
||||||
|
MpiDecTestCmd* cmd = &cmd_ctx;
|
||||||
|
|
||||||
|
memset((void*)cmd, 0, sizeof(*cmd));
|
||||||
|
cmd->format = MPP_FMT_BUTT;
|
||||||
|
cmd->pkt_size = MPI_DEC_STREAM_SIZE;
|
||||||
|
|
||||||
|
// parse the cmd option
|
||||||
|
ret = mpi_dec_test_cmd_init(cmd, argc, argv);
|
||||||
|
if (ret)
|
||||||
|
goto RET;
|
||||||
|
|
||||||
|
mpi_dec_test_cmd_options(cmd);
|
||||||
|
|
||||||
|
ret = dec_nt_decode(cmd);
|
||||||
|
if (MPP_OK == ret)
|
||||||
|
mpp_log("test success max memory %.2f MB\n", cmd->max_usage / (float)(1 << 20));
|
||||||
|
else
|
||||||
|
mpp_err("test failed ret %d\n", ret);
|
||||||
|
|
||||||
|
RET:
|
||||||
|
mpi_dec_test_cmd_deinit(cmd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user