| /* Any workload management goes in this file */ |
| |
| #include "viddec_fw_debug.h" |
| #include "vc1.h" |
| #include "vc1parse.h" |
| #include "viddec_fw_workload.h" |
| #include <auto_eas/gen4_mfd.h> |
| #include "viddec_pm_utils_bstream.h" |
| |
| /* this function returns workload frame types corresponding to VC1 PTYPES (frame types) |
| * VC1 frame types: can be found in vc1parse_common_defs.h |
| * workload frame types are in viddec_workload.h |
| */ |
| static inline uint32_t vc1_populate_frame_type(uint32_t vc1_frame_type) |
| { |
| uint32_t viddec_frame_type; |
| |
| switch (vc1_frame_type) |
| { |
| case VC1_I_FRAME: |
| viddec_frame_type = VIDDEC_FRAME_TYPE_I; |
| break; |
| case VC1_P_FRAME: |
| viddec_frame_type = VIDDEC_FRAME_TYPE_P; |
| break; |
| case VC1_B_FRAME: |
| viddec_frame_type = VIDDEC_FRAME_TYPE_B; |
| break; |
| case VC1_BI_FRAME: |
| viddec_frame_type = VIDDEC_FRAME_TYPE_BI; |
| break; |
| case VC1_SKIPPED_FRAME : |
| viddec_frame_type = VIDDEC_FRAME_TYPE_SKIP; |
| break; |
| default: |
| viddec_frame_type = VIDDEC_FRAME_TYPE_INVALID; |
| break; |
| } // switch on vc1 frame type |
| |
| return(viddec_frame_type); |
| } // vc1_populate_frame_type |
| |
| static void translate_parser_info_to_frame_attributes(void *parent, vc1_viddec_parser_t *parser) |
| { |
| viddec_workload_t *wl = viddec_pm_get_header( parent ); |
| viddec_frame_attributes_t *attrs = &wl->attrs; |
| vc1_Info *info = &parser->info; |
| unsigned i; |
| |
| /* typical sequence layer and entry_point data */ |
| attrs->cont_size.height = info->metadata.height * 2 + 2; |
| attrs->cont_size.width = info->metadata.width * 2 + 2; |
| |
| /* frame type */ |
| /* we can have two fileds with different types for field interlace coding mode */ |
| if (info->picLayerHeader.FCM == VC1_FCM_FIELD_INTERLACE) { |
| attrs->frame_type = vc1_populate_frame_type(info->picLayerHeader.PTypeField1); |
| attrs->bottom_field_type = vc1_populate_frame_type(info->picLayerHeader.PTypeField2); |
| } else { |
| attrs->frame_type = vc1_populate_frame_type(info->picLayerHeader.PTYPE); |
| attrs->bottom_field_type = VIDDEC_FRAME_TYPE_INVALID; //unknown |
| } |
| |
| /* frame counter */ |
| attrs->vc1.tfcntr = info->picLayerHeader.TFCNTR; |
| |
| /* TFF, repeat frame, field */ |
| attrs->vc1.tff = info->picLayerHeader.TFF; |
| attrs->vc1.rptfrm = info->picLayerHeader.RPTFRM; |
| attrs->vc1.rff = info->picLayerHeader.RFF; |
| |
| /* PAN Scan */ |
| attrs->vc1.ps_present = info->picLayerHeader.PS_PRESENT; |
| attrs->vc1.num_of_pan_scan_windows = info->picLayerHeader.number_of_pan_scan_window; |
| for (i=0; i<attrs->vc1.num_of_pan_scan_windows; i++) { |
| attrs->vc1.pan_scan_window[i].hoffset = info->picLayerHeader.PAN_SCAN_WINDOW[i].hoffset; |
| attrs->vc1.pan_scan_window[i].voffset = info->picLayerHeader.PAN_SCAN_WINDOW[i].voffset; |
| attrs->vc1.pan_scan_window[i].width = info->picLayerHeader.PAN_SCAN_WINDOW[i].width; |
| attrs->vc1.pan_scan_window[i].height = info->picLayerHeader.PAN_SCAN_WINDOW[i].height; |
| } //end for i |
| |
| return; |
| } // translate_parser_info_to_frame_attributes |
| |
| /* sends VIDDEC_WORKLOAD_VC1_PAST_FRAME item */ |
| static inline void vc1_send_past_ref_items(void *parent) |
| { |
| viddec_workload_item_t wi; |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_PAST_FRAME; |
| wi.ref_frame.reference_id = 0; |
| wi.ref_frame.luma_phys_addr = 0; |
| wi.ref_frame.chroma_phys_addr = 0; |
| viddec_pm_append_workitem( parent, &wi, false ); |
| return; |
| } |
| |
| /* send future frame item */ |
| static inline void vc1_send_future_ref_items(void *parent) |
| { |
| viddec_workload_item_t wi; |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_FUTURE_FRAME; |
| wi.ref_frame.reference_id = 0; |
| wi.ref_frame.luma_phys_addr = 0; |
| wi.ref_frame.chroma_phys_addr = 0; |
| viddec_pm_append_workitem( parent, &wi, false ); |
| return; |
| } |
| |
| /* send reorder frame item to host |
| * future frame gets push to past */ |
| static inline void send_reorder_ref_items(void *parent) |
| { |
| viddec_workload_item_t wi; |
| wi.vwi_type = VIDDEC_WORKLOAD_REFERENCE_FRAME_REORDER; |
| wi.ref_reorder.ref_table_offset = 0; |
| wi.ref_reorder.ref_reorder_00010203 = 0x01010203; //put reference frame index 1 as reference index 0 |
| wi.ref_reorder.ref_reorder_04050607 = 0x04050607; // index 4,5,6,7 stay the same |
| viddec_pm_append_workitem( parent, &wi, false ); |
| return; |
| } // send_reorder_ref_items |
| |
| |
| /* sends VIDDEC_WORKLOAD_VC1_PAST_FRAME item */ |
| static inline void vc1_send_ref_fcm_items(void *parent, uint32_t past_fcm, uint32_t future_fcm) |
| { |
| viddec_workload_item_t wi; |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_REGS_REF_FRAME_TYPE; |
| wi.vwi_payload[0]= 0; |
| wi.vwi_payload[1]= past_fcm; |
| wi.vwi_payload[2]= future_fcm; |
| viddec_pm_append_workitem( parent, &wi, false ); |
| return; |
| } |
| |
| |
| |
| /* send reorder frame item to host |
| * future frame gets push to past */ |
| static inline void send_SEQ_ENTRY_registers(void *parent, vc1_viddec_parser_t *parser) |
| { |
| uint32_t stream_format1 = 0; |
| uint32_t stream_format2 = 0; |
| uint32_t entrypoint1 = 0; |
| viddec_workload_item_t wi; |
| |
| vc1_metadata_t *md = &(parser->info.metadata); |
| |
| |
| |
| BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_1, PROFILE, stream_format1, md->PROFILE); |
| BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_1, LEVEL, stream_format1, md->LEVEL); |
| BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_1, CHROMAFORMAT, stream_format1, md->CHROMAFORMAT); |
| BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_1, FRMRTQ, stream_format1, md->FRMRTQ); |
| BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_1, BITRTQ, stream_format1, md->BITRTQ); |
| BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_1, POSTPRO, stream_format1, md->POSTPROCFLAG); |
| |
| |
| BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_2, PULLDOWN, stream_format2, md->PULLDOWN); |
| BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_2, INTERLACE, stream_format2, md->INTERLACE); |
| BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_2, TFCNTRFLAG, stream_format2, md->TFCNTRFLAG); |
| BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_2, FINTERPFLAG, stream_format2, md->FINTERPFLAG); |
| BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_2, PSF, stream_format2, md->PSF); |
| |
| |
| BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, BROKEN_LINK, entrypoint1, md->BROKEN_LINK); |
| BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, CLOSED_ENTRY, entrypoint1, md->CLOSED_ENTRY); |
| BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, PANSCAN_FLAG, entrypoint1, md->PANSCAN_FLAG); |
| BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, REFDIST_FLAG, entrypoint1, md->REFDIST_FLAG); |
| BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, LOOPFILTER, entrypoint1, md->LOOPFILTER); |
| BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, FASTUVMC, entrypoint1, md->FASTUVMC); |
| BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, EXTENDED_MV, entrypoint1, md->EXTENDED_MV); |
| BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, DQUANT, entrypoint1, md->DQUANT); |
| BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, VS_TRANSFORM, entrypoint1, md->VSTRANSFORM); |
| BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, OVERLAP, entrypoint1, md->OVERLAP); |
| BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, QUANTIZER, entrypoint1, md->QUANTIZER); |
| BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, EXTENDED_DMV, entrypoint1, md->EXTENDED_DMV); |
| |
| |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_REGS_SEQ_ENTRY; |
| |
| |
| wi.vwi_payload[0] = stream_format1; |
| wi.vwi_payload[1] = stream_format2; |
| wi.vwi_payload[2] = entrypoint1; |
| |
| viddec_pm_append_workitem( parent, &wi, false ); |
| return; |
| } // send_reorder_ref_items |
| |
| |
| /* send reorder frame item to host |
| * future frame gets push to past */ |
| static inline void send_SIZE_AND_AP_RANGEMAP_registers(void *parent, vc1_viddec_parser_t *parser) |
| { |
| uint32_t coded_size = 0; |
| uint32_t ap_range_map = 0; |
| |
| viddec_workload_item_t wi; |
| |
| vc1_metadata_t *md = &(parser->info.metadata); |
| |
| |
| BF_WRITE(VC1_0_SEQPIC_CODED_SIZE, WIDTH, coded_size, md->width); |
| BF_WRITE(VC1_0_SEQPIC_CODED_SIZE, HEIGHT, coded_size, md->height); |
| |
| |
| /* if range reduction is indicated at seq. layer, populate range reduction registers for the frame*/ |
| if (VC1_PROFILE_ADVANCED == md->PROFILE) |
| { |
| |
| |
| BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_Y_FLAG, ap_range_map, md->RANGE_MAPY_FLAG); |
| BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_Y, ap_range_map, md->RANGE_MAPY); |
| BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_UV_FLAG, ap_range_map, md->RANGE_MAPUV_FLAG); |
| BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_UV, ap_range_map, md->RANGE_MAPUV); |
| |
| |
| |
| |
| } |
| else |
| { |
| ap_range_map = 0; |
| } |
| |
| |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_REGS_SIZE_AND_AP_RANGEMAP; |
| |
| |
| wi.vwi_payload[0] = 0; |
| wi.vwi_payload[1] = coded_size; |
| wi.vwi_payload[2] = ap_range_map; |
| |
| viddec_pm_append_workitem( parent, &wi, false ); |
| return; |
| } // send_reorder_ref_items |
| |
| |
| |
| /* send reorder frame item to host |
| * future frame gets push to past */ |
| static inline void send_SLICE_FRAME_TYPE_INFO_registers(void *parent, vc1_viddec_parser_t *parser) |
| { |
| uint32_t alt_frame_type = 0; |
| uint32_t frame_type = 0; |
| |
| vc1_PictureLayerHeader *pic = &(parser->info.picLayerHeader); |
| viddec_workload_item_t wi; |
| |
| vc1_metadata_t *md = &(parser->info.metadata); |
| |
| |
| BF_WRITE(VC1_0_SEQPIC_FRAME_TYPE, FCM, frame_type, pic->FCM); |
| BF_WRITE(VC1_0_SEQPIC_FRAME_TYPE, PTYPE, frame_type, pic->PTYPE); |
| |
| alt_frame_type = frame_type; |
| |
| if (VC1_PROFILE_ADVANCED == md->PROFILE) |
| { |
| if ( (VC1_P_FRAME == pic->PTYPE)||(VC1_B_FRAME == pic->PTYPE) ) |
| { |
| BF_WRITE(VC1_0_SEQPIC_ALT_FRAME_TYPE, PQUANT, alt_frame_type, pic->PQUANT); |
| } |
| } |
| else |
| { |
| if ( VC1_SKIPPED_FRAME== pic->PTYPE) |
| { |
| BF_WRITE(VC1_0_SEQPIC_ALT_FRAME_TYPE, PQUANT, alt_frame_type, 0); |
| } else { |
| BF_WRITE(VC1_0_SEQPIC_ALT_FRAME_TYPE, PQUANT, alt_frame_type, pic->PQUANT); |
| } |
| } |
| |
| |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_REGS_SLICE_FRAME_TYPE_INFO; |
| |
| |
| wi.vwi_payload[0] = 0; |
| wi.vwi_payload[1] = frame_type; |
| wi.vwi_payload[2] = alt_frame_type; |
| |
| viddec_pm_append_workitem( parent, &wi, false ); |
| return; |
| } // send_reorder_ref_items |
| |
| /* send reorder frame item to host |
| * future frame gets push to past */ |
| static inline void send_SLICE_CONTROL_INFO_registers(void *parent, vc1_viddec_parser_t *parser) |
| { |
| uint32_t recon_control = 0; |
| uint32_t mv_control = 0; |
| uint32_t blk_control = 0; |
| |
| vc1_PictureLayerHeader *pic = &(parser->info.picLayerHeader); |
| viddec_workload_item_t wi; |
| |
| int is_previous_ref_rr=0; |
| |
| vc1_metadata_t *md = &(parser->info.metadata); |
| |
| |
| BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, RNDCTRL, recon_control, md->RNDCTRL); |
| BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, UVSAMP, recon_control, pic->UVSAMP); |
| BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, PQUANT, recon_control, pic->PQUANT); |
| BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, HALFQP, recon_control, pic->HALFQP); |
| BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, UNIFORM_QNT, recon_control, pic->UniformQuant); |
| BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, POSTPROC, recon_control, pic->POSTPROC); |
| BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, CONDOVER, recon_control, pic->CONDOVER); |
| BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, PQINDEX_LE8, recon_control, (pic->PQINDEX <= 8)); |
| |
| /* Get the range reduced status of the previous frame */ |
| switch (pic->PTYPE) |
| { |
| case VC1_P_FRAME: |
| { |
| is_previous_ref_rr = parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].rr_frm; |
| break; |
| } |
| case VC1_B_FRAME: |
| { |
| is_previous_ref_rr = parser->ref_frame[VC1_REF_FRAME_T_MINUS_2].rr_frm; |
| break; |
| } |
| default: |
| { |
| break; |
| } |
| } |
| |
| if (pic->RANGEREDFRM) |
| { |
| |
| if (!is_previous_ref_rr) |
| { |
| BF_WRITE(VC1_0_SEQPIC_RECON_CONTROL, RANGE_REF_RED_EN, recon_control, 1); |
| BF_WRITE(VC1_0_SEQPIC_RECON_CONTROL, RANGE_REF_RED_TYPE, recon_control, 1); |
| } |
| } |
| else |
| { |
| /* if current frame is not RR but previous was RR, scale up the reference frame ( RANGE_REF_RED_TYPE = 0) */ |
| if (is_previous_ref_rr) |
| { |
| BF_WRITE(VC1_0_SEQPIC_RECON_CONTROL, RANGE_REF_RED_EN, recon_control, 1); |
| BF_WRITE(VC1_0_SEQPIC_RECON_CONTROL, RANGE_REF_RED_TYPE, recon_control, 0); |
| } |
| } // end for RR upscale |
| |
| |
| |
| |
| |
| BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MVRANGE, mv_control, pic->MVRANGE); |
| if ( pic->MVMODE == VC1_MVMODE_INTENSCOMP) |
| BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MVMODE, mv_control, pic->MVMODE2); |
| else |
| BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MVMODE, mv_control, pic->MVMODE); |
| BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MVTAB, mv_control, pic->MVTAB); |
| BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, DMVRANGE, mv_control, pic->DMVRANGE); |
| BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MV4SWITCH, mv_control, pic->MV4SWITCH); |
| BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MBMODETAB, mv_control, pic->MBMODETAB); |
| BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, NUMREF, mv_control, |
| pic->NUMREF || ((pic->PTYPE == VC1_B_FRAME) && ( pic->FCM == VC1_FCM_FIELD_INTERLACE ) )); |
| BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, REFFIELD, mv_control, pic->REFFIELD); |
| |
| |
| |
| // BLOCK CONTROL REGISTER Offset 0x2C |
| BF_WRITE( VC1_0_SEQPIC_BLOCK_CONTROL, CBPTAB, blk_control, pic->CBPTAB); |
| BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, TTMFB, blk_control, pic->TTMBF); |
| BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, TTFRM, blk_control, pic->TTFRM); |
| BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, MV2BPTAB, blk_control, pic->MV2BPTAB); |
| BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, MV4BPTAB, blk_control, pic->MV4BPTAB); |
| if ((pic->CurrField == 1) && (pic->SLICE_ADDR)) |
| { |
| int mby = md->height * 2 + 2; |
| mby = (mby + 15 ) / 16; |
| pic->SLICE_ADDR -= (mby/2); |
| } |
| BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, INITIAL_MV_Y, blk_control, pic->SLICE_ADDR); |
| BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, BP_RAW_ID2, blk_control, md->bp_raw[0]); |
| BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, BP_RAW_ID1, blk_control, md->bp_raw[1]); |
| BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, BP_RAW_ID0, blk_control, md->bp_raw[2]); |
| |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_REGS_SLICE_CONTROL_INFO; |
| |
| |
| wi.vwi_payload[0] = recon_control; |
| wi.vwi_payload[1] = mv_control; |
| wi.vwi_payload[2] = blk_control; |
| |
| viddec_pm_append_workitem( parent, &wi, false ); |
| return; |
| } // send_reorder_ref_items |
| |
| /* send reorder frame item to host |
| * future frame gets push to past */ |
| static inline void send_SLICE_OTHER_INFO_registers(void *parent, vc1_viddec_parser_t *parser) |
| { |
| uint32_t trans_data = 0; |
| uint32_t vop_dquant = 0; |
| uint32_t ref_bfraction = 0; |
| |
| vc1_PictureLayerHeader *pic = &(parser->info.picLayerHeader); |
| viddec_workload_item_t wi; |
| |
| vc1_metadata_t *md = &(parser->info.metadata); |
| |
| BF_WRITE(VC1_0_SEQPIC_REFERENCE_B_FRACTION, BFRACTION_DEN, ref_bfraction, pic->BFRACTION_DEN); |
| BF_WRITE(VC1_0_SEQPIC_REFERENCE_B_FRACTION, BFRACTION_NUM, ref_bfraction, pic->BFRACTION_NUM); |
| BF_WRITE(VC1_0_SEQPIC_REFERENCE_B_FRACTION, REFDIST, ref_bfraction, md->REFDIST); |
| |
| if (md->DQUANT) |
| { |
| if (pic->PQDIFF == 7) |
| BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, PQUANT_ALT, vop_dquant, pic->ABSPQ); |
| else if (pic->DQUANTFRM == 1) |
| BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, PQUANT_ALT, vop_dquant, pic->PQUANT + pic->PQDIFF + 1); |
| } |
| BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, DQUANTFRM, vop_dquant, pic->DQUANTFRM); |
| BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, DQPROFILE, vop_dquant, pic->DQPROFILE); |
| BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, DQES, vop_dquant, pic->DQSBEDGE); |
| BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, DQBILEVEL, vop_dquant, pic->DQBILEVEL); |
| |
| BF_WRITE( VC1_0_SEQPIC_TRANSFORM_DATA, TRANSACFRM, trans_data, pic->TRANSACFRM); |
| BF_WRITE( VC1_0_SEQPIC_TRANSFORM_DATA, TRANSACFRM2, trans_data, pic->TRANSACFRM2); |
| BF_WRITE( VC1_0_SEQPIC_TRANSFORM_DATA, TRANSDCTAB, trans_data, pic->TRANSDCTAB); |
| |
| |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_REGS_SLICE_OTHER_INFO; |
| |
| |
| wi.vwi_payload[0] = trans_data; |
| wi.vwi_payload[1] = vop_dquant; |
| wi.vwi_payload[2] = ref_bfraction; |
| |
| viddec_pm_append_workitem( parent, &wi, false ); |
| return; |
| } // send_reorder_ref_items |
| |
| |
| |
| /* send reorder frame item to host |
| * future frame gets push to past */ |
| static inline void send_STRUCT_FIELD_AND_SMP_RANGEMAP_INFO_registers(void *parent, vc1_viddec_parser_t *parser) |
| { |
| uint32_t imgstruct = 0; |
| uint32_t fieldref_ctrl_id = 0; |
| uint32_t smp_rangemap = 0; |
| |
| vc1_PictureLayerHeader *pic = &(parser->info.picLayerHeader); |
| viddec_workload_item_t wi; |
| |
| vc1_metadata_t *md = &(parser->info.metadata); |
| |
| if ( pic->FCM == VC1_FCM_FIELD_INTERLACE ) { |
| BF_WRITE(VC1_0_SEQPIC_IMAGE_STRUCTURE, IMG_STRUC, imgstruct, (pic->BottomField) ? 2 : 1); |
| } |
| |
| BF_WRITE( VC1_0_SEQPIC_FIELD_REF_FRAME_ID, TOP_FIELD, fieldref_ctrl_id, pic->BottomField); |
| BF_WRITE( VC1_0_SEQPIC_FIELD_REF_FRAME_ID, SECOND_FIELD, fieldref_ctrl_id, pic->CurrField); |
| if (parser->info.picLayerHeader.PTYPE == VC1_I_FRAME) |
| { |
| BF_WRITE(VC1_0_SEQPIC_FIELD_REF_FRAME_ID, ANCHOR, fieldref_ctrl_id, 1); |
| } |
| else |
| { |
| BF_WRITE(VC1_0_SEQPIC_FIELD_REF_FRAME_ID, ANCHOR, fieldref_ctrl_id, parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].anchor[pic->CurrField]); |
| } |
| |
| if (VC1_PROFILE_ADVANCED != md->PROFILE) |
| { |
| if (pic->RANGEREDFRM) |
| { |
| //BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_Y_FLAG, smp_rangemap, md->RANGE_MAPY_FLAG); |
| //BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_UV_FLAG, smp_rangemap, md->RANGE_MAPUV_FLAG); |
| smp_rangemap = 0x11; |
| } |
| |
| } |
| |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_REGS_STRUCT_FIELD_AND_SMP_RANGEMAP_INFO; |
| |
| |
| wi.vwi_payload[0] = imgstruct; |
| wi.vwi_payload[1] = fieldref_ctrl_id; |
| wi.vwi_payload[2] = smp_rangemap; |
| |
| viddec_pm_append_workitem( parent, &wi, false ); |
| return; |
| } // send_reorder_ref_items |
| |
| |
| /* send reorder frame item to host |
| * future frame gets push to past */ |
| static inline void send_INT_COM_registers(void *parent, vc1_viddec_parser_t *parser) |
| { |
| uint32_t intcomp_fwd_top = 0; |
| uint32_t intcomp_fwd_bot = 0; |
| uint32_t intcomp_bwd_top = 0; |
| uint32_t intcomp_bwd_bot = 0; |
| uint32_t intcomp_cur = 0; |
| |
| uint32_t POS_2nd_INTCOMP = 13; |
| uint32_t MASK_1st_INTCOMP = 0x1fff; |
| uint32_t MASK_2nd_INTCOMP = 0x3ffe000; |
| |
| vc1_PictureLayerHeader *pic = &(parser->info.picLayerHeader); |
| viddec_workload_item_t wi; |
| |
| vc1_metadata_t *md = &(parser->info.metadata); |
| |
| |
| |
| if (VC1_SKIPPED_FRAME == pic->PTYPE) |
| { |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top =0; |
| return; |
| } |
| |
| if ( VC1_FCM_FIELD_INTERLACE != pic->FCM ) |
| { |
| |
| BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, intcomp_cur, 1); |
| BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SCALE_1, intcomp_cur, pic->LUMSCALE); |
| BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SHIFT_1, intcomp_cur, pic->LUMSHIFT); |
| |
| if ( !((pic->MVMODE == VC1_MVMODE_INTENSCOMP) || (pic->INTCOMP)) ) |
| intcomp_cur = 0; |
| |
| if ( (VC1_BI_FRAME==pic->PTYPE)||(VC1_B_FRAME==pic->PTYPE) ) |
| { |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = 0; |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_bot = 0; |
| |
| intcomp_bwd_top = parser->intcomp_top[0]; |
| intcomp_bwd_bot = parser->intcomp_bot[0]; |
| intcomp_fwd_bot = parser->intcomp_bot[1]; |
| |
| |
| if ( parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].id != (-1) ) |
| { |
| if (VC1_SKIPPED_FRAME != parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].type) |
| intcomp_fwd_top = parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].intcomp_top; |
| } |
| else |
| { |
| if (VC1_SKIPPED_FRAME != parser->ref_frame[VC1_REF_FRAME_T_MINUS_2].type) |
| intcomp_fwd_top = parser->intcomp_top[1]; |
| } |
| } |
| else |
| { //I,P TYPE |
| |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = intcomp_cur; |
| |
| if (VC1_FCM_FIELD_INTERLACE == parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm) |
| { |
| intcomp_fwd_top = parser->intcomp_top[1]; |
| intcomp_fwd_top |= intcomp_cur << POS_2nd_INTCOMP; |
| |
| intcomp_fwd_bot = parser->intcomp_bot[1]; |
| intcomp_fwd_bot |= intcomp_cur << POS_2nd_INTCOMP; |
| } |
| else |
| { |
| intcomp_fwd_top = intcomp_cur;// << POS_2nd_INTCOMP; |
| intcomp_fwd_bot = 0; |
| } |
| } |
| } |
| else |
| { |
| //FIELD INTERLACE |
| //if(0!=md->INTCOMPFIELD) |
| //No debugging |
| |
| if (md->INTCOMPFIELD == VC1_INTCOMP_BOTTOM_FIELD) |
| { |
| BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, intcomp_cur, 1); |
| BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SCALE_2, intcomp_cur, md->LUMSCALE2); |
| BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SHIFT_2, intcomp_cur, md->LUMSHIFT2); |
| } |
| else |
| { |
| BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, intcomp_cur, 1); |
| BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SCALE_1, intcomp_cur, pic->LUMSCALE); |
| BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SHIFT_1, intcomp_cur, pic->LUMSHIFT); |
| } |
| |
| if (md->INTCOMPFIELD == VC1_INTCOMP_BOTH_FIELD) |
| { |
| BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, intcomp_cur, 1); |
| BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SCALE_2, intcomp_cur, md->LUMSCALE2); |
| BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SHIFT_2, intcomp_cur, md->LUMSHIFT2); |
| } |
| |
| if (pic->MVMODE != VC1_MVMODE_INTENSCOMP) |
| { |
| intcomp_cur = 0; |
| } |
| |
| if (pic->CurrField == 0) |
| { |
| if (pic->TFF) |
| { |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = intcomp_cur; |
| } |
| else |
| { |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_bot = intcomp_cur; |
| } |
| } |
| else |
| { |
| if (pic->TFF) |
| { |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_bot = intcomp_cur; |
| } |
| else |
| { |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = intcomp_cur; |
| } |
| } |
| |
| if (pic->CurrField == 1) |
| { //SECOND FIELD |
| |
| if (VC1_B_FRAME != pic->PTYPE) |
| { |
| if (pic->TFF) |
| { |
| intcomp_bwd_top = intcomp_cur & MASK_1st_INTCOMP; |
| |
| intcomp_fwd_bot = (parser->intcomp_bot[1] & MASK_2nd_INTCOMP) >> POS_2nd_INTCOMP; //??????? |
| intcomp_fwd_bot |= (intcomp_cur & MASK_2nd_INTCOMP); |
| |
| intcomp_fwd_top = parser->intcomp_top[1]; |
| } |
| else |
| { |
| intcomp_bwd_bot= (intcomp_cur & MASK_2nd_INTCOMP)>>POS_2nd_INTCOMP; |
| |
| intcomp_fwd_top = (parser->intcomp_top[1] & MASK_2nd_INTCOMP) >> POS_2nd_INTCOMP; |
| intcomp_fwd_top |= (intcomp_cur&MASK_1st_INTCOMP) << POS_2nd_INTCOMP; |
| |
| intcomp_fwd_bot = parser->intcomp_bot[1]; |
| } |
| } |
| else |
| { //B TYPE |
| intcomp_fwd_top = parser->intcomp_top[1]; |
| intcomp_fwd_bot = parser->intcomp_bot[1]; |
| |
| intcomp_bwd_top = parser->intcomp_top[0]; |
| intcomp_bwd_bot = parser->intcomp_bot[0]; |
| } |
| } |
| else |
| { //FIRST FILED |
| |
| if ( (VC1_B_FRAME==pic->PTYPE)||(VC1_BI_FRAME==pic->PTYPE) ) |
| { |
| if (VC1_SKIPPED_FRAME!=parser->ref_frame[VC1_REF_FRAME_T_MINUS_2].type) |
| { |
| intcomp_fwd_top = parser->intcomp_top[1]; |
| intcomp_fwd_bot = parser->intcomp_bot[1]; |
| } |
| |
| intcomp_bwd_top = parser->intcomp_top[0]; |
| intcomp_bwd_bot = parser->intcomp_bot[0]; |
| |
| } |
| else |
| { //I,P TYPE |
| |
| intcomp_fwd_top = parser->intcomp_top[1] & MASK_1st_INTCOMP; |
| intcomp_fwd_top |= (intcomp_cur&MASK_1st_INTCOMP)<<POS_2nd_INTCOMP; |
| |
| intcomp_fwd_bot = parser->intcomp_bot[1] & MASK_1st_INTCOMP; |
| intcomp_fwd_bot |= (intcomp_cur & MASK_2nd_INTCOMP); |
| } //pic->PTYPE == I,P TYPE |
| } //pic->CurrField == 0 |
| } //VC1_FCM_FIELD_INTERLACE != pic->FCM |
| |
| if ( (VC1_B_FRAME != pic->PTYPE) && (VC1_BI_FRAME != pic->PTYPE) ) |
| { |
| parser->intcomp_top[1] = intcomp_fwd_top; |
| parser->intcomp_bot[1] = intcomp_fwd_bot; |
| |
| parser->intcomp_top[0] = intcomp_bwd_top; |
| parser->intcomp_bot[0] = intcomp_bwd_bot; |
| } |
| |
| //OS_INFO("intcomp_fwd_top = %d\n", intcomp_fwd_top); |
| //OS_INFO("intcomp_fwd_bot = %d\n", intcomp_fwd_bot); |
| |
| |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_REGS_INT_COM_FW; |
| |
| wi.vwi_payload[0] = 0; |
| wi.vwi_payload[1] = intcomp_fwd_top; |
| wi.vwi_payload[2] = intcomp_fwd_bot; |
| |
| viddec_pm_append_workitem( parent, &wi, false ); |
| |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_REGS_INT_COM_BW; |
| |
| wi.vwi_payload[0] = 0; |
| wi.vwi_payload[1] = intcomp_bwd_top; |
| wi.vwi_payload[2] = intcomp_bwd_bot; |
| |
| viddec_pm_append_workitem( parent, &wi, false ); |
| |
| |
| return; |
| } // send_reorder_ref_items |
| |
| |
| /** update workload with more workload items for ref and update values to store... |
| */ |
| void vc1_parse_emit_frame_start(void *parent, vc1_viddec_parser_t *parser) |
| { |
| vc1_metadata_t *md = &(parser->info.metadata); |
| viddec_workload_t *wl = viddec_pm_get_header(parent); |
| int frame_type = parser->info.picLayerHeader.PTYPE; |
| int frame_id = 1; // new reference frame is assigned index 1 |
| |
| /* init */ |
| memset(&parser->spr, 0, sizeof(parser->spr)); |
| wl->is_reference_frame = 0; |
| |
| /* set flag - extra ouput frame needed for range adjustment (range mapping or range reduction */ |
| if (parser->info.metadata.RANGE_MAPY_FLAG || |
| parser->info.metadata.RANGE_MAPUV_FLAG || |
| parser->info.picLayerHeader.RANGEREDFRM) |
| { |
| wl->is_reference_frame |= WORKLOAD_FLAGS_RA_FRAME; |
| } |
| |
| LOG_CRIT("vc1_start_new_frame: frame_type=%d \n",frame_type); |
| |
| parser->is_reference_picture = ((VC1_B_FRAME != frame_type) && (VC1_BI_FRAME != frame_type)); |
| |
| /* reference / anchor frames processing |
| * we need to send reorder before reference frames */ |
| if (parser->is_reference_picture) |
| { |
| /* one frame has been sent */ |
| if (parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].id != -1) |
| { |
| /* there is a frame in the reference buffer, move it to the past */ |
| send_reorder_ref_items(parent); |
| } |
| } |
| |
| /* send workitems for reference frames */ |
| switch ( frame_type ) |
| { |
| case VC1_B_FRAME: |
| { |
| vc1_send_past_ref_items(parent); |
| vc1_send_future_ref_items(parent); |
| vc1_send_ref_fcm_items(parent, parser->ref_frame[VC1_REF_FRAME_T_MINUS_2].fcm, parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm); |
| break; |
| } |
| case VC1_SKIPPED_FRAME: |
| { |
| wl->is_reference_frame |= WORKLOAD_SKIPPED_FRAME; |
| vc1_send_past_ref_items(parent); |
| vc1_send_ref_fcm_items(parent, parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm, vc1_PictureFormatNone); |
| break; |
| } |
| case VC1_P_FRAME: |
| { |
| vc1_send_past_ref_items( parent); |
| vc1_send_ref_fcm_items(parent, parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm, vc1_PictureFormatNone); |
| break; |
| } |
| default: |
| break; |
| } |
| |
| /* reference / anchor frames from previous code |
| * we may need it for frame reduction */ |
| if (parser->is_reference_picture) |
| { |
| wl->is_reference_frame |= WORKLOAD_REFERENCE_FRAME | (frame_id & WORKLOAD_REFERENCE_FRAME_BMASK); |
| |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].id = frame_id; |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].fcm = parser->info.picLayerHeader.FCM; |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].anchor[0] = (parser->info.picLayerHeader.PTYPE == VC1_I_FRAME); |
| if (parser->info.picLayerHeader.FCM == VC1_FCM_FIELD_INTERLACE) |
| { |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].anchor[1] = (parser->info.picLayerHeader.PTypeField2 == VC1_I_FRAME); |
| } |
| else |
| { |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].anchor[1] = parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].anchor[0]; |
| } |
| |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].type = parser->info.picLayerHeader.PTYPE; |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].rr_en = md->RANGERED; |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].rr_frm = parser->info.picLayerHeader.RANGEREDFRM; |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].tff = parser->info.picLayerHeader.TFF; |
| |
| LOG_CRIT("anchor[0] = %d, anchor[1] = %d", |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].anchor[0], |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].anchor[1] ); |
| } |
| |
| if ( parser->info.picLayerHeader.PTYPE == VC1_SKIPPED_FRAME ) |
| { |
| translate_parser_info_to_frame_attributes( parent, parser ); |
| return; |
| } |
| |
| translate_parser_info_to_frame_attributes( parent, parser ); |
| |
| |
| send_SEQ_ENTRY_registers(parent, parser); |
| send_SIZE_AND_AP_RANGEMAP_registers(parent, parser); |
| send_SLICE_FRAME_TYPE_INFO_registers(parent, parser); |
| send_SLICE_CONTROL_INFO_registers(parent, parser); |
| send_SLICE_OTHER_INFO_registers(parent, parser); |
| send_STRUCT_FIELD_AND_SMP_RANGEMAP_INFO_registers(parent, parser); |
| send_INT_COM_registers(parent, parser); |
| |
| { |
| viddec_workload_item_t wi; |
| uint32_t bit, byte; |
| uint8_t is_emul = 0; |
| |
| viddec_pm_get_au_pos(parent, &bit, &byte, &is_emul); |
| |
| // Send current bit offset and current slice |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_BITOFFSET; |
| |
| // If slice data starts in the middle of the emulation prevention sequence - |
| // Special Case1----[is_emul = 1]: |
| // Eg: 00 00 03 01 - slice data starts at the second byte of 0s, we still feed the data |
| // to the decoder starting at the first byte of 0s so that the decoder can detect the |
| // emulation prevention. But the actual data starts are offset 8 in this bit sequence. |
| |
| // Specail Case 2----[is_emul = 2]: |
| // If slice data starts in the middle of the emulation prevention sequence - |
| // Eg: [00 00] 03 00 - slice data starts at the third byte (0x03), we need readout this byte. |
| // |
| |
| wi.vwi_payload[0] = bit + (is_emul*8) ; |
| wi.vwi_payload[1] = 0xdeaddead; |
| wi.vwi_payload[2] = 0xdeaddead; |
| viddec_pm_append_workitem( parent, &wi, false ); |
| } |
| |
| |
| viddec_pm_append_pixeldata( parent ); |
| |
| return; |
| } // vc1_start_new_frame |
| |
| |
| void vc1_parse_emit_second_field_start(void *parent, vc1_viddec_parser_t *parser) |
| { |
| |
| send_SLICE_FRAME_TYPE_INFO_registers(parent, parser); |
| send_SLICE_CONTROL_INFO_registers(parent, parser); |
| send_SLICE_OTHER_INFO_registers(parent, parser); |
| send_STRUCT_FIELD_AND_SMP_RANGEMAP_INFO_registers(parent, parser); |
| send_INT_COM_registers(parent, parser); |
| |
| { |
| viddec_workload_item_t wi; |
| uint32_t bit, byte; |
| uint8_t is_emul = 0; |
| |
| viddec_pm_get_au_pos(parent, &bit, &byte, &is_emul); |
| |
| |
| // Send current bit offset and current slice |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_BITOFFSET; |
| // If slice data starts in the middle of the emulation prevention sequence - |
| // Special Case1----[is_emul = 1]: |
| // Eg: 00 00 03 01 - slice data starts at the second byte of 0s, we still feed the data |
| // to the decoder starting at the first byte of 0s so that the decoder can detect the |
| // emulation prevention. But the actual data starts are offset 8 in this bit sequence. |
| |
| // Specail Case 2----[is_emul = 2]: |
| // If slice data starts in the middle of the emulation prevention sequence - |
| // Eg: [00 00] 03 00 - slice data starts at the third byte (0x03), we need readout this byte. |
| // |
| |
| |
| wi.vwi_payload[0] = bit + (is_emul*8); |
| wi.vwi_payload[1] = 0xdeaddead; |
| wi.vwi_payload[2] = 0xdeaddead; |
| viddec_pm_append_workitem( parent, &wi, false ); |
| } |
| |
| viddec_pm_append_pixeldata( parent ); |
| |
| return; |
| |
| } |
| |
| |
| void vc1_parse_emit_current_slice(void *parent, vc1_viddec_parser_t *parser) |
| { |
| send_SLICE_FRAME_TYPE_INFO_registers(parent, parser); |
| send_SLICE_CONTROL_INFO_registers(parent, parser); |
| send_SLICE_OTHER_INFO_registers(parent, parser); |
| //send_STRUCT_FIELD_AND_SMP_RANGEMAP_INFO_registers(parent, parser); |
| //send_INT_COM_registers(parent, parser); |
| |
| { |
| viddec_workload_item_t wi; |
| uint32_t bit, byte; |
| uint8_t is_emul = 0; |
| |
| viddec_pm_get_au_pos(parent, &bit, &byte, &is_emul); |
| |
| // Send current bit offset and current slice |
| wi.vwi_type = VIDDEC_WORKLOAD_VC1_BITOFFSET; |
| |
| // If slice data starts in the middle of the emulation prevention sequence - |
| // Special Case1----[is_emul = 1]: |
| // Eg: 00 00 03 01 - slice data starts at the second byte of 0s, we still feed the data |
| // to the decoder starting at the first byte of 0s so that the decoder can detect the |
| // emulation prevention. But the actual data starts are offset 8 in this bit sequence. |
| |
| // Specail Case 2----[is_emul = 2]: |
| // If slice data starts in the middle of the emulation prevention sequence - |
| // Eg: [00 00] 03 00 - slice data starts at the third byte (0x03), we need readout this byte. |
| // |
| |
| wi.vwi_payload[0] = bit + (is_emul*8); |
| wi.vwi_payload[1] = 0xdeaddead; |
| wi.vwi_payload[2] = 0xdeaddead; |
| viddec_pm_append_workitem( parent, &wi, false ); |
| } |
| |
| viddec_pm_append_pixeldata( parent ); |
| |
| return; |
| } |
| |
| |
| void vc1_end_frame(vc1_viddec_parser_t *parser) |
| { |
| /* update status of reference frames */ |
| if (parser->is_reference_picture) |
| { |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_2] = parser->ref_frame[VC1_REF_FRAME_T_MINUS_1]; |
| parser->ref_frame[VC1_REF_FRAME_T_MINUS_1] = parser->ref_frame[VC1_REF_FRAME_T_MINUS_0]; |
| } |
| |
| return; |
| } // vc1_end_frame |
| |