libavcodec/libxvidff.c
Go to the documentation of this file.
00001 /*
00002  * Interface to xvidcore for mpeg4 encoding
00003  * Copyright (c) 2004 Adam Thayer <krevnik@comcast.net>
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00028 #include <xvid.h>
00029 #include <unistd.h>
00030 #include "avcodec.h"
00031 #include "libavutil/file.h"
00032 #include "libavutil/cpu.h"
00033 #include "libavutil/intreadwrite.h"
00034 #include "libavutil/mathematics.h"
00035 #include "libxvid_internal.h"
00036 
00040 #define BUFFER_SIZE                 1024
00041 #define BUFFER_REMAINING(x)         (BUFFER_SIZE - strlen(x))
00042 #define BUFFER_CAT(x)               (&((x)[strlen(x)]))
00043 
00048 struct xvid_context {
00049     void *encoder_handle;          
00050     int xsize;                     
00051     int ysize;                     
00052     int vop_flags;                 
00053     int vol_flags;                 
00054     int me_flags;                  
00055     int qscale;                    
00056     int quicktime_format;          
00057     AVFrame encoded_picture;       
00058     char *twopassbuffer;           
00059     char *old_twopassbuffer;       
00060     char *twopassfile;             
00061     unsigned char *intra_matrix;   
00062     unsigned char *inter_matrix;   
00063 };
00064 
00068 struct xvid_ff_pass1 {
00069     int     version;                
00070     struct xvid_context *context;   
00071 };
00072 
00073 /* Prototypes - See function implementation for details */
00074 int xvid_strip_vol_header(AVCodecContext *avctx, unsigned char *frame, unsigned int header_len, unsigned int frame_len);
00075 int xvid_ff_2pass(void *ref, int opt, void *p1, void *p2);
00076 void xvid_correct_framerate(AVCodecContext *avctx);
00077 
00078 #if CONFIG_LIBXVID_ENCODER
00079 
00088 static av_cold int xvid_encode_init(AVCodecContext *avctx)  {
00089     int xerr, i;
00090     int xvid_flags = avctx->flags;
00091     struct xvid_context *x = avctx->priv_data;
00092     uint16_t *intra, *inter;
00093     int fd;
00094 
00095     xvid_plugin_single_t single;
00096     struct xvid_ff_pass1 rc2pass1;
00097     xvid_plugin_2pass2_t rc2pass2;
00098     xvid_gbl_init_t xvid_gbl_init;
00099     xvid_enc_create_t xvid_enc_create;
00100     xvid_enc_plugin_t plugins[7];
00101 
00102     /* Bring in VOP flags from ffmpeg command-line */
00103     x->vop_flags = XVID_VOP_HALFPEL; /* Bare minimum quality */
00104     if( xvid_flags & CODEC_FLAG_4MV )
00105         x->vop_flags |= XVID_VOP_INTER4V; /* Level 3 */
00106     if( avctx->trellis
00107         )
00108         x->vop_flags |= XVID_VOP_TRELLISQUANT; /* Level 5 */
00109     if( xvid_flags & CODEC_FLAG_AC_PRED )
00110         x->vop_flags |= XVID_VOP_HQACPRED; /* Level 6 */
00111     if( xvid_flags & CODEC_FLAG_GRAY )
00112         x->vop_flags |= XVID_VOP_GREYSCALE;
00113 
00114     /* Decide which ME quality setting to use */
00115     x->me_flags = 0;
00116     switch( avctx->me_method ) {
00117        case ME_FULL:   /* Quality 6 */
00118            x->me_flags |=  XVID_ME_EXTSEARCH16
00119                        |   XVID_ME_EXTSEARCH8;
00120 
00121        case ME_EPZS:   /* Quality 4 */
00122            x->me_flags |=  XVID_ME_ADVANCEDDIAMOND8
00123                        |   XVID_ME_HALFPELREFINE8
00124                        |   XVID_ME_CHROMA_PVOP
00125                        |   XVID_ME_CHROMA_BVOP;
00126 
00127        case ME_LOG:    /* Quality 2 */
00128        case ME_PHODS:
00129        case ME_X1:
00130            x->me_flags |=  XVID_ME_ADVANCEDDIAMOND16
00131                        |   XVID_ME_HALFPELREFINE16;
00132 
00133        case ME_ZERO:   /* Quality 0 */
00134        default:
00135            break;
00136     }
00137 
00138     /* Decide how we should decide blocks */
00139     switch( avctx->mb_decision ) {
00140        case 2:
00141            x->vop_flags |= XVID_VOP_MODEDECISION_RD;
00142            x->me_flags |=  XVID_ME_HALFPELREFINE8_RD
00143                        |   XVID_ME_QUARTERPELREFINE8_RD
00144                        |   XVID_ME_EXTSEARCH_RD
00145                        |   XVID_ME_CHECKPREDICTION_RD;
00146        case 1:
00147            if( !(x->vop_flags & XVID_VOP_MODEDECISION_RD) )
00148                x->vop_flags |= XVID_VOP_FAST_MODEDECISION_RD;
00149            x->me_flags |=  XVID_ME_HALFPELREFINE16_RD
00150                        |   XVID_ME_QUARTERPELREFINE16_RD;
00151 
00152        default:
00153            break;
00154     }
00155 
00156     /* Bring in VOL flags from ffmpeg command-line */
00157     x->vol_flags = 0;
00158     if( xvid_flags & CODEC_FLAG_GMC ) {
00159         x->vol_flags |= XVID_VOL_GMC;
00160         x->me_flags |= XVID_ME_GME_REFINE;
00161     }
00162     if( xvid_flags & CODEC_FLAG_QPEL ) {
00163         x->vol_flags |= XVID_VOL_QUARTERPEL;
00164         x->me_flags |= XVID_ME_QUARTERPELREFINE16;
00165         if( x->vop_flags & XVID_VOP_INTER4V )
00166             x->me_flags |= XVID_ME_QUARTERPELREFINE8;
00167     }
00168 
00169     memset(&xvid_gbl_init, 0, sizeof(xvid_gbl_init));
00170     xvid_gbl_init.version = XVID_VERSION;
00171     xvid_gbl_init.debug = 0;
00172 
00173 #if ARCH_PPC
00174     /* Xvid's PPC support is borked, use libavcodec to detect */
00175 #if HAVE_ALTIVEC
00176     if (av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) {
00177         xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_ALTIVEC;
00178     } else
00179 #endif
00180         xvid_gbl_init.cpu_flags = XVID_CPU_FORCE;
00181 #else
00182     /* Xvid can detect on x86 */
00183     xvid_gbl_init.cpu_flags = 0;
00184 #endif
00185 
00186     /* Initialize */
00187     xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL);
00188 
00189     /* Create the encoder reference */
00190     memset(&xvid_enc_create, 0, sizeof(xvid_enc_create));
00191     xvid_enc_create.version = XVID_VERSION;
00192 
00193     /* Store the desired frame size */
00194     xvid_enc_create.width = x->xsize = avctx->width;
00195     xvid_enc_create.height = x->ysize = avctx->height;
00196 
00197     /* Xvid can determine the proper profile to use */
00198     /* xvid_enc_create.profile = XVID_PROFILE_S_L3; */
00199 
00200     /* We don't use zones */
00201     xvid_enc_create.zones = NULL;
00202     xvid_enc_create.num_zones = 0;
00203 
00204     xvid_enc_create.num_threads = avctx->thread_count;
00205 
00206     xvid_enc_create.plugins = plugins;
00207     xvid_enc_create.num_plugins = 0;
00208 
00209     /* Initialize Buffers */
00210     x->twopassbuffer = NULL;
00211     x->old_twopassbuffer = NULL;
00212     x->twopassfile = NULL;
00213 
00214     if( xvid_flags & CODEC_FLAG_PASS1 ) {
00215         memset(&rc2pass1, 0, sizeof(struct xvid_ff_pass1));
00216         rc2pass1.version = XVID_VERSION;
00217         rc2pass1.context = x;
00218         x->twopassbuffer = av_malloc(BUFFER_SIZE);
00219         x->old_twopassbuffer = av_malloc(BUFFER_SIZE);
00220         if( x->twopassbuffer == NULL || x->old_twopassbuffer == NULL ) {
00221             av_log(avctx, AV_LOG_ERROR,
00222                 "Xvid: Cannot allocate 2-pass log buffers\n");
00223             return -1;
00224         }
00225         x->twopassbuffer[0] = x->old_twopassbuffer[0] = 0;
00226 
00227         plugins[xvid_enc_create.num_plugins].func = xvid_ff_2pass;
00228         plugins[xvid_enc_create.num_plugins].param = &rc2pass1;
00229         xvid_enc_create.num_plugins++;
00230     } else if( xvid_flags & CODEC_FLAG_PASS2 ) {
00231         memset(&rc2pass2, 0, sizeof(xvid_plugin_2pass2_t));
00232         rc2pass2.version = XVID_VERSION;
00233         rc2pass2.bitrate = avctx->bit_rate;
00234 
00235         fd = av_tempfile("xvidff.", &x->twopassfile, 0, avctx);
00236         if( fd == -1 ) {
00237             av_log(avctx, AV_LOG_ERROR,
00238                 "Xvid: Cannot write 2-pass pipe\n");
00239             return -1;
00240         }
00241 
00242         if( avctx->stats_in == NULL ) {
00243             av_log(avctx, AV_LOG_ERROR,
00244                 "Xvid: No 2-pass information loaded for second pass\n");
00245             return -1;
00246         }
00247 
00248         if( strlen(avctx->stats_in) >
00249               write(fd, avctx->stats_in, strlen(avctx->stats_in)) ) {
00250             close(fd);
00251             av_log(avctx, AV_LOG_ERROR,
00252                 "Xvid: Cannot write to 2-pass pipe\n");
00253             return -1;
00254         }
00255 
00256         close(fd);
00257         rc2pass2.filename = x->twopassfile;
00258         plugins[xvid_enc_create.num_plugins].func = xvid_plugin_2pass2;
00259         plugins[xvid_enc_create.num_plugins].param = &rc2pass2;
00260         xvid_enc_create.num_plugins++;
00261     } else if( !(xvid_flags & CODEC_FLAG_QSCALE) ) {
00262         /* Single Pass Bitrate Control! */
00263         memset(&single, 0, sizeof(xvid_plugin_single_t));
00264         single.version = XVID_VERSION;
00265         single.bitrate = avctx->bit_rate;
00266 
00267         plugins[xvid_enc_create.num_plugins].func = xvid_plugin_single;
00268         plugins[xvid_enc_create.num_plugins].param = &single;
00269         xvid_enc_create.num_plugins++;
00270     }
00271 
00272     /* Luminance Masking */
00273     if( 0.0 != avctx->lumi_masking ) {
00274         plugins[xvid_enc_create.num_plugins].func = xvid_plugin_lumimasking;
00275         plugins[xvid_enc_create.num_plugins].param = NULL;
00276         xvid_enc_create.num_plugins++;
00277     }
00278 
00279     /* Frame Rate and Key Frames */
00280     xvid_correct_framerate(avctx);
00281     xvid_enc_create.fincr = avctx->time_base.num;
00282     xvid_enc_create.fbase = avctx->time_base.den;
00283     if( avctx->gop_size > 0 )
00284         xvid_enc_create.max_key_interval = avctx->gop_size;
00285     else
00286         xvid_enc_create.max_key_interval = 240; /* Xvid's best default */
00287 
00288     /* Quants */
00289     if( xvid_flags & CODEC_FLAG_QSCALE ) x->qscale = 1;
00290     else x->qscale = 0;
00291 
00292     xvid_enc_create.min_quant[0] = avctx->qmin;
00293     xvid_enc_create.min_quant[1] = avctx->qmin;
00294     xvid_enc_create.min_quant[2] = avctx->qmin;
00295     xvid_enc_create.max_quant[0] = avctx->qmax;
00296     xvid_enc_create.max_quant[1] = avctx->qmax;
00297     xvid_enc_create.max_quant[2] = avctx->qmax;
00298 
00299     /* Quant Matrices */
00300     x->intra_matrix = x->inter_matrix = NULL;
00301     if( avctx->mpeg_quant )
00302        x->vol_flags |= XVID_VOL_MPEGQUANT;
00303     if( (avctx->intra_matrix || avctx->inter_matrix) ) {
00304        x->vol_flags |= XVID_VOL_MPEGQUANT;
00305 
00306        if( avctx->intra_matrix ) {
00307            intra = avctx->intra_matrix;
00308            x->intra_matrix = av_malloc(sizeof(unsigned char) * 64);
00309        } else
00310            intra = NULL;
00311        if( avctx->inter_matrix ) {
00312            inter = avctx->inter_matrix;
00313            x->inter_matrix = av_malloc(sizeof(unsigned char) * 64);
00314        } else
00315            inter = NULL;
00316 
00317        for( i = 0; i < 64; i++ ) {
00318            if( intra )
00319                x->intra_matrix[i] = (unsigned char)intra[i];
00320            if( inter )
00321                x->inter_matrix[i] = (unsigned char)inter[i];
00322        }
00323     }
00324 
00325     /* Misc Settings */
00326     xvid_enc_create.frame_drop_ratio = 0;
00327     xvid_enc_create.global = 0;
00328     if( xvid_flags & CODEC_FLAG_CLOSED_GOP )
00329         xvid_enc_create.global |= XVID_GLOBAL_CLOSED_GOP;
00330 
00331     /* Determines which codec mode we are operating in */
00332     avctx->extradata = NULL;
00333     avctx->extradata_size = 0;
00334     if( xvid_flags & CODEC_FLAG_GLOBAL_HEADER ) {
00335         /* In this case, we are claiming to be MPEG4 */
00336         x->quicktime_format = 1;
00337         avctx->codec_id = CODEC_ID_MPEG4;
00338     } else {
00339         /* We are claiming to be Xvid */
00340         x->quicktime_format = 0;
00341         if(!avctx->codec_tag)
00342             avctx->codec_tag = AV_RL32("xvid");
00343     }
00344 
00345     /* Bframes */
00346     xvid_enc_create.max_bframes = avctx->max_b_frames;
00347     xvid_enc_create.bquant_offset = 100 * avctx->b_quant_offset;
00348     xvid_enc_create.bquant_ratio = 100 * avctx->b_quant_factor;
00349     if( avctx->max_b_frames > 0  && !x->quicktime_format ) xvid_enc_create.global |= XVID_GLOBAL_PACKED;
00350 
00351     /* Create encoder context */
00352     xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL);
00353     if( xerr ) {
00354         av_log(avctx, AV_LOG_ERROR, "Xvid: Could not create encoder reference\n");
00355         return -1;
00356     }
00357 
00358     x->encoder_handle = xvid_enc_create.handle;
00359     avctx->coded_frame = &x->encoded_picture;
00360 
00361     return 0;
00362 }
00363 
00373 static int xvid_encode_frame(AVCodecContext *avctx,
00374                          unsigned char *frame, int buf_size, void *data) {
00375     int xerr, i;
00376     char *tmp;
00377     struct xvid_context *x = avctx->priv_data;
00378     AVFrame *picture = data;
00379     AVFrame *p = &x->encoded_picture;
00380 
00381     xvid_enc_frame_t xvid_enc_frame;
00382     xvid_enc_stats_t xvid_enc_stats;
00383 
00384     /* Start setting up the frame */
00385     memset(&xvid_enc_frame, 0, sizeof(xvid_enc_frame));
00386     xvid_enc_frame.version = XVID_VERSION;
00387     memset(&xvid_enc_stats, 0, sizeof(xvid_enc_stats));
00388     xvid_enc_stats.version = XVID_VERSION;
00389     *p = *picture;
00390 
00391     /* Let Xvid know where to put the frame. */
00392     xvid_enc_frame.bitstream = frame;
00393     xvid_enc_frame.length = buf_size;
00394 
00395     /* Initialize input image fields */
00396     if( avctx->pix_fmt != PIX_FMT_YUV420P ) {
00397         av_log(avctx, AV_LOG_ERROR, "Xvid: Color spaces other than 420p not supported\n");
00398         return -1;
00399     }
00400 
00401     xvid_enc_frame.input.csp = XVID_CSP_PLANAR; /* YUV420P */
00402 
00403     for( i = 0; i < 4; i++ ) {
00404         xvid_enc_frame.input.plane[i] = picture->data[i];
00405         xvid_enc_frame.input.stride[i] = picture->linesize[i];
00406     }
00407 
00408     /* Encoder Flags */
00409     xvid_enc_frame.vop_flags = x->vop_flags;
00410     xvid_enc_frame.vol_flags = x->vol_flags;
00411     xvid_enc_frame.motion = x->me_flags;
00412     xvid_enc_frame.type =
00413         picture->pict_type == AV_PICTURE_TYPE_I ? XVID_TYPE_IVOP :
00414         picture->pict_type == AV_PICTURE_TYPE_P ? XVID_TYPE_PVOP :
00415         picture->pict_type == AV_PICTURE_TYPE_B ? XVID_TYPE_BVOP :
00416                                           XVID_TYPE_AUTO;
00417 
00418     /* Pixel aspect ratio setting */
00419     if (avctx->sample_aspect_ratio.num < 0 || avctx->sample_aspect_ratio.num > 255 ||
00420         avctx->sample_aspect_ratio.den < 0 || avctx->sample_aspect_ratio.den > 255) {
00421         av_log(avctx, AV_LOG_ERROR, "Invalid pixel aspect ratio %i/%i\n",
00422                avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
00423         return -1;
00424     }
00425     xvid_enc_frame.par = XVID_PAR_EXT;
00426     xvid_enc_frame.par_width  = avctx->sample_aspect_ratio.num;
00427     xvid_enc_frame.par_height = avctx->sample_aspect_ratio.den;
00428 
00429     /* Quant Setting */
00430     if( x->qscale ) xvid_enc_frame.quant = picture->quality / FF_QP2LAMBDA;
00431     else xvid_enc_frame.quant = 0;
00432 
00433     /* Matrices */
00434     xvid_enc_frame.quant_intra_matrix = x->intra_matrix;
00435     xvid_enc_frame.quant_inter_matrix = x->inter_matrix;
00436 
00437     /* Encode */
00438     xerr = xvid_encore(x->encoder_handle, XVID_ENC_ENCODE,
00439         &xvid_enc_frame, &xvid_enc_stats);
00440 
00441     /* Two-pass log buffer swapping */
00442     avctx->stats_out = NULL;
00443     if( x->twopassbuffer ) {
00444         tmp = x->old_twopassbuffer;
00445         x->old_twopassbuffer = x->twopassbuffer;
00446         x->twopassbuffer = tmp;
00447         x->twopassbuffer[0] = 0;
00448         if( x->old_twopassbuffer[0] != 0 ) {
00449             avctx->stats_out = x->old_twopassbuffer;
00450         }
00451     }
00452 
00453     if( 0 <= xerr ) {
00454         p->quality = xvid_enc_stats.quant * FF_QP2LAMBDA;
00455         if( xvid_enc_stats.type == XVID_TYPE_PVOP )
00456             p->pict_type = AV_PICTURE_TYPE_P;
00457         else if( xvid_enc_stats.type == XVID_TYPE_BVOP )
00458             p->pict_type = AV_PICTURE_TYPE_B;
00459         else if( xvid_enc_stats.type == XVID_TYPE_SVOP )
00460             p->pict_type = AV_PICTURE_TYPE_S;
00461         else
00462             p->pict_type = AV_PICTURE_TYPE_I;
00463         if( xvid_enc_frame.out_flags & XVID_KEYFRAME ) {
00464             p->key_frame = 1;
00465             if( x->quicktime_format )
00466                 return xvid_strip_vol_header(avctx, frame,
00467                     xvid_enc_stats.hlength, xerr);
00468          } else
00469             p->key_frame = 0;
00470 
00471         return xerr;
00472     } else {
00473         av_log(avctx, AV_LOG_ERROR, "Xvid: Encoding Error Occurred: %i\n", xerr);
00474         return -1;
00475     }
00476 }
00477 
00485 static av_cold int xvid_encode_close(AVCodecContext *avctx) {
00486     struct xvid_context *x = avctx->priv_data;
00487 
00488     xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL);
00489 
00490     av_freep(&avctx->extradata);
00491     if( x->twopassbuffer != NULL ) {
00492         av_free(x->twopassbuffer);
00493         av_free(x->old_twopassbuffer);
00494         avctx->stats_out = NULL;
00495     }
00496     av_free(x->twopassfile);
00497     av_free(x->intra_matrix);
00498     av_free(x->inter_matrix);
00499 
00500     return 0;
00501 }
00502 
00516 int xvid_strip_vol_header(AVCodecContext *avctx,
00517                   unsigned char *frame,
00518                   unsigned int header_len,
00519                   unsigned int frame_len) {
00520     int vo_len = 0, i;
00521 
00522     for( i = 0; i < header_len - 3; i++ ) {
00523         if( frame[i] == 0x00 &&
00524             frame[i+1] == 0x00 &&
00525             frame[i+2] == 0x01 &&
00526             frame[i+3] == 0xB6 ) {
00527             vo_len = i;
00528             break;
00529         }
00530     }
00531 
00532     if( vo_len > 0 ) {
00533         /* We need to store the header, so extract it */
00534         if( avctx->extradata == NULL ) {
00535             avctx->extradata = av_malloc(vo_len);
00536             memcpy(avctx->extradata, frame, vo_len);
00537             avctx->extradata_size = vo_len;
00538         }
00539         /* Less dangerous now, memmove properly copies the two
00540            chunks of overlapping data */
00541         memmove(frame, &frame[vo_len], frame_len - vo_len);
00542         return frame_len - vo_len;
00543     } else
00544         return frame_len;
00545 }
00546 
00556 void xvid_correct_framerate(AVCodecContext *avctx) {
00557     int frate, fbase;
00558     int est_frate, est_fbase;
00559     int gcd;
00560     float est_fps, fps;
00561 
00562     frate = avctx->time_base.den;
00563     fbase = avctx->time_base.num;
00564 
00565     gcd = av_gcd(frate, fbase);
00566     if( gcd > 1 ) {
00567         frate /= gcd;
00568         fbase /= gcd;
00569     }
00570 
00571     if( frate <= 65000 && fbase <= 65000 ) {
00572         avctx->time_base.den = frate;
00573         avctx->time_base.num = fbase;
00574         return;
00575     }
00576 
00577     fps = (float)frate / (float)fbase;
00578     est_fps = roundf(fps * 1000.0) / 1000.0;
00579 
00580     est_frate = (int)est_fps;
00581     if( est_fps > (int)est_fps ) {
00582         est_frate = (est_frate + 1) * 1000;
00583         est_fbase = (int)roundf((float)est_frate / est_fps);
00584     } else
00585         est_fbase = 1;
00586 
00587     gcd = av_gcd(est_frate, est_fbase);
00588     if( gcd > 1 ) {
00589         est_frate /= gcd;
00590         est_fbase /= gcd;
00591     }
00592 
00593     if( fbase > est_fbase ) {
00594         avctx->time_base.den = est_frate;
00595         avctx->time_base.num = est_fbase;
00596         av_log(avctx, AV_LOG_DEBUG,
00597             "Xvid: framerate re-estimated: %.2f, %.3f%% correction\n",
00598             est_fps, (((est_fps - fps)/fps) * 100.0));
00599     } else {
00600         avctx->time_base.den = frate;
00601         avctx->time_base.num = fbase;
00602     }
00603 }
00604 
00605 /*
00606  * Xvid 2-Pass Kludge Section
00607  *
00608  * Xvid's default 2-pass doesn't allow us to create data as we need to, so
00609  * this section spends time replacing the first pass plugin so we can write
00610  * statistic information as libavcodec requests in. We have another kludge
00611  * that allows us to pass data to the second pass in Xvid without a custom
00612  * rate-control plugin.
00613  */
00614 
00622 static int xvid_ff_2pass_create(xvid_plg_create_t * param,
00623                                 void ** handle) {
00624     struct xvid_ff_pass1 *x = (struct xvid_ff_pass1 *)param->param;
00625     char *log = x->context->twopassbuffer;
00626 
00627     /* Do a quick bounds check */
00628     if( log == NULL )
00629         return XVID_ERR_FAIL;
00630 
00631     /* We use snprintf() */
00632     /* This is because we can safely prevent a buffer overflow */
00633     log[0] = 0;
00634     snprintf(log, BUFFER_REMAINING(log),
00635         "# ffmpeg 2-pass log file, using xvid codec\n");
00636     snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log),
00637         "# Do not modify. libxvidcore version: %d.%d.%d\n\n",
00638         XVID_VERSION_MAJOR(XVID_VERSION),
00639         XVID_VERSION_MINOR(XVID_VERSION),
00640         XVID_VERSION_PATCH(XVID_VERSION));
00641 
00642     *handle = x->context;
00643     return 0;
00644 }
00645 
00653 static int xvid_ff_2pass_destroy(struct xvid_context *ref,
00654                                 xvid_plg_destroy_t *param) {
00655     /* Currently cannot think of anything to do on destruction */
00656     /* Still, the framework should be here for reference/use */
00657     if( ref->twopassbuffer != NULL )
00658         ref->twopassbuffer[0] = 0;
00659     return 0;
00660 }
00661 
00669 static int xvid_ff_2pass_before(struct xvid_context *ref,
00670                                 xvid_plg_data_t *param) {
00671     int motion_remove;
00672     int motion_replacements;
00673     int vop_remove;
00674 
00675     /* Nothing to do here, result is changed too much */
00676     if( param->zone && param->zone->mode == XVID_ZONE_QUANT )
00677         return 0;
00678 
00679     /* We can implement a 'turbo' first pass mode here */
00680     param->quant = 2;
00681 
00682     /* Init values */
00683     motion_remove = ~XVID_ME_CHROMA_PVOP &
00684                     ~XVID_ME_CHROMA_BVOP &
00685                     ~XVID_ME_EXTSEARCH16 &
00686                     ~XVID_ME_ADVANCEDDIAMOND16;
00687     motion_replacements = XVID_ME_FAST_MODEINTERPOLATE |
00688                           XVID_ME_SKIP_DELTASEARCH |
00689                           XVID_ME_FASTREFINE16 |
00690                           XVID_ME_BFRAME_EARLYSTOP;
00691     vop_remove = ~XVID_VOP_MODEDECISION_RD &
00692                  ~XVID_VOP_FAST_MODEDECISION_RD &
00693                  ~XVID_VOP_TRELLISQUANT &
00694                  ~XVID_VOP_INTER4V &
00695                  ~XVID_VOP_HQACPRED;
00696 
00697     param->vol_flags &= ~XVID_VOL_GMC;
00698     param->vop_flags &= vop_remove;
00699     param->motion_flags &= motion_remove;
00700     param->motion_flags |= motion_replacements;
00701 
00702     return 0;
00703 }
00704 
00712 static int xvid_ff_2pass_after(struct xvid_context *ref,
00713                                 xvid_plg_data_t *param) {
00714     char *log = ref->twopassbuffer;
00715     const char *frame_types = " ipbs";
00716     char frame_type;
00717 
00718     /* Quick bounds check */
00719     if( log == NULL )
00720         return XVID_ERR_FAIL;
00721 
00722     /* Convert the type given to us into a character */
00723     if( param->type < 5 && param->type > 0 ) {
00724         frame_type = frame_types[param->type];
00725     } else {
00726         return XVID_ERR_FAIL;
00727     }
00728 
00729     snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log),
00730         "%c %d %d %d %d %d %d\n",
00731         frame_type, param->stats.quant, param->stats.kblks, param->stats.mblks,
00732         param->stats.ublks, param->stats.length, param->stats.hlength);
00733 
00734     return 0;
00735 }
00736 
00748 int xvid_ff_2pass(void *ref, int cmd, void *p1, void *p2) {
00749     switch( cmd ) {
00750         case XVID_PLG_INFO:
00751         case XVID_PLG_FRAME:
00752             return 0;
00753 
00754         case XVID_PLG_BEFORE:
00755             return xvid_ff_2pass_before(ref, p1);
00756 
00757         case XVID_PLG_CREATE:
00758             return xvid_ff_2pass_create(p1, p2);
00759 
00760         case XVID_PLG_AFTER:
00761             return xvid_ff_2pass_after(ref, p1);
00762 
00763         case XVID_PLG_DESTROY:
00764             return xvid_ff_2pass_destroy(ref, p1);
00765 
00766         default:
00767             return XVID_ERR_FAIL;
00768     }
00769 }
00770 
00774 AVCodec ff_libxvid_encoder = {
00775     .name           = "libxvid",
00776     .type           = AVMEDIA_TYPE_VIDEO,
00777     .id             = CODEC_ID_MPEG4,
00778     .priv_data_size = sizeof(struct xvid_context),
00779     .init           = xvid_encode_init,
00780     .encode         = xvid_encode_frame,
00781     .close          = xvid_encode_close,
00782     .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
00783     .long_name= NULL_IF_CONFIG_SMALL("libxvidcore MPEG-4 part 2"),
00784 };
00785 
00786 #endif /* CONFIG_LIBXVID_ENCODER */