| /****************************************************************************** |
| * |
| * Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore |
| * |
| * 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. |
| * |
| ******************************************************************************/ |
| /** |
| ******************************************************************************* |
| * @file |
| * ihevcd_bitstream.c |
| * |
| * @brief |
| * Contains functions for bitstream access |
| * |
| * @author |
| * Harish |
| * |
| * @par List of Functions: |
| * - ihevcd_bits_init() |
| * - ihevcd_bits_flush() |
| * - ihevcd_bits_flush_to_byte_boundary() |
| * - ihevcd_bits_nxt() |
| * - ihevcd_bits_nxt32() |
| * - ihevcd_bits_get() |
| * - ihevcd_bits_num_bits_remaining() |
| * - ihevcd_bits_num_bits_consumed() |
| * - ihevcd_sev() |
| * - ihevcd_uev() |
| * |
| * |
| * @remarks |
| * None |
| * |
| ******************************************************************************* |
| */ |
| /*****************************************************************************/ |
| /* File Includes */ |
| /*****************************************************************************/ |
| #include <stdio.h> |
| #include <stddef.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <assert.h> |
| #include "ihevc_typedefs.h" |
| #include "iv.h" |
| #include "ivd.h" |
| #include "ihevcd_cxa.h" |
| |
| #include "ihevc_defs.h" |
| #include "ihevc_debug.h" |
| #include "ihevc_structs.h" |
| #include "ihevc_macros.h" |
| #include "ihevc_platform_macros.h" |
| #include "ihevc_cabac_tables.h" |
| |
| #include "ihevcd_defs.h" |
| #include "ihevcd_function_selector.h" |
| #include "ihevcd_structs.h" |
| #include "ihevcd_error.h" |
| #include "ihevcd_bitstream.h" |
| |
| /*****************************************************************************/ |
| /* Function Prototypes */ |
| /*****************************************************************************/ |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Function used for bitstream structure initialization |
| * |
| * @par Description: |
| * Initialize bitstream structure elements |
| * |
| * @param[in] ps_bitstrm |
| * Pointer to bitstream structure |
| * |
| * @param[in] pu1_buf |
| * Pointer to bitstream data |
| * |
| * @param[in] u4_numbytes |
| * Number of bytes in bitstream |
| * |
| * @returns none |
| * |
| * @remarks |
| * Assumes pu1_buf is aligned to 4 bytes. If not aligned then all bitstream |
| * accesses will be unaligned and hence costlier. Since this is codec memory |
| * that holds emulation prevented data, assumption of aligned to 4 bytes is |
| * valid |
| * |
| ******************************************************************************* |
| */ |
| void ihevcd_bits_init(bitstrm_t *ps_bitstrm, |
| UWORD8 *pu1_buf, |
| UWORD32 u4_numbytes) |
| { |
| UWORD32 u4_cur_word; |
| UWORD32 u4_nxt_word; |
| UWORD32 u4_temp; |
| UWORD32 *pu4_buf; |
| |
| pu4_buf = (UWORD32 *)pu1_buf; |
| u4_temp = *pu4_buf++; |
| u4_cur_word = ITT_BIG_ENDIAN(u4_temp); |
| u4_temp = *pu4_buf++; |
| u4_nxt_word = ITT_BIG_ENDIAN(u4_temp); |
| |
| ps_bitstrm->u4_bit_ofst = 0; |
| ps_bitstrm->pu1_buf_base = pu1_buf; |
| ps_bitstrm->pu4_buf = pu4_buf; |
| ps_bitstrm->u4_cur_word = u4_cur_word; |
| ps_bitstrm->u4_nxt_word = u4_nxt_word; |
| |
| ps_bitstrm->pu1_buf_max = pu1_buf + u4_numbytes + 8; |
| |
| return; |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Flushes given number of bits. Bits consumed increases by this number |
| * |
| * @par Description: |
| * Increment bit offset by numbits. If bit offset increases beyond 32, then |
| * move nxt_word to cur_word, read next word32 to nxt_word after endian |
| * conversion |
| * |
| * @param[in] ps_bitstrm |
| * Pointer to bitstream structure |
| * |
| * @param[in] u4_numbits |
| * Number of bits to be flushed |
| * |
| * @returns None |
| * |
| * @remarks |
| * |
| * |
| ******************************************************************************* |
| */ |
| void ihevcd_bits_flush(bitstrm_t *ps_bitstrm, UWORD32 u4_numbits) |
| { |
| |
| BITS_FLUSH(ps_bitstrm->pu4_buf, |
| ps_bitstrm->u4_bit_ofst, |
| ps_bitstrm->u4_cur_word, |
| ps_bitstrm->u4_nxt_word, |
| u4_numbits); |
| |
| return; |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Flushes to next byte boundary.Bits consumed increases by this number |
| * |
| * @par Description: |
| * Compute number of bits remaining in the current byte then call |
| * ihevcd_bits_flush() bits with this number |
| * |
| * @param[in] ps_bitstrm |
| * Pointer to bitstream structure |
| * |
| * @returns None |
| * |
| * @remarks |
| * |
| * |
| ******************************************************************************* |
| */ |
| void ihevcd_bits_flush_to_byte_boundary(bitstrm_t *ps_bitstrm) |
| { |
| UWORD32 u4_numbits; |
| u4_numbits = (ps_bitstrm->u4_bit_ofst) & 7; |
| |
| u4_numbits = 8 - u4_numbits; |
| |
| BITS_FLUSH(ps_bitstrm->pu4_buf, |
| ps_bitstrm->u4_bit_ofst, |
| ps_bitstrm->u4_cur_word, |
| ps_bitstrm->u4_nxt_word, |
| u4_numbits); |
| |
| return; |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Seeks by given number of bits in the bitstream from current position |
| * |
| * @par Description: |
| * Add given number of bits to bitstream offset and update pu4_buf, cur_word and |
| * nxt_word accordingly |
| * |
| * @param[in] ps_bitstrm |
| * Pointer to bitstream structure |
| * |
| * @param[in] numbits |
| * Number of bits to seek |
| * |
| * @returns None |
| * |
| * @remarks |
| * Assumes emulation prevention has been done before and the buffer does not |
| * contain any emulation prevention bytes |
| * |
| ******************************************************************************* |
| */ |
| void ihevcd_bits_seek(bitstrm_t *ps_bitstrm, WORD32 numbits) |
| { |
| WORD32 val; |
| ASSERT(numbits >= -32); |
| ASSERT(numbits <= 32); |
| /* Check if Seeking backwards*/ |
| if(numbits < 0) |
| { |
| UWORD32 abs_numbits = -numbits; |
| if(ps_bitstrm->u4_bit_ofst >= abs_numbits) |
| { |
| /* If the current offset is greater than number of bits to seek back, |
| * then subtract abs_numbits from offset and return. |
| */ |
| ps_bitstrm->u4_bit_ofst -= abs_numbits; |
| return; |
| } |
| else |
| { |
| /* If the current offset is lesser than number of bits to seek back, |
| * then subtract abs_numbits from offset and add 32 and move cur_word to nxt_word |
| * and load cur_word appropriately and decrement pu4_buf |
| */ |
| ps_bitstrm->u4_bit_ofst -= abs_numbits; |
| ps_bitstrm->u4_bit_ofst += 32; |
| ps_bitstrm->pu4_buf--; |
| |
| val = *(ps_bitstrm->pu4_buf - 2); |
| ps_bitstrm->u4_nxt_word = ps_bitstrm->u4_cur_word; |
| ps_bitstrm->u4_cur_word = ITT_BIG_ENDIAN(val); |
| return; |
| } |
| } |
| else |
| { |
| /* Not supported/tested currently */ |
| ASSERT(1); |
| BITS_FLUSH(ps_bitstrm->pu4_buf, |
| ps_bitstrm->u4_bit_ofst, |
| ps_bitstrm->u4_cur_word, |
| ps_bitstrm->u4_nxt_word, |
| numbits); |
| |
| |
| } |
| return; |
| } |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Snoops for next numbits number of bits from the bitstream this does not |
| * update the bitstream offset and does not consume the bits |
| * |
| * @par Description: |
| * Extract required number of bits from cur_word & nxt_word return these |
| * bits |
| * |
| * @param[in] ps_bitstrm |
| * Pointer to bitstream structure |
| * |
| * @param[in] u4_numbits |
| * Number of bits |
| * |
| * @returns Next u4_numbits number of bits |
| * |
| * @remarks |
| * |
| * |
| ******************************************************************************* |
| */ |
| UWORD32 ihevcd_bits_nxt(bitstrm_t *ps_bitstrm, UWORD32 u4_numbits) |
| { |
| UWORD32 u4_bits_read; |
| |
| BITS_NXT(u4_bits_read, |
| ps_bitstrm->pu4_buf, |
| ps_bitstrm->u4_bit_ofst, |
| ps_bitstrm->u4_cur_word, |
| ps_bitstrm->u4_nxt_word, |
| u4_numbits); |
| return u4_bits_read; |
| } |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Snoops for next 32 bits from the bitstream this does not update the |
| * bitstream offset and does not consume the bits |
| * |
| * @par Description: |
| * Extract required number of bits from cur_word & nxt_word return these |
| * bits |
| * |
| * @param[in] ps_bitstrm |
| * Pointer to bitstream structure |
| * |
| * @param[in] u4_numbits |
| * Number of bits |
| * |
| * @returns Next 32 bits |
| * |
| * @remarks |
| * |
| * |
| ******************************************************************************* |
| */ |
| UWORD32 ihevcd_bits_nxt32(bitstrm_t *ps_bitstrm, UWORD32 u4_numbits) |
| { |
| UWORD32 u4_bits_read; |
| UNUSED(u4_numbits); |
| BITS_NXT32(u4_bits_read, |
| ps_bitstrm->pu4_buf, |
| ps_bitstrm->u4_bit_ofst, |
| ps_bitstrm->u4_cur_word, |
| ps_bitstrm->u4_nxt_word); |
| return u4_bits_read; |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Reads next numbits number of bits from the bitstream this updates the |
| * bitstream offset and consumes the bits |
| * |
| * @par Description: |
| * Extract required number of bits from cur_word & nxt_word return these |
| * bits |
| * |
| * @param[in] ps_bitstrm |
| * Pointer to bitstream structure |
| * |
| * @param[in] u4_numbits |
| * Number of bits |
| * |
| * @returns Bits read |
| * |
| * @remarks |
| * |
| * |
| ******************************************************************************* |
| */ |
| UWORD32 ihevcd_bits_get(bitstrm_t *ps_bitstrm, UWORD32 u4_numbits) |
| { |
| UWORD32 u4_bits_read; |
| |
| BITS_GET(u4_bits_read, |
| ps_bitstrm->pu4_buf, |
| ps_bitstrm->u4_bit_ofst, |
| ps_bitstrm->u4_cur_word, |
| ps_bitstrm->u4_nxt_word, |
| u4_numbits); |
| return u4_bits_read; |
| |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Returns the number of bits remaining in the bitstream |
| * |
| * @par Description: |
| * Compute number of bits remaining based on current pointer and buffer base |
| * and current offset. Since 8 bytes are read at the start into cur_word and |
| * nxt_word and are not consumed, 8 has to be subtracted |
| * |
| * @param[in] ps_bitstrm |
| * Pointer to bitstream structure |
| * |
| * @returns Total number of bits remaining |
| * |
| * @remarks |
| * |
| * |
| ******************************************************************************* |
| */ |
| UWORD32 ihevcd_bits_num_bits_remaining(bitstrm_t *ps_bitstrm) |
| { |
| UWORD32 u4_bits_consumed; |
| UWORD32 u4_size_in_bits; |
| |
| /* 8 bytes are read in cur_word and nxt_word at the start. Hence */ |
| /* subtract 8 bytes */ |
| u4_bits_consumed = (UWORD32)(((UWORD8 *)ps_bitstrm->pu4_buf - |
| (UWORD8 *)ps_bitstrm->pu1_buf_base - 8) << |
| 3) + ps_bitstrm->u4_bit_ofst; |
| |
| u4_size_in_bits = (UWORD32)(ps_bitstrm->pu1_buf_max - |
| ps_bitstrm->pu1_buf_base) - 8; |
| u4_size_in_bits <<= 3; |
| if(u4_size_in_bits > u4_bits_consumed) |
| { |
| return (u4_size_in_bits - u4_bits_consumed); |
| } |
| else |
| { |
| return 0; |
| } |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Returns the number of bits consumed in the bitstream |
| * |
| * @par Description: |
| * Compute number of bits consumed based on current pointer and buffer base |
| * and current offset. Since 8 bytes are read at the start into cur_word and |
| * nxt_word and are not consumed, 8 has to be subtracted |
| * |
| * @param[in] ps_bitstrm |
| * Pointer to bitstream structure |
| * |
| * @returns Total number of bits bits consumed |
| * |
| * @remarks |
| * |
| * |
| ******************************************************************************* |
| */ |
| UWORD32 ihevcd_bits_num_bits_consumed(bitstrm_t *ps_bitstrm) |
| { |
| UWORD32 u4_bits_consumed; |
| /* 8 bytes are read in cur_word and nxt_word at the start. Hence */ |
| /* subtract 8 bytes */ |
| |
| u4_bits_consumed = (UWORD32)(((UWORD8 *)ps_bitstrm->pu4_buf - |
| (UWORD8 *)ps_bitstrm->pu1_buf_base - 8) << |
| 3) + ps_bitstrm->u4_bit_ofst; |
| return u4_bits_consumed; |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Reads unsigned integer 0-th order exp-golomb-coded syntax element from |
| * the bitstream Section: 9.2 |
| * |
| * @par Description: |
| * Extract required number of bits from cur_word & nxt_word return these |
| * bits |
| * |
| * @param[in] ps_bitstrm |
| * Pointer to bitstream structure |
| * |
| * @returns UEV decoded syntax element |
| * |
| * @remarks |
| * |
| * |
| ******************************************************************************* |
| */ |
| UWORD32 ihevcd_uev(bitstrm_t *ps_bitstrm) |
| { |
| UWORD32 u4_bits_read; |
| UWORD32 u4_clz; |
| |
| |
| /***************************************************************/ |
| /* Find leading zeros in next 32 bits */ |
| /***************************************************************/ |
| BITS_NXT32(u4_bits_read, |
| ps_bitstrm->pu4_buf, |
| ps_bitstrm->u4_bit_ofst, |
| ps_bitstrm->u4_cur_word, |
| ps_bitstrm->u4_nxt_word); |
| |
| |
| u4_clz = CLZ(u4_bits_read); |
| |
| BITS_FLUSH(ps_bitstrm->pu4_buf, |
| ps_bitstrm->u4_bit_ofst, |
| ps_bitstrm->u4_cur_word, |
| ps_bitstrm->u4_nxt_word, |
| (u4_clz + 1)); |
| |
| u4_bits_read = 0; |
| if(u4_clz) |
| { |
| BITS_GET(u4_bits_read, |
| ps_bitstrm->pu4_buf, |
| ps_bitstrm->u4_bit_ofst, |
| ps_bitstrm->u4_cur_word, |
| ps_bitstrm->u4_nxt_word, |
| u4_clz); |
| } |
| return ((1 << u4_clz) + u4_bits_read - 1); |
| |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Reads signed integer 0-th order exp-golomb-coded syntax element from the |
| * bitstream. Function similar to get_uev Section: 9.2.1 |
| * |
| * @par Description: |
| * Extract required number of bits from cur_word & nxt_word return these |
| * bits |
| * |
| * @param[in] ps_bitstrm |
| * Pointer to bitstream structure |
| * |
| * @returns UEV decoded syntax element |
| * |
| * @remarks |
| * |
| * |
| ******************************************************************************* |
| */ |
| WORD32 ihevcd_sev(bitstrm_t *ps_bitstrm) |
| { |
| UWORD32 u4_bits_read; |
| UWORD32 u4_clz; |
| UWORD32 u4_abs_val; |
| |
| |
| /***************************************************************/ |
| /* Find leading zeros in next 32 bits */ |
| /***************************************************************/ |
| BITS_NXT32(u4_bits_read, |
| ps_bitstrm->pu4_buf, |
| ps_bitstrm->u4_bit_ofst, |
| ps_bitstrm->u4_cur_word, |
| ps_bitstrm->u4_nxt_word); |
| |
| |
| u4_clz = CLZ(u4_bits_read); |
| |
| BITS_FLUSH(ps_bitstrm->pu4_buf, |
| ps_bitstrm->u4_bit_ofst, |
| ps_bitstrm->u4_cur_word, |
| ps_bitstrm->u4_nxt_word, |
| (u4_clz + 1)); |
| |
| u4_bits_read = 0; |
| if(u4_clz) |
| { |
| BITS_GET(u4_bits_read, |
| ps_bitstrm->pu4_buf, |
| ps_bitstrm->u4_bit_ofst, |
| ps_bitstrm->u4_cur_word, |
| ps_bitstrm->u4_nxt_word, |
| u4_clz); |
| } |
| u4_abs_val = ((1 << u4_clz) + u4_bits_read) >> 1; |
| if(u4_bits_read & 0x1) |
| return (-(WORD32)u4_abs_val); |
| else |
| return (u4_abs_val); |
| } |
| |
| |
| |
| |
| |
| |