summaryrefslogtreecommitdiff
path: root/drivers/mxc/vpu-decoder-b0/insert_startcode.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mxc/vpu-decoder-b0/insert_startcode.c')
-rw-r--r--drivers/mxc/vpu-decoder-b0/insert_startcode.c546
1 files changed, 546 insertions, 0 deletions
diff --git a/drivers/mxc/vpu-decoder-b0/insert_startcode.c b/drivers/mxc/vpu-decoder-b0/insert_startcode.c
new file mode 100644
index 000000000000..dc2825b63e09
--- /dev/null
+++ b/drivers/mxc/vpu-decoder-b0/insert_startcode.c
@@ -0,0 +1,546 @@
+/*
+ * Copyright 2018 NXP
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @file insert_startcode.c
+ *
+ * copyright here may be changed later
+ *
+ *
+ */
+#include "insert_startcode.h"
+// Global VC1 ID and version
+u_int32 uVC1CodecID = 0x10; // Simple = 0x10, Main = 0x11
+u_int32 uVC1VersionID = 1;
+
+static int insert_RCV_seqhdr(unsigned char *pHeader, u_int32 *pHeaderLen, unsigned char *src,
+ u_int32 nFrameSize, u_int32 nWidth, u_int32 nHeight, int *pNoError)
+{
+ int nHeaderLen;
+
+ unsigned int nValue;
+ unsigned int HdrExtDataLen;
+ int i = 0;
+ int profile;
+
+ nHeaderLen = RCV_HEADER_LEN;
+
+ //Number of Frames, Header Extension Bit, Codec Version
+ nValue = RCV_NUM_FRAMES | RCV_SET_HDR_EXT | RCV_CODEC_VERSION;
+ pHeader[i++] = (unsigned char)nValue;
+ pHeader[i++] = (unsigned char)(nValue >> 8);
+ pHeader[i++] = (unsigned char)(nValue >> 16);
+#if 0 //1 ???
+ pHeader[i++] = 0xC5;
+#else
+ pHeader[i++] = (unsigned char)(nValue >> 24);
+#endif
+
+ //Header Extension Size
+ //ASF Parser gives 5 bytes whereas the VPU expects only 4 bytes, so limiting it
+ HdrExtDataLen = 4;
+ pHeader[i++] = (unsigned char)HdrExtDataLen;
+ pHeader[i++] = (unsigned char)(HdrExtDataLen >> 8);
+ pHeader[i++] = (unsigned char)(HdrExtDataLen >> 16);
+ pHeader[i++] = (unsigned char)(HdrExtDataLen >> 24);
+
+ profile = (*src)>>4;
+ if ((profile != 0) && (profile != 4) && (profile != 12)) {
+ //it is reasonable to return error immediately since only one sequence header inserted in whole rcv clip
+ *pNoError = 0;
+ }
+ memcpy(pHeader+i, src, HdrExtDataLen);
+ i += HdrExtDataLen;
+
+ //Height
+ pHeader[i++] = (unsigned char)nHeight;
+ pHeader[i++] = (unsigned char)(((nHeight >> 8) & 0xff));
+ pHeader[i++] = (unsigned char)(((nHeight >> 16) & 0xff));
+ pHeader[i++] = (unsigned char)(((nHeight >> 24) & 0xff));
+ //Width
+ pHeader[i++] = (unsigned char)nWidth;
+ pHeader[i++] = (unsigned char)(((nWidth >> 8) & 0xff));
+ pHeader[i++] = (unsigned char)(((nWidth >> 16) & 0xff));
+ pHeader[i++] = (unsigned char)(((nWidth >> 24) & 0xff));
+
+ //Frame Size
+ pHeader[i++] = (unsigned char)nFrameSize;
+ pHeader[i++] = (unsigned char)(nFrameSize >> 8);
+ pHeader[i++] = (unsigned char)(nFrameSize >> 16);
+#if 0 //1 ???
+ pHeader[i++] = (unsigned char)((nFrameSize >> 24));
+#else
+ pHeader[i++] = (unsigned char)((nFrameSize >> 24) | 0x80);
+#endif
+
+ *pHeaderLen = nHeaderLen;
+
+ return 1;
+}
+
+static int insert_RCV_pichdr(unsigned char *pHeader, int *pHeaderLen, unsigned int nInSize)
+{
+ pHeader[0] = (unsigned char)nInSize;
+ pHeader[1] = (unsigned char)(nInSize >> 8);
+ pHeader[2] = (unsigned char)(nInSize >> 16);
+ pHeader[3] = (unsigned char)(nInSize >> 24);
+ *pHeaderLen = 4;
+
+ return 1;
+}
+
+/*
+ * Byte 0-3: Startcode
+ * Byte 4: Payload length bits[23:16]
+ * Byte 5: Payload length bits[15:8]
+ * Byte 6: 0x4e
+ * Byte 7: Payload length bits[7:0]
+ * Byte 8: Codec ID Non-zero
+ * Byte 9: Codec Version ID Non-zero
+ * Byte 10: Picture Width bits[15:8]
+ * Byte 11: Picture Width bits[7:0]
+ * Byte 12: 0x58
+ * Byte 13: Picture Height bits[15:8]
+ * Byte 14: Picture Height bits[7:0]
+ * Byte 15: 0x50
+ */
+
+static void insert_payload_header_vc1(u_int8 *dst, u_int32 uScodeType, u_int32 uPayloadSize, u_int32 uWidth, u_int32 uHeight)
+{
+ // Startcode
+ dst[0] = 0x00;
+ dst[1] = 0x00;
+ dst[2] = 0x01;
+ dst[3] = uScodeType;
+
+ // Length
+ dst[4] = ((uPayloadSize>>16)&0xff);
+ dst[5] = ((uPayloadSize>>8)&0xff);
+ dst[6] = 0x4e;
+ dst[7] = ((uPayloadSize>>0)&0xff);
+
+ // Codec ID and Version
+ dst[8] = uVC1CodecID;
+ dst[9] = uVC1VersionID;
+
+ // Width
+ dst[10] = ((uWidth>>8)&0xff);
+ dst[11] = ((uWidth>>0)&0xff);
+ dst[12] = 0x58;
+
+ // Height
+ dst[13] = ((uHeight>>8)&0xff);
+ dst[14] = ((uHeight>>0)&0xff);
+ dst[15] = 0x50;
+}
+
+static int VC1CreateNALSeqHeader(unsigned char *pHeader, int *pHeaderLen,
+ unsigned char *pCodecPri, int nCodecSize, unsigned int *pData, int nMaxHeader)
+{
+ int nHeaderLen;
+ unsigned char temp[4] = {0x00, 0x00, 0x01, 0x0D};
+
+ nHeaderLen = nCodecSize - 1;
+ if ((4+nHeaderLen) > nMaxHeader) {
+ nHeaderLen = nMaxHeader - 4;
+ vpu_dbg(LVL_ERR, "error: header length %d overrun !!! \r\n", nCodecSize);
+ }
+ memcpy(pHeader, pCodecPri+1, nHeaderLen);
+
+ if (VC1_IS_NOT_NAL(pData[0])) {
+ //insert 0x0000010D at the end of header
+ memcpy(pHeader+nHeaderLen, temp, 4);
+ nHeaderLen += 4;
+ }
+
+ *pHeaderLen = nHeaderLen;
+
+ return 1;
+}
+
+static int VC1CreateNalFrameHeader(unsigned char *pHeader, int *pHeaderLen, unsigned int *pInData)
+{
+ unsigned int VC1Id;
+
+ VC1Id = *pInData;
+ if (VC1_IS_NOT_NAL(VC1Id)) {
+ //need insert header : special ID
+ pHeader[0] = 0x0;
+ pHeader[1] = 0x0;
+ pHeader[2] = 0x01;
+ pHeader[3] = 0x0D;
+ *pHeaderLen = 4;
+ } else {
+ //need not insert header
+ //do nothing
+ *pHeaderLen = 0;
+ }
+
+ return 1;
+}
+
+void vp6_scd_sequence_header(unsigned char *buffer, int pic_width, int pic_height)
+{
+ int Length = 0;
+
+ buffer[0] = 0x00;
+ buffer[1] = 0x00;
+ buffer[2] = 0x01;
+ buffer[3] = 0x31;
+ buffer[4] = (Length+12)>>16;
+ buffer[5] = (Length+12)>>8;
+ buffer[6] = 0x4e;
+ buffer[7] = (Length+12);
+ buffer[8] = 0x36;
+ buffer[9] = 0x1;
+ buffer[10] = pic_width>>8;
+ buffer[11] = pic_width;
+ buffer[12] = 0x58;
+ buffer[13] = pic_height>>8;
+ buffer[14] = pic_height;
+ buffer[15] = 0x50;
+}
+
+void vp6_scd_frame_header(unsigned char *buffer, int pic_width, int pic_height, int Length)
+{
+ buffer[0] = 0x00;
+ buffer[1] = 0x00;
+ buffer[2] = 0x01;
+ buffer[3] = 0x32;
+ buffer[4] = (Length+12)>>16;
+ buffer[5] = (Length+12)>>8;
+ buffer[6] = 0x4e;
+ buffer[7] = (Length+12);
+ buffer[8] = 0x36;
+ buffer[9] = 0x1;
+ buffer[10] = pic_width>>8;
+ buffer[11] = pic_width;
+ buffer[12] = 0x58;
+ buffer[13] = pic_height>>8;
+ buffer[14] = pic_height;
+ buffer[15] = 0x50;
+}
+
+void vp8_ivf_sequence_header(unsigned char *buffer, int pic_width, int pic_height)
+{
+ int Length = 32;
+
+ buffer[0] = 0x44;
+ buffer[1] = 0x4b;
+ buffer[2] = 0x49;
+ buffer[3] = 0x46; //0-3byte signature "DKIF"
+ buffer[4] = 0x00;
+ buffer[5] = 0x00; //4-5byte version 0
+ buffer[6] = Length;
+ buffer[7] = Length >> 8; //length of Header
+ buffer[8] = 0x56;
+ buffer[9] = 0x50;
+ buffer[10] = 0x38;
+ buffer[11] = 0x30; //VP8 fourcc
+ buffer[12] = pic_width;
+ buffer[13] = pic_width >> 8;
+ buffer[14] = pic_height;
+ buffer[15] = pic_height >> 8;
+ buffer[16] = 0xe8;
+ buffer[17] = 0x03;
+ buffer[18] = 0x00;
+ buffer[19] = 0x00; //16-19 frame rate
+ buffer[20] = 0x01;
+ buffer[21] = 0x00;
+ buffer[22] = 0x00;
+ buffer[23] = 0x00; //20-23 time scale
+ buffer[24] = 0xdf;
+ buffer[25] = 0xf9;
+ buffer[26] = 0x09;
+ buffer[27] = 0x00; //24-27 number frames
+ //28-31 unused
+}
+
+void vp8_ivf_frame_header(unsigned char *buffer, u_int32 FrameSize)
+{
+ buffer[0] = FrameSize;
+ buffer[1] = FrameSize >> 8;
+ buffer[2] = FrameSize >> 16;
+ buffer[3] = FrameSize >> 24;
+ //4-11 timestamp
+}
+
+void vp8_scd_sequence_header(unsigned char *buffer, int pic_width, int pic_height)
+{
+ int Length = 32;
+
+ buffer[0] = 0x00;
+ buffer[1] = 0x00;
+ buffer[2] = 0x01;
+ buffer[3] = 0x31;
+ buffer[4] = (Length+12)>>16;
+ buffer[5] = (Length+12)>>8;
+ buffer[6] = 0x4e;
+ buffer[7] = (Length+12);
+ buffer[8] = 0x36;
+ buffer[9] = 0x1;
+ buffer[10] = pic_width>>8;
+ buffer[11] = pic_width;
+ buffer[12] = 0x58;
+ buffer[13] = pic_height>>8;
+ buffer[14] = pic_height;
+ buffer[15] = 0x50;
+}
+void vp8_scd_frame_header(unsigned char *buffer, int pic_width, int pic_height, int Length)
+{
+ buffer[0] = 0x00;
+ buffer[1] = 0x00;
+ buffer[2] = 0x01;
+ buffer[3] = 0x32;
+ buffer[4] = (Length+12)>>16;
+ buffer[5] = (Length+12)>>8;
+ buffer[6] = 0x4e;
+ buffer[7] = (Length+12);
+ buffer[8] = 0x36;
+ buffer[9] = 0x1;
+ buffer[10] = pic_width>>8;
+ buffer[11] = pic_width;
+ buffer[12] = 0x58;
+ buffer[13] = pic_height>>8;
+ buffer[14] = pic_height;
+ buffer[15] = 0x50;
+}
+
+static void insert_payload_header_divx(u_int8 *dst, u_int32 uPayloadSize, u_int32 uWidth, u_int32 uHeight)
+{
+ // Startcode
+ dst[0] = 0x00;
+ dst[1] = 0x00;
+ dst[2] = 0x01;
+ dst[3] = 0x32;
+
+ // Length
+ dst[4] = ((uPayloadSize>>16)&0xff);
+ dst[5] = ((uPayloadSize>>8)&0xff);
+ dst[6] = 0x4e;
+ dst[7] = ((uPayloadSize>>0)&0xff);
+
+ // Codec ID and Version
+ dst[8] = 0x38;
+ dst[9] = 0x01;
+
+ // Width
+ dst[10] = ((uWidth>>8)&0xff);
+ dst[11] = ((uWidth>>0)&0xff);
+ dst[12] = 0x58;
+
+ // Height
+ dst[13] = ((uHeight>>8)&0xff);
+ dst[14] = ((uHeight>>0)&0xff);
+ dst[15] = 0x50;
+}
+
+static void insert_seq_header_spk(u_int8 *dst, u_int32 uPayloadSize, u_int32 uWidth, u_int32 uHeight)
+{
+ // Startcode
+ dst[0] = 0x00;
+ dst[1] = 0x00;
+ dst[2] = 0x01;
+ dst[3] = 0x31;
+
+ // Length
+ dst[4] = ((uPayloadSize>>16)&0xff);
+ dst[5] = ((uPayloadSize>>8)&0xff);
+ dst[6] = 0x4e;
+ dst[7] = ((uPayloadSize>>0)&0xff);
+
+ // Codec ID and Version
+ dst[8] = 0x39;
+ dst[9] = 0x01;
+
+ // Width
+ dst[10] = ((uWidth>>8)&0xff);
+ dst[11] = ((uWidth>>0)&0xff);
+ dst[12] = 0x58;
+
+ // Height
+ dst[13] = ((uHeight>>8)&0xff);
+ dst[14] = ((uHeight>>0)&0xff);
+ dst[15] = 0x50;
+}
+
+static void insert_frame_header_spk(u_int8 *dst, u_int32 uPayloadSize, u_int32 uWidth, u_int32 uHeight)
+{
+ uPayloadSize = 0;
+ // Startcode
+ dst[0] = 0x00;
+ dst[1] = 0x00;
+ dst[2] = 0x01;
+ dst[3] = 0x32;
+
+ // Length
+ dst[4] = ((uPayloadSize>>16)&0xff);
+ dst[5] = ((uPayloadSize>>8)&0xff);
+ dst[6] = 0x4e;
+ dst[7] = ((uPayloadSize>>0)&0xff);
+
+ // Codec ID and Version
+ dst[8] = 0x39;
+ dst[9] = 0x01;
+
+ // Width
+ dst[10] = ((uWidth>>8)&0xff);
+ dst[11] = ((uWidth>>0)&0xff);
+ dst[12] = 0x58;
+
+ // Height
+ dst[13] = ((uHeight>>8)&0xff);
+ dst[14] = ((uHeight>>0)&0xff);
+ dst[15] = 0x50;
+}
+
+u_int32 insert_scode_4_seq(struct vpu_ctx *ctx, u_int8 *src, u_int8 *dst, 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 Header[VC1_MAX_SEQ_HEADER_SIZE];
+ u_int32 uWidth = q_data->width;
+ u_int32 uHeight = q_data->height; //Width & Height in the generic payload header are ignored
+ u_int32 FrameSize = 0x60;
+ u_int32 HeaderLen, NoError = 1;
+ //insert startcode for vc1
+ insert_payload_header_vc1(dst, VC1_SCODE_NEW_SEQUENCE, 20, uWidth, uHeight);
+ length = 16;
+ //insert RCV sequence header for vc1 v1, length=20
+ insert_RCV_seqhdr(Header, &HeaderLen, src, FrameSize, uWidth, uHeight, &NoError);
+ HeaderLen = RCV_HEADER_LEN - 4;
+ memcpy(dst + 16, Header, HeaderLen);
+ length += HeaderLen;
+ } else {
+ u_int8 Header[VC1_MAX_SEQ_HEADER_SIZE];
+ u_int32 HeaderLen;
+
+ VC1CreateNALSeqHeader(Header, &HeaderLen, src, uPayloadSize,
+ (unsigned int *)src, VC1_MAX_SEQ_HEADER_SIZE);
+ if (VC1_IS_NOT_NAL(((unsigned int *)src)[0]))
+ HeaderLen -= 4;
+ memcpy(dst, Header, HeaderLen);
+ length += HeaderLen;
+ }
+ }
+
+ break;
+ case VPU_VIDEO_VP6: {
+ vp6_scd_sequence_header(dst, q_data->width, q_data->height);
+ length = 16;
+ }
+ break;
+ case VPU_VIDEO_VP8: {
+ u_int8 seq_header[32] = {0};
+ u_int8 frame_header[8] = {0};
+
+ vp8_scd_sequence_header(dst, q_data->width, q_data->height);
+ length = 16;
+ vp8_ivf_sequence_header(seq_header, q_data->width, q_data->height);
+ memcpy(dst+length, seq_header, 32);
+ length += 32;
+ vp8_scd_frame_header(dst + length, q_data->width, q_data->height, uPayloadSize);
+ length += 16;
+ vp8_ivf_frame_header(frame_header, uPayloadSize);
+ memcpy(dst+length, frame_header, 8);
+ length += 8;
+ memcpy(dst+length, src, uPayloadSize);
+ length += uPayloadSize;
+ }
+ break;
+ case VPU_VIDEO_ASP: {
+ if (q_data->fourcc == VPU_PIX_FMT_DIVX) {
+ insert_payload_header_divx(dst, uPayloadSize, q_data->width, q_data->height);
+ length = 16;
+ memcpy(dst+length, src, uPayloadSize);
+ length += uPayloadSize;
+ }
+ }
+ break;
+ case VPU_VIDEO_SPK: {
+ insert_seq_header_spk(dst, uPayloadSize, q_data->width, q_data->height);
+ length = 16;
+ }
+ 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 Header[VC1_MAX_FRM_HEADER_SIZE];
+ u_int32 HeaderLen;
+ u_int32 uWidth = q_data->width;
+ u_int32 uHeight = q_data->height; //Width & Height in the generic payload header are ignored
+
+ insert_payload_header_vc1(dst, VC1_SCODE_NEW_PICTURE, uPayloadSize + 4, uWidth, uHeight);
+ insert_RCV_pichdr(Header, &HeaderLen, uPayloadSize);
+ memcpy(dst+16, Header, 4);
+ length = 16 + 4;
+ } else {
+ u_int8 Header[VC1_MAX_FRM_HEADER_SIZE];
+ u_int32 HeaderLen;
+
+ VC1CreateNalFrameHeader(Header, (int *)(&HeaderLen), (unsigned int *)(src));
+ memcpy(dst, Header, HeaderLen);
+ length = HeaderLen;
+ }
+ }
+ break;
+ case VPU_VIDEO_VP6: {
+ vp6_scd_frame_header(dst, q_data->width, q_data->height, uPayloadSize);
+ length = 16;
+ }
+ break;
+ case VPU_VIDEO_VP8: {
+ u_int8 frame_header[8];
+
+ vp8_scd_frame_header(dst, q_data->width, q_data->height, uPayloadSize);
+ length = 16;
+ vp8_ivf_frame_header(frame_header, uPayloadSize);
+ memcpy(dst+length, frame_header, 8);
+ length += 8;
+ }
+ break;
+ case VPU_VIDEO_ASP: {
+ if (q_data->fourcc == VPU_PIX_FMT_DIVX) {
+ insert_payload_header_divx(dst, uPayloadSize, q_data->width, q_data->height);
+ length = 16;
+ }
+ }
+ break;
+ case VPU_VIDEO_SPK: {
+ insert_frame_header_spk(dst, uPayloadSize, q_data->width, q_data->height);
+ length = 16;
+ }
+ break;
+ default:
+ break;
+ }
+ return length;
+}
+
+
+