mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 06:09:23 -04:00
msm: vidc: support encoder auto dynamic fps
Encoder calculate fps based on timestamp, if fps changes and stable for 2 frames, set to firmware to facilitate rate control. Use closest rounding instead of floor rounding when calculate fps. Change-Id: Id2420729a309378107ff6f7830515fae31512ddd Signed-off-by: Qiwei Liu <qiweil@codeaurora.org>
This commit is contained in:
parent
6ec572de63
commit
930011097f
7 changed files with 93 additions and 6 deletions
|
|
@ -47,6 +47,7 @@
|
|||
|
||||
#define MIN_NUM_ENC_OUTPUT_BUFFERS 4
|
||||
#define MIN_NUM_ENC_CAPTURE_BUFFERS 5
|
||||
#define VENC_MAX_TIMESTAMP_LIST_SIZE 2
|
||||
|
||||
static const char *const mpeg_video_rate_control[] = {
|
||||
"VBR",
|
||||
|
|
@ -1653,6 +1654,7 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
|
|||
if (rc)
|
||||
s_vpr_e(sid, "%s: set frame rate failed\n",
|
||||
__func__);
|
||||
msm_comm_release_timestamps(inst);
|
||||
}
|
||||
break;
|
||||
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
|
||||
|
|
@ -2112,6 +2114,72 @@ int msm_venc_set_frame_rate(struct msm_vidc_inst *inst)
|
|||
return rc;
|
||||
}
|
||||
|
||||
int msm_venc_store_timestamp(struct msm_vidc_inst *inst, u64 timestamp_us)
|
||||
{
|
||||
struct msm_vidc_timestamps *entry, *node, *prev = NULL;
|
||||
int count = 0;
|
||||
int rc = 0;
|
||||
|
||||
if (!inst || !inst->core) {
|
||||
d_vpr_e("%s: invalid parameters\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!inst->core->resources.enc_auto_dynamic_fps ||
|
||||
is_image_session(inst))
|
||||
return rc;
|
||||
|
||||
mutex_lock(&inst->timestamps.lock);
|
||||
list_for_each_entry(node, &inst->timestamps.list, list) {
|
||||
count++;
|
||||
if (timestamp_us <= node->timestamp_us) {
|
||||
s_vpr_e(inst->sid, "%s: invalid ts %llu, exist %llu\n",
|
||||
__func__, timestamp_us, node->timestamp_us);
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
/* Maintain a sliding window */
|
||||
entry = NULL;
|
||||
if (count >= VENC_MAX_TIMESTAMP_LIST_SIZE) {
|
||||
entry = list_first_entry(&inst->timestamps.list,
|
||||
struct msm_vidc_timestamps, list);
|
||||
list_del_init(&entry->list);
|
||||
}
|
||||
if (!entry) {
|
||||
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
|
||||
if (!entry) {
|
||||
s_vpr_e(inst->sid, "%s: ts malloc failure\n",
|
||||
__func__);
|
||||
rc = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
entry->timestamp_us = timestamp_us;
|
||||
entry->framerate = inst->clk_data.frame_rate;
|
||||
prev = list_last_entry(&inst->timestamps.list,
|
||||
struct msm_vidc_timestamps, list);
|
||||
list_add_tail(&entry->list, &inst->timestamps.list);
|
||||
|
||||
if (!count)
|
||||
goto unlock;
|
||||
|
||||
entry->framerate = msm_comm_calc_framerate(inst,
|
||||
timestamp_us, prev->timestamp_us);
|
||||
|
||||
/* if framerate changed and stable for 2 frames, set to firmware */
|
||||
if (entry->framerate == prev->framerate &&
|
||||
entry->framerate != inst->clk_data.frame_rate) {
|
||||
inst->clk_data.frame_rate = entry->framerate;
|
||||
msm_venc_set_frame_rate(inst);
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&inst->timestamps.lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_venc_set_color_format(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int rc = 0;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst,
|
|||
int msm_venc_set_properties(struct msm_vidc_inst *inst);
|
||||
int msm_venc_set_extradata(struct msm_vidc_inst *inst);
|
||||
int msm_venc_set_frame_rate(struct msm_vidc_inst *inst);
|
||||
int msm_venc_store_timestamp(struct msm_vidc_inst *inst, u64 timestamp_us);
|
||||
int msm_venc_set_bitrate(struct msm_vidc_inst *inst);
|
||||
int msm_venc_set_layer_bitrate(struct msm_vidc_inst *inst);
|
||||
int msm_venc_set_operating_rate(struct msm_vidc_inst *inst);
|
||||
|
|
|
|||
|
|
@ -420,18 +420,27 @@ int msm_vidc_qbuf(void *instance, struct media_device *mdev,
|
|||
if (is_grid_session(inst) && b->type == INPUT_MPLANE)
|
||||
b->flags |= V4L2_BUF_FLAG_PERF_MODE;
|
||||
|
||||
timestamp_us = (u64)((b->timestamp.tv_sec * 1000000ULL) +
|
||||
b->timestamp.tv_usec);
|
||||
if (is_decode_session(inst) && b->type == INPUT_MPLANE) {
|
||||
if (inst->flush_timestamps)
|
||||
msm_comm_release_timestamps(inst);
|
||||
inst->flush_timestamps = false;
|
||||
|
||||
timestamp_us = (u64)((b->timestamp.tv_sec * 1000000ULL) +
|
||||
b->timestamp.tv_usec);
|
||||
rc = msm_comm_store_timestamp(inst, timestamp_us);
|
||||
if (rc)
|
||||
return rc;
|
||||
inst->clk_data.frame_rate = msm_comm_get_max_framerate(inst);
|
||||
}
|
||||
if (is_encode_session(inst) && b->type == INPUT_MPLANE) {
|
||||
if (inst->flush_timestamps)
|
||||
msm_comm_release_timestamps(inst);
|
||||
inst->flush_timestamps = false;
|
||||
|
||||
rc = msm_venc_store_timestamp(inst, timestamp_us);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
q = msm_comm_get_vb2q(inst, b->type);
|
||||
if (!q) {
|
||||
|
|
|
|||
|
|
@ -5596,7 +5596,7 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
|
|||
* flush is issued, before adding the next buffer's timestamp
|
||||
* to the list.
|
||||
*/
|
||||
if (is_decode_session(inst) && inst->in_flush) {
|
||||
if (!is_image_session(inst) && inst->in_flush) {
|
||||
inst->flush_timestamps = true;
|
||||
s_vpr_h(inst->sid,
|
||||
"Setting flush variable to clear timestamp list: %d\n",
|
||||
|
|
@ -7610,7 +7610,7 @@ int msm_comm_store_timestamp(struct msm_vidc_inst *inst, u64 timestamp_us)
|
|||
goto unlock;
|
||||
}
|
||||
entry->timestamp_us = timestamp_us;
|
||||
entry->framerate = DEFAULT_FPS << 16;
|
||||
entry->framerate = inst->clk_data.frame_rate;
|
||||
entry->is_valid = true;
|
||||
|
||||
/* add new entry into the list in sorted order */
|
||||
|
|
@ -7661,14 +7661,16 @@ unlock:
|
|||
u32 msm_comm_calc_framerate(struct msm_vidc_inst *inst,
|
||||
u64 timestamp_us, u64 prev_ts)
|
||||
{
|
||||
u32 framerate = DEFAULT_FPS << 16;
|
||||
u32 framerate = inst->clk_data.frame_rate;
|
||||
u32 interval;
|
||||
|
||||
if (timestamp_us <= prev_ts) {
|
||||
s_vpr_e(inst->sid, "%s: invalid ts %lld, prev ts %lld\n",
|
||||
__func__, timestamp_us, prev_ts);
|
||||
return framerate;
|
||||
}
|
||||
framerate = (1000000 / (timestamp_us - prev_ts)) << 16;
|
||||
interval = (u32)(timestamp_us - prev_ts);
|
||||
framerate = ((1000000 + interval / 2) / interval) << 16;
|
||||
return framerate;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -453,6 +453,10 @@ static struct msm_vidc_common_data lahaina_common_data[] = {
|
|||
.key = "qcom,vpp_delay_supported",
|
||||
.value = 1,
|
||||
},
|
||||
{
|
||||
.key = "qcom,enc_auto_dynamic_fps",
|
||||
.value = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct msm_vidc_common_data bengal_common_data_v0[] = {
|
||||
|
|
|
|||
|
|
@ -826,6 +826,8 @@ int read_platform_resources_from_drv_data(
|
|||
"qcom,ubwc_stats_in_fbd");
|
||||
res->has_vpp_delay = find_key_value(platform_data,
|
||||
"qcom,vpp_delay_supported");
|
||||
res->enc_auto_dynamic_fps = find_key_value(platform_data,
|
||||
"qcom,enc_auto_dynamic_fps");
|
||||
|
||||
res->csc_coeff_data = &platform_data->csc_data;
|
||||
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ struct msm_vidc_platform_resources {
|
|||
struct cx_ipeak_client *cx_ipeak_context;
|
||||
uint32_t ubwc_stats_in_fbd;
|
||||
uint32_t has_vpp_delay;
|
||||
bool enc_auto_dynamic_fps;
|
||||
};
|
||||
|
||||
static inline bool is_iommu_present(struct msm_vidc_platform_resources *res)
|
||||
|
|
|
|||
Loading…
Reference in a new issue