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