diff -Naurb main/DOCS/man/en/mplayer.1 main.new/DOCS/man/en/mplayer.1 --- main/DOCS/man/en/mplayer.1 2004-01-29 19:45:20.000000000 +0100 +++ main.new/DOCS/man/en/mplayer.1 2004-01-29 23:02:42.000000000 +0100 @@ -5049,6 +5049,18 @@ .RE .PD 1 .TP +.B aspect= +Store movie aspect internally, just like MPEG files. +Much nicer solution than rescaling, because quality isn't decreased. +MPlayer and few others players will play these files correctly, others will display +them with the wrong aspect. +The aspect parameter can be given as a ratio or a floating point number. +.TP +.B autoaspect +Same as the aspect option, but automatically computes aspect, taking +into account all the adjustments (crop/expand/scale/etc.) made in the +filter chain. +.TP .B psnr\ \ \ Print the psnr (peak signal to noise ratio) for the whole video after encoding and store the per frame psnr in a file with a name like 'psnr_hhmmss.log'. diff -Naurb main/libmpcodecs/ve_xvid4.c main.new/libmpcodecs/ve_xvid4.c --- main/libmpcodecs/ve_xvid4.c 2003-12-08 17:56:46.000000000 +0100 +++ main.new/libmpcodecs/ve_xvid4.c 2004-01-29 22:52:53.000000000 +0100 @@ -52,6 +52,7 @@ #include #include #include +#include #include "m_option.h" @@ -59,6 +60,86 @@ #define FINE (!0) #define BAD (!FINE) +// Code taken from Libavcodec and ve_lavc.c to handle Aspect Ratio calculation + +typedef struct XVIDRational{ + int num; + int den; +} XVIDRational; + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define ABS(a) ((a) >= 0 ? (a) : (-(a))) + + +static int64_t xvid_gcd(int64_t a, int64_t b){ + if(b) return xvid_gcd(b, a%b); + else return a; +} + +static int xvid_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max){ + int exact=1, sign=0; + int64_t gcd; + + assert(den != 0); + + if(den < 0){ + den= -den; + nom= -nom; + } + + if(nom < 0){ + nom= -nom; + sign= 1; + } + + gcd = xvid_gcd(nom, den); + nom /= gcd; + den /= gcd; + + if(nom > max || den > max){ + XVIDRational a0={0,1}, a1={1,0}; + exact=0; + + for(;;){ + int64_t x= nom / den; + int64_t a2n= x*a1.num + a0.num; + int64_t a2d= x*a1.den + a0.den; + + if(a2n > max || a2d > max) break; + + nom %= den; + + a0= a1; + a1= (XVIDRational){a2n, a2d}; + if(nom==0) break; + x= nom; nom=den; den=x; + } + nom= a1.num; + den= a1.den; + } + + assert(xvid_gcd(nom, den) == 1); + + if(sign) nom= -nom; + + *dst_nom = nom; + *dst_den = den; + + return exact; +} + + +static XVIDRational xvid_d2q(double d, int max){ + XVIDRational a; + int exponent= MAX( (int)(log(ABS(d) + 1e-20)/log(2)), 0); + int64_t den= 1LL << (61 - exponent); + xvid_reduce(&a.num, &a.den, (int64_t)(d * den + 0.5), den, max); + + return a; +} + + + /***************************************************************************** * Configuration options ****************************************************************************/ @@ -76,14 +157,16 @@ static int xvidenc_cartoon = 0; static int xvidenc_hqacpred = 1; static int xvidenc_chromame = 0; +static int xvidenc_chroma_opt = 0; static int xvidenc_vhq = 0; static int xvidenc_motion = 6; +static int xvidenc_turbo = 0; static int xvidenc_stats = 0; -static int xvidenc_max_key_interval = 0; +static int xvidenc_max_key_interval = 0; /* Let xvidcore set a 10s interval by default */ static int xvidenc_frame_drop_ratio = 0; static int xvidenc_greyscale = 0; -static int xvidenc_max_bframes = 0; +static int xvidenc_max_bframes = 2; static int xvidenc_bquant_ratio = 150; static int xvidenc_bquant_offset = 100; static int xvidenc_bframe_threshold = 0; @@ -99,18 +182,20 @@ static int xvidenc_cbr_buffer = 0; static int xvidenc_vbr_keyframe_boost = 0; -static int xvidenc_vbr_overflow_control_strength = 0; +static int xvidenc_vbr_overflow_control_strength = 5; static int xvidenc_vbr_curve_compression_high = 0; static int xvidenc_vbr_curve_compression_low = 0; -static int xvidenc_vbr_max_overflow_improvement = 0; -static int xvidenc_vbr_max_overflow_degradation = 0; +static int xvidenc_vbr_max_overflow_improvement = 5; +static int xvidenc_vbr_max_overflow_degradation = 5; static int xvidenc_vbr_kfreduction = 0; static int xvidenc_vbr_kfthreshold = 0; -static int xvidenc_vbr_container_frame_overhead = 0; +static int xvidenc_vbr_container_frame_overhead = 24; /* mencoder uses AVI container */ static char *xvidenc_par = NULL; static int xvidenc_par_width = 0; static int xvidenc_par_height = 0; +static float xvidenc_dar_aspect = 0.0f; +static int xvidenc_autoaspect = 0; m_option_t xvidencopts_conf[] = { @@ -123,6 +208,7 @@ {"quant_type", &xvidenc_quant_method, CONF_TYPE_STRING, 0, 0, 0, NULL}, {"me_quality", &xvidenc_motion, CONF_TYPE_INT, CONF_RANGE, 0, 6, NULL}, {"chroma_me", &xvidenc_chromame, CONF_TYPE_FLAG, 0, 0, 1, NULL}, + {"chroma_opt", &xvidenc_chroma_opt, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"vhq", &xvidenc_vhq, CONF_TYPE_INT, CONF_RANGE, 0, 4, NULL}, {"max_bframes", &xvidenc_max_bframes, CONF_TYPE_INT, CONF_RANGE, 0, 20, NULL}, {"bquant_ratio", &xvidenc_bquant_ratio, CONF_TYPE_INT, CONF_RANGE, 0, 200, NULL}, @@ -139,6 +225,7 @@ {"frame_drop_ratio", &xvidenc_frame_drop_ratio, CONF_TYPE_INT, CONF_RANGE, 0, 100, NULL}, {"max_key_interval", &xvidenc_max_key_interval, CONF_TYPE_INT, CONF_MIN, 0, 0, NULL}, {"greyscale", &xvidenc_greyscale, CONF_TYPE_FLAG, 0, 0, 1, NULL}, + {"turbo", &xvidenc_turbo, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"stats", &xvidenc_stats, CONF_TYPE_FLAG, 0, 0, 1, NULL}, @@ -172,6 +259,8 @@ {"par", &xvidenc_par, CONF_TYPE_STRING, 0, 0, 0, NULL}, {"par_width", &xvidenc_par_width, CONF_TYPE_INT, CONF_RANGE, 0, 255, NULL}, {"par_height", &xvidenc_par_height, CONF_TYPE_INT, CONF_RANGE, 0, 255, NULL}, + {"aspect", &xvidenc_dar_aspect, CONF_TYPE_FLOAT, CONF_RANGE, 0.1, 9.99, NULL}, + {"autoaspect", &xvidenc_autoaspect, CONF_TYPE_FLAG, 0, 0, 1, NULL}, /* End of the config array */ {NULL, 0, 0, 0, 0, 0, NULL} @@ -212,6 +301,8 @@ int max_sse_y; int max_sse_u; int max_sse_v; + + int d_width, d_height; } xvid_mplayer_module_t; static void dispatch_settings(xvid_mplayer_module_t *mod); @@ -251,6 +342,9 @@ * Dispatch all module settings to XviD structures *------------------------------------------------------------------*/ + mod->d_width = d_width; + mod->d_height = d_height; + dispatch_settings(mod); /*-------------------------------------------------------------------- @@ -518,6 +612,7 @@ xvid_enc_frame_t *frame = &mod->frame; xvid_plugin_single_t *onepass = &mod->onepass; xvid_plugin_2pass2_t *pass2 = &mod->pass2; + XVIDRational ar; const int motion_presets[7] = { @@ -652,6 +747,9 @@ if(xvidenc_hqacpred) { frame->vop_flags |= XVID_VOP_HQACPRED; } + if(xvidenc_chroma_opt) { + frame->vop_flags |= XVID_VOP_CHROMAOPT; + } if(xvidenc_motion > 4) { frame->vop_flags |= XVID_VOP_INTER4V; } @@ -674,6 +772,13 @@ if(xvidenc_vhq >= 4) { frame->motion |= XVID_ME_EXTSEARCH_RD; } + if(xvidenc_turbo) { + frame->motion |= XVID_ME_FASTREFINE16; + frame->motion |= XVID_ME_FASTREFINE8; + frame->motion |= XVID_ME_SKIP_DELTASEARCH; + frame->motion |= XVID_ME_FAST_MODEINTERPOLATE; + frame->motion |= XVID_ME_BFRAME_EARLYSTOP; + } /* motion level == 0 means no motion search which is equivalent to * intra coding only */ @@ -685,22 +790,46 @@ frame->bframe_threshold = xvidenc_bframe_threshold; - frame->par = 0; - if(xvidenc_par != NULL) { + /* PAR related initialization */ + frame->par = XVID_PAR_11_VGA; /* Default */ + + if(xvidenc_dar_aspect > 0) + ar = xvid_d2q(xvidenc_dar_aspect * mod->mux->bih->biHeight / mod->mux->bih->biWidth, 255); + else if(xvidenc_autoaspect) + ar = xvid_d2q((float)mod->d_width / mod->d_height * mod->mux->bih->biHeight / mod->mux->bih->biWidth, 255); + else ar.num = ar.den = 0; + + if(ar.den != 0) { + if(ar.num == 12 && ar.den == 11) + frame->par = XVID_PAR_43_PAL; + else if(ar.num == 10 && ar.den == 11) + frame->par = XVID_PAR_43_NTSC; + else if(ar.num == 16 && ar.den == 11) + frame->par = XVID_PAR_169_PAL; + else if(ar.num == 40 && ar.den == 33) + frame->par = XVID_PAR_169_NTSC; + else + { + frame->par = XVID_PAR_EXT; + frame->par_width = ar.num; + frame->par_height= ar.den; + } + + mp_msg(MSGT_MENCODER, MSGL_INFO, "XVID4_DAR: %d/%d code %d, Display frame: (%d, %d), original frame: (%d, %d)\n", + ar.num, ar.den, frame->par, + mod->d_width, mod->d_height, mod->mux->bih->biWidth, mod->mux->bih->biHeight); + } else if(xvidenc_par != NULL) { if(strcasecmp(xvidenc_par, "pal43") == 0) frame->par = XVID_PAR_43_PAL; - if(strcasecmp(xvidenc_par, "pal169") == 0) + else if(strcasecmp(xvidenc_par, "pal169") == 0) frame->par = XVID_PAR_169_PAL; - if(strcasecmp(xvidenc_par, "ntsc43") == 0) + else if(strcasecmp(xvidenc_par, "ntsc43") == 0) frame->par = XVID_PAR_43_NTSC; - if(strcasecmp(xvidenc_par, "ntsc169") == 0) + else if(strcasecmp(xvidenc_par, "ntsc169") == 0) frame->par = XVID_PAR_169_NTSC; - if(strcasecmp(xvidenc_par, "ext") == 0) + else if(strcasecmp(xvidenc_par, "ext") == 0) frame->par = XVID_PAR_EXT; - } - if(frame->par == 0) { - frame->par = XVID_PAR_11_VGA; - } + if(frame->par == XVID_PAR_EXT) { if(xvidenc_par_width) frame->par_width = xvidenc_par_width; @@ -712,7 +841,7 @@ else frame->par_height = 1; } - + } return; } @@ -1011,6 +1140,7 @@ return((const char *)error); } + /***************************************************************************** * Module structure definition ****************************************************************************/