Home | History | Annotate | Download | only in decoder
      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 {
     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 */
    180 IHEVCD_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 */
    288 IHEVCD_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 */
    330 IHEVCD_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->i4_cra_as_first_pic) ? 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             ps_codec->i4_cra_as_first_pic = 0;
    397 
    398             ret = ihevcd_parse_slice_header(ps_codec, &s_nal);
    399             DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
    400             if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
    401             {
    402                 if((s_nal.i1_nal_unit_type != NAL_RASL_N && s_nal.i1_nal_unit_type != NAL_RASL_R) ||
    403                                 ps_codec->i4_rasl_output_flag ||
    404                                 ps_codec->i4_slice_error)
    405                     ret = ihevcd_parse_slice_data(ps_codec);
    406             }
    407             break;
    408 
    409         case NAL_VPS        :
    410             // ret = ihevcd_parse_vps(ps_codec);
    411             DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
    412             break;
    413 
    414         case NAL_SPS        :
    415             if(0 == ps_codec->i4_header_mode)
    416             {
    417                 ps_codec->i4_header_in_slice_mode = 1;
    418                 if(ps_codec->i4_sps_done &&
    419                                 ps_codec->i4_pic_present)
    420                     break;
    421             }
    422 
    423             ret = ihevcd_parse_sps(ps_codec);
    424             if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
    425             {
    426                 sps_t *ps_sps = ps_codec->ps_sps_base + MAX_SPS_CNT - 1;
    427                 ihevcd_copy_sps(ps_codec, ps_sps->i1_sps_id, MAX_SPS_CNT - 1);
    428             }
    429             ps_codec->i4_error_code = ret;
    430 
    431             DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
    432             break;
    433 
    434         case NAL_PPS        :
    435             if(0 == ps_codec->i4_header_mode)
    436             {
    437                 ps_codec->i4_header_in_slice_mode = 1;
    438                 if(ps_codec->i4_pps_done &&
    439                                 ps_codec->i4_pic_present)
    440                     break;
    441             }
    442 
    443             ret = ihevcd_parse_pps(ps_codec);
    444             if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
    445             {
    446                 pps_t *ps_pps = ps_codec->ps_pps_base + MAX_PPS_CNT - 1;
    447                 ihevcd_copy_pps(ps_codec, ps_pps->i1_pps_id, MAX_PPS_CNT - 1);
    448             }
    449             ps_codec->i4_error_code = ret;
    450             DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
    451             break;
    452 
    453         case NAL_EOS        :
    454             ps_codec->i4_cra_as_first_pic = 1;
    455             break;
    456 
    457         default:
    458             DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
    459             break;
    460     }
    461 
    462     return ret;
    463 }
    464 
    465