Home | History | Annotate | Download | only in parser
      1 /* ///////////////////////////////////////////////////////////////////////
      2 //
      3 //               INTEL CORPORATION PROPRIETARY INFORMATION
      4 //  This software is supplied under the terms of a license agreement or
      5 //  nondisclosure agreement with Intel Corporation and may not be copied
      6 //  or disclosed except in accordance with the terms of that agreement.
      7 //        Copyright (c) 2008 Intel Corporation. All Rights Reserved.
      8 //
      9 //  Description: Parses VC-1 bitstream layers down to but not including
     10 //  macroblock layer.
     11 //
     12 */
     13 
     14 #include "viddec_fw_debug.h"
     15 #include "vc1parse.h"
     16 
     17 #define VC1_PIXEL_IN_LUMA 16
     18 
     19 /*------------------------------------------------------------------------------
     20  * Parse modified rcv file, start codes are inserted using rcv2vc1.c.
     21  * source is in
     22  * http://svn.jf.intel.com/svn/DHG_Src/CESWE_Src/DEV/trunk/sv/mfd/tools/utils.
     23  * Assumme rcv file width < 90,112 pixel to differenciate from real VC1
     24  * advanced profile header.
     25  * Original rcv description is in annex L
     26  * Table 263 of SMPTE 421M.
     27  */
     28 vc1_Status vc1_ParseRCVSequenceLayer (void* ctxt, vc1_Info *pInfo)
     29 {
     30     uint32_t result;
     31     vc1_Status status = VC1_STATUS_OK;
     32     vc1_metadata_t *md = &pInfo->metadata;
     33     vc1_RcvSequenceHeader rcv;
     34 
     35     memset(&rcv, 0, sizeof(vc1_RcvSequenceHeader));
     36 
     37     result = viddec_pm_get_bits(ctxt, &rcv.struct_a_rcv, 32);
     38     md->width = rcv.struct_a.HORIZ_SIZE;
     39     md->height = rcv.struct_a.VERT_SIZE;
     40 
     41     result = viddec_pm_get_bits(ctxt, &rcv.struct_c_rcv, 32);
     42     md->PROFILE = rcv.struct_c.PROFILE >> 2;
     43     md->LOOPFILTER = rcv.struct_c.LOOPFILTER;
     44     md->MULTIRES = rcv.struct_c.MULTIRES;
     45     md->FASTUVMC = rcv.struct_c.FASTUVMC;
     46     md->EXTENDED_MV = rcv.struct_c.EXTENDED_MV;
     47     md->DQUANT = rcv.struct_c.DQUANT;
     48     md->VSTRANSFORM = rcv.struct_c.VSTRANSFORM;
     49     md->OVERLAP = rcv.struct_c.OVERLAP;
     50     md->RANGERED = rcv.struct_c.RANGERED;
     51     md->MAXBFRAMES = rcv.struct_c.MAXBFRAMES;
     52     md->QUANTIZER = rcv.struct_c.QUANTIZER;
     53     md->FINTERPFLAG = rcv.struct_c.FINTERPFLAG;
     54 #ifdef VBP
     55 	md->SYNCMARKER = rcv.struct_c.SYNCMARKER;
     56 #endif
     57 
     58     if ((md->PROFILE == VC1_PROFILE_SIMPLE) ||
     59         (md->MULTIRES && md->PROFILE == VC1_PROFILE_MAIN))
     60     {
     61         md->DQUANT = 0;
     62     }
     63     // TODO: NEED TO CHECK RESERVED BITS ARE 0
     64 
     65     md->widthMB = (md->width + 15 )  / VC1_PIXEL_IN_LUMA;
     66     md->heightMB = (md->height + 15) / VC1_PIXEL_IN_LUMA;
     67 
     68     DEB("rcv: beforemod: res: %dx%d\n", md->width, md->height);
     69 
     70     /* WL takes resolution in unit of 2 pel - sec. 6.2.13.1 */
     71     md->width = md->width/2 -1;
     72     md->height = md->height/2 -1;
     73 
     74     DEB("rcv: res: %dx%d\n", md->width, md->height);
     75 
     76     // POPULATE WORKLOAD ITEM
     77     {
     78         viddec_workload_item_t wi;
     79 
     80         wi.vwi_type = VIDDEC_WORKLOAD_VC1_SEQ_HDR_STRUCT_A_C;
     81 
     82         wi.vc1_sh_struct_a_c.size = 0;
     83         wi.vc1_sh_struct_a_c.flags = 0;
     84         wi.vc1_sh_struct_a_c.pad = 0;
     85 
     86         viddec_fw_vc1_set_rcv_horiz_size(&wi.vc1_sh_struct_a_c, rcv.struct_a.HORIZ_SIZE);
     87         viddec_fw_vc1_set_rcv_vert_size(&wi.vc1_sh_struct_a_c, rcv.struct_a.VERT_SIZE);
     88 
     89         viddec_fw_vc1_set_rcv_bitrtq_postproc(&wi.vc1_sh_struct_a_c, rcv.struct_c.BITRTQ_POSTPROC);
     90         viddec_fw_vc1_set_rcv_frmrtq_postproc(&wi.vc1_sh_struct_a_c, rcv.struct_c.FRMRTQ_POSTPROC);
     91         viddec_fw_vc1_set_rcv_profile(&wi.vc1_sh_struct_a_c, rcv.struct_c.PROFILE);
     92         viddec_fw_vc1_set_rcv_level(&wi.vc1_sh_struct_a_c, 0);
     93         viddec_fw_vc1_set_rcv_cbr(&wi.vc1_sh_struct_a_c, 0);
     94         viddec_fw_vc1_set_rcv_rangered(&wi.vc1_sh_struct_a_c, rcv.struct_c.RANGERED);
     95         viddec_fw_vc1_set_rcv_maxbframes(&wi.vc1_sh_struct_a_c, rcv.struct_c.MAXBFRAMES);
     96         viddec_fw_vc1_set_rcv_finterpflag(&wi.vc1_sh_struct_a_c, rcv.struct_c.FINTERPFLAG);
     97 
     98         result = viddec_pm_append_workitem(ctxt, &wi);
     99     }
    100 
    101     return status;
    102 }
    103 
    104 /*------------------------------------------------------------------------------
    105  * Parse sequence layer.  This function is only applicable to advanced profile
    106  * as simple and main profiles use other mechanisms to communicate these
    107  * metadata.
    108  * Table 3 of SMPTE 421M.
    109  * Table 13 of SMPTE 421M for HRD_PARAM().
    110  *------------------------------------------------------------------------------
    111  */
    112 
    113 vc1_Status vc1_ParseSequenceLayer(void* ctxt, vc1_Info *pInfo)
    114 {
    115     uint32_t tempValue;
    116     vc1_Status status = VC1_STATUS_OK;
    117     vc1_metadata_t *md = &pInfo->metadata;
    118     vc1_SequenceLayerHeader sh;
    119     uint32_t result;
    120 
    121     memset(&sh, 0, sizeof(vc1_SequenceLayerHeader));
    122 
    123     // PARSE SEQUENCE HEADER
    124     result = viddec_pm_get_bits(ctxt, &sh.flags, 15);
    125     if(result == 1)
    126     {
    127         md->PROFILE = sh.seq_flags.PROFILE;
    128 #ifdef VBP
    129         md->LEVEL = sh.seq_flags.LEVEL;
    130 #endif
    131     }
    132 
    133     result = viddec_pm_get_bits(ctxt, &sh.max_size, 32);
    134     if(result == 1)
    135     {
    136         md->POSTPROCFLAG = sh.seq_max_size.POSTPROCFLAG;
    137         md->width = sh.seq_max_size.MAX_CODED_WIDTH;
    138         md->height = sh.seq_max_size.MAX_CODED_HEIGHT;
    139         md->PULLDOWN = sh.seq_max_size.PULLDOWN;
    140         md->INTERLACE = sh.seq_max_size.INTERLACE;
    141         md->TFCNTRFLAG = sh.seq_max_size.TFCNTRFLAG;
    142         md->FINTERPFLAG = sh.seq_max_size.FINTERPFLAG;
    143         md->PSF = sh.seq_max_size.PSF;
    144     }
    145 
    146     if (sh.seq_max_size.DISPLAY_EXT == 1)
    147     {
    148         result = viddec_pm_get_bits(ctxt, &sh.disp_size, 29);
    149         if(result == 1)
    150         {
    151             if (sh.seq_disp_size.ASPECT_RATIO_FLAG == 1)
    152             {
    153                 result = viddec_pm_get_bits(ctxt, &tempValue, 4);
    154                 sh.ASPECT_RATIO = tempValue;
    155                 if (sh.ASPECT_RATIO == 15)
    156                 {
    157                     result = viddec_pm_get_bits(ctxt, &sh.aspect_size, 16);
    158                 }
    159             }
    160 
    161             result = viddec_pm_get_bits(ctxt, &tempValue, 1);
    162             sh.FRAMERATE_FLAG = tempValue;
    163             if (sh.FRAMERATE_FLAG == 1)
    164             {
    165                 result = viddec_pm_get_bits(ctxt, &tempValue, 1);
    166                 sh.FRAMERATEIND = tempValue;
    167                 if (sh.FRAMERATEIND == 0)
    168                 {
    169                     result = viddec_pm_get_bits(ctxt, &sh.framerate_fraction, 12);
    170                 }
    171                 else
    172                 {
    173                     result = viddec_pm_get_bits(ctxt, &tempValue, 16);
    174                     sh.FRAMERATEEXP = tempValue;
    175                 }
    176             }
    177 
    178             result = viddec_pm_get_bits(ctxt, &tempValue, 1);
    179             sh.COLOR_FORMAT_FLAG = tempValue;
    180             if (sh.COLOR_FORMAT_FLAG == 1)
    181             {
    182                 result = viddec_pm_get_bits(ctxt, &sh.color_format, 24);
    183             }
    184         } // Successful get of display size
    185     } // DISPLAY_EXT is 1
    186 
    187     result = viddec_pm_get_bits(ctxt, &tempValue, 1);
    188     sh.HRD_PARAM_FLAG = tempValue;
    189     if (sh.HRD_PARAM_FLAG == 1)
    190     {
    191         /* HRD_PARAM(). */
    192         result = viddec_pm_get_bits(ctxt, &tempValue, 5);
    193         sh.HRD_NUM_LEAKY_BUCKETS = tempValue;
    194         md->HRD_NUM_LEAKY_BUCKETS = sh.HRD_NUM_LEAKY_BUCKETS;
    195         // Skip the rest of the parsing - hrdinfo is not required for decode or for attributes
    196     }
    197     else
    198     {
    199         md->HRD_NUM_LEAKY_BUCKETS = 0;
    200     }
    201 
    202     md->widthMB = (((md->width + 1) * 2) + 15) / VC1_PIXEL_IN_LUMA;
    203     md->heightMB = (((md->height + 1) * 2) + 15) / VC1_PIXEL_IN_LUMA;
    204 
    205     DEB("md: res: %dx%d\n", md->width, md->height);
    206     DEB("sh: dispres: %dx%d\n", sh.seq_disp_size.DISP_HORIZ_SIZE, sh.seq_disp_size.DISP_VERT_SIZE);
    207 
    208     // POPULATE WORKLOAD ITEM
    209     {
    210         viddec_workload_item_t wi_sl, wi_de;
    211 
    212         wi_sl.vwi_type = VIDDEC_WORKLOAD_SEQUENCE_INFO;
    213 
    214         wi_sl.vc1_sl.size = 0;
    215         wi_sl.vc1_sl.flags = 0;
    216         wi_sl.vc1_sl.pad = 0;
    217 
    218         viddec_fw_vc1_set_profile(&wi_sl.vc1_sl, sh.seq_flags.PROFILE);
    219         viddec_fw_vc1_set_level(&wi_sl.vc1_sl, sh.seq_flags.LEVEL);
    220         viddec_fw_vc1_set_colordiff_format(&wi_sl.vc1_sl, sh.seq_flags.COLORDIFF_FORMAT);
    221         viddec_fw_vc1_set_pulldown(&wi_sl.vc1_sl, sh.seq_max_size.PULLDOWN);
    222         viddec_fw_vc1_set_max_coded_width(&wi_sl.vc1_sl, sh.seq_max_size.MAX_CODED_WIDTH);
    223         viddec_fw_vc1_set_max_coded_height(&wi_sl.vc1_sl, sh.seq_max_size.MAX_CODED_HEIGHT);
    224 
    225         viddec_fw_vc1_set_bitrtq_postproc(&wi_sl.vc1_sl, sh.seq_flags.BITRTQ_POSTPROC);
    226         viddec_fw_vc1_set_frmrtq_postproc(&wi_sl.vc1_sl, sh.seq_flags.FRMRTQ_POSTPROC);
    227         viddec_fw_vc1_set_interlace(&wi_sl.vc1_sl, sh.seq_max_size.INTERLACE);
    228         viddec_fw_vc1_set_tfcntrflag(&wi_sl.vc1_sl, sh.seq_max_size.TFCNTRFLAG);
    229         viddec_fw_vc1_set_finterpflag(&wi_sl.vc1_sl, sh.seq_max_size.FINTERPFLAG);
    230         viddec_fw_vc1_set_psf(&wi_sl.vc1_sl, sh.seq_max_size.PSF);
    231         viddec_fw_vc1_set_display_ext(&wi_sl.vc1_sl, sh.seq_max_size.DISPLAY_EXT);
    232 
    233         result = viddec_pm_append_workitem(ctxt, &wi_sl);
    234 
    235         // send DISPLAY EXTENSION metadata if present
    236         if (sh.seq_max_size.DISPLAY_EXT)
    237         {
    238             wi_de.vwi_type = VIDDEC_WORKLOAD_DISPLAY_INFO;
    239 
    240             wi_de.vc1_sl_de.size = 0;
    241             wi_de.vc1_sl_de.framerate = 0;
    242             wi_de.vc1_sl_de.aspectsize = 0;
    243 
    244             viddec_fw_vc1_set_disp_horiz_size(&wi_de.vc1_sl_de, sh.seq_disp_size.DISP_HORIZ_SIZE);
    245             viddec_fw_vc1_set_disp_vert_size(&wi_de.vc1_sl_de, sh.seq_disp_size.DISP_VERT_SIZE);
    246             viddec_fw_vc1_set_disp_aspect_ratio_flag(&wi_de.vc1_sl_de, sh.seq_disp_size.ASPECT_RATIO_FLAG);
    247             viddec_fw_vc1_set_disp_color_format_flag(&wi_de.vc1_sl_de, sh.COLOR_FORMAT_FLAG);
    248             viddec_fw_vc1_set_disp_framerate_flag(&wi_de.vc1_sl_de, sh.FRAMERATE_FLAG);
    249             viddec_fw_vc1_set_disp_framerateind(&wi_de.vc1_sl_de, sh.FRAMERATEIND);
    250 
    251             viddec_fw_vc1_set_disp_aspect_ratio(&wi_de.vc1_sl_de, sh.ASPECT_RATIO);
    252             viddec_fw_vc1_set_disp_frameratenr(&wi_de.vc1_sl_de, sh.seq_framerate_fraction.FRAMERATENR);
    253             viddec_fw_vc1_set_disp_frameratedr(&wi_de.vc1_sl_de, sh.seq_framerate_fraction.FRAMERATEDR);
    254             viddec_fw_vc1_set_disp_framerateexp(&wi_de.vc1_sl_de, sh.FRAMERATEEXP);
    255 
    256             viddec_fw_vc1_set_disp_aspect_ratio_horiz_size(&wi_de.vc1_sl_de, sh.seq_aspect_size.ASPECT_HORIZ_SIZE);
    257             viddec_fw_vc1_set_disp_aspect_ratio_vert_size(&wi_de.vc1_sl_de, sh.seq_aspect_size.ASPECT_VERT_SIZE);
    258             viddec_fw_vc1_set_disp_color_prim(&wi_de.vc1_sl_de, sh.seq_color_format.COLOR_PRIM);
    259             viddec_fw_vc1_set_disp_transfer_char(&wi_de.vc1_sl_de, sh.seq_color_format.TRANSFER_CHAR);
    260 
    261             result = viddec_pm_append_workitem(ctxt, &wi_de);
    262         }
    263     }
    264 
    265     return status;
    266 }
    267 
    268 /*------------------------------------------------------------------------------
    269  * Parse entry point layer.  This function is only applicable for advanced
    270  * profile and is used to signal a random access point and changes in coding
    271  * control parameters.
    272  * Table 14 of SMPTE 421M.
    273  * Table 15 of SMPTE 421M for HRD_FULLNESS().
    274  *------------------------------------------------------------------------------
    275  */
    276 vc1_Status vc1_ParseEntryPointLayer(void* ctxt, vc1_Info *pInfo)
    277 {
    278     vc1_Status status = VC1_STATUS_OK;
    279     vc1_metadata_t *md = &pInfo->metadata;
    280     vc1_EntryPointHeader ep;
    281     uint32_t result;
    282     uint32_t temp;
    283 
    284     memset(&ep, 0, sizeof(vc1_EntryPointHeader));
    285 
    286     // PARSE ENTRYPOINT HEADER
    287     result = viddec_pm_get_bits(ctxt, &ep.flags, 13);
    288     if(result == 1)
    289     {
    290         // Skip the flags already peeked at (13) and the unneeded hrd_full data
    291         // NOTE: HRD_NUM_LEAKY_BUCKETS is initialized to 0 when HRD_PARAM_FLAG is not present
    292         int hrd_bits = md->HRD_NUM_LEAKY_BUCKETS * 8;
    293         while(hrd_bits >= 32)
    294         {
    295             result = viddec_pm_skip_bits(ctxt, 32);
    296             hrd_bits -= 32;
    297         }
    298         result = viddec_pm_skip_bits(ctxt, hrd_bits);
    299 
    300         md->REFDIST = 0;
    301         md->PANSCAN_FLAG = ep.ep_flags.PANSCAN_FLAG;
    302         md->REFDIST_FLAG = ep.ep_flags.REFDIST_FLAG;
    303         md->LOOPFILTER = ep.ep_flags.LOOPFILTER;
    304         md->FASTUVMC = ep.ep_flags.FASTUVMC;
    305         md->EXTENDED_MV = ep.ep_flags.EXTENDED_MV;
    306         md->DQUANT = ep.ep_flags.DQUANT;
    307         md->VSTRANSFORM = ep.ep_flags.VSTRANSFORM;
    308         md->OVERLAP = ep.ep_flags.OVERLAP;
    309         md->QUANTIZER = ep.ep_flags.QUANTIZER;
    310 
    311         result = viddec_pm_get_bits(ctxt, &temp, 1);
    312         if(result == 1)
    313         {
    314             ep.CODED_SIZE_FLAG = temp;
    315             if(ep.CODED_SIZE_FLAG)
    316             {
    317                 result = viddec_pm_get_bits(ctxt, &ep.size, 24);
    318                 md->width = ep.ep_size.CODED_WIDTH;
    319                 md->height = ep.ep_size.CODED_HEIGHT;
    320             }
    321         }
    322         if(ep.ep_flags.EXTENDED_MV)
    323         {
    324             result = viddec_pm_get_bits(ctxt, &temp, 1);
    325             md->EXTENDED_DMV = ep.EXTENDED_DMV = temp;
    326         }
    327 
    328         result = viddec_pm_get_bits(ctxt, &temp, 1);
    329         if(result == 1)
    330         {
    331             md->RANGE_MAPY_FLAG = ep.RANGE_MAPY_FLAG = temp;
    332             if(ep.RANGE_MAPY_FLAG)
    333             {
    334                 result = viddec_pm_get_bits(ctxt, &temp, 3);
    335                 md->RANGE_MAPY = ep.RANGE_MAPY = temp;
    336             }
    337         }
    338 
    339         result = viddec_pm_get_bits(ctxt, &temp, 1);
    340         if(result == 1)
    341         {
    342             md->RANGE_MAPUV_FLAG = ep.RANGE_MAPUV_FLAG = temp;
    343             if(ep.RANGE_MAPUV_FLAG)
    344             {
    345                 result = viddec_pm_get_bits(ctxt, &temp, 3);
    346                 md->RANGE_MAPUV = ep.RANGE_MAPUV = temp;
    347             }
    348         }
    349     }
    350 
    351     // POPULATE WORKLOAD ITEM
    352     {
    353         viddec_workload_item_t wi;
    354 
    355         wi.vwi_type = VIDDEC_WORKLOAD_GOP_INFO;
    356 
    357         wi.vc1_ep.size = 0;
    358         wi.vc1_ep.flags = 0;
    359         wi.vc1_ep.pad = 0;
    360 
    361         viddec_fw_vc1_set_ep_size_flag(&wi.vc1_ep, ep.CODED_SIZE_FLAG);
    362         viddec_fw_vc1_set_ep_horiz_size(&wi.vc1_ep, ep.ep_size.CODED_WIDTH);
    363         viddec_fw_vc1_set_ep_vert_size(&wi.vc1_ep, ep.ep_size.CODED_HEIGHT);
    364 
    365         viddec_fw_vc1_set_ep_broken_link(&wi.vc1_ep, ep.ep_flags.BROKEN_LINK);
    366         viddec_fw_vc1_set_ep_closed_entry(&wi.vc1_ep, ep.ep_flags.CLOSED_ENTRY);
    367         viddec_fw_vc1_set_ep_panscan_flag(&wi.vc1_ep, ep.ep_flags.PANSCAN_FLAG);
    368         viddec_fw_vc1_set_ep_range_mapy_flag(&wi.vc1_ep, ep.RANGE_MAPY_FLAG);
    369         viddec_fw_vc1_set_ep_range_mapy(&wi.vc1_ep, ep.RANGE_MAPY);
    370         viddec_fw_vc1_set_ep_range_mapuv_flag(&wi.vc1_ep, ep.RANGE_MAPUV_FLAG);
    371         viddec_fw_vc1_set_ep_range_mapuv(&wi.vc1_ep, ep.RANGE_MAPUV);
    372 
    373         result = viddec_pm_append_workitem(ctxt, &wi);
    374     }
    375 
    376 #ifdef VBP
    377     md->BROKEN_LINK = ep.ep_flags.BROKEN_LINK;
    378     md->CLOSED_ENTRY = ep.ep_flags.CLOSED_ENTRY;
    379 #endif
    380 
    381     DEB("ep: res: %dx%d\n", ep.ep_size.CODED_WIDTH, ep.ep_size.CODED_HEIGHT);
    382     DEB("md: after ep: res: %dx%d\n", md->width, md->height);
    383     return status;
    384 }
    385 
    386 /*------------------------------------------------------------------------------
    387  * Parse picture layer.  This function parses the picture layer.
    388  *------------------------------------------------------------------------------
    389  */
    390 
    391 vc1_Status vc1_ParsePictureLayer(void* ctxt, vc1_Info *pInfo)
    392 {
    393     vc1_Status status = VC1_STATUS_OK;
    394     uint32_t temp;
    395     int i;
    396 
    397     for(i=0; i<VC1_MAX_BITPLANE_CHUNKS; i++)
    398     {
    399         pInfo->metadata.bp_raw[i] = true;
    400     }
    401 
    402     if (pInfo->metadata.PROFILE == VC1_PROFILE_ADVANCED)
    403     {
    404         VC1_PEEK_BITS(2, temp); /* fcm */
    405         if( (pInfo->metadata.INTERLACE == 1) && (temp == VC1_FCM_FIELD_INTERLACE))
    406         {
    407             status = vc1_ParseFieldHeader_Adv(ctxt, pInfo);
    408         }
    409         else
    410         {
    411             status = vc1_ParsePictureHeader_Adv(ctxt, pInfo);
    412         }
    413     }
    414     else
    415     {
    416         status = vc1_ParsePictureHeader(ctxt, pInfo);
    417     }
    418 
    419     return status;
    420 }
    421 
    422 /*------------------------------------------------------------------------------
    423  * Parse field picture layer.  This function parses the field picture layer.
    424  *------------------------------------------------------------------------------
    425  */
    426 
    427 vc1_Status vc1_ParseFieldLayer(void* ctxt, vc1_Info *pInfo)
    428 {
    429     vc1_Status status = VC1_STATUS_PARSE_ERROR;
    430     vc1_PictureLayerHeader *picLayerHeader = &pInfo->picLayerHeader;
    431 
    432     if (pInfo->metadata.PROFILE == VC1_PROFILE_ADVANCED) {
    433         if (picLayerHeader->CurrField == 0)
    434         {
    435             picLayerHeader->PTYPE = picLayerHeader->PTypeField1;
    436             picLayerHeader->BottomField = (uint8_t) (1 - picLayerHeader->TFF);
    437         }
    438         else
    439         {
    440             picLayerHeader->BottomField = (uint8_t) (picLayerHeader->TFF);
    441             picLayerHeader->PTYPE = picLayerHeader->PTypeField2;
    442         }
    443         status = vc1_ParsePictureFieldHeader_Adv(ctxt, pInfo);
    444     }
    445 
    446     return status;
    447 }
    448 
    449 /*------------------------------------------------------------------------------
    450  * Parse slice layer.  This function parses the slice layer, which is only
    451  * supported by advanced profile.
    452  * Table 26 of SMPTE 421M but skipping parsing of macroblock layer.
    453  *------------------------------------------------------------------------------
    454  */
    455 
    456 vc1_Status vc1_ParseSliceLayer(void* ctxt, vc1_Info *pInfo)
    457 {
    458     uint32_t tempValue;
    459     uint32_t SLICE_ADDR;
    460     vc1_Status status = VC1_STATUS_OK;
    461 
    462     VC1_GET_BITS9(9, SLICE_ADDR);
    463     VC1_GET_BITS9(1, tempValue); /* PIC_HEADER_FLAG. */
    464     if (tempValue == 1) {
    465         uint8_t *last_bufptr = pInfo->bufptr;
    466         uint32_t last_bitoff = pInfo->bitoff;
    467         status = vc1_ParsePictureLayer(ctxt, pInfo);
    468         pInfo->picture_info_has_changed = 1;
    469         if( status ) {
    470             /* FIXME - is this a good way of handling this? Failed, see if it's for fields */
    471             pInfo->bufptr = last_bufptr;
    472             pInfo->bitoff = last_bitoff;
    473             status = vc1_ParseFieldHeader_Adv(ctxt, pInfo);
    474         }
    475     } else
    476         pInfo->picture_info_has_changed = 0;
    477 
    478     pInfo->picLayerHeader.SLICE_ADDR = SLICE_ADDR;
    479 
    480     return status;
    481 }
    482 
    483 /*------------------------------------------------------------------------------
    484  * This function parses the user data information as defined in SMPTE 421M annex F.
    485  * It then appends that data to the workload.
    486  * Assume the flush byte 0x80 is within the 3 bytes before next start code.
    487  * let's put 1 byte per item first
    488  *------------------------------------------------------------------------------
    489  */
    490 vc1_Status vc1_ParseAndAppendUserData(void* ctxt, uint32_t sc)
    491 {
    492     vc1_Status status = VC1_STATUS_OK;
    493     uint32_t user_data;
    494     viddec_workload_item_t wi;
    495     uint32_t ud_id;
    496 
    497     /* find the scope based on start code sc */
    498     switch(sc) {
    499         case vc1_SCSequenceUser:
    500             wi.vwi_type = VIDDEC_WORKLOAD_SEQ_USER_DATA;
    501             break;
    502         case vc1_SCEntryPointUser:
    503             wi.vwi_type = VIDDEC_WORKLOAD_GOP_USER_DATA;
    504             break;
    505         case vc1_SCFrameUser:
    506             wi.vwi_type = VIDDEC_WORKLOAD_FRM_USER_DATA;
    507             break;
    508         case vc1_SCFieldUser:
    509             wi.vwi_type = VIDDEC_WORKLOAD_FLD_USER_DATA;
    510             break;
    511         case vc1_SCSliceUser:
    512             wi.vwi_type = VIDDEC_WORKLOAD_SLC_USER_DATA;
    513             break;
    514         default:
    515             wi.vwi_type = VIDDEC_WORKLOAD_INVALID; //ERROR - should not happen
    516             break;
    517     }
    518 
    519     /* get identifier - 4 bytes*/
    520     // Extract this information but discard it for now
    521     VC1_GET_BITS(32, ud_id);
    522 
    523     /* Read 1 byte of user data and store it in workitem for the current stream level (SEQ/GOP/PIC).
    524        Keep adding data payloads till it reaches size 11. When it is 11, the maximum user data payload size,
    525        append the workitem. This loop is repeated till all user data is extracted and appended. */
    526     wi.user_data.size = 0;
    527     while(viddec_pm_get_bits(ctxt, &user_data, 8) != -1)
    528     {
    529         /* Store the valid byte in data payload */
    530         wi.user_data.data_payload[wi.user_data.size] = user_data;
    531         wi.user_data.size++;
    532 
    533         /* When size exceeds payload size, append workitem and continue */
    534         if (wi.user_data.size >= 11)
    535         {
    536             viddec_pm_setup_userdata(&wi);
    537             viddec_pm_append_workitem(ctxt, &wi);
    538             wi.user_data.size = 0;
    539         }
    540         if(user_data == 0x80) // flushing byte
    541             break;
    542     }
    543     /* If size is not 0, append remaining user data. */
    544     if (wi.user_data.size > 0)
    545     {
    546         int i;
    547         for(i=wi.user_data.size;i<11;i++)
    548         {
    549             wi.user_data.data_payload[i] = 0;
    550         }
    551         viddec_pm_setup_userdata(&wi);
    552         viddec_pm_append_workitem(ctxt, &wi);
    553         wi.user_data.size = 0;
    554     }
    555 
    556     return(status);
    557 } // vc1_ParseAndAppendUserData
    558