From ab12a0e2996a3c5a7603949d5f12b4c42b2c12b6 Mon Sep 17 00:00:00 2001 From: Shijie Qin Date: Mon, 25 May 2020 10:23:58 +0800 Subject: [PATCH] LF-1430-4 mxc: vpu_malone: refine the operation of insert scode For more readable, use a handler table to insert scode for each format. Signed-off-by: Shijie Qin Reviewed-by: ming_qian --- drivers/mxc/vpu_malone/insert_startcode.c | 566 ++++++++++++++-------- drivers/mxc/vpu_malone/insert_startcode.h | 20 +- drivers/mxc/vpu_malone/vpu_b0.c | 43 +- 3 files changed, 374 insertions(+), 255 deletions(-) diff --git a/drivers/mxc/vpu_malone/insert_startcode.c b/drivers/mxc/vpu_malone/insert_startcode.c index ba82c318e32d..3d945ba00e3d 100644 --- a/drivers/mxc/vpu_malone/insert_startcode.c +++ b/drivers/mxc/vpu_malone/insert_startcode.c @@ -115,6 +115,85 @@ static int create_vc1_nal_pichdr(unsigned char *dst, void *data) return len; } +static unsigned int insert_scd_pic_vc1(struct vpu_ctx *ctx, unsigned int buffer_size, void *data) +{ + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + + if (q_data->fourcc == V4L2_PIX_FMT_VC1_ANNEX_G) { + unsigned int rcv_pichdr_size = IMX_VC1_RCV_PIC_HEADER_LEN; + unsigned char rcv_pichdr[IMX_VC1_RCV_PIC_HEADER_LEN] = { 0 }; + unsigned char scd_pichdr[16] = { 0 }; + + set_payload_hdr(scd_pichdr, SCODE_NEW_PICTURE, IMX_CODEC_ID_VC1_SIMPLE, + rcv_pichdr_size + buffer_size, q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, scd_pichdr, 16); + set_vc1_rcv_pichdr(rcv_pichdr, buffer_size); + length += copy_buffer_to_stream(ctx, rcv_pichdr, rcv_pichdr_size); + } else { + unsigned char nal_hdr[IMX_VC1_NAL_HEADER_LEN] = { 0 }; + unsigned int len; + + len = create_vc1_nal_pichdr(nal_hdr, data); + length += copy_buffer_to_stream(ctx, nal_hdr, len); + } + + return length; +} + +static unsigned int insert_scd_seq_vc1(struct vpu_ctx *ctx, unsigned int buffer_size, void *data) +{ + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + unsigned int rvc_seqhdr_size = IMX_VC1_RCV_SEQ_HEADER_LEN; + unsigned char rcv_seqhdr[IMX_VC1_RCV_SEQ_HEADER_LEN] = { 0 }; + unsigned char scd_seqhdr[16] = { 0 }; + + if (q_data->fourcc == V4L2_PIX_FMT_VC1_ANNEX_G) { + set_payload_hdr(scd_seqhdr, SCODE_NEW_SEQUENCE, IMX_CODEC_ID_VC1_SIMPLE, + rvc_seqhdr_size, q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, scd_seqhdr, 16); + + set_vc1_rcv_seqhdr(rcv_seqhdr, data, q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, rcv_seqhdr, rvc_seqhdr_size); + } else { + length += copy_buffer_to_stream(ctx, data, buffer_size); + } + + return length; +} + +static unsigned int insert_scd_pic_vp6(struct vpu_ctx *ctx, unsigned int buffer_size, void *data) +{ + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + unsigned char pic_header[16] = { 0 }; + + set_payload_hdr(pic_header, SCODE_NEW_PICTURE, IMX_CODEC_ID_VC1_SIMPLE, + buffer_size, q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, pic_header, 16); + + return length; +} + +static unsigned int insert_scd_seq_vp6(struct vpu_ctx *ctx, unsigned int buffer_size, void *data) +{ + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + unsigned char seq_header[16] = {0}; + unsigned char *src = (unsigned char *)data; + + set_payload_hdr(seq_header, SCODE_NEW_SEQUENCE, IMX_CODEC_ID_VP6, + 0, q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, seq_header, 16); + + /* first data include frame data, need to handle them too */ + length += insert_scd_pic_vp6(ctx, buffer_size, data); + length += copy_buffer_to_stream(ctx, src, buffer_size); + + return length; +} + static void set_vp8_ivf_seqhdr(unsigned char *dst, int width, int height) { /* 0-3byte signature "DKIF" */ @@ -166,6 +245,183 @@ static void set_vp8_ivf_pichdr(unsigned char *dst, unsigned int frame_size) */ } +static unsigned int insert_scd_pic_vp8(struct vpu_ctx *ctx, unsigned int buffer_size, void *data) +{ + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + unsigned int ivf_pichdr_size = IMX_VP8_IVF_FRAME_HEADER_LEN; + unsigned char pic_header[16] = { 0 }; + unsigned char ivf_frame_header[IMX_VP8_IVF_FRAME_HEADER_LEN] = { 0 }; + + set_payload_hdr(pic_header, SCODE_NEW_PICTURE, IMX_CODEC_ID_VP8, + ivf_pichdr_size + buffer_size, q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, pic_header, 16); + set_vp8_ivf_pichdr(ivf_frame_header, buffer_size); + length += copy_buffer_to_stream(ctx, ivf_frame_header, ivf_pichdr_size); + + return length; +} + +static unsigned int insert_scd_seq_vp8(struct vpu_ctx *ctx, unsigned int buffer_size, void *data) +{ + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + unsigned int ivf_seqhdr_size = IMX_VP8_IVF_SEQ_HEADER_LEN; + unsigned char scd_seqhdr[16] = { 0 }; + unsigned char ivf_seqhdr[IMX_VP8_IVF_SEQ_HEADER_LEN] = { 0 }; + unsigned char *src = (unsigned char *)data; + + set_payload_hdr(scd_seqhdr, SCODE_NEW_SEQUENCE, IMX_CODEC_ID_VP8, + ivf_seqhdr_size, q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, scd_seqhdr, 16); + set_vp8_ivf_seqhdr(ivf_seqhdr, q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, ivf_seqhdr, ivf_seqhdr_size); + + /* first data include frame data, need to handle them too */ + length += insert_scd_pic_vp8(ctx, buffer_size, data); + length += copy_buffer_to_stream(ctx, src, buffer_size); + + return length; +} + +static unsigned int insert_scd_pic_asp(struct vpu_ctx *ctx, unsigned int buffer_size, void *data) +{ + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + unsigned char pic_header[16] = { 0 }; + + if (q_data->fourcc == VPU_PIX_FMT_DIV3) { + set_payload_hdr(pic_header, SCODE_NEW_PICTURE, IMX_CODEC_ID_DIVX3, + buffer_size, q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, pic_header, 16); + } + + return length; +} + +static unsigned int insert_scd_seq_asp(struct vpu_ctx *ctx, unsigned int buffer_size, void *data) +{ + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + unsigned char seq_header[16] = {0}; + unsigned char *src = (unsigned char *)data; + + if (q_data->fourcc == VPU_PIX_FMT_DIV3) { + set_payload_hdr(seq_header, SCODE_NEW_SEQUENCE, IMX_CODEC_ID_DIVX3, + 0, q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, seq_header, 16); + + /* first data include frame data, need to handle them too */ + length += insert_scd_pic_asp(ctx, buffer_size, data); + length += copy_buffer_to_stream(ctx, src, buffer_size); + } else { + /* + * other format no sequence or picture header + * directly copy frame data to ring buffer + */ + length += copy_buffer_to_stream(ctx, src, buffer_size); + } + + return length; +} + +static unsigned int insert_scd_pic_spk(struct vpu_ctx *ctx, unsigned int buffer_size, void *data) +{ + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + unsigned char pic_header[16] = { 0 }; + + set_payload_hdr(pic_header, SCODE_NEW_PICTURE, IMX_CODEC_ID_SPK, + buffer_size, q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, pic_header, 16); + + return length; +} + +static unsigned int insert_scd_seq_spk(struct vpu_ctx *ctx, unsigned int buffer_size, void *data) +{ + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + unsigned char seq_header[16] = {0}; + unsigned char *src = (unsigned char *)data; + + set_payload_hdr(seq_header, SCODE_NEW_SEQUENCE, IMX_CODEC_ID_SPK, + 0, q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, seq_header, 16); + + /* first data include frame data, need to handle them too */ + length += insert_scd_pic_spk(ctx, buffer_size, data); + length += copy_buffer_to_stream(ctx, src, buffer_size); + + return length; +} + +static unsigned int insert_slice_arv(struct vpu_ctx *ctx, unsigned int buffer_size, void *data) +{ + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + unsigned char slice_header[16] = { 0 }; + unsigned int codec_id; + + if (ctx->arv_type == ARV_8) + codec_id = IMX_CODEC_ID_ARV8; + else + codec_id = IMX_CODEC_ID_ARV9; + + set_payload_hdr(slice_header, SCODE_NEW_SLICE, codec_id, buffer_size, + q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, slice_header, 16); + + return length; +} + +static unsigned int insert_scd_pic_arv(struct vpu_ctx *ctx, unsigned int buffer_size, void *data) +{ + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + unsigned int slice_num = 0; + unsigned int packlen = 0; + unsigned char pic_header[16] = { 0 }; + unsigned char *src = (unsigned char *)data; + unsigned int codec_id; + + slice_num = ((src[16] << 24) | (src[17] << 16) | (src[18] << 8) | (src[19])); + packlen = 20 + 8 * slice_num; + if (ctx->arv_type == ARV_8) + codec_id = IMX_CODEC_ID_ARV8; + else + codec_id = IMX_CODEC_ID_ARV9; + + set_payload_hdr(pic_header, SCODE_NEW_PICTURE, codec_id, packlen, + q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, pic_header, 16); + + return length; +} + +static unsigned int insert_scd_seq_arv(struct vpu_ctx *ctx, unsigned int buffer_size, void *data) +{ + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + unsigned char seq_header[16] = {0}; + unsigned int codec_id; + + if (strncmp((const char *)(data + 8), "RV30", 4) == 0) { + ctx->arv_type = ARV_8; + codec_id = IMX_CODEC_ID_ARV8; + } else { + ctx->arv_type = ARV_9; + codec_id = IMX_CODEC_ID_ARV9; + } + + set_payload_hdr(seq_header, SCODE_NEW_SEQUENCE, codec_id, + buffer_size, q_data->width, q_data->height); + length += copy_buffer_to_stream(ctx, seq_header, 16); + length += copy_buffer_to_stream(ctx, data, buffer_size); + + return length; +} + u_int32 single_seq_info_format(struct queue_data *q_data) { u_int32 ret = 0; @@ -236,235 +492,52 @@ bool check_free_size_4_seq(struct vpu_ctx *ctx, u_int32 uPayloadSize) return true; } -u_int32 insert_scode_4_seq(struct vpu_ctx *ctx, u_int8 *src, u_int32 uPayloadSize) +bool check_free_size_pic(struct vpu_ctx *ctx, unsigned int buffer_size) { struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; - u_int32 length = 0; - - if (!check_free_size_4_seq(ctx, uPayloadSize)) - return 0; + pSTREAM_BUFFER_DESCRIPTOR_TYPE pStrBufDesc; + unsigned int nfreespace = 0; + unsigned int length = 0; switch (q_data->vdec_std) { - case VPU_VIDEO_VC1: { - if (q_data->fourcc == V4L2_PIX_FMT_VC1_ANNEX_G) { - u_int8 payload_header[32] = {0}; - u_int8 rcv_seqhdr[IMX_VC1_RCV_SEQ_HEADER_LEN] = {0}; - unsigned int rvc_seqhdr_size = IMX_VC1_RCV_SEQ_HEADER_LEN; - - set_payload_hdr(payload_header, SCODE_NEW_SEQUENCE, IMX_CODEC_ID_VC1_SIMPLE, - rvc_seqhdr_size, q_data->width, q_data->height); - copy_buffer_to_stream(ctx, payload_header, 16); - length = 16; - set_vc1_rcv_seqhdr(rcv_seqhdr, src, q_data->width, q_data->height); - copy_buffer_to_stream(ctx, rcv_seqhdr, rvc_seqhdr_size); - length += rvc_seqhdr_size; - } else { - length += copy_buffer_to_stream(ctx, src, uPayloadSize); - } - } - break; - case VPU_VIDEO_VP6: { - u_int8 seq_header[16] = {0}; - u_int8 frame_header[16] = {0}; - - set_payload_hdr(seq_header, SCODE_NEW_SEQUENCE, IMX_CODEC_ID_VP6, - 0, q_data->width, q_data->height); - copy_buffer_to_stream(ctx, seq_header, 16); - length = 16; - set_payload_hdr(frame_header, SCODE_NEW_PICTURE, IMX_CODEC_ID_VP6, - uPayloadSize, q_data->width, q_data->height); - copy_buffer_to_stream(ctx, frame_header, 16); - length += 16; - copy_buffer_to_stream(ctx, src, uPayloadSize); - length += uPayloadSize; - } - break; - case VPU_VIDEO_VP8: { - u_int8 scd_seq_header[16] = {0}; - u_int8 ivf_seq_header[IMX_VP8_IVF_SEQ_HEADER_LEN] = {0}; - u_int8 scd_frame_header[16] = {0}; - u_int8 ivf_frame_header[IMX_VP8_IVF_FRAME_HEADER_LEN] = {0}; - unsigned int ivf_seqhdr_size = IMX_VP8_IVF_SEQ_HEADER_LEN; - unsigned int ivf_pichdr_size = IMX_VP8_IVF_FRAME_HEADER_LEN; - - set_payload_hdr(scd_seq_header, SCODE_NEW_SEQUENCE, IMX_CODEC_ID_VP8, - ivf_seqhdr_size, q_data->width, q_data->height); - length += copy_buffer_to_stream(ctx, scd_seq_header, 16); - set_vp8_ivf_seqhdr(ivf_seq_header, q_data->width, q_data->height); - length += copy_buffer_to_stream(ctx, ivf_seq_header, ivf_seqhdr_size); - - set_payload_hdr(scd_frame_header, SCODE_NEW_SEQUENCE, IMX_CODEC_ID_VP8, - ivf_seqhdr_size + ivf_pichdr_size, q_data->width, q_data->height); - length += copy_buffer_to_stream(ctx, scd_frame_header, 16); - set_vp8_ivf_pichdr(ivf_frame_header, uPayloadSize); - length += copy_buffer_to_stream(ctx, ivf_frame_header, ivf_pichdr_size); - length += copy_buffer_to_stream(ctx, src, uPayloadSize); - } - break; - case VPU_VIDEO_ASP: { - if (q_data->fourcc == VPU_PIX_FMT_DIV3) { - u_int8 seq_header[16] = {0}; - u_int8 frame_header[16] = {0}; - - set_payload_hdr(seq_header, SCODE_NEW_SEQUENCE, IMX_CODEC_ID_DIVX3, - 0, q_data->width, q_data->height); - length += copy_buffer_to_stream(ctx, seq_header, 16); - - set_payload_hdr(frame_header, SCODE_NEW_PICTURE, IMX_CODEC_ID_DIVX3, - uPayloadSize, q_data->width, q_data->height); - length += copy_buffer_to_stream(ctx, frame_header, 16); - length += copy_buffer_to_stream(ctx, src, uPayloadSize); - } else { - copy_buffer_to_stream(ctx, src, uPayloadSize); - length = uPayloadSize; - } - } - break; - case VPU_VIDEO_SPK: { - u_int8 seq_header[16] = {0}; - u_int8 frame_header[16] = {0}; - - set_payload_hdr(seq_header, SCODE_NEW_SEQUENCE, IMX_CODEC_ID_SPK, - 0, q_data->width, q_data->height); - length += copy_buffer_to_stream(ctx, seq_header, 16); - - set_payload_hdr(frame_header, SCODE_NEW_PICTURE, IMX_CODEC_ID_SPK, - uPayloadSize, q_data->width, q_data->height); - length += copy_buffer_to_stream(ctx, frame_header, 16); - length += copy_buffer_to_stream(ctx, src, uPayloadSize); - } - break; - case VPU_VIDEO_RV: { - u_int8 seq_header[16] = {0}; - unsigned int codec_id; - - if (strncmp((const char *)(src+8), "RV30", 4) == 0) { - ctx->arv_type = ARV_8; - codec_id = IMX_CODEC_ID_ARV8; - } else { - ctx->arv_type = ARV_9; - codec_id = IMX_CODEC_ID_ARV9; - } - - set_payload_hdr(seq_header, SCODE_NEW_SEQUENCE, codec_id, - uPayloadSize, q_data->width, q_data->height); - length += copy_buffer_to_stream(ctx, seq_header, 16); - length += copy_buffer_to_stream(ctx, src, uPayloadSize); - } - break; + case VPU_VIDEO_VC1: + length = buffer_size + IMX_VC1_RCV_PIC_HEADER_LEN + + IMX_PAYLOAD_HEADER_SIZE; + break; + case VPU_VIDEO_VP8: + length = buffer_size + IMX_VP8_IVF_FRAME_HEADER_LEN + IMX_PAYLOAD_HEADER_SIZE; + break; + case VPU_VIDEO_VP6: + case VPU_VIDEO_ASP: + case VPU_VIDEO_SPK: + length = buffer_size + IMX_PAYLOAD_HEADER_SIZE; + break; + case VPU_VIDEO_RV: + /* speciall: buffer_size need to include all slice header size*/ + length = buffer_size + IMX_PAYLOAD_HEADER_SIZE; + break; case VPU_VIDEO_AVC: case VPU_VIDEO_MPEG2: case VPU_VIDEO_AVS: case VPU_VIDEO_JPEG: case VPU_VIDEO_AVC_MVC: case VPU_VIDEO_HEVC: - case VPU_VIDEO_UNDEFINED: { - copy_buffer_to_stream(ctx, src, uPayloadSize); - length = uPayloadSize; - } - break; + case VPU_VIDEO_UNDEFINED: + length = buffer_size; + break; default: break; } - return length; -} -u_int32 insert_scode_4_pic(struct vpu_ctx *ctx, u_int8 *dst, u_int8 *src, u_int32 vdec_std, u_int32 uPayloadSize) -{ - struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; - u_int32 length = 0; - - switch (vdec_std) { - case VPU_VIDEO_VC1: { - if (q_data->fourcc == V4L2_PIX_FMT_VC1_ANNEX_G) { - u_int8 rcv_pichdr[IMX_VC1_RCV_PIC_HEADER_LEN]; - unsigned int rcv_pichdr_size = IMX_VC1_RCV_PIC_HEADER_LEN; - - set_payload_hdr(dst, SCODE_NEW_PICTURE, IMX_CODEC_ID_VC1_SIMPLE, - uPayloadSize + rcv_pichdr_size, q_data->width, q_data->height); - set_vc1_rcv_pichdr(rcv_pichdr, uPayloadSize); - memcpy(dst+16, rcv_pichdr, rcv_pichdr_size); - length = 16 + rcv_pichdr_size; - } else { - unsigned char nal_hdr[IMX_VC1_NAL_HEADER_LEN] = { 0 }; - unsigned int len; - - len = create_vc1_nal_pichdr(nal_hdr, src); - memcpy(dst, nal_hdr, len); - length = len; - } + pStrBufDesc = get_str_buffer_desc(ctx); + nfreespace = got_free_space(pStrBufDesc->wptr, pStrBufDesc->rptr, + pStrBufDesc->start, pStrBufDesc->end); + if (nfreespace < (length + MIN_SPACE)) { + vpu_dbg(LVL_INFO, "buffer_full: the circular buffer freespace < buffer_size\n"); + return false; } - break; - case VPU_VIDEO_VP6: { - set_payload_hdr(dst, SCODE_NEW_PICTURE, IMX_CODEC_ID_VC1_SIMPLE, - uPayloadSize, q_data->width, q_data->height); - length = 16; - } - break; - case VPU_VIDEO_VP8: { - u_int8 frame_header[IMX_VP8_IVF_FRAME_HEADER_LEN] = { 0 }; - unsigned int ivf_pichdr_size = IMX_VP8_IVF_FRAME_HEADER_LEN; - set_payload_hdr(dst, SCODE_NEW_PICTURE, IMX_CODEC_ID_VP8, uPayloadSize + ivf_pichdr_size, - q_data->width, q_data->height); - length = 16; - set_vp8_ivf_pichdr(frame_header, uPayloadSize); - memcpy(dst+length, frame_header, ivf_pichdr_size); - length += ivf_pichdr_size; - } - break; - case VPU_VIDEO_ASP: { - if (q_data->fourcc == VPU_PIX_FMT_DIV3) { - set_payload_hdr(dst, SCODE_NEW_PICTURE, IMX_CODEC_ID_DIVX3, - uPayloadSize, q_data->width, q_data->height); - length = 16; - } - } - break; - case VPU_VIDEO_SPK: { - set_payload_hdr(dst, SCODE_NEW_PICTURE, IMX_CODEC_ID_SPK, - uPayloadSize, q_data->width, q_data->height); - length = 16; - } - break; - case VPU_VIDEO_RV: { - u_int32 slice_num; - u_int32 packlen; - unsigned int codec_id; - - slice_num = ((src[16] << 24) | (src[17] << 16) | (src[18] << 8) | (src[19])); - packlen = 20 + 8 * slice_num; - if (ctx->arv_type == ARV_8) - codec_id = IMX_CODEC_ID_ARV8; - else - codec_id = IMX_CODEC_ID_ARV9; - set_payload_hdr(dst, SCODE_NEW_PICTURE, codec_id, packlen, - q_data->width, q_data->height); - length = 16; - } - break; - default: - break; - } - return length; -} - -u_int32 insert_scode_4_arv_slice(struct vpu_ctx *ctx, u_int8 *dst, struct VPU_FMT_INFO_ARV *arv_frame, u_int32 uPayloadSize) -{ - struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; - u_int32 length = 0; - unsigned int codec_id; - - if (ctx->arv_type == ARV_8) - codec_id = IMX_CODEC_ID_ARV8; - else - codec_id = IMX_CODEC_ID_ARV9; - - set_payload_hdr(dst, codec_id, SCODE_NEW_SLICE, uPayloadSize, - q_data->width, q_data->height); - length = 16; - - return length; + return true; } struct VPU_FMT_INFO_ARV *get_arv_info(struct vpu_ctx *ctx, u_int8 *src, u_int32 size) @@ -517,3 +590,70 @@ void put_arv_info(struct VPU_FMT_INFO_ARV *arv_frame) kfree(arv_frame); } +static const struct imx_scd_handler handlers[] = { + {.vdec_std = VPU_VIDEO_VC1, + .insert_scd_seq = insert_scd_seq_vc1, + .insert_scd_pic = insert_scd_pic_vc1, + }, + {.vdec_std = VPU_VIDEO_VP6, + .insert_scd_seq = insert_scd_seq_vp6, + .insert_scd_pic = insert_scd_pic_vp6, + }, + {.vdec_std = VPU_VIDEO_VP8, + .insert_scd_seq = insert_scd_seq_vp8, + .insert_scd_pic = insert_scd_pic_vp8, + }, + {.vdec_std = VPU_VIDEO_ASP, + .insert_scd_seq = insert_scd_seq_asp, + .insert_scd_pic = insert_scd_pic_asp, + }, + {.vdec_std = VPU_VIDEO_SPK, + .insert_scd_seq = insert_scd_seq_spk, + .insert_scd_pic = insert_scd_pic_spk, + }, + {.vdec_std = VPU_VIDEO_RV, + .insert_scd_seq = insert_scd_seq_arv, + .insert_scd_pic = insert_scd_pic_arv, + .insert_scd_slice = insert_slice_arv, + }, +}; + +unsigned int insert_scode(struct vpu_ctx *ctx, unsigned int scd_type, unsigned int buffer_size, void *data) +{ + const struct imx_scd_handler *handler; + int i = 0; + bool found = false; + struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; + unsigned int length = 0; + + for (i = 0; i < ARRAY_SIZE(handlers); i++) { + handler = &handlers[i]; + if (handler->vdec_std != q_data->vdec_std) + continue; + found = true; + break; + } + + if (scd_type == SCODE_NEW_SEQUENCE) { + if (!check_free_size_4_seq(ctx, buffer_size)) + return length; + + /* some format first data is frame data, and no need to add + * any header, directly copy it to ring buffer. + */ + if (found && handler->insert_scd_seq) + length = handler->insert_scd_seq(ctx, buffer_size, data); + else + length = copy_buffer_to_stream(ctx, data, buffer_size); + } else if (scd_type == SCODE_NEW_PICTURE) { + if (found && handler->insert_scd_pic) + length = handler->insert_scd_pic(ctx, buffer_size, data); + } else if (scd_type == SCODE_NEW_SLICE) { + if (found && handler->insert_scd_slice) + length = handler->insert_scd_slice(ctx, buffer_size, data); + } else { + vpu_dbg(LVL_WARN, "ctx[%d] scd_type invalid\n", ctx->str_index); + } + + return length; +} diff --git a/drivers/mxc/vpu_malone/insert_startcode.h b/drivers/mxc/vpu_malone/insert_startcode.h index 564af6146d74..7fc67a09fbeb 100644 --- a/drivers/mxc/vpu_malone/insert_startcode.h +++ b/drivers/mxc/vpu_malone/insert_startcode.h @@ -24,6 +24,8 @@ #define SCODE_NEW_PICTURE 0x32 #define SCODE_NEW_SLICE 0x33 +#define IMX_PAYLOAD_HEADER_SIZE 16 + #define IMX_CODEC_VERSION_ID 0x1 #define IMX_CODEC_ID_VC1_SIMPLE 0x10 @@ -47,13 +49,21 @@ #define IMX_VP8_IVF_SEQ_HEADER_LEN 32 #define IMX_VP8_IVF_FRAME_HEADER_LEN 8 -u_int32 insert_scode_4_pic(struct vpu_ctx *ctx, u_int8 *dst, u_int8 *src, u_int32 vdec_std, u_int32 uPayloadSize); -u_int32 insert_scode_4_seq(struct vpu_ctx *ctx, u_int8 *src, u_int32 uPayloadSize); -u_int32 insert_scode_4_arv_slice(struct vpu_ctx *ctx, u_int8 *dst, struct VPU_FMT_INFO_ARV *arv_frame, u_int32 uPayloadSize); + +struct imx_scd_handler { + unsigned int vdec_std; + + unsigned int (*insert_scd_seq)(struct vpu_ctx *ctx, unsigned int buffer_size, void *data); + unsigned int (*insert_scd_pic)(struct vpu_ctx *ctx, unsigned int buffer_size, void *data); + unsigned int (*insert_scd_slice)(struct vpu_ctx *ctx, unsigned int buffer_size, void *data); +}; + + struct VPU_FMT_INFO_ARV *get_arv_info(struct vpu_ctx *ctx, u_int8 *src, u_int32 size); void put_arv_info(struct VPU_FMT_INFO_ARV *arv_frame); -void insert_payload_header_arv(u_int8 *dst, u_int32 uScodeType, - enum ARV_FRAME_TYPE type, u_int32 uPayloadSize, u_int32 uWidth, u_int32 uHeight); u_int32 single_seq_info_format(struct queue_data *q_data); +unsigned int insert_scode(struct vpu_ctx *ctx, unsigned int scd_type, + unsigned int buffer_size, void *data); +bool check_free_size_pic(struct vpu_ctx *ctx, unsigned int buffer_size); #endif diff --git a/drivers/mxc/vpu_malone/vpu_b0.c b/drivers/mxc/vpu_malone/vpu_b0.c index 387f8da03d06..29092aa53eb8 100644 --- a/drivers/mxc/vpu_malone/vpu_b0.c +++ b/drivers/mxc/vpu_malone/vpu_b0.c @@ -3165,46 +3165,17 @@ static void vpu_dec_event_decode_error(struct vpu_ctx *ctx) static int update_stream_addr(struct vpu_ctx *ctx, void *input_buffer, uint32_t buffer_size, uint32_t uStrBufIdx) { - pSTREAM_BUFFER_DESCRIPTOR_TYPE pStrBufDesc; struct queue_data *q_data = &ctx->q_data[V4L2_SRC]; - u_int8 payload_header[256] = {0}; - uint32_t nfreespace = 0; - uint32_t wptr; - uint32_t rptr; - uint32_t start; - uint32_t end; - uint32_t header_length = 0; uint32_t copy_length = 0; uint32_t input_offset = 0; struct VPU_FMT_INFO_ARV *arv_frame; uint32_t i; - vpu_dbg(LVL_BIT_FUNC, "enter %s\n", __func__); - - // changed to virtual address and back - pStrBufDesc = get_str_buffer_desc(ctx); - vpu_dbg(LVL_BIT_BUFFER_DESC, - "%s wptr(%x) rptr(%x) start(%x) end(%x) uStrBufIdx(%d)\n", - __func__, - pStrBufDesc->wptr, - pStrBufDesc->rptr, - pStrBufDesc->start, - pStrBufDesc->end, - uStrBufIdx); - wptr = pStrBufDesc->wptr; - rptr = pStrBufDesc->rptr; - start = pStrBufDesc->start; - end = pStrBufDesc->end; - - nfreespace = got_free_space(wptr, rptr, start, end); - header_length = insert_scode_4_pic(ctx, payload_header, input_buffer, q_data->vdec_std, buffer_size); if (q_data->vdec_std != VPU_VIDEO_RV) { - if (nfreespace < (buffer_size + header_length + MIN_SPACE)) { - vpu_dbg(LVL_INFO, "buffer_full: the circular buffer freespace < buffer_size\n"); + if (!check_free_size_pic(ctx, buffer_size)) return 0; - } - copy_length += copy_buffer_to_stream(ctx, payload_header, header_length); + copy_length += insert_scode(ctx, SCODE_NEW_PICTURE, buffer_size, input_buffer); copy_length += copy_buffer_to_stream(ctx, input_buffer, buffer_size); } else { arv_frame = get_arv_info(ctx, input_buffer, buffer_size); @@ -3212,8 +3183,7 @@ static int update_stream_addr(struct vpu_ctx *ctx, void *input_buffer, uint32_t vpu_dbg(LVL_WARN, "warning: %s() get arv frame info failed\n", __func__); return -1; } - if (nfreespace < (buffer_size + header_length + arv_frame->slice_num * 16 + MIN_SPACE)) { - vpu_dbg(LVL_INFO, "buffer_full: the circular buffer freespace < buffer_size\n"); + if (!check_free_size_pic(ctx, buffer_size + arv_frame->slice_num * 16)) { put_arv_info(arv_frame); arv_frame = NULL; return 0; @@ -3227,7 +3197,7 @@ static int update_stream_addr(struct vpu_ctx *ctx, void *input_buffer, uint32_t return -1; } - copy_length += copy_buffer_to_stream(ctx, payload_header, header_length); + copy_length += insert_scode(ctx, SCODE_NEW_PICTURE, buffer_size, input_buffer); copy_length += copy_buffer_to_stream(ctx, input_buffer + input_offset, arv_frame->packlen); input_offset += arv_frame->packlen; for (i = 0; i < arv_frame->slice_num; i++) { @@ -3235,8 +3205,7 @@ static int update_stream_addr(struct vpu_ctx *ctx, void *input_buffer, uint32_t arv_frame->packlen = arv_frame->data_len - arv_frame->slice_offset[i]; else arv_frame->packlen = arv_frame->slice_offset[i+1] - arv_frame->slice_offset[i]; - header_length = insert_scode_4_arv_slice(ctx, payload_header, arv_frame, arv_frame->packlen + 12); - copy_length += copy_buffer_to_stream(ctx, payload_header, header_length); + copy_length += insert_scode(ctx, SCODE_NEW_SLICE, arv_frame->packlen, input_buffer + input_offset); copy_length += copy_buffer_to_stream(ctx, input_buffer + input_offset, arv_frame->packlen); input_offset += arv_frame->packlen; } @@ -3455,7 +3424,7 @@ static void enqueue_stream_data(struct vpu_ctx *ctx, uint32_t uStrBufIdx) if (ctx->start_code_bypass) frame_bytes = update_stream_addr_bypass(ctx, input_buffer, buffer_size); else if (ctx->first_data_flag || is_codec_config_data(vb)) - frame_bytes = insert_scode_4_seq(ctx, input_buffer, buffer_size); + frame_bytes = insert_scode(ctx, SCODE_NEW_SEQUENCE, buffer_size, input_buffer); else frame_bytes = update_stream_addr_vpu(ctx, input_buffer, buffer_size, uStrBufIdx);