• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "viddec_fw_debug.h"    // For DEB
2 #include "viddec_parser_ops.h"  // For parser helper functions
3 #include "vc1.h"                // For the parser structure
4 #include "vc1parse.h"           // For vc1 parser helper functions
5 #ifdef VBP
6 #include "viddec_pm.h"
7 #endif
8 #define vc1_is_frame_start_code( ch )                                   \
9     (( vc1_SCField == ch ||vc1_SCSlice == ch || vc1_SCFrameHeader == ch ) ? 1 : 0)
10 
11 /* init function */
12 #ifdef VBP
viddec_vc1_init(void * ctxt,uint32_t * persist_mem,uint32_t preserve)13 void viddec_vc1_init(void *ctxt, uint32_t *persist_mem, uint32_t preserve)
14 #else
15 static void viddec_vc1_init(void *ctxt, uint32_t *persist_mem, uint32_t preserve)
16 #endif
17 {
18     vc1_viddec_parser_t *parser = ctxt;
19     int i;
20 
21     persist_mem = persist_mem;
22 
23     for(i=0; i<VC1_NUM_REFERENCE_FRAMES; i++)
24     {
25         parser->ref_frame[i].id   = -1; /* first I frame checks that value */
26         parser->ref_frame[i].anchor[0] = 1;
27         parser->ref_frame[i].anchor[1] = 1;
28         parser->ref_frame[i].intcomp_top = 0;
29         parser->ref_frame[i].intcomp_bot = 0;
30     }
31 
32     parser->intcomp_top[0] = 0;
33     parser->intcomp_bot[0] = 0;
34     parser->intcomp_top[1] = 0;
35     parser->intcomp_bot[1] = 0;
36     parser->is_reference_picture = false;
37 
38     memset(&parser->info.picLayerHeader, 0, sizeof(vc1_PictureLayerHeader));
39 
40     if(preserve)
41     {
42         parser->sc_seen &= VC1_EP_MASK;
43         parser->sc_seen_since_last_wkld &= VC1_EP_MASK;
44     }
45     else
46     {
47         parser->sc_seen = VC1_SC_INVALID;
48         parser->sc_seen_since_last_wkld = VC1_SC_INVALID;
49         memset(&parser->info.metadata, 0, sizeof(parser->info.metadata));
50     }
51 
52     return;
53 } // viddec_vc1_init
54 
vc1_swap_intcomp(vc1_viddec_parser_t * parser)55 static void vc1_swap_intcomp(vc1_viddec_parser_t *parser)
56 {
57     parser->intcomp_top[1] = parser->intcomp_top[0];
58     parser->intcomp_bot[1] = parser->intcomp_bot[0];
59     parser->intcomp_top[0] = 0;
60     parser->intcomp_bot[0] = 0;
61 
62     return;
63 } // vc1_swap_intcomp
64 
65 #ifdef VBP
viddec_vc1_parse(void * parent,void * ctxt)66 uint32_t viddec_vc1_parse(void *parent, void *ctxt)
67 #else
68 static uint32_t viddec_vc1_parse(void *parent, void *ctxt)
69 #endif
70 {
71     vc1_viddec_parser_t *parser = ctxt;
72     uint32_t sc=0x0;
73     int32_t ret=0, status=0;
74 
75 #ifdef VBP
76     /* This works only if there is one slice and no start codes */
77     /* A better fix would be to insert start codes it there aren't any. */
78     ret = viddec_pm_peek_bits(parent, &sc, 32);
79     if ((sc > 0x0100) && (sc < 0x0200)) /* a Start code will be in this range. */
80     {
81       ret = viddec_pm_get_bits(parent, &sc, 32);
82     }
83     else
84     {
85       /* In cases where we get a buffer with no start codes, we assume */
86       /* that this is a frame of data. We may have to fix this later. */
87       sc = vc1_SCFrameHeader;
88     }
89 #else
90     ret = viddec_pm_get_bits(parent, &sc, 32);
91 #endif
92     sc = sc & 0xFF;
93     parser->is_frame_start = (sc == vc1_SCFrameHeader);
94     DEB("START_CODE = %02x\n", sc);
95     switch( sc )
96     {
97         case vc1_SCSequenceHeader:
98         {
99             uint32_t data=0;
100             parser->ref_frame[0].anchor[0] = 1;
101             parser->ref_frame[0].anchor[1] = 1;
102             parser->ref_frame[1].anchor[0] = 1;
103             parser->ref_frame[1].anchor[1] = 1;
104             memset( &parser->info.metadata, 0, sizeof(parser->info.metadata));
105             /* look if we have a rcv header for main or simple profile */
106             ret = viddec_pm_peek_bits(parent,&data ,2);
107 
108             if (data == 3)
109             {
110                 status = vc1_ParseSequenceLayer(parent, &parser->info);
111             }
112             else
113             {
114                 status = vc1_ParseRCVSequenceLayer(parent, &parser->info);
115             }
116             parser->sc_seen = VC1_SC_SEQ;
117             parser->sc_seen_since_last_wkld |= VC1_SC_SEQ;
118 #ifdef VBP
119 			parser->start_code = VC1_SC_SEQ;
120 #endif
121             break;
122         }
123 
124         case vc1_SCEntryPointHeader:
125         {
126             status = vc1_ParseEntryPointLayer(parent, &parser->info);
127             parser->sc_seen |= VC1_SC_EP;
128             // Clear all bits indicating data below ep header
129             parser->sc_seen &= VC1_EP_MASK;
130             parser->sc_seen_since_last_wkld |= VC1_SC_EP;
131 #ifdef VBP
132 			parser->start_code = VC1_SC_EP;
133 #endif
134 			break;
135         }
136 
137         case vc1_SCFrameHeader:
138         {
139             memset(&parser->info.picLayerHeader, 0, sizeof(vc1_PictureLayerHeader));
140             status = vc1_ParsePictureLayer(parent, &parser->info);
141             if((parser->info.picLayerHeader.PTypeField1 == VC1_I_FRAME) ||
142                (parser->info.picLayerHeader.PTypeField1 == VC1_P_FRAME) ||
143                (parser->info.picLayerHeader.PTYPE == VC1_I_FRAME) ||
144                (parser->info.picLayerHeader.PTYPE == VC1_P_FRAME))
145             {
146                 vc1_swap_intcomp(parser);
147             }
148             parser->sc_seen |= VC1_SC_FRM;
149             // Clear all bits indicating data below frm header
150             parser->sc_seen &= VC1_FRM_MASK;
151             parser->sc_seen_since_last_wkld |= VC1_SC_FRM;
152             vc1_start_new_frame ( parent, parser );
153 #ifdef VBP
154 			parser->start_code = VC1_SC_FRM;
155 #endif
156 			break;
157         }
158 
159         case vc1_SCSlice:
160         {
161             status = vc1_ParseSliceLayer(parent, &parser->info);
162             parser->sc_seen_since_last_wkld |= VC1_SC_SLC;
163 #ifdef VBP
164          	parser->start_code = VC1_SC_SLC;
165 #endif
166             break;
167         }
168 
169         case vc1_SCField:
170         {
171             parser->info.picLayerHeader.SLICE_ADDR = 0;
172             parser->info.picLayerHeader.CurrField = 1;
173             parser->info.picLayerHeader.REFFIELD = 0;
174             parser->info.picLayerHeader.NUMREF = 0;
175             parser->info.picLayerHeader.MBMODETAB = 0;
176             parser->info.picLayerHeader.MV4SWITCH = 0;
177             parser->info.picLayerHeader.DMVRANGE = 0;
178             parser->info.picLayerHeader.MVTAB = 0;
179             parser->info.picLayerHeader.MVMODE = 0;
180             parser->info.picLayerHeader.MVRANGE = 0;
181 #ifdef VBP
182 			parser->info.picLayerHeader.raw_MVTYPEMB = 0;
183 			parser->info.picLayerHeader.raw_DIRECTMB = 0;
184 			parser->info.picLayerHeader.raw_SKIPMB = 0;
185 			parser->info.picLayerHeader.raw_ACPRED = 0;
186 			parser->info.picLayerHeader.raw_FIELDTX = 0;
187 			parser->info.picLayerHeader.raw_OVERFLAGS = 0;
188 			parser->info.picLayerHeader.raw_FORWARDMB = 0;
189 
190 			memset(&(parser->info.picLayerHeader.MVTYPEMB), 0, sizeof(vc1_Bitplane));
191 			memset(&(parser->info.picLayerHeader.DIRECTMB), 0, sizeof(vc1_Bitplane));
192 			memset(&(parser->info.picLayerHeader.SKIPMB), 0, sizeof(vc1_Bitplane));
193 			memset(&(parser->info.picLayerHeader.ACPRED), 0, sizeof(vc1_Bitplane));
194 			memset(&(parser->info.picLayerHeader.FIELDTX), 0, sizeof(vc1_Bitplane));
195 			memset(&(parser->info.picLayerHeader.OVERFLAGS), 0, sizeof(vc1_Bitplane));
196 			memset(&(parser->info.picLayerHeader.FORWARDMB), 0, sizeof(vc1_Bitplane));
197 
198 			parser->info.picLayerHeader.ALTPQUANT = 0;
199 			parser->info.picLayerHeader.DQDBEDGE = 0;
200  #endif
201 
202             status = vc1_ParseFieldLayer(parent, &parser->info);
203             if((parser->info.picLayerHeader.PTypeField2 == VC1_I_FRAME) ||
204                (parser->info.picLayerHeader.PTypeField2 == VC1_P_FRAME))
205             {
206                 vc1_swap_intcomp(parser);
207             }
208 
209             parser->sc_seen |= VC1_SC_FLD;
210             parser->sc_seen_since_last_wkld |= VC1_SC_FLD;
211 #ifdef VBP
212 			parser->start_code = VC1_SC_FLD;
213 #endif
214             break;
215         }
216 
217         case vc1_SCSequenceUser:
218         case vc1_SCEntryPointUser:
219         case vc1_SCFrameUser:
220         case vc1_SCSliceUser:
221         case vc1_SCFieldUser:
222         {/* Handle user data */
223             status = vc1_ParseAndAppendUserData(parent, sc); //parse and add items
224             parser->sc_seen_since_last_wkld |= VC1_SC_UD;
225 #ifdef VBP
226             parser->start_code = VC1_SC_UD;
227 #endif
228             break;
229         }
230 
231         case vc1_SCEndOfSequence:
232         {
233             parser->sc_seen = VC1_SC_INVALID;
234             parser->sc_seen_since_last_wkld |= VC1_SC_INVALID;
235 #ifdef VBP
236             parser->start_code = VC1_SC_INVALID;
237 #endif
238             break;
239         }
240         default: /* Any other SC that is not handled */
241         {
242             DEB("SC = %02x - unhandled\n", sc );
243 #ifdef VBP
244             parser->start_code = VC1_SC_INVALID;
245 #endif
246             break;
247         }
248     }
249 
250     if( vc1_is_frame_start_code( sc ) ) {
251         vc1_parse_emit_current_frame( parent, parser );
252     }
253 
254     return VIDDEC_PARSE_SUCESS;
255 } // viddec_vc1_parse
256 
257 /**
258    If a picture header was seen and the next start code is a sequence header, entrypoint header,
259    end of sequence or another frame header, this api returns frame done.
260    If a sequence header and a frame header was not seen before this point, all the
261    information needed for decode is not present and parser errors are reported.
262 */
263 #ifdef VBP
viddec_vc1_wkld_done(void * parent,void * ctxt,unsigned int next_sc,uint32_t * codec_specific_errors)264 uint32_t viddec_vc1_wkld_done(void *parent, void *ctxt, unsigned int next_sc, uint32_t *codec_specific_errors)
265 #else
266 static uint32_t viddec_vc1_wkld_done(void *parent, void *ctxt, unsigned int next_sc, uint32_t *codec_specific_errors)
267 #endif
268 {
269     vc1_viddec_parser_t *parser = ctxt;
270     int ret = VIDDEC_PARSE_SUCESS;
271     parent = parent;
272     switch (next_sc)
273     {
274         case vc1_SCFrameHeader:
275             if(((parser->sc_seen_since_last_wkld & VC1_SC_EP) ||
276                 (parser->sc_seen_since_last_wkld & VC1_SC_SEQ)) &&
277                (!(parser->sc_seen_since_last_wkld & VC1_SC_FRM)))
278             {
279                 break;
280             }
281             // Deliberate fall-thru case
282         case vc1_SCEntryPointHeader:
283             if((next_sc == vc1_SCEntryPointHeader) &&
284                (parser->sc_seen_since_last_wkld & VC1_SC_SEQ) &&
285                (!(parser->sc_seen_since_last_wkld & VC1_SC_EP)))
286             {
287                 break;
288             }
289             // Deliberate fall-thru case
290         case vc1_SCSequenceHeader:
291         case vc1_SCEndOfSequence:
292         case VIDDEC_PARSE_EOS:
293         case VIDDEC_PARSE_DISCONTINUITY:
294             ret = VIDDEC_PARSE_FRMDONE;
295             // Set errors for progressive
296             if((parser->sc_seen & VC1_SC_SEQ) && (parser->sc_seen & VC1_SC_FRM))
297                 *codec_specific_errors = 0;
298             else
299                 *codec_specific_errors |= VIDDEC_FW_WORKLOAD_ERR_NOTDECODABLE;
300             vc1_end_frame(parser);
301             parser->sc_seen_since_last_wkld = VC1_SC_INVALID;
302             // TODO: Need to check for interlaced
303             break;
304         default:
305             ret = VIDDEC_PARSE_SUCESS;
306             break;
307     } //switch
308     DEB("sc: 0x%x, sc_seen: 0x%x, sc_since_last_wkld:%d, error:%d, ret: %d\n",
309         next_sc, parser->sc_seen, parser->sc_seen_since_last_wkld,
310         *codec_specific_errors, ret);
311 
312     return ret;
313 } // viddec_vc1_wkld_done
314 
315 #ifdef VBP
viddec_vc1_get_context_size(viddec_parser_memory_sizes_t * size)316 void viddec_vc1_get_context_size(viddec_parser_memory_sizes_t *size)
317 #else
318 static void viddec_vc1_get_context_size(viddec_parser_memory_sizes_t *size)
319 #endif
320 {
321     size->context_size = sizeof(vc1_viddec_parser_t);
322     size->persist_size = 0;
323     return;
324 } // viddec_vc1_get_context_size
325 
326 #ifdef VBP
viddec_vc1_is_start_frame(void * ctxt)327 uint32_t viddec_vc1_is_start_frame(void *ctxt)
328 #else
329 static uint32_t viddec_vc1_is_start_frame(void *ctxt)
330 #endif
331 {
332     vc1_viddec_parser_t *parser = (vc1_viddec_parser_t *) ctxt;
333     return parser->is_frame_start;
334 } // viddec_vc1_is_start_frame
335 
viddec_vc1_get_ops(viddec_parser_ops_t * ops)336 void viddec_vc1_get_ops(viddec_parser_ops_t *ops)
337 {
338     ops->init = viddec_vc1_init;
339     ops->parse_syntax = viddec_vc1_parse;
340     ops->get_cxt_size = viddec_vc1_get_context_size;
341     ops->is_wkld_done = viddec_vc1_wkld_done;
342     ops->is_frame_start = viddec_vc1_is_start_frame;
343     return;
344 } // viddec_vc1_get_ops
345 
346