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