msm: vidc: Use pre-computed frame delta values in WFD use case
In WFD use-case with frame skipping enabled, we wish to fool the core
into thinking that that the frames are coming at a consistent rate so
that we don't run into any issues with the core's rate control
mechanism.
Introduce a client-settable property that dictates what the timestamp
delta between any two frames might be.
Change-Id: Iea3f97879227b7932543d3449d311758dc4a2f59
Signed-off-by: Deva Ramasubramanian <dramasub@codeaurora.org>
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index b7ae0f4..8cad387 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -191,7 +191,7 @@
}
vbuf->v4l2_buf.timestamp =
- ns_to_timeval(frame_data->time_stamp);
+ ns_to_timeval(frame_data->time_stamp * NSEC_PER_USEC);
WFD_MSG_DBG("bytes used %d, ts: %d.%d, frame type is %d\n",
frame_data->data_len,
@@ -1051,6 +1051,7 @@
struct v4l2_fract *frate = arg;
struct vcd_property_hdr vcd_property_hdr;
struct vcd_property_frame_rate vcd_frame_rate;
+ struct vcd_property_vop_timing_constant_delta vcd_delta;
int rc;
vcd_property_hdr.prop_id = VCD_I_FRAME_RATE;
vcd_property_hdr.sz =
@@ -1060,8 +1061,25 @@
vcd_frame_rate.fps_numerator = frate->denominator;
rc = vcd_set_property(client_ctx->vcd_handle,
&vcd_property_hdr, &vcd_frame_rate);
- if (rc)
+ if (rc) {
WFD_MSG_ERR("Failed to set frame rate, rc = %d\n", rc);
+ goto set_framerate_fail;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_VOP_TIMING_CONSTANT_DELTA;
+ vcd_property_hdr.sz = sizeof(vcd_delta);
+
+ vcd_delta.constant_delta = (frate->numerator * USEC_PER_SEC) /
+ frate->denominator;
+ rc = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_delta);
+
+ if (rc) {
+ WFD_MSG_ERR("Failed to set frame delta, rc = %d", rc);
+ goto set_framerate_fail;
+ }
+
+set_framerate_fail:
return rc;
}
@@ -1827,12 +1845,16 @@
struct venc_buf_info *venc_buf = arg;
struct mem_region *mregion = venc_buf->mregion;
struct vcd_frame_data vcd_input_buffer = {0};
+ int64_t ts = 0;
+
+ ts = venc_buf->timestamp;
+ do_div(ts, NSEC_PER_USEC);
vcd_input_buffer.virtual = mregion->kvaddr;
vcd_input_buffer.frm_clnt_data = (u32)mregion;
vcd_input_buffer.ip_frm_tag = (u32)mregion;
vcd_input_buffer.data_len = mregion->size;
- vcd_input_buffer.time_stamp = venc_buf->timestamp;
+ vcd_input_buffer.time_stamp = ts;
vcd_input_buffer.offset = 0;
rc = vcd_encode_frame(client_ctx->vcd_handle,
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index 0d5ba9c..5019d31 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -502,7 +502,12 @@
}
rc = ddl_set_property(cctxt->ddl_handle, prop_hdr, prop_val);
- VCD_FAILED_RETURN(rc, "Failed: ddl_set_property");
+ if (rc) {
+ /* Some properties aren't known to ddl that we can handle */
+ if (prop_hdr->prop_id != VCD_I_VOP_TIMING_CONSTANT_DELTA)
+ VCD_FAILED_RETURN(rc, "Failed: ddl_set_property");
+ }
+
switch (prop_hdr->prop_id) {
case VCD_I_META_BUFFER_MODE:
{
@@ -537,16 +542,30 @@
break;
}
case VCD_I_INTRA_PERIOD:
- {
- struct vcd_property_i_period *iperiod =
- (struct vcd_property_i_period *)prop_val;
- cctxt->bframe = iperiod->b_frames;
- break;
- }
+ {
+ struct vcd_property_i_period *iperiod =
+ (struct vcd_property_i_period *)prop_val;
+ cctxt->bframe = iperiod->b_frames;
+ break;
+ }
case VCD_REQ_PERF_LEVEL:
rc = vcd_req_perf_level(cctxt,
- (struct vcd_property_perf_level *)prop_val);
+ (struct vcd_property_perf_level *)prop_val);
break;
+ case VCD_I_VOP_TIMING_CONSTANT_DELTA:
+ {
+ struct vcd_property_vop_timing_constant_delta *delta =
+ prop_val;
+
+ if (delta->constant_delta > 0) {
+ cctxt->time_frame_delta = delta->constant_delta;
+ rc = VCD_S_SUCCESS;
+ } else {
+ VCD_MSG_ERROR("Frame delta must be positive");
+ rc = VCD_ERR_ILLEGAL_PARM;
+ }
+ break;
+ }
default:
{
break;
@@ -559,6 +578,7 @@
(struct vcd_clnt_ctxt *cctxt,
struct vcd_property_hdr *prop_hdr, void *prop_val)
{
+ int rc;
VCD_MSG_LOW("vcd_get_property_cmn in %d:", cctxt->clnt_state.state);
VCD_MSG_LOW("property Id = %d", prop_hdr->prop_id);
if (!prop_hdr->sz || !prop_hdr->prop_id) {
@@ -566,7 +586,24 @@
return VCD_ERR_ILLEGAL_PARM;
}
- return ddl_get_property(cctxt->ddl_handle, prop_hdr, prop_val);
+ rc = ddl_get_property(cctxt->ddl_handle, prop_hdr, prop_val);
+ if (rc) {
+ /* Some properties aren't known to ddl that we can handle */
+ if (prop_hdr->prop_id != VCD_I_VOP_TIMING_CONSTANT_DELTA)
+ VCD_FAILED_RETURN(rc, "Failed: ddl_set_property");
+ }
+
+ switch (prop_hdr->prop_id) {
+ case VCD_I_VOP_TIMING_CONSTANT_DELTA:
+ {
+ struct vcd_property_vop_timing_constant_delta *delta =
+ (struct vcd_property_vop_timing_constant_delta *)
+ prop_val;
+ delta->constant_delta = cctxt->time_frame_delta;
+ rc = VCD_S_SUCCESS;
+ }
+ }
+ return rc;
}
static u32 vcd_set_buffer_requirements_cmn
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index d228146..7ae4f45 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -191,6 +191,7 @@
u32 frm_p_units;
u32 reqd_perf_lvl;
u32 time_resoln;
+ u32 time_frame_delta;
struct vcd_buffer_pool in_buf_pool;
struct vcd_buffer_pool out_buf_pool;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 2df7144..6358a0e 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -3052,13 +3052,15 @@
u32 frm_delta;
u64 temp, max = ~((u64)0);
- if (frame->time_stamp >= cctxt->status.prev_ts)
+ if (cctxt->time_frame_delta)
+ temp = cctxt->time_frame_delta;
+ else if (frame->time_stamp >= cctxt->status.prev_ts)
temp = frame->time_stamp - cctxt->status.prev_ts;
else
temp = (max - cctxt->status.prev_ts) +
frame->time_stamp;
- VCD_MSG_LOW("Curr_ts=%lld Prev_ts=%lld Diff=%llu",
+ VCD_MSG_LOW("Curr_ts=%lld Prev_ts=%lld Diff=%llu\n",
frame->time_stamp, cctxt->status.prev_ts, temp);
temp *= cctxt->time_resoln;
diff --git a/include/media/msm/vcd_api.h b/include/media/msm/vcd_api.h
index 32a1759..c93b696 100644
--- a/include/media/msm/vcd_api.h
+++ b/include/media/msm/vcd_api.h
@@ -66,7 +66,7 @@
u32 alloc_len;
u32 data_len;
u32 offset;
- s64 time_stamp;
+ s64 time_stamp; /* in usecs*/
u32 flags;
u32 frm_clnt_data;
struct vcd_property_dec_output_buffer dec_op_prop;
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index e776d41..cd00800 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -53,6 +53,7 @@
#define VCD_I_ENABLE_SPS_PPS_FOR_IDR (VCD_START_BASE + 0x25)
#define VCD_REQ_PERF_LEVEL (VCD_START_BASE + 0x26)
#define VCD_I_SLICE_DELIVERY_MODE (VCD_START_BASE + 0x27)
+#define VCD_I_VOP_TIMING_CONSTANT_DELTA (VCD_START_BASE + 0x28)
#define VCD_START_REQ (VCD_START_BASE + 0x1000)
#define VCD_I_REQ_IFRAME (VCD_START_REQ + 0x1)
@@ -300,6 +301,10 @@
u32 vop_time_resolution;
};
+struct vcd_property_vop_timing_constant_delta {
+ u32 constant_delta; /*In usecs */
+};
+
struct vcd_property_short_header {
u32 short_header;
};