diff options
author | Harish Mahendrakar <harish.mahendrakar@ittiam.com> | 2014-05-16 10:31:13 -0700 |
---|---|---|
committer | Lajos Molnar <lajos@google.com> | 2014-05-21 18:14:55 -0700 |
commit | 0d8951cef4b1a1dbf4ff5ba3e8796cf1d4503098 (patch) | |
tree | 8a81f7d0f636b8b69bfe611aa124035e32ed4edc /decoder/ihevcd_nal.c | |
parent | 446ae52464da2263587877973845fe044100e205 (diff) | |
download | android_external_libhevc-0d8951cef4b1a1dbf4ff5ba3e8796cf1d4503098.tar.gz android_external_libhevc-0d8951cef4b1a1dbf4ff5ba3e8796cf1d4503098.tar.bz2 android_external_libhevc-0d8951cef4b1a1dbf4ff5ba3e8796cf1d4503098.zip |
Initial Version of HEVC decoder
Compliant to reference software HM11.0 onwards
Bug: 14571712
Change-Id: I8af25c1221cc6ab70440141c4d9b48c1ac69696a
Diffstat (limited to 'decoder/ihevcd_nal.c')
-rw-r--r-- | decoder/ihevcd_nal.c | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/decoder/ihevcd_nal.c b/decoder/ihevcd_nal.c new file mode 100644 index 0000000..cf2208f --- /dev/null +++ b/decoder/ihevcd_nal.c @@ -0,0 +1,458 @@ +/****************************************************************************** +* +* Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +******************************************************************************/ +/** +******************************************************************************* +* @file +* ihevcd_nal.c +* +* @brief +* Contains functions for NAL level such as search start code etc +* +* @author +* Harish +* +* @par List of Functions: +* +* @remarks +* None +* +******************************************************************************* +*/ +/*****************************************************************************/ +/* File Includes */ +/*****************************************************************************/ +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "ihevc_typedefs.h" +#include "iv.h" +#include "ivd.h" +#include "ihevcd_cxa.h" + +#include "ihevc_defs.h" +#include "ihevc_debug.h" +#include "ihevc_structs.h" +#include "ihevc_macros.h" +#include "ihevc_platform_macros.h" +#include "ihevc_cabac_tables.h" + + +#include "ihevcd_defs.h" +#include "ihevcd_function_selector.h" +#include "ihevcd_structs.h" +#include "ihevcd_error.h" +#include "ihevcd_nal.h" +#include "ihevcd_bitstream.h" +#include "ihevcd_parse_headers.h" +#include "ihevcd_parse_slice.h" +#include "ihevcd_debug.h" +/*****************************************************************************/ +/* Function Prototypes */ +/*****************************************************************************/ + +/** +******************************************************************************* +* +* @brief +* Search start code from the given buffer pointer +* +* @par Description: +* Search for start code Return the offset of start code if start code is +* found If no start code is found till end of given bitstream then treat +* it as invalid NAL and return end of buffer as offset +* +* @param[in] pu1_buf +* Pointer to bitstream +* +* @param[in] bytes_remaining +* Number of bytes remaining in the buffer +* +* @returns Offset to the first byte in NAL after start code +* +* @remarks +* Incomplete start code at the end of input bitstream is not handled. This +* has to be taken care outside this func +* +******************************************************************************* +*/ +WORD32 ihevcd_nal_search_start_code(UWORD8 *pu1_buf, WORD32 bytes_remaining) +{ + WORD32 ofst; + + WORD32 zero_byte_cnt; + WORD32 start_code_found; + + ofst = -1; + + zero_byte_cnt = 0; + start_code_found = 0; + while(ofst < (bytes_remaining - 1)) + { + ofst++; + if(pu1_buf[ofst] != 0) + { + zero_byte_cnt = 0; + continue; + } + + zero_byte_cnt++; + if((pu1_buf[ofst + 1] == START_CODE_PREFIX_BYTE) && + (zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE)) + { + /* Found the start code */ + ofst++; + start_code_found = 1; + break; + } + } + if(0 == start_code_found) + { + if((START_CODE_PREFIX_BYTE == pu1_buf[ofst]) && + (zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE)) + { + /* Found a start code at the end*/ + ofst++; + } + } + /* Since ofst started at -1, increment it by 1 */ + ofst++; + + return ofst; +} + +/** +******************************************************************************* +* +* @brief +* Remove emulation prevention byte present in the bitstream till next start +* code is found. Emulation prevention byte removed data is stored in a +* different buffer +* +* @par Description: +* Assumption is first start code is already found and pu1_buf is pointing +* to a byte after the start code Search for Next NAL's start code Return +* if start code is found Remove any emulation prevention byte present Copy +* data to new buffer If no start code is found, then treat complete buffer +* as one nal. +* +* @param[in] pu1_src +* Pointer to bitstream (excludes the initial the start code) +* +* @param[in] pu1_dst +* Pointer to destination buffer +* +* @param[in] bytes_remaining +* Number of bytes remaining +* +* @param[out] pi4_nal_len +* NAL length (length of bitstream parsed) +* +* @param[out] pi4_dst_len +* Destination bitstream size (length of bitstream parsed with emulation bytes +* removed) +* +* @returns Error code from IHEVCD_ERROR_T +* +* @remarks +* Incomplete start code at the end of input bitstream is not handled. This +* has to be taken care outside this func +* +******************************************************************************* +*/ +IHEVCD_ERROR_T ihevcd_nal_remv_emuln_bytes(UWORD8 *pu1_src, + UWORD8 *pu1_dst, + WORD32 bytes_remaining, + WORD32 *pi4_nal_len, + WORD32 *pi4_dst_len) +{ + WORD32 src_cnt; + WORD32 dst_cnt; + WORD32 zero_byte_cnt; + WORD32 start_code_found; + UWORD8 u1_src; + IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS; + + src_cnt = 0; + dst_cnt = 0; + zero_byte_cnt = 0; + start_code_found = 0; + while(src_cnt < (bytes_remaining - 1)) + { + u1_src = pu1_src[src_cnt++]; + + pu1_dst[dst_cnt++] = u1_src; + if(u1_src != 0) + { + zero_byte_cnt = 0; + continue; + } + + zero_byte_cnt++; + if(zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE) + { + u1_src = pu1_src[src_cnt]; + if(START_CODE_PREFIX_BYTE == u1_src) + { + /* Found the start code */ + src_cnt -= zero_byte_cnt; + dst_cnt -= zero_byte_cnt; + start_code_found = 1; + break; + } + else if(EMULATION_PREVENT_BYTE == u1_src) + { + /* Found the emulation prevention byte */ + src_cnt++; + zero_byte_cnt = 0; + + /* Decrement dst_cnt so that the next byte overwrites + * the emulation prevention byte already copied to dst above + */ + } + } + + } + + if(0 == start_code_found) + { + u1_src = pu1_src[src_cnt++]; + if(zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE) + { + + if(START_CODE_PREFIX_BYTE == u1_src) + { + /* Found a start code at the end*/ + src_cnt -= zero_byte_cnt; + } + else if(EMULATION_PREVENT_BYTE == u1_src) + { + /* Found the emulation prevention byte at the end*/ + src_cnt++; + /* Decrement dst_cnt so that the next byte overwrites + * the emulation prevention byte already copied to dst above + */ + dst_cnt--; + } + } + else + { + pu1_dst[dst_cnt++] = u1_src; + } + + + } + *pi4_nal_len = src_cnt; + *pi4_dst_len = dst_cnt; + return ret; +} +/** +******************************************************************************* +* +* @brief +* Decode given NAL unit's header +* +* @par Description: +* Call NAL unit's header decode Section: 7.3.1.2 +* +* @param[in] ps_bitstrm +* Pointer to bitstream context +* +* @param[out] ps_nal +* Pointer to NAL header +* +* @returns Error code from IHEVCD_ERROR_T +* +* @remarks +* +* +******************************************************************************* +*/ +IHEVCD_ERROR_T ihevcd_nal_unit_header(bitstrm_t *ps_bitstrm, nal_header_t *ps_nal) +{ + WORD32 unused; + IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS; + UNUSED(unused); + /* Syntax : forbidden_zero_bit */ + unused = ihevcd_bits_get(ps_bitstrm, 1); + + /* Syntax : nal_unit_type */ + ps_nal->i1_nal_unit_type = ihevcd_bits_get(ps_bitstrm, 6); + + /* Syntax : nuh_reserved_zero_6bits */ + unused = ihevcd_bits_get(ps_bitstrm, 6); + + /* Syntax : nuh_temporal_id_plus1 */ + ps_nal->i1_nuh_temporal_id = ihevcd_bits_get(ps_bitstrm, 3) - 1; + + return ret; + +} + +/** +******************************************************************************* +* +* @brief +* Decode given NAL +* +* @par Description: +* Based on the NAL type call appropriate decode function Section: 7.3.1.1 +* +* +* @param[in,out] ps_codec +* Pointer to codec context (Functions called within will modify contents of +* ps_codec) +* +* @returns Error code from IHEVCD_ERROR_T +* +* @remarks +* +* +******************************************************************************* +*/ +IHEVCD_ERROR_T ihevcd_nal_unit(codec_t *ps_codec) +{ + IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS; + + /* NAL Header */ + nal_header_t s_nal; + + ret = ihevcd_nal_unit_header(&ps_codec->s_parse.s_bitstrm, &s_nal); + RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret); + + if(ps_codec->i4_slice_error) + s_nal.i1_nal_unit_type = ps_codec->s_parse.ps_slice_hdr->i1_nal_unit_type; + + /* Setting RASL Output flag */ + switch(s_nal.i1_nal_unit_type) + { + case NAL_BLA_W_LP : + case NAL_BLA_W_DLP : + case NAL_BLA_N_LP : + ps_codec->i4_rasl_output_flag = 0; + break; + + //TODO: After IDR, there is no case of open GOP + //To be fixed appropriately by ignoring RASL only if the + // required references are not found + case NAL_IDR_W_LP : + case NAL_IDR_N_LP : + ps_codec->i4_rasl_output_flag = 1; + break; + + case NAL_CRA : + ps_codec->i4_rasl_output_flag = (0 == ps_codec->u4_pic_cnt) ? 0 : 1; + break; + + default: + break; + } + + switch(s_nal.i1_nal_unit_type) + { + case NAL_BLA_W_LP : + case NAL_BLA_W_DLP : + case NAL_BLA_N_LP : + case NAL_IDR_W_LP : + case NAL_IDR_N_LP : + case NAL_CRA : + case NAL_TRAIL_N : + case NAL_TRAIL_R : + case NAL_TSA_N : + case NAL_TSA_R : + case NAL_STSA_N : + case NAL_STSA_R : + case NAL_RADL_N : + case NAL_RADL_R : + case NAL_RASL_N : + case NAL_RASL_R : + if(ps_codec->i4_header_mode) + return IHEVCD_SLICE_IN_HEADER_MODE; + + if((0 == ps_codec->i4_sps_done) || + (0 == ps_codec->i4_pps_done)) + { + return IHEVCD_INVALID_HEADER; + } + + ps_codec->i4_header_in_slice_mode = 0; + + ret = ihevcd_parse_slice_header(ps_codec, &s_nal); + DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type); + if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS) + { + if((s_nal.i1_nal_unit_type != NAL_RASL_N && s_nal.i1_nal_unit_type != NAL_RASL_R) || + ps_codec->i4_rasl_output_flag || + ps_codec->i4_slice_error) + ret = ihevcd_parse_slice_data(ps_codec); + } + break; + + case NAL_VPS : + // ret = ihevcd_parse_vps(ps_codec); + DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type); + break; + + case NAL_SPS : + if(0 == ps_codec->i4_header_mode) + { + ps_codec->i4_header_in_slice_mode = 1; + if(ps_codec->i4_sps_done && + ps_codec->i4_pic_present) + break; + } + + ret = ihevcd_parse_sps(ps_codec); + if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS) + { + sps_t *ps_sps = ps_codec->ps_sps_base + MAX_SPS_CNT - 1; + ihevcd_copy_sps(ps_codec, ps_sps->i1_sps_id, MAX_SPS_CNT - 1); + } + + DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type); + break; + + case NAL_PPS : + if(0 == ps_codec->i4_header_mode) + { + ps_codec->i4_header_in_slice_mode = 1; + if(ps_codec->i4_pps_done && + ps_codec->i4_pic_present) + break; + } + + ret = ihevcd_parse_pps(ps_codec); + if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS) + { + pps_t *ps_pps = ps_codec->ps_pps_base + MAX_PPS_CNT - 1; + ihevcd_copy_pps(ps_codec, ps_pps->i1_pps_id, MAX_PPS_CNT - 1); + } + + DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type); + break; + + default: + DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type); + break; + } + + return ret; +} + |