/****************************************************************************** * * 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 * ih264e_bitstream.c * * @brief * This file contains function definitions related to bitstream generation * * @author * ittiam * * @par List of Functions: * - ih264e_bitstrm_init() * - ih264e_put_bits() * - ih264e_put_bit() * - ih264e_put_rbsp_trailing_bits() * - ih264e_put_uev() * - ih264e_put_sev() * - ih264e_put_nal_start_code_prefix() * ****************************************************************************** */ /*****************************************************************************/ /* File Includes */ /*****************************************************************************/ /* System include files */ #include #include #include #include #include #include /* User include files */ #include "ih264e_config.h" #include "ih264_typedefs.h" #include "ih264_platform_macros.h" #include "ih264_debug.h" #include "ih264e_error.h" #include "ih264e_bitstream.h" #include "ih264_defs.h" #include "ih264_macros.h" /*****************************************************************************/ /* Function Definitions */ /*****************************************************************************/ /** ****************************************************************************** * * @brief Initializes the encoder bitstream engine * * @par Description * This routine needs to be called at start of slice/frame encode * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] p1_bitstrm_buf * bitstream buffer pointer where the encoded stream is generated in byte order * * @param[in] u4_max_bitstrm_size * indicates maximum bitstream buffer size. (in bytes) * If actual stream size exceeds the maximum size, encoder should * 1. Not corrupt data beyond u4_max_bitstrm_size bytes * 2. Report an error back to application indicating overflow * * @return success or failure error code * ****************************************************************************** */ IH264E_ERROR_T ih264e_bitstrm_init(bitstrm_t *ps_bitstrm, UWORD8 *pu1_bitstrm_buf, UWORD32 u4_max_bitstrm_size) { ps_bitstrm->pu1_strm_buffer = pu1_bitstrm_buf; ps_bitstrm->u4_max_strm_size = u4_max_bitstrm_size; /* Default init values for other members of bitstream context */ ps_bitstrm->u4_strm_buf_offset = 0; ps_bitstrm->u4_cur_word = 0; ps_bitstrm->i4_bits_left_in_cw = WORD_SIZE; ps_bitstrm->i4_zero_bytes_run = 0; return(IH264E_SUCCESS); } /** ****************************************************************************** * * @brief puts a code with specified number of bits into the bitstream * * @par Description * inserts code_len number of bits from lsb of code_val into the * bitstream. updates context members like u4_cur_word, u4_strm_buf_offset and * i4_bits_left_in_cw. If the total words (u4_strm_buf_offset) exceeds max * available size (u4_max_strm_size), returns error without corrupting data * beyond it * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] u4_code_val * code value that needs to be inserted in the stream. * * @param[in] code_len * indicates code length (in bits) of code_val that would be inserted in * bitstream buffer size. Range of length[1:WORD_SIZE] * * @remarks Assumptions: all bits from bit position code_len to msb of * code_val shall be zero * * @return success or failure error code * ****************************************************************************** */ IH264E_ERROR_T ih264e_put_bits(bitstrm_t *ps_bitstrm, UWORD32 u4_code_val, WORD32 code_len) { UWORD32 u4_cur_word = ps_bitstrm->u4_cur_word; WORD32 bits_left_in_cw = ps_bitstrm->i4_bits_left_in_cw; /* check assumptions made in the module */ ASSERT(code_len > 0 && code_len <= WORD_SIZE); if(code_len < WORD_SIZE) ASSERT((u4_code_val >> code_len) == 0); /* sanity check on the bitstream engine state */ ASSERT(bits_left_in_cw > 0 && bits_left_in_cw <= WORD_SIZE); ASSERT(ps_bitstrm->i4_zero_bytes_run <= EPB_ZERO_BYTES); ASSERT(ps_bitstrm->pu1_strm_buffer != NULL); if(bits_left_in_cw > code_len) { /*******************************************************************/ /* insert the code in local bitstream word and return */ /* code is inserted in position of bits left (post decrement) */ /*******************************************************************/ bits_left_in_cw -= code_len; u4_cur_word |= (u4_code_val << bits_left_in_cw); ps_bitstrm->u4_cur_word = u4_cur_word; ps_bitstrm->i4_bits_left_in_cw = bits_left_in_cw; return(IH264E_SUCCESS); } else { /********************************************************************/ /* 1. insert partial code corresponding to bits left in cur word */ /* 2. flush all the bits of cur word to bitstream */ /* 3. insert emulation prevention bytes while flushing the bits */ /* 4. insert remaining bits of code starting from msb of cur word */ /* 5. update bitsleft in current word and stream buffer offset */ /********************************************************************/ IH264E_ERROR_T status = IH264E_SUCCESS; WORD32 i, rem_bits = (code_len - bits_left_in_cw); /* insert parital code corresponding to bits left in cur word */ u4_cur_word |= u4_code_val >> rem_bits; for(i = WORD_SIZE; i > 0; i -= 8) { /* flush the bits in cur word byte by byte and copy to stream */ UWORD8 u1_next_byte = (u4_cur_word >> (i-8)) & 0xFF; status |= ih264e_put_byte_epb(ps_bitstrm, u1_next_byte); } /* insert the remaining bits from code val into current word */ u4_cur_word = rem_bits ? (u4_code_val << (WORD_SIZE - rem_bits)) : 0; /* update the state variables and return success */ ps_bitstrm->u4_cur_word = u4_cur_word; ps_bitstrm->i4_bits_left_in_cw = WORD_SIZE - rem_bits; return (status); } } /** ****************************************************************************** * * @brief inserts a 1-bit code into the bitstream * * @par Description * inserts 1bit lsb of code_val into the bitstream * updates context members like u4_cur_word, u4_strm_buf_offset and * i4_bits_left_in_cw. If the total words (u4_strm_buf_offset) exceeds max * available size (u4_max_strm_size), returns error without corrupting data * beyond it * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] u4_code_val * code value that needs to be inserted in the stream. * * @remarks Assumptions: all bits from bit position 1 to msb of code_val * shall be zero * * @return success or failure error code * ****************************************************************************** */ IH264E_ERROR_T ih264e_put_bit(bitstrm_t *ps_bitstrm, UWORD32 u4_code_val) { /* call the put bits function for 1 bit and return */ return(ih264e_put_bits(ps_bitstrm, u4_code_val, 1)); } /** ****************************************************************************** * * @brief inserts rbsp trailing bits at the end of stream buffer (NAL) * * @par Description * inserts rbsp trailing bits, updates context members like u4_cur_word and * i4_bits_left_in_cw and flushes the same in the bitstream buffer. If the * total words (u4_strm_buf_offset) exceeds max available size * (u4_max_strm_size), returns error without corrupting data beyond it * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @return success or failure error code * ****************************************************************************** */ IH264E_ERROR_T ih264e_put_rbsp_trailing_bits(bitstrm_t *ps_bitstrm) { WORD32 i; UWORD32 u4_cur_word = ps_bitstrm->u4_cur_word; WORD32 bits_left_in_cw = ps_bitstrm->i4_bits_left_in_cw; WORD32 bytes_left_in_cw = (bits_left_in_cw - 1) >> 3; IH264E_ERROR_T status = IH264E_SUCCESS; /* insert a 1 at the end of current word and flush all the bits */ u4_cur_word |= (1 << (bits_left_in_cw - 1)); /* get the bits to be inserted in msbdb of the word */ //u4_cur_word <<= (WORD_SIZE - bytes_left_in_cw + 1); for(i = WORD_SIZE; i > (bytes_left_in_cw*8); i -= 8) { /* flush the bits in cur word byte by byte and copy to stream */ UWORD8 u1_next_byte = (u4_cur_word >> (i-8)) & 0xFF; status |= ih264e_put_byte_epb(ps_bitstrm, u1_next_byte); } /* Default init values for scratch variables of bitstream context */ ps_bitstrm->u4_cur_word = 0; ps_bitstrm->i4_bits_left_in_cw = WORD_SIZE; ps_bitstrm->i4_zero_bytes_run = 0; return (status); } /** ****************************************************************************** * * @brief puts exponential golomb code of a unsigned integer into bitstream * * @par Description * computes uev code for given syntax element and inserts the same into * bitstream by calling ih264e_put_bits() interface. * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] u4_code_num * unsigned integer input whose golomb code is written in stream * * @remarks Assumptions: code value can be represented in less than 16bits * * @return success or failure error code * ****************************************************************************** */ IH264E_ERROR_T ih264e_put_uev(bitstrm_t *ps_bitstrm, UWORD32 u4_code_num) { UWORD32 u4_bit_str, u4_range; IH264E_ERROR_T e_error; /* convert the codenum to exp-golomb bit code: Table 9-2 JCTVC-J1003_d7 */ u4_bit_str = u4_code_num + 1; /* get range of the bit string and put using put_bits() */ GETRANGE(u4_range, u4_bit_str); e_error = ih264e_put_bits(ps_bitstrm, u4_bit_str, (2 * u4_range - 1)); return(e_error); } /** ****************************************************************************** * * @brief puts exponential golomb code of a signed integer into bitstream * * @par Description * computes sev code for given syntax element and inserts the same into * bitstream by calling ih264e_put_bits() interface. * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] syntax_elem * signed integer input whose golomb code is written in stream * * @remarks Assumptions: code value can be represented in less than 16bits * * @return success or failure error code * ****************************************************************************** */ IH264E_ERROR_T ih264e_put_sev(bitstrm_t *ps_bitstrm, WORD32 syntax_elem) { UWORD32 u4_code_num, u4_bit_str, u4_range; IH264E_ERROR_T e_error; /************************************************************************/ /* convert the codenum to exp-golomb bit code for signed syntax element */ /* See Table9-2 and Table 9-3 of standard JCTVC-J1003_d7 */ /************************************************************************/ if(syntax_elem <= 0) { /* codeNum for non-positive integer = 2*abs(x) : Table9-3 */ u4_code_num = ((-syntax_elem) << 1); } else { /* codeNum for positive integer = 2x-1 : Table9-3 */ u4_code_num = (syntax_elem << 1) - 1; } /* convert the codenum to exp-golomb bit code: Table 9-2 JCTVC-J1003_d7 */ u4_bit_str = u4_code_num + 1; /* get range of the bit string and put using put_bits() */ GETRANGE(u4_range, u4_bit_str); e_error = ih264e_put_bits(ps_bitstrm, u4_bit_str, (2 * u4_range - 1)); return(e_error); } /** ****************************************************************************** * * @brief insert NAL start code prefix (0x000001) into bitstream with an option * of inserting leading_zero_8bits (which makes startcode prefix as 0x00000001) * * @par Description * Although start code prefix could have been put by calling ih264e_put_bits(), * ih264e_put_nal_start_code_prefix() is specially added to make sure emulation * prevention insertion is not done for the NAL start code prefix which will * surely happen otherwise by calling ih264e_put_bits() interface. * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] insert_leading_zero_8bits * flag indicating if one more zero bytes needs to prefixed before start code * * @return success or failure error code * ****************************************************************************** */ IH264E_ERROR_T ih264e_put_nal_start_code_prefix(bitstrm_t *ps_bitstrm, WORD32 insert_leading_zero_8bits) { UWORD32 u4_strm_buf_offset = ps_bitstrm->u4_strm_buf_offset; UWORD8* pu1_strm_buf = ps_bitstrm->pu1_strm_buffer; /* Bitstream buffer overflow check assuming worst case of 4 bytes */ if((u4_strm_buf_offset + 4) >= ps_bitstrm->u4_max_strm_size) { return(IH264E_BITSTREAM_BUFFER_OVERFLOW); } /* Insert leading zero 8 bits conditionally */ if(insert_leading_zero_8bits) { pu1_strm_buf[u4_strm_buf_offset] = 0x00; u4_strm_buf_offset++; } /* Insert NAL start code prefix 0x00 00 01 */ pu1_strm_buf[u4_strm_buf_offset] = 0x00; u4_strm_buf_offset++; pu1_strm_buf[u4_strm_buf_offset] = 0x00; u4_strm_buf_offset++; pu1_strm_buf[u4_strm_buf_offset] = 0x01; u4_strm_buf_offset++; /* update the stream offset */ ps_bitstrm->u4_strm_buf_offset = u4_strm_buf_offset; return (IH264E_SUCCESS); }