[FFmpeg-devel] [PATCH v3 07/11] avcodec: add cbs for h266/vvc
James Almer
jamrial at gmail.com
Wed Jan 13 04:34:37 EET 2021
On 1/11/2021 1:33 PM, Nuo Mi wrote:
> ---
> configure | 2 +
> libavcodec/Makefile | 1 +
> libavcodec/cbs.c | 6 +
> libavcodec/cbs_h2645.c | 374 ++++
> libavcodec/cbs_h266.h | 758 +++++++
> libavcodec/cbs_h266_syntax_template.c | 2774 +++++++++++++++++++++++++
> libavcodec/cbs_internal.h | 3 +-
> 7 files changed, 3917 insertions(+), 1 deletion(-)
> create mode 100644 libavcodec/cbs_h266.h
> create mode 100644 libavcodec/cbs_h266_syntax_template.c
>
[...]
> +static int cbs_h266_replace_ph(CodedBitstreamContext *ctx,
> + CodedBitstreamUnit *unit)
> +{
> + CodedBitstreamH266Context *priv = ctx->priv_data;
> + int err;
> + err = ff_cbs_make_unit_refcounted(ctx, unit);
> + if (err < 0)
> + return err;
> + av_buffer_unref(&priv->ph_ref);
> + av_assert0(unit->content_ref);
> + priv->ph_ref = av_buffer_ref(unit->content_ref);
> + if (!priv->ph_ref)
> + return AVERROR(ENOMEM);
> + priv->ph = (H266RawPH *)priv->ph_ref->data;
Make this function take a pointer to H266RawPH as argument, and set it here.
See below.
> + return 0;
> +}
> +
> +static int cbs_h266_read_nal_unit(CodedBitstreamContext *ctx,
> + CodedBitstreamUnit *unit)
> +{
> + GetBitContext gbc;
> + int err;
> +
> + err = init_get_bits8(&gbc, unit->data, unit->data_size);
> + if (err < 0)
> + return err;
> +
> + err = ff_cbs_alloc_unit_content2(ctx, unit);
> + if (err < 0)
> + return err;
> +
> + switch (unit->type) {
> + case VVC_SPS_NUT:
> + {
> + H266RawSPS *sps = unit->content;
> +
> + err = cbs_h266_read_sps(ctx, &gbc, sps);
> + if (err < 0)
> + return err;
> +
> + err = cbs_h266_replace_sps(ctx, unit);
> + if (err < 0)
> + return err;
> + }
> + break;
> +
> + case VVC_PPS_NUT:
> + {
> + H266RawPPS *pps = unit->content;
> +
> + err = cbs_h266_read_pps(ctx, &gbc, pps);
> + if (err < 0)
> + return err;
> +
> + err = cbs_h266_replace_pps(ctx, unit);
> + if (err < 0)
> + return err;
> + }
> + break;
> +
> + case VVC_PH_NUT:
> + {
> + H266RawPH *ph = unit->content;
> + err = cbs_h266_read_ph(ctx, &gbc, ph);
> + if (err < 0)
> + return err;
> +
> + err = cbs_h266_replace_ph(ctx, unit);
Pass ph as mentioned above.
> + if (err < 0)
> + return err;
> + }
> + break;
> +
> + case VVC_TRAIL_NUT:
> + case VVC_STSA_NUT:
> + case VVC_RADL_NUT:
> + case VVC_RASL_NUT:
> + case VVC_IDR_W_RADL:
> + case VVC_IDR_N_LP:
> + case VVC_CRA_NUT:
> + case VVC_GDR_NUT:
> + {
> + H266RawSlice *slice = unit->content;
> + int pos, len;
> +
> + err = cbs_h266_read_slice_header(ctx, &gbc, &slice->header);
> + if (err < 0)
> + return err;
Add a call to cbs_h266_replace_ph() here when
slice->header.sh_picture_header_in_slice_header_flag is true, and pass a
pointer to slice->header.sh_picture_header to it.
Do the same for the writing functions.
[...]
> +static int FUNC(slice_header)(CodedBitstreamContext *ctx, RWContext *rw,
> + H266RawSliceHeader *current)
> +{
> + CodedBitstreamH266Context *h266 = ctx->priv_data;
> + const H266RawSPS *sps;
> + const H266RawPPS *pps;
> + const H266RawPH *ph;
> + const H266RefPicLists *ref_pic_lists;
> + int err, i;
> + uint8_t nal_unit_type, qp_bd_offset;
> + uint16_t curr_subpic_idx;
> + uint16_t num_slices_in_subpic;
> +
> + HEADER("Slice Header");
> +
> + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, -1));
> +
> + flag(sh_picture_header_in_slice_header_flag);
> + if (current->sh_picture_header_in_slice_header_flag){
> + CHECK(FUNC(picture_header)(ctx, rw, ¤t->sh_picture_header));
> + if (!h266->ph_ref) {
> + h266->ph_ref = av_buffer_allocz(sizeof(H266RawPH));
> + if (!h266->ph_ref)
> + return AVERROR(ENOMEM);
> + }
> + h266->ph = (H266RawPH*)h266->ph_ref->data;
> + memcpy(h266->ph, ¤t->sh_picture_header, sizeof(H266RawPH));
With the above, you can remove all this and simply set ph to
¤t->sh_picture_header when
current->sh_picture_header_in_slice_header_flag is true, or to h266->ph
otherwise.
This saves an unnecessary buffer alloc per slice header that includes a
picture header. The buffer reference most assuredly already exists, and
you can reuse it.
> + }
> + sps = h266->active_sps;
> + pps = h266->active_pps;
> + ph = h266->ph;
> +
> + if (!ph) {
> + av_log(ctx->log_ctx, AV_LOG_ERROR, "Picture header not available.\n");
> + return AVERROR_INVALIDDATA;
> + }
More information about the ffmpeg-devel
mailing list