deintl.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 2,337 行 · 第 1/4 页

CPP
2,337
字号

			tmp = c_ne + c_se - c_nw - c_sw;
			if (tmp > 100)
			{
				next_mode = INTL_LINE_REMOVE_AVG;
				goto proc;
			}
			if (tmp < -100)
			{
				next_mode = INTL_LINE_REMOVE_AVG;
				goto proc;
			}

			// Load previous pels
			d = ((unsigned int *)pfp1)[1];
			e = ((unsigned int *)pfp2)[1];
			f = ((unsigned int *)pfp3)[1];

			// Diff with previous pels
			tmp = c_nw;
			tmp -= (d >> 24);
			diff = tmp ^ (tmp >> 31);

			tmp = c_ne;
			tmp -= (d & 0xff);
			diff += tmp ^ (tmp >> 31);

			if (diff > 100)
			{
				next_mode = INTL_LINE_REMOVE_AVG;
				goto proc;
			}

			tmp = c_sw;
			tmp -= (f >> 24);
			diff += tmp ^ (tmp >> 31);

			tmp = c_se;
			tmp -= (f & 0xff);
			diff += tmp ^ (tmp >> 31);

			if (diff > 200)
			{
				next_mode = INTL_LINE_REMOVE_AVG;
				goto proc;
			}

			tmp = (b >> 24);
			tmp -= (e >> 24);
			diff += tmp ^ (tmp >> 31);
			tmp = (b & 0xff);
			tmp -= (e & 0xff);
			diff += tmp ^ (tmp >> 31);

			if (diff > 300)
			{
				next_mode = INTL_LINE_REMOVE_AVG;
				goto proc;
			}

			next_mode = INTL_LINE_REMOVE_MEDIAN;

proc:
			if (mode == INTL_LINE_REMOVE_MEDIAN || prev_mode == INTL_LINE_REMOVE_MEDIAN || next_mode == INTL_LINE_REMOVE_MEDIAN)
			{
				// median
				fp2[0] = MEDIAN_3(fp1[0],fp2[0],fp3[0]);
				fp2[1] = MEDIAN_3(fp1[1],fp2[1],fp3[1]);
				fp2[2] = MEDIAN_3(fp1[2],fp2[2],fp3[2]);
				fp2[3] = MEDIAN_3(fp1[3],fp2[3],fp3[3]);

#ifdef TIME_DEINTERLACE
				num_med++;
#endif

			}
			else
			{
				// average
				a = ((unsigned int *)fp1)[0];
				c = ((unsigned int *)fp3)[0];
				((unsigned int*)fp2)[0] = (((a^c)>>1) & 0x7F7F7F7F) + (a&c);

#ifdef TIME_DEINTERLACE
				num_avg++;
#endif
			}

			prev_mode = mode;
			mode = next_mode;

			fp1 += 4;
			fp2 += 4;
			fp3 += 4;

			pfp1 += 4;
			pfp2 += 4;
			pfp3 += 4;
		}

		// last 4 pels
		if (mode == INTL_LINE_REMOVE_MEDIAN || prev_mode == INTL_LINE_REMOVE_MEDIAN)
		{
			// median
			fp2[0] = MEDIAN_3(fp1[0],fp2[0],fp3[0]);
			fp2[1] = MEDIAN_3(fp1[1],fp2[1],fp3[1]);
			fp2[2] = MEDIAN_3(fp1[2],fp2[2],fp3[2]);
			fp2[3] = MEDIAN_3(fp1[3],fp2[3],fp3[3]);

#ifdef TIME_DEINTERLACE
			num_med++;
#endif

		}
		else
		{
			// average
			a = ((unsigned int *)fp1)[0];
			c = ((unsigned int *)fp3)[0];
			((unsigned int*)fp2)[0] = (((a^c)>>1) & 0x7F7F7F7F) + (a&c);

#ifdef TIME_DEINTERLACE
			num_avg++;
#endif
		}
	}
}

////////////////////////////////////////////////////////
//
//	Deinterlace_I420_Advanced
//
//	Slow deinterlacing of I420 data, using Edge Interpolation
//
////////////////////////////////////////////////////////

void
Deinterlace_I420_Advanced(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format)
{
	int line, pel;
	unsigned char *fpy, *pfpy;
	unsigned char *fp1, *pfp1;
	unsigned char *fp2, *pfp2;
	unsigned char *fp3, *pfp3;
	
	int edge1, edge2, pedge1, pedge2, diff1, diff2;
	unsigned int a, c;

	int tmp, pitch2;
	pitch2= pitch<<1;

	for (line = 1; line < lines - 2; line += 2)
	{
	
		fpy = frame + line*pitch;				
		
		// current frame
		// current line
		fp2 = fpy;
		// prev line
		fp1 = fp2 - pitch;
		// next line
		fp3 = fp2 + pitch;
		// current frame

		// previous frame
		if (prev_frame != 0)
		{
			pfpy = prev_frame + line * pitch;
			pfp2 = pfpy;
			pfp1 = pfp2 - pitch;
			pfp3 = pfp2 + pitch;
		}
		else
		{			
			pfp2 = fp2;
			pfp1 = fp1;
			pfp3 = fp3;
		}
				
		// handle first pel
		tmp = (*fp1 + *fp3) >> 1;
		*fp2 = (unsigned char) tmp;
		fp1++;
		fp2++;
		fp3++;
		pfp1++;

		edge1 = (*fp1) + *(fp1+1) +*(fp1+2);
		edge2=  (*fp3) + *(fp3+1) +*(fp3+2);
				
		for (pel = 1; pel < pels-4; pel += 1)
		{					
			edge1+=*(fp1+3);
			edge2+=*(fp3+3);
			tmp = (edge1 - edge2);

			if( tmp > 160 || tmp < -160) {
				// horiz
				pfp3 = pfp1 + pitch2;
				pedge1= *pfp1 + *(pfp1+1) + *(pfp1+2) + *(pfp1+3);
				pedge2= *pfp3 + *(pfp3+1) + *(pfp3+2) + *(pfp3+3);				
				
				diff1 = (edge1 - pedge1);				
				if (diff1 < 0) diff1=-(diff1);
				//diff1 = ABS(diff1);
				diff2 = (edge2  - pedge2);
				if (diff2 < 0) diff2=-(diff2);
				//diff2 = ABS(diff2);

				if ((diff1 + diff2) < 200) {
					// not moving					
					*fp2 = MEDIAN_3(*fp1,*fp2,*fp3);
					*(fp2+1) = MEDIAN_3(*(fp1+1),*(fp2+1),*(fp3+1));
					
#ifdef TIME_DEINTERLACE
						num_med++;
#endif				
					edge1 -= *fp1;
					edge2 -= *fp3;					
					fp1++;
					fp2++;
					fp3++;
					pfp1++;					
					pel++;
					edge1+=*(fp1+3);
					edge2+=*(fp3+3);					
				} else {		
					tmp = *(fp2-1) + *fp1 + *fp3;	
					tmp *= 21845;
					*fp2 = 	(unsigned char) (tmp >> 16);
					//tmp = (*(fp2-1)<<1) + *fp1 + *fp3;	
					//*fp2 = 	(unsigned char) (tmp >> 2);
#ifdef TIME_DEINTERLACE
						num_avg++;
#endif									
				}	
			} else {
				// not horiz				
				// average
				tmp = (*fp1 + *fp3) >> 1;
				*fp2 = (unsigned char) tmp;
				
#ifdef TIME_DEINTERLACE
					num_avg++;
#endif				
			}			
			edge1 -= (*fp1);
			edge2 -= (*fp3);					
			fp1++;
			fp2++;
			fp3++;
			pfp1++;			
		}
		// handle last four pels
		// last 4 pels
		pfp3 = pfp1 + pitch2;
		pedge1= *pfp1 + *(pfp1+1) + *(pfp1+2) + *(pfp1+3);
		pedge2= *pfp3 + *(pfp3+1) + *(pfp3+2) + *(pfp3+3);		
			
		diff1 = (edge1 - pedge1);
		diff1 = ABS(diff1);
		diff2 = (edge2  - pedge2);
		diff2 = ABS(diff2);
		if ((diff1 + diff2) < 200) {
					// not moving					
					// median
				fp2[0] = MEDIAN_3(fp1[0],fp2[0],fp3[0]);
				fp2[1] = MEDIAN_3(fp1[1],fp2[1],fp3[1]);
				fp2[2] = MEDIAN_3(fp1[2],fp2[2],fp3[2]);
				fp2[3] = MEDIAN_3(fp1[3],fp2[3],fp3[3]);

#ifdef TIME_DEINTERLACE
					num_med++;
#endif
		}
		else
		{
			// average
			a = ((unsigned int *)fp1)[0];
			c = ((unsigned int *)fp3)[0];
			((unsigned int*)fp2)[0] = (((a^c)>>1) & 0x7F7F7F7F) + (a&c);

#ifdef TIME_DEINTERLACE
				num_avg++;
#endif
		}
	}
	
}	


////////////////////////////////////////////////////////
//
//	Deinterlace_I420
//
//	Slow deinterlacing of I420 data, using both fields
//
////////////////////////////////////////////////////////

static void
Deinterlace_I420(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format)
{
	int line, pel;
	unsigned char *fp1,*pfp1;			// line above
	unsigned char *fp2,*pfp2;			// current line
	unsigned char *fp3,*pfp3;			// line below
	int tmp;

	// Only handle RGB for now...
	if (format != INTL_FORMAT_I420)
		return;

	for (line = 1; line < lines - 2; line += 2)
	{
		int a,b,c,d,e;
		int mode = INTL_LINE_REMOVE_AVG;

		// set pointers
		fp1 = frame + (line - 1) * pitch;
		fp2 = fp1 + pitch;
		fp3 = fp2 + pitch;

		if (prev_frame != 0)
		{
			pfp2 = prev_frame + line * pitch;
			pfp1 = pfp1 - pitch;
			pfp3 = pfp2 + pitch;
		}
		else
		{
			pfp2 = fp2;
			pfp1 = fp1;
			pfp3 = fp3;
		}

		// initialize
		// a
		tmp = (int)(*fp1++);
		tmp -= (int)(*pfp1++);
		a = DIFF_FCN(tmp);
		tmp = (int)(*fp2++);
		tmp -= (int)(*pfp2++);
		a += DIFF_FCN(tmp);
		tmp = (int)(*fp3++);
		tmp -= (int)(*pfp3++);
		a += DIFF_FCN(tmp);

		// b
		tmp = (int)(*fp1++);
		tmp -= (int)(*pfp1++);
		b = DIFF_FCN(tmp);
		tmp = (int)(*fp2++);
		tmp -= (int)(*pfp2++);
		b += DIFF_FCN(tmp);
		tmp = (int)(*fp3++);
		tmp -= (int)(*pfp3++);
		b += DIFF_FCN(tmp);

		// c
		tmp = (int)(*fp1);
		tmp -= (int)(*pfp1);
		c = DIFF_FCN(tmp);
		tmp = (int)(*fp2);
		tmp -= (int)(*pfp2);
		c += DIFF_FCN(tmp);
		tmp = (int)(*fp3);
		tmp -= (int)(*pfp3);
		c += DIFF_FCN(tmp);

		// d
		tmp = (int)(fp1[1]);
		tmp -= (int)(pfp1[1]);
		d = DIFF_FCN(tmp);
		tmp = (int)(fp2[1]);
		tmp -= (int)(pfp2[1]);
		d += DIFF_FCN(tmp);
		tmp = (int)(fp3[1]);
		tmp -= (int)(pfp3[1]);
		d += DIFF_FCN(tmp);

		for (pel = 2; pel < pels - 2; pel++)
		{
			// e
			tmp = (int)(fp1[2]);
			tmp -= (int)(pfp1[2]);
			e = DIFF_FCN(tmp);
			tmp = (int)(fp2[2]);
			tmp -= (int)(pfp2[2]);
			e += DIFF_FCN(tmp);
			tmp = (int)(fp3[2]);
			tmp -= (int)(pfp3[2]);
			e += DIFF_FCN(tmp);

			// should we switch line removal mode?
			if (mode == INTL_LINE_REMOVE_MEDIAN)
			{
				if (a + b + c + d + e > INTL_DIFF_THRESH)
				{
					a =  MABS(fp1[-2] - fp1[+1]);
					a += MABS(fp3[-2] - fp3[+1]);
					a += MABS(fp1[-1] - fp1[+2]);
					a += MABS(fp3[-1] - fp3[+2]);
					a <<= 1;
					a += MABS(fp1[-2] - fp3[-2]);
					a += MABS(fp1[-1] - fp3[-1]);
					a += MABS(fp1[+1] - fp3[+1]);
					a += MABS(fp1[+2] - fp3[+2]);
					if (a > 0)
					{
						mode = INTL_LINE_REMOVE_AVG;
					}
				}
			}
			else
			{
				if (a + b + c + d + e < INTL_DIFF_THRESH)
				{
					a =  MABS(fp1[-2] - fp1[+1]);
					a += MABS(fp3[-2] - fp3[+1]);
					a += MABS(fp1[-1] - fp1[+2]);
					a += MABS(fp3[-1] - fp3[+2]);
					a <<= 1;
					a += MABS(fp1[-2] - fp3[-2]);
					a += MABS(fp1[-1] - fp3[-1]);
					a += MABS(fp1[+1] - fp3[+1]);
					a += MABS(fp1[+2] - fp3[+2]);
					if (a < 0)
					{
						mode = INTL_LINE_REMOVE_MEDIAN;
					}
				}
			}
				
			if (mode == INTL_LINE_REMOVE_MEDIAN)
			{
				// median
				fp2[0] = MEDIAN_3(fp1[0],fp2[0],fp3[0]);
			}
			else
			{
				// average
				tmp = fp1[0];
				tmp += fp3[0];
				fp2[0] = (tmp >> 1);
			}
			
			// shift difference measures
			a = b;
			b = c;
			c = d;
			d = e;

			// move pointers
			fp1++;pfp1++;
			fp2++;pfp2++;
			fp3++;pfp3++;

		}
	}
}



////////////////////////////////////////////////////////
//
//	Deinterlace_RGB24_Field
//
//	Replaces 'frame' with only one field.
//  The result is an image with dimesions pels x lines/2
//
////////////////////////////////////////////////////////

static void
Deinterlace_RGB24_Field(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format, int field)
{
	int line;
	unsigned char *in,*out;

	lines >>= 1;

	// R
	in  = frame + field * pitch;
	out = frame;
	for (line = field; line < lines; line++)
	{
		memcpy(out, in, pels); /* Flawfinder: ignore */
		out += pitch;
		in  += (pitch << 1);
	}

	// G
	in  = frame + pels * (lines << 1);
	out = frame + pels * lines;
	for (line = 0; line < lines; line++)
	{
		memcpy(out, in, pels); /* Flawfinder: ignore */
		out += pitch;
		in  += (pitch << 1);
	}

	// B
	in  = frame + pels * (lines << 1) * 2;
	out = frame + pels * lines * 2;
	for (line = 0; line < lines; line++)
	{
		memcpy(out, in, pels); /* Flawfinder: ignore */
		out += pitch;
		in  += (pitch << 1);
	}
}



////////////////////////////////////////////////////////
//
//	Deinterlace_I420_Field
//
//	Replaces 'frame' with only one field.
//  The result is an image with dimesions pels x lines/2
//
////////////////////////////////////////////////////////

static void
Deinterlace_I420_Field(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format, int field)
{
	register int line;
	register unsigned char *in,*out;
	int in_pitch;
	int out_pitch;
	int out_lines;

	// Y
	in_pitch = (pitch << 1);
	out_pitch = pitch;
	out_lines = (lines >> 1) & ~3;

	in  = frame + field * pitch;
	out = frame;
	for (line = 0; line < out_lines; line++)
	{
		memcpy(out, in, pels); /* Flawfinder: ignore */
		out += out_pitch;
		in  += in_pitch;
	}

	pels >>= 1;
	lines >>= 1;
	in_pitch >>= 1;
	out_pitch >>= 1;
	out_lines >>= 1;

	// U
	in  = frame + ((pels * lines) << 2);
	out = frame + ((pels * out_lines) << 2);
	for (line = 0; line < out_lines; line++)
	{
		memcpy(out, in, pels); /* Flawfinder: ignore */
		out += out_pitch;
		in  += in_pitch;
	}

	// V
	in  = frame + pels * lines * 5;
	out = frame + pels * out_lines * 5;
	for (line = 0; line < out_lines; line++)
	{
		memcpy(out, in, pels); /* Flawfinder: ignore */
		out += out_pitch;
		in  += in_pitch;
	}
}



////////////////////////////////////////////////////////
//
//	Deinterlace_I420_FlipFlop
//
//	The Odd field is put at the top of the frame,
//  the Even field is put up-side-down at the bottom.
//
////////////////////////////////////////////////////////

static void

⌨️ 快捷键说明

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