[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:
timkingh.huang
2017-11-22 11:51:40 +08:00
parent 687c940566
commit 47da174ef9
13 changed files with 1713 additions and 1513 deletions

View File

@@ -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,

View File

@@ -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__

View File

@@ -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

View File

@@ -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);

View 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;
}

View 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__ */

View 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;
}

View 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__ */

View 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;
}

View 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__ */

View 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;
}

View 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__ */