Home | History | Annotate | Download | only in parser
      1 /* Any workload management goes in this file */
      2 
      3 #include "viddec_fw_debug.h"
      4 #include "vc1.h"
      5 #include "vc1parse.h"
      6 #include "viddec_fw_workload.h"
      7 #include <auto_eas/gen4_mfd.h>
      8 #include "viddec_pm_utils_bstream.h"
      9 
     10 /* this function returns workload frame types corresponding to VC1 PTYPES (frame types)
     11  * VC1 frame types: can be found in vc1parse_common_defs.h
     12  * workload frame types are in viddec_workload.h
     13 */
     14 static inline uint32_t vc1_populate_frame_type(uint32_t vc1_frame_type)
     15 {
     16     uint32_t viddec_frame_type;
     17 
     18       switch(vc1_frame_type)
     19       {
     20         case VC1_I_FRAME:
     21             viddec_frame_type = VIDDEC_FRAME_TYPE_I;
     22             break;
     23         case VC1_P_FRAME:
     24             viddec_frame_type = VIDDEC_FRAME_TYPE_P;
     25             break;
     26         case VC1_B_FRAME:
     27             viddec_frame_type = VIDDEC_FRAME_TYPE_B;
     28             break;
     29         case VC1_BI_FRAME:
     30             viddec_frame_type = VIDDEC_FRAME_TYPE_BI;
     31             break;
     32         case VC1_SKIPPED_FRAME :
     33             viddec_frame_type =  VIDDEC_FRAME_TYPE_SKIP;
     34             break;
     35         default:
     36             viddec_frame_type = VIDDEC_FRAME_TYPE_INVALID;
     37             break;
     38       } // switch on vc1 frame type
     39 
     40    return(viddec_frame_type);
     41 } // vc1_populate_frame_type
     42 
     43 static void translate_parser_info_to_frame_attributes(void *parent, vc1_viddec_parser_t *parser)
     44 {
     45     viddec_workload_t        *wl = viddec_pm_get_header( parent );
     46     viddec_frame_attributes_t *attrs = &wl->attrs;
     47     vc1_Info        *info = &parser->info;
     48     unsigned i;
     49 
     50     /* typical sequence layer and entry_point data */
     51     attrs->cont_size.height       = info->metadata.height * 2 + 2;
     52     attrs->cont_size.width        = info->metadata.width  * 2 + 2;
     53 
     54     /* frame type */
     55     /* we can have two fileds with different types for field interlace coding mode */
     56     if (info->picLayerHeader.FCM == VC1_FCM_FIELD_INTERLACE) {
     57       attrs->frame_type = vc1_populate_frame_type(info->picLayerHeader.PTypeField1);
     58       attrs->bottom_field_type = vc1_populate_frame_type(info->picLayerHeader.PTypeField2);
     59     } else {
     60       attrs->frame_type = vc1_populate_frame_type(info->picLayerHeader.PTYPE);
     61       attrs->bottom_field_type = VIDDEC_FRAME_TYPE_INVALID; //unknown
     62     }
     63 
     64     /* frame counter */
     65     attrs->vc1.tfcntr = info->picLayerHeader.TFCNTR;
     66 
     67     /* TFF, repeat frame, field */
     68     attrs->vc1.tff = info->picLayerHeader.TFF;
     69     attrs->vc1.rptfrm = info->picLayerHeader.RPTFRM;
     70     attrs->vc1.rff = info->picLayerHeader.RFF;
     71 
     72     /* PAN Scan */
     73     attrs->vc1.ps_present = info->picLayerHeader.PS_PRESENT;
     74     attrs->vc1.num_of_pan_scan_windows = info->picLayerHeader.number_of_pan_scan_window;
     75     for (i=0;i<attrs->vc1.num_of_pan_scan_windows;i++) {
     76       attrs->vc1.pan_scan_window[i].hoffset =  info->picLayerHeader.PAN_SCAN_WINDOW[i].hoffset;
     77       attrs->vc1.pan_scan_window[i].voffset =  info->picLayerHeader.PAN_SCAN_WINDOW[i].voffset;
     78       attrs->vc1.pan_scan_window[i].width =  info->picLayerHeader.PAN_SCAN_WINDOW[i].width;
     79       attrs->vc1.pan_scan_window[i].height =  info->picLayerHeader.PAN_SCAN_WINDOW[i].height;
     80     } //end for i
     81 
     82     return;
     83 } // translate_parser_info_to_frame_attributes
     84 
     85 void vc1_intcomp(vc1_viddec_parser_t *parser, vc1_Info *pInfo, VC1D_SPR_REGS *spr)
     86 {
     87     vc1_metadata_t *md = &pInfo->metadata;
     88     vc1_PictureLayerHeader *pic = &pInfo->picLayerHeader;
     89     uint32_t intcomp1 = 1;
     90     uint32_t intcomp2 = 0;
     91 
     92     // Get the intensity compensation from the bitstream
     93     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SCALE_1, intcomp1, pic->LUMSCALE);
     94     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SHIFT_1, intcomp1, pic->LUMSHIFT);
     95 
     96     if(md->INTCOMPFIELD == VC1_INTCOMP_BOTH_FIELD)
     97     {
     98         intcomp2 = 1;
     99         BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SCALE_1, intcomp2, md->LUMSCALE2);
    100         BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SHIFT_1, intcomp2, md->LUMSHIFT2);
    101     }
    102 
    103     switch(md->INTCOMPFIELD)
    104     {
    105         case VC1_INTCOMP_TOP_FIELD:
    106             if(pic->CurrField == 0) // First field decoded
    107             {
    108                 if(pic->TFF)
    109                 {
    110                     //parser->intcomp_bot[0] = intcomp1 << 13;
    111                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_top, intcomp1);
    112                 }
    113                 else
    114                 {
    115                     parser->intcomp_top[0] = intcomp1;
    116                     parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = intcomp1;
    117                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_fwd_top, intcomp1);
    118                 }
    119             }
    120             else // Second field
    121             {
    122                 if(pic->TFF)
    123                 {
    124                     parser->intcomp_top[0] = intcomp1;
    125                     parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = intcomp1;
    126                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_bwd_top, intcomp1);
    127                 }
    128                 else
    129                 {
    130                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_top, intcomp1);
    131                 }
    132             }
    133             break;
    134         case VC1_INTCOMP_BOTTOM_FIELD:
    135             if(pic->CurrField == 0) // First field decoded
    136             {
    137                 if(pic->TFF)
    138                 {
    139                     parser->intcomp_bot[0] = intcomp1;
    140                     parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_bot = intcomp1;
    141                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_fwd_bot, intcomp1);
    142                 }
    143                 else
    144                 {
    145                     parser->intcomp_bot[0] = intcomp1 << 13;
    146                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_bot, intcomp1);
    147                 }
    148             }
    149             else // Second field
    150             {
    151                 if(pic->TFF)
    152                 {
    153                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_bot, intcomp1);
    154                 }
    155                 else
    156                 {
    157                     parser->intcomp_bot[0] = intcomp1;
    158                     parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_bot = intcomp1;
    159                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_bwd_bot, intcomp1);
    160                 }
    161             }
    162             break;
    163         case VC1_INTCOMP_BOTH_FIELD:
    164             if(pic->CurrField == 0) // First field decoded
    165             {
    166                 if(pic->TFF)
    167                 {
    168                     parser->intcomp_bot[0] = intcomp2;
    169                     parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_bot = intcomp2;
    170                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_top, intcomp1);
    171                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_fwd_bot, intcomp2);
    172                 }
    173                 else
    174                 {
    175                     parser->intcomp_top[0] = intcomp2;
    176                     parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = intcomp2;
    177                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_bot, intcomp1);
    178                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_fwd_top, intcomp2);
    179                 }
    180             }
    181             else // Second field
    182             {
    183                 if(pic->TFF)
    184                 {
    185                     parser->intcomp_top[0] = intcomp1;
    186                     parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = intcomp1;
    187                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_bwd_top, intcomp1);
    188                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_bot, intcomp2);
    189                 }
    190                 else
    191                 {
    192                     parser->intcomp_bot[0] = intcomp1;
    193                     parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_bot = intcomp1;
    194                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_bwd_bot, intcomp1);
    195                     BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_top, intcomp2);
    196                 }
    197             }
    198             break;
    199         default:
    200             break;
    201     } // switch on INTCOMPFIELD
    202 
    203     return;
    204 } // vc1_intcomp
    205 
    206 static void handle_intensity_compensation(vc1_viddec_parser_t *parser, vc1_Info *pInfo, VC1D_SPR_REGS *spr)
    207 {
    208     vc1_PictureLayerHeader *pic = &pInfo->picLayerHeader;
    209     uint8_t intcomp_present = false;
    210 
    211     if((pic->MVMODE == VC1_MVMODE_INTENSCOMP) || (pic->INTCOMP))
    212     {
    213         intcomp_present = true;
    214         if(pic->FCM == VC1_FCM_FIELD_INTERLACE)
    215         {
    216             vc1_intcomp(parser, pInfo, spr);
    217         }
    218         else
    219         {
    220             BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_fwd_top, 1);
    221             BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SCALE_1, spr->intcomp_fwd_top, pic->LUMSCALE);
    222             BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SHIFT_1, spr->intcomp_fwd_top, pic->LUMSHIFT);
    223 
    224             if(parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm == VC1_FCM_FIELD_INTERLACE)
    225             {
    226                BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_bot, 1);
    227                BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SCALE_2, spr->intcomp_fwd_bot, pic->LUMSCALE);
    228                BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SHIFT_2, spr->intcomp_fwd_bot, pic->LUMSHIFT);
    229             }
    230 
    231             parser->intcomp_top[0] = spr->intcomp_fwd_top;
    232             parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = spr->intcomp_fwd_top;
    233             parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_bot = spr->intcomp_fwd_top;
    234         }
    235     }
    236 
    237     // Propagate the previous picture's intensity compensation
    238     if(pic->FCM == VC1_FCM_FIELD_INTERLACE)
    239     {
    240         if( (pic->CurrField) ||
    241             ((pic->CurrField == 0) && (parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm == VC1_FCM_FIELD_INTERLACE)))
    242         {
    243             spr->intcomp_fwd_top |= parser->intcomp_top[1];
    244             spr->intcomp_fwd_bot |= parser->intcomp_bot[1];
    245         }
    246     }
    247     if(pic->FCM == VC1_FCM_FRAME_INTERLACE)
    248     {
    249         if( (pic->CurrField) ||
    250             ((pic->CurrField == 0) && (parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm == VC1_FCM_FIELD_INTERLACE)))
    251         {
    252             spr->intcomp_fwd_bot |= parser->intcomp_bot[1];
    253         }
    254     }
    255 
    256     switch(pic->PTYPE)
    257     {
    258         case VC1_B_FRAME:
    259             spr->intcomp_fwd_top = parser->intcomp_last[0];
    260             spr->intcomp_fwd_bot = parser->intcomp_last[1];
    261             spr->intcomp_bwd_top = parser->intcomp_last[2];
    262             spr->intcomp_bwd_bot = parser->intcomp_last[3];
    263             break;
    264         case VC1_P_FRAME:
    265             // If first field, store the intcomp values to propagate.
    266             // If second field has valid intcomp values, store them
    267             // to propagate.
    268             if(pic->CurrField == 0) // first field
    269             {
    270                 parser->intcomp_last[0] = spr->intcomp_fwd_top;
    271                 parser->intcomp_last[1] = spr->intcomp_fwd_bot;
    272                 parser->intcomp_last[2] = spr->intcomp_bwd_top;
    273                 parser->intcomp_last[3] = spr->intcomp_bwd_bot;
    274             }
    275             else // Second field
    276             {
    277                     parser->intcomp_last[0] |= spr->intcomp_fwd_top;
    278                     parser->intcomp_last[1] |= spr->intcomp_fwd_bot;
    279                     parser->intcomp_last[2] |= spr->intcomp_bwd_top;
    280                     parser->intcomp_last[3] |= spr->intcomp_bwd_bot;
    281             }
    282             break;
    283         case VC1_I_FRAME:
    284         case VC1_BI_FRAME:
    285             break;
    286         default:
    287             break;
    288     }
    289 
    290     return;
    291 } // handle_intensity_compensation
    292 
    293 /**
    294  * This function populates the registers for range reduction (main profile)
    295  * This function assumes pInfo->metadata.RANGERED is ON at the sequence layer (J.1.17)
    296  * A frame is marked as range reduced by the RANGEREDFRM flag at the picture layer,
    297  * and the output of the decoded range reduced frame needs to be scaled up (8.1.1.4).
    298  * Previous reference frame needs be upscaled or downscaled based on the RR status of
    299  * current and previous frame (8.3.4.11)
    300  */
    301 static inline void vc1_fill_RR_hw_struct(vc1_viddec_parser_t *parser, vc1_Info *pInfo, VC1D_SPR_REGS *spr)
    302 {
    303     vc1_PictureLayerHeader *pic = &pInfo->picLayerHeader;
    304     int is_previous_ref_rr=0;
    305 
    306     /* range reduction applies to luma and chroma component
    307     which are the same register bit as RANGE_MAPY_FLAG, RANGE_MAPUV_FLAG */
    308     BF_WRITE(VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_Y_FLAG, spr->range_map, pic->RANGEREDFRM);
    309     BF_WRITE(VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_UV_FLAG, spr->range_map, pic->RANGEREDFRM);
    310 
    311     /* Get the range reduced status of the previous frame */
    312     switch (pic->PTYPE)
    313     {
    314         case VC1_P_FRAME:
    315         {
    316             is_previous_ref_rr = parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].rr_frm;
    317             break;
    318         }
    319         case VC1_B_FRAME:
    320         {
    321             is_previous_ref_rr = parser->ref_frame[VC1_REF_FRAME_T_MINUS_2].rr_frm;
    322             break;
    323         }
    324         default:
    325         {
    326             break;
    327         }
    328     }
    329 
    330     /* if current frame is RR and previous frame is not
    331         donwscale the reference pixel ( RANGE_REF_RED_TYPE =1 in register) */
    332     if(pic->RANGEREDFRM)
    333     {
    334         if(!is_previous_ref_rr)
    335         {
    336             BF_WRITE(VC1_0_SEQPIC_RECON_CONTROL, RANGE_REF_RED_EN, spr->recon_control, 1);
    337             BF_WRITE(VC1_0_SEQPIC_RECON_CONTROL, RANGE_REF_RED_TYPE, spr->recon_control, 1);
    338         }
    339     }
    340     else
    341     {
    342         /* if current frame is not RR but previous was RR,  scale up the reference frame ( RANGE_REF_RED_TYPE = 0) */
    343         if(is_previous_ref_rr)
    344         {
    345             BF_WRITE(VC1_0_SEQPIC_RECON_CONTROL, RANGE_REF_RED_EN, spr->recon_control, 1);
    346             BF_WRITE(VC1_0_SEQPIC_RECON_CONTROL, RANGE_REF_RED_TYPE, spr->recon_control, 0);
    347         }
    348     } // end for RR upscale
    349 
    350 } // vc1_fill_RR_hw_struct
    351 
    352 /**
    353  * fill workload items that will load registers for HW decoder
    354  */
    355 static void vc1_fill_hw_struct(vc1_viddec_parser_t *parser, vc1_Info* pInfo, VC1D_SPR_REGS *spr)
    356 {
    357     vc1_metadata_t *md = &pInfo->metadata;
    358     vc1_PictureLayerHeader *pic = &pInfo->picLayerHeader;
    359     int field = pic->CurrField;
    360     int ptype;
    361 
    362     ptype = pic->PTYPE;
    363 
    364     LOG_CRIT("ptype = %d, field = %d, topfield = %d, slice = %d", ptype, pic->CurrField, pic->BottomField, pic->SLICE_ADDR);
    365 
    366     /* Common to both fields */
    367     BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_1, PROFILE, spr->stream_format1, md->PROFILE);
    368 
    369     BF_WRITE(VC1_0_SEQPIC_CODED_SIZE, WIDTH, spr->coded_size, md->width);
    370     BF_WRITE(VC1_0_SEQPIC_CODED_SIZE, HEIGHT, spr->coded_size, md->height);
    371 
    372     BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_2, INTERLACE, spr->stream_format2, md->INTERLACE);
    373 
    374     BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, LOOPFILTER,    spr->entrypoint1, md->LOOPFILTER);
    375     BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, FASTUVMC,      spr->entrypoint1, md->FASTUVMC);
    376     BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, EXTENDED_MV,   spr->entrypoint1, md->EXTENDED_MV);
    377     BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, DQUANT,        spr->entrypoint1, md->DQUANT);
    378     BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, VS_TRANSFORM,  spr->entrypoint1, md->VSTRANSFORM);
    379     BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, OVERLAP,       spr->entrypoint1, md->OVERLAP);
    380     BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, QUANTIZER,     spr->entrypoint1, md->QUANTIZER);
    381     BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, EXTENDED_DMV,  spr->entrypoint1, md->EXTENDED_DMV);
    382 
    383     /* if range reduction is indicated at seq. layer, populate range reduction registers for the frame*/
    384     if(md->RANGERED)
    385     {
    386         vc1_fill_RR_hw_struct(parser, pInfo, spr );
    387     }
    388     else
    389     { //range mapping
    390         BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_Y_FLAG, spr->range_map, md->RANGE_MAPY_FLAG);
    391         BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_Y, spr->range_map, md->RANGE_MAPY);
    392         BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_UV_FLAG, spr->range_map, md->RANGE_MAPUV_FLAG);
    393         BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_UV, spr->range_map, md->RANGE_MAPUV);
    394     }
    395 
    396     BF_WRITE(VC1_0_SEQPIC_FRAME_TYPE, FCM, spr->frame_type, pic->FCM);
    397     BF_WRITE(VC1_0_SEQPIC_FRAME_TYPE, PTYPE, spr->frame_type, pic->PTYPE);
    398 
    399     BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, RNDCTRL, spr->recon_control, md->RNDCTRL);
    400     BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, UVSAMP, spr->recon_control, pic->UVSAMP);
    401     BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, PQUANT, spr->recon_control, pic->PQUANT);
    402     BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, HALFQP, spr->recon_control, pic->HALFQP);
    403     BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, UNIFORM_QNT, spr->recon_control, pic->UniformQuant);
    404     BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, POSTPROC, spr->recon_control, pic->POSTPROC);
    405     BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, CONDOVER, spr->recon_control, pic->CONDOVER);
    406     BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, PQINDEX_LE8, spr->recon_control, (pic->PQINDEX <= 8));
    407 
    408     BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MVRANGE,   spr->mv_control, pic->MVRANGE);
    409     if ( pic->MVMODE == VC1_MVMODE_INTENSCOMP)
    410         BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MVMODE,    spr->mv_control, pic->MVMODE2);
    411     else
    412         BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MVMODE,    spr->mv_control, pic->MVMODE);
    413     BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MVTAB,  spr->mv_control,  pic->MVTAB);
    414     BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, DMVRANGE,  spr->mv_control, pic->DMVRANGE);
    415     BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MV4SWITCH, spr->mv_control, pic->MV4SWITCH);
    416     BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MBMODETAB, spr->mv_control, pic->MBMODETAB);
    417     BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, NUMREF,    spr->mv_control,
    418         pic->NUMREF || ((pic->PTYPE == VC1_B_FRAME) && ( pic->FCM == VC1_FCM_FIELD_INTERLACE )  ));
    419     BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, REFFIELD,  spr->mv_control, pic->REFFIELD);
    420 
    421     handle_intensity_compensation(parser, pInfo, spr);
    422 
    423     BF_WRITE(VC1_0_SEQPIC_REFERENCE_B_FRACTION, BFRACTION_DEN, spr->ref_bfraction, pic->BFRACTION_DEN);
    424     BF_WRITE(VC1_0_SEQPIC_REFERENCE_B_FRACTION, BFRACTION_NUM, spr->ref_bfraction, pic->BFRACTION_NUM);
    425     BF_WRITE(VC1_0_SEQPIC_REFERENCE_B_FRACTION, REFDIST, spr->ref_bfraction, md->REFDIST);
    426 
    427     // BLOCK CONTROL REGISTER Offset 0x2C
    428     BF_WRITE( VC1_0_SEQPIC_BLOCK_CONTROL, CBPTAB, spr->blk_control, pic->CBPTAB);
    429     BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, TTMFB, spr->blk_control, pic->TTMBF);
    430     BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, TTFRM, spr->blk_control, pic->TTFRM);
    431     BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, MV2BPTAB, spr->blk_control, pic->MV2BPTAB);
    432     BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, MV4BPTAB, spr->blk_control, pic->MV4BPTAB);
    433     if((field == 1) && (pic->SLICE_ADDR))
    434     {
    435         int mby = md->height * 2 + 2;
    436         mby = (mby + 15 ) / 16;
    437         pic->SLICE_ADDR -= (mby/2);
    438     }
    439     BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, INITIAL_MV_Y, spr->blk_control, pic->SLICE_ADDR);
    440     BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, BP_RAW_ID2, spr->blk_control, md->bp_raw[0]);
    441     BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, BP_RAW_ID1, spr->blk_control, md->bp_raw[1]);
    442     BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, BP_RAW_ID0, spr->blk_control, md->bp_raw[2]);
    443 
    444     BF_WRITE( VC1_0_SEQPIC_TRANSFORM_DATA, TRANSACFRM,  spr->trans_data, pic->TRANSACFRM);
    445     BF_WRITE( VC1_0_SEQPIC_TRANSFORM_DATA, TRANSACFRM2, spr->trans_data, pic->TRANSACFRM2);
    446     BF_WRITE( VC1_0_SEQPIC_TRANSFORM_DATA, TRANSDCTAB,  spr->trans_data, pic->TRANSDCTAB);
    447 
    448     // When DQUANT is 1 or 2, we have the VOPDQUANT structure in the bitstream that
    449     // controls the value calculated for ALTPQUANT
    450     // ALTPQUANT must be in the range of 1 and 31 for it to be valid
    451     // DQUANTFRM is present only when DQUANT is 1 and ALTPQUANT setting should be dependent on DQUANT instead
    452     if(md->DQUANT)
    453     {
    454         if(pic->PQDIFF == 7)
    455             BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, PQUANT_ALT, spr->vop_dquant, pic->ABSPQ);
    456         else if (pic->DQUANTFRM == 1)
    457             BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, PQUANT_ALT, spr->vop_dquant, pic->PQUANT + pic->PQDIFF + 1);
    458     }
    459     BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, DQUANTFRM, spr->vop_dquant, pic->DQUANTFRM);
    460     BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, DQPROFILE, spr->vop_dquant, pic->DQPROFILE);
    461     BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, DQES,      spr->vop_dquant, pic->DQSBEDGE);
    462     BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, DQBILEVEL, spr->vop_dquant, pic->DQBILEVEL);
    463 
    464     BF_WRITE(VC1_0_SEQPIC_CURR_FRAME_ID,FCM, spr->ref_frm_id[VC1_FRAME_CURRENT_REF], pic->FCM );
    465 
    466     if ( ptype == VC1_B_FRAME) {
    467          // Forward reference is past reference and is the second temporally closest reference - hence minus_2
    468          BF_WRITE(VC1_0_SEQPIC_FWD_REF_FRAME_ID, FCM, parser->spr.ref_frm_id[VC1_FRAME_PAST], parser->ref_frame[VC1_REF_FRAME_T_MINUS_2].fcm );
    469          // Backward reference is future reference frame and is temporally the closest - hence minus_1
    470          BF_WRITE(VC1_0_SEQPIC_BWD_REF_FRAME_ID, FCM, parser->spr.ref_frm_id[VC1_FRAME_FUTURE], parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm );
    471     } else {
    472          // Only Forward reference is valid and is the temporally closest reference - hence minus_1, backward is set same as forward
    473          BF_WRITE(VC1_0_SEQPIC_FWD_REF_FRAME_ID, FCM, parser->spr.ref_frm_id[VC1_FRAME_PAST], parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm );
    474          BF_WRITE(VC1_0_SEQPIC_BWD_REF_FRAME_ID, FCM, parser->spr.ref_frm_id[VC1_FRAME_FUTURE], parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm );
    475     }
    476 
    477     BF_WRITE( VC1_0_SEQPIC_FIELD_REF_FRAME_ID, TOP_FIELD,    spr->fieldref_ctrl_id, pic->BottomField);
    478     BF_WRITE( VC1_0_SEQPIC_FIELD_REF_FRAME_ID, SECOND_FIELD, spr->fieldref_ctrl_id, pic->CurrField);
    479     if(parser->info.picLayerHeader.PTYPE == VC1_I_FRAME)
    480     {
    481         BF_WRITE(VC1_0_SEQPIC_FIELD_REF_FRAME_ID, ANCHOR, spr->fieldref_ctrl_id, 1);
    482     }
    483     else
    484     {
    485         BF_WRITE(VC1_0_SEQPIC_FIELD_REF_FRAME_ID, ANCHOR, spr->fieldref_ctrl_id, parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].anchor[pic->CurrField]);
    486     }
    487 
    488     if( pic->FCM == VC1_FCM_FIELD_INTERLACE ) {
    489         BF_WRITE(VC1_0_SEQPIC_IMAGE_STRUCTURE, IMG_STRUC, spr->imgstruct, (pic->BottomField) ? 2 : 1);
    490     }
    491 
    492     return;
    493 } // vc1_fill_hw_struct
    494 
    495 int32_t vc1_parse_emit_current_frame(void *parent, vc1_viddec_parser_t *parser)
    496 {
    497    viddec_workload_item_t wi;
    498    const uint32_t *pl;
    499    int i;
    500    int nitems;
    501 
    502     if( parser->info.picLayerHeader.PTYPE == VC1_SKIPPED_FRAME ) {
    503         translate_parser_info_to_frame_attributes( parent, parser );
    504         return 0;
    505     }
    506 
    507    translate_parser_info_to_frame_attributes( parent, parser );
    508    memset(&parser->spr, 0, sizeof(VC1D_SPR_REGS));
    509    vc1_fill_hw_struct( parser, &parser->info, &parser->spr );
    510 
    511    /* STUFF BSP Data Memory it into a variety of workload items */
    512 
    513    pl = (const uint32_t *) &parser->spr;
    514 
    515    // How many payloads must be generated
    516    nitems = (sizeof(parser->spr) + 7) / 8; /* In QWORDs rounded up */
    517 
    518 
    519    // Dump DMEM to an array of workitems
    520    for( i = 0; (i < nitems) && ( (parser->info.picLayerHeader.SLICE_ADDR == 0) || parser->info.picture_info_has_changed ); i++ )
    521    {
    522       wi.vwi_type           = VIDDEC_WORKLOAD_DECODER_SPECIFIC;
    523       wi.data.data_offset   = (unsigned int)pl - (unsigned int)&parser->spr; // offset within struct
    524       wi.data.data_payload[0] = pl[0];
    525       wi.data.data_payload[1] = pl[1];
    526       pl += 2;
    527 
    528       viddec_pm_append_workitem( parent, &wi );
    529    }
    530 
    531    {
    532       uint32_t bit, byte;
    533       uint8_t is_emul;
    534       viddec_pm_get_au_pos(parent, &bit, &byte, &is_emul);
    535       // Send current bit offset and current slice
    536       wi.vwi_type          = VIDDEC_WORKLOAD_VC1_BITOFFSET;
    537       // If slice data starts in the middle of the emulation prevention sequence -
    538       // Eg: 00 00 03 01 - slice data starts at the second byte of 0s, we still feed the data
    539       // to the decoder starting at the first byte of 0s so that the decoder can detect the
    540       // emulation prevention. But the actual data starts are offset 8 in this bit sequence.
    541       wi.vwi_payload[0]    = bit + (is_emul*8);
    542       wi.vwi_payload[1]    = parser->info.picLayerHeader.SLICE_ADDR;
    543       wi.vwi_payload[2]    = 0xdeaddead;
    544       viddec_pm_append_workitem( parent, &wi );
    545    }
    546 
    547    viddec_pm_append_pixeldata( parent );
    548 
    549    return(0);
    550 }
    551 
    552 /* sends VIDDEC_WORKLOAD_VC1_PAST_FRAME item */
    553 static inline void vc1_send_past_ref_items(void *parent)
    554 {
    555    viddec_workload_item_t wi;
    556    wi.vwi_type = VIDDEC_WORKLOAD_VC1_PAST_FRAME;
    557    wi.ref_frame.reference_id = 0;
    558    wi.ref_frame.luma_phys_addr = 0;
    559    wi.ref_frame.chroma_phys_addr = 0;
    560    viddec_pm_append_workitem( parent, &wi );
    561    return;
    562 }
    563 
    564 /* send future frame item */
    565 static inline void vc1_send_future_ref_items(void *parent)
    566 {
    567    viddec_workload_item_t wi;
    568    wi.vwi_type = VIDDEC_WORKLOAD_VC1_FUTURE_FRAME;
    569    wi.ref_frame.reference_id = 0;
    570    wi.ref_frame.luma_phys_addr = 0;
    571    wi.ref_frame.chroma_phys_addr = 0;
    572    viddec_pm_append_workitem( parent, &wi );
    573    return;
    574 }
    575 
    576 /* send reorder frame item to host
    577  * future frame gets push to past   */
    578 static inline void send_reorder_ref_items(void *parent)
    579 {
    580    viddec_workload_item_t wi;
    581    wi.vwi_type = VIDDEC_WORKLOAD_REFERENCE_FRAME_REORDER;
    582    wi.ref_reorder.ref_table_offset = 0;
    583    wi.ref_reorder.ref_reorder_00010203 = 0x01010203; //put reference frame index 1 as reference index 0
    584    wi.ref_reorder.ref_reorder_04050607 = 0x04050607; // index 4,5,6,7 stay the same
    585    viddec_pm_append_workitem( parent, &wi );
    586    return;
    587 } // send_reorder_ref_items
    588 
    589 /** update workload with more workload items for ref and update values to store...
    590  */
    591 void vc1_start_new_frame(void *parent, vc1_viddec_parser_t *parser)
    592 {
    593    vc1_metadata_t *md = &(parser->info.metadata);
    594    viddec_workload_t *wl = viddec_pm_get_header(parent);
    595    int frame_type = parser->info.picLayerHeader.PTYPE;
    596    int frame_id = 1; // new reference frame is assigned index 1
    597 
    598    /* init */
    599    memset(&parser->spr, 0, sizeof(parser->spr));
    600    wl->is_reference_frame = 0;
    601 
    602    /* set flag - extra ouput frame needed for range adjustment (range mapping or range reduction */
    603    if (parser->info.metadata.RANGE_MAPY_FLAG ||
    604         parser->info.metadata.RANGE_MAPUV_FLAG ||
    605         parser->info.picLayerHeader.RANGEREDFRM)
    606    {
    607       wl->is_reference_frame |= WORKLOAD_FLAGS_RA_FRAME;
    608    }
    609 
    610    LOG_CRIT("vc1_start_new_frame: frame_type=%d \n",frame_type);
    611 
    612    parser->is_reference_picture = ((VC1_B_FRAME != frame_type) && (VC1_BI_FRAME != frame_type));
    613 
    614    /* reference / anchor frames processing
    615     * we need to send reorder before reference frames */
    616    if (parser->is_reference_picture)
    617    {
    618       /* one frame has been sent */
    619       if (parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].id != -1)
    620       {
    621          /* there is a frame in the reference buffer, move it to the past */
    622          send_reorder_ref_items(parent);
    623       }
    624    }
    625 
    626    /* send workitems for reference frames */
    627    switch( frame_type )
    628    {
    629       case VC1_B_FRAME:
    630       {
    631           vc1_send_past_ref_items(parent);
    632           vc1_send_future_ref_items(parent);
    633           break;
    634       }
    635       case VC1_SKIPPED_FRAME:
    636       {
    637          wl->is_reference_frame |= WORKLOAD_SKIPPED_FRAME;
    638            vc1_send_past_ref_items(parent);
    639           break;
    640       }
    641       case VC1_P_FRAME:
    642       {
    643           vc1_send_past_ref_items( parent);
    644          break;
    645       }
    646     default:
    647         break;
    648    }
    649 
    650     /* reference / anchor frames from previous code
    651      * we may need it for frame reduction */
    652     if (parser->is_reference_picture)
    653     {
    654         wl->is_reference_frame |= WORKLOAD_REFERENCE_FRAME | (frame_id & WORKLOAD_REFERENCE_FRAME_BMASK);
    655 
    656         parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].id      = frame_id;
    657         parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].fcm     = parser->info.picLayerHeader.FCM;
    658         parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].anchor[0]  = (parser->info.picLayerHeader.PTYPE == VC1_I_FRAME);
    659         if(parser->info.picLayerHeader.FCM == VC1_FCM_FIELD_INTERLACE)
    660         {
    661             parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].anchor[1] = (parser->info.picLayerHeader.PTypeField2 == VC1_I_FRAME);
    662         }
    663         else
    664         {
    665             parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].anchor[1] = parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].anchor[0];
    666         }
    667 
    668         parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].type = parser->info.picLayerHeader.PTYPE;
    669         parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].rr_en = md->RANGERED;
    670         parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].rr_frm = parser->info.picLayerHeader.RANGEREDFRM;
    671 
    672         LOG_CRIT("anchor[0] = %d, anchor[1] = %d",
    673             parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].anchor[0],
    674             parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].anchor[1] );
    675     }
    676 
    677     return;
    678 } // vc1_start_new_frame
    679 
    680 void vc1_end_frame(vc1_viddec_parser_t *parser)
    681 {
    682     /* update status of reference frames */
    683     if(parser->is_reference_picture)
    684     {
    685         parser->ref_frame[VC1_REF_FRAME_T_MINUS_2] = parser->ref_frame[VC1_REF_FRAME_T_MINUS_1];
    686         parser->ref_frame[VC1_REF_FRAME_T_MINUS_1] = parser->ref_frame[VC1_REF_FRAME_T_MINUS_0];
    687     }
    688 
    689     return;
    690 } // vc1_end_frame
    691 
    692