/****************************************************************************** * * Copyright (C) 2015 The Android Open Source Project * * 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. * ***************************************************************************** * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore */ /*! ************************************************************************** * \file ih264d_nal.c * * \brief NAL parsing routines * * Detailed_description * * \author * - AI 19 11 2002 Creation ************************************************************************** */ #include "ih264d_bitstrm.h" #include "ih264d_defs.h" #include "ih264_typedefs.h" #include "ih264_macros.h" #include "ih264_platform_macros.h" #include "ih264d_defs.h" #define NUM_OF_ZERO_BYTES_BEFORE_START_CODE 2 #define EMULATION_PREVENTION_BYTE 0x03 #define NAL_FIRST_BYTE_SIZE 1 /*! ************************************************************************** * \if Function name : ih264d_find_start_code \endif * * \brief * This function searches for the Start Code Prefix. * * \param pu1_buf : Pointer to char buffer which contains bitstream. * \param u4_cur_pos : Current position in the buffer. * \param u4_max_ofst : Number of bytes in Buffer. * \param pu4_length_of_start_code : Poiter to length of Start Code. * * \return * Returns 0 on success and -1 on error. * ************************************************************************** */ #define START_CODE_NOT_FOUND -1 #define END_OF_STREAM_BUFFER -2 #define END_OF_STREAM -1 void ih264d_check_if_aud(UWORD8 *pu1_buf, UWORD32 u4_cur_pos, UWORD32 u4_max_ofst, UWORD32 *pu4_next_is_aud) { UWORD8 u1_first_byte, u1_nal_unit_type; if(u4_cur_pos + 1 < u4_max_ofst) { u1_first_byte = pu1_buf[u4_cur_pos + 1]; u1_nal_unit_type = NAL_UNIT_TYPE(u1_first_byte); if(u1_nal_unit_type == ACCESS_UNIT_DELIMITER_RBSP) { *pu4_next_is_aud = 1; } } } WORD32 ih264d_find_start_code(UWORD8 *pu1_buf, UWORD32 u4_cur_pos, UWORD32 u4_max_ofst, UWORD32 *pu4_length_of_start_code, UWORD32 *pu4_next_is_aud) { WORD32 zero_byte_cnt = 0; UWORD32 ui_curPosTemp; *pu4_length_of_start_code = 0; /*Find first start code */ while(u4_cur_pos < u4_max_ofst) { if(pu1_buf[u4_cur_pos] == 0) zero_byte_cnt++; else if(pu1_buf[u4_cur_pos] == 0x01 && zero_byte_cnt >= NUM_OF_ZERO_BYTES_BEFORE_START_CODE) { /* Found the start code */ u4_cur_pos++; break; } else { zero_byte_cnt = 0; } u4_cur_pos++; } /*Find Next Start Code */ *pu4_length_of_start_code = u4_cur_pos; zero_byte_cnt = 0; ui_curPosTemp = u4_cur_pos; while(u4_cur_pos < u4_max_ofst) { if(pu1_buf[u4_cur_pos] == 0) zero_byte_cnt++; else if(pu1_buf[u4_cur_pos] == 0x01 && zero_byte_cnt >= NUM_OF_ZERO_BYTES_BEFORE_START_CODE) { /* Found the start code */ ih264d_check_if_aud(pu1_buf, u4_cur_pos, u4_max_ofst, pu4_next_is_aud); return (u4_cur_pos - zero_byte_cnt - ui_curPosTemp); } else { zero_byte_cnt = 0; } u4_cur_pos++; } return (u4_cur_pos - zero_byte_cnt - ui_curPosTemp); //(START_CODE_NOT_FOUND); } /*! ************************************************************************** * \if Function name : ih264d_get_next_nal_unit \endif * * \brief * This function reads one NAl unit. * * \param ps_nalStream : Poiter to NalUnitStream structure. * \param ps_nalUnit : Pointer to NalUnit. * * \return * Returns 0 on success and -1 on error. * ************************************************************************** */ WORD32 ih264d_get_next_nal_unit(UWORD8 *pu1_buf, UWORD32 u4_cur_pos, UWORD32 u4_max_ofst, UWORD32 *pu4_length_of_start_code) { WORD32 i_length_of_nal_unit = 0; UWORD32 u4_next_is_aud; /* NAL Thread starts */ ih264d_find_start_code(pu1_buf, u4_cur_pos, u4_max_ofst, pu4_length_of_start_code, &u4_next_is_aud); return (i_length_of_nal_unit); } /*! ************************************************************************** * \if Function name : ih264d_process_nal_unit \endif * * \brief * This function removes emulation byte "0x03" from bitstream (EBSP to RBSP). * It also converts bytestream format into 32 bit little-endian format. * * \param ps_bitstrm : Poiter to dec_bit_stream_t structure. * \param pu1_nal_unit : Pointer to char buffer of NalUnit. * \param u4_numbytes_in_nal_unit : Number bytes in NalUnit buffer. * * \return * Returns number of bytes in RBSP ps_bitstrm. * * \note * This function is same as nal_unit() of 7.3.1. Apart from nal_unit() * implementation it converts char buffer into 32 bit Buffer. This * facilitates efficient access of bitstream. This has been done taking * into account present processor architectures. * ************************************************************************** */ WORD32 ih264d_process_nal_unit(dec_bit_stream_t *ps_bitstrm, UWORD8 *pu1_nal_unit, UWORD32 u4_numbytes_in_nal_unit) { UWORD32 u4_num_bytes_in_rbsp; UWORD8 u1_cur_byte; WORD32 i = 0; WORD8 c_count; UWORD32 ui_word; UWORD32 *puc_bitstream_buffer = (UWORD32*)pu1_nal_unit; ps_bitstrm->pu4_buffer = puc_bitstream_buffer; /*--------------------------------------------------------------------*/ /* First Byte of the NAL Unit */ /*--------------------------------------------------------------------*/ ui_word = *pu1_nal_unit++; /*--------------------------------------------------------------------*/ /* Convertion of the EBSP to RBSP */ /* ie Remove the emulation_prevention_byte [equal to 0x03] */ /*--------------------------------------------------------------------*/ u4_num_bytes_in_rbsp = 0; c_count = 0; //first iteration u1_cur_byte = *pu1_nal_unit++; ui_word = ((ui_word << 8) | u1_cur_byte); c_count++; if(u1_cur_byte != 0x00) c_count = 0; //second iteration u1_cur_byte = *pu1_nal_unit++; ui_word = ((ui_word << 8) | u1_cur_byte); u4_num_bytes_in_rbsp = 2; c_count++; if(u1_cur_byte != 0x00) c_count = 0; if(u4_numbytes_in_nal_unit > 2) { i = ((u4_numbytes_in_nal_unit - 3)); } for(; i > 8; i -= 4) { // loop 0 u1_cur_byte = *pu1_nal_unit++; if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE && u1_cur_byte == EMULATION_PREVENTION_BYTE) { c_count = 0; u1_cur_byte = *pu1_nal_unit++; i--; } ui_word = ((ui_word << 8) | u1_cur_byte); *puc_bitstream_buffer = ui_word; puc_bitstream_buffer++; c_count++; if(u1_cur_byte != 0x00) c_count = 0; // loop 1 u1_cur_byte = *pu1_nal_unit++; if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE && u1_cur_byte == EMULATION_PREVENTION_BYTE) { c_count = 0; u1_cur_byte = *pu1_nal_unit++; i--; } ui_word = ((ui_word << 8) | u1_cur_byte); c_count++; if(u1_cur_byte != 0x00) c_count = 0; // loop 2 u1_cur_byte = *pu1_nal_unit++; if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE && u1_cur_byte == EMULATION_PREVENTION_BYTE) { c_count = 0; u1_cur_byte = *pu1_nal_unit++; i--; } ui_word = ((ui_word << 8) | u1_cur_byte); c_count++; if(u1_cur_byte != 0x00) c_count = 0; // loop 3 u1_cur_byte = *pu1_nal_unit++; if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE && u1_cur_byte == EMULATION_PREVENTION_BYTE) { c_count = 0; u1_cur_byte = *pu1_nal_unit++; i--; } ui_word = ((ui_word << 8) | u1_cur_byte); c_count++; if(u1_cur_byte != 0x00) c_count = 0; u4_num_bytes_in_rbsp += 4; } for(; i > 0; i--) { u1_cur_byte = *pu1_nal_unit++; if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE && u1_cur_byte == EMULATION_PREVENTION_BYTE) { c_count = 0; i--; u1_cur_byte = *pu1_nal_unit++; } ui_word = ((ui_word << 8) | u1_cur_byte); u4_num_bytes_in_rbsp++; if((u4_num_bytes_in_rbsp & 0x03) == 0x03) { *puc_bitstream_buffer = ui_word; puc_bitstream_buffer++; } c_count++; if(u1_cur_byte != 0x00) c_count = 0; } *puc_bitstream_buffer = (ui_word << ((3 - (((u4_num_bytes_in_rbsp << 30) >> 30))) << 3)); ps_bitstrm->u4_ofst = 0; ps_bitstrm->u4_max_ofst = ((u4_num_bytes_in_rbsp + NAL_FIRST_BYTE_SIZE) << 3); return (u4_num_bytes_in_rbsp); } /*! ************************************************************************** * \if Function name : ih264d_rbsp_to_sodb \endif * * \brief * This function converts RBSP to SODB. * * \param ps_bitstrm : Poiter to dec_bit_stream_t structure. * * \return * None. * ************************************************************************** */ void ih264d_rbsp_to_sodb(dec_bit_stream_t *ps_bitstrm) { UWORD32 ui_lastWord; UWORD32 ui_word; UWORD8 uc_lastByte; WORD8 i; ui_lastWord = (ps_bitstrm->u4_max_ofst >> 5); i = (ps_bitstrm->u4_max_ofst >> 3) & 0x03; if(i) { ui_word = ps_bitstrm->pu4_buffer[ui_lastWord]; uc_lastByte = ((ui_word << ((i - 1) << 3)) >> 24); } else { ui_word = ps_bitstrm->pu4_buffer[ui_lastWord - 1]; uc_lastByte = ((ui_word << 24) >> 24); } /*--------------------------------------------------------------------*/ /* Find out the rbsp_stop_bit position in the last byte of rbsp */ /*--------------------------------------------------------------------*/ for(i = 0; (i < 8) && !CHECKBIT(uc_lastByte, i); ++i) ; ps_bitstrm->u4_max_ofst = ps_bitstrm->u4_max_ofst - (i + 1); }