diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 6ab9ba57f5..6a7c9e500f 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1245,30 +1245,38 @@ static int skip_check(MpegEncContext *s, Picture *p, Picture *ref) static int encode_frame(AVCodecContext *c, AVFrame *frame) { AVPacket pkt = { 0 }; - int ret, got_output; + int ret; + int size = 0; av_init_packet(&pkt); - ret = avcodec_encode_video2(c, &pkt, frame, &got_output); + + ret = avcodec_send_frame(c, frame); if (ret < 0) return ret; - ret = pkt.size; - av_packet_unref(&pkt); - return ret; + do { + ret = avcodec_receive_packet(c, &pkt); + if (ret >= 0) { + size += pkt.size; + av_packet_unref(&pkt); + } else if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + return ret; + } while (ret >= 0); + + return size; } static int estimate_best_b_count(MpegEncContext *s) { const AVCodec *codec = avcodec_find_encoder(s->avctx->codec_id); - AVCodecContext *c = avcodec_alloc_context3(NULL); const int scale = s->brd_scale; + int width = s->width >> scale; + int height = s->height >> scale; int i, j, out_size, p_lambda, b_lambda, lambda2; int64_t best_rd = INT64_MAX; int best_b_count = -1; int ret = 0; - if (!c) - return AVERROR(ENOMEM); assert(scale >= 0 && scale <= 3); //emms_c(); @@ -1281,21 +1289,6 @@ static int estimate_best_b_count(MpegEncContext *s) 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 = AV_CODEC_FLAG_QSCALE | AV_CODEC_FLAG_PSNR; - c->flags |= s->avctx->flags & AV_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; @@ -1313,27 +1306,46 @@ static int estimate_best_b_count(MpegEncContext *s) s->tmp_frames[i]->linesize[0], pre_input.f->data[0], pre_input.f->linesize[0], - c->width, c->height); + width, height); s->mpvencdsp.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); + width >> 1, height >> 1); s->mpvencdsp.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); + width >> 1, height >> 1); } } for (j = 0; j < s->max_b_frames + 1; j++) { + AVCodecContext *c; int64_t rd = 0; if (!s->input_picture[j]) break; - c->error[0] = c->error[1] = c->error[2] = 0; + c = avcodec_alloc_context3(NULL); + if (!c) + return AVERROR(ENOMEM); + + c->width = width; + c->height = height; + c->flags = AV_CODEC_FLAG_QSCALE | AV_CODEC_FLAG_PSNR; + c->flags |= s->avctx->flags & AV_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; + + ret = avcodec_open2(c, codec, NULL); + if (ret < 0) + goto fail; s->tmp_frames[0]->pict_type = AV_PICTURE_TYPE_I; s->tmp_frames[0]->quality = 1 * FF_QP2LAMBDA; @@ -1363,14 +1375,12 @@ static int estimate_best_b_count(MpegEncContext *s) } /* get the delayed frames */ - while (out_size) { - out_size = encode_frame(c, NULL); - if (out_size < 0) { - ret = out_size; - goto fail; - } - rd += (out_size * lambda2) >> (FF_LAMBDA_SHIFT - 3); + out_size = encode_frame(c, NULL); + if (out_size < 0) { + ret = out_size; + goto fail; } + rd += (out_size * lambda2) >> (FF_LAMBDA_SHIFT - 3); rd += c->error[0] + c->error[1] + c->error[2]; @@ -1378,14 +1388,14 @@ static int estimate_best_b_count(MpegEncContext *s) best_rd = rd; best_b_count = j; } - } - avcodec_free_context(&c); +fail: + avcodec_free_context(&c); + if (ret < 0) + return ret; + } return best_b_count; -fail: - avcodec_free_context(&c); - return ret; } static int select_input_picture(MpegEncContext *s)