diff --git a/mpp/codec/enc/h264/h264e_api_v2.c b/mpp/codec/enc/h264/h264e_api_v2.c index a000cc13..52f44d0a 100644 --- a/mpp/codec/enc/h264/h264e_api_v2.c +++ b/mpp/codec/enc/h264/h264e_api_v2.c @@ -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, }; diff --git a/mpp/codec/enc/h264/h264e_dpb.c b/mpp/codec/enc/h264/h264e_dpb.c index fbfa419e..98692b78 100644 --- a/mpp/codec/enc/h264/h264e_dpb.c +++ b/mpp/codec/enc/h264/h264e_dpb.c @@ -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); } - diff --git a/mpp/codec/enc/h264/h264e_dpb.h b/mpp/codec/enc/h264/h264e_dpb.h index cbca82aa..6e69c6a8 100644 --- a/mpp/codec/enc/h264/h264e_dpb.h +++ b/mpp/codec/enc/h264/h264e_dpb.h @@ -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 diff --git a/mpp/codec/enc/h264/h264e_slice.c b/mpp/codec/enc/h264/h264e_slice.c index f0317189..627d4883 100644 --- a/mpp/codec/enc/h264/h264e_slice.c +++ b/mpp/codec/enc/h264/h264e_slice.c @@ -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 diff --git a/mpp/codec/enc/h264/h264e_slice.h b/mpp/codec/enc/h264/h264e_slice.h index 59225a43..298b66cd 100644 --- a/mpp/codec/enc/h264/h264e_slice.h +++ b/mpp/codec/enc/h264/h264e_slice.h @@ -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);