Coverage Report

Created: 2026-01-17 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libavc/decoder/mvc/imvcd_error_handler.c
Line
Count
Source
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
41
static IV_API_CALL_STATUS_T imvcd_check_invalid_numViews(mvc_dec_ctxt_t *ps_mvcd_ctxt)
42
90.2k
{
43
90.2k
    WORD32 i;
44
45
90.2k
    UWORD8 u1_num_valid_subset_sps_found = 0;
46
90.2k
    UWORD16 u2_max_views = 1;
47
48
90.2k
    if((ps_mvcd_ctxt->u1_num_subset_sps == 0) && (ps_mvcd_ctxt->u2_num_views_decoded > 0))
49
0
    {
50
0
        return IV_FAIL;
51
0
    }
52
53
2.97M
    for(i = 0; i < MAX_NUM_SEQ_PARAMS; i++)
54
2.88M
    {
55
2.88M
        if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_is_valid)
56
2.99k
        {
57
2.99k
            if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_mvc_ext.u2_num_views > MAX_NUM_VIEWS)
58
0
            {
59
0
                return IV_FAIL;
60
0
            }
61
62
2.99k
            u2_max_views =
63
2.99k
                MAX(u2_max_views, ps_mvcd_ctxt->as_subset_sps[i].s_sps_mvc_ext.u2_num_views);
64
2.99k
            u1_num_valid_subset_sps_found++;
65
2.99k
        }
66
2.88M
    }
67
68
90.2k
    if(u1_num_valid_subset_sps_found > ps_mvcd_ctxt->u1_num_subset_sps)
69
0
    {
70
0
        return IV_FAIL;
71
0
    }
72
73
90.2k
    if(ps_mvcd_ctxt->u2_num_views > u2_max_views)
74
1
    {
75
1
        return IV_FAIL;
76
1
    }
77
78
90.2k
    if(ps_mvcd_ctxt->u2_num_views_decoded >= u2_max_views)
79
0
    {
80
0
        return IV_FAIL;
81
0
    }
82
83
90.2k
    return IV_SUCCESS;
84
90.2k
}
85
86
static IV_API_CALL_STATUS_T imvcd_check_sps_and_subset_sps(mvc_dec_ctxt_t *ps_mvcd_ctxt)
87
90.2k
{
88
90.2k
    UWORD32 i;
89
90.2k
    UWORD32 u4_cnt;
90
91
90.2k
    dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt;
92
93
90.2k
    UWORD32 u4_num_sps = ps_mvcd_ctxt->u1_num_sps;
94
90.2k
    UWORD32 u4_num_subset_sps = ps_mvcd_ctxt->u1_num_subset_sps;
95
90.2k
    WORD32 i4_max_mb_addr = INT32_MIN;
96
97
90.2k
    i = 0;
98
90.2k
    u4_cnt = 0;
99
100
284k
    while((u4_cnt < u4_num_sps) && (i < MAX_NUM_SEQ_PARAMS))
101
193k
    {
102
193k
        if(ps_view_ctxt->ps_sps[i].u1_is_valid)
103
97.2k
        {
104
97.2k
            u4_cnt++;
105
106
97.2k
            if(i4_max_mb_addr == INT32_MIN)
107
90.2k
            {
108
90.2k
                i4_max_mb_addr = ps_view_ctxt->ps_sps[i].u4_max_mb_addr;
109
90.2k
            }
110
6.92k
            else if(i4_max_mb_addr != ps_view_ctxt->ps_sps[i].u4_max_mb_addr)
111
0
            {
112
0
                return IV_FAIL;
113
0
            }
114
115
97.2k
            if(ps_view_ctxt->ps_sps[i].u4_max_mb_addr >
116
97.2k
               imvcd_get_num_mbs_in_level(ps_view_ctxt->ps_sps[i].u1_level_idc))
117
3
            {
118
3
                return IV_FAIL;
119
3
            }
120
121
97.2k
            if(ps_view_ctxt->ps_sps[i].u1_mb_aff_flag)
122
4
            {
123
4
                return IV_FAIL;
124
4
            }
125
126
97.2k
            if(!ps_view_ctxt->ps_sps[i].u1_frame_mbs_only_flag)
127
1
            {
128
1
                return IV_FAIL;
129
1
            }
130
97.2k
        }
131
132
193k
        i++;
133
193k
    }
134
135
90.2k
    if(u4_cnt != u4_num_sps)
136
0
    {
137
0
        return IV_FAIL;
138
0
    }
139
140
90.2k
    i = 0;
141
90.2k
    u4_cnt = 0;
142
143
99.0k
    while((u4_cnt < u4_num_subset_sps) && (i < MAX_NUM_SEQ_PARAMS))
144
8.77k
    {
145
8.77k
        if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_is_valid)
146
2.99k
        {
147
2.99k
            u4_cnt++;
148
149
2.99k
            if(i4_max_mb_addr == INT32_MIN)
150
0
            {
151
0
                i4_max_mb_addr = ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u4_max_mb_addr;
152
0
            }
153
2.99k
            else if(i4_max_mb_addr != ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u4_max_mb_addr)
154
0
            {
155
0
                return IV_FAIL;
156
0
            }
157
158
2.99k
            if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u4_max_mb_addr >
159
2.99k
               imvcd_get_num_mbs_in_level(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_level_idc))
160
0
            {
161
0
                return IV_FAIL;
162
0
            }
163
164
2.99k
            if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_mb_aff_flag)
165
0
            {
166
0
                return IV_FAIL;
167
0
            }
168
169
2.99k
            if(!ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_frame_mbs_only_flag)
170
0
            {
171
0
                return IV_FAIL;
172
0
            }
173
2.99k
        }
174
175
8.77k
        i++;
176
8.77k
    }
177
178
90.2k
    if(u4_cnt != u4_num_subset_sps)
179
0
    {
180
0
        return IV_FAIL;
181
0
    }
182
183
90.2k
    return IV_SUCCESS;
184
90.2k
}
185
186
static IV_API_CALL_STATUS_T imvcd_check_pps(mvc_dec_ctxt_t *ps_mvcd_ctxt)
187
90.2k
{
188
90.2k
    WORD32 i;
189
190
90.2k
    dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt;
191
192
90.2k
    bool b_is_valid_pps_found = false;
193
194
23.2M
    for(i = 0; i < MAX_NUM_PIC_PARAMS; i++)
195
23.1M
    {
196
23.1M
        if(ps_view_ctxt->ps_pps[i].u1_is_valid)
197
94.9k
        {
198
94.9k
            b_is_valid_pps_found = true;
199
200
94.9k
            if(ps_view_ctxt->ps_pps[i].u1_frame_cropping_flag)
201
0
            {
202
0
                return IV_FAIL;
203
0
            }
204
205
94.9k
            if(ps_view_ctxt->ps_pps[i].u1_num_slice_groups != 1)
206
0
            {
207
0
                return IV_FAIL;
208
0
            }
209
94.9k
        }
210
23.1M
    }
211
212
90.2k
    return b_is_valid_pps_found ? IV_SUCCESS : IV_FAIL;
213
90.2k
}
214
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
90.2k
{
218
90.2k
    AVC_EXT_NALU_ID_T e_nalu_id;
219
220
90.2k
    UWORD16 u2_num_view_slices_in_au = 0;
221
90.2k
    UWORD8 *pu1_input_buffer = (UWORD8 *) ps_ip->s_ivd_ip.pv_stream_buffer;
222
90.2k
    UWORD32 u4_num_bytes_remaining = ps_ip->s_ivd_ip.u4_num_Bytes;
223
224
90.2k
    while(true)
225
123k
    {
226
123k
        UWORD32 u4_length_of_start_code = 0;
227
123k
        UWORD32 u4_next_is_aud = 0;
228
123k
        WORD32 i4_nalu_length = ih264d_find_start_code(pu1_input_buffer, 0, u4_num_bytes_remaining,
229
123k
                                                       &u4_length_of_start_code, &u4_next_is_aud);
230
231
123k
        if(i4_nalu_length <= 0)
232
410
        {
233
410
            break;
234
410
        }
235
236
123k
        if((0 != u4_next_is_aud) && (1 != u4_next_is_aud))
237
0
        {
238
0
            break;
239
0
        }
240
241
123k
        if(u4_length_of_start_code < (NUM_OF_ZERO_BYTES_BEFORE_START_CODE + 1))
242
0
        {
243
0
            break;
244
0
        }
245
246
123k
        e_nalu_id = NAL_UNIT_TYPE(pu1_input_buffer[u4_length_of_start_code]);
247
123k
        u2_num_view_slices_in_au += (SLICE_NON_IDR == e_nalu_id) || (SLICE_IDR == e_nalu_id) ||
248
31.7k
                                    (CODED_SLICE_EXTENSION == e_nalu_id);
249
250
123k
        if(((WORD64) u4_num_bytes_remaining) <=
251
123k
           ((WORD64) (((WORD64) u4_length_of_start_code) + ((WORD64) i4_nalu_length))))
252
2.60k
        {
253
2.60k
            break;
254
2.60k
        }
255
120k
        else
256
120k
        {
257
120k
            pu1_input_buffer += u4_length_of_start_code + i4_nalu_length;
258
120k
            u4_num_bytes_remaining -= u4_length_of_start_code + i4_nalu_length;
259
120k
        }
260
261
120k
        if(u2_num_view_slices_in_au == ps_mvcd_ctxt->u2_num_views)
262
87.2k
        {
263
87.2k
            break;
264
87.2k
        }
265
120k
    }
266
267
90.2k
    return (u2_num_view_slices_in_au != ps_mvcd_ctxt->u2_num_views) ? IV_FAIL : IV_SUCCESS;
268
90.2k
}
269
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
90.2k
{
273
90.2k
    dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt;
274
275
90.2k
    if(ps_mvcd_ctxt->b_header_only_decode)
276
0
    {
277
0
        return IV_FAIL;
278
0
    }
279
280
90.2k
    if(!ps_view_ctxt->init_done)
281
0
    {
282
0
        return IV_FAIL;
283
0
    }
284
285
90.2k
    if(IV_FAIL == imvcd_check_invalid_numViews(ps_mvcd_ctxt))
286
1
    {
287
1
        return IV_FAIL;
288
1
    }
289
290
90.2k
    if(IV_FAIL == imvcd_check_sps_and_subset_sps(ps_mvcd_ctxt))
291
8
    {
292
8
        return IV_FAIL;
293
8
    }
294
295
90.2k
    if(IV_FAIL == imvcd_check_pps(ps_mvcd_ctxt))
296
11
    {
297
11
        return IV_FAIL;
298
11
    }
299
300
90.2k
    if(!ps_mvcd_ctxt->b_flush_enabled)
301
90.2k
    {
302
90.2k
        if(IV_FAIL == imvcd_check_num_view_slices_in_au(ps_mvcd_ctxt, ps_ip))
303
485
        {
304
485
            return IV_FAIL;
305
485
        }
306
90.2k
    }
307
308
89.7k
    return IV_SUCCESS;
309
90.2k
}
310
311
IV_API_CALL_STATUS_T imvcd_view_error_checks(mvc_dec_ctxt_t *ps_mvcd_ctxt)
312
90.8k
{
313
90.8k
    WORD32 i;
314
315
90.8k
    nalu_mvc_ext_t *ps_nalu_mvc_ext = imvcd_get_cur_nalu_mvc_ext(ps_mvcd_ctxt);
316
90.8k
    dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt;
317
90.8k
    dec_pic_params_t *ps_pps = ps_view_ctxt->ps_cur_pps;
318
319
90.8k
    bool b_is_idr_slice = imvcd_is_idr_au(ps_mvcd_ctxt);
320
321
90.8k
    if(b_is_idr_slice && (ps_view_ctxt->ps_cur_slice->u1_slice_type != ISLICE))
322
1
    {
323
1
        return IV_FAIL;
324
1
    }
325
326
90.8k
    if(ps_view_ctxt->u1_first_slice_in_stream && !b_is_idr_slice)
327
11
    {
328
11
        return IV_FAIL;
329
11
    }
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
90.8k
    if(b_is_idr_slice)
338
25.9k
    {
339
25.9k
        if(ps_view_ctxt->ps_cur_slice->u1_field_pic_flag)
340
0
        {
341
0
            if(ps_view_ctxt->ps_cur_slice->u1_bottom_field_flag &&
342
0
               (ps_pps->i4_bottom_field_order_cnt != 0))
343
0
            {
344
0
                return IV_FAIL;
345
0
            }
346
0
            else if(!ps_view_ctxt->ps_cur_slice->u1_bottom_field_flag &&
347
0
                    (ps_pps->i4_top_field_order_cnt != 0))
348
0
            {
349
0
                return IV_FAIL;
350
0
            }
351
0
        }
352
25.9k
        else if(MIN(ps_pps->i4_top_field_order_cnt, ps_pps->i4_bottom_field_order_cnt) != 0)
353
8
        {
354
8
            return IV_FAIL;
355
8
        }
356
25.9k
    }
357
358
90.8k
    if(ps_nalu_mvc_ext->u2_view_id != 0)
359
1.80k
    {
360
1.80k
        subset_sps_t *ps_subset_sps =
361
1.80k
            ps_mvcd_ctxt->aps_pps_id_to_subset_sps_map[ps_pps->u1_pic_parameter_set_id];
362
363
1.80k
        if((NULL == ps_subset_sps) || !ps_subset_sps->s_sps_data.u1_is_valid)
364
0
        {
365
0
            return IV_FAIL;
366
0
        }
367
368
1.80k
        if(0 == ps_mvcd_ctxt->u1_num_subset_sps)
369
0
        {
370
0
            return IV_FAIL;
371
0
        }
372
373
1.80k
        if(ps_nalu_mvc_ext->u2_view_id >= ps_subset_sps->s_sps_mvc_ext.u2_num_views)
374
0
        {
375
0
            return IV_FAIL;
376
0
        }
377
1.80k
    }
378
89.0k
    else
379
89.0k
    {
380
89.0k
        if(ps_mvcd_ctxt->u2_num_views_decoded > 0)
381
7
        {
382
7
            return IV_FAIL;
383
7
        }
384
89.0k
    }
385
386
90.8k
    if(!ps_view_ctxt->u4_first_slice_in_pic || (ps_view_ctxt->u2_cur_slice_num > 0))
387
0
    {
388
0
        return IV_FAIL;
389
0
    }
390
391
90.8k
    if(ps_view_ctxt->u4_first_slice_in_pic &&
392
90.8k
       (ps_view_ctxt->ps_cur_slice->u2_first_mb_in_slice != 0))
393
2
    {
394
2
        return IV_FAIL;
395
2
    }
396
397
90.8k
    if(ps_view_ctxt->ps_cur_slice->u1_mmco_equalto5)
398
0
    {
399
0
        return IV_FAIL;
400
0
    }
401
402
92.6k
    for(i = 0; i < ps_mvcd_ctxt->u2_num_views_decoded; i++)
403
1.82k
    {
404
1.82k
        if(ps_mvcd_ctxt->as_slices[i].i4_poc != ps_view_ctxt->ps_cur_slice->i4_poc)
405
1
        {
406
1
            return IV_FAIL;
407
1
        }
408
409
1.82k
        if(ps_mvcd_ctxt->as_slices[i].u2_frame_num != ps_view_ctxt->ps_cur_slice->u2_frame_num)
410
1
        {
411
1
            return IV_FAIL;
412
1
        }
413
1.82k
    }
414
415
90.8k
    if(SKIP_NONE != ps_view_ctxt->u4_skip_frm_mask)
416
0
    {
417
0
        return IV_FAIL;
418
0
    }
419
420
90.8k
    return IV_SUCCESS;
421
90.8k
}