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 */
mpeg2_copy_matrix(const uint8_t * src,uint8_t * 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 */
mpeg2_get_quant_matrix(void * parent,uint8_t * matrix,uint32_t alternate_scan)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 */
viddec_mpeg2_parse_seq_hdr(void * parent,void * ctxt)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 */
viddec_mpeg2_parse_gop_hdr(void * parent,void * ctxt)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 */
viddec_mpeg2_parse_pic_hdr(void * parent,void * ctxt)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 */
viddec_mpeg2_parse_ext_seq(void * parent,void * ctxt)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 */
viddec_mpeg2_parse_ext_seq_disp(void * parent,void * ctxt)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 */
viddec_mpeg2_parse_ext_seq_scal(void * parent,void * ctxt)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 */
viddec_mpeg2_parse_ext_pic(void * parent,void * ctxt)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 */
viddec_mpeg2_parse_ext_pic_disp(void * parent,void * ctxt)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 */
viddec_mpeg2_parse_ext_quant(void * parent,void * ctxt)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 */
viddec_mpeg2_parse_ext(void * parent,void * ctxt)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. */
viddec_mpeg2_parse_and_append_user_data(void * parent,void * ctxt)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
get_mb_addr_increment(uint32_t * data)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
viddec_mpeg2_get_first_mb_number(void * parent,void * ctxt,uint32_t * first_mb)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. */
viddec_mpeg2_parse_and_append_slice_data(void * parent,void * ctxt)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