| /****************************************************************************** |
| * |
| * 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); |
| } |