/****************************************************************************** * * 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.h * * @brief * This file contains encoder bitstream engine related structures and * interface prototypes * * @author * ittiam * * @remarks * none * ******************************************************************************* */ #ifndef IH264E_BITSTREAM_H_ #define IH264E_BITSTREAM_H_ /*****************************************************************************/ /* Constant Macros */ /*****************************************************************************/ /** ****************************************************************************** * @brief defines the maximum number of bits in a bitstream word ****************************************************************************** */ #define WORD_SIZE 32 /** ****************************************************************************** * @brief The number of consecutive zero bytes for emulation prevention check ****************************************************************************** */ #define EPB_ZERO_BYTES 2 /** ****************************************************************************** * @brief Emulation prevention insertion byte ****************************************************************************** */ #define EPB_BYTE 0x03 /** ****************************************************************************** * @brief Stream buffer allocated per frame should be atleast MIN_STREAM_SIZE ****************************************************************************** */ #define MIN_STREAM_SIZE 0x800 /*****************************************************************************/ /* Function Macros */ /*****************************************************************************/ /** ****************************************************************************** * @brief Macro to check if emulation prevention byte insertion is required ****************************************************************************** */ #define INSERT_EPB(zero_run, next_byte) \ ((zero_run) == EPB_ZERO_BYTES) && (0 == ((next_byte) & 0xFC)) /** ****************************************************************************** * @brief returns the bit position of a leading 1 (msb) in a code value ****************************************************************************** */ #if !MSVC #define GETRANGE(r,value) \ { \ r = 0; \ if(0 == value) \ r = 1; \ else \ { \ r = 32-CLZ(value); \ }\ } #else #define GETRANGE(r,value) \ { \ unsigned long msb_one_bit = 0; \ r = _BitScanReverse(&msb_one_bit, value) ? (UWORD32)(msb_one_bit + 1) : 1 ; \ } #endif /** ****************************************************************************** * @brief returns bits required to code a value ****************************************************************************** */ #define UE_LENGTH(bits,x) \ { \ UWORD32 r_bit; \ GETRANGE(r_bit,x+1) \ bits =(((r_bit - 1) << 1)+1);\ } \ /** ****************************************************************************** * @brief Inserts 1 byte and Emulation Prevention Byte(if any) into bitstream * Increments the stream offset and zero run correspondingly ****************************************************************************** */ #define PUTBYTE_EPB(ptr,off,byte,zero_run) \ { \ if( INSERT_EPB(zero_run, byte) ) \ { \ ptr[off] = EPB_BYTE; \ off++; \ zero_run = 0; \ } \ \ ptr[off] = byte; \ off++; \ zero_run = byte ? 0 : zero_run+1; \ } \ /** ****************************************************************************** * @brief Ensures Byte alignment of the slice header ****************************************************************************** */ #define BYTE_ALIGNMENT(ps_bitstrm) ih264e_put_rbsp_trailing_bits(ps_bitstrm) /** ****************************************************************************** * @brief Gets number of bits coded ****************************************************************************** */ #define GET_NUM_BITS(ps_bitstream) ((ps_bitstream->u4_strm_buf_offset << 3) \ + 32 - ps_bitstream->i4_bits_left_in_cw); /** ****************************************************************************** * @macro Align bitstream to byte - Remainig bits are filled with '1' ****************************************************************************** */ #define BITSTREAM_BYTE_ALIGN(ps_bitstrm) \ if (ps_bitstrm->i4_bits_left_in_cw & 0x07) \ { \ const WORD32 len = (WORD32)((ps_bitstrm->i4_bits_left_in_cw) & 0x07);\ ih264e_put_bits(ps_bitstrm, (UWORD32)((1 << len) - 1), len); \ } \ /*****************************************************************************/ /* Structures */ /*****************************************************************************/ /** ****************************************************************************** * @brief Bitstream context for encoder ****************************************************************************** */ typedef struct bitstrm { /** points to start of stream buffer. */ UWORD8 *pu1_strm_buffer; /** * max bitstream size (in bytes). * Encoded stream shall not exceed this size. */ UWORD32 u4_max_strm_size; /** * byte offset (w.r.t pu1_strm_buffer) where next byte would be written * Bitstream engine makes sure it would not corrupt data beyond * u4_max_strm_size bytes */ UWORD32 u4_strm_buf_offset; /** * current bitstream word; It is a scratch word containing max of * WORD_SIZE bits. Will be copied to stream buffer when the word is * full */ UWORD32 u4_cur_word; /** * signifies number of bits available in u4_cur_word * bits from msb to i4_bits_left_in_cw of u4_cur_word have already been * inserted next bits would be inserted from pos [i4_bits_left_in_cw-1] * Range of this variable [1 : WORD_SIZE] */ WORD32 i4_bits_left_in_cw; /** * signifies the number of consecutive zero bytes propogated from previous * word. It is used for emulation prevention byte insertion in the stream */ WORD32 i4_zero_bytes_run; } bitstrm_t; /** ****************************************************************************** * @brief Inserts 1 byte and Emulation Prevention Byte(if any) into bitstream * Increments the stream offset and zero run correspondingly ****************************************************************************** */ static inline IH264E_ERROR_T ih264e_put_byte_epb(bitstrm_t *ps_bitstrm, UWORD8 byte) { if (INSERT_EPB(ps_bitstrm->i4_zero_bytes_run, byte)) { if ((ps_bitstrm->u4_strm_buf_offset + 1) >= ps_bitstrm->u4_max_strm_size) { return IH264E_BITSTREAM_BUFFER_OVERFLOW; } ps_bitstrm->pu1_strm_buffer[ps_bitstrm->u4_strm_buf_offset++] = EPB_BYTE; ps_bitstrm->i4_zero_bytes_run = 0; } if ((ps_bitstrm->u4_strm_buf_offset + 1) >= ps_bitstrm->u4_max_strm_size) { return IH264E_BITSTREAM_BUFFER_OVERFLOW; } ps_bitstrm->pu1_strm_buffer[ps_bitstrm->u4_strm_buf_offset++] = byte; ps_bitstrm->i4_zero_bytes_run = byte ? 0 : ps_bitstrm->i4_zero_bytes_run + 1; return IH264E_SUCCESS; } /** ****************************************************************************** * flush the bits in cur word byte by byte and copy to stream * * (current word is assumed to be byte aligned) * ****************************************************************************** */ #define BITSTREAM_FLUSH(ps_bitstrm, err) \ { \ WORD32 i; \ for (i = WORD_SIZE; i > ps_bitstrm->i4_bits_left_in_cw; i -= 8) \ { \ UWORD8 u1_next_byte = (ps_bitstrm->u4_cur_word >> (i - 8)) & 0xFF; \ err |= ih264e_put_byte_epb(ps_bitstrm, u1_next_byte); \ } \ ps_bitstrm->u4_cur_word = 0; \ ps_bitstrm->i4_bits_left_in_cw = WORD_SIZE; \ } \ /*****************************************************************************/ /* Extern Function Declarations */ /*****************************************************************************/ /** ****************************************************************************** * * @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 ); /** ****************************************************************************** * * @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. If the total bytes (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. * * @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 ); /** ****************************************************************************** * * @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 ); /** ****************************************************************************** * * @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 ); /** ****************************************************************************** * * @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 ); /** ****************************************************************************** * * @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 ); /** ****************************************************************************** * * @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 ); #endif /* IH264E_BITSTREAM_H_ */