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*/
96WORD32 ihevcd_nal_search_start_code(UWORD8 *pu1_buf, WORD32 bytes_remaining)
97{
98    WORD32 ofst;
99
100    WORD32 zero_byte_cnt;
101    WORD32 start_code_found;
102
103    ofst = -1;
104
105    zero_byte_cnt = 0;
106    start_code_found = 0;
107    while(ofst < (bytes_remaining - 1))
108    {
109        ofst++;
110        if(pu1_buf[ofst] != 0)
111        {
112            zero_byte_cnt = 0;
113            continue;
114        }
115
116        zero_byte_cnt++;
117        if((pu1_buf[ofst + 1] == START_CODE_PREFIX_BYTE) &&
118           (zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE))
119        {
120            /* Found the start code */
121            ofst++;
122            start_code_found = 1;
123            break;
124        }
125    }
126    if(0 == start_code_found)
127    {
128        if((START_CODE_PREFIX_BYTE == pu1_buf[ofst]) &&
129           (zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE))
130        {
131            /* Found a start code at the end*/
132            ofst++;
133        }
134    }
135    /* Since ofst started at -1, increment it by 1 */
136    ofst++;
137
138    return ofst;
139}
140
141/**
142*******************************************************************************
143*
144* @brief
145*  Remove emulation prevention byte present in the bitstream till next start
146* code is found. Emulation prevention byte  removed data is stored in a
147* different buffer
148*
149* @par Description:
150*  Assumption is first start code is already found and  pu1_buf is pointing
151* to a byte after the start code  Search for Next NAL's start code  Return
152* if start code is found  Remove any emulation prevention byte present  Copy
153* data to new buffer  If no start code is found, then treat complete buffer
154* as  one nal.
155*
156* @param[in] pu1_src
157*  Pointer to bitstream (excludes the initial the start code)
158*
159* @param[in] pu1_dst
160*  Pointer to destination buffer
161*
162* @param[in] bytes_remaining
163*  Number of bytes remaining
164*
165* @param[out] pi4_nal_len
166*  NAL length (length of bitstream parsed)
167*
168* @param[out] pi4_dst_len
169*  Destination bitstream size (length of bitstream parsed with emulation bytes
170* removed)
171*
172* @returns Error code from IHEVCD_ERROR_T
173*
174* @remarks
175*  Incomplete start code at the end of input bitstream is  not handled. This
176* has to be taken care outside this func
177*
178*******************************************************************************
179*/
180IHEVCD_ERROR_T ihevcd_nal_remv_emuln_bytes(UWORD8 *pu1_src,
181                                           UWORD8 *pu1_dst,
182                                           WORD32 bytes_remaining,
183                                           WORD32 *pi4_nal_len,
184                                           WORD32 *pi4_dst_len)
185{
186    WORD32 src_cnt;
187    WORD32 dst_cnt;
188    WORD32 zero_byte_cnt;
189    WORD32 start_code_found;
190    UWORD8 u1_src;
191    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
192
193    src_cnt = 0;
194    dst_cnt = 0;
195    zero_byte_cnt = 0;
196    start_code_found = 0;
197    while(src_cnt < (bytes_remaining - 1))
198    {
199        u1_src = pu1_src[src_cnt++];
200
201        pu1_dst[dst_cnt++] = u1_src;
202        if(u1_src != 0)
203        {
204            zero_byte_cnt = 0;
205            continue;
206        }
207
208        zero_byte_cnt++;
209        if(zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE)
210        {
211            u1_src = pu1_src[src_cnt];
212            if(START_CODE_PREFIX_BYTE == u1_src)
213            {
214                /* Found the start code */
215                src_cnt -= zero_byte_cnt;
216                dst_cnt -= zero_byte_cnt;
217                start_code_found = 1;
218                break;
219            }
220            else if(EMULATION_PREVENT_BYTE == u1_src)
221            {
222                /* Found the emulation prevention byte */
223                src_cnt++;
224                zero_byte_cnt = 0;
225
226                /* Decrement dst_cnt so that the next byte overwrites
227                 * the emulation prevention byte already copied to dst above
228                 */
229            }
230        }
231
232    }
233
234    if(0 == start_code_found)
235    {
236        u1_src = pu1_src[src_cnt++];
237        if(zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE)
238        {
239
240            if(START_CODE_PREFIX_BYTE == u1_src)
241            {
242                /* Found a start code at the end*/
243                src_cnt -= zero_byte_cnt;
244            }
245            else if(EMULATION_PREVENT_BYTE == u1_src)
246            {
247                /* Found the emulation prevention byte at the end*/
248                src_cnt++;
249                /* Decrement dst_cnt so that the next byte overwrites
250                 * the emulation prevention byte already copied to dst above
251                 */
252                dst_cnt--;
253            }
254        }
255        else
256        {
257            pu1_dst[dst_cnt++] = u1_src;
258        }
259
260
261    }
262    *pi4_nal_len = src_cnt;
263    *pi4_dst_len = dst_cnt;
264    return ret;
265}
266/**
267*******************************************************************************
268*
269* @brief
270*  Decode given NAL unit's header
271*
272* @par Description:
273*  Call NAL unit's header decode  Section: 7.3.1.2
274*
275* @param[in] ps_bitstrm
276*  Pointer to bitstream context
277*
278* @param[out] ps_nal
279*  Pointer to NAL header
280*
281* @returns Error code from IHEVCD_ERROR_T
282*
283* @remarks
284*
285*
286*******************************************************************************
287*/
288IHEVCD_ERROR_T ihevcd_nal_unit_header(bitstrm_t *ps_bitstrm, nal_header_t *ps_nal)
289{
290    WORD32 unused;
291    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
292    UNUSED(unused);
293    /* Syntax : forbidden_zero_bit */
294    unused = ihevcd_bits_get(ps_bitstrm, 1);
295
296    /* Syntax : nal_unit_type */
297    ps_nal->i1_nal_unit_type = ihevcd_bits_get(ps_bitstrm, 6);
298
299    /* Syntax : nuh_reserved_zero_6bits */
300    unused = ihevcd_bits_get(ps_bitstrm, 6);
301
302    /* Syntax : nuh_temporal_id_plus1 */
303    ps_nal->i1_nuh_temporal_id = ihevcd_bits_get(ps_bitstrm, 3) - 1;
304
305    return ret;
306
307}
308
309/**
310*******************************************************************************
311*
312* @brief
313*  Decode given NAL
314*
315* @par Description:
316*  Based on the NAL type call appropriate decode function  Section: 7.3.1.1
317*
318*
319* @param[in,out] ps_codec
320*  Pointer to codec context (Functions called within will modify contents of
321* ps_codec)
322*
323* @returns Error code from IHEVCD_ERROR_T
324*
325* @remarks
326*
327*
328*******************************************************************************
329*/
330IHEVCD_ERROR_T ihevcd_nal_unit(codec_t *ps_codec)
331{
332    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
333
334    /* NAL Header */
335    nal_header_t s_nal;
336
337    ret = ihevcd_nal_unit_header(&ps_codec->s_parse.s_bitstrm, &s_nal);
338    RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
339
340    if(ps_codec->i4_slice_error)
341        s_nal.i1_nal_unit_type = ps_codec->s_parse.ps_slice_hdr->i1_nal_unit_type;
342
343    /* Setting RASL Output flag */
344    switch(s_nal.i1_nal_unit_type)
345    {
346        case NAL_BLA_W_LP    :
347        case NAL_BLA_W_DLP   :
348        case NAL_BLA_N_LP    :
349            ps_codec->i4_rasl_output_flag = 0;
350            break;
351
352        //TODO: After IDR, there is no case of open GOP
353        //To be fixed appropriately by ignoring RASL only if the
354        // required references are not found
355        case NAL_IDR_W_LP    :
356        case NAL_IDR_N_LP    :
357            ps_codec->i4_rasl_output_flag = 1;
358            break;
359
360        case NAL_CRA         :
361            ps_codec->i4_rasl_output_flag = (0 == ps_codec->u4_pic_cnt) ? 0 : 1;
362            break;
363
364        default:
365            break;
366    }
367
368    switch(s_nal.i1_nal_unit_type)
369    {
370        case NAL_BLA_W_LP    :
371        case NAL_BLA_W_DLP   :
372        case NAL_BLA_N_LP    :
373        case NAL_IDR_W_LP    :
374        case NAL_IDR_N_LP    :
375        case NAL_CRA         :
376        case NAL_TRAIL_N     :
377        case NAL_TRAIL_R     :
378        case NAL_TSA_N       :
379        case NAL_TSA_R       :
380        case NAL_STSA_N      :
381        case NAL_STSA_R      :
382        case NAL_RADL_N      :
383        case NAL_RADL_R      :
384        case NAL_RASL_N      :
385        case NAL_RASL_R      :
386            if(ps_codec->i4_header_mode)
387                return IHEVCD_SLICE_IN_HEADER_MODE;
388
389            if((0 == ps_codec->i4_sps_done) ||
390                            (0 == ps_codec->i4_pps_done))
391            {
392                return IHEVCD_INVALID_HEADER;
393            }
394
395            ps_codec->i4_header_in_slice_mode = 0;
396
397            ret = ihevcd_parse_slice_header(ps_codec, &s_nal);
398            DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
399            if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
400            {
401                if((s_nal.i1_nal_unit_type != NAL_RASL_N && s_nal.i1_nal_unit_type != NAL_RASL_R) ||
402                                ps_codec->i4_rasl_output_flag ||
403                                ps_codec->i4_slice_error)
404                    ret = ihevcd_parse_slice_data(ps_codec);
405            }
406            break;
407
408        case NAL_VPS        :
409            // ret = ihevcd_parse_vps(ps_codec);
410            DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
411            break;
412
413        case NAL_SPS        :
414            if(0 == ps_codec->i4_header_mode)
415            {
416                ps_codec->i4_header_in_slice_mode = 1;
417                if(ps_codec->i4_sps_done &&
418                                ps_codec->i4_pic_present)
419                    break;
420            }
421
422            ret = ihevcd_parse_sps(ps_codec);
423            if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
424            {
425                sps_t *ps_sps = ps_codec->ps_sps_base + MAX_SPS_CNT - 1;
426                ihevcd_copy_sps(ps_codec, ps_sps->i1_sps_id, MAX_SPS_CNT - 1);
427            }
428
429            DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
430            break;
431
432        case NAL_PPS        :
433            if(0 == ps_codec->i4_header_mode)
434            {
435                ps_codec->i4_header_in_slice_mode = 1;
436                if(ps_codec->i4_pps_done &&
437                                ps_codec->i4_pic_present)
438                    break;
439            }
440
441            ret = ihevcd_parse_pps(ps_codec);
442            if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
443            {
444                pps_t *ps_pps = ps_codec->ps_pps_base + MAX_PPS_CNT - 1;
445                ihevcd_copy_pps(ps_codec, ps_pps->i1_pps_id, MAX_PPS_CNT - 1);
446            }
447
448            DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
449            break;
450
451        default:
452            DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
453            break;
454    }
455
456    return ret;
457}
458
459