• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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