Home | History | Annotate | Download | only in parser
      1 /**
      2  * viddec_mpeg2_metadata.c
      3  * -----------------------
      4  * This file contains all the routines to parse the information from MPEG2
      5  * elementary stream and store it in the parser context. Based on the data
      6  * parsed, the state information in the context is updated.
      7  *
      8  * Headers currently parsed from MPEG2 stream include:
      9  * - Sequence Header
     10  * - Sequence Extension
     11  * - Sequence Display Extension
     12  * - GOP Header
     13  * - Picture Header
     14  * - Picture Coding Extension
     15  * - Quantization Matrix Extension
     16  * - Picture Display Extension
     17  *
     18  * The slice data is parsed and appended into workload in viddec_mpeg2_parse.c
     19  */
     20 
     21 #include "viddec_mpeg2.h"
     22 
     23 /* Default quantization matrix values */
     24 const uint8_t mpeg2_default_intra_quant_matrix[MPEG2_QUANT_MAT_SIZE] = {
     25     8, 16, 19, 22, 26, 27, 29, 34,
     26     16, 16, 22, 24, 27, 29, 34, 37,
     27     19, 22, 26, 27, 29, 34, 34, 38,
     28     22, 22, 26, 27, 29, 34, 37, 40,
     29     22, 26, 27, 29, 32, 35, 40, 48,
     30     26, 27, 29, 32, 35, 40, 48, 58,
     31     26, 27, 29, 34, 38, 46, 56, 69,
     32     27, 29, 35, 38, 46, 56, 69, 83
     33 };
     34 const uint8_t mpeg2_default_non_intra_quant_matrix[MPEG2_QUANT_MAT_SIZE] = {
     35     16, 16, 16, 16, 16, 16, 16, 16,
     36     16, 16, 16, 16, 16, 16, 16, 16,
     37     16, 16, 16, 16, 16, 16, 16, 16,
     38     16, 16, 16, 16, 16, 16, 16, 16,
     39     16, 16, 16, 16, 16, 16, 16, 16,
     40     16, 16, 16, 16, 16, 16, 16, 16,
     41     16, 16, 16, 16, 16, 16, 16, 16,
     42     16, 16, 16, 16, 16, 16, 16, 16
     43 };
     44 
     45 /* Matrix for converting scan order */
     46 const uint8_t mpeg2_classic_scan[MPEG2_QUANT_MAT_SIZE] = {
     47      0,  1,  8, 16,  9,  2,  3, 10,
     48     17, 24, 32, 25, 18, 11,  4,  5,
     49     12, 19, 26, 33, 40, 48, 41, 34,
     50     27, 20, 13,  6,  7, 14, 21, 28,
     51     35, 42, 49, 56, 57, 50, 43, 36,
     52     29, 22, 15, 23, 30, 37, 44, 51,
     53     58, 59, 52, 45, 38, 31, 39, 46,
     54     53, 60, 61, 54, 47, 55, 62, 63
     55 };
     56 const uint8_t mpeg2_alternate_scan[MPEG2_QUANT_MAT_SIZE] = {
     57      0,  8, 16, 24,  1,  9,  2, 10,
     58     17, 25, 32, 40, 48, 56, 57, 49,
     59     41, 33, 26, 18,  3, 11,  4, 12,
     60     19, 27, 34, 42, 50, 58, 35, 43,
     61     51, 59, 20, 28,  5, 13,  6, 14,
     62     21, 29, 36, 44, 52, 60, 37, 45,
     63     53, 61, 22, 30,  7, 15, 23, 31,
     64     38, 46, 54, 62, 39, 47, 55, 63
     65 };
     66 
     67 /* Look-up tables for macro block address increment VLC */
     68 const uint8_t mb_addr_inc_tab1[16] = {
     69     0, 0, 7, 6, 5, 5, 4, 4,
     70     3, 3, 3, 3, 2, 2, 2, 2
     71 };
     72 const uint8_t mb_addr_inc_tab2[8] = {
     73     13, 12, 11, 10, 9, 9, 8, 8
     74 };
     75 const uint8_t mb_addr_inc_tab3[40] = {
     76     33, 32, 31, 30, 29, 28, 27, 26,
     77     25, 24, 23, 22, 21, 21, 20, 20,
     78     19, 19, 18, 18, 17, 17, 16, 16,
     79     15, 15, 15, 15, 15, 15, 15, 15,
     80     14, 14, 14, 14, 14, 14, 14, 14
     81 };
     82 
     83 /* viddec_mpeg2_copy_default_matrix() - Copies quantization matrix from src  */
     84 /* to dst                                                                    */
     85 static inline void mpeg2_copy_matrix(const uint8_t *src, uint8_t *dst)
     86 {
     87     register uint32_t index = 0;
     88     for(index=0; index < MPEG2_QUANT_MAT_SIZE; index++)
     89         dst[index] = src[index];
     90 }
     91 
     92 /* viddec_mpeg2_copy_matrix() - Copies next 64bytes in the stream into given */
     93 /* matrix                                                                    */
     94 static inline int32_t mpeg2_get_quant_matrix(void *parent, uint8_t *matrix, uint32_t alternate_scan)
     95 {
     96 	int32_t ret = 1;
     97     uint32_t index = 0, code = 0;
     98     const uint8_t  *zigzag_scan = (const uint8_t *) mpeg2_classic_scan;
     99 
    100     if (alternate_scan)
    101     {
    102         zigzag_scan = (const uint8_t *) mpeg2_alternate_scan;
    103     }
    104 
    105     /* Start extracting matrix co-efficients and copy them in */
    106     /* inverse zigzag scan order */
    107     for (index = 0; index < MPEG2_QUANT_MAT_SIZE; index++)
    108     {
    109         ret = viddec_pm_get_bits(parent, &code, MPEG2_BITS_EIGHT);
    110         /* Quantization values cannot be zero. If zero value if found, */
    111         /* further parsing is stopped and the existing values are used.*/
    112         if ((ret != 1) || (code == 0))
    113         {
    114         	ret = -1;
    115             break;
    116         }
    117         matrix[zigzag_scan[index]] = (uint8_t)(code & 0xFF);
    118     }
    119 
    120     return ret;
    121 }
    122 
    123 /* viddec_mpeg2_parse_seq_hdr() - Parse sequence header metadata and store   */
    124 /* in parser context                                                         */
    125 void viddec_mpeg2_parse_seq_hdr(void *parent, void *ctxt)
    126 {
    127     int32_t ret_code = 0;
    128 
    129     /* Get MPEG2 Parser context */
    130     struct viddec_mpeg2_parser *parser = (struct viddec_mpeg2_parser *) ctxt;
    131 
    132     /* Get Horizontal Frame Size */
    133     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_hdr.horizontal_size_value, 12);
    134 
    135     /* Get Vertical Frame Size */
    136     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_hdr.vertical_size_value, 12);
    137 
    138     /* Get Frame Aspect Ratio */
    139     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_hdr.aspect_ratio_information, 4);
    140 
    141     /* Get Frame Rate */
    142     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_hdr.frame_rate_code, 4);
    143 
    144     /* Get Bit Rate */
    145     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_hdr.bit_rate_value, 18);
    146 
    147     /* Skip Marker bit */
    148     ret_code |= viddec_pm_skip_bits(parent, 1);
    149 
    150     /* Get VBV Buffer Size Value */
    151     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_hdr.vbv_buffer_size_value, 10);
    152 
    153     /* Get Constrained Parameters Flag */
    154     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_hdr.constrained_parameters_flag, 1);
    155 
    156     /* Quantization Matrix Support */
    157     /* Get Intra Quantizer matrix, if available or use default values */
    158     ret_code |= viddec_pm_get_bits(parent, &parser->info.qnt_ext.load_intra_quantiser_matrix, 1);
    159     if (parser->info.qnt_ext.load_intra_quantiser_matrix)
    160     {
    161         ret_code |= mpeg2_get_quant_matrix(parent, parser->info.qnt_mat.intra_quantiser_matrix, 0);
    162         mpeg2_copy_matrix(parser->info.qnt_mat.intra_quantiser_matrix, parser->info.qnt_mat.chroma_intra_quantiser_matrix);
    163     }
    164     else
    165     {
    166         if (!parser->mpeg2_custom_qmat_parsed)
    167         {
    168             mpeg2_copy_matrix(mpeg2_default_intra_quant_matrix, parser->info.qnt_mat.intra_quantiser_matrix);
    169             mpeg2_copy_matrix(mpeg2_default_intra_quant_matrix, parser->info.qnt_mat.chroma_intra_quantiser_matrix);
    170         }
    171     }
    172 
    173     /* Get Non-Intra Qualtizer matrix, if available or use default values */
    174     ret_code |= viddec_pm_get_bits(parent, &parser->info.qnt_ext.load_non_intra_quantiser_matrix, 1);
    175     if (parser->info.qnt_ext.load_non_intra_quantiser_matrix)
    176     {
    177         ret_code |= mpeg2_get_quant_matrix(parent, parser->info.qnt_mat.non_intra_quantiser_matrix, 0);
    178         mpeg2_copy_matrix(parser->info.qnt_mat.non_intra_quantiser_matrix, parser->info.qnt_mat.chroma_non_intra_quantiser_matrix);
    179     }
    180     else
    181     {
    182         if (!parser->mpeg2_custom_qmat_parsed)
    183         {
    184             mpeg2_copy_matrix(mpeg2_default_non_intra_quant_matrix, parser->info.qnt_mat.non_intra_quantiser_matrix);
    185             mpeg2_copy_matrix(mpeg2_default_non_intra_quant_matrix, parser->info.qnt_mat.chroma_non_intra_quantiser_matrix);
    186         }
    187     }
    188 
    189     /* Error handling */
    190     /* The return value from get_bits() function is accumulated. If the return value is not 1, */
    191     /* then there was an error getting the required information from the stream and the status */
    192     /* is updated for the current workload. */
    193     if (ret_code == 1)
    194     {
    195         /* This flag indicates a valid sequence header has been parsed and so even if */
    196         /* a sequence haeder is corrupted in the future, this valid sequence header   */
    197         /* could be reused. */
    198         parser->mpeg2_valid_seq_hdr_parsed = true;
    199         /* This flag indicates a valid custom quantization matrix has been parsed.  */
    200         /* So, if in the future, there is an error parsing quantization matrix, the */
    201         /* parser will use the previously parsed custom values. */
    202         if ((parser->info.qnt_ext.load_intra_quantiser_matrix)
    203             || (parser->info.qnt_ext.load_non_intra_quantiser_matrix))
    204         {
    205             parser->mpeg2_custom_qmat_parsed = true;
    206         }
    207         MPEG2_DEB("Seqeunce header parsed successfully.\n");
    208     }
    209     else
    210     {
    211         /* Setting status to mark parser error while emitting the current workload. */
    212         parser->mpeg2_wl_status |= MPEG2_WL_CORRUPTED_SEQ_HDR;
    213         MPEG2_DEB("Sequence header corrupted.\n");
    214     }
    215 
    216     parser->mpeg2_stream               = false;
    217     parser->mpeg2_curr_seq_headers    |= MPEG2_HEADER_SEQ;
    218     parser->mpeg2_curr_frame_headers  |= MPEG2_HEADER_SEQ;
    219     parser->mpeg2_stream_level         = MPEG2_LEVEL_SEQ;
    220 
    221     return;
    222 }
    223 
    224 /* viddec_mpeg2_parse_gop_hdr() - Parse group of pictures header info and    */
    225 /* store it in parser context                                                */
    226 void viddec_mpeg2_parse_gop_hdr(void *parent, void *ctxt)
    227 {
    228     int32_t ret_code = 0;
    229 
    230     /* Get MPEG2 Parser context */
    231     struct viddec_mpeg2_parser *parser = (struct viddec_mpeg2_parser *) ctxt;
    232 
    233     /* Skip first 25 bits */
    234     /* Skip time_code */
    235     ret_code |= viddec_pm_skip_bits(parent, 25);
    236 
    237     /* Get closed gop info */
    238     ret_code |= viddec_pm_get_bits(parent, &parser->info.gop_hdr.closed_gop, 1);
    239 
    240     /* Get broken link info */
    241     ret_code |= viddec_pm_get_bits(parent, &parser->info.gop_hdr.broken_link, 1);
    242 
    243     if (ret_code == 1)
    244     {
    245         MPEG2_DEB("GOP Header parsed successfully.\n");
    246     }
    247     else
    248     {
    249         parser->mpeg2_wl_status |= MPEG2_WL_CORRUPTED_GOP_HDR;
    250         MPEG2_DEB("GOP header corrupted.\n");
    251     }
    252 
    253     parser->mpeg2_curr_frame_headers |= MPEG2_HEADER_GOP;
    254     parser->mpeg2_stream_level        = MPEG2_LEVEL_GOP;
    255 
    256     return;
    257 }
    258 
    259 /* viddec_mpeg2_parse_pic_hdr() - Parse picture header info and store it in  */
    260 /* parser context                                                            */
    261 void viddec_mpeg2_parse_pic_hdr(void *parent, void *ctxt)
    262 {
    263     int32_t ret_code = 0, found_error = 0;
    264 
    265     /* Get MPEG2 Parser context */
    266     struct viddec_mpeg2_parser *parser = (struct viddec_mpeg2_parser *) ctxt;
    267 
    268     /* Get Temporal Reference info */
    269     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_hdr.temporal_reference, 10);
    270 
    271     /* Get Picture Coding type and skip the following byte */
    272     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_hdr.picture_coding_type, 3);
    273 
    274     /* Error Handling and Concealment */
    275     /* Picture coding type should be one I, P or B */
    276     if ((parser->info.pic_hdr.picture_coding_type != MPEG2_PC_TYPE_I) &&
    277         (parser->info.pic_hdr.picture_coding_type != MPEG2_PC_TYPE_P) &&
    278         (parser->info.pic_hdr.picture_coding_type != MPEG2_PC_TYPE_B))
    279     {
    280         found_error = 1;
    281     }
    282     /* The first frame after a gop header should be a coded I picture as per */
    283     /* section 6.3.1 in MPEG2 Specification. */
    284     else if (parser->mpeg2_curr_frame_headers & MPEG2_HEADER_GOP)
    285     {
    286         if (parser->info.pic_hdr.picture_coding_type != MPEG2_PC_TYPE_I)
    287         {
    288             found_error = 1;
    289         }
    290     }
    291     /* The first frame after a sequence header cannot be a coded B picture as per */
    292     /* section 6.1.1.6 in MPEG2 Specification. */
    293     else if (parser->mpeg2_curr_frame_headers & MPEG2_HEADER_SEQ)
    294     {
    295         if (parser->info.pic_hdr.picture_coding_type == MPEG2_PC_TYPE_B)
    296         {
    297             found_error = 1;
    298         }
    299     }
    300 
    301     /* If there is an error parsing picture coding type, do error concealment and continue. */
    302     if ((ret_code != 1) || (found_error))
    303     {
    304         if (found_error)
    305         {
    306             /* Setting status to mark parser error while emitting the current workload. */
    307             parser->mpeg2_wl_status |= MPEG2_WL_CORRUPTED_PIC_HDR;
    308             MPEG2_DEB("Picture header corrupted.\n");
    309         }
    310 
    311         /* Error concealment for picture coding type - Default to I picture. */
    312         parser->info.pic_hdr.picture_coding_type = MPEG2_PC_TYPE_I;
    313         parser->mpeg2_wl_status |= MPEG2_WL_CONCEALED_PIC_COD_TYPE;
    314         MPEG2_DEB("Picture Coding Type corrupted. Concealing to I type.\n");
    315     }
    316 
    317     /* Skip next 16 bits */
    318     /* Skip vbv_delay */
    319     ret_code |= viddec_pm_skip_bits(parent, 16);
    320 
    321     /* If Picture Coding type is either P or B then */
    322     /* Get forward vector code */
    323     if ((MPEG2_PC_TYPE_P == parser->info.pic_hdr.picture_coding_type) ||
    324         (MPEG2_PC_TYPE_B == parser->info.pic_hdr.picture_coding_type))
    325     {
    326         ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_hdr.full_pel_forward_vect, 1);
    327         ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_hdr.forward_f_code, 3);
    328     }
    329     else
    330     {
    331         parser->info.pic_hdr.full_pel_forward_vect = 0;
    332         parser->info.pic_hdr.forward_f_code        = 0;
    333     }
    334 
    335     /* If Picture coding type is B then */
    336     /*    Get backward vector code */
    337     if (MPEG2_PC_TYPE_B == parser->info.pic_hdr.picture_coding_type)
    338     {
    339         ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_hdr.full_pel_backward_vect, 1);
    340         ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_hdr.backward_f_code, 3);
    341     }
    342     else
    343     {
    344         parser->info.pic_hdr.full_pel_backward_vect = 0;
    345         parser->info.pic_hdr.backward_f_code        = 0;
    346     }
    347 
    348     if (ret_code == 1)
    349     {
    350         MPEG2_DEB("Picture header parsed successfully.\n")
    351     }
    352     else
    353     {
    354         /* Setting status to mark parser error while emitting the current workload. */
    355         parser->mpeg2_wl_status |= MPEG2_WL_CORRUPTED_PIC_HDR;
    356         MPEG2_DEB("Picture header corrupted.\n");
    357     }
    358 
    359     parser->mpeg2_curr_frame_headers |= MPEG2_HEADER_PIC;
    360     parser->mpeg2_stream_level        = MPEG2_LEVEL_PIC;
    361 
    362     return;
    363 }
    364 
    365 /* viddec_mpeg2_parse_ext_seq() - Parse Sequence extension metadata and      */
    366 /* store in parser context                                                   */
    367 void viddec_mpeg2_parse_ext_seq(void *parent, void *ctxt)
    368 {
    369     int32_t ret_code = 0;
    370 
    371     /* Get MPEG2 Parser context */
    372     struct viddec_mpeg2_parser *parser = (struct viddec_mpeg2_parser *) ctxt;
    373 
    374     /* Get Profile and Level info */
    375     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_ext.profile_and_level_indication, 8);
    376 
    377     /* Get Progressive Sequence Flag */
    378     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_ext.progressive_sequence, 1);
    379 
    380     /* Get Chroma Format */
    381     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_ext.chroma_format, 2);
    382 
    383     /* Error Concealment */
    384     /* If there is an error parsing chroma format, do error concealment and continue. */
    385     if ((ret_code != 1) || (parser->info.seq_ext.chroma_format == MPEG2_CF_RESERVED))
    386     {
    387         if (parser->info.seq_ext.chroma_format == MPEG2_CF_RESERVED)
    388         {
    389             /* Setting status to mark parser error while emitting the current workload. */
    390             parser->mpeg2_wl_status |= MPEG2_WL_CORRUPTED_SEQ_EXT;
    391             MPEG2_DEB("Sequence extension corrupted.\n")
    392         }
    393 
    394         /* Error concealment for chroma format - Default to 4:2:0 */
    395         parser->info.seq_ext.chroma_format = MPEG2_CF_420;
    396         parser->mpeg2_wl_status |= MPEG2_WL_CONCEALED_CHROMA_FMT;
    397         MPEG2_DEB("Chroma Format corrupted. Concealing to 4:2:0.\n");
    398     }
    399 
    400     /* Get Content Size Extension Data */
    401     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_ext.horizontal_size_extension, 2);
    402     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_ext.vertical_size_extension, 2);
    403 
    404     /* Get Bit Rate Extension */
    405     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_ext.bit_rate_extension, 12);
    406 
    407     /* Skip Marker bit */
    408     ret_code |= viddec_pm_skip_bits(parent, 1);
    409 
    410     /* Get VBV Buffer Size Extension Data */
    411     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_ext.vbv_buffer_size_extension, 8);
    412 
    413     /* Skip 1 bit */
    414     /* Skip low_delay */
    415     ret_code |= viddec_pm_skip_bits(parent, 1);
    416 
    417     /* Get Frame Rate extension data */
    418     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_ext.frame_rate_extension_n, 2);
    419     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_ext.frame_rate_extension_d, 5);
    420 
    421     if (ret_code == 1)
    422     {
    423         MPEG2_DEB("Sequence extension header parsed successfully.\n")
    424     }
    425     else
    426     {
    427         /* Setting status to mark parser error while emitting the current workload. */
    428         parser->mpeg2_wl_status |= MPEG2_WL_CORRUPTED_SEQ_EXT;
    429         MPEG2_DEB("Sequence extension corrupted.\n")
    430     }
    431 
    432     /* Check if the last parsed start code was that of sequence header. */
    433     /* If true, seq extension followed seq header => MPEG2 Stream */
    434     parser->mpeg2_stream = (parser->mpeg2_last_parsed_sc == MPEG2_SC_SEQ_HDR) ? true:false;
    435     parser->mpeg2_curr_seq_headers   |= MPEG2_HEADER_SEQ_EXT;
    436     parser->mpeg2_curr_frame_headers |= MPEG2_HEADER_SEQ_EXT;
    437 
    438     return;
    439 }
    440 
    441 /* viddec_mpeg2_parse_ext_seq_disp() - Parse Sequence Display extension      */
    442 /* metadata and store in parser context                                      */
    443 void viddec_mpeg2_parse_ext_seq_disp(void *parent, void *ctxt)
    444 {
    445     int32_t ret_code = 0;
    446 
    447     /* Get MPEG2 Parser context */
    448     struct viddec_mpeg2_parser *parser = (struct viddec_mpeg2_parser *) ctxt;
    449 
    450     /* Get video format */
    451     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_disp_ext.video_format, 3);
    452 
    453     /* Check if color description info is present */
    454     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_disp_ext.colour_description, 1);
    455 
    456     /* If color description is found, get color primaries info */
    457     /* and transfer characteristics */
    458     if (parser->info.seq_disp_ext.colour_description)
    459     {
    460         ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_disp_ext.colour_primaries, 8);
    461         ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_disp_ext.transfer_characteristics, 8);
    462         ret_code |= viddec_pm_skip_bits(parent, 8);
    463     }
    464 
    465     /* Get Display Horizontal Size */
    466     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_disp_ext.display_horizontal_size, 14);
    467     ret_code |= viddec_pm_skip_bits(parent, 1);
    468     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_disp_ext.display_vertical_size, 14);
    469 
    470     if (ret_code == 1)
    471     {
    472         MPEG2_DEB("Sequence display extension parsed successfully.\n");
    473     }
    474     else
    475     {
    476         /* Setting status to mark parser error while emitting the current workload. */
    477         parser->mpeg2_wl_status |= MPEG2_WL_CORRUPTED_SEQ_DISP_EXT;
    478         MPEG2_DEB("Sequence display extension corrupted.\n")
    479     }
    480 
    481     /* Set flag to indicate Sequence Display Extension is present */
    482     parser->mpeg2_curr_frame_headers |= MPEG2_HEADER_SEQ_DISP_EXT;
    483     parser->mpeg2_curr_seq_headers   |= MPEG2_HEADER_SEQ_DISP_EXT;
    484 
    485     return;
    486 }
    487 
    488 /* viddec_mpeg2_parse_ext_seq_scal() - Parse Sequence Scalable extension     */
    489 /* metadata and store in parser context                                      */
    490 void viddec_mpeg2_parse_ext_seq_scal(void *parent, void *ctxt)
    491 {
    492     int32_t ret_code = 0;
    493 
    494     /* Get MPEG2 Parser context */
    495     struct viddec_mpeg2_parser *parser = (struct viddec_mpeg2_parser *) ctxt;
    496 
    497     /* Get video format */
    498     ret_code |= viddec_pm_get_bits(parent, &parser->info.seq_scal_ext.scalable_mode, 2);
    499 
    500     if (ret_code == 1)
    501     {
    502         MPEG2_DEB("Sequence scalable extension parsed successfully.\n");
    503     }
    504 
    505     /* Set flag to indicate Sequence Display Extension is present */
    506     parser->mpeg2_curr_frame_headers |= MPEG2_HEADER_SEQ_SCAL_EXT;
    507     parser->mpeg2_curr_seq_headers   |= MPEG2_HEADER_SEQ_SCAL_EXT;
    508 
    509     return;
    510 }
    511 
    512 /* viddec_mpeg2_parse_ext_pic() - Parse Picture Coding extension             */
    513 /* metadata and store in parser context                                      */
    514 void viddec_mpeg2_parse_ext_pic(void *parent, void *ctxt)
    515 {
    516     int32_t ret_code = 0, found_error = 0;
    517 
    518     /* Get MPEG2 Parser context */
    519     struct viddec_mpeg2_parser *parser = (struct viddec_mpeg2_parser *) ctxt;
    520 
    521     /* Get Forward/Backward, Horizontal/Vertical codes */
    522     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.fcode00, 4);
    523     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.fcode01, 4);
    524     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.fcode10, 4);
    525     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.fcode11, 4);
    526 
    527     /* Get Intra DC Precision */
    528     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.intra_dc_precision, 2);
    529 
    530     /* Get Picture Structure */
    531     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.picture_structure,  2);
    532 
    533     /* Error Handling and Concealment */
    534     /* Picture structure should be frame, top field or bottom field */
    535     if (parser->info.pic_cod_ext.picture_structure == MPEG2_PIC_STRUCT_RESERVED)
    536     {
    537         found_error = 1;
    538     }
    539     /* All pictures in progressive sequence should be frame picture */
    540     else if (parser->info.seq_ext.progressive_sequence)
    541     {
    542         if (parser->info.pic_cod_ext.picture_structure != MPEG2_PIC_STRUCT_FRAME)
    543         {
    544             found_error = 1;
    545         }
    546     }
    547 
    548     /* If there is an error parsing picture structure, do error concealment and continue. */
    549     if ((ret_code != 1) || (found_error))
    550     {
    551         if (found_error)
    552         {
    553             /* Setting status to mark parser error while emitting the current workload. */
    554             parser->mpeg2_wl_status |= MPEG2_WL_CORRUPTED_PIC_COD_EXT;
    555             MPEG2_DEB("Picture coding extension corrupted.\n");
    556         }
    557 
    558         /* Error concealment for picture structure - Default to frame picture. */
    559         parser->info.pic_cod_ext.picture_structure = MPEG2_PIC_STRUCT_FRAME;
    560         parser->mpeg2_wl_status |= MPEG2_WL_CONCEALED_PIC_STRUCT;
    561         MPEG2_DEB("Picture Structure corrupted. Concealing to Frame picture.\n");
    562     }
    563 
    564     /* Get flags */
    565     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.top_field_first, 1);
    566     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.frame_pred_frame_dct, 1);
    567     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.concealment_motion_vectors, 1);
    568     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.q_scale_type, 1);
    569     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.intra_vlc_format, 1);
    570     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.alternate_scan, 1);
    571     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.repeat_first_field, 1);
    572     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.chroma_420_type, 1);
    573     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.progressive_frame, 1);
    574     ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_cod_ext.composite_display_flag, 1);
    575 
    576     /* Error concealment for frame picture */
    577     if ((parser->info.pic_cod_ext.top_field_first)
    578         || (parser->info.pic_cod_ext.frame_pred_frame_dct)
    579         || (parser->info.pic_cod_ext.repeat_first_field)
    580         || (parser->info.pic_cod_ext.progressive_frame))
    581     {
    582         if (parser->info.pic_cod_ext.picture_structure != MPEG2_PIC_STRUCT_FRAME)
    583         {
    584             parser->info.pic_cod_ext.picture_structure = MPEG2_PIC_STRUCT_FRAME;
    585             parser->mpeg2_wl_status |= MPEG2_WL_CONCEALED_PIC_STRUCT;
    586             MPEG2_DEB("Picture Structure corrupted. Concealing to Frame picture.\n");
    587         }
    588     }
    589 
    590     if (ret_code == 1)
    591     {
    592         MPEG2_DEB("Picture coding extension parsed successfully.\n");
    593     }
    594     else
    595     {
    596         /* Setting status to mark parser error while emitting the current workload. */
    597         parser->mpeg2_wl_status |= MPEG2_WL_CORRUPTED_PIC_COD_EXT;
    598         MPEG2_DEB("Picture coding extension corrupted.\n");
    599     }
    600 
    601     /* Dangling field detection */
    602     /* If the previous picture is the first field, then the temporal reference number */
    603     /* should match with the second field. Otherwise, one of the fields in the previous */
    604     /* picture is missing and dangling field error is marked. The workload containing */
    605     /* the previous picture is emitted out and current picture data is added to the next */
    606     /* workload. The mpeg2_use_next_workload variable is used as a flag to direct the */
    607     /* items into the current/next workload. */
    608     if ((parser->mpeg2_picture_interlaced) && (parser->mpeg2_first_field))
    609     {
    610         if (parser->mpeg2_prev_temp_ref != parser->info.pic_hdr.temporal_reference)
    611         {
    612             /* Mark dangling field info in workload status */
    613             parser->mpeg2_wl_status |= MPEG2_WL_DANGLING_FIELD;
    614             if (parser->mpeg2_prev_picture_structure == MPEG2_PIC_STRUCT_BOTTOM)
    615             {
    616                 parser->mpeg2_wl_status |= MPEG2_WL_DANGLING_FIELD_TOP;
    617             }
    618             else
    619             {
    620                 parser->mpeg2_wl_status |= MPEG2_WL_DANGLING_FIELD_BOTTOM;
    621             }
    622             /* Set flag stating current workload is done */
    623             parser->mpeg2_pic_metadata_complete = true;
    624             /* Set flag to use the next workload for adding workitems for */
    625             /* the current frame */
    626             parser->mpeg2_use_next_workload = true;
    627             /* Toggle first field flag to compensate for missing field */
    628             parser->mpeg2_first_field = (parser->mpeg2_first_field) ? false : true;
    629         }
    630         else
    631         {
    632             /* Same field repeated */
    633             if (parser->mpeg2_prev_picture_structure == parser->info.pic_cod_ext.picture_structure)
    634             {
    635                 /* Mark unsupported in workload status */
    636                 parser->mpeg2_wl_status |= MPEG2_WL_REPEAT_FIELD;
    637             }
    638         }
    639     }
    640 
    641     /* Set context variables for interlaced picture handling */
    642     if (parser->info.pic_cod_ext.picture_structure == MPEG2_PIC_STRUCT_FRAME)
    643     {
    644         /* Frame picture found. Reset variables used for interlaced fields picture. */
    645         parser->mpeg2_picture_interlaced = false;
    646         parser->mpeg2_first_field        = false;
    647         parser->mpeg2_use_next_workload  = false;
    648     }
    649     else
    650     {
    651         /* Interlaced fields picture found. */
    652         parser->mpeg2_picture_interlaced = true;
    653         parser->mpeg2_first_field = (parser->mpeg2_first_field) ? false : true;
    654     }
    655 
    656     /* Set flags */
    657     parser->mpeg2_curr_frame_headers |= MPEG2_HEADER_PIC_COD_EXT;
    658     parser->mpeg2_prev_temp_ref = parser->info.pic_hdr.temporal_reference;
    659     parser->mpeg2_prev_picture_structure = parser->info.pic_cod_ext.picture_structure;
    660     if ((!parser->mpeg2_picture_interlaced)
    661         || ((parser->mpeg2_picture_interlaced) && (parser->mpeg2_first_field)))
    662     {
    663         parser->mpeg2_frame_start = true;
    664     }
    665 
    666     return;
    667 }
    668 
    669 /* viddec_mpeg2_parse_ext_pic_disp() - Parse Picture Display extension       */
    670 /* metadata and store in parser context                                      */
    671 void viddec_mpeg2_parse_ext_pic_disp(void *parent, void *ctxt)
    672 {
    673     int32_t ret_code = 0;
    674     uint32_t index = 0;
    675 
    676     /* Get MPEG2 Parser context */
    677     struct viddec_mpeg2_parser *parser = (struct viddec_mpeg2_parser *) ctxt;
    678 
    679     /* Determine number of offsets */
    680     if (parser->info.seq_ext.progressive_sequence)
    681     {
    682         if (parser->info.pic_cod_ext.repeat_first_field)
    683         {
    684             parser->mpeg2_num_pan_scan_offsets =
    685                 (parser->info.pic_cod_ext.top_field_first) ? 3 : 2;
    686         }
    687         else /* Not repeat field */
    688             parser->mpeg2_num_pan_scan_offsets = 1;
    689     }
    690     else /* Not progressive sequence */
    691     {
    692         /* Check if picture structure is a field */
    693         if ((parser->info.pic_cod_ext.picture_structure == MPEG2_PIC_STRUCT_TOP) ||
    694             (parser->info.pic_cod_ext.picture_structure == MPEG2_PIC_STRUCT_BOTTOM))
    695         {
    696             parser->mpeg2_num_pan_scan_offsets = 1;
    697         }
    698         else
    699         {
    700             parser->mpeg2_num_pan_scan_offsets =
    701                 (parser->info.pic_cod_ext.repeat_first_field) ? 3 : 2;
    702         }
    703     }
    704 
    705     /* Get the offsets */
    706     for (index = 0; index < parser->mpeg2_num_pan_scan_offsets; index++)
    707     {
    708         ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_disp_ext.frame_center_horizontal_offset[index], 16);
    709         ret_code |= viddec_pm_skip_bits(parent, 1);
    710         ret_code |= viddec_pm_get_bits(parent, &parser->info.pic_disp_ext.frame_center_vertical_offset[index], 16);
    711         ret_code |= viddec_pm_skip_bits(parent, 1);
    712     }
    713 
    714     if (ret_code == 1)
    715     {
    716         MPEG2_DEB("Picture display extension parsed successfully.\n");
    717     }
    718     else
    719     {
    720         /* Setting status to mark parser error while emitting the current workload. */
    721         parser->mpeg2_wl_status |= MPEG2_WL_CORRUPTED_PIC_DISP_EXT;
    722         MPEG2_DEB("Picture display extension corrupted.\n");
    723     }
    724 
    725     /* Set flag to indicate picture display extension is found */
    726     parser->mpeg2_curr_frame_headers |= MPEG2_HEADER_PIC_DISP_EXT;
    727     return;
    728 }
    729 
    730 /* viddec_mpeg2_parse_ext_quant() - Parse Quantization Matrix extension      */
    731 /* metadata and store in parser context                                      */
    732 void viddec_mpeg2_parse_ext_quant(void *parent, void *ctxt)
    733 {
    734     int32_t ret_code = 0;
    735 
    736     /* Get MPEG2 Parser context */
    737     struct viddec_mpeg2_parser *parser = (struct viddec_mpeg2_parser *) ctxt;
    738 
    739     /* Quantization Matrix Support */
    740     /* Get Intra Quantizer matrix, if available or use default values */
    741     ret_code |= viddec_pm_get_bits(parent, &parser->info.qnt_ext.load_intra_quantiser_matrix, 1);
    742     if (parser->info.qnt_ext.load_intra_quantiser_matrix)
    743     {
    744         ret_code |= mpeg2_get_quant_matrix(parent,
    745                                             parser->info.qnt_mat.intra_quantiser_matrix,
    746                                             parser->info.pic_cod_ext.alternate_scan);
    747         mpeg2_copy_matrix(parser->info.qnt_mat.intra_quantiser_matrix,
    748                            parser->info.qnt_mat.chroma_intra_quantiser_matrix);
    749     }
    750 
    751     /* Get Non-Intra Qualtizer matrix, if available */
    752     ret_code |= viddec_pm_get_bits(parent, &parser->info.qnt_ext.load_non_intra_quantiser_matrix, 1);
    753     if (parser->info.qnt_ext.load_non_intra_quantiser_matrix)
    754     {
    755         ret_code |= mpeg2_get_quant_matrix(parent,
    756                                             parser->info.qnt_mat.non_intra_quantiser_matrix,
    757                                             parser->info.pic_cod_ext.alternate_scan);
    758         mpeg2_copy_matrix(parser->info.qnt_mat.non_intra_quantiser_matrix,
    759                            parser->info.qnt_mat.chroma_non_intra_quantiser_matrix);
    760     }
    761 
    762     /* Get Chroma Intra Quantizer matrix, if available */
    763     ret_code |= viddec_pm_get_bits(parent, &parser->info.qnt_ext.load_chroma_intra_quantiser_matrix, 1);
    764     if (parser->info.qnt_ext.load_chroma_intra_quantiser_matrix)
    765     {
    766         ret_code |= mpeg2_get_quant_matrix(parent,
    767                                             parser->info.qnt_mat.chroma_intra_quantiser_matrix,
    768                                             parser->info.pic_cod_ext.alternate_scan);
    769     }
    770 
    771     /* Get Chroma Non-Intra Quantizer matrix, if available */
    772     ret_code |= viddec_pm_get_bits(parent, &parser->info.qnt_ext.load_chroma_non_intra_quantiser_matrix, 1);
    773     if (parser->info.qnt_ext.load_chroma_non_intra_quantiser_matrix)
    774     {
    775         ret_code |= mpeg2_get_quant_matrix(parent,
    776                                             parser->info.qnt_mat.chroma_non_intra_quantiser_matrix,
    777                                             parser->info.pic_cod_ext.alternate_scan);
    778     }
    779 
    780     if (ret_code == 1)
    781     {
    782         MPEG2_DEB("Quantization matrix extension parsed successfully.\n");
    783     }
    784     else
    785     {
    786         /* Setting status to mark parser error while emitting the current workload. */
    787         parser->mpeg2_wl_status |= MPEG2_WL_CORRUPTED_QMAT_EXT;
    788         MPEG2_DEB("Quantization matrix extension corrupted.\n");
    789     }
    790 
    791     /* Set quantization matrices updated flag */
    792     if ( (parser->info.qnt_ext.load_intra_quantiser_matrix) ||
    793          (parser->info.qnt_ext.load_non_intra_quantiser_matrix) ||
    794          (parser->info.qnt_ext.load_chroma_intra_quantiser_matrix) ||
    795          (parser->info.qnt_ext.load_chroma_non_intra_quantiser_matrix) )
    796     {
    797         MPEG2_DEB("Custom quantization matrix found.\n");
    798     }
    799 
    800     return;
    801 }
    802 
    803 /* viddec_mpeg2_parse_ext() - Parse extension metadata and store in parser   */
    804 /* context                                                                   */
    805 void viddec_mpeg2_parse_ext(void *parent, void *ctxt)
    806 {
    807     uint32_t ext_code  = 0;
    808 
    809     /* Get extension start code */
    810     viddec_pm_get_bits(parent, &ext_code, 4);
    811 
    812     /* Switch on extension type */
    813     switch ( ext_code )
    814     {
    815         /* Sequence Extension Info */
    816         case MPEG2_EXT_SEQ:
    817             viddec_mpeg2_parse_ext_seq(parent, ctxt);
    818             break;
    819 
    820         /* Sequence Display Extension info */
    821         case MPEG2_EXT_SEQ_DISP:
    822             viddec_mpeg2_parse_ext_seq_disp(parent, ctxt);
    823             break;
    824 
    825         case MPEG2_EXT_SEQ_SCAL:
    826             viddec_mpeg2_parse_ext_seq_scal(parent, ctxt);
    827             break;
    828 
    829         /* Picture Coding Extension */
    830         case MPEG2_EXT_PIC_CODING:
    831             viddec_mpeg2_parse_ext_pic(parent, ctxt);
    832             break;
    833 
    834         /* Picture Display Extension */
    835         case MPEG2_EXT_PIC_DISP:
    836             viddec_mpeg2_parse_ext_pic_disp(parent, ctxt);
    837             break;
    838 
    839         /*  Quantization Extension*/
    840         case MPEG2_EXT_QUANT_MAT:
    841             viddec_mpeg2_parse_ext_quant(parent, ctxt);
    842             break;
    843 
    844         default:
    845             break;
    846     } /* Switch, on extension type */
    847 
    848     return;
    849 }
    850 
    851 /* viddec_mpeg2_parse_ext() - Parse user data and append to workload.        */
    852 void viddec_mpeg2_parse_and_append_user_data(void *parent, void *ctxt)
    853 {
    854     uint32_t user_data = 0;
    855     viddec_workload_item_t wi;
    856 
    857     /* Get MPEG2 Parser context */
    858     struct viddec_mpeg2_parser *parser = (struct viddec_mpeg2_parser *) ctxt;
    859 
    860     /* Set the user data level (SEQ/GOP/PIC) in the workitem type. */
    861     switch (parser->mpeg2_stream_level)
    862     {
    863         case MPEG2_LEVEL_SEQ:
    864         {
    865             wi.vwi_type = VIDDEC_WORKLOAD_SEQ_USER_DATA;
    866             break;
    867         }
    868         case MPEG2_LEVEL_GOP:
    869         {
    870             wi.vwi_type = VIDDEC_WORKLOAD_GOP_USER_DATA;
    871             break;
    872         }
    873         case MPEG2_LEVEL_PIC:
    874         {
    875             wi.vwi_type = VIDDEC_WORKLOAD_FRM_USER_DATA;
    876             break;
    877         }
    878         default:
    879         {
    880             wi.vwi_type = VIDDEC_WORKLOAD_INVALID;
    881             break;
    882         }
    883     }
    884 
    885     /* Read 1 byte of user data and store it in workitem for the current      */
    886     /* stream level (SEQ/GOP/PIC). Keep adding data payloads till it reaches  */
    887     /* size 11. When it is 11, the maximum user data payload size, append the */
    888     /* workitem. This loop is repeated till all user data is extracted and    */
    889     /* appended. */
    890     wi.user_data.size = 0;
    891     memset(&(wi.user_data), 0, sizeof(wi.user_data));
    892     while(viddec_pm_get_bits(parent, &user_data, MPEG2_BITS_EIGHT) != -1)
    893     {
    894         /* Store the valid byte in data payload */
    895         wi.user_data.data_payload[wi.user_data.size] = user_data;
    896         wi.user_data.size++;
    897 
    898         /* When size exceeds payload size, append workitem and continue */
    899         if (wi.user_data.size >= 11)
    900         {
    901             viddec_pm_setup_userdata(&wi);
    902             viddec_mpeg2_append_workitem(parent, &wi, parser->mpeg2_use_next_workload);
    903             viddec_fw_reset_workload_item(&wi);
    904             wi.user_data.size = 0;
    905         }
    906     }
    907     /* If size is not 0, append remaining user data. */
    908     if (wi.user_data.size > 0)
    909     {
    910         viddec_pm_setup_userdata(&wi);
    911         viddec_mpeg2_append_workitem(parent, &wi, parser->mpeg2_use_next_workload);
    912         wi.user_data.size = 0;
    913     }
    914 
    915     MPEG2_DEB("User data @ Level %d found.\n", parser->mpeg2_stream_level);
    916     return;
    917 }
    918 
    919 static inline uint32_t get_mb_addr_increment(uint32_t *data)
    920 {
    921     if (*data >= 1024)
    922     {
    923         return 1;
    924     }
    925     else if (*data >= 128)
    926     {
    927         *data >>= 6;
    928         return mb_addr_inc_tab1[*data];
    929     }
    930     else if (*data >= 64)
    931     {
    932         *data >>= 3;
    933         *data -= 8;
    934         return mb_addr_inc_tab2[*data];
    935     }
    936     else
    937     {
    938         *data -= 24;
    939         return mb_addr_inc_tab3[*data];
    940     }
    941 }
    942 
    943 static void viddec_mpeg2_get_first_mb_number(void *parent, void *ctxt, uint32_t *first_mb)
    944 {
    945     uint32_t mb_row = 0, mb_width = 0, prev_mb_addr = 0;
    946     uint32_t temp = 0;
    947 
    948     /* Get MPEG2 Parser context */
    949     struct viddec_mpeg2_parser *parser = (struct viddec_mpeg2_parser *) ctxt;
    950     *first_mb = 0;
    951     mb_row   = ((parser->mpeg2_last_parsed_slice_sc & 0xFF) - 1);
    952     mb_width = parser->info.seq_hdr.horizontal_size_value >> 4;
    953     prev_mb_addr = (mb_row * mb_width) - 1;
    954 
    955     /* Skip slice start code */
    956     viddec_pm_skip_bits(parent, 32);
    957 
    958     if (parser->info.seq_hdr.vertical_size_value > 2800)
    959     {
    960         /* Get 3 bits of slice_vertical_position_extension */
    961         viddec_pm_get_bits(parent, &temp, 3);
    962         mb_row += (temp << 7);
    963     }
    964 
    965     /* Skip proprity_breakpoint if sequence scalable extension is present */
    966     if (parser->mpeg2_curr_seq_headers & MPEG2_HEADER_SEQ_SCAL_EXT)
    967     {
    968         /* Skip 7 bits if scalable mode is 00 (Data partition) */
    969         if (parser->info.seq_scal_ext.scalable_mode == 0)
    970         {
    971             viddec_pm_skip_bits(parent, 7);
    972         }
    973     }
    974 
    975     /* Skip quantizer_scale */
    976     viddec_pm_skip_bits(parent, 5);
    977 
    978     /* Skip a few bits with slice information */
    979     temp = 0;
    980     viddec_pm_peek_bits(parent, &temp, 1);
    981     if (temp == 0x1)
    982     {
    983         /* Skip intra_slice_flag(1), intra_slice(1) and reserved_bits(7) */
    984         viddec_pm_skip_bits(parent, 9);
    985         temp=0;
    986         viddec_pm_peek_bits(parent, &temp, 1);
    987         while (temp == 0x1)
    988         {
    989             /* Skip extra_bit_slice(1) and extra_information_slice(8) */
    990             viddec_pm_skip_bits(parent, 9);
    991             temp=0;
    992             viddec_pm_peek_bits(parent, &temp, 1);
    993         }
    994     }
    995 
    996     /* Skip extra_bit_slice flag */
    997     viddec_pm_skip_bits(parent, 1);
    998 
    999     /* Increment prev_mb_addr by 33 for every 11 bits of macroblock_escape string */
   1000     temp=0;
   1001     viddec_pm_peek_bits(parent, &temp, 11);
   1002     while (temp == 0x8)
   1003     {
   1004         viddec_pm_skip_bits(parent, 11);
   1005         prev_mb_addr += 33;
   1006         temp=0;
   1007         viddec_pm_peek_bits(parent, &temp, 11);
   1008     }
   1009 
   1010     /* Get the mb_addr_increment and add it to prev_mb_addr to get the current mb number. */
   1011     *first_mb = prev_mb_addr + get_mb_addr_increment(&temp);
   1012     MPEG2_DEB("First MB number in slice is 0x%08X.\n", *first_mb);
   1013 
   1014     return;
   1015 }
   1016 
   1017 /* Parse slice data to get the number of macroblocks in the current slice and then */
   1018 /* append as pixel data. */
   1019 void viddec_mpeg2_parse_and_append_slice_data(void *parent, void *ctxt)
   1020 {
   1021     uint32_t bit_off=0, start_byte=0, first_mb = 0;
   1022     uint8_t  is_emul=0;
   1023     viddec_workload_item_t wi;
   1024 
   1025     /* Get MPEG2 Parser context */
   1026     struct viddec_mpeg2_parser *parser = (struct viddec_mpeg2_parser *) ctxt;
   1027 
   1028     /* Get current byte position */
   1029     viddec_pm_get_au_pos(parent, &bit_off, &start_byte, &is_emul);
   1030 
   1031     /* Populate wi type */
   1032     viddec_mpeg2_get_first_mb_number(parent, ctxt, &first_mb);
   1033     wi.vwi_type = VIDDEC_WORKLOAD_PIXEL_ES;
   1034     wi.es.es_flags = (first_mb << 16);
   1035 
   1036     /* Append data from given byte position as pixel data */
   1037     viddec_pm_append_misc_tags(parent, start_byte, (unsigned int) -1, &wi, !parser->mpeg2_use_next_workload);
   1038     return;
   1039 }
   1040