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

📄 deintl.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
 *      
 * The contents of this file, and the files included with this file, are 
 * subject to the current version of the RealNetworks Public Source License 
 * Version 1.0 (the "RPSL") available at 
 * http://www.helixcommunity.org/content/rpsl unless you have licensed 
 * the file under the RealNetworks Community Source License Version 1.0 
 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
 * in which case the RCSL will apply. You may also obtain the license terms 
 * directly from RealNetworks.  You may not use this file except in 
 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
 * applicable to this file, the RCSL.  Please see the applicable RPSL or 
 * RCSL for the rights, obligations and limitations governing use of the 
 * contents of the file.  
 *  
 * This file is part of the Helix DNA Technology. RealNetworks is the 
 * developer of the Original Code and owns the copyrights in the portions 
 * it created. 
 *  
 * This file, and the files included with this file, is distributed and made 
 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
 * 
 * Technology Compatibility Kit Test Suite(s) Location: 
 *    http://www.helixcommunity.org/content/tck 
 * 
 * Contributor(s): 
 *  
 * ***** END LICENSE BLOCK ***** */ 


////////////////////////////////////////////////////////
//	defines
////////////////////////////////////////////////////////

// Defineing TIME_DEINTERLACE will time the deinterlacer
// and write a file with filename TIME_DEINTERLACE_FILENAME
// with the times.

//#define TIME_DEINTERLACE
//#define TIME_DEINTERLACE_FILENAME "d:\\dintl.log"

////////////////////////////////////////////////////////
//	include files
////////////////////////////////////////////////////////

#include "hlxclib/stdlib.h"
#include "hlxclib/string.h"

#define INTL_I420_CODE

#ifdef TIME_DEINTERLACE
#include "hlxclib/stdio.h"
#endif

#include "mmx_util.h"
#include "deintl.h"


////////////////////////////////////////////////////////
//	internal prototypes
////////////////////////////////////////////////////////

static void
Deinterlace_RGB24(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);

static void
Deinterlace_I420(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);

static void
Deinterlace_RGB24_Fast(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);

static void
Deinterlace_I420_Fast(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);

static void
Deinterlace_I420_Advanced(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);

static void
Deinterlace_I420_EdgeInterp(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);

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

static void
Deinterlace_I420_Field(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format, int field);

static void
Deinterlace_I420_FlipFlop(unsigned char *frame, unsigned char *temp_frame, int pels, int lines, int pitch, int format);

#ifdef _M_IX86

static void
Deinterlace_I420_MMX(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);

#endif

int
C_DetectInterlace_I420(unsigned char *frame, unsigned char *prev_frame, int first_frame, int pels, int lines, int pitch);


////////////////////////////////////////////////////////
//	macros
////////////////////////////////////////////////////////

#define MEDIAN_3(a,b,c)			\
	((a > b)?					\
		(						\
			(b > c)?			\
			(b):				\
			(					\
				(a > c)?		\
				(c):			\
				(a)				\
			)					\
		):						\
		(						\
			(a > c)?			\
			(a):				\
			(					\
				(b > c)?		\
				(c):			\
				(b)				\
			)					\
		))						\

#define MABS(v) (tmp=(v),((tmp)^(tmp>>31)))
#define ABS(a)  (((a) < 0) ? (-(a)) : (a))
#define DIFF_FCN(v) ((v)*(v))		// Squared difference

static const int SQUARED_TAB[255+255+1] = {
    65025,  64516,  64009,  63504,  63001,  62500,
    62001,  61504,  61009,  60516,  60025,  59536,  59049,  58564,  58081,  57600,
    57121,  56644,  56169,  55696,  55225,  54756,  54289,  53824,  53361,  52900,
    52441,  51984,  51529,  51076,  50625,  50176,  49729,  49284,  48841,  48400,
    47961,  47524,  47089,  46656,  46225,  45796,  45369,  44944,  44521,  44100,
    43681,  43264,  42849,  42436,  42025,  41616,  41209,  40804,  40401,  40000,
    39601,  39204,  38809,  38416,  38025,  37636,  37249,  36864,  36481,  36100,
    35721,  35344,  34969,  34596,  34225,  33856,  33489,  33124,  32761,  32400,
    32041,  31684,  31329,  30976,  30625,  30276,  29929,  29584,  29241,  28900,
    28561,  28224,  27889,  27556,  27225,  26896,  26569,  26244,  25921,  25600,
    25281,  24964,  24649,  24336,  24025,  23716,  23409,  23104,  22801,  22500,
    22201,  21904,  21609,  21316,  21025,  20736,  20449,  20164,  19881,  19600,
    19321,  19044,  18769,  18496,  18225,  17956,  17689,  17424,  17161,  16900,
    16641,  16384,  16129,  15876,  15625,  15376,  15129,  14884,  14641,  14400,
    14161,  13924,  13689,  13456,  13225,  12996,  12769,  12544,  12321,  12100,
    11881,  11664,  11449,  11236,  11025,  10816,  10609,  10404,  10201,  10000,
    9801,   9604,   9409,   9216,   9025,   8836,   8649,   8464,   8281,   8100,
    7921,   7744,   7569,   7396,   7225,   7056,   6889,   6724,   6561,   6400,
    6241,   6084,   5929,   5776,   5625,   5476,   5329,   5184,   5041,   4900,
    4761,   4624,   4489,   4356,   4225,   4096,   3969,   3844,   3721,   3600,
    3481,   3364,   3249,   3136,   3025,   2916,   2809,   2704,   2601,   2500,
    2401,   2304,   2209,   2116,   2025,   1936,   1849,   1764,   1681,   1600,
    1521,   1444,   1369,   1296,   1225,   1156,   1089,   1024,   961,    900,
    841,    784,    729,    676,    625,    576,    529,    484,    441,    400,
    361,    324,    289,    256,    225,    196,    169,    144,    121,    100,
    81,     64,     49,     36,     25,     16,     9,      4,      1,      0,
    1,      4,      9,      16,     25,     36,     49,     64,     81,     100,
    121,    144,    169,    196,    225,    256,    289,    324,    361,    400,
    441,    484,    529,    576,    625,    676,    729,    784,    841,    900,
    961,    1024,   1089,   1156,   1225,   1296,   1369,   1444,   1521,   1600,
    1681,   1764,   1849,   1936,   2025,   2116,   2209,   2304,   2401,   2500,
    2601,   2704,   2809,   2916,   3025,   3136,   3249,   3364,   3481,   3600,
    3721,   3844,   3969,   4096,   4225,   4356,   4489,   4624,   4761,   4900,
    5041,   5184,   5329,   5476,   5625,   5776,   5929,   6084,   6241,   6400,
    6561,   6724,   6889,   7056,   7225,   7396,   7569,   7744,   7921,   8100,
    8281,   8464,   8649,   8836,   9025,   9216,   9409,   9604,   9801,   10000,
    10201,  10404,  10609,  10816,  11025,  11236,  11449,  11664,  11881,  12100,
    12321,  12544,  12769,  12996,  13225,  13456,  13689,  13924,  14161,  14400,
    14641,  14884,  15129,  15376,  15625,  15876,  16129,  16384,  16641,  16900,
    17161,  17424,  17689,  17956,  18225,  18496,  18769,  19044,  19321,  19600,
    19881,  20164,  20449,  20736,  21025,  21316,  21609,  21904,  22201,  22500,
    22801,  23104,  23409,  23716,  24025,  24336,  24649,  24964,  25281,  25600,
    25921,  26244,  26569,  26896,  27225,  27556,  27889,  28224,  28561,  28900,
    29241,  29584,  29929,  30276,  30625,  30976,  31329,  31684,  32041,  32400,
    32761,  33124,  33489,  33856,  34225,  34596,  34969,  35344,  35721,  36100,
    36481,  36864,  37249,  37636,  38025,  38416,  38809,  39204,  39601,  40000,
    40401,  40804,  41209,  41616,  42025,  42436,  42849,  43264,  43681,  44100,
    44521,  44944,  45369,  45796,  46225,  46656,  47089,  47524,  47961,  48400,
    48841,  49284,  49729,  50176,  50625,  51076,  51529,  51984,  52441,  52900,
    53361,  53824,  54289,  54756,  55225,  55696,  56169,  56644,  57121,  57600,
    58081,  58564,  59049,  59536,  60025,  60516,  61009,  61504,  62001,  62500,
    63001,  63504,  64009,  64516,  65025
};

#define MSQUARED(v) (SQUARED_TAB[(v) + 255])

// Some thresholds
#define INTL_DIFF_THRESH	40000
#define INTL_HORIZ_THRESH	80

#ifdef TIME_DEINTERLACE
static unsigned int num_avg = 0;
static unsigned int num_med = 0;
#endif


int
InitDeinterlace (
	int pels, int lines, int pitch, 
	int format, 
	INTL_MODE mode, 
	T_DEINTL_STATE **state)
{
	T_DEINTL_STATE *new_state = 0;

	if (*state == 0)
	{
		new_state = (T_DEINTL_STATE *)malloc(sizeof(T_DEINTL_STATE));
	}

	if (new_state == 0)
		return 1;

	new_state->pels = pels;
	new_state->lines = lines;
	new_state->pitch = pitch;
	new_state->format = format;
	new_state->detection_measure = (lines > 242)?(16):(0);
	new_state->commit_deinterlace = FALSE;

	*state = new_state;

	return 0;
}

void
FreeDeinterlace (T_DEINTL_STATE **state)
{
	if (*state != 0)
		free(*state);
	*state = 0;
}

BOOL
IsContentInterlaced (T_DEINTL_STATE *state)
{
	if (state != 0)
		return (state->commit_deinterlace == 1)?(TRUE):(FALSE);

	return FALSE;
}

void
ResetDeinterlace (T_DEINTL_STATE *state)
{
	state->detection_measure = 0;
	state->commit_deinterlace = FALSE;
}


////////////////////////////////////////////////////////
//
//	Deinterlace
//
//	Top level function to deinterlace a video frame
//
//	Parameters:
//		frame:		Pointer to the frame to deinterlace
//		prev_frame:	Pointer to the previous frame.
//					Better results are achieved by giving
//					the previous *interlaced* frame
//		pels,
//		lines,
//		pitch:		Frame dimensions
//		format:		INTL_FORMAT_RGB24 or INTL_FORMAT_I420
//		mode:		Choose either using both fields or
//					to remove one field entirely
//					(see 'deintl.h')
//
////////////////////////////////////////////////////////

int
Deinterlace(
	unsigned char *frame, 
	unsigned char *prev_frame,
	int pels, int lines, int pitch,
	int format,
	int first_frame, 
	INTL_MODE mode,
	T_DEINTL_STATE *state)
{
	if (pels == 0)
		pels = state->pels;
	if (lines == 0)
		lines = state->lines;
	if (pitch == 0)
		pitch = state->pitch;
	if (format == 0)
		format = state->format;

	unsigned char *pfp = (first_frame == TRUE)?(NULL):(prev_frame);

	// Unless were going to do detection first (i.e. in INTL_MODE_SMART_AUTO mode),
	// don't de-interlace when there is less than 242 lines.  This is a little
	// check to prevent unintentional de-interlacing of probable progressive frames.
	if (lines < 242 && mode != INTL_MODE_SMART_AUTO)
		return 0;

	// Run detection
	if (mode == INTL_MODE_SMART_AUTO)
	{
		unsigned char *detection_frame;
		unsigned char *detection_prev_frame;
		int res;

		if (format == INTL_FORMAT_I420)
		{
			// point to the Y-Plane
			detection_frame = frame;
			detection_prev_frame = prev_frame;
		}
		if (format == INTL_FORMAT_RGB24)
		{
			// point to the G-Plane
			detection_frame = frame + pels * lines;
			detection_prev_frame = prev_frame + pels * lines;
		}

		// Perform detection
		res = C_DetectInterlace_I420(
			detection_frame, 
			detection_prev_frame, 
			first_frame, 
			pels, lines, pitch);

		// Update the "detection measure" based on result of detection
		switch (res)
		{
		case INTL_STRONG_INTERLACE:
			{
				state->detection_measure = (31 * state->detection_measure + 256) >> 5;
			}
			break;

		case INTL_WEAK_INTERLACE:
			{
				state->detection_measure = (31 * state->detection_measure + 256) >> 5;
			}
			break;

		case INTL_WEAK_PROGRESSIVE:
			{
				state->detection_measure = (31 * state->detection_measure + 0) >> 5;
			}
			break;

		case INTL_STRONG_PROGRESSIVE:
			{
				state->detection_measure = 0;
			}
			break;
		}

		// If the detection measure is above a threshold, set this flag used
		// to indicate we are confident the content is interlaced.
		if (state->detection_measure > 128)
		{
			state->commit_deinterlace = TRUE;
		}

		// If the detection measure is above this threshold, we should
		// de-interlace this frame. Otherwise, return without de-interlacing
		if (state->detection_measure > 16)
		{
			mode = INTL_MODE_SMART;
		}
		else
		{
			return 0;
		}
	}

#ifdef TIME_DEINTERLACE
	FILE *fp = NULL;
	double proc_time;

	USE_CODEC_TIMER;

	num_avg = 0;
	num_med = 0;

	START_CODEC_TIMER;
#endif

	switch (format)
	{

#ifdef INTL_RBG24_CODE
	case INTL_FORMAT_RGB24:
		Deinterlace_RGB24_Fast(frame, pfp, pels, lines, pitch, format);
		break;
#endif

#ifdef INTL_I420_CODE

	case INTL_FORMAT_I420:

#ifdef USE_MMX_DEINTERLACING		//_M_IX86
        if (checkMmxAvailablity() & CPU_HAS_MMX)
			Deinterlace_I420_MMX(frame, pfp, pels, lines, pitch, format);
		else
#endif
		// Neelesh's new deinterlacer.
		Deinterlace_I420_Advanced(frame, pfp, pels, lines, pitch, format);

		break;

#endif
	}

#ifdef TIME_DEINTERLACE
	STOP_CODEC_TIMER(proc_time);
	
	fp = fopen(TIME_DEINTERLACE_FILENAME,"a+");
	if (fp != NULL)
	{
		fprintf(fp,"deinterlace time\t%f\t%d\t%d\n",proc_time,num_avg,num_med);
		fclose(fp);
	}
#endif

	return 1;
}


////////////////////////////////////////////////////////
//
//	C_DetectInterlace_I420
//
//	Top level function to detect the presense of 
//	interlaced video content
//
//	Parameters:
//		frame:		Pointer to the frame to deinterlace
//		prev_frame:	Pointer to the previous frame.
//		pels,
//		lines,
//		pitch:		Frame dimensions
//
////////////////////////////////////////////////////////

// Threshold: If 8x8 SAD is above MOVEMENT_THRESH then
// we'll decide that the block is in motion
#define MOVEMENT_THRESH (400)

// This is the factor by which 8x8 are skipped (not checked).
// SKIP_FACTOR = 1 means no skipping.
#define SKIP_FACTOR 4

#ifdef DEBUG
// This increments with each call, 
// and is useful for debugging a specific frame.
static unsigned int call_count = 0;
#endif

int
C_DetectInterlace_I420(
	unsigned char *frame, 
	unsigned char *prev_frame, 
	int first_frame, 
	int pels, int lines, int pitch)
{
	unsigned int image_size = (unsigned int)(pels * lines);
		// pre-calculated image size used for determining thresholds

	unsigned int interlaced_blocks = 0;			
		// count of the number of 8x8 blocks that look to be interlaced

	unsigned int progressive_blocks = 0;
		// count of the number of 8x8 blocks that look to be progressive

	unsigned int step1v_tot = 0;
		// running total of the 1-step squared vertical difference of pixels

	unsigned int step2v_tot = 0;
		// running total of the 2-step squared vertical difference of pixels

	unsigned int step1h_tot = 0;
		// running total of the 1-step squared horizontal difference of pixels

	unsigned int step2h_tot = 0;
		// running total of the 2-step squared horizontal difference of pixels

	unsigned char *fp, *pp;
	unsigned char *f0, *f1, *f2, *f3;
		// various temporary frame pointers

	int i, j, k;	// loop counter	
	int tmp;		// intermediate values for correlation and SAD macro
	int d0, d1;		// SAD counters

#ifdef DEBUG
	call_count++;
#endif

	// We have no detection scheme for the first frame yet.
	if (first_frame)
	{
		return INTL_NO_DETECTION;
	}

	// Loop through tiled 8x8 blocks of the image
	for (i = 8; i < lines - 8; i += 8)
	{
		// Start pointer at new line
		fp = frame + i * pitch + (i & (8*(SKIP_FACTOR - 1))) + 8;
		pp = prev_frame + i * pitch + (i &  (8*(SKIP_FACTOR - 1))) + 8;

		for (j = 8; j < pels - 8; j += 8 * SKIP_FACTOR)
		{
			f0 = fp;
			f1 = f0 + pitch;
			f2 = pp;
			f3 = f2 + pitch;

			d0 = d1 = 0;

			// Calculate SAD for even and odd lines of 8x8 block.
			// We're doing a partial SAD here for speed.
			for (k = 0; k < 4; k++)
			{
				d0 += MABS(f0[0] - f2[0]);
				d0 += MABS(f0[2] - f2[2]);
				d0 += MABS(f0[4] - f2[4]);
				d0 += MABS(f0[6] - f2[6]);
				d1 += MABS(f1[1] - f3[1]);
				d1 += MABS(f1[3] - f3[3]);
				d1 += MABS(f1[5] - f3[5]);
				d1 += MABS(f1[7] - f3[7]);

				f0 += 2 * pitch;
				f1 += 2 * pitch;
				f2 += 2 * pitch;
				f3 += 2 * pitch;
			}
			d0 <<= 1;
			d1 <<= 1;
			
			// If there is enough difference to determine movement,
			// check this region for indications of interlaced artifacts
			if (d0 > MOVEMENT_THRESH || d1 > MOVEMENT_THRESH)
			{
				int step1v_corr = 0;
				int step2v_corr = 0;
				int step1h_corr = 0;
				int step2h_corr = 0;

				f0 = fp;
				f1 = f0 + pitch;
				f2 = f1 + pitch;

				// Determine 1 and 2 step pixel differences for 8x8 region
				for (k = 0; k < 4; k++)
				{
					tmp = f0[1] - f1[1];
					step1v_corr += MSQUARED(tmp);
					tmp = f0[1] - f2[1];
					step2v_corr += MSQUARED(tmp);
					tmp = f1[0] - f1[1];
					step1h_corr += MSQUARED(tmp);
					tmp = f1[0] - f1[2];
					step2h_corr += MSQUARED(tmp);

					tmp = f0[3] - f1[3];
					step1v_corr += MSQUARED(tmp);
					tmp = f0[3] - f2[3];
					step2v_corr += MSQUARED(tmp);
					tmp = f1[2] - f1[3];
					step1h_corr += MSQUARED(tmp);
					tmp = f1[2] - f1[4];
					step2h_corr += MSQUARED(tmp);

					tmp = f0[5] - f1[5];
					step1v_corr += MSQUARED(tmp);
					tmp = f0[5] - f2[5];

⌨️ 快捷键说明

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