| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843 | 
							- #include "main.h"
 
- #include <multimon.h>
 
- #include "vid_overlay.h"
 
- #include "vid_subs.h"
 
- #include "directdraw.h"
 
- #include "WinampAttributes.h"
 
- #include "../nsutil/image.h"
 
- #include <api.h>
 
- OverlayVideoOutput overlayVideo;
 
- extern "C" void getViewport(RECT *r, HWND wnd, int full, RECT *sr);
 
- #if 0
 
- #include <math.h>
 
- _inline long int lrintf(float flt)
 
- {
 
- 	int intgr;
 
- 	_asm
 
- 	{
 
- 	  fld flt
 
- 	  fistp intgr
 
- 	}
 
- 	return intgr;
 
- }
 
- static float clip(float x, float a, float b)
 
- {
 
- 	float x1 = fabs(x - a);
 
- 	float x2 = fabs(x - b);
 
- 	x = x1 + (a + b);
 
- 	x -= x2;
 
- 	x *= 0.5f;
 
- 	return (x);
 
- }
 
- void DoGamma(YV12_PLANES *planes, int height)
 
- {
 
- 	if (config_video_brightness != 128 || config_video_contrast != 128)
 
- 	{
 
- 		int x, y = height * planes->y.rowBytes;
 
- 		float add = config_video_brightness - 128;
 
- 		float mult = config_video_contrast / 128.f;
 
- 		unsigned char *pix = planes->y.baseAddr;
 
- 		for (x = 0; x < y; x++)
 
- 		{
 
- 			float value = (float) * pix;
 
- 			value = clip(value * mult + add, 0.0f, 255.0f);
 
- 			*pix++ = lrintf(value);
 
- 		}
 
- 	}
 
- }
 
- #else
 
- #define DoGamma(a,b)
 
- #endif
 
- void YV12_to_YUY2(unsigned char *output, const YV12_PLANES *planes, int pitch, int width, int height, int flip)
 
- {
 
- 	const unsigned char *yi = planes->y.baseAddr;
 
- 	const unsigned char *ui = planes->u.baseAddr;
 
- 	const unsigned char *vi = planes->v.baseAddr;
 
- 	if (flip)
 
- 		output += pitch * (height - 1);
 
- 	while (height > 0)
 
- 	{
 
- 		int x = width;
 
- 		unsigned char *oo = output;
 
- 		while (x > 0)
 
- 		{
 
- 			output[0] = *yi++; output[1] = *ui++; output[2] = *yi++; output[3] = *vi++;
 
- 			output += 4; x -= 2;
 
- 		}
 
- 		ui -= width / 2;
 
- 		vi -= width / 2;
 
- 		yi += planes->y.rowBytes - width;
 
- 		x = width;
 
- 		if (flip) output = oo - pitch;
 
- 		else output += pitch - width * 2;
 
- 		oo = output;
 
- 		while (x > 0)
 
- 		{
 
- 			output[0] = *yi++; output[1] = *ui++; output[2] = *yi++; output[3] = *vi++;
 
- 			output += 4; x -= 2;
 
- 		}
 
- 		if (flip) output = oo - pitch;
 
- 		else output += pitch - width * 2;
 
- 		ui += planes->u.rowBytes - (width / 2);
 
- 		vi += planes->v.rowBytes - (width / 2);
 
- 		yi += planes->y.rowBytes - width;
 
- 		height -= 2;
 
- 	}
 
- }
 
- void YV12_to_UYVY(unsigned char *output, const YV12_PLANES *planes, int pitch, int width, int height, int flip)
 
- {
 
- 	const unsigned char *yi = planes->y.baseAddr;
 
- 	const unsigned char *ui = planes->u.baseAddr;
 
- 	const unsigned char *vi = planes->v.baseAddr;
 
- 	if (flip) output += pitch * (height - 1);
 
- 	while (height > 0)
 
- 	{
 
- 		int x = width;
 
- 		unsigned char *oo = output;
 
- 		while (x > 0)
 
- 		{
 
- 			output[0] = *ui++; output[1] = *yi++; output[2] = *vi++; output[3] = *yi++;
 
- 			output += 4; x -= 2;
 
- 		}
 
- 		ui -= width / 2;
 
- 		vi -= width / 2;
 
- 		yi += planes->y.rowBytes - width;
 
- 		x = width;
 
- 		if (flip) output = oo - pitch;
 
- 		else output += pitch - width * 2;
 
- 		oo = output;
 
- 		while (x > 0)
 
- 		{
 
- 			output[0] = *ui++; output[1] = *yi++; output[2] = *vi++; output[3] = *yi++;
 
- 			output += 4; x -= 2;
 
- 		}
 
- 		if (flip) output = oo - pitch;
 
- 		else output += pitch - width * 2;
 
- 		ui += planes->u.rowBytes - (width / 2);
 
- 		vi += planes->v.rowBytes - (width / 2);
 
- 		yi += planes->y.rowBytes - width;
 
- 		height -= 2;
 
- 	}
 
- }
 
- void YV12_to_YV12(unsigned char *output, const YV12_PLANES *planes, int pitch, int width, int height, int flip)
 
- { // woo native YV12 copy
 
- 	if (flip)
 
- 	{
 
- 		nsutil_image_CopyFlipped_U8(output, pitch, planes->y.baseAddr, planes->y.rowBytes, width, height);
 
- 		unsigned char *o = output + height * pitch;
 
- 		nsutil_image_CopyFlipped_U8(o, pitch/2, planes->v.baseAddr, planes->v.rowBytes, width/2, height/2);
 
- 		o = output + (height * pitch) + (height/2) * (pitch/2); // benski> because height might be an odd number, it is important NOT to simplify this equation!
 
- 		nsutil_image_CopyFlipped_U8(o, pitch/2, planes->u.baseAddr, planes->u.rowBytes, width/2, height/2);
 
- 	}
 
- 	else
 
- 	{
 
- 		nsutil_image_Copy_U8(output, pitch, planes->y.baseAddr, planes->y.rowBytes, width, height);
 
- 		unsigned char *o = output + height * pitch;
 
- 		nsutil_image_Copy_U8(o, pitch/2, planes->v.baseAddr, planes->v.rowBytes, width/2, height/2);
 
- 		o = output + (height * pitch) + (height/2) * (pitch/2); // benski> because height might be an odd number, it is important NOT to simplify this equation!
 
- 		nsutil_image_Copy_U8(o, pitch/2, planes->u.baseAddr, planes->u.rowBytes, width/2, height/2);
 
- 	}
 
- }
 
- void YUY2_to_YUY2(unsigned char *output, const char *buf, int pitch, int width, int height, int flip)
 
- {
 
- 	const char *a = buf;
 
- 	unsigned char *b = output;
 
- 	int l = width * 2, l2 = pitch;
 
- 	if (flip)
 
- 	{
 
- 		b += (height - 1) * l2;
 
- 		l2 = -l2;
 
- 	}
 
- 	//wee straight YUY2 copy
 
- 	for (int i = 0;i < height;i++)
 
- 	{
 
- 		memcpy(b, a, l);
 
- 		b += l2;
 
- 		a += l;
 
- 	}
 
- }
 
- void YUY2_to_UYVY(unsigned char *output, const char *buf, int pitch, int width, int height, int flip)
 
- {
 
- 	const char *a = buf;
 
- 	unsigned char *b = output;
 
- 	int l = width * 2, l2 = pitch;
 
- 	if (flip)
 
- 	{
 
- 		b += (height - 1) * l2;
 
- 		l2 = -l2;
 
- 	}
 
- 	for (int i = 0;i < height;i++)
 
- 	{
 
- 		int x = width / 2;
 
- 		while (x-- > 0)
 
- 		{
 
- 			b[0] = a[1];
 
- 			b[1] = a[0];
 
- 			b[2] = a[3];
 
- 			b[3] = a[2];
 
- 			a += 4;
 
- 			b += 4;
 
- 		}
 
- 		memcpy(b, a, l);
 
- 		b += l2;
 
- 		a += l;
 
- 	}
 
- }
 
- #define INIT_DIRECTDRAW_STRUCT(x) (ZeroMemory(&x, sizeof(x)), x.dwSize=sizeof(x))
 
- // I like to set these to 255,0,255 to test that we arent drawing this color too many playces
 
- #define OV_COL_R 16
 
- #define OV_COL_G 0
 
- #define OV_COL_B 16
 
- OverlayVideoOutput::OverlayVideoOutput()
 
- {
 
- 	lpDD = NULL;
 
- 	m_closed = 0;
 
- 	overlay_color = RGB(OV_COL_R, OV_COL_G, OV_COL_B);
 
- 	lpddsOverlay = NULL;
 
- 	lpddsPrimary = NULL;
 
- 	lpBackBuffer = NULL;
 
- 	width = height = flip = 0;
 
- 	type = VIDEO_MAKETYPE('Y', 'V', '1', '2');
 
- 	uDestSizeAlign = 0;
 
- 	uSrcSizeAlign = 0;
 
- 	dwUpdateFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;
 
- 	curSubtitle = NULL;
 
- 	yuy2_output = uyvy_output = 0;
 
- 	initing = false;
 
- 	needchange = 0;
 
- 	memset(&m_oldrd, 0, sizeof(m_oldrd));
 
- 	memset(&winRect, 0, sizeof(winRect));
 
- 	subFont = NULL;
 
- 	m_fontsize = 0;
 
- 	resetSubtitle();
 
- }
 
- OverlayVideoOutput::~OverlayVideoOutput()
 
- {
 
- 	OverlayVideoOutput::close();
 
- }
 
- static DWORD DD_ColorMatch(LPDIRECTDRAWSURFACE pdds, COLORREF rgb)
 
- {
 
- 	COLORREF rgbT = CLR_INVALID;
 
- 	HDC hdc;
 
- 	DWORD dw = CLR_INVALID;
 
- 	DDSURFACEDESC ddsd;
 
- 	HRESULT hres;
 
- 	//
 
- 	//  use GDI SetPixel to color match for us
 
- 	//
 
- 	if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
 
- 	{
 
- 		rgbT = GetPixel(hdc, 0, 0);     // save current pixel value
 
- 		SetPixel(hdc, 0, 0, rgb);       // set our value
 
- 		pdds->ReleaseDC(hdc);
 
- 	}
 
- 	// now lock the surface so we can read back the converted color
 
- 	ddsd.dwSize = sizeof(ddsd);
 
- 	while ((hres = pdds->Lock(NULL, &ddsd, 0, NULL)) ==
 
- 	       DDERR_WASSTILLDRAWING)
 
- 		;
 
- 	if (hres == DD_OK)
 
- 	{
 
- 		dw = *(DWORD *)ddsd.lpSurface;    // get DWORD
 
- 		if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
 
- 			dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1;                        // mask it to bpp
 
- 		pdds->Unlock(NULL);
 
- 	}
 
- 	//  now put the color that was there back.
 
- 	if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
 
- 	{
 
- 		SetPixel(hdc, 0, 0, rgbT);
 
- 		pdds->ReleaseDC(hdc);
 
- 	}
 
- 	return dw;
 
- }
 
- int OverlayVideoOutput::create(HWND parent, VideoAspectAdjuster *_adjuster, int w, int h, unsigned int ptype, int flipit, double aspectratio)
 
- {
 
- 	OverlayVideoOutput::close();
 
- 	this->parent = parent;
 
- 	type = ptype;
 
- 	width = w;
 
- 	height = h;
 
- 	flip = flipit;
 
- 	adjuster = _adjuster;
 
- 	initing = true;
 
- 	HWND hwnd = this->parent;
 
- 	if (lpDD) lpDD->Release();
 
- 	lpDD = NULL;
 
- 	update_monitor_coords();
 
- 	if (_DirectDrawCreate)
 
- 	{
 
- 		if (!foundGUID) _DirectDrawCreate(NULL, &lpDD, NULL);
 
- 		else _DirectDrawCreate(&m_devguid, &lpDD, NULL);
 
- 	}
 
- 	if (!lpDD)
 
- 	{
 
- 		initing = false;
 
- 		return 0;
 
- 	}
 
- 	lpDD->SetCooperativeLevel(hwnd, DDSCL_NOWINDOWCHANGES | DDSCL_NORMAL);
 
- 	DDSURFACEDESC ddsd;
 
- 	INIT_DIRECTDRAW_STRUCT(ddsd);
 
- 	ddsd.dwFlags = DDSD_CAPS;
 
- 	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
 
- 	lpDD->CreateSurface(&ddsd, &lpddsPrimary, NULL);
 
- 	if (!lpddsPrimary)
 
- 	{
 
- 		if (lpDD) lpDD->Release();
 
- 		lpDD = NULL;
 
- 		initing = false;
 
- 		return 0;
 
- 	}
 
- 	// init overlay
 
- 	DDSURFACEDESC ddsdOverlay;
 
- 	INIT_DIRECTDRAW_STRUCT(ddsdOverlay);
 
- 	ddsdOverlay.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
 
- 	ddsdOverlay.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_BACKBUFFERCOUNT;
 
- 	ddsdOverlay.dwBackBufferCount = 1;
 
- 	ddsdOverlay.dwWidth = w;
 
- 	ddsdOverlay.dwHeight = h;
 
- 	ddsdOverlay.lPitch = w * 4;
 
- 	DDPIXELFORMAT pf[] =
 
- 	  {
 
- 	    {sizeof(DDPIXELFORMAT), DDPF_FOURCC | DDPF_YUV, MAKEFOURCC('Y', 'U', 'Y', '2'), 0, 0, 0, 0, 0},
 
- 	    {sizeof(DDPIXELFORMAT), DDPF_FOURCC | DDPF_YUV, MAKEFOURCC('U', 'Y', 'V', 'Y'), 0, 0, 0, 0, 0},         // UYVY
 
- 	    {sizeof(DDPIXELFORMAT), DDPF_FOURCC | DDPF_YUV, MAKEFOURCC('Y', 'V', '1', '2'), 0, 0, 0, 0, 0},
 
- 	    // TODO:
 
-     //					{sizeof(DDPIXELFORMAT), DDPF_FOURCC | DDPF_YUV, MAKEFOURCC('N','V','1','2'), 12, 0, 0, 0, 0},   // NV12
 
-     //					{sizeof(DDPIXELFORMAT), DDPF_RGB,0,16,0xf800,0x07e0,0x001f,0}                                   // RGB565
 
- 	  };
 
- 	int tab[5];
 
- 	if (type == VIDEO_MAKETYPE('Y', 'U', 'Y', '2'))
 
- 	{
 
- 		tab[0] = 0; // default is YUY2
 
- 		tab[1] = 1;
 
- 		tab[2] = -1;
 
- 	}
 
- 	else if (type == VIDEO_MAKETYPE('U', 'Y', 'V', 'Y'))
 
- 	{
 
- 		tab[0] = 1; // make UYVY default
 
- 		tab[1] = 0;
 
- 		tab[2] = -1;
 
- 	}
 
- 	else if (type == VIDEO_MAKETYPE('Y', 'V', '1', '2'))
 
- 	{
 
- 		if (config_video_yv12)
 
- 		{
 
- 			tab[0] = 2;
 
- 			tab[1] = 0;
 
- 			tab[2] = 1;
 
- 			tab[3] = -1;
 
- 		}
 
- 		else
 
- 		{
 
- 			//use YUY2
 
- 			tab[0] = 0; // default is YUY2
 
- 			tab[1] = 1;
 
- 			tab[2] = -1;
 
- 		}
 
- 	}
 
- 	else
 
- 	{
 
- 		tab[0] = -1; // default is RGB
 
- 	}
 
- 	int x = 4096;
 
- 	HRESULT v = -1;
 
- 	for (x = 0; x < sizeof(tab) / sizeof(tab[0]) && tab[x] >= 0; x ++)
 
- 	{
 
- 		ddsdOverlay.ddpfPixelFormat = pf[tab[x]];
 
- 		v = lpDD->CreateSurface(&ddsdOverlay, &lpddsOverlay, NULL);
 
- 		if (!FAILED(v)) break;
 
- 	}
 
- 	if (FAILED(v) || x >= sizeof(tab) / sizeof(tab[0]) || tab[x] < 0)
 
- 	{
 
- 		initing = false;
 
- 		return 0;
 
- 	}
 
- 	yuy2_output = (tab[x] == 0);
 
- 	uyvy_output = (tab[x] == 1);
 
- 	//get the backbuffer surface
 
- 	DDSCAPS ddscaps;
 
- 	ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
 
- 	v = lpddsOverlay->GetAttachedSurface(&ddscaps, &lpBackBuffer);
 
- 	if (v != DD_OK || lpBackBuffer == 0)
 
- 	{
 
- 		//FUCKO: make it use normal vsync
 
- 		lpBackBuffer = 0;
 
- 		initing = FALSE;
 
- 		return 0;
 
- 	}
 
- 	INIT_DIRECTDRAW_STRUCT(capsDrv);
 
- 	lpDD->GetCaps(&capsDrv, NULL);
 
- 	uDestSizeAlign = capsDrv.dwAlignSizeDest;
 
- 	uSrcSizeAlign = capsDrv.dwAlignSizeSrc;
 
- 	dwUpdateFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;
 
- 	DEVMODE d;
 
- 	d.dmSize = sizeof(d);
 
- 	d.dmDriverExtra = 0;
 
- 	EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &d);
 
- 	int rv = OV_COL_R, gv = OV_COL_G, bv = OV_COL_B;
 
- 	overlay_color = RGB(rv, gv, bv);
 
- 	if (d.dmBitsPerPel == 8)
 
- 	{
 
- 		overlay_color = RGB(255, 0, 255);
 
- 	}
 
- 	INIT_DIRECTDRAW_STRUCT(ovfx);
 
- 	ovfx.dwDDFX = 0;
 
- 	switch (d.dmBitsPerPel)
 
- 	{
 
- 		case 8:
 
- 			ovfx.dckDestColorkey.dwColorSpaceLowValue = 253;
 
- 			break;
 
- 		case 16:
 
- 			ovfx.dckDestColorkey.dwColorSpaceLowValue = ((rv >> 3) << 11) | ((gv >> 2) << 5) | (bv >> 3);
 
- 			break;
 
- 		case 15:
 
- 			ovfx.dckDestColorkey.dwColorSpaceLowValue = ((rv >> 3) << 10) | ((gv >> 3) << 5) | (bv >> 3);
 
- 			break;
 
- 	case 24: case 32:
 
- 			ovfx.dckDestColorkey.dwColorSpaceLowValue = (rv << 16) | (gv << 8) | bv;
 
- 			break;
 
- 	}
 
- 	//try to get the correct bit depth thru directdraw (for fucked up 16 bits displays for ie.)
 
- 	{
 
- 		DDSURFACEDESC DDsd = {sizeof(DDsd), };
 
- 		lpddsPrimary->GetSurfaceDesc(&ddsd);
 
- 		DDsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; //create the surface at screen depth
 
- 		DDsd.dwWidth = 8;
 
- 		DDsd.dwHeight = 8;
 
- 		DDsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
 
- 		LPDIRECTDRAWSURFACE tempsurf;
 
- 		if (lpDD->CreateSurface(&DDsd, &tempsurf, NULL) == DD_OK)
 
- 		{
 
- 			int res = DD_ColorMatch(tempsurf, overlay_color);
 
- 			if (res != CLR_INVALID) ovfx.dckDestColorkey.dwColorSpaceLowValue = res;
 
- 			tempsurf->Release();
 
- 		}
 
- 	}
 
- 	ovfx.dckDestColorkey.dwColorSpaceHighValue = ovfx.dckDestColorkey.dwColorSpaceLowValue;
 
- 	getRects(&rs, &rd);
 
- 	if (FAILED(lpddsOverlay->UpdateOverlay(&rs, lpddsPrimary, &rd, dwUpdateFlags, &ovfx)))
 
- 	{
 
- 		initing = false;
 
- 		return 0;
 
- 	}
 
- 	initing = false;
 
- 	DDSURFACEDESC dd = {sizeof(dd), };
 
- 	if (lpddsOverlay->Lock(NULL, &dd, DDLOCK_WAIT, NULL) != DD_OK) return 0;
 
- 	unsigned char *o = (unsigned char*)dd.lpSurface;
 
- 	if (uyvy_output || yuy2_output)
 
- 	{
 
- 		int x = dd.lPitch * height / 2;
 
- 		while (x--)
 
- 		{
 
- 			if (uyvy_output)
 
- 			{
 
- 				*o++ = 128;
 
- 				*o++ = 0;
 
- 			}
 
- 			else
 
- 			{
 
- 				*o++ = 0;
 
- 				*o++ = -128;
 
- 			}
 
- 		}
 
- 	}
 
- 	else
 
- 	{
 
- 		memset(o, 0, dd.lPitch*height); o += dd.lPitch * height;
 
- 		memset(o, 128, dd.lPitch*height / 2);
 
- 	}
 
- 	lpddsOverlay->Unlock(&dd);
 
- 	m_closed = 0;
 
- 	needchange = 0;
 
- 	InvalidateRect(hwnd, NULL, TRUE);
 
- 	return 1;
 
- }
 
- void OverlayVideoOutput::close()
 
- {
 
- 	m_closed = 1;
 
- 	if (lpddsOverlay) lpddsOverlay->UpdateOverlay(NULL, lpddsPrimary, NULL, DDOVER_HIDE , NULL);
 
- 	if (lpBackBuffer) lpBackBuffer->Release(); lpBackBuffer = 0;
 
- 	if (lpddsOverlay) lpddsOverlay->Release(); lpddsOverlay = 0;
 
- 	if (lpddsPrimary) lpddsPrimary->Release(); lpddsPrimary = 0;
 
- 	if (lpDD) lpDD->Release();	lpDD = 0; // BU added NULL check in response to talkback
 
- 	if (subFont) DeleteObject(subFont); subFont = 0;
 
- }
 
- void OverlayVideoOutput::getRects(RECT *drs, RECT *drd, int fixmultimon) const
 
- {
 
- 	//if(GetParent(hwnd)) hwnd=GetParent(hwnd);
 
- 	RECT rd, rs;
 
- 	GetClientRect(parent, &rd);
 
- 	ClientToScreen(parent, (LPPOINT)&rd);
 
- 	ClientToScreen(parent, ((LPPOINT)&rd) + 1);
 
- 	adjuster->adjustAspect(rd);
 
- 	rd.left -= m_mon_x;
 
- 	rd.right -= m_mon_x;
 
- 	rd.top -= m_mon_y;
 
- 	rd.bottom -= m_mon_y;
 
- 	memset(&rs, 0, sizeof(rs));
 
- 	rs.right = width;
 
- 	rs.bottom = height;
 
- 	if (fixmultimon)
 
- 	{
 
- 		//resize overlay for off-screen
 
- 		RECT rfull;
 
- 		getViewport(&rfull, parent, 1, NULL);
 
- 		rfull.left -= m_mon_x;
 
- 		rfull.right -= m_mon_x;
 
- 		rfull.top -= m_mon_y;
 
- 		rfull.bottom -= m_mon_y;
 
- 		if (rd.right > rfull.right)
 
- 		{
 
- 			int diff = rd.right - rfull.right;
 
- 			float sc = (float)(width) / (float)(rd.right - rd.left);
 
- 			rd.right = rfull.right;
 
- 			rs.right = width - (int)(diff * sc);
 
- 		}
 
- 		if (rd.left < rfull.left)
 
- 		{
 
- 			int diff = rfull.left - rd.left;
 
- 			float sc = (float)(width) / (float)(rd.right - rd.left);
 
- 			rd.left = rfull.left;
 
- 			rs.left = (int)(diff * sc);
 
- 		}
 
- 		if (rd.bottom > rfull.bottom)
 
- 		{
 
- 			int diff = rd.bottom - rfull.bottom;
 
- 			float sc = (float)(height) / (float)(rd.bottom - rd.top);
 
- 			rd.bottom = rfull.bottom;
 
- 			rs.bottom = height - (int)(diff * sc);
 
- 		}
 
- 		if (rd.top < rfull.top)
 
- 		{
 
- 			int diff = rfull.top - rd.top;
 
- 			float sc = (float)(height) / (float)(rd.bottom - rd.top);
 
- 			rd.top = rfull.top;
 
- 			rs.top = (int)(diff * sc);
 
- 		}
 
- 	}
 
- 	if (capsDrv.dwCaps & DDCAPS_ALIGNSIZESRC && uDestSizeAlign)
 
- 	{
 
- 		rs.left = (int)((rs.left + uDestSizeAlign - 1) / uDestSizeAlign) * uDestSizeAlign;
 
- 		rs.right = (int)((rs.right + uDestSizeAlign - 1) / uDestSizeAlign) * uDestSizeAlign;
 
- 	}
 
- 	if (capsDrv.dwCaps & DDCAPS_ALIGNSIZEDEST && uDestSizeAlign)
 
- 	{
 
- 		rd.left = (int)((rd.left + uDestSizeAlign - 1) / uDestSizeAlign) * uDestSizeAlign;
 
- 		rd.right = (int)((rd.right + uDestSizeAlign - 1) / uDestSizeAlign) * uDestSizeAlign;
 
- 	}
 
- 	*drd = rd;
 
- 	*drs = rs;
 
- }
 
- void OverlayVideoOutput::timerCallback()
 
- {
 
- 	if (!adjuster)
 
- 		return ;
 
- 	RECT rd, rs;
 
- 	getRects(&rs, &rd);
 
- 	if (memcmp(&m_oldrd, &rd, sizeof(RECT)))
 
- 	{
 
- 		if ((m_oldrd.right - m_oldrd.left) != (rd.right - rd.left) || (m_oldrd.bottom - m_oldrd.top) != (rd.bottom - rd.top))
 
- 		{
 
- 			resetSubtitle();
 
- 		}
 
- 		m_oldrd = rd;
 
- 		if (!initing && lpddsOverlay)
 
- 			if (FAILED(lpddsOverlay->UpdateOverlay(&rs, lpddsPrimary, &rd, dwUpdateFlags, &ovfx)))
 
- 			{
 
- 				needchange = 1;
 
- 			}
 
- 		InvalidateRect(parent, NULL, FALSE);
 
- 	}
 
- }
 
- int OverlayVideoOutput::onPaint(HWND hwnd)
 
- {
 
- 	PAINTSTRUCT p;
 
- 	BeginPaint(hwnd, &p);
 
- 	if (!m_closed)
 
- 	{
 
- 		RECT r, rs, rfull, clientRect;
 
- 		RECT drawRect;
 
- 		getRects(&rs, &r, 0); // we don't just fill the entire client rect, cause that looks gross
 
- 		getViewport(&rfull, hwnd, 1, NULL);
 
- 		// go from this screen coords to global coords
 
- 		r.left += rfull.left;
 
- 		r.top += rfull.top;
 
- 		r.right += rfull.left;
 
- 		r.bottom += rfull.top;
 
- 		// go from global back to client
 
- 		ScreenToClient(hwnd, (LPPOINT)&r);
 
- 		ScreenToClient(hwnd, ((LPPOINT)&r) + 1);
 
- 		HBRUSH br = (HBRUSH) GetStockObject(BLACK_BRUSH);
 
- 		GetClientRect(hwnd, &clientRect);
 
- 		// left black box
 
- 		drawRect.left = clientRect.left;
 
- 		drawRect.right = r.left;
 
- 		drawRect.top = clientRect.top;
 
- 		drawRect.bottom = clientRect.bottom;
 
- 		FillRect(p.hdc, &drawRect, br);
 
- 		// right black box
 
- 		drawRect.left = r.right;
 
- 		drawRect.right = clientRect.right;
 
- 		drawRect.top = clientRect.top;
 
- 		drawRect.bottom = clientRect.bottom;
 
- 		FillRect(p.hdc, &drawRect, br);
 
- 		// top black box
 
- 		drawRect.left = clientRect.left;
 
- 		drawRect.right = clientRect.right;
 
- 		drawRect.top = clientRect.top;
 
- 		drawRect.bottom = r.top;
 
- 		FillRect(p.hdc, &drawRect, br);
 
- 		// bottom black box
 
- 		drawRect.left = clientRect.left;
 
- 		drawRect.right = clientRect.right;
 
- 		drawRect.top = r.bottom;
 
- 		drawRect.bottom = clientRect.bottom;
 
- 		FillRect(p.hdc, &drawRect, br);
 
- 		LOGBRUSH lb = {BS_SOLID, (COLORREF)overlay_color, };
 
- 		br = CreateBrushIndirect(&lb);
 
- 		FillRect(p.hdc, &r, br);
 
- 		DeleteObject(br);
 
- 	}
 
- 	SubsItem *cst = curSubtitle;
 
- 	if (cst)
 
- 	{
 
- 		int m_lastsubxp = cst->xPos;
 
- 		int m_lastsubyp = cst->yPos;
 
- 		HDC out = p.hdc;
 
- 		HGDIOBJ oldobj = SelectObject(out, subFont);
 
- 		SetBkMode(out, TRANSPARENT);
 
- 		int centerflags = 0;
 
- 		if (m_lastsubxp < 127) centerflags |= DT_LEFT;
 
- 		else if (m_lastsubxp > 127) centerflags |= DT_RIGHT;
 
- 		else centerflags |= DT_CENTER;
 
- 		if (m_lastsubyp < 127) centerflags |= DT_TOP;
 
- 		else if (m_lastsubyp > 127) centerflags |= DT_BOTTOM;
 
- 		// draw outline
 
- 		SetTextColor(out, RGB(0, 0, 0));
 
- 		for (int y = -1; y < 2; y++)
 
- 			for (int x = -1; x < 2; x++)
 
- 			{
 
- 				if (!y && !x) continue;
 
- 				RECT r2 = {subRect.left + x, subRect.top + y, subRect.right + x, subRect.bottom + y};
 
- 				DrawTextA(out, cst->text, -1, &r2, centerflags | DT_NOCLIP | DT_NOPREFIX);
 
- 			}
 
- 		// draw text
 
- 		SetTextColor(out, RGB(cst->colorRed, cst->colorGreen, cst->colorBlue));
 
- 		DrawTextA(out, cst->text, -1, &subRect, centerflags | DT_NOCLIP | DT_NOPREFIX);
 
- 		SelectObject(out, oldobj);
 
- 	}
 
- 	EndPaint(hwnd, &p);
 
- 	return 1;
 
- }
 
- bool OverlayVideoOutput::LockSurface(DDSURFACEDESC *dd)
 
- {
 
- 	for (;;Sleep(0))
 
- 	{
 
- 		HRESULT hr = lpBackBuffer->Lock(0, dd, DDLOCK_WAIT | DDLOCK_WRITEONLY, 0);
 
- 		if (dd->lpSurface)
 
- 			break;
 
- 		if (hr == DDERR_SURFACELOST)
 
- 		{
 
- 			lpddsPrimary->Restore();
 
- 			lpBackBuffer->Restore();
 
- 			hr = lpddsOverlay->Lock(0, dd, DDLOCK_WAIT | DDLOCK_WRITEONLY, 0);
 
- 			if (hr == DDERR_SURFACELOST)
 
- 				return false;
 
- 		}
 
- 		else if (hr != DDERR_WASSTILLDRAWING)
 
- 			return false;
 
- 	}
 
- 	return true;
 
- }
 
- void OverlayVideoOutput::displayFrame(const char *buf, int size, int time)
 
- {
 
- 	DDSURFACEDESC dd = {sizeof(dd), };
 
- 	//CT> vsync wait not used anymore
 
- 	//if (config_video_vsync) lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0);
 
- 	if (!LockSurface(&dd))
 
- 	{
 
- 		needchange = 1;
 
- 		return ;
 
- 	}
 
- 	if (type == VIDEO_MAKETYPE('Y', 'V', '1', '2'))
 
- 	{
 
- 		YV12_PLANES *planes = (YV12_PLANES *)buf;
 
- 		DoGamma(planes, height);
 
- 		if (uyvy_output)
 
- 			YV12_to_UYVY((unsigned char*)dd.lpSurface, planes, dd.lPitch, width, height, flip);
 
- 		else if (yuy2_output)
 
- 			YV12_to_YUY2((unsigned char*)dd.lpSurface, planes, dd.lPitch, width, height, flip);
 
- 		else
 
- 			YV12_to_YV12((unsigned char*)dd.lpSurface, planes, dd.lPitch, width, height, flip);
 
- 	}
 
- 	else if (type == VIDEO_MAKETYPE('Y', 'U', 'Y', '2'))
 
- 	{
 
- 		if (yuy2_output)
 
- 			YUY2_to_YUY2((unsigned char*)dd.lpSurface, buf, dd.lPitch, width, height, flip);
 
- 		else if (uyvy_output)
 
- 			YUY2_to_UYVY((unsigned char*)dd.lpSurface, buf, dd.lPitch, width, height, flip);
 
- 		else
 
- 			YUY2_to_YUY2((unsigned char*)dd.lpSurface, buf, dd.lPitch, width, height, flip); // is this right?
 
- 	}
 
- 	else if (type == VIDEO_MAKETYPE('U', 'Y', 'V', 'Y'))
 
- 	{
 
- 		if (yuy2_output)
 
- 			YUY2_to_UYVY((unsigned char*)dd.lpSurface, buf, dd.lPitch, width, height, flip);
 
- 		else if (uyvy_output)	// TODO check this is correct i.e. dup YUY2_to_YUY2(..) calls
 
- 			YUY2_to_YUY2((unsigned char*)dd.lpSurface, buf, dd.lPitch, width, height, flip);
 
- 		else
 
- 			YUY2_to_YUY2((unsigned char*)dd.lpSurface, buf, dd.lPitch, width, height, flip); // is this right?
 
- 	}
 
- 	lpBackBuffer->Unlock(&dd);
 
- 	lpddsOverlay->Flip(lpBackBuffer, DDFLIP_WAIT);
 
- }
 
- void OverlayVideoOutput::drawSubtitle(SubsItem *item)
 
- {
 
- 	curSubtitle = item;
 
- 	RECT oldrect = subRect;
 
- 	GetClientRect(parent, &subRect);
 
- 	if (item)
 
- 	{
 
- 		RECT oldwinRect = winRect;
 
- 		GetClientRect(parent, &winRect);
 
- 		if (!subFont || ((winRect.bottom - winRect.top) != (oldwinRect.bottom - oldwinRect.top)) || m_fontsize != item->fontSize)
 
- 		{
 
- 			if (subFont)
 
- 				DeleteObject(subFont);
 
- 			m_fontsize = item->fontSize;
 
- 			subFont = CreateFontA(14 + item->fontSize + 18 * (winRect.bottom - winRect.top) / 768, 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
 
- 		}
 
- 		HDC out = GetDC(parent);
 
- 		SelectObject(out, subFont);
 
- 		SIZE s;
 
- 		GetTextExtentPoint32A(out, item->text, lstrlenA(item->text), &s);
 
- 		{
 
- 			// calcul for multiline text
 
- 			const char *p = item->text;
 
- 			int n = 0;
 
- 			while (*p != 0) if (*p++ == '\n') n++;
 
- 			if (n) s.cy *= (n + 1);
 
- 		}
 
- 		if (item->xPos > 127) // towards the right
 
- 			subRect.right -= ((subRect.right - subRect.left) * (255 - item->xPos)) / 256;
 
- 		else if (item->xPos < 127)
 
- 			subRect.left += ((subRect.right - subRect.left) * item->xPos) / 256;
 
- 		subRect.top += ((subRect.bottom - s.cy - subRect.top) * item->yPos) / 255;
 
- 		subRect.bottom = subRect.top + s.cy;
 
- 		ReleaseDC(parent, out);
 
- 	}
 
- 	//just redraw the correct portion
 
- 	InvalidateRect(parent, &oldrect, TRUE);
 
- 	InvalidateRect(parent, &subRect, TRUE);
 
- }
 
- void OverlayVideoOutput::resetSubtitle()
 
- {
 
- 	curSubtitle = NULL;
 
- 	subRect.top = 65536;
 
- }
 
 
  |