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

📄 tdeinterlace.cpp

📁 the De-interlace video processing developed with C++ enviroment in Motion adaptive in 3D and Bi-indi
💻 CPP
字号:
/*
**                TDeinterlace v1.0b4 for AviSynth 2.5.x
**
**   TDeinterlace is a bi-directionally motion adaptive deinterlacer.
**   It also uses a couple modified forms of ela interpolation which 
**   help to reduce "jaggy" edges in places where interpolation must 
**   be used. TDeinterlace currently supports YV12 and YUY2 colorspaces.
**   
**   Copyright (C) 2004-2005 Kevin Stone
**
**   This program is free software; you can redistribute it and/or modify
**   it under the terms of the GNU General Public License as published by
**   the Free Software Foundation; either version 2 of the License, or
**   (at your option) any later version.
**
**   This program is distributed in the hope that it will be useful,
**   but WITHOUT ANY WARRANTY; without even the implied warranty of
**   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**   GNU General Public License for more details.
**
**   You should have received a copy of the GNU General Public License
**   along with this program; if not, write to the Free Software
**   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "TDeinterlace.h"

PVideoFrame __stdcall TDeinterlace::GetFrame(int n, IScriptEnvironment* env)
{
	if (n < 0) n = 0;
	else if (mode == 0 && n > nfrms) n = nfrms;
	else if (mode == 1 && n > nfrms2) n = nfrms2;
	if (vi.IsYV12()) return(GetFrameYV12(n, env));
	else return(GetFrameYUY2(n, env));
}

int TDeinterlace::getHint(PVideoFrame &src, unsigned int &storeHint, int &hintField)
{
	hintField = -1;
	const unsigned char *p = src->GetReadPtr(PLANAR_Y);
	unsigned int i, magic_number = 0, hint = 0;
	storeHint = 0xFFFFFFFF;
	for (i=0; i<32; ++i)
	{
		magic_number |= ((*p++ & 1) << i);
	}
	if (magic_number != 0xdeadbeef && magic_number != 0xdeadfeed) return -1;
	for (i=0; i<32; ++i)
	{
		hint |= ((*p++ & 1) << i);
	}
	if (magic_number == 0xdeadbeef && hint&0xFFFFFF00) return -1;
	if (magic_number == 0xdeadfeed && hint&0xFFFFFF00) return -1;
	storeHint = hint;
	if (magic_number == 0xdeadbeef)
	{
		storeHint |= 0x00100000;
		if (hint&0x00000001) return 0;
		return 1;
	}
	if (hint&0x00000008) hintField = 1;
	else hintField = 0;
	if (hint&0x00000010) return 1;
	return 0;
}

void TDeinterlace::putHint(PVideoFrame &src, unsigned int hint, int fieldt)
{
	int type = hint&0x00100000 ? 0 : 1;
	hint &= ~0x00100000;
	if (hint&0xFFFFFF00) return;
	if (type == 1)
	{
		hint &= 0x00000020;
		if (fieldt == 1) hint |= 0x0000000E;
		else hint |= 0x00000005;
	}
	unsigned char *p = src->GetWritePtr(PLANAR_Y);
	unsigned int i;
	for (i=0; i<32; ++i)
	{
		*p &= ~1;
		if (type == 0) *p++ |= ((0xdeadbeef & (1 << i)) >> i);
		else *p++ |= ((0xdeadfeed & (1 << i)) >> i);
	}
	for (i=0; i<32; ++i)
	{
		*p &= ~1;
		*p++ |= ((hint & (1 << i)) >> i);
	}
}

TDeinterlace::TDeinterlace(PClip _child, int _mode, int _order, int _field, int _mthreshL, 
	int _mthreshC, int _map, const char* _ovr, int _ovrDefault, int _type, bool _debug, 
	int _mtnmode, bool _sharp, bool _hints, PClip _clip2, bool _full, int _cthresh, 
	bool _chroma, int _MI, bool _tryWeave, int _link, bool _denoise, int _AP, 
	int _blockx, int _blocky, int _APType, IScriptEnvironment* env) :
GenericVideoFilter(_child), mode(_mode), order(_order), field(_field), mthreshL(_mthreshL), 
	mthreshC(_mthreshC), map(_map), ovr(_ovr), ovrDefault(_ovrDefault), type(_type), 
	debug(_debug), mtnmode(_mtnmode), sharp(_sharp), hints(_hints), clip2(_clip2), full(_full),
	cthresh(_cthresh), chroma(_chroma), MI(_MI), tryWeave(_tryWeave), link(_link), 
	denoise(_denoise), AP(_AP), blockx(_blockx), blocky(_blocky), APType(_APType)
{
	int z, w, q, b, i, track, count;
	char linein[81];
	char *linep;
	FILE *f = NULL;
	input = cArray = NULL;
	if (!vi.IsYV12() && !vi.IsYUY2()) 
		env->ThrowError("TDeint:  YV12 and YUY2 data only!");
	if (mode != 0 && mode != 1 && mode != -1 && mode != -2)
		env->ThrowError("TDeint:  mode must be set to -2, -1, 0, or 1!");
	if (order != 0 && order != 1 && order != -1)
		env->ThrowError("TDeint:  order must be set to 0, 1, or -1!");
	if (field != 0 && field != 1 && field != -1)
		env->ThrowError("TDeint:  field must be set to 0, 1, or -1!");
	if (map < 0 || map > 2)
		env->ThrowError("TDeint:  map option must be set to 0, 1, or 2!");
	if (ovrDefault != 0 && ovrDefault != 1)
		env->ThrowError("TDeint:  ovrDefault must be set to either 0 or 1!");
	if (type != 0 && type != 1 && type != 2 && type != 3)
		env->ThrowError("TDeint:  type must be set to either 0, 1, 2, or 3!");
	if (mtnmode < 0 || mtnmode > 3)
		env->ThrowError("TDeint:  mtnmode must be set to either 0, 1, 2, or 3!");
	if (vi.height&1 || vi.width&1)
		env->ThrowError("TDeint:  width and height must be multiples of 2!");
	if (link < 0 || link > 3)
		env->ThrowError("TDeint:  link must be set to 0, 1, 2, or 3!");
	if (blockx != 4 && blockx != 8 && blockx != 16 && blockx != 32 && blockx != 64 && 
		blockx != 128 && blockx != 256 && blockx != 512 && blockx != 1024 && blockx != 2048)
		env->ThrowError("TDeint:  illegal blockx size!");
	if (blocky != 4 && blocky != 8 && blocky != 16 && blocky != 32 && blocky != 64 && 
		blocky != 128 && blocky != 256 && blocky != 512 && blocky != 1024 && blocky != 2048)
		env->ThrowError("TDeint:  illegal blocky size!");
	if (APType < 0 || APType > 2)
		env->ThrowError("TDeint:  APType must be set to 0, 1, or 2!");
	child->SetCacheHints(CACHE_RANGE, 4);
	useClip2 = false;
	if ((hints || !full) && mode == 0 && clip2)
	{
		const VideoInfo& vi1 = clip2->GetVideoInfo();
		if (vi1.height != vi.height || vi1.width != vi.width)
			env->ThrowError("TDeint:  width and height of clip2 must equal that of the input clip!");
		if (!vi1.IsYV12() && !vi1.IsYUY2())
			env->ThrowError("TDeint:  YV12 and YUY2 data only (clip2)!");
		if ((vi.IsYV12() && vi1.IsYUY2()) || (vi.IsYUY2() && vi1.IsYV12()))
			env->ThrowError("TDeint:  colorspace of clip2 doesn't match that of the input clip!");
		if (vi.num_frames != vi1.num_frames)
			env->ThrowError("TDeint:  number of frames in clip2 doesn't match that of the input clip!");
		useClip2 = true;
	}
	xhalf = blockx >> 1;
	yhalf = blocky >> 1;
	xshift = blockx == 4 ? 2 : blockx == 8 ? 3 : blockx == 16 ? 4 : blockx == 32 ? 5 :
		blockx == 64 ? 6 : blockx == 128 ? 7 : blockx == 256 ? 8 : blockx == 512 ? 9 : 
		blockx == 1024 ? 10 : 11;
	yshift = blocky == 4 ? 2 : blocky == 8 ? 3 : blocky == 16 ? 4 : blocky == 32 ? 5 :
		blocky == 64 ? 6 : blocky == 128 ? 7 : blocky == 256 ? 8 : blocky == 512 ? 9 : 
		blocky == 1024 ? 10 : 11;
	if (((!full && mode == 0) || tryWeave) && mode >= 0)
	{
		cArray = (int *)_aligned_malloc((((vi.width+xhalf)>>xshift)+1)*(((vi.height+yhalf)>>yshift)+1)*4*sizeof(int), 32);
		if (cArray == NULL) env->ThrowError("TDeint:  malloc failure!");
	}
	if (vi.IsYUY2())
	{
		xhalf *= 2;
		++xshift;
	}
	vi.SetFieldBased(false);
	nfrms = nfrms2 = vi.num_frames - 1;
	accumP = accumN = 0;
	cthresh6 = cthresh * 6;
	passHint = 0xFFFFFFFF;
	autoFO = false;
	if (mode < 0) 
	{
		vi.height *= 2;
		field = 1;
	}
	if (order == -1) autoFO = true;
	if (mode == 1)
	{
		vi.num_frames *= 2;
		nfrms2 = vi.num_frames - 1;
		vi.SetFPS(vi.fps_numerator*2, vi.fps_denominator);
	}
	else if (field == -1)
	{
		// telecide matches off the bottom field so we want field=0 in that case.
		// tfm can match off top or bottom, but it will indicate which in its hints
		// and field is adjusted appropriately then... so we use field=0 by default
		// if hints=true.  Otherwise, if hints=false, we default to field = 1.
		if (hints) field = 0;
		else field = 1;
	}
	orderS = order; 
	fieldS = field; 
	mthreshLS = mthreshL; 
	mthreshCS = mthreshC;
	typeS = type;
	if (debug)
	{
		sprintf(buf,"TDeint:  %s (%s) by tritical\n", VERSION, DATE);
		OutputDebugString(buf);
		sprintf(buf,"TDeint:  mode = %d (%s)\n", mode, mode == 0 ? "normal - same rate" : 
				mode == 1 ? "bob - double rate" : mode == -2 ? "upsize - ELA" : "upsize - ELA-2");
		OutputDebugString(buf);
	}
	if (*ovr && mode >= 0)
	{
		countOvr = i = 0;
		if ((f = fopen(ovr, "r")) != NULL)
		{
			while(fgets(linein, 80, f) != 0)
			{
				if (linein[0] == 0 || linein[0] == '\n' || linein[0] == '\r' || linein[0] == ';' || 
					linein[0] == '#') continue;
				linep = linein;
				while (*linep != '-' && *linep != '+' && *linep != 0) *linep++;
				if (*linep == 0) ++countOvr;
				else if (*(linep+1) == '-' || *(linep+1) == '+') 
				{
					linep = linein;
					while (*linep != ',' && *linep != 0) *linep++;
					if (*linep == ',')
					{
						sscanf(linein, "%d,%d", &z, &w);
						if (z<0 || z>nfrms || w<0 || w>nfrms || w < z) 
						{
							fclose(f);
							f = NULL;
							env->ThrowError("TDeint: ovr input error (invalid frame range)!");
						}
						countOvr += (w - z + 1);
					}
					else 
					{
						fclose(f);
						f = NULL;
						env->ThrowError("TDeint:  ovr input error (invalid entry)!");
					}
				}
				else ++countOvr;
			}
			fclose(f);
			f = NULL;
			if (countOvr <= 0)
			{
				goto noovrexit;
			}
			++countOvr;
			countOvr *= 4;
			input = (int *)malloc(countOvr*sizeof(int));
			if (input == NULL) 
				env->ThrowError("TDeint: ovr input error (malloc failure)!");
			memset(input,255,countOvr*sizeof(int));
			if ((f = fopen(ovr, "r")) != NULL)
			{
				while (fgets(linein, 80, f) != NULL)
				{
					if (linein[0] == 0 || linein[0] == '\n' || linein[0] == '\r' ||
						linein[0] == ';' || linein[0] == '#') continue;
					linep = linein;
					while (*linep != ',' && *linep != 0 && *linep != ' ') *linep++;
					if (*linep == ',')
					{
						sscanf(linein, "%d,%d", &z, &w);
						if (w == 0) w = nfrms;
						if (z<0 || z>nfrms || w<0 || w>nfrms || w < z) 
						{
							free(input);
							input = NULL;
							fclose(f);
							f = NULL;
							env->ThrowError("TDeint: ovr input error (invalid frame range)!");
						}
						linep = linein;
						while (*linep != ' ' && *linep != 0) *linep++;
						if (*linep != 0)
						{
							*linep++;
							if (*linep == 'f' || *linep == 'o' || *linep == 'l' || *linep == 'c' || *linep == 't')
							{
								q = *linep;
								linep += 2;
								if (*linep == 0) 
								{
									free(input);
									input = NULL;
									fclose(f);
									f = NULL;
									env->ThrowError("TDeint:  ovr input error (no change value specified)!");
								}
								sscanf(linep, "%d", &b);
								if (q == 102 && b != 0 && b != 1) 
								{
									free(input);
									input = NULL;
									fclose(f);
									f = NULL;
									env->ThrowError("TDeint:  ovr input error (bad field value)!");
								}
								else if (q == 111 && b != 0 && b != 1) 
								{
									free(input);
									input = NULL;
									fclose(f);
									f = NULL;
									env->ThrowError("TDeint:  ovr input error (bad order value)!");
								}
								else if (q == 116 && b != 0 && b != 1 && b != 2 && b != 3) 
								{
									free(input);
									input = NULL;
									fclose(f);
									f = NULL;
									env->ThrowError("TDeint:  ovr input error (bad type value)!");
								}
								input[i] = q; ++i;
								input[i] = z; ++i;
								input[i] = w; ++i;
								input[i] = b; ++i;
							}
							else if (*linep == '+' || *linep == '-') 
							{
								if (*(linep+1) == '+' || *(linep+1) == '-')
								{
									track = z; count = 0;
									while ((*linep == '+' || *linep == '-') && (track <= w))
									{
										q = *linep;
										input[i] = q; ++i;
										input[i] = track; ++i;
										input[i] = track; ++i; ++i;
										++count; ++track;
										*linep++;
									}
									while (track <= w)
									{
										input[i] = input[i-(count*4)]; ++i;
										input[i] = track; ++i;
										input[i] = track; ++i; ++i;
										++track;
									}
								}
								else
								{
									q = *linep;
									input[i] = q; ++i;
									input[i] = z; ++i;
									input[i] = w; ++i; ++i;
								}
							}
							else 
							{
								free(input);
								input = NULL;
								fclose(f);
								f = NULL;
								env->ThrowError("TDeint:  ovr input error (bad specifier)!");
							}
						}
						else 
						{
							free(input);
							input = NULL;
							fclose(f);
							f = NULL;
							env->ThrowError("TDeint:  ovr input error (no space after frame range)!");
						}
					}
					else if (*linep == ' ')
					{
						sscanf(linein, "%d", &z);
						if (z<0 || z>nfrms) 
						{
							free(input);
							input = NULL;
							fclose(f);
							f = NULL;
							env->ThrowError("TDeint: ovr input error (out of range frame #)!");
						}
						linep = linein;
						while (*linep != ' ' && *linep != 0) *linep++;
						if (*linep != 0)
						{
							*linep++;
							q = *linep;
							input[i] = q; ++i;
							input[i] = z; ++i;
							input[i] = z; ++i;
							if (*linep == 'f' || *linep == 'o' || *linep == 'l' || *linep == 'c' || *linep == 't')
							{
								linep += 2;
								if (*linep == 0) 
								{
									free(input);
									input = NULL;
									fclose(f);
									f = NULL;
									env->ThrowError("TDeint:  ovr input error (no change value specified)!");
								}
								sscanf(linep, "%d", &b);
								if (q == 102 && b != 0 && b != 1) 
								{
									free(input);
									input = NULL;
									fclose(f);
									f = NULL;
									env->ThrowError("TDeint:  ovr input error (bad field value)!");
								}
								else if (q == 111 && b != 0 && b != 1) 
								{
									free(input);
									input = NULL;
									fclose(f);
									f = NULL;
									env->ThrowError("TDeint:  ovr input error (bad order value)!");
								}
								else if (q == 116 && b != 0 && b != 1 && b != 2 && b != 3) 
								{
									free(input);
									input = NULL;
									fclose(f);
									f = NULL;
									env->ThrowError("TDeint:  ovr input error (bad type value)!");
								}
								input[i] = b; ++i;
							}
							else if (*linep == '+' || *linep == '-') ++i;
							else 
							{
								free(input);
								input = NULL;
								fclose(f);
								f = NULL;
								env->ThrowError("TDeint:  ovr input error (bad specifier)!");
							}
						}
						else 
						{
							free(input);
							input = NULL;
							fclose(f);
							f = NULL;
							env->ThrowError("TDeint:  ovr input error (no space after frame number)!");
						}
					}
					else
					{
						free(input);
						input = NULL;
						fclose(f);
						f = NULL;
						env->ThrowError("TDeint:  ovr input error (invalid line)!");
					}
				}
				fclose(f);
				f = NULL;
			}
			else 
			{
				free(input);
				input = NULL;
				env->ThrowError("TDeint: ovr input error (cannot open file)!");
			}
		}
		else env->ThrowError("TDeint: ovr input error (cannot open file)!");
	}
noovrexit:
	_asm emms;
}

TDeinterlace::~TDeinterlace()
{
	if (input != NULL) free(input);
	if (cArray != NULL) _aligned_free(cArray);
}

⌨️ 快捷键说明

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