⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 plugin_2pass2.c

📁 这是一个压缩解压包,用C语言进行编程的,里面有详细的源代码.
💻 C
📖 第 1 页 / 共 4 页
字号:
			symetric_total += dbytes;			/* Apply assymetric curve compression */			if (dbytes > rc->avg_length[s->type-1])				assymetric_delta = (rc->avg_length[s->type-1] - dbytes) * (double)rc->param.curve_compression_high / 100.0f;			else				assymetric_delta = (rc->avg_length[s->type-1] - dbytes) * (double)rc->param.curve_compression_low  / 100.0f;			/* Cap to the minimum frame size if needed */			if (dbytes + assymetric_delta < rc->min_length[s->type-1])				assymetric_delta = rc->min_length[s->type-1] - dbytes;			/* Accumulate after assymetric curve compression */			assymetric_delta_total += assymetric_delta;		}		/* Compute the tax that all p/b frames have to pay in order to respect the		 * bit distribution changes that the assymetric compression curve imposes		 * We want assymetric_total = sum(0, n-1, tax.scaled_length)		 *      ie assymetric_total = ratio.sum(0, n-1, scaled_length)		 *         ratio = assymetric_total / symmetric_total */		rc->assymetric_tax_ratio = ((double)symetric_total - (double)assymetric_delta_total) / (double)symetric_total;	} else {		rc->assymetric_tax_ratio = 1.0f;	}	DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- Assymetric tax ratio:%.2f\n", rc->assymetric_tax_ratio);	/* Last bits that need to be reset */	rc->overflow = 0;	rc->KFoverflow = 0;	rc->KFoverflow_partial = 0;	rc->KF_idx = 0;	rc->desired_total = 0;	rc->real_total = 0;	/* Job done */	return;}/***************************************************************************** * VBV compliancy check and scale * MPEG-4 standard specifies certain restrictions for bitrate/framesize in VBR * to enable playback on devices with limited readspeed and memory (and which * aren't...) * * DivX profiles have 2 criteria: VBV as in MPEG standard *                                a limit on peak bitrate for any 3 seconds * * But if VBV is fulfilled, peakrate is automatically fulfilled in any profile * define so far, so we check for it (for completeness) but correct only VBV * *****************************************************************************/#define VBV_COMPLIANT 0#define VBV_UNDERFLOW 1 /* video buffer runs empty */#define VBV_OVERFLOW 2  /* doesn't exist for VBR encoding */#define VBV_PEAKRATE 4  /* peak bitrate (within 3s) violated */static intcheck_curve_for_vbv_compliancy(rc_2pass2_t * rc, const float fps){	/* We do all calculations in float, for higher accuracy,	 * and in bytes for convenience.	 *	 * typical values from DivX Home Theater profile:	 *  vbv_size= 384*1024 (384kB)	 *  vbv_initial= 288*1024 (75% fill)	 *  maxrate= 4854000 (4.854MBps)	 *  peakrate= 8000000 (8MBps)	 *	 *  PAL: offset3s = 75 (3 seconds of 25fps)	 *  NTSC: offset3s = 90 (3 seconds of 29.97fps) or 72 (3 seconds of 23.976fps)	 */	const float vbv_size = (float)rc->param.vbv_size/8.f;	float vbvfill = (float)rc->param.vbv_initial/8.f;	float vbvmin;	const float maxrate = (float)rc->param.vbv_maxrate;	const float peakrate = (float)rc->param.vbv_peakrate;	const float r0 = (int)(maxrate/fps+0.5)/8.f;	int bytes3s = 0;	int offset3s = (int)(3.f*fps+0.5);	int i;	/* 1Gbit should be enough to inuitialize the vbvmin	 *	an arbitrary high value */	vbvmin = 1000*1000*1000;	for (i=0; i<rc->num_frames; i++) {		/* DivX 3s peak bitrate check  */		bytes3s += rc->stats[i].scaled_length;		if (i>=offset3s)			bytes3s -= rc->stats[i-offset3s].scaled_length;    /* ignore peakrate constraint if peakrate is <= 0.f */		if (peakrate>0.f && 8.f*bytes3s > 3*peakrate)			return(VBV_PEAKRATE);		/* update vbv fill level */		vbvfill += r0 - rc->stats[i].scaled_length;		/* this check is _NOT_ an "overflow"! only reading from disk stops then */		if (vbvfill > vbv_size)			vbvfill = vbv_size;		/* but THIS would be an underflow. report it! */		if (vbvfill < 0)			return(VBV_UNDERFLOW);		/* Store the minimum buffer filling */		if (vbvfill < vbvmin)			vbvmin = vbvfill;	}	DPRINTF(XVID_DEBUG_RC, "[xvid rc] Minimum buffer fill: %f bytes\n", vbvmin);	return(VBV_COMPLIANT);}static intscale_curve_for_vbv_compliancy(rc_2pass2_t * rc, const float fps){	/* correct any VBV violations. Peak bitrate violations disappears	 * by this automatically	 *	 * This implementation follows	 *	 * Westerink, Rajagopalan, Gonzales "Two-pass MPEG-2 variable-bitrate encoding"	 * IBM J. RES. DEVELOP. VOL 43, No. 4, July 1999, p.471--488	 *	 * Thanks, guys! This paper rocks!!! */	/* For each scene of len N, we have to check up to N^2 possible buffer fills.	 * This works well with MPEG-2 where N==12 or so, but for MPEG-4 it's a	 * little slow...	 *	 * TODO: Better control on VBVfill between scenes */	const float vbv_size = (float)rc->param.vbv_size/8.f;	const float vbv_initial = (float)rc->param.vbv_initial/8.f;	const float maxrate = 0.9*rc->param.vbv_maxrate;	const float vbv_low = 0.10f*vbv_size;	const float r0 = (int)(maxrate/fps+0.5)/8.f;	int i,k,l,n,violation = 0;	float *scenefactor;	int *scenestart;	int *scenelength;	/* first step: determine how many "scenes" there are and store their	 * boundaries we could get all this from existing keyframe_positions,	 * somehow, but there we don't have a min_scenelength, and it's no big	 * deal to get it again. */	const int min_scenelength = (int)(fps+0.5);	int num_scenes = 0;	int last_scene = -999;	for (i=0; i<rc->num_frames; i++) {		if ((rc->stats[i].type == XVID_TYPE_IVOP) && (i-last_scene>min_scenelength)) {			last_scene = i;			num_scenes++;		}	}	scenefactor = (float*)malloc(num_scenes*sizeof(float));	scenestart = (int*)malloc(num_scenes*sizeof(int));	scenelength = (int*)malloc(num_scenes*sizeof(int));	if ((!scenefactor) || (!scenestart) || (!scenelength) ) {		free(scenefactor);		free(scenestart);		free(scenelength);		/* remember: free(0) is valid and does exactly nothing. */		return(-1);	}	/* count again and safe the length/position */	num_scenes = 0;	last_scene = -999;	for (i=0; i<rc->num_frames; i++) {		if ((rc->stats[i].type == XVID_TYPE_IVOP) && (i-last_scene>min_scenelength)) {			if (num_scenes>0) {				scenelength[num_scenes-1]=i-last_scene;			}			scenestart[num_scenes]=i;			num_scenes++;			last_scene = i;		}	}	scenelength[num_scenes-1]=i-last_scene;	/* second step: check for each scene, how much we can scale its frames up or	 * down such that the VBV restriction is just fulfilled */#define R(k,n) (((n)+1-(k))*r0)     /* how much enters the buffer between frame k and n */	for (l=0; l<num_scenes;l++) {		const int start = scenestart[l];		const int length = scenelength[l];		twopass_stat_t * frames = &rc->stats[start];		float S0n,Skn;		float f,minf = 99999.f;		S0n=0.;		for (n=0;n<=length-1;n++) {			S0n += frames[n].scaled_length;			k = 0;			Skn = S0n;			f = (R(k,n-1) + (vbv_initial - vbv_low)) / Skn;			if (f < minf)				minf = f;			for (k=1;k<=n;k++) {				Skn -= frames[k].scaled_length;				f = (R(k,n-1) + (vbv_size - vbv_low)) / Skn;				if (f < minf)					minf = f;			}		}		/* special case: at the end, fill buffer up to vbv_initial again		 *		 * TODO: Allow other values for buffer fill between scenes		 * e.g. if n=N is smallest f-value, then check for better value */		n=length;		k=0;		Skn = S0n;		f = R(k,n-1)/Skn;		if (f < minf)			minf = f;		for (k=1;k<=n-1;k++) {			Skn -= frames[k].scaled_length;			f = (R(k,n-1) + (vbv_initial - vbv_low)) / Skn;			if (f < minf)				minf = f;		}		DPRINTF(XVID_DEBUG_RC, "[xvid rc] Scene %d (Frames %d-%d): VBVfactor %f\n",			   	l, start, start+length-1 , minf);		scenefactor[l] = minf;	}#undef R	/* last step: now we know of any scene how much it can be scaled up or down	 * without violating VBV. Next, distribute bits from the evil scenes to the	 * good ones */	do {		float S_red = 0.f;    /* how much to redistribute */		float S_elig = 0.f;   /* sum of bit for those scenes you can still swallow something*/		float f_red;		int l;		/* check how much is wrong */		for (l=0;l<num_scenes;l++) {			const int start = scenestart[l];			const int length = scenelength[l];			twopass_stat_t * frames = &rc->stats[start];			/* exactly 1 means "don't touch this anymore!" */			if (scenefactor[l] == 1.)				continue;			/* within limits */			if (scenefactor[l] > 1.) {				for (n= 0; n < length; n++)					S_elig += frames[n].scaled_length;			} else {				/* underflowing segment */				for (n= 0; n < length; n++) {					float newbytes = (float)frames[n].scaled_length * scenefactor[l];					S_red += (float)frames[n].scaled_length - (float)newbytes;					frames[n].scaled_length =(int)newbytes;				}				scenefactor[l] = 1.f;			}		}		/* no more underflows */		if (S_red < 1.f)			break;		if (S_elig < 1.f) {			DPRINTF(XVID_DEBUG_RC, "[xvid rc] Everything underflowing.\n");			free(scenefactor);			free(scenestart);			free(scenelength);			return(-2);		}		f_red = (1.f + S_red/S_elig);		DPRINTF(XVID_DEBUG_RC, "[xvid rc] Moving %.0f kB to avoid buffer underflow, correction factor: %.5f\n",			   	S_red/1024.f, f_red);		violation=0;		/* scale remaining scenes up to meet total size */		for (l=0; l<num_scenes; l++) {			const int start = scenestart[l];			const int length = scenelength[l];			twopass_stat_t * frames = &rc->stats[start];			if (scenefactor[l] == 1.)				continue;			/* there shouldn't be any segments with factor<1 left, so all the rest is >1 */			for (n= 0; n < length; n++) {				frames[n].scaled_length = (int)(frames[n].scaled_length * f_red + 0.5);			}			scenefactor[l] /= f_red;			if (scenefactor[l] < 1.f)				violation=1;		}	} while (violation);	free(scenefactor);	free(scenestart);	free(scenelength);	return(0);}/***************************************************************************** * Still more low level stuff (nothing to do with stats treatment) ****************************************************************************//* This function returns an allocated string containing a complete line read * from the file starting at the current position */static char *readline(FILE *f){	char *buffer = NULL;	int buffer_size = 0;	int pos = 0;	do {		int c;		/* Read a character from the stream */		c = fgetc(f);		/* Is that EOF or new line ? */		if(c == EOF || c == '\n')			break;		/* Do we have to update buffer ? */		if(pos >= buffer_size - 1) {			buffer_size += BUF_SZ;			buffer = (char*)realloc(buffer, buffer_size);			if (buffer == NULL)				return(NULL);		}		buffer[pos] = c;		pos++;	} while(1);	/* Read \n or EOF */	if (buffer == NULL) {		/* EOF, so we reached the end of the file, return NULL */		if(feof(f))			return(NULL);		/* Just an empty line with just a newline, allocate a 1 byte buffer to		 * store a zero length string */		buffer = (char*)malloc(1);		if(buffer == NULL)			return(NULL);	}	/* Zero terminated string */	buffer[pos] = '\0';	return(buffer);}/* This function returns a pointer to the first non space char in the given * string */static char *skipspaces(char *string){	const char spaces[] =		{			' ','\t','\0'		};	const char *spacechar = spaces;	if (string == NULL) return(NULL);	while (*string != '\0') {		/* Test against space chars */		while (*spacechar != '\0') {			if (*string == *spacechar) {				string++;				spacechar = spaces;				break;			}			spacechar++;		}		/* No space char */		if (*spacechar == '\0') return(string);	}	return(string);}/* This function returns a boolean that tells if the string is only a * comment */static intiscomment(char *string){	const char comments[] =		{			'#',';', '%', '\0'		};	const char *cmtchar = comments;	int iscomment = 0;	if (string == NULL) return(1);	string = skipspaces(string);	while(*cmtchar != '\0') {		if(*string == *cmtchar) {			iscomment = 1;			break;		}		cmtchar++;	}	return(iscomment);}#if 0static voidstats_print(rc_2pass2_t * rc){	int i;	const char frame_type[4] = { 'i', 'p', 'b', 's'};	for (i=0; i<rc->num_frames; i++) {		twopass_stat_t *s = &rc->stats[i];		DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- frame:%d type:%c quant:%d stats:%d scaled:%d desired:%d actual:%d overflow(%c):%.2f\n",				i, frame_type[s->type-1], -1, s->length, s->scaled_length,				s->desired_length, -1, frame_type[s->type-1], -1.0f);	}}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -