Coverage Report

Created: 2026-04-01 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libhevc/decoder/ihevcd_nal.c
Line
Count
Source
1
/******************************************************************************
2
*
3
* Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
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
/**
19
*******************************************************************************
20
* @file
21
*  ihevcd_nal.c
22
*
23
* @brief
24
*  Contains functions for NAL level such as search start code etc
25
*
26
* @author
27
*  Harish
28
*
29
* @par List of Functions:
30
*
31
* @remarks
32
*  None
33
*
34
*******************************************************************************
35
*/
36
/*****************************************************************************/
37
/* File Includes                                                             */
38
/*****************************************************************************/
39
#include <stdio.h>
40
#include <stddef.h>
41
#include <stdlib.h>
42
#include <string.h>
43
#include <assert.h>
44
45
#include "ihevc_typedefs.h"
46
#include "iv.h"
47
#include "ivd.h"
48
#include "ihevcd_cxa.h"
49
50
#include "ihevc_defs.h"
51
#include "ihevc_debug.h"
52
#include "ihevc_structs.h"
53
#include "ihevc_macros.h"
54
#include "ihevc_platform_macros.h"
55
#include "ihevc_cabac_tables.h"
56
57
58
#include "ihevcd_defs.h"
59
#include "ihevcd_function_selector.h"
60
#include "ihevcd_structs.h"
61
#include "ihevcd_error.h"
62
#include "ihevcd_nal.h"
63
#include "ihevcd_bitstream.h"
64
#include "ihevcd_parse_headers.h"
65
#include "ihevcd_parse_slice.h"
66
#include "ihevcd_debug.h"
67
/*****************************************************************************/
68
/* Function Prototypes                                                       */
69
/*****************************************************************************/
70
71
/**
72
*******************************************************************************
73
*
74
* @brief
75
*  Search start code from the given buffer pointer
76
*
77
* @par Description:
78
*  Search for start code  Return the offset of start code if start code is
79
* found  If no start code is found till end of given bitstream  then treat
80
* it as invalid NAL and return end of buffer as  offset
81
*
82
* @param[in] pu1_buf
83
*  Pointer to bitstream
84
*
85
* @param[in] bytes_remaining
86
*  Number of bytes remaining in the buffer
87
*
88
* @returns  Offset to the first byte in NAL after start code
89
*
90
* @remarks
91
*  Incomplete start code at the end of input bitstream is  not handled. This
92
* has to be taken care outside this func
93
*
94
*******************************************************************************
95
*/
96
WORD32 ihevcd_nal_search_start_code(UWORD8 *pu1_buf, WORD32 bytes_remaining)
97
435k
{
98
435k
    WORD32 ofst;
99
100
435k
    WORD32 zero_byte_cnt;
101
435k
    WORD32 start_code_found;
102
103
435k
    ofst = -1;
104
105
435k
    zero_byte_cnt = 0;
106
435k
    start_code_found = 0;
107
137M
    while(ofst < (bytes_remaining - 1))
108
137M
    {
109
137M
        ofst++;
110
137M
        if(pu1_buf[ofst] != 0)
111
77.0M
        {
112
77.0M
            zero_byte_cnt = 0;
113
77.0M
            continue;
114
77.0M
        }
115
116
59.9M
        zero_byte_cnt++;
117
59.9M
        if((ofst < (bytes_remaining - 1)) &&
118
59.9M
           (pu1_buf[ofst + 1] == START_CODE_PREFIX_BYTE) &&
119
454k
           (zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE))
120
433k
        {
121
            /* Found the start code */
122
433k
            ofst++;
123
433k
            start_code_found = 1;
124
433k
            break;
125
433k
        }
126
59.9M
    }
127
435k
    if((0 == start_code_found) && (ofst < bytes_remaining))
128
1.52k
    {
129
1.52k
        if((START_CODE_PREFIX_BYTE == pu1_buf[ofst]) &&
130
26
           (zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE))
131
0
        {
132
            /* Found a start code at the end*/
133
0
            ofst++;
134
0
        }
135
1.52k
    }
136
    /* Since ofst started at -1, increment it by 1 */
137
435k
    ofst++;
138
139
435k
    return ofst;
140
435k
}
141
142
/**
143
*******************************************************************************
144
*
145
* @brief
146
*  Remove emulation prevention byte present in the bitstream till next start
147
* code is found. Emulation prevention byte  removed data is stored in a
148
* different buffer
149
*
150
* @par Description:
151
*  Assumption is first start code is already found and  pu1_buf is pointing
152
* to a byte after the start code  Search for Next NAL's start code  Return
153
* if start code is found  Remove any emulation prevention byte present  Copy
154
* data to new buffer  If no start code is found, then treat complete buffer
155
* as  one nal.
156
*
157
* @param[in] pu1_src
158
*  Pointer to bitstream (excludes the initial the start code)
159
*
160
* @param[in] pu1_dst
161
*  Pointer to destination buffer
162
*
163
* @param[in] bytes_remaining
164
*  Number of bytes remaining
165
*
166
* @param[out] pi4_nal_len
167
*  NAL length (length of bitstream parsed)
168
*
169
* @param[out] pi4_dst_len
170
*  Destination bitstream size (length of bitstream parsed with emulation bytes
171
* removed)
172
*
173
* @returns Error code from IHEVCD_ERROR_T
174
*
175
* @remarks
176
*  Incomplete start code at the end of input bitstream is  not handled. This
177
* has to be taken care outside this func
178
*
179
*******************************************************************************
180
*/
181
IHEVCD_ERROR_T ihevcd_nal_remv_emuln_bytes(UWORD8 *pu1_src,
182
                                           UWORD8 *pu1_dst,
183
                                           WORD32 bytes_remaining,
184
                                           WORD32 *pi4_nal_len,
185
                                           WORD32 *pi4_dst_len)
186
433k
{
187
433k
    WORD32 src_cnt;
188
433k
    WORD32 dst_cnt;
189
433k
    WORD32 zero_byte_cnt;
190
433k
    WORD32 start_code_found;
191
433k
    UWORD8 u1_src;
192
433k
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
193
194
433k
    src_cnt = 0;
195
433k
    dst_cnt = 0;
196
433k
    zero_byte_cnt = 0;
197
433k
    start_code_found = 0;
198
236M
    while(src_cnt < (bytes_remaining - 1))
199
236M
    {
200
236M
        u1_src = pu1_src[src_cnt++];
201
202
236M
        pu1_dst[dst_cnt++] = u1_src;
203
236M
        if(u1_src != 0)
204
106M
        {
205
106M
            zero_byte_cnt = 0;
206
106M
            continue;
207
106M
        }
208
209
129M
        zero_byte_cnt++;
210
129M
        if(zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE)
211
128M
        {
212
128M
            u1_src = pu1_src[src_cnt];
213
128M
            if(START_CODE_PREFIX_BYTE == u1_src)
214
414k
            {
215
                /* Found the start code */
216
414k
                src_cnt -= zero_byte_cnt;
217
414k
                dst_cnt -= zero_byte_cnt;
218
414k
                start_code_found = 1;
219
414k
                break;
220
414k
            }
221
127M
            else if(EMULATION_PREVENT_BYTE == u1_src)
222
41.9k
            {
223
                /* Found the emulation prevention byte */
224
41.9k
                src_cnt++;
225
41.9k
                zero_byte_cnt = 0;
226
227
                /* Decrement dst_cnt so that the next byte overwrites
228
                 * the emulation prevention byte already copied to dst above
229
                 */
230
41.9k
            }
231
128M
        }
232
233
129M
    }
234
235
433k
    if((0 == start_code_found) && (src_cnt < bytes_remaining))
236
19.5k
    {
237
19.5k
        u1_src = pu1_src[src_cnt++];
238
19.5k
        if(zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE)
239
1.27k
        {
240
241
1.27k
            if(START_CODE_PREFIX_BYTE == u1_src)
242
0
            {
243
                /* Found a start code at the end*/
244
0
                src_cnt -= zero_byte_cnt;
245
0
            }
246
1.27k
            else if(EMULATION_PREVENT_BYTE == u1_src)
247
0
            {
248
                /* Found the emulation prevention byte at the end*/
249
0
                src_cnt++;
250
                /* Decrement dst_cnt so that the next byte overwrites
251
                 * the emulation prevention byte already copied to dst above
252
                 */
253
0
                dst_cnt--;
254
0
            }
255
1.27k
        }
256
18.2k
        else
257
18.2k
        {
258
18.2k
            pu1_dst[dst_cnt++] = u1_src;
259
18.2k
        }
260
261
262
19.5k
    }
263
433k
    *pi4_nal_len = src_cnt;
264
433k
    *pi4_dst_len = dst_cnt;
265
433k
    return ret;
266
433k
}
267
/**
268
*******************************************************************************
269
*
270
* @brief
271
*  Decode given NAL unit's header
272
*
273
* @par Description:
274
*  Call NAL unit's header decode  Section: 7.3.1.2
275
*
276
* @param[in] ps_bitstrm
277
*  Pointer to bitstream context
278
*
279
* @param[out] ps_nal
280
*  Pointer to NAL header
281
*
282
* @returns Error code from IHEVCD_ERROR_T
283
*
284
* @remarks
285
*
286
*
287
*******************************************************************************
288
*/
289
IHEVCD_ERROR_T ihevcd_nal_unit_header(bitstrm_t *ps_bitstrm, nal_header_t *ps_nal)
290
433k
{
291
433k
    WORD32 unused;
292
433k
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
293
433k
    UNUSED(unused);
294
    /* Syntax : forbidden_zero_bit */
295
433k
    unused = ihevcd_bits_get(ps_bitstrm, 1);
296
297
    /* Syntax : nal_unit_type */
298
433k
    ps_nal->i1_nal_unit_type = ihevcd_bits_get(ps_bitstrm, 6);
299
300
    /* Syntax : nuh_reserved_zero_6bits */
301
433k
    unused = ihevcd_bits_get(ps_bitstrm, 6);
302
303
    /* Syntax : nuh_temporal_id_plus1 */
304
433k
    ps_nal->i1_nuh_temporal_id = (WORD32)ihevcd_bits_get(ps_bitstrm, 3) - 1;
305
306
433k
    return ret;
307
308
433k
}
309
310
/**
311
*******************************************************************************
312
*
313
* @brief
314
*  Decode given NAL
315
*
316
* @par Description:
317
*  Based on the NAL type call appropriate decode function  Section: 7.3.1.1
318
*
319
*
320
* @param[in,out] ps_codec
321
*  Pointer to codec context (Functions called within will modify contents of
322
* ps_codec)
323
*
324
* @returns Error code from IHEVCD_ERROR_T
325
*
326
* @remarks
327
*
328
*
329
*******************************************************************************
330
*/
331
IHEVCD_ERROR_T ihevcd_nal_unit(codec_t *ps_codec)
332
433k
{
333
433k
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
334
335
    /* NAL Header */
336
433k
    nal_header_t s_nal;
337
338
433k
    ret = ihevcd_nal_unit_header(&ps_codec->s_parse.s_bitstrm, &s_nal);
339
433k
    RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
340
341
433k
    if(ps_codec->i4_slice_error)
342
7.83k
        s_nal.i1_nal_unit_type = ps_codec->s_parse.ps_slice_hdr->i1_nal_unit_type;
343
344
    /* Setting RASL Output flag */
345
433k
    switch(s_nal.i1_nal_unit_type)
346
433k
    {
347
3.27k
        case NAL_BLA_W_LP    :
348
14.7k
        case NAL_BLA_W_DLP   :
349
22.2k
        case NAL_BLA_N_LP    :
350
22.2k
            ps_codec->i4_rasl_output_flag = 0;
351
22.2k
            break;
352
353
        //TODO: After IDR, there is no case of open GOP
354
        //To be fixed appropriately by ignoring RASL only if the
355
        // required references are not found
356
29.7k
        case NAL_IDR_W_LP    :
357
66.5k
        case NAL_IDR_N_LP    :
358
66.5k
            ps_codec->i4_rasl_output_flag = 1;
359
66.5k
            break;
360
361
3.47k
        case NAL_CRA         :
362
3.47k
            ps_codec->i4_rasl_output_flag = (0 != ps_codec->i4_cra_as_first_pic) ? 0 : 1;
363
3.47k
            break;
364
365
341k
        default:
366
341k
            break;
367
433k
    }
368
369
433k
    switch(s_nal.i1_nal_unit_type)
370
433k
    {
371
3.27k
        case NAL_BLA_W_LP    :
372
14.7k
        case NAL_BLA_W_DLP   :
373
22.2k
        case NAL_BLA_N_LP    :
374
51.9k
        case NAL_IDR_W_LP    :
375
88.7k
        case NAL_IDR_N_LP    :
376
92.1k
        case NAL_CRA         :
377
188k
        case NAL_TRAIL_N     :
378
200k
        case NAL_TRAIL_R     :
379
207k
        case NAL_TSA_N       :
380
210k
        case NAL_TSA_R       :
381
229k
        case NAL_STSA_N      :
382
233k
        case NAL_STSA_R      :
383
235k
        case NAL_RADL_N      :
384
236k
        case NAL_RADL_R      :
385
241k
        case NAL_RASL_N      :
386
249k
        case NAL_RASL_R      :
387
249k
            if(ps_codec->i4_header_mode)
388
102k
                return IHEVCD_SLICE_IN_HEADER_MODE;
389
390
147k
            if((0 == ps_codec->i4_sps_done) ||
391
126k
                            (0 == ps_codec->i4_pps_done))
392
27.5k
            {
393
27.5k
                return IHEVCD_INVALID_HEADER;
394
27.5k
            }
395
396
119k
            ps_codec->i4_header_in_slice_mode = 0;
397
119k
            ps_codec->i4_cra_as_first_pic = 0;
398
399
119k
            ret = ihevcd_parse_slice_header(ps_codec, &s_nal);
400
119k
            DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
401
119k
            if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
402
58.5k
            {
403
58.5k
                if((s_nal.i1_nal_unit_type != NAL_RASL_N && s_nal.i1_nal_unit_type != NAL_RASL_R) ||
404
3.36k
                                ps_codec->i4_rasl_output_flag ||
405
2.57k
                                ps_codec->i4_slice_error)
406
56.4k
                    ret = ihevcd_parse_slice_data(ps_codec);
407
58.5k
            }
408
119k
            break;
409
410
3.63k
        case NAL_VPS        :
411
            // ret = ihevcd_parse_vps(ps_codec);
412
3.63k
            DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
413
3.63k
            break;
414
415
78.9k
        case NAL_SPS        :
416
78.9k
            if(0 == ps_codec->i4_header_mode)
417
51.2k
            {
418
51.2k
                ps_codec->i4_header_in_slice_mode = 1;
419
51.2k
                if(ps_codec->i4_sps_done &&
420
32.6k
                                ps_codec->i4_pic_present)
421
3.38k
                    break;
422
51.2k
            }
423
424
75.5k
            ret = ihevcd_parse_sps(ps_codec);
425
75.5k
            if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
426
21.0k
            {
427
21.0k
                sps_t *ps_sps = ps_codec->ps_sps_base + MAX_SPS_CNT - 1;
428
21.0k
                ihevcd_copy_sps(ps_codec, ps_sps->i1_sps_id, MAX_SPS_CNT - 1);
429
21.0k
            }
430
75.5k
            ps_codec->i4_error_code = ret;
431
432
75.5k
            DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
433
75.5k
            break;
434
435
46.0k
        case NAL_PPS        :
436
46.0k
            if(0 == ps_codec->i4_header_mode)
437
31.9k
            {
438
31.9k
                ps_codec->i4_header_in_slice_mode = 1;
439
31.9k
                if(ps_codec->i4_pps_done &&
440
19.0k
                                ps_codec->i4_pic_present)
441
1.47k
                    break;
442
31.9k
            }
443
444
44.6k
            ret = ihevcd_parse_pps(ps_codec);
445
44.6k
            if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
446
21.3k
            {
447
21.3k
                pps_t *ps_pps = ps_codec->ps_pps_base + MAX_PPS_CNT - 1;
448
21.3k
                ihevcd_copy_pps(ps_codec, ps_pps->i1_pps_id, MAX_PPS_CNT - 1);
449
21.3k
            }
450
44.6k
            ps_codec->i4_error_code = ret;
451
44.6k
            DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
452
44.6k
            break;
453
454
0
#ifndef DISABLE_SEI
455
28.0k
        case NAL_PREFIX_SEI:
456
35.1k
        case NAL_SUFFIX_SEI:
457
35.1k
            if(IVD_DECODE_HEADER == ps_codec->i4_header_mode)
458
9.75k
            {
459
9.75k
                return IHEVCD_SLICE_IN_HEADER_MODE;
460
9.75k
            }
461
462
25.3k
            ret = ihevcd_parse_sei(ps_codec, &s_nal);
463
25.3k
            break;
464
465
0
#endif
466
1.09k
        case NAL_EOS        :
467
1.09k
            ps_codec->i4_cra_as_first_pic = 1;
468
1.09k
            break;
469
470
19.0k
        default:
471
19.0k
            DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
472
19.0k
            break;
473
433k
    }
474
475
294k
    return ret;
476
433k
}
477