1 /* ///////////////////////////////////////////////////////////////////////
2 //
3 //               INTEL CORPORATION PROPRIETARY INFORMATION
4 //  This software is supplied under the terms of a license agreement or
5 //  nondisclosure agreement with Intel Corporation and may not be copied
6 //  or disclosed except in accordance with the terms of that agreement.
7 //        Copyright (c) 2008 Intel Corporation. All Rights Reserved.
8 //
9 //  Description: Parses VC-1 bitstream layers down to but not including
10 //  macroblock layer.
11 //
12 */
13 
14 #include "viddec_fw_debug.h"
15 #include "vc1parse.h"
16 
17 #define VC1_PIXEL_IN_LUMA 16
18 
19 /*------------------------------------------------------------------------------
20  * Parse modified rcv file, start codes are inserted using rcv2vc1.c.
21  * source is in
22  * http://svn.jf.intel.com/svn/DHG_Src/CESWE_Src/DEV/trunk/sv/mfd/tools/utils.
23  * Assumme rcv file width < 90,112 pixel to differenciate from real VC1
24  * advanced profile header.
25  * Original rcv description is in annex L
26  * Table 263 of SMPTE 421M.
27  */
vc1_ParseRCVSequenceLayer(void * ctxt,vc1_Info * pInfo)28 vc1_Status vc1_ParseRCVSequenceLayer (void* ctxt, vc1_Info *pInfo)
29 {
30     uint32_t result;
31     vc1_Status status = VC1_STATUS_OK;
32     vc1_metadata_t *md = &pInfo->metadata;
33     vc1_RcvSequenceHeader rcv;
34 
35     memset(&rcv, 0, sizeof(vc1_RcvSequenceHeader));
36 
37     result = viddec_pm_get_bits(ctxt, &rcv.struct_a_rcv, 32);
38     md->width = rcv.struct_a.HORIZ_SIZE;
39     md->height = rcv.struct_a.VERT_SIZE;
40 
41     result = viddec_pm_get_bits(ctxt, &rcv.struct_c_rcv, 32);
42     md->PROFILE = rcv.struct_c.PROFILE >> 2;
43     md->LOOPFILTER = rcv.struct_c.LOOPFILTER;
44     md->MULTIRES = rcv.struct_c.MULTIRES;
45     md->FASTUVMC = rcv.struct_c.FASTUVMC;
46     md->EXTENDED_MV = rcv.struct_c.EXTENDED_MV;
47     md->DQUANT = rcv.struct_c.DQUANT;
48     md->VSTRANSFORM = rcv.struct_c.VSTRANSFORM;
49     md->OVERLAP = rcv.struct_c.OVERLAP;
50     md->RANGERED = rcv.struct_c.RANGERED;
51     md->MAXBFRAMES = rcv.struct_c.MAXBFRAMES;
52     md->QUANTIZER = rcv.struct_c.QUANTIZER;
53     md->FINTERPFLAG = rcv.struct_c.FINTERPFLAG;
54 #ifdef VBP
55 	md->SYNCMARKER = rcv.struct_c.SYNCMARKER;
56 #endif
57 
58     if ((md->PROFILE == VC1_PROFILE_SIMPLE) ||
59         (md->MULTIRES && md->PROFILE == VC1_PROFILE_MAIN))
60     {
61         md->DQUANT = 0;
62     }
63     // TODO: NEED TO CHECK RESERVED BITS ARE 0
64 
65     md->widthMB = (md->width + 15 )  / VC1_PIXEL_IN_LUMA;
66     md->heightMB = (md->height + 15) / VC1_PIXEL_IN_LUMA;
67 
68     DEB("rcv: beforemod: res: %dx%d\n", md->width, md->height);
69 
70     /* WL takes resolution in unit of 2 pel - sec. 6.2.13.1 */
71     md->width = md->width/2 -1;
72     md->height = md->height/2 -1;
73 
74     DEB("rcv: res: %dx%d\n", md->width, md->height);
75 
76     // POPULATE WORKLOAD ITEM
77     {
78         viddec_workload_item_t wi;
79 
80         wi.vwi_type = VIDDEC_WORKLOAD_VC1_SEQ_HDR_STRUCT_A_C;
81 
82         wi.vc1_sh_struct_a_c.size = 0;
83         wi.vc1_sh_struct_a_c.flags = 0;
84         wi.vc1_sh_struct_a_c.pad = 0;
85 
86         viddec_fw_vc1_set_rcv_horiz_size(&wi.vc1_sh_struct_a_c, rcv.struct_a.HORIZ_SIZE);
87         viddec_fw_vc1_set_rcv_vert_size(&wi.vc1_sh_struct_a_c, rcv.struct_a.VERT_SIZE);
88 
89         viddec_fw_vc1_set_rcv_bitrtq_postproc(&wi.vc1_sh_struct_a_c, rcv.struct_c.BITRTQ_POSTPROC);
90         viddec_fw_vc1_set_rcv_frmrtq_postproc(&wi.vc1_sh_struct_a_c, rcv.struct_c.FRMRTQ_POSTPROC);
91         viddec_fw_vc1_set_rcv_profile(&wi.vc1_sh_struct_a_c, rcv.struct_c.PROFILE);
92         viddec_fw_vc1_set_rcv_level(&wi.vc1_sh_struct_a_c, 0);
93         viddec_fw_vc1_set_rcv_cbr(&wi.vc1_sh_struct_a_c, 0);
94         viddec_fw_vc1_set_rcv_rangered(&wi.vc1_sh_struct_a_c, rcv.struct_c.RANGERED);
95         viddec_fw_vc1_set_rcv_maxbframes(&wi.vc1_sh_struct_a_c, rcv.struct_c.MAXBFRAMES);
96         viddec_fw_vc1_set_rcv_finterpflag(&wi.vc1_sh_struct_a_c, rcv.struct_c.FINTERPFLAG);
97 
98         result = viddec_pm_append_workitem(ctxt, &wi);
99     }
100 
101     return status;
102 }
103 
104 /*------------------------------------------------------------------------------
105  * Parse sequence layer.  This function is only applicable to advanced profile
106  * as simple and main profiles use other mechanisms to communicate these
107  * metadata.
108  * Table 3 of SMPTE 421M.
109  * Table 13 of SMPTE 421M for HRD_PARAM().
110  *------------------------------------------------------------------------------
111  */
112 
vc1_ParseSequenceLayer(void * ctxt,vc1_Info * pInfo)113 vc1_Status vc1_ParseSequenceLayer(void* ctxt, vc1_Info *pInfo)
114 {
115     uint32_t tempValue;
116     vc1_Status status = VC1_STATUS_OK;
117     vc1_metadata_t *md = &pInfo->metadata;
118     vc1_SequenceLayerHeader sh;
119     uint32_t result;
120 
121     memset(&sh, 0, sizeof(vc1_SequenceLayerHeader));
122 
123     // PARSE SEQUENCE HEADER
124     result = viddec_pm_get_bits(ctxt, &sh.flags, 15);
125     if(result == 1)
126     {
127         md->PROFILE = sh.seq_flags.PROFILE;
128 #ifdef VBP
129         md->LEVEL = sh.seq_flags.LEVEL;
130 #endif
131     }
132 
133     result = viddec_pm_get_bits(ctxt, &sh.max_size, 32);
134     if(result == 1)
135     {
136         md->POSTPROCFLAG = sh.seq_max_size.POSTPROCFLAG;
137         md->width = sh.seq_max_size.MAX_CODED_WIDTH;
138         md->height = sh.seq_max_size.MAX_CODED_HEIGHT;
139         md->PULLDOWN = sh.seq_max_size.PULLDOWN;
140         md->INTERLACE = sh.seq_max_size.INTERLACE;
141         md->TFCNTRFLAG = sh.seq_max_size.TFCNTRFLAG;
142         md->FINTERPFLAG = sh.seq_max_size.FINTERPFLAG;
143         md->PSF = sh.seq_max_size.PSF;
144     }
145 
146     if (sh.seq_max_size.DISPLAY_EXT == 1)
147     {
148         result = viddec_pm_get_bits(ctxt, &sh.disp_size, 29);
149         if(result == 1)
150         {
151             if (sh.seq_disp_size.ASPECT_RATIO_FLAG == 1)
152             {
153                 result = viddec_pm_get_bits(ctxt, &tempValue, 4);
154                 sh.ASPECT_RATIO = tempValue;
155                 if (sh.ASPECT_RATIO == 15)
156                 {
157                     result = viddec_pm_get_bits(ctxt, &sh.aspect_size, 16);
158                 }
159             }
160 
161             result = viddec_pm_get_bits(ctxt, &tempValue, 1);
162             sh.FRAMERATE_FLAG = tempValue;
163             if (sh.FRAMERATE_FLAG == 1)
164             {
165                 result = viddec_pm_get_bits(ctxt, &tempValue, 1);
166                 sh.FRAMERATEIND = tempValue;
167                 if (sh.FRAMERATEIND == 0)
168                 {
169                     result = viddec_pm_get_bits(ctxt, &sh.framerate_fraction, 12);
170                 }
171                 else
172                 {
173                     result = viddec_pm_get_bits(ctxt, &tempValue, 16);
174                     sh.FRAMERATEEXP = tempValue;
175                 }
176             }
177 
178             result = viddec_pm_get_bits(ctxt, &tempValue, 1);
179             sh.COLOR_FORMAT_FLAG = tempValue;
180             if (sh.COLOR_FORMAT_FLAG == 1)
181             {
182                 result = viddec_pm_get_bits(ctxt, &sh.color_format, 24);
183             }
184         } // Successful get of display size
185     } // DISPLAY_EXT is 1
186 
187     result = viddec_pm_get_bits(ctxt, &tempValue, 1);
188     sh.HRD_PARAM_FLAG = tempValue;
189     if (sh.HRD_PARAM_FLAG == 1)
190     {
191         /* HRD_PARAM(). */
192         result = viddec_pm_get_bits(ctxt, &tempValue, 5);
193         sh.HRD_NUM_LEAKY_BUCKETS = tempValue;
194         md->HRD_NUM_LEAKY_BUCKETS = sh.HRD_NUM_LEAKY_BUCKETS;
195         // Skip the rest of the parsing - hrdinfo is not required for decode or for attributes
196     }
197     else
198     {
199         md->HRD_NUM_LEAKY_BUCKETS = 0;
200     }
201 
202     md->widthMB = (((md->width + 1) * 2) + 15) / VC1_PIXEL_IN_LUMA;
203     md->heightMB = (((md->height + 1) * 2) + 15) / VC1_PIXEL_IN_LUMA;
204 
205     DEB("md: res: %dx%d\n", md->width, md->height);
206     DEB("sh: dispres: %dx%d\n", sh.seq_disp_size.DISP_HORIZ_SIZE, sh.seq_disp_size.DISP_VERT_SIZE);
207 
208     // POPULATE WORKLOAD ITEM
209     {
210         viddec_workload_item_t wi_sl, wi_de;
211 
212         wi_sl.vwi_type = VIDDEC_WORKLOAD_SEQUENCE_INFO;
213 
214         wi_sl.vc1_sl.size = 0;
215         wi_sl.vc1_sl.flags = 0;
216         wi_sl.vc1_sl.pad = 0;
217 
218         viddec_fw_vc1_set_profile(&wi_sl.vc1_sl, sh.seq_flags.PROFILE);
219         viddec_fw_vc1_set_level(&wi_sl.vc1_sl, sh.seq_flags.LEVEL);
220         viddec_fw_vc1_set_colordiff_format(&wi_sl.vc1_sl, sh.seq_flags.COLORDIFF_FORMAT);
221         viddec_fw_vc1_set_pulldown(&wi_sl.vc1_sl, sh.seq_max_size.PULLDOWN);
222         viddec_fw_vc1_set_max_coded_width(&wi_sl.vc1_sl, sh.seq_max_size.MAX_CODED_WIDTH);
223         viddec_fw_vc1_set_max_coded_height(&wi_sl.vc1_sl, sh.seq_max_size.MAX_CODED_HEIGHT);
224 
225         viddec_fw_vc1_set_bitrtq_postproc(&wi_sl.vc1_sl, sh.seq_flags.BITRTQ_POSTPROC);
226         viddec_fw_vc1_set_frmrtq_postproc(&wi_sl.vc1_sl, sh.seq_flags.FRMRTQ_POSTPROC);
227         viddec_fw_vc1_set_interlace(&wi_sl.vc1_sl, sh.seq_max_size.INTERLACE);
228         viddec_fw_vc1_set_tfcntrflag(&wi_sl.vc1_sl, sh.seq_max_size.TFCNTRFLAG);
229         viddec_fw_vc1_set_finterpflag(&wi_sl.vc1_sl, sh.seq_max_size.FINTERPFLAG);
230         viddec_fw_vc1_set_psf(&wi_sl.vc1_sl, sh.seq_max_size.PSF);
231         viddec_fw_vc1_set_display_ext(&wi_sl.vc1_sl, sh.seq_max_size.DISPLAY_EXT);
232 
233         result = viddec_pm_append_workitem(ctxt, &wi_sl);
234 
235         // send DISPLAY EXTENSION metadata if present
236         if (sh.seq_max_size.DISPLAY_EXT)
237         {
238             wi_de.vwi_type = VIDDEC_WORKLOAD_DISPLAY_INFO;
239 
240             wi_de.vc1_sl_de.size = 0;
241             wi_de.vc1_sl_de.framerate = 0;
242             wi_de.vc1_sl_de.aspectsize = 0;
243 
244             viddec_fw_vc1_set_disp_horiz_size(&wi_de.vc1_sl_de, sh.seq_disp_size.DISP_HORIZ_SIZE);
245             viddec_fw_vc1_set_disp_vert_size(&wi_de.vc1_sl_de, sh.seq_disp_size.DISP_VERT_SIZE);
246             viddec_fw_vc1_set_disp_aspect_ratio_flag(&wi_de.vc1_sl_de, sh.seq_disp_size.ASPECT_RATIO_FLAG);
247             viddec_fw_vc1_set_disp_color_format_flag(&wi_de.vc1_sl_de, sh.COLOR_FORMAT_FLAG);
248             viddec_fw_vc1_set_disp_framerate_flag(&wi_de.vc1_sl_de, sh.FRAMERATE_FLAG);
249             viddec_fw_vc1_set_disp_framerateind(&wi_de.vc1_sl_de, sh.FRAMERATEIND);
250 
251             viddec_fw_vc1_set_disp_aspect_ratio(&wi_de.vc1_sl_de, sh.ASPECT_RATIO);
252             viddec_fw_vc1_set_disp_frameratenr(&wi_de.vc1_sl_de, sh.seq_framerate_fraction.FRAMERATENR);
253             viddec_fw_vc1_set_disp_frameratedr(&wi_de.vc1_sl_de, sh.seq_framerate_fraction.FRAMERATEDR);
254             viddec_fw_vc1_set_disp_framerateexp(&wi_de.vc1_sl_de, sh.FRAMERATEEXP);
255 
256             viddec_fw_vc1_set_disp_aspect_ratio_horiz_size(&wi_de.vc1_sl_de, sh.seq_aspect_size.ASPECT_HORIZ_SIZE);
257             viddec_fw_vc1_set_disp_aspect_ratio_vert_size(&wi_de.vc1_sl_de, sh.seq_aspect_size.ASPECT_VERT_SIZE);
258             viddec_fw_vc1_set_disp_color_prim(&wi_de.vc1_sl_de, sh.seq_color_format.COLOR_PRIM);
259             viddec_fw_vc1_set_disp_transfer_char(&wi_de.vc1_sl_de, sh.seq_color_format.TRANSFER_CHAR);
260 
261             result = viddec_pm_append_workitem(ctxt, &wi_de);
262         }
263     }
264 
265     return status;
266 }
267 
268 /*------------------------------------------------------------------------------
269  * Parse entry point layer.  This function is only applicable for advanced
270  * profile and is used to signal a random access point and changes in coding
271  * control parameters.
272  * Table 14 of SMPTE 421M.
273  * Table 15 of SMPTE 421M for HRD_FULLNESS().
274  *------------------------------------------------------------------------------
275  */
vc1_ParseEntryPointLayer(void * ctxt,vc1_Info * pInfo)276 vc1_Status vc1_ParseEntryPointLayer(void* ctxt, vc1_Info *pInfo)
277 {
278     vc1_Status status = VC1_STATUS_OK;
279     vc1_metadata_t *md = &pInfo->metadata;
280     vc1_EntryPointHeader ep;
281     uint32_t result;
282     uint32_t temp;
283 
284     memset(&ep, 0, sizeof(vc1_EntryPointHeader));
285 
286     // PARSE ENTRYPOINT HEADER
287     result = viddec_pm_get_bits(ctxt, &ep.flags, 13);
288     if(result == 1)
289     {
290         // Skip the flags already peeked at (13) and the unneeded hrd_full data
291         // NOTE: HRD_NUM_LEAKY_BUCKETS is initialized to 0 when HRD_PARAM_FLAG is not present
292         int hrd_bits = md->HRD_NUM_LEAKY_BUCKETS * 8;
293         while(hrd_bits >= 32)
294         {
295             result = viddec_pm_skip_bits(ctxt, 32);
296             hrd_bits -= 32;
297         }
298         result = viddec_pm_skip_bits(ctxt, hrd_bits);
299 
300         md->REFDIST = 0;
301         md->PANSCAN_FLAG = ep.ep_flags.PANSCAN_FLAG;
302         md->REFDIST_FLAG = ep.ep_flags.REFDIST_FLAG;
303         md->LOOPFILTER = ep.ep_flags.LOOPFILTER;
304         md->FASTUVMC = ep.ep_flags.FASTUVMC;
305         md->EXTENDED_MV = ep.ep_flags.EXTENDED_MV;
306         md->DQUANT = ep.ep_flags.DQUANT;
307         md->VSTRANSFORM = ep.ep_flags.VSTRANSFORM;
308         md->OVERLAP = ep.ep_flags.OVERLAP;
309         md->QUANTIZER = ep.ep_flags.QUANTIZER;
310 
311         result = viddec_pm_get_bits(ctxt, &temp, 1);
312         if(result == 1)
313         {
314             ep.CODED_SIZE_FLAG = temp;
315             if(ep.CODED_SIZE_FLAG)
316             {
317                 result = viddec_pm_get_bits(ctxt, &ep.size, 24);
318                 md->width = ep.ep_size.CODED_WIDTH;
319                 md->height = ep.ep_size.CODED_HEIGHT;
320             }
321         }
322         if(ep.ep_flags.EXTENDED_MV)
323         {
324             result = viddec_pm_get_bits(ctxt, &temp, 1);
325             md->EXTENDED_DMV = ep.EXTENDED_DMV = temp;
326         }
327 
328         result = viddec_pm_get_bits(ctxt, &temp, 1);
329         if(result == 1)
330         {
331             md->RANGE_MAPY_FLAG = ep.RANGE_MAPY_FLAG = temp;
332             if(ep.RANGE_MAPY_FLAG)
333             {
334                 result = viddec_pm_get_bits(ctxt, &temp, 3);
335                 md->RANGE_MAPY = ep.RANGE_MAPY = temp;
336             }
337         }
338 
339         result = viddec_pm_get_bits(ctxt, &temp, 1);
340         if(result == 1)
341         {
342             md->RANGE_MAPUV_FLAG = ep.RANGE_MAPUV_FLAG = temp;
343             if(ep.RANGE_MAPUV_FLAG)
344             {
345                 result = viddec_pm_get_bits(ctxt, &temp, 3);
346                 md->RANGE_MAPUV = ep.RANGE_MAPUV = temp;
347             }
348         }
349     }
350 
351     // POPULATE WORKLOAD ITEM
352     {
353         viddec_workload_item_t wi;
354 
355         wi.vwi_type = VIDDEC_WORKLOAD_GOP_INFO;
356 
357         wi.vc1_ep.size = 0;
358         wi.vc1_ep.flags = 0;
359         wi.vc1_ep.pad = 0;
360 
361         viddec_fw_vc1_set_ep_size_flag(&wi.vc1_ep, ep.CODED_SIZE_FLAG);
362         viddec_fw_vc1_set_ep_horiz_size(&wi.vc1_ep, ep.ep_size.CODED_WIDTH);
363         viddec_fw_vc1_set_ep_vert_size(&wi.vc1_ep, ep.ep_size.CODED_HEIGHT);
364 
365         viddec_fw_vc1_set_ep_broken_link(&wi.vc1_ep, ep.ep_flags.BROKEN_LINK);
366         viddec_fw_vc1_set_ep_closed_entry(&wi.vc1_ep, ep.ep_flags.CLOSED_ENTRY);
367         viddec_fw_vc1_set_ep_panscan_flag(&wi.vc1_ep, ep.ep_flags.PANSCAN_FLAG);
368         viddec_fw_vc1_set_ep_range_mapy_flag(&wi.vc1_ep, ep.RANGE_MAPY_FLAG);
369         viddec_fw_vc1_set_ep_range_mapy(&wi.vc1_ep, ep.RANGE_MAPY);
370         viddec_fw_vc1_set_ep_range_mapuv_flag(&wi.vc1_ep, ep.RANGE_MAPUV_FLAG);
371         viddec_fw_vc1_set_ep_range_mapuv(&wi.vc1_ep, ep.RANGE_MAPUV);
372 
373         result = viddec_pm_append_workitem(ctxt, &wi);
374     }
375 
376 #ifdef VBP
377     md->BROKEN_LINK = ep.ep_flags.BROKEN_LINK;
378     md->CLOSED_ENTRY = ep.ep_flags.CLOSED_ENTRY;
379 #endif
380 
381     DEB("ep: res: %dx%d\n", ep.ep_size.CODED_WIDTH, ep.ep_size.CODED_HEIGHT);
382     DEB("md: after ep: res: %dx%d\n", md->width, md->height);
383     return status;
384 }
385 
386 /*------------------------------------------------------------------------------
387  * Parse picture layer.  This function parses the picture layer.
388  *------------------------------------------------------------------------------
389  */
390 
vc1_ParsePictureLayer(void * ctxt,vc1_Info * pInfo)391 vc1_Status vc1_ParsePictureLayer(void* ctxt, vc1_Info *pInfo)
392 {
393     vc1_Status status = VC1_STATUS_OK;
394     uint32_t temp;
395     int i;
396 
397     for(i=0; i<VC1_MAX_BITPLANE_CHUNKS; i++)
398     {
399         pInfo->metadata.bp_raw[i] = true;
400     }
401 
402     if (pInfo->metadata.PROFILE == VC1_PROFILE_ADVANCED)
403     {
404         VC1_PEEK_BITS(2, temp); /* fcm */
405         if( (pInfo->metadata.INTERLACE == 1) && (temp == VC1_FCM_FIELD_INTERLACE))
406         {
407             status = vc1_ParseFieldHeader_Adv(ctxt, pInfo);
408         }
409         else
410         {
411             status = vc1_ParsePictureHeader_Adv(ctxt, pInfo);
412         }
413     }
414     else
415     {
416         status = vc1_ParsePictureHeader(ctxt, pInfo);
417     }
418 
419     return status;
420 }
421 
422 /*------------------------------------------------------------------------------
423  * Parse field picture layer.  This function parses the field picture layer.
424  *------------------------------------------------------------------------------
425  */
426 
vc1_ParseFieldLayer(void * ctxt,vc1_Info * pInfo)427 vc1_Status vc1_ParseFieldLayer(void* ctxt, vc1_Info *pInfo)
428 {
429     vc1_Status status = VC1_STATUS_PARSE_ERROR;
430     vc1_PictureLayerHeader *picLayerHeader = &pInfo->picLayerHeader;
431 
432     if (pInfo->metadata.PROFILE == VC1_PROFILE_ADVANCED) {
433         if (picLayerHeader->CurrField == 0)
434         {
435             picLayerHeader->PTYPE = picLayerHeader->PTypeField1;
436             picLayerHeader->BottomField = (uint8_t) (1 - picLayerHeader->TFF);
437         }
438         else
439         {
440             picLayerHeader->BottomField = (uint8_t) (picLayerHeader->TFF);
441             picLayerHeader->PTYPE = picLayerHeader->PTypeField2;
442         }
443         status = vc1_ParsePictureFieldHeader_Adv(ctxt, pInfo);
444     }
445 
446     return status;
447 }
448 
449 /*------------------------------------------------------------------------------
450  * Parse slice layer.  This function parses the slice layer, which is only
451  * supported by advanced profile.
452  * Table 26 of SMPTE 421M but skipping parsing of macroblock layer.
453  *------------------------------------------------------------------------------
454  */
455 
vc1_ParseSliceLayer(void * ctxt,vc1_Info * pInfo)456 vc1_Status vc1_ParseSliceLayer(void* ctxt, vc1_Info *pInfo)
457 {
458     uint32_t tempValue;
459     uint32_t SLICE_ADDR;
460     vc1_Status status = VC1_STATUS_OK;
461 
462     VC1_GET_BITS9(9, SLICE_ADDR);
463     VC1_GET_BITS9(1, tempValue); /* PIC_HEADER_FLAG. */
464     if (tempValue == 1) {
465         uint8_t *last_bufptr = pInfo->bufptr;
466         uint32_t last_bitoff = pInfo->bitoff;
467         status = vc1_ParsePictureLayer(ctxt, pInfo);
468         pInfo->picture_info_has_changed = 1;
469         if( status ) {
470             /* FIXME - is this a good way of handling this? Failed, see if it's for fields */
471             pInfo->bufptr = last_bufptr;
472             pInfo->bitoff = last_bitoff;
473             status = vc1_ParseFieldHeader_Adv(ctxt, pInfo);
474         }
475     } else
476         pInfo->picture_info_has_changed = 0;
477 
478     pInfo->picLayerHeader.SLICE_ADDR = SLICE_ADDR;
479 
480     return status;
481 }
482 
483 /*------------------------------------------------------------------------------
484  * This function parses the user data information as defined in SMPTE 421M annex F.
485  * It then appends that data to the workload.
486  * Assume the flush byte 0x80 is within the 3 bytes before next start code.
487  * let's put 1 byte per item first
488  *------------------------------------------------------------------------------
489  */
vc1_ParseAndAppendUserData(void * ctxt,uint32_t sc)490 vc1_Status vc1_ParseAndAppendUserData(void* ctxt, uint32_t sc)
491 {
492     vc1_Status status = VC1_STATUS_OK;
493     uint32_t user_data;
494     viddec_workload_item_t wi;
495     uint32_t ud_id;
496 
497     /* find the scope based on start code sc */
498     switch(sc) {
499         case vc1_SCSequenceUser:
500             wi.vwi_type = VIDDEC_WORKLOAD_SEQ_USER_DATA;
501             break;
502         case vc1_SCEntryPointUser:
503             wi.vwi_type = VIDDEC_WORKLOAD_GOP_USER_DATA;
504             break;
505         case vc1_SCFrameUser:
506             wi.vwi_type = VIDDEC_WORKLOAD_FRM_USER_DATA;
507             break;
508         case vc1_SCFieldUser:
509             wi.vwi_type = VIDDEC_WORKLOAD_FLD_USER_DATA;
510             break;
511         case vc1_SCSliceUser:
512             wi.vwi_type = VIDDEC_WORKLOAD_SLC_USER_DATA;
513             break;
514         default:
515             wi.vwi_type = VIDDEC_WORKLOAD_INVALID; //ERROR - should not happen
516             break;
517     }
518 
519     /* get identifier - 4 bytes*/
520     // Extract this information but discard it for now
521     VC1_GET_BITS(32, ud_id);
522 
523     /* Read 1 byte of user data and store it in workitem for the current stream level (SEQ/GOP/PIC).
524        Keep adding data payloads till it reaches size 11. When it is 11, the maximum user data payload size,
525        append the workitem. This loop is repeated till all user data is extracted and appended. */
526     wi.user_data.size = 0;
527     while(viddec_pm_get_bits(ctxt, &user_data, 8) != -1)
528     {
529         /* Store the valid byte in data payload */
530         wi.user_data.data_payload[wi.user_data.size] = user_data;
531         wi.user_data.size++;
532 
533         /* When size exceeds payload size, append workitem and continue */
534         if (wi.user_data.size >= 11)
535         {
536             viddec_pm_setup_userdata(&wi);
537             viddec_pm_append_workitem(ctxt, &wi);
538             wi.user_data.size = 0;
539         }
540         if(user_data == 0x80) // flushing byte
541             break;
542     }
543     /* If size is not 0, append remaining user data. */
544     if (wi.user_data.size > 0)
545     {
546         int i;
547         for(i=wi.user_data.size;i<11;i++)
548         {
549             wi.user_data.data_payload[i] = 0;
550         }
551         viddec_pm_setup_userdata(&wi);
552         viddec_pm_append_workitem(ctxt, &wi);
553         wi.user_data.size = 0;
554     }
555 
556     return(status);
557 } // vc1_ParseAndAppendUserData
558