From 736bb6bf2f0bd5b4bbdc0dd0c6996f91e2512455 Mon Sep 17 00:00:00 2001 From: Gan Zhang Date: Wed, 6 May 2020 14:24:04 +0800 Subject: [PATCH] h265: Support long term reference picture set in h265 format. [2/2] PD#SWPL-25233 Problem: h265 format playback appears mosaic. Solution: Add long term reference picture set in drivers and ucode. ucode gerrit id:108332 ucode commit id:2b404e ucode change id:I0baac PS:Video_ucode.bin corresponds to the wrong information because there is no rebase for the ucode commit. Verify: W400 Change-Id: I9925744ca14029cd4f41e4892504ebc26b4c9ab9 Signed-off-by: Gan Zhang --- drivers/frame_provider/decoder/h265/vh265.c | 111 ++++++++++++++++++-- firmware/video_ucode.bin | Bin 1459200 -> 1459200 bytes 2 files changed, 101 insertions(+), 10 deletions(-) diff --git a/drivers/frame_provider/decoder/h265/vh265.c b/drivers/frame_provider/decoder/h265/vh265.c index 1976def..ac497bd 100644 --- a/drivers/frame_provider/decoder/h265/vh265.c +++ b/drivers/frame_provider/decoder/h265/vh265.c @@ -55,6 +55,7 @@ to enable DV of frame mode */ #define HEVC_8K_LFTOFFSET_FIX +#define SUPPORT_LONG_TERM_RPS #define CONSTRAIN_MAX_BUF_NUM @@ -807,8 +808,18 @@ enum NalUnitType { #define RPM_BEGIN 0x100 #define modification_list_cur 0x148 #define RPM_END 0x180 - +#ifdef SUPPORT_LONG_TERM_RPS +/* + */ +#define RPS_END 0x8000 +#define RPS_LT_BIT 14 +#define RPS_USED_BIT 13 +#define RPS_SIGN_BIT 12 +#else +#define RPS_END 0x8000 #define RPS_USED_BIT 14 +#define RPS_SIGN_BIT 13 +#endif /* MISC_FLAG0 */ #define PCM_LOOP_FILTER_DISABLED_FLAG_BIT 0 #define PCM_ENABLE_FLAG_BIT 1 @@ -1369,6 +1380,11 @@ struct PIC_s { /**/ int slice_idx; int m_aiRefPOCList0[MAX_SLICE_NUM][16]; int m_aiRefPOCList1[MAX_SLICE_NUM][16]; +#ifdef SUPPORT_LONG_TERM_RPS + unsigned char long_term_ref; + unsigned char m_aiRefLTflgList0[MAX_SLICE_NUM][16]; + unsigned char m_aiRefLTflgList1[MAX_SLICE_NUM][16]; +#endif /*buffer */ unsigned int header_adr; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION @@ -3838,14 +3854,20 @@ static void dump_pic_list(struct hevc_state_s *hevc) if (pic == NULL || pic->index == -1) continue; hevc_print_cont(hevc, 0, - "index %d buf_idx %d mv_idx %d decode_idx:%d, POC:%d, referenced:%d, ", + "index %d buf_idx %d mv_idx %d decode_idx:%d, POC:%d, referenced:%d (LT %d), ", pic->index, pic->BUF_index, #ifndef MV_USE_FIXED_BUF pic->mv_buf_index, #else -1, #endif - pic->decode_idx, pic->POC, pic->referenced); + pic->decode_idx, pic->POC, pic->referenced +#ifdef SUPPORT_LONG_TERM_RPS + , pic->long_term_ref +#else + , 0 +#endif + ); hevc_print_cont(hevc, 0, "num_reorder_pic:%d, output_mark:%d, error_mark:%d w/h %d,%d", pic->num_reorder_pic, pic->output_mark, pic->error_mark, @@ -4112,6 +4134,28 @@ static int config_mc_buffer(struct hevc_state_s *hevc, struct PIC_s *cur_pic) return 0; } +#ifdef SUPPORT_LONG_TERM_RPS +static unsigned char is_ref_long_term(struct hevc_state_s *hevc, int poc) +{ + int ii; + struct PIC_s *pic; + for (ii = 0; ii < MAX_REF_PIC_NUM; ii++) { + pic = hevc->m_PIC[ii]; + if (pic == NULL || + pic->index == -1 || + pic->BUF_index == -1 + ) + continue; + + if (pic->referenced && pic->POC == poc + && pic->long_term_ref) + return 1; + } + return 0; +} + +#endif + static void apply_ref_pic_set(struct hevc_state_s *hevc, int cur_poc, union param_u *params) { @@ -4132,14 +4176,22 @@ static void apply_ref_pic_set(struct hevc_state_s *hevc, int cur_poc, ) continue; +#ifdef SUPPORT_LONG_TERM_RPS + pic->long_term_ref = 0; +#endif if ((pic->referenced == 0 || pic->POC == cur_poc)) continue; is_referenced = 0; + for (i = 0; i < 16; i++) { int delt; - +#ifdef SUPPORT_LONG_TERM_RPS + if (params->p.CUR_RPS[i] == RPS_END) + break; +#else if (params->p.CUR_RPS[i] & 0x8000) break; +#endif delt = params->p.CUR_RPS[i] & ((1 << (RPS_USED_BIT - 1)) - 1); @@ -4150,8 +4202,15 @@ static void apply_ref_pic_set(struct hevc_state_s *hevc, int cur_poc, } else poc_tmp = cur_poc + delt; if (poc_tmp == pic->POC) { +#ifdef SUPPORT_LONG_TERM_RPS + if (params->p.CUR_RPS[i] & (1 << (RPS_LT_BIT))) + pic->long_term_ref = 1; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) + hevc_print(hevc, 0, "%d: CUR_RPS 0x%x, LT %d\n", + i, params->p.CUR_RPS[i], + pic->long_term_ref); +#endif is_referenced = 1; - /* hevc_print(hevc, 0, "i is %d\n", i); */ break; } } @@ -4194,8 +4253,13 @@ static void set_ref_pic_list(struct hevc_state_s *hevc, union param_u *params) pic->m_aiRefPOCList1[pic->slice_idx][i] = 0; } for (i = 0; i < 16; i++) { +#ifdef SUPPORT_LONG_TERM_RPS + if (params->p.CUR_RPS[i] == RPS_END) + break; +#else if (params->p.CUR_RPS[i] & 0x8000) break; +#endif if ((params->p.CUR_RPS[i] >> RPS_USED_BIT) & 1) { int delt = params->p.CUR_RPS[i] & @@ -5193,7 +5257,27 @@ static void config_mpred_hw(struct hevc_state_s *hevc) ); WRITE_VREG(HEVC_MPRED_REF_NUM, data32); - data32 = (hevc->LongTerm_Ref); +#ifdef SUPPORT_LONG_TERM_RPS + data32 = 0; + for (i = 0; i < hevc->RefNum_L0; i++) { + if (is_ref_long_term(hevc, + cur_pic->m_aiRefPOCList0 + [cur_pic->slice_idx][i])) + data32 = data32 | (1 << i); + } + for (i = 0; i < hevc->RefNum_L1; i++) { + if (is_ref_long_term(hevc, + cur_pic->m_aiRefPOCList1 + [cur_pic->slice_idx][i])) + data32 = data32 | (1 << (i + 16)); + } + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "LongTerm_Ref 0x%x\n", data32); + } +#else + data32 = hevc->LongTerm_Ref; +#endif WRITE_VREG(HEVC_MPRED_LT_REF, data32); data32 = 0; @@ -11109,13 +11193,20 @@ static void vh265_check_timer_func(unsigned long arg) #endif if (radr != 0) { +#ifdef SUPPORT_LONG_TERM_RPS + if ((radr >> 24) != 0) { + int count = radr >> 24; + int adr = radr & 0xffffff; + int i; + for (i = 0; i < count; i++) + pr_info("READ_VREG(%x)=%x\n", adr+i, READ_VREG(adr+i)); + } else +#endif if (rval != 0) { WRITE_VREG(radr, rval); - hevc_print(hevc, 0, - "WRITE_VREG(%x,%x)\n", radr, rval); + pr_info("WRITE_VREG(%x,%x)\n", radr, rval); } else - hevc_print(hevc, 0, - "READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); + pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); rval = 0; radr = 0; } diff --git a/firmware/video_ucode.bin b/firmware/video_ucode.bin index e587044183a1f7e1b3dc17de09dc0aa23bd17da6..2463b92baed6cb21fcae11658e8f34f7ff171eec 100644 GIT binary patch delta 29038 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 TS{UGz$WR8j78*>Ayhi>%_jKCt -- 2.20.1