summaryrefslogtreecommitdiffstats
path: root/decoder/ihevcd_nal.c
diff options
context:
space:
mode:
authorHarish Mahendrakar <harish.mahendrakar@ittiam.com>2014-05-16 10:31:13 -0700
committerLajos Molnar <lajos@google.com>2014-05-21 18:14:55 -0700
commit0d8951cef4b1a1dbf4ff5ba3e8796cf1d4503098 (patch)
tree8a81f7d0f636b8b69bfe611aa124035e32ed4edc /decoder/ihevcd_nal.c
parent446ae52464da2263587877973845fe044100e205 (diff)
downloadandroid_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.c458
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;
+}
+