Message ID | 20230705183601.4998-1-jamrial@gmail.com |
---|---|
State | Accepted |
Commit | 68e9d2835fa3e5c0f73a32a8455fdcd9a5a01e77 |
Headers | show |
Series | [FFmpeg-devel,v4] avcodec/cbs_h266: add support for Adaptation parameter set NALU type | expand |
Context | Check | Description |
---|---|---|
andriy/configure_x86 | warning | Failed to apply patch |
yinshiyou/configure_loongarch64 | warning | Failed to apply patch |
On Thu, Jul 6, 2023 at 2:36 AM James Almer <jamrial@gmail.com> wrote: > Signed-off-by: James Almer <jamrial@gmail.com> > --- > v3 was mistakenly sent without the amended changes, so it's the > same as v2. > > libavcodec/cbs_h2645.c | 21 +++ > libavcodec/cbs_h266.h | 46 +++++ > libavcodec/cbs_h266_syntax_template.c | 231 ++++++++++++++++++++++++++ > libavcodec/vvc.h | 10 ++ > 4 files changed, 308 insertions(+) > > diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c > index 95da597427..34c5d1d372 100644 > --- a/libavcodec/cbs_h2645.c > +++ b/libavcodec/cbs_h2645.c > @@ -1116,6 +1116,16 @@ static int > cbs_h266_read_nal_unit(CodedBitstreamContext *ctx, > } > break; > > + case VVC_PREFIX_APS_NUT: > + case VVC_SUFFIX_APS_NUT: > + { > + err = cbs_h266_read_aps(ctx, &gbc, unit->content, > + unit->type == VVC_PREFIX_APS_NUT); > + > + if (err < 0) > + return err; > + } > + break; > case VVC_PH_NUT: > { > H266RawPH *ph = unit->content; > @@ -1668,6 +1678,15 @@ static int > cbs_h266_write_nal_unit(CodedBitstreamContext *ctx, > } > break; > > + case VVC_PREFIX_APS_NUT: > + case VVC_SUFFIX_APS_NUT: > + { > + err = cbs_h266_write_aps(ctx, pbc, unit->content, > + unit->type == VVC_PREFIX_APS_NUT); > + if (err < 0) > + return err; > + } > + break; > case VVC_PH_NUT: > { > H266RawPH *ph = unit->content; > @@ -2004,6 +2023,8 @@ static const CodedBitstreamUnitTypeDescriptor > cbs_h266_unit_types[] = { > CBS_UNIT_TYPE_INTERNAL_REF(VVC_VPS_NUT, H266RawVPS, > extension_data.data), > CBS_UNIT_TYPE_INTERNAL_REF(VVC_SPS_NUT, H266RawSPS, > extension_data.data), > CBS_UNIT_TYPE_INTERNAL_REF(VVC_PPS_NUT, H266RawPPS, > extension_data.data), > + CBS_UNIT_TYPE_INTERNAL_REF(VVC_PREFIX_APS_NUT, H266RawAPS, > extension_data.data), > + CBS_UNIT_TYPE_INTERNAL_REF(VVC_SUFFIX_APS_NUT, H266RawAPS, > extension_data.data), > > CBS_UNIT_TYPE_POD(VVC_PH_NUT , H266RawPH), > CBS_UNIT_TYPE_POD(VVC_AUD_NUT, H266RawAUD), > diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h > index 63af3bacf0..08cae68036 100644 > --- a/libavcodec/cbs_h266.h > +++ b/libavcodec/cbs_h266.h > @@ -578,6 +578,52 @@ typedef struct H266RawPPS { > uint16_t row_height_val[VVC_MAX_TILE_ROWS]; > } H266RawPPS; > > +typedef struct H266RawAPS { > + H266RawNALUnitHeader nal_unit_header; > + uint8_t aps_params_type; > + uint8_t aps_adaptation_parameter_set_id; > + uint8_t aps_chroma_present_flag; > + > + uint8_t alf_luma_filter_signal_flag; > + uint8_t alf_chroma_filter_signal_flag; > + uint8_t alf_cc_cb_filter_signal_flag; > + uint8_t alf_cc_cr_filter_signal_flag; > + uint8_t alf_luma_clip_flag; > + uint8_t alf_luma_num_filters_signalled_minus1; > + uint8_t alf_luma_coeff_delta_idx[VVC_NUM_ALF_FILTERS]; > + uint8_t alf_luma_coeff_abs[VVC_NUM_ALF_FILTERS][12]; > + uint8_t alf_luma_coeff_sign[VVC_NUM_ALF_FILTERS][12]; > + uint8_t alf_luma_clip_idx[VVC_NUM_ALF_FILTERS][12]; > + uint8_t alf_chroma_clip_flag; > + uint8_t alf_chroma_num_alt_filters_minus1; > + uint8_t alf_chroma_coeff_abs[8][6]; > + uint8_t alf_chroma_coeff_sign[8][6]; > + uint8_t alf_chroma_clip_idx[8][6]; > + uint8_t alf_cc_cb_filters_signalled_minus1; > + uint8_t alf_cc_cb_mapped_coeff_abs[4][7]; > + uint8_t alf_cc_cb_coeff_sign[4][7]; > + uint8_t alf_cc_cr_filters_signalled_minus1; > + uint8_t alf_cc_cr_mapped_coeff_abs[4][7]; > + uint8_t alf_cc_cr_coeff_sign[4][7]; > + > + uint8_t scaling_list_copy_mode_flag[28]; > + uint8_t scaling_list_pred_mode_flag[28]; > + uint8_t scaling_list_pred_id_delta[28]; > + int8_t scaling_list_dc_coef[14]; > + int8_t scaling_list_delta_coef[28][64]; > + > + uint8_t lmcs_min_bin_idx; > + uint8_t lmcs_delta_max_bin_idx; > + uint8_t lmcs_delta_cw_prec_minus1; > + uint16_t lmcs_delta_abs_cw[16]; > + uint8_t lmcs_delta_sign_cw_flag[16]; > + uint8_t lmcs_delta_abs_crs; > + uint8_t lmcs_delta_sign_crs_flag; > + > + uint8_t aps_extension_flag; > + H266RawExtensionData extension_data; > +} H266RawAPS; > + > typedef struct H266RawAUD { > H266RawNALUnitHeader nal_unit_header; > uint8_t aud_irap_or_gdr_flag; > diff --git a/libavcodec/cbs_h266_syntax_template.c > b/libavcodec/cbs_h266_syntax_template.c > index e2246cfc1b..d8ac493edc 100644 > --- a/libavcodec/cbs_h266_syntax_template.c > +++ b/libavcodec/cbs_h266_syntax_template.c > @@ -2185,6 +2185,237 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, > RWContext *rw, > return 0; > } > > +static int FUNC(alf_data)(CodedBitstreamContext *ctx, RWContext *rw, > + H266RawAPS *current) > +{ > + int err, j, k; > + > + flag(alf_luma_filter_signal_flag); > + > + if (current->aps_chroma_present_flag) { > + flag(alf_chroma_filter_signal_flag); > + flag(alf_cc_cb_filter_signal_flag); > + flag(alf_cc_cr_filter_signal_flag); > + } else { > + infer(alf_chroma_filter_signal_flag, 0); > + infer(alf_cc_cb_filter_signal_flag, 0); > + infer(alf_cc_cr_filter_signal_flag, 0); > + } > + > + if (current->alf_luma_filter_signal_flag) { > + flag(alf_luma_clip_flag); > + ue(alf_luma_num_filters_signalled_minus1, 0, VVC_NUM_ALF_FILTERS > - 1); > + if (current->alf_luma_num_filters_signalled_minus1 > 0) { > + unsigned int bits = > av_ceil_log2(current->alf_luma_num_filters_signalled_minus1 + 1); > + for (int filt_idx = 0; filt_idx < VVC_NUM_ALF_FILTERS; > filt_idx++) > + us(bits, alf_luma_coeff_delta_idx[filt_idx], > + 0, current->alf_luma_num_filters_signalled_minus1, > + 1, filt_idx); > + } > + for (int sf_idx = 0; sf_idx <= > current->alf_luma_num_filters_signalled_minus1; sf_idx++) > + for (j = 0; j < 12; j++) { > + ues(alf_luma_coeff_abs[sf_idx][j], 0, 128, 2, sf_idx, j); > + if (current->alf_luma_coeff_abs[sf_idx][j]) > + ubs(1, alf_luma_coeff_sign[sf_idx][j], 2, sf_idx, j); > + else > + infer(alf_luma_coeff_sign[sf_idx][j], 0); > + } > + } else { > + infer(alf_luma_clip_flag, 0); > + infer(alf_luma_num_filters_signalled_minus1, 0); > + } > + for (int sf_idx = 0; sf_idx <= > current->alf_luma_num_filters_signalled_minus1; sf_idx++) { > + for (j = 0; j < 12; j++) { > + if (current->alf_luma_clip_flag) > + ubs(2, alf_luma_clip_idx[sf_idx][j], 2, sf_idx, j); > + else > + infer(alf_luma_clip_idx[sf_idx][j], 0); > + } > + } > + > + if (current->alf_chroma_filter_signal_flag) { > + flag(alf_chroma_clip_flag); > + ue(alf_chroma_num_alt_filters_minus1, 0, 7); > + } else { > + infer(alf_chroma_clip_flag, 0); > + infer(alf_chroma_num_alt_filters_minus1, 0); > + } > + for (int alt_idx = 0; alt_idx <= > current->alf_chroma_num_alt_filters_minus1; alt_idx++) { > + for (j = 0; j < 6; j++) { > + if (current->alf_chroma_filter_signal_flag) > + ues(alf_chroma_coeff_abs[alt_idx][j], 0, 128, 2, alt_idx, > j); > + else > + infer(alf_chroma_coeff_abs[alt_idx][j], 0); > + if (current->alf_chroma_coeff_abs[alt_idx][j] > 0) > + ubs(1, alf_chroma_coeff_sign[alt_idx][j], 2, alt_idx, j); > + else > + infer(alf_chroma_coeff_sign[alt_idx][j], 0); > + } > + for (j = 0; j < 6; j++) { > + if (current->alf_chroma_clip_flag) > + ubs(2, alf_chroma_clip_idx[alt_idx][j], 2, alt_idx, j); > + else > + infer(alf_chroma_clip_idx[alt_idx][j], 0); > + } > + } > + > + if (current->alf_cc_cb_filter_signal_flag) > + ue(alf_cc_cb_filters_signalled_minus1, 0, 3); > + else > + infer(alf_cc_cb_filters_signalled_minus1, 0); > Not right, it will overread one filter set even alf_cc_cb_filter_signal_flag is false. > + for (k = 0; k <= current->alf_cc_cb_filters_signalled_minus1; k++) { > + for (j = 0; j < 7; j++) { > + if (current->alf_cc_cb_filter_signal_flag) > + ubs(3, alf_cc_cb_mapped_coeff_abs[k][j], 2, k, j); > + else > + infer(alf_cc_cb_mapped_coeff_abs[k][j], 0); > + if (current->alf_cc_cb_mapped_coeff_abs[k][j]) > + ubs(1, alf_cc_cb_coeff_sign[k][j], 2, k, j); > + else > + infer(alf_cc_cb_coeff_sign[k][j], 0); > + } > + } > + > + if (current->alf_cc_cr_filter_signal_flag) > + ue(alf_cc_cr_filters_signalled_minus1, 0, 3); > + else > + infer(alf_cc_cr_filters_signalled_minus1, 0); > Not right, > + for (k = 0; k < current->alf_cc_cr_filters_signalled_minus1 + 1; k++) > { > + for (j = 0; j < 7; j++) { > + if (current->alf_cc_cr_filter_signal_flag) > + ubs(3, alf_cc_cr_mapped_coeff_abs[k][j], 2, k, j); > + else > + infer(alf_cc_cr_mapped_coeff_abs[k][j], 0); > + if (current->alf_cc_cr_mapped_coeff_abs[k][j]) > + ubs(1, alf_cc_cr_coeff_sign[k][j], 2, k, j); > + else > + infer(alf_cc_cr_coeff_sign[k][j], 0); > + } > + } > + > + return 0; > +} > + > +static int FUNC(lmcs_data)(CodedBitstreamContext *ctx, RWContext *rw, > + H266RawAPS *current) > +{ > + int err, i, lmcs_max_bin_idx; > + > + ue(lmcs_min_bin_idx, 0, 15); > + ue(lmcs_delta_max_bin_idx, 0, 15); > + ue(lmcs_delta_cw_prec_minus1, 0, 14); > + > + lmcs_max_bin_idx = 15 - current->lmcs_delta_max_bin_idx; > + > + if (lmcs_max_bin_idx < current->lmcs_min_bin_idx) > + return AVERROR_INVALIDDATA; > + > + for (i = current->lmcs_min_bin_idx; i <= lmcs_max_bin_idx; i++) { > + ubs(current->lmcs_delta_cw_prec_minus1 + 1, lmcs_delta_abs_cw[i], > 1, i); > + if (current->lmcs_delta_abs_cw[i] > 0) > + flags(lmcs_delta_sign_cw_flag[i], 1, i); > + else > + infer(lmcs_delta_sign_cw_flag[i], 0); > + } > + > + if (current->aps_chroma_present_flag) { > + ub(3, lmcs_delta_abs_crs); > + if (current->lmcs_delta_abs_crs > 0) > + flag(lmcs_delta_sign_crs_flag); > + else > + infer(lmcs_delta_sign_crs_flag, 0); > + } else { > + infer(lmcs_delta_abs_crs, 0); > + infer(lmcs_delta_sign_crs_flag, 0); > + } > + > + return 0; > +} > + > +static int FUNC(scaling_list_data)(CodedBitstreamContext *ctx, RWContext > *rw, > + H266RawAPS *current) > +{ > + // 7.4.3.4, deriving DiagScanOrder > + static const uint8_t diag_scan_order[64][2] = { > + { 0, 0, }, { 0, 1, }, { 1, 0, }, { 0, 2, }, { 1, 1, }, { 2, > 0, }, { 0, 3, }, { 1, 2, }, > + { 2, 1, }, { 3, 0, }, { 0, 4, }, { 1, 3, }, { 2, 2, }, { 3, > 1, }, { 4, 0, }, { 0, 5, }, > + { 1, 4, }, { 2, 3, }, { 3, 2, }, { 4, 1, }, { 5, 0, }, { 0, > 6, }, { 1, 5, }, { 2, 4, }, > + { 3, 3, }, { 4, 2, }, { 5, 1, }, { 6, 0, }, { 0, 7, }, { 1, > 6, }, { 2, 5, }, { 3, 4, }, > + { 4, 3, }, { 5, 2, }, { 6, 1, }, { 7, 0, }, { 1, 7, }, { 2, > 6, }, { 3, 5, }, { 4, 4, }, > + { 5, 3, }, { 6, 2, }, { 7, 1, }, { 2, 7, }, { 3, 6, }, { 4, > 5, }, { 5, 4, }, { 6, 3, }, > + { 7, 2, }, { 3, 7, }, { 4, 6, }, { 5, 5, }, { 6, 4, }, { 7, > 3, }, { 4, 7, }, { 5, 6, }, > + { 6, 5, }, { 7, 4, }, { 5, 7, }, { 6, 6, }, { 7, 5, }, { 6, > 7, }, { 7, 6, }, { 7, 7, }, }; > + int err; > + > + for (int id = 0; id < 28; id ++) { > + if (current->aps_chroma_present_flag || id % 3 == 2 || id == 27) { > + flags(scaling_list_copy_mode_flag[id], 1, id); > + if (!current->scaling_list_copy_mode_flag[id]) > + flags(scaling_list_pred_mode_flag[id], 1, id); > + else > + infer(scaling_list_pred_mode_flag[id], 0); > + if ((current->scaling_list_copy_mode_flag[id] || > + current->scaling_list_pred_mode_flag[id]) && > + id != 0 && id != 2 && id != 8) { > + int max_id_delta = (id < 2) ? id : ((id < 8) ? (id - 2) : > (id - 8)); > + ues(scaling_list_pred_id_delta[id], 0, max_id_delta, 1, > id); > + } > + if (!current->scaling_list_copy_mode_flag[id]) { > + int matrix_size = id < 2 ? 2 : (id < 8 ? 4 : 8); > + if (id > 13) { > + int idx = id - 14; > + ses(scaling_list_dc_coef[idx], -128, 127, 1, idx); > + } > + for (int i = 0; i < matrix_size * matrix_size; i++) { > + int x = diag_scan_order[i][0]; > + int y = diag_scan_order[i][1]; > + if (!(id > 25 && x >= 4 && y >= 4)) > + ses(scaling_list_delta_coef[id][i], -128, 127, 2, > id, i); > + } > + } else if (id > 13) { > + int idx = id - 14; > + infer(scaling_list_dc_coef[idx], 0); > + } > + } else { > + infer(scaling_list_copy_mode_flag[id], 1); > + infer(scaling_list_pred_mode_flag[id], 0); > + } > + } > + > + return 0; > +} > + > +static int FUNC(aps)(CodedBitstreamContext *ctx, RWContext *rw, > + H266RawAPS *current, int prefix) > +{ > + int err; > + > + if (prefix) > + HEADER("Prefix Adaptation parameter set"); > + else > + HEADER("Suffix Adaptation parameter set"); > + > + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, > + prefix ? VVC_PREFIX_APS_NUT > + : VVC_SUFFIX_APS_NUT)); > + > + ub(3, aps_params_type); > + ub(5, aps_adaptation_parameter_set_id); > + flag(aps_chroma_present_flag); > + if (current->aps_params_type == VVC_ASP_TYPE_ALF) > + CHECK(FUNC(alf_data)(ctx, rw, current)); > + else if(current->aps_params_type == VVC_ASP_TYPE_LMCS) > + CHECK(FUNC(lmcs_data)(ctx, rw, current)); > + else if (current->aps_params_type == VVC_ASP_TYPE_SCALING) > + CHECK(FUNC(scaling_list_data)(ctx, rw, current)); > + flag(aps_extension_flag); > + if (current->aps_extension_flag) > + CHECK(FUNC(extension_data) (ctx, rw, ¤t->extension_data)); > + CHECK(FUNC(rbsp_trailing_bits) (ctx, rw)); > + > + return 0; > +} > + > static int FUNC(aud) (CodedBitstreamContext *ctx, RWContext *rw, > H266RawAUD *current) > { > diff --git a/libavcodec/vvc.h b/libavcodec/vvc.h > index 9fbb4a953c..7d165cdb86 100644 > --- a/libavcodec/vvc.h > +++ b/libavcodec/vvc.h > @@ -66,6 +66,12 @@ enum VVCSliceType { > VVC_SLICE_TYPE_I = 2, > }; > > +enum VVCAPSType { > + VVC_ASP_TYPE_ALF = 0, > + VVC_ASP_TYPE_LMCS = 1, > + VVC_ASP_TYPE_SCALING = 2, > +}; > + > enum { > //6.2 we can have 3 sample arrays > VVC_MAX_SAMPLE_ARRAYS = 3, > @@ -95,6 +101,10 @@ enum { > // 7.4.4.1: ptl_num_sub_profiles is u(8) > VVC_MAX_SUB_PROFILES = 256, > > + // 7.4.3.18: The variable NumAlfFilters specifying the number of > different adaptive loop > + // filters is set equal to 25. > + VVC_NUM_ALF_FILTERS = 25, > + > // A.4.2: according to (1577), MaxDpbSize is bounded above by 2 * > maxDpbPicBuf(8) > VVC_MAX_DPB_SIZE = 16, > > -- > 2.41.0 > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". >
On 7/5/2023 9:41 PM, Nuo Mi wrote: >> + if (current->alf_cc_cb_filter_signal_flag) >> + ue(alf_cc_cb_filters_signalled_minus1, 0, 3); >> + else >> + infer(alf_cc_cb_filters_signalled_minus1, 0); >> > Not right, it will overread one filter set even > alf_cc_cb_filter_signal_flag is false. It will infer all values in alf_cc_cb_mapped_coeff_abs[0][0..7] and alf_cc_cb_coeff_sign[0][0..7] to be 0, as they are not present. > >> + for (k = 0; k <= current->alf_cc_cb_filters_signalled_minus1; k++) { >> + for (j = 0; j < 7; j++) { >> + if (current->alf_cc_cb_filter_signal_flag) >> + ubs(3, alf_cc_cb_mapped_coeff_abs[k][j], 2, k, j); >> + else >> + infer(alf_cc_cb_mapped_coeff_abs[k][j], 0); >> + if (current->alf_cc_cb_mapped_coeff_abs[k][j]) >> + ubs(1, alf_cc_cb_coeff_sign[k][j], 2, k, j); >> + else >> + infer(alf_cc_cb_coeff_sign[k][j], 0); >> + } >> + } >> + >> + if (current->alf_cc_cr_filter_signal_flag) >> + ue(alf_cc_cr_filters_signalled_minus1, 0, 3); >> + else >> + infer(alf_cc_cr_filters_signalled_minus1, 0); >> > Not right, Same as the above.
On Thu, Jul 6, 2023 at 9:04 AM James Almer <jamrial@gmail.com> wrote: > On 7/5/2023 9:41 PM, Nuo Mi wrote: > >> + if (current->alf_cc_cb_filter_signal_flag) > >> + ue(alf_cc_cb_filters_signalled_minus1, 0, 3); > >> + else > >> + infer(alf_cc_cb_filters_signalled_minus1, 0); > >> > > Not right, it will overread one filter set even > > alf_cc_cb_filter_signal_flag is false. > > It will infer all values in alf_cc_cb_mapped_coeff_abs[0][0..7] and > alf_cc_cb_coeff_sign[0][0..7] to be 0, as they are not present. > > Oh, my bad. thank you for the explanation. LGTM now. > > > >> + for (k = 0; k <= current->alf_cc_cb_filters_signalled_minus1; k++) > { > >> + for (j = 0; j < 7; j++) { > >> + if (current->alf_cc_cb_filter_signal_flag) > >> + ubs(3, alf_cc_cb_mapped_coeff_abs[k][j], 2, k, j); > >> + else > >> + infer(alf_cc_cb_mapped_coeff_abs[k][j], 0); > >> + if (current->alf_cc_cb_mapped_coeff_abs[k][j]) > >> + ubs(1, alf_cc_cb_coeff_sign[k][j], 2, k, j); > >> + else > >> + infer(alf_cc_cb_coeff_sign[k][j], 0); > >> + } > >> + } > >> + > >> + if (current->alf_cc_cr_filter_signal_flag) > >> + ue(alf_cc_cr_filters_signalled_minus1, 0, 3); > >> + else > >> + infer(alf_cc_cr_filters_signalled_minus1, 0); > >> > > Not right, > > Same as the above. > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". >
diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 95da597427..34c5d1d372 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -1116,6 +1116,16 @@ static int cbs_h266_read_nal_unit(CodedBitstreamContext *ctx, } break; + case VVC_PREFIX_APS_NUT: + case VVC_SUFFIX_APS_NUT: + { + err = cbs_h266_read_aps(ctx, &gbc, unit->content, + unit->type == VVC_PREFIX_APS_NUT); + + if (err < 0) + return err; + } + break; case VVC_PH_NUT: { H266RawPH *ph = unit->content; @@ -1668,6 +1678,15 @@ static int cbs_h266_write_nal_unit(CodedBitstreamContext *ctx, } break; + case VVC_PREFIX_APS_NUT: + case VVC_SUFFIX_APS_NUT: + { + err = cbs_h266_write_aps(ctx, pbc, unit->content, + unit->type == VVC_PREFIX_APS_NUT); + if (err < 0) + return err; + } + break; case VVC_PH_NUT: { H266RawPH *ph = unit->content; @@ -2004,6 +2023,8 @@ static const CodedBitstreamUnitTypeDescriptor cbs_h266_unit_types[] = { CBS_UNIT_TYPE_INTERNAL_REF(VVC_VPS_NUT, H266RawVPS, extension_data.data), CBS_UNIT_TYPE_INTERNAL_REF(VVC_SPS_NUT, H266RawSPS, extension_data.data), CBS_UNIT_TYPE_INTERNAL_REF(VVC_PPS_NUT, H266RawPPS, extension_data.data), + CBS_UNIT_TYPE_INTERNAL_REF(VVC_PREFIX_APS_NUT, H266RawAPS, extension_data.data), + CBS_UNIT_TYPE_INTERNAL_REF(VVC_SUFFIX_APS_NUT, H266RawAPS, extension_data.data), CBS_UNIT_TYPE_POD(VVC_PH_NUT , H266RawPH), CBS_UNIT_TYPE_POD(VVC_AUD_NUT, H266RawAUD), diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h index 63af3bacf0..08cae68036 100644 --- a/libavcodec/cbs_h266.h +++ b/libavcodec/cbs_h266.h @@ -578,6 +578,52 @@ typedef struct H266RawPPS { uint16_t row_height_val[VVC_MAX_TILE_ROWS]; } H266RawPPS; +typedef struct H266RawAPS { + H266RawNALUnitHeader nal_unit_header; + uint8_t aps_params_type; + uint8_t aps_adaptation_parameter_set_id; + uint8_t aps_chroma_present_flag; + + uint8_t alf_luma_filter_signal_flag; + uint8_t alf_chroma_filter_signal_flag; + uint8_t alf_cc_cb_filter_signal_flag; + uint8_t alf_cc_cr_filter_signal_flag; + uint8_t alf_luma_clip_flag; + uint8_t alf_luma_num_filters_signalled_minus1; + uint8_t alf_luma_coeff_delta_idx[VVC_NUM_ALF_FILTERS]; + uint8_t alf_luma_coeff_abs[VVC_NUM_ALF_FILTERS][12]; + uint8_t alf_luma_coeff_sign[VVC_NUM_ALF_FILTERS][12]; + uint8_t alf_luma_clip_idx[VVC_NUM_ALF_FILTERS][12]; + uint8_t alf_chroma_clip_flag; + uint8_t alf_chroma_num_alt_filters_minus1; + uint8_t alf_chroma_coeff_abs[8][6]; + uint8_t alf_chroma_coeff_sign[8][6]; + uint8_t alf_chroma_clip_idx[8][6]; + uint8_t alf_cc_cb_filters_signalled_minus1; + uint8_t alf_cc_cb_mapped_coeff_abs[4][7]; + uint8_t alf_cc_cb_coeff_sign[4][7]; + uint8_t alf_cc_cr_filters_signalled_minus1; + uint8_t alf_cc_cr_mapped_coeff_abs[4][7]; + uint8_t alf_cc_cr_coeff_sign[4][7]; + + uint8_t scaling_list_copy_mode_flag[28]; + uint8_t scaling_list_pred_mode_flag[28]; + uint8_t scaling_list_pred_id_delta[28]; + int8_t scaling_list_dc_coef[14]; + int8_t scaling_list_delta_coef[28][64]; + + uint8_t lmcs_min_bin_idx; + uint8_t lmcs_delta_max_bin_idx; + uint8_t lmcs_delta_cw_prec_minus1; + uint16_t lmcs_delta_abs_cw[16]; + uint8_t lmcs_delta_sign_cw_flag[16]; + uint8_t lmcs_delta_abs_crs; + uint8_t lmcs_delta_sign_crs_flag; + + uint8_t aps_extension_flag; + H266RawExtensionData extension_data; +} H266RawAPS; + typedef struct H266RawAUD { H266RawNALUnitHeader nal_unit_header; uint8_t aud_irap_or_gdr_flag; diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index e2246cfc1b..d8ac493edc 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -2185,6 +2185,237 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, return 0; } +static int FUNC(alf_data)(CodedBitstreamContext *ctx, RWContext *rw, + H266RawAPS *current) +{ + int err, j, k; + + flag(alf_luma_filter_signal_flag); + + if (current->aps_chroma_present_flag) { + flag(alf_chroma_filter_signal_flag); + flag(alf_cc_cb_filter_signal_flag); + flag(alf_cc_cr_filter_signal_flag); + } else { + infer(alf_chroma_filter_signal_flag, 0); + infer(alf_cc_cb_filter_signal_flag, 0); + infer(alf_cc_cr_filter_signal_flag, 0); + } + + if (current->alf_luma_filter_signal_flag) { + flag(alf_luma_clip_flag); + ue(alf_luma_num_filters_signalled_minus1, 0, VVC_NUM_ALF_FILTERS - 1); + if (current->alf_luma_num_filters_signalled_minus1 > 0) { + unsigned int bits = av_ceil_log2(current->alf_luma_num_filters_signalled_minus1 + 1); + for (int filt_idx = 0; filt_idx < VVC_NUM_ALF_FILTERS; filt_idx++) + us(bits, alf_luma_coeff_delta_idx[filt_idx], + 0, current->alf_luma_num_filters_signalled_minus1, + 1, filt_idx); + } + for (int sf_idx = 0; sf_idx <= current->alf_luma_num_filters_signalled_minus1; sf_idx++) + for (j = 0; j < 12; j++) { + ues(alf_luma_coeff_abs[sf_idx][j], 0, 128, 2, sf_idx, j); + if (current->alf_luma_coeff_abs[sf_idx][j]) + ubs(1, alf_luma_coeff_sign[sf_idx][j], 2, sf_idx, j); + else + infer(alf_luma_coeff_sign[sf_idx][j], 0); + } + } else { + infer(alf_luma_clip_flag, 0); + infer(alf_luma_num_filters_signalled_minus1, 0); + } + for (int sf_idx = 0; sf_idx <= current->alf_luma_num_filters_signalled_minus1; sf_idx++) { + for (j = 0; j < 12; j++) { + if (current->alf_luma_clip_flag) + ubs(2, alf_luma_clip_idx[sf_idx][j], 2, sf_idx, j); + else + infer(alf_luma_clip_idx[sf_idx][j], 0); + } + } + + if (current->alf_chroma_filter_signal_flag) { + flag(alf_chroma_clip_flag); + ue(alf_chroma_num_alt_filters_minus1, 0, 7); + } else { + infer(alf_chroma_clip_flag, 0); + infer(alf_chroma_num_alt_filters_minus1, 0); + } + for (int alt_idx = 0; alt_idx <= current->alf_chroma_num_alt_filters_minus1; alt_idx++) { + for (j = 0; j < 6; j++) { + if (current->alf_chroma_filter_signal_flag) + ues(alf_chroma_coeff_abs[alt_idx][j], 0, 128, 2, alt_idx, j); + else + infer(alf_chroma_coeff_abs[alt_idx][j], 0); + if (current->alf_chroma_coeff_abs[alt_idx][j] > 0) + ubs(1, alf_chroma_coeff_sign[alt_idx][j], 2, alt_idx, j); + else + infer(alf_chroma_coeff_sign[alt_idx][j], 0); + } + for (j = 0; j < 6; j++) { + if (current->alf_chroma_clip_flag) + ubs(2, alf_chroma_clip_idx[alt_idx][j], 2, alt_idx, j); + else + infer(alf_chroma_clip_idx[alt_idx][j], 0); + } + } + + if (current->alf_cc_cb_filter_signal_flag) + ue(alf_cc_cb_filters_signalled_minus1, 0, 3); + else + infer(alf_cc_cb_filters_signalled_minus1, 0); + for (k = 0; k <= current->alf_cc_cb_filters_signalled_minus1; k++) { + for (j = 0; j < 7; j++) { + if (current->alf_cc_cb_filter_signal_flag) + ubs(3, alf_cc_cb_mapped_coeff_abs[k][j], 2, k, j); + else + infer(alf_cc_cb_mapped_coeff_abs[k][j], 0); + if (current->alf_cc_cb_mapped_coeff_abs[k][j]) + ubs(1, alf_cc_cb_coeff_sign[k][j], 2, k, j); + else + infer(alf_cc_cb_coeff_sign[k][j], 0); + } + } + + if (current->alf_cc_cr_filter_signal_flag) + ue(alf_cc_cr_filters_signalled_minus1, 0, 3); + else + infer(alf_cc_cr_filters_signalled_minus1, 0); + for (k = 0; k < current->alf_cc_cr_filters_signalled_minus1 + 1; k++) { + for (j = 0; j < 7; j++) { + if (current->alf_cc_cr_filter_signal_flag) + ubs(3, alf_cc_cr_mapped_coeff_abs[k][j], 2, k, j); + else + infer(alf_cc_cr_mapped_coeff_abs[k][j], 0); + if (current->alf_cc_cr_mapped_coeff_abs[k][j]) + ubs(1, alf_cc_cr_coeff_sign[k][j], 2, k, j); + else + infer(alf_cc_cr_coeff_sign[k][j], 0); + } + } + + return 0; +} + +static int FUNC(lmcs_data)(CodedBitstreamContext *ctx, RWContext *rw, + H266RawAPS *current) +{ + int err, i, lmcs_max_bin_idx; + + ue(lmcs_min_bin_idx, 0, 15); + ue(lmcs_delta_max_bin_idx, 0, 15); + ue(lmcs_delta_cw_prec_minus1, 0, 14); + + lmcs_max_bin_idx = 15 - current->lmcs_delta_max_bin_idx; + + if (lmcs_max_bin_idx < current->lmcs_min_bin_idx) + return AVERROR_INVALIDDATA; + + for (i = current->lmcs_min_bin_idx; i <= lmcs_max_bin_idx; i++) { + ubs(current->lmcs_delta_cw_prec_minus1 + 1, lmcs_delta_abs_cw[i], 1, i); + if (current->lmcs_delta_abs_cw[i] > 0) + flags(lmcs_delta_sign_cw_flag[i], 1, i); + else + infer(lmcs_delta_sign_cw_flag[i], 0); + } + + if (current->aps_chroma_present_flag) { + ub(3, lmcs_delta_abs_crs); + if (current->lmcs_delta_abs_crs > 0) + flag(lmcs_delta_sign_crs_flag); + else + infer(lmcs_delta_sign_crs_flag, 0); + } else { + infer(lmcs_delta_abs_crs, 0); + infer(lmcs_delta_sign_crs_flag, 0); + } + + return 0; +} + +static int FUNC(scaling_list_data)(CodedBitstreamContext *ctx, RWContext *rw, + H266RawAPS *current) +{ + // 7.4.3.4, deriving DiagScanOrder + static const uint8_t diag_scan_order[64][2] = { + { 0, 0, }, { 0, 1, }, { 1, 0, }, { 0, 2, }, { 1, 1, }, { 2, 0, }, { 0, 3, }, { 1, 2, }, + { 2, 1, }, { 3, 0, }, { 0, 4, }, { 1, 3, }, { 2, 2, }, { 3, 1, }, { 4, 0, }, { 0, 5, }, + { 1, 4, }, { 2, 3, }, { 3, 2, }, { 4, 1, }, { 5, 0, }, { 0, 6, }, { 1, 5, }, { 2, 4, }, + { 3, 3, }, { 4, 2, }, { 5, 1, }, { 6, 0, }, { 0, 7, }, { 1, 6, }, { 2, 5, }, { 3, 4, }, + { 4, 3, }, { 5, 2, }, { 6, 1, }, { 7, 0, }, { 1, 7, }, { 2, 6, }, { 3, 5, }, { 4, 4, }, + { 5, 3, }, { 6, 2, }, { 7, 1, }, { 2, 7, }, { 3, 6, }, { 4, 5, }, { 5, 4, }, { 6, 3, }, + { 7, 2, }, { 3, 7, }, { 4, 6, }, { 5, 5, }, { 6, 4, }, { 7, 3, }, { 4, 7, }, { 5, 6, }, + { 6, 5, }, { 7, 4, }, { 5, 7, }, { 6, 6, }, { 7, 5, }, { 6, 7, }, { 7, 6, }, { 7, 7, }, }; + int err; + + for (int id = 0; id < 28; id ++) { + if (current->aps_chroma_present_flag || id % 3 == 2 || id == 27) { + flags(scaling_list_copy_mode_flag[id], 1, id); + if (!current->scaling_list_copy_mode_flag[id]) + flags(scaling_list_pred_mode_flag[id], 1, id); + else + infer(scaling_list_pred_mode_flag[id], 0); + if ((current->scaling_list_copy_mode_flag[id] || + current->scaling_list_pred_mode_flag[id]) && + id != 0 && id != 2 && id != 8) { + int max_id_delta = (id < 2) ? id : ((id < 8) ? (id - 2) : (id - 8)); + ues(scaling_list_pred_id_delta[id], 0, max_id_delta, 1, id); + } + if (!current->scaling_list_copy_mode_flag[id]) { + int matrix_size = id < 2 ? 2 : (id < 8 ? 4 : 8); + if (id > 13) { + int idx = id - 14; + ses(scaling_list_dc_coef[idx], -128, 127, 1, idx); + } + for (int i = 0; i < matrix_size * matrix_size; i++) { + int x = diag_scan_order[i][0]; + int y = diag_scan_order[i][1]; + if (!(id > 25 && x >= 4 && y >= 4)) + ses(scaling_list_delta_coef[id][i], -128, 127, 2, id, i); + } + } else if (id > 13) { + int idx = id - 14; + infer(scaling_list_dc_coef[idx], 0); + } + } else { + infer(scaling_list_copy_mode_flag[id], 1); + infer(scaling_list_pred_mode_flag[id], 0); + } + } + + return 0; +} + +static int FUNC(aps)(CodedBitstreamContext *ctx, RWContext *rw, + H266RawAPS *current, int prefix) +{ + int err; + + if (prefix) + HEADER("Prefix Adaptation parameter set"); + else + HEADER("Suffix Adaptation parameter set"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + prefix ? VVC_PREFIX_APS_NUT + : VVC_SUFFIX_APS_NUT)); + + ub(3, aps_params_type); + ub(5, aps_adaptation_parameter_set_id); + flag(aps_chroma_present_flag); + if (current->aps_params_type == VVC_ASP_TYPE_ALF) + CHECK(FUNC(alf_data)(ctx, rw, current)); + else if(current->aps_params_type == VVC_ASP_TYPE_LMCS) + CHECK(FUNC(lmcs_data)(ctx, rw, current)); + else if (current->aps_params_type == VVC_ASP_TYPE_SCALING) + CHECK(FUNC(scaling_list_data)(ctx, rw, current)); + flag(aps_extension_flag); + if (current->aps_extension_flag) + CHECK(FUNC(extension_data) (ctx, rw, ¤t->extension_data)); + CHECK(FUNC(rbsp_trailing_bits) (ctx, rw)); + + return 0; +} + static int FUNC(aud) (CodedBitstreamContext *ctx, RWContext *rw, H266RawAUD *current) { diff --git a/libavcodec/vvc.h b/libavcodec/vvc.h index 9fbb4a953c..7d165cdb86 100644 --- a/libavcodec/vvc.h +++ b/libavcodec/vvc.h @@ -66,6 +66,12 @@ enum VVCSliceType { VVC_SLICE_TYPE_I = 2, }; +enum VVCAPSType { + VVC_ASP_TYPE_ALF = 0, + VVC_ASP_TYPE_LMCS = 1, + VVC_ASP_TYPE_SCALING = 2, +}; + enum { //6.2 we can have 3 sample arrays VVC_MAX_SAMPLE_ARRAYS = 3, @@ -95,6 +101,10 @@ enum { // 7.4.4.1: ptl_num_sub_profiles is u(8) VVC_MAX_SUB_PROFILES = 256, + // 7.4.3.18: The variable NumAlfFilters specifying the number of different adaptive loop + // filters is set equal to 25. + VVC_NUM_ALF_FILTERS = 25, + // A.4.2: according to (1577), MaxDpbSize is bounded above by 2 * maxDpbPicBuf(8) VVC_MAX_DPB_SIZE = 16,
Signed-off-by: James Almer <jamrial@gmail.com> --- v3 was mistakenly sent without the amended changes, so it's the same as v2. libavcodec/cbs_h2645.c | 21 +++ libavcodec/cbs_h266.h | 46 +++++ libavcodec/cbs_h266_syntax_template.c | 231 ++++++++++++++++++++++++++ libavcodec/vvc.h | 10 ++ 4 files changed, 308 insertions(+)