/*
- * Interface to xvidcore for mpeg4 encoding
+ * Interface to xvidcore for MPEG-4 encoding
* Copyright (c) 2004 Adam Thayer <krevnik@comcast.net>
*
* This file is part of Libav.
* @author Adam Thayer (krevnik@comcast.net)
*/
+#include <stdio.h>
+#include <string.h>
#include <unistd.h>
#include <xvid.h>
#include "libavutil/cpu.h"
+#include "libavutil/internal.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mathematics.h"
+#include "libavutil/mem.h"
+#include "libavutil/opt.h"
#include "avcodec.h"
#include "internal.h"
#include "libxvid.h"
-#include "mpegvideo.h"
+#include "mpegutils.h"
/**
* Buffer management macros.
int ssim_acc; /**< SSIM accuracy. 0: accurate. 4: fast. */
int gmc;
int me_quality; /**< Motion estimation quality. 0: fast 6: best. */
+ int mpeg_quant; /**< Quantization type. 0: H.263, 1: MPEG */
};
/**
struct xvid_context *context; /**< Pointer to private context */
};
+static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
+ const AVFrame *picture, int *got_packet);
+
+
/*
* Xvid 2-Pass Kludge Section
*
* Destroy the two-pass plugin context.
*
* @param ref Context pointer for the plugin
- * @param param Destrooy context
+ * @param param Destroy context
* @return Returns 0, success guaranteed
*/
static int xvid_ff_2pass_destroy(struct xvid_context *ref,
/* Bring in VOP flags from avconv command-line */
x->vop_flags = XVID_VOP_HALFPEL; /* Bare minimum quality */
- if (xvid_flags & CODEC_FLAG_4MV)
+ if (xvid_flags & AV_CODEC_FLAG_4MV)
x->vop_flags |= XVID_VOP_INTER4V; /* Level 3 */
if (avctx->trellis)
x->vop_flags |= XVID_VOP_TRELLISQUANT; /* Level 5 */
- if (xvid_flags & CODEC_FLAG_AC_PRED)
+ if (xvid_flags & AV_CODEC_FLAG_AC_PRED)
x->vop_flags |= XVID_VOP_HQACPRED; /* Level 6 */
- if (xvid_flags & CODEC_FLAG_GRAY)
+ if (xvid_flags & AV_CODEC_FLAG_GRAY)
x->vop_flags |= XVID_VOP_GREYSCALE;
/* Decide which ME quality setting to use */
x->vol_flags |= XVID_VOL_GMC;
x->me_flags |= XVID_ME_GME_REFINE;
}
- if (xvid_flags & CODEC_FLAG_QPEL) {
+ if (xvid_flags & AV_CODEC_FLAG_QPEL) {
x->vol_flags |= XVID_VOL_QUARTERPEL;
x->me_flags |= XVID_ME_QUARTERPELREFINE16;
if (x->vop_flags & XVID_VOP_INTER4V)
x->old_twopassbuffer = NULL;
x->twopassfile = NULL;
- if (xvid_flags & CODEC_FLAG_PASS1) {
+ if (xvid_flags & AV_CODEC_FLAG_PASS1) {
rc2pass1.version = XVID_VERSION;
rc2pass1.context = x;
x->twopassbuffer = av_malloc(BUFFER_SIZE);
plugins[xvid_enc_create.num_plugins].func = xvid_ff_2pass;
plugins[xvid_enc_create.num_plugins].param = &rc2pass1;
xvid_enc_create.num_plugins++;
- } else if (xvid_flags & CODEC_FLAG_PASS2) {
+ } else if (xvid_flags & AV_CODEC_FLAG_PASS2) {
rc2pass2.version = XVID_VERSION;
rc2pass2.bitrate = avctx->bit_rate;
plugins[xvid_enc_create.num_plugins].func = xvid_plugin_2pass2;
plugins[xvid_enc_create.num_plugins].param = &rc2pass2;
xvid_enc_create.num_plugins++;
- } else if (!(xvid_flags & CODEC_FLAG_QSCALE)) {
+ } else if (!(xvid_flags & AV_CODEC_FLAG_QSCALE)) {
/* Single Pass Bitrate Control! */
single.version = XVID_VERSION;
single.bitrate = avctx->bit_rate;
xvid_enc_create.max_key_interval = 240; /* Xvid's best default */
/* Quants */
- if (xvid_flags & CODEC_FLAG_QSCALE)
+ if (xvid_flags & AV_CODEC_FLAG_QSCALE)
x->qscale = 1;
else
x->qscale = 0;
/* Quant Matrices */
x->intra_matrix =
x->inter_matrix = NULL;
+
+#if FF_API_PRIVATE_OPT
+FF_DISABLE_DEPRECATION_WARNINGS
if (avctx->mpeg_quant)
+ x->mpeg_quant = avctx->mpeg_quant;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+ if (x->mpeg_quant)
x->vol_flags |= XVID_VOL_MPEGQUANT;
if ((avctx->intra_matrix || avctx->inter_matrix)) {
x->vol_flags |= XVID_VOL_MPEGQUANT;
/* Misc Settings */
xvid_enc_create.frame_drop_ratio = 0;
xvid_enc_create.global = 0;
- if (xvid_flags & CODEC_FLAG_CLOSED_GOP)
+ if (xvid_flags & AV_CODEC_FLAG_CLOSED_GOP)
xvid_enc_create.global |= XVID_GLOBAL_CLOSED_GOP;
/* Determines which codec mode we are operating in */
avctx->extradata = NULL;
avctx->extradata_size = 0;
- if (xvid_flags & CODEC_FLAG_GLOBAL_HEADER) {
- /* In this case, we are claiming to be MPEG4 */
+ if (xvid_flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
+ /* In this case, we are claiming to be MPEG-4 */
x->quicktime_format = 1;
avctx->codec_id = AV_CODEC_ID_MPEG4;
} else {
if (avctx->max_b_frames > 0 && !x->quicktime_format)
xvid_enc_create.global |= XVID_GLOBAL_PACKED;
+ /* Encode a dummy frame to get the extradata immediately */
+ if (x->quicktime_format) {
+ AVFrame *picture;
+ AVPacket packet;
+ int got_packet, ret;
+
+ av_init_packet(&packet);
+
+ picture = av_frame_alloc();
+ if (!picture)
+ return AVERROR(ENOMEM);
+
+ xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL);
+ if (xerr) {
+ av_frame_free(&picture);
+ av_log(avctx, AV_LOG_ERROR, "Xvid: Could not create encoder reference\n");
+ return AVERROR_UNKNOWN;
+ }
+ x->encoder_handle = xvid_enc_create.handle;
+
+ picture->width = avctx->width;
+ picture->height = avctx->height;
+ picture->format = avctx->pix_fmt;
+
+ if ((ret = av_frame_get_buffer(picture, 32)) < 0) {
+ xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL);
+ av_frame_free(&picture);
+ return ret;
+ }
+
+ ret = xvid_encode_frame(avctx, &packet, picture, &got_packet);
+ if (!ret && got_packet)
+ av_packet_unref(&packet);
+ av_frame_free(&picture);
+ xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL);
+ }
+
/* Create encoder context */
xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL);
if (xerr) {
xvid_enc_stats_t xvid_enc_stats = { 0 };
if (!user_packet &&
- (ret = av_new_packet(pkt, mb_width * mb_height * MAX_MB_BYTES + FF_MIN_BUFFER_SIZE)) < 0) {
+ (ret = av_new_packet(pkt, mb_width * mb_height * MAX_MB_BYTES + AV_INPUT_BUFFER_MIN_SIZE)) < 0) {
av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
return ret;
}
return 0;
} else {
if (!user_packet)
- av_free_packet(pkt);
+ av_packet_unref(pkt);
if (!xerr)
return 0;
av_log(avctx, AV_LOG_ERROR,
{ "ssim_acc", "SSIM accuracy", OFFSET(ssim_acc), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 4, VE },
{ "gmc", "use GMC", OFFSET(gmc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
{ "me_quality", "Motion estimation quality", OFFSET(me_quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 6, VE },
+ { "mpeg_quant", "Use MPEG quantizers instead of H.263", OFFSET(mpeg_quant), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
{ NULL },
};