static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic,

                            int trellis_node, int x, int y, int mbs_per_slice)

{

    ProresContext *ctx = avctx->priv_data;

    int i, q, pq, xp, yp;

    const uint16_t *src;

    int slice_width_factor = av_log2(mbs_per_slice);

    int num_cblocks[MAX_PLANES], pwidth;

    int plane_factor[MAX_PLANES], is_chroma[MAX_PLANES];

    const int min_quant = ctx->profile_info->min_quant;

    const int max_quant = ctx->profile_info->max_quant;

    int error, bits, bits_limit;

    int mbs, prev, cur, new_score;

    int slice_bits[TRELLIS_WIDTH], slice_score[TRELLIS_WIDTH];



    mbs = x + mbs_per_slice;



    for (i = 0; i < ctx->num_planes; i++) {

        is_chroma[i]    = (i == 1 || i == 2);

        plane_factor[i] = slice_width_factor + 2;

        if (is_chroma[i])

            plane_factor[i] += ctx->chroma_factor - 3;

        if (!is_chroma[i] || ctx->chroma_factor == CFACTOR_Y444) {

            xp             = x << 4;

            yp             = y << 4;

            num_cblocks[i] = 4;

            pwidth         = avctx->width;

        } else {

            xp             = x << 3;

            yp             = y << 4;

            num_cblocks[i] = 2;

            pwidth         = avctx->width >> 1;

        }

        src = (const uint16_t*)(pic->data[i] + yp * pic->linesize[i]) + xp;



        get_slice_data(ctx, src, pic->linesize[i], xp, yp,

                       pwidth, avctx->height, ctx->blocks[i],

                       mbs_per_slice, num_cblocks[i]);

    }



    for (q = min_quant; q <= max_quant; q++) {

        ctx->nodes[trellis_node + q].prev_node = -1;

        ctx->nodes[trellis_node + q].quant     = q;

    }



    // todo: maybe perform coarser quantising to fit into frame size when needed

    for (q = min_quant; q <= max_quant; q++) {

        bits  = 0;

        error = 0;

        for (i = 0; i < ctx->num_planes; i++) {

            bits += estimate_slice_plane(ctx, &error, i,

                                         src, pic->linesize[i],

                                         mbs_per_slice,

                                         num_cblocks[i], plane_factor[i],

                                         ctx->quants[q]);

        }

        if (bits > 65000 * 8) {

            error = SCORE_LIMIT;

            break;

        }

        slice_bits[q]  = bits;

        slice_score[q] = error;

    }



    bits_limit = mbs * ctx->bits_per_mb;

    for (pq = min_quant; pq <= max_quant; pq++) {

        prev = trellis_node - TRELLIS_WIDTH + pq;



        for (q = min_quant; q <= max_quant; q++) {

            cur = trellis_node + q;



            bits  = ctx->nodes[prev].bits + slice_bits[q];

            error = slice_score[q];

            if (bits > bits_limit)

                error = SCORE_LIMIT;



            if (ctx->nodes[prev].score < SCORE_LIMIT && error < SCORE_LIMIT)

                new_score = ctx->nodes[prev].score + error;

            else

                new_score = SCORE_LIMIT;

            if (ctx->nodes[cur].prev_node == -1 ||

                ctx->nodes[cur].score >= new_score) {



                ctx->nodes[cur].bits      = bits;

                ctx->nodes[cur].score     = new_score;

                ctx->nodes[cur].prev_node = prev;

            }

        }

    }



    error = ctx->nodes[trellis_node + min_quant].score;

    pq    = trellis_node + min_quant;

    for (q = min_quant + 1; q <= max_quant; q++) {

        if (ctx->nodes[trellis_node + q].score <= error) {

            error = ctx->nodes[trellis_node + q].score;

            pq    = trellis_node + q;

        }

    }



    return pq;

}

static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic,

                            int trellis_node, int x, int y, int mbs_per_slice)

{

    ProresContext *ctx = avctx->priv_data;

    int i, q, pq, xp, yp;

    const uint16_t *src;

    int slice_width_factor = av_log2(mbs_per_slice);

    int num_cblocks[MAX_PLANES], pwidth;

    int plane_factor[MAX_PLANES], is_chroma[MAX_PLANES];

    const int min_quant = ctx->profile_info->min_quant;

    const int max_quant = ctx->profile_info->max_quant;

    int error, bits, bits_limit;

    int mbs, prev, cur, new_score;

    int slice_bits[TRELLIS_WIDTH], slice_score[TRELLIS_WIDTH];



    mbs = x + mbs_per_slice;



    for (i = 0; i < ctx->num_planes; i++) {

        is_chroma[i]    = (i == 1 || i == 2);

        plane_factor[i] = slice_width_factor + 2;

        if (is_chroma[i])

            plane_factor[i] += ctx->chroma_factor - 3;

        if (!is_chroma[i] || ctx->chroma_factor == CFACTOR_Y444) {

            xp             = x << 4;

            yp             = y << 4;

            num_cblocks[i] = 4;

            pwidth         = avctx->width;

        } else {

            xp             = x << 3;

            yp             = y << 4;

            num_cblocks[i] = 2;

            pwidth         = avctx->width >> 1;

        }

        src = (const uint16_t*)(pic->data[i] + yp * pic->linesize[i]) + xp;



        get_slice_data(ctx, src, pic->linesize[i], xp, yp,

                       pwidth, avctx->height, ctx->blocks[i],

                       mbs_per_slice, num_cblocks[i]);

    }



    for (q = min_quant; q <= max_quant; q++) {

        ctx->nodes[trellis_node + q].prev_node = -1;

        ctx->nodes[trellis_node + q].quant     = q;

    }



    

    for (q = min_quant; q <= max_quant; q++) {

        bits  = 0;

        error = 0;

        for (i = 0; i < ctx->num_planes; i++) {

            bits += estimate_slice_plane(ctx, &error, i,

                                         src, pic->linesize[i],

                                         mbs_per_slice,

                                         num_cblocks[i], plane_factor[i],

                                         ctx->quants[q]);

        }

        if (bits > 65000 * 8) {

            error = SCORE_LIMIT;

            break;

        }

        slice_bits[q]  = bits;

        slice_score[q] = error;

    }



    bits_limit = mbs * ctx->bits_per_mb;

    for (pq = min_quant; pq <= max_quant; pq++) {

        prev = trellis_node - TRELLIS_WIDTH + pq;



        for (q = min_quant; q <= max_quant; q++) {

            cur = trellis_node + q;



            bits  = ctx->nodes[prev].bits + slice_bits[q];

            error = slice_score[q];

            if (bits > bits_limit)

                error = SCORE_LIMIT;



            if (ctx->nodes[prev].score < SCORE_LIMIT && error < SCORE_LIMIT)

                new_score = ctx->nodes[prev].score + error;

            else

                new_score = SCORE_LIMIT;

            if (ctx->nodes[cur].prev_node == -1 ||

                ctx->nodes[cur].score >= new_score) {



                ctx->nodes[cur].bits      = bits;

                ctx->nodes[cur].score     = new_score;

                ctx->nodes[cur].prev_node = prev;

            }

        }

    }



    error = ctx->nodes[trellis_node + min_quant].score;

    pq    = trellis_node + min_quant;

    for (q = min_quant + 1; q <= max_quant; q++) {

        if (ctx->nodes[trellis_node + q].score <= error) {

            error = ctx->nodes[trellis_node + q].score;

            pq    = trellis_node + q;

        }

    }



    return pq;

}

static int FUNC_0(AVCodecContext *VAR_0, const AVFrame *VAR_1,

                            int VAR_2, int VAR_3, int VAR_4, int VAR_5)

{

    ProresContext *ctx = VAR_0->priv_data;

    int VAR_6, VAR_7, VAR_8, VAR_9, VAR_10;

    const uint16_t *VAR_11;

    int VAR_12 = av_log2(VAR_5);

    int VAR_13[MAX_PLANES], pwidth;

    int VAR_14[MAX_PLANES], is_chroma[MAX_PLANES];

    const int VAR_15 = ctx->profile_info->VAR_15;

    const int VAR_16 = ctx->profile_info->VAR_16;

    int VAR_17, VAR_18, VAR_19;

    int VAR_20, VAR_21, VAR_22, VAR_23;

    int VAR_24[TRELLIS_WIDTH], slice_score[TRELLIS_WIDTH];



    VAR_20 = VAR_3 + VAR_5;



    for (VAR_6 = 0; VAR_6 < ctx->num_planes; VAR_6++) {

        is_chroma[VAR_6]    = (VAR_6 == 1 || VAR_6 == 2);

        VAR_14[VAR_6] = VAR_12 + 2;

        if (is_chroma[VAR_6])

            VAR_14[VAR_6] += ctx->chroma_factor - 3;

        if (!is_chroma[VAR_6] || ctx->chroma_factor == CFACTOR_Y444) {

            VAR_9             = VAR_3 << 4;

            VAR_10             = VAR_4 << 4;

            VAR_13[VAR_6] = 4;

            pwidth         = VAR_0->width;

        } else {

            VAR_9             = VAR_3 << 3;

            VAR_10             = VAR_4 << 4;

            VAR_13[VAR_6] = 2;

            pwidth         = VAR_0->width >> 1;

        }

        VAR_11 = (const uint16_t*)(VAR_1->data[VAR_6] + VAR_10 * VAR_1->linesize[VAR_6]) + VAR_9;



        get_slice_data(ctx, VAR_11, VAR_1->linesize[VAR_6], VAR_9, VAR_10,

                       pwidth, VAR_0->height, ctx->blocks[VAR_6],

                       VAR_5, VAR_13[VAR_6]);

    }



    for (VAR_7 = VAR_15; VAR_7 <= VAR_16; VAR_7++) {

        ctx->nodes[VAR_2 + VAR_7].prev_node = -1;

        ctx->nodes[VAR_2 + VAR_7].quant     = VAR_7;

    }



    

    for (VAR_7 = VAR_15; VAR_7 <= VAR_16; VAR_7++) {

        VAR_18  = 0;

        VAR_17 = 0;

        for (VAR_6 = 0; VAR_6 < ctx->num_planes; VAR_6++) {

            VAR_18 += estimate_slice_plane(ctx, &VAR_17, VAR_6,

                                         VAR_11, VAR_1->linesize[VAR_6],

                                         VAR_5,

                                         VAR_13[VAR_6], VAR_14[VAR_6],

                                         ctx->quants[VAR_7]);

        }

        if (VAR_18 > 65000 * 8) {

            VAR_17 = SCORE_LIMIT;

            break;

        }

        VAR_24[VAR_7]  = VAR_18;

        slice_score[VAR_7] = VAR_17;

    }



    VAR_19 = VAR_20 * ctx->bits_per_mb;

    for (VAR_8 = VAR_15; VAR_8 <= VAR_16; VAR_8++) {

        VAR_21 = VAR_2 - TRELLIS_WIDTH + VAR_8;



        for (VAR_7 = VAR_15; VAR_7 <= VAR_16; VAR_7++) {

            VAR_22 = VAR_2 + VAR_7;



            VAR_18  = ctx->nodes[VAR_21].VAR_18 + VAR_24[VAR_7];

            VAR_17 = slice_score[VAR_7];

            if (VAR_18 > VAR_19)

                VAR_17 = SCORE_LIMIT;



            if (ctx->nodes[VAR_21].score < SCORE_LIMIT && VAR_17 < SCORE_LIMIT)

                VAR_23 = ctx->nodes[VAR_21].score + VAR_17;

            else

                VAR_23 = SCORE_LIMIT;

            if (ctx->nodes[VAR_22].prev_node == -1 ||

                ctx->nodes[VAR_22].score >= VAR_23) {



                ctx->nodes[VAR_22].VAR_18      = VAR_18;

                ctx->nodes[VAR_22].score     = VAR_23;

                ctx->nodes[VAR_22].prev_node = VAR_21;

            }

        }

    }



    VAR_17 = ctx->nodes[VAR_2 + VAR_15].score;

    VAR_8    = VAR_2 + VAR_15;

    for (VAR_7 = VAR_15 + 1; VAR_7 <= VAR_16; VAR_7++) {

        if (ctx->nodes[VAR_2 + VAR_7].score <= VAR_17) {

            VAR_17 = ctx->nodes[VAR_2 + VAR_7].score;

            VAR_8    = VAR_2 + VAR_7;

        }

    }



    return VAR_8;

}

static int FUNC_0(AVCodecContext *VAR_0, const AVFrame *VAR_1,
int VAR_2, int VAR_3, int VAR_4, int VAR_5)
{ ProresContext *ctx = VAR_0->priv_data; int VAR_6, VAR_7, VAR_8, VAR_9, VAR_10; const uint16_t *VAR_11; int VAR_12 = av_log2(VAR_5); int VAR_13[MAX_PLANES], pwidth; int VAR_14[MAX_PLANES], is_chroma[MAX_PLANES]; const int VAR_15 = ctx->profile_info->VAR_15; const int VAR_16 = ctx->profile_info->VAR_16; int VAR_17, VAR_18, VAR_19; int VAR_20, VAR_21, VAR_22, VAR_23; int VAR_24[TRELLIS_WIDTH], slice_score[TRELLIS_WIDTH]; VAR_20 = VAR_3 + VAR_5; for (VAR_6 = 0; VAR_6 < ctx->num_planes; VAR_6++) { is_chroma[VAR_6]    = (VAR_6 == 1 || VAR_6 == 2); VAR_14[VAR_6] = VAR_12 + 2; if (is_chroma[VAR_6])
VAR_14[VAR_6] += ctx->chroma_factor - 3; if (!is_chroma[VAR_6] || ctx->chroma_factor == CFACTOR_Y444) { VAR_9             = VAR_3 << 4; VAR_10             = VAR_4 << 4; VAR_13[VAR_6] = 4; pwidth         = VAR_0->width; } else { VAR_9             = VAR_3 << 3; VAR_10             = VAR_4 << 4; VAR_13[VAR_6] = 2; pwidth         = VAR_0->width >> 1; } VAR_11 = (const uint16_t*)(VAR_1->data[VAR_6] + VAR_10 * VAR_1->linesize[VAR_6]) + VAR_9; get_slice_data(ctx, VAR_11, VAR_1->linesize[VAR_6], VAR_9, VAR_10,
pwidth, VAR_0->height, ctx->blocks[VAR_6],
VAR_5, VAR_13[VAR_6]); } for (VAR_7 = VAR_15; VAR_7 <= VAR_16; VAR_7++) { ctx->nodes[VAR_2 + VAR_7].prev_node = -1; ctx->nodes[VAR_2 + VAR_7].quant     = VAR_7; } for (VAR_7 = VAR_15; VAR_7 <= VAR_16; VAR_7++) { VAR_18  = 0; VAR_17 = 0; for (VAR_6 = 0; VAR_6 < ctx->num_planes; VAR_6++) { VAR_18 += estimate_slice_plane(ctx, &VAR_17, VAR_6,
VAR_11, VAR_1->linesize[VAR_6],
VAR_5,
VAR_13[VAR_6], VAR_14[VAR_6],
ctx->quants[VAR_7]); } if (VAR_18 > 65000 * 8) { VAR_17 = SCORE_LIMIT; break; } VAR_24[VAR_7]  = VAR_18; slice_score[VAR_7] = VAR_17; } VAR_19 = VAR_20 * ctx->bits_per_mb; for (VAR_8 = VAR_15; VAR_8 <= VAR_16; VAR_8++) { VAR_21 = VAR_2 - TRELLIS_WIDTH + VAR_8; for (VAR_7 = VAR_15; VAR_7 <= VAR_16; VAR_7++) { VAR_22 = VAR_2 + VAR_7; VAR_18  = ctx->nodes[VAR_21].VAR_18 + VAR_24[VAR_7]; VAR_17 = slice_score[VAR_7]; if (VAR_18 > VAR_19)
VAR_17 = SCORE_LIMIT; if (ctx->nodes[VAR_21].score < SCORE_LIMIT && VAR_17 < SCORE_LIMIT)
VAR_23 = ctx->nodes[VAR_21].score + VAR_17; else
VAR_23 = SCORE_LIMIT; if (ctx->nodes[VAR_22].prev_node == -1 ||
ctx->nodes[VAR_22].score >= VAR_23) { ctx->nodes[VAR_22].VAR_18      = VAR_18; ctx->nodes[VAR_22].score     = VAR_23; ctx->nodes[VAR_22].prev_node = VAR_21; } } } VAR_17 = ctx->nodes[VAR_2 + VAR_15].score; VAR_8    = VAR_2 + VAR_15; for (VAR_7 = VAR_15 + 1; VAR_7 <= VAR_16; VAR_7++) { if (ctx->nodes[VAR_2 + VAR_7].score <= VAR_17) { VAR_17 = ctx->nodes[VAR_2 + VAR_7].score; VAR_8    = VAR_2 + VAR_7; } } return VAR_8; }