vidc: 1080p : Add support for skip frame in slice delivery mode
Slice delivery mode for H264 encoder will deliver constant number of
output slice buffers for each frame. In case of CBR rate control method,
core will skip frames to maintain the output quality, in which case
driver need to send out the output buffers with data length as zero
for skipped frame output type from the core.
CRs-fixed: 362356
Change-Id: I647092d802b95558422cf1537f3e8bf69cd68b1b
Signed-off-by: Maheshwar Ajja <majja@codeaurora.org>
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
index 8da0995..81b1436 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -471,6 +471,10 @@
struct ddl_encoder_data *encoder =
&ddl->codec_data.encoder;
u32 vcd_status = VCD_S_SUCCESS;
+ struct vcd_transc *transc;
+ transc = (struct vcd_transc *)(ddl->client_data);
+ DDL_MSG_LOW("%s: transc = 0x%x, in_use = %u",
+ __func__, (u32)ddl->client_data, transc->in_use);
if (encoder->slice_delivery_info.enable) {
return ddl_encode_frame_batch(ddl_handle,
input_frame,
@@ -480,7 +484,6 @@
client_data);
}
- DDL_MSG_HIGH("ddl_encode_frame");
ddl_set_core_start_time(__func__, ENC_OP_TIME);
ddl_context = ddl_get_context();
if (!DDL_IS_INITIALIZED(ddl_context)) {
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index 5b9aea8..e2c0a2a 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -34,6 +34,8 @@
static void ddl_handle_slice_done_slice_batch(struct ddl_client_context *ddl);
static void ddl_handle_enc_frame_done_slice_mode(
struct ddl_client_context *ddl, u32 eos_present);
+static void ddl_handle_enc_skipframe_slice_mode(
+ struct ddl_client_context *ddl, u32 eos_present);
static void ddl_fw_status_done_callback(struct ddl_context *ddl_context)
{
@@ -511,11 +513,15 @@
if (encoder->enc_frame_info.enc_frame_size ||
(encoder->enc_frame_info.enc_frame ==
VIDC_1080P_ENCODE_FRAMETYPE_SKIPPED) ||
- DDLCLIENT_STATE_IS(ddl,
- DDL_CLIENT_WAIT_FOR_EOS_DONE)) {
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE)) {
if (encoder->slice_delivery_info.enable) {
- ddl_handle_enc_frame_done_slice_mode(ddl,
- eos_present);
+ if (encoder->enc_frame_info.enc_frame ==
+ VIDC_1080P_ENCODE_FRAMETYPE_SKIPPED)
+ ddl_handle_enc_skipframe_slice_mode(
+ ddl, eos_present);
+ else
+ ddl_handle_enc_frame_done_slice_mode(
+ ddl, eos_present);
} else {
ddl_handle_enc_frame_done(ddl, eos_present);
}
@@ -1892,3 +1898,78 @@
(u32 *) ddl, ddl->client_data);
}
}
+
+static void ddl_handle_enc_skipframe_slice_mode(
+ struct ddl_client_context *ddl, u32 eos_present)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ struct vcd_frame_data *output_frame = NULL;
+ u32 bottom_frame_tag;
+ u8 *input_buffer_address = NULL;
+ u32 index = 0;
+ DDL_MSG_HIGH("ddl_handle_enc_skipframe_slice_mode: frame skipped");
+ vidc_sm_set_encoder_slice_batch_int_ctrl(
+ &ddl->shared_mem[ddl->command_channel],
+ 1);
+ for (index = 0;
+ index < encoder->batch_frame.num_output_frames;
+ index++) {
+ output_frame =
+ &(encoder->batch_frame.output_frame[index].vcd_frm);
+ DDL_MSG_MED("output buffer: vcd_frm = 0x%x "
+ "frmbfr(virtual) = 0x%x frmbfr(physical) = 0x%x",
+ (u32)output_frame, (u32)output_frame->virtual,
+ (u32)output_frame->physical);
+ vidc_sm_get_frame_tags(
+ &ddl->shared_mem[ddl->command_channel],
+ &output_frame->ip_frm_tag,
+ &bottom_frame_tag);
+ ddl_get_encoded_frame(
+ output_frame,
+ encoder->codec.codec,
+ encoder->enc_frame_info.enc_frame);
+ output_frame->data_len = 0;
+ ddl->output_frame.frm_trans_end = false;
+ if (encoder->batch_frame.num_output_frames ==
+ (index + 1)) {
+ DDL_MSG_MED("last output bfr for skip frame, set EOF");
+ output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
+ ddl_vidc_encode_dynamic_property(ddl, false);
+ if (eos_present)
+ ddl->output_frame.frm_trans_end = false;
+ else
+ ddl->output_frame.frm_trans_end = true;
+ }
+ ddl->output_frame.vcd_frm = *output_frame;
+ ddl_context->ddl_callback(
+ VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_S_SUCCESS,
+ &(ddl->output_frame),
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *)ddl,
+ ddl->client_data);
+
+ if (encoder->batch_frame.num_output_frames ==
+ (index + 1)) {
+ ddl->input_frame.frm_trans_end = false;
+ input_buffer_address =
+ ddl_context->dram_base_a.physical_base_addr +
+ (encoder->enc_frame_info.enc_luma_address);
+ ddl_get_input_frame_from_pool(ddl,
+ input_buffer_address);
+ DDL_MSG_MED("InpBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
+ " frmbfr(physical) 0x%x",
+ (u32)&(ddl->input_frame.vcd_frm),
+ (u32)ddl->input_frame.vcd_frm.virtual,
+ (u32)ddl->input_frame.vcd_frm.physical);
+ ddl_context->ddl_callback(
+ VCD_EVT_RESP_INPUT_DONE,
+ VCD_S_SUCCESS,
+ &(ddl->input_frame),
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *)ddl,
+ ddl->client_data);
+ }
+ }
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index 363fe53..3827bc1 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -983,8 +983,7 @@
DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
encoder->slice_delivery_info.enable
= *(u32 *)property_value;
- DDL_MSG_HIGH("set encoder->slice_delivery_mode"
- " = %u\n",
+ DDL_MSG_HIGH("set encoder->slice_delivery_mode = %u\n",
encoder->slice_delivery_info.enable);
output_buf_size =
encoder->client_output_buf_req.sz;
@@ -998,8 +997,26 @@
encoder->slice_delivery_info.num_slices =
num_slices;
if (num_slices <= DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH) {
- encoder->client_output_buf_req.min_count
- = ((DDL_ENC_SLICE_BATCH_FACTOR * num_slices + 2)
+ DDL_MSG_HIGH("%s: currently slice info "
+ "metadata is not supported when slice "
+ "delivery mode is enabled. hence "
+ "disabling slice info metadata.\n",
+ __func__);
+ slice_property_hdr.prop_id =
+ VCD_I_METADATA_ENABLE;
+ slice_property_hdr.sz =
+ sizeof(struct \
+ vcd_property_meta_data_enable);
+ ddl_get_metadata_params(ddl,
+ &slice_property_hdr,
+ &slice_meta_data);
+ slice_meta_data.meta_data_enable_flag
+ &= ~VCD_METADATA_ENC_SLICE;
+ ddl_set_metadata_params(ddl,
+ &slice_property_hdr,
+ &slice_meta_data);
+ encoder->client_output_buf_req.min_count =
+ ((DDL_ENC_SLICE_BATCH_FACTOR * num_slices + 2)
> DDL_MAX_BUFFER_COUNT)
? DDL_MAX_BUFFER_COUNT :
(DDL_ENC_SLICE_BATCH_FACTOR * num_slices + 2);
@@ -1016,18 +1033,6 @@
encoder->client_output_buf_req.min_count,
output_buf_size,
encoder->client_output_buf_req.sz);
- slice_property_hdr.prop_id =
- VCD_I_METADATA_ENABLE;
- slice_property_hdr.sz =
- sizeof(struct vcd_property_meta_data_enable);
- ddl_get_metadata_params(ddl,
- &slice_property_hdr,
- &slice_meta_data);
- slice_meta_data.meta_data_enable_flag
- &= ~VCD_METADATA_ENC_SLICE;
- ddl_set_metadata_params(ddl,
- &slice_property_hdr,
- &slice_meta_data);
vcd_status = VCD_S_SUCCESS;
}
}
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
index 49d885c..d517028 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
@@ -129,10 +129,16 @@
{
transc = (struct vcd_transc *)client_data;
- if (!transc || !transc->in_use
- || !transc->cctxt) {
+ if (!transc || !transc->in_use || !transc->cctxt) {
VCD_MSG_ERROR("Invalid clientdata "
- "received from DDL ");
+ "received from DDL, transc = 0x%x\n",
+ (u32)transc);
+ if (transc) {
+ VCD_MSG_ERROR("transc->in_use = %u, "
+ "transc->cctxt = 0x%x\n",
+ transc->in_use,
+ (u32)transc->cctxt);
+ }
} else {
cctxt = transc->cctxt;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 1218794..6ca4dbe 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -1900,9 +1900,10 @@
} else {
memset(&dev_ctxt->trans_tbl[i], 0,
sizeof(struct vcd_transc));
-
dev_ctxt->trans_tbl[i].in_use = true;
-
+ VCD_MSG_LOW("%s: Get transc = 0x%x, in_use = %u\n",
+ __func__, (u32)(&dev_ctxt->trans_tbl[i]),
+ dev_ctxt->trans_tbl[i].in_use);
return &dev_ctxt->trans_tbl[i];
}
}
@@ -1911,7 +1912,8 @@
{
if (trans_entry) {
trans_entry->in_use = false;
- VCD_MSG_LOW("%s in_use set to false\n", __func__);
+ VCD_MSG_LOW("%s: Free transc = 0x%x, in_use = %u\n",
+ __func__, (u32)trans_entry, trans_entry->in_use);
}
}