static int ffv1_encode_frame(AVCodecContext *avctx, AVPacket *pkt,

                        const AVFrame *pict, int *got_packet)

{

    FFV1Context *f      = avctx->priv_data;

    RangeCoder *const c = &f->slice_context[0]->c;

    int used_count      = 0;

    uint8_t keystate    = 128;

    uint8_t *buf_p;

    int i, ret;



    f->frame = pict;



    if ((ret = ff_alloc_packet(pkt, avctx->width * avctx->height *

                             ((8 * 2 + 1 + 1) * 4) / 8 +

                             AV_INPUT_BUFFER_MIN_SIZE)) < 0) {

        av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");

        return ret;

    }



    ff_init_range_encoder(c, pkt->data, pkt->size);

    ff_build_rac_states(c, 0.05 * (1LL << 32), 256 - 8);



    if (avctx->gop_size == 0 || f->picture_number % avctx->gop_size == 0) {

        put_rac(c, &keystate, 1);

        f->key_frame = 1;

        f->gob_count++;

        write_header(f);

    } else {

        put_rac(c, &keystate, 0);

        f->key_frame = 0;

    }



    if (f->ac > 1) {

        int i;

        for (i = 1; i < 256; i++) {

            c->one_state[i]        = f->state_transition[i];

            c->zero_state[256 - i] = 256 - c->one_state[i];

        }

    }



    for (i = 1; i < f->slice_count; i++) {

        FFV1Context *fs = f->slice_context[i];

        uint8_t *start  = pkt->data +

                          (pkt->size - used_count) * (int64_t)i / f->slice_count;

        int len = pkt->size / f->slice_count;

        ff_init_range_encoder(&fs->c, start, len);

    }

    avctx->execute(avctx, encode_slice, &f->slice_context[0], NULL,

                   f->slice_count, sizeof(void *));



    buf_p = pkt->data;

    for (i = 0; i < f->slice_count; i++) {

        FFV1Context *fs = f->slice_context[i];

        int bytes;



        if (fs->ac) {

            uint8_t state = 129;

            put_rac(&fs->c, &state, 0);

            bytes = ff_rac_terminate(&fs->c);

        } else {

            flush_put_bits(&fs->pb); // FIXME: nicer padding

            bytes = fs->ac_byte_count + (put_bits_count(&fs->pb) + 7) / 8;

        }

        if (i > 0 || f->version > 2) {

            av_assert0(bytes < pkt->size / f->slice_count);

            memmove(buf_p, fs->c.bytestream_start, bytes);

            av_assert0(bytes < (1 << 24));

            AV_WB24(buf_p + bytes, bytes);

            bytes += 3;

        }

        if (f->ec) {

            unsigned v;

            buf_p[bytes++] = 0;

            v = av_crc(av_crc_get_table(AV_CRC_32_IEEE), 0, buf_p, bytes);

            AV_WL32(buf_p + bytes, v);

            bytes += 4;

        }

        buf_p += bytes;

    }



    if ((avctx->flags & AV_CODEC_FLAG_PASS1) && (f->picture_number & 31) == 0) {

        int j, k, m;

        char *p   = avctx->stats_out;

        char *end = p + STATS_OUT_SIZE;



        memset(f->rc_stat, 0, sizeof(f->rc_stat));

        for (i = 0; i < f->quant_table_count; i++)

            memset(f->rc_stat2[i], 0, f->context_count[i] * sizeof(*f->rc_stat2[i]));



        for (j = 0; j < f->slice_count; j++) {

            FFV1Context *fs = f->slice_context[j];

            for (i = 0; i < 256; i++) {

                f->rc_stat[i][0] += fs->rc_stat[i][0];

                f->rc_stat[i][1] += fs->rc_stat[i][1];

            }

            for (i = 0; i < f->quant_table_count; i++) {

                for (k = 0; k < f->context_count[i]; k++)

                    for (m = 0; m < 32; m++) {

                        f->rc_stat2[i][k][m][0] += fs->rc_stat2[i][k][m][0];

                        f->rc_stat2[i][k][m][1] += fs->rc_stat2[i][k][m][1];

                    }

            }

        }



        for (j = 0; j < 256; j++) {

            snprintf(p, end - p, "%" PRIu64 " %" PRIu64 " ",

                     f->rc_stat[j][0], f->rc_stat[j][1]);

            p += strlen(p);

        }

        snprintf(p, end - p, "\n");



        for (i = 0; i < f->quant_table_count; i++) {

            for (j = 0; j < f->context_count[i]; j++)

                for (m = 0; m < 32; m++) {

                    snprintf(p, end - p, "%" PRIu64 " %" PRIu64 " ",

                             f->rc_stat2[i][j][m][0], f->rc_stat2[i][j][m][1]);

                    p += strlen(p);

                }

        }

        snprintf(p, end - p, "%d\n", f->gob_count);

    } else if (avctx->flags & AV_CODEC_FLAG_PASS1)

        avctx->stats_out[0] = '\0';



#if FF_API_CODED_FRAME

FF_DISABLE_DEPRECATION_WARNINGS

    avctx->coded_frame->key_frame = f->key_frame;

FF_ENABLE_DEPRECATION_WARNINGS

#endif



    f->picture_number++;

    pkt->size   = buf_p - pkt->data;

    pkt->flags |= AV_PKT_FLAG_KEY * f->key_frame;

    *got_packet = 1;



    return 0;

}
