Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: IndecisiveTurtle <geoster3d@gmail.com>
To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
Subject: Re: [FFmpeg-devel] [PATCH 1/4] libavcodec/vc2enc: Split out common functions between software and hardware encoders
Date: Sat, 8 Mar 2025 15:52:16 +0200
Message-ID: <CAJpqCyKq8k_dLpYnYt-P6COwC6g6W7Dso+6B=BcJBZvRLgN9uA@mail.gmail.com> (raw)
In-Reply-To: <DU0P250MB0747FA2CEC3ADFD9D57AFD928FD42@DU0P250MB0747.EURP250.PROD.OUTLOOK.COM>

Hello Andreas

Thank you for your feedback. I will resubmit the patch with the proper
implementation you described.
Could you elaborate on the array duplication comment? I don't see any other
place it's defined

Στις Σάβ 8 Μαρ 2025 στις 3:14 μ.μ., ο/η Andreas Rheinhardt <
andreas.rheinhardt@outlook.com> έγραψε:

> IndecisiveTurtle:
> > From: IndecisiveTurtle <geoster3d@gmail.com>
> >
> > ---
> >  libavcodec/Makefile        |   2 +-
> >  libavcodec/vc2enc.c        | 515 +------------------------------------
> >  libavcodec/vc2enc_common.c | 321 +++++++++++++++++++++++
> >  libavcodec/vc2enc_common.h | 323 +++++++++++++++++++++++
> >  4 files changed, 653 insertions(+), 508 deletions(-)
> >  create mode 100644 libavcodec/vc2enc_common.c
> >  create mode 100644 libavcodec/vc2enc_common.h
> >
> > diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> > index 499f826635..a96c700745 100644
> > --- a/libavcodec/Makefile
> > +++ b/libavcodec/Makefile
> > @@ -768,7 +768,7 @@ OBJS-$(CONFIG_VC1_CUVID_DECODER)       += cuviddec.o
> >  OBJS-$(CONFIG_VC1_MMAL_DECODER)        += mmaldec.o
> >  OBJS-$(CONFIG_VC1_QSV_DECODER)         += qsvdec.o
> >  OBJS-$(CONFIG_VC1_V4L2M2M_DECODER)     += v4l2_m2m_dec.o
> > -OBJS-$(CONFIG_VC2_ENCODER)             += vc2enc.o vc2enc_dwt.o
> diractab.o
> > +OBJS-$(CONFIG_VC2_ENCODER)             += vc2enc.o vc2enc_dwt.o
> vc2enc_common.o diractab.o
> >  OBJS-$(CONFIG_VCR1_DECODER)            += vcr1.o
> >  OBJS-$(CONFIG_VMDAUDIO_DECODER)        += vmdaudio.o
> >  OBJS-$(CONFIG_VMDVIDEO_DECODER)        += vmdvideo.o
> > diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c
> > index b82370a753..712d0cf68a 100644
> > --- a/libavcodec/vc2enc.c
> > +++ b/libavcodec/vc2enc.c
> > @@ -29,506 +29,7 @@
> >  #include "put_bits.h"
> >  #include "version.h"
> >
> > -#include "vc2enc_dwt.h"
> > -#include "diractab.h"
> > -
> > -/* The limited size resolution of each slice forces us to do this */
> > -#define SSIZE_ROUND(b) (FFALIGN((b), s->size_scaler) + 4 +
> s->prefix_bytes)
> > -
> > -/* Decides the cutoff point in # of slices to distribute the leftover
> bytes */
> > -#define SLICE_REDIST_TOTAL 150
> > -
> > -typedef struct VC2BaseVideoFormat {
> > -    enum AVPixelFormat pix_fmt;
> > -    AVRational time_base;
> > -    int width, height;
> > -    uint8_t interlaced, level;
> > -    char name[13];
> > -} VC2BaseVideoFormat;
> > -
> > -static const VC2BaseVideoFormat base_video_fmts[] = {
> > -    { 0 }, /* Custom format, here just to make indexing equal to
> base_vf */
> > -    { AV_PIX_FMT_YUV420P,   { 1001, 15000 },  176,  120, 0, 1,
>  "QSIF525" },
> > -    { AV_PIX_FMT_YUV420P,   {    2,    25 },  176,  144, 0, 1,
>  "QCIF"    },
> > -    { AV_PIX_FMT_YUV420P,   { 1001, 15000 },  352,  240, 0, 1,
>  "SIF525"  },
> > -    { AV_PIX_FMT_YUV420P,   {    2,    25 },  352,  288, 0, 1,
>  "CIF"     },
> > -    { AV_PIX_FMT_YUV420P,   { 1001, 15000 },  704,  480, 0, 1,
>  "4SIF525" },
> > -    { AV_PIX_FMT_YUV420P,   {    2,    25 },  704,  576, 0, 1,
>  "4CIF"    },
> > -
> > -    { AV_PIX_FMT_YUV422P10, { 1001, 30000 },  720,  480, 1, 2,
>  "SD480I-60" },
> > -    { AV_PIX_FMT_YUV422P10, {    1,    25 },  720,  576, 1, 2,
>  "SD576I-50" },
> > -
> > -    { AV_PIX_FMT_YUV422P10, { 1001, 60000 }, 1280,  720, 0, 3,
> "HD720P-60"  },
> > -    { AV_PIX_FMT_YUV422P10, {    1,    50 }, 1280,  720, 0, 3,
> "HD720P-50"  },
> > -    { AV_PIX_FMT_YUV422P10, { 1001, 30000 }, 1920, 1080, 1, 3,
> "HD1080I-60" },
> > -    { AV_PIX_FMT_YUV422P10, {    1,    25 }, 1920, 1080, 1, 3,
> "HD1080I-50" },
> > -    { AV_PIX_FMT_YUV422P10, { 1001, 60000 }, 1920, 1080, 0, 3,
> "HD1080P-60" },
> > -    { AV_PIX_FMT_YUV422P10, {    1,    50 }, 1920, 1080, 0, 3,
> "HD1080P-50" },
> > -
> > -    { AV_PIX_FMT_YUV444P12, {    1,    24 }, 2048, 1080, 0, 4,
> "DC2K" },
> > -    { AV_PIX_FMT_YUV444P12, {    1,    24 }, 4096, 2160, 0, 5,
> "DC4K" },
> > -
> > -    { AV_PIX_FMT_YUV422P10, { 1001, 60000 }, 3840, 2160, 0, 6, "UHDTV
> 4K-60" },
> > -    { AV_PIX_FMT_YUV422P10, {    1,    50 }, 3840, 2160, 0, 6, "UHDTV
> 4K-50" },
> > -
> > -    { AV_PIX_FMT_YUV422P10, { 1001, 60000 }, 7680, 4320, 0, 7, "UHDTV
> 8K-60" },
> > -    { AV_PIX_FMT_YUV422P10, {    1,    50 }, 7680, 4320, 0, 7, "UHDTV
> 8K-50" },
> > -
> > -    { AV_PIX_FMT_YUV422P10, { 1001, 24000 }, 1920, 1080, 0, 3,
> "HD1080P-24" },
> > -    { AV_PIX_FMT_YUV422P10, { 1001, 30000 },  720,  486, 1, 2,  "SD
> Pro486"  },
> > -};
> > -static const int base_video_fmts_len = FF_ARRAY_ELEMS(base_video_fmts);
> > -
> > -enum VC2_QM {
> > -    VC2_QM_DEF = 0,
> > -    VC2_QM_COL,
> > -    VC2_QM_FLAT,
> > -
> > -    VC2_QM_NB
> > -};
> > -
> > -typedef struct SubBand {
> > -    dwtcoef *buf;
> > -    ptrdiff_t stride;
> > -    int width;
> > -    int height;
> > -} SubBand;
> > -
> > -typedef struct Plane {
> > -    SubBand band[MAX_DWT_LEVELS][4];
> > -    dwtcoef *coef_buf;
> > -    int width;
> > -    int height;
> > -    int dwt_width;
> > -    int dwt_height;
> > -    ptrdiff_t coef_stride;
> > -} Plane;
> > -
> > -typedef struct SliceArgs {
> > -    const struct VC2EncContext *ctx;
> > -    union {
> > -        int cache[DIRAC_MAX_QUANT_INDEX];
> > -        uint8_t *buf;
> > -    };
> > -    int x;
> > -    int y;
> > -    int quant_idx;
> > -    int bits_ceil;
> > -    int bits_floor;
> > -    int bytes;
> > -} SliceArgs;
> > -
> > -typedef struct TransformArgs {
> > -    const struct VC2EncContext *ctx;
> > -    Plane *plane;
> > -    const void *idata;
> > -    ptrdiff_t istride;
> > -    int field;
> > -    VC2TransformContext t;
> > -} TransformArgs;
> > -
> > -typedef struct VC2EncContext {
> > -    AVClass *av_class;
> > -    PutBitContext pb;
> > -    Plane plane[3];
> > -    AVCodecContext *avctx;
> > -    DiracVersionInfo ver;
> > -
> > -    SliceArgs *slice_args;
> > -    TransformArgs transform_args[3];
> > -
> > -    /* For conversion from unsigned pixel values to signed */
> > -    int diff_offset;
> > -    int bpp;
> > -    int bpp_idx;
> > -
> > -    /* Picture number */
> > -    uint32_t picture_number;
> > -
> > -    /* Base video format */
> > -    int base_vf;
> > -    int level;
> > -    int profile;
> > -
> > -    /* Quantization matrix */
> > -    uint8_t quant[MAX_DWT_LEVELS][4];
> > -    int custom_quant_matrix;
> > -
> > -    /* Division LUT */
> > -    uint32_t qmagic_lut[116][2];
> > -
> > -    int num_x; /* #slices horizontally */
> > -    int num_y; /* #slices vertically */
> > -    int prefix_bytes;
> > -    int size_scaler;
> > -    int chroma_x_shift;
> > -    int chroma_y_shift;
> > -
> > -    /* Rate control stuff */
> > -    int frame_max_bytes;
> > -    int slice_max_bytes;
> > -    int slice_min_bytes;
> > -    int q_ceil;
> > -    int q_avg;
> > -
> > -    /* Options */
> > -    double tolerance;
> > -    int wavelet_idx;
> > -    int wavelet_depth;
> > -    int strict_compliance;
> > -    int slice_height;
> > -    int slice_width;
> > -    int interlaced;
> > -    enum VC2_QM quant_matrix;
> > -
> > -    /* Parse code state */
> > -    uint32_t next_parse_offset;
> > -    enum DiracParseCodes last_parse_code;
> > -} VC2EncContext;
> > -
> > -static av_always_inline void put_vc2_ue_uint(PutBitContext *pb,
> uint32_t val)
> > -{
> > -    int i;
> > -    int bits = 0;
> > -    unsigned topbit = 1, maxval = 1;
> > -    uint64_t pbits = 0;
> > -
> > -    if (!val++) {
> > -        put_bits(pb, 1, 1);
> > -        return;
> > -    }
> > -
> > -    while (val > maxval) {
> > -        topbit <<= 1;
> > -        maxval <<= 1;
> > -        maxval |=  1;
> > -    }
> > -
> > -    bits = ff_log2(topbit);
> > -
> > -    for (i = 0; i < bits; i++) {
> > -        topbit >>= 1;
> > -        av_assert2(pbits <= UINT64_MAX>>3);
> > -        pbits <<= 2;
> > -        if (val & topbit)
> > -            pbits |= 0x1;
> > -    }
> > -
> > -    put_bits64(pb, bits*2 + 1, (pbits << 1) | 1);
> > -}
> > -
> > -static av_always_inline int count_vc2_ue_uint(uint32_t val)
> > -{
> > -    int topbit = 1, maxval = 1;
> > -
> > -    if (!val++)
> > -        return 1;
> > -
> > -    while (val > maxval) {
> > -        topbit <<= 1;
> > -        maxval <<= 1;
> > -        maxval |=  1;
> > -    }
> > -
> > -    return ff_log2(topbit)*2 + 1;
> > -}
> > -
> > -/* VC-2 10.4 - parse_info() */
> > -static void encode_parse_info(VC2EncContext *s, enum DiracParseCodes
> pcode)
> > -{
> > -    uint32_t cur_pos, dist;
> > -
> > -    align_put_bits(&s->pb);
> > -
> > -    cur_pos = put_bytes_count(&s->pb, 0);
> > -
> > -    /* Magic string */
> > -    ff_put_string(&s->pb, "BBCD", 0);
> > -
> > -    /* Parse code */
> > -    put_bits(&s->pb, 8, pcode);
> > -
> > -    /* Next parse offset */
> > -    dist = cur_pos - s->next_parse_offset;
> > -    AV_WB32(s->pb.buf + s->next_parse_offset + 5, dist);
> > -    s->next_parse_offset = cur_pos;
> > -    put_bits32(&s->pb, pcode == DIRAC_PCODE_END_SEQ ? 13 : 0);
> > -
> > -    /* Last parse offset */
> > -    put_bits32(&s->pb, s->last_parse_code == DIRAC_PCODE_END_SEQ ? 13 :
> dist);
> > -
> > -    s->last_parse_code = pcode;
> > -}
> > -
> > -/* VC-2 11.1 - parse_parameters()
> > - * The level dictates what the decoder should expect in terms of
> resolution
> > - * and allows it to quickly reject whatever it can't support. Remember,
> > - * this codec kinda targets cheapo FPGAs without much memory.
> Unfortunately
> > - * it also limits us greatly in our choice of formats, hence the flag
> to disable
> > - * strict_compliance */
> > -static void encode_parse_params(VC2EncContext *s)
> > -{
> > -    put_vc2_ue_uint(&s->pb, s->ver.major); /* VC-2 demands this to be 2
> */
> > -    put_vc2_ue_uint(&s->pb, s->ver.minor); /* ^^ and this to be 0
>  */
> > -    put_vc2_ue_uint(&s->pb, s->profile);   /* 3 to signal HQ profile
> */
> > -    put_vc2_ue_uint(&s->pb, s->level);     /* 3 - 1080/720, 6 - 4K
> */
> > -}
> > -
> > -/* VC-2 11.3 - frame_size() */
> > -static void encode_frame_size(VC2EncContext *s)
> > -{
> > -    put_bits(&s->pb, 1, !s->strict_compliance);
> > -    if (!s->strict_compliance) {
> > -        AVCodecContext *avctx = s->avctx;
> > -        put_vc2_ue_uint(&s->pb, avctx->width);
> > -        put_vc2_ue_uint(&s->pb, avctx->height);
> > -    }
> > -}
> > -
> > -/* VC-2 11.3.3 - color_diff_sampling_format() */
> > -static void encode_sample_fmt(VC2EncContext *s)
> > -{
> > -    put_bits(&s->pb, 1, !s->strict_compliance);
> > -    if (!s->strict_compliance) {
> > -        int idx;
> > -        if (s->chroma_x_shift == 1 && s->chroma_y_shift == 0)
> > -            idx = 1; /* 422 */
> > -        else if (s->chroma_x_shift == 1 && s->chroma_y_shift == 1)
> > -            idx = 2; /* 420 */
> > -        else
> > -            idx = 0; /* 444 */
> > -        put_vc2_ue_uint(&s->pb, idx);
> > -    }
> > -}
> > -
> > -/* VC-2 11.3.4 - scan_format() */
> > -static void encode_scan_format(VC2EncContext *s)
> > -{
> > -    put_bits(&s->pb, 1, !s->strict_compliance);
> > -    if (!s->strict_compliance)
> > -        put_vc2_ue_uint(&s->pb, s->interlaced);
> > -}
> > -
> > -/* VC-2 11.3.5 - frame_rate() */
> > -static void encode_frame_rate(VC2EncContext *s)
> > -{
> > -    put_bits(&s->pb, 1, !s->strict_compliance);
> > -    if (!s->strict_compliance) {
> > -        AVCodecContext *avctx = s->avctx;
> > -        put_vc2_ue_uint(&s->pb, 0);
> > -        put_vc2_ue_uint(&s->pb, avctx->time_base.den);
> > -        put_vc2_ue_uint(&s->pb, avctx->time_base.num);
> > -    }
> > -}
> > -
> > -/* VC-2 11.3.6 - aspect_ratio() */
> > -static void encode_aspect_ratio(VC2EncContext *s)
> > -{
> > -    put_bits(&s->pb, 1, !s->strict_compliance);
> > -    if (!s->strict_compliance) {
> > -        AVCodecContext *avctx = s->avctx;
> > -        put_vc2_ue_uint(&s->pb, 0);
> > -        put_vc2_ue_uint(&s->pb, avctx->sample_aspect_ratio.num);
> > -        put_vc2_ue_uint(&s->pb, avctx->sample_aspect_ratio.den);
> > -    }
> > -}
> > -
> > -/* VC-2 11.3.7 - clean_area() */
> > -static void encode_clean_area(VC2EncContext *s)
> > -{
> > -    put_bits(&s->pb, 1, 0);
> > -}
> > -
> > -/* VC-2 11.3.8 - signal_range() */
> > -static void encode_signal_range(VC2EncContext *s)
> > -{
> > -    put_bits(&s->pb, 1, !s->strict_compliance);
> > -    if (!s->strict_compliance)
> > -        put_vc2_ue_uint(&s->pb, s->bpp_idx);
> > -}
> > -
> > -/* VC-2 11.3.9 - color_spec() */
> > -static void encode_color_spec(VC2EncContext *s)
> > -{
> > -    AVCodecContext *avctx = s->avctx;
> > -    put_bits(&s->pb, 1, !s->strict_compliance);
> > -    if (!s->strict_compliance) {
> > -        int val;
> > -        put_vc2_ue_uint(&s->pb, 0);
> > -
> > -        /* primaries */
> > -        put_bits(&s->pb, 1, 1);
> > -        if (avctx->color_primaries == AVCOL_PRI_BT470BG)
> > -            val = 2;
> > -        else if (avctx->color_primaries == AVCOL_PRI_SMPTE170M)
> > -            val = 1;
> > -        else if (avctx->color_primaries == AVCOL_PRI_SMPTE240M)
> > -            val = 1;
> > -        else
> > -            val = 0;
> > -        put_vc2_ue_uint(&s->pb, val);
> > -
> > -        /* color matrix */
> > -        put_bits(&s->pb, 1, 1);
> > -        if (avctx->colorspace == AVCOL_SPC_RGB)
> > -            val = 3;
> > -        else if (avctx->colorspace == AVCOL_SPC_YCOCG)
> > -            val = 2;
> > -        else if (avctx->colorspace == AVCOL_SPC_BT470BG)
> > -            val = 1;
> > -        else
> > -            val = 0;
> > -        put_vc2_ue_uint(&s->pb, val);
> > -
> > -        /* transfer function */
> > -        put_bits(&s->pb, 1, 1);
> > -        if (avctx->color_trc == AVCOL_TRC_LINEAR)
> > -            val = 2;
> > -        else if (avctx->color_trc == AVCOL_TRC_BT1361_ECG)
> > -            val = 1;
> > -        else
> > -            val = 0;
> > -        put_vc2_ue_uint(&s->pb, val);
> > -    }
> > -}
> > -
> > -/* VC-2 11.3 - source_parameters() */
> > -static void encode_source_params(VC2EncContext *s)
> > -{
> > -    encode_frame_size(s);
> > -    encode_sample_fmt(s);
> > -    encode_scan_format(s);
> > -    encode_frame_rate(s);
> > -    encode_aspect_ratio(s);
> > -    encode_clean_area(s);
> > -    encode_signal_range(s);
> > -    encode_color_spec(s);
> > -}
> > -
> > -/* VC-2 11 - sequence_header() */
> > -static void encode_seq_header(VC2EncContext *s)
> > -{
> > -    align_put_bits(&s->pb);
> > -    encode_parse_params(s);
> > -    put_vc2_ue_uint(&s->pb, s->base_vf);
> > -    encode_source_params(s);
> > -    put_vc2_ue_uint(&s->pb, s->interlaced); /* Frames or fields coding
> */
> > -}
> > -
> > -/* VC-2 12.1 - picture_header() */
> > -static void encode_picture_header(VC2EncContext *s)
> > -{
> > -    align_put_bits(&s->pb);
> > -    put_bits32(&s->pb, s->picture_number++);
> > -}
> > -
> > -/* VC-2 12.3.4.1 - slice_parameters() */
> > -static void encode_slice_params(VC2EncContext *s)
> > -{
> > -    put_vc2_ue_uint(&s->pb, s->num_x);
> > -    put_vc2_ue_uint(&s->pb, s->num_y);
> > -    put_vc2_ue_uint(&s->pb, s->prefix_bytes);
> > -    put_vc2_ue_uint(&s->pb, s->size_scaler);
> > -}
> > -
> > -/* 1st idx = LL, second - vertical, third - horizontal, fourth - total
> */
> > -static const uint8_t vc2_qm_col_tab[][4] = {
> > -    {20,  9, 15,  4},
> > -    { 0,  6,  6,  4},
> > -    { 0,  3,  3,  5},
> > -    { 0,  3,  5,  1},
> > -    { 0, 11, 10, 11}
> > -};
> > -
> > -static const uint8_t vc2_qm_flat_tab[][4] = {
> > -    { 0,  0,  0,  0},
> > -    { 0,  0,  0,  0},
> > -    { 0,  0,  0,  0},
> > -    { 0,  0,  0,  0},
> > -    { 0,  0,  0,  0}
> > -};
> > -
> > -static void init_quant_matrix(VC2EncContext *s)
> > -{
> > -    int level, orientation;
> > -
> > -    if (s->wavelet_depth <= 4 && s->quant_matrix == VC2_QM_DEF) {
> > -        s->custom_quant_matrix = 0;
> > -        for (level = 0; level < s->wavelet_depth; level++) {
> > -            s->quant[level][0] =
> ff_dirac_default_qmat[s->wavelet_idx][level][0];
> > -            s->quant[level][1] =
> ff_dirac_default_qmat[s->wavelet_idx][level][1];
> > -            s->quant[level][2] =
> ff_dirac_default_qmat[s->wavelet_idx][level][2];
> > -            s->quant[level][3] =
> ff_dirac_default_qmat[s->wavelet_idx][level][3];
> > -        }
> > -        return;
> > -    }
> > -
> > -    s->custom_quant_matrix = 1;
> > -
> > -    if (s->quant_matrix == VC2_QM_DEF) {
> > -        for (level = 0; level < s->wavelet_depth; level++) {
> > -            for (orientation = 0; orientation < 4; orientation++) {
> > -                if (level <= 3)
> > -                    s->quant[level][orientation] =
> ff_dirac_default_qmat[s->wavelet_idx][level][orientation];
> > -                else
> > -                    s->quant[level][orientation] =
> vc2_qm_col_tab[level][orientation];
> > -            }
> > -        }
> > -    } else if (s->quant_matrix == VC2_QM_COL) {
> > -        for (level = 0; level < s->wavelet_depth; level++) {
> > -            for (orientation = 0; orientation < 4; orientation++) {
> > -                s->quant[level][orientation] =
> vc2_qm_col_tab[level][orientation];
> > -            }
> > -        }
> > -    } else {
> > -        for (level = 0; level < s->wavelet_depth; level++) {
> > -            for (orientation = 0; orientation < 4; orientation++) {
> > -                s->quant[level][orientation] =
> vc2_qm_flat_tab[level][orientation];
> > -            }
> > -        }
> > -    }
> > -}
> > -
> > -/* VC-2 12.3.4.2 - quant_matrix() */
> > -static void encode_quant_matrix(VC2EncContext *s)
> > -{
> > -    int level;
> > -    put_bits(&s->pb, 1, s->custom_quant_matrix);
> > -    if (s->custom_quant_matrix) {
> > -        put_vc2_ue_uint(&s->pb, s->quant[0][0]);
> > -        for (level = 0; level < s->wavelet_depth; level++) {
> > -            put_vc2_ue_uint(&s->pb, s->quant[level][1]);
> > -            put_vc2_ue_uint(&s->pb, s->quant[level][2]);
> > -            put_vc2_ue_uint(&s->pb, s->quant[level][3]);
> > -        }
> > -    }
> > -}
> > -
> > -/* VC-2 12.3 - transform_parameters() */
> > -static void encode_transform_params(VC2EncContext *s)
> > -{
> > -    put_vc2_ue_uint(&s->pb, s->wavelet_idx);
> > -    put_vc2_ue_uint(&s->pb, s->wavelet_depth);
> > -
> > -    encode_slice_params(s);
> > -    encode_quant_matrix(s);
> > -}
> > -
> > -/* VC-2 12.2 - wavelet_transform() */
> > -static void encode_wavelet_transform(VC2EncContext *s)
> > -{
> > -    encode_transform_params(s);
> > -    align_put_bits(&s->pb);
> > -}
> > -
> > -/* VC-2 12 - picture_parse() */
> > -static void encode_picture_start(VC2EncContext *s)
> > -{
> > -    align_put_bits(&s->pb);
> > -    encode_picture_header(s);
> > -    align_put_bits(&s->pb);
> > -    encode_wavelet_transform(s);
> > -}
> > +#include "vc2enc_common.h"
> >
> >  #define QUANT(c, mul, add, shift) (((mul) * (c) + (add)) >> (shift))
> >
> > @@ -658,7 +159,7 @@ static int calc_slice_sizes(VC2EncContext *s)
> >      SliceArgs *enc_args = s->slice_args;
> >      SliceArgs *top_loc[SLICE_REDIST_TOTAL] = {NULL};
> >
> > -    init_quant_matrix(s);
> > +    ff_vc2_init_quant_matrix(s);
> >
> >      for (slice_y = 0; slice_y < s->num_y; slice_y++) {
> >          for (slice_x = 0; slice_x < s->num_x; slice_x++) {
> > @@ -931,24 +432,24 @@ static int encode_frame(VC2EncContext *s, AVPacket
> *avpkt, const AVFrame *frame,
> >      }
> >
> >      /* Sequence header */
> > -    encode_parse_info(s, DIRAC_PCODE_SEQ_HEADER);
> > -    encode_seq_header(s);
> > +    ff_vc2_encode_parse_info(s, DIRAC_PCODE_SEQ_HEADER);
> > +    ff_vc2_encode_seq_header(s);
> >
> >      /* Encoder version */
> >      if (aux_data) {
> > -        encode_parse_info(s, DIRAC_PCODE_AUX);
> > +        ff_vc2_encode_parse_info(s, DIRAC_PCODE_AUX);
> >          ff_put_string(&s->pb, aux_data, 1);
> >      }
> >
> >      /* Picture header */
> > -    encode_parse_info(s, DIRAC_PCODE_PICTURE_HQ);
> > -    encode_picture_start(s);
> > +    ff_vc2_encode_parse_info(s, DIRAC_PCODE_PICTURE_HQ);
> > +    ff_vc2_encode_picture_start(s);
> >
> >      /* Encode slices */
> >      encode_slices(s);
> >
> >      /* End sequence */
> > -    encode_parse_info(s, DIRAC_PCODE_END_SEQ);
> > +    ff_vc2_encode_parse_info(s, DIRAC_PCODE_END_SEQ);
> >
> >      return 0;
> >  }
> > diff --git a/libavcodec/vc2enc_common.c b/libavcodec/vc2enc_common.c
> > new file mode 100644
> > index 0000000000..2f40814f5a
> > --- /dev/null
> > +++ b/libavcodec/vc2enc_common.c
> > @@ -0,0 +1,321 @@
> > +/*
> > + * Copyright (C) 2016 Open Broadcast Systems Ltd.
> > + * Author        2016 Rostislav Pehlivanov <atomnuker@gmail.com>
> > + *
> > + * This file is part of FFmpeg.
> > + *
> > + * FFmpeg is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU Lesser General Public
> > + * License as published by the Free Software Foundation; either
> > + * version 2.1 of the License, or (at your option) any later version.
> > + *
> > + * FFmpeg is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > + * Lesser General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU Lesser General Public
> > + * License along with FFmpeg; if not, write to the Free Software
> > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> 02110-1301 USA
> > + */
> > +
> > +#include "vc2enc_common.h"
> > +
> > +/* VC-2 10.4 - parse_info() */
> > +void ff_vc2_encode_parse_info(VC2EncContext *s, enum DiracParseCodes
> pcode)
> > +{
> > +    uint32_t cur_pos, dist;
> > +
> > +    align_put_bits(&s->pb);
> > +
> > +    cur_pos = put_bytes_count(&s->pb, 0);
> > +
> > +    /* Magic string */
> > +    ff_put_string(&s->pb, "BBCD", 0);
> > +
> > +    /* Parse code */
> > +    put_bits(&s->pb, 8, pcode);
> > +
> > +    /* Next parse offset */
> > +    dist = cur_pos - s->next_parse_offset;
> > +    AV_WB32(s->pb.buf + s->next_parse_offset + 5, dist);
> > +    s->next_parse_offset = cur_pos;
> > +    put_bits32(&s->pb, pcode == DIRAC_PCODE_END_SEQ ? 13 : 0);
> > +
> > +    cur_pos = put_bytes_count(&s->pb, 0);
> > +
> > +    /* Last parse offset */
> > +    put_bits32(&s->pb, s->last_parse_code == DIRAC_PCODE_END_SEQ ? 13 :
> dist);
> > +
> > +    s->last_parse_code = pcode;
> > +}
> > +
> > +/* VC-2 11.1 - parse_parameters()
> > + * The level dictates what the decoder should expect in terms of
> resolution
> > + * and allows it to quickly reject whatever it can't support. Remember,
> > + * this codec kinda targets cheapo FPGAs without much memory.
> Unfortunately
> > + * it also limits us greatly in our choice of formats, hence the flag
> to disable
> > + * strict_compliance */
> > +static void encode_parse_params(VC2EncContext *s)
> > +{
> > +    put_vc2_ue_uint(&s->pb, s->ver.major); /* VC-2 demands this to be 2
> */
> > +    put_vc2_ue_uint(&s->pb, s->ver.minor); /* ^^ and this to be 0
>  */
> > +    put_vc2_ue_uint(&s->pb, s->profile);   /* 3 to signal HQ profile
> */
> > +    put_vc2_ue_uint(&s->pb, s->level);     /* 3 - 1080/720, 6 - 4K
> */
> > +}
> > +
> > +/* VC-2 11.3 - frame_size() */
> > +static void encode_frame_size(VC2EncContext *s)
> > +{
> > +    put_bits(&s->pb, 1, !s->strict_compliance);
> > +    if (!s->strict_compliance) {
> > +        AVCodecContext *avctx = s->avctx;
> > +        put_vc2_ue_uint(&s->pb, avctx->width);
> > +        put_vc2_ue_uint(&s->pb, avctx->height);
> > +    }
> > +}
> > +
> > +/* VC-2 11.3.3 - color_diff_sampling_format() */
> > +static void encode_sample_fmt(VC2EncContext *s)
> > +{
> > +    put_bits(&s->pb, 1, !s->strict_compliance);
> > +    if (!s->strict_compliance) {
> > +        int idx;
> > +        if (s->chroma_x_shift == 1 && s->chroma_y_shift == 0)
> > +            idx = 1; /* 422 */
> > +        else if (s->chroma_x_shift == 1 && s->chroma_y_shift == 1)
> > +            idx = 2; /* 420 */
> > +        else
> > +            idx = 0; /* 444 */
> > +        put_vc2_ue_uint(&s->pb, idx);
> > +    }
> > +}
> > +
> > +/* VC-2 11.3.4 - scan_format() */
> > +static void encode_scan_format(VC2EncContext *s)
> > +{
> > +    put_bits(&s->pb, 1, !s->strict_compliance);
> > +    if (!s->strict_compliance)
> > +        put_vc2_ue_uint(&s->pb, s->interlaced);
> > +}
> > +
> > +/* VC-2 11.3.5 - frame_rate() */
> > +static void encode_frame_rate(VC2EncContext *s)
> > +{
> > +    put_bits(&s->pb, 1, !s->strict_compliance);
> > +    if (!s->strict_compliance) {
> > +        AVCodecContext *avctx = s->avctx;
> > +        put_vc2_ue_uint(&s->pb, 0);
> > +        put_vc2_ue_uint(&s->pb, avctx->time_base.den);
> > +        put_vc2_ue_uint(&s->pb, avctx->time_base.num);
> > +    }
> > +}
> > +
> > +/* VC-2 11.3.6 - aspect_ratio() */
> > +static void encode_aspect_ratio(VC2EncContext *s)
> > +{
> > +    put_bits(&s->pb, 1, !s->strict_compliance);
> > +    if (!s->strict_compliance) {
> > +        AVCodecContext *avctx = s->avctx;
> > +        put_vc2_ue_uint(&s->pb, 0);
> > +        put_vc2_ue_uint(&s->pb, avctx->sample_aspect_ratio.num);
> > +        put_vc2_ue_uint(&s->pb, avctx->sample_aspect_ratio.den);
> > +    }
> > +}
> > +
> > +/* VC-2 11.3.7 - clean_area() */
> > +static void encode_clean_area(VC2EncContext *s)
> > +{
> > +    put_bits(&s->pb, 1, 0);
> > +}
> > +
> > +/* VC-2 11.3.8 - signal_range() */
> > +static void encode_signal_range(VC2EncContext *s)
> > +{
> > +    put_bits(&s->pb, 1, !s->strict_compliance);
> > +    if (!s->strict_compliance)
> > +        put_vc2_ue_uint(&s->pb, s->bpp_idx);
> > +}
> > +
> > +/* VC-2 11.3.9 - color_spec() */
> > +static void encode_color_spec(VC2EncContext *s)
> > +{
> > +    AVCodecContext *avctx = s->avctx;
> > +    put_bits(&s->pb, 1, !s->strict_compliance);
> > +    if (!s->strict_compliance) {
> > +        int val;
> > +        put_vc2_ue_uint(&s->pb, 0);
> > +
> > +        /* primaries */
> > +        put_bits(&s->pb, 1, 1);
> > +        if (avctx->color_primaries == AVCOL_PRI_BT470BG)
> > +            val = 2;
> > +        else if (avctx->color_primaries == AVCOL_PRI_SMPTE170M)
> > +            val = 1;
> > +        else if (avctx->color_primaries == AVCOL_PRI_SMPTE240M)
> > +            val = 1;
> > +        else
> > +            val = 0;
> > +        put_vc2_ue_uint(&s->pb, val);
> > +
> > +        /* color matrix */
> > +        put_bits(&s->pb, 1, 1);
> > +        if (avctx->colorspace == AVCOL_SPC_RGB)
> > +            val = 3;
> > +        else if (avctx->colorspace == AVCOL_SPC_YCOCG)
> > +            val = 2;
> > +        else if (avctx->colorspace == AVCOL_SPC_BT470BG)
> > +            val = 1;
> > +        else
> > +            val = 0;
> > +        put_vc2_ue_uint(&s->pb, val);
> > +
> > +        /* transfer function */
> > +        put_bits(&s->pb, 1, 1);
> > +        if (avctx->color_trc == AVCOL_TRC_LINEAR)
> > +            val = 2;
> > +        else if (avctx->color_trc == AVCOL_TRC_BT1361_ECG)
> > +            val = 1;
> > +        else
> > +            val = 0;
> > +        put_vc2_ue_uint(&s->pb, val);
> > +    }
> > +}
> > +
> > +/* VC-2 11.3 - source_parameters() */
> > +static void encode_source_params(VC2EncContext *s)
> > +{
> > +    encode_frame_size(s);
> > +    encode_sample_fmt(s);
> > +    encode_scan_format(s);
> > +    encode_frame_rate(s);
> > +    encode_aspect_ratio(s);
> > +    encode_clean_area(s);
> > +    encode_signal_range(s);
> > +    encode_color_spec(s);
> > +}
> > +
> > +/* VC-2 11 - sequence_header() */
> > +void ff_vc2_encode_seq_header(VC2EncContext *s)
> > +{
> > +    align_put_bits(&s->pb);
> > +    encode_parse_params(s);
> > +    put_vc2_ue_uint(&s->pb, s->base_vf);
> > +    encode_source_params(s);
> > +    put_vc2_ue_uint(&s->pb, s->interlaced); /* Frames or fields coding
> */
> > +}
> > +
> > +/* VC-2 12.1 - picture_header() */
> > +static void encode_picture_header(VC2EncContext *s)
> > +{
> > +    align_put_bits(&s->pb);
> > +    put_bits32(&s->pb, s->picture_number++);
> > +}
> > +
> > +/* VC-2 12.3.4.1 - slice_parameters() */
> > +static void encode_slice_params(VC2EncContext *s)
> > +{
> > +    put_vc2_ue_uint(&s->pb, s->num_x);
> > +    put_vc2_ue_uint(&s->pb, s->num_y);
> > +    put_vc2_ue_uint(&s->pb, s->prefix_bytes);
> > +    put_vc2_ue_uint(&s->pb, s->size_scaler);
> > +}
> > +
> > +/* 1st idx = LL, second - vertical, third - horizontal, fourth - total
> */
> > +static const uint8_t vc2_qm_col_tab[][4] = {
> > +    {20,  9, 15,  4},
> > +    { 0,  6,  6,  4},
> > +    { 0,  3,  3,  5},
> > +    { 0,  3,  5,  1},
> > +    { 0, 11, 10, 11}
> > +};
> > +
> > +static const uint8_t vc2_qm_flat_tab[][4] = {
> > +    { 0,  0,  0,  0},
> > +    { 0,  0,  0,  0},
> > +    { 0,  0,  0,  0},
> > +    { 0,  0,  0,  0},
> > +    { 0,  0,  0,  0}
> > +};
> > +
> > +void ff_vc2_init_quant_matrix(VC2EncContext *s)
> > +{
> > +    int level, orientation;
> > +
> > +    if (s->wavelet_depth <= 4 && s->quant_matrix == VC2_QM_DEF) {
> > +        s->custom_quant_matrix = 0;
> > +        for (level = 0; level < s->wavelet_depth; level++) {
> > +            s->quant[level][0] =
> ff_dirac_default_qmat[s->wavelet_idx][level][0];
> > +            s->quant[level][1] =
> ff_dirac_default_qmat[s->wavelet_idx][level][1];
> > +            s->quant[level][2] =
> ff_dirac_default_qmat[s->wavelet_idx][level][2];
> > +            s->quant[level][3] =
> ff_dirac_default_qmat[s->wavelet_idx][level][3];
> > +        }
> > +        return;
> > +    }
> > +
> > +    s->custom_quant_matrix = 1;
> > +
> > +    if (s->quant_matrix == VC2_QM_DEF) {
> > +        for (level = 0; level < s->wavelet_depth; level++) {
> > +            for (orientation = 0; orientation < 4; orientation++) {
> > +                if (level <= 3)
> > +                    s->quant[level][orientation] =
> ff_dirac_default_qmat[s->wavelet_idx][level][orientation];
> > +                else
> > +                    s->quant[level][orientation] =
> vc2_qm_col_tab[level][orientation];
> > +            }
> > +        }
> > +    } else if (s->quant_matrix == VC2_QM_COL) {
> > +        for (level = 0; level < s->wavelet_depth; level++) {
> > +            for (orientation = 0; orientation < 4; orientation++) {
> > +                s->quant[level][orientation] =
> vc2_qm_col_tab[level][orientation];
> > +            }
> > +        }
> > +    } else {
> > +        for (level = 0; level < s->wavelet_depth; level++) {
> > +            for (orientation = 0; orientation < 4; orientation++) {
> > +                s->quant[level][orientation] =
> vc2_qm_flat_tab[level][orientation];
> > +            }
> > +        }
> > +    }
> > +}
> > +
> > +/* VC-2 12.3.4.2 - quant_matrix() */
> > +static void encode_quant_matrix(VC2EncContext *s)
> > +{
> > +    int level;
> > +    put_bits(&s->pb, 1, s->custom_quant_matrix);
> > +    if (s->custom_quant_matrix) {
> > +        put_vc2_ue_uint(&s->pb, s->quant[0][0]);
> > +        for (level = 0; level < s->wavelet_depth; level++) {
> > +            put_vc2_ue_uint(&s->pb, s->quant[level][1]);
> > +            put_vc2_ue_uint(&s->pb, s->quant[level][2]);
> > +            put_vc2_ue_uint(&s->pb, s->quant[level][3]);
> > +        }
> > +    }
> > +}
> > +
> > +/* VC-2 12.3 - transform_parameters() */
> > +static void encode_transform_params(VC2EncContext *s)
> > +{
> > +    put_vc2_ue_uint(&s->pb, s->wavelet_idx);
> > +    put_vc2_ue_uint(&s->pb, s->wavelet_depth);
> > +
> > +    encode_slice_params(s);
> > +    encode_quant_matrix(s);
> > +}
> > +
> > +/* VC-2 12.2 - wavelet_transform() */
> > +static void encode_wavelet_transform(VC2EncContext *s)
> > +{
> > +    encode_transform_params(s);
> > +    align_put_bits(&s->pb);
> > +}
> > +
> > +/* VC-2 12 - picture_parse() */
> > +void ff_vc2_encode_picture_start(VC2EncContext *s)
> > +{
> > +    align_put_bits(&s->pb);
> > +    encode_picture_header(s);
> > +    align_put_bits(&s->pb);
> > +    encode_wavelet_transform(s);
> > +}
> > diff --git a/libavcodec/vc2enc_common.h b/libavcodec/vc2enc_common.h
> > new file mode 100644
> > index 0000000000..72e944c8e6
> > --- /dev/null
> > +++ b/libavcodec/vc2enc_common.h
> > @@ -0,0 +1,323 @@
> > +/*
> > + * Copyright (C) 2016 Open Broadcast Systems Ltd.
> > + * Author        2016 Rostislav Pehlivanov <atomnuker@gmail.com>
> > + *
> > + * This file is part of FFmpeg.
> > + *
> > + * FFmpeg is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU Lesser General Public
> > + * License as published by the Free Software Foundation; either
> > + * version 2.1 of the License, or (at your option) any later version.
> > + *
> > + * FFmpeg is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > + * Lesser General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU Lesser General Public
> > + * License along with FFmpeg; if not, write to the Free Software
> > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> 02110-1301 USA
> > + */
> > +
> > +#ifndef AVCODEC_VC2ENC_COMMON_H
> > +#define AVCODEC_VC2ENC_COMMON_H
> > +
> > +#include "avcodec.h"
> > +#include "dirac.h"
> > +#include "put_bits.h"
> > +
> > +#include "vc2enc_dwt.h"
> > +#include "diractab.h"
> > +#include "libavutil/vulkan.h"
>
> This header relies on vulkan headers being present and must therefore
> not be included by any non-vulkan code.
>
> > +
> > +/* The limited size resolution of each slice forces us to do this */
> > +#define SSIZE_ROUND(b) (FFALIGN((b), s->size_scaler) + 4 +
> s->prefix_bytes)
> > +
> > +/* Decides the cutoff point in # of slices to distribute the leftover
> bytes */
> > +#define SLICE_REDIST_TOTAL 150
> > +
> > +typedef struct VC2BaseVideoFormat {
> > +    enum AVPixelFormat pix_fmt;
> > +    AVRational time_base;
> > +    int width, height;
> > +    uint8_t interlaced, level;
> > +    char name[13];
> > +} VC2BaseVideoFormat;
> > +
> > +static const VC2BaseVideoFormat base_video_fmts[] = {
> > +    { 0 }, /* Custom format, here just to make indexing equal to
> base_vf */
> > +    { AV_PIX_FMT_YUV420P,   { 1001, 15000 },  176,  120, 0, 1,
>  "QSIF525" },
> > +    { AV_PIX_FMT_YUV420P,   {    2,    25 },  176,  144, 0, 1,
>  "QCIF"    },
> > +    { AV_PIX_FMT_YUV420P,   { 1001, 15000 },  352,  240, 0, 1,
>  "SIF525"  },
> > +    { AV_PIX_FMT_YUV420P,   {    2,    25 },  352,  288, 0, 1,
>  "CIF"     },
> > +    { AV_PIX_FMT_YUV420P,   { 1001, 15000 },  704,  480, 0, 1,
>  "4SIF525" },
> > +    { AV_PIX_FMT_YUV420P,   {    2,    25 },  704,  576, 0, 1,
>  "4CIF"    },
> > +
> > +    { AV_PIX_FMT_YUV422P10, { 1001, 30000 },  720,  480, 1, 2,
>  "SD480I-60" },
> > +    { AV_PIX_FMT_YUV422P10, {    1,    25 },  720,  576, 1, 2,
>  "SD576I-50" },
> > +
> > +    { AV_PIX_FMT_YUV422P10, { 1001, 60000 }, 1280,  720, 0, 3,
> "HD720P-60"  },
> > +    { AV_PIX_FMT_YUV422P10, {    1,    50 }, 1280,  720, 0, 3,
> "HD720P-50"  },
> > +    { AV_PIX_FMT_YUV422P10, { 1001, 30000 }, 1920, 1080, 1, 3,
> "HD1080I-60" },
> > +    { AV_PIX_FMT_YUV422P10, {    1,    25 }, 1920, 1080, 1, 3,
> "HD1080I-50" },
> > +    { AV_PIX_FMT_YUV422P10, { 1001, 60000 }, 1920, 1080, 0, 3,
> "HD1080P-60" },
> > +    { AV_PIX_FMT_YUV422P10, {    1,    50 }, 1920, 1080, 0, 3,
> "HD1080P-50" },
> > +
> > +    { AV_PIX_FMT_YUV444P12, {    1,    24 }, 2048, 1080, 0, 4,
> "DC2K" },
> > +    { AV_PIX_FMT_YUV444P12, {    1,    24 }, 4096, 2160, 0, 5,
> "DC4K" },
> > +
> > +    { AV_PIX_FMT_YUV422P10, { 1001, 60000 }, 3840, 2160, 0, 6, "UHDTV
> 4K-60" },
> > +    { AV_PIX_FMT_YUV422P10, {    1,    50 }, 3840, 2160, 0, 6, "UHDTV
> 4K-50" },
> > +
> > +    { AV_PIX_FMT_YUV422P10, { 1001, 60000 }, 7680, 4320, 0, 7, "UHDTV
> 8K-60" },
> > +    { AV_PIX_FMT_YUV422P10, {    1,    50 }, 7680, 4320, 0, 7, "UHDTV
> 8K-50" },
> > +
> > +    { AV_PIX_FMT_YUV422P10, { 1001, 24000 }, 1920, 1080, 0, 3,
> "HD1080P-24" },
> > +    { AV_PIX_FMT_YUV422P10, { 1001, 30000 },  720,  486, 1, 2,  "SD
> Pro486"  },
> > +};
> > +static const int base_video_fmts_len = FF_ARRAY_ELEMS(base_video_fmts);
>
> Don't duplicate this array.
>
> > +
> > +enum VC2_QM {
> > +    VC2_QM_DEF = 0,
> > +    VC2_QM_COL,
> > +    VC2_QM_FLAT,
> > +
> > +    VC2_QM_NB
> > +};
> > +
> > +typedef struct SubBand {
> > +    dwtcoef *buf;
> > +    ptrdiff_t stride;
> > +    int width;
> > +    int height;
> > +    int shift;
> > +} SubBand;
> > +
> > +typedef struct Plane {
> > +    SubBand band[MAX_DWT_LEVELS][4];
> > +    dwtcoef *coef_buf;
> > +    int width;
> > +    int height;
> > +    int dwt_width;
> > +    int dwt_height;
> > +    ptrdiff_t coef_stride;
> > +} Plane;
> > +
> > +typedef struct SliceArgs {
> > +    const struct VC2EncContext *ctx;
> > +    union {
> > +        int cache[DIRAC_MAX_QUANT_INDEX];
> > +        uint8_t *buf;
> > +    };
> > +    int x;
> > +    int y;
> > +    int quant_idx;
> > +    int bits_ceil;
> > +    int bits_floor;
> > +    int bytes;
> > +} SliceArgs;
> > +
> > +typedef struct TransformArgs {
> > +    struct VC2EncContext *ctx;
> > +    Plane *plane;
> > +    const void *idata;
> > +    ptrdiff_t istride;
> > +    int field;
> > +    VC2TransformContext t;
> > +} TransformArgs;
> > +
> > +typedef struct VC2DwtPlane {
> > +    int width;
> > +    int height;
> > +    int dwt_width;
> > +    int dwt_height;
> > +} VC2DwtPlane;
> > +
> > +typedef struct VC2DwtPushData {
> > +    int s;
> > +    union {
> > +        int diff_offset;
> > +        int plane_idx;
> > +    };
> > +    int level;
> > +    VC2DwtPlane planes[3];
> > +} VC2DwtPushData;
> > +
> > +typedef struct VC2EncAuxData {
> > +    uint32_t quant[MAX_DWT_LEVELS][4];
> > +    int ff_dirac_qscale_tab[116];
> > +} VC2EncAuxData;
> > +
> > +typedef struct VC2EncPushData {
> > +    VkDeviceAddress pb;
> > +    VkDeviceAddress luts;
> > +    VkDeviceAddress slice;
> > +    int num_x;
> > +    int num_y;
> > +    VC2DwtPlane planes[3];
> > +    int wavelet_depth;
> > +    int size_scaler;
> > +    int prefix_bytes;
> > +} VC2EncPushData;
> > +
> > +typedef struct VC2EncSliceArgs {
> > +    int quant_idx;
> > +    int bytes;
> > +    int pb_start;
> > +    int pad;
> > +} VC2EncSliceArgs;
> > +
> > +typedef struct VC2EncSliceCalcPushData {
> > +    VkDeviceAddress luts;
> > +    VkDeviceAddress slice;
> > +    int num_x;
> > +    int num_y;
> > +    VC2DwtPlane planes[3];
> > +    int wavelet_depth;
> > +    int size_scaler;
> > +    int prefix_bytes;
> > +    int bits_ceil;
> > +    int bits_floor;
> > +} VC2EncSliceCalcPushData;
> > +
> > +typedef struct VC2EncContext {
> > +    AVClass *av_class;
> > +    PutBitContext pb;
> > +    Plane plane[3];
> > +    AVCodecContext *avctx;
> > +    DiracVersionInfo ver;
> > +
> > +    SliceArgs *slice_args;
> > +    VC2EncSliceArgs* vk_slice_args;
> > +    TransformArgs transform_args[3];
> > +
> > +    /* For conversion from unsigned pixel values to signed */
> > +    int diff_offset;
> > +    int bpp;
> > +    int bpp_idx;
> > +
> > +    /* Picture number */
> > +    uint32_t picture_number;
> > +
> > +    /* Base video format */
> > +    int base_vf;
> > +    int level;
> > +    int profile;
> > +
> > +    /* Quantization matrix */
> > +    uint8_t quant[MAX_DWT_LEVELS][4];
> > +    int custom_quant_matrix;
> > +
> > +    /* Division LUT */
> > +    uint32_t qmagic_lut[116][2];
> > +
> > +    int num_x; /* #slices horizontally */
> > +    int num_y; /* #slices vertically */
> > +    int group_x;
> > +    int group_y;
> > +    int prefix_bytes;
> > +    int size_scaler;
> > +    int chroma_x_shift;
> > +    int chroma_y_shift;
> > +
> > +    /* Rate control stuff */
> > +    int frame_max_bytes;
> > +    int slice_max_bytes;
> > +    int slice_min_bytes;
> > +    int q_ceil;
> > +    int q_avg;
> > +
> > +    /* Options */
> > +    double tolerance;
> > +    int wavelet_idx;
> > +    int wavelet_depth;
> > +    int strict_compliance;
> > +    int slice_height;
> > +    int slice_width;
> > +    int interlaced;
> > +    enum VC2_QM quant_matrix;
> > +
> > +    /* Parse code state */
> > +    uint32_t next_parse_offset;
> > +    enum DiracParseCodes last_parse_code;
> > +
> > +    /* Vulkan state */
> > +    FFVulkanContext vkctx;
> > +    AVVulkanDeviceQueueFamily *qf;
> > +    FFVkExecPool e;
> > +
> > +    FFVulkanShader dwt_haar_shd;
> > +    FFVulkanShader dwt_upload_shd;
> > +    FFVulkanShader dwt_hor_shd, dwt_ver_shd;
> > +    FFVulkanShader slice_shd;
> > +    FFVulkanShader enc_shd;
>
> You are adding your vulkan stuff to the common header. This means that
> the software encoder's private context will be bloated with stuff it
> does not use at all which is not how it should be done even if it could
> be done. But it can't given that the vulkan header is not always available.
>
> It also means that your commit message is absolutely wrong: You are not
> only splitting out, you are adding new stuff.
>
> Instead you should use a common base structure containing the stuff that
> the common functions need to access and use extended structures (one for
> each encoder) as private contexts for the encoders.
>
> > +    AVBufferPool* dwt_buf_pool;
> > +    int haar_subgroup;
> > +
> > +    VkBuffer plane_buf, slice_buf;
> > +    VC2EncPushData enc_consts;
> > +    VC2DwtPushData dwt_consts;
> > +    VC2EncSliceCalcPushData calc_consts;
> > +
> > +    /* Intermediate frame pool */
> > +    AVBufferRef *intermediate_frames_ref[3];
> > +    AVFrame *intermediate_frame[AV_NUM_DATA_POINTERS];
> > +    VkImageView intermediate_views[AV_NUM_DATA_POINTERS];
> > +} VC2EncContext;
> > +
> > +static inline void put_vc2_ue_uint(PutBitContext *pb, uint32_t val)
> > +{
> > +    int i;
> > +    int bits = 0;
> > +    unsigned topbit = 1, maxval = 1;
> > +    uint64_t pbits = 0;
> > +
> > +    if (!val++) {
> > +        put_bits(pb, 1, 1);
> > +        return;
> > +    }
> > +
> > +    while (val > maxval) {
> > +        topbit <<= 1;
> > +        maxval <<= 1;
> > +        maxval |=  1;
> > +    }
> > +
> > +    bits = ff_log2(topbit);
> > +
> > +    for (i = 0; i < bits; i++) {
> > +        topbit >>= 1;
> > +        av_assert2(pbits <= UINT64_MAX>>3);
> > +        pbits <<= 2;
> > +        if (val & topbit)
> > +            pbits |= 0x1;
> > +    }
> > +
> > +    put_bits64(pb, bits*2 + 1, (pbits << 1) | 1);
> > +}
> > +
> > +static inline int count_vc2_ue_uint(uint32_t val)
> > +{
> > +    int topbit = 1, maxval = 1;
> > +
> > +    if (!val++)
> > +        return 1;
> > +
> > +    while (val > maxval) {
> > +        topbit <<= 1;
> > +        maxval <<= 1;
> > +        maxval |=  1;
> > +    }
> > +
> > +    return ff_log2(topbit)*2 + 1;
> > +}
> > +
> > +void ff_vc2_init_quant_matrix(VC2EncContext *s);
> > +
> > +void ff_vc2_encode_parse_info(VC2EncContext *s, enum DiracParseCodes
> pcode);
> > +
> > +void ff_vc2_encode_seq_header(VC2EncContext *s);
> > +
> > +void ff_vc2_encode_picture_start(VC2EncContext *s);
> > +
> > +#endif
>
> _______________________________________________
> 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".
>
_______________________________________________
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".

  reply	other threads:[~2025-03-08 13:52 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-08 12:21 IndecisiveTurtle
2025-03-08 12:21 ` [FFmpeg-devel] [PATCH 2/4] libavcodec/vulkan: Add modifications to common shader for VC2 vulkan encoder IndecisiveTurtle
2025-03-08 12:21 ` [FFmpeg-devel] [PATCH 3/4] libavcodec/vulkan: Add vulkan vc2 shaders IndecisiveTurtle
2025-03-08 12:21 ` [FFmpeg-devel] [PATCH 4/4] avcodec/vc2enc: Initial vulkan VC2 encoder Implements a Vulkan based dirac encoder. Supports Haar and Legall wavelets and should work with all wavelet depths IndecisiveTurtle
2025-03-08 13:13 ` [FFmpeg-devel] [PATCH 1/4] libavcodec/vc2enc: Split out common functions between software and hardware encoders Andreas Rheinhardt
2025-03-08 13:52   ` IndecisiveTurtle [this message]
2025-03-08 14:05     ` Andreas Rheinhardt
2025-03-08 14:22       ` IndecisiveTurtle

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAJpqCyKq8k_dLpYnYt-P6COwC6g6W7Dso+6B=BcJBZvRLgN9uA@mail.gmail.com' \
    --to=geoster3d@gmail.com \
    --cc=ffmpeg-devel@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git