diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-04-14 21:49:01 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-04-14 22:37:43 +0200 |
commit | 7432bcfe5a36331502c49fe03aefe39b9936247a (patch) | |
tree | 398b1874abbd4bcf7c103738ac4548e830af0a43 /libavcodec/libxvidff.c | |
parent | 01bf2ad7351fdaa2e21b6bdf963d22d6ffccb920 (diff) | |
parent | 7bf9e3391fa21d90ff283fc03a12287fe73db9e8 (diff) | |
download | ffmpeg-7432bcfe5a36331502c49fe03aefe39b9936247a.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
vsrc_buffer: fix check from 7ae7c41.
libxvid: Reorder functions to avoid forward declarations; make functions static.
libxvid: drop some pointless dead code
wmal: vertical alignment cosmetics
wmal: Warn about missing bitstream splicing feature and ask for sample.
wmal: Skip seekable_frame_in_packet.
wmal: Drop unused variable num_possible_block_size.
avfiltergraph: make the AVFilterInOut alloc/free API public
graphparser: allow specifying sws flags in the graph description.
graphparser: fix the order of connecting unlabeled links.
graphparser: add avfilter_graph_parse2().
vsrc_buffer: allow using a NULL buffer to signal EOF.
swscale: handle last pixel if lines have an odd width.
qdm2: fix a dubious pointer cast
WMAL: Do not try to read rawpcm coefficients if bits is invalid
mov: Fix detecting there is no sync sample.
tiffdec: K&R cosmetics
avf: has_duration does not check the global one
dsputil: fix optimized emu_edge function on Win64.
Conflicts:
doc/APIchanges
libavcodec/libxvid_rc.c
libavcodec/libxvidff.c
libavcodec/tiff.c
libavcodec/wmalosslessdec.c
libavfilter/avfiltergraph.h
libavfilter/graphparser.c
libavfilter/version.h
libavfilter/vsrc_buffer.c
libswscale/output.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/libxvidff.c')
-rw-r--r-- | libavcodec/libxvidff.c | 541 |
1 files changed, 269 insertions, 272 deletions
diff --git a/libavcodec/libxvidff.c b/libavcodec/libxvidff.c index 811efc3793..0426e9de14 100644 --- a/libavcodec/libxvidff.c +++ b/libavcodec/libxvidff.c @@ -72,11 +72,276 @@ struct xvid_ff_pass1 { struct xvid_context *context; /**< Pointer to private context */ }; -/* Prototypes - See function implementation for details */ -int xvid_strip_vol_header(AVCodecContext *avctx, AVPacket *pkt, unsigned int header_len, unsigned int frame_len); -int xvid_ff_2pass(void *ref, int opt, void *p1, void *p2); -void xvid_correct_framerate(AVCodecContext *avctx); +/* + * Xvid 2-Pass Kludge Section + * + * Xvid's default 2-pass doesn't allow us to create data as we need to, so + * this section spends time replacing the first pass plugin so we can write + * statistic information as libavcodec requests in. We have another kludge + * that allows us to pass data to the second pass in Xvid without a custom + * rate-control plugin. + */ + + +/** + * Initialize the two-pass plugin and context. + * + * @param param Input construction parameter structure + * @param handle Private context handle + * @return Returns XVID_ERR_xxxx on failure, or 0 on success. + */ +static int xvid_ff_2pass_create(xvid_plg_create_t * param, + void ** handle) { + struct xvid_ff_pass1 *x = (struct xvid_ff_pass1 *)param->param; + char *log = x->context->twopassbuffer; + + /* Do a quick bounds check */ + if( log == NULL ) + return XVID_ERR_FAIL; + + /* We use snprintf() */ + /* This is because we can safely prevent a buffer overflow */ + log[0] = 0; + snprintf(log, BUFFER_REMAINING(log), + "# ffmpeg 2-pass log file, using xvid codec\n"); + snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log), + "# Do not modify. libxvidcore version: %d.%d.%d\n\n", + XVID_VERSION_MAJOR(XVID_VERSION), + XVID_VERSION_MINOR(XVID_VERSION), + XVID_VERSION_PATCH(XVID_VERSION)); + + *handle = x->context; + return 0; +} + +/** + * Destroy the two-pass plugin context. + * + * @param ref Context pointer for the plugin + * @param param Destrooy context + * @return Returns 0, success guaranteed + */ +static int xvid_ff_2pass_destroy(struct xvid_context *ref, + xvid_plg_destroy_t *param) { + /* Currently cannot think of anything to do on destruction */ + /* Still, the framework should be here for reference/use */ + if( ref->twopassbuffer != NULL ) + ref->twopassbuffer[0] = 0; + return 0; +} + +/** + * Enable fast encode mode during the first pass. + * + * @param ref Context pointer for the plugin + * @param param Frame data + * @return Returns 0, success guaranteed + */ +static int xvid_ff_2pass_before(struct xvid_context *ref, + xvid_plg_data_t *param) { + int motion_remove; + int motion_replacements; + int vop_remove; + + /* Nothing to do here, result is changed too much */ + if( param->zone && param->zone->mode == XVID_ZONE_QUANT ) + return 0; + + /* We can implement a 'turbo' first pass mode here */ + param->quant = 2; + + /* Init values */ + motion_remove = ~XVID_ME_CHROMA_PVOP & + ~XVID_ME_CHROMA_BVOP & + ~XVID_ME_EXTSEARCH16 & + ~XVID_ME_ADVANCEDDIAMOND16; + motion_replacements = XVID_ME_FAST_MODEINTERPOLATE | + XVID_ME_SKIP_DELTASEARCH | + XVID_ME_FASTREFINE16 | + XVID_ME_BFRAME_EARLYSTOP; + vop_remove = ~XVID_VOP_MODEDECISION_RD & + ~XVID_VOP_FAST_MODEDECISION_RD & + ~XVID_VOP_TRELLISQUANT & + ~XVID_VOP_INTER4V & + ~XVID_VOP_HQACPRED; + + param->vol_flags &= ~XVID_VOL_GMC; + param->vop_flags &= vop_remove; + param->motion_flags &= motion_remove; + param->motion_flags |= motion_replacements; + + return 0; +} + +/** + * Capture statistic data and write it during first pass. + * + * @param ref Context pointer for the plugin + * @param param Statistic data + * @return Returns XVID_ERR_xxxx on failure, or 0 on success + */ +static int xvid_ff_2pass_after(struct xvid_context *ref, + xvid_plg_data_t *param) { + char *log = ref->twopassbuffer; + const char *frame_types = " ipbs"; + char frame_type; + + /* Quick bounds check */ + if( log == NULL ) + return XVID_ERR_FAIL; + + /* Convert the type given to us into a character */ + if( param->type < 5 && param->type > 0 ) { + frame_type = frame_types[param->type]; + } else { + return XVID_ERR_FAIL; + } + + snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log), + "%c %d %d %d %d %d %d\n", + frame_type, param->stats.quant, param->stats.kblks, param->stats.mblks, + param->stats.ublks, param->stats.length, param->stats.hlength); + + return 0; +} + +/** + * Dispatch function for our custom plugin. + * This handles the dispatch for the Xvid plugin. It passes data + * on to other functions for actual processing. + * + * @param ref Context pointer for the plugin + * @param cmd The task given for us to complete + * @param p1 First parameter (varies) + * @param p2 Second parameter (varies) + * @return Returns XVID_ERR_xxxx on failure, or 0 on success + */ +static int xvid_ff_2pass(void *ref, int cmd, void *p1, void *p2) +{ + switch( cmd ) { + case XVID_PLG_INFO: + case XVID_PLG_FRAME: + return 0; + + case XVID_PLG_BEFORE: + return xvid_ff_2pass_before(ref, p1); + + case XVID_PLG_CREATE: + return xvid_ff_2pass_create(p1, p2); + case XVID_PLG_AFTER: + return xvid_ff_2pass_after(ref, p1); + + case XVID_PLG_DESTROY: + return xvid_ff_2pass_destroy(ref, p1); + + default: + return XVID_ERR_FAIL; + } +} + +/** + * Routine to create a global VO/VOL header for MP4 container. + * What we do here is extract the header from the Xvid bitstream + * as it is encoded. We also strip the repeated headers from the + * bitstream when a global header is requested for MPEG-4 ISO + * compliance. + * + * @param avctx AVCodecContext pointer to context + * @param frame Pointer to encoded frame data + * @param header_len Length of header to search + * @param frame_len Length of encoded frame data + * @return Returns new length of frame data + */ +static int xvid_strip_vol_header(AVCodecContext *avctx, + AVPacket *pkt, + unsigned int header_len, + unsigned int frame_len) { + int vo_len = 0, i; + + for( i = 0; i < header_len - 3; i++ ) { + if( pkt->data[i] == 0x00 && + pkt->data[i+1] == 0x00 && + pkt->data[i+2] == 0x01 && + pkt->data[i+3] == 0xB6 ) { + vo_len = i; + break; + } + } + + if( vo_len > 0 ) { + /* We need to store the header, so extract it */ + if( avctx->extradata == NULL ) { + avctx->extradata = av_malloc(vo_len); + memcpy(avctx->extradata, pkt->data, vo_len); + avctx->extradata_size = vo_len; + } + /* Less dangerous now, memmove properly copies the two + chunks of overlapping data */ + memmove(pkt->data, &pkt->data[vo_len], frame_len - vo_len); + pkt->size = frame_len - vo_len; + } + return 0; +} + +/** + * Routine to correct a possibly erroneous framerate being fed to us. + * Xvid currently chokes on framerates where the ticks per frame is + * extremely large. This function works to correct problems in this area + * by estimating a new framerate and taking the simpler fraction of + * the two presented. + * + * @param avctx Context that contains the framerate to correct. + */ +static void xvid_correct_framerate(AVCodecContext *avctx) +{ + int frate, fbase; + int est_frate, est_fbase; + int gcd; + float est_fps, fps; + + frate = avctx->time_base.den; + fbase = avctx->time_base.num; + + gcd = av_gcd(frate, fbase); + if( gcd > 1 ) { + frate /= gcd; + fbase /= gcd; + } + + if( frate <= 65000 && fbase <= 65000 ) { + avctx->time_base.den = frate; + avctx->time_base.num = fbase; + return; + } + + fps = (float)frate / (float)fbase; + est_fps = roundf(fps * 1000.0) / 1000.0; + + est_frate = (int)est_fps; + if( est_fps > (int)est_fps ) { + est_frate = (est_frate + 1) * 1000; + est_fbase = (int)roundf((float)est_frate / est_fps); + } else + est_fbase = 1; + + gcd = av_gcd(est_frate, est_fbase); + if( gcd > 1 ) { + est_frate /= gcd; + est_fbase /= gcd; + } + + if( fbase > est_fbase ) { + avctx->time_base.den = est_frate; + avctx->time_base.num = est_fbase; + av_log(avctx, AV_LOG_DEBUG, + "Xvid: framerate re-estimated: %.2f, %.3f%% correction\n", + est_fps, (((est_fps - fps)/fps) * 100.0)); + } else { + avctx->time_base.den = frate; + avctx->time_base.num = fbase; + } +} /** * Create the private context for the encoder. @@ -509,274 +774,6 @@ static av_cold int xvid_encode_close(AVCodecContext *avctx) { } /** - * Routine to create a global VO/VOL header for MP4 container. - * What we do here is extract the header from the Xvid bitstream - * as it is encoded. We also strip the repeated headers from the - * bitstream when a global header is requested for MPEG-4 ISO - * compliance. - * - * @param avctx AVCodecContext pointer to context - * @param frame Pointer to encoded frame data - * @param header_len Length of header to search - * @param frame_len Length of encoded frame data - * @return Returns new length of frame data - */ -int xvid_strip_vol_header(AVCodecContext *avctx, - AVPacket *pkt, - unsigned int header_len, - unsigned int frame_len) { - int vo_len = 0, i; - - for( i = 0; i < header_len - 3; i++ ) { - if( pkt->data[i] == 0x00 && - pkt->data[i+1] == 0x00 && - pkt->data[i+2] == 0x01 && - pkt->data[i+3] == 0xB6 ) { - vo_len = i; - break; - } - } - - if( vo_len > 0 ) { - /* We need to store the header, so extract it */ - if( avctx->extradata == NULL ) { - avctx->extradata = av_malloc(vo_len); - memcpy(avctx->extradata, pkt->data, vo_len); - avctx->extradata_size = vo_len; - } - /* Less dangerous now, memmove properly copies the two - chunks of overlapping data */ - memmove(pkt->data, &pkt->data[vo_len], frame_len - vo_len); - pkt->size = frame_len - vo_len; - } - return 0; -} - -/** - * Routine to correct a possibly erroneous framerate being fed to us. - * Xvid currently chokes on framerates where the ticks per frame is - * extremely large. This function works to correct problems in this area - * by estimating a new framerate and taking the simpler fraction of - * the two presented. - * - * @param avctx Context that contains the framerate to correct. - */ -void xvid_correct_framerate(AVCodecContext *avctx) { - int frate, fbase; - int est_frate, est_fbase; - int gcd; - float est_fps, fps; - - frate = avctx->time_base.den; - fbase = avctx->time_base.num; - - gcd = av_gcd(frate, fbase); - if( gcd > 1 ) { - frate /= gcd; - fbase /= gcd; - } - - if( frate <= 65000 && fbase <= 65000 ) { - avctx->time_base.den = frate; - avctx->time_base.num = fbase; - return; - } - - fps = (float)frate / (float)fbase; - est_fps = roundf(fps * 1000.0) / 1000.0; - - est_frate = (int)est_fps; - if( est_fps > (int)est_fps ) { - est_frate = (est_frate + 1) * 1000; - est_fbase = (int)roundf((float)est_frate / est_fps); - } else - est_fbase = 1; - - gcd = av_gcd(est_frate, est_fbase); - if( gcd > 1 ) { - est_frate /= gcd; - est_fbase /= gcd; - } - - if( fbase > est_fbase ) { - avctx->time_base.den = est_frate; - avctx->time_base.num = est_fbase; - av_log(avctx, AV_LOG_DEBUG, - "Xvid: framerate re-estimated: %.2f, %.3f%% correction\n", - est_fps, (((est_fps - fps)/fps) * 100.0)); - } else { - avctx->time_base.den = frate; - avctx->time_base.num = fbase; - } -} - -/* - * Xvid 2-Pass Kludge Section - * - * Xvid's default 2-pass doesn't allow us to create data as we need to, so - * this section spends time replacing the first pass plugin so we can write - * statistic information as libavcodec requests in. We have another kludge - * that allows us to pass data to the second pass in Xvid without a custom - * rate-control plugin. - */ - -/** - * Initialize the two-pass plugin and context. - * - * @param param Input construction parameter structure - * @param handle Private context handle - * @return Returns XVID_ERR_xxxx on failure, or 0 on success. - */ -static int xvid_ff_2pass_create(xvid_plg_create_t * param, - void ** handle) { - struct xvid_ff_pass1 *x = (struct xvid_ff_pass1 *)param->param; - char *log = x->context->twopassbuffer; - - /* Do a quick bounds check */ - if( log == NULL ) - return XVID_ERR_FAIL; - - /* We use snprintf() */ - /* This is because we can safely prevent a buffer overflow */ - log[0] = 0; - snprintf(log, BUFFER_REMAINING(log), - "# ffmpeg 2-pass log file, using xvid codec\n"); - snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log), - "# Do not modify. libxvidcore version: %d.%d.%d\n\n", - XVID_VERSION_MAJOR(XVID_VERSION), - XVID_VERSION_MINOR(XVID_VERSION), - XVID_VERSION_PATCH(XVID_VERSION)); - - *handle = x->context; - return 0; -} - -/** - * Destroy the two-pass plugin context. - * - * @param ref Context pointer for the plugin - * @param param Destrooy context - * @return Returns 0, success guaranteed - */ -static int xvid_ff_2pass_destroy(struct xvid_context *ref, - xvid_plg_destroy_t *param) { - /* Currently cannot think of anything to do on destruction */ - /* Still, the framework should be here for reference/use */ - if( ref->twopassbuffer != NULL ) - ref->twopassbuffer[0] = 0; - return 0; -} - -/** - * Enable fast encode mode during the first pass. - * - * @param ref Context pointer for the plugin - * @param param Frame data - * @return Returns 0, success guaranteed - */ -static int xvid_ff_2pass_before(struct xvid_context *ref, - xvid_plg_data_t *param) { - int motion_remove; - int motion_replacements; - int vop_remove; - - /* Nothing to do here, result is changed too much */ - if( param->zone && param->zone->mode == XVID_ZONE_QUANT ) - return 0; - - /* We can implement a 'turbo' first pass mode here */ - param->quant = 2; - - /* Init values */ - motion_remove = ~XVID_ME_CHROMA_PVOP & - ~XVID_ME_CHROMA_BVOP & - ~XVID_ME_EXTSEARCH16 & - ~XVID_ME_ADVANCEDDIAMOND16; - motion_replacements = XVID_ME_FAST_MODEINTERPOLATE | - XVID_ME_SKIP_DELTASEARCH | - XVID_ME_FASTREFINE16 | - XVID_ME_BFRAME_EARLYSTOP; - vop_remove = ~XVID_VOP_MODEDECISION_RD & - ~XVID_VOP_FAST_MODEDECISION_RD & - ~XVID_VOP_TRELLISQUANT & - ~XVID_VOP_INTER4V & - ~XVID_VOP_HQACPRED; - - param->vol_flags &= ~XVID_VOL_GMC; - param->vop_flags &= vop_remove; - param->motion_flags &= motion_remove; - param->motion_flags |= motion_replacements; - - return 0; -} - -/** - * Capture statistic data and write it during first pass. - * - * @param ref Context pointer for the plugin - * @param param Statistic data - * @return Returns XVID_ERR_xxxx on failure, or 0 on success - */ -static int xvid_ff_2pass_after(struct xvid_context *ref, - xvid_plg_data_t *param) { - char *log = ref->twopassbuffer; - const char *frame_types = " ipbs"; - char frame_type; - - /* Quick bounds check */ - if( log == NULL ) - return XVID_ERR_FAIL; - - /* Convert the type given to us into a character */ - if( param->type < 5 && param->type > 0 ) { - frame_type = frame_types[param->type]; - } else { - return XVID_ERR_FAIL; - } - - snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log), - "%c %d %d %d %d %d %d\n", - frame_type, param->stats.quant, param->stats.kblks, param->stats.mblks, - param->stats.ublks, param->stats.length, param->stats.hlength); - - return 0; -} - -/** - * Dispatch function for our custom plugin. - * This handles the dispatch for the Xvid plugin. It passes data - * on to other functions for actual processing. - * - * @param ref Context pointer for the plugin - * @param cmd The task given for us to complete - * @param p1 First parameter (varies) - * @param p2 Second parameter (varies) - * @return Returns XVID_ERR_xxxx on failure, or 0 on success - */ -int xvid_ff_2pass(void *ref, int cmd, void *p1, void *p2) { - switch( cmd ) { - case XVID_PLG_INFO: - case XVID_PLG_FRAME: - return 0; - - case XVID_PLG_BEFORE: - return xvid_ff_2pass_before(ref, p1); - - case XVID_PLG_CREATE: - return xvid_ff_2pass_create(p1, p2); - - case XVID_PLG_AFTER: - return xvid_ff_2pass_after(ref, p1); - - case XVID_PLG_DESTROY: - return xvid_ff_2pass_destroy(ref, p1); - - default: - return XVID_ERR_FAIL; - } -} - -/** * Xvid codec definition for libavcodec. */ AVCodec ff_libxvid_encoder = { |