/*
 * H.263 encoder header
 *
 * 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_H263ENC_H
#define AVCODEC_H263ENC_H

#include <stdint.h>
#include "h263data.h"
#include "mpegvideoenc.h"

void ff_h263_encode_init(MpegEncContext *s);
void ff_h263_encode_picture_header(MpegEncContext *s);
void ff_h263_encode_gob_header(MpegEncContext * s, int mb_line);
void ff_h263_encode_mb(MpegEncContext *s,
                       int16_t block[6][64],
                       int motion_x, int motion_y);
void ff_h263_encode_mba(MpegEncContext *s);

void ff_init_qscale_tab(MpegEncContext *s);
void ff_clean_h263_qscales(MpegEncContext *s);

void ff_h263_encode_motion(PutBitContext *pb, int val, int f_code);


static inline int h263_get_motion_length(int val, int f_code)
{
    int bit_size, code, sign;

    if (val == 0) {
        return 1; /* ff_mvtab[0][1] */
    } else {
        bit_size = f_code - 1;
        /* modulo encoding */
        val  = sign_extend(val, 6 + bit_size);
        sign = val >> 31;
        val  = (val ^ sign) - sign; /* val = FFABS(val) */
        val--;
        code = (val >> bit_size) + 1;

        return ff_mvtab[code][1] + 1 + bit_size;
    }
}

static inline void ff_h263_encode_motion_vector(MpegEncContext * s,
                                                int x, int y, int f_code)
{
    if (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT) {
        skip_put_bits(&s->pb,
                      h263_get_motion_length(x, f_code) +
                      h263_get_motion_length(y, f_code));
    } else {
        ff_h263_encode_motion(&s->pb, x, f_code);
        ff_h263_encode_motion(&s->pb, y, f_code);
    }
}

static inline int get_p_cbp(MpegEncContext * s,
                      int16_t block[6][64],
                      int motion_x, int motion_y){
    int cbp;

    if (s->mpv_flags & FF_MPV_FLAG_CBP_RD) {
        int best_cbpy_score = INT_MAX;
        int best_cbpc_score = INT_MAX;
        int cbpc = (-1), cbpy = (-1);
        const int offset = (s->mv_type == MV_TYPE_16X16 ? 0 : 16) + (s->dquant ? 8 : 0);
        const int lambda = s->lambda2 >> (FF_LAMBDA_SHIFT - 6);

        for (int i = 0; i < 4; i++) {
            int score = ff_h263_inter_MCBPC_bits[i + offset] * lambda;
            if (i & 1) score += s->coded_score[5];
            if (i & 2) score += s->coded_score[4];

            if (score < best_cbpc_score) {
                best_cbpc_score = score;
                cbpc = i;
            }
        }

        for (int i = 0; i < 16; i++) {
            int score= ff_h263_cbpy_tab[i ^ 0xF][1] * lambda;
            if (i & 1) score += s->coded_score[3];
            if (i & 2) score += s->coded_score[2];
            if (i & 4) score += s->coded_score[1];
            if (i & 8) score += s->coded_score[0];

            if (score < best_cbpy_score) {
                best_cbpy_score = score;
                cbpy = i;
            }
        }
        cbp = cbpc + 4 * cbpy;
        if (!(motion_x | motion_y | s->dquant) && s->mv_type == MV_TYPE_16X16) {
            if (best_cbpy_score + best_cbpc_score + 2 * lambda >= 0)
                cbp= 0;
        }

        for (int i = 0; i < 6; i++) {
            if (s->block_last_index[i] >= 0 && !((cbp >> (5 - i)) & 1)) {
                s->block_last_index[i] = -1;
                s->bdsp.clear_block(s->block[i]);
            }
        }
    } else {
        cbp = 0;
        for (int i = 0; i < 6; i++) {
            if (s->block_last_index[i] >= 0)
                cbp |= 1 << (5 - i);
        }
    }
    return cbp;
}

#endif
