1 /******************************************************************************
2 *
3 * Copyright (C) 2021 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20
21 /*****************************************************************************/
22 /* */
23 /* File Name : imvcd_error_handler.c */
24 /* */
25 /* Description : Functions for error handling */
26 /* */
27 /*****************************************************************************/
28
29 #include "ih264_typedefs.h"
30 #include "iv.h"
31 #include "imvcd.h"
32 #include "ih264_macros.h"
33 #include "imvc_defs.h"
34 #include "ih264d_defs.h"
35 #include "ih264d_error_handler.h"
36 #include "ih264d_nal.h"
37 #include "ih264d_structs.h"
38 #include "imvcd_structs.h"
39 #include "imvcd_utils.h"
40
imvcd_check_invalid_numViews(mvc_dec_ctxt_t * ps_mvcd_ctxt)41 static IV_API_CALL_STATUS_T imvcd_check_invalid_numViews(mvc_dec_ctxt_t *ps_mvcd_ctxt)
42 {
43 WORD32 i;
44
45 UWORD8 u1_num_valid_subset_sps_found = 0;
46 UWORD16 u2_max_views = 1;
47
48 if((ps_mvcd_ctxt->u1_num_subset_sps == 0) && (ps_mvcd_ctxt->u2_num_views_decoded > 0))
49 {
50 return IV_FAIL;
51 }
52
53 for(i = 0; i < MAX_NUM_SEQ_PARAMS; i++)
54 {
55 if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_is_valid)
56 {
57 if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_mvc_ext.u2_num_views > MAX_NUM_VIEWS)
58 {
59 return IV_FAIL;
60 }
61
62 u2_max_views =
63 MAX(u2_max_views, ps_mvcd_ctxt->as_subset_sps[i].s_sps_mvc_ext.u2_num_views);
64 u1_num_valid_subset_sps_found++;
65 }
66 }
67
68 if(u1_num_valid_subset_sps_found > ps_mvcd_ctxt->u1_num_subset_sps)
69 {
70 return IV_FAIL;
71 }
72
73 if(ps_mvcd_ctxt->u2_num_views > u2_max_views)
74 {
75 return IV_FAIL;
76 }
77
78 if(ps_mvcd_ctxt->u2_num_views_decoded >= u2_max_views)
79 {
80 return IV_FAIL;
81 }
82
83 return IV_SUCCESS;
84 }
85
imvcd_check_sps_and_subset_sps(mvc_dec_ctxt_t * ps_mvcd_ctxt)86 static IV_API_CALL_STATUS_T imvcd_check_sps_and_subset_sps(mvc_dec_ctxt_t *ps_mvcd_ctxt)
87 {
88 UWORD32 i;
89 UWORD32 u4_cnt;
90
91 dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt;
92
93 UWORD32 u4_num_sps = ps_mvcd_ctxt->u1_num_sps;
94 UWORD32 u4_num_subset_sps = ps_mvcd_ctxt->u1_num_subset_sps;
95 WORD32 i4_max_mb_addr = INT32_MIN;
96
97 i = 0;
98 u4_cnt = 0;
99
100 while((u4_cnt < u4_num_sps) && (i < MAX_NUM_SEQ_PARAMS))
101 {
102 if(ps_view_ctxt->ps_sps[i].u1_is_valid)
103 {
104 u4_cnt++;
105
106 if(i4_max_mb_addr == INT32_MIN)
107 {
108 i4_max_mb_addr = ps_view_ctxt->ps_sps[i].u2_max_mb_addr;
109 }
110 else if(i4_max_mb_addr != ps_view_ctxt->ps_sps[i].u2_max_mb_addr)
111 {
112 return IV_FAIL;
113 }
114
115 if(ps_view_ctxt->ps_sps[i].u2_max_mb_addr >
116 imvcd_get_num_mbs_in_level(ps_view_ctxt->ps_sps[i].u1_level_idc))
117 {
118 return IV_FAIL;
119 }
120
121 if(ps_view_ctxt->ps_sps[i].u1_mb_aff_flag)
122 {
123 return IV_FAIL;
124 }
125
126 if(!ps_view_ctxt->ps_sps[i].u1_frame_mbs_only_flag)
127 {
128 return IV_FAIL;
129 }
130 }
131
132 i++;
133 }
134
135 if(u4_cnt != u4_num_sps)
136 {
137 return IV_FAIL;
138 }
139
140 i = 0;
141 u4_cnt = 0;
142
143 while((u4_cnt < u4_num_subset_sps) && (i < MAX_NUM_SEQ_PARAMS))
144 {
145 if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_is_valid)
146 {
147 u4_cnt++;
148
149 if(i4_max_mb_addr == INT32_MIN)
150 {
151 i4_max_mb_addr = ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u2_max_mb_addr;
152 }
153 else if(i4_max_mb_addr != ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u2_max_mb_addr)
154 {
155 return IV_FAIL;
156 }
157
158 if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u2_max_mb_addr >
159 imvcd_get_num_mbs_in_level(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_level_idc))
160 {
161 return IV_FAIL;
162 }
163
164 if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_mb_aff_flag)
165 {
166 return IV_FAIL;
167 }
168
169 if(!ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_frame_mbs_only_flag)
170 {
171 return IV_FAIL;
172 }
173 }
174
175 i++;
176 }
177
178 if(u4_cnt != u4_num_subset_sps)
179 {
180 return IV_FAIL;
181 }
182
183 return IV_SUCCESS;
184 }
185
imvcd_check_pps(mvc_dec_ctxt_t * ps_mvcd_ctxt)186 static IV_API_CALL_STATUS_T imvcd_check_pps(mvc_dec_ctxt_t *ps_mvcd_ctxt)
187 {
188 WORD32 i;
189
190 dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt;
191
192 bool b_is_valid_pps_found = false;
193
194 for(i = 0; i < MAX_NUM_PIC_PARAMS; i++)
195 {
196 if(ps_view_ctxt->ps_pps[i].u1_is_valid)
197 {
198 b_is_valid_pps_found = true;
199
200 if(ps_view_ctxt->ps_pps[i].u1_frame_cropping_flag)
201 {
202 return IV_FAIL;
203 }
204
205 if(ps_view_ctxt->ps_pps[i].u1_num_slice_groups != 1)
206 {
207 return IV_FAIL;
208 }
209 }
210 }
211
212 return b_is_valid_pps_found ? IV_SUCCESS : IV_FAIL;
213 }
214
imvcd_check_num_view_slices_in_au(mvc_dec_ctxt_t * ps_mvcd_ctxt,imvcd_video_decode_ip_t * ps_ip)215 static IV_API_CALL_STATUS_T imvcd_check_num_view_slices_in_au(mvc_dec_ctxt_t *ps_mvcd_ctxt,
216 imvcd_video_decode_ip_t *ps_ip)
217 {
218 AVC_EXT_NALU_ID_T e_nalu_id;
219
220 UWORD16 u2_num_view_slices_in_au = 0;
221 UWORD8 *pu1_input_buffer = (UWORD8 *) ps_ip->s_ivd_ip.pv_stream_buffer;
222 UWORD32 u4_num_bytes_remaining = ps_ip->s_ivd_ip.u4_num_Bytes;
223
224 while(true)
225 {
226 UWORD32 u4_length_of_start_code = 0;
227 UWORD32 u4_next_is_aud = 0;
228 WORD32 i4_nalu_length = ih264d_find_start_code(pu1_input_buffer, 0, u4_num_bytes_remaining,
229 &u4_length_of_start_code, &u4_next_is_aud);
230
231 if(i4_nalu_length <= 0)
232 {
233 break;
234 }
235
236 if((0 != u4_next_is_aud) && (1 != u4_next_is_aud))
237 {
238 break;
239 }
240
241 if(u4_length_of_start_code < (NUM_OF_ZERO_BYTES_BEFORE_START_CODE + 1))
242 {
243 break;
244 }
245
246 e_nalu_id = NAL_UNIT_TYPE(pu1_input_buffer[u4_length_of_start_code]);
247 u2_num_view_slices_in_au += (SLICE_NON_IDR == e_nalu_id) || (SLICE_IDR == e_nalu_id) ||
248 (CODED_SLICE_EXTENSION == e_nalu_id);
249
250 if(((WORD64) u4_num_bytes_remaining) <=
251 ((WORD64) (((WORD64) u4_length_of_start_code) + ((WORD64) i4_nalu_length))))
252 {
253 break;
254 }
255 else
256 {
257 pu1_input_buffer += u4_length_of_start_code + i4_nalu_length;
258 u4_num_bytes_remaining -= u4_length_of_start_code + i4_nalu_length;
259 }
260
261 if(u2_num_view_slices_in_au == ps_mvcd_ctxt->u2_num_views)
262 {
263 break;
264 }
265 }
266
267 return (u2_num_view_slices_in_au != ps_mvcd_ctxt->u2_num_views) ? IV_FAIL : IV_SUCCESS;
268 }
269
imvcd_au_error_checks(mvc_dec_ctxt_t * ps_mvcd_ctxt,imvcd_video_decode_ip_t * ps_ip)270 IV_API_CALL_STATUS_T imvcd_au_error_checks(mvc_dec_ctxt_t *ps_mvcd_ctxt,
271 imvcd_video_decode_ip_t *ps_ip)
272 {
273 dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt;
274
275 if(ps_mvcd_ctxt->b_header_only_decode)
276 {
277 return IV_FAIL;
278 }
279
280 if(!ps_view_ctxt->init_done)
281 {
282 return IV_FAIL;
283 }
284
285 if(IV_FAIL == imvcd_check_invalid_numViews(ps_mvcd_ctxt))
286 {
287 return IV_FAIL;
288 }
289
290 if(IV_FAIL == imvcd_check_sps_and_subset_sps(ps_mvcd_ctxt))
291 {
292 return IV_FAIL;
293 }
294
295 if(IV_FAIL == imvcd_check_pps(ps_mvcd_ctxt))
296 {
297 return IV_FAIL;
298 }
299
300 if(!ps_mvcd_ctxt->b_flush_enabled)
301 {
302 if(IV_FAIL == imvcd_check_num_view_slices_in_au(ps_mvcd_ctxt, ps_ip))
303 {
304 return IV_FAIL;
305 }
306 }
307
308 return IV_SUCCESS;
309 }
310
imvcd_view_error_checks(mvc_dec_ctxt_t * ps_mvcd_ctxt)311 IV_API_CALL_STATUS_T imvcd_view_error_checks(mvc_dec_ctxt_t *ps_mvcd_ctxt)
312 {
313 WORD32 i;
314
315 nalu_mvc_ext_t *ps_nalu_mvc_ext = imvcd_get_cur_nalu_mvc_ext(ps_mvcd_ctxt);
316 dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt;
317 dec_pic_params_t *ps_pps = ps_view_ctxt->ps_cur_pps;
318
319 bool b_is_idr_slice = imvcd_is_idr_au(ps_mvcd_ctxt);
320
321 if(b_is_idr_slice && (ps_view_ctxt->ps_cur_slice->u1_slice_type != ISLICE))
322 {
323 return IV_FAIL;
324 }
325
326 if(ps_view_ctxt->u1_first_slice_in_stream && !b_is_idr_slice)
327 {
328 return IV_FAIL;
329 }
330
331 /* In accordance with section 8.2.1 from spec. It is reproduced below - */
332 /* The bitstream shall not contain data that result in Min( TopFieldOrderCnt,
333 BottomFieldOrderCnt ) not equal to 0 for a coded IDR frame, TopFieldOrderCnt not equal to
334 0 for a coded IDR top field, or BottomFieldOrderCnt not equal to 0 for a coded IDR bottom
335 field. Thus, at least one of TopFieldOrderCnt and BottomFieldOrderCnt shall be equal to 0
336 for the fields of a coded IDR frame. */
337 if(b_is_idr_slice)
338 {
339 if(ps_view_ctxt->ps_cur_slice->u1_field_pic_flag)
340 {
341 if(ps_view_ctxt->ps_cur_slice->u1_bottom_field_flag &&
342 (ps_pps->i4_bottom_field_order_cnt != 0))
343 {
344 return IV_FAIL;
345 }
346 else if(!ps_view_ctxt->ps_cur_slice->u1_bottom_field_flag &&
347 (ps_pps->i4_top_field_order_cnt != 0))
348 {
349 return IV_FAIL;
350 }
351 }
352 else if(MIN(ps_pps->i4_top_field_order_cnt, ps_pps->i4_bottom_field_order_cnt) != 0)
353 {
354 return IV_FAIL;
355 }
356 }
357
358 if(ps_nalu_mvc_ext->u2_view_id != 0)
359 {
360 subset_sps_t *ps_subset_sps =
361 ps_mvcd_ctxt->aps_pps_id_to_subset_sps_map[ps_pps->u1_pic_parameter_set_id];
362
363 if((NULL == ps_subset_sps) || !ps_subset_sps->s_sps_data.u1_is_valid)
364 {
365 return IV_FAIL;
366 }
367
368 if(0 == ps_mvcd_ctxt->u1_num_subset_sps)
369 {
370 return IV_FAIL;
371 }
372
373 if(ps_nalu_mvc_ext->u2_view_id >= ps_subset_sps->s_sps_mvc_ext.u2_num_views)
374 {
375 return IV_FAIL;
376 }
377 }
378 else
379 {
380 if(ps_mvcd_ctxt->u2_num_views_decoded > 0)
381 {
382 return IV_FAIL;
383 }
384 }
385
386 if(!ps_view_ctxt->u4_first_slice_in_pic || (ps_view_ctxt->u2_cur_slice_num > 0))
387 {
388 return IV_FAIL;
389 }
390
391 if(ps_view_ctxt->u4_first_slice_in_pic &&
392 (ps_view_ctxt->ps_cur_slice->u2_first_mb_in_slice != 0))
393 {
394 return IV_FAIL;
395 }
396
397 if(ps_view_ctxt->ps_cur_slice->u1_mmco_equalto5)
398 {
399 return IV_FAIL;
400 }
401
402 for(i = 0; i < ps_mvcd_ctxt->u2_num_views_decoded; i++)
403 {
404 if(ps_mvcd_ctxt->as_slices[i].i4_poc != ps_view_ctxt->ps_cur_slice->i4_poc)
405 {
406 return IV_FAIL;
407 }
408
409 if(ps_mvcd_ctxt->as_slices[i].u2_frame_num != ps_view_ctxt->ps_cur_slice->u2_frame_num)
410 {
411 return IV_FAIL;
412 }
413 }
414
415 if(SKIP_NONE != ps_view_ctxt->u4_skip_frm_mask)
416 {
417 return IV_FAIL;
418 }
419
420 return IV_SUCCESS;
421 }
422