mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-10-12 12:30:04 +08:00
[h264e]: refactor hal_h264e_rkv.c
*dpb.c : dpb management *stream.c: encapsulation of stream *utils.c : functions of h.264 encoder such as osd, roi *nal.c : NALs such as sps, pps, sei Change-Id: I7b947795b94c2f02fd5fe0e7ddd39f45d6c22214 Signed-off-by: timkingh.huang <timkingh.huang@rock-chips.com>
This commit is contained in:
@@ -39,25 +39,6 @@ static const RK_S32 h264e_vpu_csp_idx_map[H264E_VPU_CSP_BUTT] = {
|
||||
H264E_CSP2_RGB, H264E_CSP2_BGR,
|
||||
};
|
||||
|
||||
static const RK_U8 h264e_ue_size_tab[256] = {
|
||||
1, 1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
};
|
||||
|
||||
/* default quant matrices */
|
||||
static const RK_U8 h264e_cqm_jvt4i[16] = {
|
||||
6, 13, 20, 28,
|
||||
|
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2015 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 __HAL_H264E_API_H__
|
||||
#define __HAL_H264E_API_H__
|
||||
|
||||
|
@@ -5,11 +5,19 @@ include_directories(../../common/h264/)
|
||||
# hal h264 header
|
||||
set(HAL_H264E_HDR
|
||||
hal_h264e_rkv.h
|
||||
hal_h264e_rkv_dpb.h
|
||||
hal_h264e_rkv_stream.h
|
||||
hal_h264e_rkv_utils.h
|
||||
hal_h264e_rkv_nal.h
|
||||
)
|
||||
|
||||
# hal h264 encoder sourse
|
||||
set(HAL_H264E_SRC
|
||||
hal_h264e_rkv.c
|
||||
hal_h264e_rkv_dpb.c
|
||||
hal_h264e_rkv_stream.c
|
||||
hal_h264e_rkv_utils.c
|
||||
hal_h264e_rkv_nal.c
|
||||
)
|
||||
|
||||
add_library(hal_h264e_rkv STATIC
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -14,12 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __HAL_H264E_RK_H__
|
||||
#define __HAL_H264E_RK_H__
|
||||
#ifndef __HAL_H264E_RKV_H__
|
||||
#define __HAL_H264E_RKV_H__
|
||||
|
||||
#include "mpp_buffer.h"
|
||||
#include "mpp_hal.h"
|
||||
#include "hal_task.h"
|
||||
#include "hal_h264e_com.h"
|
||||
|
||||
#define RKV_H264E_ENC_MODE 1 //2/3
|
||||
#define RKV_H264E_LINKTABLE_FRAME_NUM 1 //2
|
||||
@@ -30,8 +31,6 @@
|
||||
#define RKV_H264E_LINKTABLE_EACH_NUM 1
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
#define RKV_H264E_LINKTABLE_MAX_SIZE 256
|
||||
#define RKV_H264E_ADD_RESERVE_REGS 1
|
||||
|
||||
@@ -45,8 +44,6 @@
|
||||
#define RKV_H264E_INT_BUS_READ_ERROR 0x00000080
|
||||
#define RKV_H264E_INT_TIMEOUT_ERROR 0x00000100
|
||||
|
||||
#define RKV_H264E_REF_MAX 16
|
||||
|
||||
typedef enum H264eRkvFrameType_t {
|
||||
H264E_RKV_FRAME_P = 0,
|
||||
H264E_RKV_FRAME_B = 1,
|
||||
@@ -63,13 +60,6 @@ typedef enum h264e_hal_rkv_buf_grp_t {
|
||||
H264E_HAL_RKV_BUF_GRP_BUTT
|
||||
} h264e_hal_rkv_buf_grp;
|
||||
|
||||
typedef struct h264e_hal_rkv_roi_cfg_t {
|
||||
RK_U8 qp_y : 6;
|
||||
RK_U8 set_qp_y_en : 1;
|
||||
RK_U8 forbit_inter : 1;
|
||||
} h264e_hal_rkv_roi_cfg;
|
||||
|
||||
|
||||
typedef struct h264e_hal_rkv_buffers_t {
|
||||
MppBufferGroup hw_buf_grp[H264E_HAL_RKV_BUF_GRP_BUTT];
|
||||
|
||||
@@ -80,143 +70,6 @@ typedef struct h264e_hal_rkv_buffers_t {
|
||||
MppBuffer hw_rec_buf[H264E_NUM_REFS + 1]; //extra 1 frame for current recon
|
||||
} h264e_hal_rkv_buffers;
|
||||
|
||||
typedef enum H264eRkvNalIdx_t {
|
||||
H264E_RKV_NAL_IDX_SPS,
|
||||
H264E_RKV_NAL_IDX_PPS,
|
||||
H264E_RKV_NAL_IDX_SEI,
|
||||
H264E_RKV_NAL_IDX_BUTT,
|
||||
} H264eRkvNalIdx;
|
||||
|
||||
typedef struct H264eRkvNal_t {
|
||||
RK_S32 i_ref_idc; /* nal_priority_e */
|
||||
RK_S32 i_type; /* nal_unit_type_e */
|
||||
RK_S32 b_long_startcode;
|
||||
RK_S32 i_first_mb; /* If this NAL is a slice, the index of the first MB in the slice. */
|
||||
RK_S32 i_last_mb; /* If this NAL is a slice, the index of the last MB in the slice. */
|
||||
|
||||
/* Size of payload (including any padding) in bytes. */
|
||||
RK_S32 i_payload;
|
||||
/* If param->b_annexb is set, Annex-B bytestream with startcode.
|
||||
* Otherwise, startcode is replaced with a 4-byte size.
|
||||
* This size is the size used in mp4/similar muxing; it is equal to i_payload-4 */
|
||||
RK_U8 *p_payload;
|
||||
|
||||
/* Size of padding in bytes. */
|
||||
RK_S32 i_padding;
|
||||
RK_S32 sh_head_len;
|
||||
} H264eRkvNal;
|
||||
|
||||
typedef struct H264eRkvDumpFiles_t {
|
||||
FILE *fp_mpp_syntax_in;
|
||||
FILE *fp_mpp_reg_in;
|
||||
FILE *fp_mpp_reg_out;
|
||||
FILE *fp_mpp_strm_out;
|
||||
FILE *fp_mpp_feedback;
|
||||
FILE *fp_mpp_extra_ino_cfg;
|
||||
} H264eRkvDumpFiles;
|
||||
|
||||
typedef struct H264eRkvStream_t {
|
||||
RK_U8 *p_start;
|
||||
RK_U8 *p;
|
||||
//RK_U8 *p_end;
|
||||
|
||||
RK_U32 cur_bits;
|
||||
RK_S32 i_left; /* i_count number of available bits */
|
||||
|
||||
//add buf pointer
|
||||
RK_U8 *buf;
|
||||
RK_U8 *buf_plus8;
|
||||
RK_U32 count_bit; // only for debug
|
||||
} H264eRkvStream;
|
||||
|
||||
typedef struct H264eRkvExtraInfo_t {
|
||||
RK_S32 nal_num;
|
||||
H264eRkvNal nal[H264E_RKV_NAL_IDX_BUTT];
|
||||
RK_U8 *nal_buf;
|
||||
RK_U8 *sei_buf;
|
||||
RK_U32 sei_change_flg;
|
||||
H264eRkvStream stream;
|
||||
H264eSps sps;
|
||||
H264ePps pps;
|
||||
H264eSei sei;
|
||||
} H264eRkvExtraInfo;
|
||||
|
||||
|
||||
typedef struct H264eRkvFrame_t {
|
||||
MppBuffer hw_buf;
|
||||
RK_S32 hw_buf_used;
|
||||
RK_S32 i_frame_cnt; /* Presentation frame number */
|
||||
RK_S32 i_frame_num; /* 7.4.3 frame_num */
|
||||
RK_S32 long_term_flag;
|
||||
RK_S32 reorder_longterm_flag;
|
||||
RK_S32 i_poc;
|
||||
RK_S32 i_delta_poc[2];
|
||||
RK_S32 i_frame_type;
|
||||
RK_S64 i_pts;
|
||||
RK_S64 i_dts;
|
||||
RK_S32 b_kept_as_ref;
|
||||
RK_S32 b_keyframe;
|
||||
RK_S32 b_corrupt;
|
||||
RK_S32 i_reference_count;
|
||||
} H264eRkvFrame;
|
||||
|
||||
|
||||
typedef struct H264eRkvDpbCtx_t {
|
||||
//H264eRkvFrame *fenc;
|
||||
H264eRkvFrame *fdec;
|
||||
H264eRkvFrame *fref[2][RKV_H264E_REF_MAX + 1];
|
||||
H264eRkvFrame *fref_nearest[2]; //Used for RC
|
||||
struct {
|
||||
/* Unused frames: 0 = fenc, 1 = fdec */
|
||||
H264eRkvFrame **unused;
|
||||
|
||||
/* frames used for reference + sentinels */
|
||||
H264eRkvFrame *reference[RKV_H264E_REF_MAX + 1]; //TODO: remove later
|
||||
|
||||
|
||||
RK_S32 i_last_keyframe; /* Frame number of the last keyframe */
|
||||
RK_S32 i_last_idr; /* Frame number of the last IDR (not RP)*/
|
||||
//RK_S64 i_largest_pts;
|
||||
//RK_S64 i_second_largest_pts;
|
||||
} frames;
|
||||
|
||||
H264eRkvFrame frame_buf[RKV_H264E_REF_MAX + 1];
|
||||
|
||||
RK_S32 i_ref[2];
|
||||
RK_U32 i_nal_type;
|
||||
RK_U32 i_nal_ref_idc;
|
||||
|
||||
RK_S32 i_frame_cnt; /* Presentation frame number */
|
||||
RK_S32 i_frame_num; /* 7.4.3 frame_num */
|
||||
|
||||
//move from slice header below
|
||||
RK_S32 i_slice_type;
|
||||
RK_S32 i_idr_pic_id; /* -1 if nal_type != 5 */
|
||||
RK_S32 i_tmp_idr_pic_id;
|
||||
//RK_S32 i_poc;
|
||||
//RK_S32 i_delta_poc[2];
|
||||
//RK_S32 i_redundant_pic_cnt;
|
||||
RK_S32 i_max_ref0;
|
||||
RK_S32 i_max_ref1;
|
||||
RK_S32 b_ref_pic_list_reordering[2];
|
||||
struct {
|
||||
RK_S32 idc;
|
||||
RK_S32 arg;
|
||||
} ref_pic_list_order[2][RKV_H264E_REF_MAX];
|
||||
|
||||
RK_S32 i_mmco_remove_from_end;
|
||||
RK_S32 i_mmco_command_count;
|
||||
struct { /* struct for future expansion */
|
||||
RK_S32 i_difference_of_pic_nums;
|
||||
RK_S32 i_poc;
|
||||
RK_S32 memory_management_control_operation;
|
||||
} mmco[RKV_H264E_REF_MAX];
|
||||
|
||||
RK_S32 i_long_term_reference_flag;
|
||||
} H264eRkvDpbCtx;
|
||||
|
||||
/* cmodel version r2893 */
|
||||
|
||||
typedef struct H264eOsdCfg_t {
|
||||
RK_U32 lt_pos_x : 8;
|
||||
RK_U32 lt_pos_y : 8;
|
||||
@@ -438,55 +291,55 @@ typedef struct H264eRkvRegSet_t {
|
||||
} swreg23; //SRC_STRID
|
||||
|
||||
/* reg[070] */
|
||||
RK_U32 swreg24_adr_srcy; //swreg24
|
||||
RK_U32 swreg24_adr_srcy;
|
||||
|
||||
/* reg[071] */
|
||||
RK_U32 swreg25_adr_srcu; //swreg25
|
||||
RK_U32 swreg25_adr_srcu;
|
||||
|
||||
/* reg[072] */
|
||||
RK_U32 swreg26_adr_srcv; //swreg26
|
||||
RK_U32 swreg26_adr_srcv;
|
||||
|
||||
/* reg[073] */
|
||||
RK_U32 swreg27_fltw_addr; //swreg27
|
||||
RK_U32 swreg27_fltw_addr;
|
||||
|
||||
/* reg[074] */
|
||||
RK_U32 swreg28_fltr_addr; //swreg28
|
||||
RK_U32 swreg28_fltr_addr;
|
||||
|
||||
/* reg[075] */
|
||||
RK_U32 swreg29_ctuc_addr; //swreg29
|
||||
RK_U32 swreg29_ctuc_addr;
|
||||
|
||||
/* reg[076] */
|
||||
RK_U32 swreg30_rfpw_addr; //swreg30
|
||||
RK_U32 swreg30_rfpw_addr;
|
||||
|
||||
/* reg[077] */
|
||||
RK_U32 swreg31_rfpr_addr; //swreg31
|
||||
RK_U32 swreg31_rfpr_addr;
|
||||
|
||||
/* reg[078] */
|
||||
RK_U32 swreg32_cmvw_addr; //swreg32
|
||||
RK_U32 swreg32_cmvw_addr;
|
||||
|
||||
/* reg[079] */
|
||||
RK_U32 swreg33_cmvr_addr; //swreg33
|
||||
RK_U32 swreg33_cmvr_addr;
|
||||
|
||||
/* reg[080] */
|
||||
RK_U32 swreg34_dspw_addr; //swreg34
|
||||
RK_U32 swreg34_dspw_addr;
|
||||
|
||||
/* reg[081] */
|
||||
RK_U32 swreg35_dspr_addr; //swreg35
|
||||
RK_U32 swreg35_dspr_addr;
|
||||
|
||||
/* reg[082] */
|
||||
RK_U32 swreg36_meiw_addr; //swreg36
|
||||
RK_U32 swreg36_meiw_addr;
|
||||
|
||||
/* reg[083] */
|
||||
RK_U32 swreg37_bsbt_addr; //swreg37
|
||||
RK_U32 swreg37_bsbt_addr;
|
||||
|
||||
/* reg[084] */
|
||||
RK_U32 swreg38_bsbb_addr; //swreg38
|
||||
RK_U32 swreg38_bsbb_addr;
|
||||
|
||||
/* reg[085] */
|
||||
RK_U32 swreg39_bsbr_addr; //swreg39
|
||||
RK_U32 swreg39_bsbr_addr;
|
||||
|
||||
/* reg[086] */
|
||||
RK_U32 swreg40_bsbw_addr; //swreg40
|
||||
RK_U32 swreg40_bsbw_addr;
|
||||
|
||||
/* reg[087] */
|
||||
struct {
|
||||
@@ -794,12 +647,12 @@ typedef struct H264eRkvIoctlExtraInfoElem_t {
|
||||
typedef struct H264eRkvIoctlExtraInfo_t {
|
||||
RK_U32 magic;
|
||||
RK_U32 cnt;
|
||||
H264eRkvIoctlExtraInfoElem elem[20];
|
||||
H264eRkvIoctlExtraInfoElem elem[20];
|
||||
} H264eRkvIoctlExtraInfo;
|
||||
|
||||
typedef struct H264eRkvIoctlRegInfo_t {
|
||||
RK_U32 reg_num;
|
||||
H264eRkvRegSet regs;
|
||||
RK_U32 reg_num;
|
||||
H264eRkvRegSet regs;
|
||||
H264eRkvIoctlExtraInfo extra_info;
|
||||
} H264eRkvIoctlRegInfo;
|
||||
|
||||
@@ -811,13 +664,11 @@ enc_mode
|
||||
3: multi_frame_encode link table update
|
||||
*/
|
||||
typedef struct H264eRkvIoctlInput_t {
|
||||
RK_U32 enc_mode;
|
||||
RK_U32 frame_num;
|
||||
|
||||
RK_U32 enc_mode;
|
||||
RK_U32 frame_num;
|
||||
H264eRkvIoctlRegInfo reg_info[RKV_H264E_LINKTABLE_MAX_SIZE];
|
||||
} H264eRkvIoctlInput;
|
||||
|
||||
|
||||
typedef struct H264eRkvIoctlOutputElem_t {
|
||||
RK_U32 hw_status;
|
||||
|
||||
@@ -886,16 +737,14 @@ typedef struct H264eRkvIoctlOutputElem_t {
|
||||
} H264eRkvIoctlOutputElem;
|
||||
|
||||
typedef struct H264eRkvIoctlOutput_t {
|
||||
RK_U32 frame_num;
|
||||
RK_U32 frame_num;
|
||||
H264eRkvIoctlOutputElem elem[RKV_H264E_LINKTABLE_MAX_SIZE];
|
||||
} H264eRkvIoctlOutput;
|
||||
|
||||
/* mode cfg */
|
||||
typedef struct H264eRkvMbRcMcfg_t {
|
||||
RK_S32 aq_prop; //0~16, 0:only enable aq, 16:only enable checkpoint
|
||||
|
||||
double aq_strength; //0~3
|
||||
|
||||
RK_U32 mb_num;
|
||||
RK_U32 qp_range; //0~15
|
||||
} H264eRkvMbRcMcfg;
|
||||
@@ -912,8 +761,6 @@ typedef struct H264eRkvMbRcQRcfg_t {
|
||||
RK_U32 qp_range;
|
||||
} H264eRkvMbRcQRcfg;
|
||||
|
||||
#define RK_H264E_NUM_REGS ((RK_S32)(sizeof(H264eRkvRegSet)/4))
|
||||
|
||||
MPP_RET hal_h264e_rkv_init (void *hal, MppHalCfg *cfg);
|
||||
MPP_RET hal_h264e_rkv_deinit (void *hal);
|
||||
MPP_RET hal_h264e_rkv_gen_regs(void *hal, HalTaskInfo *task);
|
||||
|
521
mpp/hal/rkenc/h264e/hal_h264e_rkv_dpb.c
Normal file
521
mpp/hal/rkenc/h264e/hal_h264e_rkv_dpb.c
Normal file
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
* Copyright 2015 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 "mpp_common.h"
|
||||
|
||||
#include "h264_syntax.h"
|
||||
#include "hal_h264e_rkv_nal.h"
|
||||
#include "hal_h264e_rkv_dpb.h"
|
||||
|
||||
static H264eRkvFrame *h264e_rkv_frame_new(H264eRkvDpbCtx *dpb_ctx)
|
||||
{
|
||||
RK_S32 k = 0;
|
||||
H264eRkvFrame *frame_buf = dpb_ctx->frame_buf;
|
||||
RK_S32 num_buf = MPP_ARRAY_ELEMS(dpb_ctx->frame_buf);
|
||||
H264eRkvFrame *new_frame = NULL;
|
||||
h264e_hal_enter();
|
||||
for (k = 0; k < num_buf; k++) {
|
||||
if (!frame_buf[k].hw_buf_used) {
|
||||
new_frame = &frame_buf[k];
|
||||
frame_buf[k].hw_buf_used = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!new_frame) {
|
||||
h264e_hal_err("!new_frame, new_frame get failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
h264e_hal_leave();
|
||||
return new_frame;
|
||||
}
|
||||
|
||||
static
|
||||
void h264e_rkv_frame_push(H264eRkvFrame **list, H264eRkvFrame *frame)
|
||||
{
|
||||
RK_S32 i = 0;
|
||||
while ( list[i] ) i++;
|
||||
list[i] = frame;
|
||||
h264e_hal_dbg(H264E_DBG_DPB, "frame push list[%d] %p", i, frame);
|
||||
|
||||
}
|
||||
|
||||
static void h264e_rkv_frame_push_unused(H264eRkvDpbCtx *dpb_ctx,
|
||||
H264eRkvFrame *frame)
|
||||
{
|
||||
h264e_hal_enter();
|
||||
mpp_assert( frame->i_reference_count > 0 );
|
||||
frame->i_reference_count--;
|
||||
if ( frame->i_reference_count == 0 )
|
||||
h264e_rkv_frame_push( dpb_ctx->frames.unused, frame );
|
||||
h264e_hal_leave();
|
||||
}
|
||||
|
||||
static H264eRkvFrame *h264e_rkv_frame_pop( H264eRkvFrame **list )
|
||||
{
|
||||
H264eRkvFrame *frame;
|
||||
RK_S32 i = 0;
|
||||
mpp_assert( list[0] );
|
||||
while ( list[i + 1] ) i++;
|
||||
frame = list[i];
|
||||
list[i] = NULL;
|
||||
h264e_hal_dbg(H264E_DBG_DPB, "frame pop list[%d] %p", i, frame);
|
||||
return frame;
|
||||
}
|
||||
|
||||
static
|
||||
H264eRkvFrame *h264e_rkv_frame_pop_unused( H264eHalContext *ctx)
|
||||
{
|
||||
H264eRkvFrame *frame = NULL;
|
||||
|
||||
H264eRkvDpbCtx *dpb_ctx = (H264eRkvDpbCtx *)ctx->dpb_ctx;
|
||||
|
||||
h264e_hal_enter();
|
||||
if ( dpb_ctx->frames.unused[0] )
|
||||
frame = h264e_rkv_frame_pop( dpb_ctx->frames.unused );
|
||||
else {
|
||||
frame = h264e_rkv_frame_new( dpb_ctx );
|
||||
}
|
||||
|
||||
if ( !frame ) {
|
||||
h264e_hal_err("!frame, return NULL");
|
||||
return NULL;
|
||||
}
|
||||
frame->i_reference_count = 1;
|
||||
frame->b_keyframe = 0;
|
||||
frame->b_corrupt = 0;
|
||||
frame->long_term_flag = 0;
|
||||
frame->reorder_longterm_flag = 0;
|
||||
|
||||
h264e_hal_leave();
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
static H264eRkvFrame *h264e_rkv_frame_shift( H264eRkvFrame **list )
|
||||
{
|
||||
H264eRkvFrame *frame = list[0];
|
||||
RK_S32 i;
|
||||
for ( i = 0; list[i]; i++ )
|
||||
list[i] = list[i + 1];
|
||||
mpp_assert(frame);
|
||||
h264e_hal_dbg(H264E_DBG_DPB, "frame shift list[0] %p", frame);
|
||||
return frame;
|
||||
}
|
||||
|
||||
static MPP_RET h264e_rkv_reference_update( H264eHalContext *ctx)
|
||||
{
|
||||
RK_S32 i = 0, j = 0;
|
||||
H264eRkvExtraInfo *extra_info = (H264eRkvExtraInfo *)ctx->extra_info;
|
||||
H264eSps *sps = &extra_info->sps;
|
||||
H264eRkvDpbCtx *dpb_ctx = (H264eRkvDpbCtx *)ctx->dpb_ctx;
|
||||
H264eRefParam *ref_cfg = &ctx->param.ref;
|
||||
|
||||
h264e_hal_enter();
|
||||
if ( !dpb_ctx->fdec->b_kept_as_ref ) {
|
||||
h264e_hal_err("!dpb_ctx->fdec->b_kept_as_ref, return early");
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
/* apply mmco from previous frame. */
|
||||
for (i = 0; i < dpb_ctx->i_mmco_command_count; i++) {
|
||||
RK_S32 mmco = dpb_ctx->mmco[i].memory_management_control_operation;
|
||||
for (j = 0; dpb_ctx->frames.reference[j]; j++) {
|
||||
if (dpb_ctx->frames.reference[j]->i_poc == dpb_ctx->mmco[i].i_poc &&
|
||||
(mmco == 1 || mmco == 2))
|
||||
h264e_rkv_frame_push_unused(dpb_ctx, h264e_rkv_frame_shift(&dpb_ctx->frames.reference[j]));
|
||||
}
|
||||
}
|
||||
|
||||
/* move frame in the buffer */
|
||||
h264e_hal_dbg(H264E_DBG_DPB, "try to push dpb_ctx->fdec %p, poc %d",
|
||||
dpb_ctx->fdec, dpb_ctx->fdec->i_poc);
|
||||
h264e_rkv_frame_push( dpb_ctx->frames.reference, dpb_ctx->fdec );
|
||||
if ( ref_cfg->i_long_term_en ) {
|
||||
if ( dpb_ctx->frames.reference[sps->i_num_ref_frames] ) {
|
||||
for (i = 0; i < 17; i++) {
|
||||
if (dpb_ctx->frames.reference[i]->long_term_flag == 0) {
|
||||
//if longterm , don't remove;
|
||||
h264e_rkv_frame_push_unused(dpb_ctx, h264e_rkv_frame_shift(&dpb_ctx->frames.reference[i]));
|
||||
break;
|
||||
}
|
||||
mpp_assert(i != 16);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( dpb_ctx->frames.reference[sps->i_num_ref_frames] )
|
||||
h264e_rkv_frame_push_unused(dpb_ctx, h264e_rkv_frame_shift(dpb_ctx->frames.reference));
|
||||
}
|
||||
|
||||
h264e_hal_leave();
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
static void h264e_rkv_reference_reset(H264eRkvDpbCtx *dpb_ctx)
|
||||
{
|
||||
h264e_hal_enter();
|
||||
while (dpb_ctx->frames.reference[0])
|
||||
h264e_rkv_frame_push_unused(dpb_ctx, h264e_rkv_frame_pop(dpb_ctx->frames.reference));
|
||||
dpb_ctx->fdec->i_poc = 0;
|
||||
h264e_hal_leave();
|
||||
}
|
||||
|
||||
static RK_S32
|
||||
h264e_rkv_reference_distance(H264eRefParam *ref_cfg,
|
||||
H264eRkvDpbCtx *dpb_ctx, H264eRkvFrame *frame )
|
||||
{
|
||||
if ( ref_cfg->i_frame_packing == 5 )
|
||||
return abs((dpb_ctx->fdec->i_frame_cnt & ~1) - (frame->i_frame_cnt & ~1)) +
|
||||
((dpb_ctx->fdec->i_frame_cnt & 1) != (frame->i_frame_cnt & 1));
|
||||
else
|
||||
return abs(dpb_ctx->fdec->i_frame_cnt - frame->i_frame_cnt);
|
||||
}
|
||||
|
||||
static void h264e_rkv_reference_build_list(H264eHalContext *ctx)
|
||||
{
|
||||
RK_S32 b_ok = 1, i = 0, list = 0, j = 0;
|
||||
H264eRkvExtraInfo *extra_info = (H264eRkvExtraInfo *)ctx->extra_info;
|
||||
H264eSps *sps = &extra_info->sps;
|
||||
H264eRkvDpbCtx *dpb_ctx = (H264eRkvDpbCtx *)ctx->dpb_ctx;
|
||||
H264eHalParam *par = &ctx->param;
|
||||
H264eRefParam *ref_cfg = &par->ref;
|
||||
H264eRkvFrame *fdec = dpb_ctx->fdec;
|
||||
RK_S32 i_poc = fdec->i_poc;
|
||||
|
||||
h264e_hal_enter();
|
||||
/* build ref list 0/1 */
|
||||
dpb_ctx->i_ref[0] = 0;
|
||||
dpb_ctx->i_ref[1] = 0;
|
||||
|
||||
if ( dpb_ctx->i_slice_type == H264E_HAL_SLICE_TYPE_I ) {
|
||||
if ( ref_cfg->i_long_term_en && ref_cfg->i_frame_reference > 1 )
|
||||
ref_cfg->hw_longterm_mode ^= 1; //0 and 1, circle; If ref==1 , longterm mode only 1;
|
||||
|
||||
if (ref_cfg->i_long_term_en && ref_cfg->hw_longterm_mode &&
|
||||
((dpb_ctx->fdec->i_frame_cnt % ref_cfg->i_long_term_internal) == 0))
|
||||
fdec->long_term_flag = 1;
|
||||
h264e_hal_dbg(H264E_DBG_DPB, "dpb_ctx->i_slice_type == SLICE_TYPE_I, return");
|
||||
return;
|
||||
}
|
||||
|
||||
h264e_hal_dbg(H264E_DBG_DPB, "fdec->i_poc: %d", fdec->i_poc);
|
||||
for ( i = 0; dpb_ctx->frames.reference[i]; i++ ) {
|
||||
if ( dpb_ctx->frames.reference[i]->b_corrupt )
|
||||
continue;
|
||||
if ( dpb_ctx->frames.reference[i]->i_poc < i_poc )
|
||||
dpb_ctx->fref[0][dpb_ctx->i_ref[0]++] = dpb_ctx->frames.reference[i];
|
||||
else if ( dpb_ctx->frames.reference[i]->i_poc > i_poc )
|
||||
dpb_ctx->fref[1][dpb_ctx->i_ref[1]++] = dpb_ctx->frames.reference[i];
|
||||
}
|
||||
|
||||
h264e_hal_dbg(H264E_DBG_DPB, "dpb_ctx->i_ref[0]: %d", dpb_ctx->i_ref[0]);
|
||||
h264e_hal_dbg(H264E_DBG_DPB, "dpb_ctx->i_ref[1]: %d", dpb_ctx->i_ref[1]);
|
||||
|
||||
if ( dpb_ctx->i_mmco_remove_from_end ) {
|
||||
/* Order ref0 for MMCO remove */
|
||||
do {
|
||||
b_ok = 1;
|
||||
for (i = 0; i < dpb_ctx->i_ref[0] - 1; i++ ) {
|
||||
if ( dpb_ctx->fref[0][i]->i_frame_cnt < dpb_ctx->fref[0][i + 1]->i_frame_cnt ) {
|
||||
MPP_SWAP( H264eRkvFrame *, dpb_ctx->fref[0][i], dpb_ctx->fref[0][i + 1] );
|
||||
b_ok = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while ( !b_ok );
|
||||
|
||||
for ( i = dpb_ctx->i_ref[0] - 1; i >= dpb_ctx->i_ref[0] - dpb_ctx->i_mmco_remove_from_end; i-- ) {
|
||||
RK_S32 diff = dpb_ctx->fdec->i_frame_num - dpb_ctx->fref[0][i]->i_frame_num;
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count].i_poc = dpb_ctx->fref[0][i]->i_poc;
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count++].i_difference_of_pic_nums = diff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Order reference lists by distance from the current frame. */
|
||||
for ( list = 0; list < 1; list++ ) { //only one list
|
||||
dpb_ctx->fref_nearest[list] = dpb_ctx->fref[list][0];
|
||||
do {
|
||||
b_ok = 1;
|
||||
for ( i = 0; i < dpb_ctx->i_ref[list] - 1; i++ ) {
|
||||
if ( list ? dpb_ctx->fref[list][i + 1]->i_poc < dpb_ctx->fref_nearest[list]->i_poc
|
||||
: dpb_ctx->fref[list][i + 1]->i_poc > dpb_ctx->fref_nearest[list]->i_poc )
|
||||
dpb_ctx->fref_nearest[list] = dpb_ctx->fref[list][i + 1];
|
||||
if ( h264e_rkv_reference_distance( ref_cfg, dpb_ctx, dpb_ctx->fref[list][i] ) >
|
||||
h264e_rkv_reference_distance( ref_cfg, dpb_ctx, dpb_ctx->fref[list][i + 1] ) ) {
|
||||
MPP_SWAP( H264eRkvFrame *, dpb_ctx->fref[list][i], dpb_ctx->fref[list][i + 1] );
|
||||
b_ok = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while ( !b_ok );
|
||||
}
|
||||
//Order long_term frame to last lists , only one long_term frame
|
||||
if (ref_cfg->i_long_term_en) {
|
||||
for (i = 0; i < dpb_ctx->i_ref[0]; i++) {
|
||||
if (dpb_ctx->fref[0][i]->long_term_flag == 1) {
|
||||
for (j = i; j < dpb_ctx->i_ref[0] - 1; j++) {
|
||||
MPP_SWAP(H264eRkvFrame *, dpb_ctx->fref[0][j], dpb_ctx->fref[0][j + 1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//reorder, when in longterm_mode "1", don't reorder;
|
||||
if (ref_cfg->i_frame_reference > 1 && ref_cfg->i_ref_pos && ref_cfg->i_ref_pos < dpb_ctx->i_ref[0])
|
||||
dpb_ctx->b_ref_pic_list_reordering[0] = 1;
|
||||
else
|
||||
dpb_ctx->b_ref_pic_list_reordering[0] = 0;
|
||||
if (dpb_ctx->b_ref_pic_list_reordering[0]) {
|
||||
for (list = 0; list < 1; list++) {
|
||||
if (dpb_ctx->fref[0][ref_cfg->i_ref_pos]->long_term_flag) {
|
||||
fdec->reorder_longterm_flag = 1;
|
||||
}
|
||||
for (i = ref_cfg->i_ref_pos; i >= 1; i--) {
|
||||
MPP_SWAP(H264eRkvFrame *, dpb_ctx->fref[list][i], dpb_ctx->fref[list][i - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//first P frame mark max_long_term_frame_idx_plus1
|
||||
if ( ref_cfg->i_long_term_en && dpb_ctx->fdec->i_frame_num == 1 ) {
|
||||
dpb_ctx->i_mmco_command_count = 0;
|
||||
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count].i_poc = 0;
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count].memory_management_control_operation = 4;
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count++].i_difference_of_pic_nums = 2; // max_long_term_frame_idx_plus1 , slice will plus 1, is 0;
|
||||
} else
|
||||
dpb_ctx->i_mmco_command_count = 0;
|
||||
|
||||
//longterm marking
|
||||
if ( ref_cfg->i_long_term_en && ((dpb_ctx->fdec->i_frame_cnt % ref_cfg->i_long_term_internal) == 0)) {
|
||||
RK_S32 reflist_longterm = 0;
|
||||
RK_S32 reflist_longidx = 0;
|
||||
RK_S32 reflist_short_to_long = 0;
|
||||
RK_S32 reflist_short_to_long_idx = 0;
|
||||
|
||||
//search frame for transferring short to long;
|
||||
if (ref_cfg->hw_longterm_mode == 0 || dpb_ctx->fdec->i_frame_num == 1) {
|
||||
for (i = 0; i < dpb_ctx->i_ref[0]; i++) {
|
||||
if (!dpb_ctx->fref[0][i]->long_term_flag && (ref_cfg->i_ref_pos + 1) == i) {
|
||||
reflist_short_to_long++;
|
||||
reflist_short_to_long_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//clear ref longterm flag
|
||||
for (i = 0; i < dpb_ctx->i_ref[0]; i++) {
|
||||
if (dpb_ctx->fref[0][i]->long_term_flag) {
|
||||
reflist_longterm++;
|
||||
reflist_longidx = i;
|
||||
dpb_ctx->fref[0][i]->long_term_flag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mpp_assert(reflist_longterm <= 1);
|
||||
|
||||
//marking ref longterm to unused;
|
||||
if ( reflist_longterm == 1 ) {
|
||||
i = reflist_longidx;
|
||||
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count].i_poc = dpb_ctx->fref[0][i]->i_poc;
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count].memory_management_control_operation = 2; //long_term_pic_num
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count++].i_difference_of_pic_nums = 1;
|
||||
} else if ( dpb_ctx->i_ref[0] >= sps->i_num_ref_frames && dpb_ctx->i_ref[0] > 1 ) { //if dpb is full, so it need release a short term ref frame;
|
||||
//if longterm marking is same with release short term, change release short term;
|
||||
RK_S32 pos = ((reflist_short_to_long && reflist_short_to_long_idx == (dpb_ctx->i_ref[0] - 1)) || dpb_ctx->fref[0][dpb_ctx->i_ref[0] - 1]->long_term_flag) + 1;
|
||||
RK_S32 diff = dpb_ctx->fdec->i_frame_num - dpb_ctx->fref[0][dpb_ctx->i_ref[0] - pos]->i_frame_num;
|
||||
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count].i_poc = dpb_ctx->fref[0][dpb_ctx->i_ref[0] - pos]->i_poc;
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count].memory_management_control_operation = 1;
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count++].i_difference_of_pic_nums = diff; // difference_of_pic_nums_minus1
|
||||
}
|
||||
|
||||
//marking curr pic to longterm;
|
||||
if ( ref_cfg->hw_longterm_mode && dpb_ctx->fdec->i_frame_num == 1) {
|
||||
fdec->long_term_flag = 1;
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count].i_poc = 0;
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count].memory_management_control_operation = 6;
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count++].i_difference_of_pic_nums = 1; // long_term_frame_idx ;
|
||||
} else if ( reflist_short_to_long ) { //Assign a long-term frame index to a short-term picture
|
||||
i = reflist_short_to_long_idx;
|
||||
RK_S32 diff = dpb_ctx->fdec->i_frame_num - dpb_ctx->fref[0][i]->i_frame_num;
|
||||
|
||||
dpb_ctx->fref[0][i]->long_term_flag = 1;
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count].i_poc = dpb_ctx->fref[0][i]->i_poc;
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count].memory_management_control_operation = 3; //short term to long term;
|
||||
dpb_ctx->mmco[dpb_ctx->i_mmco_command_count++].i_difference_of_pic_nums = diff; // difference_of_pic_nums_minus1 , slice will minus 1, is 0;
|
||||
}
|
||||
} else {
|
||||
if (!(ref_cfg->i_long_term_en && dpb_ctx->fdec->i_frame_num == 1))
|
||||
dpb_ctx->i_mmco_command_count = 0;
|
||||
}
|
||||
|
||||
dpb_ctx->i_ref[1] = H264E_HAL_MIN( dpb_ctx->i_ref[1], dpb_ctx->i_max_ref1 );
|
||||
dpb_ctx->i_ref[0] = H264E_HAL_MIN( dpb_ctx->i_ref[0], dpb_ctx->i_max_ref0 );
|
||||
dpb_ctx->i_ref[0] = H264E_HAL_MIN( dpb_ctx->i_ref[0], ref_cfg->i_frame_reference ); // if reconfig() has lowered the limit
|
||||
|
||||
/* EXP: add duplicates */
|
||||
mpp_assert( dpb_ctx->i_ref[0] + dpb_ctx->i_ref[1] <= H264E_REF_MAX );
|
||||
|
||||
h264e_hal_leave();
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_reference_frame_update( H264eHalContext *ctx)
|
||||
{
|
||||
h264e_hal_enter();
|
||||
if (MPP_OK != h264e_rkv_reference_update(ctx)) {
|
||||
h264e_hal_err("reference update failed, return now");
|
||||
return MPP_NOK;
|
||||
}
|
||||
|
||||
h264e_hal_leave();
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET
|
||||
h264e_rkv_reference_frame_set( H264eHalContext *ctx, H264eHwCfg *syn)
|
||||
{
|
||||
RK_U32 i_nal_type = 0, i_nal_ref_idc = 0;
|
||||
RK_S32 list = 0, k = 0;
|
||||
H264eRkvDpbCtx *dpb_ctx = (H264eRkvDpbCtx *)ctx->dpb_ctx;
|
||||
H264eRkvExtraInfo *extra_info = (H264eRkvExtraInfo *)ctx->extra_info;
|
||||
H264eSps *sps = &extra_info->sps;
|
||||
H264eRefParam *ref_cfg = &ctx->param.ref;
|
||||
|
||||
h264e_hal_enter();
|
||||
|
||||
dpb_ctx->fdec = h264e_rkv_frame_pop_unused(ctx);
|
||||
if ( !dpb_ctx->fdec ) {
|
||||
h264e_hal_err("!dpb_ctx->fdec, current recon buf get failed");
|
||||
return MPP_NOK;
|
||||
}
|
||||
|
||||
dpb_ctx->i_max_ref0 = ref_cfg->i_frame_reference;
|
||||
dpb_ctx->i_max_ref1 = H264E_HAL_MIN(sps->vui.i_num_reorder_frames,
|
||||
ref_cfg->i_frame_reference);
|
||||
|
||||
if (syn->coding_type == RKVENC_CODING_TYPE_IDR) {
|
||||
dpb_ctx->i_frame_num = 0;
|
||||
dpb_ctx->frames.i_last_idr = dpb_ctx->i_frame_cnt;
|
||||
}
|
||||
|
||||
dpb_ctx->fdec->i_frame_cnt = dpb_ctx->i_frame_cnt;
|
||||
dpb_ctx->fdec->i_frame_num = dpb_ctx->i_frame_num;
|
||||
dpb_ctx->fdec->i_frame_type = syn->coding_type;
|
||||
dpb_ctx->fdec->i_poc = 2 * (dpb_ctx->fdec->i_frame_cnt -
|
||||
H264E_HAL_MAX(dpb_ctx->frames.i_last_idr, 0));
|
||||
|
||||
if ( !RKVENC_IS_TYPE_I( dpb_ctx->fdec->i_frame_type ) ) {
|
||||
RK_S32 valid_refs_left = 0;
|
||||
for ( k = 0; dpb_ctx->frames.reference[k]; k++ )
|
||||
if ( !dpb_ctx->frames.reference[k]->b_corrupt )
|
||||
valid_refs_left++;
|
||||
/* No valid reference frames left: force an IDR. */
|
||||
if ( !valid_refs_left ) {
|
||||
dpb_ctx->fdec->b_keyframe = 1;
|
||||
dpb_ctx->fdec->i_frame_type = RKVENC_CODING_TYPE_IDR;
|
||||
}
|
||||
}
|
||||
if ( dpb_ctx->fdec->b_keyframe )
|
||||
dpb_ctx->frames.i_last_keyframe = dpb_ctx->fdec->i_frame_cnt;
|
||||
|
||||
|
||||
dpb_ctx->i_mmco_command_count =
|
||||
dpb_ctx->i_mmco_remove_from_end = 0;
|
||||
dpb_ctx->b_ref_pic_list_reordering[0] = 0;
|
||||
dpb_ctx->b_ref_pic_list_reordering[1] = 0;
|
||||
|
||||
/* calculate nal type and nal ref idc */
|
||||
if (syn->coding_type == RKVENC_CODING_TYPE_IDR) {
|
||||
//TODO: extend syn->frame_coding_type definition
|
||||
/* reset ref pictures */
|
||||
i_nal_type = H264E_NAL_SLICE_IDR;
|
||||
i_nal_ref_idc = H264E_NAL_PRIORITY_HIGHEST;
|
||||
dpb_ctx->i_slice_type = H264E_HAL_SLICE_TYPE_I;
|
||||
h264e_rkv_reference_reset(dpb_ctx);
|
||||
} else if ( syn->coding_type == RKVENC_CODING_TYPE_I ) {
|
||||
i_nal_type = H264E_NAL_SLICE;
|
||||
i_nal_ref_idc = H264E_NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/
|
||||
dpb_ctx->i_slice_type = H264E_HAL_SLICE_TYPE_I;
|
||||
} else if ( syn->coding_type == RKVENC_CODING_TYPE_P ) {
|
||||
i_nal_type = H264E_NAL_SLICE;
|
||||
i_nal_ref_idc = H264E_NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/
|
||||
dpb_ctx->i_slice_type = H264E_HAL_SLICE_TYPE_P;
|
||||
} else if ( syn->coding_type == RKVENC_CODING_TYPE_BREF ) {
|
||||
i_nal_type = H264E_NAL_SLICE;
|
||||
i_nal_ref_idc = H264E_NAL_PRIORITY_HIGH;
|
||||
dpb_ctx->i_slice_type = H264E_HAL_SLICE_TYPE_B;
|
||||
} else { /* B frame */
|
||||
i_nal_type = H264E_NAL_SLICE;
|
||||
i_nal_ref_idc = H264E_NAL_PRIORITY_DISPOSABLE;
|
||||
dpb_ctx->i_slice_type = H264E_HAL_SLICE_TYPE_B;
|
||||
}
|
||||
|
||||
dpb_ctx->fdec->b_kept_as_ref = i_nal_ref_idc != H264E_NAL_PRIORITY_DISPOSABLE;// && h->param.i_keyint_max > 1;
|
||||
|
||||
if (sps->keyframe_max_interval == 1)
|
||||
i_nal_ref_idc = H264E_NAL_PRIORITY_LOW;
|
||||
|
||||
dpb_ctx->i_nal_ref_idc = i_nal_ref_idc;
|
||||
dpb_ctx->i_nal_type = i_nal_type;
|
||||
dpb_ctx->fdec->i_pts = dpb_ctx->fdec->i_pts;
|
||||
|
||||
/* build list */
|
||||
h264e_rkv_reference_build_list(ctx);
|
||||
|
||||
/* set syntax (slice header) */
|
||||
|
||||
/* If the ref list isn't in the default order, construct reordering header */
|
||||
for (list = 0; list < 2; list++ ) {
|
||||
if ( dpb_ctx->b_ref_pic_list_reordering[list] ) {
|
||||
RK_S32 pred_frame_num = dpb_ctx->fdec->i_frame_num & ((1 << sps->i_log2_max_frame_num) - 1);
|
||||
for ( k = 0; k < dpb_ctx->i_ref[list]; k++ ) {
|
||||
if ( dpb_ctx->fdec->reorder_longterm_flag ) { //
|
||||
dpb_ctx->fdec->reorder_longterm_flag = 0; //clear reorder_longterm_flag
|
||||
dpb_ctx->ref_pic_list_order[list][k].idc = 2; //reorder long_term_pic_num;
|
||||
dpb_ctx->ref_pic_list_order[list][k].arg = 0; //long_term_pic_num
|
||||
break; //NOTE: RK feature: only reorder one time
|
||||
} else {
|
||||
RK_S32 lx_frame_num = dpb_ctx->fref[list][k]->i_frame_num & ((1 << sps->i_log2_max_frame_num) - 1);
|
||||
RK_S32 diff = lx_frame_num - pred_frame_num;
|
||||
dpb_ctx->ref_pic_list_order[list][k].idc = ( diff > 0 );
|
||||
dpb_ctx->ref_pic_list_order[list][k].arg = (abs(diff) - 1) & ((1 << sps->i_log2_max_frame_num) - 1);
|
||||
pred_frame_num = dpb_ctx->fref[list][k]->i_frame_num;
|
||||
break; //NOTE: RK feature: only reorder one time
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dpb_ctx->i_nal_type == H264E_NAL_SLICE_IDR) {
|
||||
if (ref_cfg->i_long_term_en && ref_cfg->hw_longterm_mode && ((dpb_ctx->fdec->i_frame_cnt % ref_cfg->i_long_term_internal) == 0) )
|
||||
dpb_ctx->i_long_term_reference_flag = 1;
|
||||
dpb_ctx->i_idr_pic_id = dpb_ctx->i_tmp_idr_pic_id;
|
||||
dpb_ctx->i_tmp_idr_pic_id ^= 1;
|
||||
} else {
|
||||
dpb_ctx->i_long_term_reference_flag = 0;
|
||||
dpb_ctx->i_idr_pic_id = -1;
|
||||
}
|
||||
|
||||
h264e_hal_leave();
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
|
109
mpp/hal/rkenc/h264e/hal_h264e_rkv_dpb.h
Normal file
109
mpp/hal/rkenc/h264e/hal_h264e_rkv_dpb.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2015 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 __HAL_H264E_RKV_DPB_H__
|
||||
#define __HAL_H264E_RKV_DPB_H__
|
||||
|
||||
#include "hal_h264e_com.h"
|
||||
|
||||
#define RKV_H264E_REF_MAX 16
|
||||
|
||||
#define RKVENC_CODING_TYPE_AUTO 0x0000 /* Let x264 choose the right type */
|
||||
#define RKVENC_CODING_TYPE_IDR 0x0001
|
||||
#define RKVENC_CODING_TYPE_I 0x0002
|
||||
#define RKVENC_CODING_TYPE_P 0x0003
|
||||
#define RKVENC_CODING_TYPE_BREF 0x0004 /* Non-disposable B-frame */
|
||||
#define RKVENC_CODING_TYPE_B 0x0005
|
||||
#define RKVENC_CODING_TYPE_KEYFRAME 0x0006 /* IDR or I depending on b_open_gop option */
|
||||
#define RKVENC_IS_TYPE_I(x) ((x)==RKVENC_CODING_TYPE_I || (x)==RKVENC_CODING_TYPE_IDR)
|
||||
#define RKVENC_IS_TYPE_B(x) ((x)==RKVENC_CODING_TYPE_B || (x)==RKVENC_CODING_TYPE_BREF)
|
||||
#define RKVENC_IS_DISPOSABLE(type) ( type == RKVENC_CODING_TYPE_B )
|
||||
|
||||
typedef struct H264eRkvFrame_t {
|
||||
MppBuffer hw_buf;
|
||||
RK_S32 hw_buf_used;
|
||||
RK_S32 i_frame_cnt; /* Presentation frame number */
|
||||
RK_S32 i_frame_num; /* 7.4.3 frame_num */
|
||||
RK_S32 long_term_flag;
|
||||
RK_S32 reorder_longterm_flag;
|
||||
RK_S32 i_poc;
|
||||
RK_S32 i_delta_poc[2];
|
||||
RK_S32 i_frame_type;
|
||||
RK_S64 i_pts;
|
||||
RK_S64 i_dts;
|
||||
RK_S32 b_kept_as_ref;
|
||||
RK_S32 b_keyframe;
|
||||
RK_S32 b_corrupt;
|
||||
RK_S32 i_reference_count;
|
||||
} H264eRkvFrame;
|
||||
|
||||
typedef struct H264eRkvDpbCtx_t {
|
||||
//H264eRkvFrame *fenc;
|
||||
H264eRkvFrame *fdec;
|
||||
H264eRkvFrame *fref[2][RKV_H264E_REF_MAX + 1];
|
||||
H264eRkvFrame *fref_nearest[2]; //Used for RC
|
||||
struct {
|
||||
/* Unused frames: 0 = fenc, 1 = fdec */
|
||||
H264eRkvFrame **unused;
|
||||
|
||||
/* frames used for reference + sentinels */
|
||||
H264eRkvFrame *reference[RKV_H264E_REF_MAX + 1]; //TODO: remove later
|
||||
|
||||
RK_S32 i_last_keyframe; /* Frame number of the last keyframe */
|
||||
RK_S32 i_last_idr; /* Frame number of the last IDR (not RP)*/
|
||||
//RK_S64 i_largest_pts;
|
||||
//RK_S64 i_second_largest_pts;
|
||||
} frames;
|
||||
|
||||
H264eRkvFrame frame_buf[RKV_H264E_REF_MAX + 1];
|
||||
|
||||
RK_S32 i_ref[2];
|
||||
RK_U32 i_nal_type;
|
||||
RK_U32 i_nal_ref_idc;
|
||||
|
||||
RK_S32 i_frame_cnt; /* Presentation frame number */
|
||||
RK_S32 i_frame_num; /* 7.4.3 frame_num */
|
||||
|
||||
//move from slice header below
|
||||
RK_S32 i_slice_type;
|
||||
RK_S32 i_idr_pic_id; /* -1 if nal_type != 5 */
|
||||
RK_S32 i_tmp_idr_pic_id;
|
||||
//RK_S32 i_poc;
|
||||
//RK_S32 i_delta_poc[2];
|
||||
//RK_S32 i_redundant_pic_cnt;
|
||||
RK_S32 i_max_ref0;
|
||||
RK_S32 i_max_ref1;
|
||||
RK_S32 b_ref_pic_list_reordering[2];
|
||||
struct {
|
||||
RK_S32 idc;
|
||||
RK_S32 arg;
|
||||
} ref_pic_list_order[2][RKV_H264E_REF_MAX];
|
||||
|
||||
RK_S32 i_mmco_remove_from_end;
|
||||
RK_S32 i_mmco_command_count;
|
||||
struct { /* struct for future expansion */
|
||||
RK_S32 i_difference_of_pic_nums;
|
||||
RK_S32 i_poc;
|
||||
RK_S32 memory_management_control_operation;
|
||||
} mmco[RKV_H264E_REF_MAX];
|
||||
|
||||
RK_S32 i_long_term_reference_flag;
|
||||
} H264eRkvDpbCtx;
|
||||
|
||||
MPP_RET h264e_rkv_reference_frame_set( H264eHalContext *ctx, H264eHwCfg *syn);
|
||||
MPP_RET h264e_rkv_reference_frame_update( H264eHalContext *ctx);
|
||||
|
||||
#endif /* __HAL_H264E_RKV_DPB_H__ */
|
536
mpp/hal/rkenc/h264e/hal_h264e_rkv_nal.c
Normal file
536
mpp/hal/rkenc/h264e/hal_h264e_rkv_nal.c
Normal file
@@ -0,0 +1,536 @@
|
||||
/*
|
||||
* Copyright 2015 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 <string.h>
|
||||
|
||||
#include "mpp_common.h"
|
||||
#include "mpp_mem.h"
|
||||
|
||||
#include "h264_syntax.h"
|
||||
#include "hal_h264e_rkv_nal.h"
|
||||
|
||||
static void h264e_rkv_nals_init(H264eRkvExtraInfo *out)
|
||||
{
|
||||
out->nal_buf = mpp_calloc(RK_U8, H264E_EXTRA_INFO_BUF_SIZE);
|
||||
out->nal_num = 0;
|
||||
}
|
||||
|
||||
static void h264e_rkv_nals_deinit(H264eRkvExtraInfo *out)
|
||||
{
|
||||
MPP_FREE(out->nal_buf);
|
||||
|
||||
out->nal_num = 0;
|
||||
}
|
||||
|
||||
static RK_U8 *h264e_rkv_nal_escape_c(RK_U8 *dst, RK_U8 *src, RK_U8 *end)
|
||||
{
|
||||
if (src < end) *dst++ = *src++;
|
||||
if (src < end) *dst++ = *src++;
|
||||
while (src < end) {
|
||||
if (src[0] <= 0x03 && !dst[-2] && !dst[-1])
|
||||
*dst++ = 0x03;
|
||||
*dst++ = *src++;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
static void h264e_rkv_nal_encode(RK_U8 *dst, H264eRkvNal *nal)
|
||||
{
|
||||
RK_S32 b_annexb = 1;
|
||||
RK_S32 size = 0;
|
||||
RK_U8 *src = nal->p_payload;
|
||||
RK_U8 *end = nal->p_payload + nal->i_payload;
|
||||
RK_U8 *orig_dst = dst;
|
||||
|
||||
if (b_annexb) {
|
||||
//if (nal->b_long_startcode)//fix by gsl
|
||||
//*dst++ = 0x00;//fix by gsl
|
||||
*dst++ = 0x00;
|
||||
*dst++ = 0x00;
|
||||
*dst++ = 0x01;
|
||||
} else /* save room for size later */
|
||||
dst += 4;
|
||||
|
||||
/* nal header */
|
||||
*dst++ = (0x00 << 7) | (nal->i_ref_idc << 5) | nal->i_type;
|
||||
|
||||
dst = h264e_rkv_nal_escape_c(dst, src, end);
|
||||
size = (RK_S32)((dst - orig_dst) - 4);
|
||||
|
||||
/* Write the size header for mp4/etc */
|
||||
if (!b_annexb) {
|
||||
/* Size doesn't include the size of the header we're writing now. */
|
||||
orig_dst[0] = size >> 24;
|
||||
orig_dst[1] = size >> 16;
|
||||
orig_dst[2] = size >> 8;
|
||||
orig_dst[3] = size >> 0;
|
||||
}
|
||||
|
||||
nal->i_payload = size + 4;
|
||||
nal->p_payload = orig_dst;
|
||||
}
|
||||
|
||||
static MPP_RET h264e_rkv_encapsulate_nals(H264eRkvExtraInfo *out)
|
||||
{
|
||||
RK_S32 i = 0;
|
||||
RK_S32 i_avcintra_class = 0;
|
||||
RK_S32 nal_size = 0;
|
||||
RK_S32 necessary_size = 0;
|
||||
RK_U8 *nal_buffer = out->nal_buf;
|
||||
RK_S32 nal_num = out->nal_num;
|
||||
H264eRkvNal *nal = out->nal;
|
||||
|
||||
h264e_hal_enter();
|
||||
|
||||
for (i = 0; i < nal_num; i++)
|
||||
nal_size += nal[i].i_payload;
|
||||
|
||||
/* Worst-case NAL unit escaping: reallocate the buffer if it's too small. */
|
||||
necessary_size = nal_size * 3 / 2 + nal_num * 4 + 4 + 64;
|
||||
for (i = 0; i < nal_num; i++)
|
||||
necessary_size += nal[i].i_padding;
|
||||
|
||||
for (i = 0; i < nal_num; i++) {
|
||||
nal[i].b_long_startcode = !i ||
|
||||
nal[i].i_type == H264E_NAL_SPS ||
|
||||
nal[i].i_type == H264E_NAL_PPS ||
|
||||
i_avcintra_class;
|
||||
h264e_rkv_nal_encode(nal_buffer, &nal[i]);
|
||||
nal_buffer += nal[i].i_payload;
|
||||
}
|
||||
|
||||
h264e_hal_dbg(H264E_DBG_HEADER, "nals total size: %d bytes",
|
||||
nal_buffer - out->nal_buf);
|
||||
|
||||
h264e_hal_leave();
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
static MPP_RET
|
||||
h264e_rkv_sei_write(H264eRkvStream *s, RK_U8 *payload,
|
||||
RK_S32 payload_size, RK_S32 payload_type)
|
||||
{
|
||||
RK_S32 i = 0;
|
||||
|
||||
h264e_hal_enter();
|
||||
|
||||
s->count_bit = 0;
|
||||
h264e_rkv_stream_realign(s);
|
||||
|
||||
for (i = 0; i <= payload_type - 255; i += 255)
|
||||
h264e_rkv_stream_write_with_log(s, 8, 0xff,
|
||||
"sei_payload_type_ff_byte");
|
||||
h264e_rkv_stream_write_with_log(s, 8, payload_type - i,
|
||||
"sei_last_payload_type_byte");
|
||||
|
||||
for (i = 0; i <= payload_size - 255; i += 255)
|
||||
h264e_rkv_stream_write_with_log(s, 8, 0xff,
|
||||
"sei_payload_size_ff_byte");
|
||||
h264e_rkv_stream_write_with_log( s, 8, payload_size - i,
|
||||
"sei_last_payload_size_byte");
|
||||
|
||||
for (i = 0; i < payload_size; i++)
|
||||
h264e_rkv_stream_write_with_log(s, 8, (RK_U32)payload[i],
|
||||
"sei_payload_data");
|
||||
|
||||
h264e_rkv_stream_rbsp_trailing(s);
|
||||
h264e_rkv_stream_flush(s);
|
||||
|
||||
h264e_hal_leave();
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_sei_encode(H264eHalContext *ctx, RcSyntax *rc_syn)
|
||||
{
|
||||
H264eRkvExtraInfo *info = (H264eRkvExtraInfo *)ctx->extra_info;
|
||||
char *str = (char *)info->sei_buf;
|
||||
RK_S32 str_len = 0;
|
||||
|
||||
h264e_sei_pack2str(str + H264E_UUID_LENGTH, ctx, rc_syn);
|
||||
str_len = strlen(str) + 1;
|
||||
if (str_len > H264E_SEI_BUF_SIZE) {
|
||||
h264e_hal_err("SEI actual string length %d exceed malloced size %d",
|
||||
str_len, H264E_SEI_BUF_SIZE);
|
||||
return MPP_NOK;
|
||||
} else {
|
||||
h264e_rkv_sei_write(&info->stream, (RK_U8 *)str, str_len,
|
||||
H264E_SEI_USER_DATA_UNREGISTERED);
|
||||
}
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
static MPP_RET h264e_rkv_sps_write(H264eSps *sps, H264eRkvStream *s)
|
||||
{
|
||||
h264e_hal_enter();
|
||||
|
||||
s->count_bit = 0;
|
||||
h264e_rkv_stream_realign(s);
|
||||
h264e_rkv_stream_write_with_log(s, 8, sps->i_profile_idc, "profile_idc");
|
||||
h264e_rkv_stream_write1_with_log(s, sps->b_constraint_set0, "constraint_set0_flag");
|
||||
h264e_rkv_stream_write1_with_log(s, sps->b_constraint_set1, "constraint_set1_flag");
|
||||
h264e_rkv_stream_write1_with_log(s, sps->b_constraint_set2, "constraint_set2_flag");
|
||||
h264e_rkv_stream_write1_with_log(s, sps->b_constraint_set3, "constraint_set3_flag");
|
||||
|
||||
h264e_rkv_stream_write_with_log(s, 4, 0, "reserved_zero_4bits");
|
||||
|
||||
h264e_rkv_stream_write_with_log(s, 8, sps->i_level_idc, "level_idc");
|
||||
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->i_id, "seq_parameter_set_id");
|
||||
|
||||
if (sps->i_profile_idc >= H264_PROFILE_HIGH) {
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->i_chroma_format_idc, "chroma_format_idc");
|
||||
if (sps->i_chroma_format_idc == H264E_CHROMA_444)
|
||||
h264e_rkv_stream_write1_with_log(s, 0, "separate_colour_plane_flag");
|
||||
h264e_rkv_stream_write_ue_with_log(s, H264_BIT_DEPTH - 8, "bit_depth_luma_minus8");
|
||||
h264e_rkv_stream_write_ue_with_log(s, H264_BIT_DEPTH - 8, "bit_depth_chroma_minus8");
|
||||
h264e_rkv_stream_write1_with_log(s, sps->b_qpprime_y_zero_transform_bypass, "qpprime_y_zero_transform_bypass_flag");
|
||||
h264e_rkv_stream_write1_with_log(s, 0, "seq_scaling_matrix_present_flag");
|
||||
}
|
||||
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->i_log2_max_frame_num - 4, "log2_max_frame_num_minus4");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->i_poc_type, "pic_order_cnt_type");
|
||||
if (sps->i_poc_type == 0)
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->i_log2_max_poc_lsb - 4, "log2_max_pic_order_cnt_lsb_minus4");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->i_num_ref_frames, "max_num_ref_frames");
|
||||
h264e_rkv_stream_write1_with_log(s, sps->b_gaps_in_frame_num_value_allowed, "gaps_in_frame_num_value_allowed_flag");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->i_mb_width - 1, "pic_width_in_mbs_minus1");
|
||||
h264e_rkv_stream_write_ue_with_log(s, (sps->i_mb_height >> !sps->b_frame_mbs_only) - 1, "pic_height_in_map_units_minus1");
|
||||
h264e_rkv_stream_write1_with_log(s, sps->b_frame_mbs_only, "frame_mbs_only_flag");
|
||||
if (!sps->b_frame_mbs_only)
|
||||
h264e_rkv_stream_write1_with_log(s, sps->b_mb_adaptive_frame_field, "mb_adaptive_frame_field_flag");
|
||||
h264e_rkv_stream_write1_with_log(s, sps->b_direct8x8_inference, "direct_8x8_inference_flag");
|
||||
|
||||
h264e_rkv_stream_write1_with_log(s, sps->b_crop, "frame_cropping_flag");
|
||||
if (sps->b_crop) {
|
||||
RK_S32 h_shift = sps->i_chroma_format_idc == H264E_CHROMA_420 || sps->i_chroma_format_idc == H264E_CHROMA_422;
|
||||
RK_S32 v_shift = sps->i_chroma_format_idc == H264E_CHROMA_420;
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->crop.i_left >> h_shift, "frame_crop_left_offset");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->crop.i_right >> h_shift, "frame_crop_right_offset");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->crop.i_top >> v_shift, "frame_crop_top_offset");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->crop.i_bottom >> v_shift, "frame_crop_bottom_offset");
|
||||
}
|
||||
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_vui, "vui_parameters_present_flag");
|
||||
if (sps->vui.b_vui) {
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_aspect_ratio_info_present, "aspect_ratio_info_present_flag");
|
||||
if (sps->vui.b_aspect_ratio_info_present) {
|
||||
RK_S32 i = 0;
|
||||
static const struct { RK_U8 w, h, sar; } sar[] = {
|
||||
// aspect_ratio_idc = 0 -> unspecified
|
||||
{ 1, 1, 1 }, { 12, 11, 2 }, { 10, 11, 3 }, { 16, 11, 4 },
|
||||
{ 40, 33, 5 }, { 24, 11, 6 }, { 20, 11, 7 }, { 32, 11, 8 },
|
||||
{ 80, 33, 9 }, { 18, 11, 10 }, { 15, 11, 11 }, { 64, 33, 12 },
|
||||
{ 160, 99, 13 }, { 4, 3, 14 }, { 3, 2, 15 }, { 2, 1, 16 },
|
||||
// aspect_ratio_idc = [17..254] -> reserved
|
||||
{ 0, 0, 255 }
|
||||
};
|
||||
for (i = 0; sar[i].sar != 255; i++) {
|
||||
if (sar[i].w == sps->vui.i_sar_width &&
|
||||
sar[i].h == sps->vui.i_sar_height)
|
||||
break;
|
||||
}
|
||||
h264e_rkv_stream_write_with_log(s, 8, sar[i].sar, "aspect_ratio_idc");
|
||||
if (sar[i].sar == 255) { /* aspect_ratio_idc (extended) */
|
||||
h264e_rkv_stream_write_with_log(s, 16, sps->vui.i_sar_width, "sar_width");
|
||||
h264e_rkv_stream_write_with_log(s, 16, sps->vui.i_sar_height, "sar_height");
|
||||
}
|
||||
}
|
||||
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_overscan_info_present, "overscan_info_present_flag");
|
||||
if (sps->vui.b_overscan_info_present)
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_overscan_info, "overscan_appropriate_flag");
|
||||
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_signal_type_present, "video_signal_type_present_flag");
|
||||
if (sps->vui.b_signal_type_present) {
|
||||
h264e_rkv_stream_write_with_log(s, 3, sps->vui.i_vidformat, "video_format");
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_fullrange, "video_full_range_flag");
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_color_description_present, "colour_description_present_flag");
|
||||
if (sps->vui.b_color_description_present) {
|
||||
h264e_rkv_stream_write_with_log(s, 8, sps->vui.i_colorprim, "colour_primaries");
|
||||
h264e_rkv_stream_write_with_log(s, 8, sps->vui.i_transfer, "transfer_characteristics");
|
||||
h264e_rkv_stream_write_with_log(s, 8, sps->vui.i_colmatrix, "matrix_coefficients");
|
||||
}
|
||||
}
|
||||
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_chroma_loc_info_present, "chroma_loc_info_present_flag");
|
||||
if (sps->vui.b_chroma_loc_info_present) {
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->vui.i_chroma_loc_top, "chroma_loc_info_present_flag");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->vui.i_chroma_loc_bottom, "chroma_sample_loc_type_bottom_field");
|
||||
}
|
||||
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_timing_info_present, "chroma_sample_loc_type_bottom_field");
|
||||
if (sps->vui.b_timing_info_present) {
|
||||
h264e_rkv_stream_write32(s, sps->vui.i_num_units_in_tick, "num_units_in_tick");
|
||||
h264e_rkv_stream_write32(s, sps->vui.i_time_scale, "time_scale");
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_fixed_frame_rate, "fixed_frame_rate_flag");
|
||||
}
|
||||
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_nal_hrd_parameters_present, "time_scale");
|
||||
if (sps->vui.b_nal_hrd_parameters_present) {
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->vui.hrd.i_cpb_cnt - 1, "cpb_cnt_minus1");
|
||||
h264e_rkv_stream_write_with_log(s, 4, sps->vui.hrd.i_bit_rate_scale, "bit_rate_scale");
|
||||
h264e_rkv_stream_write_with_log(s, 4, sps->vui.hrd.i_cpb_size_scale, "cpb_size_scale");
|
||||
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->vui.hrd.i_bit_rate_value - 1, "bit_rate_value_minus1");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->vui.hrd.i_cpb_size_value - 1, "cpb_size_value_minus1");
|
||||
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.hrd.b_cbr_hrd, "cbr_flag");
|
||||
|
||||
h264e_rkv_stream_write_with_log(s, 5, sps->vui.hrd.i_initial_cpb_removal_delay_length - 1, "initial_cpb_removal_delay_length_minus1");
|
||||
h264e_rkv_stream_write_with_log(s, 5, sps->vui.hrd.i_cpb_removal_delay_length - 1, "cpb_removal_delay_length_minus1");
|
||||
h264e_rkv_stream_write_with_log(s, 5, sps->vui.hrd.i_dpb_output_delay_length - 1, "dpb_output_delay_length_minus1");
|
||||
h264e_rkv_stream_write_with_log(s, 5, sps->vui.hrd.i_time_offset_length, "time_offset_length");
|
||||
}
|
||||
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_vcl_hrd_parameters_present, "vcl_hrd_parameters_present_flag");
|
||||
|
||||
if (sps->vui.b_nal_hrd_parameters_present || sps->vui.b_vcl_hrd_parameters_present)
|
||||
h264e_rkv_stream_write1_with_log(s, 0, "low_delay_hrd_flag"); /* low_delay_hrd_flag */
|
||||
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_pic_struct_present, "pic_struct_present_flag");
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_bitstream_restriction, "bitstream_restriction_flag");
|
||||
if (sps->vui.b_bitstream_restriction) {
|
||||
h264e_rkv_stream_write1_with_log(s, sps->vui.b_motion_vectors_over_pic_boundaries, "motion_vectors_over_pic_boundaries_flag");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->vui.i_max_bytes_per_pic_denom, "max_bytes_per_pic_denom");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->vui.i_max_bits_per_mb_denom, "max_bits_per_mb_denom");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->vui.i_log2_max_mv_length_horizontal, "log2_max_mv_length_horizontal");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->vui.i_log2_max_mv_length_vertical, "log2_max_mv_length_vertical");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->vui.i_num_reorder_frames, "max_num_reorder_frames");
|
||||
h264e_rkv_stream_write_ue_with_log(s, sps->vui.i_max_dec_frame_buffering, "max_dec_frame_buffering");
|
||||
}
|
||||
}
|
||||
h264e_rkv_stream_rbsp_trailing(s);
|
||||
h264e_rkv_stream_flush(s);
|
||||
|
||||
h264e_hal_dbg(H264E_DBG_HEADER, "write pure sps head size: %d bits", s->count_bit);
|
||||
|
||||
h264e_hal_leave();
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
static void h264e_rkv_scaling_list_write( H264eRkvStream *s,
|
||||
H264ePps *pps, RK_S32 idx )
|
||||
{
|
||||
RK_S32 k = 0;
|
||||
const RK_S32 len = idx < 4 ? 16 : 64;
|
||||
const RK_U8 *zigzag = idx < 4 ? h264e_zigzag_scan4[0] : h264e_zigzag_scan8[0];
|
||||
const RK_U8 *list = pps->scaling_list[idx];
|
||||
const RK_U8 *def_list = (idx == H264E_CQM_4IC) ? pps->scaling_list[H264E_CQM_4IY]
|
||||
: (idx == H264E_CQM_4PC) ? pps->scaling_list[H264E_CQM_4PY]
|
||||
: (idx == H264E_CQM_8IC + 4) ? pps->scaling_list[H264E_CQM_8IY + 4]
|
||||
: (idx == H264E_CQM_8PC + 4) ? pps->scaling_list[H264E_CQM_8PY + 4]
|
||||
: h264e_cqm_jvt[idx];
|
||||
if ( !memcmp( list, def_list, len ) )
|
||||
h264e_rkv_stream_write1_with_log( s, 0, "scaling_list_present_flag"); // scaling_list_present_flag
|
||||
else if ( !memcmp( list, h264e_cqm_jvt[idx], len ) ) {
|
||||
h264e_rkv_stream_write1_with_log( s, 1, "scaling_list_present_flag"); // scaling_list_present_flag
|
||||
h264e_rkv_stream_write_se_with_log( s, -8, "use_jvt_list"); // use jvt list
|
||||
} else {
|
||||
RK_S32 run;
|
||||
h264e_rkv_stream_write1_with_log( s, 1, "scaling_list_present_flag"); // scaling_list_present_flag
|
||||
|
||||
// try run-length compression of trailing values
|
||||
for ( run = len; run > 1; run-- )
|
||||
if ( list[zigzag[run - 1]] != list[zigzag[run - 2]] )
|
||||
break;
|
||||
if ( run < len && len - run < h264e_rkv_stream_size_se( (RK_S8) - list[zigzag[run]] ) )
|
||||
run = len;
|
||||
|
||||
for ( k = 0; k < run; k++ )
|
||||
h264e_rkv_stream_write_se_with_log( s, (RK_S8)(list[zigzag[k]] - (k > 0 ? list[zigzag[k - 1]] : 8)), "delta_scale"); // delta
|
||||
|
||||
if ( run < len )
|
||||
h264e_rkv_stream_write_se_with_log( s, (RK_S8) - list[zigzag[run]], "-scale");
|
||||
}
|
||||
}
|
||||
|
||||
static MPP_RET h264e_rkv_pps_write(H264ePps *pps, H264eSps *sps, H264eRkvStream *s)
|
||||
{
|
||||
h264e_hal_enter();
|
||||
|
||||
s->count_bit = 0;
|
||||
h264e_rkv_stream_realign( s );
|
||||
|
||||
h264e_rkv_stream_write_ue_with_log( s, pps->i_id, "pic_parameter_set_id");
|
||||
h264e_rkv_stream_write_ue_with_log( s, pps->i_sps_id, "seq_parameter_set_id");
|
||||
|
||||
h264e_rkv_stream_write1_with_log( s, pps->b_cabac, "entropy_coding_mode_flag");
|
||||
h264e_rkv_stream_write1_with_log( s, pps->b_pic_order, "bottom_field_pic_order_in_frame_present_flag");
|
||||
h264e_rkv_stream_write_ue_with_log( s, pps->i_num_slice_groups - 1, "num_slice_groups_minus1");
|
||||
|
||||
h264e_rkv_stream_write_ue_with_log( s, pps->i_num_ref_idx_l0_default_active - 1, "num_ref_idx_l0_default_active_minus1");
|
||||
h264e_rkv_stream_write_ue_with_log( s, pps->i_num_ref_idx_l1_default_active - 1, "num_ref_idx_l1_default_active_minus1");
|
||||
h264e_rkv_stream_write1_with_log( s, pps->b_weighted_pred, "weighted_pred_flag");
|
||||
h264e_rkv_stream_write_with_log( s, 2, pps->i_weighted_bipred_idc, "weighted_bipred_idc");
|
||||
|
||||
h264e_rkv_stream_write_se_with_log( s, pps->i_pic_init_qp - 26 - H264_QP_BD_OFFSET, "pic_init_qp_minus26");
|
||||
h264e_rkv_stream_write_se_with_log( s, pps->i_pic_init_qs - 26 - H264_QP_BD_OFFSET, "pic_init_qs_minus26");
|
||||
h264e_rkv_stream_write_se_with_log( s, pps->i_chroma_qp_index_offset, "chroma_qp_index_offset");
|
||||
|
||||
h264e_rkv_stream_write1_with_log( s, pps->b_deblocking_filter_control, "deblocking_filter_control_present_flag");
|
||||
h264e_rkv_stream_write1_with_log( s, pps->b_constrained_intra_pred, "constrained_intra_pred_flag");
|
||||
h264e_rkv_stream_write1_with_log( s, pps->b_redundant_pic_cnt, "redundant_pic_cnt_present_flag");
|
||||
|
||||
if ( pps->b_transform_8x8_mode || pps->b_cqm_preset != H264E_CQM_FLAT ) {
|
||||
h264e_rkv_stream_write1_with_log( s, pps->b_transform_8x8_mode, "transform_8x8_mode_flag");
|
||||
h264e_rkv_stream_write1_with_log( s, (pps->b_cqm_preset != H264E_CQM_FLAT), "pic_scaling_matrix_present_flag");
|
||||
if ( pps->b_cqm_preset != H264E_CQM_FLAT ) {
|
||||
h264e_rkv_scaling_list_write( s, pps, H264E_CQM_4IY);
|
||||
h264e_rkv_scaling_list_write( s, pps, H264E_CQM_4IC );
|
||||
h264e_rkv_stream_write1_with_log( s, 0, "scaling_list_end_flag"); // Cr = Cb TODO:replaced with real name
|
||||
h264e_rkv_scaling_list_write( s, pps, H264E_CQM_4PY );
|
||||
h264e_rkv_scaling_list_write( s, pps, H264E_CQM_4PC );
|
||||
h264e_rkv_stream_write1_with_log( s, 0, "scaling_list_end_flag"); // Cr = Cb TODO:replaced with real name
|
||||
if ( pps->b_transform_8x8_mode ) {
|
||||
if ( sps->i_chroma_format_idc == H264E_CHROMA_444 ) {
|
||||
h264e_rkv_scaling_list_write( s, pps, H264E_CQM_8IY + 4 );
|
||||
h264e_rkv_scaling_list_write( s, pps, H264E_CQM_8IC + 4 );
|
||||
h264e_rkv_stream_write1_with_log( s, 0, "scaling_list_end_flag" ); // Cr = Cb TODO:replaced with real name
|
||||
h264e_rkv_scaling_list_write( s, pps, H264E_CQM_8PY + 4 );
|
||||
h264e_rkv_scaling_list_write( s, pps, H264E_CQM_8PC + 4 );
|
||||
h264e_rkv_stream_write1_with_log( s, 0, "scaling_list_end_flag" ); // Cr = Cb TODO:replaced with real name
|
||||
} else {
|
||||
h264e_rkv_scaling_list_write( s, pps, H264E_CQM_8IY + 4 );
|
||||
h264e_rkv_scaling_list_write( s, pps, H264E_CQM_8PY + 4 );
|
||||
}
|
||||
}
|
||||
}
|
||||
h264e_rkv_stream_write_se_with_log( s, pps->i_second_chroma_qp_index_offset, "second_chroma_qp_index_offset");
|
||||
}
|
||||
|
||||
h264e_rkv_stream_rbsp_trailing( s );
|
||||
h264e_rkv_stream_flush( s );
|
||||
|
||||
h264e_hal_dbg(H264E_DBG_HEADER, "write pure pps size: %d bits", s->count_bit);
|
||||
|
||||
h264e_hal_leave();
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
void h264e_rkv_nal_start(H264eRkvExtraInfo *out, RK_S32 i_type,
|
||||
RK_S32 i_ref_idc)
|
||||
{
|
||||
H264eRkvStream *s = &out->stream;
|
||||
H264eRkvNal *nal = &out->nal[out->nal_num];
|
||||
|
||||
nal->i_ref_idc = i_ref_idc;
|
||||
nal->i_type = i_type;
|
||||
nal->b_long_startcode = 1;
|
||||
|
||||
nal->i_payload = 0;
|
||||
/* NOTE: consistent with stream_init */
|
||||
nal->p_payload = &s->buf_plus8[h264e_rkv_stream_get_pos(s) / 8];
|
||||
nal->i_padding = 0;
|
||||
}
|
||||
|
||||
void h264e_rkv_nal_end(H264eRkvExtraInfo *out)
|
||||
{
|
||||
H264eRkvNal *nal = &(out->nal[out->nal_num]);
|
||||
H264eRkvStream *s = &out->stream;
|
||||
/* NOTE: consistent with stream_init */
|
||||
RK_U8 *end = &s->buf_plus8[h264e_rkv_stream_get_pos(s) / 8];
|
||||
nal->i_payload = (RK_S32)(end - nal->p_payload);
|
||||
/*
|
||||
* Assembly implementation of nal_escape reads past the end of the input.
|
||||
* While undefined padding wouldn't actually affect the output,
|
||||
* it makes valgrind unhappy.
|
||||
*/
|
||||
memset(end, 0xff, 64);
|
||||
out->nal_num++;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_init_extra_info(H264eRkvExtraInfo *extra_info)
|
||||
{
|
||||
// random ID number generated according to ISO-11578
|
||||
// NOTE: any element of h264e_sei_uuid should NOT be 0x00,
|
||||
// otherwise the string length of sei_buf will always be the distance between the
|
||||
// element 0x00 address and the sei_buf start address.
|
||||
static const RK_U8 h264e_sei_uuid[H264E_UUID_LENGTH] = {
|
||||
0x63, 0xfc, 0x6a, 0x3c, 0xd8, 0x5c, 0x44, 0x1e,
|
||||
0x87, 0xfb, 0x3f, 0xab, 0xec, 0xb3, 0xb6, 0x77
|
||||
};
|
||||
|
||||
h264e_rkv_nals_init(extra_info);
|
||||
h264e_rkv_stream_init(&extra_info->stream);
|
||||
|
||||
extra_info->sei_buf = mpp_calloc_size(RK_U8, H264E_SEI_BUF_SIZE);
|
||||
memcpy(extra_info->sei_buf, h264e_sei_uuid, H264E_UUID_LENGTH);
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_deinit_extra_info(void *extra_info)
|
||||
{
|
||||
H264eRkvExtraInfo *info = (H264eRkvExtraInfo *)extra_info;
|
||||
h264e_rkv_stream_deinit(&info->stream);
|
||||
h264e_rkv_nals_deinit(info);
|
||||
|
||||
MPP_FREE(info->sei_buf);
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_set_extra_info(H264eHalContext *ctx)
|
||||
{
|
||||
H264eRkvExtraInfo *info = (H264eRkvExtraInfo *)ctx->extra_info;
|
||||
H264eSps *sps = &info->sps;
|
||||
H264ePps *pps = &info->pps;
|
||||
|
||||
h264e_hal_enter();
|
||||
|
||||
info->nal_num = 0;
|
||||
h264e_rkv_stream_reset(&info->stream);
|
||||
|
||||
h264e_rkv_nal_start(info, H264E_NAL_SPS, H264E_NAL_PRIORITY_HIGHEST);
|
||||
h264e_set_sps(ctx, sps);
|
||||
h264e_rkv_sps_write(sps, &info->stream);
|
||||
h264e_rkv_nal_end(info);
|
||||
|
||||
h264e_rkv_nal_start(info, H264E_NAL_PPS, H264E_NAL_PRIORITY_HIGHEST);
|
||||
h264e_set_pps(ctx, pps, sps);
|
||||
h264e_rkv_pps_write(pps, sps, &info->stream);
|
||||
h264e_rkv_nal_end(info);
|
||||
|
||||
h264e_rkv_encapsulate_nals(info);
|
||||
|
||||
h264e_hal_leave();
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_get_extra_info(H264eHalContext *ctx, MppPacket *pkt_out)
|
||||
{
|
||||
RK_S32 k = 0;
|
||||
size_t offset = 0;
|
||||
MppPacket pkt = ctx->packeted_param;
|
||||
H264eRkvExtraInfo *src = (H264eRkvExtraInfo *)ctx->extra_info;
|
||||
|
||||
for (k = 0; k < src->nal_num; k++) {
|
||||
h264e_hal_dbg(H264E_DBG_HEADER, "get extra info nal type %d, size %d bytes",
|
||||
src->nal[k].i_type, src->nal[k].i_payload);
|
||||
mpp_packet_write(pkt, offset, src->nal[k].p_payload, src->nal[k].i_payload);
|
||||
offset += src->nal[k].i_payload;
|
||||
}
|
||||
mpp_packet_set_length(pkt, offset);
|
||||
*pkt_out = pkt;
|
||||
|
||||
return MPP_OK;
|
||||
}
|
71
mpp/hal/rkenc/h264e/hal_h264e_rkv_nal.h
Normal file
71
mpp/hal/rkenc/h264e/hal_h264e_rkv_nal.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2015 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 __HAL_H264E_RKV_NAL_H__
|
||||
#define __HAL_H264E_RKV_NAL_H__
|
||||
|
||||
#include "hal_h264e_com.h"
|
||||
#include "hal_h264e_rkv_stream.h"
|
||||
|
||||
typedef enum H264eRkvNalIdx_t {
|
||||
H264E_RKV_NAL_IDX_SPS,
|
||||
H264E_RKV_NAL_IDX_PPS,
|
||||
H264E_RKV_NAL_IDX_SEI,
|
||||
H264E_RKV_NAL_IDX_BUTT,
|
||||
} H264eRkvNalIdx;
|
||||
|
||||
typedef struct H264eRkvNal_t {
|
||||
RK_S32 i_ref_idc; /* nal_priority_e */
|
||||
RK_S32 i_type; /* nal_unit_type_e */
|
||||
RK_S32 b_long_startcode;
|
||||
RK_S32 i_first_mb; /* If this NAL is a slice, the index of the first MB in the slice. */
|
||||
RK_S32 i_last_mb; /* If this NAL is a slice, the index of the last MB in the slice. */
|
||||
|
||||
/* Size of payload (including any padding) in bytes. */
|
||||
RK_S32 i_payload;
|
||||
/* If param->b_annexb is set, Annex-B bytestream with startcode.
|
||||
* Otherwise, startcode is replaced with a 4-byte size.
|
||||
* This size is the size used in mp4/similar muxing; it is equal to i_payload-4 */
|
||||
RK_U8 *p_payload;
|
||||
|
||||
/* Size of padding in bytes. */
|
||||
RK_S32 i_padding;
|
||||
RK_S32 sh_head_len;
|
||||
} H264eRkvNal;
|
||||
|
||||
typedef struct H264eRkvExtraInfo_t {
|
||||
RK_S32 nal_num;
|
||||
H264eRkvNal nal[H264E_RKV_NAL_IDX_BUTT];
|
||||
RK_U8 *nal_buf;
|
||||
RK_U8 *sei_buf;
|
||||
RK_U32 sei_change_flg;
|
||||
H264eRkvStream stream;
|
||||
H264eSps sps;
|
||||
H264ePps pps;
|
||||
H264eSei sei;
|
||||
} H264eRkvExtraInfo;
|
||||
|
||||
MPP_RET h264e_rkv_init_extra_info(H264eRkvExtraInfo *extra_info);
|
||||
MPP_RET h264e_rkv_deinit_extra_info(void *extra_info);
|
||||
void h264e_rkv_nal_start(H264eRkvExtraInfo *out, RK_S32 i_type,
|
||||
RK_S32 i_ref_idc);
|
||||
void h264e_rkv_nal_end(H264eRkvExtraInfo *out);
|
||||
MPP_RET h264e_rkv_set_extra_info(H264eHalContext *ctx);
|
||||
|
||||
MPP_RET h264e_rkv_get_extra_info(H264eHalContext *ctx, MppPacket *pkt_out);
|
||||
MPP_RET h264e_rkv_sei_encode(H264eHalContext *ctx, RcSyntax *rc_syn);
|
||||
|
||||
#endif /* __HAL_H264E_RKV_NAL_H__ */
|
257
mpp/hal/rkenc/h264e/hal_h264e_rkv_stream.c
Normal file
257
mpp/hal/rkenc/h264e/hal_h264e_rkv_stream.c
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright 2015 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 "mpp_common.h"
|
||||
#include "mpp_mem.h"
|
||||
#include "hal_h264e_com.h"
|
||||
#include "hal_h264e_rkv_stream.h"
|
||||
|
||||
static const RK_U8 h264e_ue_size_tab[256] = {
|
||||
1, 1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
};
|
||||
|
||||
RK_S32 h264e_rkv_stream_get_pos(H264eRkvStream *s)
|
||||
{
|
||||
return (RK_S32)(8 * (s->p - s->p_start) + (4 * 8) - s->i_left);
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_stream_init(H264eRkvStream *s)
|
||||
{
|
||||
RK_S32 offset = 0;
|
||||
s->buf = mpp_calloc(RK_U8, H264E_EXTRA_INFO_BUF_SIZE);
|
||||
s->buf_plus8 = s->buf + 8; //NOTE: prepare for align
|
||||
|
||||
offset = (size_t)(s->buf_plus8) & 3;
|
||||
s->p = s->p_start = s->buf_plus8 - offset;
|
||||
//s->p_end = (RK_U8*)s->buf + i_data;
|
||||
s->i_left = (4 - offset) * 8;
|
||||
//s->cur_bits = endian_fix32(M32(s->p));
|
||||
s->cur_bits = (*(s->p) << 24) + (*(s->p + 1) << 16)
|
||||
+ (*(s->p + 2) << 8) + (*(s->p + 3) << 0);
|
||||
s->cur_bits >>= (4 - offset) * 8;
|
||||
s->count_bit = 0;
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_stream_deinit(H264eRkvStream *s)
|
||||
{
|
||||
MPP_FREE(s->buf);
|
||||
|
||||
s->p = NULL;
|
||||
s->p_start = NULL;
|
||||
//s->p_end = NULL;
|
||||
|
||||
s->i_left = 0;
|
||||
s->cur_bits = 0;
|
||||
s->count_bit = 0;
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_stream_reset(H264eRkvStream *s)
|
||||
{
|
||||
RK_S32 offset = 0;
|
||||
h264e_hal_enter();
|
||||
|
||||
offset = (size_t)(s->buf_plus8) & 3;
|
||||
s->p = s->p_start;
|
||||
s->i_left = (4 - offset) * 8;
|
||||
s->cur_bits = (*(s->p) << 24) + (*(s->p + 1) << 16)
|
||||
+ (*(s->p + 2) << 8) + (*(s->p + 3) << 0);
|
||||
s->cur_bits >>= (4 - offset) * 8;
|
||||
s->count_bit = 0;
|
||||
|
||||
h264e_hal_leave();
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_stream_realign(H264eRkvStream *s)
|
||||
{
|
||||
RK_S32 offset = (size_t)(s->p) & 3; //used to judge alignment
|
||||
if (offset) {
|
||||
s->p = s->p - offset; //move pointer to 32bit aligned pos
|
||||
s->i_left = (4 - offset) * 8; //init
|
||||
//s->cur_bits = endian_fix32(M32(s->p));
|
||||
s->cur_bits = (*(s->p) << 24) + (*(s->p + 1) << 16)
|
||||
+ (*(s->p + 2) << 8) + (*(s->p + 3) << 0);
|
||||
s->cur_bits >>= (4 - offset) * 8; //shift right the invalid bit
|
||||
}
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_stream_write_with_log(H264eRkvStream *s,
|
||||
RK_S32 i_count, RK_U32 val, char *name)
|
||||
{
|
||||
RK_U32 i_bits = val;
|
||||
|
||||
h264e_hal_dbg(H264E_DBG_HEADER, "write bits name %s, count %d, val %d",
|
||||
name, i_count, val);
|
||||
|
||||
s->count_bit += i_count;
|
||||
if (i_count < s->i_left) {
|
||||
s->cur_bits = (s->cur_bits << i_count) | i_bits;
|
||||
s->i_left -= i_count;
|
||||
} else {
|
||||
i_count -= s->i_left;
|
||||
s->cur_bits = (s->cur_bits << s->i_left) | (i_bits >> i_count);
|
||||
//M32(s->p) = endian_fix32(s->cur_bits);
|
||||
*(s->p) = 0;
|
||||
*(s->p) = (s->cur_bits >> 24) & 0xff;
|
||||
*(s->p + 1) = (s->cur_bits >> 16) & 0xff;
|
||||
*(s->p + 2) = (s->cur_bits >> 8) & 0xff;
|
||||
*(s->p + 3) = (s->cur_bits >> 0) & 0xff;
|
||||
s->p += 4;
|
||||
s->cur_bits = i_bits;
|
||||
s->i_left = 32 - i_count;
|
||||
}
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_stream_write1_with_log(H264eRkvStream *s,
|
||||
RK_U32 val, char *name)
|
||||
{
|
||||
RK_U32 i_bit = val;
|
||||
|
||||
h264e_hal_dbg(H264E_DBG_HEADER, "write 1 bit name %s, val %d", name, val);
|
||||
|
||||
s->count_bit += 1;
|
||||
s->cur_bits <<= 1;
|
||||
s->cur_bits |= i_bit;
|
||||
s->i_left--;
|
||||
if (s->i_left == 4 * 8 - 32) {
|
||||
//M32(s->p) = endian_fix32(s->cur_bits);
|
||||
*(s->p) = (s->cur_bits >> 24) & 0xff;
|
||||
*(s->p + 1) = (s->cur_bits >> 16) & 0xff;
|
||||
*(s->p + 2) = (s->cur_bits >> 8) & 0xff;
|
||||
*(s->p + 3) = (s->cur_bits >> 0) & 0xff;
|
||||
s->p += 4;
|
||||
s->i_left = 4 * 8;
|
||||
}
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_stream_write_ue_with_log(H264eRkvStream *s,
|
||||
RK_U32 val, char *name)
|
||||
{
|
||||
RK_S32 size = 0;
|
||||
RK_S32 tmp = ++val;
|
||||
|
||||
h264e_hal_dbg(H264E_DBG_HEADER,
|
||||
"write UE bits name %s, val %d (2 steps below are real writting)",
|
||||
name, val);
|
||||
if (tmp >= 0x10000) {
|
||||
size = 32;
|
||||
tmp >>= 16;
|
||||
}
|
||||
if (tmp >= 0x100) {
|
||||
size += 16;
|
||||
tmp >>= 8;
|
||||
}
|
||||
size += h264e_ue_size_tab[tmp];
|
||||
|
||||
h264e_rkv_stream_write_with_log(s, size >> 1, 0, name);
|
||||
h264e_rkv_stream_write_with_log(s, (size >> 1) + 1, val, name);
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_stream_write_se_with_log(H264eRkvStream *s,
|
||||
RK_S32 val, char *name)
|
||||
{
|
||||
RK_S32 size = 0;
|
||||
RK_S32 tmp = 1 - val * 2;
|
||||
if (tmp < 0)
|
||||
tmp = val * 2;
|
||||
|
||||
val = tmp;
|
||||
if (tmp >= 0x100) {
|
||||
size = 16;
|
||||
tmp >>= 8;
|
||||
}
|
||||
size += h264e_ue_size_tab[tmp];
|
||||
|
||||
return h264e_rkv_stream_write_with_log(s, size, val, name);
|
||||
}
|
||||
|
||||
MPP_RET
|
||||
h264e_rkv_stream_write32(H264eRkvStream *s, RK_U32 i_bits, char *name)
|
||||
{
|
||||
h264e_rkv_stream_write_with_log(s, 16, i_bits >> 16, name);
|
||||
h264e_rkv_stream_write_with_log(s, 16, i_bits , name);
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
RK_S32 h264e_rkv_stream_size_se( RK_S32 val )
|
||||
{
|
||||
RK_S32 tmp = 1 - val * 2;
|
||||
if ( tmp < 0 ) tmp = val * 2;
|
||||
if ( tmp < 256 )
|
||||
return h264e_ue_size_tab[tmp];
|
||||
else
|
||||
return h264e_ue_size_tab[tmp >> 8] + 16;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_stream_rbsp_trailing(H264eRkvStream *s)
|
||||
{
|
||||
//align bits, 1+N zeros.
|
||||
h264e_rkv_stream_write1_with_log(s, 1, "align_1_bit");
|
||||
h264e_rkv_stream_write_with_log(s, s->i_left & 7, 0, "align_N_bits");
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the rest of cur_bits to the bitstream;
|
||||
* results in a bitstream no longer 32-bit aligned.
|
||||
*/
|
||||
MPP_RET h264e_rkv_stream_flush(H264eRkvStream *s)
|
||||
{
|
||||
//do 4 bytes aligned
|
||||
//M32(s->p) = endian_fix32(s->cur_bits << (s->i_left & 31));
|
||||
RK_U32 tmp_bit = s->cur_bits << (s->i_left & 31);
|
||||
*(s->p) = (tmp_bit >> 24) & 0xff;
|
||||
*(s->p + 1) = (tmp_bit >> 16) & 0xff;
|
||||
*(s->p + 2) = (tmp_bit >> 8) & 0xff;
|
||||
*(s->p + 3) = (tmp_bit >> 0) & 0xff;
|
||||
/*
|
||||
* p point to bit which aligned, rather than
|
||||
* the pos next to 4-byte alinged
|
||||
*/
|
||||
s->p += 4 - (s->i_left >> 3);
|
||||
s->i_left = 4 * 8;
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
|
55
mpp/hal/rkenc/h264e/hal_h264e_rkv_stream.h
Normal file
55
mpp/hal/rkenc/h264e/hal_h264e_rkv_stream.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2015 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 __HAL_H264E_RKV_STREAM_H__
|
||||
#define __HAL_H264E_RKV_STREAM_H__
|
||||
|
||||
#include "h264_syntax.h"
|
||||
|
||||
typedef struct H264eRkvStream_t {
|
||||
RK_U8 *p_start;
|
||||
RK_U8 *p;
|
||||
//RK_U8 *p_end;
|
||||
|
||||
RK_U32 cur_bits;
|
||||
RK_S32 i_left; /* i_count number of available bits */
|
||||
|
||||
//add buf pointer
|
||||
RK_U8 *buf;
|
||||
RK_U8 *buf_plus8;
|
||||
RK_U32 count_bit; /* only for debug */
|
||||
} H264eRkvStream;
|
||||
|
||||
MPP_RET h264e_rkv_stream_init(H264eRkvStream *s);
|
||||
MPP_RET h264e_rkv_stream_deinit(H264eRkvStream *s);
|
||||
RK_S32 h264e_rkv_stream_get_pos(H264eRkvStream *s);
|
||||
MPP_RET h264e_rkv_stream_reset(H264eRkvStream *s);
|
||||
MPP_RET h264e_rkv_stream_realign(H264eRkvStream *s);
|
||||
MPP_RET h264e_rkv_stream_write_with_log(H264eRkvStream *s,
|
||||
RK_S32 i_count, RK_U32 val, char *name);
|
||||
MPP_RET h264e_rkv_stream_write1_with_log(H264eRkvStream *s,
|
||||
RK_U32 val, char *name);
|
||||
MPP_RET h264e_rkv_stream_write_ue_with_log(H264eRkvStream *s,
|
||||
RK_U32 val, char *name);
|
||||
MPP_RET h264e_rkv_stream_write_se_with_log(H264eRkvStream *s,
|
||||
RK_S32 val, char *name);
|
||||
MPP_RET h264e_rkv_stream_write32(H264eRkvStream *s, RK_U32 i_bits,
|
||||
char *name);
|
||||
RK_S32 h264e_rkv_stream_size_se( RK_S32 val );
|
||||
MPP_RET h264e_rkv_stream_rbsp_trailing(H264eRkvStream *s);
|
||||
MPP_RET h264e_rkv_stream_flush(H264eRkvStream *s);
|
||||
|
||||
#endif /* __HAL_H264E_RKV_STREAM_H__ */
|
75
mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.c
Normal file
75
mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2015 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 <string.h>
|
||||
|
||||
#include "mpp_device.h"
|
||||
#include "hal_h264e_rkv_utils.h"
|
||||
|
||||
#define H264E_IOC_CUSTOM_BASE 0x1000
|
||||
#define H264E_IOC_SET_OSD_PLT (H264E_IOC_CUSTOM_BASE + 1)
|
||||
|
||||
MPP_RET h264e_rkv_set_osd_plt(H264eHalContext *ctx, void *param)
|
||||
{
|
||||
MppEncOSDPlt *plt = (MppEncOSDPlt *)param;
|
||||
h264e_hal_enter();
|
||||
|
||||
if (plt->buf) {
|
||||
ctx->osd_plt_type = H264E_OSD_PLT_TYPE_USERDEF;
|
||||
#ifdef RKPLATFORM
|
||||
if (MPP_OK != mpp_device_send_reg_with_id(ctx->vpu_fd,
|
||||
H264E_IOC_SET_OSD_PLT, param,
|
||||
sizeof(MppEncOSDPlt))) {
|
||||
h264e_hal_err("set osd plt error");
|
||||
return MPP_NOK;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
ctx->osd_plt_type = H264E_OSD_PLT_TYPE_DEFAULT;
|
||||
}
|
||||
|
||||
h264e_hal_leave();
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET h264e_rkv_set_osd_data(H264eHalContext *ctx, void *param)
|
||||
{
|
||||
MppEncOSDData *src = (MppEncOSDData *)param;
|
||||
MppEncOSDData *dst = &ctx->osd_data;
|
||||
RK_U32 num = src->num_region;
|
||||
|
||||
h264e_hal_enter();
|
||||
if (ctx->osd_plt_type == H264E_OSD_PLT_TYPE_NONE)
|
||||
mpp_err("warning: plt type is invalid\n");
|
||||
|
||||
if (num > 8) {
|
||||
h264e_hal_err("number of region %d exceed maxinum 8");
|
||||
return MPP_NOK;
|
||||
}
|
||||
|
||||
if (num) {
|
||||
dst->num_region = num;
|
||||
if (src->buf) {
|
||||
dst->buf = src->buf;
|
||||
memcpy(dst->region, src->region, num * sizeof(MppEncOSDRegion));
|
||||
}
|
||||
} else {
|
||||
memset(dst, 0, sizeof(*dst));
|
||||
}
|
||||
|
||||
h264e_hal_leave();
|
||||
return MPP_OK;
|
||||
}
|
33
mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.h
Normal file
33
mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2015 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 __HAL_H264E_RKV_UTILS_H__
|
||||
#define __HAL_H264E_RKV_UTILS_H__
|
||||
|
||||
#include "hal_h264e_com.h"
|
||||
|
||||
// TODO: add ROI function
|
||||
typedef struct h264e_hal_rkv_roi_cfg_t {
|
||||
RK_U8 qp_y : 6;
|
||||
RK_U8 set_qp_y_en : 1;
|
||||
RK_U8 forbid_inter : 1;
|
||||
} h264e_hal_rkv_roi_cfg;
|
||||
|
||||
MPP_RET h264e_rkv_set_osd_plt(H264eHalContext *ctx, void *param);
|
||||
MPP_RET h264e_rkv_set_osd_data(H264eHalContext *ctx, void *param);
|
||||
|
||||
|
||||
#endif /* __HAL_H264E_RKV_UTILS_H__ */
|
Reference in New Issue
Block a user