/******************************************************************************
*
* 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); \
}
/**
******************************************************************************
* 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) \
{ \
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; \
PUTBYTE_EPB(ps_bitstrm->pu1_strm_buffer, ps_bitstrm->u4_strm_buf_offset,\
u1_next_byte, ps_bitstrm->i4_zero_bytes_run); \
} \
ps_bitstrm->u4_cur_word = 0; \
ps_bitstrm->i4_bits_left_in_cw = WORD_SIZE; \
} \
/*****************************************************************************/
/* 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;
/*****************************************************************************/
/* 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_ */