Merge "video: driver: Add support for enc auto framerate"
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
0df7a874b9
@@ -93,6 +93,7 @@ static struct msm_platform_core_capability core_data_waipio[] = {
|
||||
{DECODE_BATCH_TIMEOUT, 200},
|
||||
{AV_SYNC_WINDOW_SIZE, 40},
|
||||
{NON_FATAL_FAULTS, 1},
|
||||
{ENC_AUTO_FRAMERATE, 1},
|
||||
};
|
||||
|
||||
static struct msm_platform_inst_capability instance_data_waipio[] = {
|
||||
|
@@ -48,7 +48,7 @@ u64 msm_vidc_calc_freq_iris2(struct msm_vidc_inst *inst, u32 data_size)
|
||||
mbpf = msm_vidc_get_mbs_per_frame(inst);
|
||||
fps = msm_vidc_get_fps(inst);
|
||||
|
||||
buf_timetamps_fps = msm_vidc_calc_framerate(inst);
|
||||
buf_timetamps_fps = msm_vidc_calc_window_avg_framerate(inst);
|
||||
|
||||
/*
|
||||
* when buffer detected fps is more than client set value by 10%,
|
||||
|
@@ -411,7 +411,8 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp);
|
||||
int msm_vidc_calc_framerate(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_set_auto_framerate(struct msm_vidc_inst *inst, u64 timestamp);
|
||||
int msm_vidc_calc_window_avg_framerate(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_flush_ts(struct msm_vidc_inst *inst);
|
||||
const char *buf_name(enum msm_vidc_buffer_type type);
|
||||
void msm_vidc_free_capabililty_list(struct msm_vidc_inst *inst,
|
||||
|
@@ -147,5 +147,6 @@ struct msm_vidc_inst {
|
||||
u32 max_input_data_size;
|
||||
u32 dpb_list_payload[MAX_DPB_LIST_ARRAY_SIZE];
|
||||
u32 max_map_output_count;
|
||||
u32 auto_framerate;
|
||||
};
|
||||
#endif // _MSM_VIDC_INST_H_
|
||||
|
@@ -69,6 +69,8 @@
|
||||
#define MAX_SUPPORTED_MIN_QUALITY 70
|
||||
|
||||
#define DCVS_WINDOW 16
|
||||
#define ENC_FPS_WINDOW 3
|
||||
#define DEC_FPS_WINDOW 10
|
||||
/* Superframe can have maximum of 32 frames */
|
||||
#define VIDC_SUPERFRAME_MAX 32
|
||||
#define COLOR_RANGE_UNSPECIFIED (-1)
|
||||
@@ -327,6 +329,7 @@ enum msm_vidc_core_capability_type {
|
||||
AV_SYNC_WINDOW_SIZE,
|
||||
CLK_FREQ_THRESHOLD,
|
||||
NON_FATAL_FAULTS,
|
||||
ENC_AUTO_FRAMERATE,
|
||||
CORE_CAP_MAX,
|
||||
};
|
||||
|
||||
|
@@ -1604,6 +1604,7 @@ set_default:
|
||||
"%s: failed to set frame rate to fw\n", __func__);
|
||||
goto exit;
|
||||
}
|
||||
inst->auto_framerate = q16_rate;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@@ -434,6 +434,7 @@ int msm_vidc_qbuf(void *instance, struct media_device *mdev,
|
||||
int rc = 0;
|
||||
struct msm_vidc_inst *inst = instance;
|
||||
struct vb2_queue *q;
|
||||
u64 timestamp_us = 0;
|
||||
|
||||
if (!inst || !inst->core || !b || !valid_v4l2_buffer(b, inst)) {
|
||||
d_vpr_e("%s: invalid params %pK %pK\n", __func__, inst, b);
|
||||
@@ -445,6 +446,12 @@ int msm_vidc_qbuf(void *instance, struct media_device *mdev,
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (is_encode_session(inst) && b->type == INPUT_MPLANE) {
|
||||
timestamp_us = (u64)((b->timestamp.tv_sec * USEC_PER_SEC) +
|
||||
b->timestamp.tv_usec);
|
||||
msm_vidc_set_auto_framerate(inst, timestamp_us);
|
||||
}
|
||||
inst->last_qbuf_time_ns = ktime_get_ns();
|
||||
|
||||
rc = vb2_qbuf(q, mdev, b);
|
||||
@@ -776,6 +783,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
|
||||
inst->request = false;
|
||||
inst->ipsc_properties_set = false;
|
||||
inst->opsc_properties_set = false;
|
||||
inst->auto_framerate = DEFAULT_FPS << 16;
|
||||
kref_init(&inst->kref);
|
||||
mutex_init(&inst->lock);
|
||||
msm_vidc_update_debug_str(inst);
|
||||
|
@@ -40,8 +40,6 @@ extern struct msm_vidc_core *g_core;
|
||||
#define SSR_ADDR_ID 0xFFFFFFFF00000000
|
||||
#define SSR_ADDR_SHIFT 32
|
||||
|
||||
#define FPS_WINDOW 10
|
||||
|
||||
struct msm_vidc_cap_name {
|
||||
enum msm_vidc_inst_capability_type cap;
|
||||
char *name;
|
||||
@@ -2019,7 +2017,67 @@ int msm_vidc_memory_unmap_completely(struct msm_vidc_inst *inst,
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_calc_framerate(struct msm_vidc_inst *inst)
|
||||
int msm_vidc_set_auto_framerate(struct msm_vidc_inst *inst, u64 timestamp)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
struct msm_vidc_timestamp *ts;
|
||||
struct msm_vidc_timestamp *prev = NULL;
|
||||
u32 counter = 0, prev_fr = 0, curr_fr = 0;
|
||||
u64 ts_ms = 0;
|
||||
int rc = 0;
|
||||
|
||||
if (!inst || !inst->core || !inst->capabilities) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
core = inst->core;
|
||||
if (!core->capabilities[ENC_AUTO_FRAMERATE].value ||
|
||||
is_image_session(inst) || msm_vidc_is_super_buffer(inst))
|
||||
goto exit;
|
||||
|
||||
rc = msm_vidc_update_timestamp(inst, timestamp);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
list_for_each_entry(ts, &inst->timestamps.list, sort.list) {
|
||||
if (prev) {
|
||||
ts_ms = div_u64(ts->sort.val - prev->sort.val, 1000);
|
||||
prev_fr = curr_fr;
|
||||
curr_fr = ts_ms ? div_u64(MSEC_PER_SEC, ts_ms) << 16 :
|
||||
inst->auto_framerate;
|
||||
if (curr_fr > inst->capabilities->cap[FRAME_RATE].max)
|
||||
curr_fr = inst->capabilities->cap[FRAME_RATE].max;
|
||||
}
|
||||
prev = ts;
|
||||
counter++;
|
||||
}
|
||||
|
||||
if (counter < ENC_FPS_WINDOW)
|
||||
goto exit;
|
||||
|
||||
/* if framerate changed and stable for 2 frames, set to firmware */
|
||||
if (curr_fr == prev_fr && curr_fr != inst->auto_framerate) {
|
||||
i_vpr_l(inst, "%s: updated fps to %u\n", __func__, curr_fr >> 16);
|
||||
rc = venus_hfi_session_property(inst,
|
||||
HFI_PROP_FRAME_RATE,
|
||||
HFI_HOST_FLAGS_NONE,
|
||||
HFI_PORT_BITSTREAM,
|
||||
HFI_PAYLOAD_Q16,
|
||||
&curr_fr,
|
||||
sizeof(u32));
|
||||
if (rc) {
|
||||
i_vpr_e(inst, "%s: set auto frame rate failed\n",
|
||||
__func__);
|
||||
goto exit;
|
||||
}
|
||||
inst->auto_framerate = curr_fr;
|
||||
}
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_calc_window_avg_framerate(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_timestamp *ts;
|
||||
struct msm_vidc_timestamp *prev = NULL;
|
||||
@@ -2129,6 +2187,7 @@ int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp)
|
||||
{
|
||||
struct msm_vidc_timestamp *ts;
|
||||
int rc = 0;
|
||||
u32 window_size = 0;
|
||||
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
@@ -2149,8 +2208,13 @@ int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp)
|
||||
return rc;
|
||||
inst->timestamps.count++;
|
||||
|
||||
/* keep sliding window of 10 ts nodes */
|
||||
if (inst->timestamps.count > FPS_WINDOW) {
|
||||
if (is_encode_session(inst))
|
||||
window_size = ENC_FPS_WINDOW;
|
||||
else
|
||||
window_size = DEC_FPS_WINDOW;
|
||||
|
||||
/* keep sliding window */
|
||||
if (inst->timestamps.count > window_size) {
|
||||
ts = msm_vidc_get_least_rank_ts(inst);
|
||||
if (!ts) {
|
||||
i_vpr_e(inst, "%s: least rank ts is NULL\n", __func__);
|
||||
|
@@ -223,7 +223,7 @@ int msm_vidc_scale_buses(struct msm_vidc_inst *inst)
|
||||
vote_data->lcu_size = (codec == V4L2_PIX_FMT_HEVC ||
|
||||
codec == V4L2_PIX_FMT_VP9) ? 32 : 16;
|
||||
vote_data->fps = msm_vidc_get_fps(inst);
|
||||
buf_ts_fps = msm_vidc_calc_framerate(inst);
|
||||
buf_ts_fps = msm_vidc_calc_window_avg_framerate(inst);
|
||||
if (buf_ts_fps > vote_data->fps) {
|
||||
i_vpr_l(inst, "%s: bitstream: fps %d, client rate %u\n", __func__,
|
||||
buf_ts_fps, vote_data->fps);
|
||||
|
@@ -3399,7 +3399,6 @@ int venus_hfi_queue_super_buffer(struct msm_vidc_inst *inst,
|
||||
/* Create yuv packet */
|
||||
update_offset(hfi_buffer.addr_offset, (cnt ? frame_size : 0u));
|
||||
update_timestamp(hfi_buffer.timestamp, (cnt ? ts_delta_us : 0u));
|
||||
msm_vidc_update_timestamp(inst, hfi_buffer.timestamp);
|
||||
rc = hfi_create_packet(inst->packet,
|
||||
inst->packet_size,
|
||||
HFI_CMD_BUFFER,
|
||||
@@ -3467,9 +3466,6 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
|
||||
if (rc)
|
||||
goto unlock;
|
||||
|
||||
if (is_encode_session(inst) && is_input_buffer(buffer->type))
|
||||
msm_vidc_update_timestamp(inst, hfi_buffer.timestamp);
|
||||
|
||||
rc = hfi_create_header(inst->packet, inst->packet_size,
|
||||
inst->session_id, core->header_id++);
|
||||
if (rc)
|
||||
|
Viittaa uudesa ongelmassa
Block a user