blob: b5bba2b9f3ed4ee30b3062c395d70d23efa6040f [file] [log] [blame]
/* 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