mirror of
https://github.com/nyanmisaka/mpp.git
synced 2026-01-24 01:20:40 +01:00
Change-Id: I648e78e4b271e914225f848309290e749fdd5176 Signed-off-by: Yanjun Liao <yanjun.liao@rock-chips.com>
1539 lines
45 KiB
C
1539 lines
45 KiB
C
/* SPDX-License-Identifier: Apache-2.0 OR MIT */
|
|
/*
|
|
* Copyright (c) 2015 Rockchip Electronics Co., Ltd.
|
|
*/
|
|
|
|
#define MODULE_TAG "mpp_buf_slot"
|
|
|
|
#include <string.h>
|
|
|
|
#include "mpp_mem.h"
|
|
#include "mpp_env.h"
|
|
#include "mpp_list.h"
|
|
#include "mpp_debug.h"
|
|
#include "mpp_common.h"
|
|
|
|
#include "mpp_frame_impl.h"
|
|
#include "mpp_buf_slot.h"
|
|
#include "mpp_compat_impl.h"
|
|
#include "rk_mpp_cfg.h"
|
|
|
|
#define BUF_SLOT_DBG_FUNCTION (0x00000001)
|
|
#define BUF_SLOT_DBG_SETUP (0x00000002)
|
|
#define BUF_SLOT_DBG_INFO_CHANGE (0x00000004)
|
|
#define BUF_SLOT_DBG_OPS_RUNTIME (0x00000010)
|
|
#define BUF_SLOT_DBG_BUFFER (0x00000100)
|
|
#define BUF_SLOT_DBG_FRAME (0x00000200)
|
|
#define BUF_SLOT_DBG_BUF_UESD (0x00000400)
|
|
#define BUF_SLOT_DBG_INFO_SET (0x00000800)
|
|
#define BUF_SLOT_DBG_OPS_HISTORY (0x10000000)
|
|
#define BUF_SLOT_DBG_ALL (0x10000011)
|
|
|
|
#define buf_slot_dbg(flag, fmt, ...) _mpp_dbg(buf_slot_debug, flag, fmt, ## __VA_ARGS__)
|
|
|
|
static RK_U32 buf_slot_debug = 0;
|
|
static RK_U32 buf_slot_idx = 0;
|
|
static RK_U32 use_legacy_align = 0;
|
|
|
|
#define slot_assert(impl, cond) do { \
|
|
if (!(cond)) { \
|
|
dump_slots(impl); \
|
|
mpp_err("Assertion %s failed at %s:%d\n", \
|
|
MPP_STRINGS(cond), __FUNCTION__, __LINE__); \
|
|
abort(); \
|
|
} \
|
|
} while (0)
|
|
|
|
typedef struct MppBufSlotEntry_t MppBufSlotEntry;
|
|
typedef struct MppBufSlotsImpl_t MppBufSlotsImpl;
|
|
|
|
#define SLOT_OPS_MAX_COUNT 1024
|
|
|
|
typedef enum MppBufSlotOps_e {
|
|
// status opertaion
|
|
SLOT_INIT,
|
|
SLOT_SET_ON_USE,
|
|
SLOT_CLR_ON_USE,
|
|
SLOT_SET_NOT_READY,
|
|
SLOT_CLR_NOT_READY,
|
|
SLOT_SET_CODEC_READY,
|
|
SLOT_CLR_CODEC_READY,
|
|
SLOT_SET_CODEC_USE,
|
|
SLOT_CLR_CODEC_USE,
|
|
SLOT_SET_HAL_INPUT,
|
|
SLOT_CLR_HAL_INPUT,
|
|
SLOT_SET_HAL_OUTPUT,
|
|
SLOT_CLR_HAL_OUTPUT,
|
|
SLOT_SET_QUEUE_USE,
|
|
SLOT_CLR_QUEUE_USE,
|
|
|
|
// queue operation
|
|
SLOT_ENQUEUE,
|
|
SLOT_ENQUEUE_OUTPUT = SLOT_ENQUEUE,
|
|
SLOT_ENQUEUE_DISPLAY,
|
|
SLOT_ENQUEUE_DEINTER,
|
|
SLOT_ENQUEUE_CONVERT,
|
|
SLOT_DEQUEUE,
|
|
SLOT_DEQUEUE_OUTPUT = SLOT_DEQUEUE,
|
|
SLOT_DEQUEUE_DISPLAY,
|
|
SLOT_DEQUEUE_DEINTER,
|
|
SLOT_DEQUEUE_CONVERT,
|
|
|
|
// value operation
|
|
SLOT_SET_EOS,
|
|
SLOT_CLR_EOS,
|
|
SLOT_SET_FRAME,
|
|
SLOT_CLR_FRAME,
|
|
SLOT_SET_BUFFER,
|
|
SLOT_CLR_BUFFER,
|
|
} MppBufSlotOps;
|
|
|
|
static const char op_string[][16] = {
|
|
"init ",
|
|
"set on use ",
|
|
"clr on use ",
|
|
"set not ready ",
|
|
"set ready ",
|
|
"set codec ready",
|
|
"clr codec ready",
|
|
"set codec use ",
|
|
"clr codec use ",
|
|
"set hal input ",
|
|
"clr hal input ",
|
|
"set hal output ",
|
|
"clr hal output ",
|
|
"set queue use ",
|
|
"clr queue use ",
|
|
|
|
"enqueue output ",
|
|
"enqueue display",
|
|
"enqueue deint ",
|
|
"enqueue convert",
|
|
"dequeue output ",
|
|
"dequeue display",
|
|
"dequeue deint ",
|
|
"dequeue convert",
|
|
|
|
"set eos ",
|
|
"clr eos ",
|
|
"set frame ",
|
|
"clr frame ",
|
|
"set buffer ",
|
|
"clr buffer ",
|
|
};
|
|
|
|
static const MppBufSlotOps set_flag_op[SLOT_USAGE_BUTT] = {
|
|
SLOT_SET_CODEC_READY,
|
|
SLOT_SET_CODEC_USE,
|
|
SLOT_SET_HAL_INPUT,
|
|
SLOT_SET_HAL_OUTPUT,
|
|
SLOT_SET_QUEUE_USE,
|
|
};
|
|
|
|
static const MppBufSlotOps clr_flag_op[SLOT_USAGE_BUTT] = {
|
|
SLOT_CLR_CODEC_READY,
|
|
SLOT_CLR_CODEC_USE,
|
|
SLOT_CLR_HAL_INPUT,
|
|
SLOT_CLR_HAL_OUTPUT,
|
|
SLOT_CLR_QUEUE_USE,
|
|
};
|
|
|
|
static const MppBufSlotOps set_val_op[SLOT_PROP_BUTT] = {
|
|
SLOT_SET_EOS,
|
|
SLOT_SET_FRAME,
|
|
SLOT_SET_BUFFER,
|
|
};
|
|
|
|
typedef union SlotStatus_u {
|
|
RK_U32 val;
|
|
struct {
|
|
// status flags
|
|
RK_U32 on_used : 1;
|
|
RK_U32 not_ready : 1; // buffer slot is filled or not
|
|
RK_U32 codec_use : 1; // buffer slot is used by codec ( dpb reference )
|
|
RK_U32 hal_output : 2; // buffer slot is set to hw output will ready when hw done
|
|
RK_U32 hal_use : 8; // buffer slot is used by hardware
|
|
RK_U32 queue_use : 5; // buffer slot is used in different queue
|
|
|
|
// value flags
|
|
RK_U32 eos : 1; // buffer slot is last buffer slot from codec
|
|
RK_U32 has_buffer : 1;
|
|
RK_U32 has_frame : 1;
|
|
};
|
|
} SlotStatus;
|
|
|
|
typedef struct MppBufSlotLog_t {
|
|
RK_S32 index;
|
|
MppBufSlotOps ops;
|
|
SlotStatus status_in;
|
|
SlotStatus status_out;
|
|
} MppBufSlotLog;
|
|
|
|
typedef struct MppBufSlotLogs_t {
|
|
pthread_mutex_t lock;
|
|
RK_U16 max_count;
|
|
RK_U16 log_count;
|
|
RK_U16 log_write;
|
|
RK_U16 log_read;
|
|
MppBufSlotLog *logs;
|
|
} MppBufSlotLogs;
|
|
|
|
struct MppBufSlotEntry_t {
|
|
MppBufSlotsImpl *slots;
|
|
struct list_head list;
|
|
SlotStatus status;
|
|
RK_S32 index;
|
|
|
|
RK_U32 eos;
|
|
MppFrame frame;
|
|
MppBuffer buffer;
|
|
};
|
|
|
|
struct MppBufSlotsImpl_t {
|
|
MppMutex lock;
|
|
RK_U32 slots_idx;
|
|
|
|
// status tracing
|
|
RK_U32 decode_count;
|
|
RK_U32 display_count;
|
|
|
|
MppCodingType coding_type;
|
|
|
|
// if slot changed, all will be hold until all slot is unused
|
|
RK_U32 info_changed;
|
|
RK_S32 info_change_slot_idx;
|
|
RK_S32 new_count;
|
|
|
|
// slot infomation for info change and eos
|
|
RK_U32 eos;
|
|
|
|
// buffer parameter, default alignement is 16
|
|
MppSysCfg sys_cfg;
|
|
AlignFunc hal_hor_align; // default NULL
|
|
AlignFunc hal_ver_align; // default NULL
|
|
AlignFunc hal_len_align; // default NULL
|
|
AlignFunc hal_width_align; // default NULL
|
|
SlotHalFbcAdjCfg hal_fbc_adj_cfg; // hal fbc frame adjust config
|
|
size_t buf_size;
|
|
RK_S32 buf_count;
|
|
RK_S32 used_count;
|
|
RK_U32 align_chk_log_env;
|
|
RK_U32 align_chk_log_en;
|
|
// buffer size equal to (h_stride * v_stride) * numerator / denominator
|
|
// internal parameter
|
|
RK_U32 numerator;
|
|
RK_U32 denominator;
|
|
|
|
// callback for free slot notify
|
|
MppCbCtx callback;
|
|
|
|
// NOTE: use MppFrame to store the buffer/display infomation
|
|
// any buffer related infomation change comparing to previous frame will
|
|
// trigger a buffer info changed requirement
|
|
// any display related infomation change comparing to pevious frame will
|
|
// trigger a display info changed requirement
|
|
MppFrame info;
|
|
MppFrame info_set;
|
|
|
|
// list for display
|
|
struct list_head queue[QUEUE_BUTT];
|
|
|
|
// list for log
|
|
MppBufSlotLogs *logs;
|
|
|
|
MppBufSlotEntry *slots;
|
|
};
|
|
|
|
typedef struct MppBufSlotInfoSet_t {
|
|
RK_U32 h_stride_by_pixel;
|
|
RK_U32 h_stride_by_byte;
|
|
RK_U32 v_stride;
|
|
RK_U32 size_total;
|
|
} MppBufSlotInfoSet;
|
|
|
|
static RK_U32 default_align_16(RK_U32 val)
|
|
{
|
|
return MPP_ALIGN(val, 16);
|
|
}
|
|
|
|
/* Based on drm_gem_framebuffer_helper.c drm_gem_afbc_min_size() */
|
|
static RK_S32 get_afbc_min_size(RK_S32 width, RK_S32 height, RK_S32 bpp)
|
|
{
|
|
#define AFBC_HEADER_SIZE 16
|
|
#define AFBC_HDR_ALIGN 64
|
|
#define AFBC_SUPERBLOCK_PIXELS 256
|
|
#define AFBC_SUPERBLOCK_ALIGNMENT 128
|
|
|
|
RK_S32 n_blocks, hdr_alignment, size;
|
|
|
|
/* AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 and !AFBC_FORMAT_MOD_TILED */
|
|
width = MPP_ALIGN(width, 16);
|
|
height = MPP_ALIGN(height, 16);
|
|
hdr_alignment = AFBC_HDR_ALIGN;
|
|
|
|
n_blocks = (width * height) / AFBC_SUPERBLOCK_PIXELS;
|
|
|
|
size = MPP_ALIGN(n_blocks * AFBC_HEADER_SIZE, hdr_alignment);
|
|
size += n_blocks * MPP_ALIGN(bpp * AFBC_SUPERBLOCK_PIXELS / 8,
|
|
AFBC_SUPERBLOCK_ALIGNMENT);
|
|
return size;
|
|
}
|
|
|
|
static void prepare_info_set_legacy(MppBufSlotsImpl *impl, MppFrame frame,
|
|
MppBufSlotInfoSet *info_set,
|
|
RK_U32 force_def_align)
|
|
{
|
|
const RK_U32 width = mpp_frame_get_width(frame);
|
|
const RK_U32 height = mpp_frame_get_height(frame);
|
|
const MppFrameFormat fmt = mpp_frame_get_fmt(frame);
|
|
RK_U32 depth = ((fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV420SP_10BIT ||
|
|
(fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV422SP_10BIT ||
|
|
(fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV444SP_10BIT) ? 10 : 8;
|
|
RK_U32 codec_hor_stride = mpp_frame_get_hor_stride(frame);
|
|
RK_U32 codec_ver_stride = mpp_frame_get_ver_stride(frame);
|
|
RK_U32 coded_width = (impl->hal_width_align) ?
|
|
(impl->hal_width_align(width)) : width;
|
|
|
|
RK_U32 hal_hor_stride = (codec_hor_stride) ?
|
|
(impl->hal_hor_align(codec_hor_stride)) :
|
|
(impl->hal_hor_align(coded_width * depth >> 3));
|
|
RK_U32 hal_ver_stride = (codec_ver_stride) ?
|
|
(impl->hal_ver_align(codec_ver_stride)) :
|
|
(impl->hal_ver_align(height));
|
|
RK_U32 hor_stride_pixel;
|
|
RK_S32 size;
|
|
|
|
hal_hor_stride = (force_def_align && codec_hor_stride) ? codec_hor_stride : hal_hor_stride;
|
|
hal_ver_stride = (force_def_align && codec_ver_stride) ? codec_ver_stride : hal_ver_stride;
|
|
|
|
if (MPP_FRAME_FMT_IS_FBC(fmt)) {
|
|
/*fbc stride default 64 align*/
|
|
if (*compat_ext_fbc_hdr_256_odd)
|
|
hal_hor_stride = (MPP_ALIGN(width, 256) | 256) * depth >> 3;
|
|
else
|
|
hal_hor_stride = MPP_ALIGN(width, 64) * depth >> 3;
|
|
}
|
|
|
|
switch (fmt & MPP_FRAME_FMT_MASK) {
|
|
case MPP_FMT_YUV420SP_10BIT:
|
|
case MPP_FMT_YUV422SP_10BIT:
|
|
case MPP_FMT_YUV444SP_10BIT: {
|
|
hor_stride_pixel = hal_hor_stride * 8 / 10;
|
|
} break;
|
|
case MPP_FMT_YUV422_YVYU:
|
|
case MPP_FMT_YUV422_YUYV:
|
|
case MPP_FMT_RGB565:
|
|
case MPP_FMT_BGR565: {
|
|
hor_stride_pixel = hal_hor_stride / 2;
|
|
} break;
|
|
case MPP_FMT_RGB888:
|
|
case MPP_FMT_BGR888: {
|
|
hor_stride_pixel = hal_hor_stride / 3;
|
|
} break;
|
|
default : {
|
|
hor_stride_pixel = hal_hor_stride;
|
|
} break;
|
|
}
|
|
|
|
size = hal_hor_stride * hal_ver_stride;
|
|
|
|
if (MPP_FRAME_FMT_IS_FBC(fmt)) {
|
|
hor_stride_pixel = MPP_ALIGN(hor_stride_pixel, 64);
|
|
switch ((fmt & MPP_FRAME_FMT_MASK)) {
|
|
case MPP_FMT_YUV420SP_10BIT : {
|
|
size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 15);
|
|
} break;
|
|
case MPP_FMT_YUV422SP_10BIT : {
|
|
size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 20);
|
|
} break;
|
|
case MPP_FMT_YUV420SP : {
|
|
size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 12);
|
|
} break;
|
|
case MPP_FMT_YUV422SP : {
|
|
size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 16);
|
|
} break;
|
|
case MPP_FMT_YUV444SP : {
|
|
size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 24);
|
|
} break;
|
|
case MPP_FMT_YUV444SP_10BIT : {
|
|
size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 30);
|
|
} break;
|
|
default : {
|
|
size = hal_hor_stride * hal_ver_stride * 3 / 2;
|
|
mpp_err("dec out fmt is no support");
|
|
} break;
|
|
}
|
|
mpp_frame_set_fbc_size(frame, size);
|
|
} else {
|
|
size *= impl->numerator;
|
|
size /= impl->denominator;
|
|
size = impl->hal_len_align ? (RK_S32)impl->hal_len_align(hal_hor_stride * hal_ver_stride) : size;
|
|
}
|
|
|
|
info_set->h_stride_by_byte = hal_hor_stride;
|
|
info_set->v_stride = hal_ver_stride;
|
|
info_set->h_stride_by_pixel = hor_stride_pixel;
|
|
info_set->size_total = size;
|
|
}
|
|
|
|
static void prepare_info_set_by_sys_cfg(MppBufSlotsImpl *impl, MppFrame frame,
|
|
MppBufSlotInfoSet *info_set)
|
|
{
|
|
const RK_U32 width = mpp_frame_get_width(frame);
|
|
const RK_U32 height = mpp_frame_get_height(frame);
|
|
const RK_U32 codec_hor_stride = mpp_frame_get_hor_stride(frame);
|
|
const RK_U32 codec_ver_stride = mpp_frame_get_ver_stride(frame);
|
|
const MppFrameFormat fmt = mpp_frame_get_fmt(frame);
|
|
|
|
/* set correct parameter */
|
|
mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:enable", 1);
|
|
mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:type", impl->coding_type);
|
|
mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:fmt_codec", fmt & MPP_FRAME_FMT_MASK);
|
|
mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:fmt_fbc", fmt & MPP_FRAME_FBC_MASK);
|
|
mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:fmt_hdr", fmt & MPP_FRAME_HDR_MASK);
|
|
mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:width", width);
|
|
mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:height", height);
|
|
mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:h_stride_by_byte", codec_hor_stride);
|
|
mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:v_stride", codec_ver_stride);
|
|
|
|
/* get result */
|
|
mpp_sys_cfg_ioctl(impl->sys_cfg);
|
|
|
|
mpp_sys_cfg_get_u32(impl->sys_cfg, "dec_buf_chk:h_stride_by_byte", &info_set->h_stride_by_byte);
|
|
mpp_sys_cfg_get_u32(impl->sys_cfg, "dec_buf_chk:h_stride_by_pixel", &info_set->h_stride_by_pixel);
|
|
mpp_sys_cfg_get_u32(impl->sys_cfg, "dec_buf_chk:v_stride", &info_set->v_stride);
|
|
mpp_sys_cfg_get_u32(impl->sys_cfg, "dec_buf_chk:size_total", &info_set->size_total);
|
|
|
|
return;
|
|
}
|
|
|
|
static void generate_info_set(MppBufSlotsImpl *impl, MppFrame frame, RK_U32 force_def_align)
|
|
{
|
|
const RK_U32 width = mpp_frame_get_width(frame);
|
|
const RK_U32 height = mpp_frame_get_height(frame);
|
|
const MppFrameFormat fmt = mpp_frame_get_fmt(frame);
|
|
MppBufSlotInfoSet legacy_info_set;
|
|
MppBufSlotInfoSet sys_cfg_info_set;
|
|
MppBufSlotInfoSet *info_set_ptr = NULL;
|
|
MppFrameImpl *info_set_impl = NULL;
|
|
MppFrameImpl *frame_impl = NULL;
|
|
|
|
prepare_info_set_legacy(impl, frame, &legacy_info_set, force_def_align);
|
|
prepare_info_set_by_sys_cfg(impl, frame, &sys_cfg_info_set);
|
|
|
|
mpp_frame_set_width(impl->info_set, width);
|
|
mpp_frame_set_height(impl->info_set, height);
|
|
mpp_frame_set_fmt(impl->info_set, fmt);
|
|
info_set_ptr = use_legacy_align ? &legacy_info_set : &sys_cfg_info_set;
|
|
mpp_frame_set_hor_stride(impl->info_set, info_set_ptr->h_stride_by_byte);
|
|
mpp_frame_set_ver_stride(impl->info_set, info_set_ptr->v_stride);
|
|
mpp_frame_set_hor_stride_pixel(impl->info_set, info_set_ptr->h_stride_by_pixel);
|
|
mpp_frame_set_buf_size(impl->info_set, info_set_ptr->size_total);
|
|
mpp_frame_set_buf_size(frame, info_set_ptr->size_total);
|
|
mpp_frame_set_hor_stride(frame, info_set_ptr->h_stride_by_byte);
|
|
mpp_frame_set_ver_stride(frame, info_set_ptr->v_stride);
|
|
mpp_frame_set_hor_stride_pixel(frame, info_set_ptr->h_stride_by_pixel);
|
|
impl->buf_size = info_set_ptr->size_total;
|
|
|
|
if (mpp_frame_get_thumbnail_en(frame) == MPP_FRAME_THUMBNAIL_MIXED) {
|
|
/*
|
|
* The decode hw only support 1/2 scaling in width and height,
|
|
* downscale output image only support raster mode with 8bit depth.
|
|
*/
|
|
RK_U32 down_scale_ver = MPP_ALIGN(mpp_frame_get_height(frame) >> 1, 16);
|
|
RK_U32 down_scale_hor = MPP_ALIGN(mpp_frame_get_width(frame) >> 1, 16);
|
|
RK_U32 downscale_buf_size;
|
|
RK_U32 down_scale_y_virstride = down_scale_ver * down_scale_hor;
|
|
|
|
switch ((fmt & MPP_FRAME_FMT_MASK)) {
|
|
case MPP_FMT_YUV400 : {
|
|
downscale_buf_size = down_scale_y_virstride;
|
|
} break;
|
|
case MPP_FMT_YUV420SP_10BIT :
|
|
case MPP_FMT_YUV420SP : {
|
|
downscale_buf_size = down_scale_y_virstride * 3 / 2;
|
|
} break;
|
|
case MPP_FMT_YUV422SP_10BIT :
|
|
case MPP_FMT_YUV422SP : {
|
|
downscale_buf_size = down_scale_y_virstride * 2;
|
|
} break;
|
|
case MPP_FMT_YUV444SP_10BIT :
|
|
case MPP_FMT_YUV444SP : {
|
|
downscale_buf_size = down_scale_y_virstride * 3;
|
|
} break;
|
|
default : {
|
|
downscale_buf_size = down_scale_y_virstride * 3 / 2;
|
|
} break;
|
|
}
|
|
downscale_buf_size = MPP_ALIGN(downscale_buf_size, 16);
|
|
impl->buf_size += downscale_buf_size;
|
|
mpp_frame_set_buf_size(impl->info_set, impl->buf_size);
|
|
mpp_frame_set_buf_size(frame, impl->buf_size);
|
|
}
|
|
info_set_impl = (MppFrameImpl *)impl->info_set;
|
|
frame_impl = (MppFrameImpl *)frame;
|
|
info_set_impl->color_range = frame_impl->color_range;
|
|
info_set_impl->color_primaries = frame_impl->color_primaries;
|
|
info_set_impl->color_trc = frame_impl->color_trc;
|
|
info_set_impl->colorspace = frame_impl->colorspace;
|
|
info_set_impl->chroma_location = frame_impl->chroma_location;
|
|
|
|
if (impl->align_chk_log_en) {
|
|
impl->align_chk_log_en = 0;
|
|
if (legacy_info_set.h_stride_by_pixel != sys_cfg_info_set.h_stride_by_pixel)
|
|
mpp_logi("mismatch h_stride_by_pixel %d - %d\n",
|
|
legacy_info_set.h_stride_by_pixel,
|
|
sys_cfg_info_set.h_stride_by_pixel);
|
|
if (legacy_info_set.h_stride_by_byte != sys_cfg_info_set.h_stride_by_byte)
|
|
mpp_logi("mismatch h_stride_by_byte %d - %d\n",
|
|
legacy_info_set.h_stride_by_byte,
|
|
sys_cfg_info_set.h_stride_by_byte);
|
|
if (legacy_info_set.v_stride != sys_cfg_info_set.v_stride)
|
|
mpp_logi("mismatch v_stride %d - %d\n",
|
|
legacy_info_set.v_stride,
|
|
sys_cfg_info_set.v_stride);
|
|
if (legacy_info_set.size_total != sys_cfg_info_set.size_total)
|
|
mpp_logi("mismatch size_total %d - %d\n",
|
|
legacy_info_set.size_total,
|
|
sys_cfg_info_set.size_total);
|
|
}
|
|
}
|
|
|
|
#define dump_slots(...) _dump_slots(__FUNCTION__, ## __VA_ARGS__)
|
|
|
|
static void buf_slot_logs_reset(MppBufSlotLogs *logs)
|
|
{
|
|
logs->log_count = 0;
|
|
logs->log_write = 0;
|
|
logs->log_read = 0;
|
|
}
|
|
|
|
static MppBufSlotLogs *buf_slot_logs_init(RK_U32 max_count)
|
|
{
|
|
MppBufSlotLogs *logs = NULL;
|
|
|
|
if (!max_count)
|
|
return NULL;
|
|
|
|
logs = mpp_malloc_size(MppBufSlotLogs, sizeof(MppBufSlotLogs) +
|
|
max_count * sizeof(MppBufSlotLog));
|
|
if (!logs) {
|
|
mpp_err_f("failed to create %d buf slot logs\n", max_count);
|
|
return NULL;
|
|
}
|
|
|
|
logs->max_count = max_count;
|
|
logs->logs = (MppBufSlotLog *)(logs + 1);
|
|
buf_slot_logs_reset(logs);
|
|
|
|
return logs;
|
|
}
|
|
|
|
static void buf_slot_logs_deinit(MppBufSlotLogs *logs)
|
|
{
|
|
MPP_FREE(logs);
|
|
}
|
|
|
|
static void buf_slot_logs_write(MppBufSlotLogs *logs, RK_S32 index, MppBufSlotOps op,
|
|
SlotStatus before, SlotStatus after)
|
|
{
|
|
MppBufSlotLog *log = NULL;
|
|
|
|
log = &logs->logs[logs->log_write];
|
|
log->index = index;
|
|
log->ops = op;
|
|
log->status_in = before;
|
|
log->status_out = after;
|
|
|
|
logs->log_write++;
|
|
if (logs->log_write >= logs->max_count)
|
|
logs->log_write = 0;
|
|
|
|
if (logs->log_count < logs->max_count)
|
|
logs->log_count++;
|
|
else {
|
|
logs->log_read++;
|
|
if (logs->log_read >= logs->max_count)
|
|
logs->log_read = 0;
|
|
}
|
|
}
|
|
|
|
static void buf_slot_logs_dump(MppBufSlotLogs *logs)
|
|
{
|
|
while (logs->log_count) {
|
|
MppBufSlotLog *log = &logs->logs[logs->log_read];
|
|
|
|
mpp_log("index %2d op: %s status in %08x out %08x",
|
|
log->index, op_string[log->ops], log->status_in.val, log->status_out.val);
|
|
|
|
logs->log_read++;
|
|
if (logs->log_read >= logs->max_count)
|
|
logs->log_read = 0;
|
|
logs->log_count--;
|
|
}
|
|
mpp_assert(logs->log_read == logs->log_write);
|
|
}
|
|
|
|
static void _dump_slots(const char *caller, MppBufSlotsImpl *impl)
|
|
{
|
|
MppBufSlotEntry *slot = impl->slots;
|
|
RK_S32 i;
|
|
|
|
mpp_log("\ncaller %s is dumping slots\n", caller, impl->slots_idx);
|
|
mpp_log("slots %d %p buffer count %d buffer size %d\n", impl->slots_idx,
|
|
impl, impl->buf_count, impl->buf_size);
|
|
mpp_log("decode count %d\n", impl->decode_count);
|
|
mpp_log("display count %d\n", impl->display_count);
|
|
|
|
for (i = 0; i < impl->buf_count; i++, slot++) {
|
|
SlotStatus status = slot->status;
|
|
mpp_log("slot %2d used %d refer %d decoding %d display %d status %08x\n",
|
|
i, status.on_used, status.codec_use, status.hal_use, status.queue_use, status.val);
|
|
}
|
|
|
|
mpp_log("\nslot operation history:\n\n");
|
|
|
|
if (impl->logs)
|
|
buf_slot_logs_dump(impl->logs);
|
|
|
|
mpp_assert(0);
|
|
|
|
return;
|
|
}
|
|
|
|
static void slot_ops_with_log(MppBufSlotsImpl *impl, MppBufSlotEntry *slot, MppBufSlotOps op, void *arg)
|
|
{
|
|
RK_U32 error = 0;
|
|
RK_S32 index = slot->index;
|
|
SlotStatus status = slot->status;
|
|
SlotStatus before = status;
|
|
switch (op) {
|
|
case SLOT_INIT : {
|
|
status.val = 0;
|
|
} break;
|
|
case SLOT_SET_ON_USE : {
|
|
status.on_used = 1;
|
|
} break;
|
|
case SLOT_CLR_ON_USE : {
|
|
status.on_used = 0;
|
|
} break;
|
|
case SLOT_SET_NOT_READY : {
|
|
status.not_ready = 1;
|
|
} break;
|
|
case SLOT_CLR_NOT_READY : {
|
|
status.not_ready = 0;
|
|
} break;
|
|
case SLOT_SET_CODEC_READY : {
|
|
status.not_ready = 0;
|
|
} break;
|
|
case SLOT_CLR_CODEC_READY : {
|
|
status.not_ready = 1;
|
|
} break;
|
|
case SLOT_SET_CODEC_USE : {
|
|
status.codec_use = 1;
|
|
} break;
|
|
case SLOT_CLR_CODEC_USE : {
|
|
status.codec_use = 0;
|
|
} break;
|
|
case SLOT_SET_HAL_INPUT : {
|
|
status.hal_use++;
|
|
} break;
|
|
case SLOT_CLR_HAL_INPUT : {
|
|
if (status.hal_use)
|
|
status.hal_use--;
|
|
else {
|
|
mpp_err("can not clr hal_input on slot %d\n", slot->index);
|
|
error = 1;
|
|
}
|
|
} break;
|
|
case SLOT_SET_HAL_OUTPUT : {
|
|
status.hal_output++;
|
|
status.not_ready = 1;
|
|
} break;
|
|
case SLOT_CLR_HAL_OUTPUT : {
|
|
if (status.hal_output)
|
|
status.hal_output--;
|
|
else
|
|
mpp_err("can not clr hal_output on slot %d\n", slot->index);
|
|
|
|
// NOTE: set output index ready here
|
|
if (!status.hal_output)
|
|
status.not_ready = 0;
|
|
} break;
|
|
case SLOT_SET_QUEUE_USE :
|
|
case SLOT_ENQUEUE_OUTPUT :
|
|
case SLOT_ENQUEUE_DISPLAY :
|
|
case SLOT_ENQUEUE_DEINTER :
|
|
case SLOT_ENQUEUE_CONVERT : {
|
|
status.queue_use++;
|
|
} break;
|
|
case SLOT_CLR_QUEUE_USE :
|
|
case SLOT_DEQUEUE_OUTPUT :
|
|
case SLOT_DEQUEUE_DISPLAY :
|
|
case SLOT_DEQUEUE_DEINTER :
|
|
case SLOT_DEQUEUE_CONVERT : {
|
|
if (status.queue_use)
|
|
status.queue_use--;
|
|
else {
|
|
mpp_err("can not clr queue_use on slot %d\n", slot->index);
|
|
error = 1;
|
|
}
|
|
} break;
|
|
case SLOT_SET_EOS : {
|
|
status.eos = 1;
|
|
} break;
|
|
case SLOT_CLR_EOS : {
|
|
status.eos = 0;
|
|
slot->eos = 0;
|
|
} break;
|
|
case SLOT_SET_FRAME : {
|
|
status.has_frame = (arg) ? (1) : (0);
|
|
} break;
|
|
case SLOT_CLR_FRAME : {
|
|
status.has_frame = 0;
|
|
} break;
|
|
case SLOT_SET_BUFFER : {
|
|
status.has_buffer = (arg) ? (1) : (0);
|
|
} break;
|
|
case SLOT_CLR_BUFFER : {
|
|
status.has_buffer = 0;
|
|
} break;
|
|
default : {
|
|
mpp_err("found invalid operation code %d\n", op);
|
|
error = 1;
|
|
} break;
|
|
}
|
|
slot->status = status;
|
|
buf_slot_dbg(BUF_SLOT_DBG_OPS_RUNTIME, "slot %3d index %2d op: %s arg %010p status in %08x out %08x",
|
|
impl->slots_idx, index, op_string[op], arg, before.val, status.val);
|
|
if (impl->logs)
|
|
buf_slot_logs_write(impl->logs, index, op, before, status);
|
|
if (error)
|
|
dump_slots(impl);
|
|
}
|
|
|
|
static void init_slot_entry(MppBufSlotsImpl *impl, RK_S32 pos, RK_S32 count)
|
|
{
|
|
MppBufSlotEntry *slot = impl->slots;
|
|
RK_S32 i;
|
|
|
|
for (i = 0; i < count; i++, slot++) {
|
|
slot->slots = impl;
|
|
INIT_LIST_HEAD(&slot->list);
|
|
slot->index = pos + i;
|
|
slot->frame = NULL;
|
|
slot_ops_with_log(impl, slot, SLOT_INIT, NULL);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* only called on unref / displayed / decoded
|
|
*
|
|
* NOTE: MppFrame will be destroyed outside mpp
|
|
* but MppBuffer must dec_ref here
|
|
*/
|
|
static RK_S32 check_entry_unused(MppBufSlotsImpl *impl, MppBufSlotEntry *entry)
|
|
{
|
|
SlotStatus status = entry->status;
|
|
|
|
if (status.on_used &&
|
|
!status.not_ready &&
|
|
!status.codec_use &&
|
|
!status.hal_output &&
|
|
!status.hal_use &&
|
|
!status.queue_use) {
|
|
if (entry->frame) {
|
|
slot_ops_with_log(impl, entry, SLOT_CLR_FRAME, entry->frame);
|
|
mpp_frame_deinit(&entry->frame);
|
|
}
|
|
if (entry->buffer) {
|
|
mpp_buffer_put(entry->buffer);
|
|
slot_ops_with_log(impl, entry, SLOT_CLR_BUFFER, entry->buffer);
|
|
entry->buffer = NULL;
|
|
}
|
|
|
|
slot_ops_with_log(impl, entry, SLOT_CLR_ON_USE, NULL);
|
|
impl->used_count--;
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void clear_slots_impl(MppBufSlotsImpl *impl)
|
|
{
|
|
MppBufSlotEntry *slot = (MppBufSlotEntry *)impl->slots;
|
|
RK_S32 i;
|
|
|
|
if (impl->sys_cfg)
|
|
mpp_sys_cfg_put(impl->sys_cfg);
|
|
|
|
for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(impl->queue); i++) {
|
|
if (!list_empty(&impl->queue[i]))
|
|
dump_slots(impl);
|
|
|
|
mpp_assert(list_empty(&impl->queue[i]));
|
|
}
|
|
|
|
for (i = 0; i < impl->buf_count; i++, slot++) {
|
|
mpp_assert(!slot->status.on_used);
|
|
if (slot->status.on_used) {
|
|
dump_slots(impl);
|
|
mpp_buf_slot_reset(impl, i);
|
|
}
|
|
}
|
|
|
|
impl->used_count = 0;
|
|
|
|
if (impl->info)
|
|
mpp_frame_deinit(&impl->info);
|
|
|
|
if (impl->info_set)
|
|
mpp_frame_deinit(&impl->info_set);
|
|
|
|
if (impl->logs) {
|
|
buf_slot_logs_deinit(impl->logs);
|
|
impl->logs = NULL;
|
|
}
|
|
|
|
mpp_mutex_destroy(&impl->lock);
|
|
|
|
mpp_free(impl->slots);
|
|
mpp_free(impl);
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_init(MppBufSlots *slots)
|
|
{
|
|
MppBufSlotsImpl *impl;
|
|
RK_U32 i;
|
|
|
|
if (!slots) {
|
|
mpp_err_f("found NULL input\n");
|
|
return MPP_ERR_NULL_PTR;
|
|
}
|
|
|
|
impl = mpp_calloc(MppBufSlotsImpl, 1);
|
|
if (!impl) {
|
|
*slots = NULL;
|
|
return MPP_NOK;
|
|
}
|
|
|
|
mpp_env_get_u32("buf_slot_debug", &buf_slot_debug,
|
|
BUF_SLOT_DBG_OPS_HISTORY | BUF_SLOT_DBG_INFO_SET);
|
|
mpp_env_get_u32("use_legacy_align", &use_legacy_align, 0);
|
|
|
|
do {
|
|
if (mpp_sys_cfg_get(&impl->sys_cfg)) {
|
|
mpp_err_f("mpp_sys_cfg_get failed\n");
|
|
break;
|
|
}
|
|
|
|
mpp_mutex_init(&impl->lock);
|
|
|
|
for (i = 0; i < MPP_ARRAY_ELEMS(impl->queue); i++) {
|
|
INIT_LIST_HEAD(&impl->queue[i]);
|
|
}
|
|
|
|
if (buf_slot_debug & BUF_SLOT_DBG_OPS_HISTORY) {
|
|
impl->logs = buf_slot_logs_init(SLOT_OPS_MAX_COUNT);
|
|
if (!impl->logs)
|
|
break;
|
|
}
|
|
|
|
if (mpp_frame_init(&impl->info))
|
|
break;
|
|
|
|
if (mpp_frame_init(&impl->info_set))
|
|
break;
|
|
|
|
// slots information default setup
|
|
impl->hal_hor_align = default_align_16;
|
|
impl->hal_ver_align = default_align_16;
|
|
impl->hal_len_align = NULL;
|
|
impl->numerator = 9;
|
|
impl->denominator = 5;
|
|
impl->slots_idx = buf_slot_idx++;
|
|
impl->info_change_slot_idx = -1;
|
|
impl->align_chk_log_env = (buf_slot_debug & BUF_SLOT_DBG_INFO_SET) ? 1 : 0;
|
|
impl->align_chk_log_en = impl->align_chk_log_env;
|
|
|
|
*slots = impl;
|
|
return MPP_OK;
|
|
} while (0);
|
|
|
|
clear_slots_impl(impl);
|
|
|
|
*slots = NULL;
|
|
return MPP_NOK;
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_deinit(MppBufSlots slots)
|
|
{
|
|
if (!slots) {
|
|
mpp_err_f("found NULL input\n");
|
|
return MPP_ERR_NULL_PTR;
|
|
}
|
|
|
|
clear_slots_impl((MppBufSlotsImpl *)slots);
|
|
return MPP_OK;
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_setup(MppBufSlots slots, RK_S32 count)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
|
|
if (!impl) {
|
|
mpp_err_f("found NULL input\n");
|
|
return MPP_ERR_NULL_PTR;
|
|
}
|
|
|
|
buf_slot_dbg(BUF_SLOT_DBG_SETUP, "slot %p setup: count %d\n", impl, count);
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
|
|
if (!impl->slots) {
|
|
// first slot setup
|
|
impl->buf_count = impl->new_count = count;
|
|
impl->slots = mpp_calloc(MppBufSlotEntry, count);
|
|
init_slot_entry(impl, 0, count);
|
|
impl->used_count = 0;
|
|
} else {
|
|
// record the slot count for info changed ready config
|
|
if (count > impl->buf_count) {
|
|
impl->slots = mpp_realloc(impl->slots, MppBufSlotEntry, count);
|
|
mpp_assert(impl->slots);
|
|
init_slot_entry(impl, impl->buf_count, (count - impl->buf_count));
|
|
}
|
|
impl->new_count = count;
|
|
}
|
|
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return MPP_OK;
|
|
}
|
|
|
|
RK_U32 mpp_buf_slot_is_changed(MppBufSlots slots)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
RK_U32 info_changed = 0;
|
|
|
|
if (!impl) {
|
|
mpp_err_f("found NULL input\n");
|
|
return 0;
|
|
}
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
info_changed = impl->info_changed;
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return info_changed;
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_ready(MppBufSlots slots)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
|
|
if (!impl) {
|
|
mpp_err_f("found NULL input\n");
|
|
return MPP_ERR_NULL_PTR;
|
|
}
|
|
|
|
buf_slot_dbg(BUF_SLOT_DBG_SETUP, "slot %p is ready now\n", impl);
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
|
|
slot_assert(impl, impl->slots);
|
|
if (!impl->info_changed)
|
|
mpp_log("found info change ready set without internal info change\n");
|
|
|
|
// ready mean the info_set will be copy to info as the new configuration
|
|
if (impl->buf_count != impl->new_count) {
|
|
impl->slots = mpp_realloc(impl->slots, MppBufSlotEntry, impl->new_count);
|
|
mpp_assert(impl->slots);
|
|
init_slot_entry(impl, 0, impl->new_count);
|
|
}
|
|
impl->buf_count = impl->new_count;
|
|
|
|
mpp_frame_copy(impl->info, impl->info_set);
|
|
|
|
if (impl->logs)
|
|
buf_slot_logs_reset(impl->logs);
|
|
|
|
impl->info_changed = 0;
|
|
impl->info_change_slot_idx = -1;
|
|
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return MPP_OK;
|
|
}
|
|
|
|
size_t mpp_buf_slot_get_size(MppBufSlots slots)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
size_t size = 0;
|
|
|
|
if (!impl) {
|
|
mpp_err_f("found NULL input\n");
|
|
return 0;
|
|
}
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
size = impl->buf_size;
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return size;
|
|
}
|
|
|
|
RK_S32 mpp_buf_slot_get_count(MppBufSlots slots)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
size_t count = 0;
|
|
|
|
if (!impl) {
|
|
mpp_err_f("found NULL input\n");
|
|
return -1;
|
|
}
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
count = impl->buf_count;
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return count;
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_set_callback(MppBufSlots slots, MppCbCtx *cb_ctx)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
|
|
if (!impl) {
|
|
mpp_err_f("found NULL input\n");
|
|
return MPP_NOK;
|
|
}
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
impl->callback = *cb_ctx;
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return MPP_OK;
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_get_unused(MppBufSlots slots, RK_S32 *index)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
MppBufSlotEntry *slot;
|
|
RK_S32 i;
|
|
|
|
if (!impl || !index) {
|
|
mpp_err_f("found NULL input\n");
|
|
return MPP_ERR_NULL_PTR;
|
|
}
|
|
|
|
slot = impl->slots;
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
|
|
for (i = 0; i < impl->buf_count; i++, slot++) {
|
|
if (!slot->status.on_used) {
|
|
*index = i;
|
|
slot_ops_with_log(impl, slot, SLOT_SET_ON_USE, NULL);
|
|
slot_ops_with_log(impl, slot, SLOT_SET_NOT_READY, NULL);
|
|
impl->used_count++;
|
|
mpp_mutex_unlock(&impl->lock);
|
|
return MPP_OK;
|
|
}
|
|
}
|
|
|
|
*index = -1;
|
|
mpp_err_f("failed to get a unused slot\n");
|
|
dump_slots(impl);
|
|
slot_assert(impl, 0);
|
|
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return MPP_NOK;
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_set_flag(MppBufSlots slots, RK_S32 index, SlotUsageType type)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
|
|
if (!impl) {
|
|
mpp_err_f("found NULL input\n");
|
|
return MPP_ERR_NULL_PTR;
|
|
}
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
|
|
slot_assert(impl, (index >= 0) && (index < impl->buf_count));
|
|
slot_ops_with_log(impl, &impl->slots[index], set_flag_op[type], NULL);
|
|
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return MPP_OK;
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_clr_flag(MppBufSlots slots, RK_S32 index, SlotUsageType type)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
MppBufSlotEntry *slot;
|
|
RK_S32 unused = 0;
|
|
|
|
if (!impl) {
|
|
mpp_err_f("found NULL input\n");
|
|
return MPP_ERR_NULL_PTR;
|
|
}
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
|
|
slot_assert(impl, (index >= 0) && (index < impl->buf_count));
|
|
slot = &impl->slots[index];
|
|
slot_ops_with_log(impl, slot, clr_flag_op[type], NULL);
|
|
|
|
if (type == SLOT_HAL_OUTPUT)
|
|
impl->decode_count++;
|
|
|
|
unused = check_entry_unused(impl, slot);
|
|
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
if (unused)
|
|
mpp_callback(&impl->callback, impl);
|
|
return MPP_OK;
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_enqueue(MppBufSlots slots, RK_S32 index, SlotQueueType type)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
MppBufSlotEntry *slot;
|
|
|
|
if (!impl) {
|
|
mpp_err_f("found NULL input\n");
|
|
return MPP_ERR_NULL_PTR;
|
|
}
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
|
|
slot_assert(impl, (index >= 0) && (index < impl->buf_count));
|
|
slot = &impl->slots[index];
|
|
slot_ops_with_log(impl, slot, (MppBufSlotOps)(SLOT_ENQUEUE + type), NULL);
|
|
|
|
// add slot to display list
|
|
list_del_init(&slot->list);
|
|
list_add_tail(&slot->list, &impl->queue[type]);
|
|
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return MPP_OK;
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_dequeue(MppBufSlots slots, RK_S32 *index, SlotQueueType type)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
MppBufSlotEntry *slot;
|
|
|
|
if (!impl || !index) {
|
|
mpp_err_f("found NULL input\n");
|
|
return MPP_ERR_NULL_PTR;
|
|
}
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
|
|
if (list_empty(&impl->queue[type])) {
|
|
mpp_mutex_unlock(&impl->lock);
|
|
return MPP_NOK;
|
|
}
|
|
|
|
slot = list_entry(impl->queue[type].next, MppBufSlotEntry, list);
|
|
if (slot->status.not_ready) {
|
|
mpp_mutex_unlock(&impl->lock);
|
|
return MPP_NOK;
|
|
}
|
|
|
|
// make sure that this slot is just the next display slot
|
|
list_del_init(&slot->list);
|
|
slot_assert(impl, slot->index < impl->buf_count);
|
|
slot_ops_with_log(impl, slot, (MppBufSlotOps)(SLOT_DEQUEUE + type), NULL);
|
|
impl->display_count++;
|
|
*index = slot->index;
|
|
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return MPP_OK;
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_set_prop(MppBufSlots slots, RK_S32 index, SlotPropType type, void *val)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
MppBufSlotEntry *slot;
|
|
|
|
if (!impl || !val || type >= SLOT_PROP_BUTT) {
|
|
mpp_err_f("found invalid input slots %p type %d val %p\n", slots, type, val);
|
|
return MPP_ERR_UNKNOW;
|
|
}
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
|
|
slot_assert(impl, (index >= 0) && (index < impl->buf_count));
|
|
slot = &impl->slots[index];
|
|
slot_ops_with_log(impl, slot, set_val_op[type], val);
|
|
|
|
switch (type) {
|
|
case SLOT_EOS: {
|
|
RK_U32 eos = *(RK_U32*)val;
|
|
|
|
slot->eos = eos;
|
|
if (slot->frame)
|
|
mpp_frame_set_eos(slot->frame, eos);
|
|
} break;
|
|
case SLOT_FRAME: {
|
|
MppFrame frame = val;
|
|
MppFrameImpl *src;
|
|
MppFrameImpl *dst;
|
|
|
|
slot_assert(impl, slot->status.not_ready);
|
|
/*
|
|
* we need to detect infomation change here
|
|
* there are two types of info change:
|
|
* 1. buffer size change
|
|
* this case need to reset buffer group and commit buffer with new size
|
|
* 2. display info change
|
|
* if only width/height/fmt is change and buffer do not need to be reset
|
|
* only display info change is need
|
|
*/
|
|
generate_info_set(impl, frame, 0);
|
|
|
|
if (!slot->frame)
|
|
mpp_frame_init(&slot->frame);
|
|
|
|
src = (MppFrameImpl *)frame;
|
|
dst = (MppFrameImpl *)slot->frame;
|
|
mpp_frame_copy(dst, src);
|
|
// NOTE: stride from codec need to be change to hal stride
|
|
// hor_stride and ver_stride can not be zero
|
|
// they are the stride required by codec
|
|
// then hal will modify it according to hardware requirement
|
|
mpp_assert(src->hor_stride);
|
|
mpp_assert(src->ver_stride);
|
|
dst->hor_stride = src->hor_stride;
|
|
dst->ver_stride = src->ver_stride;
|
|
dst->eos = slot->eos;
|
|
|
|
if (mpp_frame_info_cmp(impl->info, impl->info_set)) {
|
|
MppFrameImpl *old = (MppFrameImpl *)impl->info;
|
|
|
|
impl->info_changed = 1;
|
|
impl->info_change_slot_idx = index;
|
|
|
|
if (impl->coding_type != MPP_VIDEO_CodingMJPEG)
|
|
impl->align_chk_log_en = impl->align_chk_log_env;
|
|
|
|
if (old->width || old->height) {
|
|
mpp_dbg_info("info change found\n");
|
|
mpp_dbg_info("old width %4d height %4d stride hor %4d ver %4d fmt %4d\n",
|
|
old->width, old->height, old->hor_stride,
|
|
old->ver_stride, old->fmt);
|
|
}
|
|
mpp_dbg_info("new width %4d height %4d stride hor %4d ver %4d fmt %4d\n",
|
|
dst->width, dst->height, dst->hor_stride, dst->ver_stride,
|
|
dst->fmt);
|
|
// info change found here
|
|
}
|
|
} break;
|
|
case SLOT_BUFFER: {
|
|
MppBuffer buffer = val;
|
|
|
|
if (slot->buffer) {
|
|
// NOTE: reset buffer only on stream buffer slot
|
|
slot_assert(impl, !slot->frame);
|
|
mpp_buffer_put(slot->buffer);
|
|
}
|
|
mpp_buffer_inc_ref(buffer);
|
|
slot->buffer = buffer;
|
|
|
|
if (slot->frame)
|
|
mpp_frame_set_buffer(slot->frame, buffer);
|
|
} break;
|
|
default : {
|
|
} break;
|
|
}
|
|
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return MPP_OK;
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_get_prop(MppBufSlots slots, RK_S32 index, SlotPropType type, void *val)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
MppBufSlotEntry *slot;
|
|
|
|
if (!impl || !val || type >= SLOT_PROP_BUTT) {
|
|
mpp_err_f("found invalid input slots %p type %d val %p\n", slots, type, val);
|
|
return MPP_ERR_UNKNOW;
|
|
}
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
|
|
slot_assert(impl, (index >= 0) && (index < impl->buf_count));
|
|
slot = &impl->slots[index];
|
|
|
|
switch (type) {
|
|
case SLOT_EOS: {
|
|
*(RK_U32*)val = slot->eos;
|
|
} break;
|
|
case SLOT_FRAME: {
|
|
MppFrame *frame = (MppFrame *)val;
|
|
//*frame = (slot->status.has_frame) ? (slot->frame) : (NULL);
|
|
|
|
mpp_assert(slot->status.has_frame);
|
|
if (slot->status.has_frame) {
|
|
if (!*frame )
|
|
mpp_frame_init(frame);
|
|
if (*frame)
|
|
mpp_frame_copy(*frame, slot->frame);
|
|
} else
|
|
*frame = NULL;
|
|
} break;
|
|
case SLOT_FRAME_PTR: {
|
|
MppFrame *frame = (MppFrame *)val;
|
|
|
|
mpp_assert(slot->status.has_frame);
|
|
*frame = (slot->status.has_frame) ? (slot->frame) : (NULL);
|
|
} break;
|
|
case SLOT_BUFFER: {
|
|
MppBuffer *buffer = (MppBuffer *)val;
|
|
|
|
*buffer = (slot->status.has_buffer) ? (slot->buffer) : (NULL);
|
|
} break;
|
|
default : {
|
|
} break;
|
|
}
|
|
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return MPP_OK;
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_reset(MppBufSlots slots, RK_S32 index)
|
|
{
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
MppBufSlotEntry *slot;
|
|
|
|
if (!impl || index < 0) {
|
|
mpp_err_f("found NULL input\n");
|
|
return MPP_ERR_NULL_PTR;
|
|
}
|
|
|
|
buf_slot_dbg(BUF_SLOT_DBG_SETUP, "slot %p reset index %d\n", slots, index);
|
|
|
|
mpp_mutex_lock(&impl->lock);
|
|
|
|
slot_assert(impl, (index >= 0) && (index < impl->buf_count));
|
|
slot = &impl->slots[index];
|
|
|
|
// make sure that this slot is just the next display slot
|
|
list_del_init(&slot->list);
|
|
slot_ops_with_log(impl, slot, SLOT_CLR_QUEUE_USE, NULL);
|
|
slot_ops_with_log(impl, slot, SLOT_DEQUEUE, NULL);
|
|
slot_ops_with_log(impl, slot, SLOT_CLR_ON_USE, NULL);
|
|
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return MPP_OK;
|
|
}
|
|
|
|
MPP_RET mpp_buf_slot_default_info(MppBufSlots slots, RK_S32 index, void *val)
|
|
{
|
|
if (!slots || index < 0) {
|
|
mpp_err_f("found NULL input\n");
|
|
return MPP_ERR_NULL_PTR;
|
|
}
|
|
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
mpp_mutex_lock(&impl->lock);
|
|
slot_assert(impl, (index >= 0) && (index < impl->buf_count));
|
|
MppBufSlotEntry *slot = &impl->slots[index];
|
|
|
|
slot_assert(impl, slot->status.not_ready);
|
|
slot_assert(impl, !slot->frame);
|
|
slot_assert(impl, impl->info_set);
|
|
|
|
if (!slot->frame) {
|
|
mpp_frame_init(&slot->frame);
|
|
mpp_frame_copy(slot->frame, impl->info_set);
|
|
}
|
|
|
|
MppFrame *frame = (MppFrame *)val;
|
|
*frame = slot->frame;
|
|
|
|
slot_ops_with_log(impl, slot, SLOT_CLR_NOT_READY, NULL);
|
|
slot_ops_with_log(impl, slot, SLOT_SET_FRAME, slot->frame);
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return MPP_OK;
|
|
}
|
|
|
|
RK_U32 mpp_slots_is_empty(MppBufSlots slots, SlotQueueType type)
|
|
{
|
|
RK_U32 is_empty = 0;
|
|
if (!slots) {
|
|
mpp_err_f("found NULL input\n");
|
|
return 0;
|
|
}
|
|
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
mpp_mutex_lock(&impl->lock);
|
|
is_empty = list_empty(&impl->queue[type]) ? 1 : 0;
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return is_empty;
|
|
}
|
|
|
|
RK_S32 mpp_slots_get_used_count(MppBufSlots slots)
|
|
{
|
|
RK_S32 used_count = 0;
|
|
if (!slots) {
|
|
mpp_err_f("found NULL input\n");
|
|
return 0;
|
|
}
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
mpp_mutex_lock(&impl->lock);
|
|
used_count = impl->used_count;
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return used_count;
|
|
}
|
|
|
|
RK_S32 mpp_slots_get_unused_count(MppBufSlots slots)
|
|
{
|
|
RK_S32 unused_count = 0;
|
|
if (!slots) {
|
|
mpp_err_f("found NULL input\n");
|
|
return MPP_ERR_NULL_PTR;
|
|
}
|
|
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
mpp_mutex_lock(&impl->lock);
|
|
slot_assert(impl, (impl->used_count >= 0) && (impl->used_count <= impl->buf_count));
|
|
unused_count = impl->buf_count - impl->used_count;
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return unused_count;
|
|
}
|
|
|
|
MPP_RET mpp_slots_set_prop(MppBufSlots slots, SlotsPropType type, void *val)
|
|
{
|
|
if (!slots || !val || type >= SLOTS_PROP_BUTT) {
|
|
mpp_err_f("found invalid input slots %p type %d val %p\n", slots, type, val);
|
|
return MPP_ERR_UNKNOW;
|
|
}
|
|
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
mpp_mutex_lock(&impl->lock);
|
|
RK_U32 value = *((RK_U32*)val);
|
|
switch (type) {
|
|
case SLOTS_EOS: {
|
|
impl->eos = value;
|
|
} break;
|
|
case SLOTS_NUMERATOR : {
|
|
impl->numerator = value;
|
|
} break;
|
|
case SLOTS_DENOMINATOR : {
|
|
impl->denominator = value;
|
|
} break;
|
|
case SLOTS_HOR_ALIGN: {
|
|
impl->hal_hor_align = (AlignFunc)val;
|
|
} break;
|
|
case SLOTS_VER_ALIGN: {
|
|
impl->hal_ver_align = (AlignFunc)val;
|
|
} break;
|
|
case SLOTS_LEN_ALIGN: {
|
|
impl->hal_len_align = (AlignFunc)val;
|
|
} break;
|
|
case SLOTS_COUNT: {
|
|
impl->buf_count = value;
|
|
} break;
|
|
case SLOTS_SIZE: {
|
|
impl->buf_size = value;
|
|
} break;
|
|
case SLOTS_FRAME_INFO: {
|
|
// do info change detection here
|
|
generate_info_set(impl, (MppFrame)val, 1);
|
|
mpp_frame_copy(impl->info, impl->info_set);
|
|
{
|
|
MppFrameImpl *p = (MppFrameImpl *)impl->info;
|
|
mpp_log("set frame info: w %4d h %4d hor %4d ver %4d\n", p->width, p->height, p->hor_stride, p->ver_stride);
|
|
}
|
|
mpp_frame_copy((MppFrame)val, impl->info_set);
|
|
if (impl->info_change_slot_idx >= 0) {
|
|
MppBufSlotEntry *slot = &impl->slots[impl->info_change_slot_idx];
|
|
|
|
if (slot->frame) {
|
|
MppFrameImpl *dst = (MppFrameImpl *)slot->frame;
|
|
MppFrameImpl *src = (MppFrameImpl *)val;
|
|
|
|
dst->fmt = src->fmt;
|
|
dst->hor_stride = src->hor_stride;
|
|
dst->hor_stride_pixel = src->hor_stride_pixel;
|
|
dst->ver_stride = src->ver_stride;
|
|
dst->buf_size = src->buf_size;
|
|
|
|
if (MPP_FRAME_FMT_IS_FBC(dst->fmt) && impl->hal_fbc_adj_cfg.func)
|
|
impl->hal_fbc_adj_cfg.func(impl, dst, impl->hal_fbc_adj_cfg.expand);
|
|
}
|
|
|
|
impl->info_change_slot_idx = -1;
|
|
}
|
|
} break;
|
|
case SLOTS_HAL_FBC_ADJ : {
|
|
impl->hal_fbc_adj_cfg = *((SlotHalFbcAdjCfg *)val);
|
|
} break;
|
|
case SLOTS_CODING_TYPE : {
|
|
impl->coding_type = *((MppCodingType *)val);
|
|
} break;
|
|
case SLOTS_WIDTH_ALIGN: {
|
|
impl->hal_width_align = (AlignFunc)val;
|
|
} break;
|
|
default : {
|
|
} break;
|
|
}
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return MPP_OK;
|
|
}
|
|
|
|
MPP_RET mpp_slots_get_prop(MppBufSlots slots, SlotsPropType type, void *val)
|
|
{
|
|
if (!slots || !val || type >= SLOTS_PROP_BUTT) {
|
|
mpp_err_f("found invalid input slots %p type %d val %p\n", slots, type, val);
|
|
return MPP_NOK;
|
|
}
|
|
|
|
MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots;
|
|
mpp_mutex_lock(&impl->lock);
|
|
MPP_RET ret = MPP_OK;
|
|
|
|
switch (type) {
|
|
case SLOTS_EOS: {
|
|
*((RK_U32 *)val) = impl->eos;
|
|
} break;
|
|
case SLOTS_COUNT: {
|
|
*((RK_U32 *)val) = impl->buf_count;
|
|
} break;
|
|
case SLOTS_SIZE: {
|
|
*((RK_U32 *)val) = (RK_U32)impl->buf_size;
|
|
} break;
|
|
case SLOTS_FRAME_INFO: {
|
|
MppFrame frame = (MppFrame)val;
|
|
MppFrame info = impl->info;
|
|
mpp_frame_copy(frame, info);
|
|
} break;
|
|
default : {
|
|
mpp_err("can not get slots prop type %d\n", type);
|
|
ret = MPP_NOK;
|
|
} break;
|
|
}
|
|
mpp_mutex_unlock(&impl->lock);
|
|
|
|
return ret;
|
|
}
|