@@ -150,6 +150,7 @@ struct vdec_h264_slice_share_info {
* @dpb: decoded picture buffer used to store reference
* buffer information
*@is_field_bitstream: is field bitstream
+ * @is_need_pending_data: add startcode for cavlc bistream when bs size is smaller than 20 bytes
*/
struct vdec_h264_slice_inst {
unsigned int slice_dec_num;
@@ -169,6 +170,7 @@ struct vdec_h264_slice_inst {
struct v4l2_h264_dpb_entry dpb[16];
bool is_field_bitstream;
+ bool is_need_pending_data;
};
static int vdec_h264_slice_fill_decode_parameters(struct vdec_h264_slice_inst *inst,
@@ -395,6 +397,7 @@ static void vdec_h264_slice_get_crop_info(struct vdec_h264_slice_inst *inst,
static int vdec_h264_slice_init(struct mtk_vcodec_ctx *ctx)
{
+ struct device *dev = &ctx->dev->plat_dev->dev;
struct vdec_h264_slice_inst *inst;
int err, vsi_size;
@@ -423,6 +426,16 @@ static int vdec_h264_slice_init(struct mtk_vcodec_ctx *ctx)
inst->resolution_changed = true;
inst->realloc_mv_buf = true;
+ /* Need to add pending data at the end of bitstream when bs_sz is small than
+ * 20 bytes for cavlc bitstream, or lat will decode fail. This pending data is
+ * useful for mt8192 and mt8195 platform.
+ *
+ * cavlc bitstream when entropy_coding_mode_flag is false.
+ */
+ if (of_device_is_compatible(dev->of_node, "mediatek,mt8192-vcodec-dec") ||
+ of_device_is_compatible(dev->of_node, "mediatek,mt8195-vcodec-dec"))
+ inst->is_need_pending_data = true;
+
mtk_vcodec_debug(inst, "lat struct size = %d,%d,%d,%d vsi: %d\n",
(int)sizeof(struct mtk_h264_sps_param),
(int)sizeof(struct mtk_h264_pps_param),
@@ -545,6 +558,19 @@ static int vdec_h264_slice_core_decode(struct vdec_lat_buf *lat_buf)
return 0;
}
+static void vdec_h264_insert_startcode(struct vdec_h264_slice_inst *inst, unsigned char *buf,
+ size_t *bs_size, struct mtk_h264_pps_param *pps)
+{
+ if (!inst->is_need_pending_data || pps->entropy_coding_mode_flag || *bs_size > 20)
+ return;
+
+ buf[*bs_size] = 0;
+ buf[*bs_size + 1] = 0;
+ buf[*bs_size + 2] = 1;
+ buf[*bs_size + 3] = 0xff;
+ (*bs_size) += 4;
+}
+
static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
struct vdec_fb *fb, bool *res_chg)
{
@@ -588,9 +614,6 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
}
inst->vsi->dec.nal_info = buf[nal_start_idx];
- inst->vsi->dec.bs_buf_addr = (u64)bs->dma_addr;
- inst->vsi->dec.bs_buf_size = bs->size;
-
lat_buf->src_buf_req = src_buf_info->m2m_buf.vb.vb2_buf.req_obj.req;
v4l2_m2m_buf_copy_metadata(&src_buf_info->m2m_buf.vb, &lat_buf->ts_info, true);
@@ -598,6 +621,10 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
if (err)
goto err_free_fb_out;
+ vdec_h264_insert_startcode(inst, buf, &bs->size, &share_info->h264_slice_params.pps);
+ inst->vsi->dec.bs_buf_addr = (uint64_t)bs->dma_addr;
+ inst->vsi->dec.bs_buf_size = bs->size;
+
*res_chg = inst->resolution_changed;
if (inst->resolution_changed) {
mtk_vcodec_debug(inst, "- resolution changed -");