h264/mpeg2/mpeg4: parse profile ande level [1/1]
authormiaohong chen <miaohong.chen@amlogic.com>
Fri, 20 Nov 2020 06:16:44 +0000 (14:16 +0800)
committermiaohong chen <miaohong.chen@amlogic.com>
Mon, 23 Nov 2020 02:56:17 +0000 (10:56 +0800)
PD#SWPL-36663

Problem:
There is no profile and level which parsed

Solution:
parse profile and level

ucode gerrit:130812
ucode commit id:25534c

Verify:
S905X2

Change-Id: Ia369b647aadf623a4bb022198f8500d846932a72
Signed-off-by: miaohong chen <miaohong.chen@amlogic.com>
drivers/frame_provider/decoder/h264_multi/h264_dpb.h
drivers/frame_provider/decoder/h264_multi/vmh264.c
drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
drivers/frame_provider/decoder/utils/vdec.c
drivers/frame_provider/decoder/utils/vdec.h
firmware/video_ucode.bin

index 0f7cb2d6b3ddd5d1b36c02b894eabffb5c55cf7c..1b340982218f33834e9506433fc6c0286f69020e 100644 (file)
@@ -480,6 +480,7 @@ enum FirstInsertFrm_State {
 
 struct SPSParameters {
        unsigned int profile_idc;
+       unsigned int level_idc;
        int pic_order_cnt_type;
        int log2_max_pic_order_cnt_lsb_minus4;
        int num_ref_frames_in_pic_order_cnt_cycle;
index e9ef17139742a6e8395d51dd1c2ce41f536d1044..38e8c4eaa3f5c5b2351369f197b9a1fb86353bf8 100644 (file)
@@ -5118,6 +5118,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw,
 
                reg_val = param4;
                level_idc = reg_val & 0xff;
+               p_H264_Dpb->mSPS.level_idc = level_idc;
                max_reference_size = (reg_val >> 8) & 0xff;
                hw->dpb.reorder_output = max_reference_size;
                dpb_print(DECODE_ID(hw), 0,
@@ -6496,6 +6497,9 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
                                                true : false;
                                }
 
+                               vdec_set_profile_level(vdec, p_H264_Dpb->mSPS.profile_idc,
+                                       p_H264_Dpb->mSPS.level_idc);
+
                                if (!field_pic_flag && (((p_H264_Dpb->mSPS.profile_idc == BASELINE) &&
                                        (p_H264_Dpb->reorder_pic_num < 2)) ||
                                        (((unsigned long)(hw->vh264_amstream_dec_info
index 48dc24988d820ac4bf259c5c2be79c77e9789e12..4113c661ef88103eef01f87e36cae716664fdbd0 100644 (file)
@@ -332,6 +332,8 @@ struct vdec_mpeg12_hw_s {
        u32 kpi_first_i_decoded;
        int sidebind_type;
        int sidebind_channel_id;
+       u32 profile_idc;
+       u32 level_idc;
 };
 static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw);
 static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw);
@@ -1942,6 +1944,17 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
                index = spec_to_index(hw, READ_VREG(REC_CANVAS_ADDR));
                seqinfo = READ_VREG(MREG_SEQ_INFO);
 
+               if (((seqinfo >> 8) & 0xff) &&
+                       ((seqinfo >> 12 & 0x7) != hw->profile_idc ||
+                       (seqinfo >> 8 & 0xf) != hw->level_idc)) {
+                       hw->profile_idc = seqinfo >> 12 & 0x7;
+                       hw->level_idc = seqinfo >> 8 & 0xf;
+                       vdec_set_profile_level(vdec, hw->profile_idc, hw->level_idc);
+                       debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+                               "profile_idc: %d  level_idc: %d\n",
+                               hw->profile_idc, hw->level_idc);
+               }
+
                if ((info & PICINFO_PROG) == 0 &&
                        (info & FRAME_PICTURE_MASK) != FRAME_PICTURE) {
                        hw->first_i_frame_ready = 1; /* for field struct case*/
index ad76deee95911517f7e6ba15cda926c27b610507..601d61082bd33911b44040ab901f787f010ca8a8 100644 (file)
@@ -81,6 +81,7 @@
 #define MP4_NOT_CODED_CNT   AV_SCRATCH_A
 #define MP4_VOP_TIME_INC    AV_SCRATCH_B
 #define MP4_OFFSET_REG      AV_SCRATCH_C
+#define MP4_VOS_INFO        AV_SCRATCH_D
 #define MP4_SYS_RATE        AV_SCRATCH_E
 #define MEM_OFFSET_REG      AV_SCRATCH_F
 #define MP4_PIC_INFO        AV_SCRATCH_H
@@ -328,6 +329,8 @@ struct vdec_mpeg4_hw_s {
        unsigned int b_decoded_frames;
        unsigned int b_lost_frames;
        unsigned int b_concealed_frames;
+       u32 profile_idc;
+       u32 level_idc;
 };
 static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw);
 static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw);
@@ -1040,7 +1043,7 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq)
        u32 pts, offset = 0;
        u64 pts_us64 = 0;
        u32 frame_size, dec_w, dec_h;
-       u32 time_increment_resolution, fixed_vop_rate, vop_time_inc;
+       u32 time_increment_resolution, fixed_vop_rate, vop_time_inc, vos_info;
        u32 repeat_cnt, duration = 3200;
        struct pic_info_t *dec_pic, *disp_pic;
        struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)(vdec->private);
@@ -1143,6 +1146,17 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq)
                picture_type = (reg >> 3) & 7;
                repeat_cnt = READ_VREG(MP4_NOT_CODED_CNT);
                vop_time_inc = READ_VREG(MP4_VOP_TIME_INC);
+               vos_info = READ_VREG(MP4_VOS_INFO);
+               if ((vos_info & 0xff) &&
+                       (((vos_info >> 4) & 0xf) != hw->profile_idc ||
+                       (vos_info & 0xf) != hw->level_idc)) {
+                       hw->profile_idc = vos_info >> 4 & 0xf;
+                       hw->level_idc = vos_info & 0xf;
+                       vdec_set_profile_level(vdec, hw->profile_idc, hw->level_idc);
+                       mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+                               "profile_idc: %d  level_idc: %d\n",
+                               hw->profile_idc, hw->level_idc);
+               }
 
                index = spec_to_index(hw, READ_VREG(REC_CANVAS_ADDR));
                if (index < 0) {
index df1048074bb554905e5ec709531687e5900e4839..42d7c7fe90250ff5d1c49ff1f58331a7451cbe3d 100644 (file)
@@ -4562,6 +4562,15 @@ void vdec_reset_userdata_fifo(struct vdec_s *vdec, int bInit)
 }
 EXPORT_SYMBOL(vdec_reset_userdata_fifo);
 
+void vdec_set_profile_level(struct vdec_s *vdec, u32 profile_idc, u32 level_idc)
+{
+       if (vdec) {
+               vdec->profile_idc = profile_idc;
+               vdec->level_idc = level_idc;
+       }
+}
+EXPORT_SYMBOL(vdec_set_profile_level);
+
 static int dump_mode;
 static ssize_t dump_risc_mem_store(struct class *class,
                struct class_attribute *attr,
@@ -4851,7 +4860,272 @@ static ssize_t dump_fps_show(struct class *class,
        return pbuf - buf;
 }
 
+static char * parser_h264_profile(char *pbuf, struct vdec_s *vdec)
+{
+       switch (vdec->profile_idc) {
+               case 66:
+                       pbuf += sprintf(pbuf, "%d: Baseline Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 77:
+                       pbuf += sprintf(pbuf, "%d: Main Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 88:
+                       pbuf += sprintf(pbuf, "%d: Extended Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 100:
+                       pbuf += sprintf(pbuf, "%d: High Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 110:
+                       pbuf += sprintf(pbuf, "%d: High 10 Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               default:
+                       pbuf += sprintf(pbuf, "%d: Not Support Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+       }
+
+       return pbuf;
+}
+
+static char * parser_mpeg2_profile(char *pbuf, struct vdec_s *vdec)
+{
+       switch (vdec->profile_idc) {
+               case 5:
+                       pbuf += sprintf(pbuf, "%d: Simple Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 4:
+                       pbuf += sprintf(pbuf, "%d: Main Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 3:
+                       pbuf += sprintf(pbuf, "%d: SNR Scalable Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 2:
+                       pbuf += sprintf(pbuf, "%d: Airspace Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 1:
+                       pbuf += sprintf(pbuf, "%d: High Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               default:
+                       pbuf += sprintf(pbuf, "%d: Not Support Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+       }
+       return pbuf;
+}
+
+static char * parser_mpeg4_profile(char *pbuf, struct vdec_s *vdec)
+{
+       switch (vdec->profile_idc) {
+               case 0:
+                       pbuf += sprintf(pbuf, "%d: Simple Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 1:
+                       pbuf += sprintf(pbuf, "%d: Simple Scalable Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 2:
+                       pbuf += sprintf(pbuf, "%d: Core Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 3:
+                       pbuf += sprintf(pbuf, "%d: Main Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 4:
+                       pbuf += sprintf(pbuf, "%d: N-bit Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 5:
+                       pbuf += sprintf(pbuf, "%d: Scalable Texture Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 6:
+                       if (vdec->profile_idc == 1 || vdec->profile_idc == 2)
+                               pbuf += sprintf(pbuf, "%d: Simple Face Animation Profile(%u)\n",
+                               vdec->id, vdec->profile_idc);
+                       else
+                               pbuf += sprintf(pbuf, "%d: Simple FBA Profile(%u)\n",
+                               vdec->id, vdec->profile_idc);
+                       break;
+               case 7:
+                       pbuf += sprintf(pbuf, "%d: Basic Animated Texture Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 8:
+                       pbuf += sprintf(pbuf, "%d: Hybrid Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 9:
+                       pbuf += sprintf(pbuf, "%d: Advanced Real Time Simple Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 10:
+                       pbuf += sprintf(pbuf, "%d: Core Scalable Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 11:
+                       pbuf += sprintf(pbuf, "%d: Advanced Coding Efficiency Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 12:
+                       pbuf += sprintf(pbuf, "%d: Advanced Core Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 13:
+                       pbuf += sprintf(pbuf, "%d: Advanced Scalable Texture Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               case 14:
+               case 15:
+                       pbuf += sprintf(pbuf, "%d: Advanced Simple Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+               default:
+                       pbuf += sprintf(pbuf, "%d: Not Support Profile(%u)\n",
+                       vdec->id, vdec->profile_idc);
+                       break;
+       }
+
+       return pbuf;
+}
+
+static ssize_t profile_idc_show(struct class *class, struct class_attribute *attr,
+                       char *buf)
+{
+       struct vdec_core_s *core = vdec_core;
+       char *pbuf = buf;
+       unsigned long flags = vdec_core_lock(vdec_core);
 
+       if (list_empty(&core->connected_vdec_list))
+               pbuf += sprintf(pbuf, "connected vdec list empty\n");
+       else {
+               struct vdec_s *vdec;
+               list_for_each_entry(vdec, &core->connected_vdec_list, list) {
+                       if (vdec->format == 0) {
+                               pbuf = parser_mpeg2_profile(pbuf, vdec);
+                       } else if (vdec->format == 1) {
+                               pbuf = parser_mpeg4_profile(pbuf, vdec);
+                       } else if (vdec->format == 2) {
+                               pbuf = parser_h264_profile(pbuf, vdec);
+                       } else {
+                               pbuf += sprintf(pbuf,
+                               "%d: Not Support\n", vdec->id);
+                       }
+               }
+       }
+
+       vdec_core_unlock(vdec_core, flags);
+       return pbuf - buf;
+}
+
+static char * parser_h264_level(char *pbuf, struct vdec_s *vdec)
+{
+
+       pbuf += sprintf(pbuf, "%d: Level %d.%d(%u)\n",
+                       vdec->id, vdec->level_idc/10, vdec->level_idc%10, vdec->level_idc);
+
+       return pbuf;
+}
+
+static char * parser_mpeg2_level(char *pbuf, struct vdec_s *vdec)
+{
+       switch (vdec->level_idc) {
+               case 10:
+                       pbuf += sprintf(pbuf, "%d: Low Level(%u)\n",
+                       vdec->id, vdec->level_idc);
+                       break;
+               case 8:
+                       pbuf += sprintf(pbuf, "%d: Main Level(%u)\n",
+                       vdec->id, vdec->level_idc);
+                       break;
+               case 6:
+                       pbuf += sprintf(pbuf, "%d: High 1440 Level(%u)\n",
+                       vdec->id, vdec->level_idc);
+                       break;
+               case 4:
+                       pbuf += sprintf(pbuf, "%d: High Level(%u)\n",
+                       vdec->id, vdec->level_idc);
+                       break;
+               default:
+                       pbuf += sprintf(pbuf, "%d: Not Support Level(%u)\n",
+                       vdec->id, vdec->level_idc);
+                       break;
+       }
+
+       return pbuf;
+}
+
+static char * parser_mpeg4_level(char *pbuf, struct vdec_s *vdec)
+{
+       switch (vdec->level_idc) {
+               case 1:
+                       pbuf += sprintf(pbuf, "%d: Level 1(%u)\n",
+                       vdec->id, vdec->level_idc);
+                       break;
+               case 2:
+                       pbuf += sprintf(pbuf, "%d: Level 2(%u)\n",
+                       vdec->id, vdec->level_idc);
+                       break;
+               case 3:
+                       pbuf += sprintf(pbuf, "%d: Level 3(%u)\n",
+                       vdec->id, vdec->level_idc);
+                       break;
+               case 4:
+                       pbuf += sprintf(pbuf, "%d: Level 4(%u)\n",
+                       vdec->id, vdec->level_idc);
+                       break;
+               case 5:
+                       pbuf += sprintf(pbuf, "%d: Level 5(%u)\n",
+                       vdec->id, vdec->level_idc);
+                       break;
+               default:
+                       pbuf += sprintf(pbuf, "%d: Not Support Level(%u)\n",
+                       vdec->id, vdec->level_idc);
+                       break;
+       }
+
+       return pbuf;
+}
+
+static ssize_t level_idc_show(struct class *class, struct class_attribute *attr,
+                       char *buf)
+{
+       struct vdec_core_s *core = vdec_core;
+       char *pbuf = buf;
+       unsigned long flags = vdec_core_lock(vdec_core);
+
+       if (list_empty(&core->connected_vdec_list))
+               pbuf += sprintf(pbuf, "connected vdec list empty\n");
+       else {
+               struct vdec_s *vdec;
+               list_for_each_entry(vdec, &core->connected_vdec_list, list) {
+                       if (vdec->format == 0) {
+                               pbuf = parser_mpeg2_level(pbuf, vdec);
+                       } else if (vdec->format == 1) {
+                               pbuf = parser_mpeg4_level(pbuf, vdec);
+                       } else if (vdec->format == 2) {
+                               pbuf = parser_h264_level(pbuf, vdec);
+                       } else {
+                               pbuf += sprintf(pbuf,
+                               "%d: Not Support\n", vdec->id);
+                       }
+               }
+       }
+
+       vdec_core_unlock(vdec_core, flags);
+       return pbuf - buf;
+}
 
 static struct class_attribute vdec_class_attrs[] = {
        __ATTR_RO(amrisc_regs),
@@ -4881,6 +5155,8 @@ static struct class_attribute vdec_class_attrs[] = {
        frame_check_show, frame_check_store),
 #endif
        __ATTR_RO(dump_fps),
+       __ATTR_RO(profile_idc),
+       __ATTR_RO(level_idc),
        __ATTR(vfm_path, S_IRUGO | S_IWUSR | S_IWGRP,
        show_vdec_vfm_path, store_vdec_vfm_path),
        __ATTR_NULL
index c4633faad48277feaa7174bc3a301abdef7fb829..b11888ea2642f4138a9d75a35bed802811f011d7 100644 (file)
@@ -283,6 +283,8 @@ struct vdec_s {
        u32 hdr10p_data_size;
        char hdr10p_data_buf[PAGE_SIZE];
        bool hdr10p_data_valid;
+       u32 profile_idc;
+       u32 level_idc;
 };
 
 /* common decoder vframe provider name to use default vfm path */
@@ -482,4 +484,5 @@ extern u32 timestamp_avsync_counter_get(void);
 
 int vdec_resource_checking(struct vdec_s *vdec);
 
+void vdec_set_profile_level(struct vdec_s *vdec, u32 profile_idc, u32 level_idc);
 #endif                         /* VDEC_H */
index 06854b3a57734d4903da71b3d788d30c73683627..065d8ba602c893191408c5a8f7c49efd686717d5 100755 (executable)
Binary files a/firmware/video_ucode.bin and b/firmware/video_ucode.bin differ