X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Flibxvidff.c;h=9008b848ca5a7010bade07a14b0d05984c086dca;hb=b0294c80d3a3981ec7ef9e4654962780e8566075;hp=ac1553f2a8b24fb23d0598fa919f54b7832618d8;hpb=b250f9c66d3ddd84652d158fb979a5f21e3f2c71;p=ffmpeg diff --git a/libavcodec/libxvidff.c b/libavcodec/libxvidff.c index ac1553f2a8b..9008b848ca5 100644 --- a/libavcodec/libxvidff.c +++ b/libavcodec/libxvidff.c @@ -20,15 +20,23 @@ */ /** - * @file xvidmpeg4.c + * @file * Interface to xvidcore for MPEG-4 compliant encoding. * @author Adam Thayer (krevnik@comcast.net) */ +/* needed for mkstemp() */ +#define _XOPEN_SOURCE 600 + #include #include #include "avcodec.h" +#include "libavutil/cpu.h" +#include "libavutil/intreadwrite.h" #include "libxvid_internal.h" +#if !HAVE_MKSTEMP +#include +#endif /** * Buffer management macros. @@ -37,35 +45,33 @@ #define BUFFER_REMAINING(x) (BUFFER_SIZE - strlen(x)) #define BUFFER_CAT(x) (&((x)[strlen(x)])) -/* For PPC Use */ -int has_altivec(void); - /** * Structure for the private Xvid context. * This stores all the private context for the codec. */ struct xvid_context { - void *encoder_handle; /** Handle for Xvid encoder */ - int xsize, ysize; /** Frame size */ - int vop_flags; /** VOP flags for Xvid encoder */ - int vol_flags; /** VOL flags for Xvid encoder */ - int me_flags; /** Motion Estimation flags */ - int qscale; /** Do we use constant scale? */ - int quicktime_format; /** Are we in a QT-based format? */ - AVFrame encoded_picture; /** Encoded frame information */ - char *twopassbuffer; /** Character buffer for two-pass */ - char *old_twopassbuffer; /** Old character buffer (two-pass) */ - char *twopassfile; /** second pass temp file name */ - unsigned char *intra_matrix; /** P-Frame Quant Matrix */ - unsigned char *inter_matrix; /** I-Frame Quant Matrix */ + void *encoder_handle; /**< Handle for Xvid encoder */ + int xsize; /**< Frame x size */ + int ysize; /**< Frame y size */ + int vop_flags; /**< VOP flags for Xvid encoder */ + int vol_flags; /**< VOL flags for Xvid encoder */ + int me_flags; /**< Motion Estimation flags */ + int qscale; /**< Do we use constant scale? */ + int quicktime_format; /**< Are we in a QT-based format? */ + AVFrame encoded_picture; /**< Encoded frame information */ + char *twopassbuffer; /**< Character buffer for two-pass */ + char *old_twopassbuffer; /**< Old character buffer (two-pass) */ + char *twopassfile; /**< second pass temp file name */ + unsigned char *intra_matrix; /**< P-Frame Quant Matrix */ + unsigned char *inter_matrix; /**< I-Frame Quant Matrix */ }; /** * Structure for the private first-pass plugin. */ struct xvid_ff_pass1 { - int version; /** Xvid version */ - struct xvid_context *context; /** Pointer to private context */ + int version; /**< Xvid version */ + struct xvid_context *context; /**< Pointer to private context */ }; /* Prototypes - See function implementation for details */ @@ -73,15 +79,53 @@ int xvid_strip_vol_header(AVCodecContext *avctx, unsigned char *frame, unsigned int xvid_ff_2pass(void *ref, int opt, void *p1, void *p2); void xvid_correct_framerate(AVCodecContext *avctx); +/* Wrapper to work around the lack of mkstemp() on mingw. + * Also, tries to create file in /tmp first, if possible. + * *prefix can be a character constant; *filename will be allocated internally. + * @return file descriptor of opened file (or -1 on error) + * and opened file name in **filename. */ +int ff_tempfile(const char *prefix, char **filename) { + int fd=-1; +#if !HAVE_MKSTEMP + *filename = tempnam(".", prefix); +#else + size_t len = strlen(prefix) + 12; /* room for "/tmp/" and "XXXXXX\0" */ + *filename = av_malloc(len); +#endif + /* -----common section-----*/ + if (*filename == NULL) { + av_log(NULL, AV_LOG_ERROR, "ff_tempfile: Cannot allocate file name\n"); + return -1; + } +#if !HAVE_MKSTEMP + fd = open(*filename, O_RDWR | O_BINARY | O_CREAT, 0444); +#else + snprintf(*filename, len, "/tmp/%sXXXXXX", prefix); + fd = mkstemp(*filename); + if (fd < 0) { + snprintf(*filename, len, "./%sXXXXXX", prefix); + fd = mkstemp(*filename); + } +#endif + /* -----common section-----*/ + if (fd < 0) { + av_log(NULL, AV_LOG_ERROR, "ff_tempfile: Cannot open temporary file %s\n", *filename); + return -1; + } + return fd; /* success */ +} + +#if CONFIG_LIBXVID_ENCODER + /** - * Creates the private context for the encoder. + * Create the private context for the encoder. * All buffers are allocated, settings are loaded from the user, * and the encoder context created. * * @param avctx AVCodecContext pointer to context * @return Returns 0 on success, -1 on failure */ -av_cold int ff_xvid_encode_init(AVCodecContext *avctx) { +static av_cold int xvid_encode_init(AVCodecContext *avctx) { int xerr, i; int xvid_flags = avctx->flags; struct xvid_context *x = avctx->priv_data; @@ -169,7 +213,7 @@ av_cold int ff_xvid_encode_init(AVCodecContext *avctx) { #if ARCH_PPC /* Xvid's PPC support is borked, use libavcodec to detect */ #if HAVE_ALTIVEC - if( has_altivec() ) { + if (av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) { xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_ALTIVEC; } else #endif @@ -228,7 +272,7 @@ av_cold int ff_xvid_encode_init(AVCodecContext *avctx) { rc2pass2.version = XVID_VERSION; rc2pass2.bitrate = avctx->bit_rate; - fd = av_tempfile("xvidff.", &(x->twopassfile)); + fd = ff_tempfile("xvidff.", &(x->twopassfile)); if( fd == -1 ) { av_log(avctx, AV_LOG_ERROR, "Xvid: Cannot write 2-pass pipe\n"); @@ -335,7 +379,7 @@ av_cold int ff_xvid_encode_init(AVCodecContext *avctx) { /* We are claiming to be Xvid */ x->quicktime_format = 0; if(!avctx->codec_tag) - avctx->codec_tag = ff_get_fourcc("xvid"); + avctx->codec_tag = AV_RL32("xvid"); } /* Bframes */ @@ -358,7 +402,7 @@ av_cold int ff_xvid_encode_init(AVCodecContext *avctx) { } /** - * Encodes a single frame. + * Encode a single frame. * * @param avctx AVCodecContext pointer to context * @param frame Pointer to encoded frame buffer @@ -366,7 +410,7 @@ av_cold int ff_xvid_encode_init(AVCodecContext *avctx) { * @param data Pointer to AVFrame of unencoded frame * @return Returns 0 on success, -1 on failure */ -int ff_xvid_encode_frame(AVCodecContext *avctx, +static int xvid_encode_frame(AVCodecContext *avctx, unsigned char *frame, int buf_size, void *data) { int xerr, i; char *tmp; @@ -405,7 +449,11 @@ int ff_xvid_encode_frame(AVCodecContext *avctx, 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 = XVID_TYPE_AUTO; + xvid_enc_frame.type = + picture->pict_type == FF_I_TYPE ? XVID_TYPE_IVOP : + picture->pict_type == FF_P_TYPE ? XVID_TYPE_PVOP : + picture->pict_type == FF_B_TYPE ? XVID_TYPE_BVOP : + XVID_TYPE_AUTO; /* Pixel aspect ratio setting */ if (avctx->sample_aspect_ratio.num < 1 || avctx->sample_aspect_ratio.num > 255 || @@ -468,29 +516,25 @@ int ff_xvid_encode_frame(AVCodecContext *avctx, } /** - * Destroys the private context for the encoder. + * Destroy the private context for the encoder. * All buffers are freed, and the Xvid encoder context is destroyed. * * @param avctx AVCodecContext pointer to context * @return Returns 0, success guaranteed */ -av_cold int ff_xvid_encode_close(AVCodecContext *avctx) { +static av_cold int xvid_encode_close(AVCodecContext *avctx) { struct xvid_context *x = avctx->priv_data; xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL); - if( avctx->extradata != NULL ) - av_free(avctx->extradata); + av_freep(&avctx->extradata); if( x->twopassbuffer != NULL ) { av_free(x->twopassbuffer); av_free(x->old_twopassbuffer); } - if( x->twopassfile != NULL ) - av_free(x->twopassfile); - if( x->intra_matrix != NULL ) - av_free(x->intra_matrix); - if( x->inter_matrix != NULL ) - av_free(x->inter_matrix); + av_free(x->twopassfile); + av_free(x->intra_matrix); + av_free(x->inter_matrix); return 0; } @@ -557,7 +601,7 @@ void xvid_correct_framerate(AVCodecContext *avctx) { frate = avctx->time_base.den; fbase = avctx->time_base.num; - gcd = ff_gcd(frate, fbase); + gcd = av_gcd(frate, fbase); if( gcd > 1 ) { frate /= gcd; fbase /= gcd; @@ -579,7 +623,7 @@ void xvid_correct_framerate(AVCodecContext *avctx) { } else est_fbase = 1; - gcd = ff_gcd(est_frate, est_fbase); + gcd = av_gcd(est_frate, est_fbase); if( gcd > 1 ) { est_frate /= gcd; est_fbase /= gcd; @@ -608,7 +652,7 @@ void xvid_correct_framerate(AVCodecContext *avctx) { */ /** - * Initializes the two-pass plugin and context. + * Initialize the two-pass plugin and context. * * @param param Input construction parameter structure * @param handle Private context handle @@ -639,7 +683,7 @@ static int xvid_ff_2pass_create(xvid_plg_create_t * param, } /** - * Destroys the two-pass plugin context. + * Destroy the two-pass plugin context. * * @param ref Context pointer for the plugin * @param param Destrooy context @@ -655,7 +699,7 @@ static int xvid_ff_2pass_destroy(struct xvid_context *ref, } /** - * Enables fast encode mode during the first pass. + * Enable fast encode mode during the first pass. * * @param ref Context pointer for the plugin * @param param Frame data @@ -698,7 +742,7 @@ static int xvid_ff_2pass_before(struct xvid_context *ref, } /** - * Captures statistic data and writes it during first pass. + * Capture statistic data and write it during first pass. * * @param ref Context pointer for the plugin * @param param Statistic data @@ -766,14 +810,16 @@ int xvid_ff_2pass(void *ref, int cmd, void *p1, void *p2) { /** * Xvid codec definition for libavcodec. */ -AVCodec libxvid_encoder = { +AVCodec ff_libxvid_encoder = { "libxvid", - CODEC_TYPE_VIDEO, - CODEC_ID_XVID, + AVMEDIA_TYPE_VIDEO, + CODEC_ID_MPEG4, sizeof(struct xvid_context), - ff_xvid_encode_init, - ff_xvid_encode_frame, - ff_xvid_encode_close, - .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, + xvid_encode_init, + xvid_encode_frame, + xvid_encode_close, + .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, .long_name= NULL_IF_CONFIG_SMALL("libxvidcore MPEG-4 part 2"), }; + +#endif /* CONFIG_LIBXVID_ENCODER */