Home | History | Annotate | Download | only in parser
      1 #include "viddec_fw_debug.h"    // For DEB
      2 #include "viddec_parser_ops.h"  // For parser helper functions
      3 #include "vc1.h"                // For the parser structure
      4 #include "vc1parse.h"           // For vc1 parser helper functions
      5 #ifdef VBP
      6 #include "viddec_pm.h"
      7 #endif
      8 #define vc1_is_frame_start_code( ch )                                   \
      9     (( vc1_SCField == ch ||vc1_SCSlice == ch || vc1_SCFrameHeader == ch ) ? 1 : 0)
     10 
     11 /* init function */
     12 #ifdef VBP
     13 void viddec_vc1_init(void *ctxt, uint32_t *persist_mem, uint32_t preserve)
     14 #else
     15 static void viddec_vc1_init(void *ctxt, uint32_t *persist_mem, uint32_t preserve)
     16 #endif
     17 {
     18     vc1_viddec_parser_t *parser = ctxt;
     19     int i;
     20 
     21     persist_mem = persist_mem;
     22 
     23     for(i=0; i<VC1_NUM_REFERENCE_FRAMES; i++)
     24     {
     25         parser->ref_frame[i].id   = -1; /* first I frame checks that value */
     26         parser->ref_frame[i].anchor[0] = 1;
     27         parser->ref_frame[i].anchor[1] = 1;
     28         parser->ref_frame[i].intcomp_top = 0;
     29         parser->ref_frame[i].intcomp_bot = 0;
     30     }
     31 
     32     parser->intcomp_top[0] = 0;
     33     parser->intcomp_bot[0] = 0;
     34     parser->intcomp_top[1] = 0;
     35     parser->intcomp_bot[1] = 0;
     36     parser->is_reference_picture = false;
     37 
     38     memset(&parser->info.picLayerHeader, 0, sizeof(vc1_PictureLayerHeader));
     39 
     40     if(preserve)
     41     {
     42         parser->sc_seen &= VC1_EP_MASK;
     43         parser->sc_seen_since_last_wkld &= VC1_EP_MASK;
     44     }
     45     else
     46     {
     47         parser->sc_seen = VC1_SC_INVALID;
     48         parser->sc_seen_since_last_wkld = VC1_SC_INVALID;
     49         memset(&parser->info.metadata, 0, sizeof(parser->info.metadata));
     50     }
     51 
     52     return;
     53 } // viddec_vc1_init
     54 
     55 static void vc1_swap_intcomp(vc1_viddec_parser_t *parser)
     56 {
     57     parser->intcomp_top[1] = parser->intcomp_top[0];
     58     parser->intcomp_bot[1] = parser->intcomp_bot[0];
     59     parser->intcomp_top[0] = 0;
     60     parser->intcomp_bot[0] = 0;
     61 
     62     return;
     63 } // vc1_swap_intcomp
     64 
     65 #ifdef VBP
     66 uint32_t viddec_vc1_parse(void *parent, void *ctxt)
     67 #else
     68 static uint32_t viddec_vc1_parse(void *parent, void *ctxt)
     69 #endif
     70 {
     71     vc1_viddec_parser_t *parser = ctxt;
     72     uint32_t sc=0x0;
     73     int32_t ret=0, status=0;
     74 
     75 #ifdef VBP
     76     /* This works only if there is one slice and no start codes */
     77     /* A better fix would be to insert start codes it there aren't any. */
     78     ret = viddec_pm_peek_bits(parent, &sc, 32);
     79     if ((sc > 0x0100) && (sc < 0x0200)) /* a Start code will be in this range. */
     80     {
     81       ret = viddec_pm_get_bits(parent, &sc, 32);
     82     }
     83     else
     84     {
     85       /* In cases where we get a buffer with no start codes, we assume */
     86       /* that this is a frame of data. We may have to fix this later. */
     87       sc = vc1_SCFrameHeader;
     88     }
     89 #else
     90     ret = viddec_pm_get_bits(parent, &sc, 32);
     91 #endif
     92     sc = sc & 0xFF;
     93     parser->is_frame_start = (sc == vc1_SCFrameHeader);
     94     DEB("START_CODE = %02x\n", sc);
     95     switch( sc )
     96     {
     97         case vc1_SCSequenceHeader:
     98         {
     99             uint32_t data=0;
    100             parser->ref_frame[0].anchor[0] = 1;
    101             parser->ref_frame[0].anchor[1] = 1;
    102             parser->ref_frame[1].anchor[0] = 1;
    103             parser->ref_frame[1].anchor[1] = 1;
    104             memset( &parser->info.metadata, 0, sizeof(parser->info.metadata));
    105             /* look if we have a rcv header for main or simple profile */
    106             ret = viddec_pm_peek_bits(parent,&data ,2);
    107 
    108             if (data == 3)
    109             {
    110                 status = vc1_ParseSequenceLayer(parent, &parser->info);
    111             }
    112             else
    113             {
    114                 status = vc1_ParseRCVSequenceLayer(parent, &parser->info);
    115             }
    116             parser->sc_seen = VC1_SC_SEQ;
    117             parser->sc_seen_since_last_wkld |= VC1_SC_SEQ;
    118 #ifdef VBP
    119 			parser->start_code = VC1_SC_SEQ;
    120 #endif
    121             break;
    122         }
    123 
    124         case vc1_SCEntryPointHeader:
    125         {
    126             status = vc1_ParseEntryPointLayer(parent, &parser->info);
    127             parser->sc_seen |= VC1_SC_EP;
    128             // Clear all bits indicating data below ep header
    129             parser->sc_seen &= VC1_EP_MASK;
    130             parser->sc_seen_since_last_wkld |= VC1_SC_EP;
    131 #ifdef VBP
    132 			parser->start_code = VC1_SC_EP;
    133 #endif
    134 			break;
    135         }
    136 
    137         case vc1_SCFrameHeader:
    138         {
    139             memset(&parser->info.picLayerHeader, 0, sizeof(vc1_PictureLayerHeader));
    140             status = vc1_ParsePictureLayer(parent, &parser->info);
    141             if((parser->info.picLayerHeader.PTypeField1 == VC1_I_FRAME) ||
    142                (parser->info.picLayerHeader.PTypeField1 == VC1_P_FRAME) ||
    143                (parser->info.picLayerHeader.PTYPE == VC1_I_FRAME) ||
    144                (parser->info.picLayerHeader.PTYPE == VC1_P_FRAME))
    145             {
    146                 vc1_swap_intcomp(parser);
    147             }
    148             parser->sc_seen |= VC1_SC_FRM;
    149             // Clear all bits indicating data below frm header
    150             parser->sc_seen &= VC1_FRM_MASK;
    151             parser->sc_seen_since_last_wkld |= VC1_SC_FRM;
    152             vc1_start_new_frame ( parent, parser );
    153 #ifdef VBP
    154 			parser->start_code = VC1_SC_FRM;
    155 #endif
    156 			break;
    157         }
    158 
    159         case vc1_SCSlice:
    160         {
    161             status = vc1_ParseSliceLayer(parent, &parser->info);
    162             parser->sc_seen_since_last_wkld |= VC1_SC_SLC;
    163 #ifdef VBP
    164          	parser->start_code = VC1_SC_SLC;
    165 #endif
    166             break;
    167         }
    168 
    169         case vc1_SCField:
    170         {
    171             parser->info.picLayerHeader.SLICE_ADDR = 0;
    172             parser->info.picLayerHeader.CurrField = 1;
    173             parser->info.picLayerHeader.REFFIELD = 0;
    174             parser->info.picLayerHeader.NUMREF = 0;
    175             parser->info.picLayerHeader.MBMODETAB = 0;
    176             parser->info.picLayerHeader.MV4SWITCH = 0;
    177             parser->info.picLayerHeader.DMVRANGE = 0;
    178             parser->info.picLayerHeader.MVTAB = 0;
    179             parser->info.picLayerHeader.MVMODE = 0;
    180             parser->info.picLayerHeader.MVRANGE = 0;
    181 #ifdef VBP
    182 			parser->info.picLayerHeader.raw_MVTYPEMB = 0;
    183 			parser->info.picLayerHeader.raw_DIRECTMB = 0;
    184 			parser->info.picLayerHeader.raw_SKIPMB = 0;
    185 			parser->info.picLayerHeader.raw_ACPRED = 0;
    186 			parser->info.picLayerHeader.raw_FIELDTX = 0;
    187 			parser->info.picLayerHeader.raw_OVERFLAGS = 0;
    188 			parser->info.picLayerHeader.raw_FORWARDMB = 0;
    189 
    190 			memset(&(parser->info.picLayerHeader.MVTYPEMB), 0, sizeof(vc1_Bitplane));
    191 			memset(&(parser->info.picLayerHeader.DIRECTMB), 0, sizeof(vc1_Bitplane));
    192 			memset(&(parser->info.picLayerHeader.SKIPMB), 0, sizeof(vc1_Bitplane));
    193 			memset(&(parser->info.picLayerHeader.ACPRED), 0, sizeof(vc1_Bitplane));
    194 			memset(&(parser->info.picLayerHeader.FIELDTX), 0, sizeof(vc1_Bitplane));
    195 			memset(&(parser->info.picLayerHeader.OVERFLAGS), 0, sizeof(vc1_Bitplane));
    196 			memset(&(parser->info.picLayerHeader.FORWARDMB), 0, sizeof(vc1_Bitplane));
    197 
    198 			parser->info.picLayerHeader.ALTPQUANT = 0;
    199 			parser->info.picLayerHeader.DQDBEDGE = 0;
    200  #endif
    201 
    202             status = vc1_ParseFieldLayer(parent, &parser->info);
    203             if((parser->info.picLayerHeader.PTypeField2 == VC1_I_FRAME) ||
    204                (parser->info.picLayerHeader.PTypeField2 == VC1_P_FRAME))
    205             {
    206                 vc1_swap_intcomp(parser);
    207             }
    208 
    209             parser->sc_seen |= VC1_SC_FLD;
    210             parser->sc_seen_since_last_wkld |= VC1_SC_FLD;
    211 #ifdef VBP
    212 			parser->start_code = VC1_SC_FLD;
    213 #endif
    214             break;
    215         }
    216 
    217         case vc1_SCSequenceUser:
    218         case vc1_SCEntryPointUser:
    219         case vc1_SCFrameUser:
    220         case vc1_SCSliceUser:
    221         case vc1_SCFieldUser:
    222         {/* Handle user data */
    223             status = vc1_ParseAndAppendUserData(parent, sc); //parse and add items
    224             parser->sc_seen_since_last_wkld |= VC1_SC_UD;
    225 #ifdef VBP
    226             parser->start_code = VC1_SC_UD;
    227 #endif
    228             break;
    229         }
    230 
    231         case vc1_SCEndOfSequence:
    232         {
    233             parser->sc_seen = VC1_SC_INVALID;
    234             parser->sc_seen_since_last_wkld |= VC1_SC_INVALID;
    235 #ifdef VBP
    236             parser->start_code = VC1_SC_INVALID;
    237 #endif
    238             break;
    239         }
    240         default: /* Any other SC that is not handled */
    241         {
    242             DEB("SC = %02x - unhandled\n", sc );
    243 #ifdef VBP
    244             parser->start_code = VC1_SC_INVALID;
    245 #endif
    246             break;
    247         }
    248     }
    249 
    250     if( vc1_is_frame_start_code( sc ) ) {
    251         vc1_parse_emit_current_frame( parent, parser );
    252     }
    253 
    254     return VIDDEC_PARSE_SUCESS;
    255 } // viddec_vc1_parse
    256 
    257 /**
    258    If a picture header was seen and the next start code is a sequence header, entrypoint header,
    259    end of sequence or another frame header, this api returns frame done.
    260    If a sequence header and a frame header was not seen before this point, all the
    261    information needed for decode is not present and parser errors are reported.
    262 */
    263 #ifdef VBP
    264 uint32_t viddec_vc1_wkld_done(void *parent, void *ctxt, unsigned int next_sc, uint32_t *codec_specific_errors)
    265 #else
    266 static uint32_t viddec_vc1_wkld_done(void *parent, void *ctxt, unsigned int next_sc, uint32_t *codec_specific_errors)
    267 #endif
    268 {
    269     vc1_viddec_parser_t *parser = ctxt;
    270     int ret = VIDDEC_PARSE_SUCESS;
    271     parent = parent;
    272     switch (next_sc)
    273     {
    274         case vc1_SCFrameHeader:
    275             if(((parser->sc_seen_since_last_wkld & VC1_SC_EP) ||
    276                 (parser->sc_seen_since_last_wkld & VC1_SC_SEQ)) &&
    277                (!(parser->sc_seen_since_last_wkld & VC1_SC_FRM)))
    278             {
    279                 break;
    280             }
    281             // Deliberate fall-thru case
    282         case vc1_SCEntryPointHeader:
    283             if((next_sc == vc1_SCEntryPointHeader) &&
    284                (parser->sc_seen_since_last_wkld & VC1_SC_SEQ) &&
    285                (!(parser->sc_seen_since_last_wkld & VC1_SC_EP)))
    286             {
    287                 break;
    288             }
    289             // Deliberate fall-thru case
    290         case vc1_SCSequenceHeader:
    291         case vc1_SCEndOfSequence:
    292         case VIDDEC_PARSE_EOS:
    293         case VIDDEC_PARSE_DISCONTINUITY:
    294             ret = VIDDEC_PARSE_FRMDONE;
    295             // Set errors for progressive
    296             if((parser->sc_seen & VC1_SC_SEQ) && (parser->sc_seen & VC1_SC_FRM))
    297                 *codec_specific_errors = 0;
    298             else
    299                 *codec_specific_errors |= VIDDEC_FW_WORKLOAD_ERR_NOTDECODABLE;
    300             vc1_end_frame(parser);
    301             parser->sc_seen_since_last_wkld = VC1_SC_INVALID;
    302             // TODO: Need to check for interlaced
    303             break;
    304         default:
    305             ret = VIDDEC_PARSE_SUCESS;
    306             break;
    307     } //switch
    308     DEB("sc: 0x%x, sc_seen: 0x%x, sc_since_last_wkld:%d, error:%d, ret: %d\n",
    309         next_sc, parser->sc_seen, parser->sc_seen_since_last_wkld,
    310         *codec_specific_errors, ret);
    311 
    312     return ret;
    313 } // viddec_vc1_wkld_done
    314 
    315 #ifdef VBP
    316 void viddec_vc1_get_context_size(viddec_parser_memory_sizes_t *size)
    317 #else
    318 static void viddec_vc1_get_context_size(viddec_parser_memory_sizes_t *size)
    319 #endif
    320 {
    321     size->context_size = sizeof(vc1_viddec_parser_t);
    322     size->persist_size = 0;
    323     return;
    324 } // viddec_vc1_get_context_size
    325 
    326 #ifdef VBP
    327 uint32_t viddec_vc1_is_start_frame(void *ctxt)
    328 #else
    329 static uint32_t viddec_vc1_is_start_frame(void *ctxt)
    330 #endif
    331 {
    332     vc1_viddec_parser_t *parser = (vc1_viddec_parser_t *) ctxt;
    333     return parser->is_frame_start;
    334 } // viddec_vc1_is_start_frame
    335 
    336 void viddec_vc1_get_ops(viddec_parser_ops_t *ops)
    337 {
    338     ops->init = viddec_vc1_init;
    339     ops->parse_syntax = viddec_vc1_parse;
    340     ops->get_cxt_size = viddec_vc1_get_context_size;
    341     ops->is_wkld_done = viddec_vc1_wkld_done;
    342     ops->is_frame_start = viddec_vc1_is_start_frame;
    343     return;
    344 } // viddec_vc1_get_ops
    345 
    346