static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *picture, int *got_packet) { int xerr, i, ret, user_packet = !!pkt->data; struct xvid_context *x = avctx->priv_data; AVFrame *p = avctx->coded_frame; int mb_width = (avctx->width + 15) / 16; int mb_height = (avctx->height + 15) / 16; char *tmp; xvid_enc_frame_t xvid_enc_frame = { 0 }; xvid_enc_stats_t xvid_enc_stats = { 0 }; if ((ret = ff_alloc_packet2(avctx, pkt, mb_width*mb_height*MAX_MB_BYTES + FF_MIN_BUFFER_SIZE)) < 0) return ret; /* Start setting up the frame */ xvid_enc_frame.version = XVID_VERSION; xvid_enc_stats.version = XVID_VERSION; /* Let Xvid know where to put the frame. */ xvid_enc_frame.bitstream = pkt->data; xvid_enc_frame.length = pkt->size; /* Initialize input image fields */ if (avctx->pix_fmt != AV_PIX_FMT_YUV420P) { av_log(avctx, AV_LOG_ERROR, "Xvid: Color spaces other than 420P not supported\n"); return AVERROR(EINVAL); } xvid_enc_frame.input.csp = XVID_CSP_PLANAR; /* YUV420P */ for (i = 0; i < 4; i++) { xvid_enc_frame.input.plane[i] = picture->data[i]; xvid_enc_frame.input.stride[i] = picture->linesize[i]; } /* Encoder Flags */ xvid_enc_frame.vop_flags = x->vop_flags; xvid_enc_frame.vol_flags = x->vol_flags; xvid_enc_frame.motion = x->me_flags; xvid_enc_frame.type = picture->pict_type == AV_PICTURE_TYPE_I ? XVID_TYPE_IVOP : picture->pict_type == AV_PICTURE_TYPE_P ? XVID_TYPE_PVOP : picture->pict_type == AV_PICTURE_TYPE_B ? XVID_TYPE_BVOP : XVID_TYPE_AUTO; /* Pixel aspect ratio setting */ if (avctx->sample_aspect_ratio.num < 0 || avctx->sample_aspect_ratio.num > 255 || avctx->sample_aspect_ratio.den < 0 || avctx->sample_aspect_ratio.den > 255) { av_log(avctx, AV_LOG_WARNING, "Invalid pixel aspect ratio %i/%i, limit is 255/255 reducing\n", avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den); av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den, avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den, 255); } xvid_enc_frame.par = XVID_PAR_EXT; xvid_enc_frame.par_width = avctx->sample_aspect_ratio.num; xvid_enc_frame.par_height = avctx->sample_aspect_ratio.den; /* Quant Setting */ if (x->qscale) xvid_enc_frame.quant = picture->quality / FF_QP2LAMBDA; else xvid_enc_frame.quant = 0; /* Matrices */ xvid_enc_frame.quant_intra_matrix = x->intra_matrix; xvid_enc_frame.quant_inter_matrix = x->inter_matrix; /* Encode */ xerr = xvid_encore(x->encoder_handle, XVID_ENC_ENCODE, &xvid_enc_frame, &xvid_enc_stats); /* Two-pass log buffer swapping */ avctx->stats_out = NULL; if (x->twopassbuffer) { tmp = x->old_twopassbuffer; x->old_twopassbuffer = x->twopassbuffer; x->twopassbuffer = tmp; x->twopassbuffer[0] = 0; if (x->old_twopassbuffer[0] != 0) { avctx->stats_out = x->old_twopassbuffer; } } if (xerr > 0) { *got_packet = 1; p->quality = xvid_enc_stats.quant * FF_QP2LAMBDA; if (xvid_enc_stats.type == XVID_TYPE_PVOP) p->pict_type = AV_PICTURE_TYPE_P; else if (xvid_enc_stats.type == XVID_TYPE_BVOP) p->pict_type = AV_PICTURE_TYPE_B; else if (xvid_enc_stats.type == XVID_TYPE_SVOP) p->pict_type = AV_PICTURE_TYPE_S; else p->pict_type = AV_PICTURE_TYPE_I; if (xvid_enc_frame.out_flags & XVID_KEYFRAME) { p->key_frame = 1; pkt->flags |= AV_PKT_FLAG_KEY; if (x->quicktime_format) return xvid_strip_vol_header(avctx, pkt, xvid_enc_stats.hlength, xerr); } else p->key_frame = 0; pkt->size = xerr; return 0; } else { if (!user_packet) av_free_packet(pkt); if (!xerr) return 0; av_log(avctx, AV_LOG_ERROR, "Xvid: Encoding Error Occurred: %i\n", xerr); return AVERROR_EXTERNAL; } }