ref: 7760836ddbcc9250ccb717d13918a37e3722604a
dir: /hantest.c/
#include <u.h> #include <libc.h> #include "g1regs.h" enum { DecodeH264, Baseline = 66, High = 100, }; typedef struct VPUctx VPUctx; #define Default_4x4_Intra {6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42} #define Default_4x4_Inter {10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34} #define Default_8x8_Intra \ {6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23, \ 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, \ 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, \ 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42} #define Default_8x8_Inter \ {9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, \ 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, \ 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, \ 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35} static u8int defsl4x4[6][16] = { Default_4x4_Intra, /* Sl_4x4_Intra_Y */ Default_4x4_Intra, /* Sl_4x4_Intra_Cb */ Default_4x4_Intra, /* Sl_4x4_Intra_Cr */ Default_4x4_Inter, /* Sl_4x4_Inter_Y */ Default_4x4_Inter, /* Sl_4x4_Inter_Cb */ Default_4x4_Inter, /* Sl_4x4_Inter_Cr */ }; static u8int defs8x8[6][64] = { Default_8x8_Intra, /* Sl_8x8_Intra_Y */ Default_8x8_Inter, /* Sl_8x8_Inter_Y */ Default_8x8_Intra, /* Sl_8x8_Intra_Cb */ Default_8x8_Inter, /* Sl_8x8_Inter_Cb */ Default_8x8_Intra, /* Sl_8x8_Intra_Cr */ Default_8x8_Inter, /* Sl_8x8_Inter_Cr */ }; struct VPUctx { int process; int slen; union { /* h.264 decoding */ struct { struct { u16int pic_height_in_map_units_minus1; u16int pic_width_in_mbs_minus1; u8int chroma_format_idc; u8int frame_mbs_only_flag; u8int log2_max_frame_num_minus4; u8int max_num_ref_frames; u8int nal_ref_idc; u8int profile_idc; u8int direct_8x8_inference_flag; u8int mb_adaptive_frame_field_flag; u8int seq_scaling_matrix_present_flag; }sps; struct { s8int chroma_qp_index_offset; s8int pic_init_qp_minus26; s8int second_chroma_qp_index_offset; u8int weighted_bipred_idc; u8int pic_parameter_set_id; u8int num_ref_idx_l0_default_active_minus1; u8int num_ref_idx_l1_default_active_minus1; u8int constrained_intra_pred_flag; u8int deblocking_filter_control_present_flag; u8int entropy_coding_mode_flag; u8int pic_scaling_matrix_present_flag; u8int redundant_pic_cnt_present_flag; u8int transform_8x8_mode_flag; u8int weighted_pred_flag; }pps; struct { u16int frame_num; u16int idr_pic_id; u32int size_dec_ref_pic_marking; u8int size_pic_order_cnt_lsb; u8int size_delta_pic_order_cnt_bottom; u8int size_delta_pic_order_cnt0; u8int size_delta_pic_order_cnt1; u8int nal_unit_type; u8int field_pic_flag; u8int bottom_field_flag; }sh; }; }; }; static u32int *g1, *g2; static void g1load(VPUctx *c) { g1[2] = 16 << SW_DEC_MAX_BURST | /* AXI burst length = 16 */ 1 << SW_DEC_STRSWAP32_E | 1 << SW_DEC_STRENDIAN_E | /* 64bit / little endian */ 1 << SW_DEC_INSWAP32_E | 1 << SW_DEC_OUTSWAP32_E | 1 << SW_DEC_IN_ENDIAN | 1 << SW_DEC_OUT_ENDIAN | 1 << SW_DEC_TIMEOUT_E; /* timeout interrupt */ g1[3] = (c->sps.frame_mbs_only_flag == 0 && (c->sps.mb_adaptive_frame_field_flag || c->sh.field_pic_flag)) << SW_PIC_INTERLACE_E | (c->sps.frame_mbs_only_flag == 0 && c->sh.field_pic_flag) << SW_PIC_FIELDMODE_E | (c->sps.frame_mbs_only_flag == 0 && c->sh.bottom_field_flag == 0) << SW_PIC_TOPFIELD_E | (c->sps.profile_idc > Baseline && c->sps.nal_ref_idc != 0) << SW_WRITE_MVS_E | c->sps.mb_adaptive_frame_field_flag << SW_SEQ_MBAFF_E | (c->sps.profile_idc > Baseline) << SW_PICORD_COUNT_E | 0xff << SW_DEC_AXI_WR_ID; g1[4] = (c->sps.pic_width_in_mbs_minus1 + 1) << SW_PIC_MB_WIDTH | (c->sps.pic_height_in_map_units_minus1 + 1) << SW_PIC_MB_HEIGHT_P | c->sps.max_num_ref_frames << SW_REF_FRAMES; g1[5] = 0 << SW_STRM_START_BIT | c->pps.pic_scaling_matrix_present_flag << SW_SCALING_LIST_E | (c->pps.chroma_qp_index_offset & ((1<<5)-1)) << SW_CH_QP_OFFSET | (c->pps.second_chroma_qp_index_offset & ((1<<5)-1)) << SW_CH_QP_OFFSET2 | (c->sps.frame_mbs_only_flag == 0) << SW_FIELDPIC_FLAG_E; g1[6] = 1 << SW_START_CODE_E | (c->pps.pic_init_qp_minus26 + 26) << SW_INIT_QP | c->slen << SW_STREAM_LEN; g1[7] = c->pps.entropy_coding_mode_flag << SW_CABAC_E | (c->sps.chroma_format_idc == 0 && c->sps.profile_idc >= High) << SW_BLACKWHITE_E | c->sps.direct_8x8_inference_flag << SW_DIR_8X8_INFER_E | c->pps.weighted_pred_flag << SW_WEIGHT_PRED_E | c->pps.weighted_bipred_idc << SW_WEIGHT_BIPR_IDC | (c->sps.log2_max_frame_num_minus4 + 4) << SW_FRAMENUM_LEN | c->sh.frame_num << SW_FRAMENUM; g1[8] = c->pps.constrained_intra_pred_flag << SW_CONST_INTRA_E | c->pps.deblocking_filter_control_present_flag << SW_FILT_CTRL_PRES | c->pps.redundant_pic_cnt_present_flag << SW_RDPIC_CNT_PRES | c->pps.transform_8x8_mode_flag << SW_8X8TRANS_FLAG_E | (c->sps.nal_ref_idc != 0 ? c->sh.size_dec_ref_pic_marking : 0) << SW_REFPIC_MK_LEN | (c->sh.nal_unit_type == 5) << SW_IDR_PIC_E | c->sh.idr_pic_id << SW_IDR_PIC_ID; g1[9] = c->pps.pic_parameter_set_id << SW_PPS_ID | (c->pps.num_ref_idx_l1_default_active_minus1 + 1) << SW_REFIDX1_ACTIVE | (c->pps.num_ref_idx_l0_default_active_minus1 + 1) << SW_REFIDX0_ACTIVE | (c->sh.size_pic_order_cnt_lsb + c->sh.size_delta_pic_order_cnt_bottom + c->sh.size_delta_pic_order_cnt0 + c->sh.size_delta_pic_order_cnt1) << SW_POC_LENGTH; /* fixed 6-tap filter values (1 -5 20) */ g1[49] = 1 << SW_PRED_BC_TAP_0_0 | (-5 & ((1<<(SW_PRED_BC_TAP_0_0-SW_PRED_BC_TAP_0_1))-1)) << SW_PRED_BC_TAP_0_1 | 20 << SW_PRED_BC_TAP_0_2; } static int parsecmd(VPUctx *c, char *s) { char *a[4]; int n, x; if((n = tokenize(s, a, nelem(a))) < 2) return -1; #define value(name, field, min, max) \ if(strcmp(a[1], name) == 0){ \ if(x < (min) || x > (max)){ \ werrstr("%s: out of range [%d, %d]", a[1], (min), (max)); \ return -1; \ } \ field = x; \ return 0; \ } if(strcmp(a[0], "decode") == 0){ if(n == 2 && strcmp(a[1], "h.264") == 0){ c->process = DecodeH264; return 0; } }else if(c->process == DecodeH264 && n == 3){ x = atoi(a[2]); if(strcmp(a[0], "sps") == 0){ value("pic_height_in_map_units_minus1", c->sps.pic_height_in_map_units_minus1, 0, 0xff); value("pic_width_in_mbs_minus1", c->sps.pic_width_in_mbs_minus1, 0, 0xff); value("chroma_format_idc", c->sps.chroma_format_idc, 0, 3); value("log2_max_frame_num_minus4", c->sps.log2_max_frame_num_minus4, 0, 12); value("max_num_ref_frames", c->sps.max_num_ref_frames, 0, 16); value("nal_ref_idc", c->sps.nal_ref_idc, 0, 3); value("profile_idc", c->sps.profile_idc, 0, 0xff); value("direct_8x8_inference_flag", c->sps.direct_8x8_inference_flag, 0, 1); value("frame_mbs_only_flag", c->sps.frame_mbs_only_flag, 0, 1); value("mb_adaptive_frame_field_flag", c->sps.mb_adaptive_frame_field_flag, 0, 1); value("seq_scaling_matrix_present_flag", c->sps.seq_scaling_matrix_present_flag, 0, 1); }else if(strcmp(a[0], "pps") == 0){ value("chroma_qp_index_offset", c->pps.chroma_qp_index_offset, -12, 12); value("pic_init_qp_minus26", c->pps.pic_init_qp_minus26, -26, 25); value("second_chroma_qp_index_offset", c->pps.second_chroma_qp_index_offset, -12, 12); value("weighted_bipred_idc", c->pps.weighted_bipred_idc, 0, 2); value("pic_parameter_set_id", c->pps.pic_parameter_set_id, 0, 0xff); value("num_ref_idx_l0_default_active_minus1", c->pps.num_ref_idx_l0_default_active_minus1, 0, 31); value("num_ref_idx_l1_default_active_minus1", c->pps.num_ref_idx_l1_default_active_minus1, 0, 31); value("constrained_intra_pred_flag", c->pps.constrained_intra_pred_flag, 0, 1); value("deblocking_filter_control_present_flag", c->pps.deblocking_filter_control_present_flag, 0, 1); value("entropy_coding_mode_flag", c->pps.entropy_coding_mode_flag, 0, 1); value("pic_scaling_matrix_present_flag", c->pps.pic_scaling_matrix_present_flag, 0, 1); value("redundant_pic_cnt_present_flag", c->pps.redundant_pic_cnt_present_flag, 0, 1); value("transform_8x8_mode_flag", c->pps.transform_8x8_mode_flag, 0, 1); value("weighted_pred_flag", c->pps.weighted_pred_flag, 0, 1); }else if(strcmp(a[0], "sh") == 0){ value("frame_num", c->sh.frame_num, 0, 0xffff); value("idr_pic_id", c->sh.idr_pic_id, 0, 0xffff); value("nal_unit_type", c->sh.nal_unit_type, 0, 0xff); value("size_dec_ref_pic_marking", c->sh.size_dec_ref_pic_marking, 0, 0x1ffff); value("size_pic_order_cnt_lsb", c->sh.size_pic_order_cnt_lsb, 0, 0xff); value("size_delta_pic_order_cnt_bottom", c->sh.size_delta_pic_order_cnt_bottom, 0, 0xff); value("size_delta_pic_order_cnt0", c->sh.size_delta_pic_order_cnt0, 0, 0xff); value("size_delta_pic_order_cnt1", c->sh.size_delta_pic_order_cnt1, 0, 0xff); value("field_pic_flag", c->sh.field_pic_flag, 0, 1); value("bottom_field_flag", c->sh.bottom_field_flag, 0, 1); } } #undef value return -1; } void main(int argc, char **argv) { int i; u32int x; ARGBEGIN{ }ARGEND if((g1 = segattach(0, "vpu_hantro_g1", 0, 0x200)) == (void*)-1) sysfatal("no G1"); /* FIXME will use polling for now */ g1[1] = SW_DEC_IRQ_DIS; /* run */ g1[2] |= SW_DEC_CLK_GATE_E; x = (g1[1] |= SW_DEC_E); for(i = 0; i < 100; i++){ sleep(1); if(g1[1] != x){ print("irq changed from 0x%ux to 0x%ux\n", x, g1[1]); break; } } segdetach(g1); exits(nil); }