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

📄 invtelec.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		state->frameRemovalPattern = (PULLDOWN_HIST_LEN-1)%5;
#ifdef CODEC_DEBUG_32PULLDOWN
		fprintf(fp_log,"things look interlaced, pulldown timer is %d, patternStart is %d\n",state->ulPulldownActiveTimerProg,patternStart);
#endif
		state->lastRemovedTimestamp = timestamp;
		goto REMOVE_FRAME;
	}

	// Otherwise no pulldown!
#ifdef CODEC_DEBUG_32PULLDOWN
	fprintf(fp_log,"no pattern, pulldown timer is %d, patternStart is %d\n",state->ulPulldownActiveTimerProg,patternStart);
#endif

	if((inMax[(PULLDOWN_HIST_LEN-1)%5] > 30) || (outMax[(PULLDOWN_HIST_LEN-1)%5] >30))
		if (state->ulPulldownActiveTimerProg > 0)
			state->ulPulldownActiveTimerProg--;

NO_PATTERN:

	// If there was no clear pattern, do nothing
	state->checkNextFrameForProgressive = FALSE;
	return INVTELE_RESULT_NO_PATTERN;

INTERLEAVE_ODD:

	state->checkNextFrameForProgressive = FALSE;

	// Test if data should be re-interleaved.
	// Look at cross difference of old vs. re-stitched. Only replace if better
	if (obviousPatternFlag == FALSE || sceneChangeFlag == TRUE)
	{
		switch (state->impl_id)
		{
#ifdef ALLOW_MMX_INVTELE
		case INVTELE_IMPL_ID_MMX:
			{
				RestitchCheck_MMX(data, prevData, 
					pels, lines, pels, &sumOld, &sumNew);
			}
			break;
#endif
		case INVTELE_IMPL_ID_C:
		default:
			{
				pNew = (LONG32 *)(data);
				pOld = (LONG32 *)(prevData);
				for (i = 0; i < lines; i += 2)  //  only do the luma.
				{
					for(j = 0; j < ll; j++)
					{
						temp = (float)((pNew[j]&0xff00) - (pNew[j+ll]&0xff00));
						sumOld += (temp*temp);
						temp = (float)((pNew[j]&0xff00) - (pOld[j+ll]&0xff00));
						sumNew += (temp*temp);
					}
					pOld += 2*ll;
					pNew += 2*ll;
				}
			}
			break;
		}

		if (sumNew > sumOld)
		{
			return INVTELE_RESULT_FRAME_OK;
		}
	}

	state->interleaveOddFlag = TRUE;

#ifdef CODEC_DEBUG_32PULLDOWN
	fprintf(fp_log,"interleaving odd\n");
#endif

	// Re-interleave
	pNew = ((LONG32 *)data)+ll;
	pOld = ((LONG32 *)prevData)+ll;

	for (k = 1; k < lines; k += 2)  //  only do the luma.
	{
		memcpy(pNew,pOld,sizeof(ULONG32)*ll); /* Flawfinder: ignore */
		pOld+=2*ll;
		pNew+=2*ll;
	}

	return INVTELE_RESULT_FRAME_OK;

INTERLEAVE_EVEN:

	state->checkNextFrameForProgressive = FALSE;

	// Test if data should be re-interleaved.
	// Look at cross difference of old vs. re-stitched. Only replace if better

	if (obviousPatternFlag == FALSE || sceneChangeFlag == TRUE)
	{
		switch (state->impl_id)
		{
#ifdef ALLOW_MMX_INVTELE
		case INVTELE_IMPL_ID_MMX:
			{
				RestitchCheck_MMX(data + pels, prevData + pels, 
					pels, lines - 2, pels, &sumOld, &sumNew);
			}
			break;
#endif
		case INVTELE_IMPL_ID_C:
		default:
			{
				pNew = (LONG32 *)(data);
				pOld = (LONG32 *)(prevData);
				for (i = 0; i < lines; i += 2)  //  only do the luma.
				{
					for(j = 0; j < ll; j++)
					{
						temp = (float)((pNew[j]&0xff00) - (pNew[j+ll]&0xff00));
						sumOld += (temp*temp);
						temp = (float)((pNew[j+ll]&0xff00) - (pOld[j]&0xff00));
						sumNew += (temp*temp);
					}
					pOld+=2*ll;
					pNew+=2*ll;
				}
			}
			break;
		}

		if (sumNew > sumOld)
		{
			return INVTELE_RESULT_FRAME_OK;
		}
	}

	state->interleaveEvenFlag = TRUE;

#ifdef CODEC_DEBUG_32PULLDOWN
	fprintf(fp_log,"interleaving even\n");
#endif
	
	// Re-interleave
	pNew = ((LONG32 *)data);
	pOld = ((LONG32 *)prevData);

	for (k = 0; k < lines; k += 2)  //  only do the luma.
	{
		memcpy(pNew,pOld,sizeof(ULONG32)*ll); /* Flawfinder: ignore */
		pOld+=2*ll;
		pNew+=2*ll;
	}

	return INVTELE_RESULT_FRAME_OK;

DO_NOTHING:

	// One final check in this case
	// If we are here, we think the frame is progressive.
	// If we think the previous frame was also progressive, then
	// the odd and even SADs should be somewhat similar.  If not,
	// we're in trouble.

	if (state->checkNextFrameForProgressive)
	{
		if (state->ulPulldownActiveTimerProg < 10 &&
			state->ulPulldownActiveTimerIntl > 90 &&
			(sumEven > 8 * sumOdd || sumOdd > 8 * sumEven))
		{
			goto NO_PATTERN;
		}

		if (sceneChangeFlag == TRUE)
		{
			// Just return here because we want to be sure
			// state->checkNextFrameForProgressive is TRUE
			return INVTELE_RESULT_NO_PATTERN;
		}
	}

	state->checkNextFrameForProgressive = TRUE;

	return INVTELE_RESULT_FRAME_OK;

REMOVE_FRAME:

#ifdef CODEC_DEBUG_32PULLDOWN
	fprintf(fp_log,"removing frame\n");
#endif

	state->checkNextFrameForProgressive = FALSE;

	return INVTELE_RESULT_DROP_FRAME;

TOO_EARLY:

	state->checkNextFrameForProgressive = FALSE;

	return INVTELE_RESULT_TOO_EARLY;

}

// Platform specific SSD functions

#ifdef ALLOW_MMX_INVTELE

void
SumSqaredFrameDiff_MMX(
	unsigned char *frame, 
	unsigned char *prev_frame,
	int pels,
	int lines,
	int pitch,
	float *ssd_odd,
	float *ssd_even)
{
	unsigned int res_odd[2];
	unsigned int res_even[2];

	float pel_avg;

	const unsigned int mask[2] = {0x00FF00FF, 0x00FF00FF};
	int line_shift;
	int pels_div8;

	pels_div8 = (pels >> 3);			// round down
	line_shift = ((pitch) - (pels & ~7));

	__asm {

		mov			ecx, lines			// ecx -> lines		
		shr			ecx, 1				// ecx -> lines/2

		mov			esi, frame			// esi -> current frame
		mov			edi, prev_frame		// edi -> previous frame

		movq		mm5, [mask]
		pxor		mm6, mm6			// mm6 -> odd ssd
		pxor		mm7, mm7			// mm7 -> even ssd

ALIGN 16
line_loop:
		mov			ebx, pels_div8		// ebx -> pels/8 (rounded down)
ALIGN 16
pel_loop_even:
		movq		mm0,[esi]
		movq		mm1,[edi]

		pand		mm0, mm5
		pand		mm1, mm5

		psubw		mm0, mm1
		pmaddwd		mm0, mm0
		paddd		mm6, mm0

		lea			esi,[esi+8]		
		lea			edi,[edi+8]		

		dec			ebx
		jnz			pel_loop_even

		add			esi, line_shift;	// move esi to the next line
		add			edi, line_shift;	// move edi to the next line

		mov			ebx, pels_div8		// ebx -> pels/8 (rounded down)
ALIGN 16
pel_loop_odd:
		movq		mm0,[esi]
		movq		mm1,[edi]

		pand		mm0, mm5
		pand		mm1, mm5

		psubw		mm0, mm1
		pmaddwd		mm0, mm0
		paddd		mm7, mm0

		lea			esi,[esi+8]		
		lea			edi,[edi+8]		

		dec			ebx
		jnz			pel_loop_odd

		add			esi, line_shift;	// move esi to the next line
		add			edi, line_shift;	// move edi to the next line

		dec			ecx
		jnz			line_loop

		movq		res_odd, mm6
		movq		res_even, mm7

		emms
	}

	// fill "even" result
	pel_avg = (float)(res_even[0] + res_even[1]);
	pel_avg /= (float)((pels*lines)>>2);
	*ssd_even = pel_avg;

	// fill "odd" result
	pel_avg = (float)(res_odd[0] + res_odd[1]);
	pel_avg /= (float)((pels*lines)>>2);
	*ssd_odd = pel_avg;

}

void
RestitchCheck_MMX(
	unsigned char *frame, 
	unsigned char *prev_frame,
	int pels,
	int lines,
	int pitch,
	float *ssd_new,
	float *ssd_old)
{
	unsigned int res_new[2];
	unsigned int res_old[2];

	const unsigned int mask[2] = {0x00FF00FF, 0x00FF00FF};
	int line_shift;
	int pels_div8;

	pels_div8 = (pels >> 3);			// round down
	line_shift = ((pitch << 1) - (pels & ~7));

	__asm {

		mov			ecx, lines			// ecx -> lines		
		shr			ecx, 1				// ecx -> lines/2

		mov			esi, frame			// esi -> current frame
		mov			edi, prev_frame		// edi -> previous frame

		mov			edx, pitch			// pitch
		lea			edi, [edi+edx]		// edi -> previous frame + pitch

		movq		mm5, [mask]
		pxor		mm6, mm6			// mm6 -> odd ssd
		pxor		mm7, mm7			// mm7 -> even ssd

ALIGN 16
line_loop:
		mov			ebx, pels_div8		// ebx -> pels/8 (rounded down)
ALIGN 16
pel_loop:
		movq		mm0,[esi]
		movq		mm1,[esi + edx]
		movq		mm2,[edi]

		pand		mm0, mm5
		pand		mm1, mm5
		pand		mm2, mm5

		psubw		mm1, mm0
		pmaddwd		mm1, mm1
		paddd		mm6, mm1

		psubw		mm2, mm0
		pmaddwd		mm2, mm2
		paddd		mm7, mm2

		lea			esi, [esi+8]		
		lea			edi, [edi+8]		

		dec			ebx
		jnz			pel_loop

		add			esi, line_shift		// move esi down 2 lines
		add			edi, line_shift		// move edi down 2 lines

		dec			ecx
		jnz			line_loop

		movq		res_new, mm6
		movq		res_old, mm7

		emms
	}

	// fill "new" result
	*ssd_new = (float)(res_new[0] + res_new[1]);

	// fill "old" result
	*ssd_old = (float)(res_old[0] + res_old[1]);

}

#endif





















⌨️ 快捷键说明

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