static int estimate_best_b_count(MpegEncContext *s)

{

    AVCodec *codec    = avcodec_find_encoder(s->avctx->codec_id);

    AVCodecContext *c = avcodec_alloc_context3(NULL);

    const int scale = s->avctx->brd_scale;

    int i, j, out_size, p_lambda, b_lambda, lambda2;

    int64_t best_rd  = INT64_MAX;

    int best_b_count = -1;



    assert(scale >= 0 && scale <= 3);



    //emms_c();

    //s->next_picture_ptr->quality;

    p_lambda = s->last_lambda_for[AV_PICTURE_TYPE_P];

    //p_lambda * FFABS(s->avctx->b_quant_factor) + s->avctx->b_quant_offset;

    b_lambda = s->last_lambda_for[AV_PICTURE_TYPE_B];

    if (!b_lambda) // FIXME we should do this somewhere else

        b_lambda = p_lambda;

    lambda2  = (b_lambda * b_lambda + (1 << FF_LAMBDA_SHIFT) / 2) >>

               FF_LAMBDA_SHIFT;



    c->width        = s->width  >> scale;

    c->height       = s->height >> scale;

    c->flags        = CODEC_FLAG_QSCALE | CODEC_FLAG_PSNR |

                      CODEC_FLAG_INPUT_PRESERVED;

    c->flags       |= s->avctx->flags & CODEC_FLAG_QPEL;

    c->mb_decision  = s->avctx->mb_decision;

    c->me_cmp       = s->avctx->me_cmp;

    c->mb_cmp       = s->avctx->mb_cmp;

    c->me_sub_cmp   = s->avctx->me_sub_cmp;

    c->pix_fmt      = AV_PIX_FMT_YUV420P;

    c->time_base    = s->avctx->time_base;

    c->max_b_frames = s->max_b_frames;



    if (avcodec_open2(c, codec, NULL) < 0)

        return -1;



    for (i = 0; i < s->max_b_frames + 2; i++) {

        Picture pre_input, *pre_input_ptr = i ? s->input_picture[i - 1] :

                                                s->next_picture_ptr;



        if (pre_input_ptr && (!i || s->input_picture[i - 1])) {

            pre_input = *pre_input_ptr;



            if (!pre_input.shared && i) {

                pre_input.f.data[0] += INPLACE_OFFSET;

                pre_input.f.data[1] += INPLACE_OFFSET;

                pre_input.f.data[2] += INPLACE_OFFSET;

            }



            s->dsp.shrink[scale](s->tmp_frames[i]->data[0], s->tmp_frames[i]->linesize[0],

                                 pre_input.f.data[0], pre_input.f.linesize[0],

                                 c->width,      c->height);

            s->dsp.shrink[scale](s->tmp_frames[i]->data[1], s->tmp_frames[i]->linesize[1],

                                 pre_input.f.data[1], pre_input.f.linesize[1],

                                 c->width >> 1, c->height >> 1);

            s->dsp.shrink[scale](s->tmp_frames[i]->data[2], s->tmp_frames[i]->linesize[2],

                                 pre_input.f.data[2], pre_input.f.linesize[2],

                                 c->width >> 1, c->height >> 1);

        }

    }



    for (j = 0; j < s->max_b_frames + 1; j++) {

        int64_t rd = 0;



        if (!s->input_picture[j])

            break;



        c->error[0] = c->error[1] = c->error[2] = 0;



        s->tmp_frames[0]->pict_type = AV_PICTURE_TYPE_I;

        s->tmp_frames[0]->quality   = 1 * FF_QP2LAMBDA;



        out_size = encode_frame(c, s->tmp_frames[0]);



        //rd += (out_size * lambda2) >> FF_LAMBDA_SHIFT;



        for (i = 0; i < s->max_b_frames + 1; i++) {

            int is_p = i % (j + 1) == j || i == s->max_b_frames;



            s->tmp_frames[i + 1]->pict_type = is_p ?

                                     AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_B;

            s->tmp_frames[i + 1]->quality   = is_p ? p_lambda : b_lambda;



            out_size = encode_frame(c, s->tmp_frames[i + 1]);



            rd += (out_size * lambda2) >> (FF_LAMBDA_SHIFT - 3);

        }



        /* get the delayed frames */

        while (out_size) {

            out_size = encode_frame(c, NULL);

            rd += (out_size * lambda2) >> (FF_LAMBDA_SHIFT - 3);

        }



        rd += c->error[0] + c->error[1] + c->error[2];



        if (rd < best_rd) {

            best_rd = rd;

            best_b_count = j;

        }

    }



    avcodec_close(c);

    av_freep(&c);



    return best_b_count;

}
