From ef9d577bafbda8d489e66524c088054c48c1eb86 Mon Sep 17 00:00:00 2001 From: Herman Chen Date: Wed, 17 Apr 2019 11:13:19 +0800 Subject: [PATCH] [h264e]: Separate h264 encoder stream writing Separate h264 encoder stream writing to a new module. Change-Id: Ibf55a20ac73e4eb2e3a3d744573eded3ebd92662 Signed-off-by: Herman Chen --- mpp/hal/common/h264/CMakeLists.txt | 1 + mpp/hal/common/h264/h264e_stream.c | 248 +++++++++++++++++++++++++++ mpp/hal/common/h264/h264e_stream.h | 53 ++++++ mpp/hal/vpu/h264e/hal_h264e_header.c | 229 +------------------------ mpp/hal/vpu/h264e/hal_h264e_vepu.h | 15 +- 5 files changed, 304 insertions(+), 242 deletions(-) create mode 100644 mpp/hal/common/h264/h264e_stream.c create mode 100644 mpp/hal/common/h264/h264e_stream.h diff --git a/mpp/hal/common/h264/CMakeLists.txt b/mpp/hal/common/h264/CMakeLists.txt index 990dbecd..b99d9fb7 100644 --- a/mpp/hal/common/h264/CMakeLists.txt +++ b/mpp/hal/common/h264/CMakeLists.txt @@ -10,6 +10,7 @@ set(HAL_H264E_HDR # hal h264 encoder sourse set(HAL_H264E_SRC + h264e_stream.c hal_h264e_com.c hal_h264e_api.c ) diff --git a/mpp/hal/common/h264/h264e_stream.c b/mpp/hal/common/h264/h264e_stream.c new file mode 100644 index 00000000..7192798a --- /dev/null +++ b/mpp/hal/common/h264/h264e_stream.c @@ -0,0 +1,248 @@ +/* + * Copyright 2015 - 2017 Rockchip Electronics Co. LTD + * + * 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. + */ + +#include +#include + +#include "mpp_log.h" +#include "mpp_mem.h" + +#include "h264e_stream.h" + +void hal_h264e_vpu_swap_endian(RK_U32 *buf, RK_S32 size_bytes) +{ + RK_U32 i = 0; + RK_S32 words = size_bytes / 4; + RK_U32 val, val2, tmp, tmp2; + + mpp_assert((size_bytes % 8) == 0); + + while (words > 0) { + val = buf[i]; + tmp = 0; + + tmp |= (val & 0xFF) << 24; + tmp |= (val & 0xFF00) << 8; + tmp |= (val & 0xFF0000) >> 8; + tmp |= (val & 0xFF000000) >> 24; + { + val2 = buf[i + 1]; + tmp2 = 0; + + tmp2 |= (val2 & 0xFF) << 24; + tmp2 |= (val2 & 0xFF00) << 8; + tmp2 |= (val2 & 0xFF0000) >> 8; + tmp2 |= (val2 & 0xFF000000) >> 24; + + buf[i] = tmp2; + words--; + i++; + } + buf[i] = tmp; + words--; + i++; + } +} + +MPP_RET hal_h264e_vpu_stream_buffer_status(H264eVpuStream *stream) +{ + if (stream->byte_cnt + 5 > stream->size) { + stream->overflow = 1; + return MPP_NOK; + } + + return MPP_OK; +} + +MPP_RET hal_h264e_vpu_stream_buffer_reset(H264eVpuStream *strmbuf) +{ + strmbuf->stream = strmbuf->buffer; + strmbuf->byte_cnt = 0; + strmbuf->overflow = 0; + strmbuf->byte_buffer = 0; + strmbuf->buffered_bits = 0; + strmbuf->zero_bytes = 0; + strmbuf->emul_cnt = 0; + + return MPP_OK; +} + +MPP_RET hal_h264e_vpu_stream_buffer_init(H264eVpuStream *strmbuf, RK_S32 size) +{ + strmbuf->buffer = mpp_calloc(RK_U8, size); + + if (strmbuf->buffer == NULL) { + mpp_err("allocate stream buffer failed\n"); + return MPP_NOK; + } + strmbuf->stream = strmbuf->buffer; + strmbuf->size = size; + strmbuf->byte_cnt = 0; + strmbuf->overflow = 0; + strmbuf->byte_buffer = 0; + strmbuf->buffered_bits = 0; + strmbuf->zero_bytes = 0; + strmbuf->emul_cnt = 0; + + if (MPP_OK != hal_h264e_vpu_stream_buffer_status(strmbuf)) { + mpp_err("stream buffer is overflow, while init"); + return MPP_NOK; + } + + return MPP_OK; +} + +void hal_h264e_vpu_stream_put_bits(H264eVpuStream *buffer, + RK_S32 value, RK_S32 number, + const char *name) +{ + RK_S32 bits; + RK_U32 byte_buffer = buffer->byte_buffer; + RK_U8*stream = buffer->stream; + (void)name; + + if (hal_h264e_vpu_stream_buffer_status(buffer) != 0) + return; + + mpp_assert(value < (1 << number)); //opposite to 'BUG_ON' in kernel + mpp_assert(number < 25); + + bits = number + buffer->buffered_bits; + value <<= (32 - bits); + byte_buffer = byte_buffer | value; + + while (bits > 7) { + *stream = (RK_U8)(byte_buffer >> 24); + + bits -= 8; + byte_buffer <<= 8; + stream++; + buffer->byte_cnt++; + } + + buffer->byte_buffer = byte_buffer; + buffer->buffered_bits = (RK_U8)bits; + buffer->stream = stream; + + return; +} + +void hal_h264e_vpu_stream_put_bits_with_detect(H264eVpuStream * buffer, + RK_S32 value, RK_S32 number, + const char *name) +{ + RK_S32 bits; + RK_U8 *stream = buffer->stream; + RK_U32 byte_buffer = buffer->byte_buffer; + (void)name; + + if (value) { + mpp_assert(value < (1 << number)); + mpp_assert(number < 25); + } + bits = number + buffer->buffered_bits; + + byte_buffer = byte_buffer | ((RK_U32) value << (32 - bits)); + + while (bits > 7) { + RK_S32 zeroBytes = buffer->zero_bytes; + RK_S32 byteCnt = buffer->byte_cnt; + + if (hal_h264e_vpu_stream_buffer_status(buffer) != MPP_OK) + return; + + *stream = (RK_U8) (byte_buffer >> 24); + byteCnt++; + + if ((zeroBytes == 2) && (*stream < 4)) { + *stream++ = 3; + *stream = (RK_U8) (byte_buffer >> 24); + byteCnt++; + zeroBytes = 0; + buffer->emul_cnt++; + } + + if (*stream == 0) + zeroBytes++; + else + zeroBytes = 0; + + bits -= 8; + byte_buffer <<= 8; + stream++; + buffer->zero_bytes = zeroBytes; + buffer->byte_cnt = byteCnt; + buffer->stream = stream; + } + + buffer->buffered_bits = (RK_U8) bits; + buffer->byte_buffer = byte_buffer; +} + +void hal_h264e_vpu_rbsp_trailing_bits(H264eVpuStream * stream) +{ + hal_h264e_vpu_stream_put_bits_with_detect(stream, 1, 1, + "rbsp_stop_one_bit"); + if (stream->buffered_bits > 0) + hal_h264e_vpu_stream_put_bits_with_detect(stream, 0, + 8 - stream->buffered_bits, + "bsp_alignment_zero_bit(s)"); +} + +void hal_h264e_vpu_write_ue(H264eVpuStream *fifo, RK_U32 val, const char *name) +{ + RK_U32 num_bits = 0; + + val++; + while (val >> ++num_bits); + + if (num_bits > 12) { + RK_U32 tmp; + + tmp = num_bits - 1; + + if (tmp > 24) { + tmp -= 24; + hal_h264e_vpu_stream_put_bits_with_detect(fifo, 0, 24, name); + } + + hal_h264e_vpu_stream_put_bits_with_detect(fifo, 0, tmp, name); + + if (num_bits > 24) { + num_bits -= 24; + hal_h264e_vpu_stream_put_bits_with_detect(fifo, val >> num_bits, + 24, name); + val = val >> num_bits; + } + + hal_h264e_vpu_stream_put_bits_with_detect(fifo, val, num_bits, name); + } else { + hal_h264e_vpu_stream_put_bits_with_detect(fifo, val, + 2 * num_bits - 1, name); + } +} + +void hal_h264e_vpu_write_se(H264eVpuStream *fifo, RK_S32 val, const char *name) +{ + RK_U32 tmp; + + if (val > 0) + tmp = (RK_U32)(2 * val - 1); + else + tmp = (RK_U32)(-2 * val); + + hal_h264e_vpu_write_ue(fifo, tmp, name); +} diff --git a/mpp/hal/common/h264/h264e_stream.h b/mpp/hal/common/h264/h264e_stream.h new file mode 100644 index 00000000..5b4aa643 --- /dev/null +++ b/mpp/hal/common/h264/h264e_stream.h @@ -0,0 +1,53 @@ +/* + * Copyright 2015 - 2017 Rockchip Electronics Co. LTD + * + * 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. + */ + +#ifndef __H264E_PUTBIT_H__ +#define __H264E_PUTBIT_H__ + +#include "rk_type.h" +#include "mpp_err.h" + +/* struct for assemble bitstream */ +typedef struct H264eVpuStream_t { + RK_U8 *buffer; /* point to first byte of stream */ + RK_U8 *stream; /* Pointer to next byte of stream */ + RK_U32 size; /* Byte size of stream buffer */ + RK_U32 byte_cnt; /* Byte counter */ + RK_U32 bit_cnt; /* Bit counter */ + RK_U32 byte_buffer; /* Byte buffer */ + RK_U32 buffered_bits; /* Amount of bits in byte buffer, [0-7] */ + RK_U32 zero_bytes; /* Amount of consecutive zero bytes */ + RK_S32 overflow; /* This will signal a buffer overflow */ + RK_U32 emul_cnt; /* Counter for emulation_3_byte, needed in SEI */ +} H264eVpuStream; + +void hal_h264e_vpu_swap_endian(RK_U32 *buf, RK_S32 size_bytes); +MPP_RET hal_h264e_vpu_stream_buffer_status(H264eVpuStream *stream); +MPP_RET hal_h264e_vpu_stream_buffer_reset(H264eVpuStream *strmbuf); +MPP_RET hal_h264e_vpu_stream_buffer_init(H264eVpuStream *strmbuf, RK_S32 size); +void hal_h264e_vpu_stream_put_bits(H264eVpuStream *buffer, + RK_S32 value, RK_S32 number, + const char *name); +void hal_h264e_vpu_stream_put_bits_with_detect(H264eVpuStream * buffer, + RK_S32 value, RK_S32 number, + const char *name); +void hal_h264e_vpu_rbsp_trailing_bits(H264eVpuStream * stream); +void hal_h264e_vpu_write_ue(H264eVpuStream *fifo, RK_U32 val, const char *name); +void hal_h264e_vpu_write_se(H264eVpuStream *fifo, RK_S32 val, const char *name); + +RK_S32 exp_golomb_signed(RK_S32 val); + +#endif /* __H264E_PUTBIT_H__ */ diff --git a/mpp/hal/vpu/h264e/hal_h264e_header.c b/mpp/hal/vpu/h264e/hal_h264e_header.c index 189c5a89..f627082b 100644 --- a/mpp/hal/vpu/h264e/hal_h264e_header.c +++ b/mpp/hal/vpu/h264e/hal_h264e_header.c @@ -27,40 +27,7 @@ #include "hal_h264e_vpu_tbl.h" #include "hal_h264e_header.h" -static void hal_h264e_vpu_swap_endian(RK_U32 *buf, RK_S32 size_bytes) -{ - RK_U32 i = 0; - RK_S32 words = size_bytes / 4; - RK_U32 val, val2, tmp, tmp2; - - mpp_assert((size_bytes % 8) == 0); - - while (words > 0) { - val = buf[i]; - tmp = 0; - - tmp |= (val & 0xFF) << 24; - tmp |= (val & 0xFF00) << 8; - tmp |= (val & 0xFF0000) >> 8; - tmp |= (val & 0xFF000000) >> 24; - { - val2 = buf[i + 1]; - tmp2 = 0; - - tmp2 |= (val2 & 0xFF) << 24; - tmp2 |= (val2 & 0xFF00) << 8; - tmp2 |= (val2 & 0xFF0000) >> 8; - tmp2 |= (val2 & 0xFF000000) >> 24; - - buf[i] = tmp2; - words--; - i++; - } - buf[i] = tmp; - words--; - i++; - } -} +#include "h264e_stream.h" static void hal_h264e_vpu_write_cabac_table(MppBuffer hw_cabac_tab_buf, RK_S32 cabac_init_idc) @@ -103,200 +70,6 @@ static void hal_h264e_vpu_write_cabac_table(MppBuffer hw_cabac_tab_buf, h264e_hal_leave(); } -static MPP_RET hal_h264e_vpu_stream_buffer_status(H264eVpuStream *stream) -{ - if (stream->byte_cnt + 5 > stream->size) { - stream->overflow = 1; - return MPP_NOK; - } - - return MPP_OK; -} - -static MPP_RET hal_h264e_vpu_stream_buffer_reset(H264eVpuStream *strmbuf) -{ - strmbuf->stream = strmbuf->buffer; - strmbuf->byte_cnt = 0; - strmbuf->overflow = 0; - strmbuf->byte_buffer = 0; - strmbuf->buffered_bits = 0; - strmbuf->zero_bytes = 0; - strmbuf->emul_cnt = 0; - - return MPP_OK; -} - -static MPP_RET hal_h264e_vpu_stream_buffer_init(H264eVpuStream *strmbuf, - RK_S32 size) -{ - strmbuf->buffer = mpp_calloc(RK_U8, size); - - if (strmbuf->buffer == NULL) { - mpp_err("allocate stream buffer failed\n"); - return MPP_NOK; - } - strmbuf->stream = strmbuf->buffer; - strmbuf->size = size; - strmbuf->byte_cnt = 0; - strmbuf->overflow = 0; - strmbuf->byte_buffer = 0; - strmbuf->buffered_bits = 0; - strmbuf->zero_bytes = 0; - strmbuf->emul_cnt = 0; - - if (MPP_OK != hal_h264e_vpu_stream_buffer_status(strmbuf)) { - mpp_err("stream buffer is overflow, while init"); - return MPP_NOK; - } - - return MPP_OK; -} - -static void hal_h264e_vpu_stream_put_bits(H264eVpuStream *buffer, - RK_S32 value, RK_S32 number, - const char *name) -{ - RK_S32 bits; - RK_U32 byte_buffer = buffer->byte_buffer; - RK_U8*stream = buffer->stream; - (void)name; - - if (hal_h264e_vpu_stream_buffer_status(buffer) != 0) - return; - - mpp_assert(value < (1 << number)); //opposite to 'BUG_ON' in kernel - mpp_assert(number < 25); - - bits = number + buffer->buffered_bits; - value <<= (32 - bits); - byte_buffer = byte_buffer | value; - - while (bits > 7) { - *stream = (RK_U8)(byte_buffer >> 24); - - bits -= 8; - byte_buffer <<= 8; - stream++; - buffer->byte_cnt++; - } - - buffer->byte_buffer = byte_buffer; - buffer->buffered_bits = (RK_U8)bits; - buffer->stream = stream; - - return; -} - -static void -hal_h264e_vpu_stream_put_bits_with_detect(H264eVpuStream * buffer, - RK_S32 value, RK_S32 number, - const char *name) -{ - RK_S32 bits; - RK_U8 *stream = buffer->stream; - RK_U32 byte_buffer = buffer->byte_buffer; - (void)name; - - if (value) { - mpp_assert(value < (1 << number)); - mpp_assert(number < 25); - } - bits = number + buffer->buffered_bits; - - byte_buffer = byte_buffer | ((RK_U32) value << (32 - bits)); - - while (bits > 7) { - RK_S32 zeroBytes = buffer->zero_bytes; - RK_S32 byteCnt = buffer->byte_cnt; - - if (hal_h264e_vpu_stream_buffer_status(buffer) != MPP_OK) - return; - - *stream = (RK_U8) (byte_buffer >> 24); - byteCnt++; - - if ((zeroBytes == 2) && (*stream < 4)) { - *stream++ = 3; - *stream = (RK_U8) (byte_buffer >> 24); - byteCnt++; - zeroBytes = 0; - buffer->emul_cnt++; - } - - if (*stream == 0) - zeroBytes++; - else - zeroBytes = 0; - - bits -= 8; - byte_buffer <<= 8; - stream++; - buffer->zero_bytes = zeroBytes; - buffer->byte_cnt = byteCnt; - buffer->stream = stream; - } - - buffer->buffered_bits = (RK_U8) bits; - buffer->byte_buffer = byte_buffer; -} - -static void hal_h264e_vpu_rbsp_trailing_bits(H264eVpuStream * stream) -{ - hal_h264e_vpu_stream_put_bits_with_detect(stream, 1, 1, - "rbsp_stop_one_bit"); - if (stream->buffered_bits > 0) - hal_h264e_vpu_stream_put_bits_with_detect(stream, 0, - 8 - stream->buffered_bits, - "bsp_alignment_zero_bit(s)"); -} - -static void hal_h264e_vpu_write_ue(H264eVpuStream *fifo, RK_U32 val, - const char *name) -{ - RK_U32 num_bits = 0; - - val++; - while (val >> ++num_bits); - - if (num_bits > 12) { - RK_U32 tmp; - - tmp = num_bits - 1; - - if (tmp > 24) { - tmp -= 24; - hal_h264e_vpu_stream_put_bits_with_detect(fifo, 0, 24, name); - } - - hal_h264e_vpu_stream_put_bits_with_detect(fifo, 0, tmp, name); - - if (num_bits > 24) { - num_bits -= 24; - hal_h264e_vpu_stream_put_bits_with_detect(fifo, val >> num_bits, - 24, name); - val = val >> num_bits; - } - - hal_h264e_vpu_stream_put_bits_with_detect(fifo, val, num_bits, name); - } else { - hal_h264e_vpu_stream_put_bits_with_detect(fifo, val, - 2 * num_bits - 1, name); - } -} - -static void hal_h264e_vpu_write_se(H264eVpuStream *fifo, - RK_S32 val, const char *name) -{ - RK_U32 tmp; - - if (val > 0) - tmp = (RK_U32)(2 * val - 1); - else - tmp = (RK_U32)(-2 * val); - - hal_h264e_vpu_write_ue(fifo, tmp, name); -} - static MPP_RET h264e_vpu_nal_start(H264eVpuStream * stream, RK_S32 nalRefIdc, H264eNalUnitType nalUnitType) diff --git a/mpp/hal/vpu/h264e/hal_h264e_vepu.h b/mpp/hal/vpu/h264e/hal_h264e_vepu.h index edd5ca5a..7f84c3ab 100644 --- a/mpp/hal/vpu/h264e/hal_h264e_vepu.h +++ b/mpp/hal/vpu/h264e/hal_h264e_vepu.h @@ -18,6 +18,7 @@ #define __HAL_H264E_VEPU_H__ #include "hal_h264e_com.h" +#include "h264e_stream.h" #define HAL_VPU_H264E_DBG_FUNCTION (0x00000001) #define HAL_VPU_H264E_DBG_QP (0x00000010) @@ -41,20 +42,6 @@ typedef enum H264eVpuFrameType_t { H264E_VPU_FRAME_I = 1 } H264eVpuFrameType; -/* struct for assemble bitstream */ -typedef struct H264eVpuStream_t { - RK_U8 *buffer; /* point to first byte of stream */ - RK_U8 *stream; /* Pointer to next byte of stream */ - RK_U32 size; /* Byte size of stream buffer */ - RK_U32 byte_cnt; /* Byte counter */ - RK_U32 bit_cnt; /* Bit counter */ - RK_U32 byte_buffer; /* Byte buffer */ - RK_U32 buffered_bits; /* Amount of bits in byte buffer, [0-7] */ - RK_U32 zero_bytes; /* Amount of consecutive zero bytes */ - RK_S32 overflow; /* This will signal a buffer overflow */ - RK_U32 emul_cnt; /* Counter for emulation_3_byte, needed in SEI */ -} H264eVpuStream; - typedef struct H264eVpuExtraInfo_t { H264eVpuStream sps_stream; H264eVpuStream pps_stream;