changeset 15619:ccf2c61afacd

XviD zones support. Patch by Doom9: < feedback123 GROOVY doom9 STEADY org >
author gpoirier
date Thu, 02 Jun 2005 22:01:38 +0000
parents 1965072518be
children 692c06b7dc92
files ChangeLog DOCS/man/en/mplayer.1 libmpcodecs/ve_xvid4.c
diffstat 3 files changed, 97 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Jun 02 21:16:21 2005 +0000
+++ b/ChangeLog	Thu Jun 02 22:01:38 2005 +0000
@@ -34,6 +34,7 @@
     * audio encoding modularized
     * AAC (FAAC) audio encoding
     * border processing adaptive quantization in libavcodec
+    * XviD's encoding zones
 
     Ports:
     * improved timer function on Mac OS X
--- a/DOCS/man/en/mplayer.1	Thu Jun 02 21:16:21 2005 +0000
+++ b/DOCS/man/en/mplayer.1	Thu Jun 02 22:01:38 2005 +0000
@@ -7269,6 +7269,36 @@
 Switch to fixed quantizer mode and specify the quantizer to be used.
 .
 .TP
+.B zones=<zone0>[/\:<zone1>[/\:...]]
+User specified quality for specific parts (ending, credits, ...)
+(ABR or two pass).
+Each zone is <start-frame>,<mode>,<value> where <mode> may be
+.PD 0
+.RSs
+.IPs "q"
+constant quantizer override.
+In that case, value=<2.0\-31.0> represents the quantizer value.
+.IPs "w"
+ratecontrol weight override.
+In that case, value=<0.01\-2.00> represents the quality correction in %.
+.RE
+.PD 1
+.RS
+.I EXAMPLE:
+.RE
+.RSs
+.IPs zones=90000,q,20
+Encodes all frames starting with frame 90000 at constant quantizer 20.
+.IPs zones=0,w,0.1/10001,w,1.0/90000,q,20
+Encode frames 0\-10000 at 10% bitrate, encode frames 90000 and 
+up to the end at constant quantizer 20.
+Note that the second zone is needed to delimit the first zone, as
+without it everything up until frame 89999 would be encoded at 10%
+bitrate.
+.RE
+.PD 1
+.
+.TP
 .B me_quality=<0\-6>
 This option controls the motion estimation subsystem.
 The higher the value, the more precise the estimation should be (default: 6).
--- a/libmpcodecs/ve_xvid4.c	Thu Jun 02 21:16:21 2005 +0000
+++ b/libmpcodecs/ve_xvid4.c	Thu Jun 02 22:01:38 2005 +0000
@@ -61,6 +61,8 @@
 #define FINE (!0)
 #define BAD (!FINE)
 
+#define MAX_ZONES   64
+
 // Code taken from Libavcodec and ve_lavc.c to handle Aspect Ratio calculation
 
 typedef struct xvid_rational_s{
@@ -201,6 +203,8 @@
 static float xvidenc_dar_aspect = 0.0f;
 static int xvidenc_autoaspect = 0;
 
+static char *xvidenc_zones = NULL; // zones string
+
 m_option_t xvidencopts_conf[] =
 {
 	/* Standard things mencoder should be able to treat directly */
@@ -281,6 +285,9 @@
 	{"autoaspect", &xvidenc_autoaspect, CONF_TYPE_FLAG, 0, 0, 1, NULL},
 	{"noautoaspect", &xvidenc_autoaspect, CONF_TYPE_FLAG, 0, 1, 0, NULL},
 
+	/* Section Zones */
+	{"zones", &xvidenc_zones, CONF_TYPE_STRING, 0, 0, 0, NULL},
+
 	/* End of the config array */
 	{NULL, 0, 0, 0, 0, 0, NULL}
 };
@@ -302,7 +309,7 @@
 
 	/* This data must survive local block scope, so here it is */
 	xvid_enc_plugin_t    plugins[7];
-	xvid_enc_zone_t      zones[1];
+	xvid_enc_zone_t      zones[MAX_ZONES];
 
 	/* MPEG4 stream buffer */
 	muxer_stream_t *mux;
@@ -873,6 +880,7 @@
 static int set_create_struct(xvid_mplayer_module_t *mod)
 {
 	int pass;
+	int doZones = 0;
 	xvid_enc_create_t *create    = &mod->create;
 
 	/* Most of the structure is initialized by dispatch settings, only a
@@ -988,6 +996,7 @@
 			mp_msg(MSGT_MENCODER, MSGL_INFO,
 			       "xvid: CBR Rate Control -- bitrate=%dkbit/s\n",
 			       xvidenc_bitrate>16000?xvidenc_bitrate/1000:xvidenc_bitrate);
+			doZones = 1;
 		}
 
 		create->plugins[create->num_plugins].func  = xvid_plugin_single;
@@ -1038,8 +1047,63 @@
 		create->plugins[create->num_plugins].func  = xvid_plugin_2pass2;
 		create->plugins[create->num_plugins].param = pass2;
 		create->num_plugins++;
+		doZones = 1;
 	}
-
+	// parse zones
+	if (xvidenc_zones != NULL && doZones > 0) // do not apply zones in CQ, and first pass mode (xvid vfw doesn't allow them in those modes either)
+	{
+		void *p;
+		int i;
+		p = xvidenc_zones;
+		create->num_zones = 0; // set the number of zones back to zero, this overwrites the zone defined for CQ - desired because each zone has to be specified on the commandline even in cq mode
+		for(i = 0; p; i++)
+		{
+        		int start;
+			double value;
+			char mode;
+        		int e = sscanf(p, "%d,%c,%lf", &start, &mode, &value); // start,mode(q = constant quant, w = weight),value
+        		if(e != 3)
+			{
+	    			mp_msg(MSGT_MENCODER,MSGL_ERR, "error parsing zones\n");
+            		return(BAD);
+        		}
+			int q = (int)(value * 100);
+			if (mode == 'q')
+			{
+				if (q < 200 || q > 3100) // make sure that quantizer is in allowable range
+				{
+					mp_msg(MSGT_MENCODER, MSGL_ERR, "zone quantizer must be between 2 and 31\n");
+					return(BAD);
+				}
+				else
+				{
+					create->zones[create->num_zones].mode      = XVID_ZONE_QUANT;
+				}
+			}
+			if (mode == 'w')
+			{
+				if (q < 1 || q > 200)
+				{
+					mp_msg(MSGT_MENCODER, MSGL_ERR, "zone weight must be between 1 and 200\n");
+					return(BAD);
+				}
+				else
+				{
+					create->zones[create->num_zones].mode      = XVID_ZONE_WEIGHT;
+				}
+			}
+			create->zones[create->num_zones].frame     = start;
+			create->zones[create->num_zones].increment = q;
+			create->zones[create->num_zones].base      = 100; // increment is 100 times the actual value
+			create->num_zones++;
+			if (create->num_zones > MAX_ZONES) // show warning if we have too many zones
+			{
+				mp_msg(MSGT_MENCODER, MSGL_ERR, "too many zones, zones will be ignored\n");
+			}
+        		p = strchr(p, '/');
+        		if(p) p++;
+    		}
+	}
 	return(FINE);
 }