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