xref: /aosp_15_r20/external/libavc/decoder/mvc/imvcd_error_handler.c (revision 495ae853bb871d1e5a258cb02c2cc13cde8ddb9a)
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