1 #include "viddec_mp4_videoobjectplane.h"
2
mp4_Parse_GroupOfVideoObjectPlane(void * parent,viddec_mp4_parser_t * parser)3 mp4_Status_t mp4_Parse_GroupOfVideoObjectPlane(void *parent, viddec_mp4_parser_t *parser)
4 {
5 mp4_Info_t* pInfo = &(parser->info);
6 uint32_t code;
7 int32_t getbits=0;
8 mp4_Status_t ret = MP4_STATUS_REQD_DATA_ERROR;
9 mp4_GroupOfVideoObjectPlane_t *data;
10 uint32_t time_code = 0;
11
12 data = &(pInfo->VisualObject.VideoObject.GroupOfVideoObjectPlane);
13
14 do
15 {
16 getbits = viddec_pm_get_bits(parent, &code, 20);
17 BREAK_GETBITS_FAIL(getbits, ret);
18 ret = MP4_STATUS_OK;
19
20 data->broken_link = ((code & 0x1) > 0);
21 data->closed_gov = ((code & 0x2) > 0);
22 time_code = code = code >> 2;
23 data->time_code_seconds = code & 0x3F;
24 code = code >> 6;
25 if((code & 1) == 0)
26 {/* SGA:Should we ignore marker bit? */
27 DEB("Error:mp4_Parse_GroupOfVideoObjectPlane: Invalid marker\n");
28 }
29 code = code >>1;
30 data->time_code_minutes = code & 0x3F;
31 code = code >> 6;
32 data->time_code_hours = code & 0x1F;
33
34 // This is the timebase in full second units
35 data->time_base = data->time_code_seconds + (60*data->time_code_minutes) + (3600*data->time_code_hours);
36 // Need to convert this into no. of ticks
37 data->time_base *= pInfo->VisualObject.VideoObject.vop_time_increment_resolution;
38
39 } while(0);
40
41 mp4_set_hdr_bitstream_error(parser, true, ret);
42
43 // POPULATE WORKLOAD ITEM
44 {
45 viddec_workload_item_t wi;
46
47 wi.vwi_type = VIDDEC_WORKLOAD_MPEG4_GRP_VIDEO_OBJ;
48
49 wi.mp4_gvop.gvop_info = 0;
50 wi.mp4_gvop.pad1 = 0;
51 wi.mp4_gvop.pad2 = 0;
52
53 viddec_fw_mp4_gvop_set_broken_link(&wi.mp4_gvop, data->broken_link);
54 viddec_fw_mp4_gvop_set_closed_gov(&wi.mp4_gvop, data->closed_gov);
55 viddec_fw_mp4_gvop_set_time_code(&wi.mp4_gvop, time_code);
56
57 ret = viddec_pm_append_workitem(parent, &wi);
58 if(ret == 1)
59 ret = MP4_STATUS_OK;
60 }
61
62 return ret;
63 }
64
mp4_brightness_change(void * parent,int32_t * b_change)65 static inline mp4_Status_t mp4_brightness_change(void *parent, int32_t *b_change)
66 {
67 uint32_t code;
68 int32_t getbits=0;
69
70 *b_change = 0;
71 getbits = viddec_pm_peek_bits(parent, &code, 4);
72 if (code == 15)
73 {
74 getbits = viddec_pm_skip_bits(parent, 4);
75 getbits = viddec_pm_get_bits(parent, &code, 10);
76 *b_change = 625 + code;
77 }
78 else if (code == 14)
79 {
80 getbits = viddec_pm_skip_bits(parent, 4);
81 getbits = viddec_pm_get_bits(parent, &code, 9);
82 *b_change = 113 + code;
83 }
84 else if (code >= 12)
85 {
86 getbits = viddec_pm_skip_bits(parent, 3);
87 getbits = viddec_pm_get_bits(parent, &code, 7);
88 *b_change = (code < 64) ? ((int32_t)code - 112) : ((int32_t)code - 15);
89 }
90 else if (code >= 8)
91 {
92 getbits = viddec_pm_skip_bits(parent, 2);
93 getbits = viddec_pm_get_bits(parent, &code, 6);
94 *b_change = (code < 32) ? ((int32_t)code - 48) : ((int32_t)code - 15);
95 }
96 else
97 {
98 getbits = viddec_pm_skip_bits(parent, 1);
99 getbits = viddec_pm_get_bits(parent, &code, 5);
100 *b_change = (code < 16) ? ((int32_t)code - 16) : ((int32_t)code - 15);
101 }
102
103 return ( (getbits == -1) ? MP4_STATUS_PARSE_ERROR: MP4_STATUS_OK);
104 }
mp4_Sprite_dmv_length(void * parent,int32_t * dmv_length)105 static inline int32_t mp4_Sprite_dmv_length(void * parent, int32_t *dmv_length)
106 {
107 uint32_t code, skip;
108 int32_t getbits=0;
109 mp4_Status_t ret= MP4_STATUS_PARSE_ERROR;
110 *dmv_length=0;
111 skip=3;
112 do{
113 getbits = viddec_pm_peek_bits(parent, &code, skip);
114 BREAK_GETBITS_REQD_MISSING(getbits, ret);
115
116 if(code == 7)
117 {
118 viddec_pm_skip_bits(parent, skip);
119 getbits = viddec_pm_peek_bits(parent, &code, 9);
120 BREAK_GETBITS_REQD_MISSING(getbits, ret);
121
122 skip=1;
123 while((code & 256) != 0)
124 {/* count number of 1 bits */
125 code <<=1;
126 skip++;
127 }
128 *dmv_length = 5 + skip;
129 }
130 else
131 {
132 skip=(code <= 1) ? 2 : 3;
133 *dmv_length = code - 1;
134 }
135 viddec_pm_skip_bits(parent, skip);
136 ret= MP4_STATUS_OK;
137
138 }while(0);
139 return ret;
140 }
141
142 static inline mp4_Status_t
mp4_Sprite_Trajectory(void * parent,mp4_VideoObjectLayer_t * vidObjLay,mp4_VideoObjectPlane_t * vidObjPlane)143 mp4_Sprite_Trajectory(void *parent, mp4_VideoObjectLayer_t *vidObjLay, mp4_VideoObjectPlane_t *vidObjPlane)
144 {
145 uint32_t code, i;
146 int32_t dmv_length=0, dmv_code=0, getbits=0;
147 mp4_Status_t ret = MP4_STATUS_OK;
148 for(i=0; i < (uint32_t)vidObjLay->sprite_info.no_of_sprite_warping_points; i++ )
149 {
150 ret = mp4_Sprite_dmv_length(parent, &dmv_length);
151 if(ret != MP4_STATUS_OK)
152 {
153 break;
154 }
155 if(dmv_length <= 0)
156 {
157 dmv_code = 0;
158 }
159 else
160 {
161 getbits = viddec_pm_get_bits(parent, &code, (uint32_t)dmv_length);
162 BREAK_GETBITS_REQD_MISSING(getbits, ret);
163 dmv_code = (int32_t)code;
164 if ((dmv_code & (1 << (dmv_length - 1))) == 0)
165 {
166 dmv_code -= (1 << dmv_length) - 1;
167 }
168 }
169 getbits = viddec_pm_get_bits(parent, &code, 1);
170 BREAK_GETBITS_REQD_MISSING(getbits, ret);
171 if(code != 1)
172 {
173 ret = MP4_STATUS_NOTSUPPORT;
174 break;
175 }
176 vidObjPlane->warping_mv_code_du[i] = dmv_code;
177 /* TODO: create another inline function to avoid code duplication */
178 ret = mp4_Sprite_dmv_length(parent, &dmv_length);
179 if(ret != MP4_STATUS_OK)
180 {
181 break;
182 }
183 if(dmv_length <= 0)
184 {
185 dmv_code = 0;
186 }
187 else
188 {
189 getbits = viddec_pm_get_bits(parent, &code, (uint32_t)dmv_length);
190 BREAK_GETBITS_REQD_MISSING(getbits, ret);
191 dmv_code = (int32_t)code;
192 if ((dmv_code & (1 << (dmv_length - 1))) == 0)
193 {
194 dmv_code -= (1 << dmv_length) - 1;
195 }
196 }
197 getbits = viddec_pm_get_bits(parent, &code, 1);
198 BREAK_GETBITS_REQD_MISSING(getbits, ret);
199 if(code != 1)
200 {
201 ret = MP4_STATUS_NOTSUPPORT;
202 break;
203 }
204 vidObjPlane->warping_mv_code_dv[i] = dmv_code;
205
206 }
207 return ret;
208 }
209
mp4_pvt_extract_modulotimebase_from_VideoObjectPlane(void * parent,uint32_t * base)210 static inline mp4_Status_t mp4_pvt_extract_modulotimebase_from_VideoObjectPlane(void *parent, uint32_t *base)
211 {
212 mp4_Status_t ret= MP4_STATUS_OK;
213 int32_t getbits=0;
214 uint32_t code = 0;
215
216 *base = 0;
217 do
218 {
219 getbits = viddec_pm_get_bits(parent, &code, 1);
220 BREAK_GETBITS_REQD_MISSING(getbits, ret);
221 *base += code;
222 }while(code != 0);
223 return ret;
224 }
225
mp4_Parse_VideoObjectPlane(void * parent,viddec_mp4_parser_t * parser)226 mp4_Status_t mp4_Parse_VideoObjectPlane(void *parent, viddec_mp4_parser_t *parser)
227 {
228 uint32_t code;
229 mp4_Info_t *pInfo = &(parser->info);
230 mp4_VideoObjectLayer_t *vidObjLay = &(pInfo->VisualObject.VideoObject);
231 mp4_VideoObjectPlane_t *vidObjPlane = &(pInfo->VisualObject.VideoObject.VideoObjectPlane);
232 int32_t getbits=0;
233 mp4_Status_t ret= MP4_STATUS_PARSE_ERROR;
234
235 do
236 {
237 getbits = viddec_pm_get_bits(parent, &code, 2);
238 BREAK_GETBITS_REQD_MISSING(getbits, ret);
239 vidObjPlane->vop_coding_type = code & 0x3;
240 if( mp4_pvt_extract_modulotimebase_from_VideoObjectPlane(parent,
241 &(vidObjPlane->modulo_time_base)) == MP4_STATUS_REQD_DATA_ERROR)
242 {
243 break;
244 }
245
246 getbits = viddec_pm_get_bits(parent, &code, 1);
247 /* TODO: check for marker bit validity */
248 {
249 uint32_t numbits=0;
250 numbits = vidObjLay->vop_time_increment_resolution_bits;
251 if(numbits == 0) numbits=1; /*TODO:check if its greater than 16 bits ?? */
252 getbits = viddec_pm_get_bits(parent, &code, numbits);
253 BREAK_GETBITS_REQD_MISSING(getbits, ret);
254 vidObjPlane->vop_time_increment = code;
255 }
256
257 getbits = viddec_pm_get_bits(parent, &code, 2);
258 BREAK_GETBITS_REQD_MISSING(getbits, ret);
259
260 vidObjPlane->vop_coded = code & 0x1;
261 if(vidObjPlane->vop_coded == 0)
262 {
263 ret = MP4_STATUS_OK;/* Exit point 1 */
264 break;
265 }
266
267 if(vidObjLay->newpred_enable)
268 {
269 /* New pred mode not supported in HW */
270 DEB("Error: mp4_Parse_VideoObjectPlane: New pred in vidObjPlane is not supported\n");
271 ret = MP4_STATUS_NOTSUPPORT;
272 break;
273 }
274
275 if ((vidObjLay->video_object_layer_shape != MP4_SHAPE_TYPE_BINARYONLY) &&
276 ((vidObjPlane->vop_coding_type == MP4_VOP_TYPE_P) ||
277 ((vidObjPlane->vop_coding_type == MP4_VOP_TYPE_S) &&
278 (vidObjLay->sprite_enable == MP4_SPRITE_GMC))))
279 {
280 getbits = viddec_pm_get_bits(parent, &code, 1);
281 BREAK_GETBITS_REQD_MISSING(getbits, ret);
282 vidObjPlane->vop_rounding_type = code;
283 }
284
285 if (vidObjLay->reduced_resolution_vop_enable &&
286 (vidObjLay->video_object_layer_shape == MP4_SHAPE_TYPE_RECTANGULAR) &&
287 ((vidObjPlane->vop_coding_type == MP4_VOP_TYPE_I) ||
288 (vidObjPlane->vop_coding_type == MP4_VOP_TYPE_P)))
289 {
290 getbits = viddec_pm_get_bits(parent, &code, 1);
291 BREAK_GETBITS_REQD_MISSING(getbits, ret);
292 vidObjPlane->vop_reduced_resolution = code;
293 if (vidObjPlane->vop_reduced_resolution)
294 {
295 DEB("Error: mp4_Parse_VideoObjectPlane: Reduced Resolution vidObjPlane is not supported\n");
296 ret = MP4_STATUS_NOTSUPPORT;
297 break;
298 }
299 }
300
301 if (vidObjLay->video_object_layer_shape != MP4_SHAPE_TYPE_RECTANGULAR)
302 {
303 /* we support only rectangular shapes so the following logic is not required */
304 ret = MP4_STATUS_NOTSUPPORT;
305 break;
306 }
307
308 if ((vidObjLay->video_object_layer_shape != MP4_SHAPE_TYPE_BINARYONLY) &&
309 (!vidObjLay->complexity_estimation_disable))
310 {
311 /* Not required according to DE team */
312 //read_vop_complexity_estimation_header();
313 ret = MP4_STATUS_NOTSUPPORT;
314 break;
315 }
316
317 if (vidObjLay->video_object_layer_shape != MP4_SHAPE_TYPE_BINARYONLY)
318 {
319 getbits = viddec_pm_get_bits(parent, &code, 3);
320 BREAK_GETBITS_REQD_MISSING(getbits, ret);
321 vidObjPlane->intra_dc_vlc_thr = code;
322 if (vidObjLay->interlaced)
323 {
324 getbits = viddec_pm_get_bits(parent, &code, 2);
325 BREAK_GETBITS_REQD_MISSING(getbits, ret);
326 vidObjPlane->top_field_first = ((code & 0x2) > 0);
327 vidObjPlane->alternate_vertical_scan_flag = code & 0x1;
328 }
329 }
330
331 if (((vidObjLay->sprite_enable == MP4_SPRITE_STATIC) || (vidObjLay->sprite_enable == MP4_SPRITE_GMC)) &&
332 (vidObjPlane->vop_coding_type == MP4_VOP_TYPE_S))
333 {
334 if (vidObjLay->sprite_info.no_of_sprite_warping_points > 0){
335 if (mp4_Sprite_Trajectory(parent, vidObjLay, vidObjPlane) != MP4_STATUS_OK){
336 break;
337 }
338 }
339 vidObjPlane->brightness_change_factor = 0;
340 if (vidObjLay->sprite_info.sprite_brightness_change)
341 {
342 int32_t change=0;
343 if(mp4_brightness_change(parent, &change) == MP4_STATUS_PARSE_ERROR)
344 {
345 break;
346 }
347 vidObjPlane->brightness_change_factor = change;
348 }
349
350 if (vidObjLay->sprite_enable == MP4_SPRITE_STATIC)
351 {
352 /* SGA: IS decode sprite not required. Is static even supported */
353 ret = MP4_STATUS_OK;/* Exit point 2 */
354 break;
355 }
356 }
357
358 if (vidObjLay->video_object_layer_shape != MP4_SHAPE_TYPE_BINARYONLY)
359 {
360 // Length of vop_quant is specified by quant_precision
361 getbits = viddec_pm_get_bits(parent, &code, vidObjLay->quant_precision);
362 BREAK_GETBITS_REQD_MISSING(getbits, ret);
363 vidObjPlane->vop_quant = code;
364 if (vidObjLay->video_object_layer_shape == MP4_SHAPE_TYPE_GRAYSCALE)
365 {
366 ret = MP4_STATUS_NOTSUPPORT;
367 break;
368 }
369 if (vidObjPlane->vop_coding_type != MP4_VOP_TYPE_I)
370 {
371 vidObjPlane->vop_fcode_forward = 0;
372 getbits = viddec_pm_get_bits(parent, &code, 3);
373 BREAK_GETBITS_REQD_MISSING(getbits, ret);
374 vidObjPlane->vop_fcode_forward = code & 0x7;
375 if (vidObjPlane->vop_fcode_forward == 0)
376 {
377 DEB("Error: vop_fcode_forward == 0\n");
378 break;
379 }
380 }
381 if (vidObjPlane->vop_coding_type == MP4_VOP_TYPE_B)
382 {
383 vidObjPlane->vop_fcode_backward = 0;
384 getbits = viddec_pm_get_bits(parent, &code, 3);
385 BREAK_GETBITS_REQD_MISSING(getbits, ret);
386 vidObjPlane->vop_fcode_backward = code &0x7;
387 if (vidObjPlane->vop_fcode_backward == 0)
388 {
389 DEB("Error: vop_fcode_backward == 0\n");
390 break;
391 }
392 }
393 if (!vidObjLay->scalability)
394 {
395 if ((vidObjLay->video_object_layer_shape != MP4_SHAPE_TYPE_RECTANGULAR) &&
396 (vidObjPlane->vop_coding_type != MP4_VOP_TYPE_I))
397 {
398 ret = MP4_STATUS_NOTSUPPORT;
399 break;
400 }
401 // The remaining data contains the macroblock information that is handled by the BSP
402 // The offsets to be sent to the BSP are obtained in the workload population
403 }
404 else
405 {
406 ret = MP4_STATUS_NOTSUPPORT;
407 break;
408 }
409 }
410 else
411 {/* Binary Not supported */
412 ret = MP4_STATUS_NOTSUPPORT;
413 break;
414 }
415 /* Since we made it all the way here it a success condition */
416 ret = MP4_STATUS_OK; /* Exit point 3 */
417 }while(0);
418
419 mp4_set_hdr_bitstream_error(parser, false, ret);
420
421 return ret;
422 } // mp4_Parse_VideoObjectPlane
423