mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-12-26 11:17:44 +01:00
[h264e]: Add H.264 sw_reenc pskip path
1. Add pps on slice update for pic_init_qp. 2. Add cabac and cavlc pskip sw encode path. 3. Add dpb rollback for reenc path. Signed-off-by: Herman Chen <herman.chen@rock-chips.com> Change-Id: I8d39cfeabcf669f66cd4e4d5ea5e08e4217d3a0e
This commit is contained in:
parent
c182090ddd
commit
4c625f0e3c
5 changed files with 371 additions and 56 deletions
|
|
@ -317,10 +317,11 @@ static MPP_RET h264e_proc_prep_cfg(MppEncPrepCfg *dst, MppEncPrepCfg *src)
|
|||
}
|
||||
}
|
||||
|
||||
src->change = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static MPP_RET h264e_proc_rc_cfg(MppEncRcCfg *dst, MppEncRcCfg *src)
|
||||
static MPP_RET h264e_proc_rc_cfg(MppEncRcCfg *dst, MppEncRcCfg *src, MppEncH264Cfg *h264)
|
||||
{
|
||||
MPP_RET ret = MPP_OK;
|
||||
RK_U32 change = src->change;
|
||||
|
|
@ -393,6 +394,13 @@ static MPP_RET h264e_proc_rc_cfg(MppEncRcCfg *dst, MppEncRcCfg *src)
|
|||
ret = MPP_ERR_VALUE;
|
||||
}
|
||||
}
|
||||
if (dst->drop_mode == MPP_ENC_RC_DROP_FRM_PSKIP &&
|
||||
dst->drop_gap == 0 &&
|
||||
h264->poc_type == 2) {
|
||||
mpp_err("poc type 2 is ocnflict with successive non-reference pskip mode\n");
|
||||
mpp_err("set drop gap to 1\n");
|
||||
dst->drop_gap = 1;
|
||||
}
|
||||
|
||||
dst->change |= change;
|
||||
|
||||
|
|
@ -406,6 +414,7 @@ static MPP_RET h264e_proc_rc_cfg(MppEncRcCfg *dst, MppEncRcCfg *src)
|
|||
}
|
||||
}
|
||||
|
||||
src->change = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -529,6 +538,7 @@ static MPP_RET h264e_proc_h264_cfg(MppEncH264Cfg *dst, MppEncH264Cfg *src)
|
|||
dst->change |= MPP_ENC_H264_CFG_CHANGE_BASE_LAYER_PID;
|
||||
}
|
||||
|
||||
src->change = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -546,6 +556,7 @@ static MPP_RET h264e_proc_split_cfg(MppEncSliceSplit *dst, MppEncSliceSplit *src
|
|||
dst->split_arg = src->split_arg;
|
||||
|
||||
dst->change |= change;
|
||||
src->change = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -563,28 +574,23 @@ static MPP_RET h264e_proc_cfg(void *ctx, MpiCmd cmd, void *param)
|
|||
MppEncCfgImpl *impl = (MppEncCfgImpl *)param;
|
||||
MppEncCfgSet *src = &impl->cfg;
|
||||
|
||||
if (src->prep.change) {
|
||||
if (src->prep.change)
|
||||
ret |= h264e_proc_prep_cfg(&cfg->prep, &src->prep);
|
||||
src->prep.change = 0;
|
||||
}
|
||||
if (src->rc.change) {
|
||||
ret |= h264e_proc_rc_cfg(&cfg->rc, &src->rc);
|
||||
src->rc.change = 0;
|
||||
}
|
||||
if (src->codec.h264.change) {
|
||||
|
||||
if (src->codec.h264.change)
|
||||
ret |= h264e_proc_h264_cfg(&cfg->codec.h264, &src->codec.h264);
|
||||
src->codec.h264.change = 0;
|
||||
}
|
||||
if (src->split.change) {
|
||||
|
||||
if (src->rc.change)
|
||||
ret |= h264e_proc_rc_cfg(&cfg->rc, &src->rc, &cfg->codec.h264);
|
||||
|
||||
if (src->split.change)
|
||||
ret |= h264e_proc_split_cfg(&cfg->split, &src->split);
|
||||
src->split.change = 0;
|
||||
}
|
||||
} break;
|
||||
case MPP_ENC_SET_PREP_CFG : {
|
||||
ret = h264e_proc_prep_cfg(&cfg->prep, param);
|
||||
} break;
|
||||
case MPP_ENC_SET_RC_CFG : {
|
||||
ret = h264e_proc_rc_cfg(&cfg->rc, param);
|
||||
ret = h264e_proc_rc_cfg(&cfg->rc, param, &cfg->codec.h264);
|
||||
} break;
|
||||
case MPP_ENC_SET_CODEC_CFG : {
|
||||
MppEncCodecCfg *codec = (MppEncCodecCfg *)param;
|
||||
|
|
@ -705,7 +711,7 @@ static MPP_RET h264e_proc_dpb(void *ctx, HalEncTask *task)
|
|||
refr = dpb->refr;
|
||||
|
||||
// update slice info
|
||||
h264e_slice_update(&p->slice, p->cfg, &p->sps, dpb->curr);
|
||||
h264e_slice_update(&p->slice, p->cfg, &p->sps, &p->pps, dpb->curr);
|
||||
|
||||
// update frame usage
|
||||
frms->seq_idx = curr->seq_idx;
|
||||
|
|
@ -790,6 +796,45 @@ static MPP_RET h264e_proc_hal(void *ctx, HalEncTask *task)
|
|||
return MPP_OK;
|
||||
}
|
||||
|
||||
static MPP_RET h264e_sw_enc(void *ctx, HalEncTask *task)
|
||||
{
|
||||
H264eCtx *p = (H264eCtx *)ctx;
|
||||
MppEncH264Cfg *h264 = &p->cfg->codec.h264;
|
||||
EncRcTaskInfo *rc_info = &task->rc_task->info;
|
||||
MppPacket packet = task->packet;
|
||||
void *pos = mpp_packet_get_pos(packet);
|
||||
void *data = mpp_packet_get_data(packet);
|
||||
size_t size = mpp_packet_get_size(packet);
|
||||
size_t length = mpp_packet_get_length(packet);
|
||||
void *base = pos + length;
|
||||
RK_S32 buf_size = (data + size) - (pos + length);
|
||||
RK_S32 slice_len = 0;
|
||||
RK_S32 final_len = 0;
|
||||
|
||||
if (h264->prefix_mode || h264->max_tid) {
|
||||
/* add prefix first */
|
||||
RK_S32 prefix_bit = h264e_slice_write_prefix_nal_unit_svc(&p->prefix, base, buf_size);
|
||||
|
||||
prefix_bit = (prefix_bit + 7) / 8;
|
||||
|
||||
base += prefix_bit;
|
||||
buf_size -= prefix_bit;
|
||||
final_len += prefix_bit;
|
||||
}
|
||||
|
||||
/* write slice header */
|
||||
slice_len = h264e_slice_write_pskip(&p->slice, base, buf_size);
|
||||
slice_len = (slice_len + 7) / 8;
|
||||
final_len += slice_len;
|
||||
|
||||
task->length += final_len;
|
||||
|
||||
rc_info->bit_real = task->length;
|
||||
rc_info->quality_real = rc_info->quality_target;
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
MPP_RET h264e_add_sei(MppPacket pkt, RK_S32 *length, RK_U8 uuid[16],
|
||||
const void *data, RK_S32 size)
|
||||
{
|
||||
|
|
@ -816,5 +861,5 @@ const EncImplApi api_h264e = {
|
|||
h264e_proc_dpb,
|
||||
h264e_proc_hal,
|
||||
h264e_add_sei,
|
||||
NULL,
|
||||
h264e_sw_enc,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -120,8 +120,8 @@ MPP_RET h264e_dpb_setup(H264eDpb *dpb, MppEncCfgSet* cfg, H264eSps *sps)
|
|||
dpb->dpb_size = info->dpb_size;
|
||||
dpb->total_cnt = info->dpb_size + 1;
|
||||
dpb->max_frm_num = 1 << log2_max_frm_num;
|
||||
dpb->max_poc_lsb = 1 << log2_max_poc_lsb;
|
||||
dpb->poc_msb = (1 << log2_max_poc_lsb);
|
||||
dpb->max_poc_lsb = (1 << log2_max_poc_lsb);
|
||||
dpb->poc_type = sps->pic_order_cnt_type;
|
||||
|
||||
h264e_dbg_dpb("max ref frm num %d total slot %d\n",
|
||||
ref_frm_num, dpb->total_cnt);
|
||||
|
|
@ -404,6 +404,7 @@ MPP_RET h264e_dpb_proc(H264eDpb *dpb, EncCpbStatus *cpb)
|
|||
EncFrmStatus *refr = &cpb->refr;
|
||||
EncFrmStatus *init = cpb->init;
|
||||
H264eDpbFrm *frames = dpb->frames;
|
||||
H264eDpbRt *rt = &dpb->rt;
|
||||
RK_S32 used_size = 0;
|
||||
RK_S32 seq_idx = curr->seq_idx;
|
||||
RK_S32 i;
|
||||
|
|
@ -418,6 +419,12 @@ MPP_RET h264e_dpb_proc(H264eDpb *dpb, EncCpbStatus *cpb)
|
|||
dpb->used_size = 0;
|
||||
dpb->curr_max_lt_idx = 0;
|
||||
dpb->next_max_lt_idx = 0;
|
||||
} else {
|
||||
if (curr->seq_idx == rt->last_seq_idx) {
|
||||
h264e_dbg_dpb("NOTE: reenc found at %d\n", curr->seq_idx);
|
||||
memcpy(rt, &dpb->rt_bak, sizeof(*rt));
|
||||
memcpy(frames, dpb->frm_bak, sizeof(dpb->frm_bak));
|
||||
}
|
||||
}
|
||||
|
||||
if (h264e_debug & H264E_DBG_DPB)
|
||||
|
|
@ -427,9 +434,13 @@ MPP_RET h264e_dpb_proc(H264eDpb *dpb, EncCpbStatus *cpb)
|
|||
* user defined cpb to hal slot index
|
||||
*/
|
||||
for (i = 0; i < MAX_CPB_REFS; i++) {
|
||||
dpb->map[i] = find_cpb_frame(frames, dpb->total_cnt, &init[i]);
|
||||
if (dpb->map[i]) {
|
||||
dpb->map[i]->on_used = 1;
|
||||
H264eDpbFrm *frm = find_cpb_frame(frames, dpb->total_cnt, &init[i]);
|
||||
dpb->map[i] = frm;
|
||||
if (frm) {
|
||||
if (!frm->on_used)
|
||||
mpp_err_f("warning frm %d is used by cpb but on not used status\n",
|
||||
frm->seq_idx);
|
||||
frm->on_used = 1;
|
||||
used_size++;
|
||||
}
|
||||
}
|
||||
|
|
@ -438,6 +449,10 @@ MPP_RET h264e_dpb_proc(H264eDpb *dpb, EncCpbStatus *cpb)
|
|||
h264e_dbg_dpb("frm %d init cpb used size %d vs %d\n", seq_idx,
|
||||
used_size, dpb->used_size);
|
||||
|
||||
/* backup current runtime status */
|
||||
memcpy(&dpb->rt_bak, rt, sizeof(dpb->rt_bak));
|
||||
memcpy(dpb->frm_bak, frames, sizeof(dpb->frm_bak));
|
||||
|
||||
/* mark current cpb */
|
||||
RK_S32 found_curr = 0;
|
||||
|
||||
|
|
@ -447,6 +462,9 @@ MPP_RET h264e_dpb_proc(H264eDpb *dpb, EncCpbStatus *cpb)
|
|||
h264e_dbg_dpb("frm %d start finding slot for storage\n", seq_idx);
|
||||
for (i = 0; i < H264E_MAX_REFS_CNT + 1; i++) {
|
||||
H264eDpbFrm *p = &frames[i];
|
||||
RK_S32 curr_frm_num = rt->last_frm_num + rt->last_is_ref;
|
||||
RK_S32 curr_poc_lsb = rt->last_poc_lsb;
|
||||
RK_S32 curr_poc_msb = rt->last_poc_msb;
|
||||
RK_S32 valid = 0;
|
||||
RK_S32 j;
|
||||
|
||||
|
|
@ -480,24 +498,38 @@ MPP_RET h264e_dpb_proc(H264eDpb *dpb, EncCpbStatus *cpb)
|
|||
if (curr->is_idr) {
|
||||
p->frame_num = 0;
|
||||
p->poc = 0;
|
||||
dpb->last_poc_lsb = 0;
|
||||
dpb->last_poc_msb = 0;
|
||||
curr_frm_num = 0;
|
||||
curr_poc_lsb = 0;
|
||||
curr_poc_msb = 0;
|
||||
} else {
|
||||
p->frame_num = dpb->last_frm_num;
|
||||
p->poc = dpb->last_poc_lsb + dpb->last_poc_msb * dpb->poc_msb;
|
||||
if (curr_frm_num >= dpb->max_frm_num)
|
||||
curr_frm_num = 0;
|
||||
|
||||
p->frame_num = curr_frm_num;
|
||||
|
||||
if (dpb->poc_type == 0)
|
||||
curr_poc_lsb += 2;
|
||||
else if (dpb->poc_type == 2)
|
||||
curr_poc_lsb += 1 + rt->last_is_ref;
|
||||
else
|
||||
mpp_err_f("do not support poc type 1\n");
|
||||
|
||||
if (curr_poc_lsb >= dpb->max_poc_lsb) {
|
||||
curr_poc_lsb = 0;
|
||||
curr_poc_msb++;
|
||||
}
|
||||
|
||||
p->poc = curr_poc_lsb + curr_poc_msb * dpb->max_poc_lsb;
|
||||
|
||||
}
|
||||
p->lt_idx = curr->lt_idx;
|
||||
p->on_used = 1;
|
||||
|
||||
dpb->last_frm_num = p->frame_num + !curr->is_non_ref;
|
||||
if (dpb->last_frm_num >= dpb->max_frm_num)
|
||||
dpb->last_frm_num = 0;
|
||||
|
||||
dpb->last_poc_lsb += 2;
|
||||
if (dpb->last_poc_lsb >= dpb->max_poc_lsb) {
|
||||
dpb->last_poc_lsb = 0;
|
||||
dpb->last_poc_msb++;
|
||||
}
|
||||
rt->last_seq_idx = curr->seq_idx;
|
||||
rt->last_is_ref = !curr->is_non_ref;
|
||||
rt->last_frm_num = curr_frm_num;
|
||||
rt->last_poc_lsb = curr_poc_lsb;
|
||||
rt->last_poc_msb = curr_poc_msb;
|
||||
|
||||
found_curr = 1;
|
||||
h264e_dbg_dpb("frm %d update slot %d with frame_num %d poc %d\n",
|
||||
|
|
@ -664,4 +696,3 @@ void h264e_dpb_check(H264eDpb *dpb, EncCpbStatus *cpb)
|
|||
|
||||
h264e_dbg_dpb("leave %p\n", dpb);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,15 @@ typedef struct H264eDpbFrm_t {
|
|||
RK_S64 pts;
|
||||
} H264eDpbFrm;
|
||||
|
||||
/* runtime status record */
|
||||
typedef struct H264eDpbRt_t {
|
||||
RK_S32 last_seq_idx;
|
||||
RK_S32 last_is_ref;
|
||||
RK_S32 last_frm_num;
|
||||
RK_S32 last_poc_lsb;
|
||||
RK_S32 last_poc_msb;
|
||||
} H264eDpbRt;
|
||||
|
||||
/*
|
||||
* dpb frame arrangement
|
||||
*
|
||||
|
|
@ -92,22 +101,27 @@ typedef struct H264eDpb_t {
|
|||
RK_S32 dpb_size;
|
||||
RK_S32 total_cnt;
|
||||
|
||||
/* status on dpb rebuild is needed */
|
||||
RK_S32 max_frm_num;
|
||||
RK_S32 max_poc_lsb;
|
||||
RK_S32 poc_msb;
|
||||
RK_S32 poc_type;
|
||||
|
||||
RK_S32 last_frm_num;
|
||||
RK_S32 last_poc_lsb;
|
||||
RK_S32 last_poc_msb;
|
||||
|
||||
H264eDpbFrm *curr;
|
||||
H264eDpbFrm *refr;
|
||||
H264eDpbFrm *list[H264E_MAX_REFS_CNT];
|
||||
H264eDpbFrm *stref[H264E_MAX_REFS_CNT];
|
||||
H264eDpbFrm *ltref[H264E_MAX_REFS_CNT];
|
||||
H264eDpbFrm *map[H264E_MAX_REFS_CNT + 1];
|
||||
H264eDpbFrm *curr;
|
||||
H264eDpbFrm *refr;
|
||||
H264eDpbFrm *list[H264E_MAX_REFS_CNT];
|
||||
H264eDpbFrm *stref[H264E_MAX_REFS_CNT];
|
||||
H264eDpbFrm *ltref[H264E_MAX_REFS_CNT];
|
||||
H264eDpbFrm *map[H264E_MAX_REFS_CNT + 1];
|
||||
|
||||
// frame storage
|
||||
H264eDpbFrm frames[H264E_MAX_REFS_CNT + 1];
|
||||
H264eDpbRt rt;
|
||||
H264eDpbRt rt_bak;
|
||||
H264eDpbFrm frames[H264E_MAX_REFS_CNT + 1];
|
||||
H264eDpbFrm frm_bak[H264E_MAX_REFS_CNT + 1];
|
||||
} H264eDpb;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -40,16 +40,19 @@ void h264e_slice_init(H264eSlice *slice, H264eReorderInfo *reorder,
|
|||
}
|
||||
|
||||
RK_S32 h264e_slice_update(H264eSlice *slice, MppEncCfgSet *cfg,
|
||||
H264eSps *sps, H264eDpbFrm *frm)
|
||||
H264eSps *sps, H264ePps *pps, H264eDpbFrm *frm)
|
||||
{
|
||||
MppEncH264Cfg *h264 = &cfg->codec.h264;
|
||||
RK_S32 is_idr = frm->status.is_idr;
|
||||
|
||||
slice->mb_w = sps->pic_width_in_mbs;
|
||||
slice->mb_h = sps->pic_height_in_mbs;
|
||||
slice->max_num_ref_frames = sps->num_ref_frames;
|
||||
slice->log2_max_frame_num = sps->log2_max_frame_num_minus4 + 4;
|
||||
slice->log2_max_poc_lsb = sps->log2_max_poc_lsb_minus4 + 4;
|
||||
slice->entropy_coding_mode = h264->entropy_coding_mode;
|
||||
slice->pic_order_cnt_type = sps->pic_order_cnt_type;
|
||||
slice->qp_init = pps->pic_init_qp;
|
||||
|
||||
slice->nal_reference_idc = (frm->status.is_non_ref) ? (H264_NALU_PRIORITY_DISPOSABLE) :
|
||||
(is_idr) ? (H264_NALU_PRIORITY_HIGHEST) :
|
||||
|
|
@ -510,20 +513,12 @@ RK_S32 h264e_slice_read(H264eSlice *slice, void *p, RK_S32 size)
|
|||
return bit_cnt;
|
||||
}
|
||||
|
||||
RK_S32 h264e_slice_write(H264eSlice *slice, void *p, RK_U32 size)
|
||||
void h264e_slice_write_header(H264eSlice *slice, MppWriteCtx *s)
|
||||
{
|
||||
MppWriteCtx stream;
|
||||
MppWriteCtx *s = &stream;
|
||||
RK_S32 i;
|
||||
RK_S32 bitCnt = 0;
|
||||
H264eMarkingInfo *marking = slice->marking;
|
||||
H264eRplmo rplmo;
|
||||
MPP_RET ret = MPP_OK;
|
||||
|
||||
mpp_writer_init(s, p, size);
|
||||
|
||||
RK_U8 *tmp = (RK_U8 *)s->buffer;
|
||||
|
||||
/* nal header */
|
||||
/* start_code_prefix 00 00 00 01 */
|
||||
mpp_writer_put_raw_bits(s, 0, 24);
|
||||
|
|
@ -694,6 +689,17 @@ RK_S32 h264e_slice_write(H264eSlice *slice, void *p, RK_U32 size)
|
|||
}
|
||||
|
||||
mpp_writer_flush(s);
|
||||
}
|
||||
|
||||
RK_S32 h264e_slice_write(H264eSlice *slice, void *p, RK_U32 size)
|
||||
{
|
||||
MppWriteCtx stream;
|
||||
MppWriteCtx *s = &stream;
|
||||
RK_S32 bitCnt = 0;
|
||||
|
||||
mpp_writer_init(s, p, size);
|
||||
|
||||
h264e_slice_write_header(slice, s);
|
||||
|
||||
bitCnt = s->buffered_bits + s->byte_cnt * 8;
|
||||
|
||||
|
|
@ -702,6 +708,8 @@ RK_S32 h264e_slice_write(H264eSlice *slice, void *p, RK_U32 size)
|
|||
bitCnt = s->buffered_bits + s->byte_cnt * 8;
|
||||
|
||||
if (h264e_debug & H264E_DBG_SLICE) {
|
||||
RK_S32 i;
|
||||
RK_U8 *tmp = p;
|
||||
RK_S32 pos = 0;
|
||||
char log[256];
|
||||
|
||||
|
|
@ -716,7 +724,217 @@ RK_S32 h264e_slice_write(H264eSlice *slice, void *p, RK_U32 size)
|
|||
return bitCnt;
|
||||
}
|
||||
|
||||
static RK_S32 frame_no = 0;
|
||||
/*
|
||||
* For software force skip stream writing
|
||||
* 3 contexts state for skip flag
|
||||
* end_of_slice flag is equal to write bypass 1
|
||||
*/
|
||||
typedef struct H264eCabac_t {
|
||||
RK_S32 state;
|
||||
|
||||
RK_S32 low;
|
||||
RK_S32 range;
|
||||
RK_S32 queue;
|
||||
RK_S32 bytes_outstanding;
|
||||
|
||||
MppWriteCtx *s;
|
||||
} H264eCabac;
|
||||
|
||||
static const RK_S8 skip_init_state[3][2] = {
|
||||
// skip_flag ctx 11
|
||||
/* model 0 */ { 23, 33 },
|
||||
/* model 1 */ { 22, 25 },
|
||||
/* model 2 */ { 29, 16 },
|
||||
};
|
||||
|
||||
static void init_context(H264eCabac *ctx, RK_S32 qp, RK_S32 model, MppWriteCtx *s)
|
||||
{
|
||||
const RK_S8 *init = &skip_init_state[model][0];
|
||||
RK_S32 state = MPP_CLIP3(1, 126, ((init[0] * qp) >> 4) + init[1]);
|
||||
|
||||
ctx->state = (MPP_MIN(state, 127 - state) << 1) | (state >> 6);
|
||||
|
||||
ctx->low = 0;
|
||||
ctx->range = 0x01FE;
|
||||
ctx->queue = -9;
|
||||
ctx->bytes_outstanding = 0;
|
||||
ctx->s = s;
|
||||
}
|
||||
|
||||
static inline void h264e_cabac_putbyte(H264eCabac *ctx)
|
||||
{
|
||||
if (ctx->queue >= 0) {
|
||||
RK_S32 out = ctx->low >> (ctx->queue + 10);
|
||||
|
||||
ctx->low &= (0x400 << ctx->queue) - 1;
|
||||
ctx->queue -= 8;
|
||||
|
||||
if ((out & 0xff) == 0xff) {
|
||||
ctx->bytes_outstanding++;
|
||||
} else {
|
||||
MppWriteCtx *s = ctx->s;
|
||||
RK_S32 carry = out >> 8;
|
||||
RK_S32 bytes_outstanding = ctx->bytes_outstanding;
|
||||
|
||||
if (ctx->queue > 0)
|
||||
mpp_writer_put_bits(s, carry, ctx->queue & 0x7);
|
||||
|
||||
while (bytes_outstanding > 0) {
|
||||
mpp_writer_put_bits(s, carry - 1, 8);
|
||||
bytes_outstanding--;
|
||||
}
|
||||
|
||||
mpp_writer_put_bits(s, out, MPP_MIN(8, 8 - ctx->queue));
|
||||
ctx->bytes_outstanding = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void h264e_cabac_renorm(H264eCabac *ctx)
|
||||
{
|
||||
static const RK_U8 x264_cabac_renorm_shift[64] = {
|
||||
6, 5, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
RK_S32 shift = x264_cabac_renorm_shift[ctx->range >> 3];
|
||||
|
||||
ctx->range <<= shift;
|
||||
ctx->low <<= shift;
|
||||
ctx->queue += shift;
|
||||
|
||||
h264e_cabac_putbyte(ctx);
|
||||
}
|
||||
|
||||
static void h264e_cabac_write_skip_flag(H264eCabac *ctx)
|
||||
{
|
||||
static const RK_U8 h264e_cabac_range_lps[64][4] = {
|
||||
{ 2, 2, 2, 2}, { 6, 7, 8, 9}, { 6, 7, 9, 10}, { 6, 8, 9, 11},
|
||||
{ 7, 8, 10, 11}, { 7, 9, 10, 12}, { 7, 9, 11, 12}, { 8, 9, 11, 13},
|
||||
{ 8, 10, 12, 14}, { 9, 11, 12, 14}, { 9, 11, 13, 15}, { 10, 12, 14, 16},
|
||||
{ 10, 12, 15, 17}, { 11, 13, 15, 18}, { 11, 14, 16, 19}, { 12, 14, 17, 20},
|
||||
{ 12, 15, 18, 21}, { 13, 16, 19, 22}, { 14, 17, 20, 23}, { 14, 18, 21, 24},
|
||||
{ 15, 19, 22, 25}, { 16, 20, 23, 27}, { 17, 21, 25, 28}, { 18, 22, 26, 30},
|
||||
{ 19, 23, 27, 31}, { 20, 24, 29, 33}, { 21, 26, 30, 35}, { 22, 27, 32, 37},
|
||||
{ 23, 28, 33, 39}, { 24, 30, 35, 41}, { 26, 31, 37, 43}, { 27, 33, 39, 45},
|
||||
{ 29, 35, 41, 48}, { 30, 37, 43, 50}, { 32, 39, 46, 53}, { 33, 41, 48, 56},
|
||||
{ 35, 43, 51, 59}, { 37, 45, 54, 62}, { 39, 48, 56, 65}, { 41, 50, 59, 69},
|
||||
{ 43, 53, 63, 72}, { 46, 56, 66, 76}, { 48, 59, 69, 80}, { 51, 62, 73, 85},
|
||||
{ 53, 65, 77, 89}, { 56, 69, 81, 94}, { 59, 72, 86, 99}, { 62, 76, 90, 104},
|
||||
{ 66, 80, 95, 110}, { 69, 85, 100, 116}, { 73, 89, 105, 122}, { 77, 94, 111, 128},
|
||||
{ 81, 99, 117, 135}, { 85, 104, 123, 142}, { 90, 110, 130, 150}, { 95, 116, 137, 158},
|
||||
{100, 122, 144, 166}, {105, 128, 152, 175}, {111, 135, 160, 185}, {116, 142, 169, 195},
|
||||
{123, 150, 178, 205}, {128, 158, 187, 216}, {128, 167, 197, 227}, {128, 176, 208, 240}
|
||||
};
|
||||
|
||||
static const RK_U8 h264e_cabac_transition[128][2] = {
|
||||
{ 0, 0}, { 1, 1}, { 2, 50}, { 51, 3}, { 2, 50}, { 51, 3}, { 4, 52}, { 53, 5},
|
||||
{ 6, 52}, { 53, 7}, { 8, 52}, { 53, 9}, { 10, 54}, { 55, 11}, { 12, 54}, { 55, 13},
|
||||
{ 14, 54}, { 55, 15}, { 16, 56}, { 57, 17}, { 18, 56}, { 57, 19}, { 20, 56}, { 57, 21},
|
||||
{ 22, 58}, { 59, 23}, { 24, 58}, { 59, 25}, { 26, 60}, { 61, 27}, { 28, 60}, { 61, 29},
|
||||
{ 30, 60}, { 61, 31}, { 32, 62}, { 63, 33}, { 34, 62}, { 63, 35}, { 36, 64}, { 65, 37},
|
||||
{ 38, 66}, { 67, 39}, { 40, 66}, { 67, 41}, { 42, 66}, { 67, 43}, { 44, 68}, { 69, 45},
|
||||
{ 46, 68}, { 69, 47}, { 48, 70}, { 71, 49}, { 50, 72}, { 73, 51}, { 52, 72}, { 73, 53},
|
||||
{ 54, 74}, { 75, 55}, { 56, 74}, { 75, 57}, { 58, 76}, { 77, 59}, { 60, 78}, { 79, 61},
|
||||
{ 62, 78}, { 79, 63}, { 64, 80}, { 81, 65}, { 66, 82}, { 83, 67}, { 68, 82}, { 83, 69},
|
||||
{ 70, 84}, { 85, 71}, { 72, 84}, { 85, 73}, { 74, 88}, { 89, 75}, { 76, 88}, { 89, 77},
|
||||
{ 78, 90}, { 91, 79}, { 80, 90}, { 91, 81}, { 82, 94}, { 95, 83}, { 84, 94}, { 95, 85},
|
||||
{ 86, 96}, { 97, 87}, { 88, 96}, { 97, 89}, { 90, 100}, {101, 91}, { 92, 100}, {101, 93},
|
||||
{ 94, 102}, {103, 95}, { 96, 104}, {105, 97}, { 98, 104}, {105, 99}, {100, 108}, {109, 101},
|
||||
{102, 108}, {109, 103}, {104, 110}, {111, 105}, {106, 112}, {113, 107}, {108, 114}, {115, 109},
|
||||
{110, 116}, {117, 111}, {112, 118}, {119, 113}, {114, 118}, {119, 115}, {116, 122}, {123, 117},
|
||||
{118, 122}, {123, 119}, {120, 124}, {125, 121}, {122, 126}, {127, 123}, {124, 127}, {126, 125}
|
||||
};
|
||||
|
||||
RK_S32 skip = 1;
|
||||
RK_S32 state = ctx->state;
|
||||
RK_S32 range_lps = h264e_cabac_range_lps[state >> 1][(ctx->range >> 6) - 4];
|
||||
|
||||
ctx->range -= range_lps;
|
||||
if (skip != (state & 1) ) {
|
||||
ctx->low += ctx->range;
|
||||
ctx->range = range_lps;
|
||||
}
|
||||
|
||||
ctx->state = h264e_cabac_transition[state][skip];
|
||||
|
||||
h264e_cabac_renorm(ctx);
|
||||
}
|
||||
|
||||
static void h264e_cabac_terminal(H264eCabac *ctx)
|
||||
{
|
||||
ctx->range -= 2;
|
||||
h264e_cabac_renorm(ctx);
|
||||
}
|
||||
|
||||
static void h264e_cabac_flush(H264eCabac *ctx)
|
||||
{
|
||||
/* end_of_slice_flag = 1 */
|
||||
ctx->low += ctx->range - 2;
|
||||
ctx->low |= 1;
|
||||
ctx->low <<= 9;
|
||||
ctx->queue += 9;
|
||||
|
||||
h264e_cabac_putbyte( ctx );
|
||||
h264e_cabac_putbyte( ctx );
|
||||
|
||||
ctx->low <<= -ctx->queue;
|
||||
ctx->low |= 1 << 10;
|
||||
ctx->queue = 0;
|
||||
|
||||
h264e_cabac_putbyte( ctx );
|
||||
|
||||
while (ctx->bytes_outstanding > 0) {
|
||||
mpp_writer_put_bits(ctx->s, 0xff, 8);
|
||||
ctx->bytes_outstanding--;
|
||||
}
|
||||
}
|
||||
|
||||
RK_S32 h264e_slice_write_pskip(H264eSlice *slice, void *p, RK_U32 size)
|
||||
{
|
||||
MppWriteCtx stream;
|
||||
MppWriteCtx *s = &stream;
|
||||
RK_S32 bitCnt = 0;
|
||||
|
||||
mpp_writer_init(s, p, size);
|
||||
|
||||
h264e_slice_write_header(slice, s);
|
||||
if (slice->entropy_coding_mode) {
|
||||
/* cabac */
|
||||
H264eCabac ctx;
|
||||
RK_S32 i;
|
||||
|
||||
init_context(&ctx, slice->qp_init, slice->cabac_init_idc, s);
|
||||
|
||||
for (i = 0; i < slice->mb_w * slice->mb_h; i++) {
|
||||
/* end_of_slice_flag = 0 */
|
||||
if (i)
|
||||
h264e_cabac_terminal(&ctx);
|
||||
|
||||
/* skip flag */
|
||||
h264e_cabac_write_skip_flag(&ctx);
|
||||
}
|
||||
|
||||
/* end_of_slice_flag = 1 and flush */
|
||||
h264e_cabac_flush(&ctx);
|
||||
} else {
|
||||
/* cavlc */
|
||||
/* mb skip run */
|
||||
mpp_writer_put_ue(s, slice->mb_w * slice->mb_h);
|
||||
h264e_dbg_slice("used bit %d mb_skip_run %d\n",
|
||||
mpp_writer_bits(s), slice->mb_w * slice->mb_h);
|
||||
|
||||
/* rbsp_stop_one_bit */
|
||||
mpp_writer_trailing(s);
|
||||
h264e_dbg_slice("used bit %d tailing %d\n", mpp_writer_bits(s));
|
||||
}
|
||||
mpp_writer_flush(s);
|
||||
|
||||
bitCnt = s->buffered_bits + s->byte_cnt * 8;
|
||||
return bitCnt;
|
||||
}
|
||||
|
||||
RK_S32 h264e_slice_move(RK_U8 *dst, RK_U8 *src, RK_S32 dst_bit, RK_S32 src_bit, RK_S32 src_size)
|
||||
{
|
||||
|
|
@ -726,6 +944,7 @@ RK_S32 h264e_slice_move(RK_U8 *dst, RK_U8 *src, RK_S32 dst_bit, RK_S32 src_bit,
|
|||
RK_S32 src_bit_r = src_bit & 7;
|
||||
RK_S32 src_len = src_size - src_byte;
|
||||
RK_S32 diff_len = 0;
|
||||
static RK_S32 frame_no = 0;
|
||||
|
||||
if (src_bit_r == 0 && dst_bit_r == 0) {
|
||||
// direct copy
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "h264e_syntax.h"
|
||||
#include "h264e_sps.h"
|
||||
#include "h264e_pps.h"
|
||||
|
||||
/*
|
||||
* For H.264 encoder slice header process.
|
||||
|
|
@ -87,11 +88,14 @@ typedef struct H264eMarkingInfo_t {
|
|||
|
||||
typedef struct H264eSlice_t {
|
||||
/* Copy of sps/pps parameter */
|
||||
RK_S32 mb_w;
|
||||
RK_S32 mb_h;
|
||||
RK_U32 max_num_ref_frames;
|
||||
RK_U32 entropy_coding_mode;
|
||||
RK_S32 log2_max_frame_num;
|
||||
RK_S32 log2_max_poc_lsb;
|
||||
RK_S32 pic_order_cnt_type;
|
||||
RK_S32 qp_init;
|
||||
|
||||
/* Nal parameters */
|
||||
RK_S32 nal_reference_idc;
|
||||
|
|
@ -159,10 +163,12 @@ MPP_RET h264e_marking_rd_op(H264eMarkingInfo *info, H264eMmco *op);
|
|||
void h264e_slice_init(H264eSlice *slice, H264eReorderInfo *reorder,
|
||||
H264eMarkingInfo *marking);
|
||||
RK_S32 h264e_slice_update(H264eSlice *slice, MppEncCfgSet *cfg,
|
||||
H264eSps *sps, H264eDpbFrm *frm);
|
||||
H264eSps *sps, H264ePps *pps,
|
||||
H264eDpbFrm *frm);
|
||||
|
||||
RK_S32 h264e_slice_read(H264eSlice *slice, void *p, RK_S32 size);
|
||||
RK_S32 h264e_slice_write(H264eSlice *slice, void *p, RK_U32 size);
|
||||
RK_S32 h264e_slice_write_pskip(H264eSlice *slice, void *p, RK_U32 size);
|
||||
RK_S32 h264e_slice_move(RK_U8 *dst, RK_U8 *src, RK_S32 dst_bit, RK_S32 src_bit,
|
||||
RK_S32 src_size);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue