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 */
24const 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};
34const 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 */
46const 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};
56const 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 */
68const 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};
72const uint8_t mb_addr_inc_tab2[8] = {
73    13, 12, 11, 10, 9, 9, 8, 8
74};
75const 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                                                                    */
85static 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                                                                    */
94static 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                                                         */
125void 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                                                */
226void 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                                                            */
261void 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                                                   */
367void 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                                      */
443void 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                                      */
490void 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                                      */
514void 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                                      */
671void 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                                      */
732void 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                                                                   */
805void 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.        */
852void 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
919static 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
943static 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. */
1019void 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