mirror of https://github.com/PCSX2/pcsx2.git
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@404 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
b0907169a4
commit
5587ee7640
|
@ -1,441 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "stdafx.h"
|
|
||||||
#include "GSdx9.h"
|
|
||||||
#include "GS.h"
|
|
||||||
#include "GSRendererHW.h"
|
|
||||||
#include "GSRendererSoft.h"
|
|
||||||
#include "GSRendererNull.h"
|
|
||||||
#include "GSWnd.h"
|
|
||||||
#include "GSSettingsDlg.h"
|
|
||||||
|
|
||||||
#define PS2E_LT_GS 0x01
|
|
||||||
#define PS2E_GS_VERSION 0x0006
|
|
||||||
#define PS2E_DLL_VERSION 0x09
|
|
||||||
#define PS2E_X86 0x01 // 32 bit
|
|
||||||
#define PS2E_X86_64 0x02 // 64 bit
|
|
||||||
|
|
||||||
EXPORT_C_(UINT32) PS2EgetLibType()
|
|
||||||
{
|
|
||||||
return PS2E_LT_GS;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C_(char*) PS2EgetLibName()
|
|
||||||
{
|
|
||||||
CString str = _T("GSdx9");
|
|
||||||
|
|
||||||
#if _M_AMD64
|
|
||||||
str += _T(" 64-bit");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CList<CString> sl;
|
|
||||||
|
|
||||||
#ifdef __INTEL_COMPILER
|
|
||||||
CString s;
|
|
||||||
s.Format(_T("Intel C++ %d.%02d"), __INTEL_COMPILER/100, __INTEL_COMPILER%100);
|
|
||||||
sl.AddTail(s);
|
|
||||||
#elif _MSC_VER
|
|
||||||
CString s;
|
|
||||||
s.Format(_T("MSVC %d.%02d"), _MSC_VER/100, _MSC_VER%100);
|
|
||||||
sl.AddTail(s);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if _M_IX86_FP >= 2
|
|
||||||
sl.AddTail(_T("SSE2"));
|
|
||||||
#elif _M_IX86_FP >= 1
|
|
||||||
sl.AddTail(_T("SSE"));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
sl.AddTail(_T("OpenMP"));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
POSITION pos = sl.GetHeadPosition();
|
|
||||||
while(pos)
|
|
||||||
{
|
|
||||||
if(pos == sl.GetHeadPosition()) str += _T(" (");
|
|
||||||
str += sl.GetNext(pos);
|
|
||||||
str += pos ? _T(", ") : _T(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
static char buff[256];
|
|
||||||
strncpy(buff, CStringA(str), min(countof(buff)-1, str.GetLength()));
|
|
||||||
return buff;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C_(UINT32) PS2EgetLibVersion2(UINT32 type)
|
|
||||||
{
|
|
||||||
return (PS2E_GS_VERSION<<16)|(0x00<<8)|PS2E_DLL_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C_(UINT32) PS2EgetCpuPlatform()
|
|
||||||
{
|
|
||||||
#if _M_AMD64
|
|
||||||
return PS2E_X86_64;
|
|
||||||
#else
|
|
||||||
return PS2E_X86;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////
|
|
||||||
|
|
||||||
#define REPLAY_TITLE "Replay"
|
|
||||||
|
|
||||||
static HRESULT s_hrCoInit = E_FAIL;
|
|
||||||
static CGSWnd s_hWnd;
|
|
||||||
static CAutoPtr<GSState> s_gs;
|
|
||||||
static void (*s_fpGSirq)() = NULL;
|
|
||||||
|
|
||||||
BYTE* g_pBasePS2Mem = NULL;
|
|
||||||
|
|
||||||
EXPORT_C GSsetBaseMem(BYTE* pBasePS2Mem)
|
|
||||||
{
|
|
||||||
g_pBasePS2Mem = pBasePS2Mem - 0x12000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C_(INT32) GSinit()
|
|
||||||
{
|
|
||||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C GSshutdown()
|
|
||||||
{
|
|
||||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C_(INT32) GSopen(void* pDsp, char* Title, int multithread)
|
|
||||||
{
|
|
||||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
s_hrCoInit = ::CoInitialize(0);
|
|
||||||
|
|
||||||
ASSERT(!s_gs);
|
|
||||||
s_gs.Free();
|
|
||||||
|
|
||||||
if(!s_hWnd.Create(_T("PCSX2")))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
switch(AfxGetApp()->GetProfileInt(_T("Settings"), _T("Renderer"), RENDERER_D3D_HW))
|
|
||||||
{
|
|
||||||
case RENDERER_D3D_HW: s_gs.Attach(new GSRendererHW(s_hWnd, hr)); break;
|
|
||||||
// case RENDERER_D3D_SW_FX: s_gs.Attach(new GSRendererSoftFX(s_hWnd, hr)); break;
|
|
||||||
case RENDERER_D3D_SW_FP: s_gs.Attach(new GSRendererSoftFP(s_hWnd, hr)); break;
|
|
||||||
case RENDERER_D3D_NULL: s_gs.Attach(new GSRendererNull(s_hWnd, hr)); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!s_gs || FAILED(hr))
|
|
||||||
{
|
|
||||||
s_gs.Free();
|
|
||||||
s_hWnd.DestroyWindow();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
if(!IsWindow(s_hWnd))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
*(HWND*)pDsp = s_hWnd;
|
|
||||||
|
|
||||||
s_gs->ResetDevice();
|
|
||||||
|
|
||||||
s_gs->GSirq(s_fpGSirq);
|
|
||||||
|
|
||||||
s_gs->m_fMultiThreaded = !!multithread;
|
|
||||||
|
|
||||||
if((!Title || strcmp(Title, REPLAY_TITLE) != 0)
|
|
||||||
&& AfxGetApp()->GetProfileInt(_T("Settings"), _T("RecordState"), FALSE))
|
|
||||||
{
|
|
||||||
CPath spath = AfxGetApp()->GetProfileString(_T("Settings"), _T("RecordStatePath"), _T(""));
|
|
||||||
CString fn;
|
|
||||||
fn.Format(_T("gsdx9_%s.gs"), CTime::GetCurrentTime().Format(_T("%Y%m%d%H%M%S")));
|
|
||||||
spath.Append(fn);
|
|
||||||
s_gs->CaptureState(spath);
|
|
||||||
}
|
|
||||||
|
|
||||||
s_hWnd.SetWindowText(CString(Title));
|
|
||||||
|
|
||||||
s_hWnd.Show();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C GSclose()
|
|
||||||
{
|
|
||||||
s_hWnd.Show(false);
|
|
||||||
|
|
||||||
ASSERT(s_gs);
|
|
||||||
s_gs.Free();
|
|
||||||
|
|
||||||
s_hWnd.DestroyWindow();
|
|
||||||
|
|
||||||
if(SUCCEEDED(s_hrCoInit)) ::CoUninitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C GSreset()
|
|
||||||
{
|
|
||||||
s_gs->Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C GSwriteCSR(UINT32 csr)
|
|
||||||
{
|
|
||||||
s_gs->WriteCSR(csr);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C GSreadFIFO(BYTE* pMem)
|
|
||||||
{
|
|
||||||
s_gs->ReadFIFO(pMem);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C GSgifTransfer1(BYTE* pMem, UINT32 addr)
|
|
||||||
{
|
|
||||||
s_gs->Transfer1(pMem, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C GSgifTransfer2(BYTE* pMem, UINT32 size)
|
|
||||||
{
|
|
||||||
s_gs->Transfer2(pMem, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C GSgifTransfer3(BYTE* pMem, UINT32 size)
|
|
||||||
{
|
|
||||||
s_gs->Transfer3(pMem, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern int Path3hack;
|
|
||||||
|
|
||||||
EXPORT_C GSgetLastTag(UINT64* ptag)
|
|
||||||
{
|
|
||||||
*(UINT32*)ptag = Path3hack;
|
|
||||||
Path3hack = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C GSvsync(int field)
|
|
||||||
{
|
|
||||||
MSG msg;
|
|
||||||
ZeroMemory(&msg, sizeof(msg));
|
|
||||||
while(msg.message != WM_QUIT)
|
|
||||||
{
|
|
||||||
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
|
||||||
{
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
// Sleep(40);
|
|
||||||
s_gs->VSync(field);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////
|
|
||||||
|
|
||||||
EXPORT_C_(UINT32) GSmakeSnapshot(char* path)
|
|
||||||
{
|
|
||||||
return s_gs->MakeSnapshot(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EXPORT_C GSkeyEvent(keyEvent* ev)
|
|
||||||
{
|
|
||||||
if(ev->event != KEYPRESS) return;
|
|
||||||
|
|
||||||
switch(ev->key)
|
|
||||||
{
|
|
||||||
case VK_INSERT:
|
|
||||||
s_gs->Capture();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VK_DELETE:
|
|
||||||
s_gs->ToggleOSD();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C_(INT32) GSfreeze(int mode, freezeData* data)
|
|
||||||
{
|
|
||||||
if(mode == FREEZE_SAVE)
|
|
||||||
{
|
|
||||||
return s_gs->Freeze(data, false);
|
|
||||||
}
|
|
||||||
else if(mode == FREEZE_SIZE)
|
|
||||||
{
|
|
||||||
return s_gs->Freeze(data, true);
|
|
||||||
}
|
|
||||||
else if(mode == FREEZE_LOAD)
|
|
||||||
{
|
|
||||||
return s_gs->Defrost(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C GSconfigure()
|
|
||||||
{
|
|
||||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
||||||
|
|
||||||
if(IDOK == CGSSettingsDlg().DoModal())
|
|
||||||
{
|
|
||||||
GSshutdown();
|
|
||||||
GSinit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C_(INT32) GStest()
|
|
||||||
{
|
|
||||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
||||||
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
D3DCAPS9 caps;
|
|
||||||
ZeroMemory(&caps, sizeof(caps));
|
|
||||||
caps.PixelShaderVersion = D3DPS_VERSION(0, 0);
|
|
||||||
|
|
||||||
if(CComPtr<IDirect3D9> pD3D = Direct3DCreate9(D3D_SDK_VERSION))
|
|
||||||
{
|
|
||||||
pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, CGSdx9App::D3DDEVTYPE_X, &caps);
|
|
||||||
|
|
||||||
LPCTSTR yep = _T("^_^"), nope = _T(":'(");
|
|
||||||
|
|
||||||
CString str, tmp;
|
|
||||||
|
|
||||||
if(caps.PixelShaderVersion < D3DPS_VERSION(1, 4))
|
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
tmp.Format(_T("%s Pixel Shader version %d.%d\n"),
|
|
||||||
caps.PixelShaderVersion >= D3DPS_VERSION(1, 4) ? yep : nope,
|
|
||||||
D3DSHADER_VERSION_MAJOR(caps.PixelShaderVersion),
|
|
||||||
D3DSHADER_VERSION_MINOR(caps.PixelShaderVersion));
|
|
||||||
str += tmp;
|
|
||||||
|
|
||||||
if(!(caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND))
|
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
tmp.Format(_T("%s Separate Alpha Blend\n"),
|
|
||||||
!!(caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) ? yep : nope);
|
|
||||||
str += tmp;
|
|
||||||
|
|
||||||
if(!(caps.SrcBlendCaps & D3DPBLENDCAPS_BLENDFACTOR)
|
|
||||||
|| !(caps.DestBlendCaps & D3DPBLENDCAPS_BLENDFACTOR))
|
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
tmp.Format(_T("%s Source Blend Factor\n"),
|
|
||||||
!!(caps.SrcBlendCaps & D3DPBLENDCAPS_BLENDFACTOR) ? yep : nope);
|
|
||||||
str += tmp;
|
|
||||||
|
|
||||||
tmp.Format(_T("%s Destination Blend Factor\n"),
|
|
||||||
!!(caps.DestBlendCaps & D3DPBLENDCAPS_BLENDFACTOR) ? yep : nope);
|
|
||||||
str += tmp;
|
|
||||||
|
|
||||||
AfxMessageBox(str);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C GSabout()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C GSirqCallback(void (*fpGSirq)())
|
|
||||||
{
|
|
||||||
s_fpGSirq = fpGSirq;
|
|
||||||
// if(s_gs) s_gs->GSirq(fpGSirq);
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////
|
|
||||||
/*
|
|
||||||
EXPORT_C GSReplay(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
|
||||||
{
|
|
||||||
if(!GSinit())
|
|
||||||
{
|
|
||||||
HWND hWnd = NULL;
|
|
||||||
if(!GSopen((void*)&hWnd, REPLAY_TITLE))
|
|
||||||
{
|
|
||||||
if(FILE* sfp = _tfopen(lpszCmdLine, _T("rb")))
|
|
||||||
{
|
|
||||||
BYTE* buff = (BYTE*)_aligned_malloc(4*1024*1024, 16);
|
|
||||||
|
|
||||||
while(!feof(sfp))
|
|
||||||
{
|
|
||||||
switch(fgetc(sfp))
|
|
||||||
{
|
|
||||||
case ST_WRITE:
|
|
||||||
{
|
|
||||||
GS_REG mem;
|
|
||||||
UINT64 value, mask;
|
|
||||||
fread(&mem, 4, 1, sfp);
|
|
||||||
fread(&value, 8, 1, sfp);
|
|
||||||
fread(&mask, 8, 1, sfp);
|
|
||||||
switch(mask)
|
|
||||||
{
|
|
||||||
case 0xff: GSwrite8(mem, (UINT8)value); break;
|
|
||||||
case 0xffff: GSwrite16(mem, (UINT16)value); break;
|
|
||||||
case 0xffffffff: GSwrite32(mem, (UINT32)value); break;
|
|
||||||
case 0xffffffffffffffff: GSwrite64(mem, value); break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ST_TRANSFER:
|
|
||||||
{
|
|
||||||
UINT32 size = 0;
|
|
||||||
fread(&size, 4, 1, sfp);
|
|
||||||
UINT32 len = 0;
|
|
||||||
fread(&len, 4, 1, sfp);
|
|
||||||
if(len > 4*1024*1024) {ASSERT(0); break;}
|
|
||||||
fread(buff, len, 1, sfp);
|
|
||||||
GSgifTransfer3(buff, size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ST_VSYNC:
|
|
||||||
GSvsync();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_aligned_free(buff);
|
|
||||||
}
|
|
||||||
|
|
||||||
GSclose();
|
|
||||||
}
|
|
||||||
|
|
||||||
GSshutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -1,945 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
* Special Notes:
|
|
||||||
*
|
|
||||||
* Register definitions and most of the enums originate from sps2dev-0.4.0
|
|
||||||
* Copyright (C) 2002 Terratron Technologies Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
|
|
||||||
//
|
|
||||||
// sps2registers.h
|
|
||||||
//
|
|
||||||
|
|
||||||
enum GS_REG
|
|
||||||
{
|
|
||||||
GS_PMODE = 0x12000000,
|
|
||||||
GS_SMODE1 = 0x12000010,
|
|
||||||
GS_SMODE2 = 0x12000020,
|
|
||||||
GS_SRFSH = 0x12000030,
|
|
||||||
GS_SYNCH1 = 0x12000040,
|
|
||||||
GS_SYNCH2 = 0x12000050,
|
|
||||||
GS_SYNCV = 0x12000060,
|
|
||||||
GS_DISPFB1 = 0x12000070,
|
|
||||||
GS_DISPLAY1 = 0x12000080,
|
|
||||||
GS_DISPFB2 = 0x12000090,
|
|
||||||
GS_DISPLAY2 = 0x120000a0,
|
|
||||||
GS_EXTBUF = 0x120000b0,
|
|
||||||
GS_EXTDATA = 0x120000c0,
|
|
||||||
GS_EXTWRITE = 0x120000d0,
|
|
||||||
GS_BGCOLOR = 0x120000e0,
|
|
||||||
GS_UNKNOWN = 0x12000400,
|
|
||||||
GS_CSR = 0x12001000,
|
|
||||||
GS_IMR = 0x12001010,
|
|
||||||
GS_BUSDIR = 0x12001040,
|
|
||||||
GS_SIGLBLID = 0x12001080
|
|
||||||
};
|
|
||||||
|
|
||||||
enum GS_PRIM
|
|
||||||
{
|
|
||||||
GS_POINTLIST = 0,
|
|
||||||
GS_LINELIST = 1,
|
|
||||||
GS_LINESTRIP = 2,
|
|
||||||
GS_TRIANGLELIST = 3,
|
|
||||||
GS_TRIANGLESTRIP = 4,
|
|
||||||
GS_TRIANGLEFAN = 5,
|
|
||||||
GS_SPRITE = 6,
|
|
||||||
GS_INVALID = 7,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum GIF_REG
|
|
||||||
{
|
|
||||||
GIF_REG_PRIM = 0x00,
|
|
||||||
GIF_REG_RGBA = 0x01,
|
|
||||||
GIF_REG_STQ = 0x02,
|
|
||||||
GIF_REG_UV = 0x03,
|
|
||||||
GIF_REG_XYZF2 = 0x04,
|
|
||||||
GIF_REG_XYZ2 = 0x05,
|
|
||||||
GIF_REG_TEX0_1 = 0x06,
|
|
||||||
GIF_REG_TEX0_2 = 0x07,
|
|
||||||
GIF_REG_CLAMP_1 = 0x08,
|
|
||||||
GIF_REG_CLAMP_2 = 0x09,
|
|
||||||
GIF_REG_FOG = 0x0a,
|
|
||||||
GIF_REG_XYZF3 = 0x0c,
|
|
||||||
GIF_REG_XYZ3 = 0x0d,
|
|
||||||
GIF_REG_A_D = 0x0e,
|
|
||||||
GIF_REG_NOP = 0x0f,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum GIF_A_D_REG
|
|
||||||
{
|
|
||||||
GIF_A_D_REG_PRIM = 0x00,
|
|
||||||
GIF_A_D_REG_RGBAQ = 0x01,
|
|
||||||
GIF_A_D_REG_ST = 0x02,
|
|
||||||
GIF_A_D_REG_UV = 0x03,
|
|
||||||
GIF_A_D_REG_XYZF2 = 0x04,
|
|
||||||
GIF_A_D_REG_XYZ2 = 0x05,
|
|
||||||
GIF_A_D_REG_TEX0_1 = 0x06,
|
|
||||||
GIF_A_D_REG_TEX0_2 = 0x07,
|
|
||||||
GIF_A_D_REG_CLAMP_1 = 0x08,
|
|
||||||
GIF_A_D_REG_CLAMP_2 = 0x09,
|
|
||||||
GIF_A_D_REG_FOG = 0x0a,
|
|
||||||
GIF_A_D_REG_XYZF3 = 0x0c,
|
|
||||||
GIF_A_D_REG_XYZ3 = 0x0d,
|
|
||||||
GIF_A_D_REG_NOP = 0x0f,
|
|
||||||
GIF_A_D_REG_TEX1_1 = 0x14,
|
|
||||||
GIF_A_D_REG_TEX1_2 = 0x15,
|
|
||||||
GIF_A_D_REG_TEX2_1 = 0x16,
|
|
||||||
GIF_A_D_REG_TEX2_2 = 0x17,
|
|
||||||
GIF_A_D_REG_XYOFFSET_1 = 0x18,
|
|
||||||
GIF_A_D_REG_XYOFFSET_2 = 0x19,
|
|
||||||
GIF_A_D_REG_PRMODECONT = 0x1a,
|
|
||||||
GIF_A_D_REG_PRMODE = 0x1b,
|
|
||||||
GIF_A_D_REG_TEXCLUT = 0x1c,
|
|
||||||
GIF_A_D_REG_SCANMSK = 0x22,
|
|
||||||
GIF_A_D_REG_MIPTBP1_1 = 0x34,
|
|
||||||
GIF_A_D_REG_MIPTBP1_2 = 0x35,
|
|
||||||
GIF_A_D_REG_MIPTBP2_1 = 0x36,
|
|
||||||
GIF_A_D_REG_MIPTBP2_2 = 0x37,
|
|
||||||
GIF_A_D_REG_TEXA = 0x3b,
|
|
||||||
GIF_A_D_REG_FOGCOL = 0x3d,
|
|
||||||
GIF_A_D_REG_TEXFLUSH = 0x3f,
|
|
||||||
GIF_A_D_REG_SCISSOR_1 = 0x40,
|
|
||||||
GIF_A_D_REG_SCISSOR_2 = 0x41,
|
|
||||||
GIF_A_D_REG_ALPHA_1 = 0x42,
|
|
||||||
GIF_A_D_REG_ALPHA_2 = 0x43,
|
|
||||||
GIF_A_D_REG_DIMX = 0x44,
|
|
||||||
GIF_A_D_REG_DTHE = 0x45,
|
|
||||||
GIF_A_D_REG_COLCLAMP = 0x46,
|
|
||||||
GIF_A_D_REG_TEST_1 = 0x47,
|
|
||||||
GIF_A_D_REG_TEST_2 = 0x48,
|
|
||||||
GIF_A_D_REG_PABE = 0x49,
|
|
||||||
GIF_A_D_REG_FBA_1 = 0x4a,
|
|
||||||
GIF_A_D_REG_FBA_2 = 0x4b,
|
|
||||||
GIF_A_D_REG_FRAME_1 = 0x4c,
|
|
||||||
GIF_A_D_REG_FRAME_2 = 0x4d,
|
|
||||||
GIF_A_D_REG_ZBUF_1 = 0x4e,
|
|
||||||
GIF_A_D_REG_ZBUF_2 = 0x4f,
|
|
||||||
GIF_A_D_REG_BITBLTBUF = 0x50,
|
|
||||||
GIF_A_D_REG_TRXPOS = 0x51,
|
|
||||||
GIF_A_D_REG_TRXREG = 0x52,
|
|
||||||
GIF_A_D_REG_TRXDIR = 0x53,
|
|
||||||
GIF_A_D_REG_HWREG = 0x54,
|
|
||||||
GIF_A_D_REG_SIGNAL = 0x60,
|
|
||||||
GIF_A_D_REG_FINISH = 0x61,
|
|
||||||
GIF_A_D_REG_LABEL = 0x62,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum GIF_FLG
|
|
||||||
{
|
|
||||||
GIF_FLG_PACKED = 0,
|
|
||||||
GIF_FLG_REGLIST = 1,
|
|
||||||
GIF_FLG_IMAGE = 2,
|
|
||||||
GIF_FLG_IMAGE2 = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
enum PSM
|
|
||||||
{
|
|
||||||
PSM_PSMCT32 = 0,
|
|
||||||
PSM_PSMCT24 = 1,
|
|
||||||
PSM_PSMCT16 = 2,
|
|
||||||
PSM_PSMCT16S = 10,
|
|
||||||
PSM_PSMT8 = 19,
|
|
||||||
PSM_PSMT4 = 20,
|
|
||||||
PSM_PSMT8H = 27,
|
|
||||||
PSM_PSMT4HL = 36,
|
|
||||||
PSM_PSMT4HH = 44,
|
|
||||||
PSM_PSMZ32 = 48,
|
|
||||||
PSM_PSMZ24 = 49,
|
|
||||||
PSM_PSMZ16 = 50,
|
|
||||||
PSM_PSMZ16S = 58,
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// sps2regstructs.h
|
|
||||||
//
|
|
||||||
|
|
||||||
#define REG64(name) \
|
|
||||||
union name \
|
|
||||||
{ \
|
|
||||||
UINT64 i64; \
|
|
||||||
UINT32 ai32[2]; \
|
|
||||||
struct { \
|
|
||||||
|
|
||||||
#define REG128(name)\
|
|
||||||
union name \
|
|
||||||
{ \
|
|
||||||
UINT64 ai64[2]; \
|
|
||||||
UINT32 ai32[4]; \
|
|
||||||
struct { \
|
|
||||||
|
|
||||||
#define REG64_(prefix, name) REG64(prefix##name)
|
|
||||||
#define REG128_(prefix, name) REG128(prefix##name)
|
|
||||||
|
|
||||||
#define REG_END }; };
|
|
||||||
#define REG_END2 };
|
|
||||||
|
|
||||||
#define REG64_SET(name) \
|
|
||||||
union name \
|
|
||||||
{ \
|
|
||||||
UINT64 i64; \
|
|
||||||
UINT32 ai32[2]; \
|
|
||||||
|
|
||||||
#define REG128_SET(name)\
|
|
||||||
union name \
|
|
||||||
{ \
|
|
||||||
UINT64 ai64[2]; \
|
|
||||||
UINT32 ai32[4]; \
|
|
||||||
|
|
||||||
#define REG_SET_END };
|
|
||||||
|
|
||||||
REG64_(GSReg, BGCOLOR)
|
|
||||||
UINT32 R:8;
|
|
||||||
UINT32 G:8;
|
|
||||||
UINT32 B:8;
|
|
||||||
UINT32 _PAD1:8;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GSReg, BUSDIR)
|
|
||||||
UINT32 DIR:1;
|
|
||||||
UINT32 _PAD1:31;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GSReg, CSR)
|
|
||||||
UINT32 rSIGNAL:1;
|
|
||||||
UINT32 rFINISH:1;
|
|
||||||
UINT32 rHSINT:1;
|
|
||||||
UINT32 rVSINT:1;
|
|
||||||
UINT32 rEDWINT:1;
|
|
||||||
UINT32 rZERO1:1;
|
|
||||||
UINT32 rZERO2:1;
|
|
||||||
UINT32 r_PAD1:1;
|
|
||||||
UINT32 rFLUSH:1;
|
|
||||||
UINT32 rRESET:1;
|
|
||||||
UINT32 r_PAD2:2;
|
|
||||||
UINT32 rNFIELD:1;
|
|
||||||
UINT32 rFIELD:1;
|
|
||||||
UINT32 rFIFO:2;
|
|
||||||
UINT32 rREV:8;
|
|
||||||
UINT32 rID:8;
|
|
||||||
UINT32 wSIGNAL:1;
|
|
||||||
UINT32 wFINISH:1;
|
|
||||||
UINT32 wHSINT:1;
|
|
||||||
UINT32 wVSINT:1;
|
|
||||||
UINT32 wEDWINT:1;
|
|
||||||
UINT32 wZERO1:1;
|
|
||||||
UINT32 wZERO2:1;
|
|
||||||
UINT32 w_PAD1:1;
|
|
||||||
UINT32 wFLUSH:1;
|
|
||||||
UINT32 wRESET:1;
|
|
||||||
UINT32 w_PAD2:2;
|
|
||||||
UINT32 wNFIELD:1;
|
|
||||||
UINT32 wFIELD:1;
|
|
||||||
UINT32 wFIFO:2;
|
|
||||||
UINT32 wREV:8;
|
|
||||||
UINT32 wID:8;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GSReg, DISPFB) // (-1/2)
|
|
||||||
UINT32 FBP:9;
|
|
||||||
UINT32 FBW:6;
|
|
||||||
UINT32 PSM:5;
|
|
||||||
UINT32 _PAD:12;
|
|
||||||
UINT32 DBX:11;
|
|
||||||
UINT32 DBY:11;
|
|
||||||
UINT32 _PAD2:10;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GSReg, DISPLAY) // (-1/2)
|
|
||||||
UINT32 DX:12;
|
|
||||||
UINT32 DY:11;
|
|
||||||
UINT32 MAGH:4;
|
|
||||||
UINT32 MAGV:2;
|
|
||||||
UINT32 _PAD:3;
|
|
||||||
UINT32 DW:12;
|
|
||||||
UINT32 DH:11;
|
|
||||||
UINT32 _PAD2:9;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GSReg, EXTBUF)
|
|
||||||
UINT32 EXBP:14;
|
|
||||||
UINT32 EXBW:6;
|
|
||||||
UINT32 FBIN:2;
|
|
||||||
UINT32 WFFMD:1;
|
|
||||||
UINT32 EMODA:2;
|
|
||||||
UINT32 EMODC:2;
|
|
||||||
UINT32 _PAD1:5;
|
|
||||||
UINT32 WDX:11;
|
|
||||||
UINT32 WDY:11;
|
|
||||||
UINT32 _PAD2:10;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GSReg, EXTDATA)
|
|
||||||
UINT32 SX:12;
|
|
||||||
UINT32 SY:11;
|
|
||||||
UINT32 SMPH:4;
|
|
||||||
UINT32 SMPV:2;
|
|
||||||
UINT32 _PAD1:3;
|
|
||||||
UINT32 WW:12;
|
|
||||||
UINT32 WH:11;
|
|
||||||
UINT32 _PAD2:9;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GSReg, EXTWRITE)
|
|
||||||
UINT32 WRITE:1;
|
|
||||||
UINT32 _PAD1:31;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GSReg, IMR)
|
|
||||||
UINT32 _PAD1:8;
|
|
||||||
UINT32 SIGMSK:1;
|
|
||||||
UINT32 FINISHMSK:1;
|
|
||||||
UINT32 HSMSK:1;
|
|
||||||
UINT32 VSMSK:1;
|
|
||||||
UINT32 EDWMSK:1;
|
|
||||||
UINT32 _PAD2:19;
|
|
||||||
UINT32 _PAD3:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GSReg, PMODE)
|
|
||||||
UINT32 EN1:1;
|
|
||||||
UINT32 EN2:1;
|
|
||||||
UINT32 CRTMD:3;
|
|
||||||
UINT32 MMOD:1;
|
|
||||||
UINT32 AMOD:1;
|
|
||||||
UINT32 SLBG:1;
|
|
||||||
UINT32 ALP:8;
|
|
||||||
UINT32 _PAD:16;
|
|
||||||
UINT32 _PAD1:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GSReg, SIGLBLID)
|
|
||||||
UINT32 SIGID:32;
|
|
||||||
UINT32 LBLID:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GSReg, SMODE1)
|
|
||||||
UINT32 RC:3;
|
|
||||||
UINT32 LC:7;
|
|
||||||
UINT32 T1248:2;
|
|
||||||
UINT32 SLCK:1;
|
|
||||||
UINT32 CMOD:2;
|
|
||||||
UINT32 EX:1;
|
|
||||||
UINT32 PRST:1;
|
|
||||||
UINT32 SINT:1;
|
|
||||||
UINT32 XPCK:1;
|
|
||||||
UINT32 PCK2:2;
|
|
||||||
UINT32 SPML:4;
|
|
||||||
UINT32 GCONT:1;
|
|
||||||
UINT32 PHS:1;
|
|
||||||
UINT32 PVS:1;
|
|
||||||
UINT32 PEHS:1;
|
|
||||||
UINT32 PEVS:1;
|
|
||||||
UINT32 CLKSEL:2;
|
|
||||||
UINT32 NVCK:1;
|
|
||||||
UINT32 SLCK2:1;
|
|
||||||
UINT32 VCKSEL:2;
|
|
||||||
UINT32 VHP:1;
|
|
||||||
UINT32 _PAD1:27;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GSReg, SMODE2)
|
|
||||||
UINT32 INT:1;
|
|
||||||
UINT32 FFMD:1;
|
|
||||||
UINT32 DPMS:2;
|
|
||||||
UINT32 _PAD2:28;
|
|
||||||
UINT32 _PAD3:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_SET(GSReg)
|
|
||||||
GSRegBGCOLOR BGCOLOR;
|
|
||||||
GSRegBUSDIR BUSDIR;
|
|
||||||
GSRegCSR CSR;
|
|
||||||
GSRegDISPFB DISPFB;
|
|
||||||
GSRegDISPLAY DISPLAY;
|
|
||||||
GSRegEXTBUF EXTBUF;
|
|
||||||
GSRegEXTDATA EXTDATA;
|
|
||||||
GSRegEXTWRITE EXTWRITE;
|
|
||||||
GSRegIMR IMR;
|
|
||||||
GSRegPMODE PMODE;
|
|
||||||
GSRegSIGLBLID SIGLBLID;
|
|
||||||
GSRegSMODE1 SMODE1;
|
|
||||||
GSRegSMODE2 SMODE2;
|
|
||||||
REG_SET_END
|
|
||||||
|
|
||||||
//
|
|
||||||
// sps2tags.h
|
|
||||||
//
|
|
||||||
|
|
||||||
#define SET_GIF_REG(gifTag, iRegNo, uiValue) \
|
|
||||||
{((GIFTag*)&gifTag)->ai64[1] |= (((uiValue) & 0xf) << ((iRegNo) << 2));}
|
|
||||||
|
|
||||||
#ifdef _M_AMD64
|
|
||||||
#define GET_GIF_REG(tag, reg) \
|
|
||||||
(((tag).ai64[1] >> ((reg) << 2)) & 0xf)
|
|
||||||
#else
|
|
||||||
#define GET_GIF_REG(tag, reg) \
|
|
||||||
(((tag).ai32[2 + ((reg) >> 3)] >> (((reg) & 7) << 2)) & 0xf)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// GIFTag
|
|
||||||
|
|
||||||
REG128(GIFTag)
|
|
||||||
UINT32 NLOOP:15;
|
|
||||||
UINT32 EOP:1;
|
|
||||||
UINT32 _PAD1:16;
|
|
||||||
UINT32 _PAD2:14;
|
|
||||||
UINT32 PRE:1;
|
|
||||||
UINT32 PRIM:11;
|
|
||||||
UINT32 FLG:2; // enum GIF_FLG
|
|
||||||
UINT32 NREG:4;
|
|
||||||
UINT64 REGS:64;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
// GIFReg
|
|
||||||
|
|
||||||
REG64_(GIFReg, ALPHA)
|
|
||||||
UINT32 A:2;
|
|
||||||
UINT32 B:2;
|
|
||||||
UINT32 C:2;
|
|
||||||
UINT32 D:2;
|
|
||||||
UINT32 _PAD1:24;
|
|
||||||
UINT32 FIX:8;
|
|
||||||
UINT32 _PAD2:24;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, BITBLTBUF)
|
|
||||||
UINT32 SBP:14;
|
|
||||||
UINT32 _PAD1:2;
|
|
||||||
UINT32 SBW:6;
|
|
||||||
UINT32 _PAD2:2;
|
|
||||||
UINT32 SPSM:6;
|
|
||||||
UINT32 _PAD3:2;
|
|
||||||
UINT32 DBP:14;
|
|
||||||
UINT32 _PAD4:2;
|
|
||||||
UINT32 DBW:6;
|
|
||||||
UINT32 _PAD5:2;
|
|
||||||
UINT32 DPSM:6;
|
|
||||||
UINT32 _PAD6:2;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, CLAMP)
|
|
||||||
UINT64 WMS:2;
|
|
||||||
UINT64 WMT:2;
|
|
||||||
UINT64 MINU:10;
|
|
||||||
UINT64 MAXU:10;
|
|
||||||
UINT64 MINV:10;
|
|
||||||
UINT64 MAXV:10;
|
|
||||||
UINT64 _PAD:20;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, COLCLAMP)
|
|
||||||
UINT32 CLAMP:1;
|
|
||||||
UINT32 _PAD1:31;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, DIMX)
|
|
||||||
UINT32 DM00:3;
|
|
||||||
UINT32 _PAD00:1;
|
|
||||||
UINT32 DM01:3;
|
|
||||||
UINT32 _PAD01:1;
|
|
||||||
UINT32 DM02:3;
|
|
||||||
UINT32 _PAD02:1;
|
|
||||||
UINT32 DM03:3;
|
|
||||||
UINT32 _PAD03:1;
|
|
||||||
|
|
||||||
UINT32 DM10:3;
|
|
||||||
UINT32 _PAD10:1;
|
|
||||||
UINT32 DM11:3;
|
|
||||||
UINT32 _PAD11:1;
|
|
||||||
UINT32 DM12:3;
|
|
||||||
UINT32 _PAD12:1;
|
|
||||||
UINT32 DM13:3;
|
|
||||||
UINT32 _PAD13:1;
|
|
||||||
|
|
||||||
UINT32 DM20:3;
|
|
||||||
UINT32 _PAD20:1;
|
|
||||||
UINT32 DM21:3;
|
|
||||||
UINT32 _PAD21:1;
|
|
||||||
UINT32 DM22:3;
|
|
||||||
UINT32 _PAD22:1;
|
|
||||||
UINT32 DM23:3;
|
|
||||||
UINT32 _PAD23:1;
|
|
||||||
|
|
||||||
UINT32 DM30:3;
|
|
||||||
UINT32 _PAD30:1;
|
|
||||||
UINT32 DM31:3;
|
|
||||||
UINT32 _PAD31:1;
|
|
||||||
UINT32 DM32:3;
|
|
||||||
UINT32 _PAD32:1;
|
|
||||||
UINT32 DM33:3;
|
|
||||||
UINT32 _PAD33:1;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, DTHE)
|
|
||||||
UINT32 DTHE:1;
|
|
||||||
UINT32 _PAD1:31;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, FBA)
|
|
||||||
UINT32 FBA:1;
|
|
||||||
UINT32 _PAD1:31;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, FINISH)
|
|
||||||
UINT32 _PAD1:32;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, FOG)
|
|
||||||
UINT32 _PAD1:32;
|
|
||||||
UINT32 _PAD2:24;
|
|
||||||
UINT32 F:8;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, FOGCOL)
|
|
||||||
UINT32 FCR:8;
|
|
||||||
UINT32 FCG:8;
|
|
||||||
UINT32 FCB:8;
|
|
||||||
UINT32 _PAD1:8;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, FRAME)
|
|
||||||
UINT32 FBP:9;
|
|
||||||
UINT32 _PAD1:7;
|
|
||||||
UINT32 FBW:6;
|
|
||||||
UINT32 _PAD2:2;
|
|
||||||
UINT32 PSM:6;
|
|
||||||
UINT32 _PAD3:2;
|
|
||||||
UINT32 FBMSK:32;
|
|
||||||
REG_END2
|
|
||||||
UINT32 Block() {return FBP<<5;}
|
|
||||||
REG_END2
|
|
||||||
|
|
||||||
REG64_(GIFReg, HWREG)
|
|
||||||
UINT32 DATA_LOWER:32;
|
|
||||||
UINT32 DATA_UPPER:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, LABEL)
|
|
||||||
UINT32 ID:32;
|
|
||||||
UINT32 IDMSK:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, MIPTBP1)
|
|
||||||
UINT64 TBP1:14;
|
|
||||||
UINT64 TBW1:6;
|
|
||||||
UINT64 TBP2:14;
|
|
||||||
UINT64 TBW2:6;
|
|
||||||
UINT64 TBP3:14;
|
|
||||||
UINT64 TBW3:6;
|
|
||||||
UINT64 _PAD:4;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, MIPTBP2)
|
|
||||||
UINT64 TBP4:14;
|
|
||||||
UINT64 TBW4:6;
|
|
||||||
UINT64 TBP5:14;
|
|
||||||
UINT64 TBW5:6;
|
|
||||||
UINT64 TBP6:14;
|
|
||||||
UINT64 TBW6:6;
|
|
||||||
UINT64 _PAD:4;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, NOP)
|
|
||||||
UINT32 _PAD1:32;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, PABE)
|
|
||||||
UINT32 PABE:1;
|
|
||||||
UINT32 _PAD1:31;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, PRIM)
|
|
||||||
UINT32 PRIM:3;
|
|
||||||
UINT32 IIP:1;
|
|
||||||
UINT32 TME:1;
|
|
||||||
UINT32 FGE:1;
|
|
||||||
UINT32 ABE:1;
|
|
||||||
UINT32 AA1:1;
|
|
||||||
UINT32 FST:1;
|
|
||||||
UINT32 CTXT:1;
|
|
||||||
UINT32 FIX:1;
|
|
||||||
UINT32 _PAD1:21;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, PRMODE)
|
|
||||||
UINT32 _PRIM:3;
|
|
||||||
UINT32 IIP:1;
|
|
||||||
UINT32 TME:1;
|
|
||||||
UINT32 FGE:1;
|
|
||||||
UINT32 ABE:1;
|
|
||||||
UINT32 AA1:1;
|
|
||||||
UINT32 FST:1;
|
|
||||||
UINT32 CTXT:1;
|
|
||||||
UINT32 FIX:1;
|
|
||||||
UINT32 _PAD2:21;
|
|
||||||
UINT32 _PAD3:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, PRMODECONT)
|
|
||||||
UINT32 AC:1;
|
|
||||||
UINT32 _PAD1:31;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, RGBAQ)
|
|
||||||
UINT32 R:8;
|
|
||||||
UINT32 G:8;
|
|
||||||
UINT32 B:8;
|
|
||||||
UINT32 A:8;
|
|
||||||
float Q;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, SCANMSK)
|
|
||||||
UINT32 MSK:2;
|
|
||||||
UINT32 _PAD1:30;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, SCISSOR)
|
|
||||||
UINT32 SCAX0:11;
|
|
||||||
UINT32 _PAD1:5;
|
|
||||||
UINT32 SCAX1:11;
|
|
||||||
UINT32 _PAD2:5;
|
|
||||||
UINT32 SCAY0:11;
|
|
||||||
UINT32 _PAD3:5;
|
|
||||||
UINT32 SCAY1:11;
|
|
||||||
UINT32 _PAD4:5;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, SIGNAL)
|
|
||||||
UINT32 ID:32;
|
|
||||||
UINT32 IDMSK:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, ST)
|
|
||||||
float S;
|
|
||||||
float T;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, TEST)
|
|
||||||
UINT32 ATE:1;
|
|
||||||
UINT32 ATST:3;
|
|
||||||
UINT32 AREF:8;
|
|
||||||
UINT32 AFAIL:2;
|
|
||||||
UINT32 DATE:1;
|
|
||||||
UINT32 DATM:1;
|
|
||||||
UINT32 ZTE:1;
|
|
||||||
UINT32 ZTST:2;
|
|
||||||
UINT32 _PAD1:13;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, TEX0)
|
|
||||||
UINT64 TBP0:14;
|
|
||||||
UINT64 TBW:6;
|
|
||||||
UINT64 PSM:6;
|
|
||||||
UINT64 TW:4;
|
|
||||||
UINT64 TH:4;
|
|
||||||
UINT64 TCC:1;
|
|
||||||
UINT64 TFX:2;
|
|
||||||
UINT64 CBP:14;
|
|
||||||
UINT64 CPSM:4;
|
|
||||||
UINT64 CSM:1;
|
|
||||||
UINT64 CSA:5;
|
|
||||||
UINT64 CLD:3;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, TEX1)
|
|
||||||
UINT32 LCM:1;
|
|
||||||
UINT32 _PAD1:1;
|
|
||||||
UINT32 MXL:3;
|
|
||||||
UINT32 MMAG:1;
|
|
||||||
UINT32 MMIN:3;
|
|
||||||
UINT32 MTBA:1;
|
|
||||||
UINT32 _PAD2:9;
|
|
||||||
UINT32 L:2;
|
|
||||||
UINT32 _PAD3:11;
|
|
||||||
UINT32 K:12;
|
|
||||||
UINT32 _PAD4:20;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, TEX2)
|
|
||||||
UINT32 _PAD1:20;
|
|
||||||
UINT32 PSM:6;
|
|
||||||
UINT32 _PAD2:6;
|
|
||||||
UINT32 _PAD3:5;
|
|
||||||
UINT32 CBP:14;
|
|
||||||
UINT32 CPSM:4;
|
|
||||||
UINT32 CSM:1;
|
|
||||||
UINT32 CSA:5;
|
|
||||||
UINT32 CLD:3;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, TEXA)
|
|
||||||
UINT32 TA0:8;
|
|
||||||
UINT32 _PAD1:7;
|
|
||||||
UINT32 AEM:1;
|
|
||||||
UINT32 _PAD2:16;
|
|
||||||
UINT32 TA1:8;
|
|
||||||
UINT32 _PAD3:24;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, TEXCLUT)
|
|
||||||
UINT32 CBW:6;
|
|
||||||
UINT32 COU:6;
|
|
||||||
UINT32 COV:10;
|
|
||||||
UINT32 _PAD1:10;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, TEXFLUSH)
|
|
||||||
UINT32 _PAD1:32;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, TRXDIR)
|
|
||||||
UINT32 XDIR:2;
|
|
||||||
UINT32 _PAD1:30;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, TRXPOS)
|
|
||||||
UINT32 SSAX:11;
|
|
||||||
UINT32 _PAD1:5;
|
|
||||||
UINT32 SSAY:11;
|
|
||||||
UINT32 _PAD2:5;
|
|
||||||
UINT32 DSAX:11;
|
|
||||||
UINT32 _PAD3:5;
|
|
||||||
UINT32 DSAY:11;
|
|
||||||
UINT32 DIR:2;
|
|
||||||
UINT32 _PAD4:3;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, TRXREG)
|
|
||||||
UINT32 RRW:12;
|
|
||||||
UINT32 _PAD1:20;
|
|
||||||
UINT32 RRH:12;
|
|
||||||
UINT32 _PAD2:20;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, UV)
|
|
||||||
UINT32 U:14;
|
|
||||||
UINT32 _PAD1:2;
|
|
||||||
UINT32 V:14;
|
|
||||||
UINT32 _PAD2:2;
|
|
||||||
UINT32 _PAD3:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, XYOFFSET)
|
|
||||||
UINT32 OFX:16;
|
|
||||||
UINT32 _PAD1:16;
|
|
||||||
UINT32 OFY:16;
|
|
||||||
UINT32 _PAD2:16;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, XYZ)
|
|
||||||
UINT32 X:16;
|
|
||||||
UINT32 Y:16;
|
|
||||||
UINT32 Z:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, XYZF)
|
|
||||||
UINT32 X:16;
|
|
||||||
UINT32 Y:16;
|
|
||||||
UINT32 Z:24;
|
|
||||||
UINT32 F:8;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_(GIFReg, ZBUF)
|
|
||||||
UINT32 ZBP:9;
|
|
||||||
UINT32 _PAD1:15;
|
|
||||||
// UINT32 PSM:4;
|
|
||||||
// UINT32 _PAD2:4;
|
|
||||||
UINT32 PSM:6;
|
|
||||||
UINT32 _PAD2:2;
|
|
||||||
UINT32 ZMSK:1;
|
|
||||||
UINT32 _PAD3:31;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG64_SET(GIFReg)
|
|
||||||
GIFRegALPHA ALPHA;
|
|
||||||
GIFRegBITBLTBUF BITBLTBUF;
|
|
||||||
GIFRegCLAMP CLAMP;
|
|
||||||
GIFRegCOLCLAMP COLCLAMP;
|
|
||||||
GIFRegDIMX DIMX;
|
|
||||||
GIFRegDTHE DTHE;
|
|
||||||
GIFRegFBA FBA;
|
|
||||||
GIFRegFINISH FINISH;
|
|
||||||
GIFRegFOG FOG;
|
|
||||||
GIFRegFOGCOL FOGCOL;
|
|
||||||
GIFRegFRAME FRAME;
|
|
||||||
GIFRegHWREG HWREG;
|
|
||||||
GIFRegLABEL LABEL;
|
|
||||||
GIFRegMIPTBP1 MIPTBP1;
|
|
||||||
GIFRegMIPTBP2 MIPTBP2;
|
|
||||||
GIFRegNOP NOP;
|
|
||||||
GIFRegPABE PABE;
|
|
||||||
GIFRegPRIM PRIM;
|
|
||||||
GIFRegPRMODE PRMODE;
|
|
||||||
GIFRegPRMODECONT PRMODECONT;
|
|
||||||
GIFRegRGBAQ RGBAQ;
|
|
||||||
GIFRegSCANMSK SCANMSK;
|
|
||||||
GIFRegSCISSOR SCISSOR;
|
|
||||||
GIFRegSIGNAL SIGNAL;
|
|
||||||
GIFRegST ST;
|
|
||||||
GIFRegTEST TEST;
|
|
||||||
GIFRegTEX0 TEX0;
|
|
||||||
GIFRegTEX1 TEX1;
|
|
||||||
GIFRegTEX2 TEX2;
|
|
||||||
GIFRegTEXA TEXA;
|
|
||||||
GIFRegTEXCLUT TEXCLUT;
|
|
||||||
GIFRegTEXFLUSH TEXFLUSH;
|
|
||||||
GIFRegTRXDIR TRXDIR;
|
|
||||||
GIFRegTRXPOS TRXPOS;
|
|
||||||
GIFRegTRXREG TRXREG;
|
|
||||||
GIFRegUV UV;
|
|
||||||
GIFRegXYOFFSET XYOFFSET;
|
|
||||||
GIFRegXYZ XYZ;
|
|
||||||
GIFRegXYZF XYZF;
|
|
||||||
GIFRegZBUF ZBUF;
|
|
||||||
REG_SET_END
|
|
||||||
|
|
||||||
// GIFPacked
|
|
||||||
|
|
||||||
REG128_(GIFPacked, PRIM)
|
|
||||||
UINT32 PRIM:11;
|
|
||||||
UINT32 _PAD1:21;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
UINT32 _PAD3:32;
|
|
||||||
UINT32 _PAD4:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG128_(GIFPacked, RGBA)
|
|
||||||
UINT32 R:8;
|
|
||||||
UINT32 _PAD1:24;
|
|
||||||
UINT32 G:8;
|
|
||||||
UINT32 _PAD2:24;
|
|
||||||
UINT32 B:8;
|
|
||||||
UINT32 _PAD3:24;
|
|
||||||
UINT32 A:8;
|
|
||||||
UINT32 _PAD4:24;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG128_(GIFPacked, STQ)
|
|
||||||
float S;
|
|
||||||
float T;
|
|
||||||
float Q;
|
|
||||||
UINT32 _PAD1:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG128_(GIFPacked, UV)
|
|
||||||
UINT32 U:14;
|
|
||||||
UINT32 _PAD1:18;
|
|
||||||
UINT32 V:14;
|
|
||||||
UINT32 _PAD2:18;
|
|
||||||
UINT32 _PAD3:32;
|
|
||||||
UINT32 _PAD4:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG128_(GIFPacked, XYZF2)
|
|
||||||
UINT32 X:16;
|
|
||||||
UINT32 _PAD1:16;
|
|
||||||
UINT32 Y:16;
|
|
||||||
UINT32 _PAD2:16;
|
|
||||||
UINT32 _PAD3:4;
|
|
||||||
UINT32 Z:24;
|
|
||||||
UINT32 _PAD4:4;
|
|
||||||
UINT32 _PAD5:4;
|
|
||||||
UINT32 F:8;
|
|
||||||
UINT32 _PAD6:3;
|
|
||||||
UINT32 ADC:1;
|
|
||||||
UINT32 _PAD7:16;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG128_(GIFPacked, XYZ2)
|
|
||||||
UINT32 X:16;
|
|
||||||
UINT32 _PAD1:16;
|
|
||||||
UINT32 Y:16;
|
|
||||||
UINT32 _PAD2:16;
|
|
||||||
UINT32 Z:32;
|
|
||||||
UINT32 _PAD3:15;
|
|
||||||
UINT32 ADC:1;
|
|
||||||
UINT32 _PAD4:16;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG128_(GIFPacked, FOG)
|
|
||||||
UINT32 _PAD1:32;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
UINT32 _PAD3:32;
|
|
||||||
UINT32 _PAD4:4;
|
|
||||||
UINT32 F:8;
|
|
||||||
UINT32 _PAD5:20;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG128_(GIFPacked, A_D)
|
|
||||||
UINT64 DATA:64;
|
|
||||||
UINT32 ADDR:8; // enum GIF_A_D_REG
|
|
||||||
UINT32 _PAD1:24;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG128_(GIFPacked, NOP)
|
|
||||||
UINT32 _PAD1:32;
|
|
||||||
UINT32 _PAD2:32;
|
|
||||||
UINT32 _PAD3:32;
|
|
||||||
UINT32 _PAD4:32;
|
|
||||||
REG_END
|
|
||||||
|
|
||||||
REG128_SET(GIFPackedReg)
|
|
||||||
GIFReg r;
|
|
||||||
GIFPackedPRIM PRIM;
|
|
||||||
GIFPackedRGBA RGBA;
|
|
||||||
GIFPackedSTQ STQ;
|
|
||||||
GIFPackedUV UV;
|
|
||||||
GIFPackedXYZF2 XYZF2;
|
|
||||||
GIFPackedXYZ2 XYZ2;
|
|
||||||
GIFPackedFOG FOG;
|
|
||||||
GIFPackedA_D A_D;
|
|
||||||
GIFPackedNOP NOP;
|
|
||||||
REG_SET_END
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
enum {KEYPRESS=1, KEYRELEASE=2};
|
|
||||||
struct keyEvent {UINT32 key, event;};
|
|
||||||
|
|
||||||
enum {FREEZE_LOAD=0, FREEZE_SAVE=1, FREEZE_SIZE=2};
|
|
||||||
struct freezeData {int size; BYTE* data;};
|
|
||||||
|
|
||||||
enum stateType {ST_WRITE, ST_TRANSFER, ST_VSYNC};
|
|
|
@ -1,309 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
|
||||||
#include "GSCapture.h"
|
|
||||||
#include "GSCaptureDlg.h"
|
|
||||||
#include <initguid.h>
|
|
||||||
#include <uuids.h>
|
|
||||||
//
|
|
||||||
// GSSource
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifdef __INTEL_COMPILER
|
|
||||||
interface __declspec(uuid("59C193BB-C520-41F3-BC1D-E245B80A86FA"))
|
|
||||||
#else
|
|
||||||
[uuid("59C193BB-C520-41F3-BC1D-E245B80A86FA")] interface
|
|
||||||
#endif
|
|
||||||
IGSSource : public IUnknown
|
|
||||||
{
|
|
||||||
STDMETHOD(DeliverNewSegment)() PURE;
|
|
||||||
STDMETHOD(DeliverFrame)(D3DLOCKED_RECT& r) PURE;
|
|
||||||
STDMETHOD(DeliverEOS)() PURE;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __INTEL_COMPILER
|
|
||||||
class __declspec(uuid("F8BB6F4F-0965-4ED4-BA74-C6A01E6E6C77"))
|
|
||||||
#else
|
|
||||||
[uuid("F8BB6F4F-0965-4ED4-BA74-C6A01E6E6C77")] class
|
|
||||||
#endif
|
|
||||||
GSSource : public CBaseFilter, public IGSSource
|
|
||||||
{
|
|
||||||
CCritSec m_csLock;
|
|
||||||
CAutoPtr<CBaseOutputPin> m_pOutput;
|
|
||||||
CSize m_size;
|
|
||||||
REFERENCE_TIME m_rtAvgTimePerFrame, m_rtNow;
|
|
||||||
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
QI(IGSSource)
|
|
||||||
__super::NonDelegatingQueryInterface(riid, ppv);
|
|
||||||
}
|
|
||||||
|
|
||||||
class GSSourceOutputPin : public CBaseOutputPin
|
|
||||||
{
|
|
||||||
CMediaType m_mt;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSSourceOutputPin(CMediaType& mt, CBaseFilter* pFilter, CCritSec* pLock, HRESULT& hr)
|
|
||||||
: CBaseOutputPin("GSSourceOutputPin", pFilter, pLock, &hr, L"Output")
|
|
||||||
, m_mt(mt)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT GSSourceOutputPin::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
|
|
||||||
{
|
|
||||||
ASSERT(pAlloc && pProperties);
|
|
||||||
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
pProperties->cBuffers = 1;
|
|
||||||
pProperties->cbBuffer = m_mt.lSampleSize;
|
|
||||||
|
|
||||||
ALLOCATOR_PROPERTIES Actual;
|
|
||||||
if(FAILED(hr = pAlloc->SetProperties(pProperties, &Actual))) return hr;
|
|
||||||
|
|
||||||
if(Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;
|
|
||||||
ASSERT(Actual.cBuffers == pProperties->cBuffers);
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT CheckMediaType(const CMediaType* pmt)
|
|
||||||
{
|
|
||||||
return pmt->majortype == MEDIATYPE_Video && pmt->subtype == MEDIASUBTYPE_RGB32 ? S_OK : E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT GetMediaType(int iPosition, CMediaType* pmt)
|
|
||||||
{
|
|
||||||
CheckPointer(pmt, E_POINTER);
|
|
||||||
if(iPosition < 0) return E_INVALIDARG;
|
|
||||||
if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
|
|
||||||
*pmt = m_mt;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP Notify(IBaseFilter* pSender, Quality q)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSSource(int w, int h, int fps, IUnknown* pUnk, HRESULT& hr)
|
|
||||||
: CBaseFilter(NAME("GSSource"), pUnk, &m_csLock, __uuidof(this), &hr)
|
|
||||||
, m_pOutput(NULL)
|
|
||||||
, m_size(w, h)
|
|
||||||
, m_rtAvgTimePerFrame(10000000i64/fps)
|
|
||||||
, m_rtNow(0)
|
|
||||||
{
|
|
||||||
CMediaType mt;
|
|
||||||
|
|
||||||
mt.majortype = MEDIATYPE_Video;
|
|
||||||
mt.subtype = MEDIASUBTYPE_RGB32;
|
|
||||||
mt.formattype = FORMAT_VideoInfo;
|
|
||||||
mt.lSampleSize = w*h*4;
|
|
||||||
|
|
||||||
VIDEOINFOHEADER vih;
|
|
||||||
memset(&vih, 0, sizeof(vih));
|
|
||||||
vih.AvgTimePerFrame = m_rtAvgTimePerFrame;
|
|
||||||
vih.bmiHeader.biSize = sizeof(vih.bmiHeader);
|
|
||||||
vih.bmiHeader.biCompression = BI_RGB;
|
|
||||||
vih.bmiHeader.biPlanes = 1;
|
|
||||||
vih.bmiHeader.biWidth = w;
|
|
||||||
vih.bmiHeader.biHeight = -h;
|
|
||||||
vih.bmiHeader.biBitCount = 32;
|
|
||||||
vih.bmiHeader.biSizeImage = w*h*4;
|
|
||||||
mt.SetFormat((BYTE*)&vih, sizeof(vih));
|
|
||||||
|
|
||||||
m_pOutput.Attach(new GSSourceOutputPin(mt, this, &m_csLock, hr));
|
|
||||||
}
|
|
||||||
|
|
||||||
DECLARE_IUNKNOWN;
|
|
||||||
|
|
||||||
int GetPinCount() {return 1;}
|
|
||||||
CBasePin* GetPin(int n) {return n == 0 ? m_pOutput.m_p : NULL;}
|
|
||||||
|
|
||||||
// IGSSource
|
|
||||||
|
|
||||||
STDMETHODIMP DeliverNewSegment()
|
|
||||||
{
|
|
||||||
return m_pOutput->DeliverNewSegment(m_rtNow = 0, _I64_MAX, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP DeliverFrame(D3DLOCKED_RECT& r)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
if(!m_pOutput || !m_pOutput->IsConnected()) return E_UNEXPECTED;
|
|
||||||
|
|
||||||
CComPtr<IMediaSample> pSample;
|
|
||||||
if(FAILED(hr = m_pOutput->GetDeliveryBuffer(&pSample, NULL, NULL, 0)))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
REFERENCE_TIME rtStart = m_rtNow, rtStop = m_rtNow + m_rtAvgTimePerFrame;
|
|
||||||
|
|
||||||
pSample->SetTime(&rtStart, &rtStop);
|
|
||||||
pSample->SetSyncPoint(TRUE);
|
|
||||||
|
|
||||||
BYTE* pSrc = (BYTE*)r.pBits;
|
|
||||||
int srcpitch = r.Pitch;
|
|
||||||
|
|
||||||
BYTE* pDst = NULL;
|
|
||||||
pSample->GetPointer(&pDst);
|
|
||||||
CMediaType mt;
|
|
||||||
m_pOutput->GetMediaType(0, &mt);
|
|
||||||
int dstpitch = ((VIDEOINFOHEADER*)mt.Format())->bmiHeader.biWidth*4;
|
|
||||||
|
|
||||||
int minpitch = min(srcpitch, dstpitch);
|
|
||||||
|
|
||||||
for(int y = 0; y < m_size.cy; y++, pDst += dstpitch, pSrc += srcpitch)
|
|
||||||
memcpy(pDst, pSrc, minpitch);
|
|
||||||
|
|
||||||
if(FAILED(hr = m_pOutput->Deliver(pSample)))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
m_rtNow = rtStop;
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP DeliverEOS()
|
|
||||||
{
|
|
||||||
return m_pOutput->DeliverEndOfStream();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// GSCapture
|
|
||||||
//
|
|
||||||
|
|
||||||
GSCapture::GSCapture()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GSCapture::BeginCapture(IDirect3DDevice9* pD3Dev, int fps)
|
|
||||||
{
|
|
||||||
ASSERT(pD3Dev != NULL && fps != 0);
|
|
||||||
|
|
||||||
EndCapture();
|
|
||||||
|
|
||||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
||||||
|
|
||||||
GSCaptureDlg dlg;
|
|
||||||
dlg.DoModal();
|
|
||||||
//if(IDOK != dlg.DoModal())
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
int w, h;
|
|
||||||
w = 640, h = 480; // TODO
|
|
||||||
|
|
||||||
CComPtr<IDirect3DSurface9> pRTSurf;
|
|
||||||
if(FAILED(hr = pD3Dev->CreateRenderTarget(w, h, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRTSurf, NULL)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(FAILED(hr = pD3Dev->CreateOffscreenPlainSurface(w, h, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &m_pSysMemSurf, NULL)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
m_pGB.CoCreateInstance(CLSID_FilterGraph);
|
|
||||||
if(!m_pGB) return false;
|
|
||||||
|
|
||||||
CComPtr<ICaptureGraphBuilder2> pCGB;
|
|
||||||
pCGB.CoCreateInstance(CLSID_CaptureGraphBuilder2);
|
|
||||||
if(!pCGB) return false;
|
|
||||||
|
|
||||||
pCGB->SetFiltergraph(m_pGB);
|
|
||||||
|
|
||||||
CComPtr<IBaseFilter> pMux;
|
|
||||||
if(FAILED(hr = pCGB->SetOutputFileName(&MEDIASUBTYPE_Avi, CStringW(dlg.m_filename), &pMux, NULL)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_pSrc = new GSSource(w, h, fps, NULL, hr);
|
|
||||||
if(FAILED(hr = m_pGB->AddFilter(m_pSrc, L"Source")))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(FAILED(hr = m_pGB->AddFilter(dlg.m_pVidEnc, L"Encoder")))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(FAILED(hr = pCGB->RenderStream(NULL, NULL, m_pSrc, dlg.m_pVidEnc, pMux)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
hr = CComQIPtr<IMediaControl>(m_pGB)->Run();
|
|
||||||
|
|
||||||
hr = CComQIPtr<IGSSource>(m_pSrc)->DeliverNewSegment();
|
|
||||||
|
|
||||||
m_pRTSurf = pRTSurf;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GSCapture::BeginFrame(int& w, int& h, IDirect3DSurface9** pRTSurf)
|
|
||||||
{
|
|
||||||
if(!m_pRTSurf || !pRTSurf) return false;
|
|
||||||
|
|
||||||
// FIXME: remember w, h from BeginCapture
|
|
||||||
D3DSURFACE_DESC desc;
|
|
||||||
if(FAILED(m_pRTSurf->GetDesc(&desc))) return false;
|
|
||||||
w = desc.Width;
|
|
||||||
h = desc.Height;
|
|
||||||
|
|
||||||
(*pRTSurf = m_pRTSurf)->AddRef();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GSCapture::EndFrame()
|
|
||||||
{
|
|
||||||
if(m_pRTSurf == NULL || m_pSysMemSurf == NULL) {ASSERT(0); return false;}
|
|
||||||
|
|
||||||
CComPtr<IDirect3DDevice9> pD3DDev;
|
|
||||||
D3DLOCKED_RECT r;
|
|
||||||
|
|
||||||
if(FAILED(m_pRTSurf->GetDevice(&pD3DDev))
|
|
||||||
|| FAILED(pD3DDev->GetRenderTargetData(m_pRTSurf, m_pSysMemSurf))
|
|
||||||
|| FAILED(m_pSysMemSurf->LockRect(&r, NULL, D3DLOCK_READONLY)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CComQIPtr<IGSSource>(m_pSrc)->DeliverFrame(r);
|
|
||||||
|
|
||||||
m_pSysMemSurf->UnlockRect();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GSCapture::EndCapture()
|
|
||||||
{
|
|
||||||
m_pRTSurf = NULL;
|
|
||||||
m_pSysMemSurf = NULL;
|
|
||||||
|
|
||||||
if(m_pSrc) CComQIPtr<IGSSource>(m_pSrc)->DeliverEOS();
|
|
||||||
if(m_pGB) CComQIPtr<IMediaControl>(m_pGB)->Stop();
|
|
||||||
|
|
||||||
m_pSrc = NULL;
|
|
||||||
m_pGB = NULL;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
class GSCapture
|
|
||||||
{
|
|
||||||
CComPtr<IDirect3DSurface9> m_pRTSurf, m_pSysMemSurf;
|
|
||||||
|
|
||||||
CComPtr<IGraphBuilder> m_pGB;
|
|
||||||
CComPtr<IBaseFilter> m_pSrc;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSCapture();
|
|
||||||
|
|
||||||
bool BeginCapture(IDirect3DDevice9* pD3Dev, int fps);
|
|
||||||
bool BeginFrame(int& w, int& h, IDirect3DSurface9** pRTSurf);
|
|
||||||
bool EndFrame();
|
|
||||||
bool EndCapture();
|
|
||||||
|
|
||||||
bool IsCapturing() {return !!m_pRTSurf;}
|
|
||||||
};
|
|
|
@ -1,230 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// GSCaptureDlg.cpp : implementation file
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "stdafx.h"
|
|
||||||
#include <afxpriv.h>
|
|
||||||
#include "GSCaptureDlg.h"
|
|
||||||
|
|
||||||
// GSCaptureDlg dialog
|
|
||||||
|
|
||||||
IMPLEMENT_DYNAMIC(GSCaptureDlg, CDialog)
|
|
||||||
GSCaptureDlg::GSCaptureDlg(CWnd* pParent /*=NULL*/)
|
|
||||||
: CDialog(GSCaptureDlg::IDD, pParent)
|
|
||||||
{
|
|
||||||
m_filename = AfxGetApp()->GetProfileString(_T("Capture"), _T("FileName"));
|
|
||||||
}
|
|
||||||
|
|
||||||
GSCaptureDlg::~GSCaptureDlg()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int GSCaptureDlg::GetSelCodec(Codec& c)
|
|
||||||
{
|
|
||||||
int iSel = m_codeclist.GetCurSel();
|
|
||||||
if(iSel < 0) return 0;
|
|
||||||
|
|
||||||
POSITION pos = (POSITION)m_codeclist.GetItemDataPtr(iSel);
|
|
||||||
if(pos == NULL) return 2;
|
|
||||||
|
|
||||||
c = m_codecs.GetAt(pos);
|
|
||||||
|
|
||||||
if(!c.pBF)
|
|
||||||
{
|
|
||||||
c.pMoniker->BindToObject(NULL, NULL, __uuidof(IBaseFilter), (void**)&c.pBF);
|
|
||||||
if(!c.pBF) return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT GSCaptureDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
LRESULT ret = __super::DefWindowProc(message, wParam, lParam);
|
|
||||||
if(message == WM_INITDIALOG) SendMessage(WM_KICKIDLE);
|
|
||||||
return(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSCaptureDlg::DoDataExchange(CDataExchange* pDX)
|
|
||||||
{
|
|
||||||
__super::DoDataExchange(pDX);
|
|
||||||
DDX_Text(pDX, IDC_EDIT1, m_filename);
|
|
||||||
DDX_Control(pDX, IDC_COMBO1, m_codeclist);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL GSCaptureDlg::OnInitDialog()
|
|
||||||
{
|
|
||||||
__super::OnInitDialog();
|
|
||||||
|
|
||||||
m_codecs.RemoveAll();
|
|
||||||
|
|
||||||
m_codeclist.ResetContent();
|
|
||||||
m_codeclist.SetItemDataPtr(m_codeclist.AddString(_T("Uncompressed")), NULL);
|
|
||||||
|
|
||||||
BeginEnumSysDev(CLSID_VideoCompressorCategory, pMoniker)
|
|
||||||
{
|
|
||||||
Codec c;
|
|
||||||
c.pMoniker = pMoniker;
|
|
||||||
|
|
||||||
LPOLESTR strName = NULL;
|
|
||||||
if(FAILED(pMoniker->GetDisplayName(NULL, NULL, &strName)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
c.DisplayName = strName;
|
|
||||||
CoTaskMemFree(strName);
|
|
||||||
|
|
||||||
CComPtr<IPropertyBag> pPB;
|
|
||||||
pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPB);
|
|
||||||
|
|
||||||
CComVariant var;
|
|
||||||
if(FAILED(pPB->Read(CComBSTR(_T("FriendlyName")), &var, NULL)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
c.FriendlyName = var.bstrVal;
|
|
||||||
|
|
||||||
CStringW str = CStringW(c.DisplayName).MakeLower();
|
|
||||||
if(str.Find(L"@device:dmo:") == 0)
|
|
||||||
c.FriendlyName = _T("(DMO) ") + c.FriendlyName;
|
|
||||||
else if(str.Find(L"@device:sw:") == 0)
|
|
||||||
c.FriendlyName = _T("(DS) ") + c.FriendlyName;
|
|
||||||
else if(str.Find(L"@device:cm:") == 0)
|
|
||||||
c.FriendlyName = _T("(VfW) ") + c.FriendlyName;
|
|
||||||
|
|
||||||
m_codeclist.SetItemDataPtr(m_codeclist.AddString(c.FriendlyName), m_codecs.AddTail(c));
|
|
||||||
}
|
|
||||||
EndEnumSysDev
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
CString DisplayNameToFind = AfxGetApp()->GetProfileString(_T("Capture"), _T("VideoCodecDisplayName"));
|
|
||||||
|
|
||||||
for(int i = 0; i < m_codeclist.GetCount(); i++)
|
|
||||||
{
|
|
||||||
CString DisplayName;
|
|
||||||
|
|
||||||
POSITION pos = (POSITION)m_codeclist.GetItemDataPtr(i);
|
|
||||||
if(pos) DisplayName = m_codecs.GetAt(pos).DisplayName;
|
|
||||||
|
|
||||||
if(DisplayName == DisplayNameToFind)
|
|
||||||
{
|
|
||||||
m_codeclist.SetCurSel(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
UpdateData(FALSE);
|
|
||||||
|
|
||||||
return TRUE; // return TRUE unless you set the focus to a control
|
|
||||||
// EXCEPTION: OCX Property Pages should return FALSE
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN_MESSAGE_MAP(GSCaptureDlg, CDialog)
|
|
||||||
ON_MESSAGE_VOID(WM_KICKIDLE, OnKickIdle)
|
|
||||||
ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
|
|
||||||
ON_BN_CLICKED(IDC_BUTTON2, OnBnClickedButton2)
|
|
||||||
ON_UPDATE_COMMAND_UI(IDC_BUTTON2, OnUpdateButton2)
|
|
||||||
ON_BN_CLICKED(IDOK, OnBnClickedOk)
|
|
||||||
ON_UPDATE_COMMAND_UI(IDOK, OnUpdateOK)
|
|
||||||
END_MESSAGE_MAP()
|
|
||||||
|
|
||||||
// GSCaptureDlg message handlers
|
|
||||||
|
|
||||||
void GSCaptureDlg::OnKickIdle()
|
|
||||||
{
|
|
||||||
UpdateDialogControls(this, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSCaptureDlg::OnBnClickedButton1()
|
|
||||||
{
|
|
||||||
UpdateData();
|
|
||||||
|
|
||||||
CFileDialog fd(FALSE, _T("avi"), m_filename,
|
|
||||||
OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST,
|
|
||||||
_T("Avi files (*.avi)|*.avi||"), this, 0);
|
|
||||||
|
|
||||||
if(fd.DoModal() == IDOK)
|
|
||||||
{
|
|
||||||
m_filename = fd.GetPathName();
|
|
||||||
UpdateData(FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSCaptureDlg::OnBnClickedButton2()
|
|
||||||
{
|
|
||||||
Codec c;
|
|
||||||
if(GetSelCodec(c) != 1) return;
|
|
||||||
|
|
||||||
if(CComQIPtr<ISpecifyPropertyPages> pSPP = c.pBF)
|
|
||||||
{
|
|
||||||
CAUUID caGUID;
|
|
||||||
caGUID.pElems = NULL;
|
|
||||||
if(SUCCEEDED(pSPP->GetPages(&caGUID)))
|
|
||||||
{
|
|
||||||
IUnknown* lpUnk = NULL;
|
|
||||||
pSPP.QueryInterface(&lpUnk);
|
|
||||||
OleCreatePropertyFrame(
|
|
||||||
m_hWnd, 0, 0, CStringW(c.FriendlyName),
|
|
||||||
1, (IUnknown**)&lpUnk,
|
|
||||||
caGUID.cElems, caGUID.pElems,
|
|
||||||
0, 0, NULL);
|
|
||||||
lpUnk->Release();
|
|
||||||
|
|
||||||
if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(CComQIPtr<IAMVfwCompressDialogs> pAMVfWCD = c.pBF)
|
|
||||||
{
|
|
||||||
if(pAMVfWCD->ShowDialog(VfwCompressDialog_QueryConfig, NULL) == S_OK)
|
|
||||||
pAMVfWCD->ShowDialog(VfwCompressDialog_Config, m_hWnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSCaptureDlg::OnUpdateButton2(CCmdUI* pCmdUI)
|
|
||||||
{
|
|
||||||
pCmdUI->Enable(m_codeclist.GetCurSel() >= 0 && m_codeclist.GetItemDataPtr(m_codeclist.GetCurSel()) != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSCaptureDlg::OnBnClickedOk()
|
|
||||||
{
|
|
||||||
UpdateData();
|
|
||||||
|
|
||||||
Codec c;
|
|
||||||
if(GetSelCodec(c) == 0) return;
|
|
||||||
|
|
||||||
m_pVidEnc = c.pBF;
|
|
||||||
|
|
||||||
AfxGetApp()->WriteProfileString(_T("Capture"), _T("FileName"), m_filename);
|
|
||||||
AfxGetApp()->WriteProfileString(_T("Capture"), _T("VideoCodecDisplayName"), CString(c.DisplayName));
|
|
||||||
|
|
||||||
OnOK();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSCaptureDlg::OnUpdateOK(CCmdUI* pCmdUI)
|
|
||||||
{
|
|
||||||
CString str;
|
|
||||||
GetDlgItem(IDC_EDIT1)->GetWindowText(str);
|
|
||||||
|
|
||||||
pCmdUI->Enable(!str.IsEmpty() && m_codeclist.GetCurSel() >= 0);
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "resource.h"
|
|
||||||
#include "afxwin.h"
|
|
||||||
|
|
||||||
// GSCaptureDlg dialog
|
|
||||||
|
|
||||||
class GSCaptureDlg : public CDialog
|
|
||||||
{
|
|
||||||
DECLARE_DYNAMIC(GSCaptureDlg)
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct Codec
|
|
||||||
{
|
|
||||||
CComPtr<IMoniker> pMoniker;
|
|
||||||
CComPtr<IBaseFilter> pBF;
|
|
||||||
CString FriendlyName;
|
|
||||||
CComBSTR DisplayName;
|
|
||||||
};
|
|
||||||
|
|
||||||
CList<Codec> m_codecs;
|
|
||||||
|
|
||||||
int GetSelCodec(Codec& c);
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSCaptureDlg(CWnd* pParent = NULL); // standard constructor
|
|
||||||
virtual ~GSCaptureDlg();
|
|
||||||
|
|
||||||
CComPtr<IBaseFilter> m_pVidEnc;
|
|
||||||
|
|
||||||
// Dialog Data
|
|
||||||
enum { IDD = IDD_CAPTURE };
|
|
||||||
CString m_filename;
|
|
||||||
CComboBox m_codeclist;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);
|
|
||||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
|
||||||
virtual BOOL OnInitDialog();
|
|
||||||
|
|
||||||
DECLARE_MESSAGE_MAP()
|
|
||||||
public:
|
|
||||||
afx_msg void OnKickIdle();
|
|
||||||
afx_msg void OnBnClickedButton1();
|
|
||||||
afx_msg void OnBnClickedButton2();
|
|
||||||
afx_msg void OnUpdateButton2(CCmdUI* pCmdUI);
|
|
||||||
afx_msg void OnBnClickedOk();
|
|
||||||
afx_msg void OnUpdateOK(CCmdUI* pCmdUI);
|
|
||||||
};
|
|
|
@ -1,181 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "stdafx.h"
|
|
||||||
|
|
||||||
static const DWORD s_crctable[256] =
|
|
||||||
{
|
|
||||||
0x00000000l, 0x90910101l, 0x91210201l, 0x01b00300l,
|
|
||||||
0x92410401l, 0x02d00500l, 0x03600600l, 0x93f10701l,
|
|
||||||
0x94810801l, 0x04100900l, 0x05a00a00l, 0x95310b01l,
|
|
||||||
0x06c00c00l, 0x96510d01l, 0x97e10e01l, 0x07700f00l,
|
|
||||||
0x99011001l, 0x09901100l, 0x08201200l, 0x98b11301l,
|
|
||||||
0x0b401400l, 0x9bd11501l, 0x9a611601l, 0x0af01700l,
|
|
||||||
0x0d801800l, 0x9d111901l, 0x9ca11a01l, 0x0c301b00l,
|
|
||||||
0x9fc11c01l, 0x0f501d00l, 0x0ee01e00l, 0x9e711f01l,
|
|
||||||
0x82012001l, 0x12902100l, 0x13202200l, 0x83b12301l,
|
|
||||||
0x10402400l, 0x80d12501l, 0x81612601l, 0x11f02700l,
|
|
||||||
0x16802800l, 0x86112901l, 0x87a12a01l, 0x17302b00l,
|
|
||||||
0x84c12c01l, 0x14502d00l, 0x15e02e00l, 0x85712f01l,
|
|
||||||
0x1b003000l, 0x8b913101l, 0x8a213201l, 0x1ab03300l,
|
|
||||||
0x89413401l, 0x19d03500l, 0x18603600l, 0x88f13701l,
|
|
||||||
0x8f813801l, 0x1f103900l, 0x1ea03a00l, 0x8e313b01l,
|
|
||||||
0x1dc03c00l, 0x8d513d01l, 0x8ce13e01l, 0x1c703f00l,
|
|
||||||
0xb4014001l, 0x24904100l, 0x25204200l, 0xb5b14301l,
|
|
||||||
0x26404400l, 0xb6d14501l, 0xb7614601l, 0x27f04700l,
|
|
||||||
0x20804800l, 0xb0114901l, 0xb1a14a01l, 0x21304b00l,
|
|
||||||
0xb2c14c01l, 0x22504d00l, 0x23e04e00l, 0xb3714f01l,
|
|
||||||
0x2d005000l, 0xbd915101l, 0xbc215201l, 0x2cb05300l,
|
|
||||||
0xbf415401l, 0x2fd05500l, 0x2e605600l, 0xbef15701l,
|
|
||||||
0xb9815801l, 0x29105900l, 0x28a05a00l, 0xb8315b01l,
|
|
||||||
0x2bc05c00l, 0xbb515d01l, 0xbae15e01l, 0x2a705f00l,
|
|
||||||
0x36006000l, 0xa6916101l, 0xa7216201l, 0x37b06300l,
|
|
||||||
0xa4416401l, 0x34d06500l, 0x35606600l, 0xa5f16701l,
|
|
||||||
0xa2816801l, 0x32106900l, 0x33a06a00l, 0xa3316b01l,
|
|
||||||
0x30c06c00l, 0xa0516d01l, 0xa1e16e01l, 0x31706f00l,
|
|
||||||
0xaf017001l, 0x3f907100l, 0x3e207200l, 0xaeb17301l,
|
|
||||||
0x3d407400l, 0xadd17501l, 0xac617601l, 0x3cf07700l,
|
|
||||||
0x3b807800l, 0xab117901l, 0xaaa17a01l, 0x3a307b00l,
|
|
||||||
0xa9c17c01l, 0x39507d00l, 0x38e07e00l, 0xa8717f01l,
|
|
||||||
0xd8018001l, 0x48908100l, 0x49208200l, 0xd9b18301l,
|
|
||||||
0x4a408400l, 0xdad18501l, 0xdb618601l, 0x4bf08700l,
|
|
||||||
0x4c808800l, 0xdc118901l, 0xdda18a01l, 0x4d308b00l,
|
|
||||||
0xdec18c01l, 0x4e508d00l, 0x4fe08e00l, 0xdf718f01l,
|
|
||||||
0x41009000l, 0xd1919101l, 0xd0219201l, 0x40b09300l,
|
|
||||||
0xd3419401l, 0x43d09500l, 0x42609600l, 0xd2f19701l,
|
|
||||||
0xd5819801l, 0x45109900l, 0x44a09a00l, 0xd4319b01l,
|
|
||||||
0x47c09c00l, 0xd7519d01l, 0xd6e19e01l, 0x46709f00l,
|
|
||||||
0x5a00a000l, 0xca91a101l, 0xcb21a201l, 0x5bb0a300l,
|
|
||||||
0xc841a401l, 0x58d0a500l, 0x5960a600l, 0xc9f1a701l,
|
|
||||||
0xce81a801l, 0x5e10a900l, 0x5fa0aa00l, 0xcf31ab01l,
|
|
||||||
0x5cc0ac00l, 0xcc51ad01l, 0xcde1ae01l, 0x5d70af00l,
|
|
||||||
0xc301b001l, 0x5390b100l, 0x5220b200l, 0xc2b1b301l,
|
|
||||||
0x5140b400l, 0xc1d1b501l, 0xc061b601l, 0x50f0b700l,
|
|
||||||
0x5780b800l, 0xc711b901l, 0xc6a1ba01l, 0x5630bb00l,
|
|
||||||
0xc5c1bc01l, 0x5550bd00l, 0x54e0be00l, 0xc471bf01l,
|
|
||||||
0x6c00c000l, 0xfc91c101l, 0xfd21c201l, 0x6db0c300l,
|
|
||||||
0xfe41c401l, 0x6ed0c500l, 0x6f60c600l, 0xfff1c701l,
|
|
||||||
0xf881c801l, 0x6810c900l, 0x69a0ca00l, 0xf931cb01l,
|
|
||||||
0x6ac0cc00l, 0xfa51cd01l, 0xfbe1ce01l, 0x6b70cf00l,
|
|
||||||
0xf501d001l, 0x6590d100l, 0x6420d200l, 0xf4b1d301l,
|
|
||||||
0x6740d400l, 0xf7d1d501l, 0xf661d601l, 0x66f0d700l,
|
|
||||||
0x6180d800l, 0xf111d901l, 0xf0a1da01l, 0x6030db00l,
|
|
||||||
0xf3c1dc01l, 0x6350dd00l, 0x62e0de00l, 0xf271df01l,
|
|
||||||
0xee01e001l, 0x7e90e100l, 0x7f20e200l, 0xefb1e301l,
|
|
||||||
0x7c40e400l, 0xecd1e501l, 0xed61e601l, 0x7df0e700l,
|
|
||||||
0x7a80e800l, 0xea11e901l, 0xeba1ea01l, 0x7b30eb00l,
|
|
||||||
0xe8c1ec01l, 0x7850ed00l, 0x79e0ee00l, 0xe971ef01l,
|
|
||||||
0x7700f000l, 0xe791f101l, 0xe621f201l, 0x76b0f300l,
|
|
||||||
0xe541f401l, 0x75d0f500l, 0x7460f600l, 0xe4f1f701l,
|
|
||||||
0xe381f801l, 0x7310f900l, 0x72a0fa00l, 0xe231fb01l,
|
|
||||||
0x71c0fc00l, 0xe151fd01l, 0xe0e1fe01l, 0x7070ff00l
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD hash_crc(const CRect& r, int pitch, BYTE* p)
|
|
||||||
{
|
|
||||||
if(r.Width() == 0) {ASSERT(0); return 0;}
|
|
||||||
|
|
||||||
DWORD hash = 0xffffffff;
|
|
||||||
|
|
||||||
for(int j = r.top; j < r.bottom; j++, p += pitch)
|
|
||||||
{
|
|
||||||
for(int i = r.left, x = 0; i < r.right; i++, x += 4)
|
|
||||||
{
|
|
||||||
hash = s_crctable[(hash ^ p[x+0]) & 0xff] ^ (hash >> 8);
|
|
||||||
hash = s_crctable[(hash ^ p[x+1]) & 0xff] ^ (hash >> 8);
|
|
||||||
hash = s_crctable[(hash ^ p[x+2]) & 0xff] ^ (hash >> 8);
|
|
||||||
hash = s_crctable[(hash ^ p[x+3]) & 0xff] ^ (hash >> 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MOD_ADLER 65521
|
|
||||||
|
|
||||||
DWORD hash_adler(const CRect& r, int pitch, BYTE* p)
|
|
||||||
{
|
|
||||||
if(r.Width() == 0) {ASSERT(0); return 0;}
|
|
||||||
|
|
||||||
DWORD a = 1, b = 0;
|
|
||||||
|
|
||||||
for(int j = r.top; j < r.bottom; j++, p += pitch)
|
|
||||||
{
|
|
||||||
for(int i = r.left, x = 0; i < r.right; i++, x += 4)
|
|
||||||
{
|
|
||||||
a += p[x+0]; b += a;
|
|
||||||
a += p[x+1]; b += a;
|
|
||||||
a += p[x+2]; b += a;
|
|
||||||
a += p[x+3]; b += a;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER);
|
|
||||||
b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER);
|
|
||||||
}
|
|
||||||
|
|
||||||
// a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER);
|
|
||||||
if(a >= MOD_ADLER) a -= MOD_ADLER;
|
|
||||||
b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER);
|
|
||||||
if(b >= MOD_ADLER) b -= MOD_ADLER;
|
|
||||||
|
|
||||||
return b << 16 | a;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD hash_checksum(const CRect& r, int pitch, BYTE* p)
|
|
||||||
{
|
|
||||||
if(r.Width() == 0) {ASSERT(0); return 0;}
|
|
||||||
|
|
||||||
DWORD hash = 0;
|
|
||||||
|
|
||||||
#if defined(_M_AMD64) || _M_IX86_FP >= 2
|
|
||||||
if(r.Width() >= 4 && !((DWORD_PTR)p & 0xf) && !(pitch & 0xf))
|
|
||||||
{
|
|
||||||
__m128i hash128 = _mm_setzero_si128();
|
|
||||||
for(int j = r.top; j < r.bottom; j++, p += pitch)
|
|
||||||
{
|
|
||||||
hash128 = _mm_add_epi32(hash128, _mm_set1_epi32(j));
|
|
||||||
for(int i = r.left, x = 0; i < r.right; i += 4, x++)
|
|
||||||
{
|
|
||||||
hash128 = _mm_shuffle_epi32(hash128, 0x93);
|
|
||||||
////hash128 = _mm_shufflelo_epi16(hash128, 0x93);
|
|
||||||
//hash128 = _mm_shufflehi_epi16(hash128, 0x93);
|
|
||||||
hash128 = _mm_add_epi32(hash128, _mm_load_si128(&((__m128i*)p)[x]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hash128 = _mm_add_epi32(hash128, _mm_srli_si128(hash128, 8));
|
|
||||||
hash128 = _mm_add_epi32(hash128, _mm_srli_si128(hash128, 4));
|
|
||||||
hash += _mm_cvtsi128_si32(hash128);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
for(int j = r.top; j < r.bottom; j++, p += pitch)
|
|
||||||
{
|
|
||||||
hash += j;
|
|
||||||
for(int i = r.left, x = 0; i < r.right; i++, x++)
|
|
||||||
{
|
|
||||||
hash += ((DWORD*)p)[x];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
extern DWORD hash_crc(const CRect& r, int pitch, BYTE* p);
|
|
||||||
extern DWORD hash_adler(const CRect& r, int pitch, BYTE* p);
|
|
||||||
extern DWORD hash_checksum(const CRect& r, int pitch, BYTE* p);
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,321 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#pragma warning(disable: 4244) // warning C4244: '=' : conversion from 'const UINT64' to 'int', possible loss of data
|
|
||||||
|
|
||||||
#include "GS.h"
|
|
||||||
#include "GSTables.h"
|
|
||||||
|
|
||||||
class GSLocalMemory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef DWORD (__fastcall *pixelAddress)(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
typedef void (GSLocalMemory::*writePixel)(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
typedef void (GSLocalMemory::*writeFrame)(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
typedef DWORD (GSLocalMemory::*readPixel)(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
typedef DWORD (GSLocalMemory::*readTexel)(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
typedef void (GSLocalMemory::*writePixelAddr)(DWORD addr, DWORD c);
|
|
||||||
typedef void (GSLocalMemory::*writeFrameAddr)(DWORD addr, DWORD c);
|
|
||||||
typedef DWORD (GSLocalMemory::*readPixelAddr)(DWORD addr);
|
|
||||||
typedef DWORD (GSLocalMemory::*readTexelAddr)(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
typedef void (GSLocalMemory::*SwizzleTexture)(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
|
|
||||||
typedef void (GSLocalMemory::*unSwizzleTexture)(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
typedef void (GSLocalMemory::*readTexture)(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA, GIFRegCLAMP& CLAMP);
|
|
||||||
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
pixelAddress pa, ba, pga;
|
|
||||||
readPixel rp;
|
|
||||||
readPixelAddr rpa;
|
|
||||||
writePixel wp;
|
|
||||||
writePixelAddr wpa;
|
|
||||||
readTexel rt, rtP, rtNP;
|
|
||||||
readTexelAddr rta;
|
|
||||||
writeFrameAddr wfa;
|
|
||||||
SwizzleTexture st;
|
|
||||||
unSwizzleTexture ust, ustP, ustNP;
|
|
||||||
DWORD bpp, pal, trbpp;
|
|
||||||
CSize bs;
|
|
||||||
int* rowOffset[8];
|
|
||||||
};
|
|
||||||
BYTE dummy[128];
|
|
||||||
} psmtbl_t;
|
|
||||||
|
|
||||||
static psmtbl_t m_psmtbl[64];
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static DWORD pageOffset32[32][32][64];
|
|
||||||
static DWORD pageOffset32Z[32][32][64];
|
|
||||||
static DWORD pageOffset16[32][64][64];
|
|
||||||
static DWORD pageOffset16S[32][64][64];
|
|
||||||
static DWORD pageOffset16Z[32][64][64];
|
|
||||||
static DWORD pageOffset16SZ[32][64][64];
|
|
||||||
static DWORD pageOffset8[32][64][128];
|
|
||||||
static DWORD pageOffset4[32][128][128];
|
|
||||||
|
|
||||||
static int rowOffset32[2048];
|
|
||||||
static int rowOffset32Z[2048];
|
|
||||||
static int rowOffset16[2048];
|
|
||||||
static int rowOffset16S[2048];
|
|
||||||
static int rowOffset16Z[2048];
|
|
||||||
static int rowOffset16SZ[2048];
|
|
||||||
static int rowOffset8[2][2048];
|
|
||||||
static int rowOffset4[2][2048];
|
|
||||||
|
|
||||||
union {BYTE* m_vm8; WORD* m_vm16; DWORD* m_vm32;};
|
|
||||||
|
|
||||||
DWORD m_CBP[2];
|
|
||||||
WORD* m_pCLUT;
|
|
||||||
DWORD* m_pCLUT32;
|
|
||||||
UINT64* m_pCLUT64;
|
|
||||||
|
|
||||||
GIFRegTEX0 m_prevTEX0;
|
|
||||||
GIFRegTEXCLUT m_prevTEXCLUT;
|
|
||||||
bool m_fCLUTMayBeDirty;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSLocalMemory();
|
|
||||||
virtual ~GSLocalMemory();
|
|
||||||
|
|
||||||
static void RoundDown(CSize& s, CSize bs);
|
|
||||||
static void RoundUp(CSize& s, CSize bs);
|
|
||||||
|
|
||||||
static DWORD Expand24To32(DWORD c, BYTE TCC, GIFRegTEXA& TEXA)
|
|
||||||
{
|
|
||||||
BYTE A = (!TEXA.AEM|(c&0xffffff)) ? TEXA.TA0 : 0;
|
|
||||||
return (A<<24) | (c&0xffffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DWORD Expand16To32(WORD c, GIFRegTEXA& TEXA)
|
|
||||||
{
|
|
||||||
BYTE A = (c&0x8000) ? TEXA.TA1 : (!TEXA.AEM|c) ? TEXA.TA0 : 0;
|
|
||||||
return (A << 24) | ((c&0x7c00) << 9) | ((c&0x03e0) << 6) | ((c&0x001f) << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
BYTE* GetVM() {return m_vm8;}
|
|
||||||
|
|
||||||
// address
|
|
||||||
|
|
||||||
static DWORD __fastcall pageAddress32(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pageAddress16(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pageAddress8(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pageAddress4(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
|
|
||||||
static DWORD __fastcall blockAddress32(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall blockAddress16(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall blockAddress16S(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall blockAddress8(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall blockAddress4(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall blockAddress32Z(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall blockAddress16Z(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall blockAddress16SZ(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
|
|
||||||
static DWORD __fastcall pixelAddressOrg32(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddressOrg16(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddressOrg16S(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddressOrg8(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddressOrg4(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddressOrg32Z(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddressOrg16Z(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddressOrg16SZ(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
|
|
||||||
static DWORD __fastcall pixelAddress32(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddress16(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddress16S(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddress8(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddress4(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddress32Z(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddress16Z(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
static DWORD __fastcall pixelAddress16SZ(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
|
|
||||||
// raw pixel R/W
|
|
||||||
|
|
||||||
void writePixel32(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
void writePixel24(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
void writePixel16(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
void writePixel16S(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
void writePixel8(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
void writePixel8H(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
void writePixel4(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
void writePixel4HL(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
void writePixel4HH(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
void writePixel32Z(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
void writePixel24Z(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
void writePixel16Z(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
void writePixel16SZ(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
|
|
||||||
void writeFrame16(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
void writeFrame16S(int x, int y, DWORD c, DWORD bp, DWORD bw);
|
|
||||||
|
|
||||||
DWORD readPixel32(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
DWORD readPixel24(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
DWORD readPixel16(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
DWORD readPixel16S(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
DWORD readPixel8(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
DWORD readPixel8H(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
DWORD readPixel4(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
DWORD readPixel4HL(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
DWORD readPixel4HH(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
DWORD readPixel32Z(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
DWORD readPixel24Z(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
DWORD readPixel16Z(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
DWORD readPixel16SZ(int x, int y, DWORD bp, DWORD bw);
|
|
||||||
|
|
||||||
void writePixel32(DWORD addr, DWORD c) {m_vm32[addr] = c;}
|
|
||||||
void writePixel24(DWORD addr, DWORD c) {m_vm32[addr] = (m_vm32[addr] & 0xff000000) | (c & 0x00ffffff);}
|
|
||||||
void writePixel16(DWORD addr, DWORD c) {m_vm16[addr] = (WORD)c;}
|
|
||||||
void writePixel16S(DWORD addr, DWORD c) {m_vm16[addr] = (WORD)c;}
|
|
||||||
void writePixel8(DWORD addr, DWORD c) {m_vm8[addr] = (BYTE)c;}
|
|
||||||
void writePixel8H(DWORD addr, DWORD c) {m_vm32[addr] = (m_vm32[addr] & 0x00ffffff) | (c << 24);}
|
|
||||||
void writePixel4(DWORD addr, DWORD c) {int shift = (addr&1) << 2; addr >>= 1; m_vm8[addr] = (BYTE)((m_vm8[addr] & (0xf0 >> shift)) | ((c & 0x0f) << shift));}
|
|
||||||
void writePixel4HL(DWORD addr, DWORD c) {m_vm32[addr] = (m_vm32[addr] & 0xf0ffffff) | ((c & 0x0f) << 24);}
|
|
||||||
void writePixel4HH(DWORD addr, DWORD c) {m_vm32[addr] = (m_vm32[addr] & 0x0fffffff) | ((c & 0x0f) << 28);}
|
|
||||||
void writePixel32Z(DWORD addr, DWORD c) {m_vm32[addr] = c;}
|
|
||||||
void writePixel24Z(DWORD addr, DWORD c) {m_vm32[addr] = (m_vm32[addr] & 0xff000000) | (c & 0x00ffffff);}
|
|
||||||
void writePixel16Z(DWORD addr, DWORD c) {m_vm16[addr] = (WORD)c;}
|
|
||||||
void writePixel16SZ(DWORD addr, DWORD c) {m_vm16[addr] = (WORD)c;}
|
|
||||||
|
|
||||||
void writeFrame16(DWORD addr, DWORD c) {writePixel16(addr, ((c>>16)&0x8000)|((c>>9)&0x7c00)|((c>>6)&0x03e0)|((c>>3)&0x001f));}
|
|
||||||
void writeFrame16S(DWORD addr, DWORD c) {writePixel16S(addr, ((c>>16)&0x8000)|((c>>9)&0x7c00)|((c>>6)&0x03e0)|((c>>3)&0x001f));}
|
|
||||||
|
|
||||||
DWORD readPixel32(DWORD addr) {return m_vm32[addr];}
|
|
||||||
DWORD readPixel24(DWORD addr) {return m_vm32[addr] & 0x00ffffff;}
|
|
||||||
DWORD readPixel16(DWORD addr) {return (DWORD)m_vm16[addr];}
|
|
||||||
DWORD readPixel16S(DWORD addr) {return (DWORD)m_vm16[addr];}
|
|
||||||
DWORD readPixel8(DWORD addr) {return (DWORD)m_vm8[addr];}
|
|
||||||
DWORD readPixel8H(DWORD addr) {return m_vm32[addr] >> 24;}
|
|
||||||
DWORD readPixel4(DWORD addr) {return (m_vm8[addr>>1] >> ((addr&1) << 2)) & 0x0f;}
|
|
||||||
DWORD readPixel4HL(DWORD addr) {return (m_vm32[addr] >> 24) & 0x0f;}
|
|
||||||
DWORD readPixel4HH(DWORD addr) {return (m_vm32[addr] >> 28) & 0x0f;}
|
|
||||||
DWORD readPixel32Z(DWORD addr) {return m_vm32[addr];}
|
|
||||||
DWORD readPixel24Z(DWORD addr) {return m_vm32[addr] & 0x00ffffff;}
|
|
||||||
DWORD readPixel16Z(DWORD addr) {return (DWORD)m_vm16[addr];}
|
|
||||||
DWORD readPixel16SZ(DWORD addr) {return (DWORD)m_vm16[addr];}
|
|
||||||
|
|
||||||
// FillRect
|
|
||||||
|
|
||||||
bool FillRect(const CRect& r, DWORD c, DWORD psm, DWORD fbp, DWORD fbw);
|
|
||||||
|
|
||||||
// CLUT
|
|
||||||
|
|
||||||
void InvalidateCLUT() {m_fCLUTMayBeDirty = true;}
|
|
||||||
void WriteCLUT(GIFRegTEX0 TEX0, GIFRegTEXCLUT TEXCLUT);
|
|
||||||
|
|
||||||
void ReadCLUT(GIFRegTEX0 TEX0, GIFRegTEXA TEXA, DWORD* pCLUT32);
|
|
||||||
void SetupCLUT(GIFRegTEX0 TEX0, GIFRegTEXA TEXA);
|
|
||||||
|
|
||||||
// expands 16->32
|
|
||||||
void ReadCLUT32(GIFRegTEX0 TEX0, GIFRegTEXA TEXA, DWORD* pCLUT32);
|
|
||||||
void SetupCLUT32(GIFRegTEX0 TEX0, GIFRegTEXA TEXA);
|
|
||||||
void CopyCLUT32(DWORD* pCLUT32, int nPaletteEntries);
|
|
||||||
|
|
||||||
// 32-only
|
|
||||||
|
|
||||||
DWORD readTexel32(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel24(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel16(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel16S(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel8(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel8H(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel4(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel4HL(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel4HH(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
|
|
||||||
DWORD readTexel32(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA) {return m_vm32[addr];}
|
|
||||||
DWORD readTexel24(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA) {return Expand24To32(m_vm32[addr], TEX0.ai32[1]&4, TEXA);}
|
|
||||||
DWORD readTexel16(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA) {return Expand16To32(m_vm16[addr], TEXA);}
|
|
||||||
DWORD readTexel16S(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA) {return Expand16To32(m_vm16[addr], TEXA);}
|
|
||||||
DWORD readTexel8(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA) {return m_pCLUT32[readPixel8(addr)];}
|
|
||||||
DWORD readTexel8H(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA) {return m_pCLUT32[readPixel8H(addr)];}
|
|
||||||
DWORD readTexel4(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA) {return m_pCLUT32[readPixel4(addr)];}
|
|
||||||
DWORD readTexel4HL(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA) {return m_pCLUT32[readPixel4HL(addr)];}
|
|
||||||
DWORD readTexel4HH(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA) {return m_pCLUT32[readPixel4HH(addr)];}
|
|
||||||
|
|
||||||
void SwizzleTexture32(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
|
|
||||||
void SwizzleTexture24(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
|
|
||||||
void SwizzleTexture16(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
|
|
||||||
void SwizzleTexture16S(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
|
|
||||||
void SwizzleTexture8(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
|
|
||||||
void SwizzleTexture8H(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
|
|
||||||
void SwizzleTexture4(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
|
|
||||||
void SwizzleTexture4HL(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
|
|
||||||
void SwizzleTexture4HH(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
|
|
||||||
void SwizzleTextureX(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
|
|
||||||
|
|
||||||
void unSwizzleTexture32(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture24(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture16(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture16S(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture8(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture8H(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture4(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture4HL(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture4HH(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
|
|
||||||
void ReadTexture(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA, GIFRegCLAMP& CLAMP);
|
|
||||||
|
|
||||||
// 32/16/8P
|
|
||||||
|
|
||||||
DWORD readTexel16P(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel16SP(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel8P(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel8HP(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel4P(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel4HLP(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
DWORD readTexel4HHP(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
|
|
||||||
void unSwizzleTexture16P(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture16SP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture8P(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture8HP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture4P(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture4HLP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture4HHP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
|
|
||||||
void ReadTextureP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA, GIFRegCLAMP& CLAMP);
|
|
||||||
|
|
||||||
// 32/16
|
|
||||||
|
|
||||||
void unSwizzleTexture8NP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture8HNP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture4NP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture4HLNP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
void unSwizzleTexture4HHNP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA);
|
|
||||||
|
|
||||||
void ReadTextureNP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA, GIFRegCLAMP& CLAMP);
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
static DWORD m_xtbl[1024], m_ytbl[1024];
|
|
||||||
|
|
||||||
template<typename DstT>
|
|
||||||
void ReadTexture(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA, GIFRegCLAMP& CLAMP, readTexel rt, unSwizzleTexture st);
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
HRESULT SaveBMP(IDirect3DDevice9* pDev, LPCTSTR fn, DWORD bp, DWORD bw, DWORD psm, int w, int h);
|
|
||||||
};
|
|
||||||
|
|
||||||
#pragma warning(default: 4244)
|
|
|
@ -1,109 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
|
||||||
#include "GSPerfMon.h"
|
|
||||||
|
|
||||||
#if _MSC_VER >= 1400
|
|
||||||
extern "C" unsigned __int64 __rdtsc();
|
|
||||||
#else
|
|
||||||
__declspec(naked) unsigned __int64 __rdtsc() {__asm rdtsc __asm ret}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GSPerfMon::GSPerfMon()
|
|
||||||
: m_total(0), m_begin(0)
|
|
||||||
, m_frame(0), m_lastframe(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSPerfMon::IncCounter(counter_t c, double val)
|
|
||||||
{
|
|
||||||
if(c == c_frame)
|
|
||||||
{
|
|
||||||
clock_t now = clock();
|
|
||||||
if(m_lastframe != 0)
|
|
||||||
m_counters[c].AddTail(now - m_lastframe);
|
|
||||||
m_lastframe = now;
|
|
||||||
m_frame++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_counters[c].AddTail(val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSPerfMon::StartTimer()
|
|
||||||
{
|
|
||||||
m_start = __rdtsc();
|
|
||||||
if(m_begin == 0) m_begin = m_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSPerfMon::StopTimer()
|
|
||||||
{
|
|
||||||
if(m_start > 0)
|
|
||||||
{
|
|
||||||
m_total += __rdtsc() - m_start;
|
|
||||||
m_start = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CString GSPerfMon::ToString(double expected_fps)
|
|
||||||
{
|
|
||||||
if(m_counters[c_frame].IsEmpty())
|
|
||||||
return _T("");
|
|
||||||
|
|
||||||
double stats[c_last];
|
|
||||||
|
|
||||||
for(int i = 0; i < countof(m_counters); i++)
|
|
||||||
{
|
|
||||||
double sum = 0;
|
|
||||||
POSITION pos = m_counters[i].GetHeadPosition();
|
|
||||||
while(pos) sum += m_counters[i].GetNext(pos);
|
|
||||||
stats[i] = sum / m_counters[c_frame].GetCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT64 start = m_start;
|
|
||||||
|
|
||||||
if(start > 0) StopTimer();
|
|
||||||
|
|
||||||
double fps = 1000.0 / stats[c_frame];
|
|
||||||
double cpu = 100.0 * m_total / (__rdtsc() - m_begin);
|
|
||||||
|
|
||||||
CString str;
|
|
||||||
|
|
||||||
str.Format(_T("frame: %I64d | cpu: %d%% | %.2f fps (%d%%) | %d ppf | %.2f kbpf | %.2f kbpf | %.2f kbpf"),
|
|
||||||
m_frame,
|
|
||||||
(int)(cpu),
|
|
||||||
(float)(fps),
|
|
||||||
(int)(100.0 * fps / expected_fps),
|
|
||||||
(int)(stats[c_prim]),
|
|
||||||
(float)(stats[c_swizzle] / 1024),
|
|
||||||
(float)(stats[c_unswizzle] / 1024),
|
|
||||||
(float)(stats[c_texture] / 1024));
|
|
||||||
|
|
||||||
for(int i = 0; i < countof(m_counters); i++)
|
|
||||||
m_counters[i].RemoveAll();
|
|
||||||
m_total = m_begin = 0;
|
|
||||||
|
|
||||||
if(start > 0) StartTimer();
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "x86.h"
|
|
||||||
|
|
||||||
class GSPerfMon
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum counter_t {c_frame, c_prim, c_swizzle, c_unswizzle, c_texture, c_last};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
CAtlList<double> m_counters[c_last];
|
|
||||||
UINT64 m_begin, m_total, m_start, m_frame;
|
|
||||||
clock_t m_lastframe;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSPerfMon();
|
|
||||||
|
|
||||||
void IncCounter(counter_t c, double val = 0);
|
|
||||||
void StartTimer(), StopTimer();
|
|
||||||
CString ToString(double expected_fps);
|
|
||||||
UINT64 GetFrame() {return m_frame;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GSPerfMonAutoTimer
|
|
||||||
{
|
|
||||||
GSPerfMon* m_pm;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSPerfMonAutoTimer(GSPerfMon& pm) {(m_pm = &pm)->StartTimer();}
|
|
||||||
~GSPerfMonAutoTimer() {m_pm->StopTimer();}
|
|
||||||
};
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,23 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
|
||||||
#include "GSRenderer.h"
|
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "GSState.h"
|
|
||||||
|
|
||||||
template <class VERTEX>
|
|
||||||
class GSRenderer : public GSState
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
GSVertexList<VERTEX> m_vl;
|
|
||||||
|
|
||||||
VERTEX* m_pVertices;
|
|
||||||
int m_nMaxVertices, m_nVertices, m_nPrims;
|
|
||||||
|
|
||||||
void Reset()
|
|
||||||
{
|
|
||||||
m_nVertices = m_nPrims = 0;
|
|
||||||
m_vl.RemoveAll();
|
|
||||||
__super::Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VertexKick(bool fSkip)
|
|
||||||
{
|
|
||||||
LOG(_T("VertexKick(%d)\n"), fSkip);
|
|
||||||
|
|
||||||
static const int vmin[8] = {1, 2, 2, 3, 3, 3, 2, 1};
|
|
||||||
|
|
||||||
while(m_vl.GetCount() >= vmin[m_pPRIM->PRIM])
|
|
||||||
{
|
|
||||||
if(m_nVertices+6 > m_nMaxVertices)
|
|
||||||
{
|
|
||||||
VERTEX* pVertices = (VERTEX*)_aligned_malloc(sizeof(VERTEX) * (m_nMaxVertices <<= 1), 16);
|
|
||||||
memcpy(pVertices, m_pVertices, m_nVertices*sizeof(VERTEX));
|
|
||||||
_aligned_free(m_pVertices);
|
|
||||||
m_pVertices = pVertices;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(_T("DrawingKick %d\n"), m_pPRIM->PRIM);
|
|
||||||
|
|
||||||
if(m_PRIM != m_pPRIM->PRIM && m_nVertices > 0) FlushPrimInternal();
|
|
||||||
m_PRIM = m_pPRIM->PRIM;
|
|
||||||
|
|
||||||
LOG2(_T("Prim (%d) %05x %05x %05x %04x\n"),
|
|
||||||
m_PRIM,
|
|
||||||
m_ctxt->FRAME.Block(),
|
|
||||||
m_pPRIM->TME ? (UINT32)m_ctxt->TEX0.TBP0 : 0xfffff,
|
|
||||||
m_pPRIM->TME ? (UINT32)m_ctxt->TEX0.CBP : 0xfffff,
|
|
||||||
(m_pPRIM->ABE || (m_PRIM == 1 || m_PRIM == 2) && m_pPRIM->AA1)
|
|
||||||
? ((m_ctxt->ALPHA.A<<12)|(m_ctxt->ALPHA.B<<8)|(m_ctxt->ALPHA.C<<4)|m_ctxt->ALPHA.D)
|
|
||||||
: 0xffff);
|
|
||||||
|
|
||||||
m_nVertices += DrawingKick(fSkip);
|
|
||||||
|
|
||||||
#ifdef DEBUG_RENDERTARGETS
|
|
||||||
if(::GetAsyncKeyState(VK_SPACE)&0x80000000) {FlushPrimInternal(); Flip();}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NewPrim() {m_vl.RemoveAll();}
|
|
||||||
void FlushPrim() {m_PRIM = 8; m_nVertices = 0;}
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSRenderer(int w, int h, HWND hWnd, HRESULT& hr)
|
|
||||||
: GSState(w, h, hWnd, hr)
|
|
||||||
{
|
|
||||||
m_pVertices = (VERTEX*)_aligned_malloc(sizeof(VERTEX) * (m_nMaxVertices = 256), 16);
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
~GSRenderer()
|
|
||||||
{
|
|
||||||
_aligned_free(m_pVertices);
|
|
||||||
}
|
|
||||||
};
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,89 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "GSRenderer.h"
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
__declspec(align(16)) union GSVertexHW
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
float x, y, z, rhw;
|
|
||||||
union {struct {BYTE r, g, b, a;}; D3DCOLOR color;};
|
|
||||||
D3DCOLOR fog;
|
|
||||||
float tu, tv;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct {__m128i xmm[2];};
|
|
||||||
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
GSVertexHW& operator = (GSVertexHW& v) {xmm[0] = v.xmm[0]; xmm[1] = v.xmm[1]; return *this;}
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
class GSRendererHW : public GSRenderer<GSVertexHW>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
CSurfMap<IDirect3DTexture9> m_pRTs;
|
|
||||||
CSurfMap<IDirect3DSurface9> m_pDSs;
|
|
||||||
CAtlMap<DWORD, CGSWnd*> m_pRenderWnds;
|
|
||||||
|
|
||||||
GSTextureCache m_tc;
|
|
||||||
|
|
||||||
void SetupTexture(const GSTextureBase& t, float tsx, float tsy);
|
|
||||||
void SetupAlphaBlend();
|
|
||||||
void SetupColorMask();
|
|
||||||
void SetupZBuffer();
|
|
||||||
void SetupAlphaTest();
|
|
||||||
void SetupScissor(scale_t& s);
|
|
||||||
|
|
||||||
void Reset();
|
|
||||||
void VertexKick(bool fSkip);
|
|
||||||
int DrawingKick(bool fSkip);
|
|
||||||
void FlushPrim();
|
|
||||||
void Flip();
|
|
||||||
void EndFrame();
|
|
||||||
void InvalidateTexture(const GIFRegBITBLTBUF& BITBLTBUF, CRect r);
|
|
||||||
void InvalidateLocalMem(DWORD BP, DWORD TBP0, DWORD PSM, CRect r);
|
|
||||||
void MinMaxUV(int w, int h, CRect& r);
|
|
||||||
|
|
||||||
D3DPRIMITIVETYPE m_primtype;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSRendererHW(HWND hWnd, HRESULT& hr);
|
|
||||||
~GSRendererHW();
|
|
||||||
|
|
||||||
HRESULT ResetDevice(bool fForceWindowed = false);
|
|
||||||
|
|
||||||
void LOGVERTEX(GSVertexHW& v, LPCTSTR type)
|
|
||||||
{
|
|
||||||
int tw = 1, th = 1;
|
|
||||||
if(m_pPRIM->TME) {tw = 1<<m_ctxt->TEX0.TW; th = 1<<m_ctxt->TEX0.TH;}
|
|
||||||
LOG2(_T("\t %s (%.2f, %.2f, %.2f, %.2f) (%08x) (%f, %f) (%f, %f)\n"),
|
|
||||||
type,
|
|
||||||
v.x, v.y, v.z, v.rhw,
|
|
||||||
v.color, v.tu, v.tv,
|
|
||||||
v.tu*tw, v.tv*th);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,101 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
|
||||||
#include "GSRendererNull.h"
|
|
||||||
|
|
||||||
GSRendererNull::GSRendererNull(HWND hWnd, HRESULT& hr)
|
|
||||||
: GSRenderer<NULLVERTEX>(256, 256, hWnd, hr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GSRendererNull::~GSRendererNull()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSRendererNull::VertexKick(bool fSkip)
|
|
||||||
{
|
|
||||||
NULLVERTEX v;
|
|
||||||
|
|
||||||
m_vl.AddTail(v);
|
|
||||||
|
|
||||||
__super::VertexKick(fSkip);
|
|
||||||
}
|
|
||||||
|
|
||||||
int GSRendererNull::DrawingKick(bool fSkip)
|
|
||||||
{
|
|
||||||
NULLVERTEX v;
|
|
||||||
|
|
||||||
switch(m_PRIM)
|
|
||||||
{
|
|
||||||
case 3: // triangle list
|
|
||||||
m_vl.RemoveAt(0, v);
|
|
||||||
m_vl.RemoveAt(0, v);
|
|
||||||
m_vl.RemoveAt(0, v);
|
|
||||||
break;
|
|
||||||
case 4: // triangle strip
|
|
||||||
m_vl.RemoveAt(0, v);
|
|
||||||
m_vl.GetAt(0, v);
|
|
||||||
m_vl.GetAt(1, v);
|
|
||||||
break;
|
|
||||||
case 5: // triangle fan
|
|
||||||
m_vl.GetAt(0, v);
|
|
||||||
m_vl.RemoveAt(1, v);
|
|
||||||
m_vl.GetAt(1, v);
|
|
||||||
break;
|
|
||||||
case 6: // sprite
|
|
||||||
m_vl.RemoveAt(0, v);
|
|
||||||
m_vl.RemoveAt(0, v);
|
|
||||||
break;
|
|
||||||
case 1: // line
|
|
||||||
m_vl.RemoveAt(0, v);
|
|
||||||
m_vl.RemoveAt(0, v);
|
|
||||||
break;
|
|
||||||
case 2: // line strip
|
|
||||||
m_vl.RemoveAt(0, v);
|
|
||||||
m_vl.GetAt(0, v);
|
|
||||||
break;
|
|
||||||
case 0: // point
|
|
||||||
m_vl.RemoveAt(0, v);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ASSERT(0);
|
|
||||||
m_vl.RemoveAll();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!fSkip)
|
|
||||||
{
|
|
||||||
m_perfmon.IncCounter(GSPerfMon::c_prim, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSRendererNull::Flip()
|
|
||||||
{
|
|
||||||
FlipInfo rt[2];
|
|
||||||
FinishFlip(rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSRendererNull::EndFrame()
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "GSRenderer.h"
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
struct NULLVERTEX {/*DWORD dummy;*/};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
class GSRendererNull : public GSRenderer<NULLVERTEX>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
void VertexKick(bool fSkip);
|
|
||||||
int DrawingKick(bool fSkip);
|
|
||||||
void Flip();
|
|
||||||
void EndFrame();
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSRendererNull(HWND hWnd, HRESULT& hr);
|
|
||||||
~GSRendererNull();
|
|
||||||
};
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,112 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "GSRenderer.h"
|
|
||||||
|
|
||||||
template <class Vertex>
|
|
||||||
class GSRendererSoft : public GSRenderer<Vertex>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
void Reset();
|
|
||||||
int DrawingKick(bool fSkip);
|
|
||||||
void FlushPrim();
|
|
||||||
void Flip();
|
|
||||||
void EndFrame();
|
|
||||||
|
|
||||||
enum {PRIM_NONE, PRIM_SPRITE, PRIM_TRIANGLE, PRIM_LINE, PRIM_POINT} m_primtype;
|
|
||||||
|
|
||||||
DWORD m_faddr_x0, m_faddr;
|
|
||||||
DWORD m_zaddr_x0, m_zaddr;
|
|
||||||
int* m_faddr_ro;
|
|
||||||
int* m_zaddr_ro;
|
|
||||||
int m_fx, m_fy;
|
|
||||||
void RowInit(int x, int y);
|
|
||||||
void RowStep();
|
|
||||||
|
|
||||||
void DrawPoint(Vertex* v);
|
|
||||||
void DrawLine(Vertex* v);
|
|
||||||
void DrawTriangle(Vertex* v);
|
|
||||||
void DrawSprite(Vertex* v);
|
|
||||||
bool DrawFilledRect(int left, int top, int right, int bottom, const Vertex& v);
|
|
||||||
|
|
||||||
template <int iZTST, int iATST>
|
|
||||||
void DrawVertex(const Vertex& v);
|
|
||||||
|
|
||||||
typedef void (GSRendererSoft<Vertex>::*DrawVertexPtr)(const Vertex& v);
|
|
||||||
DrawVertexPtr m_dv[4][8], m_pDrawVertex;
|
|
||||||
|
|
||||||
template <int iLOD, bool bLCM, bool bTCC, int iTFX>
|
|
||||||
void DrawVertexTFX(typename Vertex::Vector& Cf, const Vertex& v);
|
|
||||||
|
|
||||||
typedef void (GSRendererSoft<Vertex>::*DrawVertexTFXPtr)(typename Vertex::Vector& Cf, const Vertex& v);
|
|
||||||
DrawVertexTFXPtr m_dvtfx[4][2][2][4], m_pDrawVertexTFX;
|
|
||||||
|
|
||||||
CComPtr<IDirect3DTexture9> m_pRT[2];
|
|
||||||
|
|
||||||
DWORD* m_pTexture;
|
|
||||||
void SetupTexture();
|
|
||||||
|
|
||||||
struct uv_wrap_t {union {struct {short min[8], max[8];}; struct {short and[8], or[8];};}; unsigned short mask[8];}* m_uv;
|
|
||||||
|
|
||||||
CRect m_scissor;
|
|
||||||
BYTE m_clip[65536];
|
|
||||||
BYTE m_mask[65536];
|
|
||||||
BYTE* m_clamp;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSRendererSoft(HWND hWnd, HRESULT& hr);
|
|
||||||
~GSRendererSoft();
|
|
||||||
|
|
||||||
HRESULT ResetDevice(bool fForceWindowed = false);
|
|
||||||
|
|
||||||
void LOGVERTEX(Vertex& v, LPCTSTR type)
|
|
||||||
{
|
|
||||||
int tw = 1, th = 1;
|
|
||||||
if(m_de.PRIM.TME) {tw = 1<<m_ctxt->TEX0.TW; th = 1<<m_ctxt->TEX0.TH;}
|
|
||||||
LOG2(_T("- %s (%.2f, %.2f, %.2f, %.2f) (%08x) (%.3f, %.3f) (%.2f, %.2f)\n"),
|
|
||||||
type,
|
|
||||||
(float)v.p.x, (float)v.p.y, (float)v.p.z / UINT_MAX, (float)v.t.q,
|
|
||||||
(DWORD)v.c,
|
|
||||||
(float)v.t.x/tw, (float)v.t.y/th, (float)v.t.x, (float)v.t.y);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GSRendererSoftFP : public GSRendererSoft<GSSoftVertexFP>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
void VertexKick(bool fSkip);
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSRendererSoftFP(HWND hWnd, HRESULT& hr);
|
|
||||||
};
|
|
||||||
/*
|
|
||||||
class GSRendererSoftFX : public GSRendererSoft<GSSoftVertexFX>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
void VertexKick(bool fSkip);
|
|
||||||
//void DrawVertex(int x, int y, GSSoftVertexFX& v);
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSRendererSoftFX(HWND hWnd, HRESULT& hr);
|
|
||||||
};
|
|
||||||
*/
|
|
|
@ -1,239 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "stdafx.h"
|
|
||||||
#include "GSdx9.h"
|
|
||||||
#include "GSSettingsDlg.h"
|
|
||||||
#include <shlobj.h>
|
|
||||||
|
|
||||||
static struct {int id; const TCHAR* name;} s_renderers[] =
|
|
||||||
{
|
|
||||||
{RENDERER_D3D_HW, "Direct3D"},
|
|
||||||
// {RENDERER_D3D_SW_FX, "Software (fixed)"},
|
|
||||||
{RENDERER_D3D_SW_FP, "Software (float)"},
|
|
||||||
{RENDERER_D3D_NULL, "Do not render"},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct {DWORD id; const TCHAR* name;} s_psversions[] =
|
|
||||||
{
|
|
||||||
{D3DPS_VERSION(3, 0), _T("Pixel Shader 3.0")},
|
|
||||||
{D3DPS_VERSION(2, 0), _T("Pixel Shader 2.0")},
|
|
||||||
{D3DPS_VERSION(1, 4), _T("Pixel Shader 1.4")},
|
|
||||||
{D3DPS_VERSION(1, 1), _T("Pixel Shader 1.1")},
|
|
||||||
{D3DPS_VERSION(0, 0), _T("Fixed Pipeline (bogus)")},
|
|
||||||
};
|
|
||||||
|
|
||||||
IMPLEMENT_DYNAMIC(CGSSettingsDlg, CDialog)
|
|
||||||
CGSSettingsDlg::CGSSettingsDlg(CWnd* pParent /*=NULL*/)
|
|
||||||
: CDialog(CGSSettingsDlg::IDD, pParent)
|
|
||||||
, m_fEnablePalettizedTextures(FALSE)
|
|
||||||
, m_fEnableTvOut(FALSE)
|
|
||||||
, m_fNloopHack(FALSE)
|
|
||||||
, m_fRecordState(FALSE)
|
|
||||||
, m_fLinearTexFilter(TRUE)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CGSSettingsDlg::~CGSSettingsDlg()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGSSettingsDlg::DoDataExchange(CDataExchange* pDX)
|
|
||||||
{
|
|
||||||
CDialog::DoDataExchange(pDX);
|
|
||||||
DDX_Control(pDX, IDC_COMBO3, m_resolution);
|
|
||||||
DDX_Control(pDX, IDC_COMBO1, m_renderer);
|
|
||||||
DDX_Control(pDX, IDC_COMBO4, m_psversion);
|
|
||||||
DDX_Check(pDX, IDC_CHECK1, m_fEnablePalettizedTextures);
|
|
||||||
DDX_Check(pDX, IDC_CHECK3, m_fEnableTvOut);
|
|
||||||
DDX_Check(pDX, IDC_CHECK2, m_fRecordState);
|
|
||||||
DDX_Check(pDX, IDC_CHECK5, m_fNloopHack);
|
|
||||||
DDX_Text(pDX, IDC_EDIT1, m_strRecordState);
|
|
||||||
DDX_Check(pDX, IDC_CHECK4, m_fLinearTexFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN_MESSAGE_MAP(CGSSettingsDlg, CDialog)
|
|
||||||
ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
|
|
||||||
END_MESSAGE_MAP()
|
|
||||||
|
|
||||||
// CGSSettingsDlg message handlers
|
|
||||||
|
|
||||||
BOOL CGSSettingsDlg::OnInitDialog()
|
|
||||||
{
|
|
||||||
__super::OnInitDialog();
|
|
||||||
|
|
||||||
CWinApp* pApp = AfxGetApp();
|
|
||||||
|
|
||||||
D3DCAPS9 caps;
|
|
||||||
ZeroMemory(&caps, sizeof(caps));
|
|
||||||
caps.PixelShaderVersion = D3DPS_VERSION(0, 0);
|
|
||||||
|
|
||||||
m_modes.RemoveAll();
|
|
||||||
|
|
||||||
// windowed
|
|
||||||
|
|
||||||
{
|
|
||||||
D3DDISPLAYMODE mode;
|
|
||||||
memset(&mode, 0, sizeof(mode));
|
|
||||||
m_modes.AddTail(mode);
|
|
||||||
|
|
||||||
int iItem = m_resolution.AddString(_T("Windowed"));
|
|
||||||
m_resolution.SetItemDataPtr(iItem, m_modes.GetTailPosition());
|
|
||||||
m_resolution.SetCurSel(iItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fullscreen
|
|
||||||
|
|
||||||
if(CComPtr<IDirect3D9> pD3D = Direct3DCreate9(D3D_SDK_VERSION))
|
|
||||||
{
|
|
||||||
int ModeWidth = pApp->GetProfileInt(_T("Settings"), _T("ModeWidth"), 0);
|
|
||||||
int ModeHeight = pApp->GetProfileInt(_T("Settings"), _T("ModeHeight"), 0);
|
|
||||||
int ModeRefreshRate = pApp->GetProfileInt(_T("Settings"), _T("ModeRefreshRate"), 0);
|
|
||||||
|
|
||||||
UINT nModes = pD3D->GetAdapterModeCount(D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
|
|
||||||
for(UINT i = 0; i < nModes; i++)
|
|
||||||
{
|
|
||||||
D3DDISPLAYMODE mode;
|
|
||||||
if(S_OK == pD3D->EnumAdapterModes(D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &mode))
|
|
||||||
{
|
|
||||||
CString str;
|
|
||||||
str.Format(_T("%dx%d %dHz"), mode.Width, mode.Height, mode.RefreshRate);
|
|
||||||
int iItem = m_resolution.AddString(str);
|
|
||||||
|
|
||||||
m_modes.AddTail(mode);
|
|
||||||
m_resolution.SetItemDataPtr(iItem, m_modes.GetTailPosition());
|
|
||||||
|
|
||||||
if(ModeWidth == mode.Width && ModeHeight == mode.Height && ModeRefreshRate == mode.RefreshRate)
|
|
||||||
m_resolution.SetCurSel(iItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, CGSdx9App::D3DDEVTYPE_X, &caps);
|
|
||||||
}
|
|
||||||
|
|
||||||
// renderer
|
|
||||||
|
|
||||||
int renderer_id = pApp->GetProfileInt(_T("Settings"), _T("Renderer"), RENDERER_D3D_HW);
|
|
||||||
|
|
||||||
for(int i = 0; i < countof(s_renderers); i++)
|
|
||||||
{
|
|
||||||
int iItem = m_renderer.AddString(s_renderers[i].name);
|
|
||||||
m_renderer.SetItemData(iItem, s_renderers[i].id);
|
|
||||||
if(s_renderers[i].id == renderer_id) m_renderer.SetCurSel(iItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// shader
|
|
||||||
|
|
||||||
DWORD psversion_id = pApp->GetProfileInt(_T("Settings"), _T("PixelShaderVersion2"), D3DPS_VERSION(2, 0));
|
|
||||||
|
|
||||||
for(int i = 0; i < countof(s_psversions); i++)
|
|
||||||
{
|
|
||||||
if(s_psversions[i].id > caps.PixelShaderVersion) continue;
|
|
||||||
int iItem = m_psversion.AddString(s_psversions[i].name);
|
|
||||||
m_psversion.SetItemData(iItem, s_psversions[i].id);
|
|
||||||
if(s_psversions[i].id == psversion_id) m_psversion.SetCurSel(iItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
m_fEnablePalettizedTextures = pApp->GetProfileInt(_T("Settings"), _T("fEnablePalettizedTextures"), FALSE);
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
m_fLinearTexFilter = (D3DTEXTUREFILTERTYPE)pApp->GetProfileInt(_T("Settings"), _T("TexFilter"), D3DTEXF_LINEAR) == D3DTEXF_LINEAR;
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
m_fEnableTvOut = pApp->GetProfileInt(_T("Settings"), _T("fEnableTvOut"), FALSE);
|
|
||||||
|
|
||||||
//
|
|
||||||
m_fNloopHack = pApp->GetProfileInt(_T("Settings"), _T("fNloopHack"), FALSE);
|
|
||||||
|
|
||||||
//
|
|
||||||
m_fRecordState = pApp->GetProfileInt(_T("Settings"), _T("RecordState"), FALSE);
|
|
||||||
m_strRecordState = pApp->GetProfileString(_T("Settings"), _T("RecordStatePath"), _T(""));
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
UpdateData(FALSE);
|
|
||||||
|
|
||||||
return TRUE; // return TRUE unless you set the focus to a control
|
|
||||||
// EXCEPTION: OCX Property Pages should return FALSE
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGSSettingsDlg::OnOK()
|
|
||||||
{
|
|
||||||
CWinApp* pApp = AfxGetApp();
|
|
||||||
|
|
||||||
UpdateData();
|
|
||||||
|
|
||||||
if(m_resolution.GetCurSel() >= 0)
|
|
||||||
{
|
|
||||||
D3DDISPLAYMODE& mode = m_modes.GetAt((POSITION)m_resolution.GetItemData(m_resolution.GetCurSel()));
|
|
||||||
pApp->WriteProfileInt(_T("Settings"), _T("ModeWidth"), mode.Width);
|
|
||||||
pApp->WriteProfileInt(_T("Settings"), _T("ModeHeight"), mode.Height);
|
|
||||||
pApp->WriteProfileInt(_T("Settings"), _T("ModeRefreshRate"), mode.RefreshRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_renderer.GetCurSel() >= 0)
|
|
||||||
{
|
|
||||||
pApp->WriteProfileInt(_T("Settings"), _T("Renderer"), m_renderer.GetItemData(m_renderer.GetCurSel()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_psversion.GetCurSel() >= 0)
|
|
||||||
{
|
|
||||||
pApp->WriteProfileInt(_T("Settings"), _T("PixelShaderVersion2"), m_psversion.GetItemData(m_psversion.GetCurSel()));
|
|
||||||
}
|
|
||||||
|
|
||||||
pApp->WriteProfileInt(_T("Settings"), _T("fEnablePalettizedTextures"), m_fEnablePalettizedTextures);
|
|
||||||
|
|
||||||
pApp->WriteProfileInt(_T("Settings"), _T("TexFilter"), m_fLinearTexFilter ? D3DTEXF_LINEAR : D3DTEXF_POINT);
|
|
||||||
|
|
||||||
pApp->WriteProfileInt(_T("Settings"), _T("fEnableTvOut"), m_fEnableTvOut);
|
|
||||||
pApp->WriteProfileInt(_T("Settings"), _T("fNloopHack"), m_fNloopHack);
|
|
||||||
pApp->WriteProfileInt(_T("Settings"), _T("RecordState"), m_fRecordState);
|
|
||||||
pApp->WriteProfileString(_T("Settings"), _T("RecordStatePath"), m_strRecordState);
|
|
||||||
|
|
||||||
__super::OnOK();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGSSettingsDlg::OnBnClickedButton1()
|
|
||||||
{
|
|
||||||
TCHAR path[MAX_PATH];
|
|
||||||
|
|
||||||
BROWSEINFO bi;
|
|
||||||
bi.hwndOwner = m_hWnd;
|
|
||||||
bi.pidlRoot = NULL;
|
|
||||||
bi.pszDisplayName = path;
|
|
||||||
bi.lpszTitle = _T("Select path for the state file");
|
|
||||||
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_VALIDATE | BIF_USENEWUI;
|
|
||||||
bi.lpfn = NULL;
|
|
||||||
bi.lParam = 0;
|
|
||||||
bi.iImage = 0;
|
|
||||||
|
|
||||||
LPITEMIDLIST iil;
|
|
||||||
if(iil = SHBrowseForFolder(&bi))
|
|
||||||
{
|
|
||||||
SHGetPathFromIDList(iil, path);
|
|
||||||
m_strRecordState = path;
|
|
||||||
UpdateData(FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "resource.h"
|
|
||||||
#include "afxwin.h"
|
|
||||||
|
|
||||||
class CGSSettingsDlg : public CDialog
|
|
||||||
{
|
|
||||||
DECLARE_DYNAMIC(CGSSettingsDlg)
|
|
||||||
|
|
||||||
private:
|
|
||||||
CList<D3DDISPLAYMODE> m_modes;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CGSSettingsDlg(CWnd* pParent = NULL); // standard constructor
|
|
||||||
virtual ~CGSSettingsDlg();
|
|
||||||
|
|
||||||
// Dialog Data
|
|
||||||
enum { IDD = IDD_CONFIG };
|
|
||||||
CComboBox m_resolution;
|
|
||||||
CComboBox m_renderer;
|
|
||||||
CComboBox m_psversion;
|
|
||||||
BOOL m_fEnablePalettizedTextures;
|
|
||||||
BOOL m_fEnableTvOut;
|
|
||||||
BOOL m_fRecordState;
|
|
||||||
BOOL m_fNloopHack;
|
|
||||||
CString m_strRecordState;
|
|
||||||
BOOL m_fLinearTexFilter;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
|
||||||
virtual BOOL OnInitDialog();
|
|
||||||
virtual void OnOK();
|
|
||||||
|
|
||||||
DECLARE_MESSAGE_MAP()
|
|
||||||
public:
|
|
||||||
afx_msg void OnBnClickedButton1();
|
|
||||||
};
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
|
||||||
#include "GSSoftVertex.h"
|
|
||||||
|
|
||||||
const __m128i _80000000 = _mm_set1_epi32(0x80000000);
|
|
||||||
const __m128i _4b000000 = _mm_set1_epi32(0x4b000000);
|
|
||||||
const __m128i _3f800000 = _mm_set1_epi32(0x3f800000);
|
|
|
@ -1,309 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
//
|
|
||||||
// GSSoftVertexFP
|
|
||||||
//
|
|
||||||
|
|
||||||
extern const __m128i _80000000, _4b000000, _3f800000;
|
|
||||||
|
|
||||||
__declspec(align(16)) union GSSoftVertexFP
|
|
||||||
{
|
|
||||||
class __declspec(novtable) Scalar
|
|
||||||
{
|
|
||||||
float val;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Scalar() {}
|
|
||||||
explicit Scalar(float f) {val = f;}
|
|
||||||
explicit Scalar(int i) {val = (float)i;}
|
|
||||||
|
|
||||||
float Value() const {return val;}
|
|
||||||
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
void sat() {_mm_store_ss(&val, _mm_min_ss(_mm_max_ss(_mm_set_ss(val), _mm_setzero_ps()), _mm_set_ss(255)));}
|
|
||||||
void rcp() {_mm_store_ss(&val, _mm_rcp_ss(_mm_set_ss(val)));}
|
|
||||||
#else
|
|
||||||
void sat() {val = val < 0 ? 0 : val > 255 ? 255 : val;}
|
|
||||||
void rcp() {val = 1.0f / val;}
|
|
||||||
#endif
|
|
||||||
void abs() {val = fabs(val);}
|
|
||||||
|
|
||||||
Scalar floor_s() const {return Scalar(floor(val));}
|
|
||||||
int floor_i() const {return (int)floor(val);}
|
|
||||||
|
|
||||||
Scalar ceil_s() const {return Scalar(-floor(-val));}
|
|
||||||
int ceil_i() const {return -(int)floor(-val);}
|
|
||||||
|
|
||||||
void operator = (float f) {val = f;}
|
|
||||||
void operator = (int i) {val = (float)i;}
|
|
||||||
|
|
||||||
operator float() const {return val;}
|
|
||||||
operator int() const {return (int)val;}
|
|
||||||
|
|
||||||
void operator += (const Scalar& s) {val += s.val;}
|
|
||||||
void operator -= (const Scalar& s) {val -= s.val;}
|
|
||||||
void operator *= (const Scalar& s) {val *= s.val;}
|
|
||||||
void operator /= (const Scalar& s) {val /= s.val;}
|
|
||||||
|
|
||||||
friend Scalar operator + (const Scalar& s1, const Scalar& s2) {return Scalar(s1.val + s2.val);}
|
|
||||||
friend Scalar operator - (const Scalar& s1, const Scalar& s2) {return Scalar(s1.val - s2.val);}
|
|
||||||
friend Scalar operator * (const Scalar& s1, const Scalar& s2) {return Scalar(s1.val * s2.val);}
|
|
||||||
friend Scalar operator / (const Scalar& s1, const Scalar& s2) {return Scalar(s1.val / s2.val);}
|
|
||||||
|
|
||||||
friend Scalar operator + (const Scalar& s, int i) {return Scalar(s.val + i);}
|
|
||||||
friend Scalar operator - (const Scalar& s, int i) {return Scalar(s.val - i);}
|
|
||||||
friend Scalar operator * (const Scalar& s, int i) {return Scalar(s.val * i);}
|
|
||||||
friend Scalar operator / (const Scalar& s, int i) {return Scalar(s.val / i);}
|
|
||||||
|
|
||||||
friend Scalar operator << (const Scalar& s, int i) {return Scalar(s.val * (1<<i));}
|
|
||||||
friend Scalar operator >> (const Scalar& s, int i) {return Scalar(s.val / (1<<i));}
|
|
||||||
|
|
||||||
friend bool operator == (const Scalar& s1, const Scalar& s2) {return s1.val == s2.val;}
|
|
||||||
friend bool operator <= (const Scalar& s1, const Scalar& s2) {return s1.val <= s2.val;}
|
|
||||||
friend bool operator < (const Scalar& s1, const Scalar& s2) {return s1.val < s2.val;}
|
|
||||||
};
|
|
||||||
|
|
||||||
__declspec(align(16)) class __declspec(novtable) Vector
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
union
|
|
||||||
{
|
|
||||||
union {struct {Scalar x, y, z, q;}; struct {Scalar r, g, b, a;};};
|
|
||||||
union {struct {Scalar v[4];}; struct {Scalar c[4];};};
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
union {__m128 xyzq; __m128 rgba;};
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector() {}
|
|
||||||
Vector(const Vector& v) {*this = v;}
|
|
||||||
Vector(Scalar s) {*this = s;}
|
|
||||||
Vector(Scalar s0, Scalar s1, Scalar s2, Scalar s3) {x = s0; y = s1; z = s2; q = s3;}
|
|
||||||
explicit Vector(DWORD dw) {*this = dw;}
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
Vector(__m128 f0123) {*this = f0123;}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
|
|
||||||
void operator = (const Vector& v) {xyzq = v.xyzq;}
|
|
||||||
void operator = (Scalar s) {xyzq = _mm_set1_ps(s);}
|
|
||||||
|
|
||||||
void operator = (__m128 f0123) {xyzq = f0123;}
|
|
||||||
operator __m128() const {return xyzq;}
|
|
||||||
|
|
||||||
void operator = (DWORD dw) {__m128i zero = _mm_setzero_si128(); xyzq = _mm_cvtepi32_ps(_mm_unpacklo_epi16(_mm_unpacklo_epi8(_mm_cvtsi32_si128(dw), zero), zero));}
|
|
||||||
operator DWORD() const {__m128i r0 = _mm_cvttps_epi32(xyzq); r0 = _mm_packs_epi32(r0, r0); r0 = _mm_packus_epi16(r0, r0); return (DWORD)_mm_cvtsi128_si32(r0);}
|
|
||||||
operator UINT64() const {__m128i r0 = _mm_cvttps_epi32(xyzq); r0 = _mm_packs_epi32(r0, r0); return *(UINT64*)&r0;}
|
|
||||||
|
|
||||||
void sat() {xyzq = _mm_min_ps(_mm_max_ps(xyzq, _mm_setzero_ps()), _mm_set1_ps(255));}
|
|
||||||
void rcp() {xyzq = _mm_rcp_ps(xyzq);}
|
|
||||||
|
|
||||||
Vector floor()
|
|
||||||
{
|
|
||||||
__m128 sign = _mm_and_ps(xyzq, *(__m128*)&_80000000);
|
|
||||||
__m128 r0 = _mm_or_ps(sign, *(__m128*)&_4b000000);
|
|
||||||
__m128 r1 = _mm_sub_ps(_mm_add_ps(xyzq, r0), r0);
|
|
||||||
__m128 r2 = _mm_sub_ps(r1, xyzq);
|
|
||||||
__m128 r3 = _mm_and_ps(_mm_cmpnle_ps(r2, sign), *(__m128*)&_3f800000);
|
|
||||||
__m128 r4 = _mm_sub_ps(r1, r3);
|
|
||||||
return r4;
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator += (const Vector& v) {xyzq = _mm_add_ps(xyzq, v);}
|
|
||||||
void operator -= (const Vector& v) {xyzq = _mm_sub_ps(xyzq, v);}
|
|
||||||
void operator *= (const Vector& v) {xyzq = _mm_mul_ps(xyzq, v);}
|
|
||||||
void operator /= (const Vector& v) {xyzq = _mm_div_ps(xyzq, v);}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
void operator = (const Vector& v) {x = v.x; y = v.y; z = v.z; q = v.q;}
|
|
||||||
void operator = (Scalar s) {x = y = z = q = s;}
|
|
||||||
|
|
||||||
void operator = (DWORD dw)
|
|
||||||
{
|
|
||||||
x = Scalar((int)((dw>>0)&0xff));
|
|
||||||
y = Scalar((int)((dw>>8)&0xff));
|
|
||||||
z = Scalar((int)((dw>>16)&0xff));
|
|
||||||
q = Scalar((int)((dw>>24)&0xff));
|
|
||||||
}
|
|
||||||
|
|
||||||
operator DWORD() const
|
|
||||||
{
|
|
||||||
return (DWORD)(
|
|
||||||
(((DWORD)(int)x&0xff)<<0) |
|
|
||||||
(((DWORD)(int)y&0xff)<<8) |
|
|
||||||
(((DWORD)(int)z&0xff)<<16) |
|
|
||||||
(((DWORD)(int)q&0xff)<<24));
|
|
||||||
}
|
|
||||||
|
|
||||||
operator UINT64() const
|
|
||||||
{
|
|
||||||
return (DWORD)(
|
|
||||||
(((UINT64)(int)x&0xffff)<<0) |
|
|
||||||
(((UINT64)(int)y&0xffff)<<16) |
|
|
||||||
(((UINT64)(int)z&0xffff)<<32) |
|
|
||||||
(((UINT64)(int)q&0xffff)<<48));
|
|
||||||
}
|
|
||||||
|
|
||||||
void sat() {x.sat(); y.sat(); z.sat(); q.sat();}
|
|
||||||
void rcp() {x.rcp(); y.rcp(); z.rcp(); q.rcp();}
|
|
||||||
|
|
||||||
Vector floor() {return Vector(x.floor_s(), y.floor_s(), z.floor_s(), q.floor_s());}
|
|
||||||
|
|
||||||
void operator += (const Vector& v) {*this = *this + v;}
|
|
||||||
void operator -= (const Vector& v) {*this = *this - v;}
|
|
||||||
void operator *= (const Vector& v) {*this = *this * v;}
|
|
||||||
void operator /= (const Vector& v) {*this = *this / v;}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
friend Vector operator + (const Vector& v1, const Vector& v2);
|
|
||||||
friend Vector operator - (const Vector& v1, const Vector& v2);
|
|
||||||
friend Vector operator * (const Vector& v1, const Vector& v2);
|
|
||||||
friend Vector operator / (const Vector& v1, const Vector& v2);
|
|
||||||
|
|
||||||
friend Vector operator + (const Vector& v, Scalar s);
|
|
||||||
friend Vector operator - (const Vector& v, Scalar s);
|
|
||||||
friend Vector operator * (const Vector& v, Scalar s);
|
|
||||||
friend Vector operator / (const Vector& v, Scalar s);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct {__declspec(align(16)) Vector c, p, t;};
|
|
||||||
struct {__declspec(align(16)) Vector sv[3];};
|
|
||||||
struct {__declspec(align(16)) Scalar s[12];};
|
|
||||||
|
|
||||||
GSSoftVertexFP() {}
|
|
||||||
GSSoftVertexFP(const GSSoftVertexFP& v) {*this = v;}
|
|
||||||
|
|
||||||
void operator = (const GSSoftVertexFP& v) {c = v.c; p = v.p; t = v.t;}
|
|
||||||
void operator += (const GSSoftVertexFP& v) {c += v.c; p += v.p; t += v.t;}
|
|
||||||
|
|
||||||
operator CPoint() const {return CPoint((int)p.x, (int)p.y);}
|
|
||||||
|
|
||||||
__forceinline DWORD GetZ() const
|
|
||||||
{
|
|
||||||
ASSERT((float)p.z >= 0 && (float)p.q >= 0);
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
__m128 z = _mm_shuffle_ps(p, p, _MM_SHUFFLE(2,2,2,2));
|
|
||||||
__m128 q = _mm_shuffle_ps(p, p, _MM_SHUFFLE(3,3,3,3));
|
|
||||||
// TODO: check if our floor is faster than doing ss->si->ss
|
|
||||||
int zh = _mm_cvttss_si32(z);
|
|
||||||
__m128 zhi = _mm_cvtsi32_ss(zhi, zh);
|
|
||||||
__m128 zhf = _mm_mul_ss(_mm_sub_ss(z, zhi), _mm_set_ss(65536));
|
|
||||||
int zl = _mm_cvtss_si32(_mm_add_ss(zhf, q));
|
|
||||||
return ((DWORD)zh << 16) + (DWORD)zl;
|
|
||||||
#else
|
|
||||||
// return ((DWORD)(int)p.z << 16) + (DWORD)(int)((p.z - p.z.floor_s())*65536 + p.q);
|
|
||||||
|
|
||||||
int z = (int)p.z;
|
|
||||||
return ((DWORD)z << 16) + (DWORD)(((float)p.z - z)*65536 + (float)p.q);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator + (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(_mm_add_ps(v1, v2));}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator - (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(_mm_sub_ps(v1, v2));}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator * (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(_mm_mul_ps(v1, v2));}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator / (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(_mm_div_ps(v1, v2));}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator + (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(_mm_add_ps(v, _mm_set1_ps(s)));}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator - (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(_mm_sub_ps(v, _mm_set1_ps(s)));}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator * (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(_mm_mul_ps(v, _mm_set1_ps(s)));}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator / (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(_mm_div_ps(v, _mm_set1_ps(s)));}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator << (const GSSoftVertexFP::Vector& v, int i) {return GSSoftVertexFP::Vector(_mm_mul_ps(v, _mm_set1_ps((float)(1 << i))));}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator >> (const GSSoftVertexFP::Vector& v, int i) {return GSSoftVertexFP::Vector(_mm_mul_ps(v, _mm_set1_ps(1.0f / (1 << i))));}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator + (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.q + v2.q);}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator - (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.q - v2.q);}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator * (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.q * v2.q);}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator / (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z, v1.q / v2.q);}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator + (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(v.x + s, v.y + s, v.z + s, v.q + s);}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator - (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(v.x - s, v.y - s, v.z - s, v.q - s);}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator * (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(v.x * s, v.y * s, v.z * s, v.q * s);}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator / (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(v.x / s, v.y / s, v.z / s, v.q / s);}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator << (const GSSoftVertexFP::Vector& v, int i) {return GSSoftVertexFP::Vector(v.x << i, v.y << i, v.z << i, v.q << i);}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator >> (const GSSoftVertexFP::Vector& v, int i) {return GSSoftVertexFP::Vector(v.x >> i, v.y >> i, v.z >> i, v.q >> i);}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
template <class Vertex>
|
|
||||||
__forceinline Vertex operator + (const Vertex& v1, const Vertex& v2)
|
|
||||||
{
|
|
||||||
Vertex v0;
|
|
||||||
v0.c = v1.c + v2.c;
|
|
||||||
v0.p = v1.p + v2.p;
|
|
||||||
v0.t = v1.t + v2.t;
|
|
||||||
return v0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Vertex>
|
|
||||||
__forceinline Vertex operator - (const Vertex& v1, const Vertex& v2)
|
|
||||||
{
|
|
||||||
Vertex v0;
|
|
||||||
v0.c = v1.c - v2.c;
|
|
||||||
v0.p = v1.p - v2.p;
|
|
||||||
v0.t = v1.t - v2.t;
|
|
||||||
return v0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Vertex>
|
|
||||||
__forceinline Vertex operator * (const Vertex& v, typename Vertex::Scalar s)
|
|
||||||
{
|
|
||||||
Vertex v0;
|
|
||||||
Vertex::Vector vs(s);
|
|
||||||
v0.c = v.c * vs;
|
|
||||||
v0.p = v.p * vs;
|
|
||||||
v0.t = v.t * vs;
|
|
||||||
return v0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Vertex>
|
|
||||||
__forceinline Vertex operator / (const Vertex& v, typename Vertex::Scalar s)
|
|
||||||
{
|
|
||||||
Vertex v0;
|
|
||||||
Vertex::Vector vs(s);
|
|
||||||
v0.c = v.c / vs;
|
|
||||||
v0.p = v.p / vs;
|
|
||||||
v0.t = v.t / vs;
|
|
||||||
return v0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Vertex>
|
|
||||||
__forceinline void Exchange(Vertex* RESTRICT v1, Vertex* RESTRICT v2)
|
|
||||||
{
|
|
||||||
typename Vertex::Vector c = v1->c, p = v1->p, t = v1->t;
|
|
||||||
v1->c = v2->c; v1->p = v2->p; v1->t = v2->t;
|
|
||||||
v2->c = c; v2->p = p; v2->t = t;
|
|
||||||
}
|
|
|
@ -1,259 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
//
|
|
||||||
// GSSoftVertexFP
|
|
||||||
//
|
|
||||||
|
|
||||||
__declspec(align(16)) union GSSoftVertexFP
|
|
||||||
{
|
|
||||||
class __declspec(novtable) Scalar
|
|
||||||
{
|
|
||||||
float val;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Scalar() {}
|
|
||||||
explicit Scalar(float f) {val = f;}
|
|
||||||
explicit Scalar(int i) {val = (float)i;}
|
|
||||||
|
|
||||||
float Value() const {return val;}
|
|
||||||
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
void sat() {_mm_store_ss(&val, _mm_min_ss(_mm_max_ss(_mm_set_ss(val), _mm_setzero_ps()), _mm_set_ss(255)));}
|
|
||||||
void rcp() {_mm_store_ss(&val, _mm_rcp_ss(_mm_set_ss(val)));}
|
|
||||||
#else
|
|
||||||
void sat() {val = val < 0 ? 0 : val > 255 ? 255 : val;}
|
|
||||||
void rcp() {val = 1.0f / val;}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void abss() {val = abs(val);}
|
|
||||||
|
|
||||||
Scalar floors() const {return Scalar(floor(val));}
|
|
||||||
int floori() const {return (int)floor(val);}
|
|
||||||
|
|
||||||
Scalar ceils() const {return Scalar(-floor(-val));}
|
|
||||||
int ceili() const {return -(int)floor(-val);}
|
|
||||||
|
|
||||||
void operator = (float f) {val = f;}
|
|
||||||
void operator = (int i) {val = (float)i;}
|
|
||||||
|
|
||||||
operator float() const {return val;}
|
|
||||||
operator int() const {return (int)val;}
|
|
||||||
|
|
||||||
void operator += (const Scalar& s) {val += s.val;}
|
|
||||||
void operator -= (const Scalar& s) {val -= s.val;}
|
|
||||||
void operator *= (const Scalar& s) {val *= s.val;}
|
|
||||||
void operator /= (const Scalar& s) {val /= s.val;}
|
|
||||||
|
|
||||||
friend Scalar operator + (const Scalar& s1, const Scalar& s2) {return Scalar(s1.val + s2.val);}
|
|
||||||
friend Scalar operator - (const Scalar& s1, const Scalar& s2) {return Scalar(s1.val - s2.val);}
|
|
||||||
friend Scalar operator * (const Scalar& s1, const Scalar& s2) {return Scalar(s1.val * s2.val);}
|
|
||||||
friend Scalar operator / (const Scalar& s1, const Scalar& s2) {return Scalar(s1.val / s2.val);}
|
|
||||||
|
|
||||||
friend Scalar operator + (const Scalar& s1, int i) {return Scalar(s1.val + i);}
|
|
||||||
friend Scalar operator - (const Scalar& s1, int i) {return Scalar(s1.val - i);}
|
|
||||||
friend Scalar operator * (const Scalar& s1, int i) {return Scalar(s1.val * i);}
|
|
||||||
friend Scalar operator / (const Scalar& s1, int i) {return Scalar(s1.val / i);}
|
|
||||||
|
|
||||||
friend bool operator == (const Scalar& s1, const Scalar& s2) {return s1.val == s2.val;}
|
|
||||||
friend bool operator <= (const Scalar& s1, const Scalar& s2) {return s1.val <= s2.val;}
|
|
||||||
friend bool operator < (const Scalar& s1, const Scalar& s2) {return s1.val < s2.val;}
|
|
||||||
};
|
|
||||||
|
|
||||||
__declspec(align(16)) class __declspec(novtable) Vector
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
union
|
|
||||||
{
|
|
||||||
union {struct {Scalar x, y, z, q;}; struct {Scalar r, g, b, a;};};
|
|
||||||
union {struct {Scalar v[4];}; struct {Scalar c[4];};};
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
union {__m128 xyzq; __m128 rgba;};
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector() {}
|
|
||||||
Vector(const Vector& v) {*this = v;}
|
|
||||||
Vector(Scalar s) {*this = s;}
|
|
||||||
Vector(Scalar s0, Scalar s1, Scalar s2, Scalar s3) {x = s0; y = s1; z = s2; q = s3;}
|
|
||||||
explicit Vector(DWORD dw) {*this = dw;}
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
Vector(__m128 f0123) {*this = f0123;}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
|
|
||||||
void operator = (const Vector& v) {xyzq = v.xyzq;}
|
|
||||||
void operator = (__m128 f0123) {xyzq = f0123;}
|
|
||||||
void operator = (Scalar s) {xyzq = _mm_set1_ps(s);}
|
|
||||||
void operator = (DWORD dw) {__m128i zero = _mm_setzero_si128(); xyzq = _mm_cvtepi32_ps(_mm_unpacklo_epi16(_mm_unpacklo_epi8(_mm_cvtsi32_si128(dw), zero), zero));}
|
|
||||||
|
|
||||||
operator __m128() const {return xyzq;}
|
|
||||||
operator DWORD() const {__m128i r0 = _mm_cvttps_epi32(xyzq); r0 = _mm_packs_epi32(r0, r0); r0 = _mm_packus_epi16(r0, r0); return (DWORD)_mm_cvtsi128_si32(r0);}
|
|
||||||
|
|
||||||
void sat() {xyzq = _mm_min_ps(_mm_max_ps(xyzq, _mm_setzero_ps()), _mm_set1_ps(255));}
|
|
||||||
void rcp() {xyzq = _mm_rcp_ps(xyzq);}
|
|
||||||
|
|
||||||
void operator += (const Vector& v) {xyzq = _mm_add_ps(xyzq, v);}
|
|
||||||
void operator -= (const Vector& v) {xyzq = _mm_sub_ps(xyzq, v);}
|
|
||||||
void operator *= (const Vector& v) {xyzq = _mm_mul_ps(xyzq, v);}
|
|
||||||
void operator /= (const Vector& v) {xyzq = _mm_div_ps(xyzq, v);}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
void operator = (const Vector& v) {x = v.x; y = v.y; z = v.z; q = v.q;}
|
|
||||||
void operator = (Scalar s) {x = y = z = q = s;}
|
|
||||||
void operator = (DWORD dw)
|
|
||||||
{
|
|
||||||
x = Scalar((int)(dw&0xff));
|
|
||||||
y = Scalar((int)((dw>>8)&0xff));
|
|
||||||
z = Scalar((int)((dw>>16)&0xff));
|
|
||||||
q = Scalar((int)((dw>>24)&0xff));
|
|
||||||
}
|
|
||||||
|
|
||||||
operator DWORD() const
|
|
||||||
{
|
|
||||||
return (DWORD)((((DWORD)(int)x&0xff)<<0) | (((DWORD)(int)y&0xff)<<8) | (((DWORD)(int)z&0xff)<<16) | (((DWORD)(int)q&0xff)<<24));
|
|
||||||
}
|
|
||||||
|
|
||||||
void sat() {x.sat(); y.sat(); z.sat(); q.sat();}
|
|
||||||
void rcp() {x.rcp(); y.rcp(); z.rcp(); q.rcp();}
|
|
||||||
|
|
||||||
void operator += (const Vector& v) {*this = *this + v;}
|
|
||||||
void operator -= (const Vector& v) {*this = *this - v;}
|
|
||||||
void operator *= (const Vector& v) {*this = *this * v;}
|
|
||||||
void operator /= (const Vector& v) {*this = *this / v;}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void absv() {x.abss(); y.abss(); z.abss(); q.abss();}
|
|
||||||
|
|
||||||
friend Vector operator + (const Vector& v1, const Vector& v2);
|
|
||||||
friend Vector operator - (const Vector& v1, const Vector& v2);
|
|
||||||
friend Vector operator * (const Vector& v1, const Vector& v2);
|
|
||||||
friend Vector operator / (const Vector& v1, const Vector& v2);
|
|
||||||
|
|
||||||
friend Vector operator + (const Vector& v, Scalar s);
|
|
||||||
friend Vector operator - (const Vector& v, Scalar s);
|
|
||||||
friend Vector operator * (const Vector& v, Scalar s);
|
|
||||||
friend Vector operator / (const Vector& v, Scalar s);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct {__declspec(align(16)) Vector c, p, t;};
|
|
||||||
struct {__declspec(align(16)) Vector sv[3];};
|
|
||||||
struct {__declspec(align(16)) Scalar s[12];};
|
|
||||||
|
|
||||||
GSSoftVertexFP() {}
|
|
||||||
GSSoftVertexFP(const GSSoftVertexFP& v) {*this = v;}
|
|
||||||
|
|
||||||
void operator = (const GSSoftVertexFP& v) {c = v.c; p = v.p; t = v.t;}
|
|
||||||
void operator += (const GSSoftVertexFP& v) {c += v.c; p += v.p; t += v.t;}
|
|
||||||
|
|
||||||
operator CPoint() const {return CPoint((int)p.x, (int)p.y);}
|
|
||||||
|
|
||||||
friend GSSoftVertexFP operator + (const GSSoftVertexFP& v1, const GSSoftVertexFP& v2);
|
|
||||||
friend GSSoftVertexFP operator - (const GSSoftVertexFP& v1, const GSSoftVertexFP& v2);
|
|
||||||
|
|
||||||
friend GSSoftVertexFP operator * (const GSSoftVertexFP& v, Scalar s);
|
|
||||||
friend GSSoftVertexFP operator / (const GSSoftVertexFP& v, Scalar s);
|
|
||||||
|
|
||||||
static void Exchange(GSSoftVertexFP* __restrict v1, GSSoftVertexFP* __restrict v2)
|
|
||||||
{
|
|
||||||
// GSSoftVertexFP v = *v1; *v1 = *v2; *v2 = v;
|
|
||||||
Vector c = v1->c, p = v1->p, t = v1->t;
|
|
||||||
v1->c = v2->c; v1->p = v2->p; v1->t = v2->t;
|
|
||||||
v2->c = c; v2->p = p; v2->t = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
//__forceinline DWORD GetZ() const {return ((DWORD)p.z<<16) + (DWORD)((p.z - floorf(p.z))*65536 + p.q);}
|
|
||||||
__forceinline DWORD GetZ() const
|
|
||||||
{
|
|
||||||
ASSERT((float)p.z >= 0 && (float)p.q >= 0);
|
|
||||||
int z = (int)p.z;
|
|
||||||
return ((DWORD)z << 16) + (DWORD)(((float)p.z - z)*65536 + (float)p.q);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator + (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(_mm_add_ps(v1, v2));}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator - (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(_mm_sub_ps(v1, v2));}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator * (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(_mm_mul_ps(v1, v2));}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator / (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(_mm_div_ps(v1, v2));}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator + (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(_mm_add_ps(v, _mm_set1_ps(s)));}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator - (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(_mm_sub_ps(v, _mm_set1_ps(s)));}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator * (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(_mm_mul_ps(v, _mm_set1_ps(s)));}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator / (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(_mm_div_ps(v, _mm_set1_ps(s)));}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator + (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.q + v2.q);}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator - (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.q - v2.q);}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator * (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.q * v2.q);}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator / (const GSSoftVertexFP::Vector& v1, const GSSoftVertexFP::Vector& v2) {return GSSoftVertexFP::Vector(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z, v1.q / v2.q);}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator + (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(v.x + s, v.y + s, v.z + s, v.q + s);}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator - (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(v.x - s, v.y - s, v.z - s, v.q - s);}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator * (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(v.x * s, v.y * s, v.z * s, v.q * s);}
|
|
||||||
__forceinline GSSoftVertexFP::Vector operator / (const GSSoftVertexFP::Vector& v, GSSoftVertexFP::Scalar s) {return GSSoftVertexFP::Vector(v.x / s, v.y / s, v.z / s, v.q / s);}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP operator + (const GSSoftVertexFP& v1, const GSSoftVertexFP& v2)
|
|
||||||
{
|
|
||||||
GSSoftVertexFP v0;
|
|
||||||
v0.c = v1.c + v2.c;
|
|
||||||
v0.p = v1.p + v2.p;
|
|
||||||
v0.t = v1.t + v2.t;
|
|
||||||
return v0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP operator - (const GSSoftVertexFP& v1, const GSSoftVertexFP& v2)
|
|
||||||
{
|
|
||||||
GSSoftVertexFP v0;
|
|
||||||
v0.c = v1.c - v2.c;
|
|
||||||
v0.p = v1.p - v2.p;
|
|
||||||
v0.t = v1.t - v2.t;
|
|
||||||
return v0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP operator * (const GSSoftVertexFP& v, GSSoftVertexFP::Scalar s)
|
|
||||||
{
|
|
||||||
GSSoftVertexFP v0;
|
|
||||||
GSSoftVertexFP::Vector vs(s);
|
|
||||||
v0.c = v.c * vs;
|
|
||||||
v0.p = v.p * vs;
|
|
||||||
v0.t = v.t * vs;
|
|
||||||
return v0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFP operator / (const GSSoftVertexFP& v, GSSoftVertexFP::Scalar s)
|
|
||||||
{
|
|
||||||
GSSoftVertexFP v0;
|
|
||||||
GSSoftVertexFP::Vector vs(s);
|
|
||||||
v0.c = v.c / vs;
|
|
||||||
v0.p = v.p / vs;
|
|
||||||
v0.t = v.t / vs;
|
|
||||||
return v0;
|
|
||||||
}
|
|
|
@ -1,377 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
/*
|
|
||||||
inline int fixmul(int x, int y)
|
|
||||||
{
|
|
||||||
#ifndef _M_AMD64
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov eax, x
|
|
||||||
imul y
|
|
||||||
add eax, 0x8000
|
|
||||||
adc edx, 0
|
|
||||||
shrd eax, edx, 16
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return (int)(((__int64)x * y + 0x8000) >> 16);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
inline int fixmul(int x, int y)
|
|
||||||
{
|
|
||||||
#ifndef _M_AMD64
|
|
||||||
_asm
|
|
||||||
{
|
|
||||||
mov eax, x
|
|
||||||
imul y
|
|
||||||
shrd eax, edx, 16
|
|
||||||
sar edx, 15
|
|
||||||
jz Out2
|
|
||||||
cmp edx, -1
|
|
||||||
jz Out2
|
|
||||||
; call _set_errno_erange
|
|
||||||
mov eax, 0x7FFFFFFF
|
|
||||||
cmp x, 0
|
|
||||||
jge Out1
|
|
||||||
neg eax
|
|
||||||
Out1:
|
|
||||||
cmp y, 0
|
|
||||||
jge Out2
|
|
||||||
neg eax
|
|
||||||
Out2:
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return (int)(((__int64)x * y + 0x8000) >> 16);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int fixdiv(int x, int y)
|
|
||||||
{
|
|
||||||
#ifndef _M_AMD64
|
|
||||||
_asm
|
|
||||||
{
|
|
||||||
push esi
|
|
||||||
|
|
||||||
mov ecx, y
|
|
||||||
xor esi, esi
|
|
||||||
mov eax, x
|
|
||||||
or eax, eax
|
|
||||||
jns Out1
|
|
||||||
neg eax
|
|
||||||
inc esi
|
|
||||||
Out1:
|
|
||||||
or ecx, ecx
|
|
||||||
jns Out2
|
|
||||||
neg ecx
|
|
||||||
inc esi
|
|
||||||
Out2:
|
|
||||||
mov edx, eax
|
|
||||||
shr edx, 0x10
|
|
||||||
shl eax, 0x10
|
|
||||||
cmp edx, ecx
|
|
||||||
jae Out3
|
|
||||||
div ecx
|
|
||||||
or eax, eax
|
|
||||||
jns Out4
|
|
||||||
Out3:
|
|
||||||
; call _set_errno_erange
|
|
||||||
mov eax, 0x7FFFFFFF
|
|
||||||
Out4:
|
|
||||||
test esi, 1
|
|
||||||
je Out5
|
|
||||||
neg eax
|
|
||||||
Out5:
|
|
||||||
pop esi
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return (int)(((__int64)x << 16) / y);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// GSSoftVertexFX
|
|
||||||
//
|
|
||||||
|
|
||||||
__declspec(align(16)) union GSSoftVertexFX
|
|
||||||
{
|
|
||||||
class __declspec(novtable) Scalar
|
|
||||||
{
|
|
||||||
int val;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Scalar() {}
|
|
||||||
explicit Scalar(float f) {val = (int)(f*65536);}
|
|
||||||
explicit Scalar(int i) {val = i;}
|
|
||||||
|
|
||||||
int Value() const {return val;}
|
|
||||||
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
void sat() {ASSERT(0); val = val < 0 ? 0 : val > (255<<16) ? (255<<16) : val;} // TODO
|
|
||||||
void rcp() {val = (int)(65536.0f*65536.0f / val);} // TODO
|
|
||||||
#else
|
|
||||||
void sat() {val = val < 0 ? 0 : val > (255<<16) ? (255<<16) : val;}
|
|
||||||
void rcp() {val = (int)(65536.0f*65536.0f / val);}
|
|
||||||
#endif
|
|
||||||
void abss() {val = abs(val);}
|
|
||||||
|
|
||||||
Scalar floors() const {Scalar s; s.val = val & 0xffff0000; return s;}
|
|
||||||
int floori() const {return val >> 16;}
|
|
||||||
|
|
||||||
Scalar ceils() const {Scalar s; s.val = (val + 0xffff) & 0xffff0000; return s;}
|
|
||||||
int ceili() const {return (val + 0xffff) >> 16;}
|
|
||||||
|
|
||||||
void operator = (float f) {val = (int)(f*65536);}
|
|
||||||
void operator = (int i) {val = i;}
|
|
||||||
|
|
||||||
operator float() const {return (float)val / 65536;}
|
|
||||||
operator int() const {return val >> 16;}
|
|
||||||
|
|
||||||
void operator += (const Scalar& s) {val += s.val;}
|
|
||||||
void operator -= (const Scalar& s) {val -= s.val;}
|
|
||||||
void operator *= (const Scalar& s) {val = fixmul(val, s.val);}
|
|
||||||
void operator /= (const Scalar& s) {val = fixdiv(val, s.val);}
|
|
||||||
|
|
||||||
friend Scalar operator + (const Scalar& s1, const Scalar& s2) {return Scalar(s1.val + s2.val);}
|
|
||||||
friend Scalar operator - (const Scalar& s1, const Scalar& s2) {return Scalar(s1.val - s2.val);}
|
|
||||||
friend Scalar operator * (const Scalar& s1, const Scalar& s2) {return Scalar(fixmul(s1.val, s2.val));}
|
|
||||||
friend Scalar operator / (const Scalar& s1, const Scalar& s2) {return Scalar(fixdiv(s1.val, s2.val));}
|
|
||||||
|
|
||||||
friend Scalar operator + (const Scalar& s1, int i) {return Scalar(s1.val + i);}
|
|
||||||
friend Scalar operator - (const Scalar& s1, int i) {return Scalar(s1.val - i);}
|
|
||||||
friend Scalar operator * (const Scalar& s1, int i) {return Scalar(s1.val * i);}
|
|
||||||
friend Scalar operator / (const Scalar& s1, int i) {return Scalar(s1.val / i);}
|
|
||||||
|
|
||||||
friend bool operator == (const Scalar& s1, const Scalar& s2) {return s1.val == s2.val;}
|
|
||||||
friend bool operator <= (const Scalar& s1, const Scalar& s2) {return s1.val <= s2.val;}
|
|
||||||
friend bool operator < (const Scalar& s1, const Scalar& s2) {return s1.val < s2.val;}
|
|
||||||
};
|
|
||||||
|
|
||||||
__declspec(align(16)) class __declspec(novtable) Vector
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
union
|
|
||||||
{
|
|
||||||
union {struct {Scalar x, y, z, q;}; struct {Scalar r, g, b, a;};};
|
|
||||||
union {struct {Scalar v[4];}; struct {Scalar c[4];};};
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
union {__m128i xyzq; __m128i rgba;};
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector() {}
|
|
||||||
Vector(const Vector& v) {*this = v;}
|
|
||||||
Vector(Scalar s) {*this = s;}
|
|
||||||
Vector(Scalar s0, Scalar s1, Scalar s2, Scalar s3) {x = s0; y = s1; z = s2; q = s3;}
|
|
||||||
explicit Vector(DWORD dw) {*this = dw;}
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
Vector(__m128i i0123) {*this = i0123;}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
|
|
||||||
void operator = (const Vector& v) {xyzq = v.xyzq;}
|
|
||||||
void operator = (__m128i i0123) {xyzq = i0123;}
|
|
||||||
void operator = (Scalar s) {xyzq = _mm_set1_epi32(s.Value());}
|
|
||||||
void operator = (DWORD dw)
|
|
||||||
{
|
|
||||||
__m128i zero = _mm_setzero_si128();
|
|
||||||
xyzq = _mm_unpacklo_epi16(zero, _mm_unpacklo_epi8(_mm_cvtsi32_si128(dw), zero));
|
|
||||||
}
|
|
||||||
|
|
||||||
operator __m128i() const {return xyzq;}
|
|
||||||
operator DWORD() const
|
|
||||||
{
|
|
||||||
__m128i r0 = xyzq;
|
|
||||||
r0 = _mm_srli_si128(r0, 2);
|
|
||||||
r0 = _mm_packs_epi32(r0, r0);
|
|
||||||
r0 = _mm_packus_epi16(r0, r0);
|
|
||||||
return (DWORD)_mm_cvtsi128_si32(r0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sat() {xyzq = _mm_and_si128(_mm_min_epi16(_mm_max_epi16(xyzq, _mm_setzero_si128()), _mm_set1_epi32(0x00ff0000)), _mm_set1_epi32(0xffff0000));}
|
|
||||||
void rcp() {ASSERT(0);} // TODO {xyzq = _mm_rcp_ps(xyzq);}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
void operator = (const Vector& v) {x = v.x; y = v.y; z = v.z; q = v.q;}
|
|
||||||
void operator = (Scalar s) {x = y = z = q = s;}
|
|
||||||
void operator = (DWORD dw)
|
|
||||||
{
|
|
||||||
x = (int)((dw & 0x000000ff) << 16);
|
|
||||||
y = (int)((dw & 0x0000ff00) << 8);
|
|
||||||
z = (int)((dw & 0x00ff0000) << 0);
|
|
||||||
q = (int)((dw & 0xff000000) >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator DWORD() const
|
|
||||||
{
|
|
||||||
return (DWORD)((((DWORD)(int)x&0xff)<<0) | (((DWORD)(int)y&0xff)<<8) | (((DWORD)(int)z&0xff)<<16) | (((DWORD)(int)q&0xff)<<24));
|
|
||||||
}
|
|
||||||
|
|
||||||
void sat() {x.sat(); y.sat(); z.sat(); q.sat();}
|
|
||||||
void rcp() {x.rcp(); y.rcp(); z.rcp(); q.rcp();}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
// TODO
|
|
||||||
void operator += (const Vector& v) {*this = *this + v;}
|
|
||||||
void operator -= (const Vector& v) {*this = *this - v;}
|
|
||||||
void operator *= (const Vector& v) {*this = *this * v;}
|
|
||||||
void operator /= (const Vector& v) {*this = *this / v;}
|
|
||||||
|
|
||||||
void absv() {x.abss(); y.abss(); z.abss(); q.abss();}
|
|
||||||
|
|
||||||
friend Vector operator + (const Vector& v1, const Vector& v2);
|
|
||||||
friend Vector operator - (const Vector& v1, const Vector& v2);
|
|
||||||
friend Vector operator * (const Vector& v1, const Vector& v2);
|
|
||||||
friend Vector operator / (const Vector& v1, const Vector& v2);
|
|
||||||
|
|
||||||
friend Vector operator + (const Vector& v, Scalar s);
|
|
||||||
friend Vector operator - (const Vector& v, Scalar s);
|
|
||||||
friend Vector operator * (const Vector& v, Scalar s);
|
|
||||||
friend Vector operator / (const Vector& v, Scalar s);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct {__declspec(align(16)) Vector c, p, t;};
|
|
||||||
struct {__declspec(align(16)) Vector sv[3];};
|
|
||||||
struct {__declspec(align(16)) Scalar s[12];};
|
|
||||||
|
|
||||||
GSSoftVertexFX() {}
|
|
||||||
GSSoftVertexFX(const GSSoftVertexFX& v) {*this = v;}
|
|
||||||
|
|
||||||
void operator = (const GSSoftVertexFX& v) {c = v.c; p = v.p; t = v.t;}
|
|
||||||
void operator += (const GSSoftVertexFX& v) {c += v.c; p += v.p; t += v.t;}
|
|
||||||
|
|
||||||
operator CPoint() const {return CPoint((int)p.x, (int)p.y);}
|
|
||||||
|
|
||||||
friend GSSoftVertexFX operator + (const GSSoftVertexFX& v1, const GSSoftVertexFX& v2);
|
|
||||||
friend GSSoftVertexFX operator - (const GSSoftVertexFX& v1, const GSSoftVertexFX& v2);
|
|
||||||
|
|
||||||
friend GSSoftVertexFX operator * (const GSSoftVertexFX& v, Scalar s);
|
|
||||||
friend GSSoftVertexFX operator / (const GSSoftVertexFX& v, Scalar s);
|
|
||||||
|
|
||||||
static void Exchange(GSSoftVertexFX* __restrict v1, GSSoftVertexFX* __restrict v2)
|
|
||||||
{
|
|
||||||
// GSSoftVertexFX v = *v1; *v1 = *v2; *v2 = v;
|
|
||||||
Vector c = v1->c, p = v1->p, t = v1->t;
|
|
||||||
v1->c = v2->c; v1->p = v2->p; v1->t = v2->t;
|
|
||||||
v2->c = c; v2->p = p; v2->t = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline DWORD GetZ() const
|
|
||||||
{
|
|
||||||
ASSERT((int)p.z >= 0 && (int)p.q >= 0);
|
|
||||||
return ((DWORD)(int)p.z << 1) + ((DWORD)(int)p.q >> 15);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#if _M_IX86_FP >= 2 || defined(_M_AMD64)
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator + (const GSSoftVertexFX::Vector& v1, const GSSoftVertexFX::Vector& v2) {return GSSoftVertexFX::Vector(_mm_add_epi32(v1, v2));}
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator - (const GSSoftVertexFX::Vector& v1, const GSSoftVertexFX::Vector& v2) {return GSSoftVertexFX::Vector(_mm_sub_epi32(v1, v2));}
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator * (const GSSoftVertexFX::Vector& v1, const GSSoftVertexFX::Vector& v2)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
__m128 r1 = _mm_mul_ps(_mm_cvtepi32_ps(v1), _mm_set1_ps(1.0f/65536));
|
|
||||||
__m128 r2 = _mm_cvtepi32_ps(v2);
|
|
||||||
__m128i r0 = _mm_cvtps_epi32(_mm_mul_ps(r1, r2));
|
|
||||||
return GSSoftVertexFX::Vector(r0);
|
|
||||||
}
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator / (const GSSoftVertexFX::Vector& v1, const GSSoftVertexFX::Vector& v2)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
__m128 r1 = _mm_mul_ps(_mm_cvtepi32_ps(v1), _mm_set1_ps(65536));
|
|
||||||
__m128 r2 = _mm_cvtepi32_ps(v2);
|
|
||||||
__m128i r0 = _mm_cvtps_epi32(_mm_div_ps(r1, r2));
|
|
||||||
return GSSoftVertexFX::Vector(r0);
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator + (const GSSoftVertexFX::Vector& v, const GSSoftVertexFX::Scalar s) {return GSSoftVertexFX::Vector(_mm_add_epi32(v, _mm_set1_epi32(s.Value())));}
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator - (const GSSoftVertexFX::Vector& v, const GSSoftVertexFX::Scalar s) {return GSSoftVertexFX::Vector(_mm_sub_epi32(v, _mm_set1_epi32(s.Value())));}
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator * (const GSSoftVertexFX::Vector& v, const GSSoftVertexFX::Scalar s)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
__m128 r1 = _mm_mul_ps(_mm_cvtepi32_ps(v), _mm_set1_ps(1.0f/65536));
|
|
||||||
__m128 r2 = _mm_cvtepi32_ps(_mm_set1_epi32(s.Value()));
|
|
||||||
__m128i r0 = _mm_cvtps_epi32(_mm_mul_ps(r1, r2));
|
|
||||||
return GSSoftVertexFX::Vector(r0);
|
|
||||||
}
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator / (const GSSoftVertexFX::Vector& v, const GSSoftVertexFX::Scalar s)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
__m128 r1 = _mm_mul_ps(_mm_cvtepi32_ps(v), _mm_set1_ps(65536));
|
|
||||||
__m128 r2 = _mm_cvtepi32_ps(_mm_set1_epi32(s.Value()));
|
|
||||||
__m128i r0 = _mm_cvtps_epi32(_mm_div_ps(r1, r2));
|
|
||||||
return GSSoftVertexFX::Vector(r0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator + (const GSSoftVertexFX::Vector& v1, const GSSoftVertexFX::Vector& v2) {return GSSoftVertexFX::Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.q + v2.q);}
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator - (const GSSoftVertexFX::Vector& v1, const GSSoftVertexFX::Vector& v2) {return GSSoftVertexFX::Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.q - v2.q);}
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator * (const GSSoftVertexFX::Vector& v1, const GSSoftVertexFX::Vector& v2) {return GSSoftVertexFX::Vector(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.q * v2.q);}
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator / (const GSSoftVertexFX::Vector& v1, const GSSoftVertexFX::Vector& v2) {return GSSoftVertexFX::Vector(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z, v1.q / v2.q);}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator + (const GSSoftVertexFX::Vector& v, GSSoftVertexFX::Scalar s) {return GSSoftVertexFX::Vector(v.x + s, v.y + s, v.z + s, v.q + s);}
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator - (const GSSoftVertexFX::Vector& v, GSSoftVertexFX::Scalar s) {return GSSoftVertexFX::Vector(v.x - s, v.y - s, v.z - s, v.q - s);}
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator * (const GSSoftVertexFX::Vector& v, GSSoftVertexFX::Scalar s) {return GSSoftVertexFX::Vector(v.x * s, v.y * s, v.z * s, v.q * s);}
|
|
||||||
__forceinline GSSoftVertexFX::Vector operator / (const GSSoftVertexFX::Vector& v, GSSoftVertexFX::Scalar s) {return GSSoftVertexFX::Vector(v.x / s, v.y / s, v.z / s, v.q / s);}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFX operator + (const GSSoftVertexFX& v1, const GSSoftVertexFX& v2)
|
|
||||||
{
|
|
||||||
GSSoftVertexFX v0;
|
|
||||||
v0.c = v1.c + v2.c;
|
|
||||||
v0.p = v1.p + v2.p;
|
|
||||||
v0.t = v1.t + v2.t;
|
|
||||||
return v0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFX operator - (const GSSoftVertexFX& v1, const GSSoftVertexFX& v2)
|
|
||||||
{
|
|
||||||
GSSoftVertexFX v0;
|
|
||||||
v0.c = v1.c - v2.c;
|
|
||||||
v0.p = v1.p - v2.p;
|
|
||||||
v0.t = v1.t - v2.t;
|
|
||||||
return v0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFX operator * (const GSSoftVertexFX& v, GSSoftVertexFX::Scalar s)
|
|
||||||
{
|
|
||||||
GSSoftVertexFX v0;
|
|
||||||
GSSoftVertexFX::Vector vs(s);
|
|
||||||
v0.c = v.c * vs;
|
|
||||||
v0.p = v.p * vs;
|
|
||||||
v0.t = v.t * vs;
|
|
||||||
return v0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline GSSoftVertexFX operator / (const GSSoftVertexFX& v, GSSoftVertexFX::Scalar s)
|
|
||||||
{
|
|
||||||
GSSoftVertexFX v0;
|
|
||||||
GSSoftVertexFX::Vector vs(s);
|
|
||||||
v0.c = v.c / vs;
|
|
||||||
v0.p = v.p / vs;
|
|
||||||
v0.t = v.t / vs;
|
|
||||||
return v0;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,446 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "GS.h"
|
|
||||||
#include "GSWnd.h"
|
|
||||||
#include "GSLocalMemory.h"
|
|
||||||
#include "GSTextureCache.h"
|
|
||||||
#include "GSSoftVertex.h"
|
|
||||||
#include "GSVertexList.h"
|
|
||||||
#include "GSCapture.h"
|
|
||||||
#include "GSPerfMon.h"
|
|
||||||
//
|
|
||||||
//#define ENABLE_CAPTURE_STATE
|
|
||||||
//
|
|
||||||
|
|
||||||
/*
|
|
||||||
//#define DEBUG_SAVETEXTURES
|
|
||||||
#define DEBUG_LOG
|
|
||||||
#define DEBUG_LOG2
|
|
||||||
#define DEBUG_LOGVERTICES
|
|
||||||
#define DEBUG_RENDERTARGETS
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define D3DCOLORWRITEENABLE_RGB (D3DCOLORWRITEENABLE_RED|D3DCOLORWRITEENABLE_GREEN|D3DCOLORWRITEENABLE_BLUE)
|
|
||||||
#define D3DCOLORWRITEENABLE_RGBA (D3DCOLORWRITEENABLE_RGB|D3DCOLORWRITEENABLE_ALPHA)
|
|
||||||
|
|
||||||
struct GSDrawingContext
|
|
||||||
{
|
|
||||||
struct GSDrawingContext() {memset(this, 0, sizeof(*this));}
|
|
||||||
|
|
||||||
GIFRegXYOFFSET XYOFFSET;
|
|
||||||
GIFRegTEX0 TEX0;
|
|
||||||
GIFRegTEX1 TEX1;
|
|
||||||
GIFRegTEX2 TEX2;
|
|
||||||
GIFRegCLAMP CLAMP;
|
|
||||||
GIFRegMIPTBP1 MIPTBP1;
|
|
||||||
GIFRegMIPTBP2 MIPTBP2;
|
|
||||||
GIFRegSCISSOR SCISSOR;
|
|
||||||
GIFRegALPHA ALPHA;
|
|
||||||
GIFRegTEST TEST;
|
|
||||||
GIFRegFBA FBA;
|
|
||||||
GIFRegFRAME FRAME;
|
|
||||||
GIFRegZBUF ZBUF;
|
|
||||||
|
|
||||||
GSLocalMemory::psmtbl_t* ftbl;
|
|
||||||
GSLocalMemory::psmtbl_t* ztbl;
|
|
||||||
GSLocalMemory::psmtbl_t* ttbl;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GSDrawingEnvironment
|
|
||||||
{
|
|
||||||
struct GSDrawingEnvironment() {memset(this, 0, sizeof(*this));}
|
|
||||||
|
|
||||||
GIFRegPRIM PRIM;
|
|
||||||
GIFRegPRMODE PRMODE;
|
|
||||||
GIFRegPRMODECONT PRMODECONT;
|
|
||||||
GIFRegTEXCLUT TEXCLUT;
|
|
||||||
GIFRegSCANMSK SCANMSK;
|
|
||||||
GIFRegTEXA TEXA;
|
|
||||||
GIFRegFOGCOL FOGCOL;
|
|
||||||
GIFRegDIMX DIMX;
|
|
||||||
GIFRegDTHE DTHE;
|
|
||||||
GIFRegCOLCLAMP COLCLAMP;
|
|
||||||
GIFRegPABE PABE;
|
|
||||||
GSDrawingContext CTXT[2];
|
|
||||||
|
|
||||||
GIFRegBITBLTBUF BITBLTBUF;
|
|
||||||
GIFRegTRXDIR TRXDIR;
|
|
||||||
GIFRegTRXPOS TRXPOS;
|
|
||||||
GIFRegTRXREG TRXREG, TRXREG2;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GSRegSet
|
|
||||||
{
|
|
||||||
GSRegPMODE* pPMODE;
|
|
||||||
GSRegSMODE1* pSMODE1;
|
|
||||||
GSRegSMODE2* pSMODE2;
|
|
||||||
GSRegDISPFB* pDISPFB[2];
|
|
||||||
GSRegDISPLAY* pDISPLAY[2];
|
|
||||||
GSRegEXTBUF* pEXTBUF;
|
|
||||||
GSRegEXTDATA* pEXTDATA;
|
|
||||||
GSRegEXTWRITE* pEXTWRITE;
|
|
||||||
GSRegBGCOLOR* pBGCOLOR;
|
|
||||||
GSRegCSR* pCSR;
|
|
||||||
GSRegIMR* pIMR;
|
|
||||||
GSRegBUSDIR* pBUSDIR;
|
|
||||||
GSRegSIGLBLID* pSIGLBLID;
|
|
||||||
|
|
||||||
struct GSRegSet()
|
|
||||||
{
|
|
||||||
memset(this, 0, sizeof(*this));
|
|
||||||
|
|
||||||
extern BYTE* g_pBasePS2Mem;
|
|
||||||
|
|
||||||
ASSERT(g_pBasePS2Mem);
|
|
||||||
|
|
||||||
pPMODE = (GSRegPMODE*)(g_pBasePS2Mem + GS_PMODE);
|
|
||||||
pSMODE1 = (GSRegSMODE1*)(g_pBasePS2Mem + GS_SMODE1);
|
|
||||||
pSMODE2 = (GSRegSMODE2*)(g_pBasePS2Mem + GS_SMODE2);
|
|
||||||
// pSRFSH = (GSRegPMODE*)(g_pBasePS2Mem + GS_SRFSH);
|
|
||||||
// pSYNCH1 = (GSRegPMODE*)(g_pBasePS2Mem + GS_SYNCH1);
|
|
||||||
// pSYNCH2 = (GSRegPMODE*)(g_pBasePS2Mem + GS_SYNCH2);
|
|
||||||
// pSYNCV = (GSRegPMODE*)(g_pBasePS2Mem + GS_SYNCV);
|
|
||||||
pDISPFB[0] = (GSRegDISPFB*)(g_pBasePS2Mem + GS_DISPFB1);
|
|
||||||
pDISPFB[1] = (GSRegDISPFB*)(g_pBasePS2Mem + GS_DISPFB2);
|
|
||||||
pDISPLAY[0] = (GSRegDISPLAY*)(g_pBasePS2Mem + GS_DISPLAY1);
|
|
||||||
pDISPLAY[1] = (GSRegDISPLAY*)(g_pBasePS2Mem + GS_DISPLAY2);
|
|
||||||
pEXTBUF = (GSRegEXTBUF*)(g_pBasePS2Mem + GS_EXTBUF);
|
|
||||||
pEXTDATA = (GSRegEXTDATA*)(g_pBasePS2Mem + GS_EXTDATA);
|
|
||||||
pEXTWRITE = (GSRegEXTWRITE*)(g_pBasePS2Mem + GS_EXTWRITE);
|
|
||||||
pBGCOLOR = (GSRegBGCOLOR*)(g_pBasePS2Mem + GS_BGCOLOR);
|
|
||||||
pCSR = (GSRegCSR*)(g_pBasePS2Mem + GS_CSR);
|
|
||||||
pIMR = (GSRegIMR*)(g_pBasePS2Mem + GS_IMR);
|
|
||||||
pBUSDIR = (GSRegBUSDIR*)(g_pBasePS2Mem + GS_BUSDIR);
|
|
||||||
pSIGLBLID = (GSRegSIGLBLID*)(g_pBasePS2Mem + GS_SIGLBLID);
|
|
||||||
}
|
|
||||||
|
|
||||||
CSize GetDispSize(int en)
|
|
||||||
{
|
|
||||||
ASSERT(en >= 0 && en < 2);
|
|
||||||
CSize size;
|
|
||||||
size.cx = (pDISPLAY[en]->DW + 1) / (pDISPLAY[en]->MAGH + 1);
|
|
||||||
size.cy = (pDISPLAY[en]->DH + 1) / (pDISPLAY[en]->MAGV + 1);
|
|
||||||
//if(pSMODE2->INT && pSMODE2->FFMD && size.cy > 1) size.cy >>= 1;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
CRect GetDispRect(int en)
|
|
||||||
{
|
|
||||||
ASSERT(en >= 0 && en < 2);
|
|
||||||
return CRect(CPoint(pDISPFB[en]->DBX, pDISPFB[en]->DBY), GetDispSize(en));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsEnabled(int en)
|
|
||||||
{
|
|
||||||
ASSERT(en >= 0 && en < 2);
|
|
||||||
if(en == 0 && pPMODE->EN1) {return(pDISPLAY[0]->DW || pDISPLAY[0]->DH);}
|
|
||||||
else if(en == 1 && pPMODE->EN2) {return(pDISPLAY[1]->DW || pDISPLAY[1]->DH);}
|
|
||||||
return(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetFPS()
|
|
||||||
{
|
|
||||||
return ((pSMODE1->CMOD&1) ? 50 : 60) / (pSMODE2->INT ? 1 : 2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GSVertex
|
|
||||||
{
|
|
||||||
GIFRegRGBAQ RGBAQ;
|
|
||||||
GIFRegST ST;
|
|
||||||
GIFRegUV UV;
|
|
||||||
GIFRegXYZ XYZ;
|
|
||||||
GIFRegFOG FOG;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GIFPath
|
|
||||||
{
|
|
||||||
GIFTag m_tag;
|
|
||||||
int m_nreg;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GSState
|
|
||||||
{
|
|
||||||
friend class GSTextureCache;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static const int m_version = 4;
|
|
||||||
|
|
||||||
GIFPath m_path[3];
|
|
||||||
GSLocalMemory m_lm;
|
|
||||||
GSDrawingEnvironment m_de;
|
|
||||||
GSDrawingContext* m_ctxt;
|
|
||||||
GSRegSet m_rs;
|
|
||||||
GSVertex m_v;
|
|
||||||
float m_q;
|
|
||||||
GSPerfMon m_perfmon;
|
|
||||||
GSCapture m_capture;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const int m_nTrMaxBytes = 1024*1024*4;
|
|
||||||
int m_nTrBytes;
|
|
||||||
BYTE* m_pTrBuff;
|
|
||||||
int m_x, m_y;
|
|
||||||
void WriteStep();
|
|
||||||
void ReadStep();
|
|
||||||
void WriteTransfer(BYTE* pMem, int len);
|
|
||||||
void FlushWriteTransfer();
|
|
||||||
void ReadTransfer(BYTE* pMem, int len);
|
|
||||||
void MoveTransfer();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
HWND m_hWnd;
|
|
||||||
int m_width, m_height;
|
|
||||||
CComPtr<IDirect3D9> m_pD3D;
|
|
||||||
CComPtr<IDirect3DDevice9> m_pD3DDev;
|
|
||||||
CComPtr<ID3DXFont> m_pD3DXFont;
|
|
||||||
CComPtr<IDirect3DSurface9> m_pOrgRenderTarget;
|
|
||||||
CComPtr<IDirect3DTexture9> m_pTmpRenderTarget;
|
|
||||||
CComPtr<IDirect3DPixelShader9> m_pPixelShaders[20];
|
|
||||||
CComPtr<IDirect3DPixelShader9> m_pHLSLTFX[38], m_pHLSLMerge[3], m_pHLSLRedBlue;
|
|
||||||
enum {PS11_EN11 = 12, PS11_EN01 = 13, PS11_EN10 = 14, PS11_EN00 = 15};
|
|
||||||
enum {PS14_EN11 = 16, PS14_EN01 = 17, PS14_EN10 = 18, PS14_EN00 = 19};
|
|
||||||
enum {PS_M16 = 0, PS_M24 = 1, PS_M32 = 2};
|
|
||||||
D3DPRESENT_PARAMETERS m_d3dpp;
|
|
||||||
DDCAPS m_ddcaps;
|
|
||||||
D3DCAPS9 m_caps;
|
|
||||||
D3DSURFACE_DESC m_bd;
|
|
||||||
D3DFORMAT m_fmtDepthStencil;
|
|
||||||
bool m_fEnablePalettizedTextures;
|
|
||||||
bool m_fNloopHack;
|
|
||||||
bool m_fField;
|
|
||||||
D3DTEXTUREFILTERTYPE m_texfilter;
|
|
||||||
|
|
||||||
virtual void VertexKick(bool fSkip) = 0;
|
|
||||||
virtual int DrawingKick(bool fSkip) = 0;
|
|
||||||
virtual void NewPrim() = 0;
|
|
||||||
virtual void FlushPrim() = 0;
|
|
||||||
virtual void Flip() = 0;
|
|
||||||
virtual void EndFrame() = 0;
|
|
||||||
virtual void InvalidateTexture(const GIFRegBITBLTBUF& BITBLTBUF, CRect r) {}
|
|
||||||
virtual void InvalidateLocalMem(DWORD TBP0, DWORD BW, DWORD PSM, CRect r) {}
|
|
||||||
virtual void MinMaxUV(int w, int h, CRect& r) {r.SetRect(0, 0, w, h);}
|
|
||||||
|
|
||||||
struct FlipInfo {CComPtr<IDirect3DTexture9> pRT; D3DSURFACE_DESC rd; scale_t scale;};
|
|
||||||
void FinishFlip(FlipInfo rt[2]);
|
|
||||||
|
|
||||||
void FlushPrimInternal();
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
// FIXME: savestate
|
|
||||||
GIFRegPRIM* m_pPRIM;
|
|
||||||
UINT32 m_PRIM;
|
|
||||||
|
|
||||||
void (*m_fpGSirq)();
|
|
||||||
|
|
||||||
typedef void (__fastcall GSState::*GIFPackedRegHandler)(GIFPackedReg* r);
|
|
||||||
GIFPackedRegHandler m_fpGIFPackedRegHandlers[16];
|
|
||||||
|
|
||||||
void __fastcall GIFPackedRegHandlerNull(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerPRIM(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerRGBA(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerSTQ(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerUV(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerXYZF2(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerXYZ2(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerTEX0_1(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerTEX0_2(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerCLAMP_1(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerCLAMP_2(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerFOG(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerXYZF3(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerXYZ3(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerA_D(GIFPackedReg* r);
|
|
||||||
void __fastcall GIFPackedRegHandlerNOP(GIFPackedReg* r);
|
|
||||||
|
|
||||||
typedef void (__fastcall GSState::*GIFRegHandler)(GIFReg* r);
|
|
||||||
GIFRegHandler m_fpGIFRegHandlers[256];
|
|
||||||
|
|
||||||
void __fastcall GIFRegHandlerNull(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerPRIM(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerRGBAQ(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerST(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerUV(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerXYZF2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerXYZ2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTEX0_1(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTEX0_2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerCLAMP_1(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerCLAMP_2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerFOG(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerXYZF3(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerXYZ3(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerNOP(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTEX1_1(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTEX1_2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTEX2_1(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTEX2_2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerXYOFFSET_1(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerXYOFFSET_2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerPRMODECONT(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerPRMODE(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTEXCLUT(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerSCANMSK(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerMIPTBP1_1(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerMIPTBP1_2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerMIPTBP2_1(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerMIPTBP2_2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTEXA(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerFOGCOL(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTEXFLUSH(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerSCISSOR_1(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerSCISSOR_2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerALPHA_1(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerALPHA_2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerDIMX(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerDTHE(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerCOLCLAMP(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTEST_1(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTEST_2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerPABE(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerFBA_1(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerFBA_2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerFRAME_1(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerFRAME_2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerZBUF_1(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerZBUF_2(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerBITBLTBUF(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTRXPOS(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTRXREG(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerTRXDIR(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerHWREG(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerSIGNAL(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerFINISH(GIFReg* r);
|
|
||||||
void __fastcall GIFRegHandlerLABEL(GIFReg* r);
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSState(int w, int h, HWND hWnd, HRESULT& hr);
|
|
||||||
virtual ~GSState();
|
|
||||||
|
|
||||||
bool m_fMultiThreaded;
|
|
||||||
|
|
||||||
virtual HRESULT ResetDevice(bool fForceWindowed = false);
|
|
||||||
|
|
||||||
UINT32 Freeze(freezeData* fd, bool fSizeOnly);
|
|
||||||
UINT32 Defrost(const freezeData* fd);
|
|
||||||
virtual void Reset();
|
|
||||||
void WriteCSR(UINT32 csr);
|
|
||||||
void ReadFIFO(BYTE* pMem);
|
|
||||||
void Transfer1(BYTE* pMem, UINT32 addr);
|
|
||||||
void Transfer2(BYTE* pMem, UINT32 size);
|
|
||||||
void Transfer3(BYTE* pMem, UINT32 size);
|
|
||||||
void Transfer(BYTE* pMem, UINT32 size, GIFPath& path);
|
|
||||||
void VSync(int field);
|
|
||||||
|
|
||||||
void GSirq(void (*fpGSirq)()) {m_fpGSirq = fpGSirq;}
|
|
||||||
|
|
||||||
UINT32 MakeSnapshot(char* path);
|
|
||||||
void Capture();
|
|
||||||
|
|
||||||
CString m_strDefaultTitle;
|
|
||||||
int m_iOSD;
|
|
||||||
void ToggleOSD();
|
|
||||||
|
|
||||||
// state
|
|
||||||
void CaptureState(CString fn);
|
|
||||||
FILE* m_sfp;
|
|
||||||
|
|
||||||
// logging
|
|
||||||
FILE* m_fp;
|
|
||||||
|
|
||||||
#ifdef DEBUG_LOGVERTICES
|
|
||||||
#define LOGV(_x_) LOGVERTEX _x_
|
|
||||||
#else
|
|
||||||
#define LOGV(_x_)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG_LOG
|
|
||||||
void LOG(LPCTSTR fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
////////////
|
|
||||||
/*
|
|
||||||
if(_tcsstr(fmt, _T("VSync"))
|
|
||||||
|| _tcsstr(fmt, _T("*** WARNING ***"))
|
|
||||||
// || _tcsstr(fmt, _T("Flush"))
|
|
||||||
|| _tcsstr(fmt, _T("CSR"))
|
|
||||||
|| _tcsstr(fmt, _T("DISP"))
|
|
||||||
|| _tcsstr(fmt, _T("FRAME"))
|
|
||||||
|| _tcsstr(fmt, _T("ZBUF"))
|
|
||||||
|| _tcsstr(fmt, _T("SMODE"))
|
|
||||||
|| _tcsstr(fmt, _T("PMODE"))
|
|
||||||
|| _tcsstr(fmt, _T("BITBLTBUF"))
|
|
||||||
|| _tcsstr(fmt, _T("TRX"))
|
|
||||||
// || _tcsstr(fmt, _T("PRIM"))
|
|
||||||
// || _tcsstr(fmt, _T("RGB"))
|
|
||||||
// || _tcsstr(fmt, _T("XYZ"))
|
|
||||||
// || _tcsstr(fmt, _T("ST"))
|
|
||||||
// || _tcsstr(fmt, _T("XYOFFSET"))
|
|
||||||
// || _tcsstr(fmt, _T("TEX"))
|
|
||||||
|| _tcsstr(fmt, _T("TEX0"))
|
|
||||||
// || _tcsstr(fmt, _T("TEX2"))
|
|
||||||
// || _tcsstr(fmt, _T("TEXFLUSH"))
|
|
||||||
// || _tcsstr(fmt, _T("UV"))
|
|
||||||
// || _tcsstr(fmt, _T("FOG"))
|
|
||||||
// || _tcsstr(fmt, _T("ALPHA"))
|
|
||||||
// || _tcsstr(fmt, _T("TBP0")) == fmt
|
|
||||||
// || _tcsstr(fmt, _T("CBP")) == fmt
|
|
||||||
// || _tcsstr(fmt, _T("*TC2 ")) == fmt
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
if(m_fp)
|
|
||||||
{
|
|
||||||
TCHAR buff[2048];
|
|
||||||
_stprintf(buff, _T("%d: "), clock());
|
|
||||||
_vstprintf(buff + strlen(buff), fmt, args);
|
|
||||||
_fputts(buff, m_fp);
|
|
||||||
fflush(m_fp);
|
|
||||||
}
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define LOG __noop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG_LOG2
|
|
||||||
void LOG2(LPCTSTR fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
if(m_fp)
|
|
||||||
{
|
|
||||||
TCHAR buff[2048];
|
|
||||||
_stprintf(buff, _T("%d: "), clock());
|
|
||||||
_vstprintf(buff + strlen(buff), fmt, args);
|
|
||||||
_fputts(buff, m_fp);
|
|
||||||
}
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define LOG2 __noop
|
|
||||||
#endif
|
|
||||||
};
|
|
|
@ -1,231 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
|
||||||
#include "gstables.h"
|
|
||||||
|
|
||||||
DWORD blockTable32[4][8] = {
|
|
||||||
{ 0, 1, 4, 5, 16, 17, 20, 21},
|
|
||||||
{ 2, 3, 6, 7, 18, 19, 22, 23},
|
|
||||||
{ 8, 9, 12, 13, 24, 25, 28, 29},
|
|
||||||
{ 10, 11, 14, 15, 26, 27, 30, 31}
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD blockTable32Z[4][8] = {
|
|
||||||
{ 24, 25, 28, 29, 8, 9, 12, 13},
|
|
||||||
{ 26, 27, 30, 31, 10, 11, 14, 15},
|
|
||||||
{ 16, 17, 20, 21, 0, 1, 4, 5},
|
|
||||||
{ 18, 19, 22, 23, 2, 3, 6, 7}
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD blockTable16[8][4] = {
|
|
||||||
{ 0, 2, 8, 10 },
|
|
||||||
{ 1, 3, 9, 11 },
|
|
||||||
{ 4, 6, 12, 14 },
|
|
||||||
{ 5, 7, 13, 15 },
|
|
||||||
{ 16, 18, 24, 26 },
|
|
||||||
{ 17, 19, 25, 27 },
|
|
||||||
{ 20, 22, 28, 30 },
|
|
||||||
{ 21, 23, 29, 31 }
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD blockTable16S[8][4] = {
|
|
||||||
{ 0, 2, 16, 18 },
|
|
||||||
{ 1, 3, 17, 19 },
|
|
||||||
{ 8, 10, 24, 26 },
|
|
||||||
{ 9, 11, 25, 27 },
|
|
||||||
{ 4, 6, 20, 22 },
|
|
||||||
{ 5, 7, 21, 23 },
|
|
||||||
{ 12, 14, 28, 30 },
|
|
||||||
{ 13, 15, 29, 31 }
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD blockTable16Z[8][4] = {
|
|
||||||
{ 24, 26, 16, 18 },
|
|
||||||
{ 25, 27, 17, 19 },
|
|
||||||
{ 28, 30, 20, 22 },
|
|
||||||
{ 29, 31, 21, 23 },
|
|
||||||
{ 8, 10, 0, 2 },
|
|
||||||
{ 9, 11, 1, 3 },
|
|
||||||
{ 12, 14, 4, 6 },
|
|
||||||
{ 13, 15, 5, 7 }
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD blockTable16SZ[8][4] = {
|
|
||||||
{ 24, 26, 8, 10 },
|
|
||||||
{ 25, 27, 9, 11 },
|
|
||||||
{ 16, 18, 0, 2 },
|
|
||||||
{ 17, 19, 1, 3 },
|
|
||||||
{ 28, 30, 12, 14 },
|
|
||||||
{ 29, 31, 13, 15 },
|
|
||||||
{ 20, 22, 4, 6 },
|
|
||||||
{ 21, 23, 5, 7 }
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD blockTable8[4][8] = {
|
|
||||||
{ 0, 1, 4, 5, 16, 17, 20, 21},
|
|
||||||
{ 2, 3, 6, 7, 18, 19, 22, 23},
|
|
||||||
{ 8, 9, 12, 13, 24, 25, 28, 29},
|
|
||||||
{ 10, 11, 14, 15, 26, 27, 30, 31}
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD blockTable4[8][4] = {
|
|
||||||
{ 0, 2, 8, 10 },
|
|
||||||
{ 1, 3, 9, 11 },
|
|
||||||
{ 4, 6, 12, 14 },
|
|
||||||
{ 5, 7, 13, 15 },
|
|
||||||
{ 16, 18, 24, 26 },
|
|
||||||
{ 17, 19, 25, 27 },
|
|
||||||
{ 20, 22, 28, 30 },
|
|
||||||
{ 21, 23, 29, 31 }
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD columnTable32[8][8] = {
|
|
||||||
{ 0, 1, 4, 5, 8, 9, 12, 13 },
|
|
||||||
{ 2, 3, 6, 7, 10, 11, 14, 15 },
|
|
||||||
{ 16, 17, 20, 21, 24, 25, 28, 29 },
|
|
||||||
{ 18, 19, 22, 23, 26, 27, 30, 31 },
|
|
||||||
{ 32, 33, 36, 37, 40, 41, 44, 45 },
|
|
||||||
{ 34, 35, 38, 39, 42, 43, 46, 47 },
|
|
||||||
{ 48, 49, 52, 53, 56, 57, 60, 61 },
|
|
||||||
{ 50, 51, 54, 55, 58, 59, 62, 63 },
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD columnTable16[8][16] = {
|
|
||||||
{ 0, 2, 8, 10, 16, 18, 24, 26,
|
|
||||||
1, 3, 9, 11, 17, 19, 25, 27 },
|
|
||||||
{ 4, 6, 12, 14, 20, 22, 28, 30,
|
|
||||||
5, 7, 13, 15, 21, 23, 29, 31 },
|
|
||||||
{ 32, 34, 40, 42, 48, 50, 56, 58,
|
|
||||||
33, 35, 41, 43, 49, 51, 57, 59 },
|
|
||||||
{ 36, 38, 44, 46, 52, 54, 60, 62,
|
|
||||||
37, 39, 45, 47, 53, 55, 61, 63 },
|
|
||||||
{ 64, 66, 72, 74, 80, 82, 88, 90,
|
|
||||||
65, 67, 73, 75, 81, 83, 89, 91 },
|
|
||||||
{ 68, 70, 76, 78, 84, 86, 92, 94,
|
|
||||||
69, 71, 77, 79, 85, 87, 93, 95 },
|
|
||||||
{ 96, 98, 104, 106, 112, 114, 120, 122,
|
|
||||||
97, 99, 105, 107, 113, 115, 121, 123 },
|
|
||||||
{ 100, 102, 108, 110, 116, 118, 124, 126,
|
|
||||||
101, 103, 109, 111, 117, 119, 125, 127 },
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD columnTable8[16][16] = {
|
|
||||||
{ 0, 4, 16, 20, 32, 36, 48, 52, // column 0
|
|
||||||
2, 6, 18, 22, 34, 38, 50, 54 },
|
|
||||||
{ 8, 12, 24, 28, 40, 44, 56, 60,
|
|
||||||
10, 14, 26, 30, 42, 46, 58, 62 },
|
|
||||||
{ 33, 37, 49, 53, 1, 5, 17, 21,
|
|
||||||
35, 39, 51, 55, 3, 7, 19, 23 },
|
|
||||||
{ 41, 45, 57, 61, 9, 13, 25, 29,
|
|
||||||
43, 47, 59, 63, 11, 15, 27, 31 },
|
|
||||||
{ 96, 100, 112, 116, 64, 68, 80, 84, // column 1
|
|
||||||
98, 102, 114, 118, 66, 70, 82, 86 },
|
|
||||||
{ 104, 108, 120, 124, 72, 76, 88, 92,
|
|
||||||
106, 110, 122, 126, 74, 78, 90, 94 },
|
|
||||||
{ 65, 69, 81, 85, 97, 101, 113, 117,
|
|
||||||
67, 71, 83, 87, 99, 103, 115, 119 },
|
|
||||||
{ 73, 77, 89, 93, 105, 109, 121, 125,
|
|
||||||
75, 79, 91, 95, 107, 111, 123, 127 },
|
|
||||||
{ 128, 132, 144, 148, 160, 164, 176, 180, // column 2
|
|
||||||
130, 134, 146, 150, 162, 166, 178, 182 },
|
|
||||||
{ 136, 140, 152, 156, 168, 172, 184, 188,
|
|
||||||
138, 142, 154, 158, 170, 174, 186, 190 },
|
|
||||||
{ 161, 165, 177, 181, 129, 133, 145, 149,
|
|
||||||
163, 167, 179, 183, 131, 135, 147, 151 },
|
|
||||||
{ 169, 173, 185, 189, 137, 141, 153, 157,
|
|
||||||
171, 175, 187, 191, 139, 143, 155, 159 },
|
|
||||||
{ 224, 228, 240, 244, 192, 196, 208, 212, // column 3
|
|
||||||
226, 230, 242, 246, 194, 198, 210, 214 },
|
|
||||||
{ 232, 236, 248, 252, 200, 204, 216, 220,
|
|
||||||
234, 238, 250, 254, 202, 206, 218, 222 },
|
|
||||||
{ 193, 197, 209, 213, 225, 229, 241, 245,
|
|
||||||
195, 199, 211, 215, 227, 231, 243, 247 },
|
|
||||||
{ 201, 205, 217, 221, 233, 237, 249, 253,
|
|
||||||
203, 207, 219, 223, 235, 239, 251, 255 },
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD columnTable4[16][32] = {
|
|
||||||
{ 0, 8, 32, 40, 64, 72, 96, 104, // column 0
|
|
||||||
2, 10, 34, 42, 66, 74, 98, 106,
|
|
||||||
4, 12, 36, 44, 68, 76, 100, 108,
|
|
||||||
6, 14, 38, 46, 70, 78, 102, 110 },
|
|
||||||
{ 16, 24, 48, 56, 80, 88, 112, 120,
|
|
||||||
18, 26, 50, 58, 82, 90, 114, 122,
|
|
||||||
20, 28, 52, 60, 84, 92, 116, 124,
|
|
||||||
22, 30, 54, 62, 86, 94, 118, 126 },
|
|
||||||
{ 65, 73, 97, 105, 1, 9, 33, 41,
|
|
||||||
67, 75, 99, 107, 3, 11, 35, 43,
|
|
||||||
69, 77, 101, 109, 5, 13, 37, 45,
|
|
||||||
71, 79, 103, 111, 7, 15, 39, 47 },
|
|
||||||
{ 81, 89, 113, 121, 17, 25, 49, 57,
|
|
||||||
83, 91, 115, 123, 19, 27, 51, 59,
|
|
||||||
85, 93, 117, 125, 21, 29, 53, 61,
|
|
||||||
87, 95, 119, 127, 23, 31, 55, 63 },
|
|
||||||
{ 192, 200, 224, 232, 128, 136, 160, 168, // column 1
|
|
||||||
194, 202, 226, 234, 130, 138, 162, 170,
|
|
||||||
196, 204, 228, 236, 132, 140, 164, 172,
|
|
||||||
198, 206, 230, 238, 134, 142, 166, 174 },
|
|
||||||
{ 208, 216, 240, 248, 144, 152, 176, 184,
|
|
||||||
210, 218, 242, 250, 146, 154, 178, 186,
|
|
||||||
212, 220, 244, 252, 148, 156, 180, 188,
|
|
||||||
214, 222, 246, 254, 150, 158, 182, 190 },
|
|
||||||
{ 129, 137, 161, 169, 193, 201, 225, 233,
|
|
||||||
131, 139, 163, 171, 195, 203, 227, 235,
|
|
||||||
133, 141, 165, 173, 197, 205, 229, 237,
|
|
||||||
135, 143, 167, 175, 199, 207, 231, 239 },
|
|
||||||
{ 145, 153, 177, 185, 209, 217, 241, 249,
|
|
||||||
147, 155, 179, 187, 211, 219, 243, 251,
|
|
||||||
149, 157, 181, 189, 213, 221, 245, 253,
|
|
||||||
151, 159, 183, 191, 215, 223, 247, 255 },
|
|
||||||
{ 256, 264, 288, 296, 320, 328, 352, 360, // column 2
|
|
||||||
258, 266, 290, 298, 322, 330, 354, 362,
|
|
||||||
260, 268, 292, 300, 324, 332, 356, 364,
|
|
||||||
262, 270, 294, 302, 326, 334, 358, 366 },
|
|
||||||
{ 272, 280, 304, 312, 336, 344, 368, 376,
|
|
||||||
274, 282, 306, 314, 338, 346, 370, 378,
|
|
||||||
276, 284, 308, 316, 340, 348, 372, 380,
|
|
||||||
278, 286, 310, 318, 342, 350, 374, 382 },
|
|
||||||
{ 321, 329, 353, 361, 257, 265, 289, 297,
|
|
||||||
323, 331, 355, 363, 259, 267, 291, 299,
|
|
||||||
325, 333, 357, 365, 261, 269, 293, 301,
|
|
||||||
327, 335, 359, 367, 263, 271, 295, 303 },
|
|
||||||
{ 337, 345, 369, 377, 273, 281, 305, 313,
|
|
||||||
339, 347, 371, 379, 275, 283, 307, 315,
|
|
||||||
341, 349, 373, 381, 277, 285, 309, 317,
|
|
||||||
343, 351, 375, 383, 279, 287, 311, 319 },
|
|
||||||
{ 448, 456, 480, 488, 384, 392, 416, 424, // column 3
|
|
||||||
450, 458, 482, 490, 386, 394, 418, 426,
|
|
||||||
452, 460, 484, 492, 388, 396, 420, 428,
|
|
||||||
454, 462, 486, 494, 390, 398, 422, 430 },
|
|
||||||
{ 464, 472, 496, 504, 400, 408, 432, 440,
|
|
||||||
466, 474, 498, 506, 402, 410, 434, 442,
|
|
||||||
468, 476, 500, 508, 404, 412, 436, 444,
|
|
||||||
470, 478, 502, 510, 406, 414, 438, 446 },
|
|
||||||
{ 385, 393, 417, 425, 449, 457, 481, 489,
|
|
||||||
387, 395, 419, 427, 451, 459, 483, 491,
|
|
||||||
389, 397, 421, 429, 453, 461, 485, 493,
|
|
||||||
391, 399, 423, 431, 455, 463, 487, 495 },
|
|
||||||
{ 401, 409, 433, 441, 465, 473, 497, 505,
|
|
||||||
403, 411, 435, 443, 467, 475, 499, 507,
|
|
||||||
405, 413, 437, 445, 469, 477, 501, 509,
|
|
||||||
407, 415, 439, 447, 471, 479, 503, 511 },
|
|
||||||
};
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
extern DWORD blockTable32[4][8];
|
|
||||||
extern DWORD blockTable32Z[4][8];
|
|
||||||
extern DWORD blockTable16[8][4];
|
|
||||||
extern DWORD blockTable16S[8][4];
|
|
||||||
extern DWORD blockTable16Z[8][4];
|
|
||||||
extern DWORD blockTable16SZ[8][4];
|
|
||||||
extern DWORD blockTable8[4][8];
|
|
||||||
extern DWORD blockTable4[8][4];
|
|
||||||
extern DWORD columnTable32[8][8];
|
|
||||||
extern DWORD columnTable16[8][16];
|
|
||||||
extern DWORD columnTable8[16][16];
|
|
||||||
extern DWORD columnTable4[16][32];
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,133 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "GS.h"
|
|
||||||
#include "GSLocalMemory.h"
|
|
||||||
|
|
||||||
template <class T> class CSurfMap : public CMap<DWORD, DWORD, CComPtr<T>, CComPtr<T>& > {};
|
|
||||||
|
|
||||||
extern bool IsRenderTarget(IDirect3DTexture9* pTexture);
|
|
||||||
extern bool HasSharedBits(DWORD sbp, DWORD spsm, DWORD dbp, DWORD dpsm);
|
|
||||||
|
|
||||||
// TODO: get rid of this *PrivateData
|
|
||||||
|
|
||||||
#ifdef __INTEL_COMPILER
|
|
||||||
struct __declspec(uuid("5D5EFE0E-5407-4BCF-855D-C46CBCD075FA"))
|
|
||||||
#else
|
|
||||||
[uuid("5D5EFE0E-5407-4BCF-855D-C46CBCD075FA")] struct
|
|
||||||
#endif
|
|
||||||
scale_t
|
|
||||||
{
|
|
||||||
float x, y;
|
|
||||||
struct scale_t() {x = y = 1;}
|
|
||||||
struct scale_t(float x, float y) {this->x = x; this->y = y;}
|
|
||||||
struct scale_t(IDirect3DResource9* p) {Get(p);}
|
|
||||||
bool operator == (const struct scale_t& s) {return fabs(x - s.x) < 0.001 && fabs(y - s.y) < 0.001;}
|
|
||||||
void Set(IDirect3DResource9* p) {p->SetPrivateData(__uuidof(*this), this, sizeof(*this), 0);}
|
|
||||||
void Get(IDirect3DResource9* p) {DWORD size = sizeof(*this); p->GetPrivateData(__uuidof(*this), this, &size);}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GSDirtyRect
|
|
||||||
{
|
|
||||||
DWORD m_PSM;
|
|
||||||
CRect m_rcDirty;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSDirtyRect() : m_PSM(PSM_PSMCT32), m_rcDirty(0, 0, 0, 0) {}
|
|
||||||
GSDirtyRect(DWORD PSM, CRect r);
|
|
||||||
CRect GetDirtyRect(const GIFRegTEX0& TEX0);
|
|
||||||
};
|
|
||||||
|
|
||||||
class GSDirtyRectList : public CAtlList<GSDirtyRect>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GSDirtyRectList() {}
|
|
||||||
GSDirtyRectList(const GSDirtyRectList& l) {*this = l;}
|
|
||||||
void operator = (const GSDirtyRectList& l);
|
|
||||||
CRect GetDirtyRect(const GIFRegTEX0& TEX0);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GSTextureBase
|
|
||||||
{
|
|
||||||
CComPtr<IDirect3DTexture9> m_pTexture, m_pPalette;
|
|
||||||
scale_t m_scale;
|
|
||||||
bool m_fRT;
|
|
||||||
D3DSURFACE_DESC m_desc;
|
|
||||||
|
|
||||||
GSTextureBase();
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GSTexture : public GSTextureBase
|
|
||||||
{
|
|
||||||
GIFRegCLAMP m_CLAMP;
|
|
||||||
GIFRegTEX0 m_TEX0;
|
|
||||||
GIFRegTEXA m_TEXA; // *
|
|
||||||
DWORD m_clut[256]; // *
|
|
||||||
GSDirtyRectList m_rcDirty;
|
|
||||||
CRect m_rcValid;
|
|
||||||
CRect m_rcHash;
|
|
||||||
DWORD m_dwHash, m_nHashDiff, m_nHashSame;
|
|
||||||
DWORD m_nBytes;
|
|
||||||
int m_nAge, m_nVsyncs;
|
|
||||||
CInterfaceList<IDirect3DTexture9> m_pSubTextures;
|
|
||||||
bool m_fTemp;
|
|
||||||
|
|
||||||
GSTexture();
|
|
||||||
};
|
|
||||||
|
|
||||||
class GSState;
|
|
||||||
|
|
||||||
class GSTextureCache : private CAtlList<GSTexture*>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
CInterfaceList<IDirect3DTexture9> m_pTexturePool;
|
|
||||||
HRESULT CreateTexture(GSState* s, GSTexture* pt, DWORD PSM, DWORD CPSM = PSM_PSMCT32);
|
|
||||||
bool IsTextureInCache(IDirect3DTexture9* pTexture);
|
|
||||||
void RemoveOldTextures(GSState* s);
|
|
||||||
bool GetDirtyRect(GSState* s, GSTexture* pt, CRect& r);
|
|
||||||
|
|
||||||
DWORD HashTexture(const CRect& r, int pitch, void* bits);
|
|
||||||
HRESULT UpdateTexture(GSState* s, GSTexture* pt, GSLocalMemory::readTexture rt);
|
|
||||||
|
|
||||||
GSTexture* ConvertRT(GSState* s, GSTexture* pt);
|
|
||||||
GSTexture* ConvertRTPitch(GSState* s, GSTexture* pt);
|
|
||||||
GSTexture* ConvertRTWidthHeight(GSState* s, GSTexture* pt);
|
|
||||||
|
|
||||||
CInterfaceList<IDirect3DTexture9> m_pRTPool;
|
|
||||||
HRESULT CreateRT(GSState* s, int w, int h, IDirect3DTexture9** ppRT);
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSTextureCache();
|
|
||||||
~GSTextureCache();
|
|
||||||
|
|
||||||
bool Fetch(GSState* s, GSTextureBase& t);
|
|
||||||
bool FetchP(GSState* s, GSTextureBase& t);
|
|
||||||
bool FetchNP(GSState* s, GSTextureBase& t);
|
|
||||||
|
|
||||||
void IncAge(CSurfMap<IDirect3DTexture9>& pRTs);
|
|
||||||
void ResetAge(DWORD TBP0);
|
|
||||||
void RemoveAll();
|
|
||||||
void InvalidateTexture(GSState* s, const GIFRegBITBLTBUF& BITBLTBUF, const CRect& r);
|
|
||||||
void InvalidateLocalMem(GSState* s, DWORD TBP0, DWORD BW, DWORD PSM, const CRect& r);
|
|
||||||
void AddRT(GIFRegTEX0& TEX0, IDirect3DTexture9* pRT, scale_t scale);
|
|
||||||
};
|
|
|
@ -1,216 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "stdafx.h"
|
|
||||||
#include "GSState.h"
|
|
||||||
|
|
||||||
void GSState::WriteStep()
|
|
||||||
{
|
|
||||||
// if(m_y == m_de.TRXREG.RRH && m_x == m_de.TRXPOS.DSAX) ASSERT(0);
|
|
||||||
|
|
||||||
if(++m_x == m_de.TRXREG.RRW)
|
|
||||||
{
|
|
||||||
m_x = m_de.TRXPOS.DSAX;
|
|
||||||
m_y++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSState::ReadStep()
|
|
||||||
{
|
|
||||||
// if(m_y == m_de.TRXREG.RRH && m_x == m_de.TRXPOS.SSAX) ASSERT(0);
|
|
||||||
|
|
||||||
if(++m_x == m_de.TRXREG.RRW)
|
|
||||||
{
|
|
||||||
m_x = m_de.TRXPOS.SSAX;
|
|
||||||
m_y++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSState::WriteTransfer(BYTE* pMem, int len)
|
|
||||||
{
|
|
||||||
LOG(_T("*TC2 WriteTransfer %d,%d (psm=%d rr=%dx%d len=%d)\n"), m_x, m_y, m_de.BITBLTBUF.DPSM, m_de.TRXREG.RRW, m_de.TRXREG.RRH, len);
|
|
||||||
|
|
||||||
if(len == 0) return;
|
|
||||||
|
|
||||||
// TODO: hmmmm
|
|
||||||
if(m_pPRIM->TME && (m_de.BITBLTBUF.DBP == m_ctxt->TEX0.TBP0 || m_de.BITBLTBUF.DBP == m_ctxt->TEX0.CBP))
|
|
||||||
FlushPrim();
|
|
||||||
|
|
||||||
int bpp = GSLocalMemory::m_psmtbl[m_de.BITBLTBUF.DPSM].trbpp;
|
|
||||||
int pitch = (m_de.TRXREG.RRW - m_de.TRXPOS.DSAX)*bpp>>3;
|
|
||||||
int height = len / pitch;
|
|
||||||
|
|
||||||
if(m_nTrBytes > 0 || height < m_de.TRXREG.RRH - m_de.TRXPOS.DSAY)
|
|
||||||
{
|
|
||||||
LOG(_T("*TC2 WriteTransfer delayed\n"));
|
|
||||||
|
|
||||||
ASSERT(len <= m_nTrMaxBytes); // transferring more than 4mb into a 4mb local mem doesn't make any sense
|
|
||||||
|
|
||||||
len = min(m_nTrMaxBytes, len);
|
|
||||||
|
|
||||||
if(m_nTrBytes + len > m_nTrMaxBytes)
|
|
||||||
FlushWriteTransfer();
|
|
||||||
|
|
||||||
memcpy(&m_pTrBuff[m_nTrBytes], pMem, len);
|
|
||||||
m_nTrBytes += len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int x = m_x, y = m_y;
|
|
||||||
|
|
||||||
(m_lm.*GSLocalMemory::m_psmtbl[m_de.BITBLTBUF.DPSM].st)(m_x, m_y, pMem, len, m_de.BITBLTBUF, m_de.TRXPOS, m_de.TRXREG);
|
|
||||||
|
|
||||||
m_perfmon.IncCounter(GSPerfMon::c_swizzle, len);
|
|
||||||
|
|
||||||
//ASSERT(m_de.TRXREG.RRH >= m_y - y);
|
|
||||||
|
|
||||||
CRect r(m_de.TRXPOS.DSAX, y, m_de.TRXREG.RRW, min(m_x == m_de.TRXPOS.DSAX ? m_y : m_y+1, m_de.TRXREG.RRH));
|
|
||||||
InvalidateTexture(m_de.BITBLTBUF, r);
|
|
||||||
|
|
||||||
m_lm.InvalidateCLUT();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSState::FlushWriteTransfer()
|
|
||||||
{
|
|
||||||
if(!m_nTrBytes) return;
|
|
||||||
|
|
||||||
int x = m_x, y = m_y;
|
|
||||||
|
|
||||||
LOG(_T("*TC2 FlushWriteTransfer %d,%d-%d,%d (psm=%d rr=%dx%d len=%d)\n"), x, y, m_x, m_y, m_de.BITBLTBUF.DPSM, m_de.TRXREG.RRW, m_de.TRXREG.RRH, m_nTrBytes);
|
|
||||||
|
|
||||||
(m_lm.*GSLocalMemory::m_psmtbl[m_de.BITBLTBUF.DPSM].st)(m_x, m_y, m_pTrBuff, m_nTrBytes, m_de.BITBLTBUF, m_de.TRXPOS, m_de.TRXREG);
|
|
||||||
|
|
||||||
m_perfmon.IncCounter(GSPerfMon::c_swizzle, m_nTrBytes);
|
|
||||||
|
|
||||||
m_nTrBytes = 0;
|
|
||||||
|
|
||||||
//ASSERT(m_de.TRXREG.RRH >= m_y - y);
|
|
||||||
|
|
||||||
CRect r(m_de.TRXPOS.DSAX, y, m_de.TRXREG.RRW, min(m_x == m_de.TRXPOS.DSAX ? m_y : m_y+1, m_de.TRXREG.RRH));
|
|
||||||
InvalidateTexture(m_de.BITBLTBUF, r);
|
|
||||||
|
|
||||||
m_lm.InvalidateCLUT();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSState::ReadTransfer(BYTE* pMem, int len)
|
|
||||||
{
|
|
||||||
BYTE* pb = (BYTE*)pMem;
|
|
||||||
WORD* pw = (WORD*)pMem;
|
|
||||||
DWORD* pd = (DWORD*)pMem;
|
|
||||||
|
|
||||||
if(m_y >= (int)m_de.TRXREG.RRH) {ASSERT(0); return;}
|
|
||||||
|
|
||||||
if(m_x == m_de.TRXPOS.SSAX && m_y == m_de.TRXPOS.SSAY)
|
|
||||||
{
|
|
||||||
CRect r(m_de.TRXPOS.SSAX, m_de.TRXPOS.SSAY, m_de.TRXREG.RRW, m_de.TRXREG.RRH);
|
|
||||||
InvalidateLocalMem(m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW, m_de.BITBLTBUF.SPSM, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(m_de.BITBLTBUF.SPSM)
|
|
||||||
{
|
|
||||||
case PSM_PSMCT32:
|
|
||||||
for(len /= 4; len-- > 0; ReadStep(), pd++)
|
|
||||||
*pd = m_lm.readPixel32(m_x, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW);
|
|
||||||
break;
|
|
||||||
case PSM_PSMCT24:
|
|
||||||
for(len /= 3; len-- > 0; ReadStep(), pb+=3)
|
|
||||||
{
|
|
||||||
DWORD dw = m_lm.readPixel24(m_x, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW);
|
|
||||||
pb[0] = ((BYTE*)&dw)[0]; pb[1] = ((BYTE*)&dw)[1]; pb[2] = ((BYTE*)&dw)[2];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PSM_PSMCT16:
|
|
||||||
for(len /= 2; len-- > 0; ReadStep(), pw++)
|
|
||||||
*pw = (WORD)m_lm.readPixel16(m_x, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW);
|
|
||||||
break;
|
|
||||||
case PSM_PSMCT16S:
|
|
||||||
for(len /= 2; len-- > 0; ReadStep(), pw++)
|
|
||||||
*pw = (WORD)m_lm.readPixel16S(m_x, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW);
|
|
||||||
break;
|
|
||||||
case PSM_PSMT8:
|
|
||||||
for(; len-- > 0; ReadStep(), pb++)
|
|
||||||
*pb = (BYTE)m_lm.readPixel8(m_x, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW);
|
|
||||||
break;
|
|
||||||
case PSM_PSMT4:
|
|
||||||
for(; len-- > 0; ReadStep(), ReadStep(), pb++)
|
|
||||||
*pb = (BYTE)(m_lm.readPixel4(m_x, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW)&0x0f)
|
|
||||||
| (BYTE)(m_lm.readPixel4(m_x+1, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW)<<4);
|
|
||||||
break;
|
|
||||||
case PSM_PSMT8H:
|
|
||||||
for(; len-- > 0; ReadStep(), pb++)
|
|
||||||
*pb = (BYTE)m_lm.readPixel8H(m_x, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW);
|
|
||||||
break;
|
|
||||||
case PSM_PSMT4HL:
|
|
||||||
for(; len-- > 0; ReadStep(), ReadStep(), pb++)
|
|
||||||
*pb = (BYTE)(m_lm.readPixel4HL(m_x, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW)&0x0f)
|
|
||||||
| (BYTE)(m_lm.readPixel4HL(m_x+1, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW)<<4);
|
|
||||||
break;
|
|
||||||
case PSM_PSMT4HH:
|
|
||||||
for(; len-- > 0; ReadStep(), ReadStep(), pb++)
|
|
||||||
*pb = (BYTE)(m_lm.readPixel4HH(m_x, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW)&0x0f)
|
|
||||||
| (BYTE)(m_lm.readPixel4HH(m_x+1, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW)<<4);
|
|
||||||
break;
|
|
||||||
case PSM_PSMZ32:
|
|
||||||
for(len /= 4; len-- > 0; ReadStep(), pd++)
|
|
||||||
*pd = m_lm.readPixel32Z(m_x, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW);
|
|
||||||
break;
|
|
||||||
case PSM_PSMZ24:
|
|
||||||
for(len /= 3; len-- > 0; ReadStep(), pb+=3)
|
|
||||||
{
|
|
||||||
DWORD dw = m_lm.readPixel24Z(m_x, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW);
|
|
||||||
pb[0] = ((BYTE*)&dw)[0]; pb[1] = ((BYTE*)&dw)[1]; pb[2] = ((BYTE*)&dw)[2];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PSM_PSMZ16:
|
|
||||||
for(len /= 2; len-- > 0; ReadStep(), pw++)
|
|
||||||
*pw = (WORD)m_lm.readPixel16Z(m_x, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW);
|
|
||||||
break;
|
|
||||||
case PSM_PSMZ16S:
|
|
||||||
for(len /= 2; len-- > 0; ReadStep(), pw++)
|
|
||||||
*pw = (WORD)m_lm.readPixel16SZ(m_x, m_y, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSState::MoveTransfer()
|
|
||||||
{
|
|
||||||
GSLocalMemory::readPixel rp = GSLocalMemory::m_psmtbl[m_de.BITBLTBUF.SPSM].rp;
|
|
||||||
GSLocalMemory::writePixel wp = GSLocalMemory::m_psmtbl[m_de.BITBLTBUF.DPSM].wp;
|
|
||||||
|
|
||||||
int sx = m_de.TRXPOS.SSAX;
|
|
||||||
int dx = m_de.TRXPOS.DSAX;
|
|
||||||
int sy = m_de.TRXPOS.SSAY;
|
|
||||||
int dy = m_de.TRXPOS.DSAY;
|
|
||||||
int w = m_de.TRXREG.RRW;
|
|
||||||
int h = m_de.TRXREG.RRH;
|
|
||||||
int xinc = 1;
|
|
||||||
int yinc = 1;
|
|
||||||
|
|
||||||
if(sx < dx) sx += w-1, dx += w-1, xinc = -1;
|
|
||||||
if(sy < dy) sy += h-1, dy += h-1, yinc = -1;
|
|
||||||
|
|
||||||
for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc*w, dx -= xinc*w)
|
|
||||||
for(int x = 0; x < w; x++, sx += xinc, dx += xinc)
|
|
||||||
(m_lm.*wp)(dx, dy, (m_lm.*rp)(sx, sy, m_de.BITBLTBUF.SBP, m_de.BITBLTBUF.SBW), m_de.BITBLTBUF.DBP, m_de.BITBLTBUF.DBW);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "stdafx.h"
|
|
||||||
#include "GSdx9.h"
|
|
||||||
#include "GSState.h"
|
|
||||||
|
|
||||||
BOOL IsDepthFormatOk(IDirect3D9* pD3D, D3DFORMAT DepthFormat, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat)
|
|
||||||
{
|
|
||||||
// Verify that the depth format exists.
|
|
||||||
HRESULT hr = pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, CGSdx9App::D3DDEVTYPE_X, AdapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, DepthFormat);
|
|
||||||
if(FAILED(hr)) return FALSE;
|
|
||||||
|
|
||||||
// Verify that the depth format is compatible.
|
|
||||||
hr = pD3D->CheckDepthStencilMatch(D3DADAPTER_DEFAULT, CGSdx9App::D3DDEVTYPE_X, AdapterFormat, BackBufferFormat, DepthFormat);
|
|
||||||
return SUCCEEDED(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT CompileShaderFromResource(IDirect3DDevice9* pD3DDev, UINT id, CString entry, CString target, UINT flags, IDirect3DPixelShader9** ppPixelShader)
|
|
||||||
{
|
|
||||||
CheckPointer(pD3DDev, E_POINTER);
|
|
||||||
CheckPointer(ppPixelShader, E_POINTER);
|
|
||||||
|
|
||||||
CComPtr<ID3DXBuffer> pShader, pErrorMsgs;
|
|
||||||
HRESULT hr = D3DXCompileShaderFromResource(
|
|
||||||
AfxGetResourceHandle(), MAKEINTRESOURCE(id),
|
|
||||||
NULL, NULL,
|
|
||||||
entry, target, flags,
|
|
||||||
&pShader, &pErrorMsgs, NULL);
|
|
||||||
ASSERT(SUCCEEDED(hr));
|
|
||||||
|
|
||||||
if(SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = pD3DDev->CreatePixelShader((DWORD*)pShader->GetBufferPointer(), ppPixelShader);
|
|
||||||
ASSERT(SUCCEEDED(hr));
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT AssembleShaderFromResource(IDirect3DDevice9* pD3DDev, UINT id, UINT flags, IDirect3DPixelShader9** ppPixelShader)
|
|
||||||
{
|
|
||||||
CheckPointer(pD3DDev, E_POINTER);
|
|
||||||
CheckPointer(ppPixelShader, E_POINTER);
|
|
||||||
|
|
||||||
CComPtr<ID3DXBuffer> pShader, pErrorMsgs;
|
|
||||||
HRESULT hr = D3DXAssembleShaderFromResource(
|
|
||||||
AfxGetResourceHandle(), MAKEINTRESOURCE(id),
|
|
||||||
NULL, NULL,
|
|
||||||
flags,
|
|
||||||
&pShader, &pErrorMsgs);
|
|
||||||
ASSERT(SUCCEEDED(hr));
|
|
||||||
|
|
||||||
if(SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = pD3DDev->CreatePixelShader((DWORD*)pShader->GetBufferPointer(), ppPixelShader);
|
|
||||||
ASSERT(SUCCEEDED(hr));
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
extern BOOL IsDepthFormatOk(IDirect3D9* pD3D, D3DFORMAT DepthFormat, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat);
|
|
||||||
extern HRESULT CompileShaderFromResource(IDirect3DDevice9* pD3DDev, UINT id, CString entry, CString target, UINT flags, IDirect3DPixelShader9** ppPixelShader);
|
|
||||||
extern HRESULT AssembleShaderFromResource(IDirect3DDevice9* pD3DDev, UINT id, UINT flags, IDirect3DPixelShader9** ppPixelShader);
|
|
|
@ -1,23 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
|
||||||
#include "GSVertexList.h"
|
|
|
@ -1,82 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
template <class VERTEX> class GSVertexList
|
|
||||||
{
|
|
||||||
VERTEX* m_v;
|
|
||||||
int m_head, m_tail, m_count;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GSVertexList()
|
|
||||||
{
|
|
||||||
m_v = (VERTEX*)_aligned_malloc(sizeof(VERTEX)*4, 16);
|
|
||||||
RemoveAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
~GSVertexList()
|
|
||||||
{
|
|
||||||
_aligned_free(m_v);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveAll()
|
|
||||||
{
|
|
||||||
m_head = m_tail = m_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
VERTEX& AddTail()
|
|
||||||
{
|
|
||||||
ASSERT(m_count < 4);
|
|
||||||
VERTEX& v = m_v[m_tail];
|
|
||||||
m_tail = (m_tail+1)&3;
|
|
||||||
m_count++;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddTail(VERTEX& v)
|
|
||||||
{
|
|
||||||
ASSERT(m_count < 4);
|
|
||||||
m_v[m_tail] = v;
|
|
||||||
m_tail = (m_tail+1)&3;
|
|
||||||
m_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveAt(int i, VERTEX& v)
|
|
||||||
{
|
|
||||||
GetAt(i, v);
|
|
||||||
i = (m_head+i)&3;
|
|
||||||
if(i == m_head) m_head = (m_head+1)&3;
|
|
||||||
else for(m_tail = (m_tail+4-1)&3; i != m_tail; i = (i+1)&3) m_v[i] = m_v[(i+1)&3];
|
|
||||||
m_count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetAt(int i, VERTEX& v)
|
|
||||||
{
|
|
||||||
ASSERT(m_count > 0);
|
|
||||||
v = m_v[(m_head+i)&3];
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetCount()
|
|
||||||
{
|
|
||||||
return m_count;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "stdafx.h"
|
|
||||||
#include "GSWnd.h"
|
|
||||||
|
|
||||||
IMPLEMENT_DYNCREATE(CGSWnd, CWnd)
|
|
||||||
|
|
||||||
CGSWnd::CGSWnd()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL CGSWnd::Create(LPCSTR pTitle)
|
|
||||||
{
|
|
||||||
CRect r;
|
|
||||||
GetDesktopWindow()->GetWindowRect(r);
|
|
||||||
// r.DeflateRect(r.Width()*3/8, r.Height()*3/8);
|
|
||||||
r.DeflateRect(r.Width()/3, r.Height()/3);
|
|
||||||
LPCTSTR wndclass = AfxRegisterWndClass(CS_VREDRAW|CS_HREDRAW|CS_DBLCLKS, AfxGetApp()->LoadStandardCursor(IDC_ARROW), 0/*(HBRUSH)(COLOR_BTNFACE + 1)*/, 0);
|
|
||||||
return CreateEx(0, wndclass, pTitle, WS_OVERLAPPEDWINDOW, r, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGSWnd::Show(bool bShow)
|
|
||||||
{
|
|
||||||
if(bShow)
|
|
||||||
{
|
|
||||||
SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
|
|
||||||
SetForegroundWindow();
|
|
||||||
ShowWindow(SW_SHOWNORMAL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ShowWindow(SW_HIDE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN_MESSAGE_MAP(CGSWnd, CWnd)
|
|
||||||
ON_WM_CLOSE()
|
|
||||||
END_MESSAGE_MAP()
|
|
||||||
|
|
||||||
void CGSWnd::OnClose()
|
|
||||||
{
|
|
||||||
PostMessage(WM_QUIT);
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
class CGSWnd : public CWnd
|
|
||||||
{
|
|
||||||
DECLARE_DYNCREATE(CGSWnd)
|
|
||||||
|
|
||||||
public:
|
|
||||||
CGSWnd();
|
|
||||||
|
|
||||||
BOOL Create(LPCSTR pTitle);
|
|
||||||
void Show(bool bShow = true);
|
|
||||||
|
|
||||||
DECLARE_MESSAGE_MAP()
|
|
||||||
|
|
||||||
afx_msg void OnClose();
|
|
||||||
};
|
|
|
@ -1,93 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
* Special Notes:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "stdafx.h"
|
|
||||||
#include "afxwin.h"
|
|
||||||
#include "GSdx9.h"
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
#define new DEBUG_NEW
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// Note!
|
|
||||||
//
|
|
||||||
// If this DLL is dynamically linked against the MFC
|
|
||||||
// DLLs, any functions exported from this DLL which
|
|
||||||
// call into MFC must have the AFX_MANAGE_STATE macro
|
|
||||||
// added at the very beginning of the function.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
//
|
|
||||||
// extern "C" BOOL PASCAL EXPORT ExportedFunction()
|
|
||||||
// {
|
|
||||||
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
||||||
// // normal function body here
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// It is very important that this macro appear in each
|
|
||||||
// function, prior to any calls into MFC. This means that
|
|
||||||
// it must appear as the first statement within the
|
|
||||||
// function, even before any object variable declarations
|
|
||||||
// as their constructors may generate calls into the MFC
|
|
||||||
// DLL.
|
|
||||||
//
|
|
||||||
// Please see MFC Technical Notes 33 and 58 for additional
|
|
||||||
// details.
|
|
||||||
//
|
|
||||||
|
|
||||||
// CGSdx9App
|
|
||||||
|
|
||||||
BEGIN_MESSAGE_MAP(CGSdx9App, CWinApp)
|
|
||||||
END_MESSAGE_MAP()
|
|
||||||
|
|
||||||
D3DDEVTYPE CGSdx9App::D3DDEVTYPE_X;
|
|
||||||
|
|
||||||
// CGSdx9App construction
|
|
||||||
|
|
||||||
CGSdx9App::CGSdx9App()
|
|
||||||
{
|
|
||||||
// TODO: add construction code here,
|
|
||||||
// Place all significant initialization in InitInstance
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// The one and only CGSdx9App object
|
|
||||||
|
|
||||||
CGSdx9App theApp;
|
|
||||||
|
|
||||||
// CGSdx9App initialization
|
|
||||||
|
|
||||||
BOOL CGSdx9App::InitInstance()
|
|
||||||
{
|
|
||||||
__super::InitInstance();
|
|
||||||
|
|
||||||
D3DDEVTYPE_X = D3DDEVTYPE_HAL;
|
|
||||||
|
|
||||||
if(GetSystemMetrics(SM_REMOTESESSION))
|
|
||||||
{
|
|
||||||
D3DDEVTYPE_X = D3DDEVTYPE_REF;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
; GSdx9.def : Declares the module parameters for the DLL.
|
|
||||||
|
|
||||||
LIBRARY "GSdx9"
|
|
||||||
|
|
||||||
EXPORTS
|
|
||||||
; Explicit exports can go here
|
|
||||||
PS2EgetLibType
|
|
||||||
PS2EgetLibName
|
|
||||||
PS2EgetLibVersion2
|
|
||||||
PS2EgetCpuPlatform
|
|
||||||
GSsetBaseMem
|
|
||||||
GSinit
|
|
||||||
GSshutdown
|
|
||||||
GSopen
|
|
||||||
GSclose
|
|
||||||
GSreset
|
|
||||||
GSwriteCSR
|
|
||||||
GSgifTransfer1
|
|
||||||
GSgifTransfer2
|
|
||||||
GSgifTransfer3
|
|
||||||
GSvsync
|
|
||||||
GSmakeSnapshot
|
|
||||||
GSkeyEvent
|
|
||||||
GSfreeze
|
|
||||||
GSconfigure
|
|
||||||
GStest
|
|
||||||
GSabout
|
|
||||||
GSreadFIFO
|
|
||||||
GSirqCallback
|
|
||||||
GSgetLastTag
|
|
||||||
; GSReplay
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2005 Gabest
|
|
||||||
* http://www.gabest.org
|
|
||||||
*
|
|
||||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef __AFXWIN_H__
|
|
||||||
#error include 'stdafx.h' before including this file for PCH
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "resource.h" // main symbols
|
|
||||||
|
|
||||||
|
|
||||||
// CGSdx9App
|
|
||||||
// See GSdx9.cpp for the implementation of this class
|
|
||||||
//
|
|
||||||
|
|
||||||
class CGSdx9App : public CWinApp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CGSdx9App();
|
|
||||||
|
|
||||||
static D3DDEVTYPE D3DDEVTYPE_X;
|
|
||||||
|
|
||||||
// Overrides
|
|
||||||
public:
|
|
||||||
virtual BOOL InitInstance();
|
|
||||||
|
|
||||||
DECLARE_MESSAGE_MAP()
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
RENDERER_D3D_NULL,
|
|
||||||
RENDERER_D3D_SW_FX,
|
|
||||||
RENDERER_D3D_SW_FP,
|
|
||||||
RENDERER_D3D_HW
|
|
||||||
};
|
|
|
@ -1,539 +0,0 @@
|
||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
|
||||||
<VisualStudioProject
|
|
||||||
ProjectType="Intel C++ Project"
|
|
||||||
Version="9.0"
|
|
||||||
Name="GSdx9"
|
|
||||||
ProjectGUID="{4A1B2A9C-A696-4523-B0A4-8046FC423932}"
|
|
||||||
VCNestedProjectGUID="{345C9F24-0B9A-4289-B375-ADD3B63461B7}"
|
|
||||||
VCNestedProjectFileName="GSdx9.vcproj"
|
|
||||||
Keyword="MFCDLLProj">
|
|
||||||
<Configurations>
|
|
||||||
<Configuration
|
|
||||||
Name="Debug|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="GeneralTool"
|
|
||||||
OutputDirectory="$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="2"
|
|
||||||
UseOfMFC="1"
|
|
||||||
CharacterSet="2"/>
|
|
||||||
<Tool
|
|
||||||
Name="DebugTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
Optimization="0"
|
|
||||||
OptimizeForProcessor="2"
|
|
||||||
PreprocessorDefinitions="D3D_DEBUG_INFO;WIN32;_WINDOWS;_DEBUG;_USRDLL"
|
|
||||||
MinimalRebuild="1"
|
|
||||||
BasicRuntimeChecks="3"
|
|
||||||
RuntimeLibrary="1"
|
|
||||||
TreatWChar_tAsBuiltInType="0"
|
|
||||||
UsePrecompiledHeader="3"
|
|
||||||
WarningLevel="3"
|
|
||||||
Detect64BitPortabilityProblems="1"
|
|
||||||
DebugInformationFormat="4"
|
|
||||||
RecognizeRestrictKeyword="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="LinkerTool"
|
|
||||||
DelayImpLib="DelayImp.lib"
|
|
||||||
AdditionalDependencies="d3d9.lib d3dx9.lib ddraw.lib strmbaseD.lib"
|
|
||||||
OutputFile="$(OutDir)\GSdx9.dll"
|
|
||||||
LinkIncremental="2"
|
|
||||||
ModuleDefinitionFile=".\GSdx9.def"
|
|
||||||
GenerateDebugInformation="1"
|
|
||||||
SubSystem="2"
|
|
||||||
ImportLibrary="$(OutDir)/GSdx9.lib"
|
|
||||||
TargetMachine="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="LibrarianTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="ResCmplrTool"
|
|
||||||
PreprocessorDefinitions="_DEBUG"
|
|
||||||
Culture="1033"
|
|
||||||
AdditionalIncludeDirectories="$(IntDir)"/>
|
|
||||||
<Tool
|
|
||||||
Name="MidlCmplrTool"
|
|
||||||
PreprocessorDefinitions="_DEBUG"
|
|
||||||
MkTypLibCompatible="0"/>
|
|
||||||
<Tool
|
|
||||||
Name="BscMakeTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="PreBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="PreLinkEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="PostBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="CustomTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="CustomNodeTool"/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="Release|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="GeneralTool"
|
|
||||||
OutputDirectory="$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="2"
|
|
||||||
UseOfMFC="1"
|
|
||||||
CharacterSet="2"/>
|
|
||||||
<Tool
|
|
||||||
Name="DebugTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
Optimization="2"
|
|
||||||
GlobalOptimizations="1"
|
|
||||||
InlineFunctionExpansion="2"
|
|
||||||
EnableIntrinsicFunctions="1"
|
|
||||||
FavorSizeOrSpeed="1"
|
|
||||||
OmitFramePointers="1"
|
|
||||||
OptimizeForProcessor="2"
|
|
||||||
OptimizeForWindowsApplication="1"
|
|
||||||
PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;_USRDLL"
|
|
||||||
StringPooling="1"
|
|
||||||
RuntimeLibrary="0"
|
|
||||||
TreatWChar_tAsBuiltInType="0"
|
|
||||||
ForceConformanceInForLoopScope="1"
|
|
||||||
UsePrecompiledHeader="3"
|
|
||||||
WarningLevel="3"
|
|
||||||
Detect64BitPortabilityProblems="1"
|
|
||||||
DebugInformationFormat="3"
|
|
||||||
RecognizeRestrictKeyword="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="LinkerTool"
|
|
||||||
DelayImpLib="DelayImp.lib"
|
|
||||||
AdditionalDependencies="d3d9.lib d3dx9.lib ddraw.lib strmbaseR.lib"
|
|
||||||
OutputFile="$(OutDir)\GSdx9.dll"
|
|
||||||
LinkIncremental="1"
|
|
||||||
ModuleDefinitionFile=".\GSdx9.def"
|
|
||||||
GenerateDebugInformation="1"
|
|
||||||
SubSystem="2"
|
|
||||||
OptimizeReferences="2"
|
|
||||||
EnableCOMDATFolding="2"
|
|
||||||
ImportLibrary="$(OutDir)/GSdx9.lib"
|
|
||||||
TargetMachine="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="LibrarianTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="ResCmplrTool"
|
|
||||||
PreprocessorDefinitions="NDEBUG"
|
|
||||||
Culture="1033"
|
|
||||||
AdditionalIncludeDirectories="$(IntDir)"/>
|
|
||||||
<Tool
|
|
||||||
Name="MidlCmplrTool"
|
|
||||||
PreprocessorDefinitions="NDEBUG"
|
|
||||||
MkTypLibCompatible="0"/>
|
|
||||||
<Tool
|
|
||||||
Name="BscMakeTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="PreBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="PreLinkEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="PostBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="CustomTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="CustomNodeTool"/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="DebugSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="GeneralTool"
|
|
||||||
OutputDirectory="$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="2"
|
|
||||||
UseOfMFC="1"
|
|
||||||
CharacterSet="2"/>
|
|
||||||
<Tool
|
|
||||||
Name="DebugTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
Optimization="0"
|
|
||||||
OptimizeForProcessor="3"
|
|
||||||
PreprocessorDefinitions="_M_IX86_FP=2;D3D_DEBUG_INFO;WIN32;_WINDOWS;_DEBUG;_USRDLL"
|
|
||||||
MinimalRebuild="1"
|
|
||||||
BasicRuntimeChecks="3"
|
|
||||||
RuntimeLibrary="1"
|
|
||||||
EnableEnhancedInstructionSet="2"
|
|
||||||
TreatWChar_tAsBuiltInType="0"
|
|
||||||
UsePrecompiledHeader="3"
|
|
||||||
WarningLevel="3"
|
|
||||||
Detect64BitPortabilityProblems="1"
|
|
||||||
DebugInformationFormat="4"
|
|
||||||
RecognizeRestrictKeyword="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="LinkerTool"
|
|
||||||
DelayImpLib="DelayImp.lib"
|
|
||||||
AdditionalDependencies="d3d9.lib d3dx9.lib ddraw.lib strmbaseD.lib"
|
|
||||||
OutputFile="$(OutDir)\GSdx9.dll"
|
|
||||||
LinkIncremental="2"
|
|
||||||
ModuleDefinitionFile=".\GSdx9.def"
|
|
||||||
GenerateDebugInformation="1"
|
|
||||||
SubSystem="2"
|
|
||||||
ImportLibrary="$(OutDir)/GSdx9.lib"
|
|
||||||
TargetMachine="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="LibrarianTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="ResCmplrTool"
|
|
||||||
PreprocessorDefinitions="_DEBUG"
|
|
||||||
Culture="1033"
|
|
||||||
AdditionalIncludeDirectories="$(IntDir)"/>
|
|
||||||
<Tool
|
|
||||||
Name="MidlCmplrTool"
|
|
||||||
PreprocessorDefinitions="_DEBUG"
|
|
||||||
MkTypLibCompatible="0"/>
|
|
||||||
<Tool
|
|
||||||
Name="BscMakeTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="PreBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="PreLinkEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="PostBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="CustomTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="CustomNodeTool"/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="ReleaseSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="GeneralTool"
|
|
||||||
OutputDirectory="$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="2"
|
|
||||||
UseOfMFC="1"
|
|
||||||
CharacterSet="2"/>
|
|
||||||
<Tool
|
|
||||||
Name="DebugTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
Optimization="1000"
|
|
||||||
GlobalOptimizations="1"
|
|
||||||
InlineFunctionExpansion="2"
|
|
||||||
EnableIntrinsicFunctions="1"
|
|
||||||
FavorSizeOrSpeed="1"
|
|
||||||
OmitFramePointers="1"
|
|
||||||
OptimizeForProcessor="3"
|
|
||||||
OptimizeForWindowsApplication="1"
|
|
||||||
PreprocessorDefinitions="_M_IX86_FP=2;WIN32;_WINDOWS;NDEBUG;_USRDLL"
|
|
||||||
StringPooling="1"
|
|
||||||
RuntimeLibrary="0"
|
|
||||||
EnableEnhancedInstructionSet="2"
|
|
||||||
TreatWChar_tAsBuiltInType="0"
|
|
||||||
ForceConformanceInForLoopScope="1"
|
|
||||||
UsePrecompiledHeader="3"
|
|
||||||
WarningLevel="3"
|
|
||||||
Detect64BitPortabilityProblems="1"
|
|
||||||
DebugInformationFormat="3"
|
|
||||||
UseProcExt="2"
|
|
||||||
RecognizeRestrictKeyword="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="LinkerTool"
|
|
||||||
DelayImpLib="DelayImp.lib"
|
|
||||||
AdditionalDependencies="d3d9.lib d3dx9.lib ddraw.lib strmbaseR.lib"
|
|
||||||
OutputFile="$(OutDir)\GSdx9.dll"
|
|
||||||
LinkIncremental="1"
|
|
||||||
ModuleDefinitionFile=".\GSdx9.def"
|
|
||||||
GenerateDebugInformation="1"
|
|
||||||
SubSystem="2"
|
|
||||||
OptimizeReferences="2"
|
|
||||||
EnableCOMDATFolding="2"
|
|
||||||
ImportLibrary="$(OutDir)/GSdx9.lib"
|
|
||||||
TargetMachine="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="LibrarianTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="ResCmplrTool"
|
|
||||||
PreprocessorDefinitions="NDEBUG"
|
|
||||||
Culture="1033"
|
|
||||||
AdditionalIncludeDirectories="$(IntDir)"/>
|
|
||||||
<Tool
|
|
||||||
Name="MidlCmplrTool"
|
|
||||||
PreprocessorDefinitions="NDEBUG"
|
|
||||||
MkTypLibCompatible="0"/>
|
|
||||||
<Tool
|
|
||||||
Name="BscMakeTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="PreBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="PreLinkEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="PostBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="CustomTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="CustomNodeTool"/>
|
|
||||||
</Configuration>
|
|
||||||
</Configurations>
|
|
||||||
<Files>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GS.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSCapture.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSCaptureDlg.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSdx9.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSdx9.def"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSHash.cpp">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="ReleaseSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
AssemblerOutput="4"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSLocalMemory.cpp">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="ReleaseSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
AssemblerOutput="4"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSPerfMon.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSRegs.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSRenderer.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSRendererHW.cpp">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="ReleaseSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
GeneratePreprocessedFile="0"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSRendererNull.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSRendererSoft.cpp">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="ReleaseSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
AssemblerOutput="4"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\gssettingsdlg.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSSoftVertex.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSState.cpp">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="ReleaseSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
AssemblerOutput="4"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSTables.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSTextureCache.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSTransfer.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSUtil.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSVertexList.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSWnd.cpp"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\stdafx.cpp">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
UsePrecompiledHeader="1"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
UsePrecompiledHeader="1"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="DebugSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
UsePrecompiledHeader="1"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="ReleaseSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
UsePrecompiledHeader="1"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\x86-32.asm">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CustomTool"
|
|
||||||
CommandLine="ml /nologo /c /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
|
|
||||||
"
|
|
||||||
Outputs="$(IntDir)\$(InputName).obj"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CustomTool"
|
|
||||||
CommandLine="ml /nologo /c /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
|
|
||||||
"
|
|
||||||
Outputs="$(IntDir)\$(InputName).obj"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="DebugSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CustomTool"
|
|
||||||
CommandLine="ml /nologo /c /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
|
|
||||||
"
|
|
||||||
Outputs="$(IntDir)\$(InputName).obj"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="ReleaseSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CustomTool"
|
|
||||||
CommandLine="ml /nologo /c /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
|
|
||||||
"
|
|
||||||
Outputs="$(IntDir)\$(InputName).obj"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\x86-64.asm">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="GeneralTool"
|
|
||||||
ExcludedFromBuild="1"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="GeneralTool"
|
|
||||||
ExcludedFromBuild="1"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="DebugSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="GeneralTool"
|
|
||||||
ExcludedFromBuild="1"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="ReleaseSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="GeneralTool"
|
|
||||||
ExcludedFromBuild="1"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\x86.cpp">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="ReleaseSSE2|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="CppCmplrTool"
|
|
||||||
AssemblerOutput="4"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\gs.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSCapture.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSCaptureDlg.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSdx9.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSHash.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\gslocalmemory.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSPerfMon.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSRenderer.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSRendererHW.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSRendererNull.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSRendererSoft.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\gssettingsdlg.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSSoftVertex.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSSoftVertexFP.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSSoftVertexFX.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSState.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSTables.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSTextureCache.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSUtil.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSVertexList.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSWnd.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\resource.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\stdafx.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\x86.h"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\GSdx9.rc"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\GSdx9.rc2"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_en00.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_en01.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_en10.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_en11.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_tfx000.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_tfx010.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_tfx011.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_tfx1x0.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_tfx1x1.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_tfx200.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_tfx210.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_tfx211.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_tfx300.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_tfx310.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_tfx311.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps11_tfx4xx.psh"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps20_merge.fx"/>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res\ps20_tfx.fx"/>
|
|
||||||
</Files>
|
|
||||||
</VisualStudioProject>
|
|
||||||
|
|
|
@ -1,220 +0,0 @@
|
||||||
// Microsoft Visual C++ generated resource script.
|
|
||||||
//
|
|
||||||
#include "resource.h"
|
|
||||||
|
|
||||||
#define APSTUDIO_READONLY_SYMBOLS
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Generated from the TEXTINCLUDE 2 resource.
|
|
||||||
//
|
|
||||||
#include "afxres.h"
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
#undef APSTUDIO_READONLY_SYMBOLS
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Hungarian resources
|
|
||||||
|
|
||||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_HUN)
|
|
||||||
#ifdef _WIN32
|
|
||||||
LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT
|
|
||||||
#pragma code_page(1250)
|
|
||||||
#endif //_WIN32
|
|
||||||
|
|
||||||
#ifdef APSTUDIO_INVOKED
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// TEXTINCLUDE
|
|
||||||
//
|
|
||||||
|
|
||||||
1 TEXTINCLUDE
|
|
||||||
BEGIN
|
|
||||||
"resource.h\0"
|
|
||||||
END
|
|
||||||
|
|
||||||
2 TEXTINCLUDE
|
|
||||||
BEGIN
|
|
||||||
"#include ""afxres.h""\r\n"
|
|
||||||
"\0"
|
|
||||||
END
|
|
||||||
|
|
||||||
3 TEXTINCLUDE
|
|
||||||
BEGIN
|
|
||||||
"#define _AFX_NO_SPLITTER_RESOURCES\r\n"
|
|
||||||
"#define _AFX_NO_OLE_RESOURCES\r\n"
|
|
||||||
"#define _AFX_NO_TRACKER_RESOURCES\r\n"
|
|
||||||
"#define _AFX_NO_PROPERTY_RESOURCES\r\n"
|
|
||||||
"\r\n"
|
|
||||||
"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
|
|
||||||
"LANGUAGE 9, 1\r\n"
|
|
||||||
"#pragma code_page(1252)\r\n"
|
|
||||||
"#include ""res\\GSdx9.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
|
|
||||||
"#include ""afxres.rc"" // Standard components\r\n"
|
|
||||||
"#endif\r\n"
|
|
||||||
"\0"
|
|
||||||
END
|
|
||||||
|
|
||||||
#endif // APSTUDIO_INVOKED
|
|
||||||
|
|
||||||
#endif // Hungarian resources
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// English (U.S.) resources
|
|
||||||
|
|
||||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
|
||||||
#ifdef _WIN32
|
|
||||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|
||||||
#pragma code_page(1252)
|
|
||||||
#endif //_WIN32
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Bitmap
|
|
||||||
//
|
|
||||||
|
|
||||||
IDB_LOGO1 BITMAP "res\\logo1.bmp"
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Dialog
|
|
||||||
//
|
|
||||||
|
|
||||||
IDD_CONFIG DIALOGEX 0, 0, 189, 209
|
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
|
|
||||||
WS_SYSMENU
|
|
||||||
CAPTION "Settings..."
|
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
|
||||||
BEGIN
|
|
||||||
PUSHBUTTON "Cancel",IDCANCEL,43,188,50,14
|
|
||||||
DEFPUSHBUTTON "OK",IDOK,98,188,50,14
|
|
||||||
COMBOBOX IDC_COMBO1,64,72,118,69,CBS_DROPDOWNLIST | WS_VSCROLL |
|
|
||||||
WS_TABSTOP
|
|
||||||
LTEXT "Renderer:",IDC_STATIC,7,74,34,8
|
|
||||||
LTEXT "Resolution:",IDC_STATIC,7,59,37,8
|
|
||||||
COMBOBOX IDC_COMBO3,64,57,118,125,CBS_DROPDOWNLIST | WS_VSCROLL |
|
|
||||||
WS_TABSTOP
|
|
||||||
LTEXT "Shader:",IDC_STATIC,7,89,26,8
|
|
||||||
COMBOBOX IDC_COMBO4,64,87,118,98,CBS_DROPDOWNLIST | WS_VSCROLL |
|
|
||||||
WS_TABSTOP
|
|
||||||
EDITTEXT IDC_EDIT1,64,158,100,13,ES_AUTOHSCROLL | ES_READONLY
|
|
||||||
PUSHBUTTON "...",IDC_BUTTON1,165,158,17,14
|
|
||||||
CONTROL "Record state",IDC_CHECK2,"Button",BS_AUTOCHECKBOX |
|
|
||||||
WS_TABSTOP,7,158,53,10
|
|
||||||
CONTROL "Enable tv-out",IDC_CHECK3,"Button",BS_AUTOCHECKBOX |
|
|
||||||
WS_TABSTOP,7,132,57,10
|
|
||||||
CONTROL "Enable palettized textures (D3D PS v2.0+, slow)",
|
|
||||||
IDC_CHECK1,"Button",BS_AUTOCHECKBOX | BS_TOP |
|
|
||||||
WS_TABSTOP,7,105,175,10
|
|
||||||
LTEXT """rundll32 gsdx9.dll,GSReplay gsdx9_*.gs"" to replay",
|
|
||||||
IDC_STATIC,14,174,168,9
|
|
||||||
CONTROL "Linear texture filtering",IDC_CHECK4,"Button",
|
|
||||||
BS_AUTOCHECKBOX | WS_TABSTOP,7,118,87,10
|
|
||||||
CONTROL 2024,IDC_STATIC,"Static",SS_BITMAP,7,7,175,44
|
|
||||||
CONTROL "NLOOP 0 hack (fixes FFX)",IDC_CHECK5,"Button",
|
|
||||||
BS_AUTOCHECKBOX | WS_TABSTOP,7,145,98,10
|
|
||||||
END
|
|
||||||
|
|
||||||
IDD_CAPTURE DIALOGEX 0, 0, 279, 67
|
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
|
|
||||||
WS_SYSMENU
|
|
||||||
CAPTION "Capture settings"
|
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
|
||||||
BEGIN
|
|
||||||
DEFPUSHBUTTON "OK",IDOK,140,46,50,14
|
|
||||||
PUSHBUTTON "Cancel",IDCANCEL,88,46,50,14
|
|
||||||
COMBOBOX IDC_COMBO1,7,27,207,122,CBS_DROPDOWNLIST | WS_VSCROLL |
|
|
||||||
WS_TABSTOP
|
|
||||||
EDITTEXT IDC_EDIT1,7,7,207,14,ES_AUTOHSCROLL
|
|
||||||
PUSHBUTTON "Browse...",IDC_BUTTON1,222,7,50,14
|
|
||||||
PUSHBUTTON "Config...",IDC_BUTTON2,222,26,50,14
|
|
||||||
END
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// DESIGNINFO
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifdef APSTUDIO_INVOKED
|
|
||||||
GUIDELINES DESIGNINFO
|
|
||||||
BEGIN
|
|
||||||
IDD_CONFIG, DIALOG
|
|
||||||
BEGIN
|
|
||||||
LEFTMARGIN, 7
|
|
||||||
RIGHTMARGIN, 182
|
|
||||||
VERTGUIDE, 64
|
|
||||||
VERTGUIDE, 182
|
|
||||||
TOPMARGIN, 7
|
|
||||||
BOTTOMMARGIN, 202
|
|
||||||
HORZGUIDE, 150
|
|
||||||
END
|
|
||||||
END
|
|
||||||
#endif // APSTUDIO_INVOKED
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Version
|
|
||||||
//
|
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
|
||||||
FILEVERSION 1,0,0,9
|
|
||||||
PRODUCTVERSION 1,0,0,9
|
|
||||||
FILEFLAGSMASK 0x3fL
|
|
||||||
#ifdef _DEBUG
|
|
||||||
FILEFLAGS 0x1L
|
|
||||||
#else
|
|
||||||
FILEFLAGS 0x0L
|
|
||||||
#endif
|
|
||||||
FILEOS 0x4L
|
|
||||||
FILETYPE 0x2L
|
|
||||||
FILESUBTYPE 0x0L
|
|
||||||
BEGIN
|
|
||||||
BLOCK "StringFileInfo"
|
|
||||||
BEGIN
|
|
||||||
BLOCK "040904e4"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Comments", "http://gabest.org/"
|
|
||||||
VALUE "CompanyName", "Gabest"
|
|
||||||
VALUE "FileDescription", "GS plugin for ps2 emulators"
|
|
||||||
VALUE "FileVersion", "1, 0, 0, 9"
|
|
||||||
VALUE "InternalName", "GSdx9.dll"
|
|
||||||
VALUE "LegalCopyright", "Copyright (c) 2004-2005 Gabest. All rights reserved."
|
|
||||||
VALUE "OriginalFilename", "GSdx9.dll"
|
|
||||||
VALUE "ProductName", "GSdx9"
|
|
||||||
VALUE "ProductVersion", "1, 0, 0, 9"
|
|
||||||
END
|
|
||||||
END
|
|
||||||
BLOCK "VarFileInfo"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Translation", 0x409, 1252
|
|
||||||
END
|
|
||||||
END
|
|
||||||
|
|
||||||
#endif // English (U.S.) resources
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef APSTUDIO_INVOKED
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Generated from the TEXTINCLUDE 3 resource.
|
|
||||||
//
|
|
||||||
#define _AFX_NO_SPLITTER_RESOURCES
|
|
||||||
#define _AFX_NO_OLE_RESOURCES
|
|
||||||
#define _AFX_NO_TRACKER_RESOURCES
|
|
||||||
#define _AFX_NO_PROPERTY_RESOURCES
|
|
||||||
|
|
||||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
|
||||||
LANGUAGE 9, 1
|
|
||||||
#pragma code_page(1252)
|
|
||||||
#include "res\GSdx9.rc2" // non-Microsoft Visual C++ edited resources
|
|
||||||
#include "afxres.rc" // Standard components
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
#endif // not APSTUDIO_INVOKED
|
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
|
||||||
# Visual Studio 2005
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GSdx9", "GSdx9_vs2005.vcproj", "{345C9F24-0B9A-4289-B375-ADD3B63461B7}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
{7CDC5863-9F36-468D-A634-6D7799E0A15E} = {7CDC5863-9F36-468D-A634-6D7799E0A15E}
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BaseClasses", "baseclasses\baseclasses.vcproj", "{7CDC5863-9F36-468D-A634-6D7799E0A15E}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Win32 = Debug|Win32
|
|
||||||
Debug|x64 = Debug|x64
|
|
||||||
DebugSSE2|Win32 = DebugSSE2|Win32
|
|
||||||
DebugSSE2|x64 = DebugSSE2|x64
|
|
||||||
Release|Win32 = Release|Win32
|
|
||||||
Release|x64 = Release|x64
|
|
||||||
ReleaseSSE2|Win32 = ReleaseSSE2|Win32
|
|
||||||
ReleaseSSE2|x64 = ReleaseSSE2|x64
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.DebugSSE2|Win32.ActiveCfg = DebugSSE2|Win32
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.DebugSSE2|Win32.Build.0 = DebugSSE2|Win32
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.DebugSSE2|x64.ActiveCfg = DebugSSE2|x64
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.DebugSSE2|x64.Build.0 = DebugSSE2|x64
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.Release|x64.Build.0 = Release|x64
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.ReleaseSSE2|Win32.ActiveCfg = ReleaseSSE2|Win32
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.ReleaseSSE2|Win32.Build.0 = ReleaseSSE2|Win32
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.ReleaseSSE2|x64.ActiveCfg = ReleaseSSE2|x64
|
|
||||||
{345C9F24-0B9A-4289-B375-ADD3B63461B7}.ReleaseSSE2|x64.Build.0 = ReleaseSSE2|x64
|
|
||||||
{7CDC5863-9F36-468D-A634-6D7799E0A15E}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{7CDC5863-9F36-468D-A634-6D7799E0A15E}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{7CDC5863-9F36-468D-A634-6D7799E0A15E}.Debug|x64.ActiveCfg = Debug|Win32
|
|
||||||
{7CDC5863-9F36-468D-A634-6D7799E0A15E}.DebugSSE2|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{7CDC5863-9F36-468D-A634-6D7799E0A15E}.DebugSSE2|Win32.Build.0 = Debug|Win32
|
|
||||||
{7CDC5863-9F36-468D-A634-6D7799E0A15E}.DebugSSE2|x64.ActiveCfg = Debug|Win32
|
|
||||||
{7CDC5863-9F36-468D-A634-6D7799E0A15E}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{7CDC5863-9F36-468D-A634-6D7799E0A15E}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
{7CDC5863-9F36-468D-A634-6D7799E0A15E}.Release|x64.ActiveCfg = Release|Win32
|
|
||||||
{7CDC5863-9F36-468D-A634-6D7799E0A15E}.ReleaseSSE2|Win32.ActiveCfg = Release|Win32
|
|
||||||
{7CDC5863-9F36-468D-A634-6D7799E0A15E}.ReleaseSSE2|Win32.Build.0 = Release|Win32
|
|
||||||
{7CDC5863-9F36-468D-A634-6D7799E0A15E}.ReleaseSSE2|x64.ActiveCfg = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,433 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: AMVideo.h
|
|
||||||
//
|
|
||||||
// Desc: Video related definitions and interfaces for ActiveMovie.
|
|
||||||
//
|
|
||||||
// Copyright (c) 1992 - 2001, Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __AMVIDEO__
|
|
||||||
#define __AMVIDEO__
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
#include <ddraw.h>
|
|
||||||
|
|
||||||
|
|
||||||
// This is an interface on the video renderer that provides information about
|
|
||||||
// DirectDraw with respect to its use by the renderer. For example it allows
|
|
||||||
// an application to get details of the surface and any hardware capabilities
|
|
||||||
// that are available. It also allows someone to adjust the surfaces that the
|
|
||||||
// renderer should use and furthermore even set the DirectDraw instance. We
|
|
||||||
// allow someone to set the DirectDraw instance because DirectDraw can only
|
|
||||||
// be opened once per process so it helps resolve conflicts. There is some
|
|
||||||
// duplication in this interface as the hardware/emulated/FOURCCs available
|
|
||||||
// can all be found through the IDirectDraw interface, this interface allows
|
|
||||||
// simple access to that information without calling the DirectDraw provider
|
|
||||||
// itself. The AMDDS prefix is ActiveMovie DirectDraw Switches abbreviated.
|
|
||||||
|
|
||||||
#define AMDDS_NONE 0x00 // No use for DCI/DirectDraw
|
|
||||||
#define AMDDS_DCIPS 0x01 // Use DCI primary surface
|
|
||||||
#define AMDDS_PS 0x02 // Use DirectDraw primary
|
|
||||||
#define AMDDS_RGBOVR 0x04 // RGB overlay surfaces
|
|
||||||
#define AMDDS_YUVOVR 0x08 // YUV overlay surfaces
|
|
||||||
#define AMDDS_RGBOFF 0x10 // RGB offscreen surfaces
|
|
||||||
#define AMDDS_YUVOFF 0x20 // YUV offscreen surfaces
|
|
||||||
#define AMDDS_RGBFLP 0x40 // RGB flipping surfaces
|
|
||||||
#define AMDDS_YUVFLP 0x80 // YUV flipping surfaces
|
|
||||||
#define AMDDS_ALL 0xFF // ALL the previous flags
|
|
||||||
#define AMDDS_DEFAULT AMDDS_ALL // Use all available surfaces
|
|
||||||
|
|
||||||
#define AMDDS_YUV (AMDDS_YUVOFF | AMDDS_YUVOVR | AMDDS_YUVFLP)
|
|
||||||
#define AMDDS_RGB (AMDDS_RGBOFF | AMDDS_RGBOVR | AMDDS_RGBFLP)
|
|
||||||
#define AMDDS_PRIMARY (AMDDS_DCIPS | AMDDS_PS)
|
|
||||||
|
|
||||||
// be nice to our friends in C
|
|
||||||
#undef INTERFACE
|
|
||||||
#define INTERFACE IDirectDrawVideo
|
|
||||||
|
|
||||||
DECLARE_INTERFACE_(IDirectDrawVideo, IUnknown)
|
|
||||||
{
|
|
||||||
// IUnknown methods
|
|
||||||
|
|
||||||
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID *ppvObj) PURE;
|
|
||||||
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
|
|
||||||
STDMETHOD_(ULONG,Release)(THIS) PURE;
|
|
||||||
|
|
||||||
// IDirectDrawVideo methods
|
|
||||||
|
|
||||||
STDMETHOD(GetSwitches)(THIS_ DWORD *pSwitches) PURE;
|
|
||||||
STDMETHOD(SetSwitches)(THIS_ DWORD Switches) PURE;
|
|
||||||
STDMETHOD(GetCaps)(THIS_ DDCAPS *pCaps) PURE;
|
|
||||||
STDMETHOD(GetEmulatedCaps)(THIS_ DDCAPS *pCaps) PURE;
|
|
||||||
STDMETHOD(GetSurfaceDesc)(THIS_ DDSURFACEDESC *pSurfaceDesc) PURE;
|
|
||||||
STDMETHOD(GetFourCCCodes)(THIS_ DWORD *pCount,DWORD *pCodes) PURE;
|
|
||||||
STDMETHOD(SetDirectDraw)(THIS_ LPDIRECTDRAW pDirectDraw) PURE;
|
|
||||||
STDMETHOD(GetDirectDraw)(THIS_ LPDIRECTDRAW *ppDirectDraw) PURE;
|
|
||||||
STDMETHOD(GetSurfaceType)(THIS_ DWORD *pSurfaceType) PURE;
|
|
||||||
STDMETHOD(SetDefault)(THIS) PURE;
|
|
||||||
STDMETHOD(UseScanLine)(THIS_ long UseScanLine) PURE;
|
|
||||||
STDMETHOD(CanUseScanLine)(THIS_ long *UseScanLine) PURE;
|
|
||||||
STDMETHOD(UseOverlayStretch)(THIS_ long UseOverlayStretch) PURE;
|
|
||||||
STDMETHOD(CanUseOverlayStretch)(THIS_ long *UseOverlayStretch) PURE;
|
|
||||||
STDMETHOD(UseWhenFullScreen)(THIS_ long UseWhenFullScreen) PURE;
|
|
||||||
STDMETHOD(WillUseFullScreen)(THIS_ long *UseWhenFullScreen) PURE;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// be nice to our friends in C
|
|
||||||
#undef INTERFACE
|
|
||||||
#define INTERFACE IQualProp
|
|
||||||
|
|
||||||
DECLARE_INTERFACE_(IQualProp, IUnknown)
|
|
||||||
{
|
|
||||||
// IUnknown methods
|
|
||||||
|
|
||||||
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID *ppvObj) PURE;
|
|
||||||
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
|
|
||||||
STDMETHOD_(ULONG,Release)(THIS) PURE;
|
|
||||||
|
|
||||||
// Compare these with the functions in class CGargle in gargle.h
|
|
||||||
|
|
||||||
STDMETHOD(get_FramesDroppedInRenderer)(THIS_ int *pcFrames) PURE; // Out
|
|
||||||
STDMETHOD(get_FramesDrawn)(THIS_ int *pcFramesDrawn) PURE; // Out
|
|
||||||
STDMETHOD(get_AvgFrameRate)(THIS_ int *piAvgFrameRate) PURE; // Out
|
|
||||||
STDMETHOD(get_Jitter)(THIS_ int *iJitter) PURE; // Out
|
|
||||||
STDMETHOD(get_AvgSyncOffset)(THIS_ int *piAvg) PURE; // Out
|
|
||||||
STDMETHOD(get_DevSyncOffset)(THIS_ int *piDev) PURE; // Out
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// This interface allows an application or plug in distributor to control a
|
|
||||||
// full screen renderer. The Modex renderer supports this interface. When
|
|
||||||
// connected a renderer should load the display modes it has available
|
|
||||||
// The number of modes available can be obtained through CountModes. Then
|
|
||||||
// information on each individual mode is available by calling GetModeInfo
|
|
||||||
// and IsModeAvailable. An application may enable and disable any modes
|
|
||||||
// by calling the SetEnabled flag with OATRUE or OAFALSE (not C/C++ TRUE
|
|
||||||
// and FALSE values) - the current value may be queried by IsModeEnabled
|
|
||||||
|
|
||||||
// A more generic way of setting the modes enabled that is easier to use
|
|
||||||
// when writing applications is the clip loss factor. This defines the
|
|
||||||
// amount of video that can be lost when deciding which display mode to
|
|
||||||
// use. Assuming the decoder cannot compress the video then playing an
|
|
||||||
// MPEG file (say 352x288) into a 320x200 display will lose about 25% of
|
|
||||||
// the image. The clip loss factor specifies the upper range permissible.
|
|
||||||
// To allow typical MPEG video to be played in 320x200 it defaults to 25%
|
|
||||||
|
|
||||||
// be nice to our friends in C
|
|
||||||
#undef INTERFACE
|
|
||||||
#define INTERFACE IFullScreenVideo
|
|
||||||
|
|
||||||
DECLARE_INTERFACE_(IFullScreenVideo, IUnknown)
|
|
||||||
{
|
|
||||||
// IUnknown methods
|
|
||||||
|
|
||||||
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID *ppvObj) PURE;
|
|
||||||
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
|
|
||||||
STDMETHOD_(ULONG,Release)(THIS) PURE;
|
|
||||||
|
|
||||||
// IFullScreenVideo methods
|
|
||||||
|
|
||||||
STDMETHOD(CountModes)(THIS_ long *pModes) PURE;
|
|
||||||
STDMETHOD(GetModeInfo)(THIS_ long Mode,long *pWidth,long *pHeight,long *pDepth) PURE;
|
|
||||||
STDMETHOD(GetCurrentMode)(THIS_ long *pMode) PURE;
|
|
||||||
STDMETHOD(IsModeAvailable)(THIS_ long Mode) PURE;
|
|
||||||
STDMETHOD(IsModeEnabled)(THIS_ long Mode) PURE;
|
|
||||||
STDMETHOD(SetEnabled)(THIS_ long Mode,long bEnabled) PURE;
|
|
||||||
STDMETHOD(GetClipFactor)(THIS_ long *pClipFactor) PURE;
|
|
||||||
STDMETHOD(SetClipFactor)(THIS_ long ClipFactor) PURE;
|
|
||||||
STDMETHOD(SetMessageDrain)(THIS_ HWND hwnd) PURE;
|
|
||||||
STDMETHOD(GetMessageDrain)(THIS_ HWND *hwnd) PURE;
|
|
||||||
STDMETHOD(SetMonitor)(THIS_ long Monitor) PURE;
|
|
||||||
STDMETHOD(GetMonitor)(THIS_ long *Monitor) PURE;
|
|
||||||
STDMETHOD(HideOnDeactivate)(THIS_ long Hide) PURE;
|
|
||||||
STDMETHOD(IsHideOnDeactivate)(THIS) PURE;
|
|
||||||
STDMETHOD(SetCaption)(THIS_ BSTR strCaption) PURE;
|
|
||||||
STDMETHOD(GetCaption)(THIS_ BSTR *pstrCaption) PURE;
|
|
||||||
STDMETHOD(SetDefault)(THIS) PURE;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// This adds the accelerator table capabilities in fullscreen. This is being
|
|
||||||
// added between the original runtime release and the full SDK release. We
|
|
||||||
// cannot just add the method to IFullScreenVideo as we don't want to force
|
|
||||||
// applications to have to ship the ActiveMovie support DLLs - this is very
|
|
||||||
// important to applications that plan on being downloaded over the Internet
|
|
||||||
|
|
||||||
// be nice to our friends in C
|
|
||||||
#undef INTERFACE
|
|
||||||
#define INTERFACE IFullScreenVideoEx
|
|
||||||
|
|
||||||
DECLARE_INTERFACE_(IFullScreenVideoEx, IFullScreenVideo)
|
|
||||||
{
|
|
||||||
// IUnknown methods
|
|
||||||
|
|
||||||
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID *ppvObj) PURE;
|
|
||||||
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
|
|
||||||
STDMETHOD_(ULONG,Release)(THIS) PURE;
|
|
||||||
|
|
||||||
// IFullScreenVideo methods
|
|
||||||
|
|
||||||
STDMETHOD(CountModes)(THIS_ long *pModes) PURE;
|
|
||||||
STDMETHOD(GetModeInfo)(THIS_ long Mode,long *pWidth,long *pHeight,long *pDepth) PURE;
|
|
||||||
STDMETHOD(GetCurrentMode)(THIS_ long *pMode) PURE;
|
|
||||||
STDMETHOD(IsModeAvailable)(THIS_ long Mode) PURE;
|
|
||||||
STDMETHOD(IsModeEnabled)(THIS_ long Mode) PURE;
|
|
||||||
STDMETHOD(SetEnabled)(THIS_ long Mode,long bEnabled) PURE;
|
|
||||||
STDMETHOD(GetClipFactor)(THIS_ long *pClipFactor) PURE;
|
|
||||||
STDMETHOD(SetClipFactor)(THIS_ long ClipFactor) PURE;
|
|
||||||
STDMETHOD(SetMessageDrain)(THIS_ HWND hwnd) PURE;
|
|
||||||
STDMETHOD(GetMessageDrain)(THIS_ HWND *hwnd) PURE;
|
|
||||||
STDMETHOD(SetMonitor)(THIS_ long Monitor) PURE;
|
|
||||||
STDMETHOD(GetMonitor)(THIS_ long *Monitor) PURE;
|
|
||||||
STDMETHOD(HideOnDeactivate)(THIS_ long Hide) PURE;
|
|
||||||
STDMETHOD(IsHideOnDeactivate)(THIS) PURE;
|
|
||||||
STDMETHOD(SetCaption)(THIS_ BSTR strCaption) PURE;
|
|
||||||
STDMETHOD(GetCaption)(THIS_ BSTR *pstrCaption) PURE;
|
|
||||||
STDMETHOD(SetDefault)(THIS) PURE;
|
|
||||||
|
|
||||||
// IFullScreenVideoEx
|
|
||||||
|
|
||||||
STDMETHOD(SetAcceleratorTable)(THIS_ HWND hwnd,HACCEL hAccel) PURE;
|
|
||||||
STDMETHOD(GetAcceleratorTable)(THIS_ HWND *phwnd,HACCEL *phAccel) PURE;
|
|
||||||
STDMETHOD(KeepPixelAspectRatio)(THIS_ long KeepAspect) PURE;
|
|
||||||
STDMETHOD(IsKeepPixelAspectRatio)(THIS_ long *pKeepAspect) PURE;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// The SDK base classes contain a base video mixer class. Video mixing in a
|
|
||||||
// software environment is tricky because we typically have multiple streams
|
|
||||||
// each sending data at unpredictable times. To work with this we defined a
|
|
||||||
// pin that is the lead pin, when data arrives on this pin we do a mix. As
|
|
||||||
// an alternative we may not want to have a lead pin but output samples at
|
|
||||||
// predefined spaces, like one every 1/15 of a second, this interfaces also
|
|
||||||
// supports that mode of operations (there is a working video mixer sample)
|
|
||||||
|
|
||||||
// be nice to our friends in C
|
|
||||||
#undef INTERFACE
|
|
||||||
#define INTERFACE IBaseVideoMixer
|
|
||||||
|
|
||||||
DECLARE_INTERFACE_(IBaseVideoMixer, IUnknown)
|
|
||||||
{
|
|
||||||
STDMETHOD(SetLeadPin)(THIS_ int iPin) PURE;
|
|
||||||
STDMETHOD(GetLeadPin)(THIS_ int *piPin) PURE;
|
|
||||||
STDMETHOD(GetInputPinCount)(THIS_ int *piPinCount) PURE;
|
|
||||||
STDMETHOD(IsUsingClock)(THIS_ int *pbValue) PURE;
|
|
||||||
STDMETHOD(SetUsingClock)(THIS_ int bValue) PURE;
|
|
||||||
STDMETHOD(GetClockPeriod)(THIS_ int *pbValue) PURE;
|
|
||||||
STDMETHOD(SetClockPeriod)(THIS_ int bValue) PURE;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define iPALETTE_COLORS 256 // Maximum colours in palette
|
|
||||||
#define iEGA_COLORS 16 // Number colours in EGA palette
|
|
||||||
#define iMASK_COLORS 3 // Maximum three components
|
|
||||||
#define iTRUECOLOR 16 // Minimum true colour device
|
|
||||||
#define iRED 0 // Index position for RED mask
|
|
||||||
#define iGREEN 1 // Index position for GREEN mask
|
|
||||||
#define iBLUE 2 // Index position for BLUE mask
|
|
||||||
#define iPALETTE 8 // Maximum colour depth using a palette
|
|
||||||
#define iMAXBITS 8 // Maximum bits per colour component
|
|
||||||
|
|
||||||
|
|
||||||
// Used for true colour images that also have a palette
|
|
||||||
|
|
||||||
typedef struct tag_TRUECOLORINFO {
|
|
||||||
DWORD dwBitMasks[iMASK_COLORS];
|
|
||||||
RGBQUAD bmiColors[iPALETTE_COLORS];
|
|
||||||
} TRUECOLORINFO;
|
|
||||||
|
|
||||||
|
|
||||||
// The BITMAPINFOHEADER contains all the details about the video stream such
|
|
||||||
// as the actual image dimensions and their pixel depth. A source filter may
|
|
||||||
// also request that the sink take only a section of the video by providing a
|
|
||||||
// clipping rectangle in rcSource. In the worst case where the sink filter
|
|
||||||
// forgets to check this on connection it will simply render the whole thing
|
|
||||||
// which isn't a disaster. Ideally a sink filter will check the rcSource and
|
|
||||||
// if it doesn't support image extraction and the rectangle is not empty then
|
|
||||||
// it will reject the connection. A filter should use SetRectEmpty to reset a
|
|
||||||
// rectangle to all zeroes (and IsRectEmpty to later check the rectangle).
|
|
||||||
// The rcTarget specifies the destination rectangle for the video, for most
|
|
||||||
// source filters they will set this to all zeroes, a downstream filter may
|
|
||||||
// request that the video be placed in a particular area of the buffers it
|
|
||||||
// supplies in which case it will call QueryAccept with a non empty target
|
|
||||||
|
|
||||||
typedef struct tagVIDEOINFOHEADER {
|
|
||||||
|
|
||||||
RECT rcSource; // The bit we really want to use
|
|
||||||
RECT rcTarget; // Where the video should go
|
|
||||||
DWORD dwBitRate; // Approximate bit data rate
|
|
||||||
DWORD dwBitErrorRate; // Bit error rate for this stream
|
|
||||||
REFERENCE_TIME AvgTimePerFrame; // Average time per frame (100ns units)
|
|
||||||
|
|
||||||
BITMAPINFOHEADER bmiHeader;
|
|
||||||
|
|
||||||
} VIDEOINFOHEADER;
|
|
||||||
|
|
||||||
// make sure the pbmi is initialized before using these macros
|
|
||||||
#define TRUECOLOR(pbmi) ((TRUECOLORINFO *)(((LPBYTE)&((pbmi)->bmiHeader)) \
|
|
||||||
+ (pbmi)->bmiHeader.biSize))
|
|
||||||
#define COLORS(pbmi) ((RGBQUAD *)(((LPBYTE)&((pbmi)->bmiHeader)) \
|
|
||||||
+ (pbmi)->bmiHeader.biSize))
|
|
||||||
#define BITMASKS(pbmi) ((DWORD *)(((LPBYTE)&((pbmi)->bmiHeader)) \
|
|
||||||
+ (pbmi)->bmiHeader.biSize))
|
|
||||||
|
|
||||||
// All the image based filters use this to communicate their media types. It's
|
|
||||||
// centred principally around the BITMAPINFO. This structure always contains a
|
|
||||||
// BITMAPINFOHEADER followed by a number of other fields depending on what the
|
|
||||||
// BITMAPINFOHEADER contains. If it contains details of a palettised format it
|
|
||||||
// will be followed by one or more RGBQUADs defining the palette. If it holds
|
|
||||||
// details of a true colour format then it may be followed by a set of three
|
|
||||||
// DWORD bit masks that specify where the RGB data can be found in the image
|
|
||||||
// (For more information regarding BITMAPINFOs see the Win32 documentation)
|
|
||||||
|
|
||||||
// The rcSource and rcTarget fields are not for use by filters supplying the
|
|
||||||
// data. The destination (target) rectangle should be set to all zeroes. The
|
|
||||||
// source may also be zero filled or set with the dimensions of the video. So
|
|
||||||
// if the video is 352x288 pixels then set it to (0,0,352,288). These fields
|
|
||||||
// are mainly used by downstream filters that want to ask the source filter
|
|
||||||
// to place the image in a different position in an output buffer. So when
|
|
||||||
// using for example the primary surface the video renderer may ask a filter
|
|
||||||
// to place the video images in a destination position of (100,100,452,388)
|
|
||||||
// on the display since that's where the window is positioned on the display
|
|
||||||
|
|
||||||
// !!! WARNING !!!
|
|
||||||
// DO NOT use this structure unless you are sure that the BITMAPINFOHEADER
|
|
||||||
// has a normal biSize == sizeof(BITMAPINFOHEADER) !
|
|
||||||
// !!! WARNING !!!
|
|
||||||
|
|
||||||
typedef struct tagVIDEOINFO {
|
|
||||||
|
|
||||||
RECT rcSource; // The bit we really want to use
|
|
||||||
RECT rcTarget; // Where the video should go
|
|
||||||
DWORD dwBitRate; // Approximate bit data rate
|
|
||||||
DWORD dwBitErrorRate; // Bit error rate for this stream
|
|
||||||
REFERENCE_TIME AvgTimePerFrame; // Average time per frame (100ns units)
|
|
||||||
|
|
||||||
BITMAPINFOHEADER bmiHeader;
|
|
||||||
|
|
||||||
union {
|
|
||||||
RGBQUAD bmiColors[iPALETTE_COLORS]; // Colour palette
|
|
||||||
DWORD dwBitMasks[iMASK_COLORS]; // True colour masks
|
|
||||||
TRUECOLORINFO TrueColorInfo; // Both of the above
|
|
||||||
};
|
|
||||||
|
|
||||||
} VIDEOINFO;
|
|
||||||
|
|
||||||
// These macros define some standard bitmap format sizes
|
|
||||||
|
|
||||||
#define SIZE_EGA_PALETTE (iEGA_COLORS * sizeof(RGBQUAD))
|
|
||||||
#define SIZE_PALETTE (iPALETTE_COLORS * sizeof(RGBQUAD))
|
|
||||||
#define SIZE_MASKS (iMASK_COLORS * sizeof(DWORD))
|
|
||||||
#define SIZE_PREHEADER (FIELD_OFFSET(VIDEOINFOHEADER,bmiHeader))
|
|
||||||
#define SIZE_VIDEOHEADER (sizeof(BITMAPINFOHEADER) + SIZE_PREHEADER)
|
|
||||||
// !!! for abnormal biSizes
|
|
||||||
// #define SIZE_VIDEOHEADER(pbmi) ((pbmi)->bmiHeader.biSize + SIZE_PREHEADER)
|
|
||||||
|
|
||||||
// DIBSIZE calculates the number of bytes required by an image
|
|
||||||
|
|
||||||
#define WIDTHBYTES(bits) ((DWORD)(((bits)+31) & (~31)) / 8)
|
|
||||||
#define DIBWIDTHBYTES(bi) (DWORD)WIDTHBYTES((DWORD)(bi).biWidth * (DWORD)(bi).biBitCount)
|
|
||||||
#define _DIBSIZE(bi) (DIBWIDTHBYTES(bi) * (DWORD)(bi).biHeight)
|
|
||||||
#define DIBSIZE(bi) ((bi).biHeight < 0 ? (-1)*(_DIBSIZE(bi)) : _DIBSIZE(bi))
|
|
||||||
|
|
||||||
// This compares the bit masks between two VIDEOINFOHEADERs
|
|
||||||
|
|
||||||
#define BIT_MASKS_MATCH(pbmi1,pbmi2) \
|
|
||||||
(((pbmi1)->dwBitMasks[iRED] == (pbmi2)->dwBitMasks[iRED]) && \
|
|
||||||
((pbmi1)->dwBitMasks[iGREEN] == (pbmi2)->dwBitMasks[iGREEN]) && \
|
|
||||||
((pbmi1)->dwBitMasks[iBLUE] == (pbmi2)->dwBitMasks[iBLUE]))
|
|
||||||
|
|
||||||
// These zero fill different parts of the VIDEOINFOHEADER structure
|
|
||||||
|
|
||||||
// Only use these macros for pbmi's with a normal BITMAPINFOHEADER biSize
|
|
||||||
#define RESET_MASKS(pbmi) (ZeroMemory((PVOID)(pbmi)->dwBitFields,SIZE_MASKS))
|
|
||||||
#define RESET_HEADER(pbmi) (ZeroMemory((PVOID)(pbmi),SIZE_VIDEOHEADER))
|
|
||||||
#define RESET_PALETTE(pbmi) (ZeroMemory((PVOID)(pbmi)->bmiColors,SIZE_PALETTE));
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// !!! This is the right way to do it, but may break existing code
|
|
||||||
#define RESET_MASKS(pbmi) (ZeroMemory((PVOID)(((LPBYTE)(pbmi)->bmiHeader) + \
|
|
||||||
(pbmi)->bmiHeader.biSize,SIZE_MASKS)))
|
|
||||||
#define RESET_HEADER(pbmi) (ZeroMemory((PVOID)(pbmi), SIZE_PREHEADER + \
|
|
||||||
sizeof(BITMAPINFOHEADER)))
|
|
||||||
#define RESET_PALETTE(pbmi) (ZeroMemory((PVOID)(((LPBYTE)(pbmi)->bmiHeader) + \
|
|
||||||
(pbmi)->bmiHeader.biSize,SIZE_PALETTE))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Other (hopefully) useful bits and bobs
|
|
||||||
|
|
||||||
#define PALETTISED(pbmi) ((pbmi)->bmiHeader.biBitCount <= iPALETTE)
|
|
||||||
#define PALETTE_ENTRIES(pbmi) ((DWORD) 1 << (pbmi)->bmiHeader.biBitCount)
|
|
||||||
|
|
||||||
// Returns the address of the BITMAPINFOHEADER from the VIDEOINFOHEADER
|
|
||||||
#define HEADER(pVideoInfo) (&(((VIDEOINFOHEADER *) (pVideoInfo))->bmiHeader))
|
|
||||||
|
|
||||||
|
|
||||||
// MPEG variant - includes a DWORD length followed by the
|
|
||||||
// video sequence header after the video header.
|
|
||||||
//
|
|
||||||
// The sequence header includes the sequence header start code and the
|
|
||||||
// quantization matrices associated with the first sequence header in the
|
|
||||||
// stream so is a maximum of 140 bytes long.
|
|
||||||
|
|
||||||
typedef struct tagMPEG1VIDEOINFO {
|
|
||||||
|
|
||||||
VIDEOINFOHEADER hdr; // Compatible with VIDEOINFO
|
|
||||||
DWORD dwStartTimeCode; // 25-bit Group of pictures time code
|
|
||||||
// at start of data
|
|
||||||
DWORD cbSequenceHeader; // Length in bytes of bSequenceHeader
|
|
||||||
BYTE bSequenceHeader[1]; // Sequence header including
|
|
||||||
// quantization matrices if any
|
|
||||||
} MPEG1VIDEOINFO;
|
|
||||||
|
|
||||||
#define MAX_SIZE_MPEG1_SEQUENCE_INFO 140
|
|
||||||
#define SIZE_MPEG1VIDEOINFO(pv) (FIELD_OFFSET(MPEG1VIDEOINFO, bSequenceHeader[0]) + (pv)->cbSequenceHeader)
|
|
||||||
#define MPEG1_SEQUENCE_INFO(pv) ((const BYTE *)(pv)->bSequenceHeader)
|
|
||||||
|
|
||||||
|
|
||||||
// Analog video variant - Use this when the format is FORMAT_AnalogVideo
|
|
||||||
//
|
|
||||||
// rcSource defines the portion of the active video signal to use
|
|
||||||
// rcTarget defines the destination rectangle
|
|
||||||
// both of the above are relative to the dwActiveWidth and dwActiveHeight fields
|
|
||||||
// dwActiveWidth is currently set to 720 for all formats (but could change for HDTV)
|
|
||||||
// dwActiveHeight is 483 for NTSC and 575 for PAL/SECAM (but could change for HDTV)
|
|
||||||
|
|
||||||
typedef struct tagAnalogVideoInfo {
|
|
||||||
RECT rcSource; // Width max is 720, height varies w/ TransmissionStd
|
|
||||||
RECT rcTarget; // Where the video should go
|
|
||||||
DWORD dwActiveWidth; // Always 720 (CCIR-601 active samples per line)
|
|
||||||
DWORD dwActiveHeight; // 483 for NTSC, 575 for PAL/SECAM
|
|
||||||
REFERENCE_TIME AvgTimePerFrame; // Normal ActiveMovie units (100 nS)
|
|
||||||
} ANALOGVIDEOINFO;
|
|
||||||
|
|
||||||
//
|
|
||||||
// AM_KSPROPSETID_FrameStep property set definitions
|
|
||||||
//
|
|
||||||
typedef enum {
|
|
||||||
// Step
|
|
||||||
AM_PROPERTY_FRAMESTEP_STEP = 0x01,
|
|
||||||
AM_PROPERTY_FRAMESTEP_CANCEL = 0x02,
|
|
||||||
|
|
||||||
// S_OK for these 2 means we can - S_FALSE if we can't
|
|
||||||
AM_PROPERTY_FRAMESTEP_CANSTEP = 0x03,
|
|
||||||
AM_PROPERTY_FRAMESTEP_CANSTEPMULTIPLE = 0x04
|
|
||||||
} AM_PROPERTY_FRAMESTEP;
|
|
||||||
|
|
||||||
typedef struct _AM_FRAMESTEP_STEP
|
|
||||||
{
|
|
||||||
// 1 means step 1 frame forward
|
|
||||||
// 0 is invalid
|
|
||||||
// n (n > 1) means skip n - 1 frames and show the nth
|
|
||||||
DWORD dwFramesToStep;
|
|
||||||
} AM_FRAMESTEP_STEP;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif // __cplusplus
|
|
||||||
#endif // __AMVIDEO__
|
|
||||||
|
|
|
@ -1,142 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: Activex.rcv
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - this file defines the version resource
|
|
||||||
// used for the application.
|
|
||||||
//
|
|
||||||
// NOTE: All strings MUST have an explicit \0 for termination!
|
|
||||||
//
|
|
||||||
// For a complete description of the Version Resource, search the
|
|
||||||
// Microsoft Developer's Network (MSDN) CD-ROM for 'version resource'..
|
|
||||||
//
|
|
||||||
// Copyright (c) 1992 - 2002, Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _ACTIVEX_RCV_
|
|
||||||
#define _ACTIVEX_RCV_
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#define WIN32
|
|
||||||
#endif
|
|
||||||
#include <winver.h>
|
|
||||||
|
|
||||||
#ifndef _ACTIVEX_VER_
|
|
||||||
#include <activex.ver>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// Version flags.
|
|
||||||
//
|
|
||||||
// OFFICIAL and FINAL should be defined when appropriate.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef OFFICIAL
|
|
||||||
#define VER_PRIVATEBUILD VS_FF_PRIVATEBUILD
|
|
||||||
#else
|
|
||||||
#define VER_PRIVATEBUILD 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FINAL
|
|
||||||
#define VER_PRERELEASE VS_FF_PRERELEASE
|
|
||||||
#else
|
|
||||||
#define VER_PRERELEASE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#define VER_DEBUG VS_FF_DEBUG
|
|
||||||
#else
|
|
||||||
#define VER_DEBUG 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// Version definitions
|
|
||||||
//
|
|
||||||
|
|
||||||
#define VERSION_RES_FLAGSMASK 0x0030003FL
|
|
||||||
#define VERSION_RES_FLAGS (VER_PRIVATEBUILD|VER_PRERELEASE|VER_DEBUG)
|
|
||||||
|
|
||||||
#ifndef VERSION_RES_OS
|
|
||||||
#define VERSION_RES_OS VOS__WINDOWS32
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef VERSION_RES_TYPE
|
|
||||||
#define VERSION_RES_TYPE VFT_DLL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef VERSION_RES_SUBTYPE
|
|
||||||
#define VERSION_RES_SUBTYPE VFT2_UNKNOWN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define VERSION_RES_LANGUAGE 0x409
|
|
||||||
|
|
||||||
#ifndef VERSION_RES_CHARSET
|
|
||||||
#ifdef UNICODE
|
|
||||||
#define VERSION_RES_CHARSET 1200
|
|
||||||
#else
|
|
||||||
#define VERSION_RES_CHARSET 1252
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef VERSION_RES_ACTIVEX
|
|
||||||
#define VERSION_RES_ACTIVEX "Filter dll\0"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef AMOVIE_SELF_REGISTER
|
|
||||||
#ifndef OLE_SELF_REGISTER
|
|
||||||
#define OLE_SELF_REGISTER
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef OLE_SELF_REGISTER
|
|
||||||
#ifdef AMOVIE_SELF_REGISTER
|
|
||||||
#define VERSION_RES_SELFREGISTER "AM20\0"
|
|
||||||
#else
|
|
||||||
#define VERSION_RES_SELFREGISTER "\0"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// Version resource
|
|
||||||
//
|
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
|
||||||
FILEVERSION VERSION_RES_MAJOR_VER, VERSION_RES_MINOR_VER, 0, VERSION_RES_BUILD
|
|
||||||
PRODUCTVERSION VERSION_RES_MAJOR_VER, VERSION_RES_MINOR_VER, 0, VERSION_RES_BUILD
|
|
||||||
FILEFLAGSMASK VERSION_RES_FLAGSMASK
|
|
||||||
FILEFLAGS VERSION_RES_FLAGS
|
|
||||||
FILEOS VERSION_RES_OS
|
|
||||||
FILETYPE VERSION_RES_TYPE
|
|
||||||
FILESUBTYPE VERSION_RES_SUBTYPE
|
|
||||||
BEGIN
|
|
||||||
BLOCK "StringFileInfo"
|
|
||||||
BEGIN
|
|
||||||
BLOCK "040904E4"
|
|
||||||
BEGIN
|
|
||||||
VALUE "CompanyName", VERSION_RES_COMPANY_NAME
|
|
||||||
VALUE "Comment", VERSION_RES_COMMENT
|
|
||||||
VALUE "FileDescription", VERSION_RES_BIN_DESCRIPTION
|
|
||||||
VALUE "FileVersion", VERSION_RES_STRING
|
|
||||||
VALUE "InternalName", VERSION_RES_BIN_NAME
|
|
||||||
VALUE "LegalCopyright", VERSION_RES_COPYRIGHT
|
|
||||||
VALUE "OriginalFilename", VERSION_RES_BIN_NAME
|
|
||||||
VALUE "ProductName", VERSION_RES_PRODUCT_NAME
|
|
||||||
#ifdef DEBUG
|
|
||||||
VALUE "ProductVersion", VERSION_RES_STRING_D
|
|
||||||
#else
|
|
||||||
VALUE "ProductVersion", VERSION_RES_STRING
|
|
||||||
#endif
|
|
||||||
VALUE "ActiveMovie", VERSION_RES_ACTIVEX
|
|
||||||
#ifdef OLE_SELF_REGISTER
|
|
||||||
VALUE "OLESelfRegister", VERSION_RES_SELFREGISTER
|
|
||||||
#endif
|
|
||||||
END
|
|
||||||
END
|
|
||||||
BLOCK "VarFileInfo"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Translation", VERSION_RES_LANGUAGE, VERSION_RES_CHARSET
|
|
||||||
END
|
|
||||||
END
|
|
||||||
|
|
||||||
#endif
|
|
||||||
// _ACTIVEX_RCV_
|
|
|
@ -1,56 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: Activex.ver
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - common versioning information for
|
|
||||||
// ACTIVEX binaries.
|
|
||||||
//
|
|
||||||
// Copyright (c) 1996-2002, Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _ACTIVEX_VER_
|
|
||||||
#define _ACTIVEX_VER_
|
|
||||||
|
|
||||||
// NOTE: all string resources that will be used in ACTIVEX.RCV for the
|
|
||||||
// version resource information *MUST* have an explicit \0 terminator!
|
|
||||||
|
|
||||||
#define VERSION_RES_MAJOR_VER 9
|
|
||||||
#define VERSION_RES_MINOR_VER 0
|
|
||||||
#define VERSION_RES_BUILD 0
|
|
||||||
|
|
||||||
#define VERSION_RES_STRING_D "9.00 (Debug)\0"
|
|
||||||
#define VERSION_RES_STRING "9.00\0"
|
|
||||||
|
|
||||||
#define VERSION_RES_PRODUCT_NAME "DirectX 9.0 Sample\0"
|
|
||||||
#define VERSION_RES_COMMENT "DirectShow Sample\0"
|
|
||||||
#define VERSION_RES_COMPANY_NAME "Microsoft Corporation\0"
|
|
||||||
#define VERSION_RES_COPYRIGHT "Copyright (C) 1992-2002 Microsoft Corporation\0"
|
|
||||||
|
|
||||||
// The following defines are required on a file-by-file basis
|
|
||||||
//
|
|
||||||
// #define VERSION_RES_BIN_NAME "sample.ax\0"
|
|
||||||
// #define VERSION_RES_BIN_DESCRIPTION "Sample Filter\0"
|
|
||||||
//
|
|
||||||
// Also required, if you don't want the defaults, are
|
|
||||||
//
|
|
||||||
// #define VERSION_RES_ACTIVEX "Filter dll\0" (the default value)
|
|
||||||
//
|
|
||||||
// A string defining the type of component.
|
|
||||||
//
|
|
||||||
// #define VERSION_RES_TYPE VFT_DLL (default)
|
|
||||||
// VFT_APP
|
|
||||||
// VFT_VXD
|
|
||||||
// VFT_DRV
|
|
||||||
// VFT_FONT
|
|
||||||
// VFT_STATIC_LIB
|
|
||||||
// VFT_UNKNOWN
|
|
||||||
//
|
|
||||||
// #define VERSION_RES_SUBTYPE VFT2_UNKNOWN (default)
|
|
||||||
// VFT2_DRV_INSTALLABLE
|
|
||||||
// VFT2_DRV_SOUND
|
|
||||||
// <several other options>
|
|
||||||
//
|
|
||||||
// See winver.h for further details
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: AMAudio.h
|
|
||||||
//
|
|
||||||
// Desc: Audio related definitions and interfaces for ActiveMovie.
|
|
||||||
//
|
|
||||||
// Copyright (c) 1992-2001, Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __AMAUDIO__
|
|
||||||
#define __AMAUDIO__
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
#include <mmsystem.h>
|
|
||||||
#include <dsound.h>
|
|
||||||
|
|
||||||
// This is the interface the audio renderer supports to give the application
|
|
||||||
// access to the direct sound object and the buffers it is using, to allow the
|
|
||||||
// application to use things like the 3D features of Direct Sound for the
|
|
||||||
// soundtrack of a movie being played with Active Movie.
|
|
||||||
|
|
||||||
// be nice to our friends in C
|
|
||||||
#undef INTERFACE
|
|
||||||
#define INTERFACE IAMDirectSound
|
|
||||||
|
|
||||||
DECLARE_INTERFACE_(IAMDirectSound,IUnknown)
|
|
||||||
{
|
|
||||||
/* IUnknown methods */
|
|
||||||
|
|
||||||
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID *ppvObj) PURE;
|
|
||||||
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
|
|
||||||
STDMETHOD_(ULONG,Release)(THIS) PURE;
|
|
||||||
|
|
||||||
/* IAMDirectSound methods */
|
|
||||||
|
|
||||||
STDMETHOD(GetDirectSoundInterface)(THIS_ LPDIRECTSOUND *lplpds) PURE;
|
|
||||||
STDMETHOD(GetPrimaryBufferInterface)(THIS_ LPDIRECTSOUNDBUFFER *lplpdsb) PURE;
|
|
||||||
STDMETHOD(GetSecondaryBufferInterface)(THIS_ LPDIRECTSOUNDBUFFER *lplpdsb) PURE;
|
|
||||||
STDMETHOD(ReleaseDirectSoundInterface)(THIS_ LPDIRECTSOUND lpds) PURE;
|
|
||||||
STDMETHOD(ReleasePrimaryBufferInterface)(THIS_ LPDIRECTSOUNDBUFFER lpdsb) PURE;
|
|
||||||
STDMETHOD(ReleaseSecondaryBufferInterface)(THIS_ LPDIRECTSOUNDBUFFER lpdsb) PURE;
|
|
||||||
STDMETHOD(SetFocusWindow)(THIS_ HWND, BOOL) PURE ;
|
|
||||||
STDMETHOD(GetFocusWindow)(THIS_ HWND *, BOOL*) PURE ;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif // __cplusplus
|
|
||||||
#endif // __AMAUDIO__
|
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: AMExtra.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - implements CRenderedInputPin class.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#include <streams.h> // DirectShow base class definitions
|
|
||||||
#include <mmsystem.h> // Needed for definition of timeGetTime
|
|
||||||
#include <limits.h> // Standard data type limit definitions
|
|
||||||
#include <measure.h> // Used for time critical log functions
|
|
||||||
|
|
||||||
#include "amextra.h"
|
|
||||||
|
|
||||||
#pragma warning(disable:4355)
|
|
||||||
|
|
||||||
// Implements CRenderedInputPin class
|
|
||||||
|
|
||||||
CRenderedInputPin::CRenderedInputPin(TCHAR *pObjectName,
|
|
||||||
CBaseFilter *pFilter,
|
|
||||||
CCritSec *pLock,
|
|
||||||
HRESULT *phr,
|
|
||||||
LPCWSTR pName) :
|
|
||||||
CBaseInputPin(pObjectName, pFilter, pLock, phr, pName),
|
|
||||||
m_bAtEndOfStream(FALSE),
|
|
||||||
m_bCompleteNotified(FALSE)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#ifdef UNICODE
|
|
||||||
CRenderedInputPin::CRenderedInputPin(CHAR *pObjectName,
|
|
||||||
CBaseFilter *pFilter,
|
|
||||||
CCritSec *pLock,
|
|
||||||
HRESULT *phr,
|
|
||||||
LPCWSTR pName) :
|
|
||||||
CBaseInputPin(pObjectName, pFilter, pLock, phr, pName),
|
|
||||||
m_bAtEndOfStream(FALSE),
|
|
||||||
m_bCompleteNotified(FALSE)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Flush end of stream condition - caller should do any
|
|
||||||
// necessary stream level locking before calling this
|
|
||||||
|
|
||||||
STDMETHODIMP CRenderedInputPin::EndOfStream()
|
|
||||||
{
|
|
||||||
HRESULT hr = CheckStreaming();
|
|
||||||
|
|
||||||
// Do EC_COMPLETE handling for rendered pins
|
|
||||||
if (S_OK == hr && !m_bAtEndOfStream) {
|
|
||||||
m_bAtEndOfStream = TRUE;
|
|
||||||
FILTER_STATE fs;
|
|
||||||
EXECUTE_ASSERT(SUCCEEDED(m_pFilter->GetState(0, &fs)));
|
|
||||||
if (fs == State_Running) {
|
|
||||||
DoCompleteHandling();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Called to complete the flush
|
|
||||||
|
|
||||||
STDMETHODIMP CRenderedInputPin::EndFlush()
|
|
||||||
{
|
|
||||||
CAutoLock lck(m_pLock);
|
|
||||||
|
|
||||||
// Clean up renderer state
|
|
||||||
m_bAtEndOfStream = FALSE;
|
|
||||||
m_bCompleteNotified = FALSE;
|
|
||||||
|
|
||||||
return CBaseInputPin::EndFlush();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Notify of Run() from filter
|
|
||||||
|
|
||||||
HRESULT CRenderedInputPin::Run(REFERENCE_TIME tStart)
|
|
||||||
{
|
|
||||||
UNREFERENCED_PARAMETER(tStart);
|
|
||||||
m_bCompleteNotified = FALSE;
|
|
||||||
if (m_bAtEndOfStream) {
|
|
||||||
DoCompleteHandling();
|
|
||||||
}
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Clear status on going into paused state
|
|
||||||
|
|
||||||
HRESULT CRenderedInputPin::Active()
|
|
||||||
{
|
|
||||||
m_bAtEndOfStream = FALSE;
|
|
||||||
m_bCompleteNotified = FALSE;
|
|
||||||
return CBaseInputPin::Active();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Do stuff to deliver end of stream
|
|
||||||
|
|
||||||
void CRenderedInputPin::DoCompleteHandling()
|
|
||||||
{
|
|
||||||
ASSERT(m_bAtEndOfStream);
|
|
||||||
if (!m_bCompleteNotified) {
|
|
||||||
m_bCompleteNotified = TRUE;
|
|
||||||
m_pFilter->NotifyEvent(EC_COMPLETE, S_OK, (LONG_PTR)(IBaseFilter *)m_pFilter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: AMExtra.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __AMEXTRA__
|
|
||||||
#define __AMEXTRA__
|
|
||||||
|
|
||||||
// Simple rendered input pin
|
|
||||||
//
|
|
||||||
// NOTE if your filter queues stuff before rendering then it may not be
|
|
||||||
// appropriate to use this class
|
|
||||||
//
|
|
||||||
// In that case queue the end of stream condition until the last sample
|
|
||||||
// is actually rendered and flush the condition appropriately
|
|
||||||
|
|
||||||
class CRenderedInputPin : public CBaseInputPin
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
CRenderedInputPin(TCHAR *pObjectName,
|
|
||||||
CBaseFilter *pFilter,
|
|
||||||
CCritSec *pLock,
|
|
||||||
HRESULT *phr,
|
|
||||||
LPCWSTR pName);
|
|
||||||
#ifdef UNICODE
|
|
||||||
CRenderedInputPin(CHAR *pObjectName,
|
|
||||||
CBaseFilter *pFilter,
|
|
||||||
CCritSec *pLock,
|
|
||||||
HRESULT *phr,
|
|
||||||
LPCWSTR pName);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Override methods to track end of stream state
|
|
||||||
STDMETHODIMP EndOfStream();
|
|
||||||
STDMETHODIMP EndFlush();
|
|
||||||
|
|
||||||
HRESULT Active();
|
|
||||||
HRESULT Run(REFERENCE_TIME tStart);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Member variables to track state
|
|
||||||
BOOL m_bAtEndOfStream; // Set by EndOfStream
|
|
||||||
BOOL m_bCompleteNotified; // Set when we notify for EC_COMPLETE
|
|
||||||
|
|
||||||
private:
|
|
||||||
void DoCompleteHandling();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __AMEXTRA__
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,275 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: AMVideo.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - implements helper functions for
|
|
||||||
// bitmap formats.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
// These are bit field masks for true colour devices
|
|
||||||
|
|
||||||
const DWORD bits555[] = {0x007C00,0x0003E0,0x00001F};
|
|
||||||
const DWORD bits565[] = {0x00F800,0x0007E0,0x00001F};
|
|
||||||
const DWORD bits888[] = {0xFF0000,0x00FF00,0x0000FF};
|
|
||||||
|
|
||||||
// This maps bitmap subtypes into a bits per pixel value and also a
|
|
||||||
// name. unicode and ansi versions are stored because we have to
|
|
||||||
// return a pointer to a static string.
|
|
||||||
const struct {
|
|
||||||
const GUID *pSubtype;
|
|
||||||
WORD BitCount;
|
|
||||||
CHAR *pName;
|
|
||||||
WCHAR *wszName;
|
|
||||||
} BitCountMap[] = { &MEDIASUBTYPE_RGB1, 1, "RGB Monochrome", L"RGB Monochrome",
|
|
||||||
&MEDIASUBTYPE_RGB4, 4, "RGB VGA", L"RGB VGA",
|
|
||||||
&MEDIASUBTYPE_RGB8, 8, "RGB 8", L"RGB 8",
|
|
||||||
&MEDIASUBTYPE_RGB565, 16, "RGB 565 (16 bit)", L"RGB 565 (16 bit)",
|
|
||||||
&MEDIASUBTYPE_RGB555, 16, "RGB 555 (16 bit)", L"RGB 555 (16 bit)",
|
|
||||||
&MEDIASUBTYPE_RGB24, 24, "RGB 24", L"RGB 24",
|
|
||||||
&MEDIASUBTYPE_RGB32, 32, "RGB 32", L"RGB 32",
|
|
||||||
&MEDIASUBTYPE_ARGB32, 32, "ARGB 32", L"ARGB 32",
|
|
||||||
&MEDIASUBTYPE_Overlay, 0, "Overlay", L"Overlay",
|
|
||||||
&GUID_NULL, 0, "UNKNOWN", L"UNKNOWN"
|
|
||||||
};
|
|
||||||
|
|
||||||
// Return the size of the bitmap as defined by this header
|
|
||||||
|
|
||||||
STDAPI_(DWORD) GetBitmapSize(const BITMAPINFOHEADER *pHeader)
|
|
||||||
{
|
|
||||||
return DIBSIZE(*pHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// This is called if the header has a 16 bit colour depth and needs to work
|
|
||||||
// out the detailed type from the bit fields (either RGB 565 or RGB 555)
|
|
||||||
|
|
||||||
STDAPI_(const GUID) GetTrueColorType(const BITMAPINFOHEADER *pbmiHeader)
|
|
||||||
{
|
|
||||||
BITMAPINFO *pbmInfo = (BITMAPINFO *) pbmiHeader;
|
|
||||||
ASSERT(pbmiHeader->biBitCount == 16);
|
|
||||||
|
|
||||||
// If its BI_RGB then it's RGB 555 by default
|
|
||||||
|
|
||||||
if (pbmiHeader->biCompression == BI_RGB) {
|
|
||||||
return MEDIASUBTYPE_RGB555;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare the bit fields with RGB 555
|
|
||||||
|
|
||||||
DWORD *pMask = (DWORD *) pbmInfo->bmiColors;
|
|
||||||
if (pMask[0] == bits555[0]) {
|
|
||||||
if (pMask[1] == bits555[1]) {
|
|
||||||
if (pMask[2] == bits555[2]) {
|
|
||||||
return MEDIASUBTYPE_RGB555;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare the bit fields with RGB 565
|
|
||||||
|
|
||||||
pMask = (DWORD *) pbmInfo->bmiColors;
|
|
||||||
if (pMask[0] == bits565[0]) {
|
|
||||||
if (pMask[1] == bits565[1]) {
|
|
||||||
if (pMask[2] == bits565[2]) {
|
|
||||||
return MEDIASUBTYPE_RGB565;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return GUID_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Given a BITMAPINFOHEADER structure this returns the GUID sub type that is
|
|
||||||
// used to describe it in format negotiations. For example a video codec fills
|
|
||||||
// in the format block with a VIDEOINFO structure, it also fills in the major
|
|
||||||
// type with MEDIATYPE_VIDEO and the subtype with a GUID that matches the bit
|
|
||||||
// count, for example if it is an eight bit image then MEDIASUBTYPE_RGB8
|
|
||||||
|
|
||||||
STDAPI_(const GUID) GetBitmapSubtype(const BITMAPINFOHEADER *pbmiHeader)
|
|
||||||
{
|
|
||||||
ASSERT(pbmiHeader);
|
|
||||||
|
|
||||||
// If it's not RGB then create a GUID from the compression type
|
|
||||||
|
|
||||||
if (pbmiHeader->biCompression != BI_RGB) {
|
|
||||||
if (pbmiHeader->biCompression != BI_BITFIELDS) {
|
|
||||||
FOURCCMap FourCCMap(pbmiHeader->biCompression);
|
|
||||||
return (const GUID) FourCCMap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map the RGB DIB bit depth to a image GUID
|
|
||||||
|
|
||||||
switch(pbmiHeader->biBitCount) {
|
|
||||||
case 1 : return MEDIASUBTYPE_RGB1;
|
|
||||||
case 4 : return MEDIASUBTYPE_RGB4;
|
|
||||||
case 8 : return MEDIASUBTYPE_RGB8;
|
|
||||||
case 16 : return GetTrueColorType(pbmiHeader);
|
|
||||||
case 24 : return MEDIASUBTYPE_RGB24;
|
|
||||||
case 32 : return MEDIASUBTYPE_RGB32;
|
|
||||||
}
|
|
||||||
return GUID_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Given a video bitmap subtype we return the number of bits per pixel it uses
|
|
||||||
// We return a WORD bit count as thats what the BITMAPINFOHEADER uses. If the
|
|
||||||
// GUID subtype is not found in the table we return an invalid USHRT_MAX
|
|
||||||
|
|
||||||
STDAPI_(WORD) GetBitCount(const GUID *pSubtype)
|
|
||||||
{
|
|
||||||
ASSERT(pSubtype);
|
|
||||||
const GUID *pMediaSubtype;
|
|
||||||
INT iPosition = 0;
|
|
||||||
|
|
||||||
// Scan the mapping list seeing if the source GUID matches any known
|
|
||||||
// bitmap subtypes, the list is terminated by a GUID_NULL entry
|
|
||||||
|
|
||||||
while (TRUE) {
|
|
||||||
pMediaSubtype = BitCountMap[iPosition].pSubtype;
|
|
||||||
if (IsEqualGUID(*pMediaSubtype,GUID_NULL)) {
|
|
||||||
return USHRT_MAX;
|
|
||||||
}
|
|
||||||
if (IsEqualGUID(*pMediaSubtype,*pSubtype)) {
|
|
||||||
return BitCountMap[iPosition].BitCount;
|
|
||||||
}
|
|
||||||
iPosition++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Given a bitmap subtype we return a description name that can be used for
|
|
||||||
// debug purposes. In a retail build this function still returns the names
|
|
||||||
// If the subtype isn't found in the lookup table we return string UNKNOWN
|
|
||||||
|
|
||||||
int LocateSubtype(const GUID *pSubtype)
|
|
||||||
{
|
|
||||||
ASSERT(pSubtype);
|
|
||||||
const GUID *pMediaSubtype;
|
|
||||||
INT iPosition = 0;
|
|
||||||
|
|
||||||
// Scan the mapping list seeing if the source GUID matches any known
|
|
||||||
// bitmap subtypes, the list is terminated by a GUID_NULL entry
|
|
||||||
|
|
||||||
while (TRUE) {
|
|
||||||
pMediaSubtype = BitCountMap[iPosition].pSubtype;
|
|
||||||
if (IsEqualGUID(*pMediaSubtype,*pSubtype) ||
|
|
||||||
IsEqualGUID(*pMediaSubtype,GUID_NULL)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
iPosition++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return iPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STDAPI_(WCHAR *) GetSubtypeNameW(const GUID *pSubtype)
|
|
||||||
{
|
|
||||||
return BitCountMap[LocateSubtype(pSubtype)].wszName;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDAPI_(CHAR *) GetSubtypeNameA(const GUID *pSubtype)
|
|
||||||
{
|
|
||||||
return BitCountMap[LocateSubtype(pSubtype)].pName;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef GetSubtypeName
|
|
||||||
#error wxutil.h should have defined GetSubtypeName
|
|
||||||
#endif
|
|
||||||
#undef GetSubtypeName
|
|
||||||
|
|
||||||
// this is here for people that linked to it directly; most people
|
|
||||||
// would use the header file that picks the A or W version.
|
|
||||||
STDAPI_(CHAR *) GetSubtypeName(const GUID *pSubtype)
|
|
||||||
{
|
|
||||||
return GetSubtypeNameA(pSubtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// The mechanism for describing a bitmap format is with the BITMAPINFOHEADER
|
|
||||||
// This is really messy to deal with because it invariably has fields that
|
|
||||||
// follow it holding bit fields, palettes and the rest. This function gives
|
|
||||||
// the number of bytes required to hold a VIDEOINFO that represents it. This
|
|
||||||
// count includes the prefix information (like the rcSource rectangle) the
|
|
||||||
// BITMAPINFOHEADER field, and any other colour information on the end.
|
|
||||||
//
|
|
||||||
// WARNING If you want to copy a BITMAPINFOHEADER into a VIDEOINFO always make
|
|
||||||
// sure that you use the HEADER macro because the BITMAPINFOHEADER field isn't
|
|
||||||
// right at the start of the VIDEOINFO (there are a number of other fields),
|
|
||||||
//
|
|
||||||
// CopyMemory(HEADER(pVideoInfo),pbmi,sizeof(BITMAPINFOHEADER));
|
|
||||||
//
|
|
||||||
|
|
||||||
STDAPI_(LONG) GetBitmapFormatSize(const BITMAPINFOHEADER *pHeader)
|
|
||||||
{
|
|
||||||
// Everyone has this to start with this
|
|
||||||
LONG Size = SIZE_PREHEADER + pHeader->biSize;
|
|
||||||
|
|
||||||
ASSERT(pHeader->biSize >= sizeof(BITMAPINFOHEADER));
|
|
||||||
|
|
||||||
// Does this format use a palette, if the number of colours actually used
|
|
||||||
// is zero then it is set to the maximum that are allowed for that colour
|
|
||||||
// depth (an example is 256 for eight bits). Truecolour formats may also
|
|
||||||
// pass a palette with them in which case the used count is non zero
|
|
||||||
|
|
||||||
// This would scare me.
|
|
||||||
ASSERT(pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed == 0);
|
|
||||||
|
|
||||||
if (pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed) {
|
|
||||||
LONG Entries = (DWORD) 1 << pHeader->biBitCount;
|
|
||||||
if (pHeader->biClrUsed) {
|
|
||||||
Entries = pHeader->biClrUsed;
|
|
||||||
}
|
|
||||||
Size += Entries * sizeof(RGBQUAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Truecolour formats may have a BI_BITFIELDS specifier for compression
|
|
||||||
// type which means that room for three DWORDs should be allocated that
|
|
||||||
// specify where in each pixel the RGB colour components may be found
|
|
||||||
|
|
||||||
if (pHeader->biCompression == BI_BITFIELDS) {
|
|
||||||
Size += SIZE_MASKS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A BITMAPINFO for a palettised image may also contain a palette map that
|
|
||||||
// provides the information to map from a source palette to a destination
|
|
||||||
// palette during a BitBlt for example, because this information is only
|
|
||||||
// ever processed during drawing you don't normally store the palette map
|
|
||||||
// nor have any way of knowing if it is present in the data structure
|
|
||||||
|
|
||||||
return Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Returns TRUE if the VIDEOINFO contains a palette
|
|
||||||
|
|
||||||
STDAPI_(BOOL) ContainsPalette(const VIDEOINFOHEADER *pVideoInfo)
|
|
||||||
{
|
|
||||||
if (PALETTISED(pVideoInfo) == FALSE) {
|
|
||||||
if (pVideoInfo->bmiHeader.biClrUsed == 0) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Return a pointer to the first entry in a palette
|
|
||||||
|
|
||||||
STDAPI_(const RGBQUAD *) GetBitmapPalette(const VIDEOINFOHEADER *pVideoInfo)
|
|
||||||
{
|
|
||||||
if (pVideoInfo->bmiHeader.biCompression == BI_BITFIELDS) {
|
|
||||||
return TRUECOLOR(pVideoInfo)->bmiColors;
|
|
||||||
}
|
|
||||||
return COLORS(pVideoInfo);
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: AudEvCod.h
|
|
||||||
//
|
|
||||||
// Desc: List of Audio device error event codes and the expected params.
|
|
||||||
//
|
|
||||||
// Copyright (c) 1999-2001, Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __AUDEVCOD__
|
|
||||||
#define __AUDEVCOD__
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_SND_DEVICE_ERROR_BASE 0x0200
|
|
||||||
|
|
||||||
typedef enum _tagSND_DEVICE_ERROR {
|
|
||||||
|
|
||||||
SNDDEV_ERROR_Open=1,
|
|
||||||
SNDDEV_ERROR_Close=2,
|
|
||||||
SNDDEV_ERROR_GetCaps=3,
|
|
||||||
SNDDEV_ERROR_PrepareHeader=4,
|
|
||||||
SNDDEV_ERROR_UnprepareHeader=5,
|
|
||||||
SNDDEV_ERROR_Reset=6,
|
|
||||||
SNDDEV_ERROR_Restart=7,
|
|
||||||
SNDDEV_ERROR_GetPosition=8,
|
|
||||||
SNDDEV_ERROR_Write=9,
|
|
||||||
SNDDEV_ERROR_Pause=10,
|
|
||||||
SNDDEV_ERROR_Stop=11,
|
|
||||||
SNDDEV_ERROR_Start=12,
|
|
||||||
SNDDEV_ERROR_AddBuffer=13,
|
|
||||||
SNDDEV_ERROR_Query=14,
|
|
||||||
|
|
||||||
} SNDDEV_ERR;
|
|
||||||
|
|
||||||
|
|
||||||
// Sound device error event codes
|
|
||||||
// ==============================
|
|
||||||
//
|
|
||||||
// All audio device error events are always passed on to the application, and are
|
|
||||||
// never processed by the filter graph
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_SNDDEV_IN_ERROR (EC_SND_DEVICE_ERROR_BASE + 0x00)
|
|
||||||
#define EC_SNDDEV_OUT_ERROR (EC_SND_DEVICE_ERROR_BASE + 0x01)
|
|
||||||
// Parameters: ( DWORD, DWORD)
|
|
||||||
// lParam1 is an enum SND_DEVICE_ERROR which notifies the app how the device was
|
|
||||||
// being accessed when the failure occurred.
|
|
||||||
//
|
|
||||||
// lParam2 is the error returned from the sound device call.
|
|
||||||
//
|
|
||||||
|
|
||||||
#endif // __AUDEVCOD__
|
|
|
@ -1,444 +0,0 @@
|
||||||
<?xml version="1.0" encoding="windows-1250"?>
|
|
||||||
<VisualStudioProject
|
|
||||||
ProjectType="Visual C++"
|
|
||||||
Version="8.00"
|
|
||||||
Name="BaseClasses"
|
|
||||||
ProjectGUID="{7CDC5863-9F36-468D-A634-6D7799E0A15E}"
|
|
||||||
RootNamespace="baseclasses"
|
|
||||||
>
|
|
||||||
<Platforms>
|
|
||||||
<Platform
|
|
||||||
Name="Win32"
|
|
||||||
/>
|
|
||||||
</Platforms>
|
|
||||||
<ToolFiles>
|
|
||||||
</ToolFiles>
|
|
||||||
<Configurations>
|
|
||||||
<Configuration
|
|
||||||
Name="Release|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="4"
|
|
||||||
UseOfMFC="0"
|
|
||||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
|
||||||
CharacterSet="1"
|
|
||||||
ManagedExtensions="0"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="."
|
|
||||||
PreprocessorDefinitions="_LIB;_WIN32_DCOM"
|
|
||||||
PrecompiledHeaderThrough="streams.h"
|
|
||||||
PrecompiledHeaderFile="$(OutDir)/baseclasses.pch"
|
|
||||||
CallingConvention="2"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
PreprocessorDefinitions="NDEBUG,WIN32"
|
|
||||||
Culture="1033"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLibrarianTool"
|
|
||||||
AdditionalDependencies="strmiids.lib winmm.lib"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
ConfigurationType="4"
|
|
||||||
UseOfMFC="0"
|
|
||||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
|
||||||
CharacterSet="1"
|
|
||||||
ManagedExtensions="0"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="."
|
|
||||||
PreprocessorDefinitions="_LIB;_WIN32_DCOM"
|
|
||||||
PrecompiledHeaderThrough="streams.h"
|
|
||||||
PrecompiledHeaderFile="$(OutDir)/baseclasses.pch"
|
|
||||||
CallingConvention="2"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
PreprocessorDefinitions="_DEBUG,WIN32"
|
|
||||||
Culture="1033"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLibrarianTool"
|
|
||||||
AdditionalDependencies="strmiids.lib winmm.lib"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
</Configurations>
|
|
||||||
<References>
|
|
||||||
</References>
|
|
||||||
<Files>
|
|
||||||
<Filter
|
|
||||||
Name="Source Files"
|
|
||||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
|
||||||
>
|
|
||||||
<File
|
|
||||||
RelativePath=".\amextra.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\amfilter.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\amvideo.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\combase.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\cprop.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\ctlutil.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\ddmm.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\dllentry.cpp"
|
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32"
|
|
||||||
ExcludedFromBuild="true"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
ExcludedFromBuild="true"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\dllsetup.cpp"
|
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32"
|
|
||||||
ExcludedFromBuild="true"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
ExcludedFromBuild="true"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mtype.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\outputq.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\pstream.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\pullpin.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\refclock.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\renbase.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\schedule.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\seekpt.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\source.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\strmctl.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\sysclock.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\transfrm.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\transip.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\videoctl.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\vtrans.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\winctrl.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\winutil.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\wxdebug.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\wxlist.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\wxutil.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="Header Files"
|
|
||||||
Filter="h;hpp;hxx;hm;inl"
|
|
||||||
>
|
|
||||||
<File
|
|
||||||
RelativePath=".\amextra.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\amfilter.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\cache.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\combase.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\cprop.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\ctlutil.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\ddmm.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\dllsetup.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\dsschedule.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\fourcc.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\measure.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\msgthrd.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mtype.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\outputq.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\pstream.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\pullpin.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\refclock.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\reftime.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\renbase.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\schedule.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\seekpt.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\source.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\streams.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\strmctl.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\sysclock.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\transfrm.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\transip.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\videoctl.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\vtrans.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\winctrl.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\winutil.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\wxdebug.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\wxlist.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\wxutil.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
</Files>
|
|
||||||
<Globals>
|
|
||||||
</Globals>
|
|
||||||
</VisualStudioProject>
|
|
|
@ -1,65 +0,0 @@
|
||||||
<?xml version="1.0" encoding="windows-1250"?>
|
|
||||||
<VisualStudioUserFile
|
|
||||||
ProjectType="Visual C++"
|
|
||||||
Version="8.00"
|
|
||||||
ShowAllFiles="false"
|
|
||||||
>
|
|
||||||
<Configurations>
|
|
||||||
<Configuration
|
|
||||||
Name="Release|Win32"
|
|
||||||
>
|
|
||||||
<DebugSettings
|
|
||||||
Command=""
|
|
||||||
WorkingDirectory=""
|
|
||||||
CommandArguments=""
|
|
||||||
Attach="false"
|
|
||||||
DebuggerType="3"
|
|
||||||
Remote="1"
|
|
||||||
RemoteMachine="REFRACTION"
|
|
||||||
RemoteCommand=""
|
|
||||||
HttpUrl=""
|
|
||||||
PDBPath=""
|
|
||||||
SQLDebugging=""
|
|
||||||
Environment=""
|
|
||||||
EnvironmentMerge="true"
|
|
||||||
DebuggerFlavor=""
|
|
||||||
MPIRunCommand=""
|
|
||||||
MPIRunArguments=""
|
|
||||||
MPIRunWorkingDirectory=""
|
|
||||||
ApplicationCommand=""
|
|
||||||
ApplicationArguments=""
|
|
||||||
ShimCommand=""
|
|
||||||
MPIAcceptMode=""
|
|
||||||
MPIAcceptFilter=""
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<DebugSettings
|
|
||||||
Command=""
|
|
||||||
WorkingDirectory=""
|
|
||||||
CommandArguments=""
|
|
||||||
Attach="false"
|
|
||||||
DebuggerType="3"
|
|
||||||
Remote="1"
|
|
||||||
RemoteMachine="REFRACTION"
|
|
||||||
RemoteCommand=""
|
|
||||||
HttpUrl=""
|
|
||||||
PDBPath=""
|
|
||||||
SQLDebugging=""
|
|
||||||
Environment=""
|
|
||||||
EnvironmentMerge="true"
|
|
||||||
DebuggerFlavor=""
|
|
||||||
MPIRunCommand=""
|
|
||||||
MPIRunArguments=""
|
|
||||||
MPIRunWorkingDirectory=""
|
|
||||||
ApplicationCommand=""
|
|
||||||
ApplicationArguments=""
|
|
||||||
ShimCommand=""
|
|
||||||
MPIAcceptMode=""
|
|
||||||
MPIAcceptFilter=""
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
</Configurations>
|
|
||||||
</VisualStudioUserFile>
|
|
|
@ -1,74 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: Cache.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - efines a non-MFC generic cache class.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
/* This class implements a simple cache. A cache object is instantiated
|
|
||||||
with the number of items it is to hold. An item is a pointer to an
|
|
||||||
object derived from CBaseObject (helps reduce memory leaks). The cache
|
|
||||||
can then have objects added to it and removed from it. The cache size
|
|
||||||
is fixed at construction time and may therefore run out or be flooded.
|
|
||||||
If it runs out it returns a NULL pointer, if it fills up it also returns
|
|
||||||
a NULL pointer instead of a pointer to the object just inserted */
|
|
||||||
|
|
||||||
/* Making these classes inherit from CBaseObject does nothing for their
|
|
||||||
functionality but it allows us to check there are no memory leaks */
|
|
||||||
|
|
||||||
/* WARNING Be very careful when using this class, what it lets you do is
|
|
||||||
store and retrieve objects so that you can minimise object creation
|
|
||||||
which in turns improves efficiency. However the object you store is
|
|
||||||
exactly the same as the object you get back which means that it short
|
|
||||||
circuits the constructor initialisation phase. This means any class
|
|
||||||
variables the object has (eg pointers) are highly likely to be invalid.
|
|
||||||
Therefore ensure you reinitialise the object before using it again */
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __CACHE__
|
|
||||||
#define __CACHE__
|
|
||||||
|
|
||||||
|
|
||||||
class CCache : CBaseObject {
|
|
||||||
|
|
||||||
/* Make copy constructor and assignment operator inaccessible */
|
|
||||||
|
|
||||||
CCache(const CCache &refCache);
|
|
||||||
CCache &operator=(const CCache &refCache);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
/* These are initialised in the constructor. The first variable points to
|
|
||||||
an array of pointers, each of which points to a CBaseObject derived
|
|
||||||
object. The m_iCacheSize is the static fixed size for the cache and the
|
|
||||||
m_iUsed defines the number of places filled with objects at any time.
|
|
||||||
We fill the array of pointers from the start (ie m_ppObjects[0] first)
|
|
||||||
and then only add and remove objects from the end position, so in this
|
|
||||||
respect the array of object pointers should be treated as a stack */
|
|
||||||
|
|
||||||
CBaseObject **m_ppObjects;
|
|
||||||
const INT m_iCacheSize;
|
|
||||||
INT m_iUsed;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CCache(TCHAR *pName,INT iItems);
|
|
||||||
virtual ~CCache();
|
|
||||||
|
|
||||||
/* Add an item to the cache */
|
|
||||||
CBaseObject *AddToCache(CBaseObject *pObject);
|
|
||||||
|
|
||||||
/* Remove an item from the cache */
|
|
||||||
CBaseObject *RemoveFromCache();
|
|
||||||
|
|
||||||
/* Delete all the objects held in the cache */
|
|
||||||
void RemoveAll(void);
|
|
||||||
|
|
||||||
/* Return the cache size which is set during construction */
|
|
||||||
INT GetCacheSize(void) const {return m_iCacheSize;};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __CACHE__ */
|
|
||||||
|
|
|
@ -1,256 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: ComBase.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - implements class hierarchy for creating
|
|
||||||
// COM objects.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
#pragma warning( disable : 4514 ) // Disable warnings re unused inline functions
|
|
||||||
|
|
||||||
|
|
||||||
/* Define the static member variable */
|
|
||||||
|
|
||||||
LONG CBaseObject::m_cObjects = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* Constructor */
|
|
||||||
|
|
||||||
CBaseObject::CBaseObject(const TCHAR *pName)
|
|
||||||
{
|
|
||||||
/* Increment the number of active objects */
|
|
||||||
InterlockedIncrement(&m_cObjects);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
m_dwCookie = DbgRegisterObjectCreation(0, pName);
|
|
||||||
#else
|
|
||||||
m_dwCookie = DbgRegisterObjectCreation(pName, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
CBaseObject::CBaseObject(const char *pName)
|
|
||||||
{
|
|
||||||
/* Increment the number of active objects */
|
|
||||||
InterlockedIncrement(&m_cObjects);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
m_dwCookie = DbgRegisterObjectCreation(pName, 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HINSTANCE hlibOLEAut32;
|
|
||||||
|
|
||||||
/* Destructor */
|
|
||||||
|
|
||||||
CBaseObject::~CBaseObject()
|
|
||||||
{
|
|
||||||
/* Decrement the number of objects active */
|
|
||||||
if (InterlockedDecrement(&m_cObjects) == 0) {
|
|
||||||
if (hlibOLEAut32) {
|
|
||||||
FreeLibrary(hlibOLEAut32);
|
|
||||||
|
|
||||||
hlibOLEAut32 = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
DbgRegisterObjectDestruction(m_dwCookie);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static const TCHAR szOle32Aut[] = TEXT("OleAut32.dll");
|
|
||||||
|
|
||||||
HINSTANCE LoadOLEAut32()
|
|
||||||
{
|
|
||||||
if (hlibOLEAut32 == 0) {
|
|
||||||
|
|
||||||
hlibOLEAut32 = LoadLibrary(szOle32Aut);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hlibOLEAut32;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Constructor */
|
|
||||||
|
|
||||||
// We know we use "this" in the initialization list, we also know we don't modify *phr.
|
|
||||||
#pragma warning( disable : 4355 4100 )
|
|
||||||
CUnknown::CUnknown(const TCHAR *pName, LPUNKNOWN pUnk)
|
|
||||||
: CBaseObject(pName)
|
|
||||||
/* Start the object with a reference count of zero - when the */
|
|
||||||
/* object is queried for it's first interface this may be */
|
|
||||||
/* incremented depending on whether or not this object is */
|
|
||||||
/* currently being aggregated upon */
|
|
||||||
, m_cRef(0)
|
|
||||||
/* Set our pointer to our IUnknown interface. */
|
|
||||||
/* If we have an outer, use its, otherwise use ours. */
|
|
||||||
/* This pointer effectivly points to the owner of */
|
|
||||||
/* this object and can be accessed by the GetOwner() method. */
|
|
||||||
, m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
|
|
||||||
/* Why the double cast? Well, the inner cast is a type-safe cast */
|
|
||||||
/* to pointer to a type from which we inherit. The second is */
|
|
||||||
/* type-unsafe but works because INonDelegatingUnknown "behaves */
|
|
||||||
/* like" IUnknown. (Only the names on the methods change.) */
|
|
||||||
{
|
|
||||||
// Everything we need to do has been done in the initializer list
|
|
||||||
}
|
|
||||||
|
|
||||||
// This does the same as above except it has a useless HRESULT argument
|
|
||||||
// use the previous constructor, this is just left for compatibility...
|
|
||||||
CUnknown::CUnknown(TCHAR *pName, LPUNKNOWN pUnk,HRESULT *phr) :
|
|
||||||
CBaseObject(pName),
|
|
||||||
m_cRef(0),
|
|
||||||
m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
CUnknown::CUnknown(const CHAR *pName, LPUNKNOWN pUnk)
|
|
||||||
: CBaseObject(pName), m_cRef(0),
|
|
||||||
m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
|
|
||||||
{ }
|
|
||||||
|
|
||||||
CUnknown::CUnknown(CHAR *pName, LPUNKNOWN pUnk,HRESULT *phr) :
|
|
||||||
CBaseObject(pName), m_cRef(0),
|
|
||||||
m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
|
|
||||||
{ }
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#pragma warning( default : 4355 4100 )
|
|
||||||
|
|
||||||
|
|
||||||
/* QueryInterface */
|
|
||||||
|
|
||||||
STDMETHODIMP CUnknown::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
|
|
||||||
{
|
|
||||||
CheckPointer(ppv,E_POINTER);
|
|
||||||
ValidateReadWritePtr(ppv,sizeof(PVOID));
|
|
||||||
|
|
||||||
/* We know only about IUnknown */
|
|
||||||
|
|
||||||
if (riid == IID_IUnknown) {
|
|
||||||
GetInterface((LPUNKNOWN) (PNDUNKNOWN) this, ppv);
|
|
||||||
return NOERROR;
|
|
||||||
} else {
|
|
||||||
*ppv = NULL;
|
|
||||||
return E_NOINTERFACE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We have to ensure that we DON'T use a max macro, since these will typically */
|
|
||||||
/* lead to one of the parameters being evaluated twice. Since we are worried */
|
|
||||||
/* about concurrency, we can't afford to access the m_cRef twice since we can't */
|
|
||||||
/* afford to run the risk that its value having changed between accesses. */
|
|
||||||
|
|
||||||
template<class T> inline static T ourmax( const T & a, const T & b )
|
|
||||||
{
|
|
||||||
return a > b ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* AddRef */
|
|
||||||
|
|
||||||
STDMETHODIMP_(ULONG) CUnknown::NonDelegatingAddRef()
|
|
||||||
{
|
|
||||||
LONG lRef = InterlockedIncrement( &m_cRef );
|
|
||||||
ASSERT(lRef > 0);
|
|
||||||
DbgLog((LOG_MEMORY,3,TEXT(" Obj %d ref++ = %d"),
|
|
||||||
m_dwCookie, m_cRef));
|
|
||||||
return ourmax(ULONG(m_cRef), 1ul);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Release */
|
|
||||||
|
|
||||||
STDMETHODIMP_(ULONG) CUnknown::NonDelegatingRelease()
|
|
||||||
{
|
|
||||||
/* If the reference count drops to zero delete ourselves */
|
|
||||||
|
|
||||||
LONG lRef = InterlockedDecrement( &m_cRef );
|
|
||||||
ASSERT(lRef >= 0);
|
|
||||||
|
|
||||||
DbgLog((LOG_MEMORY,3,TEXT(" Object %d ref-- = %d"),
|
|
||||||
m_dwCookie, m_cRef));
|
|
||||||
if (lRef == 0) {
|
|
||||||
|
|
||||||
// COM rules say we must protect against re-entrancy.
|
|
||||||
// If we are an aggregator and we hold our own interfaces
|
|
||||||
// on the aggregatee, the QI for these interfaces will
|
|
||||||
// addref ourselves. So after doing the QI we must release
|
|
||||||
// a ref count on ourselves. Then, before releasing the
|
|
||||||
// private interface, we must addref ourselves. When we do
|
|
||||||
// this from the destructor here it will result in the ref
|
|
||||||
// count going to 1 and then back to 0 causing us to
|
|
||||||
// re-enter the destructor. Hence we add an extra refcount here
|
|
||||||
// once we know we will delete the object.
|
|
||||||
// for an example aggregator see filgraph\distrib.cpp.
|
|
||||||
|
|
||||||
m_cRef++;
|
|
||||||
|
|
||||||
delete this;
|
|
||||||
return ULONG(0);
|
|
||||||
} else {
|
|
||||||
return ourmax(ULONG(m_cRef), 1ul);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Return an interface pointer to a requesting client
|
|
||||||
performing a thread safe AddRef as necessary */
|
|
||||||
|
|
||||||
STDAPI GetInterface(LPUNKNOWN pUnk, void **ppv)
|
|
||||||
{
|
|
||||||
CheckPointer(ppv, E_POINTER);
|
|
||||||
*ppv = pUnk;
|
|
||||||
pUnk->AddRef();
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Compares two interfaces and returns TRUE if they are on the same object */
|
|
||||||
|
|
||||||
BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond)
|
|
||||||
{
|
|
||||||
/* Different objects can't have the same interface pointer for
|
|
||||||
any interface
|
|
||||||
*/
|
|
||||||
if (pFirst == pSecond) {
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
/* OK - do it the hard way - check if they have the same
|
|
||||||
IUnknown pointers - a single object can only have one of these
|
|
||||||
*/
|
|
||||||
LPUNKNOWN pUnknown1; // Retrieve the IUnknown interface
|
|
||||||
LPUNKNOWN pUnknown2; // Retrieve the other IUnknown interface
|
|
||||||
HRESULT hr; // General OLE return code
|
|
||||||
|
|
||||||
ASSERT(pFirst);
|
|
||||||
ASSERT(pSecond);
|
|
||||||
|
|
||||||
/* See if the IUnknown pointers match */
|
|
||||||
|
|
||||||
hr = pFirst->QueryInterface(IID_IUnknown,(void **) &pUnknown1);
|
|
||||||
ASSERT(SUCCEEDED(hr));
|
|
||||||
ASSERT(pUnknown1);
|
|
||||||
|
|
||||||
hr = pSecond->QueryInterface(IID_IUnknown,(void **) &pUnknown2);
|
|
||||||
ASSERT(SUCCEEDED(hr));
|
|
||||||
ASSERT(pUnknown2);
|
|
||||||
|
|
||||||
/* Release the extra interfaces we hold */
|
|
||||||
|
|
||||||
pUnknown1->Release();
|
|
||||||
pUnknown2->Release();
|
|
||||||
return (pUnknown1 == pUnknown2);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,319 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: ComBase.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - defines a class hierarchy for creating
|
|
||||||
// COM objects.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
a. Derive your COM object from CUnknown
|
|
||||||
|
|
||||||
b. Make a static CreateInstance function that takes an LPUNKNOWN, an HRESULT *
|
|
||||||
and a TCHAR *. The LPUNKNOWN defines the object to delegate IUnknown calls
|
|
||||||
to. The HRESULT * allows error codes to be passed around constructors and
|
|
||||||
the TCHAR * is a descriptive name that can be printed on the debugger.
|
|
||||||
|
|
||||||
It is important that constructors only change the HRESULT * if they have
|
|
||||||
to set an ERROR code, if it was successful then leave it alone or you may
|
|
||||||
overwrite an error code from an object previously created.
|
|
||||||
|
|
||||||
When you call a constructor the descriptive name should be in static store
|
|
||||||
as we do not copy the string. To stop large amounts of memory being used
|
|
||||||
in retail builds by all these static strings use the NAME macro,
|
|
||||||
|
|
||||||
CMyFilter = new CImplFilter(NAME("My filter"),pUnknown,phr);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
In retail builds NAME(_x_) compiles to NULL, the base CBaseObject class
|
|
||||||
knows not to do anything with objects that don't have a name.
|
|
||||||
|
|
||||||
c. Have a constructor for your object that passes the LPUNKNOWN, HRESULT * and
|
|
||||||
TCHAR * to the CUnknown constructor. You can set the HRESULT if you have an
|
|
||||||
error, or just simply pass it through to the constructor.
|
|
||||||
|
|
||||||
The object creation will fail in the class factory if the HRESULT indicates
|
|
||||||
an error (ie FAILED(HRESULT) == TRUE)
|
|
||||||
|
|
||||||
d. Create a FactoryTemplate with your object's class id and CreateInstance
|
|
||||||
function.
|
|
||||||
|
|
||||||
Then (for each interface) either
|
|
||||||
|
|
||||||
Multiple inheritance
|
|
||||||
|
|
||||||
1. Also derive it from ISomeInterface
|
|
||||||
2. Include DECLARE_IUNKNOWN in your class definition to declare
|
|
||||||
implementations of QueryInterface, AddRef and Release that
|
|
||||||
call the outer unknown
|
|
||||||
3. Override NonDelegatingQueryInterface to expose ISomeInterface by
|
|
||||||
code something like
|
|
||||||
|
|
||||||
if (riid == IID_ISomeInterface) {
|
|
||||||
return GetInterface((ISomeInterface *) this, ppv);
|
|
||||||
} else {
|
|
||||||
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
|
|
||||||
}
|
|
||||||
|
|
||||||
4. Declare and implement the member functions of ISomeInterface.
|
|
||||||
|
|
||||||
or: Nested interfaces
|
|
||||||
|
|
||||||
1. Declare a class derived from CUnknown
|
|
||||||
2. Include DECLARE_IUNKNOWN in your class definition
|
|
||||||
3. Override NonDelegatingQueryInterface to expose ISomeInterface by
|
|
||||||
code something like
|
|
||||||
|
|
||||||
if (riid == IID_ISomeInterface) {
|
|
||||||
return GetInterface((ISomeInterface *) this, ppv);
|
|
||||||
} else {
|
|
||||||
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
|
|
||||||
}
|
|
||||||
|
|
||||||
4. Implement the member functions of ISomeInterface. Use GetOwner() to
|
|
||||||
access the COM object class.
|
|
||||||
|
|
||||||
And in your COM object class:
|
|
||||||
|
|
||||||
5. Make the nested class a friend of the COM object class, and declare
|
|
||||||
an instance of the nested class as a member of the COM object class.
|
|
||||||
|
|
||||||
NOTE that because you must always pass the outer unknown and an hResult
|
|
||||||
to the CUnknown constructor you cannot use a default constructor, in
|
|
||||||
other words you will have to make the member variable a pointer to the
|
|
||||||
class and make a NEW call in your constructor to actually create it.
|
|
||||||
|
|
||||||
6. override the NonDelegatingQueryInterface with code like this:
|
|
||||||
|
|
||||||
if (riid == IID_ISomeInterface) {
|
|
||||||
return m_pImplFilter->
|
|
||||||
NonDelegatingQueryInterface(IID_ISomeInterface, ppv);
|
|
||||||
} else {
|
|
||||||
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
|
|
||||||
}
|
|
||||||
|
|
||||||
You can have mixed classes which support some interfaces via multiple
|
|
||||||
inheritance and some via nested classes
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __COMBASE__
|
|
||||||
#define __COMBASE__
|
|
||||||
|
|
||||||
// Filter Setup data structures no defined in axextend.idl
|
|
||||||
|
|
||||||
typedef REGPINTYPES
|
|
||||||
AMOVIESETUP_MEDIATYPE, * PAMOVIESETUP_MEDIATYPE, * FAR LPAMOVIESETUP_MEDIATYPE;
|
|
||||||
|
|
||||||
typedef REGFILTERPINS
|
|
||||||
AMOVIESETUP_PIN, * PAMOVIESETUP_PIN, * FAR LPAMOVIESETUP_PIN;
|
|
||||||
|
|
||||||
typedef struct _AMOVIESETUP_FILTER
|
|
||||||
{
|
|
||||||
const CLSID * clsID;
|
|
||||||
const WCHAR * strName;
|
|
||||||
DWORD dwMerit;
|
|
||||||
UINT nPins;
|
|
||||||
const AMOVIESETUP_PIN * lpPin;
|
|
||||||
}
|
|
||||||
AMOVIESETUP_FILTER, * PAMOVIESETUP_FILTER, * FAR LPAMOVIESETUP_FILTER;
|
|
||||||
|
|
||||||
/* The DLLENTRY module initialises the module handle on loading */
|
|
||||||
|
|
||||||
extern HINSTANCE g_hInst;
|
|
||||||
|
|
||||||
/* On DLL load remember which platform we are running on */
|
|
||||||
|
|
||||||
extern DWORD g_amPlatform;
|
|
||||||
extern OSVERSIONINFO g_osInfo; // Filled in by GetVersionEx
|
|
||||||
|
|
||||||
/* Version of IUnknown that is renamed to allow a class to support both
|
|
||||||
non delegating and delegating IUnknowns in the same COM object */
|
|
||||||
|
|
||||||
#ifndef INONDELEGATINGUNKNOWN_DEFINED
|
|
||||||
DECLARE_INTERFACE(INonDelegatingUnknown)
|
|
||||||
{
|
|
||||||
STDMETHOD(NonDelegatingQueryInterface) (THIS_ REFIID, LPVOID *) PURE;
|
|
||||||
STDMETHOD_(ULONG, NonDelegatingAddRef)(THIS) PURE;
|
|
||||||
STDMETHOD_(ULONG, NonDelegatingRelease)(THIS) PURE;
|
|
||||||
};
|
|
||||||
#define INONDELEGATINGUNKNOWN_DEFINED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef INonDelegatingUnknown *PNDUNKNOWN;
|
|
||||||
|
|
||||||
|
|
||||||
/* This is the base object class that supports active object counting. As
|
|
||||||
part of the debug facilities we trace every time a C++ object is created
|
|
||||||
or destroyed. The name of the object has to be passed up through the class
|
|
||||||
derivation list during construction as you cannot call virtual functions
|
|
||||||
in the constructor. The downside of all this is that every single object
|
|
||||||
constructor has to take an object name parameter that describes it */
|
|
||||||
|
|
||||||
class CBaseObject
|
|
||||||
{
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Disable the copy constructor and assignment by default so you will get
|
|
||||||
// compiler errors instead of unexpected behaviour if you pass objects
|
|
||||||
// by value or assign objects.
|
|
||||||
CBaseObject(const CBaseObject& objectSrc); // no implementation
|
|
||||||
void operator=(const CBaseObject& objectSrc); // no implementation
|
|
||||||
|
|
||||||
private:
|
|
||||||
static LONG m_cObjects; /* Total number of objects active */
|
|
||||||
|
|
||||||
protected:
|
|
||||||
#ifdef DEBUG
|
|
||||||
DWORD m_dwCookie; /* Cookie identifying this object */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/* These increment and decrement the number of active objects */
|
|
||||||
|
|
||||||
CBaseObject(const TCHAR *pName);
|
|
||||||
#ifdef UNICODE
|
|
||||||
CBaseObject(const char *pName);
|
|
||||||
#endif
|
|
||||||
~CBaseObject();
|
|
||||||
|
|
||||||
/* Call this to find if there are any CUnknown derived objects active */
|
|
||||||
|
|
||||||
static LONG ObjectsActive() {
|
|
||||||
return m_cObjects;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* An object that supports one or more COM interfaces will be based on
|
|
||||||
this class. It supports counting of total objects for DLLCanUnloadNow
|
|
||||||
support, and an implementation of the core non delegating IUnknown */
|
|
||||||
|
|
||||||
class AM_NOVTABLE CUnknown : public INonDelegatingUnknown,
|
|
||||||
public CBaseObject
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
const LPUNKNOWN m_pUnknown; /* Owner of this object */
|
|
||||||
|
|
||||||
protected: /* So we can override NonDelegatingRelease() */
|
|
||||||
volatile LONG m_cRef; /* Number of reference counts */
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CUnknown(const TCHAR *pName, LPUNKNOWN pUnk);
|
|
||||||
virtual ~CUnknown() {};
|
|
||||||
|
|
||||||
// This is redundant, just use the other constructor
|
|
||||||
// as we never touch the HRESULT in this anyway
|
|
||||||
CUnknown(TCHAR *pName, LPUNKNOWN pUnk,HRESULT *phr);
|
|
||||||
#ifdef UNICODE
|
|
||||||
CUnknown(const char *pName, LPUNKNOWN pUnk);
|
|
||||||
CUnknown(char *pName, LPUNKNOWN pUnk,HRESULT *phr);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Return the owner of this object */
|
|
||||||
|
|
||||||
LPUNKNOWN GetOwner() const {
|
|
||||||
return m_pUnknown;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Called from the class factory to create a new instance, it is
|
|
||||||
pure virtual so it must be overriden in your derived class */
|
|
||||||
|
|
||||||
/* static CUnknown *CreateInstance(LPUNKNOWN, HRESULT *) */
|
|
||||||
|
|
||||||
/* Non delegating unknown implementation */
|
|
||||||
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID, void **);
|
|
||||||
STDMETHODIMP_(ULONG) NonDelegatingAddRef();
|
|
||||||
STDMETHODIMP_(ULONG) NonDelegatingRelease();
|
|
||||||
};
|
|
||||||
|
|
||||||
#if (_MSC_VER <= 1200)
|
|
||||||
#pragma warning(disable:4211)
|
|
||||||
|
|
||||||
/* The standard InterlockedXXX functions won't take volatiles */
|
|
||||||
static inline LONG WINAPI InterlockedIncrement( volatile LONG * plong )
|
|
||||||
{ return InterlockedIncrement( const_cast<LONG*>( plong ) ); }
|
|
||||||
|
|
||||||
static inline LONG WINAPI InterlockedDecrement( volatile LONG * plong )
|
|
||||||
{ return InterlockedDecrement( const_cast<LONG*>( plong ) ); }
|
|
||||||
|
|
||||||
#pragma warning(default:4211)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Return an interface pointer to a requesting client
|
|
||||||
performing a thread safe AddRef as necessary */
|
|
||||||
|
|
||||||
STDAPI GetInterface(LPUNKNOWN pUnk, void **ppv);
|
|
||||||
|
|
||||||
/* A function that can create a new COM object */
|
|
||||||
|
|
||||||
typedef CUnknown *(CALLBACK *LPFNNewCOMObject)(LPUNKNOWN pUnkOuter, HRESULT *phr);
|
|
||||||
|
|
||||||
/* A function (can be NULL) which is called from the DLL entrypoint
|
|
||||||
routine for each factory template:
|
|
||||||
|
|
||||||
bLoading - TRUE on DLL load, FALSE on DLL unload
|
|
||||||
rclsid - the m_ClsID of the entry
|
|
||||||
*/
|
|
||||||
typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid);
|
|
||||||
|
|
||||||
/* Create one of these per object class in an array so that
|
|
||||||
the default class factory code can create new instances */
|
|
||||||
|
|
||||||
class CFactoryTemplate {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
const WCHAR * m_Name;
|
|
||||||
const CLSID * m_ClsID;
|
|
||||||
LPFNNewCOMObject m_lpfnNew;
|
|
||||||
LPFNInitRoutine m_lpfnInit;
|
|
||||||
const AMOVIESETUP_FILTER * m_pAMovieSetup_Filter;
|
|
||||||
|
|
||||||
BOOL IsClassID(REFCLSID rclsid) const {
|
|
||||||
return (IsEqualCLSID(*m_ClsID,rclsid));
|
|
||||||
};
|
|
||||||
|
|
||||||
CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr) const {
|
|
||||||
CheckPointer(phr,NULL);
|
|
||||||
return m_lpfnNew(pUnk, phr);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* You must override the (pure virtual) NonDelegatingQueryInterface to return
|
|
||||||
interface pointers (using GetInterface) to the interfaces your derived
|
|
||||||
class supports (the default implementation only supports IUnknown) */
|
|
||||||
|
|
||||||
#define DECLARE_IUNKNOWN \
|
|
||||||
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { \
|
|
||||||
return GetOwner()->QueryInterface(riid,ppv); \
|
|
||||||
}; \
|
|
||||||
STDMETHODIMP_(ULONG) AddRef() { \
|
|
||||||
return GetOwner()->AddRef(); \
|
|
||||||
}; \
|
|
||||||
STDMETHODIMP_(ULONG) Release() { \
|
|
||||||
return GetOwner()->Release(); \
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HINSTANCE LoadOLEAut32();
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __COMBASE__ */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: COMLite.h
|
|
||||||
//
|
|
||||||
// Desc: This header file is to provide a migration path for users of
|
|
||||||
// ActiveMovie betas 1 and 2.
|
|
||||||
//
|
|
||||||
// Copyright (c) 1992-2001, Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _INC_COMLITE_
|
|
||||||
#define _INC_COMLITE_
|
|
||||||
|
|
||||||
#define QzInitialize CoInitialize
|
|
||||||
#define QzUninitialize CoUninitialize
|
|
||||||
#define QzFreeUnusedLibraries CoFreeUnusedLibraries
|
|
||||||
|
|
||||||
#define QzGetMalloc CoGetMalloc
|
|
||||||
#define QzTaskMemAlloc CoTaskMemAlloc
|
|
||||||
#define QzTaskMemRealloc CoTaskMemRealloc
|
|
||||||
#define QzTaskMemFree CoTaskMemFree
|
|
||||||
#define QzCreateFilterObject CoCreateInstance
|
|
||||||
#define QzCLSIDFromString CLSIDFromString
|
|
||||||
#define QzStringFromGUID2 StringFromGUID2
|
|
||||||
|
|
||||||
#endif // _INC_COMLITE_
|
|
|
@ -1,380 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: CProp.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - implements CBasePropertyPage class.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
|
|
||||||
// Constructor for the base property page class. As described in the header
|
|
||||||
// file we must be initialised with dialog and title resource identifiers.
|
|
||||||
// The class supports IPropertyPage and overrides AddRef and Release calls
|
|
||||||
// to keep track of the reference counts. When the last count is released
|
|
||||||
// we call SetPageSite(NULL) and SetObjects(0,NULL) to release interfaces
|
|
||||||
// previously obtained by the property page when it had SetObjects called
|
|
||||||
|
|
||||||
CBasePropertyPage::CBasePropertyPage(TCHAR *pName, // Debug only name
|
|
||||||
LPUNKNOWN pUnk, // COM Delegator
|
|
||||||
int DialogId, // Resource ID
|
|
||||||
int TitleId) : // To get tital
|
|
||||||
CUnknown(pName,pUnk),
|
|
||||||
m_DialogId(DialogId),
|
|
||||||
m_TitleId(TitleId),
|
|
||||||
m_hwnd(NULL),
|
|
||||||
m_Dlg(NULL),
|
|
||||||
m_pPageSite(NULL),
|
|
||||||
m_bObjectSet(FALSE),
|
|
||||||
m_bDirty(FALSE)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
CBasePropertyPage::CBasePropertyPage(CHAR *pName, // Debug only name
|
|
||||||
LPUNKNOWN pUnk, // COM Delegator
|
|
||||||
int DialogId, // Resource ID
|
|
||||||
int TitleId) : // To get tital
|
|
||||||
CUnknown(pName,pUnk),
|
|
||||||
m_DialogId(DialogId),
|
|
||||||
m_TitleId(TitleId),
|
|
||||||
m_hwnd(NULL),
|
|
||||||
m_Dlg(NULL),
|
|
||||||
m_pPageSite(NULL),
|
|
||||||
m_bObjectSet(FALSE),
|
|
||||||
m_bDirty(FALSE)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Increment our reference count
|
|
||||||
|
|
||||||
STDMETHODIMP_(ULONG) CBasePropertyPage::NonDelegatingAddRef()
|
|
||||||
{
|
|
||||||
LONG lRef = InterlockedIncrement(&m_cRef);
|
|
||||||
ASSERT(lRef > 0);
|
|
||||||
return max(ULONG(m_cRef),1ul);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Release a reference count and protect against reentrancy
|
|
||||||
|
|
||||||
STDMETHODIMP_(ULONG) CBasePropertyPage::NonDelegatingRelease()
|
|
||||||
{
|
|
||||||
// If the reference count drops to zero delete ourselves
|
|
||||||
|
|
||||||
if (InterlockedDecrement(&m_cRef) == 0) {
|
|
||||||
m_cRef++;
|
|
||||||
SetPageSite(NULL);
|
|
||||||
SetObjects(0,NULL);
|
|
||||||
delete this;
|
|
||||||
return ULONG(0);
|
|
||||||
} else {
|
|
||||||
return max(ULONG(m_cRef),1ul);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Expose our IPropertyPage interface
|
|
||||||
|
|
||||||
STDMETHODIMP
|
|
||||||
CBasePropertyPage::NonDelegatingQueryInterface(REFIID riid,void **ppv)
|
|
||||||
{
|
|
||||||
if (riid == IID_IPropertyPage) {
|
|
||||||
return GetInterface((IPropertyPage *)this,ppv);
|
|
||||||
} else {
|
|
||||||
return CUnknown::NonDelegatingQueryInterface(riid,ppv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Get the page info so that the page site can size itself
|
|
||||||
|
|
||||||
STDMETHODIMP CBasePropertyPage::GetPageInfo(LPPROPPAGEINFO pPageInfo)
|
|
||||||
{
|
|
||||||
CheckPointer(pPageInfo,E_POINTER);
|
|
||||||
WCHAR wszTitle[STR_MAX_LENGTH];
|
|
||||||
WideStringFromResource(wszTitle,m_TitleId);
|
|
||||||
|
|
||||||
// Allocate dynamic memory for the property page title
|
|
||||||
|
|
||||||
LPOLESTR pszTitle;
|
|
||||||
HRESULT hr = AMGetWideString(wszTitle, &pszTitle);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
NOTE("No caption memory");
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
pPageInfo->cb = sizeof(PROPPAGEINFO);
|
|
||||||
pPageInfo->pszTitle = pszTitle;
|
|
||||||
pPageInfo->pszDocString = NULL;
|
|
||||||
pPageInfo->pszHelpFile = NULL;
|
|
||||||
pPageInfo->dwHelpContext = 0;
|
|
||||||
|
|
||||||
// Set defaults in case GetDialogSize fails
|
|
||||||
pPageInfo->size.cx = 340;
|
|
||||||
pPageInfo->size.cy = 150;
|
|
||||||
|
|
||||||
GetDialogSize(m_DialogId, DialogProc,0L,&pPageInfo->size);
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Handles the messages for our property window
|
|
||||||
|
|
||||||
INT_PTR CALLBACK CBasePropertyPage::DialogProc(HWND hwnd,
|
|
||||||
UINT uMsg,
|
|
||||||
WPARAM wParam,
|
|
||||||
LPARAM lParam)
|
|
||||||
{
|
|
||||||
CBasePropertyPage *pPropertyPage;
|
|
||||||
|
|
||||||
switch (uMsg) {
|
|
||||||
|
|
||||||
case WM_INITDIALOG:
|
|
||||||
|
|
||||||
SetWindowLongPtr(hwnd, DWLP_USER, lParam);
|
|
||||||
|
|
||||||
// This pointer may be NULL when calculating size
|
|
||||||
|
|
||||||
pPropertyPage = (CBasePropertyPage *) lParam;
|
|
||||||
if (pPropertyPage == NULL) {
|
|
||||||
return (LRESULT) 1;
|
|
||||||
}
|
|
||||||
pPropertyPage->m_Dlg = hwnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This pointer may be NULL when calculating size
|
|
||||||
|
|
||||||
pPropertyPage = (CBasePropertyPage *) GetWindowLongPtr(hwnd, DWLP_USER);
|
|
||||||
if (pPropertyPage == NULL) {
|
|
||||||
return (LRESULT) 1;
|
|
||||||
}
|
|
||||||
return pPropertyPage->OnReceiveMessage(hwnd,uMsg,wParam,lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Tells us the object that should be informed of the property changes
|
|
||||||
|
|
||||||
STDMETHODIMP CBasePropertyPage::SetObjects(ULONG cObjects,LPUNKNOWN *ppUnk)
|
|
||||||
{
|
|
||||||
if (cObjects == 1) {
|
|
||||||
|
|
||||||
if ((ppUnk == NULL) || (*ppUnk == NULL)) {
|
|
||||||
return E_POINTER;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set a flag to say that we have set the Object
|
|
||||||
m_bObjectSet = TRUE ;
|
|
||||||
return OnConnect(*ppUnk);
|
|
||||||
|
|
||||||
} else if (cObjects == 0) {
|
|
||||||
|
|
||||||
// Set a flag to say that we have not set the Object for the page
|
|
||||||
m_bObjectSet = FALSE ;
|
|
||||||
return OnDisconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
DbgBreak("No support for more than one object");
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Create the window we will use to edit properties
|
|
||||||
|
|
||||||
STDMETHODIMP CBasePropertyPage::Activate(HWND hwndParent,
|
|
||||||
LPCRECT pRect,
|
|
||||||
BOOL fModal)
|
|
||||||
{
|
|
||||||
CheckPointer(pRect,E_POINTER);
|
|
||||||
|
|
||||||
// Return failure if SetObject has not been called.
|
|
||||||
if (m_bObjectSet == FALSE) {
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_hwnd) {
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_hwnd = CreateDialogParam(g_hInst,
|
|
||||||
MAKEINTRESOURCE(m_DialogId),
|
|
||||||
hwndParent,
|
|
||||||
DialogProc,
|
|
||||||
(LPARAM) this);
|
|
||||||
if (m_hwnd == NULL) {
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
OnActivate();
|
|
||||||
Move(pRect);
|
|
||||||
return Show(SW_SHOWNORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Set the position of the property page
|
|
||||||
|
|
||||||
STDMETHODIMP CBasePropertyPage::Move(LPCRECT pRect)
|
|
||||||
{
|
|
||||||
CheckPointer(pRect,E_POINTER);
|
|
||||||
|
|
||||||
if (m_hwnd == NULL) {
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
MoveWindow(m_hwnd, // Property page handle
|
|
||||||
pRect->left, // x coordinate
|
|
||||||
pRect->top, // y coordinate
|
|
||||||
WIDTH(pRect), // Overall window width
|
|
||||||
HEIGHT(pRect), // And likewise height
|
|
||||||
TRUE); // Should we repaint it
|
|
||||||
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Display the property dialog
|
|
||||||
|
|
||||||
STDMETHODIMP CBasePropertyPage::Show(UINT nCmdShow)
|
|
||||||
{
|
|
||||||
// Have we been activated yet
|
|
||||||
|
|
||||||
if (m_hwnd == NULL) {
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore wrong show flags
|
|
||||||
|
|
||||||
if ((nCmdShow != SW_SHOW) && (nCmdShow != SW_SHOWNORMAL) && (nCmdShow != SW_HIDE)) {
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShowWindow(m_hwnd,nCmdShow);
|
|
||||||
InvalidateRect(m_hwnd,NULL,TRUE);
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Destroy the property page dialog
|
|
||||||
|
|
||||||
STDMETHODIMP CBasePropertyPage::Deactivate(void)
|
|
||||||
{
|
|
||||||
if (m_hwnd == NULL) {
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove WS_EX_CONTROLPARENT before DestroyWindow call
|
|
||||||
|
|
||||||
DWORD dwStyle = GetWindowLong(m_hwnd, GWL_EXSTYLE);
|
|
||||||
dwStyle = dwStyle & (~WS_EX_CONTROLPARENT);
|
|
||||||
|
|
||||||
// Set m_hwnd to be NULL temporarily so the message handler
|
|
||||||
// for WM_STYLECHANGING doesn't add the WS_EX_CONTROLPARENT
|
|
||||||
// style back in
|
|
||||||
HWND hwnd = m_hwnd;
|
|
||||||
m_hwnd = NULL;
|
|
||||||
SetWindowLong(hwnd, GWL_EXSTYLE, dwStyle);
|
|
||||||
m_hwnd = hwnd;
|
|
||||||
|
|
||||||
OnDeactivate();
|
|
||||||
|
|
||||||
// Destroy the dialog window
|
|
||||||
|
|
||||||
DestroyWindow(m_hwnd);
|
|
||||||
m_hwnd = NULL;
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Tells the application property page site
|
|
||||||
|
|
||||||
STDMETHODIMP CBasePropertyPage::SetPageSite(LPPROPERTYPAGESITE pPageSite)
|
|
||||||
{
|
|
||||||
if (pPageSite) {
|
|
||||||
|
|
||||||
if (m_pPageSite) {
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pPageSite = pPageSite;
|
|
||||||
m_pPageSite->AddRef();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (m_pPageSite == NULL) {
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pPageSite->Release();
|
|
||||||
m_pPageSite = NULL;
|
|
||||||
}
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Apply any changes so far made
|
|
||||||
|
|
||||||
STDMETHODIMP CBasePropertyPage::Apply()
|
|
||||||
{
|
|
||||||
// In ActiveMovie 1.0 we used to check whether we had been activated or
|
|
||||||
// not. This is too constrictive. Apply should be allowed as long as
|
|
||||||
// SetObject was called to set an object. So we will no longer check to
|
|
||||||
// see if we have been activated (ie., m_hWnd != NULL), but instead
|
|
||||||
// make sure that m_bObjectSet is TRUE (ie., SetObject has been called).
|
|
||||||
|
|
||||||
if (m_bObjectSet == FALSE) {
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must have had a site set
|
|
||||||
|
|
||||||
if (m_pPageSite == NULL) {
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has anything changed
|
|
||||||
|
|
||||||
if (m_bDirty == FALSE) {
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commit derived class changes
|
|
||||||
|
|
||||||
HRESULT hr = OnApplyChanges();
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
m_bDirty = FALSE;
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Base class definition for message handling
|
|
||||||
|
|
||||||
INT_PTR CBasePropertyPage::OnReceiveMessage(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
|
||||||
{
|
|
||||||
// we would like the TAB key to move around the tab stops in our property
|
|
||||||
// page, but for some reason OleCreatePropertyFrame clears the CONTROLPARENT
|
|
||||||
// style behind our back, so we need to switch it back on now behind its
|
|
||||||
// back. Otherwise the tab key will be useless in every page.
|
|
||||||
//
|
|
||||||
|
|
||||||
CBasePropertyPage *pPropertyPage;
|
|
||||||
{
|
|
||||||
pPropertyPage = (CBasePropertyPage *) GetWindowLongPtr(hwnd, DWLP_USER);
|
|
||||||
if (pPropertyPage->m_hwnd == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
switch (uMsg) {
|
|
||||||
case WM_STYLECHANGING:
|
|
||||||
if (wParam == GWL_EXSTYLE) {
|
|
||||||
LPSTYLESTRUCT lpss = (LPSTYLESTRUCT)lParam;
|
|
||||||
lpss->styleNew |= WS_EX_CONTROLPARENT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return DefWindowProc(hwnd,uMsg,wParam,lParam);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: CProp.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __CPROP__
|
|
||||||
#define __CPROP__
|
|
||||||
|
|
||||||
// Base property page class. Filters typically expose custom properties by
|
|
||||||
// implementing special control interfaces, examples are IDirectDrawVideo
|
|
||||||
// and IQualProp on renderers. This allows property pages to be built that
|
|
||||||
// use the given interface. Applications such as the ActiveMovie OCX query
|
|
||||||
// filters for the property pages they support and expose them to the user
|
|
||||||
//
|
|
||||||
// This class provides all the framework for a property page. A property
|
|
||||||
// page is a COM object that supports IPropertyPage. We should be created
|
|
||||||
// with a resource ID for the dialog which we will load when required. We
|
|
||||||
// should also be given in the constructor a resource ID for a title string
|
|
||||||
// we will load from the DLLs STRINGTABLE. The property page titles must be
|
|
||||||
// stored in resource files so that they can be easily internationalised
|
|
||||||
//
|
|
||||||
// We have a number of virtual methods (not PURE) that may be overriden in
|
|
||||||
// derived classes to query for interfaces and so on. These functions have
|
|
||||||
// simple implementations here that just return NOERROR. Derived classes
|
|
||||||
// will almost definately have to override the message handler method called
|
|
||||||
// OnReceiveMessage. We have a static dialog procedure that calls the method
|
|
||||||
// so that derived classes don't have to fiddle around with the this pointer
|
|
||||||
|
|
||||||
class AM_NOVTABLE CBasePropertyPage : public IPropertyPage, public CUnknown
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
LPPROPERTYPAGESITE m_pPageSite; // Details for our property site
|
|
||||||
HWND m_hwnd; // Window handle for the page
|
|
||||||
HWND m_Dlg; // Actual dialog window handle
|
|
||||||
BOOL m_bDirty; // Has anything been changed
|
|
||||||
int m_TitleId; // Resource identifier for title
|
|
||||||
int m_DialogId; // Dialog resource identifier
|
|
||||||
|
|
||||||
static INT_PTR CALLBACK DialogProc(HWND hwnd,
|
|
||||||
UINT uMsg,
|
|
||||||
WPARAM wParam,
|
|
||||||
LPARAM lParam);
|
|
||||||
|
|
||||||
private:
|
|
||||||
BOOL m_bObjectSet ; // SetObject has been called or not.
|
|
||||||
public:
|
|
||||||
|
|
||||||
CBasePropertyPage(TCHAR *pName, // Debug only name
|
|
||||||
LPUNKNOWN pUnk, // COM Delegator
|
|
||||||
int DialogId, // Resource ID
|
|
||||||
int TitleId); // To get tital
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
CBasePropertyPage(CHAR *pName,
|
|
||||||
LPUNKNOWN pUnk,
|
|
||||||
int DialogId,
|
|
||||||
int TitleId);
|
|
||||||
#endif
|
|
||||||
virtual ~CBasePropertyPage() { };
|
|
||||||
DECLARE_IUNKNOWN
|
|
||||||
|
|
||||||
// Override these virtual methods
|
|
||||||
|
|
||||||
virtual HRESULT OnConnect(IUnknown *pUnknown) { return NOERROR; };
|
|
||||||
virtual HRESULT OnDisconnect() { return NOERROR; };
|
|
||||||
virtual HRESULT OnActivate() { return NOERROR; };
|
|
||||||
virtual HRESULT OnDeactivate() { return NOERROR; };
|
|
||||||
virtual HRESULT OnApplyChanges() { return NOERROR; };
|
|
||||||
virtual INT_PTR OnReceiveMessage(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
|
|
||||||
|
|
||||||
// These implement an IPropertyPage interface
|
|
||||||
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,void **ppv);
|
|
||||||
STDMETHODIMP_(ULONG) NonDelegatingRelease();
|
|
||||||
STDMETHODIMP_(ULONG) NonDelegatingAddRef();
|
|
||||||
STDMETHODIMP SetPageSite(LPPROPERTYPAGESITE pPageSite);
|
|
||||||
STDMETHODIMP Activate(HWND hwndParent,LPCRECT prect,BOOL fModal);
|
|
||||||
STDMETHODIMP Deactivate(void);
|
|
||||||
STDMETHODIMP GetPageInfo(LPPROPPAGEINFO pPageInfo);
|
|
||||||
STDMETHODIMP SetObjects(ULONG cObjects, LPUNKNOWN *ppUnk);
|
|
||||||
STDMETHODIMP Show(UINT nCmdShow);
|
|
||||||
STDMETHODIMP Move(LPCRECT prect);
|
|
||||||
STDMETHODIMP IsPageDirty(void) { return m_bDirty ? S_OK : S_FALSE; }
|
|
||||||
STDMETHODIMP Apply(void);
|
|
||||||
STDMETHODIMP Help(LPCWSTR lpszHelpDir) { return E_NOTIMPL; }
|
|
||||||
STDMETHODIMP TranslateAccelerator(LPMSG lpMsg) { return E_NOTIMPL; }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __CPROP__
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,919 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: CtlUtil.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
// Base classes implementing IDispatch parsing for the basic control dual
|
|
||||||
// interfaces. Derive from these and implement just the custom method and
|
|
||||||
// property methods. We also implement CPosPassThru that can be used by
|
|
||||||
// renderers and transforms to pass by IMediaPosition and IMediaSeeking
|
|
||||||
|
|
||||||
#ifndef __CTLUTIL__
|
|
||||||
#define __CTLUTIL__
|
|
||||||
|
|
||||||
// OLE Automation has different ideas of TRUE and FALSE
|
|
||||||
|
|
||||||
#define OATRUE (-1)
|
|
||||||
#define OAFALSE (0)
|
|
||||||
|
|
||||||
|
|
||||||
// It's possible that we could replace this class with CreateStdDispatch
|
|
||||||
|
|
||||||
class CBaseDispatch
|
|
||||||
{
|
|
||||||
ITypeInfo * m_pti;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CBaseDispatch() : m_pti(NULL) {}
|
|
||||||
~CBaseDispatch();
|
|
||||||
|
|
||||||
/* IDispatch methods */
|
|
||||||
STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetTypeInfo(
|
|
||||||
REFIID riid,
|
|
||||||
UINT itinfo,
|
|
||||||
LCID lcid,
|
|
||||||
ITypeInfo ** pptinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetIDsOfNames(
|
|
||||||
REFIID riid,
|
|
||||||
OLECHAR ** rgszNames,
|
|
||||||
UINT cNames,
|
|
||||||
LCID lcid,
|
|
||||||
DISPID * rgdispid);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class AM_NOVTABLE CMediaControl :
|
|
||||||
public IMediaControl,
|
|
||||||
public CUnknown
|
|
||||||
{
|
|
||||||
CBaseDispatch m_basedisp;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CMediaControl(const TCHAR *, LPUNKNOWN);
|
|
||||||
|
|
||||||
DECLARE_IUNKNOWN
|
|
||||||
|
|
||||||
// override this to publicise our interfaces
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
|
|
||||||
|
|
||||||
/* IDispatch methods */
|
|
||||||
STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetTypeInfo(
|
|
||||||
UINT itinfo,
|
|
||||||
LCID lcid,
|
|
||||||
ITypeInfo ** pptinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetIDsOfNames(
|
|
||||||
REFIID riid,
|
|
||||||
OLECHAR ** rgszNames,
|
|
||||||
UINT cNames,
|
|
||||||
LCID lcid,
|
|
||||||
DISPID * rgdispid);
|
|
||||||
|
|
||||||
STDMETHODIMP Invoke(
|
|
||||||
DISPID dispidMember,
|
|
||||||
REFIID riid,
|
|
||||||
LCID lcid,
|
|
||||||
WORD wFlags,
|
|
||||||
DISPPARAMS * pdispparams,
|
|
||||||
VARIANT * pvarResult,
|
|
||||||
EXCEPINFO * pexcepinfo,
|
|
||||||
UINT * puArgErr);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class AM_NOVTABLE CMediaEvent :
|
|
||||||
public IMediaEventEx,
|
|
||||||
public CUnknown
|
|
||||||
{
|
|
||||||
CBaseDispatch m_basedisp;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CMediaEvent(const TCHAR *, LPUNKNOWN);
|
|
||||||
|
|
||||||
DECLARE_IUNKNOWN
|
|
||||||
|
|
||||||
// override this to publicise our interfaces
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
|
|
||||||
|
|
||||||
/* IDispatch methods */
|
|
||||||
STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetTypeInfo(
|
|
||||||
UINT itinfo,
|
|
||||||
LCID lcid,
|
|
||||||
ITypeInfo ** pptinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetIDsOfNames(
|
|
||||||
REFIID riid,
|
|
||||||
OLECHAR ** rgszNames,
|
|
||||||
UINT cNames,
|
|
||||||
LCID lcid,
|
|
||||||
DISPID * rgdispid);
|
|
||||||
|
|
||||||
STDMETHODIMP Invoke(
|
|
||||||
DISPID dispidMember,
|
|
||||||
REFIID riid,
|
|
||||||
LCID lcid,
|
|
||||||
WORD wFlags,
|
|
||||||
DISPPARAMS * pdispparams,
|
|
||||||
VARIANT * pvarResult,
|
|
||||||
EXCEPINFO * pexcepinfo,
|
|
||||||
UINT * puArgErr);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class AM_NOVTABLE CMediaPosition :
|
|
||||||
public IMediaPosition,
|
|
||||||
public CUnknown
|
|
||||||
{
|
|
||||||
CBaseDispatch m_basedisp;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CMediaPosition(const TCHAR *, LPUNKNOWN);
|
|
||||||
CMediaPosition(const TCHAR *, LPUNKNOWN, HRESULT *phr);
|
|
||||||
|
|
||||||
DECLARE_IUNKNOWN
|
|
||||||
|
|
||||||
// override this to publicise our interfaces
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
|
|
||||||
|
|
||||||
/* IDispatch methods */
|
|
||||||
STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetTypeInfo(
|
|
||||||
UINT itinfo,
|
|
||||||
LCID lcid,
|
|
||||||
ITypeInfo ** pptinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetIDsOfNames(
|
|
||||||
REFIID riid,
|
|
||||||
OLECHAR ** rgszNames,
|
|
||||||
UINT cNames,
|
|
||||||
LCID lcid,
|
|
||||||
DISPID * rgdispid);
|
|
||||||
|
|
||||||
STDMETHODIMP Invoke(
|
|
||||||
DISPID dispidMember,
|
|
||||||
REFIID riid,
|
|
||||||
LCID lcid,
|
|
||||||
WORD wFlags,
|
|
||||||
DISPPARAMS * pdispparams,
|
|
||||||
VARIANT * pvarResult,
|
|
||||||
EXCEPINFO * pexcepinfo,
|
|
||||||
UINT * puArgErr);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// OA-compatibility means that we must use double as the RefTime value,
|
|
||||||
// and REFERENCE_TIME (essentially a LONGLONG) within filters.
|
|
||||||
// this class converts between the two
|
|
||||||
|
|
||||||
class COARefTime : public CRefTime {
|
|
||||||
public:
|
|
||||||
|
|
||||||
COARefTime() {
|
|
||||||
};
|
|
||||||
|
|
||||||
COARefTime(CRefTime t)
|
|
||||||
: CRefTime(t)
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
COARefTime(REFERENCE_TIME t)
|
|
||||||
: CRefTime(t)
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
COARefTime(double d) {
|
|
||||||
m_time = (LONGLONG) (d * 10000000);
|
|
||||||
};
|
|
||||||
|
|
||||||
operator double() {
|
|
||||||
return double(m_time) / 10000000;
|
|
||||||
};
|
|
||||||
|
|
||||||
operator REFERENCE_TIME() {
|
|
||||||
return m_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
COARefTime& operator=(const double& rd) {
|
|
||||||
m_time = (LONGLONG) (rd * 10000000);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
COARefTime& operator=(const REFERENCE_TIME& rt) {
|
|
||||||
m_time = rt;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BOOL operator==(const COARefTime& rt)
|
|
||||||
{
|
|
||||||
return m_time == rt.m_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline BOOL operator!=(const COARefTime& rt)
|
|
||||||
{
|
|
||||||
return m_time != rt.m_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline BOOL operator < (const COARefTime& rt)
|
|
||||||
{
|
|
||||||
return m_time < rt.m_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline BOOL operator > (const COARefTime& rt)
|
|
||||||
{
|
|
||||||
return m_time > rt.m_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline BOOL operator >= (const COARefTime& rt)
|
|
||||||
{
|
|
||||||
return m_time >= rt.m_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline BOOL operator <= (const COARefTime& rt)
|
|
||||||
{
|
|
||||||
return m_time <= rt.m_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline COARefTime operator+(const COARefTime& rt)
|
|
||||||
{
|
|
||||||
return COARefTime(m_time + rt.m_time);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline COARefTime operator-(const COARefTime& rt)
|
|
||||||
{
|
|
||||||
return COARefTime(m_time - rt.m_time);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline COARefTime operator*(LONG l)
|
|
||||||
{
|
|
||||||
return COARefTime(m_time * l);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline COARefTime operator/(LONG l)
|
|
||||||
{
|
|
||||||
return COARefTime(m_time / l);
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Prevent bugs from constructing from LONG (which gets
|
|
||||||
// converted to double and then multiplied by 10000000
|
|
||||||
COARefTime(LONG);
|
|
||||||
int operator=(LONG);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// A utility class that handles IMediaPosition and IMediaSeeking on behalf
|
|
||||||
// of single-input pin renderers, or transform filters.
|
|
||||||
//
|
|
||||||
// Renderers will expose this from the filter; transform filters will
|
|
||||||
// expose it from the output pin and not the renderer.
|
|
||||||
//
|
|
||||||
// Create one of these, giving it your IPin* for your input pin, and delegate
|
|
||||||
// all IMediaPosition methods to it. It will query the input pin for
|
|
||||||
// IMediaPosition and respond appropriately.
|
|
||||||
//
|
|
||||||
// Call ForceRefresh if the pin connection changes.
|
|
||||||
//
|
|
||||||
// This class no longer caches the upstream IMediaPosition or IMediaSeeking
|
|
||||||
// it acquires it on each method call. This means ForceRefresh is not needed.
|
|
||||||
// The method is kept for source compatibility and to minimise the changes
|
|
||||||
// if we need to put it back later for performance reasons.
|
|
||||||
|
|
||||||
class CPosPassThru : public IMediaSeeking, public CMediaPosition
|
|
||||||
{
|
|
||||||
IPin *m_pPin;
|
|
||||||
|
|
||||||
HRESULT GetPeer(IMediaPosition **ppMP);
|
|
||||||
HRESULT GetPeerSeeking(IMediaSeeking **ppMS);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CPosPassThru(const TCHAR *, LPUNKNOWN, HRESULT*, IPin *);
|
|
||||||
DECLARE_IUNKNOWN
|
|
||||||
|
|
||||||
HRESULT ForceRefresh() {
|
|
||||||
return S_OK;
|
|
||||||
};
|
|
||||||
|
|
||||||
// override to return an accurate current position
|
|
||||||
virtual HRESULT GetMediaTime(LONGLONG *pStartTime,LONGLONG *pEndTime) {
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,void **ppv);
|
|
||||||
|
|
||||||
// IMediaSeeking methods
|
|
||||||
STDMETHODIMP GetCapabilities( DWORD * pCapabilities );
|
|
||||||
STDMETHODIMP CheckCapabilities( DWORD * pCapabilities );
|
|
||||||
STDMETHODIMP SetTimeFormat(const GUID * pFormat);
|
|
||||||
STDMETHODIMP GetTimeFormat(GUID *pFormat);
|
|
||||||
STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
|
|
||||||
STDMETHODIMP IsFormatSupported( const GUID * pFormat);
|
|
||||||
STDMETHODIMP QueryPreferredFormat( GUID *pFormat);
|
|
||||||
STDMETHODIMP ConvertTimeFormat(LONGLONG * pTarget, const GUID * pTargetFormat,
|
|
||||||
LONGLONG Source, const GUID * pSourceFormat );
|
|
||||||
STDMETHODIMP SetPositions( LONGLONG * pCurrent, DWORD CurrentFlags
|
|
||||||
, LONGLONG * pStop, DWORD StopFlags );
|
|
||||||
|
|
||||||
STDMETHODIMP GetPositions( LONGLONG * pCurrent, LONGLONG * pStop );
|
|
||||||
STDMETHODIMP GetCurrentPosition( LONGLONG * pCurrent );
|
|
||||||
STDMETHODIMP GetStopPosition( LONGLONG * pStop );
|
|
||||||
STDMETHODIMP SetRate( double dRate);
|
|
||||||
STDMETHODIMP GetRate( double * pdRate);
|
|
||||||
STDMETHODIMP GetDuration( LONGLONG *pDuration);
|
|
||||||
STDMETHODIMP GetAvailable( LONGLONG *pEarliest, LONGLONG *pLatest );
|
|
||||||
STDMETHODIMP GetPreroll( LONGLONG *pllPreroll );
|
|
||||||
|
|
||||||
// IMediaPosition properties
|
|
||||||
STDMETHODIMP get_Duration(REFTIME * plength);
|
|
||||||
STDMETHODIMP put_CurrentPosition(REFTIME llTime);
|
|
||||||
STDMETHODIMP get_StopTime(REFTIME * pllTime);
|
|
||||||
STDMETHODIMP put_StopTime(REFTIME llTime);
|
|
||||||
STDMETHODIMP get_PrerollTime(REFTIME * pllTime);
|
|
||||||
STDMETHODIMP put_PrerollTime(REFTIME llTime);
|
|
||||||
STDMETHODIMP get_Rate(double * pdRate);
|
|
||||||
STDMETHODIMP put_Rate(double dRate);
|
|
||||||
STDMETHODIMP get_CurrentPosition(REFTIME * pllTime);
|
|
||||||
STDMETHODIMP CanSeekForward(LONG *pCanSeekForward);
|
|
||||||
STDMETHODIMP CanSeekBackward(LONG *pCanSeekBackward);
|
|
||||||
|
|
||||||
private:
|
|
||||||
HRESULT GetSeekingLongLong( HRESULT (__stdcall IMediaSeeking::*pMethod)( LONGLONG * ),
|
|
||||||
LONGLONG * pll );
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Adds the ability to return a current position
|
|
||||||
|
|
||||||
class CRendererPosPassThru : public CPosPassThru
|
|
||||||
{
|
|
||||||
CCritSec m_PositionLock; // Locks access to our position
|
|
||||||
LONGLONG m_StartMedia; // Start media time last seen
|
|
||||||
LONGLONG m_EndMedia; // And likewise the end media
|
|
||||||
BOOL m_bReset; // Have media times been set
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Used to help with passing media times through graph
|
|
||||||
|
|
||||||
CRendererPosPassThru(const TCHAR *, LPUNKNOWN, HRESULT*, IPin *);
|
|
||||||
HRESULT RegisterMediaTime(IMediaSample *pMediaSample);
|
|
||||||
HRESULT RegisterMediaTime(LONGLONG StartTime,LONGLONG EndTime);
|
|
||||||
HRESULT GetMediaTime(LONGLONG *pStartTime,LONGLONG *pEndTime);
|
|
||||||
HRESULT ResetMediaTime();
|
|
||||||
HRESULT EOS();
|
|
||||||
};
|
|
||||||
|
|
||||||
STDAPI CreatePosPassThru(
|
|
||||||
LPUNKNOWN pAgg,
|
|
||||||
BOOL bRenderer,
|
|
||||||
IPin *pPin,
|
|
||||||
IUnknown **ppPassThru
|
|
||||||
);
|
|
||||||
|
|
||||||
// A class that handles the IDispatch part of IBasicAudio and leaves the
|
|
||||||
// properties and methods themselves pure virtual.
|
|
||||||
|
|
||||||
class AM_NOVTABLE CBasicAudio : public IBasicAudio, public CUnknown
|
|
||||||
{
|
|
||||||
CBaseDispatch m_basedisp;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CBasicAudio(const TCHAR *, LPUNKNOWN);
|
|
||||||
|
|
||||||
DECLARE_IUNKNOWN
|
|
||||||
|
|
||||||
// override this to publicise our interfaces
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
|
|
||||||
|
|
||||||
/* IDispatch methods */
|
|
||||||
STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetTypeInfo(
|
|
||||||
UINT itinfo,
|
|
||||||
LCID lcid,
|
|
||||||
ITypeInfo ** pptinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetIDsOfNames(
|
|
||||||
REFIID riid,
|
|
||||||
OLECHAR ** rgszNames,
|
|
||||||
UINT cNames,
|
|
||||||
LCID lcid,
|
|
||||||
DISPID * rgdispid);
|
|
||||||
|
|
||||||
STDMETHODIMP Invoke(
|
|
||||||
DISPID dispidMember,
|
|
||||||
REFIID riid,
|
|
||||||
LCID lcid,
|
|
||||||
WORD wFlags,
|
|
||||||
DISPPARAMS * pdispparams,
|
|
||||||
VARIANT * pvarResult,
|
|
||||||
EXCEPINFO * pexcepinfo,
|
|
||||||
UINT * puArgErr);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// A class that handles the IDispatch part of IBasicVideo and leaves the
|
|
||||||
// properties and methods themselves pure virtual.
|
|
||||||
|
|
||||||
class AM_NOVTABLE CBaseBasicVideo : public IBasicVideo2, public CUnknown
|
|
||||||
{
|
|
||||||
CBaseDispatch m_basedisp;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CBaseBasicVideo(const TCHAR *, LPUNKNOWN);
|
|
||||||
|
|
||||||
DECLARE_IUNKNOWN
|
|
||||||
|
|
||||||
// override this to publicise our interfaces
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
|
|
||||||
|
|
||||||
/* IDispatch methods */
|
|
||||||
STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetTypeInfo(
|
|
||||||
UINT itinfo,
|
|
||||||
LCID lcid,
|
|
||||||
ITypeInfo ** pptinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetIDsOfNames(
|
|
||||||
REFIID riid,
|
|
||||||
OLECHAR ** rgszNames,
|
|
||||||
UINT cNames,
|
|
||||||
LCID lcid,
|
|
||||||
DISPID * rgdispid);
|
|
||||||
|
|
||||||
STDMETHODIMP Invoke(
|
|
||||||
DISPID dispidMember,
|
|
||||||
REFIID riid,
|
|
||||||
LCID lcid,
|
|
||||||
WORD wFlags,
|
|
||||||
DISPPARAMS * pdispparams,
|
|
||||||
VARIANT * pvarResult,
|
|
||||||
EXCEPINFO * pexcepinfo,
|
|
||||||
UINT * puArgErr);
|
|
||||||
|
|
||||||
STDMETHODIMP GetPreferredAspectRatio(
|
|
||||||
long *plAspectX,
|
|
||||||
long *plAspectY)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// A class that handles the IDispatch part of IVideoWindow and leaves the
|
|
||||||
// properties and methods themselves pure virtual.
|
|
||||||
|
|
||||||
class AM_NOVTABLE CBaseVideoWindow : public IVideoWindow, public CUnknown
|
|
||||||
{
|
|
||||||
CBaseDispatch m_basedisp;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CBaseVideoWindow(const TCHAR *, LPUNKNOWN);
|
|
||||||
|
|
||||||
DECLARE_IUNKNOWN
|
|
||||||
|
|
||||||
// override this to publicise our interfaces
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
|
|
||||||
|
|
||||||
/* IDispatch methods */
|
|
||||||
STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetTypeInfo(
|
|
||||||
UINT itinfo,
|
|
||||||
LCID lcid,
|
|
||||||
ITypeInfo ** pptinfo);
|
|
||||||
|
|
||||||
STDMETHODIMP GetIDsOfNames(
|
|
||||||
REFIID riid,
|
|
||||||
OLECHAR ** rgszNames,
|
|
||||||
UINT cNames,
|
|
||||||
LCID lcid,
|
|
||||||
DISPID * rgdispid);
|
|
||||||
|
|
||||||
STDMETHODIMP Invoke(
|
|
||||||
DISPID dispidMember,
|
|
||||||
REFIID riid,
|
|
||||||
LCID lcid,
|
|
||||||
WORD wFlags,
|
|
||||||
DISPPARAMS * pdispparams,
|
|
||||||
VARIANT * pvarResult,
|
|
||||||
EXCEPINFO * pexcepinfo,
|
|
||||||
UINT * puArgErr);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// abstract class to help source filters with their implementation
|
|
||||||
// of IMediaPosition. Derive from this and set the duration (and stop
|
|
||||||
// position). Also override NotifyChange to do something when the properties
|
|
||||||
// change.
|
|
||||||
|
|
||||||
class AM_NOVTABLE CSourcePosition : public CMediaPosition
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
CSourcePosition(const TCHAR *, LPUNKNOWN, HRESULT*, CCritSec *);
|
|
||||||
|
|
||||||
// IMediaPosition methods
|
|
||||||
STDMETHODIMP get_Duration(REFTIME * plength);
|
|
||||||
STDMETHODIMP put_CurrentPosition(REFTIME llTime);
|
|
||||||
STDMETHODIMP get_StopTime(REFTIME * pllTime);
|
|
||||||
STDMETHODIMP put_StopTime(REFTIME llTime);
|
|
||||||
STDMETHODIMP get_PrerollTime(REFTIME * pllTime);
|
|
||||||
STDMETHODIMP put_PrerollTime(REFTIME llTime);
|
|
||||||
STDMETHODIMP get_Rate(double * pdRate);
|
|
||||||
STDMETHODIMP put_Rate(double dRate);
|
|
||||||
STDMETHODIMP CanSeekForward(LONG *pCanSeekForward);
|
|
||||||
STDMETHODIMP CanSeekBackward(LONG *pCanSeekBackward);
|
|
||||||
|
|
||||||
// override if you can return the data you are actually working on
|
|
||||||
STDMETHODIMP get_CurrentPosition(REFTIME * pllTime) {
|
|
||||||
return E_NOTIMPL;
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// we call this to notify changes. Override to handle them
|
|
||||||
virtual HRESULT ChangeStart() PURE;
|
|
||||||
virtual HRESULT ChangeStop() PURE;
|
|
||||||
virtual HRESULT ChangeRate() PURE;
|
|
||||||
|
|
||||||
COARefTime m_Duration;
|
|
||||||
COARefTime m_Start;
|
|
||||||
COARefTime m_Stop;
|
|
||||||
double m_Rate;
|
|
||||||
|
|
||||||
CCritSec * m_pLock;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AM_NOVTABLE CSourceSeeking :
|
|
||||||
public IMediaSeeking,
|
|
||||||
public CUnknown
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
DECLARE_IUNKNOWN;
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
|
|
||||||
|
|
||||||
// IMediaSeeking methods
|
|
||||||
|
|
||||||
STDMETHODIMP IsFormatSupported(const GUID * pFormat);
|
|
||||||
STDMETHODIMP QueryPreferredFormat(GUID *pFormat);
|
|
||||||
STDMETHODIMP SetTimeFormat(const GUID * pFormat);
|
|
||||||
STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
|
|
||||||
STDMETHODIMP GetTimeFormat(GUID *pFormat);
|
|
||||||
STDMETHODIMP GetDuration(LONGLONG *pDuration);
|
|
||||||
STDMETHODIMP GetStopPosition(LONGLONG *pStop);
|
|
||||||
STDMETHODIMP GetCurrentPosition(LONGLONG *pCurrent);
|
|
||||||
STDMETHODIMP GetCapabilities( DWORD * pCapabilities );
|
|
||||||
STDMETHODIMP CheckCapabilities( DWORD * pCapabilities );
|
|
||||||
STDMETHODIMP ConvertTimeFormat( LONGLONG * pTarget, const GUID * pTargetFormat,
|
|
||||||
LONGLONG Source, const GUID * pSourceFormat );
|
|
||||||
|
|
||||||
STDMETHODIMP SetPositions( LONGLONG * pCurrent, DWORD CurrentFlags
|
|
||||||
, LONGLONG * pStop, DWORD StopFlags );
|
|
||||||
|
|
||||||
STDMETHODIMP GetPositions( LONGLONG * pCurrent, LONGLONG * pStop );
|
|
||||||
|
|
||||||
STDMETHODIMP GetAvailable( LONGLONG * pEarliest, LONGLONG * pLatest );
|
|
||||||
STDMETHODIMP SetRate( double dRate);
|
|
||||||
STDMETHODIMP GetRate( double * pdRate);
|
|
||||||
STDMETHODIMP GetPreroll(LONGLONG *pPreroll);
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// ctor
|
|
||||||
CSourceSeeking(const TCHAR *, LPUNKNOWN, HRESULT*, CCritSec *);
|
|
||||||
|
|
||||||
// we call this to notify changes. Override to handle them
|
|
||||||
virtual HRESULT ChangeStart() PURE;
|
|
||||||
virtual HRESULT ChangeStop() PURE;
|
|
||||||
virtual HRESULT ChangeRate() PURE;
|
|
||||||
|
|
||||||
CRefTime m_rtDuration; // length of stream
|
|
||||||
CRefTime m_rtStart; // source will start here
|
|
||||||
CRefTime m_rtStop; // source will stop here
|
|
||||||
double m_dRateSeeking;
|
|
||||||
|
|
||||||
// seeking capabilities
|
|
||||||
DWORD m_dwSeekingCaps;
|
|
||||||
|
|
||||||
CCritSec * m_pLock;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Base classes supporting Deferred commands.
|
|
||||||
|
|
||||||
// Deferred commands are queued by calls to methods on the IQueueCommand
|
|
||||||
// interface, exposed by the filtergraph and by some filters. A successful
|
|
||||||
// call to one of these methods will return an IDeferredCommand interface
|
|
||||||
// representing the queued command.
|
|
||||||
//
|
|
||||||
// A CDeferredCommand object represents a single deferred command, and exposes
|
|
||||||
// the IDeferredCommand interface as well as other methods permitting time
|
|
||||||
// checks and actual execution. It contains a reference to the CCommandQueue
|
|
||||||
// object on which it is queued.
|
|
||||||
//
|
|
||||||
// CCommandQueue is a base class providing a queue of CDeferredCommand
|
|
||||||
// objects, and methods to add, remove, check status and invoke the queued
|
|
||||||
// commands. A CCommandQueue object would be part of an object that
|
|
||||||
// implemented IQueueCommand.
|
|
||||||
|
|
||||||
class CCmdQueue;
|
|
||||||
|
|
||||||
// take a copy of the params and store them. Release any allocated
|
|
||||||
// memory in destructor
|
|
||||||
|
|
||||||
class CDispParams : public DISPPARAMS
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CDispParams(UINT nArgs, VARIANT* pArgs, HRESULT *phr = NULL);
|
|
||||||
~CDispParams();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// CDeferredCommand lifetime is controlled by refcounts. Caller of
|
|
||||||
// InvokeAt.. gets a refcounted interface pointer, and the CCmdQueue
|
|
||||||
// object also holds a refcount on us. Calling Cancel or Invoke takes
|
|
||||||
// us off the CCmdQueue and thus reduces the refcount by 1. Once taken
|
|
||||||
// off the queue we cannot be put back on the queue.
|
|
||||||
|
|
||||||
class CDeferredCommand
|
|
||||||
: public CUnknown,
|
|
||||||
public IDeferredCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
CDeferredCommand(
|
|
||||||
CCmdQueue * pQ,
|
|
||||||
LPUNKNOWN pUnk, // aggregation outer unk
|
|
||||||
HRESULT * phr,
|
|
||||||
LPUNKNOWN pUnkExecutor, // object that will execute this cmd
|
|
||||||
REFTIME time,
|
|
||||||
GUID* iid,
|
|
||||||
long dispidMethod,
|
|
||||||
short wFlags,
|
|
||||||
long cArgs,
|
|
||||||
VARIANT* pDispParams,
|
|
||||||
VARIANT* pvarResult,
|
|
||||||
short* puArgErr,
|
|
||||||
BOOL bStream
|
|
||||||
);
|
|
||||||
|
|
||||||
DECLARE_IUNKNOWN
|
|
||||||
|
|
||||||
// override this to publicise our interfaces
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
|
|
||||||
|
|
||||||
// IDeferredCommand methods
|
|
||||||
STDMETHODIMP Cancel();
|
|
||||||
STDMETHODIMP Confidence(
|
|
||||||
LONG* pConfidence);
|
|
||||||
STDMETHODIMP Postpone(
|
|
||||||
REFTIME newtime);
|
|
||||||
STDMETHODIMP GetHResult(
|
|
||||||
HRESULT* phrResult);
|
|
||||||
|
|
||||||
// other public methods
|
|
||||||
|
|
||||||
HRESULT Invoke();
|
|
||||||
|
|
||||||
// access methods
|
|
||||||
|
|
||||||
// returns TRUE if streamtime, FALSE if presentation time
|
|
||||||
BOOL IsStreamTime() {
|
|
||||||
return m_bStream;
|
|
||||||
};
|
|
||||||
|
|
||||||
CRefTime GetTime() {
|
|
||||||
return m_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
REFIID GetIID() {
|
|
||||||
return *m_iid;
|
|
||||||
};
|
|
||||||
|
|
||||||
long GetMethod() {
|
|
||||||
return m_dispidMethod;
|
|
||||||
};
|
|
||||||
|
|
||||||
short GetFlags() {
|
|
||||||
return m_wFlags;
|
|
||||||
};
|
|
||||||
|
|
||||||
DISPPARAMS* GetParams() {
|
|
||||||
return &m_DispParams;
|
|
||||||
};
|
|
||||||
|
|
||||||
VARIANT* GetResult() {
|
|
||||||
return m_pvarResult;
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
CCmdQueue* m_pQueue;
|
|
||||||
|
|
||||||
// pUnk for the interface that we will execute the command on
|
|
||||||
LPUNKNOWN m_pUnk;
|
|
||||||
|
|
||||||
// stored command data
|
|
||||||
REFERENCE_TIME m_time;
|
|
||||||
GUID* m_iid;
|
|
||||||
long m_dispidMethod;
|
|
||||||
short m_wFlags;
|
|
||||||
VARIANT* m_pvarResult;
|
|
||||||
BOOL m_bStream;
|
|
||||||
CDispParams m_DispParams;
|
|
||||||
DISPID m_DispId; // For get and put
|
|
||||||
|
|
||||||
// we use this for ITypeInfo access
|
|
||||||
CBaseDispatch m_Dispatch;
|
|
||||||
|
|
||||||
// save retval here
|
|
||||||
HRESULT m_hrResult;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// a list of CDeferredCommand objects. this is a base class providing
|
|
||||||
// the basics of access to the list. If you want to use CDeferredCommand
|
|
||||||
// objects then your queue needs to be derived from this class.
|
|
||||||
|
|
||||||
class AM_NOVTABLE CCmdQueue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CCmdQueue();
|
|
||||||
virtual ~CCmdQueue();
|
|
||||||
|
|
||||||
// returns a new CDeferredCommand object that will be initialised with
|
|
||||||
// the parameters and will be added to the queue during construction.
|
|
||||||
// returns S_OK if successfully created otherwise an error and
|
|
||||||
// no object has been queued.
|
|
||||||
virtual HRESULT New(
|
|
||||||
CDeferredCommand **ppCmd,
|
|
||||||
LPUNKNOWN pUnk,
|
|
||||||
REFTIME time,
|
|
||||||
GUID* iid,
|
|
||||||
long dispidMethod,
|
|
||||||
short wFlags,
|
|
||||||
long cArgs,
|
|
||||||
VARIANT* pDispParams,
|
|
||||||
VARIANT* pvarResult,
|
|
||||||
short* puArgErr,
|
|
||||||
BOOL bStream
|
|
||||||
);
|
|
||||||
|
|
||||||
// called by the CDeferredCommand object to add and remove itself
|
|
||||||
// from the queue
|
|
||||||
virtual HRESULT Insert(CDeferredCommand* pCmd);
|
|
||||||
virtual HRESULT Remove(CDeferredCommand* pCmd);
|
|
||||||
|
|
||||||
// Command-Due Checking
|
|
||||||
//
|
|
||||||
// There are two schemes of synchronisation: coarse and accurate. In
|
|
||||||
// coarse mode, you wait till the time arrives and then execute the cmd.
|
|
||||||
// In accurate mode, you wait until you are processing the sample that
|
|
||||||
// will appear at the time, and then execute the command. It's up to the
|
|
||||||
// filter which one it will implement. The filtergraph will always
|
|
||||||
// implement coarse mode for commands queued at the filtergraph.
|
|
||||||
//
|
|
||||||
// If you want coarse sync, you probably want to wait until there is a
|
|
||||||
// command due, and then execute it. You can do this by calling
|
|
||||||
// GetDueCommand. If you have several things to wait for, get the
|
|
||||||
// event handle from GetDueHandle() and when this is signalled then call
|
|
||||||
// GetDueCommand. Stream time will only advance between calls to Run and
|
|
||||||
// EndRun. Note that to avoid an extra thread there is no guarantee that
|
|
||||||
// if the handle is set there will be a command ready. Each time the
|
|
||||||
// event is signalled, call GetDueCommand (probably with a 0 timeout);
|
|
||||||
// This may return E_ABORT.
|
|
||||||
//
|
|
||||||
// If you want accurate sync, you must call GetCommandDueFor, passing
|
|
||||||
// as a parameter the stream time of the samples you are about to process.
|
|
||||||
// This will return:
|
|
||||||
// -- a stream-time command due at or before that stream time
|
|
||||||
// -- a presentation-time command due at or before the
|
|
||||||
// time that stream time will be presented (only between Run
|
|
||||||
// and EndRun calls, since outside of this, the mapping from
|
|
||||||
// stream time to presentation time is not known.
|
|
||||||
// -- any presentation-time command due now.
|
|
||||||
// This means that if you want accurate synchronisation on samples that
|
|
||||||
// might be processed during Paused mode, you need to use
|
|
||||||
// stream-time commands.
|
|
||||||
//
|
|
||||||
// In all cases, commands remain queued until Invoked or Cancelled. The
|
|
||||||
// setting and resetting of the event handle is managed entirely by this
|
|
||||||
// queue object.
|
|
||||||
|
|
||||||
// set the clock used for timing
|
|
||||||
virtual HRESULT SetSyncSource(IReferenceClock*);
|
|
||||||
|
|
||||||
// switch to run mode. Streamtime to Presentation time mapping known.
|
|
||||||
virtual HRESULT Run(REFERENCE_TIME tStreamTimeOffset);
|
|
||||||
|
|
||||||
// switch to Stopped or Paused mode. Time mapping not known.
|
|
||||||
virtual HRESULT EndRun();
|
|
||||||
|
|
||||||
// return a pointer to the next due command. Blocks for msTimeout
|
|
||||||
// milliseconds until there is a due command.
|
|
||||||
// Stream-time commands will only become due between Run and Endrun calls.
|
|
||||||
// The command remains queued until invoked or cancelled.
|
|
||||||
// Returns E_ABORT if timeout occurs, otherwise S_OK (or other error).
|
|
||||||
// Returns an AddRef-ed object
|
|
||||||
virtual HRESULT GetDueCommand(CDeferredCommand ** ppCmd, long msTimeout);
|
|
||||||
|
|
||||||
// return the event handle that will be signalled whenever
|
|
||||||
// there are deferred commands due for execution (when GetDueCommand
|
|
||||||
// will not block).
|
|
||||||
HANDLE GetDueHandle() {
|
|
||||||
return HANDLE(m_evDue);
|
|
||||||
};
|
|
||||||
|
|
||||||
// return a pointer to a command that will be due for a given time.
|
|
||||||
// Pass in a stream time here. The stream time offset will be passed
|
|
||||||
// in via the Run method.
|
|
||||||
// Commands remain queued until invoked or cancelled.
|
|
||||||
// This method will not block. It will report VFW_E_NOT_FOUND if there
|
|
||||||
// are no commands due yet.
|
|
||||||
// Returns an AddRef-ed object
|
|
||||||
virtual HRESULT GetCommandDueFor(REFERENCE_TIME tStream, CDeferredCommand**ppCmd);
|
|
||||||
|
|
||||||
// check if a given time is due (TRUE if it is due yet)
|
|
||||||
BOOL CheckTime(CRefTime time, BOOL bStream) {
|
|
||||||
|
|
||||||
// if no clock, nothing is due!
|
|
||||||
if (!m_pClock) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// stream time
|
|
||||||
if (bStream) {
|
|
||||||
|
|
||||||
// not valid if not running
|
|
||||||
if (!m_bRunning) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
// add on known stream time offset to get presentation time
|
|
||||||
time += m_StreamTimeOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
CRefTime Now;
|
|
||||||
m_pClock->GetTime((REFERENCE_TIME*)&Now);
|
|
||||||
return (time <= Now);
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// protect access to lists etc
|
|
||||||
CCritSec m_Lock;
|
|
||||||
|
|
||||||
// commands queued in presentation time are stored here
|
|
||||||
CGenericList<CDeferredCommand> m_listPresentation;
|
|
||||||
|
|
||||||
// commands queued in stream time are stored here
|
|
||||||
CGenericList<CDeferredCommand> m_listStream;
|
|
||||||
|
|
||||||
// set when any commands are due
|
|
||||||
CAMEvent m_evDue;
|
|
||||||
|
|
||||||
// creates an advise for the earliest time required, if any
|
|
||||||
void SetTimeAdvise(void);
|
|
||||||
|
|
||||||
// advise id from reference clock (0 if no outstanding advise)
|
|
||||||
DWORD_PTR m_dwAdvise;
|
|
||||||
|
|
||||||
// advise time is for this presentation time
|
|
||||||
CRefTime m_tCurrentAdvise;
|
|
||||||
|
|
||||||
// the reference clock we are using (addrefed)
|
|
||||||
IReferenceClock* m_pClock;
|
|
||||||
|
|
||||||
// true when running
|
|
||||||
BOOL m_bRunning;
|
|
||||||
|
|
||||||
// contains stream time offset when m_bRunning is true
|
|
||||||
CRefTime m_StreamTimeOffset;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __CTLUTIL__
|
|
|
@ -1,129 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: DDMM.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - implements routines for using DirectDraw
|
|
||||||
// on a multimonitor system.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
#include <ddraw.h>
|
|
||||||
#include "ddmm.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FindDeviceCallback
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
LPSTR szDevice;
|
|
||||||
GUID* lpGUID;
|
|
||||||
GUID GUID;
|
|
||||||
BOOL fFound;
|
|
||||||
} FindDeviceData;
|
|
||||||
|
|
||||||
BOOL CALLBACK FindDeviceCallback(GUID* lpGUID, LPSTR szName, LPSTR szDevice, LPVOID lParam)
|
|
||||||
{
|
|
||||||
FindDeviceData *p = (FindDeviceData*)lParam;
|
|
||||||
|
|
||||||
if (lstrcmpiA(p->szDevice, szDevice) == 0) {
|
|
||||||
if (lpGUID) {
|
|
||||||
p->GUID = *lpGUID;
|
|
||||||
p->lpGUID = &p->GUID;
|
|
||||||
} else {
|
|
||||||
p->lpGUID = NULL;
|
|
||||||
}
|
|
||||||
p->fFound = TRUE;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOL CALLBACK FindDeviceCallbackEx(GUID* lpGUID, LPSTR szName, LPSTR szDevice, LPVOID lParam, HMONITOR hMonitor)
|
|
||||||
{
|
|
||||||
FindDeviceData *p = (FindDeviceData*)lParam;
|
|
||||||
|
|
||||||
if (lstrcmpiA(p->szDevice, szDevice) == 0) {
|
|
||||||
if (lpGUID) {
|
|
||||||
p->GUID = *lpGUID;
|
|
||||||
p->lpGUID = &p->GUID;
|
|
||||||
} else {
|
|
||||||
p->lpGUID = NULL;
|
|
||||||
}
|
|
||||||
p->fFound = TRUE;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DirectDrawCreateFromDevice
|
|
||||||
*
|
|
||||||
* create a DirectDraw object for a particular device
|
|
||||||
*/
|
|
||||||
IDirectDraw * DirectDrawCreateFromDevice(LPSTR szDevice, PDRAWCREATE DirectDrawCreateP, PDRAWENUM DirectDrawEnumerateP)
|
|
||||||
{
|
|
||||||
IDirectDraw* pdd = NULL;
|
|
||||||
FindDeviceData find;
|
|
||||||
|
|
||||||
if (szDevice == NULL) {
|
|
||||||
DirectDrawCreateP(NULL, &pdd, NULL);
|
|
||||||
return pdd;
|
|
||||||
}
|
|
||||||
|
|
||||||
find.szDevice = szDevice;
|
|
||||||
find.fFound = FALSE;
|
|
||||||
DirectDrawEnumerateP(FindDeviceCallback, (LPVOID)&find);
|
|
||||||
|
|
||||||
if (find.fFound)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// In 4bpp mode the following DDraw call causes a message box to be popped
|
|
||||||
// up by DDraw (!?!). It's DDraw's fault, but we don't like it. So we
|
|
||||||
// make sure it doesn't happen.
|
|
||||||
//
|
|
||||||
UINT ErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
|
||||||
DirectDrawCreateP(find.lpGUID, &pdd, NULL);
|
|
||||||
SetErrorMode(ErrorMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pdd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DirectDrawCreateFromDeviceEx
|
|
||||||
*
|
|
||||||
* create a DirectDraw object for a particular device
|
|
||||||
*/
|
|
||||||
IDirectDraw * DirectDrawCreateFromDeviceEx(LPSTR szDevice, PDRAWCREATE DirectDrawCreateP, LPDIRECTDRAWENUMERATEEXA DirectDrawEnumerateExP)
|
|
||||||
{
|
|
||||||
IDirectDraw* pdd = NULL;
|
|
||||||
FindDeviceData find;
|
|
||||||
|
|
||||||
if (szDevice == NULL) {
|
|
||||||
DirectDrawCreateP(NULL, &pdd, NULL);
|
|
||||||
return pdd;
|
|
||||||
}
|
|
||||||
|
|
||||||
find.szDevice = szDevice;
|
|
||||||
find.fFound = FALSE;
|
|
||||||
DirectDrawEnumerateExP(FindDeviceCallbackEx, (LPVOID)&find,
|
|
||||||
DDENUM_ATTACHEDSECONDARYDEVICES);
|
|
||||||
|
|
||||||
if (find.fFound)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// In 4bpp mode the following DDraw call causes a message box to be popped
|
|
||||||
// up by DDraw (!?!). It's DDraw's fault, but we don't like it. So we
|
|
||||||
// make sure it doesn't happen.
|
|
||||||
//
|
|
||||||
UINT ErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
|
||||||
DirectDrawCreateP(find.lpGUID, &pdd, NULL);
|
|
||||||
SetErrorMode(ErrorMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pdd;
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: DDMM.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - efines routines for using DirectDraw
|
|
||||||
// on a multimonitor system.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" { /* Assume C declarations for C++ */
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
// DDRAW.H might not include these
|
|
||||||
#ifndef DDENUM_ATTACHEDSECONDARYDEVICES
|
|
||||||
#define DDENUM_ATTACHEDSECONDARYDEVICES 0x00000001L
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef HRESULT (*PDRAWCREATE)(IID *,LPDIRECTDRAW *,LPUNKNOWN);
|
|
||||||
typedef HRESULT (*PDRAWENUM)(LPDDENUMCALLBACKA, LPVOID);
|
|
||||||
|
|
||||||
IDirectDraw * DirectDrawCreateFromDevice(LPSTR, PDRAWCREATE, PDRAWENUM);
|
|
||||||
IDirectDraw * DirectDrawCreateFromDeviceEx(LPSTR, PDRAWCREATE, LPDIRECTDRAWENUMERATEEXA);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif /* __cplusplus */
|
|
|
@ -1,333 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: DllEntry.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - implements classes used to support dll
|
|
||||||
// entry points for COM objects.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
#include <initguid.h>
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#ifdef UNICODE
|
|
||||||
#ifndef _UNICODE
|
|
||||||
#define _UNICODE
|
|
||||||
#endif // _UNICODE
|
|
||||||
#endif // UNICODE
|
|
||||||
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
extern CFactoryTemplate g_Templates[];
|
|
||||||
extern int g_cTemplates;
|
|
||||||
|
|
||||||
HINSTANCE g_hInst;
|
|
||||||
DWORD g_amPlatform; // VER_PLATFORM_WIN32_WINDOWS etc... (from GetVersionEx)
|
|
||||||
OSVERSIONINFO g_osInfo;
|
|
||||||
|
|
||||||
//
|
|
||||||
// an instance of this is created by the DLLGetClassObject entrypoint
|
|
||||||
// it uses the CFactoryTemplate object it is given to support the
|
|
||||||
// IClassFactory interface
|
|
||||||
|
|
||||||
class CClassFactory : public IClassFactory, public CBaseObject
|
|
||||||
{
|
|
||||||
|
|
||||||
private:
|
|
||||||
const CFactoryTemplate *const m_pTemplate;
|
|
||||||
|
|
||||||
ULONG m_cRef;
|
|
||||||
|
|
||||||
static int m_cLocked;
|
|
||||||
public:
|
|
||||||
CClassFactory(const CFactoryTemplate *);
|
|
||||||
|
|
||||||
// IUnknown
|
|
||||||
STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
|
|
||||||
STDMETHODIMP_(ULONG)AddRef();
|
|
||||||
STDMETHODIMP_(ULONG)Release();
|
|
||||||
|
|
||||||
// IClassFactory
|
|
||||||
STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **pv);
|
|
||||||
STDMETHODIMP LockServer(BOOL fLock);
|
|
||||||
|
|
||||||
// allow DLLGetClassObject to know about global server lock status
|
|
||||||
static BOOL IsLocked() {
|
|
||||||
return (m_cLocked > 0);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// process-wide dll locked state
|
|
||||||
int CClassFactory::m_cLocked = 0;
|
|
||||||
|
|
||||||
CClassFactory::CClassFactory(const CFactoryTemplate *pTemplate)
|
|
||||||
: CBaseObject(NAME("Class Factory"))
|
|
||||||
, m_cRef(0)
|
|
||||||
, m_pTemplate(pTemplate)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
STDMETHODIMP
|
|
||||||
CClassFactory::QueryInterface(REFIID riid,void **ppv)
|
|
||||||
{
|
|
||||||
CheckPointer(ppv,E_POINTER)
|
|
||||||
ValidateReadWritePtr(ppv,sizeof(PVOID));
|
|
||||||
*ppv = NULL;
|
|
||||||
|
|
||||||
// any interface on this object is the object pointer.
|
|
||||||
if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) {
|
|
||||||
*ppv = (LPVOID) this;
|
|
||||||
// AddRef returned interface pointer
|
|
||||||
((LPUNKNOWN) *ppv)->AddRef();
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ResultFromScode(E_NOINTERFACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
STDMETHODIMP_(ULONG)
|
|
||||||
CClassFactory::AddRef()
|
|
||||||
{
|
|
||||||
return ++m_cRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP_(ULONG)
|
|
||||||
CClassFactory::Release()
|
|
||||||
{
|
|
||||||
if (--m_cRef == 0) {
|
|
||||||
delete this;
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return m_cRef;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP
|
|
||||||
CClassFactory::CreateInstance(
|
|
||||||
LPUNKNOWN pUnkOuter,
|
|
||||||
REFIID riid,
|
|
||||||
void **pv)
|
|
||||||
{
|
|
||||||
CheckPointer(pv,E_POINTER)
|
|
||||||
ValidateReadWritePtr(pv,sizeof(void *));
|
|
||||||
|
|
||||||
/* Enforce the normal OLE rules regarding interfaces and delegation */
|
|
||||||
|
|
||||||
if (pUnkOuter != NULL) {
|
|
||||||
if (IsEqualIID(riid,IID_IUnknown) == FALSE) {
|
|
||||||
return ResultFromScode(E_NOINTERFACE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the new object through the derived class's create function */
|
|
||||||
|
|
||||||
HRESULT hr = NOERROR;
|
|
||||||
CUnknown *pObj = m_pTemplate->CreateInstance(pUnkOuter, &hr);
|
|
||||||
|
|
||||||
if (pObj == NULL) {
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete the object if we got a construction error */
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
delete pObj;
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a reference counted interface on the object */
|
|
||||||
|
|
||||||
/* We wrap the non-delegating QI with NDAddRef & NDRelease. */
|
|
||||||
/* This protects any outer object from being prematurely */
|
|
||||||
/* released by an inner object that may have to be created */
|
|
||||||
/* in order to supply the requested interface. */
|
|
||||||
pObj->NonDelegatingAddRef();
|
|
||||||
hr = pObj->NonDelegatingQueryInterface(riid, pv);
|
|
||||||
pObj->NonDelegatingRelease();
|
|
||||||
/* Note that if NonDelegatingQueryInterface fails, it will */
|
|
||||||
/* not increment the ref count, so the NonDelegatingRelease */
|
|
||||||
/* will drop the ref back to zero and the object will "self-*/
|
|
||||||
/* destruct". Hence we don't need additional tidy-up code */
|
|
||||||
/* to cope with NonDelegatingQueryInterface failing. */
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
ASSERT(*pv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP
|
|
||||||
CClassFactory::LockServer(BOOL fLock)
|
|
||||||
{
|
|
||||||
if (fLock) {
|
|
||||||
m_cLocked++;
|
|
||||||
} else {
|
|
||||||
m_cLocked--;
|
|
||||||
}
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// --- COM entrypoints -----------------------------------------
|
|
||||||
|
|
||||||
//called by COM to get the class factory object for a given class
|
|
||||||
STDAPI
|
|
||||||
DllGetClassObject(
|
|
||||||
REFCLSID rClsID,
|
|
||||||
REFIID riid,
|
|
||||||
void **pv)
|
|
||||||
{
|
|
||||||
if (!(riid == IID_IUnknown) && !(riid == IID_IClassFactory)) {
|
|
||||||
return E_NOINTERFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// traverse the array of templates looking for one with this
|
|
||||||
// class id
|
|
||||||
for (int i = 0; i < g_cTemplates; i++) {
|
|
||||||
const CFactoryTemplate * pT = &g_Templates[i];
|
|
||||||
if (pT->IsClassID(rClsID)) {
|
|
||||||
|
|
||||||
// found a template - make a class factory based on this
|
|
||||||
// template
|
|
||||||
|
|
||||||
*pv = (LPVOID) (LPUNKNOWN) new CClassFactory(pT);
|
|
||||||
if (*pv == NULL) {
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
((LPUNKNOWN)*pv)->AddRef();
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return CLASS_E_CLASSNOTAVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Call any initialization routines
|
|
||||||
//
|
|
||||||
void
|
|
||||||
DllInitClasses(BOOL bLoading)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// traverse the array of templates calling the init routine
|
|
||||||
// if they have one
|
|
||||||
for (i = 0; i < g_cTemplates; i++) {
|
|
||||||
const CFactoryTemplate * pT = &g_Templates[i];
|
|
||||||
if (pT->m_lpfnInit != NULL) {
|
|
||||||
(*pT->m_lpfnInit)(bLoading, pT->m_ClsID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// called by COM to determine if this dll can be unloaded
|
|
||||||
// return ok unless there are outstanding objects or a lock requested
|
|
||||||
// by IClassFactory::LockServer
|
|
||||||
//
|
|
||||||
// CClassFactory has a static function that can tell us about the locks,
|
|
||||||
// and CCOMObject has a static function that can tell us about the active
|
|
||||||
// object count
|
|
||||||
STDAPI
|
|
||||||
DllCanUnloadNow()
|
|
||||||
{
|
|
||||||
DbgLog((LOG_MEMORY,2,TEXT("DLLCanUnloadNow called - IsLocked = %d, Active objects = %d"),
|
|
||||||
CClassFactory::IsLocked(),
|
|
||||||
CBaseObject::ObjectsActive()));
|
|
||||||
|
|
||||||
if (CClassFactory::IsLocked() || CBaseObject::ObjectsActive()) {
|
|
||||||
return S_FALSE;
|
|
||||||
} else {
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// --- standard WIN32 entrypoints --------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
|
|
||||||
|
|
||||||
BOOL WINAPI
|
|
||||||
DllEntryPoint(HINSTANCE hInstance, ULONG ulReason, LPVOID pv)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
extern bool g_fDbgInDllEntryPoint;
|
|
||||||
g_fDbgInDllEntryPoint = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (ulReason)
|
|
||||||
{
|
|
||||||
|
|
||||||
case DLL_PROCESS_ATTACH:
|
|
||||||
DisableThreadLibraryCalls(hInstance);
|
|
||||||
DbgInitialise(hInstance);
|
|
||||||
|
|
||||||
{
|
|
||||||
// The platform identifier is used to work out whether
|
|
||||||
// full unicode support is available or not. Hence the
|
|
||||||
// default will be the lowest common denominator - i.e. N/A
|
|
||||||
g_amPlatform = VER_PLATFORM_WIN32_WINDOWS; // win95 assumed in case GetVersionEx fails
|
|
||||||
|
|
||||||
g_osInfo.dwOSVersionInfoSize = sizeof(g_osInfo);
|
|
||||||
if (GetVersionEx(&g_osInfo)) {
|
|
||||||
g_amPlatform = g_osInfo.dwPlatformId;
|
|
||||||
} else {
|
|
||||||
DbgLog((LOG_ERROR, 1, TEXT("Failed to get the OS platform, assuming Win95")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_hInst = hInstance;
|
|
||||||
DllInitClasses(TRUE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DLL_PROCESS_DETACH:
|
|
||||||
DllInitClasses(FALSE);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (CBaseObject::ObjectsActive()) {
|
|
||||||
DbgSetModuleLevel(LOG_MEMORY, 2);
|
|
||||||
TCHAR szInfo[512];
|
|
||||||
extern TCHAR m_ModuleName[]; // Cut down module name
|
|
||||||
|
|
||||||
TCHAR FullName[_MAX_PATH]; // Load the full path and module name
|
|
||||||
TCHAR *pName; // Searches from the end for a backslash
|
|
||||||
|
|
||||||
GetModuleFileName(NULL,FullName,_MAX_PATH);
|
|
||||||
pName = _tcsrchr(FullName,'\\');
|
|
||||||
if (pName == NULL) {
|
|
||||||
pName = FullName;
|
|
||||||
} else {
|
|
||||||
pName++;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)StringCchPrintf(szInfo, NUMELMS(szInfo), TEXT("Executable: %s Pid %x Tid %x. "),
|
|
||||||
pName, GetCurrentProcessId(), GetCurrentThreadId());
|
|
||||||
DWORD cch = lstrlen(szInfo);
|
|
||||||
|
|
||||||
(void)StringCchPrintf(szInfo+cch, NUMELMS(szInfo) - cch, TEXT("Module %s, %d objects left active!"),
|
|
||||||
m_ModuleName, CBaseObject::ObjectsActive());
|
|
||||||
DbgAssert(szInfo, TEXT(__FILE__),__LINE__);
|
|
||||||
|
|
||||||
// If running remotely wait for the Assert to be acknowledged
|
|
||||||
// before dumping out the object register
|
|
||||||
DbgDumpObjectRegister();
|
|
||||||
}
|
|
||||||
DbgTerminate();
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
g_fDbgInDllEntryPoint = false;
|
|
||||||
#endif
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,727 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: DllSetup.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// defines and constants
|
|
||||||
|
|
||||||
#define MAX_KEY_LEN 260
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
static LPCTSTR CLSID_KEY_FORMAT_STRING = TEXT("CLSID\\%s");
|
|
||||||
#else
|
|
||||||
static LPCTSTR CLSID_KEY_FORMAT_STRING = TEXT("CLSID\\%S");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// externally defined functions/variable
|
|
||||||
|
|
||||||
extern int g_cTemplates;
|
|
||||||
extern CFactoryTemplate g_Templates[];
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// internally defined functions
|
|
||||||
|
|
||||||
static HRESULT
|
|
||||||
ConvertUnicodeStringToTCHARString( LPTSTR szDest, size_t cchDest, LPCWSTR szSource );
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// EliminateSubKey
|
|
||||||
//
|
|
||||||
// Try to enumerate all keys under this one.
|
|
||||||
// if we find anything, delete it completely.
|
|
||||||
// Otherwise just delete it.
|
|
||||||
//
|
|
||||||
// note - this was pinched/duplicated from
|
|
||||||
// Filgraph\Mapper.cpp - so should it be in
|
|
||||||
// a lib somewhere?
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
STDAPI
|
|
||||||
EliminateSubKey( HKEY hkey, LPTSTR strSubKey )
|
|
||||||
{
|
|
||||||
HKEY hk;
|
|
||||||
if (0 == lstrlen(strSubKey) ) {
|
|
||||||
// defensive approach
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
LONG lreturn = RegOpenKeyEx( hkey
|
|
||||||
, strSubKey
|
|
||||||
, 0
|
|
||||||
, MAXIMUM_ALLOWED
|
|
||||||
, &hk );
|
|
||||||
|
|
||||||
ASSERT( lreturn == ERROR_SUCCESS
|
|
||||||
|| lreturn == ERROR_FILE_NOT_FOUND
|
|
||||||
|| lreturn == ERROR_INVALID_HANDLE );
|
|
||||||
|
|
||||||
if( ERROR_SUCCESS == lreturn )
|
|
||||||
{
|
|
||||||
// Keep on enumerating the first (zero-th)
|
|
||||||
// key and deleting that
|
|
||||||
|
|
||||||
for( ; ; )
|
|
||||||
{
|
|
||||||
TCHAR Buffer[MAX_KEY_LEN];
|
|
||||||
DWORD dw = MAX_KEY_LEN;
|
|
||||||
FILETIME ft;
|
|
||||||
|
|
||||||
lreturn = RegEnumKeyEx( hk
|
|
||||||
, 0
|
|
||||||
, Buffer
|
|
||||||
, &dw
|
|
||||||
, NULL
|
|
||||||
, NULL
|
|
||||||
, NULL
|
|
||||||
, &ft);
|
|
||||||
|
|
||||||
ASSERT( lreturn == ERROR_SUCCESS
|
|
||||||
|| lreturn == ERROR_NO_MORE_ITEMS );
|
|
||||||
|
|
||||||
if( ERROR_SUCCESS == lreturn )
|
|
||||||
{
|
|
||||||
EliminateSubKey(hk, Buffer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RegCloseKey(hk);
|
|
||||||
RegDeleteKey(hkey, strSubKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AMovieSetupRegisterServer()
|
|
||||||
//
|
|
||||||
// registers specfied file "szFileName" as server for
|
|
||||||
// CLSID "clsServer". A description is also required.
|
|
||||||
// The ThreadingModel and ServerType are optional, as
|
|
||||||
// they default to InprocServer32 (i.e. dll) and Both.
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
STDAPI
|
|
||||||
AMovieSetupRegisterServer( CLSID clsServer
|
|
||||||
, LPCWSTR szDescription
|
|
||||||
, LPCWSTR szFileName
|
|
||||||
, LPCWSTR szThreadingModel = L"Both"
|
|
||||||
, LPCWSTR szServerType = L"InprocServer32" )
|
|
||||||
{
|
|
||||||
// temp buffer
|
|
||||||
//
|
|
||||||
TCHAR achTemp[MAX_PATH];
|
|
||||||
|
|
||||||
// convert CLSID uuid to string and write
|
|
||||||
// out subkey as string - CLSID\{}
|
|
||||||
//
|
|
||||||
OLECHAR szCLSID[CHARS_IN_GUID];
|
|
||||||
HRESULT hr = StringFromGUID2( clsServer
|
|
||||||
, szCLSID
|
|
||||||
, CHARS_IN_GUID );
|
|
||||||
ASSERT( SUCCEEDED(hr) );
|
|
||||||
|
|
||||||
// create key
|
|
||||||
//
|
|
||||||
HKEY hkey;
|
|
||||||
|
|
||||||
(void)StringCchPrintf( achTemp, NUMELMS(achTemp), CLSID_KEY_FORMAT_STRING, szCLSID );
|
|
||||||
|
|
||||||
LONG lreturn = RegCreateKey( HKEY_CLASSES_ROOT
|
|
||||||
, (LPCTSTR)achTemp
|
|
||||||
, &hkey );
|
|
||||||
if( ERROR_SUCCESS != lreturn )
|
|
||||||
{
|
|
||||||
return AmHresultFromWin32(lreturn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set description string
|
|
||||||
//
|
|
||||||
|
|
||||||
(void)ConvertUnicodeStringToTCHARString( achTemp, NUMELMS(achTemp), szDescription );
|
|
||||||
lreturn = RegSetValue( hkey
|
|
||||||
, (LPCTSTR)NULL
|
|
||||||
, REG_SZ
|
|
||||||
, achTemp
|
|
||||||
, sizeof(achTemp) );
|
|
||||||
if( ERROR_SUCCESS != lreturn )
|
|
||||||
{
|
|
||||||
RegCloseKey( hkey );
|
|
||||||
return AmHresultFromWin32(lreturn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create CLSID\\{"CLSID"}\\"ServerType" key,
|
|
||||||
// using key to CLSID\\{"CLSID"} passed back by
|
|
||||||
// last call to RegCreateKey().
|
|
||||||
//
|
|
||||||
HKEY hsubkey;
|
|
||||||
|
|
||||||
(void)ConvertUnicodeStringToTCHARString( achTemp, NUMELMS(achTemp), szServerType );
|
|
||||||
lreturn = RegCreateKey( hkey
|
|
||||||
, achTemp
|
|
||||||
, &hsubkey );
|
|
||||||
if( ERROR_SUCCESS != lreturn )
|
|
||||||
{
|
|
||||||
RegCloseKey( hkey );
|
|
||||||
return AmHresultFromWin32(lreturn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set Server string
|
|
||||||
//
|
|
||||||
(void)ConvertUnicodeStringToTCHARString( achTemp, NUMELMS(achTemp), szFileName );
|
|
||||||
lreturn = RegSetValue( hsubkey
|
|
||||||
, (LPCTSTR)NULL
|
|
||||||
, REG_SZ
|
|
||||||
, (LPCTSTR)achTemp
|
|
||||||
, sizeof(TCHAR) * (lstrlen(achTemp)+1) );
|
|
||||||
if( ERROR_SUCCESS != lreturn )
|
|
||||||
{
|
|
||||||
RegCloseKey( hkey );
|
|
||||||
RegCloseKey( hsubkey );
|
|
||||||
return AmHresultFromWin32(lreturn);
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)ConvertUnicodeStringToTCHARString( achTemp, NUMELMS(achTemp), szThreadingModel );
|
|
||||||
lreturn = RegSetValueEx( hsubkey
|
|
||||||
, TEXT("ThreadingModel")
|
|
||||||
, 0L
|
|
||||||
, REG_SZ
|
|
||||||
, (CONST BYTE *)achTemp
|
|
||||||
, sizeof(TCHAR) * (lstrlen(achTemp)+1) );
|
|
||||||
|
|
||||||
// close hkeys
|
|
||||||
//
|
|
||||||
RegCloseKey( hkey );
|
|
||||||
RegCloseKey( hsubkey );
|
|
||||||
|
|
||||||
// and return
|
|
||||||
//
|
|
||||||
return HRESULT_FROM_WIN32(lreturn);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AMovieSetupUnregisterServer()
|
|
||||||
//
|
|
||||||
// default ActiveMovie dll setup function
|
|
||||||
// - to use must be called from an exported
|
|
||||||
// function named DllRegisterServer()
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
STDAPI
|
|
||||||
AMovieSetupUnregisterServer( CLSID clsServer )
|
|
||||||
{
|
|
||||||
// convert CLSID uuid to string and write
|
|
||||||
// out subkey CLSID\{}
|
|
||||||
//
|
|
||||||
OLECHAR szCLSID[CHARS_IN_GUID];
|
|
||||||
HRESULT hr = StringFromGUID2( clsServer
|
|
||||||
, szCLSID
|
|
||||||
, CHARS_IN_GUID );
|
|
||||||
ASSERT( SUCCEEDED(hr) );
|
|
||||||
|
|
||||||
TCHAR achBuffer[MAX_KEY_LEN];
|
|
||||||
(void)StringCchPrintf( achBuffer, NUMELMS(achBuffer), CLSID_KEY_FORMAT_STRING, szCLSID );
|
|
||||||
|
|
||||||
// delete subkey
|
|
||||||
//
|
|
||||||
|
|
||||||
hr = EliminateSubKey( HKEY_CLASSES_ROOT, achBuffer );
|
|
||||||
ASSERT( SUCCEEDED(hr) );
|
|
||||||
|
|
||||||
// return
|
|
||||||
//
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AMovieSetupRegisterFilter through IFilterMapper2
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
STDAPI
|
|
||||||
AMovieSetupRegisterFilter2( const AMOVIESETUP_FILTER * const psetupdata
|
|
||||||
, IFilterMapper2 * pIFM2
|
|
||||||
, BOOL bRegister )
|
|
||||||
{
|
|
||||||
DbgLog((LOG_TRACE, 3, TEXT("= AMovieSetupRegisterFilter")));
|
|
||||||
|
|
||||||
// check we've got data
|
|
||||||
//
|
|
||||||
if( NULL == psetupdata ) return S_FALSE;
|
|
||||||
|
|
||||||
|
|
||||||
// unregister filter
|
|
||||||
// (as pins are subkeys of filter's CLSID key
|
|
||||||
// they do not need to be removed separately).
|
|
||||||
//
|
|
||||||
DbgLog((LOG_TRACE, 3, TEXT("= = unregister filter")));
|
|
||||||
HRESULT hr = pIFM2->UnregisterFilter(
|
|
||||||
0, // default category
|
|
||||||
0, // default instance name
|
|
||||||
*psetupdata->clsID );
|
|
||||||
|
|
||||||
|
|
||||||
if( bRegister )
|
|
||||||
{
|
|
||||||
REGFILTER2 rf2;
|
|
||||||
rf2.dwVersion = 1;
|
|
||||||
rf2.dwMerit = psetupdata->dwMerit;
|
|
||||||
rf2.cPins = psetupdata->nPins;
|
|
||||||
rf2.rgPins = psetupdata->lpPin;
|
|
||||||
|
|
||||||
// register filter
|
|
||||||
//
|
|
||||||
DbgLog((LOG_TRACE, 3, TEXT("= = register filter")));
|
|
||||||
hr = pIFM2->RegisterFilter(*psetupdata->clsID
|
|
||||||
, psetupdata->strName
|
|
||||||
, 0 // moniker
|
|
||||||
, 0 // category
|
|
||||||
, NULL // instance
|
|
||||||
, &rf2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle one acceptable "error" - that
|
|
||||||
// of filter not being registered!
|
|
||||||
// (couldn't find a suitable #define'd
|
|
||||||
// name for the error!)
|
|
||||||
//
|
|
||||||
if( 0x80070002 == hr)
|
|
||||||
return NOERROR;
|
|
||||||
else
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// RegisterAllServers()
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
STDAPI
|
|
||||||
RegisterAllServers( LPCWSTR szFileName, BOOL bRegister )
|
|
||||||
{
|
|
||||||
HRESULT hr = NOERROR;
|
|
||||||
|
|
||||||
for( int i = 0; i < g_cTemplates; i++ )
|
|
||||||
{
|
|
||||||
// get i'th template
|
|
||||||
//
|
|
||||||
const CFactoryTemplate *pT = &g_Templates[i];
|
|
||||||
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("- - register %ls"),
|
|
||||||
(LPCWSTR)pT->m_Name ));
|
|
||||||
|
|
||||||
// register CLSID and InprocServer32
|
|
||||||
//
|
|
||||||
if( bRegister )
|
|
||||||
{
|
|
||||||
hr = AMovieSetupRegisterServer( *(pT->m_ClsID)
|
|
||||||
, (LPCWSTR)pT->m_Name
|
|
||||||
, szFileName );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = AMovieSetupUnregisterServer( *(pT->m_ClsID) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// check final error for this pass
|
|
||||||
// and break loop if we failed
|
|
||||||
//
|
|
||||||
if( FAILED(hr) )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AMovieDllRegisterServer2()
|
|
||||||
//
|
|
||||||
// default ActiveMovie dll setup function
|
|
||||||
// - to use must be called from an exported
|
|
||||||
// function named DllRegisterServer()
|
|
||||||
//
|
|
||||||
// this function is table driven using the
|
|
||||||
// static members of the CFactoryTemplate
|
|
||||||
// class defined in the dll.
|
|
||||||
//
|
|
||||||
// it registers the Dll as the InprocServer32
|
|
||||||
// and then calls the IAMovieSetup.Register
|
|
||||||
// method.
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
STDAPI
|
|
||||||
AMovieDllRegisterServer2( BOOL bRegister )
|
|
||||||
{
|
|
||||||
HRESULT hr = NOERROR;
|
|
||||||
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("AMovieDllRegisterServer2()")));
|
|
||||||
|
|
||||||
// get file name (where g_hInst is the
|
|
||||||
// instance handle of the filter dll)
|
|
||||||
//
|
|
||||||
WCHAR achFileName[MAX_PATH];
|
|
||||||
|
|
||||||
// WIN95 doesn't support GetModuleFileNameW
|
|
||||||
//
|
|
||||||
{
|
|
||||||
char achTemp[MAX_PATH];
|
|
||||||
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("- get module file name")));
|
|
||||||
|
|
||||||
// g_hInst handle is set in our dll entry point. Make sure
|
|
||||||
// DllEntryPoint in dllentry.cpp is called
|
|
||||||
ASSERT(g_hInst != 0);
|
|
||||||
|
|
||||||
if( 0 == GetModuleFileNameA( g_hInst
|
|
||||||
, achTemp
|
|
||||||
, sizeof(achTemp) ) )
|
|
||||||
{
|
|
||||||
// we've failed!
|
|
||||||
DWORD dwerr = GetLastError();
|
|
||||||
return AmHresultFromWin32(dwerr);
|
|
||||||
}
|
|
||||||
|
|
||||||
MultiByteToWideChar( CP_ACP
|
|
||||||
, 0L
|
|
||||||
, achTemp
|
|
||||||
, lstrlenA(achTemp) + 1
|
|
||||||
, achFileName
|
|
||||||
, NUMELMS(achFileName) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// first registering, register all OLE servers
|
|
||||||
//
|
|
||||||
if( bRegister )
|
|
||||||
{
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers")));
|
|
||||||
hr = RegisterAllServers( achFileName, TRUE );
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// next, register/unregister all filters
|
|
||||||
//
|
|
||||||
|
|
||||||
if( SUCCEEDED(hr) )
|
|
||||||
{
|
|
||||||
// init is ref counted so call just in case
|
|
||||||
// we're being called cold.
|
|
||||||
//
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("- CoInitialize")));
|
|
||||||
hr = CoInitialize( (LPVOID)NULL );
|
|
||||||
ASSERT( SUCCEEDED(hr) );
|
|
||||||
|
|
||||||
// get hold of IFilterMapper2
|
|
||||||
//
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("- obtain IFilterMapper2")));
|
|
||||||
IFilterMapper2 *pIFM2 = 0;
|
|
||||||
IFilterMapper *pIFM = 0;
|
|
||||||
hr = CoCreateInstance( CLSID_FilterMapper2
|
|
||||||
, NULL
|
|
||||||
, CLSCTX_INPROC_SERVER
|
|
||||||
, IID_IFilterMapper2
|
|
||||||
, (void **)&pIFM2 );
|
|
||||||
if(FAILED(hr))
|
|
||||||
{
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("- trying IFilterMapper instead")));
|
|
||||||
|
|
||||||
hr = CoCreateInstance(
|
|
||||||
CLSID_FilterMapper,
|
|
||||||
NULL,
|
|
||||||
CLSCTX_INPROC_SERVER,
|
|
||||||
IID_IFilterMapper,
|
|
||||||
(void **)&pIFM);
|
|
||||||
}
|
|
||||||
if( SUCCEEDED(hr) )
|
|
||||||
{
|
|
||||||
// scan through array of CFactoryTemplates
|
|
||||||
// registering servers and filters.
|
|
||||||
//
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("- register Filters")));
|
|
||||||
for( int i = 0; i < g_cTemplates; i++ )
|
|
||||||
{
|
|
||||||
// get i'th template
|
|
||||||
//
|
|
||||||
const CFactoryTemplate *pT = &g_Templates[i];
|
|
||||||
|
|
||||||
if( NULL != pT->m_pAMovieSetup_Filter )
|
|
||||||
{
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("- - register %ls"), (LPCWSTR)pT->m_Name ));
|
|
||||||
|
|
||||||
if(pIFM2)
|
|
||||||
{
|
|
||||||
hr = AMovieSetupRegisterFilter2( pT->m_pAMovieSetup_Filter, pIFM2, bRegister );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = AMovieSetupRegisterFilter( pT->m_pAMovieSetup_Filter, pIFM, bRegister );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check final error for this pass
|
|
||||||
// and break loop if we failed
|
|
||||||
//
|
|
||||||
if( FAILED(hr) )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// release interface
|
|
||||||
//
|
|
||||||
if(pIFM2)
|
|
||||||
pIFM2->Release();
|
|
||||||
else
|
|
||||||
pIFM->Release();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// and clear up
|
|
||||||
//
|
|
||||||
CoFreeUnusedLibraries();
|
|
||||||
CoUninitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// if unregistering, unregister all OLE servers
|
|
||||||
//
|
|
||||||
if( SUCCEEDED(hr) && !bRegister )
|
|
||||||
{
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers")));
|
|
||||||
hr = RegisterAllServers( achFileName, FALSE );
|
|
||||||
}
|
|
||||||
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("- return %0x"), hr));
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AMovieDllRegisterServer()
|
|
||||||
//
|
|
||||||
// default ActiveMovie dll setup function
|
|
||||||
// - to use must be called from an exported
|
|
||||||
// function named DllRegisterServer()
|
|
||||||
//
|
|
||||||
// this function is table driven using the
|
|
||||||
// static members of the CFactoryTemplate
|
|
||||||
// class defined in the dll.
|
|
||||||
//
|
|
||||||
// it registers the Dll as the InprocServer32
|
|
||||||
// and then calls the IAMovieSetup.Register
|
|
||||||
// method.
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
STDAPI
|
|
||||||
AMovieDllRegisterServer( void )
|
|
||||||
{
|
|
||||||
HRESULT hr = NOERROR;
|
|
||||||
|
|
||||||
// get file name (where g_hInst is the
|
|
||||||
// instance handle of the filter dll)
|
|
||||||
//
|
|
||||||
WCHAR achFileName[MAX_PATH];
|
|
||||||
|
|
||||||
{
|
|
||||||
// WIN95 doesn't support GetModuleFileNameW
|
|
||||||
//
|
|
||||||
char achTemp[MAX_PATH];
|
|
||||||
|
|
||||||
if( 0 == GetModuleFileNameA( g_hInst
|
|
||||||
, achTemp
|
|
||||||
, sizeof(achTemp) ) )
|
|
||||||
{
|
|
||||||
// we've failed!
|
|
||||||
DWORD dwerr = GetLastError();
|
|
||||||
return AmHresultFromWin32(dwerr);
|
|
||||||
}
|
|
||||||
|
|
||||||
MultiByteToWideChar( CP_ACP
|
|
||||||
, 0L
|
|
||||||
, achTemp
|
|
||||||
, lstrlenA(achTemp) + 1
|
|
||||||
, achFileName
|
|
||||||
, NUMELMS(achFileName) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// scan through array of CFactoryTemplates
|
|
||||||
// registering servers and filters.
|
|
||||||
//
|
|
||||||
for( int i = 0; i < g_cTemplates; i++ )
|
|
||||||
{
|
|
||||||
// get i'th template
|
|
||||||
//
|
|
||||||
const CFactoryTemplate *pT = &g_Templates[i];
|
|
||||||
|
|
||||||
// register CLSID and InprocServer32
|
|
||||||
//
|
|
||||||
hr = AMovieSetupRegisterServer( *(pT->m_ClsID)
|
|
||||||
, (LPCWSTR)pT->m_Name
|
|
||||||
, achFileName );
|
|
||||||
|
|
||||||
// instantiate all servers and get hold of
|
|
||||||
// IAMovieSetup, if implemented, and call
|
|
||||||
// IAMovieSetup.Register() method
|
|
||||||
//
|
|
||||||
if( SUCCEEDED(hr) && (NULL != pT->m_lpfnNew) )
|
|
||||||
{
|
|
||||||
// instantiate object
|
|
||||||
//
|
|
||||||
PAMOVIESETUP psetup;
|
|
||||||
hr = CoCreateInstance( *(pT->m_ClsID)
|
|
||||||
, 0
|
|
||||||
, CLSCTX_INPROC_SERVER
|
|
||||||
, IID_IAMovieSetup
|
|
||||||
, reinterpret_cast<void**>(&psetup) );
|
|
||||||
if( SUCCEEDED(hr) )
|
|
||||||
{
|
|
||||||
hr = psetup->Unregister();
|
|
||||||
if( SUCCEEDED(hr) )
|
|
||||||
hr = psetup->Register();
|
|
||||||
psetup->Release();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( (E_NOINTERFACE == hr )
|
|
||||||
|| (VFW_E_NEED_OWNER == hr ) )
|
|
||||||
hr = NOERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check final error for this pass
|
|
||||||
// and break loop if we failed
|
|
||||||
//
|
|
||||||
if( FAILED(hr) )
|
|
||||||
break;
|
|
||||||
|
|
||||||
} // end-for
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AMovieDllUnregisterServer()
|
|
||||||
//
|
|
||||||
// default ActiveMovie dll uninstall function
|
|
||||||
// - to use must be called from an exported
|
|
||||||
// function named DllRegisterServer()
|
|
||||||
//
|
|
||||||
// this function is table driven using the
|
|
||||||
// static members of the CFactoryTemplate
|
|
||||||
// class defined in the dll.
|
|
||||||
//
|
|
||||||
// it calls the IAMovieSetup.Unregister
|
|
||||||
// method and then unregisters the Dll
|
|
||||||
// as the InprocServer32
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
STDAPI
|
|
||||||
AMovieDllUnregisterServer()
|
|
||||||
{
|
|
||||||
// initialize return code
|
|
||||||
//
|
|
||||||
HRESULT hr = NOERROR;
|
|
||||||
|
|
||||||
// scan through CFactory template and unregister
|
|
||||||
// all OLE servers and filters.
|
|
||||||
//
|
|
||||||
for( int i = g_cTemplates; i--; )
|
|
||||||
{
|
|
||||||
// get i'th template
|
|
||||||
//
|
|
||||||
const CFactoryTemplate *pT = &g_Templates[i];
|
|
||||||
|
|
||||||
// check method exists
|
|
||||||
//
|
|
||||||
if( NULL != pT->m_lpfnNew )
|
|
||||||
{
|
|
||||||
// instantiate object
|
|
||||||
//
|
|
||||||
PAMOVIESETUP psetup;
|
|
||||||
hr = CoCreateInstance( *(pT->m_ClsID)
|
|
||||||
, 0
|
|
||||||
, CLSCTX_INPROC_SERVER
|
|
||||||
, IID_IAMovieSetup
|
|
||||||
, reinterpret_cast<void**>(&psetup) );
|
|
||||||
if( SUCCEEDED(hr) )
|
|
||||||
{
|
|
||||||
hr = psetup->Unregister();
|
|
||||||
psetup->Release();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( (E_NOINTERFACE == hr )
|
|
||||||
|| (VFW_E_NEED_OWNER == hr ) )
|
|
||||||
hr = NOERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// unregister CLSID and InprocServer32
|
|
||||||
//
|
|
||||||
if( SUCCEEDED(hr) )
|
|
||||||
{
|
|
||||||
hr = AMovieSetupUnregisterServer( *(pT->m_ClsID) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// check final error for this pass
|
|
||||||
// and break loop if we failed
|
|
||||||
//
|
|
||||||
if( FAILED(hr) )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT
|
|
||||||
ConvertUnicodeStringToTCHARString( LPTSTR szDest, size_t cchDest, LPCWSTR szSource )
|
|
||||||
{
|
|
||||||
HRESULT hr = NOERROR;
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
LPCTSTR FORMAT_STRING = TEXT("%s");
|
|
||||||
#else
|
|
||||||
LPCTSTR FORMAT_STRING = TEXT("%S");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
hr = StringCchPrintf( szDest, cchDest, FORMAT_STRING, szSource );
|
|
||||||
if( FAILED( hr ) )
|
|
||||||
{
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: DllSetup.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
// To be self registering, OLE servers must
|
|
||||||
// export functions named DllRegisterServer
|
|
||||||
// and DllUnregisterServer. To allow use of
|
|
||||||
// custom and default implementations the
|
|
||||||
// defaults are named AMovieDllRegisterServer
|
|
||||||
// and AMovieDllUnregisterServer.
|
|
||||||
//
|
|
||||||
// To the use the default implementation you
|
|
||||||
// must provide stub functions.
|
|
||||||
//
|
|
||||||
// i.e. STDAPI DllRegisterServer()
|
|
||||||
// {
|
|
||||||
// return AMovieDllRegisterServer();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// STDAPI DllUnregisterServer()
|
|
||||||
// {
|
|
||||||
// return AMovieDllUnregisterServer();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// AMovieDllRegisterServer calls IAMovieSetup.Register(), and
|
|
||||||
// AMovieDllUnregisterServer calls IAMovieSetup.Unregister().
|
|
||||||
|
|
||||||
STDAPI AMovieDllRegisterServer2( BOOL );
|
|
||||||
STDAPI AMovieDllRegisterServer();
|
|
||||||
STDAPI AMovieDllUnregisterServer();
|
|
||||||
|
|
||||||
// helper functions
|
|
||||||
STDAPI EliminateSubKey( HKEY, LPTSTR );
|
|
||||||
|
|
||||||
|
|
||||||
STDAPI
|
|
||||||
AMovieSetupRegisterFilter2( const AMOVIESETUP_FILTER * const psetupdata
|
|
||||||
, IFilterMapper2 * pIFM2
|
|
||||||
, BOOL bRegister );
|
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: DShow.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow top-level include file
|
|
||||||
//
|
|
||||||
// Copyright (c) 2000-2001, Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifndef __DSHOW_INCLUDED__
|
|
||||||
#define __DSHOW_INCLUDED__
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// Set up constants & pragmas for the compiler
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
// disable some level-4 warnings, use #pragma warning(default:###) to re-enable
|
|
||||||
#pragma warning(disable:4100) // warning C4100: unreferenced formal parameter
|
|
||||||
#pragma warning(disable:4201) // warning C4201: nonstandard extension used : nameless struct/union
|
|
||||||
#pragma warning(disable:4511) // warning C4511: copy constructor could not be generated
|
|
||||||
#pragma warning(disable:4512) // warning C4512: assignment operator could not be generated
|
|
||||||
#pragma warning(disable:4514) // warning C4514: "unreferenced inline function has been removed"
|
|
||||||
|
|
||||||
#if _MSC_VER>=1100
|
|
||||||
#define AM_NOVTABLE __declspec(novtable)
|
|
||||||
#else
|
|
||||||
#define AM_NOVTABLE
|
|
||||||
#endif
|
|
||||||
#endif // MSC_VER
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// Include standard Windows files
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
#include <windows.h>
|
|
||||||
#include <windowsx.h>
|
|
||||||
#include <olectl.h>
|
|
||||||
#include <ddraw.h>
|
|
||||||
#include <mmsystem.h>
|
|
||||||
|
|
||||||
#ifndef NO_DSHOW_STRSAFE
|
|
||||||
#define NO_SHLWAPI_STRFCNS
|
|
||||||
#include <strsafe.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NUMELMS
|
|
||||||
#define NUMELMS(aa) (sizeof(aa)/sizeof((aa)[0]))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// Include DirectShow include files
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
#include <strmif.h> // Generated IDL header file for streams interfaces
|
|
||||||
#include <amvideo.h> // ActiveMovie video interfaces and definitions
|
|
||||||
#include <amaudio.h> // ActiveMovie audio interfaces and definitions
|
|
||||||
#include <control.h> // generated from control.odl
|
|
||||||
#include <evcode.h> // event code definitions
|
|
||||||
#include <uuids.h> // declaration of type GUIDs and well-known clsids
|
|
||||||
#include <errors.h> // HRESULT status and error definitions
|
|
||||||
#include <edevdefs.h> // External device control interface defines
|
|
||||||
#include <audevcod.h> // audio filter device error event codes
|
|
||||||
#include <dvdevcod.h> // DVD error event codes
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// Define OLE Automation constants
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
#ifndef OATRUE
|
|
||||||
#define OATRUE (-1)
|
|
||||||
#endif // OATRUE
|
|
||||||
#ifndef OAFALSE
|
|
||||||
#define OAFALSE (0)
|
|
||||||
#endif // OAFALSE
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// Define Win64 interfaces if not already defined
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// InterlockedExchangePointer
|
|
||||||
#ifndef InterlockedExchangePointer
|
|
||||||
#define InterlockedExchangePointer(Target, Value) \
|
|
||||||
(PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif // __DSHOW_INCLUDED__
|
|
|
@ -1,128 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: DSSchedule.h (replaces DirectX 8's schedule.h)
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __CAMSchedule__
|
|
||||||
#define __CAMSchedule__
|
|
||||||
|
|
||||||
class CAMSchedule : private CBaseObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~CAMSchedule();
|
|
||||||
// ev is the event we should fire if the advise time needs re-evaluating
|
|
||||||
CAMSchedule( HANDLE ev );
|
|
||||||
|
|
||||||
DWORD GetAdviseCount();
|
|
||||||
REFERENCE_TIME GetNextAdviseTime();
|
|
||||||
|
|
||||||
// We need a method for derived classes to add advise packets, we return the cookie
|
|
||||||
DWORD_PTR AddAdvisePacket( const REFERENCE_TIME & time1, const REFERENCE_TIME & time2, HANDLE h, BOOL periodic );
|
|
||||||
// And a way to cancel
|
|
||||||
HRESULT Unadvise(DWORD_PTR dwAdviseCookie);
|
|
||||||
|
|
||||||
// Tell us the time please, and we'll dispatch the expired events. We return the time of the next event.
|
|
||||||
// NB: The time returned will be "useless" if you start adding extra Advises. But that's the problem of
|
|
||||||
// whoever is using this helper class (typically a clock).
|
|
||||||
REFERENCE_TIME Advise( const REFERENCE_TIME & rtTime );
|
|
||||||
|
|
||||||
// Get the event handle which will be set if advise time requires re-evaluation.
|
|
||||||
HANDLE GetEvent() const { return m_ev; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
// We define the nodes that will be used in our singly linked list
|
|
||||||
// of advise packets. The list is ordered by time, with the
|
|
||||||
// elements that will expire first at the front.
|
|
||||||
class CAdvisePacket
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CAdvisePacket()
|
|
||||||
{}
|
|
||||||
|
|
||||||
CAdvisePacket * m_next;
|
|
||||||
DWORD_PTR m_dwAdviseCookie;
|
|
||||||
REFERENCE_TIME m_rtEventTime; // Time at which event should be set
|
|
||||||
REFERENCE_TIME m_rtPeriod; // Periodic time
|
|
||||||
HANDLE m_hNotify; // Handle to event or semephore
|
|
||||||
BOOL m_bPeriodic; // TRUE => Periodic event
|
|
||||||
|
|
||||||
CAdvisePacket( CAdvisePacket * next, LONGLONG time ) : m_next(next), m_rtEventTime(time)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void InsertAfter( CAdvisePacket * p )
|
|
||||||
{
|
|
||||||
p->m_next = m_next;
|
|
||||||
m_next = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IsZ() const // That is, is it the node that represents the end of the list
|
|
||||||
{ return m_next == 0; }
|
|
||||||
|
|
||||||
CAdvisePacket * RemoveNext()
|
|
||||||
{
|
|
||||||
CAdvisePacket *const next = m_next;
|
|
||||||
CAdvisePacket *const new_next = next->m_next;
|
|
||||||
m_next = new_next;
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeleteNext()
|
|
||||||
{
|
|
||||||
delete RemoveNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
CAdvisePacket * Next() const
|
|
||||||
{
|
|
||||||
CAdvisePacket * result = m_next;
|
|
||||||
if (result->IsZ()) result = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD_PTR Cookie() const
|
|
||||||
{ return m_dwAdviseCookie; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Structure is:
|
|
||||||
// head -> elmt1 -> elmt2 -> z -> null
|
|
||||||
// So an empty list is: head -> z -> null
|
|
||||||
// Having head & z as links makes insertaion,
|
|
||||||
// deletion and shunting much easier.
|
|
||||||
CAdvisePacket head, z; // z is both a tail and a sentry
|
|
||||||
|
|
||||||
volatile DWORD_PTR m_dwNextCookie; // Strictly increasing
|
|
||||||
volatile DWORD m_dwAdviseCount; // Number of elements on list
|
|
||||||
|
|
||||||
CCritSec m_Serialize;
|
|
||||||
|
|
||||||
// AddAdvisePacket: adds the packet, returns the cookie (0 if failed)
|
|
||||||
DWORD_PTR AddAdvisePacket( CAdvisePacket * pPacket );
|
|
||||||
// Event that we should set if the packed added above will be the next to fire.
|
|
||||||
const HANDLE m_ev;
|
|
||||||
|
|
||||||
// A Shunt is where we have changed the first element in the
|
|
||||||
// list and want it re-evaluating (i.e. repositioned) in
|
|
||||||
// the list.
|
|
||||||
void ShuntHead();
|
|
||||||
|
|
||||||
// Rather than delete advise packets, we cache them for future use
|
|
||||||
CAdvisePacket * m_pAdviseCache;
|
|
||||||
DWORD m_dwCacheCount;
|
|
||||||
enum { dwCacheMax = 5 }; // Don't bother caching more than five
|
|
||||||
|
|
||||||
void Delete( CAdvisePacket * pLink );// This "Delete" will cache the Link
|
|
||||||
|
|
||||||
// Attributes and methods for debugging
|
|
||||||
public:
|
|
||||||
#ifdef DEBUG
|
|
||||||
void DumpLinkedList();
|
|
||||||
#else
|
|
||||||
void DumpLinkedList() {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __CAMSchedule__
|
|
|
@ -1,363 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: DVDevCod.h
|
|
||||||
//
|
|
||||||
// Desc: List of standard DVD-Video event codes and the expected params.
|
|
||||||
//
|
|
||||||
// Copyright (c) 1992 - 2001, Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifndef __DVDEVCOD__
|
|
||||||
#define __DVDEVCOD__
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_DVDBASE 0x0100
|
|
||||||
|
|
||||||
#ifndef EXCLUDE_DVDEVCODE_ENUMS
|
|
||||||
|
|
||||||
typedef enum _tagDVD_ERROR {
|
|
||||||
DVD_ERROR_Unexpected=1, // Something unexpected happened, perhaps content
|
|
||||||
// is incorrectly authored. Playback is stopped.
|
|
||||||
DVD_ERROR_CopyProtectFail=2, // Key exchange for DVD copy protection failed.
|
|
||||||
// Playback is stopped.
|
|
||||||
DVD_ERROR_InvalidDVD1_0Disc=3, // DVD-Video disc is incorrectly authored for v1.0
|
|
||||||
// of spec. Playback is stopped.
|
|
||||||
DVD_ERROR_InvalidDiscRegion=4, // The Disc cannot be played because the disc is not
|
|
||||||
// authored to play in system region.
|
|
||||||
// The region mismatch may be fixable by
|
|
||||||
// changing the system region with dvdrgn.exe
|
|
||||||
DVD_ERROR_LowParentalLevel=5, // Player parental level is lower than the lowest parental
|
|
||||||
// level available in the DVD content. Playback is stopped.
|
|
||||||
DVD_ERROR_MacrovisionFail=6, // Macrovision Distribution Failed.
|
|
||||||
// Playback is stopped.
|
|
||||||
DVD_ERROR_IncompatibleSystemAndDecoderRegions=7,
|
|
||||||
// No discs can be played because the system region
|
|
||||||
// does not match the decoder region.
|
|
||||||
DVD_ERROR_IncompatibleDiscAndDecoderRegions=8
|
|
||||||
// The disc cannot be played because the disc is
|
|
||||||
// not authored to be played in the decoder's region
|
|
||||||
} DVD_ERROR;
|
|
||||||
|
|
||||||
typedef enum _tagDVD_WARNING {
|
|
||||||
DVD_WARNING_InvalidDVD1_0Disc=1,// DVD-Video disc is incorrectly authored. Playback
|
|
||||||
// can continue, but unexpected behavior may occur.
|
|
||||||
DVD_WARNING_FormatNotSupported=2,// A decoder would not support the current format. Playback
|
|
||||||
// of a stream (audio, video of SP) may not function.
|
|
||||||
// lParam2 contains the stream type (see AM_DVD_STREAM_FLAGS)
|
|
||||||
DVD_WARNING_IllegalNavCommand=3,// The internal DVD navigation command processor attempted to
|
|
||||||
// process an illegal command.
|
|
||||||
DVD_WARNING_Open = 4, // File Open Failed
|
|
||||||
DVD_WARNING_Seek = 5, // File Seek Failed
|
|
||||||
DVD_WARNING_Read = 6 // File Read Failed
|
|
||||||
} DVD_WARNING;
|
|
||||||
|
|
||||||
typedef enum _tagDVD_PB_STOPPED {
|
|
||||||
DVD_PB_STOPPED_Other=0, // The navigator stopped the playback (no reason available).
|
|
||||||
DVD_PB_STOPPED_NoBranch=1, // The nav completed the current pgc and there was no more video and
|
|
||||||
// did not find any other branching instruction for subsequent playback.
|
|
||||||
DVD_PB_STOPPED_NoFirstPlayDomain =2, // The disc does not contain an initial startup program.
|
|
||||||
DVD_PB_STOPPED_StopCommand = 3, // The app issued a stop() command or a stop command was authored on the disc.
|
|
||||||
DVD_PB_STOPPED_Reset=4, // The navigator was reset to the start of the disc (using ResetOnStop).
|
|
||||||
DVD_PB_STOPPED_DiscEjected=5, // The disc was ejected.
|
|
||||||
DVD_PB_STOPPED_IllegalNavCommand = 6, // An illegal nav command prevented playback from continuing.
|
|
||||||
DVD_PB_STOPPED_PlayPeriodAutoStop = 7, // PlayPeriod completed
|
|
||||||
DVD_PB_STOPPED_PlayChapterAutoStop = 8, // PlayChapter completed
|
|
||||||
DVD_PB_STOPPED_ParentalFailure = 9, // A parental level failure prevented playback
|
|
||||||
DVD_PB_STOPPED_RegionFailure = 10, // A region failure prevented playback
|
|
||||||
DVD_PB_STOPPED_MacrovisionFailure = 11, // A Macrovision failure prevented playback.
|
|
||||||
DVD_PB_STOPPED_DiscReadError = 12, // A read error prevented playback.
|
|
||||||
DVD_PB_STOPPED_CopyProtectFailure = 13 // Copy protection failure.
|
|
||||||
} DVD_PB_STOPPED;
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// DVD-Video event codes
|
|
||||||
// ======================
|
|
||||||
//
|
|
||||||
// All DVD-Video event are always passed on to the application, and are
|
|
||||||
// never processed by the filter graph
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_DVD_DOMAIN_CHANGE (EC_DVDBASE + 0x01)
|
|
||||||
// Parameters: ( DWORD, void )
|
|
||||||
// lParam1 is enum DVD_DOMAIN, and indicates the player's new domain
|
|
||||||
//
|
|
||||||
// Raised from following domains: all
|
|
||||||
//
|
|
||||||
// Signaled when ever the DVD player changes domains.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_DVD_TITLE_CHANGE (EC_DVDBASE + 0x02)
|
|
||||||
// Parameters: ( DWORD, void )
|
|
||||||
// lParam1 is the new title number.
|
|
||||||
//
|
|
||||||
// Raised from following domains: DVD_DOMAIN_Title
|
|
||||||
//
|
|
||||||
// Indicates when the current title number changes. Title numbers
|
|
||||||
// range 1 to 99. This indicates the TTN, which is the title number
|
|
||||||
// with respect to the whole disc, not the VTS_TTN which is the title
|
|
||||||
// number with respect to just a current VTS.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_DVD_CHAPTER_START (EC_DVDBASE + 0x03)
|
|
||||||
// Parameters: ( DWORD, void )
|
|
||||||
// lParam1 is the new chapter number (which is the program number for
|
|
||||||
// One_Sequential_PGC_Titles).
|
|
||||||
//
|
|
||||||
// Raised from following domains: DVD_DOMAIN_Title
|
|
||||||
//
|
|
||||||
// Signales that DVD player started playback of a new program in the Title
|
|
||||||
// domain. This is only signaled for One_Sequential_PGC_Titles.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_DVD_AUDIO_STREAM_CHANGE (EC_DVDBASE + 0x04)
|
|
||||||
// Parameters: ( DWORD, void )
|
|
||||||
// lParam1 is the new user audio stream number.
|
|
||||||
//
|
|
||||||
// Raised from following domains: all
|
|
||||||
//
|
|
||||||
// Signaled when ever the current user audio stream number changes for the main
|
|
||||||
// title. This can be changed automatically with a navigation command on disc
|
|
||||||
// as well as through IDVDAnnexJ.
|
|
||||||
// Audio stream numbers range from 0 to 7. Stream 0xffffffff
|
|
||||||
// indicates that no stream is selected.
|
|
||||||
|
|
||||||
#define EC_DVD_SUBPICTURE_STREAM_CHANGE (EC_DVDBASE + 0x05)
|
|
||||||
// Parameters: ( DWORD, BOOL )
|
|
||||||
// lParam1 is the new user subpicture stream number.
|
|
||||||
// lParam2 is the subpicture's on/off state (TRUE if on)
|
|
||||||
//
|
|
||||||
// Raised from following domains: all
|
|
||||||
//
|
|
||||||
// Signaled when ever the current user subpicture stream number changes for the main
|
|
||||||
// title. This can be changed automatically with a navigation command on disc
|
|
||||||
// as well as through IDVDAnnexJ.
|
|
||||||
// Subpicture stream numbers range from 0 to 31. Stream 0xffffffff
|
|
||||||
// indicates that no stream is selected.
|
|
||||||
|
|
||||||
#define EC_DVD_ANGLE_CHANGE (EC_DVDBASE + 0x06)
|
|
||||||
// Parameters: ( DWORD, DWORD )
|
|
||||||
// lParam1 is the number of available angles.
|
|
||||||
// lParam2 is the current user angle number.
|
|
||||||
//
|
|
||||||
// Raised from following domains: all
|
|
||||||
//
|
|
||||||
// Signaled when ever either
|
|
||||||
// a) the number of available angles changes, or
|
|
||||||
// b) the current user angle number changes.
|
|
||||||
// Current angle number can be changed automatically with navigation command
|
|
||||||
// on disc as well as through IDVDAnnexJ.
|
|
||||||
// When the number of available angles is 1, the current video is not multiangle.
|
|
||||||
// Angle numbers range from 1 to 9.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_DVD_BUTTON_CHANGE (EC_DVDBASE + 0x07)
|
|
||||||
// Parameters: ( DWORD, DWORD )
|
|
||||||
// lParam1 is the number of available buttons.
|
|
||||||
// lParam2 is the current selected button number.
|
|
||||||
//
|
|
||||||
// Raised from following domains: all
|
|
||||||
//
|
|
||||||
// Signaled when ever either
|
|
||||||
// a) the number of available buttons changes, or
|
|
||||||
// b) the current selected button number changes.
|
|
||||||
// The current selected button can be changed automatically with navigation
|
|
||||||
// commands on disc as well as through IDVDAnnexJ.
|
|
||||||
// Button numbers range from 1 to 36. Selected button number 0 implies that
|
|
||||||
// no button is selected. Note that these button numbers enumerate all
|
|
||||||
// available button numbers, and do not always correspond to button numbers
|
|
||||||
// used for IDVDAnnexJ::ButtonSelectAndActivate since only a subset of buttons
|
|
||||||
// may be activated with ButtonSelectAndActivate.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_DVD_VALID_UOPS_CHANGE (EC_DVDBASE + 0x08)
|
|
||||||
// Parameters: ( DWORD, void )
|
|
||||||
// lParam1 is a VALID_UOP_SOMTHING_OR_OTHER bit-field stuct which indicates
|
|
||||||
// which IDVDAnnexJ commands are explicitly disable by the DVD disc.
|
|
||||||
//
|
|
||||||
// Raised from following domains: all
|
|
||||||
//
|
|
||||||
// Signaled when ever the available set of IDVDAnnexJ methods changes. This
|
|
||||||
// only indicates which operations are explicited disabled by the content on
|
|
||||||
// the DVD disc, and does not guarentee that it is valid to call methods
|
|
||||||
// which are not disabled. For example, if no buttons are currently present,
|
|
||||||
// IDVDAnnexJ::ButtonActivate() won't work, even though the buttons are not
|
|
||||||
// explicitly disabled.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_DVD_STILL_ON (EC_DVDBASE + 0x09)
|
|
||||||
// Parameters: ( BOOL, DWORD )
|
|
||||||
// lParam1 == 0 --> buttons are available, so StillOff won't work
|
|
||||||
// lParam1 == 1 --> no buttons available, so StillOff will work
|
|
||||||
// lParam2 indicates the number of seconds the still will last, with 0xffffffff
|
|
||||||
// indicating an infinite still (wait till button or StillOff selected).
|
|
||||||
//
|
|
||||||
// Raised from following domains: all
|
|
||||||
//
|
|
||||||
// Signaled at the beginning of any still: PGC still, Cell Still, or VOBU Still.
|
|
||||||
// Note that all combinations of buttons and still are possible (buttons on with
|
|
||||||
// still on, buttons on with still off, button off with still on, button off
|
|
||||||
// with still off).
|
|
||||||
|
|
||||||
#define EC_DVD_STILL_OFF (EC_DVDBASE + 0x0a)
|
|
||||||
// Parameters: ( void, void )
|
|
||||||
//
|
|
||||||
// Indicating that any still that is currently active
|
|
||||||
// has been released.
|
|
||||||
//
|
|
||||||
// Raised from following domains: all
|
|
||||||
//
|
|
||||||
// Signaled at the end of any still: PGC still, Cell Still, or VOBU Still.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_CURRENT_TIME (EC_DVDBASE + 0x0b)
|
|
||||||
// Parameters: ( DWORD, BOOL )
|
|
||||||
// lParam1 is a DVD_TIMECODE which indicates the current
|
|
||||||
// playback time code in a BCD HH:MM:SS:FF format.
|
|
||||||
// lParam2 == 0 --> time code is 25 frames/sec
|
|
||||||
// lParam2 == 1 --> time code is 30 frames/sec (non-drop).
|
|
||||||
// lParam2 == 2 --> time code is invalid (current playback time
|
|
||||||
// cannot be determined for current title)
|
|
||||||
//
|
|
||||||
// Raised from following domains: DVD_DOMAIN_Title
|
|
||||||
//
|
|
||||||
// Signaled at the beginning of every VOBU, which occurs every .4 to 1.0 sec.
|
|
||||||
// This is only signaled for One_Sequential_PGC_Titles.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_DVD_ERROR (EC_DVDBASE + 0x0c)
|
|
||||||
// Parameters: ( DWORD, void)
|
|
||||||
// lParam1 is an enum DVD_ERROR which notifies the app of some error condition.
|
|
||||||
//
|
|
||||||
// Raised from following domains: all
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_WARNING (EC_DVDBASE + 0x0d)
|
|
||||||
// Parameters: ( DWORD, DWORD)
|
|
||||||
// lParam1 is an enum DVD_WARNING which notifies the app of some warning condition.
|
|
||||||
// lParam2 contains more specific information about the warning (warning dependent)
|
|
||||||
//
|
|
||||||
// Raised from following domains: all
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_CHAPTER_AUTOSTOP (EC_DVDBASE + 0x0e)
|
|
||||||
// Parameters: (BOOL, void)
|
|
||||||
// lParam1 is a BOOL which indicates the reason for the cancellation of ChapterPlayAutoStop
|
|
||||||
// lParam1 == 0 indicates successful completion of ChapterPlayAutoStop
|
|
||||||
// lParam1 == 1 indicates that ChapterPlayAutoStop is being cancelled as a result of another
|
|
||||||
// IDVDControl call or the end of content has been reached & no more chapters
|
|
||||||
// can be played.
|
|
||||||
// Indicating that playback is stopped as a result of a call
|
|
||||||
// to IDVDControl::ChapterPlayAutoStop()
|
|
||||||
//
|
|
||||||
// Raised from following domains : DVD_DOMAIN_TITLE
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_NO_FP_PGC (EC_DVDBASE + 0x0f)
|
|
||||||
// Parameters : (void, void)
|
|
||||||
//
|
|
||||||
// Raised from the following domains : FP_DOM
|
|
||||||
//
|
|
||||||
// Indicates that the DVD disc does not have a FP_PGC (First Play Program Chain)
|
|
||||||
// and the DVD Navigator will not automatically load any PGC and start playback.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_PLAYBACK_RATE_CHANGE (EC_DVDBASE + 0x10)
|
|
||||||
// Parameters : (LONG, void)
|
|
||||||
// lParam1 is a LONG indicating the new playback rate.
|
|
||||||
// lParam1 < 0 indicates reverse playback mode.
|
|
||||||
// lParam1 > 0 indicates forward playback mode
|
|
||||||
// Value of lParam1 is the actual playback rate multiplied by 10000.
|
|
||||||
// i.e. lParam1 = rate * 10000
|
|
||||||
//
|
|
||||||
// Raised from the following domains : TT_DOM
|
|
||||||
//
|
|
||||||
// Indicates that a rate change in playback has been initiated and the parameter
|
|
||||||
// lParam1 indicates the new playback rate that is being used.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_PARENTAL_LEVEL_CHANGE (EC_DVDBASE + 0x11)
|
|
||||||
// Parameters : (LONG, void)
|
|
||||||
// lParam1 is a LONG indicating the new parental level.
|
|
||||||
//
|
|
||||||
// Raised from the following domains : VMGM_DOM
|
|
||||||
//
|
|
||||||
// Indicates that an authored Nav command has changed the parental level
|
|
||||||
// setting in the player.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_PLAYBACK_STOPPED (EC_DVDBASE + 0x12)
|
|
||||||
// Parameters : (DWORD, void)
|
|
||||||
//
|
|
||||||
// Raised from the following domains : All Domains
|
|
||||||
//
|
|
||||||
// Indicates that playback has been stopped as the Navigator has completed
|
|
||||||
// playback of the pgc and did not find any other branching instruction for
|
|
||||||
// subsequent playback.
|
|
||||||
//
|
|
||||||
// The DWORD returns the reason for the completion of the playback. See
|
|
||||||
// The DVD_PB_STOPPED enumeration for details.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_ANGLES_AVAILABLE (EC_DVDBASE + 0x13)
|
|
||||||
// Parameters : (BOOL, void)
|
|
||||||
// lParam1 == 0 indicates that playback is not in an angle block and angles are
|
|
||||||
// not available
|
|
||||||
// lParam1 == 1 indicates that an angle block is being played back and angle changes
|
|
||||||
// can be performed.
|
|
||||||
//
|
|
||||||
// Indicates whether an angle block is being played and if angle changes can be
|
|
||||||
// performed. However, angle changes are not restricted to angle blocks and the
|
|
||||||
// manifestation of the angle change can be seen only in an angle block.
|
|
||||||
|
|
||||||
#define EC_DVD_PLAYPERIOD_AUTOSTOP (EC_DVDBASE + 0x14)
|
|
||||||
// Parameters: (void, void)
|
|
||||||
// Sent when the PlayPeriodInTitle completes or is cancelled
|
|
||||||
//
|
|
||||||
// Raised from following domains : DVD_DOMAIN_TITLE
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_BUTTON_AUTO_ACTIVATED (EC_DVDBASE + 0x15)
|
|
||||||
// Parameters: (DWORD button, void)
|
|
||||||
// Sent when a button is automatically activated
|
|
||||||
//
|
|
||||||
// Raised from following domains : DVD_DOMAIN_MENU
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_CMD_START (EC_DVDBASE + 0x16)
|
|
||||||
// Parameters: (CmdID, HRESULT)
|
|
||||||
// Sent when a command begins
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_CMD_END (EC_DVDBASE + 0x17)
|
|
||||||
// Parameters: (CmdID, HRESULT)
|
|
||||||
// Sent when a command completes
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_DISC_EJECTED (EC_DVDBASE + 0x18)
|
|
||||||
// Parameters: none
|
|
||||||
// Sent when the nav detects that a disc was ejected and stops the playback
|
|
||||||
// The app does not need to take any action to stop the playback.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_DISC_INSERTED (EC_DVDBASE + 0x19)
|
|
||||||
// Parameters: none
|
|
||||||
// Sent when the nav detects that a disc was inserted and the nav begins playback
|
|
||||||
// The app does not need to take any action to start the playback.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define EC_DVD_CURRENT_HMSF_TIME (EC_DVDBASE + 0x1a)
|
|
||||||
// Parameters: ( ULONG, ULONG )
|
|
||||||
// lParam2 contains a union of the DVD_TIMECODE_FLAGS
|
|
||||||
// lParam1 contains a DVD_HMSF_TIMECODE. Assign lParam1 to a ULONG then cast the
|
|
||||||
// ULONG as a DVD_HMSF_TIMECODE to use its values.
|
|
||||||
//
|
|
||||||
// Raised from following domains: DVD_DOMAIN_Title
|
|
||||||
//
|
|
||||||
// Signaled at the beginning of every VOBU, which occurs every .4 to 1.0 sec.
|
|
||||||
|
|
||||||
#define EC_DVD_KARAOKE_MODE (EC_DVDBASE + 0x1b)
|
|
||||||
// Parameters: ( BOOL, reserved )
|
|
||||||
// lParam1 is either TRUE (a karaoke track is being played) or FALSE (no karaoke data is being played).
|
|
||||||
//
|
|
||||||
#endif // __DVDEVCOD__
|
|
|
@ -1,427 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: DVDMedia.h
|
|
||||||
//
|
|
||||||
// Desc: Contains typedefs and defines necessary for user mode (ring 3) DVD
|
|
||||||
// filters and applications.
|
|
||||||
//
|
|
||||||
// This should be included in the DirectShow SDK for user mode filters.
|
|
||||||
// The types defined here should be kept in synch with ksmedia.h WDM
|
|
||||||
// DDK for kernel mode filters.
|
|
||||||
//
|
|
||||||
// Copyright (c) 1997 - 2001, Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __DVDMEDIA_H__
|
|
||||||
#define __DVDMEDIA_H__
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// AC-3 definition for the AM_KSPROPSETID_AC3 property set
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
AM_PROPERTY_AC3_ERROR_CONCEALMENT = 1,
|
|
||||||
AM_PROPERTY_AC3_ALTERNATE_AUDIO = 2,
|
|
||||||
AM_PROPERTY_AC3_DOWNMIX = 3,
|
|
||||||
AM_PROPERTY_AC3_BIT_STREAM_MODE = 4,
|
|
||||||
AM_PROPERTY_AC3_DIALOGUE_LEVEL = 5,
|
|
||||||
AM_PROPERTY_AC3_LANGUAGE_CODE = 6,
|
|
||||||
AM_PROPERTY_AC3_ROOM_TYPE = 7
|
|
||||||
} AM_PROPERTY_AC3;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
BOOL fRepeatPreviousBlock;
|
|
||||||
BOOL fErrorInCurrentBlock;
|
|
||||||
} AM_AC3_ERROR_CONCEALMENT, *PAM_AC3_ERROR_CONCEALMENT;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
BOOL fStereo;
|
|
||||||
ULONG DualMode;
|
|
||||||
} AM_AC3_ALTERNATE_AUDIO, *PAM_AC3_ALTERNATE_AUDIO;
|
|
||||||
|
|
||||||
#define AM_AC3_ALTERNATE_AUDIO_1 1
|
|
||||||
#define AM_AC3_ALTERNATE_AUDIO_2 2
|
|
||||||
#define AM_AC3_ALTERNATE_AUDIO_BOTH 3
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
BOOL fDownMix;
|
|
||||||
BOOL fDolbySurround;
|
|
||||||
} AM_AC3_DOWNMIX, *PAM_AC3_DOWNMIX;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
LONG BitStreamMode;
|
|
||||||
} AM_AC3_BIT_STREAM_MODE, *PAM_AC3_BIT_STREAM_MODE;
|
|
||||||
|
|
||||||
#define AM_AC3_SERVICE_MAIN_AUDIO 0
|
|
||||||
#define AM_AC3_SERVICE_NO_DIALOG 1
|
|
||||||
#define AM_AC3_SERVICE_VISUALLY_IMPAIRED 2
|
|
||||||
#define AM_AC3_SERVICE_HEARING_IMPAIRED 3
|
|
||||||
#define AM_AC3_SERVICE_DIALOG_ONLY 4
|
|
||||||
#define AM_AC3_SERVICE_COMMENTARY 5
|
|
||||||
#define AM_AC3_SERVICE_EMERGENCY_FLASH 6
|
|
||||||
#define AM_AC3_SERVICE_VOICE_OVER 7
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ULONG DialogueLevel;
|
|
||||||
} AM_AC3_DIALOGUE_LEVEL, *PAM_AC3_DIALOGUE_LEVEL;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
BOOL fLargeRoom;
|
|
||||||
} AM_AC3_ROOM_TYPE, *PAM_AC3_ROOM_TYPE;
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// subpicture definition for the AM_KSPROPSETID_DvdSubPic property set
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
AM_PROPERTY_DVDSUBPIC_PALETTE = 0,
|
|
||||||
AM_PROPERTY_DVDSUBPIC_HLI = 1,
|
|
||||||
AM_PROPERTY_DVDSUBPIC_COMPOSIT_ON = 2 // TRUE for subpicture is displayed
|
|
||||||
} AM_PROPERTY_DVDSUBPIC;
|
|
||||||
|
|
||||||
typedef struct _AM_DVD_YUV {
|
|
||||||
UCHAR Reserved;
|
|
||||||
UCHAR Y;
|
|
||||||
UCHAR U;
|
|
||||||
UCHAR V;
|
|
||||||
} AM_DVD_YUV, *PAM_DVD_YUV;
|
|
||||||
|
|
||||||
typedef struct _AM_PROPERTY_SPPAL {
|
|
||||||
AM_DVD_YUV sppal[16];
|
|
||||||
} AM_PROPERTY_SPPAL, *PAM_PROPERTY_SPPAL;
|
|
||||||
|
|
||||||
typedef struct _AM_COLCON {
|
|
||||||
UCHAR emph1col:4;
|
|
||||||
UCHAR emph2col:4;
|
|
||||||
UCHAR backcol:4;
|
|
||||||
UCHAR patcol:4;
|
|
||||||
UCHAR emph1con:4;
|
|
||||||
UCHAR emph2con:4;
|
|
||||||
UCHAR backcon:4;
|
|
||||||
UCHAR patcon:4;
|
|
||||||
|
|
||||||
} AM_COLCON, *PAM_COLCON;
|
|
||||||
|
|
||||||
typedef struct _AM_PROPERTY_SPHLI {
|
|
||||||
USHORT HLISS; //
|
|
||||||
USHORT Reserved;
|
|
||||||
ULONG StartPTM; // start presentation time in x/90000
|
|
||||||
ULONG EndPTM; // end PTM in x/90000
|
|
||||||
USHORT StartX;
|
|
||||||
USHORT StartY;
|
|
||||||
USHORT StopX;
|
|
||||||
USHORT StopY;
|
|
||||||
AM_COLCON ColCon; // color contrast description (4 bytes as given in HLI)
|
|
||||||
} AM_PROPERTY_SPHLI, *PAM_PROPERTY_SPHLI;
|
|
||||||
|
|
||||||
typedef BOOL AM_PROPERTY_COMPOSIT_ON, *PAM_PROPERTY_COMPOSIT_ON;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// copy protection definitions
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
// AM_UseNewCSSKey for the dwTypeSpecificFlags in IMediaSample2 to indicate
|
|
||||||
// the exact point in a stream after which to start applying a new CSS key.
|
|
||||||
// This is typically sent on an empty media sample just before attempting
|
|
||||||
// to renegotiate a CSS key.
|
|
||||||
#define AM_UseNewCSSKey 0x1
|
|
||||||
|
|
||||||
//
|
|
||||||
// AM_KSPROPSETID_CopyProt property set definitions
|
|
||||||
//
|
|
||||||
typedef enum {
|
|
||||||
AM_PROPERTY_DVDCOPY_CHLG_KEY = 0x01,
|
|
||||||
AM_PROPERTY_DVDCOPY_DVD_KEY1 = 0x02,
|
|
||||||
AM_PROPERTY_DVDCOPY_DEC_KEY2 = 0x03,
|
|
||||||
AM_PROPERTY_DVDCOPY_TITLE_KEY = 0x04,
|
|
||||||
AM_PROPERTY_COPY_MACROVISION = 0x05,
|
|
||||||
AM_PROPERTY_DVDCOPY_REGION = 0x06,
|
|
||||||
AM_PROPERTY_DVDCOPY_SET_COPY_STATE = 0x07,
|
|
||||||
AM_PROPERTY_DVDCOPY_DISC_KEY = 0x80
|
|
||||||
} AM_PROPERTY_DVDCOPYPROT;
|
|
||||||
|
|
||||||
typedef struct _AM_DVDCOPY_CHLGKEY {
|
|
||||||
BYTE ChlgKey[10];
|
|
||||||
BYTE Reserved[2];
|
|
||||||
} AM_DVDCOPY_CHLGKEY, *PAM_DVDCOPY_CHLGKEY;
|
|
||||||
|
|
||||||
typedef struct _AM_DVDCOPY_BUSKEY {
|
|
||||||
BYTE BusKey[5];
|
|
||||||
BYTE Reserved[1];
|
|
||||||
} AM_DVDCOPY_BUSKEY, *PAM_DVDCOPY_BUSKEY;
|
|
||||||
|
|
||||||
typedef struct _AM_DVDCOPY_DISCKEY {
|
|
||||||
BYTE DiscKey[2048];
|
|
||||||
} AM_DVDCOPY_DISCKEY, *PAM_DVDCOPY_DISCKEY;
|
|
||||||
|
|
||||||
typedef struct AM_DVDCOPY_TITLEKEY {
|
|
||||||
ULONG KeyFlags;
|
|
||||||
ULONG Reserved1[2];
|
|
||||||
UCHAR TitleKey[6];
|
|
||||||
UCHAR Reserved2[2];
|
|
||||||
} AM_DVDCOPY_TITLEKEY, *PAM_DVDCOPY_TITLEKEY;
|
|
||||||
|
|
||||||
typedef struct _AM_COPY_MACROVISION {
|
|
||||||
ULONG MACROVISIONLevel;
|
|
||||||
} AM_COPY_MACROVISION, *PAM_COPY_MACROVISION;
|
|
||||||
|
|
||||||
typedef struct AM_DVDCOPY_SET_COPY_STATE {
|
|
||||||
ULONG DVDCopyState;
|
|
||||||
} AM_DVDCOPY_SET_COPY_STATE, *PAM_DVDCOPY_SET_COPY_STATE;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
AM_DVDCOPYSTATE_INITIALIZE = 0,
|
|
||||||
AM_DVDCOPYSTATE_INITIALIZE_TITLE = 1, // indicates we are starting a title
|
|
||||||
// key copy protection sequence
|
|
||||||
AM_DVDCOPYSTATE_AUTHENTICATION_NOT_REQUIRED = 2,
|
|
||||||
AM_DVDCOPYSTATE_AUTHENTICATION_REQUIRED = 3,
|
|
||||||
AM_DVDCOPYSTATE_DONE = 4
|
|
||||||
} AM_DVDCOPYSTATE;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
AM_MACROVISION_DISABLED = 0,
|
|
||||||
AM_MACROVISION_LEVEL1 = 1,
|
|
||||||
AM_MACROVISION_LEVEL2 = 2,
|
|
||||||
AM_MACROVISION_LEVEL3 = 3
|
|
||||||
} AM_COPY_MACROVISION_LEVEL, *PAM_COPY_MACROVISION_LEVEL;
|
|
||||||
|
|
||||||
|
|
||||||
// CSS region stucture
|
|
||||||
typedef struct _DVD_REGION {
|
|
||||||
UCHAR CopySystem;
|
|
||||||
UCHAR RegionData;
|
|
||||||
UCHAR SystemRegion;
|
|
||||||
UCHAR Reserved;
|
|
||||||
} DVD_REGION, *PDVD_REGION;
|
|
||||||
|
|
||||||
//
|
|
||||||
// CGMS Copy Protection Flags
|
|
||||||
//
|
|
||||||
|
|
||||||
#define AM_DVD_CGMS_RESERVED_MASK 0x00000078
|
|
||||||
|
|
||||||
#define AM_DVD_CGMS_COPY_PROTECT_MASK 0x00000018
|
|
||||||
#define AM_DVD_CGMS_COPY_PERMITTED 0x00000000
|
|
||||||
#define AM_DVD_CGMS_COPY_ONCE 0x00000010
|
|
||||||
#define AM_DVD_CGMS_NO_COPY 0x00000018
|
|
||||||
|
|
||||||
#define AM_DVD_COPYRIGHT_MASK 0x00000040
|
|
||||||
#define AM_DVD_NOT_COPYRIGHTED 0x00000000
|
|
||||||
#define AM_DVD_COPYRIGHTED 0x00000040
|
|
||||||
|
|
||||||
#define AM_DVD_SECTOR_PROTECT_MASK 0x00000020
|
|
||||||
#define AM_DVD_SECTOR_NOT_PROTECTED 0x00000000
|
|
||||||
#define AM_DVD_SECTOR_PROTECTED 0x00000020
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// video format blocks
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
enum AM_MPEG2Level {
|
|
||||||
AM_MPEG2Level_Low = 1,
|
|
||||||
AM_MPEG2Level_Main = 2,
|
|
||||||
AM_MPEG2Level_High1440 = 3,
|
|
||||||
AM_MPEG2Level_High = 4
|
|
||||||
};
|
|
||||||
|
|
||||||
enum AM_MPEG2Profile {
|
|
||||||
AM_MPEG2Profile_Simple = 1,
|
|
||||||
AM_MPEG2Profile_Main = 2,
|
|
||||||
AM_MPEG2Profile_SNRScalable = 3,
|
|
||||||
AM_MPEG2Profile_SpatiallyScalable = 4,
|
|
||||||
AM_MPEG2Profile_High = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
#define AMINTERLACE_IsInterlaced 0x00000001 // if 0, other interlace bits are irrelevent
|
|
||||||
#define AMINTERLACE_1FieldPerSample 0x00000002 // else 2 fields per media sample
|
|
||||||
#define AMINTERLACE_Field1First 0x00000004 // else Field 2 is first; top field in PAL is field 1, top field in NTSC is field 2?
|
|
||||||
#define AMINTERLACE_UNUSED 0x00000008 //
|
|
||||||
#define AMINTERLACE_FieldPatternMask 0x00000030 // use this mask with AMINTERLACE_FieldPat*
|
|
||||||
#define AMINTERLACE_FieldPatField1Only 0x00000000 // stream never contains a Field2
|
|
||||||
#define AMINTERLACE_FieldPatField2Only 0x00000010 // stream never contains a Field1
|
|
||||||
#define AMINTERLACE_FieldPatBothRegular 0x00000020 // There will be a Field2 for every Field1 (required for Weave?)
|
|
||||||
#define AMINTERLACE_FieldPatBothIrregular 0x00000030 // Random pattern of Field1s and Field2s
|
|
||||||
#define AMINTERLACE_DisplayModeMask 0x000000c0
|
|
||||||
#define AMINTERLACE_DisplayModeBobOnly 0x00000000
|
|
||||||
#define AMINTERLACE_DisplayModeWeaveOnly 0x00000040
|
|
||||||
#define AMINTERLACE_DisplayModeBobOrWeave 0x00000080
|
|
||||||
|
|
||||||
#define AMCOPYPROTECT_RestrictDuplication 0x00000001 // duplication of this stream should be restricted
|
|
||||||
|
|
||||||
#define AMMPEG2_DoPanScan 0x00000001 //if set, the MPEG-2 video decoder should crop output image
|
|
||||||
// based on pan-scan vectors in picture_display_extension
|
|
||||||
// and change the picture aspect ratio accordingly.
|
|
||||||
#define AMMPEG2_DVDLine21Field1 0x00000002 //if set, the MPEG-2 decoder must be able to produce an output
|
|
||||||
// pin for DVD style closed caption data found in GOP layer of field 1
|
|
||||||
#define AMMPEG2_DVDLine21Field2 0x00000004 //if set, the MPEG-2 decoder must be able to produce an output
|
|
||||||
// pin for DVD style closed caption data found in GOP layer of field 2
|
|
||||||
#define AMMPEG2_SourceIsLetterboxed 0x00000008 //if set, indicates that black bars have been encoded in the top
|
|
||||||
// and bottom of the video.
|
|
||||||
#define AMMPEG2_FilmCameraMode 0x00000010 //if set, indicates "film mode" used for 625/50 content. If cleared,
|
|
||||||
// indicates that "camera mode" was used.
|
|
||||||
#define AMMPEG2_LetterboxAnalogOut 0x00000020 //if set and this stream is sent to an analog output, it should
|
|
||||||
// be letterboxed. Streams sent to VGA should be letterboxed only by renderers.
|
|
||||||
#define AMMPEG2_DSS_UserData 0x00000040 //if set, the MPEG-2 decoder must process DSS style user data
|
|
||||||
#define AMMPEG2_DVB_UserData 0x00000080 //if set, the MPEG-2 decoder must process DVB style user data
|
|
||||||
#define AMMPEG2_27MhzTimebase 0x00000100 //if set, the PTS,DTS timestamps advance at 27MHz rather than 90KHz
|
|
||||||
|
|
||||||
#define AMMPEG2_WidescreenAnalogOut 0x00000200 //if set and this stream is sent to an analog output, it should
|
|
||||||
// be in widescreen format (4x3 content should be centered on a 16x9 output).
|
|
||||||
// Streams sent to VGA should be widescreened only by renderers.
|
|
||||||
|
|
||||||
// PRESENT in dwReserved1 field in VIDEOINFOHEADER2
|
|
||||||
#define AMCONTROL_USED 0x00000001 // Used to test if these flags are supported. Set and test for AcceptMediaType.
|
|
||||||
// If rejected, then you cannot use the AMCONTROL flags (send 0 for dwReserved1)
|
|
||||||
#define AMCONTROL_PAD_TO_4x3 0x00000002 // if set means display the image in a 4x3 area
|
|
||||||
#define AMCONTROL_PAD_TO_16x9 0x00000004 // if set means display the image in a 16x9 area
|
|
||||||
|
|
||||||
typedef struct tagVIDEOINFOHEADER2 {
|
|
||||||
RECT rcSource;
|
|
||||||
RECT rcTarget;
|
|
||||||
DWORD dwBitRate;
|
|
||||||
DWORD dwBitErrorRate;
|
|
||||||
REFERENCE_TIME AvgTimePerFrame;
|
|
||||||
DWORD dwInterlaceFlags; // use AMINTERLACE_* defines. Reject connection if undefined bits are not 0
|
|
||||||
DWORD dwCopyProtectFlags; // use AMCOPYPROTECT_* defines. Reject connection if undefined bits are not 0
|
|
||||||
DWORD dwPictAspectRatioX; // X dimension of picture aspect ratio, e.g. 16 for 16x9 display
|
|
||||||
DWORD dwPictAspectRatioY; // Y dimension of picture aspect ratio, e.g. 9 for 16x9 display
|
|
||||||
union {
|
|
||||||
DWORD dwControlFlags; // use AMCONTROL_* defines, use this from now on
|
|
||||||
DWORD dwReserved1; // for backward compatiblity (was "must be 0"; connection rejected otherwise)
|
|
||||||
};
|
|
||||||
DWORD dwReserved2; // must be 0; reject connection otherwise
|
|
||||||
BITMAPINFOHEADER bmiHeader;
|
|
||||||
} VIDEOINFOHEADER2;
|
|
||||||
|
|
||||||
typedef struct tagMPEG2VIDEOINFO {
|
|
||||||
VIDEOINFOHEADER2 hdr;
|
|
||||||
DWORD dwStartTimeCode; // ?? not used for DVD ??
|
|
||||||
DWORD cbSequenceHeader; // is 0 for DVD (no sequence header)
|
|
||||||
DWORD dwProfile; // use enum MPEG2Profile
|
|
||||||
DWORD dwLevel; // use enum MPEG2Level
|
|
||||||
DWORD dwFlags; // use AMMPEG2_* defines. Reject connection if undefined bits are not 0
|
|
||||||
DWORD dwSequenceHeader[1]; // DWORD instead of Byte for alignment purposes
|
|
||||||
// For MPEG-2, if a sequence_header is included, the sequence_extension
|
|
||||||
// should also be included
|
|
||||||
} MPEG2VIDEOINFO;
|
|
||||||
|
|
||||||
#define SIZE_MPEG2VIDEOINFO(pv) (FIELD_OFFSET(MPEG2VIDEOINFO, dwSequenceHeader[0]) + (pv)->cbSequenceHeader)
|
|
||||||
|
|
||||||
// do not use
|
|
||||||
#define MPEG1_SEQUENCE_INFO(pv) ((const BYTE *)(pv)->bSequenceHeader)
|
|
||||||
|
|
||||||
// use this macro instead, the previous only works for MPEG1VIDEOINFO structures
|
|
||||||
#define MPEG2_SEQUENCE_INFO(pv) ((const BYTE *)(pv)->dwSequenceHeader)
|
|
||||||
|
|
||||||
|
|
||||||
//===================================================================================
|
|
||||||
// flags for dwTypeSpecificFlags in AM_SAMPLE2_PROPERTIES which define type specific
|
|
||||||
// data in IMediaSample2
|
|
||||||
//===================================================================================
|
|
||||||
|
|
||||||
#define AM_VIDEO_FLAG_FIELD_MASK 0x0003L // use this mask to check whether the sample is field1 or field2 or frame
|
|
||||||
#define AM_VIDEO_FLAG_INTERLEAVED_FRAME 0x0000L // the sample is a frame (remember to use AM_VIDEO_FLAG_FIELD_MASK when using this)
|
|
||||||
#define AM_VIDEO_FLAG_FIELD1 0x0001L // the sample is field1 (remember to use AM_VIDEO_FLAG_FIELD_MASK when using this)
|
|
||||||
#define AM_VIDEO_FLAG_FIELD2 0x0002L // the sample is the field2 (remember to use AM_VIDEO_FLAG_FIELD_MASK when using this)
|
|
||||||
#define AM_VIDEO_FLAG_FIELD1FIRST 0x0004L // if set means display field1 first, else display field2 first.
|
|
||||||
// this bit is irrelavant for 1FieldPerSample mode
|
|
||||||
#define AM_VIDEO_FLAG_WEAVE 0x0008L // if set use bob display mode else weave
|
|
||||||
#define AM_VIDEO_FLAG_IPB_MASK 0x0030L // use this mask to check whether the sample is I, P or B
|
|
||||||
#define AM_VIDEO_FLAG_I_SAMPLE 0x0000L // I Sample (remember to use AM_VIDEO_FLAG_IPB_MASK when using this)
|
|
||||||
#define AM_VIDEO_FLAG_P_SAMPLE 0x0010L // P Sample (remember to use AM_VIDEO_FLAG_IPB_MASK when using this)
|
|
||||||
#define AM_VIDEO_FLAG_B_SAMPLE 0x0020L // B Sample (remember to use AM_VIDEO_FLAG_IPB_MASK when using this)
|
|
||||||
#define AM_VIDEO_FLAG_REPEAT_FIELD 0x0040L // if set means display the field which has been displayed first again after displaying
|
|
||||||
// both fields first. This bit is irrelavant for 1FieldPerSample mode
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// AM_KSPROPSETID_DvdKaraoke property set definitions
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
typedef struct tagAM_DvdKaraokeData
|
|
||||||
{
|
|
||||||
DWORD dwDownmix; // bitwise OR of AM_DvdKaraoke_Downmix flags
|
|
||||||
DWORD dwSpeakerAssignment; // AM_DvdKaraoke_SpeakerAssignment
|
|
||||||
} AM_DvdKaraokeData;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
AM_PROPERTY_DVDKARAOKE_ENABLE = 0, // BOOL
|
|
||||||
AM_PROPERTY_DVDKARAOKE_DATA = 1,
|
|
||||||
} AM_PROPERTY_DVDKARAOKE;
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// AM_KSPROPSETID_TSRateChange property set definitions for time stamp
|
|
||||||
// rate changes.
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
AM_RATE_SimpleRateChange = 1, // rw, use AM_SimpleRateChange
|
|
||||||
AM_RATE_ExactRateChange = 2, // rw, use AM_ExactRateChange
|
|
||||||
AM_RATE_MaxFullDataRate = 3, // r, use AM_MaxFullDataRate
|
|
||||||
AM_RATE_Step = 4, // w, use AM_Step
|
|
||||||
AM_RATE_UseRateVersion = 5, // w, use WORD
|
|
||||||
AM_RATE_QueryFullFrameRate =6, // r, use AM_QueryRate
|
|
||||||
AM_RATE_QueryLastRateSegPTS =7, // r, use REFERENCE_TIME
|
|
||||||
AM_RATE_CorrectTS = 8 // w, use LONG
|
|
||||||
} AM_PROPERTY_TS_RATE_CHANGE;
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
|
||||||
// AM_KSPROPSETID_DVD_RateChange property set definitions for new DVD
|
|
||||||
// rate change scheme.
|
|
||||||
// -------------------------------------------------------------------
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
AM_RATE_ChangeRate = 1, // w, use AM_DVD_ChangeRate
|
|
||||||
AM_RATE_FullDataRateMax = 2, // r, use AM_MaxFullDataRate
|
|
||||||
AM_RATE_ReverseDecode = 3, // r, use LONG
|
|
||||||
AM_RATE_DecoderPosition = 4, // r, use AM_DVD_DecoderPosition
|
|
||||||
AM_RATE_DecoderVersion = 5 // r, use LONG
|
|
||||||
} AM_PROPERTY_DVD_RATE_CHANGE;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
// this is the simplest mechanism to set a time stamp rate change on
|
|
||||||
// a filter (simplest for the person setting the rate change, harder
|
|
||||||
// for the filter doing the rate change).
|
|
||||||
REFERENCE_TIME StartTime; //stream time at which to start this rate
|
|
||||||
LONG Rate; //new rate * 10000 (decimal)
|
|
||||||
} AM_SimpleRateChange;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
LONG lMaxForwardFullFrame ; // rate * 10000
|
|
||||||
LONG lMaxReverseFullFrame ; // rate * 10000
|
|
||||||
} AM_QueryRate ;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
REFERENCE_TIME OutputZeroTime; //input TS that maps to zero output TS
|
|
||||||
LONG Rate; //new rate * 10000 (decimal)
|
|
||||||
} AM_ExactRateChange;
|
|
||||||
|
|
||||||
typedef LONG AM_MaxFullDataRate; //rate * 10000 (decimal)
|
|
||||||
|
|
||||||
typedef DWORD AM_Step; // number of frame to step
|
|
||||||
|
|
||||||
// New rate change property set, structs. enums etc.
|
|
||||||
typedef struct {
|
|
||||||
REFERENCE_TIME StartInTime; // stream time (input) at which to start decoding at this rate
|
|
||||||
REFERENCE_TIME StartOutTime; // reference time (output) at which to start showing at this rate
|
|
||||||
LONG Rate; // new rate * 10000 (decimal)
|
|
||||||
} AM_DVD_ChangeRate ;
|
|
||||||
|
|
||||||
typedef LONGLONG AM_DVD_DecoderPosition ;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
DVD_DIR_FORWARD = 0,
|
|
||||||
DVD_DIR_BACKWARD = 1
|
|
||||||
} DVD_PLAY_DIRECTION ;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif // __cplusplus
|
|
||||||
#endif // __DVDMEDIA_H__
|
|
|
@ -1,531 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: EDevDefs.h
|
|
||||||
//
|
|
||||||
// Desc: External Device (such as a VCR) control interface parameter and
|
|
||||||
// value definitions.
|
|
||||||
//
|
|
||||||
// Note: new constants added: ED_BASE+800L -> ED_BASE+811L
|
|
||||||
//
|
|
||||||
// Copyright (c) 1992-2001, Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __EDEVDEFS__
|
|
||||||
#define __EDEVDEFS__
|
|
||||||
|
|
||||||
|
|
||||||
#define ED_BASE 0x1000L
|
|
||||||
|
|
||||||
// this is used to tell the device communications object which
|
|
||||||
// physical communications port to use.
|
|
||||||
#define DEV_PORT_SIM 1
|
|
||||||
#define DEV_PORT_COM1 2 // standard serial ports
|
|
||||||
#define DEV_PORT_COM2 3
|
|
||||||
#define DEV_PORT_COM3 4
|
|
||||||
#define DEV_PORT_COM4 5
|
|
||||||
#define DEV_PORT_DIAQ 6 // Diaquest driver
|
|
||||||
#define DEV_PORT_ARTI 7 // ARTI driver
|
|
||||||
#define DEV_PORT_1394 8 // IEEE 1394 Bus
|
|
||||||
#define DEV_PORT_USB 9 // Universal Serial Bus
|
|
||||||
#define DEV_PORT_MIN DEV_PORT_SIM
|
|
||||||
#define DEV_PORT_MAX DEV_PORT_USB
|
|
||||||
|
|
||||||
|
|
||||||
// IAMExtDevice Capability Items: unless otherwise specified, these items return
|
|
||||||
// OATRUE or OAFALSE. All return values are in pdwValue unless otherwise specified:
|
|
||||||
|
|
||||||
#define ED_DEVCAP_CAN_RECORD ED_BASE+1L
|
|
||||||
#define ED_DEVCAP_CAN_RECORD_STROBE ED_BASE+2L // for multitrack devices:
|
|
||||||
// switches currently recording tracks off
|
|
||||||
// and selected non-recording tracks into record
|
|
||||||
#define ED_DEVCAP_HAS_AUDIO ED_BASE+3L
|
|
||||||
#define ED_DEVCAP_HAS_VIDEO ED_BASE+4L
|
|
||||||
#define ED_DEVCAP_USES_FILES ED_BASE+5L
|
|
||||||
#define ED_DEVCAP_CAN_SAVE ED_BASE+6L
|
|
||||||
|
|
||||||
#define ED_DEVCAP_DEVICE_TYPE ED_BASE+7L // returns one of the following:
|
|
||||||
#define ED_DEVTYPE_VCR ED_BASE+8L
|
|
||||||
#define ED_DEVTYPE_LASERDISK ED_BASE+9L
|
|
||||||
#define ED_DEVTYPE_ATR ED_BASE+10L
|
|
||||||
#define ED_DEVTYPE_DDR ED_BASE+11L
|
|
||||||
#define ED_DEVTYPE_ROUTER ED_BASE+12L
|
|
||||||
#define ED_DEVTYPE_KEYER ED_BASE+13L
|
|
||||||
#define ED_DEVTYPE_MIXER_VIDEO ED_BASE+14L
|
|
||||||
#define ED_DEVTYPE_DVE ED_BASE+15L
|
|
||||||
#define ED_DEVTYPE_WIPEGEN ED_BASE+16L
|
|
||||||
#define ED_DEVTYPE_MIXER_AUDIO ED_BASE+17L
|
|
||||||
#define ED_DEVTYPE_CG ED_BASE+18L
|
|
||||||
#define ED_DEVTYPE_TBC ED_BASE+19L
|
|
||||||
#define ED_DEVTYPE_TCG ED_BASE+20L
|
|
||||||
#define ED_DEVTYPE_GPI ED_BASE+21L
|
|
||||||
#define ED_DEVTYPE_JOYSTICK ED_BASE+22L
|
|
||||||
#define ED_DEVTYPE_KEYBOARD ED_BASE+23L
|
|
||||||
|
|
||||||
// returns mfr-specific ID from external device.
|
|
||||||
#define ED_DEVCAP_EXTERNAL_DEVICE_ID ED_BASE+24L
|
|
||||||
|
|
||||||
#define ED_DEVCAP_TIMECODE_READ ED_BASE+25L
|
|
||||||
#define ED_DEVCAP_TIMECODE_WRITE ED_BASE+26L
|
|
||||||
// used for seekable non-timecode enabled devices
|
|
||||||
#define ED_DEVCAP_CTLTRK_READ ED_BASE+27L
|
|
||||||
// used for seekable non-timecode enabled devices
|
|
||||||
#define ED_DEVCAP_INDEX_READ ED_BASE+28L
|
|
||||||
|
|
||||||
// returns device preroll time in current time format
|
|
||||||
#define ED_DEVCAP_PREROLL ED_BASE+29L
|
|
||||||
// returns device postroll time in current time format
|
|
||||||
#define ED_DEVCAP_POSTROLL ED_BASE+30L
|
|
||||||
|
|
||||||
// returns indication of device’s synchronization accuracy.
|
|
||||||
#define ED_DEVCAP_SYNC_ACCURACY ED_BASE+31L // returns one of the following:
|
|
||||||
#define ED_SYNCACC_PRECISE ED_BASE+32L
|
|
||||||
#define ED_SYNCACC_FRAME ED_BASE+33L
|
|
||||||
#define ED_SYNCACC_ROUGH ED_BASE+34L
|
|
||||||
|
|
||||||
// returns device’s normal framerate.
|
|
||||||
#define ED_DEVCAP_NORMAL_RATE ED_BASE+35L // returns one of the following:
|
|
||||||
#define ED_RATE_24 ED_BASE+36L
|
|
||||||
#define ED_RATE_25 ED_BASE+37L
|
|
||||||
#define ED_RATE_2997 ED_BASE+38L
|
|
||||||
#define ED_RATE_30 ED_BASE+39L
|
|
||||||
|
|
||||||
#define ED_DEVCAP_CAN_PREVIEW ED_BASE+40L
|
|
||||||
#define ED_DEVCAP_CAN_MONITOR_SOURCES ED_BASE+41L
|
|
||||||
|
|
||||||
// indicates implementation allows testing of methods/parameters by
|
|
||||||
// setting the hi bit of a parm that makes sense - see individual methods
|
|
||||||
// for details.
|
|
||||||
#define ED_DEVCAP_CAN_TEST ED_BASE+42L
|
|
||||||
|
|
||||||
// indicates device accepts video as an input.
|
|
||||||
#define ED_DEVCAP_VIDEO_INPUTS ED_BASE+43L
|
|
||||||
|
|
||||||
// indicates device accepts audio as an input.
|
|
||||||
#define ED_DEVCAP_AUDIO_INPUTS ED_BASE+44L
|
|
||||||
|
|
||||||
#define ED_DEVCAP_NEEDS_CALIBRATING ED_BASE+45L
|
|
||||||
|
|
||||||
#define ED_DEVCAP_SEEK_TYPE ED_BASE+46L // returns one of the following:
|
|
||||||
#define ED_SEEK_PERFECT ED_BASE+47L // indicates device can execute seek
|
|
||||||
// within 1 video frames without signal
|
|
||||||
// break (like a DDR)
|
|
||||||
#define ED_SEEK_FAST ED_BASE+48L // indicates device can move pretty quick
|
|
||||||
// with short break in signal
|
|
||||||
#define ED_SEEK_SLOW ED_BASE+49L // seeks like a tape transport
|
|
||||||
|
|
||||||
#define ED_POWER_ON ED_BASE+50L
|
|
||||||
#define ED_POWER_OFF ED_BASE+51L
|
|
||||||
#define ED_POWER_STANDBY ED_BASE+52L
|
|
||||||
|
|
||||||
#define ED_ACTIVE ED_BASE+53L
|
|
||||||
#define ED_INACTIVE ED_BASE+54L
|
|
||||||
#define ED_ALL ED_BASE+55L
|
|
||||||
#define ED_TEST ED_BASE+56L
|
|
||||||
|
|
||||||
// IAMExtTransport Capability Items: unless otherwise specified, these items return
|
|
||||||
// OATRUE or OAFALSE. All return values are in pdwValue unless otherwise specified:
|
|
||||||
|
|
||||||
#define ED_TRANSCAP_CAN_EJECT ED_BASE+100L
|
|
||||||
#define ED_TRANSCAP_CAN_BUMP_PLAY ED_BASE+101L // variable speed for synchronizing
|
|
||||||
#define ED_TRANSCAP_CAN_PLAY_BACKWARDS ED_BASE+102L // servo locked for use during an edit
|
|
||||||
#define ED_TRANSCAP_CAN_SET_EE ED_BASE+103L // show device’s input on its output
|
|
||||||
#define ED_TRANSCAP_CAN_SET_PB ED_BASE+104L // show media playback on device’s output
|
|
||||||
#define ED_TRANSCAP_CAN_DELAY_VIDEO_IN ED_BASE+105L // transport can do delayed-in video edits
|
|
||||||
#define ED_TRANSCAP_CAN_DELAY_VIDEO_OUT ED_BASE+106L // transport can do delayed-out video edits
|
|
||||||
#define ED_TRANSCAP_CAN_DELAY_AUDIO_IN ED_BASE+107L // transport can do delayed-in audio edits
|
|
||||||
#define ED_TRANSCAP_CAN_DELAY_AUDIO_OUT ED_BASE+108L // transport can do delayed-out audio edits
|
|
||||||
#define ED_TRANSCAP_FWD_VARIABLE_MAX ED_BASE+109L // max forward speed (multiple of play speed)
|
|
||||||
// in pdblValue
|
|
||||||
#define ED_TRANSCAP_FWD_VARIABLE_MIN ED_BASE+800L // min forward speed (multiple of play speed)
|
|
||||||
// in pdblValue
|
|
||||||
#define ED_TRANSCAP_REV_VARIABLE_MAX ED_BASE+110L // max reverse speed (multiple of play speed) in
|
|
||||||
// pdblValue
|
|
||||||
#define ED_TRANSCAP_REV_VARIABLE_MIN ED_BASE+801L // min reverse speed (multiple of play speed)
|
|
||||||
// in pdblValue
|
|
||||||
#define ED_TRANSCAP_FWD_SHUTTLE_MAX ED_BASE+802L // max forward speed in Shuttle mode (multiple
|
|
||||||
// of play speed) in pdblValue
|
|
||||||
#define ED_TRANSCAP_FWD_SHUTTLE_MIN ED_BASE+803L // min forward speed in Shuttle mode (multiple
|
|
||||||
// of play speed) in pdblValue
|
|
||||||
#define ED_TRANSCAP_REV_SHUTTLE_MAX ED_BASE+804L // max reverse speed in Shuttle mode (multiple
|
|
||||||
// of play speed) in pdblValue
|
|
||||||
#define ED_TRANSCAP_REV_SHUTTLE_MIN ED_BASE+805L // min reverse speed in Shuttle mode (multiple
|
|
||||||
// of play speed) in pdblValue
|
|
||||||
#define ED_TRANSCAP_NUM_AUDIO_TRACKS ED_BASE+111L // returns number of audio tracks
|
|
||||||
#define ED_TRANSCAP_LTC_TRACK ED_BASE+112L // returns track number of LTC timecode track.
|
|
||||||
// ED_ALL means no dedicated timecode track
|
|
||||||
#define ED_TRANSCAP_NEEDS_TBC ED_BASE+113L // device’s output not stable
|
|
||||||
#define ED_TRANSCAP_NEEDS_CUEING ED_BASE+114L // device must be cued prior to performing edit
|
|
||||||
#define ED_TRANSCAP_CAN_INSERT ED_BASE+115L
|
|
||||||
#define ED_TRANSCAP_CAN_ASSEMBLE ED_BASE+116L
|
|
||||||
#define ED_TRANSCAP_FIELD_STEP ED_BASE+117L // device responds to Frame Advance command by
|
|
||||||
// advancing one field
|
|
||||||
#define ED_TRANSCAP_CLOCK_INC_RATE ED_BASE+118L // VISCA command - keep for compatibility
|
|
||||||
#define ED_TRANSCAP_CAN_DETECT_LENGTH ED_BASE+119L
|
|
||||||
#define ED_TRANSCAP_CAN_FREEZE ED_BASE+120L
|
|
||||||
#define ED_TRANSCAP_HAS_TUNER ED_BASE+121L
|
|
||||||
#define ED_TRANSCAP_HAS_TIMER ED_BASE+122L
|
|
||||||
#define ED_TRANSCAP_HAS_CLOCK ED_BASE+123L
|
|
||||||
#define ED_TRANSCAP_MULTIPLE_EDITS ED_BASE+806L // OATRUE means device/filter can support
|
|
||||||
// multiple edit events
|
|
||||||
#define ED_TRANSCAP_IS_MASTER ED_BASE+807L // OATRUE means device is the master clock
|
|
||||||
// for synchronizing (this sets timecode-to-
|
|
||||||
// reference clock offset for editing)
|
|
||||||
#define ED_TRANSCAP_HAS_DT ED_BASE+814L // OATRUE means device has Dynamic Tracking
|
|
||||||
|
|
||||||
// IAMExtTransport Media States
|
|
||||||
#define ED_MEDIA_SPIN_UP ED_BASE+130L
|
|
||||||
#define ED_MEDIA_SPIN_DOWN ED_BASE+131L
|
|
||||||
#define ED_MEDIA_UNLOAD ED_BASE+132L
|
|
||||||
|
|
||||||
// IAMExtTransport Modes
|
|
||||||
#define ED_MODE_PLAY ED_BASE+200L
|
|
||||||
#define ED_MODE_STOP ED_BASE+201L
|
|
||||||
#define ED_MODE_FREEZE ED_BASE+202L // really "pause"
|
|
||||||
#define ED_MODE_THAW ED_BASE+203L
|
|
||||||
#define ED_MODE_FF ED_BASE+204L
|
|
||||||
#define ED_MODE_REW ED_BASE+205L
|
|
||||||
#define ED_MODE_RECORD ED_BASE+206L
|
|
||||||
#define ED_MODE_RECORD_STROBE ED_BASE+207L
|
|
||||||
#define ED_MODE_RECORD_FREEZE ED_BASE+808L // never "put", only "get"
|
|
||||||
#define ED_MODE_STEP ED_BASE+208L // same as "jog"
|
|
||||||
#define ED_MODE_STEP_FWD ED_BASE+208L // same as ED_MODE_STEP
|
|
||||||
#define ED_MODE_STEP_REV ED_BASE+809L
|
|
||||||
#define ED_MODE_SHUTTLE ED_BASE+209L
|
|
||||||
#define ED_MODE_EDIT_CUE ED_BASE+210L
|
|
||||||
#define ED_MODE_VAR_SPEED ED_BASE+211L
|
|
||||||
#define ED_MODE_PERFORM ED_BASE+212L // returned status only
|
|
||||||
#define ED_MODE_LINK_ON ED_BASE+280L
|
|
||||||
#define ED_MODE_LINK_OFF ED_BASE+281L
|
|
||||||
#define ED_MODE_NOTIFY_ENABLE ED_BASE+810L
|
|
||||||
#define ED_MODE_NOTIFY_DISABLE ED_BASE+811L
|
|
||||||
#define ED_MODE_SHOT_SEARCH ED_BASE+812L
|
|
||||||
|
|
||||||
// IAMTimecodeReader/Generator/Display defines
|
|
||||||
//
|
|
||||||
// Timecode Generator Mode params and values:
|
|
||||||
//
|
|
||||||
#define ED_TCG_TIMECODE_TYPE ED_BASE+400L // can be one of the following:
|
|
||||||
#define ED_TCG_SMPTE_LTC ED_BASE+401L
|
|
||||||
#define ED_TCG_SMPTE_VITC ED_BASE+402L
|
|
||||||
#define ED_TCG_MIDI_QF ED_BASE+403L
|
|
||||||
#define ED_TCG_MIDI_FULL ED_BASE+404L
|
|
||||||
|
|
||||||
#define ED_TCG_FRAMERATE ED_BASE+405L // can be one of the following:
|
|
||||||
#define ED_FORMAT_SMPTE_30 ED_BASE+406L
|
|
||||||
#define ED_FORMAT_SMPTE_30DROP ED_BASE+407L
|
|
||||||
#define ED_FORMAT_SMPTE_25 ED_BASE+408L
|
|
||||||
#define ED_FORMAT_SMPTE_24 ED_BASE+409L
|
|
||||||
|
|
||||||
#define ED_TCG_SYNC_SOURCE ED_BASE+410L // can be one of the following:
|
|
||||||
#define ED_TCG_VIDEO ED_BASE+411L
|
|
||||||
#define ED_TCG_READER ED_BASE+412L
|
|
||||||
#define ED_TCG_FREE ED_BASE+413L
|
|
||||||
|
|
||||||
#define ED_TCG_REFERENCE_SOURCE ED_BASE+414L // can have one these values:
|
|
||||||
// ED_TCG_FREE || ED_TCG_READER
|
|
||||||
// (for regen/jamsync)
|
|
||||||
|
|
||||||
// TimeCodeReader Mode params and values:
|
|
||||||
#define ED_TCR_SOURCE ED_BASE+416L // can be one of the following:
|
|
||||||
// ED_TCG (already defined)
|
|
||||||
#define ED_TCR_LTC ED_BASE+417L
|
|
||||||
#define ED_TCR_VITC ED_BASE+418L
|
|
||||||
#define ED_TCR_CT ED_BASE+419L // Control Track
|
|
||||||
#define ED_TCR_FTC ED_BASE+420L // File TimeCode - for file-based devices
|
|
||||||
// that wish they were transports
|
|
||||||
// ED_MODE_NOTIFY_ENABLE can be OATRUE or OAFALSE (defined in transport mode
|
|
||||||
// section of this file).
|
|
||||||
#define ED_TCR_LAST_VALUE ED_BASE+421L // for notification mode -
|
|
||||||
// successive calls to GetTimecode
|
|
||||||
// return the last read value
|
|
||||||
// TimeCode Display Mode params and values:
|
|
||||||
//
|
|
||||||
#define ED_TCD_SOURCE ED_BASE+422L // can be one of the following:
|
|
||||||
#define ED_TCR ED_BASE+423L
|
|
||||||
#define ED_TCG ED_BASE+424L
|
|
||||||
|
|
||||||
#define ED_TCD_SIZE ED_BASE+425L // can be one of the following:
|
|
||||||
#define ED_SMALL ED_BASE+426L
|
|
||||||
#define ED_MED ED_BASE+427L
|
|
||||||
#define ED_LARGE ED_BASE+428L
|
|
||||||
|
|
||||||
#define ED_TCD_POSITION ED_BASE+429L // can be one of the following:
|
|
||||||
#define ED_TOP 0x0001
|
|
||||||
#define ED_MIDDLE 0x0002
|
|
||||||
#define ED_BOTTOM 0x0004 // OR'd with
|
|
||||||
#define ED_LEFT 0x0100
|
|
||||||
#define ED_CENTER 0x0200
|
|
||||||
#define ED_RIGHT 0x0400
|
|
||||||
|
|
||||||
#define ED_TCD_INTENSITY ED_BASE+436L // can be one of the following:
|
|
||||||
#define ED_HIGH ED_BASE+437L
|
|
||||||
#define ED_LOW ED_BASE+438L
|
|
||||||
|
|
||||||
#define ED_TCD_TRANSPARENCY ED_BASE+439L // 0-4, 0 is opaque
|
|
||||||
|
|
||||||
#define ED_TCD_INVERT ED_BASE+440L // OATRUE=black on white
|
|
||||||
// OAFALSE=white on black
|
|
||||||
// IAMExtTransport defines
|
|
||||||
//
|
|
||||||
// Transport status, params and values
|
|
||||||
//
|
|
||||||
|
|
||||||
// IAMExtTransport Status items and and values:
|
|
||||||
#define ED_MODE ED_BASE+500L // see ED_MODE_xxx values above
|
|
||||||
#define ED_ERROR ED_BASE+501L
|
|
||||||
#define ED_LOCAL ED_BASE+502L
|
|
||||||
#define ED_RECORD_INHIBIT ED_BASE+503L
|
|
||||||
#define ED_SERVO_LOCK ED_BASE+504L
|
|
||||||
#define ED_MEDIA_PRESENT ED_BASE+505L
|
|
||||||
#define ED_MEDIA_LENGTH ED_BASE+506L
|
|
||||||
#define ED_MEDIA_SIZE ED_BASE+507L
|
|
||||||
#define ED_MEDIA_TRACK_COUNT ED_BASE+508L
|
|
||||||
#define ED_MEDIA_TRACK_LENGTH ED_BASE+509L
|
|
||||||
#define ED_MEDIA_SIDE ED_BASE+510L
|
|
||||||
|
|
||||||
#define ED_MEDIA_TYPE ED_BASE+511L // can be one of the following:
|
|
||||||
#define ED_MEDIA_VHS ED_BASE+512L
|
|
||||||
#define ED_MEDIA_SVHS ED_BASE+513L
|
|
||||||
#define ED_MEDIA_HI8 ED_BASE+514L
|
|
||||||
#define ED_MEDIA_UMATIC ED_BASE+515L
|
|
||||||
#define ED_MEDIA_DVC ED_BASE+516L
|
|
||||||
#define ED_MEDIA_1_INCH ED_BASE+517L
|
|
||||||
#define ED_MEDIA_D1 ED_BASE+518L
|
|
||||||
#define ED_MEDIA_D2 ED_BASE+519L
|
|
||||||
#define ED_MEDIA_D3 ED_BASE+520L
|
|
||||||
#define ED_MEDIA_D5 ED_BASE+521L
|
|
||||||
#define ED_MEDIA_DBETA ED_BASE+522L
|
|
||||||
#define ED_MEDIA_BETA ED_BASE+523L
|
|
||||||
#define ED_MEDIA_8MM ED_BASE+524L
|
|
||||||
#define ED_MEDIA_DDR ED_BASE+525L
|
|
||||||
#define ED_MEDIA_SX ED_BASE+813L
|
|
||||||
#define ED_MEDIA_OTHER ED_BASE+526L
|
|
||||||
#define ED_MEDIA_CLV ED_BASE+527L
|
|
||||||
#define ED_MEDIA_CAV ED_BASE+528L
|
|
||||||
#define ED_MEDIA_POSITION ED_BASE+529L
|
|
||||||
|
|
||||||
#define ED_LINK_MODE ED_BASE+530L // OATRUE if transport controls
|
|
||||||
// are linked to graph's RUN,
|
|
||||||
// STOP, and PAUSE methods
|
|
||||||
|
|
||||||
// IAMExtTransport Basic Parms
|
|
||||||
#define ED_TRANSBASIC_TIME_FORMAT ED_BASE+540L // can be one of the following:
|
|
||||||
#define ED_FORMAT_MILLISECONDS ED_BASE+541L
|
|
||||||
#define ED_FORMAT_FRAMES ED_BASE+542L
|
|
||||||
#define ED_FORMAT_REFERENCE_TIME ED_BASE+543L
|
|
||||||
|
|
||||||
#define ED_FORMAT_HMSF ED_BASE+547L
|
|
||||||
#define ED_FORMAT_TMSF ED_BASE+548L
|
|
||||||
|
|
||||||
#define ED_TRANSBASIC_TIME_REFERENCE ED_BASE+549L // can be one of the following:
|
|
||||||
#define ED_TIMEREF_TIMECODE ED_BASE+550L
|
|
||||||
#define ED_TIMEREF_CONTROL_TRACK ED_BASE+551L
|
|
||||||
#define ED_TIMEREF_INDEX ED_BASE+552L
|
|
||||||
|
|
||||||
#define ED_TRANSBASIC_SUPERIMPOSE ED_BASE+553L // enable/disable onscreen display
|
|
||||||
#define ED_TRANSBASIC_END_STOP_ACTION ED_BASE+554L // can be one of: ED_MODE_STOP |
|
|
||||||
// ED_MODE_REWIND | ED_MODE_FREEZE
|
|
||||||
#define ED_TRANSBASIC_RECORD_FORMAT ED_BASE+555L // can be one of the following:
|
|
||||||
#define ED_RECORD_FORMAT_SP ED_BASE+556L
|
|
||||||
#define ED_RECORD_FORMAT_LP ED_BASE+557L
|
|
||||||
#define ED_RECORD_FORMAT_EP ED_BASE+558L
|
|
||||||
|
|
||||||
#define ED_TRANSBASIC_STEP_COUNT ED_BASE+559L
|
|
||||||
#define ED_TRANSBASIC_STEP_UNIT ED_BASE+560L // can be one of the following:
|
|
||||||
#define ED_STEP_FIELD ED_BASE+561L
|
|
||||||
#define ED_STEP_FRAME ED_BASE+562L
|
|
||||||
#define ED_STEP_3_2 ED_BASE+563L
|
|
||||||
|
|
||||||
#define ED_TRANSBASIC_PREROLL ED_BASE+564L
|
|
||||||
#define ED_TRANSBASIC_RECPREROLL ED_BASE+565L
|
|
||||||
#define ED_TRANSBASIC_POSTROLL ED_BASE+566L
|
|
||||||
#define ED_TRANSBASIC_EDIT_DELAY ED_BASE+567L
|
|
||||||
#define ED_TRANSBASIC_PLAYTC_DELAY ED_BASE+568L
|
|
||||||
#define ED_TRANSBASIC_RECTC_DELAY ED_BASE+569L
|
|
||||||
#define ED_TRANSBASIC_EDIT_FIELD ED_BASE+570L
|
|
||||||
#define ED_TRANSBASIC_FRAME_SERVO ED_BASE+571L
|
|
||||||
#define ED_TRANSBASIC_CF_SERVO ED_BASE+572L
|
|
||||||
#define ED_TRANSBASIC_SERVO_REF ED_BASE+573L // can be one of the following:
|
|
||||||
#define ED_REF_EXTERNAL ED_BASE+574L
|
|
||||||
#define ED_REF_INPUT ED_BASE+575L
|
|
||||||
#define ED_REF_INTERNAL ED_BASE+576L
|
|
||||||
#define ED_REF_AUTO ED_BASE+577L
|
|
||||||
|
|
||||||
#define ED_TRANSBASIC_WARN_GL ED_BASE+578L
|
|
||||||
#define ED_TRANSBASIC_SET_TRACKING ED_BASE+579L // can be one of the following:
|
|
||||||
#define ED_TRACKING_PLUS ED_BASE+580L
|
|
||||||
#define ED_TRACKING_MINUS ED_BASE+581L
|
|
||||||
#define ED_TRACKING_RESET ED_BASE+582L
|
|
||||||
|
|
||||||
#define ED_TRANSBASIC_SET_FREEZE_TIMEOUT ED_BASE+583L
|
|
||||||
#define ED_TRANSBASIC_VOLUME_NAME ED_BASE+584L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_1 ED_BASE+585L // space for proprietary data
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_2 ED_BASE+586L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_3 ED_BASE+587L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_4 ED_BASE+588L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_5 ED_BASE+589L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_6 ED_BASE+590L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_7 ED_BASE+591L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_8 ED_BASE+592L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_9 ED_BASE+593L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_10 ED_BASE+594L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_11 ED_BASE+595L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_12 ED_BASE+596L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_13 ED_BASE+597L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_14 ED_BASE+598L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_15 ED_BASE+599L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_16 ED_BASE+600L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_17 ED_BASE+601L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_18 ED_BASE+602L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_19 ED_BASE+603L
|
|
||||||
#define ED_TRANSBASIC_BALLISTIC_20 ED_BASE+604L
|
|
||||||
|
|
||||||
// consumer VCR items
|
|
||||||
#define ED_TRANSBASIC_SETCLOCK ED_BASE+605L
|
|
||||||
#define ED_TRANSBASIC_SET_COUNTER_FORMAT ED_BASE+606L // uses time format flags
|
|
||||||
#define ED_TRANSBASIC_SET_COUNTER_VALUE ED_BASE+607L
|
|
||||||
|
|
||||||
#define ED_TRANSBASIC_SETTUNER_CH_UP ED_BASE+608L
|
|
||||||
#define ED_TRANSBASIC_SETTUNER_CH_DN ED_BASE+609L
|
|
||||||
#define ED_TRANSBASIC_SETTUNER_SK_UP ED_BASE+610L
|
|
||||||
#define ED_TRANSBASIC_SETTUNER_SK_DN ED_BASE+611L
|
|
||||||
#define ED_TRANSBASIC_SETTUNER_CH ED_BASE+612L
|
|
||||||
#define ED_TRANSBASIC_SETTUNER_NUM ED_BASE+613L
|
|
||||||
|
|
||||||
#define ED_TRANSBASIC_SETTIMER_EVENT ED_BASE+614L
|
|
||||||
#define ED_TRANSBASIC_SETTIMER_STARTDAY ED_BASE+615L
|
|
||||||
#define ED_TRANSBASIC_SETTIMER_STARTTIME ED_BASE+616L
|
|
||||||
#define ED_TRANSBASIC_SETTIMER_STOPDAY ED_BASE+617L
|
|
||||||
#define ED_TRANSBASIC_SETTIMER_STOPTIME ED_BASE+618L
|
|
||||||
|
|
||||||
// IAMExtTransport video parameters
|
|
||||||
#define ED_TRANSVIDEO_SET_OUTPUT ED_BASE+630L // can be one of the following:
|
|
||||||
#define ED_E2E ED_BASE+631L
|
|
||||||
#define ED_PLAYBACK ED_BASE+632L
|
|
||||||
#define ED_OFF ED_BASE+633L
|
|
||||||
|
|
||||||
#define ED_TRANSVIDEO_SET_SOURCE ED_BASE+634L
|
|
||||||
|
|
||||||
// IAMExtTransport audio parameters
|
|
||||||
#define ED_TRANSAUDIO_ENABLE_OUTPUT ED_BASE+640L // can be the following:
|
|
||||||
#define ED_AUDIO_ALL 0x10000000 // or any of the following OR'd together
|
|
||||||
#define ED_AUDIO_1 0x0000001L
|
|
||||||
#define ED_AUDIO_2 0x0000002L
|
|
||||||
#define ED_AUDIO_3 0x0000004L
|
|
||||||
#define ED_AUDIO_4 0x0000008L
|
|
||||||
#define ED_AUDIO_5 0x0000010L
|
|
||||||
#define ED_AUDIO_6 0x0000020L
|
|
||||||
#define ED_AUDIO_7 0x0000040L
|
|
||||||
#define ED_AUDIO_8 0x0000080L
|
|
||||||
#define ED_AUDIO_9 0x0000100L
|
|
||||||
#define ED_AUDIO_10 0x0000200L
|
|
||||||
#define ED_AUDIO_11 0x0000400L
|
|
||||||
#define ED_AUDIO_12 0x0000800L
|
|
||||||
#define ED_AUDIO_13 0x0001000L
|
|
||||||
#define ED_AUDIO_14 0x0002000L
|
|
||||||
#define ED_AUDIO_15 0x0004000L
|
|
||||||
#define ED_AUDIO_16 0x0008000L
|
|
||||||
#define ED_AUDIO_17 0x0010000L
|
|
||||||
#define ED_AUDIO_18 0x0020000L
|
|
||||||
#define ED_AUDIO_19 0x0040000L
|
|
||||||
#define ED_AUDIO_20 0x0080000L
|
|
||||||
#define ED_AUDIO_21 0x0100000L
|
|
||||||
#define ED_AUDIO_22 0x0200000L
|
|
||||||
#define ED_AUDIO_23 0x0400000L
|
|
||||||
#define ED_AUDIO_24 0x0800000L
|
|
||||||
#define ED_VIDEO 0x2000000L // for Edit props below
|
|
||||||
|
|
||||||
#define ED_TRANSAUDIO_ENABLE_RECORD ED_BASE+642L
|
|
||||||
#define ED_TRANSAUDIO_ENABLE_SELSYNC ED_BASE+643L
|
|
||||||
#define ED_TRANSAUDIO_SET_SOURCE ED_BASE+644L
|
|
||||||
#define ED_TRANSAUDIO_SET_MONITOR ED_BASE+645L
|
|
||||||
|
|
||||||
|
|
||||||
// Edit Property Set-related defs
|
|
||||||
|
|
||||||
// The following values reflect (and control) the state of an
|
|
||||||
// edit property set
|
|
||||||
#define ED_INVALID ED_BASE+652L
|
|
||||||
#define ED_EXECUTING ED_BASE+653L
|
|
||||||
#define ED_REGISTER ED_BASE+654L
|
|
||||||
#define ED_DELETE ED_BASE+655L
|
|
||||||
|
|
||||||
// Edit property set parameters and values
|
|
||||||
#define ED_EDIT_HEVENT ED_BASE+656L // event handle to signal event
|
|
||||||
// completion
|
|
||||||
#define ED_EDIT_TEST ED_BASE+657L // returns OAFALSE if filter thinks
|
|
||||||
// edit can be done, OATRUE if not
|
|
||||||
#define ED_EDIT_IMMEDIATE ED_BASE+658L // OATRUE means start put the
|
|
||||||
// device into edit mode (editing
|
|
||||||
// "on the fly") immediately upon
|
|
||||||
// execution of Mode(ED_MODE_EDIT_CUE)
|
|
||||||
#define ED_EDIT_MODE ED_BASE+659L
|
|
||||||
// can be one of the following values:
|
|
||||||
#define ED_EDIT_MODE_ASSEMBLE ED_BASE+660L
|
|
||||||
#define ED_EDIT_MODE_INSERT ED_BASE+661L
|
|
||||||
#define ED_EDIT_MODE_CRASH_RECORD ED_BASE+662L
|
|
||||||
#define ED_EDIT_MODE_BOOKMARK_TIME ED_BASE+663L // these two are for
|
|
||||||
#define ED_EDIT_MODE_BOOKMARK_CHAPTER ED_BASE+664L // laserdisks
|
|
||||||
|
|
||||||
#define ED_EDIT_MASTER ED_BASE+666L // OATRUE causes device
|
|
||||||
// not to synchronize
|
|
||||||
|
|
||||||
#define ED_EDIT_TRACK ED_BASE+667L
|
|
||||||
// can be one of the following possible OR'd values:
|
|
||||||
// ED_VIDEO, ED_AUDIO_1 thru ED_AUDIO_24 (or ED_AUDIO_ALL)
|
|
||||||
|
|
||||||
#define ED_EDIT_SRC_INPOINT ED_BASE+668L // in current time format
|
|
||||||
#define ED_EDIT_SRC_OUTPOINT ED_BASE+669L // in current time format
|
|
||||||
#define ED_EDIT_REC_INPOINT ED_BASE+670L // in current time format
|
|
||||||
#define ED_EDIT_REC_OUTPOINT ED_BASE+671L // in current time format
|
|
||||||
|
|
||||||
#define ED_EDIT_REHEARSE_MODE ED_BASE+672L
|
|
||||||
// can be one of the following possible values:
|
|
||||||
#define ED_EDIT_BVB ED_BASE+673L // means rehearse the edit with
|
|
||||||
// "black-video-black"
|
|
||||||
#define ED_EDIT_VBV ED_BASE+674L
|
|
||||||
#define ED_EDIT_VVV ED_BASE+675L
|
|
||||||
#define ED_EDIT_PERFORM ED_BASE+676L // means perform the edit with no
|
|
||||||
// rehearsal.
|
|
||||||
|
|
||||||
// Set this property to OATRUE to kill the edit if in progress
|
|
||||||
#define ED_EDIT_ABORT ED_BASE+677L
|
|
||||||
// how long to wait for edit to complete
|
|
||||||
#define ED_EDIT_TIMEOUT ED_BASE+678L // in current time format
|
|
||||||
|
|
||||||
// This property causes the device to seek to a point specified by
|
|
||||||
// ED_EDIT_SEEK_MODE (see below). NOTE: Only one event at a time can seek.
|
|
||||||
#define ED_EDIT_SEEK ED_BASE+679L // OATRUE means do it now.
|
|
||||||
#define ED_EDIT_SEEK_MODE ED_BASE+680L
|
|
||||||
//possible values:
|
|
||||||
#define ED_EDIT_SEEK_EDIT_IN ED_BASE+681L // seek to edit's inpoint
|
|
||||||
#define ED_EDIT_SEEK_EDIT_OUT ED_BASE+682L // seek to edit's outpoint
|
|
||||||
#define ED_EDIT_SEEK_PREROLL ED_BASE+683L // seek to edit's
|
|
||||||
// inpoint-preroll
|
|
||||||
#define ED_EDIT_SEEK_PREROLL_CT ED_BASE+684L // seek to preroll point
|
|
||||||
// using control track (used for tapes with
|
|
||||||
// discontinuoustimecode before edit point: seek
|
|
||||||
// to inpoint using timecode, then backup to
|
|
||||||
// preroll point using control track)
|
|
||||||
#define ED_EDIT_SEEK_BOOKMARK ED_BASE+685L // seek to bookmark (just like
|
|
||||||
// timecode search)
|
|
||||||
// This property is used for multiple-VCR systems where each machine must
|
|
||||||
// cue to a different location relative to the graph's reference clock. The
|
|
||||||
// basic idea is that an edit event is setup with an ED_EDIT_OFFSET property
|
|
||||||
// that tells the VCR what offset to maintain between it's timecode (converted
|
|
||||||
// to reference clock units) and the reference clock.
|
|
||||||
#define ED_EDIT_OFFSET ED_BASE+686L // in current time format
|
|
||||||
|
|
||||||
#define ED_EDIT_PREREAD ED_BASE+815L // OATRUE means device supports
|
|
||||||
// pre-read (recorder can also be
|
|
||||||
// player
|
|
||||||
|
|
||||||
//
|
|
||||||
// Some error codes:
|
|
||||||
//
|
|
||||||
// device could be in local mode
|
|
||||||
#define ED_ERR_DEVICE_NOT_READY ED_BASE+700L
|
|
||||||
|
|
||||||
#endif // __EDEVDEFS__
|
|
||||||
|
|
||||||
// eof edevdefs.h
|
|
|
@ -1,47 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: Errors.h
|
|
||||||
//
|
|
||||||
// Desc: ActiveMovie error defines.
|
|
||||||
//
|
|
||||||
// Copyright (c) 1992-2001, Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __ERRORS__
|
|
||||||
#define __ERRORS__
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
#ifndef _AMOVIE_
|
|
||||||
#define AMOVIEAPI DECLSPEC_IMPORT
|
|
||||||
#else
|
|
||||||
#define AMOVIEAPI
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// codes 0-01ff are reserved for OLE
|
|
||||||
#define VFW_FIRST_CODE 0x200
|
|
||||||
#define MAX_ERROR_TEXT_LEN 160
|
|
||||||
|
|
||||||
#include <VFWMSGS.H> // includes all message definitions
|
|
||||||
|
|
||||||
typedef BOOL (WINAPI* AMGETERRORTEXTPROCA)(HRESULT, char *, DWORD);
|
|
||||||
typedef BOOL (WINAPI* AMGETERRORTEXTPROCW)(HRESULT, WCHAR *, DWORD);
|
|
||||||
|
|
||||||
AMOVIEAPI DWORD WINAPI AMGetErrorTextA( HRESULT hr , char *pbuffer , DWORD MaxLen);
|
|
||||||
AMOVIEAPI DWORD WINAPI AMGetErrorTextW( HRESULT hr , WCHAR *pbuffer , DWORD MaxLen);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
#define AMGetErrorText AMGetErrorTextW
|
|
||||||
typedef AMGETERRORTEXTPROCW AMGETERRORTEXTPROC;
|
|
||||||
#else
|
|
||||||
#define AMGetErrorText AMGetErrorTextA
|
|
||||||
typedef AMGETERRORTEXTPROCA AMGETERRORTEXTPROC;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif // __cplusplus
|
|
||||||
#endif // __ERRORS__
|
|
|
@ -1,428 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: EvCode.h
|
|
||||||
//
|
|
||||||
// Desc: List of standard Quartz event codes and the expected params.
|
|
||||||
//
|
|
||||||
// Copyright (c) 1992 - 2001, Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
// Event codes are broken into two groups
|
|
||||||
// -- system event codes
|
|
||||||
// -- extension event codes
|
|
||||||
// All system event codes are below EC_USER
|
|
||||||
|
|
||||||
#define EC_SYSTEMBASE 0x00
|
|
||||||
#define EC_USER 0x8000
|
|
||||||
|
|
||||||
// System-defined event codes
|
|
||||||
// ==========================
|
|
||||||
//
|
|
||||||
// There are three types of system-defined event codes:
|
|
||||||
//
|
|
||||||
// 1. Those which are always passed through to the application
|
|
||||||
// (To be collected by calls to GetEvent or within WaitForCompletion.)
|
|
||||||
// (e.g. EC_ERRORABORT, EC_USERABORT.)
|
|
||||||
//
|
|
||||||
// 2. Those which are pure internal and will never be passed to
|
|
||||||
// the application. (e.g. EC_SHUTDOWN)
|
|
||||||
//
|
|
||||||
// 3. Those which have default handling. Default handing implies that
|
|
||||||
// the event is not passed to the application. However, default
|
|
||||||
// handling may be canceled by calling
|
|
||||||
// IMediaEvent::CancelDefaultHandling. If the default handling is
|
|
||||||
// cancelled in this way, then the message will be delivered to the
|
|
||||||
// application and the application must action it appropriately.
|
|
||||||
// Default handling can be restored by calling RestoreDefaultHandling.
|
|
||||||
//
|
|
||||||
// We will refer to these events as application, internal and defaulted
|
|
||||||
// events respectively.
|
|
||||||
//
|
|
||||||
// System-defined events may have interface pointers, BSTR's, etc passed
|
|
||||||
// as parameters. It is therefore essential that, for any message
|
|
||||||
// retrieved using GetEvent, a matching call to FreeEventParams is made
|
|
||||||
// to ensure that relevant interfaces are released and storage freed.
|
|
||||||
// Failure to call FreeEventParams will result in memory leaks, if not
|
|
||||||
// worse.
|
|
||||||
//
|
|
||||||
// Filters sending these messages to the filter graph should not AddRef()
|
|
||||||
// any interfaces that they may pass as parameters. The filter graph
|
|
||||||
// manager will AddRef them if required. E.g. if the event is to be queued
|
|
||||||
// for the application or queued to a worker thread.
|
|
||||||
|
|
||||||
// Each event listed below is immediately followed by a parameter list
|
|
||||||
// detailing the types of the parameters associated with the message,
|
|
||||||
// and an indication of whether the message is an application, internal
|
|
||||||
// or defaulted message. This is then followed by a short description.
|
|
||||||
// The use of "void" in the parameter list implies that the parameter is not
|
|
||||||
// used. Such parameters should be zero.
|
|
||||||
|
|
||||||
// Other defined EC_ regions:
|
|
||||||
// DVD event codes 0x0100 - 0x0150 (dvdevcod.h)
|
|
||||||
// audio device event codes 0x0200 - 0x0250 (audevcod.h)
|
|
||||||
// WindowsMedia SDK-originated events 0x0251 - 0x0300 (see below)
|
|
||||||
// MSVIDCTL 0x0301 - 0x0325 (msvidctl.idl)
|
|
||||||
// stream buffer engine (PVR) 0x0326 - 0x0350 (sbe.idl)
|
|
||||||
|
|
||||||
#define EC_COMPLETE 0x01
|
|
||||||
// ( HRESULT, void ) : defaulted (special)
|
|
||||||
// Signals the completed playback of a stream within the graph. This message
|
|
||||||
// is sent by renderers when they receive end-of-stream. The default handling
|
|
||||||
// of this message results in a _SINGLE_ EC_COMPLETE being sent to the
|
|
||||||
// application when ALL of the individual renderers have signaled EC_COMPLETE
|
|
||||||
// to the filter graph. If the default handing is canceled, the application
|
|
||||||
// will see all of the individual EC_COMPLETEs.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_USERABORT 0x02
|
|
||||||
// ( void, void ) : application
|
|
||||||
// In some sense, the user has requested that playback be terminated.
|
|
||||||
// This message is typically sent by renderers that render into a
|
|
||||||
// window if the user closes the window into which it was rendering.
|
|
||||||
// It is up to the application to decide if playback should actually
|
|
||||||
// be stopped.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_ERRORABORT 0x03
|
|
||||||
// ( HRESULT, void ) : application
|
|
||||||
// Operation aborted because of error
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_TIME 0x04
|
|
||||||
// ( DWORD, DWORD ) : application
|
|
||||||
// The requested reference time occurred. (This event is currently not used).
|
|
||||||
// lParam1 is low dword of ref time, lParam2 is high dword of reftime.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_REPAINT 0x05
|
|
||||||
// ( IPin * (could be NULL), void ) : defaulted
|
|
||||||
// A repaint is required - lParam1 contains the (IPin *) that needs the data
|
|
||||||
// to be sent again. Default handling is: if the output pin which the IPin is
|
|
||||||
// attached to supports the IMediaEventSink interface then it will be called
|
|
||||||
// with the EC_REPAINT first. If that fails then normal repaint processing is
|
|
||||||
// done by the filter graph.
|
|
||||||
|
|
||||||
|
|
||||||
// Stream error notifications
|
|
||||||
#define EC_STREAM_ERROR_STOPPED 0x06
|
|
||||||
#define EC_STREAM_ERROR_STILLPLAYING 0x07
|
|
||||||
// ( HRESULT, DWORD ) : application
|
|
||||||
// lParam 1 is major code, lParam2 is minor code, either may be zero.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_ERROR_STILLPLAYING 0x08
|
|
||||||
// ( HRESULT, void ) : application
|
|
||||||
// The filter graph manager may issue Run's to the graph asynchronously.
|
|
||||||
// If such a Run fails, EC_ERROR_STILLPLAYING is issued to notify the
|
|
||||||
// application of the failure. The state of the underlying filters
|
|
||||||
// at such a time will be indeterminate - they will all have been asked
|
|
||||||
// to run, but some are almost certainly not.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_PALETTE_CHANGED 0x09
|
|
||||||
// ( void, void ) : application
|
|
||||||
// notify application that the video palette has changed
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_VIDEO_SIZE_CHANGED 0x0A
|
|
||||||
// ( DWORD, void ) : application
|
|
||||||
// Sent by video renderers.
|
|
||||||
// Notifies the application that the native video size has changed.
|
|
||||||
// LOWORD of the DWORD is the new width, HIWORD is the new height.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_QUALITY_CHANGE 0x0B
|
|
||||||
// ( void, void ) : application
|
|
||||||
// Notify application that playback degradation has occurred
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_SHUTTING_DOWN 0x0C
|
|
||||||
// ( void, void ) : internal
|
|
||||||
// This message is sent by the filter graph manager to any plug-in
|
|
||||||
// distributors which support IMediaEventSink to notify them that
|
|
||||||
// the filter graph is starting to shutdown.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_CLOCK_CHANGED 0x0D
|
|
||||||
// ( void, void ) : application
|
|
||||||
// Notify application that the clock has changed.
|
|
||||||
// (i.e. SetSyncSource has been called on the filter graph and has been
|
|
||||||
// distributed successfully to the filters in the graph.)
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_PAUSED 0x0E
|
|
||||||
// ( HRESULT, void ) : application
|
|
||||||
// Notify application the previous pause request has completed
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_OPENING_FILE 0x10
|
|
||||||
#define EC_BUFFERING_DATA 0x11
|
|
||||||
// ( BOOL, void ) : application
|
|
||||||
// lParam1 == 1 --> starting to open file or buffer data
|
|
||||||
// lParam1 == 0 --> not opening or buffering any more
|
|
||||||
// (This event does not appear to be used by ActiveMovie.)
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_FULLSCREEN_LOST 0x12
|
|
||||||
// ( void, IBaseFilter * ) : application
|
|
||||||
// Sent by full screen renderers when switched away from full screen.
|
|
||||||
// IBaseFilter may be NULL.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_ACTIVATE 0x13
|
|
||||||
// ( BOOL, IBaseFilter * ) : internal
|
|
||||||
// Sent by video renderers when they lose or gain activation.
|
|
||||||
// lParam1 is set to 1 if gained or 0 if lost
|
|
||||||
// lParam2 is the IBaseFilter* for the filter that is sending the message
|
|
||||||
// Used for sound follows focus and full-screen switching
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_NEED_RESTART 0x14
|
|
||||||
// ( void, void ) : defaulted
|
|
||||||
// Sent by renderers when they regain a resource (e.g. audio renderer).
|
|
||||||
// Causes a restart by Pause/put_Current/Run (if running).
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_WINDOW_DESTROYED 0x15
|
|
||||||
// ( IBaseFilter *, void ) : internal
|
|
||||||
// Sent by video renderers when the window has been destroyed. Handled
|
|
||||||
// by the filter graph / distributor telling the resource manager.
|
|
||||||
// lParam1 is the IBaseFilter* of the filter whose window is being destroyed
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_DISPLAY_CHANGED 0x16
|
|
||||||
// ( IPin *, void ) : internal
|
|
||||||
// Sent by renderers when they detect a display change. the filter graph
|
|
||||||
// will arrange for the graph to be stopped and the pin send in lParam1
|
|
||||||
// to be reconnected. by being reconnected it allows a renderer to reset
|
|
||||||
// and connect with a more appropriate format for the new display mode
|
|
||||||
// lParam1 contains an (IPin *) that should be reconnected by the graph
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_STARVATION 0x17
|
|
||||||
// ( void, void ) : defaulted
|
|
||||||
// Sent by a filter when it detects starvation. Default handling (only when
|
|
||||||
// running) is for the graph to be paused until all filters enter the
|
|
||||||
// paused state and then run. Normally this would be sent by a parser or source
|
|
||||||
// filter when too little data is arriving.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_OLE_EVENT 0x18
|
|
||||||
// ( BSTR, BSTR ) : application
|
|
||||||
// Sent by a filter to pass a text string to the application.
|
|
||||||
// Conventionally, the first string is a type, and the second a parameter.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_NOTIFY_WINDOW 0x19
|
|
||||||
// ( HWND, void ) : internal
|
|
||||||
// Pass the window handle around during pin connection.
|
|
||||||
|
|
||||||
#define EC_STREAM_CONTROL_STOPPED 0x1A
|
|
||||||
// ( IPin * pSender, DWORD dwCookie )
|
|
||||||
// Notification that an earlier call to IAMStreamControl::StopAt
|
|
||||||
// has now take effect. Calls to the method can be marked
|
|
||||||
// with a cookie which is passed back in the second parameter,
|
|
||||||
// allowing applications to easily tie together request
|
|
||||||
// and completion notifications.
|
|
||||||
//
|
|
||||||
// NB: IPin will point to the pin that actioned the Stop. This
|
|
||||||
// may not be the pin that the StopAt was sent to.
|
|
||||||
|
|
||||||
#define EC_STREAM_CONTROL_STARTED 0x1B
|
|
||||||
// ( IPin * pSender, DWORD dwCookie )
|
|
||||||
// Notification that an earlier call to IAMStreamControl::StartAt
|
|
||||||
// has now take effect. Calls to the method can be marked
|
|
||||||
// with a cookie which is passed back in the second parameter,
|
|
||||||
// allowing applications to easily tie together request
|
|
||||||
// and completion notifications.
|
|
||||||
//
|
|
||||||
// NB: IPin will point to the pin that actioned the Start. This
|
|
||||||
// may not be the pin that the StartAt was sent to.
|
|
||||||
|
|
||||||
#define EC_END_OF_SEGMENT 0x1C
|
|
||||||
//
|
|
||||||
// ( const REFERENCE_TIME *pStreamTimeAtEndOfSegment, DWORD dwSegmentNumber )
|
|
||||||
//
|
|
||||||
// pStreamTimeAtEndOfSegment
|
|
||||||
// pointer to the accumulated stream clock
|
|
||||||
// time since the start of the segment - this is directly computable
|
|
||||||
// as the sum of the previous and current segment durations (Stop - Start)
|
|
||||||
// and the rate applied to each segment
|
|
||||||
// The source add this time to the time within each segment to get
|
|
||||||
// a total elapsed time
|
|
||||||
//
|
|
||||||
// dwSegmentNumber
|
|
||||||
// Segment number - starts at 0
|
|
||||||
//
|
|
||||||
// Notifies that a segment end has been reached when the
|
|
||||||
// AM_SEEKING_Segment flags was set for IMediaSeeking::SetPositions
|
|
||||||
// Passes in an IMediaSeeking interface to allow the next segment
|
|
||||||
// to be defined by the application
|
|
||||||
|
|
||||||
#define EC_SEGMENT_STARTED 0x1D
|
|
||||||
//
|
|
||||||
// ( const REFERENCE_TIME *pStreamTimeAtStartOfSegment, DWORD dwSegmentNumber)
|
|
||||||
//
|
|
||||||
// pStreamTimeAtStartOfSegment
|
|
||||||
// pointer to the accumulated stream clock
|
|
||||||
// time since the start of the segment - this is directly computable
|
|
||||||
// as the sum of the previous segment durations (Stop - Start)
|
|
||||||
// and the rate applied to each segment
|
|
||||||
//
|
|
||||||
// dwSegmentNumber
|
|
||||||
// Segment number - starts at 0
|
|
||||||
//
|
|
||||||
// Notifies that a new segment has been started.
|
|
||||||
// This is sent synchronously by any entity that will issue
|
|
||||||
// EC_END_OF_SEGMENT when a new segment is started
|
|
||||||
// (See IMediaSeeking::SetPositions - AM_SEEKING_Segment flag)
|
|
||||||
// It is used to compute how many EC_END_OF_SEGMENT notifications
|
|
||||||
// to expect at the end of a segment and as a consitency check
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_LENGTH_CHANGED 0x1E
|
|
||||||
// (void, void)
|
|
||||||
// sent to indicate that the length of the "file" has changed
|
|
||||||
|
|
||||||
#define EC_DEVICE_LOST 0x1f
|
|
||||||
// (IUnknown, 0)
|
|
||||||
//
|
|
||||||
// request window notification when the device is available again
|
|
||||||
// (through WM_DEVICECHANGED messages registered with
|
|
||||||
// RegisterDeviceNotification; see IAMDeviceRemoval interface)
|
|
||||||
|
|
||||||
#define EC_STEP_COMPLETE 0x24
|
|
||||||
// (BOOL bCacelled, void)
|
|
||||||
// Step request complete
|
|
||||||
// if bCancelled is TRUE the step was cancelled. This can happen
|
|
||||||
// if the application issued some control request or because there
|
|
||||||
// was a mode change etc etc
|
|
||||||
|
|
||||||
// Event code 25 is reserved for future use.
|
|
||||||
|
|
||||||
#define EC_TIMECODE_AVAILABLE 0x30
|
|
||||||
// Sent by filter supporting timecode
|
|
||||||
// Param1 has a pointer to the sending object
|
|
||||||
// Param2 has the device ID of the sending object
|
|
||||||
|
|
||||||
#define EC_EXTDEVICE_MODE_CHANGE 0x31
|
|
||||||
// Sent by filter supporting IAMExtDevice
|
|
||||||
// Param1 has the new mode
|
|
||||||
// Param2 has the device ID of the sending object
|
|
||||||
|
|
||||||
#define EC_STATE_CHANGE 0x32
|
|
||||||
// ( FILTER_STATE, BOOL bInternal)
|
|
||||||
// Used to notify the application of any state changes in the filter graph.
|
|
||||||
// lParam1 is of type enum FILTER_STATE (defined in strmif.h) and indicates
|
|
||||||
// the state of the filter graph.
|
|
||||||
//
|
|
||||||
// lParam2 == 0 indicates that the previous state change request has completed
|
|
||||||
// & a change in application state.
|
|
||||||
// lParam2 == 1 reserved for future use to indicate internal state changes.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_GRAPH_CHANGED 0x50
|
|
||||||
// Sent by filter to notify interesting graph changes
|
|
||||||
|
|
||||||
#define EC_CLOCK_UNSET 0x51
|
|
||||||
// ( void, void ) : application
|
|
||||||
// Used to notify the filter graph to unset the current graph clock.
|
|
||||||
// Has the affect of forcing the filter graph to reestablish the graph clock
|
|
||||||
// on the next Pause/Run (note that this is only used by ksproxy, when the pin
|
|
||||||
// of a clock providing filter is disconnected)
|
|
||||||
|
|
||||||
#define EC_VMR_RENDERDEVICE_SET 0x53
|
|
||||||
// (Render_Device type, void)
|
|
||||||
// Identifies the type of rendering mechanism the VMR
|
|
||||||
// is using to display video. Types used include:
|
|
||||||
#define VMR_RENDER_DEVICE_OVERLAY 0x01
|
|
||||||
#define VMR_RENDER_DEVICE_VIDMEM 0x02
|
|
||||||
#define VMR_RENDER_DEVICE_SYSMEM 0x04
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_VMR_SURFACE_FLIPPED 0x54
|
|
||||||
// (hr - Flip return code, void)
|
|
||||||
// Identifies the VMR's allocator-presenter has called the DDraw flip api on
|
|
||||||
// the surface being presented. This allows the VMR to keep its DX-VA table
|
|
||||||
// of DDraw surfaces in sync with DDraws flipping chain.
|
|
||||||
|
|
||||||
#define EC_VMR_RECONNECTION_FAILED 0x55
|
|
||||||
// (hr - ReceiveConnection return code, void)
|
|
||||||
// Identifies that an upstream decoder tried to perform a dynamic format
|
|
||||||
// change and the VMR was unable to accept the new format.
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_PREPROCESS_COMPLETE 0x56
|
|
||||||
// Sent by the WM ASF writer filter (WMSDK V9 version) to signal the completion
|
|
||||||
// of a pre-process run when running in multipass encode mode.
|
|
||||||
// Param1 = 0, Param2 = IBaseFilter ptr of sending filter
|
|
||||||
|
|
||||||
#define EC_CODECAPI_EVENT 0x57
|
|
||||||
// Sent by the Codec API when an event is encountered. Both the Data
|
|
||||||
// must be freed by the recipient using CoTaskMemFree
|
|
||||||
// Param1 = UserDataPointer, Param2 = VOID* Data
|
|
||||||
|
|
||||||
//------------------------------------------
|
|
||||||
//
|
|
||||||
// BDA events:
|
|
||||||
//
|
|
||||||
// Event code 0x80 through 0x8f are reserved for BDA
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------
|
|
||||||
//
|
|
||||||
// WindowsMedia SDK filter-specific events:
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Note that for EC_WMT_EVENT events the wmsdk-based filters use the following structure for
|
|
||||||
// passing event parameters to the app:
|
|
||||||
#ifndef AM_WMT_EVENT_DATA_DEFINED
|
|
||||||
#define AM_WMT_EVENT_DATA_DEFINED
|
|
||||||
typedef struct {
|
|
||||||
HRESULT hrStatus; // status code
|
|
||||||
void * pData; // event data
|
|
||||||
} AM_WMT_EVENT_DATA;
|
|
||||||
#endif
|
|
||||||
//
|
|
||||||
#define EC_WMT_EVENT_BASE 0x0251
|
|
||||||
//
|
|
||||||
#define EC_WMT_INDEX_EVENT EC_WMT_EVENT_BASE
|
|
||||||
// WindowsMedia SDK-originated file indexing status, sent by WMSDK-based filters
|
|
||||||
//
|
|
||||||
// lParam1 is one of the enum WMT_STATUS messages listed below, sent by the WindowsMedia SDK
|
|
||||||
// lParam2 is specific to the lParam event
|
|
||||||
//
|
|
||||||
// the following WMT_STATUS messages are sent for this event:
|
|
||||||
// WMT_STARTED - lParam2 is 0
|
|
||||||
// WMT_CLOSED - lParam2 is 0
|
|
||||||
// WMT_INDEX_PROGRESS - lParam2 is a DWORD containing the progress percent complete
|
|
||||||
//
|
|
||||||
#define EC_WMT_EVENT EC_WMT_EVENT_BASE+1
|
|
||||||
// WindowsMedia SDK-originated event, sent by WMSDK-based filters
|
|
||||||
//
|
|
||||||
// lParam1 is one of the enum WMT_STATUS messages listed below, sent by the WindowsMedia SDK
|
|
||||||
// lParam2 is a pointer an AM_WMT_EVENT_DATA structure where,
|
|
||||||
// hrStatus is the status code sent by the wmsdk
|
|
||||||
// pData is specific to the lParam1 event
|
|
||||||
//
|
|
||||||
// the following WMT_STATUS messages are sent by the WMSDK Reader filter for this event:
|
|
||||||
// WMT_NO_RIGHTS - pData is a pointer to a WCHAR string containing a challenge URL
|
|
||||||
// WMT_ACQUIRE_LICENSE - lParam2 is a pointer to a WM_GET_LICENSE_DATA struct
|
|
||||||
// WMT_NO_RIGHTS_EX - lParam2 is a pointer to a WM_GET_LICENSE_DATA struct
|
|
||||||
// WMT_NEEDS_INDIVIDUALIZATION - lParam2 is NULL
|
|
||||||
// WMT_INDIVIDUALIZE - lParam2 is a pointer to a WM_INDIVIDUALIZE_STATUS struct
|
|
||||||
// the WMSDK (V9) ASF Writer filter will send this event in response to a wmsdk-signaled error during file
|
|
||||||
// writing, along with the wmsdk WMT_STATUS error as the lParam1 and hrStatus embedded in the
|
|
||||||
// AM_WMT_EVENT_DATA struct pointed to by the lParam2 pointer.
|
|
||||||
//
|
|
||||||
// end WMSDK-originated events
|
|
||||||
//-----------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_BUILT 0x300
|
|
||||||
// Sent to notify transition from unbuilt to built state
|
|
||||||
|
|
||||||
|
|
||||||
#define EC_UNBUILT 0x301
|
|
||||||
// Sent to notify transtion from built to unbuilt state
|
|
|
@ -1,101 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: FourCC.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
// FOURCCMap
|
|
||||||
//
|
|
||||||
// provides a mapping between old-style multimedia format DWORDs
|
|
||||||
// and new-style GUIDs.
|
|
||||||
//
|
|
||||||
// A range of 4 billion GUIDs has been allocated to ensure that this
|
|
||||||
// mapping can be done straightforwardly one-to-one in both directions.
|
|
||||||
//
|
|
||||||
// January 95
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __FOURCC__
|
|
||||||
#define __FOURCC__
|
|
||||||
|
|
||||||
|
|
||||||
// Multimedia format types are marked with DWORDs built from four 8-bit
|
|
||||||
// chars and known as FOURCCs. New multimedia AM_MEDIA_TYPE definitions include
|
|
||||||
// a subtype GUID. In order to simplify the mapping, GUIDs in the range:
|
|
||||||
// XXXXXXXX-0000-0010-8000-00AA00389B71
|
|
||||||
// are reserved for FOURCCs.
|
|
||||||
|
|
||||||
class FOURCCMap : public GUID
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
FOURCCMap();
|
|
||||||
FOURCCMap(DWORD Fourcc);
|
|
||||||
FOURCCMap(const GUID *);
|
|
||||||
|
|
||||||
|
|
||||||
DWORD GetFOURCC(void);
|
|
||||||
void SetFOURCC(DWORD fourcc);
|
|
||||||
void SetFOURCC(const GUID *);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void InitGUID();
|
|
||||||
};
|
|
||||||
|
|
||||||
#define GUID_Data2 0
|
|
||||||
#define GUID_Data3 0x10
|
|
||||||
#define GUID_Data4_1 0xaa000080
|
|
||||||
#define GUID_Data4_2 0x719b3800
|
|
||||||
|
|
||||||
inline void
|
|
||||||
FOURCCMap::InitGUID() {
|
|
||||||
Data2 = GUID_Data2;
|
|
||||||
Data3 = GUID_Data3;
|
|
||||||
((DWORD *)Data4)[0] = GUID_Data4_1;
|
|
||||||
((DWORD *)Data4)[1] = GUID_Data4_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
FOURCCMap::FOURCCMap() {
|
|
||||||
InitGUID();
|
|
||||||
SetFOURCC( DWORD(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
FOURCCMap::FOURCCMap(DWORD fourcc)
|
|
||||||
{
|
|
||||||
InitGUID();
|
|
||||||
SetFOURCC(fourcc);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
FOURCCMap::FOURCCMap(const GUID * pGuid)
|
|
||||||
{
|
|
||||||
InitGUID();
|
|
||||||
SetFOURCC(pGuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
FOURCCMap::SetFOURCC(const GUID * pGuid)
|
|
||||||
{
|
|
||||||
FOURCCMap * p = (FOURCCMap*) pGuid;
|
|
||||||
SetFOURCC(p->GetFOURCC());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
FOURCCMap::SetFOURCC(DWORD fourcc)
|
|
||||||
{
|
|
||||||
Data1 = fourcc;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline DWORD
|
|
||||||
FOURCCMap::GetFOURCC(void)
|
|
||||||
{
|
|
||||||
return Data1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __FOURCC__ */
|
|
||||||
|
|
|
@ -1,222 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: Measure.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
The idea is to pepper the source code with interesting measurements and
|
|
||||||
have the last few thousand of these recorded in a circular buffer that
|
|
||||||
can be post-processed to give interesting numbers.
|
|
||||||
|
|
||||||
WHAT THE LOG LOOKS LIKE:
|
|
||||||
|
|
||||||
Time (sec) Type Delta Incident_Name
|
|
||||||
0.055,41 NOTE -. Incident Nine - Another note
|
|
||||||
0.055,42 NOTE 0.000,01 Incident Nine - Another note
|
|
||||||
0.055,44 NOTE 0.000,02 Incident Nine - Another note
|
|
||||||
0.055,45 STOP -. Incident Eight - Also random
|
|
||||||
0.055,47 START -. Incident Seven - Random
|
|
||||||
0.055,49 NOTE 0.000,05 Incident Nine - Another note
|
|
||||||
------- <etc. there is a lot of this> ----------------
|
|
||||||
0.125,60 STOP 0.000,03 Msr_Stop
|
|
||||||
0.125,62 START -. Msr_Start
|
|
||||||
0.125,63 START -. Incident Two - Start/Stop
|
|
||||||
0.125,65 STOP 0.000,03 Msr_Start
|
|
||||||
0.125,66 START -. Msr_Stop
|
|
||||||
0.125,68 STOP 0.000,05 Incident Two - Start/Stop
|
|
||||||
0.125,70 STOP 0.000,04 Msr_Stop
|
|
||||||
0.125,72 START -. Msr_Start
|
|
||||||
0.125,73 START -. Incident Two - Start/Stop
|
|
||||||
0.125,75 STOP 0.000,03 Msr_Start
|
|
||||||
0.125,77 START -. Msr_Stop
|
|
||||||
0.125,78 STOP 0.000,05 Incident Two - Start/Stop
|
|
||||||
0.125,80 STOP 0.000,03 Msr_Stop
|
|
||||||
0.125,81 NOTE -. Incident Three - single Note
|
|
||||||
0.125,83 START -. Incident Four - Start, no stop
|
|
||||||
0.125,85 START -. Incident Five - Single Start/Stop
|
|
||||||
0.125,87 STOP 0.000,02 Incident Five - Single Start/Stop
|
|
||||||
|
|
||||||
Number Average StdDev Smallest Largest Incident_Name
|
|
||||||
10 0.000,58 0.000,10 0.000,55 0.000,85 Incident One - Note
|
|
||||||
50 0.000,05 0.000,00 0.000,05 0.000,05 Incident Two - Start/Stop
|
|
||||||
1 -. -. -. -. Incident Three - single Note
|
|
||||||
0 -. -. -. -. Incident Four - Start, no stop
|
|
||||||
1 0.000,02 -. 0.000,02 0.000,02 Incident Five - Single Start/Stop
|
|
||||||
0 -. -. -. -. Incident Six - zero occurrences
|
|
||||||
100 0.000,25 0.000,12 0.000,02 0.000,62 Incident Seven - Random
|
|
||||||
100 0.000,79 0.000,48 0.000,02 0.001,92 Incident Eight - Also random
|
|
||||||
5895 0.000,01 0.000,01 0.000,01 0.000,56 Incident Nine - Another note
|
|
||||||
10 0.000,03 0.000,00 0.000,03 0.000,04 Msr_Note
|
|
||||||
50 0.000,03 0.000,00 0.000,03 0.000,04 Msr_Start
|
|
||||||
50 0.000,04 0.000,03 0.000,03 0.000,31 Msr_Stop
|
|
||||||
|
|
||||||
WHAT IT MEANS:
|
|
||||||
The log shows what happened and when. Each line shows the time at which
|
|
||||||
something happened (see WHAT YOU CODE below) what it was that happened
|
|
||||||
and (if approporate) the time since the corresponding previous event
|
|
||||||
(that's the delta column).
|
|
||||||
|
|
||||||
The statistics show how many times each event occurred, what the average
|
|
||||||
delta time was, also the standard deviation, largest and smalles delta.
|
|
||||||
|
|
||||||
WHAT YOU CODE:
|
|
||||||
|
|
||||||
Before anything else executes: - register your ids
|
|
||||||
|
|
||||||
int id1 = Msr_Register("Incident One - Note");
|
|
||||||
int id2 = Msr_Register("Incident Two - Start/Stop");
|
|
||||||
int id3 = Msr_Register("Incident Three - single Note");
|
|
||||||
etc.
|
|
||||||
|
|
||||||
At interesting moments:
|
|
||||||
|
|
||||||
// To measure a repetitive event - e.g. end of bitblt to screen
|
|
||||||
Msr_Note(Id9); // e.g. "video frame hiting the screen NOW!"
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
// To measure an elapsed time e.g. time taken to decode an MPEG B-frame
|
|
||||||
Msr_Start(Id2); // e.g. "Starting to decode MPEG B-frame"
|
|
||||||
. . .
|
|
||||||
MsrStop(Id2); // "Finished MPEG decode"
|
|
||||||
|
|
||||||
At the end:
|
|
||||||
|
|
||||||
HANDLE hFile;
|
|
||||||
hFile = CreateFile("Perf.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
|
||||||
Msr_Dump(hFile); // This writes the log out to the file
|
|
||||||
CloseHandle(hFile);
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
Msr_Dump(NULL); // This writes it to DbgLog((LOG_TRACE,0, ... ));
|
|
||||||
// but if you are writing it out to the debugger
|
|
||||||
// then the times are probably all garbage because
|
|
||||||
// the debugger can make things run awfully slow.
|
|
||||||
|
|
||||||
A given id should be used either for start / stop or Note calls. If Notes
|
|
||||||
are mixed in with Starts and Stops their statistics will be gibberish.
|
|
||||||
|
|
||||||
If you code the calls in upper case i.e. MSR_START(idMunge); then you get
|
|
||||||
macros which will turn into nothing unless PERF is defined.
|
|
||||||
|
|
||||||
You can reset the statistical counts for a given id by calling Reset(Id).
|
|
||||||
They are reset by default at the start.
|
|
||||||
It logs Reset as a special incident, so you can see it in the log.
|
|
||||||
|
|
||||||
The log is a circular buffer in storage (to try to minimise disk I/O).
|
|
||||||
It overwrites the oldest entries once full. The statistics include ALL
|
|
||||||
incidents since the last Reset, whether still visible in the log or not.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __MEASURE__
|
|
||||||
#define __MEASURE__
|
|
||||||
|
|
||||||
#ifdef PERF
|
|
||||||
#define MSR_INIT() Msr_Init()
|
|
||||||
#define MSR_TERMINATE() Msr_Terminate()
|
|
||||||
#define MSR_REGISTER(a) Msr_Register(a)
|
|
||||||
#define MSR_RESET(a) Msr_Reset(a)
|
|
||||||
#define MSR_CONTROL(a) Msr_Control(a)
|
|
||||||
#define MSR_START(a) Msr_Start(a)
|
|
||||||
#define MSR_STOP(a) Msr_Stop(a)
|
|
||||||
#define MSR_NOTE(a) Msr_Note(a)
|
|
||||||
#define MSR_INTEGER(a,b) Msr_Integer(a,b)
|
|
||||||
#define MSR_DUMP(a) Msr_Dump(a)
|
|
||||||
#define MSR_DUMPSTATS(a) Msr_DumpStats(a)
|
|
||||||
#else
|
|
||||||
#define MSR_INIT() ((void)0)
|
|
||||||
#define MSR_TERMINATE() ((void)0)
|
|
||||||
#define MSR_REGISTER(a) 0
|
|
||||||
#define MSR_RESET(a) ((void)0)
|
|
||||||
#define MSR_CONTROL(a) ((void)0)
|
|
||||||
#define MSR_START(a) ((void)0)
|
|
||||||
#define MSR_STOP(a) ((void)0)
|
|
||||||
#define MSR_NOTE(a) ((void)0)
|
|
||||||
#define MSR_INTEGER(a,b) ((void)0)
|
|
||||||
#define MSR_DUMP(a) ((void)0)
|
|
||||||
#define MSR_DUMPSTATS(a) ((void)0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// This must be called first - (called by the DllEntry)
|
|
||||||
|
|
||||||
void WINAPI Msr_Init(void);
|
|
||||||
|
|
||||||
|
|
||||||
// Call this last to clean up (or just let it fall off the end - who cares?)
|
|
||||||
|
|
||||||
void WINAPI Msr_Terminate(void);
|
|
||||||
|
|
||||||
|
|
||||||
// Call this to get an Id for an "incident" that you can pass to Start, Stop or Note
|
|
||||||
// everything that's logged is called an "incident".
|
|
||||||
|
|
||||||
int WINAPI Msr_Register(LPTSTR Incident);
|
|
||||||
|
|
||||||
|
|
||||||
// Reset the statistical counts for an incident
|
|
||||||
|
|
||||||
void WINAPI Msr_Reset(int Id);
|
|
||||||
|
|
||||||
|
|
||||||
// Reset all the counts for all incidents
|
|
||||||
#define MSR_RESET_ALL 0
|
|
||||||
#define MSR_PAUSE 1
|
|
||||||
#define MSR_RUN 2
|
|
||||||
|
|
||||||
void WINAPI Msr_Control(int iAction);
|
|
||||||
|
|
||||||
|
|
||||||
// log the start of an operation
|
|
||||||
|
|
||||||
void WINAPI Msr_Start(int Id);
|
|
||||||
|
|
||||||
|
|
||||||
// log the end of an operation
|
|
||||||
|
|
||||||
void WINAPI Msr_Stop(int Id);
|
|
||||||
|
|
||||||
|
|
||||||
// log a one-off or repetitive operation
|
|
||||||
|
|
||||||
void WINAPI Msr_Note(int Id);
|
|
||||||
|
|
||||||
|
|
||||||
// log an integer (on which we can see statistics later)
|
|
||||||
void WINAPI Msr_Integer(int Id, int n);
|
|
||||||
|
|
||||||
|
|
||||||
// print out all the vaialable log (it may have wrapped) and then the statistics.
|
|
||||||
// When the log wraps you lose log but the statistics are still complete.
|
|
||||||
// hFIle==NULL => use DbgLog
|
|
||||||
// otherwise hFile must have come from CreateFile or OpenFile.
|
|
||||||
|
|
||||||
void WINAPI Msr_Dump(HANDLE hFile);
|
|
||||||
|
|
||||||
|
|
||||||
// just dump the statistics - never mind the log
|
|
||||||
|
|
||||||
void WINAPI Msr_DumpStats(HANDLE hFile);
|
|
||||||
|
|
||||||
// Type definitions in case you want to declare a pointer to the dump functions
|
|
||||||
// (makes it a trifle easier to do dynamic linking
|
|
||||||
// i.e. LoadModule, GetProcAddress and call that)
|
|
||||||
|
|
||||||
// Typedefs so can declare MSR_DUMPPROC *MsrDumpStats; or whatever
|
|
||||||
typedef void WINAPI MSR_DUMPPROC(HANDLE hFile);
|
|
||||||
typedef void WINAPI MSR_CONTROLPROC(int iAction);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __MEASURE__
|
|
|
@ -1,120 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: MsgThrd.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - provides support for a worker thread
|
|
||||||
// class to which one can asynchronously post messages.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
// Message class - really just a structure.
|
|
||||||
//
|
|
||||||
class CMsg {
|
|
||||||
public:
|
|
||||||
UINT uMsg;
|
|
||||||
DWORD dwFlags;
|
|
||||||
LPVOID lpParam;
|
|
||||||
CAMEvent *pEvent;
|
|
||||||
|
|
||||||
CMsg(UINT u, DWORD dw, LPVOID lp, CAMEvent *pEvnt)
|
|
||||||
: uMsg(u), dwFlags(dw), lpParam(lp), pEvent(pEvnt) {}
|
|
||||||
|
|
||||||
CMsg()
|
|
||||||
: uMsg(0), dwFlags(0L), lpParam(NULL), pEvent(NULL) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is the actual thread class. It exports all the usual thread control
|
|
||||||
// functions. The created thread is different from a normal WIN32 thread in
|
|
||||||
// that it is prompted to perform particaular tasks by responding to messages
|
|
||||||
// posted to its message queue.
|
|
||||||
//
|
|
||||||
class AM_NOVTABLE CMsgThread {
|
|
||||||
private:
|
|
||||||
static DWORD WINAPI DefaultThreadProc(LPVOID lpParam);
|
|
||||||
DWORD m_ThreadId;
|
|
||||||
HANDLE m_hThread;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// if you want to override GetThreadMsg to block on other things
|
|
||||||
// as well as this queue, you need access to this
|
|
||||||
CGenericList<CMsg> m_ThreadQueue;
|
|
||||||
CCritSec m_Lock;
|
|
||||||
HANDLE m_hSem;
|
|
||||||
LONG m_lWaiting;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CMsgThread()
|
|
||||||
: m_ThreadId(0),
|
|
||||||
m_hThread(NULL),
|
|
||||||
m_lWaiting(0),
|
|
||||||
m_hSem(NULL),
|
|
||||||
// make a list with a cache of 5 items
|
|
||||||
m_ThreadQueue(NAME("MsgThread list"), 5)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~CMsgThread();
|
|
||||||
// override this if you want to block on other things as well
|
|
||||||
// as the message loop
|
|
||||||
void virtual GetThreadMsg(CMsg *msg);
|
|
||||||
|
|
||||||
// override this if you want to do something on thread startup
|
|
||||||
virtual void OnThreadInit() {
|
|
||||||
};
|
|
||||||
|
|
||||||
BOOL CreateThread();
|
|
||||||
|
|
||||||
BOOL WaitForThreadExit(LPDWORD lpdwExitCode) {
|
|
||||||
if (m_hThread != NULL) {
|
|
||||||
WaitForSingleObject(m_hThread, INFINITE);
|
|
||||||
return GetExitCodeThread(m_hThread, lpdwExitCode);
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD ResumeThread() {
|
|
||||||
return ::ResumeThread(m_hThread);
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD SuspendThread() {
|
|
||||||
return ::SuspendThread(m_hThread);
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetThreadPriority() {
|
|
||||||
return ::GetThreadPriority(m_hThread);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL SetThreadPriority(int nPriority) {
|
|
||||||
return ::SetThreadPriority(m_hThread, nPriority);
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE GetThreadHandle() {
|
|
||||||
return m_hThread;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD GetThreadId() {
|
|
||||||
return m_ThreadId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PutThreadMsg(UINT uMsg, DWORD dwMsgFlags,
|
|
||||||
LPVOID lpMsgParam, CAMEvent *pEvent = NULL) {
|
|
||||||
CAutoLock lck(&m_Lock);
|
|
||||||
CMsg* pMsg = new CMsg(uMsg, dwMsgFlags, lpMsgParam, pEvent);
|
|
||||||
m_ThreadQueue.AddTail(pMsg);
|
|
||||||
if (m_lWaiting != 0) {
|
|
||||||
ReleaseSemaphore(m_hSem, m_lWaiting, 0);
|
|
||||||
m_lWaiting = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is the function prototype of the function that the client
|
|
||||||
// supplies. It is always called on the created thread, never on
|
|
||||||
// the creator thread.
|
|
||||||
//
|
|
||||||
virtual LRESULT ThreadMessageProc(
|
|
||||||
UINT uMsg, DWORD dwFlags, LPVOID lpParam, CAMEvent *pEvent) = 0;
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,477 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: MType.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - implements a class that holds and
|
|
||||||
// manages media type information.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
// helper class that derived pin objects can use to compare media
|
|
||||||
// types etc. Has same data members as the struct AM_MEDIA_TYPE defined
|
|
||||||
// in the streams IDL file, but also has (non-virtual) functions
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
#include <mmreg.h>
|
|
||||||
|
|
||||||
CMediaType::~CMediaType(){
|
|
||||||
FreeMediaType(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CMediaType::CMediaType()
|
|
||||||
{
|
|
||||||
InitMediaType();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CMediaType::CMediaType(const GUID * type)
|
|
||||||
{
|
|
||||||
InitMediaType();
|
|
||||||
majortype = *type;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// copy constructor does a deep copy of the format block
|
|
||||||
|
|
||||||
CMediaType::CMediaType(const AM_MEDIA_TYPE& rt, HRESULT* phr)
|
|
||||||
{
|
|
||||||
HRESULT hr = CopyMediaType(this, &rt);
|
|
||||||
if (FAILED(hr) && (NULL != phr)) {
|
|
||||||
*phr = hr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CMediaType::CMediaType(const CMediaType& rt, HRESULT* phr)
|
|
||||||
{
|
|
||||||
HRESULT hr = CopyMediaType(this, &rt);
|
|
||||||
if (FAILED(hr) && (NULL != phr)) {
|
|
||||||
*phr = hr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// this class inherits publicly from AM_MEDIA_TYPE so the compiler could generate
|
|
||||||
// the following assignment operator itself, however it could introduce some
|
|
||||||
// memory conflicts and leaks in the process because the structure contains
|
|
||||||
// a dynamically allocated block (pbFormat) which it will not copy correctly
|
|
||||||
|
|
||||||
CMediaType&
|
|
||||||
CMediaType::operator=(const AM_MEDIA_TYPE& rt)
|
|
||||||
{
|
|
||||||
Set(rt);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CMediaType&
|
|
||||||
CMediaType::operator=(const CMediaType& rt)
|
|
||||||
{
|
|
||||||
*this = (AM_MEDIA_TYPE &) rt;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
CMediaType::operator == (const CMediaType& rt) const
|
|
||||||
{
|
|
||||||
// I don't believe we need to check sample size or
|
|
||||||
// temporal compression flags, since I think these must
|
|
||||||
// be represented in the type, subtype and format somehow. They
|
|
||||||
// are pulled out as separate flags so that people who don't understand
|
|
||||||
// the particular format representation can still see them, but
|
|
||||||
// they should duplicate information in the format block.
|
|
||||||
|
|
||||||
return ((IsEqualGUID(majortype,rt.majortype) == TRUE) &&
|
|
||||||
(IsEqualGUID(subtype,rt.subtype) == TRUE) &&
|
|
||||||
(IsEqualGUID(formattype,rt.formattype) == TRUE) &&
|
|
||||||
(cbFormat == rt.cbFormat) &&
|
|
||||||
( (cbFormat == 0) ||
|
|
||||||
(memcmp(pbFormat, rt.pbFormat, cbFormat) == 0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
CMediaType::operator != (const CMediaType& rt) const
|
|
||||||
{
|
|
||||||
/* Check to see if they are equal */
|
|
||||||
|
|
||||||
if (*this == rt) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
CMediaType::Set(const CMediaType& rt)
|
|
||||||
{
|
|
||||||
return Set((AM_MEDIA_TYPE &) rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
CMediaType::Set(const AM_MEDIA_TYPE& rt)
|
|
||||||
{
|
|
||||||
if (&rt != this) {
|
|
||||||
FreeMediaType(*this);
|
|
||||||
HRESULT hr = CopyMediaType(this, &rt);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
CMediaType::IsValid() const
|
|
||||||
{
|
|
||||||
return (!IsEqualGUID(majortype,GUID_NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
CMediaType::SetType(const GUID* ptype)
|
|
||||||
{
|
|
||||||
majortype = *ptype;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
CMediaType::SetSubtype(const GUID* ptype)
|
|
||||||
{
|
|
||||||
subtype = *ptype;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ULONG
|
|
||||||
CMediaType::GetSampleSize() const {
|
|
||||||
if (IsFixedSize()) {
|
|
||||||
return lSampleSize;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
CMediaType::SetSampleSize(ULONG sz) {
|
|
||||||
if (sz == 0) {
|
|
||||||
SetVariableSize();
|
|
||||||
} else {
|
|
||||||
bFixedSizeSamples = TRUE;
|
|
||||||
lSampleSize = sz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
CMediaType::SetVariableSize() {
|
|
||||||
bFixedSizeSamples = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
CMediaType::SetTemporalCompression(BOOL bCompressed) {
|
|
||||||
bTemporalCompression = bCompressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
CMediaType::SetFormat(BYTE * pformat, ULONG cb)
|
|
||||||
{
|
|
||||||
if (NULL == AllocFormatBuffer(cb))
|
|
||||||
return(FALSE);
|
|
||||||
|
|
||||||
ASSERT(pbFormat);
|
|
||||||
memcpy(pbFormat, pformat, cb);
|
|
||||||
return(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// set the type of the media type format block, this type defines what you
|
|
||||||
// will actually find in the format pointer. For example FORMAT_VideoInfo or
|
|
||||||
// FORMAT_WaveFormatEx. In the future this may be an interface pointer to a
|
|
||||||
// property set. Before sending out media types this should be filled in.
|
|
||||||
|
|
||||||
void
|
|
||||||
CMediaType::SetFormatType(const GUID *pformattype)
|
|
||||||
{
|
|
||||||
formattype = *pformattype;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// reset the format buffer
|
|
||||||
|
|
||||||
void CMediaType::ResetFormatBuffer()
|
|
||||||
{
|
|
||||||
if (cbFormat) {
|
|
||||||
CoTaskMemFree((PVOID)pbFormat);
|
|
||||||
}
|
|
||||||
cbFormat = 0;
|
|
||||||
pbFormat = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// allocate length bytes for the format and return a read/write pointer
|
|
||||||
// If we cannot allocate the new block of memory we return NULL leaving
|
|
||||||
// the original block of memory untouched (as does ReallocFormatBuffer)
|
|
||||||
|
|
||||||
BYTE*
|
|
||||||
CMediaType::AllocFormatBuffer(ULONG length)
|
|
||||||
{
|
|
||||||
ASSERT(length);
|
|
||||||
|
|
||||||
// do the types have the same buffer size
|
|
||||||
|
|
||||||
if (cbFormat == length) {
|
|
||||||
return pbFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate the new format buffer
|
|
||||||
|
|
||||||
BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
|
|
||||||
if (pNewFormat == NULL) {
|
|
||||||
if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete the old format
|
|
||||||
|
|
||||||
if (cbFormat != 0) {
|
|
||||||
ASSERT(pbFormat);
|
|
||||||
CoTaskMemFree((PVOID)pbFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
cbFormat = length;
|
|
||||||
pbFormat = pNewFormat;
|
|
||||||
return pbFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// reallocate length bytes for the format and return a read/write pointer
|
|
||||||
// to it. We keep as much information as we can given the new buffer size
|
|
||||||
// if this fails the original format buffer is left untouched. The caller
|
|
||||||
// is responsible for ensuring the size of memory required is non zero
|
|
||||||
|
|
||||||
BYTE*
|
|
||||||
CMediaType::ReallocFormatBuffer(ULONG length)
|
|
||||||
{
|
|
||||||
ASSERT(length);
|
|
||||||
|
|
||||||
// do the types have the same buffer size
|
|
||||||
|
|
||||||
if (cbFormat == length) {
|
|
||||||
return pbFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate the new format buffer
|
|
||||||
|
|
||||||
BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
|
|
||||||
if (pNewFormat == NULL) {
|
|
||||||
if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy any previous format (or part of if new is smaller)
|
|
||||||
// delete the old format and replace with the new one
|
|
||||||
|
|
||||||
if (cbFormat != 0) {
|
|
||||||
ASSERT(pbFormat);
|
|
||||||
memcpy(pNewFormat,pbFormat,min(length,cbFormat));
|
|
||||||
CoTaskMemFree((PVOID)pbFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
cbFormat = length;
|
|
||||||
pbFormat = pNewFormat;
|
|
||||||
return pNewFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialise a media type structure
|
|
||||||
|
|
||||||
void CMediaType::InitMediaType()
|
|
||||||
{
|
|
||||||
ZeroMemory((PVOID)this, sizeof(*this));
|
|
||||||
lSampleSize = 1;
|
|
||||||
bFixedSizeSamples = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// a partially specified media type can be passed to IPin::Connect
|
|
||||||
// as a constraint on the media type used in the connection.
|
|
||||||
// the type, subtype or format type can be null.
|
|
||||||
BOOL
|
|
||||||
CMediaType::IsPartiallySpecified(void) const
|
|
||||||
{
|
|
||||||
if ((majortype == GUID_NULL) ||
|
|
||||||
(formattype == GUID_NULL)) {
|
|
||||||
return TRUE;
|
|
||||||
} else {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
CMediaType::MatchesPartial(const CMediaType* ppartial) const
|
|
||||||
{
|
|
||||||
if ((ppartial->majortype != GUID_NULL) &&
|
|
||||||
(majortype != ppartial->majortype)) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if ((ppartial->subtype != GUID_NULL) &&
|
|
||||||
(subtype != ppartial->subtype)) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ppartial->formattype != GUID_NULL) {
|
|
||||||
// if the format block is specified then it must match exactly
|
|
||||||
if (formattype != ppartial->formattype) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (cbFormat != ppartial->cbFormat) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if ((cbFormat != 0) &&
|
|
||||||
(memcmp(pbFormat, ppartial->pbFormat, cbFormat) != 0)) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// general purpose function to delete a heap allocated AM_MEDIA_TYPE structure
|
|
||||||
// which is useful when calling IEnumMediaTypes::Next as the interface
|
|
||||||
// implementation allocates the structures which you must later delete
|
|
||||||
// the format block may also be a pointer to an interface to release
|
|
||||||
|
|
||||||
void WINAPI DeleteMediaType(AM_MEDIA_TYPE *pmt)
|
|
||||||
{
|
|
||||||
// allow NULL pointers for coding simplicity
|
|
||||||
|
|
||||||
if (pmt == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeMediaType(*pmt);
|
|
||||||
CoTaskMemFree((PVOID)pmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// this also comes in useful when using the IEnumMediaTypes interface so
|
|
||||||
// that you can copy a media type, you can do nearly the same by creating
|
|
||||||
// a CMediaType object but as soon as it goes out of scope the destructor
|
|
||||||
// will delete the memory it allocated (this takes a copy of the memory)
|
|
||||||
|
|
||||||
AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc)
|
|
||||||
{
|
|
||||||
ASSERT(pSrc);
|
|
||||||
|
|
||||||
// Allocate a block of memory for the media type
|
|
||||||
|
|
||||||
AM_MEDIA_TYPE *pMediaType =
|
|
||||||
(AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
|
|
||||||
|
|
||||||
if (pMediaType == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
// Copy the variable length format block
|
|
||||||
|
|
||||||
HRESULT hr = CopyMediaType(pMediaType,pSrc);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
CoTaskMemFree((PVOID)pMediaType);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pMediaType;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Copy 1 media type to another
|
|
||||||
|
|
||||||
HRESULT WINAPI CopyMediaType(AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource)
|
|
||||||
{
|
|
||||||
// We'll leak if we copy onto one that already exists - there's one
|
|
||||||
// case we can check like that - copying to itself.
|
|
||||||
ASSERT(pmtSource != pmtTarget);
|
|
||||||
*pmtTarget = *pmtSource;
|
|
||||||
if (pmtSource->cbFormat != 0) {
|
|
||||||
ASSERT(pmtSource->pbFormat != NULL);
|
|
||||||
pmtTarget->pbFormat = (PBYTE)CoTaskMemAlloc(pmtSource->cbFormat);
|
|
||||||
if (pmtTarget->pbFormat == NULL) {
|
|
||||||
pmtTarget->cbFormat = 0;
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
} else {
|
|
||||||
CopyMemory((PVOID)pmtTarget->pbFormat, (PVOID)pmtSource->pbFormat,
|
|
||||||
pmtTarget->cbFormat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pmtTarget->pUnk != NULL) {
|
|
||||||
pmtTarget->pUnk->AddRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free an existing media type (ie free resources it holds)
|
|
||||||
|
|
||||||
void WINAPI FreeMediaType(AM_MEDIA_TYPE& mt)
|
|
||||||
{
|
|
||||||
if (mt.cbFormat != 0) {
|
|
||||||
CoTaskMemFree((PVOID)mt.pbFormat);
|
|
||||||
|
|
||||||
// Strictly unnecessary but tidier
|
|
||||||
mt.cbFormat = 0;
|
|
||||||
mt.pbFormat = NULL;
|
|
||||||
}
|
|
||||||
if (mt.pUnk != NULL) {
|
|
||||||
mt.pUnk->Release();
|
|
||||||
mt.pUnk = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize a media type from a WAVEFORMATEX
|
|
||||||
|
|
||||||
STDAPI CreateAudioMediaType(
|
|
||||||
const WAVEFORMATEX *pwfx,
|
|
||||||
AM_MEDIA_TYPE *pmt,
|
|
||||||
BOOL bSetFormat
|
|
||||||
)
|
|
||||||
{
|
|
||||||
pmt->majortype = MEDIATYPE_Audio;
|
|
||||||
if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
|
|
||||||
pmt->subtype = ((PWAVEFORMATEXTENSIBLE)pwfx)->SubFormat;
|
|
||||||
} else {
|
|
||||||
pmt->subtype = FOURCCMap(pwfx->wFormatTag);
|
|
||||||
}
|
|
||||||
pmt->formattype = FORMAT_WaveFormatEx;
|
|
||||||
pmt->bFixedSizeSamples = TRUE;
|
|
||||||
pmt->bTemporalCompression = FALSE;
|
|
||||||
pmt->lSampleSize = pwfx->nBlockAlign;
|
|
||||||
pmt->pUnk = NULL;
|
|
||||||
if (bSetFormat) {
|
|
||||||
if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
|
|
||||||
pmt->cbFormat = sizeof(WAVEFORMATEX);
|
|
||||||
} else {
|
|
||||||
pmt->cbFormat = sizeof(WAVEFORMATEX) + pwfx->cbSize;
|
|
||||||
}
|
|
||||||
pmt->pbFormat = (PBYTE)CoTaskMemAlloc(pmt->cbFormat);
|
|
||||||
if (pmt->pbFormat == NULL) {
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
|
|
||||||
CopyMemory(pmt->pbFormat, pwfx, sizeof(PCMWAVEFORMAT));
|
|
||||||
((WAVEFORMATEX *)pmt->pbFormat)->cbSize = 0;
|
|
||||||
} else {
|
|
||||||
CopyMemory(pmt->pbFormat, pwfx, pmt->cbFormat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eliminate very many spurious warnings from MS compiler
|
|
||||||
#pragma warning(disable:4514)
|
|
|
@ -1,89 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: MtType.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - defines a class that holds and manages
|
|
||||||
// media type information.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __MTYPE__
|
|
||||||
#define __MTYPE__
|
|
||||||
|
|
||||||
/* Helper class that derived pin objects can use to compare media
|
|
||||||
types etc. Has same data members as the struct AM_MEDIA_TYPE defined
|
|
||||||
in the streams IDL file, but also has (non-virtual) functions */
|
|
||||||
|
|
||||||
class CMediaType : public _AMMediaType {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
~CMediaType();
|
|
||||||
CMediaType();
|
|
||||||
CMediaType(const GUID * majortype);
|
|
||||||
CMediaType(const AM_MEDIA_TYPE&, HRESULT* phr = NULL);
|
|
||||||
CMediaType(const CMediaType&, HRESULT* phr = NULL);
|
|
||||||
|
|
||||||
CMediaType& operator=(const CMediaType&);
|
|
||||||
CMediaType& operator=(const AM_MEDIA_TYPE&);
|
|
||||||
|
|
||||||
BOOL operator == (const CMediaType&) const;
|
|
||||||
BOOL operator != (const CMediaType&) const;
|
|
||||||
|
|
||||||
HRESULT Set(const CMediaType& rt);
|
|
||||||
HRESULT Set(const AM_MEDIA_TYPE& rt);
|
|
||||||
|
|
||||||
BOOL IsValid() const;
|
|
||||||
|
|
||||||
const GUID *Type() const { return &majortype;} ;
|
|
||||||
void SetType(const GUID *);
|
|
||||||
const GUID *Subtype() const { return &subtype;} ;
|
|
||||||
void SetSubtype(const GUID *);
|
|
||||||
|
|
||||||
BOOL IsFixedSize() const {return bFixedSizeSamples; };
|
|
||||||
BOOL IsTemporalCompressed() const {return bTemporalCompression; };
|
|
||||||
ULONG GetSampleSize() const;
|
|
||||||
|
|
||||||
void SetSampleSize(ULONG sz);
|
|
||||||
void SetVariableSize();
|
|
||||||
void SetTemporalCompression(BOOL bCompressed);
|
|
||||||
|
|
||||||
// read/write pointer to format - can't change length without
|
|
||||||
// calling SetFormat, AllocFormatBuffer or ReallocFormatBuffer
|
|
||||||
|
|
||||||
BYTE* Format() const {return pbFormat; };
|
|
||||||
ULONG FormatLength() const { return cbFormat; };
|
|
||||||
|
|
||||||
void SetFormatType(const GUID *);
|
|
||||||
const GUID *FormatType() const {return &formattype; };
|
|
||||||
BOOL SetFormat(BYTE *pFormat, ULONG length);
|
|
||||||
void ResetFormatBuffer();
|
|
||||||
BYTE* AllocFormatBuffer(ULONG length);
|
|
||||||
BYTE* ReallocFormatBuffer(ULONG length);
|
|
||||||
|
|
||||||
void InitMediaType();
|
|
||||||
|
|
||||||
BOOL MatchesPartial(const CMediaType* ppartial) const;
|
|
||||||
BOOL IsPartiallySpecified(void) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* General purpose functions to copy and delete a task allocated AM_MEDIA_TYPE
|
|
||||||
structure which is useful when using the IEnumMediaFormats interface as
|
|
||||||
the implementation allocates the structures which you must later delete */
|
|
||||||
|
|
||||||
void WINAPI DeleteMediaType(AM_MEDIA_TYPE *pmt);
|
|
||||||
AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc);
|
|
||||||
HRESULT WINAPI CopyMediaType(AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource);
|
|
||||||
void WINAPI FreeMediaType(AM_MEDIA_TYPE& mt);
|
|
||||||
|
|
||||||
// Initialize a media type from a WAVEFORMATEX
|
|
||||||
|
|
||||||
STDAPI CreateAudioMediaType(
|
|
||||||
const WAVEFORMATEX *pwfx,
|
|
||||||
AM_MEDIA_TYPE *pmt,
|
|
||||||
BOOL bSetFormat);
|
|
||||||
|
|
||||||
#endif /* __MTYPE__ */
|
|
||||||
|
|
|
@ -1,794 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: OutputQ.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - implements COutputQueue class used by an
|
|
||||||
// output pin which may sometimes want to queue output samples on a
|
|
||||||
// separate thread and sometimes call Receive() directly on the input
|
|
||||||
// pin.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// COutputQueue Constructor :
|
|
||||||
//
|
|
||||||
// Determines if a thread is to be created and creates resources
|
|
||||||
//
|
|
||||||
// pInputPin - the downstream input pin we're queueing samples to
|
|
||||||
//
|
|
||||||
// phr - changed to a failure code if this function fails
|
|
||||||
// (otherwise unchanges)
|
|
||||||
//
|
|
||||||
// bAuto - Ask pInputPin if it can block in Receive by calling
|
|
||||||
// its ReceiveCanBlock method and create a thread if
|
|
||||||
// it can block, otherwise not.
|
|
||||||
//
|
|
||||||
// bQueue - if bAuto == FALSE then we create a thread if and only
|
|
||||||
// if bQueue == TRUE
|
|
||||||
//
|
|
||||||
// lBatchSize - work in batches of lBatchSize
|
|
||||||
//
|
|
||||||
// bBatchEact - Use exact batch sizes so don't send until the
|
|
||||||
// batch is full or SendAnyway() is called
|
|
||||||
//
|
|
||||||
// lListSize - If we create a thread make the list of samples queued
|
|
||||||
// to the thread have this size cache
|
|
||||||
//
|
|
||||||
// dwPriority - If we create a thread set its priority to this
|
|
||||||
//
|
|
||||||
COutputQueue::COutputQueue(
|
|
||||||
IPin *pInputPin, // Pin to send stuff to
|
|
||||||
HRESULT *phr, // 'Return code'
|
|
||||||
BOOL bAuto, // Ask pin if queue or not
|
|
||||||
BOOL bQueue, // Send through queue
|
|
||||||
LONG lBatchSize, // Batch
|
|
||||||
BOOL bBatchExact, // Batch exactly to BatchSize
|
|
||||||
LONG lListSize,
|
|
||||||
DWORD dwPriority,
|
|
||||||
bool bFlushingOpt // flushing optimization
|
|
||||||
) : m_lBatchSize(lBatchSize),
|
|
||||||
m_bBatchExact(bBatchExact && (lBatchSize > 1)),
|
|
||||||
m_hThread(NULL),
|
|
||||||
m_hSem(NULL),
|
|
||||||
m_List(NULL),
|
|
||||||
m_pPin(pInputPin),
|
|
||||||
m_ppSamples(NULL),
|
|
||||||
m_lWaiting(0),
|
|
||||||
m_pInputPin(NULL),
|
|
||||||
m_bSendAnyway(FALSE),
|
|
||||||
m_nBatched(0),
|
|
||||||
m_bFlushing(FALSE),
|
|
||||||
m_bFlushed(TRUE),
|
|
||||||
m_bFlushingOpt(bFlushingOpt),
|
|
||||||
m_bTerminate(FALSE),
|
|
||||||
m_hEventPop(NULL),
|
|
||||||
m_hr(S_OK)
|
|
||||||
{
|
|
||||||
ASSERT(m_lBatchSize > 0);
|
|
||||||
|
|
||||||
|
|
||||||
if (FAILED(*phr)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the input pin is OK and cache its IMemInputPin interface
|
|
||||||
|
|
||||||
*phr = pInputPin->QueryInterface(IID_IMemInputPin, (void **)&m_pInputPin);
|
|
||||||
if (FAILED(*phr)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if we should ask the downstream pin
|
|
||||||
|
|
||||||
if (bAuto) {
|
|
||||||
HRESULT hr = m_pInputPin->ReceiveCanBlock();
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
bQueue = hr == S_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create our sample batch
|
|
||||||
|
|
||||||
m_ppSamples = new PMEDIASAMPLE[m_lBatchSize];
|
|
||||||
if (m_ppSamples == NULL) {
|
|
||||||
*phr = E_OUTOFMEMORY;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're queueing allocate resources
|
|
||||||
|
|
||||||
if (bQueue) {
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("Creating thread for output pin")));
|
|
||||||
m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
|
|
||||||
if (m_hSem == NULL) {
|
|
||||||
DWORD dwError = GetLastError();
|
|
||||||
*phr = AmHresultFromWin32(dwError);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_List = new CSampleList(NAME("Sample Queue List"),
|
|
||||||
lListSize,
|
|
||||||
FALSE // No lock
|
|
||||||
);
|
|
||||||
if (m_List == NULL) {
|
|
||||||
*phr = E_OUTOFMEMORY;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DWORD dwThreadId;
|
|
||||||
m_hThread = CreateThread(NULL,
|
|
||||||
0,
|
|
||||||
InitialThreadProc,
|
|
||||||
(LPVOID)this,
|
|
||||||
0,
|
|
||||||
&dwThreadId);
|
|
||||||
if (m_hThread == NULL) {
|
|
||||||
DWORD dwError = GetLastError();
|
|
||||||
*phr = AmHresultFromWin32(dwError);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SetThreadPriority(m_hThread, dwPriority);
|
|
||||||
} else {
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("Calling input pin directly - no thread")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// COutputQueuee Destructor :
|
|
||||||
//
|
|
||||||
// Free all resources -
|
|
||||||
//
|
|
||||||
// Thread,
|
|
||||||
// Batched samples
|
|
||||||
//
|
|
||||||
COutputQueue::~COutputQueue()
|
|
||||||
{
|
|
||||||
DbgLog((LOG_TRACE, 3, TEXT("COutputQueue::~COutputQueue")));
|
|
||||||
/* Free our pointer */
|
|
||||||
if (m_pInputPin != NULL) {
|
|
||||||
m_pInputPin->Release();
|
|
||||||
}
|
|
||||||
if (m_hThread != NULL) {
|
|
||||||
{
|
|
||||||
CAutoLock lck(this);
|
|
||||||
m_bTerminate = TRUE;
|
|
||||||
m_hr = S_FALSE;
|
|
||||||
NotifyThread();
|
|
||||||
}
|
|
||||||
DbgWaitForSingleObject(m_hThread);
|
|
||||||
EXECUTE_ASSERT(CloseHandle(m_hThread));
|
|
||||||
|
|
||||||
// The thread frees the samples when asked to terminate
|
|
||||||
|
|
||||||
ASSERT(m_List->GetCount() == 0);
|
|
||||||
delete m_List;
|
|
||||||
} else {
|
|
||||||
FreeSamples();
|
|
||||||
}
|
|
||||||
if (m_hSem != NULL) {
|
|
||||||
EXECUTE_ASSERT(CloseHandle(m_hSem));
|
|
||||||
}
|
|
||||||
delete [] m_ppSamples;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Call the real thread proc as a member function
|
|
||||||
//
|
|
||||||
DWORD WINAPI COutputQueue::InitialThreadProc(LPVOID pv)
|
|
||||||
{
|
|
||||||
HRESULT hrCoInit = CAMThread::CoInitializeHelper();
|
|
||||||
|
|
||||||
COutputQueue *pSampleQueue = (COutputQueue *)pv;
|
|
||||||
DWORD dwReturn = pSampleQueue->ThreadProc();
|
|
||||||
|
|
||||||
if(hrCoInit == S_OK) {
|
|
||||||
CoUninitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
return dwReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Thread sending the samples downstream :
|
|
||||||
//
|
|
||||||
// When there is nothing to do the thread sets m_lWaiting (while
|
|
||||||
// holding the critical section) and then waits for m_hSem to be
|
|
||||||
// set (not holding the critical section)
|
|
||||||
//
|
|
||||||
DWORD COutputQueue::ThreadProc()
|
|
||||||
{
|
|
||||||
while (TRUE) {
|
|
||||||
BOOL bWait = FALSE;
|
|
||||||
IMediaSample *pSample;
|
|
||||||
LONG lNumberToSend; // Local copy
|
|
||||||
NewSegmentPacket* ppacket;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get a batch of samples and send it if possible
|
|
||||||
// In any case exit the loop if there is a control action
|
|
||||||
// requested
|
|
||||||
//
|
|
||||||
{
|
|
||||||
CAutoLock lck(this);
|
|
||||||
while (TRUE) {
|
|
||||||
|
|
||||||
if (m_bTerminate) {
|
|
||||||
FreeSamples();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (m_bFlushing) {
|
|
||||||
FreeSamples();
|
|
||||||
SetEvent(m_evFlushComplete);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a sample off the list
|
|
||||||
|
|
||||||
pSample = m_List->RemoveHead();
|
|
||||||
// inform derived class we took something off the queue
|
|
||||||
if (m_hEventPop) {
|
|
||||||
//DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
|
|
||||||
SetEvent(m_hEventPop);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pSample != NULL &&
|
|
||||||
!IsSpecialSample(pSample)) {
|
|
||||||
|
|
||||||
// If its just a regular sample just add it to the batch
|
|
||||||
// and exit the loop if the batch is full
|
|
||||||
|
|
||||||
m_ppSamples[m_nBatched++] = pSample;
|
|
||||||
if (m_nBatched == m_lBatchSize) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// If there was nothing in the queue and there's nothing
|
|
||||||
// to send (either because there's nothing or the batch
|
|
||||||
// isn't full) then prepare to wait
|
|
||||||
|
|
||||||
if (pSample == NULL &&
|
|
||||||
(m_bBatchExact || m_nBatched == 0)) {
|
|
||||||
|
|
||||||
// Tell other thread to set the event when there's
|
|
||||||
// something do to
|
|
||||||
|
|
||||||
ASSERT(m_lWaiting == 0);
|
|
||||||
m_lWaiting++;
|
|
||||||
bWait = TRUE;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// We break out of the loop on SEND_PACKET unless
|
|
||||||
// there's nothing to send
|
|
||||||
|
|
||||||
if (pSample == SEND_PACKET && m_nBatched == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pSample == NEW_SEGMENT) {
|
|
||||||
// now we need the parameters - we are
|
|
||||||
// guaranteed that the next packet contains them
|
|
||||||
ppacket = (NewSegmentPacket *) m_List->RemoveHead();
|
|
||||||
// we took something off the queue
|
|
||||||
if (m_hEventPop) {
|
|
||||||
//DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
|
|
||||||
SetEvent(m_hEventPop);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(ppacket);
|
|
||||||
}
|
|
||||||
// EOS_PACKET falls through here and we exit the loop
|
|
||||||
// In this way it acts like SEND_PACKET
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!bWait) {
|
|
||||||
// We look at m_nBatched from the client side so keep
|
|
||||||
// it up to date inside the critical section
|
|
||||||
lNumberToSend = m_nBatched; // Local copy
|
|
||||||
m_nBatched = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for some more data
|
|
||||||
|
|
||||||
if (bWait) {
|
|
||||||
DbgWaitForSingleObject(m_hSem);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// OK - send it if there's anything to send
|
|
||||||
// We DON'T check m_bBatchExact here because either we've got
|
|
||||||
// a full batch or we dropped through because we got
|
|
||||||
// SEND_PACKET or EOS_PACKET - both of which imply we should
|
|
||||||
// flush our batch
|
|
||||||
|
|
||||||
if (lNumberToSend != 0) {
|
|
||||||
long nProcessed;
|
|
||||||
if (m_hr == S_OK) {
|
|
||||||
ASSERT(!m_bFlushed);
|
|
||||||
HRESULT hr = m_pInputPin->ReceiveMultiple(m_ppSamples,
|
|
||||||
lNumberToSend,
|
|
||||||
&nProcessed);
|
|
||||||
/* Don't overwrite a flushing state HRESULT */
|
|
||||||
CAutoLock lck(this);
|
|
||||||
if (m_hr == S_OK) {
|
|
||||||
m_hr = hr;
|
|
||||||
}
|
|
||||||
ASSERT(!m_bFlushed);
|
|
||||||
}
|
|
||||||
while (lNumberToSend != 0) {
|
|
||||||
m_ppSamples[--lNumberToSend]->Release();
|
|
||||||
}
|
|
||||||
if (m_hr != S_OK) {
|
|
||||||
|
|
||||||
// In any case wait for more data - S_OK just
|
|
||||||
// means there wasn't an error
|
|
||||||
|
|
||||||
DbgLog((LOG_ERROR, 2, TEXT("ReceiveMultiple returned %8.8X"),
|
|
||||||
m_hr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for end of stream
|
|
||||||
|
|
||||||
if (pSample == EOS_PACKET) {
|
|
||||||
|
|
||||||
// We don't send even end of stream on if we've previously
|
|
||||||
// returned something other than S_OK
|
|
||||||
// This is because in that case the pin which returned
|
|
||||||
// something other than S_OK should have either sent
|
|
||||||
// EndOfStream() or notified the filter graph
|
|
||||||
|
|
||||||
if (m_hr == S_OK) {
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("COutputQueue sending EndOfStream()")));
|
|
||||||
HRESULT hr = m_pPin->EndOfStream();
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
DbgLog((LOG_ERROR, 2, TEXT("COutputQueue got code 0x%8.8X from EndOfStream()")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Data from a new source
|
|
||||||
|
|
||||||
if (pSample == RESET_PACKET) {
|
|
||||||
m_hr = S_OK;
|
|
||||||
SetEvent(m_evFlushComplete);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pSample == NEW_SEGMENT) {
|
|
||||||
m_pPin->NewSegment(ppacket->tStart, ppacket->tStop, ppacket->dRate);
|
|
||||||
delete ppacket;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send batched stuff anyway
|
|
||||||
void COutputQueue::SendAnyway()
|
|
||||||
{
|
|
||||||
if (!IsQueued()) {
|
|
||||||
|
|
||||||
// m_bSendAnyway is a private parameter checked in ReceiveMultiple
|
|
||||||
|
|
||||||
m_bSendAnyway = TRUE;
|
|
||||||
LONG nProcessed;
|
|
||||||
ReceiveMultiple(NULL, 0, &nProcessed);
|
|
||||||
m_bSendAnyway = FALSE;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
CAutoLock lck(this);
|
|
||||||
QueueSample(SEND_PACKET);
|
|
||||||
NotifyThread();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
COutputQueue::NewSegment(
|
|
||||||
REFERENCE_TIME tStart,
|
|
||||||
REFERENCE_TIME tStop,
|
|
||||||
double dRate)
|
|
||||||
{
|
|
||||||
if (!IsQueued()) {
|
|
||||||
if (S_OK == m_hr) {
|
|
||||||
if (m_bBatchExact) {
|
|
||||||
SendAnyway();
|
|
||||||
}
|
|
||||||
m_pPin->NewSegment(tStart, tStop, dRate);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (m_hr == S_OK) {
|
|
||||||
//
|
|
||||||
// we need to queue the new segment to appear in order in the
|
|
||||||
// data, but we need to pass parameters to it. Rather than
|
|
||||||
// take the hit of wrapping every single sample so we can tell
|
|
||||||
// special ones apart, we queue special pointers to indicate
|
|
||||||
// special packets, and we guarantee (by holding the
|
|
||||||
// critical section) that the packet immediately following a
|
|
||||||
// NEW_SEGMENT value is a NewSegmentPacket containing the
|
|
||||||
// parameters.
|
|
||||||
NewSegmentPacket * ppack = new NewSegmentPacket;
|
|
||||||
if (ppack == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ppack->tStart = tStart;
|
|
||||||
ppack->tStop = tStop;
|
|
||||||
ppack->dRate = dRate;
|
|
||||||
|
|
||||||
CAutoLock lck(this);
|
|
||||||
QueueSample(NEW_SEGMENT);
|
|
||||||
QueueSample( (IMediaSample*) ppack);
|
|
||||||
NotifyThread();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// End of Stream is queued to output device
|
|
||||||
//
|
|
||||||
void COutputQueue::EOS()
|
|
||||||
{
|
|
||||||
CAutoLock lck(this);
|
|
||||||
if (!IsQueued()) {
|
|
||||||
if (m_bBatchExact) {
|
|
||||||
SendAnyway();
|
|
||||||
}
|
|
||||||
if (m_hr == S_OK) {
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("COutputQueue sending EndOfStream()")));
|
|
||||||
m_bFlushed = FALSE;
|
|
||||||
HRESULT hr = m_pPin->EndOfStream();
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
DbgLog((LOG_ERROR, 2, TEXT("COutputQueue got code 0x%8.8X from EndOfStream()")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (m_hr == S_OK) {
|
|
||||||
m_bFlushed = FALSE;
|
|
||||||
QueueSample(EOS_PACKET);
|
|
||||||
NotifyThread();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Flush all the samples in the queue
|
|
||||||
//
|
|
||||||
void COutputQueue::BeginFlush()
|
|
||||||
{
|
|
||||||
if (IsQueued()) {
|
|
||||||
{
|
|
||||||
CAutoLock lck(this);
|
|
||||||
|
|
||||||
// block receives -- we assume this is done by the
|
|
||||||
// filter in which we are a component
|
|
||||||
|
|
||||||
// discard all queued data
|
|
||||||
|
|
||||||
m_bFlushing = TRUE;
|
|
||||||
|
|
||||||
// Make sure we discard all samples from now on
|
|
||||||
|
|
||||||
if (m_hr == S_OK) {
|
|
||||||
m_hr = S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimize so we don't keep calling downstream all the time
|
|
||||||
|
|
||||||
if (m_bFlushed && m_bFlushingOpt) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we really wait for the flush to complete
|
|
||||||
m_evFlushComplete.Reset();
|
|
||||||
|
|
||||||
NotifyThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass this downstream
|
|
||||||
|
|
||||||
m_pPin->BeginFlush();
|
|
||||||
} else {
|
|
||||||
// pass downstream first to avoid deadlocks
|
|
||||||
m_pPin->BeginFlush();
|
|
||||||
CAutoLock lck(this);
|
|
||||||
// discard all queued data
|
|
||||||
|
|
||||||
m_bFlushing = TRUE;
|
|
||||||
|
|
||||||
// Make sure we discard all samples from now on
|
|
||||||
|
|
||||||
if (m_hr == S_OK) {
|
|
||||||
m_hr = S_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// leave flush mode - pass this downstream
|
|
||||||
void COutputQueue::EndFlush()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
CAutoLock lck(this);
|
|
||||||
ASSERT(m_bFlushing);
|
|
||||||
if (m_bFlushingOpt && m_bFlushed && IsQueued()) {
|
|
||||||
m_bFlushing = FALSE;
|
|
||||||
m_hr = S_OK;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sync with pushing thread -- done in BeginFlush
|
|
||||||
// ensure no more data to go downstream -- done in BeginFlush
|
|
||||||
//
|
|
||||||
// Because we are synching here there is no need to hold the critical
|
|
||||||
// section (in fact we'd deadlock if we did!)
|
|
||||||
|
|
||||||
if (IsQueued()) {
|
|
||||||
m_evFlushComplete.Wait();
|
|
||||||
} else {
|
|
||||||
FreeSamples();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Be daring - the caller has guaranteed no samples will arrive
|
|
||||||
// before EndFlush() returns
|
|
||||||
|
|
||||||
m_bFlushing = FALSE;
|
|
||||||
m_bFlushed = TRUE;
|
|
||||||
|
|
||||||
// call EndFlush on downstream pins
|
|
||||||
|
|
||||||
m_pPin->EndFlush();
|
|
||||||
|
|
||||||
m_hr = S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// COutputQueue::QueueSample
|
|
||||||
//
|
|
||||||
// private method to Send a sample to the output queue
|
|
||||||
// The critical section MUST be held when this is called
|
|
||||||
|
|
||||||
void COutputQueue::QueueSample(IMediaSample *pSample)
|
|
||||||
{
|
|
||||||
if (NULL == m_List->AddTail(pSample)) {
|
|
||||||
if (!IsSpecialSample(pSample)) {
|
|
||||||
pSample->Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// COutputQueue::Receive()
|
|
||||||
//
|
|
||||||
// Send a single sample by the multiple sample route
|
|
||||||
// (NOTE - this could be optimized if necessary)
|
|
||||||
//
|
|
||||||
// On return the sample will have been Release()'d
|
|
||||||
//
|
|
||||||
|
|
||||||
HRESULT COutputQueue::Receive(IMediaSample *pSample)
|
|
||||||
{
|
|
||||||
LONG nProcessed;
|
|
||||||
return ReceiveMultiple(&pSample, 1, &nProcessed);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// COutputQueue::ReceiveMultiple()
|
|
||||||
//
|
|
||||||
// Send a set of samples to the downstream pin
|
|
||||||
//
|
|
||||||
// ppSamples - array of samples
|
|
||||||
// nSamples - how many
|
|
||||||
// nSamplesProcessed - How many were processed
|
|
||||||
//
|
|
||||||
// On return all samples will have been Release()'d
|
|
||||||
//
|
|
||||||
|
|
||||||
HRESULT COutputQueue::ReceiveMultiple (
|
|
||||||
IMediaSample **ppSamples,
|
|
||||||
long nSamples,
|
|
||||||
long *nSamplesProcessed)
|
|
||||||
{
|
|
||||||
CAutoLock lck(this);
|
|
||||||
// Either call directly or queue up the samples
|
|
||||||
|
|
||||||
if (!IsQueued()) {
|
|
||||||
|
|
||||||
// If we already had a bad return code then just return
|
|
||||||
|
|
||||||
if (S_OK != m_hr) {
|
|
||||||
|
|
||||||
// If we've never received anything since the last Flush()
|
|
||||||
// and the sticky return code is not S_OK we must be
|
|
||||||
// flushing
|
|
||||||
// ((!A || B) is equivalent to A implies B)
|
|
||||||
ASSERT(!m_bFlushed || m_bFlushing);
|
|
||||||
|
|
||||||
// We're supposed to Release() them anyway!
|
|
||||||
*nSamplesProcessed = 0;
|
|
||||||
for (int i = 0; i < nSamples; i++) {
|
|
||||||
DbgLog((LOG_TRACE, 3, TEXT("COutputQueue (direct) : Discarding %d samples code 0x%8.8X"),
|
|
||||||
nSamples, m_hr));
|
|
||||||
ppSamples[i]->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_hr;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// If we're flushing the sticky return code should be S_FALSE
|
|
||||||
//
|
|
||||||
ASSERT(!m_bFlushing);
|
|
||||||
m_bFlushed = FALSE;
|
|
||||||
|
|
||||||
ASSERT(m_nBatched < m_lBatchSize);
|
|
||||||
ASSERT(m_nBatched == 0 || m_bBatchExact);
|
|
||||||
|
|
||||||
// Loop processing the samples in batches
|
|
||||||
|
|
||||||
LONG iLost = 0;
|
|
||||||
long iDone;
|
|
||||||
for (iDone = 0;
|
|
||||||
iDone < nSamples || (m_nBatched != 0 && m_bSendAnyway);
|
|
||||||
) {
|
|
||||||
|
|
||||||
//pragma message (REMIND("Implement threshold scheme"))
|
|
||||||
ASSERT(m_nBatched < m_lBatchSize);
|
|
||||||
if (iDone < nSamples) {
|
|
||||||
m_ppSamples[m_nBatched++] = ppSamples[iDone++];
|
|
||||||
}
|
|
||||||
if (m_nBatched == m_lBatchSize ||
|
|
||||||
nSamples == 0 && (m_bSendAnyway || !m_bBatchExact)) {
|
|
||||||
LONG nDone;
|
|
||||||
DbgLog((LOG_TRACE, 4, TEXT("Batching %d samples"),
|
|
||||||
m_nBatched));
|
|
||||||
|
|
||||||
if (m_hr == S_OK) {
|
|
||||||
m_hr = m_pInputPin->ReceiveMultiple(m_ppSamples,
|
|
||||||
m_nBatched,
|
|
||||||
&nDone);
|
|
||||||
} else {
|
|
||||||
nDone = 0;
|
|
||||||
}
|
|
||||||
iLost += m_nBatched - nDone;
|
|
||||||
for (LONG i = 0; i < m_nBatched; i++) {
|
|
||||||
m_ppSamples[i]->Release();
|
|
||||||
}
|
|
||||||
m_nBatched = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*nSamplesProcessed = iDone - iLost;
|
|
||||||
if (*nSamplesProcessed < 0) {
|
|
||||||
*nSamplesProcessed = 0;
|
|
||||||
}
|
|
||||||
return m_hr;
|
|
||||||
} else {
|
|
||||||
/* We're sending to our thread */
|
|
||||||
|
|
||||||
if (m_hr != S_OK) {
|
|
||||||
*nSamplesProcessed = 0;
|
|
||||||
DbgLog((LOG_TRACE, 3, TEXT("COutputQueue (queued) : Discarding %d samples code 0x%8.8X"),
|
|
||||||
nSamples, m_hr));
|
|
||||||
for (int i = 0; i < nSamples; i++) {
|
|
||||||
ppSamples[i]->Release();
|
|
||||||
}
|
|
||||||
return m_hr;
|
|
||||||
}
|
|
||||||
m_bFlushed = FALSE;
|
|
||||||
for (long i = 0; i < nSamples; i++) {
|
|
||||||
QueueSample(ppSamples[i]);
|
|
||||||
}
|
|
||||||
*nSamplesProcessed = nSamples;
|
|
||||||
if (!m_bBatchExact ||
|
|
||||||
m_nBatched + m_List->GetCount() >= m_lBatchSize) {
|
|
||||||
NotifyThread();
|
|
||||||
}
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get ready for new data - cancels sticky m_hr
|
|
||||||
void COutputQueue::Reset()
|
|
||||||
{
|
|
||||||
if (!IsQueued()) {
|
|
||||||
m_hr = S_OK;
|
|
||||||
} else {
|
|
||||||
CAutoLock lck(this);
|
|
||||||
QueueSample(RESET_PACKET);
|
|
||||||
NotifyThread();
|
|
||||||
m_evFlushComplete.Wait();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove and Release() all queued and Batched samples
|
|
||||||
void COutputQueue::FreeSamples()
|
|
||||||
{
|
|
||||||
CAutoLock lck(this);
|
|
||||||
if (IsQueued()) {
|
|
||||||
while (TRUE) {
|
|
||||||
IMediaSample *pSample = m_List->RemoveHead();
|
|
||||||
// inform derived class we took something off the queue
|
|
||||||
if (m_hEventPop) {
|
|
||||||
//DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
|
|
||||||
SetEvent(m_hEventPop);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pSample == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!IsSpecialSample(pSample)) {
|
|
||||||
pSample->Release();
|
|
||||||
} else {
|
|
||||||
if (pSample == NEW_SEGMENT) {
|
|
||||||
// Free NEW_SEGMENT packet
|
|
||||||
NewSegmentPacket *ppacket =
|
|
||||||
(NewSegmentPacket *) m_List->RemoveHead();
|
|
||||||
// inform derived class we took something off the queue
|
|
||||||
if (m_hEventPop) {
|
|
||||||
//DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
|
|
||||||
SetEvent(m_hEventPop);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(ppacket != NULL);
|
|
||||||
delete ppacket;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < m_nBatched; i++) {
|
|
||||||
m_ppSamples[i]->Release();
|
|
||||||
}
|
|
||||||
m_nBatched = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify the thread if there is something to do
|
|
||||||
//
|
|
||||||
// The critical section MUST be held when this is called
|
|
||||||
void COutputQueue::NotifyThread()
|
|
||||||
{
|
|
||||||
// Optimize - no need to signal if it's not waiting
|
|
||||||
ASSERT(IsQueued());
|
|
||||||
if (m_lWaiting) {
|
|
||||||
ReleaseSemaphore(m_hSem, m_lWaiting, NULL);
|
|
||||||
m_lWaiting = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if there's any work to do
|
|
||||||
// Returns
|
|
||||||
// TRUE if there is nothing on the queue and nothing in the batch
|
|
||||||
// and all data has been sent
|
|
||||||
// FALSE otherwise
|
|
||||||
//
|
|
||||||
BOOL COutputQueue::IsIdle()
|
|
||||||
{
|
|
||||||
CAutoLock lck(this);
|
|
||||||
|
|
||||||
// We're idle if
|
|
||||||
// there is no thread (!IsQueued()) OR
|
|
||||||
// the thread is waiting for more work (m_lWaiting != 0)
|
|
||||||
// AND
|
|
||||||
// there's nothing in the current batch (m_nBatched == 0)
|
|
||||||
|
|
||||||
if (IsQueued() && m_lWaiting == 0 || m_nBatched != 0) {
|
|
||||||
return FALSE;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// If we're idle it shouldn't be possible for there
|
|
||||||
// to be anything on the work queue
|
|
||||||
|
|
||||||
ASSERT(!IsQueued() || m_List->GetCount() == 0);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void COutputQueue::SetPopEvent(HANDLE hEvent)
|
|
||||||
{
|
|
||||||
m_hEventPop = hEvent;
|
|
||||||
}
|
|
|
@ -1,137 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: OutputQ.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - defines the COutputQueue class, which
|
|
||||||
// makes a queue of samples and sends them to an output pin. The
|
|
||||||
// class will optionally send the samples to the pin directly.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
typedef CGenericList<IMediaSample> CSampleList;
|
|
||||||
|
|
||||||
class COutputQueue : public CCritSec
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
COutputQueue(IPin *pInputPin, // Pin to send stuff to
|
|
||||||
HRESULT *phr, // 'Return code'
|
|
||||||
BOOL bAuto = TRUE, // Ask pin if blocks
|
|
||||||
BOOL bQueue = TRUE, // Send through queue (ignored if
|
|
||||||
// bAuto set)
|
|
||||||
LONG lBatchSize = 1, // Batch
|
|
||||||
BOOL bBatchExact = FALSE,// Batch exactly to BatchSize
|
|
||||||
LONG lListSize = // Likely number in the list
|
|
||||||
DEFAULTCACHE,
|
|
||||||
DWORD dwPriority = // Priority of thread to create
|
|
||||||
THREAD_PRIORITY_NORMAL,
|
|
||||||
bool bFlushingOpt = false // flushing optimization
|
|
||||||
);
|
|
||||||
~COutputQueue();
|
|
||||||
|
|
||||||
// enter flush state - discard all data
|
|
||||||
void BeginFlush(); // Begin flushing samples
|
|
||||||
|
|
||||||
// re-enable receives (pass this downstream)
|
|
||||||
void EndFlush(); // Complete flush of samples - downstream
|
|
||||||
// pin guaranteed not to block at this stage
|
|
||||||
|
|
||||||
void EOS(); // Call this on End of stream
|
|
||||||
|
|
||||||
void SendAnyway(); // Send batched samples anyway (if bBatchExact set)
|
|
||||||
|
|
||||||
void NewSegment(
|
|
||||||
REFERENCE_TIME tStart,
|
|
||||||
REFERENCE_TIME tStop,
|
|
||||||
double dRate);
|
|
||||||
|
|
||||||
HRESULT Receive(IMediaSample *pSample);
|
|
||||||
|
|
||||||
// do something with these media samples
|
|
||||||
HRESULT ReceiveMultiple (
|
|
||||||
IMediaSample **pSamples,
|
|
||||||
long nSamples,
|
|
||||||
long *nSamplesProcessed);
|
|
||||||
|
|
||||||
void Reset(); // Reset m_hr ready for more data
|
|
||||||
|
|
||||||
// See if its idle or not
|
|
||||||
BOOL IsIdle();
|
|
||||||
|
|
||||||
// give the class an event to fire after everything removed from the queue
|
|
||||||
void SetPopEvent(HANDLE hEvent);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static DWORD WINAPI InitialThreadProc(LPVOID pv);
|
|
||||||
DWORD ThreadProc();
|
|
||||||
BOOL IsQueued()
|
|
||||||
{
|
|
||||||
return m_List != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The critical section MUST be held when this is called
|
|
||||||
void QueueSample(IMediaSample *pSample);
|
|
||||||
|
|
||||||
BOOL IsSpecialSample(IMediaSample *pSample)
|
|
||||||
{
|
|
||||||
return (DWORD_PTR)pSample > (DWORD_PTR)(LONG_PTR)(-16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove and Release() batched and queued samples
|
|
||||||
void FreeSamples();
|
|
||||||
|
|
||||||
// Notify the thread there is something to do
|
|
||||||
void NotifyThread();
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Queue 'messages'
|
|
||||||
#define SEND_PACKET ((IMediaSample *)(LONG_PTR)(-2)) // Send batch
|
|
||||||
#define EOS_PACKET ((IMediaSample *)(LONG_PTR)(-3)) // End of stream
|
|
||||||
#define RESET_PACKET ((IMediaSample *)(LONG_PTR)(-4)) // Reset m_hr
|
|
||||||
#define NEW_SEGMENT ((IMediaSample *)(LONG_PTR)(-5)) // send NewSegment
|
|
||||||
|
|
||||||
// new segment packet is always followed by one of these
|
|
||||||
struct NewSegmentPacket {
|
|
||||||
REFERENCE_TIME tStart;
|
|
||||||
REFERENCE_TIME tStop;
|
|
||||||
double dRate;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Remember input stuff
|
|
||||||
IPin * const m_pPin;
|
|
||||||
IMemInputPin * m_pInputPin;
|
|
||||||
BOOL const m_bBatchExact;
|
|
||||||
LONG const m_lBatchSize;
|
|
||||||
|
|
||||||
CSampleList * m_List;
|
|
||||||
HANDLE m_hSem;
|
|
||||||
CAMEvent m_evFlushComplete;
|
|
||||||
HANDLE m_hThread;
|
|
||||||
IMediaSample ** m_ppSamples;
|
|
||||||
LONG m_nBatched;
|
|
||||||
|
|
||||||
// Wait optimization
|
|
||||||
LONG m_lWaiting;
|
|
||||||
// Flush synchronization
|
|
||||||
BOOL m_bFlushing;
|
|
||||||
|
|
||||||
// flushing optimization. some downstream filters have trouble
|
|
||||||
// with the queue's flushing optimization. other rely on it
|
|
||||||
BOOL m_bFlushed;
|
|
||||||
bool m_bFlushingOpt;
|
|
||||||
|
|
||||||
// Terminate now
|
|
||||||
BOOL m_bTerminate;
|
|
||||||
|
|
||||||
// Send anyway flag for batching
|
|
||||||
BOOL m_bSendAnyway;
|
|
||||||
|
|
||||||
// Deferred 'return code'
|
|
||||||
BOOL volatile m_hr;
|
|
||||||
|
|
||||||
// an event that can be fired after every deliver
|
|
||||||
HANDLE m_hEventPop;
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,196 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: PStream.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
|
|
||||||
#ifdef PERF
|
|
||||||
#include <measure.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Constructor
|
|
||||||
//
|
|
||||||
CPersistStream::CPersistStream(IUnknown *punk, HRESULT *phr)
|
|
||||||
: mPS_fDirty(FALSE)
|
|
||||||
{
|
|
||||||
mPS_dwFileVersion = GetSoftwareVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Destructor
|
|
||||||
//
|
|
||||||
CPersistStream::~CPersistStream() {
|
|
||||||
// Nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
SAMPLE CODE TO COPY - not active at the moment
|
|
||||||
|
|
||||||
//
|
|
||||||
// NonDelegatingQueryInterface
|
|
||||||
//
|
|
||||||
// This object supports IPersist & IPersistStream
|
|
||||||
STDMETHODIMP CPersistStream::NonDelegatingQueryInterface(REFIID riid, void **ppv)
|
|
||||||
{
|
|
||||||
if (riid == IID_IPersist) {
|
|
||||||
return GetInterface((IPersist *) this, ppv);
|
|
||||||
}
|
|
||||||
else if (riid == IID_IPersistStream) {
|
|
||||||
return GetInterface((IPersistStream *) this, ppv);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// WriteToStream
|
|
||||||
//
|
|
||||||
// Writes to the stream (default action is to write nothing)
|
|
||||||
HRESULT CPersistStream::WriteToStream(IStream *pStream)
|
|
||||||
{
|
|
||||||
// You can override this to do things like
|
|
||||||
// hr = pStream->Write(MyStructure, sizeof(MyStructure), NULL);
|
|
||||||
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HRESULT CPersistStream::ReadFromStream(IStream * pStream)
|
|
||||||
{
|
|
||||||
// You can override this to do things like
|
|
||||||
// hr = pStream->Read(MyStructure, sizeof(MyStructure), NULL);
|
|
||||||
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Load
|
|
||||||
//
|
|
||||||
// Load all the data from the given stream
|
|
||||||
STDMETHODIMP CPersistStream::Load(LPSTREAM pStm)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
// Load the version number then the data
|
|
||||||
mPS_dwFileVersion = ReadInt(pStm, hr);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ReadFromStream(pStm);
|
|
||||||
} // Load
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Save
|
|
||||||
//
|
|
||||||
// Save the contents of this Stream.
|
|
||||||
STDMETHODIMP CPersistStream::Save(LPSTREAM pStm, BOOL fClearDirty)
|
|
||||||
{
|
|
||||||
|
|
||||||
HRESULT hr = WriteInt(pStm, GetSoftwareVersion());
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = WriteToStream(pStm);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
mPS_fDirty = !fClearDirty;
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
} // Save
|
|
||||||
|
|
||||||
|
|
||||||
// WriteInt
|
|
||||||
//
|
|
||||||
// Writes an integer to an IStream as 11 UNICODE characters followed by one space.
|
|
||||||
// You could use this for shorts or unsigneds or anything (up to 32 bits)
|
|
||||||
// where the value isn't actually truncated by squeezing it into 32 bits.
|
|
||||||
// Values such as (unsigned) 0x80000000 would come out as -2147483648
|
|
||||||
// but would then load as 0x80000000 through ReadInt. Cast as you please.
|
|
||||||
|
|
||||||
STDAPI WriteInt(IStream *pIStream, int n)
|
|
||||||
{
|
|
||||||
WCHAR Buff[13]; // Allows for trailing null that we don't write
|
|
||||||
(void)StringCchPrintfW(Buff, NUMELMS(Buff), L"%011d ",n);
|
|
||||||
return pIStream->Write(&(Buff[0]), 12*sizeof(WCHAR), NULL);
|
|
||||||
} // WriteInt
|
|
||||||
|
|
||||||
|
|
||||||
// ReadInt
|
|
||||||
//
|
|
||||||
// Reads an integer from an IStream.
|
|
||||||
// Read as 4 bytes. You could use this for shorts or unsigneds or anything
|
|
||||||
// where the value isn't actually truncated by squeezing it into 32 bits
|
|
||||||
// Striped down subset of what sscanf can do (without dragging in the C runtime)
|
|
||||||
|
|
||||||
STDAPI_(int) ReadInt(IStream *pIStream, HRESULT &hr)
|
|
||||||
{
|
|
||||||
|
|
||||||
int Sign = 1;
|
|
||||||
unsigned int n = 0; // result wil be n*Sign
|
|
||||||
WCHAR wch;
|
|
||||||
|
|
||||||
hr = pIStream->Read( &wch, sizeof(wch), NULL);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wch==L'-'){
|
|
||||||
Sign = -1;
|
|
||||||
hr = pIStream->Read( &wch, sizeof(wch), NULL);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for( ; ; ) {
|
|
||||||
if (wch>=L'0' && wch<=L'9') {
|
|
||||||
n = 10*n+(int)(wch-L'0');
|
|
||||||
} else if ( wch == L' '
|
|
||||||
|| wch == L'\t'
|
|
||||||
|| wch == L'\r'
|
|
||||||
|| wch == L'\n'
|
|
||||||
|| wch == L'\0'
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
hr = VFW_E_INVALID_FILE_FORMAT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = pIStream->Read( &wch, sizeof(wch), NULL);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n==0x80000000 && Sign==-1) {
|
|
||||||
// This is the negative number that has no positive version!
|
|
||||||
return (int)n;
|
|
||||||
}
|
|
||||||
else return (int)n * Sign;
|
|
||||||
} // ReadInt
|
|
||||||
|
|
||||||
|
|
||||||
// The microsoft C/C++ compile generates level 4 warnings to the effect that
|
|
||||||
// a particular inline function (from some base class) was not needed.
|
|
||||||
// This line gets rid of hundreds of such unwanted messages and makes
|
|
||||||
// -W4 compilation feasible:
|
|
||||||
#pragma warning(disable: 4514)
|
|
|
@ -1,114 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: PStream.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - defines a class for persistent properties
|
|
||||||
// of filters.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __PSTREAM__
|
|
||||||
#define __PSTREAM__
|
|
||||||
|
|
||||||
// Base class for persistent properties of filters
|
|
||||||
// (i.e. filter properties in saved graphs)
|
|
||||||
|
|
||||||
// The simplest way to use this is:
|
|
||||||
// 1. Arrange for your filter to inherit this class
|
|
||||||
// 2. Implement in your class WriteToStream and ReadFromStream
|
|
||||||
// These will override the "do nothing" functions here.
|
|
||||||
// 3. Change your NonDelegatingQueryInterface to handle IPersistStream
|
|
||||||
// 4. Implement SizeMax to return the number of bytes of data you save.
|
|
||||||
// If you save UNICODE data, don't forget a char is 2 bytes.
|
|
||||||
// 5. Whenever your data changes, call SetDirty()
|
|
||||||
//
|
|
||||||
// At some point you may decide to alter, or extend the format of your data.
|
|
||||||
// At that point you will wish that you had a version number in all the old
|
|
||||||
// saved graphs, so that you can tell, when you read them, whether they
|
|
||||||
// represent the old or new form. To assist you in this, this class
|
|
||||||
// writes and reads a version number.
|
|
||||||
// When it writes, it calls GetSoftwareVersion() to enquire what version
|
|
||||||
// of the software we have at the moment. (In effect this is a version number
|
|
||||||
// of the data layout in the file). It writes this as the first thing in the data.
|
|
||||||
// If you want to change the version, implement (override) GetSoftwareVersion().
|
|
||||||
// It reads this from the file into mPS_dwFileVersion before calling ReadFromStream,
|
|
||||||
// so in ReadFromStream you can check mPS_dwFileVersion to see if you are reading
|
|
||||||
// an old version file.
|
|
||||||
// Normally you should accept files whose version is no newer than the software
|
|
||||||
// version that's reading them.
|
|
||||||
|
|
||||||
|
|
||||||
// CPersistStream
|
|
||||||
//
|
|
||||||
// Implements IPersistStream.
|
|
||||||
// See 'OLE Programmers Reference (Vol 1):Structured Storage Overview' for
|
|
||||||
// more implementation information.
|
|
||||||
class CPersistStream : public IPersistStream {
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Internal state:
|
|
||||||
|
|
||||||
protected:
|
|
||||||
DWORD mPS_dwFileVersion; // version number of file (being read)
|
|
||||||
BOOL mPS_fDirty;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// IPersistStream methods
|
|
||||||
|
|
||||||
STDMETHODIMP IsDirty()
|
|
||||||
{return (mPS_fDirty ? S_OK : S_FALSE);} // note FALSE means clean
|
|
||||||
STDMETHODIMP Load(LPSTREAM pStm);
|
|
||||||
STDMETHODIMP Save(LPSTREAM pStm, BOOL fClearDirty);
|
|
||||||
STDMETHODIMP GetSizeMax(ULARGE_INTEGER * pcbSize)
|
|
||||||
// Allow 24 bytes for version.
|
|
||||||
{ pcbSize->QuadPart = 12*sizeof(WCHAR)+SizeMax(); return NOERROR; }
|
|
||||||
|
|
||||||
// implementation
|
|
||||||
|
|
||||||
CPersistStream(IUnknown *punk, HRESULT *phr);
|
|
||||||
~CPersistStream();
|
|
||||||
|
|
||||||
HRESULT SetDirty(BOOL fDirty)
|
|
||||||
{ mPS_fDirty = fDirty; return NOERROR;}
|
|
||||||
|
|
||||||
|
|
||||||
// override to reveal IPersist & IPersistStream
|
|
||||||
// STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
|
|
||||||
|
|
||||||
// --- IPersist ---
|
|
||||||
|
|
||||||
// You must override this to provide your own class id
|
|
||||||
STDMETHODIMP GetClassID(CLSID *pClsid) PURE;
|
|
||||||
|
|
||||||
// overrideable if you want
|
|
||||||
// file version number. Override it if you ever change format
|
|
||||||
virtual DWORD GetSoftwareVersion(void) { return 0; }
|
|
||||||
|
|
||||||
|
|
||||||
//=========================================================================
|
|
||||||
// OVERRIDE THESE to read and write your data
|
|
||||||
// OVERRIDE THESE to read and write your data
|
|
||||||
// OVERRIDE THESE to read and write your data
|
|
||||||
|
|
||||||
virtual int SizeMax() {return 0;}
|
|
||||||
virtual HRESULT WriteToStream(IStream *pStream);
|
|
||||||
virtual HRESULT ReadFromStream(IStream *pStream);
|
|
||||||
//=========================================================================
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// --- Useful helpers ---
|
|
||||||
|
|
||||||
|
|
||||||
// Writes an int to an IStream as UNICODE.
|
|
||||||
STDAPI WriteInt(IStream *pIStream, int n);
|
|
||||||
|
|
||||||
// inverse of WriteInt
|
|
||||||
STDAPI_(int) ReadInt(IStream *pIStream, HRESULT &hr);
|
|
||||||
|
|
||||||
#endif // __PSTREAM__
|
|
|
@ -1,527 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: PullPin.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - implements CPullPin class that pulls data
|
|
||||||
// from IAsyncReader.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
#include "pullpin.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CPullPin::CPullPin()
|
|
||||||
: m_pReader(NULL),
|
|
||||||
m_pAlloc(NULL),
|
|
||||||
m_State(TM_Exit)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CPullPin::~CPullPin()
|
|
||||||
{
|
|
||||||
Disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns S_OK if successfully connected to an IAsyncReader interface
|
|
||||||
// from this object
|
|
||||||
// Optional allocator should be proposed as a preferred allocator if
|
|
||||||
// necessary
|
|
||||||
HRESULT
|
|
||||||
CPullPin::Connect(IUnknown* pUnk, IMemAllocator* pAlloc, BOOL bSync)
|
|
||||||
{
|
|
||||||
CAutoLock lock(&m_AccessLock);
|
|
||||||
|
|
||||||
if (m_pReader) {
|
|
||||||
return VFW_E_ALREADY_CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT hr = pUnk->QueryInterface(IID_IAsyncReader, (void**)&m_pReader);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = DecideAllocator(pAlloc, NULL);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
Disconnect();
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
LONGLONG llTotal, llAvail;
|
|
||||||
hr = m_pReader->Length(&llTotal, &llAvail);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
Disconnect();
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert from file position to reference time
|
|
||||||
m_tDuration = llTotal * UNITS;
|
|
||||||
m_tStop = m_tDuration;
|
|
||||||
m_tStart = 0;
|
|
||||||
|
|
||||||
m_bSync = bSync;
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// disconnect any connection made in Connect
|
|
||||||
HRESULT
|
|
||||||
CPullPin::Disconnect()
|
|
||||||
{
|
|
||||||
CAutoLock lock(&m_AccessLock);
|
|
||||||
|
|
||||||
StopThread();
|
|
||||||
|
|
||||||
if (m_pReader) {
|
|
||||||
m_pReader->Release();
|
|
||||||
m_pReader = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_pAlloc) {
|
|
||||||
m_pAlloc->Release();
|
|
||||||
m_pAlloc = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// agree an allocator using RequestAllocator - optional
|
|
||||||
// props param specifies your requirements (non-zero fields).
|
|
||||||
// returns an error code if fail to match requirements.
|
|
||||||
// optional IMemAllocator interface is offered as a preferred allocator
|
|
||||||
// but no error occurs if it can't be met.
|
|
||||||
HRESULT
|
|
||||||
CPullPin::DecideAllocator(
|
|
||||||
IMemAllocator * pAlloc,
|
|
||||||
ALLOCATOR_PROPERTIES * pProps)
|
|
||||||
{
|
|
||||||
ALLOCATOR_PROPERTIES *pRequest;
|
|
||||||
ALLOCATOR_PROPERTIES Request;
|
|
||||||
if (pProps == NULL) {
|
|
||||||
Request.cBuffers = 3;
|
|
||||||
Request.cbBuffer = 64*1024;
|
|
||||||
Request.cbAlign = 0;
|
|
||||||
Request.cbPrefix = 0;
|
|
||||||
pRequest = &Request;
|
|
||||||
} else {
|
|
||||||
pRequest = pProps;
|
|
||||||
}
|
|
||||||
HRESULT hr = m_pReader->RequestAllocator(
|
|
||||||
pAlloc,
|
|
||||||
pRequest,
|
|
||||||
&m_pAlloc);
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// start pulling data
|
|
||||||
HRESULT
|
|
||||||
CPullPin::Active(void)
|
|
||||||
{
|
|
||||||
ASSERT(!ThreadExists());
|
|
||||||
return StartThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop pulling data
|
|
||||||
HRESULT
|
|
||||||
CPullPin::Inactive(void)
|
|
||||||
{
|
|
||||||
StopThread();
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
CPullPin::Seek(REFERENCE_TIME tStart, REFERENCE_TIME tStop)
|
|
||||||
{
|
|
||||||
CAutoLock lock(&m_AccessLock);
|
|
||||||
|
|
||||||
ThreadMsg AtStart = m_State;
|
|
||||||
|
|
||||||
if (AtStart == TM_Start) {
|
|
||||||
BeginFlush();
|
|
||||||
PauseThread();
|
|
||||||
EndFlush();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_tStart = tStart;
|
|
||||||
m_tStop = tStop;
|
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (AtStart == TM_Start) {
|
|
||||||
hr = StartThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
CPullPin::Duration(REFERENCE_TIME* ptDuration)
|
|
||||||
{
|
|
||||||
*ptDuration = m_tDuration;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
CPullPin::StartThread()
|
|
||||||
{
|
|
||||||
CAutoLock lock(&m_AccessLock);
|
|
||||||
|
|
||||||
if (!m_pAlloc || !m_pReader) {
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT hr;
|
|
||||||
if (!ThreadExists()) {
|
|
||||||
|
|
||||||
// commit allocator
|
|
||||||
hr = m_pAlloc->Commit();
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// start thread
|
|
||||||
if (!Create()) {
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_State = TM_Start;
|
|
||||||
hr = (HRESULT) CallWorker(m_State);
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
CPullPin::PauseThread()
|
|
||||||
{
|
|
||||||
CAutoLock lock(&m_AccessLock);
|
|
||||||
|
|
||||||
if (!ThreadExists()) {
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// need to flush to ensure the thread is not blocked
|
|
||||||
// in WaitForNext
|
|
||||||
HRESULT hr = m_pReader->BeginFlush();
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_State = TM_Pause;
|
|
||||||
hr = CallWorker(TM_Pause);
|
|
||||||
|
|
||||||
m_pReader->EndFlush();
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
CPullPin::StopThread()
|
|
||||||
{
|
|
||||||
CAutoLock lock(&m_AccessLock);
|
|
||||||
|
|
||||||
if (!ThreadExists()) {
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// need to flush to ensure the thread is not blocked
|
|
||||||
// in WaitForNext
|
|
||||||
HRESULT hr = m_pReader->BeginFlush();
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_State = TM_Exit;
|
|
||||||
hr = CallWorker(TM_Exit);
|
|
||||||
|
|
||||||
m_pReader->EndFlush();
|
|
||||||
|
|
||||||
// wait for thread to completely exit
|
|
||||||
Close();
|
|
||||||
|
|
||||||
// decommit allocator
|
|
||||||
if (m_pAlloc) {
|
|
||||||
m_pAlloc->Decommit();
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
CPullPin::ThreadProc(void)
|
|
||||||
{
|
|
||||||
while(1) {
|
|
||||||
DWORD cmd = GetRequest();
|
|
||||||
switch(cmd) {
|
|
||||||
case TM_Exit:
|
|
||||||
Reply(S_OK);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case TM_Pause:
|
|
||||||
// we are paused already
|
|
||||||
Reply(S_OK);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TM_Start:
|
|
||||||
Reply(S_OK);
|
|
||||||
Process();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// at this point, there should be no outstanding requests on the
|
|
||||||
// upstream filter.
|
|
||||||
// We should force begin/endflush to ensure that this is true.
|
|
||||||
// !!!Note that we may currently be inside a BeginFlush/EndFlush pair
|
|
||||||
// on another thread, but the premature EndFlush will do no harm now
|
|
||||||
// that we are idle.
|
|
||||||
m_pReader->BeginFlush();
|
|
||||||
CleanupCancelled();
|
|
||||||
m_pReader->EndFlush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
CPullPin::QueueSample(
|
|
||||||
REFERENCE_TIME& tCurrent,
|
|
||||||
REFERENCE_TIME tAlignStop,
|
|
||||||
BOOL bDiscontinuity
|
|
||||||
)
|
|
||||||
{
|
|
||||||
IMediaSample* pSample;
|
|
||||||
|
|
||||||
HRESULT hr = m_pAlloc->GetBuffer(&pSample, NULL, NULL, 0);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
LONGLONG tStopThis = tCurrent + (pSample->GetSize() * UNITS);
|
|
||||||
if (tStopThis > tAlignStop) {
|
|
||||||
tStopThis = tAlignStop;
|
|
||||||
}
|
|
||||||
pSample->SetTime(&tCurrent, &tStopThis);
|
|
||||||
tCurrent = tStopThis;
|
|
||||||
|
|
||||||
pSample->SetDiscontinuity(bDiscontinuity);
|
|
||||||
|
|
||||||
hr = m_pReader->Request(
|
|
||||||
pSample,
|
|
||||||
0);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
pSample->Release();
|
|
||||||
|
|
||||||
CleanupCancelled();
|
|
||||||
OnError(hr);
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
CPullPin::CollectAndDeliver(
|
|
||||||
REFERENCE_TIME tStart,
|
|
||||||
REFERENCE_TIME tStop)
|
|
||||||
{
|
|
||||||
IMediaSample* pSample = NULL; // better be sure pSample is set
|
|
||||||
DWORD_PTR dwUnused;
|
|
||||||
HRESULT hr = m_pReader->WaitForNext(
|
|
||||||
INFINITE,
|
|
||||||
&pSample,
|
|
||||||
&dwUnused);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
if (pSample) {
|
|
||||||
pSample->Release();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
hr = DeliverSample(pSample, tStart, tStop);
|
|
||||||
}
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
CleanupCancelled();
|
|
||||||
OnError(hr);
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
CPullPin::DeliverSample(
|
|
||||||
IMediaSample* pSample,
|
|
||||||
REFERENCE_TIME tStart,
|
|
||||||
REFERENCE_TIME tStop
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// fix up sample if past actual stop (for sector alignment)
|
|
||||||
REFERENCE_TIME t1, t2;
|
|
||||||
pSample->GetTime(&t1, &t2);
|
|
||||||
if (t2 > tStop) {
|
|
||||||
t2 = tStop;
|
|
||||||
}
|
|
||||||
|
|
||||||
// adjust times to be relative to (aligned) start time
|
|
||||||
t1 -= tStart;
|
|
||||||
t2 -= tStart;
|
|
||||||
pSample->SetTime(&t1, &t2);
|
|
||||||
|
|
||||||
|
|
||||||
HRESULT hr = Receive(pSample);
|
|
||||||
pSample->Release();
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPullPin::Process(void)
|
|
||||||
{
|
|
||||||
// is there anything to do?
|
|
||||||
if (m_tStop <= m_tStart) {
|
|
||||||
EndOfStream();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL bDiscontinuity = TRUE;
|
|
||||||
|
|
||||||
// if there is more than one sample at the allocator,
|
|
||||||
// then try to queue 2 at once in order to overlap.
|
|
||||||
// -- get buffer count and required alignment
|
|
||||||
ALLOCATOR_PROPERTIES Actual;
|
|
||||||
HRESULT hr = m_pAlloc->GetProperties(&Actual);
|
|
||||||
|
|
||||||
// align the start position downwards
|
|
||||||
REFERENCE_TIME tStart = AlignDown(m_tStart / UNITS, Actual.cbAlign) * UNITS;
|
|
||||||
REFERENCE_TIME tCurrent = tStart;
|
|
||||||
|
|
||||||
REFERENCE_TIME tStop = m_tStop;
|
|
||||||
if (tStop > m_tDuration) {
|
|
||||||
tStop = m_tDuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
// align the stop position - may be past stop, but that
|
|
||||||
// doesn't matter
|
|
||||||
REFERENCE_TIME tAlignStop = AlignUp(tStop / UNITS, Actual.cbAlign) * UNITS;
|
|
||||||
|
|
||||||
|
|
||||||
DWORD dwRequest;
|
|
||||||
|
|
||||||
if (!m_bSync) {
|
|
||||||
|
|
||||||
// Break out of the loop either if we get to the end or we're asked
|
|
||||||
// to do something else
|
|
||||||
while (tCurrent < tAlignStop) {
|
|
||||||
|
|
||||||
// Break out without calling EndOfStream if we're asked to
|
|
||||||
// do something different
|
|
||||||
if (CheckRequest(&dwRequest)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// queue a first sample
|
|
||||||
if (Actual.cBuffers > 1) {
|
|
||||||
|
|
||||||
hr = QueueSample(tCurrent, tAlignStop, TRUE);
|
|
||||||
bDiscontinuity = FALSE;
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// loop queueing second and waiting for first..
|
|
||||||
while (tCurrent < tAlignStop) {
|
|
||||||
|
|
||||||
hr = QueueSample(tCurrent, tAlignStop, bDiscontinuity);
|
|
||||||
bDiscontinuity = FALSE;
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = CollectAndDeliver(tStart, tStop);
|
|
||||||
if (S_OK != hr) {
|
|
||||||
|
|
||||||
// stop if error, or if downstream filter said
|
|
||||||
// to stop.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Actual.cBuffers > 1) {
|
|
||||||
hr = CollectAndDeliver(tStart, tStop);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// sync version of above loop
|
|
||||||
while (tCurrent < tAlignStop) {
|
|
||||||
|
|
||||||
// Break out without calling EndOfStream if we're asked to
|
|
||||||
// do something different
|
|
||||||
if (CheckRequest(&dwRequest)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMediaSample* pSample;
|
|
||||||
|
|
||||||
hr = m_pAlloc->GetBuffer(&pSample, NULL, NULL, 0);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
OnError(hr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LONGLONG tStopThis = tCurrent + (pSample->GetSize() * UNITS);
|
|
||||||
if (tStopThis > tAlignStop) {
|
|
||||||
tStopThis = tAlignStop;
|
|
||||||
}
|
|
||||||
pSample->SetTime(&tCurrent, &tStopThis);
|
|
||||||
tCurrent = tStopThis;
|
|
||||||
|
|
||||||
if (bDiscontinuity) {
|
|
||||||
pSample->SetDiscontinuity(TRUE);
|
|
||||||
bDiscontinuity = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = m_pReader->SyncReadAligned(pSample);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
pSample->Release();
|
|
||||||
OnError(hr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = DeliverSample(pSample, tStart, tStop);
|
|
||||||
if (hr != S_OK) {
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
OnError(hr);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EndOfStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
// after a flush, cancelled i/o will be waiting for collection
|
|
||||||
// and release
|
|
||||||
void
|
|
||||||
CPullPin::CleanupCancelled(void)
|
|
||||||
{
|
|
||||||
while (1) {
|
|
||||||
IMediaSample * pSample;
|
|
||||||
DWORD_PTR dwUnused;
|
|
||||||
|
|
||||||
HRESULT hr = m_pReader->WaitForNext(
|
|
||||||
0, // no wait
|
|
||||||
&pSample,
|
|
||||||
&dwUnused);
|
|
||||||
if(pSample) {
|
|
||||||
pSample->Release();
|
|
||||||
} else {
|
|
||||||
// no more samples
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,152 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: PullPin.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - defines CPullPin class.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __PULLPIN_H__
|
|
||||||
#define __PULLPIN_H__
|
|
||||||
|
|
||||||
//
|
|
||||||
// CPullPin
|
|
||||||
//
|
|
||||||
// object supporting pulling data from an IAsyncReader interface.
|
|
||||||
// Given a start/stop position, calls a pure Receive method with each
|
|
||||||
// IMediaSample received.
|
|
||||||
//
|
|
||||||
// This is essentially for use in a MemInputPin when it finds itself
|
|
||||||
// connected to an IAsyncReader pin instead of a pushing pin.
|
|
||||||
//
|
|
||||||
|
|
||||||
class CPullPin : public CAMThread
|
|
||||||
{
|
|
||||||
IAsyncReader* m_pReader;
|
|
||||||
REFERENCE_TIME m_tStart;
|
|
||||||
REFERENCE_TIME m_tStop;
|
|
||||||
REFERENCE_TIME m_tDuration;
|
|
||||||
BOOL m_bSync;
|
|
||||||
|
|
||||||
enum ThreadMsg {
|
|
||||||
TM_Pause, // stop pulling and wait for next message
|
|
||||||
TM_Start, // start pulling
|
|
||||||
TM_Exit, // stop and exit
|
|
||||||
};
|
|
||||||
|
|
||||||
ThreadMsg m_State;
|
|
||||||
|
|
||||||
// override pure thread proc from CAMThread
|
|
||||||
DWORD ThreadProc(void);
|
|
||||||
|
|
||||||
// running pull method (check m_bSync)
|
|
||||||
void Process(void);
|
|
||||||
|
|
||||||
// clean up any cancelled i/o after a flush
|
|
||||||
void CleanupCancelled(void);
|
|
||||||
|
|
||||||
// suspend thread from pulling, eg during seek
|
|
||||||
HRESULT PauseThread();
|
|
||||||
|
|
||||||
// start thread pulling - create thread if necy
|
|
||||||
HRESULT StartThread();
|
|
||||||
|
|
||||||
// stop and close thread
|
|
||||||
HRESULT StopThread();
|
|
||||||
|
|
||||||
// called from ProcessAsync to queue and collect requests
|
|
||||||
HRESULT QueueSample(
|
|
||||||
REFERENCE_TIME& tCurrent,
|
|
||||||
REFERENCE_TIME tAlignStop,
|
|
||||||
BOOL bDiscontinuity);
|
|
||||||
|
|
||||||
HRESULT CollectAndDeliver(
|
|
||||||
REFERENCE_TIME tStart,
|
|
||||||
REFERENCE_TIME tStop);
|
|
||||||
|
|
||||||
HRESULT DeliverSample(
|
|
||||||
IMediaSample* pSample,
|
|
||||||
REFERENCE_TIME tStart,
|
|
||||||
REFERENCE_TIME tStop);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
IMemAllocator * m_pAlloc;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CPullPin();
|
|
||||||
virtual ~CPullPin();
|
|
||||||
|
|
||||||
// returns S_OK if successfully connected to an IAsyncReader interface
|
|
||||||
// from this object
|
|
||||||
// Optional allocator should be proposed as a preferred allocator if
|
|
||||||
// necessary
|
|
||||||
// bSync is TRUE if we are to use sync reads instead of the
|
|
||||||
// async methods.
|
|
||||||
HRESULT Connect(IUnknown* pUnk, IMemAllocator* pAlloc, BOOL bSync);
|
|
||||||
|
|
||||||
// disconnect any connection made in Connect
|
|
||||||
HRESULT Disconnect();
|
|
||||||
|
|
||||||
// agree an allocator using RequestAllocator - optional
|
|
||||||
// props param specifies your requirements (non-zero fields).
|
|
||||||
// returns an error code if fail to match requirements.
|
|
||||||
// optional IMemAllocator interface is offered as a preferred allocator
|
|
||||||
// but no error occurs if it can't be met.
|
|
||||||
virtual HRESULT DecideAllocator(
|
|
||||||
IMemAllocator* pAlloc,
|
|
||||||
ALLOCATOR_PROPERTIES * pProps);
|
|
||||||
|
|
||||||
// set start and stop position. if active, will start immediately at
|
|
||||||
// the new position. Default is 0 to duration
|
|
||||||
HRESULT Seek(REFERENCE_TIME tStart, REFERENCE_TIME tStop);
|
|
||||||
|
|
||||||
// return the total duration
|
|
||||||
HRESULT Duration(REFERENCE_TIME* ptDuration);
|
|
||||||
|
|
||||||
// start pulling data
|
|
||||||
HRESULT Active(void);
|
|
||||||
|
|
||||||
// stop pulling data
|
|
||||||
HRESULT Inactive(void);
|
|
||||||
|
|
||||||
// helper functions
|
|
||||||
LONGLONG AlignDown(LONGLONG ll, LONG lAlign) {
|
|
||||||
// aligning downwards is just truncation
|
|
||||||
return ll & ~(lAlign-1);
|
|
||||||
};
|
|
||||||
|
|
||||||
LONGLONG AlignUp(LONGLONG ll, LONG lAlign) {
|
|
||||||
// align up: round up to next boundary
|
|
||||||
return (ll + (lAlign -1)) & ~(lAlign -1);
|
|
||||||
};
|
|
||||||
|
|
||||||
// GetReader returns the (addrefed) IAsyncReader interface
|
|
||||||
// for SyncRead etc
|
|
||||||
IAsyncReader* GetReader() {
|
|
||||||
m_pReader->AddRef();
|
|
||||||
return m_pReader;
|
|
||||||
};
|
|
||||||
|
|
||||||
// -- pure --
|
|
||||||
|
|
||||||
// override this to handle data arrival
|
|
||||||
// return value other than S_OK will stop data
|
|
||||||
virtual HRESULT Receive(IMediaSample*) PURE;
|
|
||||||
|
|
||||||
// override this to handle end-of-stream
|
|
||||||
virtual HRESULT EndOfStream(void) PURE;
|
|
||||||
|
|
||||||
// called on runtime errors that will have caused pulling
|
|
||||||
// to stop
|
|
||||||
// these errors are all returned from the upstream filter, who
|
|
||||||
// will have already reported any errors to the filtergraph.
|
|
||||||
virtual void OnError(HRESULT hr) PURE;
|
|
||||||
|
|
||||||
// flush this pin and all downstream
|
|
||||||
virtual HRESULT BeginFlush() PURE;
|
|
||||||
virtual HRESULT EndFlush() PURE;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //__PULLPIN_H__
|
|
|
@ -1,340 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: RefClock.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - implements the IReferenceClock interface.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 'this' used in constructor list
|
|
||||||
#pragma warning(disable:4355)
|
|
||||||
|
|
||||||
|
|
||||||
STDMETHODIMP CBaseReferenceClock::NonDelegatingQueryInterface(
|
|
||||||
REFIID riid,
|
|
||||||
void ** ppv)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
if (riid == IID_IReferenceClock)
|
|
||||||
{
|
|
||||||
hr = GetInterface((IReferenceClock *) this, ppv);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = CUnknown::NonDelegatingQueryInterface(riid, ppv);
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBaseReferenceClock::~CBaseReferenceClock()
|
|
||||||
{
|
|
||||||
|
|
||||||
if (m_TimerResolution) timeEndPeriod(m_TimerResolution);
|
|
||||||
|
|
||||||
m_pSchedule->DumpLinkedList();
|
|
||||||
|
|
||||||
if (m_hThread)
|
|
||||||
{
|
|
||||||
m_bAbort = TRUE;
|
|
||||||
TriggerThread();
|
|
||||||
WaitForSingleObject( m_hThread, INFINITE );
|
|
||||||
EXECUTE_ASSERT( CloseHandle(m_hThread) );
|
|
||||||
m_hThread = 0;
|
|
||||||
EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) );
|
|
||||||
delete m_pSchedule;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A derived class may supply a hThreadEvent if it has its own thread that will take care
|
|
||||||
// of calling the schedulers Advise method. (Refere to CBaseReferenceClock::AdviseThread()
|
|
||||||
// to see what such a thread has to do.)
|
|
||||||
CBaseReferenceClock::CBaseReferenceClock( TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr, CAMSchedule * pShed )
|
|
||||||
: CUnknown( pName, pUnk )
|
|
||||||
, m_rtLastGotTime(0)
|
|
||||||
, m_TimerResolution(0)
|
|
||||||
, m_bAbort( FALSE )
|
|
||||||
, m_pSchedule( pShed ? pShed : new CAMSchedule(CreateEvent(NULL, FALSE, FALSE, NULL)) )
|
|
||||||
, m_hThread(0)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
ASSERT(m_pSchedule);
|
|
||||||
if (!m_pSchedule)
|
|
||||||
{
|
|
||||||
*phr = E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Set up the highest resolution timer we can manage
|
|
||||||
TIMECAPS tc;
|
|
||||||
m_TimerResolution = (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(tc)))
|
|
||||||
? tc.wPeriodMin
|
|
||||||
: 1;
|
|
||||||
|
|
||||||
timeBeginPeriod(m_TimerResolution);
|
|
||||||
|
|
||||||
/* Initialise our system times - the derived clock should set the right values */
|
|
||||||
m_dwPrevSystemTime = timeGetTime();
|
|
||||||
m_rtPrivateTime = (UNITS / MILLISECONDS) * m_dwPrevSystemTime;
|
|
||||||
|
|
||||||
#ifdef PERF
|
|
||||||
m_idGetSystemTime = MSR_REGISTER(TEXT("CBaseReferenceClock::GetTime"));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( !pShed )
|
|
||||||
{
|
|
||||||
DWORD ThreadID;
|
|
||||||
m_hThread = ::CreateThread(NULL, // Security attributes
|
|
||||||
(DWORD) 0, // Initial stack size
|
|
||||||
AdviseThreadFunction, // Thread start address
|
|
||||||
(LPVOID) this, // Thread parameter
|
|
||||||
(DWORD) 0, // Creation flags
|
|
||||||
&ThreadID); // Thread identifier
|
|
||||||
|
|
||||||
if (m_hThread)
|
|
||||||
{
|
|
||||||
SetThreadPriority( m_hThread, THREAD_PRIORITY_TIME_CRITICAL );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*phr = E_FAIL;
|
|
||||||
EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) );
|
|
||||||
delete m_pSchedule;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBaseReferenceClock::Restart (IN REFERENCE_TIME rtMinTime)
|
|
||||||
{
|
|
||||||
Lock();
|
|
||||||
m_rtLastGotTime = rtMinTime ;
|
|
||||||
Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP CBaseReferenceClock::GetTime(REFERENCE_TIME *pTime)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
if (pTime)
|
|
||||||
{
|
|
||||||
REFERENCE_TIME rtNow;
|
|
||||||
Lock();
|
|
||||||
rtNow = GetPrivateTime();
|
|
||||||
if (rtNow > m_rtLastGotTime)
|
|
||||||
{
|
|
||||||
m_rtLastGotTime = rtNow;
|
|
||||||
hr = S_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = S_FALSE;
|
|
||||||
}
|
|
||||||
*pTime = m_rtLastGotTime;
|
|
||||||
Unlock();
|
|
||||||
MSR_INTEGER(m_idGetSystemTime, LONG((*pTime) / (UNITS/MILLISECONDS)) );
|
|
||||||
}
|
|
||||||
else hr = E_POINTER;
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ask for an async notification that a time has elapsed */
|
|
||||||
|
|
||||||
STDMETHODIMP CBaseReferenceClock::AdviseTime(
|
|
||||||
REFERENCE_TIME baseTime, // base reference time
|
|
||||||
REFERENCE_TIME streamTime, // stream offset time
|
|
||||||
HEVENT hEvent, // advise via this event
|
|
||||||
DWORD_PTR *pdwAdviseCookie) // where your cookie goes
|
|
||||||
{
|
|
||||||
CheckPointer(pdwAdviseCookie, E_POINTER);
|
|
||||||
*pdwAdviseCookie = 0;
|
|
||||||
|
|
||||||
// Check that the event is not already set
|
|
||||||
ASSERT(WAIT_TIMEOUT == WaitForSingleObject(HANDLE(hEvent),0));
|
|
||||||
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
const REFERENCE_TIME lRefTime = baseTime + streamTime;
|
|
||||||
if ( lRefTime <= 0 || lRefTime == MAX_TIME )
|
|
||||||
{
|
|
||||||
hr = E_INVALIDARG;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*pdwAdviseCookie = m_pSchedule->AddAdvisePacket( lRefTime, 0, HANDLE(hEvent), FALSE );
|
|
||||||
hr = *pdwAdviseCookie ? NOERROR : E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Ask for an asynchronous periodic notification that a time has elapsed */
|
|
||||||
|
|
||||||
STDMETHODIMP CBaseReferenceClock::AdvisePeriodic(
|
|
||||||
REFERENCE_TIME StartTime, // starting at this time
|
|
||||||
REFERENCE_TIME PeriodTime, // time between notifications
|
|
||||||
HSEMAPHORE hSemaphore, // advise via a semaphore
|
|
||||||
DWORD_PTR *pdwAdviseCookie) // where your cookie goes
|
|
||||||
{
|
|
||||||
CheckPointer(pdwAdviseCookie, E_POINTER);
|
|
||||||
*pdwAdviseCookie = 0;
|
|
||||||
|
|
||||||
HRESULT hr;
|
|
||||||
if (StartTime > 0 && PeriodTime > 0 && StartTime != MAX_TIME )
|
|
||||||
{
|
|
||||||
*pdwAdviseCookie = m_pSchedule->AddAdvisePacket( StartTime, PeriodTime, HANDLE(hSemaphore), TRUE );
|
|
||||||
hr = *pdwAdviseCookie ? NOERROR : E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
else hr = E_INVALIDARG;
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
STDMETHODIMP CBaseReferenceClock::Unadvise(DWORD_PTR dwAdviseCookie)
|
|
||||||
{
|
|
||||||
return m_pSchedule->Unadvise(dwAdviseCookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
REFERENCE_TIME CBaseReferenceClock::GetPrivateTime()
|
|
||||||
{
|
|
||||||
CAutoLock cObjectLock(this);
|
|
||||||
|
|
||||||
|
|
||||||
/* If the clock has wrapped then the current time will be less than
|
|
||||||
* the last time we were notified so add on the extra milliseconds
|
|
||||||
*
|
|
||||||
* The time period is long enough so that the likelihood of
|
|
||||||
* successive calls spanning the clock cycle is not considered.
|
|
||||||
*/
|
|
||||||
|
|
||||||
DWORD dwTime = timeGetTime();
|
|
||||||
{
|
|
||||||
m_rtPrivateTime += Int32x32To64(UNITS / MILLISECONDS, (DWORD)(dwTime - m_dwPrevSystemTime));
|
|
||||||
m_dwPrevSystemTime = dwTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_rtPrivateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Adjust the current time by the input value. This allows an
|
|
||||||
external time source to work out some of the latency of the clock
|
|
||||||
system and adjust the "current" time accordingly. The intent is
|
|
||||||
that the time returned to the user is synchronised to a clock
|
|
||||||
source and allows drift to be catered for.
|
|
||||||
|
|
||||||
For example: if the clock source detects a drift it can pass a delta
|
|
||||||
to the current time rather than having to set an explicit time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
STDMETHODIMP CBaseReferenceClock::SetTimeDelta(const REFERENCE_TIME & TimeDelta)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
|
|
||||||
// Just break if passed an improper time delta value
|
|
||||||
LONGLONG llDelta = TimeDelta > 0 ? TimeDelta : -TimeDelta;
|
|
||||||
if (llDelta > UNITS * 1000) {
|
|
||||||
DbgLog((LOG_TRACE, 0, TEXT("Bad Time Delta")));
|
|
||||||
//DebugBreak();
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're going to calculate a "severity" for the time change. Max -1
|
|
||||||
// min 8. We'll then use this as the debug logging level for a
|
|
||||||
// debug log message.
|
|
||||||
const LONG usDelta = LONG(TimeDelta/10); // Delta in micro-secs
|
|
||||||
|
|
||||||
DWORD delta = abs(usDelta); // varying delta
|
|
||||||
// Severity == 8 - ceil(log<base 8>(abs( micro-secs delta)))
|
|
||||||
int Severity = 8;
|
|
||||||
while ( delta > 0 )
|
|
||||||
{
|
|
||||||
delta >>= 3; // div 8
|
|
||||||
Severity--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sev == 0 => > 2 second delta!
|
|
||||||
DbgLog((LOG_TIMING, Severity < 0 ? 0 : Severity,
|
|
||||||
TEXT("Sev %2i: CSystemClock::SetTimeDelta(%8ld us) %lu -> %lu ms."),
|
|
||||||
Severity, usDelta, DWORD(ConvertToMilliseconds(m_rtPrivateTime)),
|
|
||||||
DWORD(ConvertToMilliseconds(TimeDelta+m_rtPrivateTime)) ));
|
|
||||||
|
|
||||||
// Don't want the DbgBreak to fire when running stress on debug-builds.
|
|
||||||
#ifdef BREAK_ON_SEVERE_TIME_DELTA
|
|
||||||
if (Severity < 0)
|
|
||||||
DbgBreakPoint(TEXT("SetTimeDelta > 16 seconds!"),
|
|
||||||
TEXT(__FILE__),__LINE__);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CAutoLock cObjectLock(this);
|
|
||||||
m_rtPrivateTime += TimeDelta;
|
|
||||||
// If time goes forwards, and we have advises, then we need to
|
|
||||||
// trigger the thread so that it can re-evaluate its wait time.
|
|
||||||
// Since we don't want the cost of the thread switches if the change
|
|
||||||
// is really small, only do it if clock goes forward by more than
|
|
||||||
// 0.5 millisecond. If the time goes backwards, the thread will
|
|
||||||
// wake up "early" (relativly speaking) and will re-evaluate at
|
|
||||||
// that time.
|
|
||||||
if ( TimeDelta > 5000 && m_pSchedule->GetAdviseCount() > 0 ) TriggerThread();
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thread stuff
|
|
||||||
|
|
||||||
DWORD __stdcall CBaseReferenceClock::AdviseThreadFunction(LPVOID p)
|
|
||||||
{
|
|
||||||
return DWORD(reinterpret_cast<CBaseReferenceClock*>(p)->AdviseThread());
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT CBaseReferenceClock::AdviseThread()
|
|
||||||
{
|
|
||||||
DWORD dwWait = INFINITE;
|
|
||||||
|
|
||||||
// The first thing we do is wait until something interesting happens
|
|
||||||
// (meaning a first advise or shutdown). This prevents us calling
|
|
||||||
// GetPrivateTime immediately which is goodness as that is a virtual
|
|
||||||
// routine and the derived class may not yet be constructed. (This
|
|
||||||
// thread is created in the base class constructor.)
|
|
||||||
|
|
||||||
while ( !m_bAbort )
|
|
||||||
{
|
|
||||||
// Wait for an interesting event to happen
|
|
||||||
DbgLog((LOG_TIMING, 3, TEXT("CBaseRefClock::AdviseThread() Delay: %lu ms"), dwWait ));
|
|
||||||
WaitForSingleObject(m_pSchedule->GetEvent(), dwWait);
|
|
||||||
if (m_bAbort) break;
|
|
||||||
|
|
||||||
// There are several reasons why we need to work from the internal
|
|
||||||
// time, mainly to do with what happens when time goes backwards.
|
|
||||||
// Mainly, it stop us looping madly if an event is just about to
|
|
||||||
// expire when the clock goes backward (i.e. GetTime stop for a
|
|
||||||
// while).
|
|
||||||
const REFERENCE_TIME rtNow = GetPrivateTime();
|
|
||||||
|
|
||||||
DbgLog((LOG_TIMING, 3,
|
|
||||||
TEXT("CBaseRefClock::AdviseThread() Woke at = %lu ms"),
|
|
||||||
ConvertToMilliseconds(rtNow) ));
|
|
||||||
|
|
||||||
// We must add in a millisecond, since this is the resolution of our
|
|
||||||
// WaitForSingleObject timer. Failure to do so will cause us to loop
|
|
||||||
// franticly for (approx) 1 a millisecond.
|
|
||||||
m_rtNextAdvise = m_pSchedule->Advise( 10000 + rtNow );
|
|
||||||
LONGLONG llWait = m_rtNextAdvise - rtNow;
|
|
||||||
|
|
||||||
ASSERT( llWait > 0 );
|
|
||||||
|
|
||||||
llWait = ConvertToMilliseconds(llWait);
|
|
||||||
// DON'T replace this with a max!! (The type's of these things is VERY important)
|
|
||||||
dwWait = (llWait > REFERENCE_TIME(UINT_MAX)) ? UINT_MAX : DWORD(llWait);
|
|
||||||
};
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
|
@ -1,171 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: RefClock.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - defines the IReferenceClock interface.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __BASEREFCLOCK__
|
|
||||||
#define __BASEREFCLOCK__
|
|
||||||
|
|
||||||
#include "dsschedule.h"
|
|
||||||
|
|
||||||
const UINT RESOLUTION = 1; /* High resolution timer */
|
|
||||||
const INT ADVISE_CACHE = 4; /* Default cache size */
|
|
||||||
const LONGLONG MAX_TIME = 0x7FFFFFFFFFFFFFFF; /* Maximum LONGLONG value */
|
|
||||||
|
|
||||||
inline LONGLONG WINAPI ConvertToMilliseconds(const REFERENCE_TIME& RT)
|
|
||||||
{
|
|
||||||
/* This converts an arbitrary value representing a reference time
|
|
||||||
into a MILLISECONDS value for use in subsequent system calls */
|
|
||||||
|
|
||||||
return (RT / (UNITS / MILLISECONDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This class hierarchy will support an IReferenceClock interface so
|
|
||||||
that an audio card (or other externally driven clock) can update the
|
|
||||||
system wide clock that everyone uses.
|
|
||||||
|
|
||||||
The interface will be pretty thin with probably just one update method
|
|
||||||
This interface has not yet been defined.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This abstract base class implements the IReferenceClock
|
|
||||||
* interface. Classes that actually provide clock signals (from
|
|
||||||
* whatever source) have to be derived from this class.
|
|
||||||
*
|
|
||||||
* The abstract class provides implementations for:
|
|
||||||
* CUnknown support
|
|
||||||
* locking support (CCritSec)
|
|
||||||
* client advise code (creates a thread)
|
|
||||||
*
|
|
||||||
* Question: what can we do about quality? Change the timer
|
|
||||||
* resolution to lower the system load? Up the priority of the
|
|
||||||
* timer thread to force more responsive signals?
|
|
||||||
*
|
|
||||||
* During class construction we create a worker thread that is destroyed during
|
|
||||||
* destuction. This thread executes a series of WaitForSingleObject calls,
|
|
||||||
* waking up when a command is given to the thread or the next wake up point
|
|
||||||
* is reached. The wakeup points are determined by clients making Advise
|
|
||||||
* calls.
|
|
||||||
*
|
|
||||||
* Each advise call defines a point in time when they wish to be notified. A
|
|
||||||
* periodic advise is a series of these such events. We maintain a list of
|
|
||||||
* advise links and calculate when the nearest event notification is due for.
|
|
||||||
* We then call WaitForSingleObject with a timeout equal to this time. The
|
|
||||||
* handle we wait on is used by the class to signal that something has changed
|
|
||||||
* and that we must reschedule the next event. This typically happens when
|
|
||||||
* someone comes in and asks for an advise link while we are waiting for an
|
|
||||||
* event to timeout.
|
|
||||||
*
|
|
||||||
* While we are modifying the list of advise requests we
|
|
||||||
* are protected from interference through a critical section. Clients are NOT
|
|
||||||
* advised through callbacks. One shot clients have an event set, while
|
|
||||||
* periodic clients have a semaphore released for each event notification. A
|
|
||||||
* semaphore allows a client to be kept up to date with the number of events
|
|
||||||
* actually triggered and be assured that they can't miss multiple events being
|
|
||||||
* set.
|
|
||||||
*
|
|
||||||
* Keeping track of advises is taken care of by the CAMSchedule class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class CBaseReferenceClock
|
|
||||||
: public CUnknown, public IReferenceClock, public CCritSec
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
virtual ~CBaseReferenceClock(); // Don't let me be created on the stack!
|
|
||||||
public:
|
|
||||||
CBaseReferenceClock(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr, CAMSchedule * pSched = 0 );
|
|
||||||
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,void ** ppv);
|
|
||||||
|
|
||||||
DECLARE_IUNKNOWN
|
|
||||||
|
|
||||||
/* IReferenceClock methods */
|
|
||||||
// Derived classes must implement GetPrivateTime(). All our GetTime
|
|
||||||
// does is call GetPrivateTime and then check so that time does not
|
|
||||||
// go backwards. A return code of S_FALSE implies that the internal
|
|
||||||
// clock has gone backwards and GetTime time has halted until internal
|
|
||||||
// time has caught up. (Don't know if this will be much use to folk,
|
|
||||||
// but it seems odd not to use the return code for something useful.)
|
|
||||||
STDMETHODIMP GetTime(REFERENCE_TIME *pTime);
|
|
||||||
// When this is called, it sets m_rtLastGotTime to the time it returns.
|
|
||||||
|
|
||||||
/* Provide standard mechanisms for scheduling events */
|
|
||||||
|
|
||||||
/* Ask for an async notification that a time has elapsed */
|
|
||||||
STDMETHODIMP AdviseTime(
|
|
||||||
REFERENCE_TIME baseTime, // base reference time
|
|
||||||
REFERENCE_TIME streamTime, // stream offset time
|
|
||||||
HEVENT hEvent, // advise via this event
|
|
||||||
DWORD_PTR *pdwAdviseCookie // where your cookie goes
|
|
||||||
);
|
|
||||||
|
|
||||||
/* Ask for an asynchronous periodic notification that a time has elapsed */
|
|
||||||
STDMETHODIMP AdvisePeriodic(
|
|
||||||
REFERENCE_TIME StartTime, // starting at this time
|
|
||||||
REFERENCE_TIME PeriodTime, // time between notifications
|
|
||||||
HSEMAPHORE hSemaphore, // advise via a semaphore
|
|
||||||
DWORD_PTR *pdwAdviseCookie // where your cookie goes
|
|
||||||
);
|
|
||||||
|
|
||||||
/* Cancel a request for notification(s) - if the notification was
|
|
||||||
* a one shot timer then this function doesn't need to be called
|
|
||||||
* as the advise is automatically cancelled, however it does no
|
|
||||||
* harm to explicitly cancel a one-shot advise. It is REQUIRED that
|
|
||||||
* clients call Unadvise to clear a Periodic advise setting.
|
|
||||||
*/
|
|
||||||
|
|
||||||
STDMETHODIMP Unadvise(DWORD_PTR dwAdviseCookie);
|
|
||||||
|
|
||||||
/* Methods for the benefit of derived classes or outer objects */
|
|
||||||
|
|
||||||
// GetPrivateTime() is the REAL clock. GetTime is just a cover for
|
|
||||||
// it. Derived classes will probably override this method but not
|
|
||||||
// GetTime() itself.
|
|
||||||
// The important point about GetPrivateTime() is it's allowed to go
|
|
||||||
// backwards. Our GetTime() will keep returning the LastGotTime
|
|
||||||
// until GetPrivateTime() catches up.
|
|
||||||
virtual REFERENCE_TIME GetPrivateTime();
|
|
||||||
|
|
||||||
/* Provide a method for correcting drift */
|
|
||||||
STDMETHODIMP SetTimeDelta( const REFERENCE_TIME& TimeDelta );
|
|
||||||
|
|
||||||
CAMSchedule * GetSchedule() const { return m_pSchedule; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
REFERENCE_TIME m_rtPrivateTime; // Current best estimate of time
|
|
||||||
DWORD m_dwPrevSystemTime; // Last vaule we got from timeGetTime
|
|
||||||
REFERENCE_TIME m_rtLastGotTime; // Last time returned by GetTime
|
|
||||||
REFERENCE_TIME m_rtNextAdvise; // Time of next advise
|
|
||||||
UINT m_TimerResolution;
|
|
||||||
|
|
||||||
#ifdef PERF
|
|
||||||
int m_idGetSystemTime;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Thread stuff
|
|
||||||
public:
|
|
||||||
void TriggerThread() // Wakes thread up. Need to do this if
|
|
||||||
{ // time to next advise needs reevaluating.
|
|
||||||
EXECUTE_ASSERT(SetEvent(m_pSchedule->GetEvent()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
BOOL m_bAbort; // Flag used for thread shutdown
|
|
||||||
HANDLE m_hThread; // Thread handle
|
|
||||||
|
|
||||||
HRESULT AdviseThread(); // Method in which the advise thread runs
|
|
||||||
static DWORD __stdcall AdviseThreadFunction(LPVOID); // Function used to get there
|
|
||||||
|
|
||||||
protected:
|
|
||||||
CAMSchedule * const m_pSchedule;
|
|
||||||
|
|
||||||
void Restart (IN REFERENCE_TIME rtMinTime = 0I64) ;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,116 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: RefTime.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - defines CRefTime, a class that manages
|
|
||||||
// reference times.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// CRefTime
|
|
||||||
//
|
|
||||||
// Manage reference times.
|
|
||||||
// Shares same data layout as REFERENCE_TIME, but adds some (nonvirtual)
|
|
||||||
// functions providing simple comparison, conversion and arithmetic.
|
|
||||||
//
|
|
||||||
// A reference time (at the moment) is a unit of seconds represented in
|
|
||||||
// 100ns units as is used in the Win32 FILETIME structure. BUT the time
|
|
||||||
// a REFERENCE_TIME represents is NOT the time elapsed since 1/1/1601 it
|
|
||||||
// will either be stream time or reference time depending upon context
|
|
||||||
//
|
|
||||||
// This class provides simple arithmetic operations on reference times
|
|
||||||
//
|
|
||||||
// keep non-virtual otherwise the data layout will not be the same as
|
|
||||||
// REFERENCE_TIME
|
|
||||||
|
|
||||||
|
|
||||||
// -----
|
|
||||||
// note that you are safe to cast a CRefTime* to a REFERENCE_TIME*, but
|
|
||||||
// you will need to do so explicitly
|
|
||||||
// -----
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __REFTIME__
|
|
||||||
#define __REFTIME__
|
|
||||||
|
|
||||||
|
|
||||||
const LONGLONG MILLISECONDS = (1000); // 10 ^ 3
|
|
||||||
const LONGLONG NANOSECONDS = (1000000000); // 10 ^ 9
|
|
||||||
const LONGLONG UNITS = (NANOSECONDS / 100); // 10 ^ 7
|
|
||||||
|
|
||||||
/* Unfortunately an inline function here generates a call to __allmul
|
|
||||||
- even for constants!
|
|
||||||
*/
|
|
||||||
#define MILLISECONDS_TO_100NS_UNITS(lMs) \
|
|
||||||
Int32x32To64((lMs), (UNITS / MILLISECONDS))
|
|
||||||
|
|
||||||
class CRefTime
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
// *MUST* be the only data member so that this class is exactly
|
|
||||||
// equivalent to a REFERENCE_TIME.
|
|
||||||
// Also, must be *no virtual functions*
|
|
||||||
|
|
||||||
REFERENCE_TIME m_time;
|
|
||||||
|
|
||||||
inline CRefTime()
|
|
||||||
{
|
|
||||||
// default to 0 time
|
|
||||||
m_time = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline CRefTime(LONG msecs)
|
|
||||||
{
|
|
||||||
m_time = MILLISECONDS_TO_100NS_UNITS(msecs);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline CRefTime(REFERENCE_TIME rt)
|
|
||||||
{
|
|
||||||
m_time = rt;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline operator REFERENCE_TIME() const
|
|
||||||
{
|
|
||||||
return m_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline CRefTime& operator=(const CRefTime& rt)
|
|
||||||
{
|
|
||||||
m_time = rt.m_time;
|
|
||||||
return *this;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline CRefTime& operator=(const LONGLONG ll)
|
|
||||||
{
|
|
||||||
m_time = ll;
|
|
||||||
return *this;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline CRefTime& operator+=(const CRefTime& rt)
|
|
||||||
{
|
|
||||||
return (*this = *this + rt);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline CRefTime& operator-=(const CRefTime& rt)
|
|
||||||
{
|
|
||||||
return (*this = *this - rt);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline LONG Millisecs(void)
|
|
||||||
{
|
|
||||||
return (LONG)(m_time / (UNITS / MILLISECONDS));
|
|
||||||
};
|
|
||||||
|
|
||||||
inline LONGLONG GetUnits(void)
|
|
||||||
{
|
|
||||||
return m_time;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const LONGLONG TimeZero = 0;
|
|
||||||
|
|
||||||
#endif /* __REFTIME__ */
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,478 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: RenBase.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - defines a generic ActiveX base renderer
|
|
||||||
// class.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __RENBASE__
|
|
||||||
#define __RENBASE__
|
|
||||||
|
|
||||||
// Forward class declarations
|
|
||||||
|
|
||||||
class CBaseRenderer;
|
|
||||||
class CBaseVideoRenderer;
|
|
||||||
class CRendererInputPin;
|
|
||||||
|
|
||||||
// This is our input pin class that channels calls to the renderer
|
|
||||||
|
|
||||||
class CRendererInputPin : public CBaseInputPin
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
CBaseRenderer *m_pRenderer;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CRendererInputPin(CBaseRenderer *pRenderer,
|
|
||||||
HRESULT *phr,
|
|
||||||
LPCWSTR Name);
|
|
||||||
|
|
||||||
// Overriden from the base pin classes
|
|
||||||
|
|
||||||
HRESULT BreakConnect();
|
|
||||||
HRESULT CompleteConnect(IPin *pReceivePin);
|
|
||||||
HRESULT SetMediaType(const CMediaType *pmt);
|
|
||||||
HRESULT CheckMediaType(const CMediaType *pmt);
|
|
||||||
HRESULT Active();
|
|
||||||
HRESULT Inactive();
|
|
||||||
|
|
||||||
// Add rendering behaviour to interface functions
|
|
||||||
|
|
||||||
STDMETHODIMP QueryId(LPWSTR *Id);
|
|
||||||
STDMETHODIMP EndOfStream();
|
|
||||||
STDMETHODIMP BeginFlush();
|
|
||||||
STDMETHODIMP EndFlush();
|
|
||||||
STDMETHODIMP Receive(IMediaSample *pMediaSample);
|
|
||||||
|
|
||||||
// Helper
|
|
||||||
IMemAllocator inline *Allocator() const
|
|
||||||
{
|
|
||||||
return m_pAllocator;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Main renderer class that handles synchronisation and state changes
|
|
||||||
|
|
||||||
class CBaseRenderer : public CBaseFilter
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
friend class CRendererInputPin;
|
|
||||||
|
|
||||||
friend void CALLBACK EndOfStreamTimer(UINT uID, // Timer identifier
|
|
||||||
UINT uMsg, // Not currently used
|
|
||||||
DWORD_PTR dwUser, // User information
|
|
||||||
DWORD_PTR dw1, // Windows reserved
|
|
||||||
DWORD_PTR dw2); // Is also reserved
|
|
||||||
|
|
||||||
CRendererPosPassThru *m_pPosition; // Media seeking pass by object
|
|
||||||
CAMEvent m_RenderEvent; // Used to signal timer events
|
|
||||||
CAMEvent m_ThreadSignal; // Signalled to release worker thread
|
|
||||||
CAMEvent m_evComplete; // Signalled when state complete
|
|
||||||
BOOL m_bAbort; // Stop us from rendering more data
|
|
||||||
BOOL m_bStreaming; // Are we currently streaming
|
|
||||||
DWORD_PTR m_dwAdvise; // Timer advise cookie
|
|
||||||
IMediaSample *m_pMediaSample; // Current image media sample
|
|
||||||
BOOL m_bEOS; // Any more samples in the stream
|
|
||||||
BOOL m_bEOSDelivered; // Have we delivered an EC_COMPLETE
|
|
||||||
CRendererInputPin *m_pInputPin; // Our renderer input pin object
|
|
||||||
CCritSec m_InterfaceLock; // Critical section for interfaces
|
|
||||||
CCritSec m_RendererLock; // Controls access to internals
|
|
||||||
IQualityControl * m_pQSink; // QualityControl sink
|
|
||||||
BOOL m_bRepaintStatus; // Can we signal an EC_REPAINT
|
|
||||||
// Avoid some deadlocks by tracking filter during stop
|
|
||||||
volatile BOOL m_bInReceive; // Inside Receive between PrepareReceive
|
|
||||||
// And actually processing the sample
|
|
||||||
REFERENCE_TIME m_SignalTime; // Time when we signal EC_COMPLETE
|
|
||||||
UINT m_EndOfStreamTimer; // Used to signal end of stream
|
|
||||||
CCritSec m_ObjectCreationLock; // This lock protects the creation and
|
|
||||||
// of m_pPosition and m_pInputPin. It
|
|
||||||
// ensures that two threads cannot create
|
|
||||||
// either object simultaneously.
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CBaseRenderer(REFCLSID RenderClass, // CLSID for this renderer
|
|
||||||
TCHAR *pName, // Debug ONLY description
|
|
||||||
LPUNKNOWN pUnk, // Aggregated owner object
|
|
||||||
HRESULT *phr); // General OLE return code
|
|
||||||
|
|
||||||
~CBaseRenderer();
|
|
||||||
|
|
||||||
// Overriden to say what interfaces we support and where
|
|
||||||
|
|
||||||
virtual HRESULT GetMediaPositionInterface(REFIID riid,void **ppv);
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID, void **);
|
|
||||||
|
|
||||||
virtual HRESULT SourceThreadCanWait(BOOL bCanWait);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
// Debug only dump of the renderer state
|
|
||||||
void DisplayRendererState();
|
|
||||||
#endif
|
|
||||||
virtual HRESULT WaitForRenderTime();
|
|
||||||
virtual HRESULT CompleteStateChange(FILTER_STATE OldState);
|
|
||||||
|
|
||||||
// Return internal information about this filter
|
|
||||||
|
|
||||||
BOOL IsEndOfStream() { return m_bEOS; };
|
|
||||||
BOOL IsEndOfStreamDelivered() { return m_bEOSDelivered; };
|
|
||||||
BOOL IsStreaming() { return m_bStreaming; };
|
|
||||||
void SetAbortSignal(BOOL bAbort) { m_bAbort = bAbort; };
|
|
||||||
virtual void OnReceiveFirstSample(IMediaSample *pMediaSample) { };
|
|
||||||
CAMEvent *GetRenderEvent() { return &m_RenderEvent; };
|
|
||||||
|
|
||||||
// Permit access to the transition state
|
|
||||||
|
|
||||||
void Ready() { m_evComplete.Set(); };
|
|
||||||
void NotReady() { m_evComplete.Reset(); };
|
|
||||||
BOOL CheckReady() { return m_evComplete.Check(); };
|
|
||||||
|
|
||||||
virtual int GetPinCount();
|
|
||||||
virtual CBasePin *GetPin(int n);
|
|
||||||
FILTER_STATE GetRealState();
|
|
||||||
void SendRepaint();
|
|
||||||
void SendNotifyWindow(IPin *pPin,HWND hwnd);
|
|
||||||
BOOL OnDisplayChange();
|
|
||||||
void SetRepaintStatus(BOOL bRepaint);
|
|
||||||
|
|
||||||
// Override the filter and pin interface functions
|
|
||||||
|
|
||||||
STDMETHODIMP Stop();
|
|
||||||
STDMETHODIMP Pause();
|
|
||||||
STDMETHODIMP Run(REFERENCE_TIME StartTime);
|
|
||||||
STDMETHODIMP GetState(DWORD dwMSecs,FILTER_STATE *State);
|
|
||||||
STDMETHODIMP FindPin(LPCWSTR Id, IPin **ppPin);
|
|
||||||
|
|
||||||
// These are available for a quality management implementation
|
|
||||||
|
|
||||||
virtual void OnRenderStart(IMediaSample *pMediaSample);
|
|
||||||
virtual void OnRenderEnd(IMediaSample *pMediaSample);
|
|
||||||
virtual HRESULT OnStartStreaming() { return NOERROR; };
|
|
||||||
virtual HRESULT OnStopStreaming() { return NOERROR; };
|
|
||||||
virtual void OnWaitStart() { };
|
|
||||||
virtual void OnWaitEnd() { };
|
|
||||||
virtual void PrepareRender() { };
|
|
||||||
|
|
||||||
#ifdef PERF
|
|
||||||
REFERENCE_TIME m_trRenderStart; // Just before we started drawing
|
|
||||||
// Set in OnRenderStart, Used in OnRenderEnd
|
|
||||||
int m_idBaseStamp; // MSR_id for frame time stamp
|
|
||||||
int m_idBaseRenderTime; // MSR_id for true wait time
|
|
||||||
int m_idBaseAccuracy; // MSR_id for time frame is late (int)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Quality management implementation for scheduling rendering
|
|
||||||
|
|
||||||
virtual BOOL ScheduleSample(IMediaSample *pMediaSample);
|
|
||||||
virtual HRESULT GetSampleTimes(IMediaSample *pMediaSample,
|
|
||||||
REFERENCE_TIME *pStartTime,
|
|
||||||
REFERENCE_TIME *pEndTime);
|
|
||||||
|
|
||||||
virtual HRESULT ShouldDrawSampleNow(IMediaSample *pMediaSample,
|
|
||||||
REFERENCE_TIME *ptrStart,
|
|
||||||
REFERENCE_TIME *ptrEnd);
|
|
||||||
|
|
||||||
// Lots of end of stream complexities
|
|
||||||
|
|
||||||
void TimerCallback();
|
|
||||||
void ResetEndOfStreamTimer();
|
|
||||||
HRESULT NotifyEndOfStream();
|
|
||||||
virtual HRESULT SendEndOfStream();
|
|
||||||
virtual HRESULT ResetEndOfStream();
|
|
||||||
virtual HRESULT EndOfStream();
|
|
||||||
|
|
||||||
// Rendering is based around the clock
|
|
||||||
|
|
||||||
void SignalTimerFired();
|
|
||||||
virtual HRESULT CancelNotification();
|
|
||||||
virtual HRESULT ClearPendingSample();
|
|
||||||
|
|
||||||
// Called when the filter changes state
|
|
||||||
|
|
||||||
virtual HRESULT Active();
|
|
||||||
virtual HRESULT Inactive();
|
|
||||||
virtual HRESULT StartStreaming();
|
|
||||||
virtual HRESULT StopStreaming();
|
|
||||||
virtual HRESULT BeginFlush();
|
|
||||||
virtual HRESULT EndFlush();
|
|
||||||
|
|
||||||
// Deal with connections and type changes
|
|
||||||
|
|
||||||
virtual HRESULT BreakConnect();
|
|
||||||
virtual HRESULT SetMediaType(const CMediaType *pmt);
|
|
||||||
virtual HRESULT CompleteConnect(IPin *pReceivePin);
|
|
||||||
|
|
||||||
// These look after the handling of data samples
|
|
||||||
|
|
||||||
virtual HRESULT PrepareReceive(IMediaSample *pMediaSample);
|
|
||||||
virtual HRESULT Receive(IMediaSample *pMediaSample);
|
|
||||||
virtual BOOL HaveCurrentSample();
|
|
||||||
virtual IMediaSample *GetCurrentSample();
|
|
||||||
virtual HRESULT Render(IMediaSample *pMediaSample);
|
|
||||||
|
|
||||||
// Derived classes MUST override these
|
|
||||||
virtual HRESULT DoRenderSample(IMediaSample *pMediaSample) PURE;
|
|
||||||
virtual HRESULT CheckMediaType(const CMediaType *) PURE;
|
|
||||||
|
|
||||||
// Helper
|
|
||||||
void WaitForReceiveToComplete();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// CBaseVideoRenderer is a renderer class (see its ancestor class) and
|
|
||||||
// it handles scheduling of media samples so that they are drawn at the
|
|
||||||
// correct time by the reference clock. It implements a degradation
|
|
||||||
// strategy. Possible degradation modes are:
|
|
||||||
// Drop frames here (only useful if the drawing takes significant time)
|
|
||||||
// Signal supplier (upstream) to drop some frame(s) - i.e. one-off skip.
|
|
||||||
// Signal supplier to change the frame rate - i.e. ongoing skipping.
|
|
||||||
// Or any combination of the above.
|
|
||||||
// In order to determine what's useful to try we need to know what's going
|
|
||||||
// on. This is done by timing various operations (including the supplier).
|
|
||||||
// This timing is done by using timeGetTime as it is accurate enough and
|
|
||||||
// usually cheaper than calling the reference clock. It also tells the
|
|
||||||
// truth if there is an audio break and the reference clock stops.
|
|
||||||
// We provide a number of public entry points (named OnXxxStart, OnXxxEnd)
|
|
||||||
// which the rest of the renderer calls at significant moments. These do
|
|
||||||
// the timing.
|
|
||||||
|
|
||||||
// the number of frames that the sliding averages are averaged over.
|
|
||||||
// the rule is (1024*NewObservation + (AVGPERIOD-1) * PreviousAverage)/AVGPERIOD
|
|
||||||
#define AVGPERIOD 4
|
|
||||||
#define DO_MOVING_AVG(avg,obs) (avg = (1024*obs + (AVGPERIOD-1)*avg)/AVGPERIOD)
|
|
||||||
// Spot the bug in this macro - I can't. but it doesn't work!
|
|
||||||
|
|
||||||
class CBaseVideoRenderer : public CBaseRenderer, // Base renderer class
|
|
||||||
public IQualProp, // Property page guff
|
|
||||||
public IQualityControl // Allow throttling
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Hungarian:
|
|
||||||
// tFoo is the time Foo in mSec (beware m_tStart from filter.h)
|
|
||||||
// trBar is the time Bar by the reference clock
|
|
||||||
|
|
||||||
//******************************************************************
|
|
||||||
// State variables to control synchronisation
|
|
||||||
//******************************************************************
|
|
||||||
|
|
||||||
// Control of sending Quality messages. We need to know whether
|
|
||||||
// we are in trouble (e.g. frames being dropped) and where the time
|
|
||||||
// is being spent.
|
|
||||||
|
|
||||||
// When we drop a frame we play the next one early.
|
|
||||||
// The frame after that is likely to wait before drawing and counting this
|
|
||||||
// wait as spare time is unfair, so we count it as a zero wait.
|
|
||||||
// We therefore need to know whether we are playing frames early or not.
|
|
||||||
|
|
||||||
int m_nNormal; // The number of consecutive frames
|
|
||||||
// drawn at their normal time (not early)
|
|
||||||
// -1 means we just dropped a frame.
|
|
||||||
|
|
||||||
#ifdef PERF
|
|
||||||
BOOL m_bDrawLateFrames; // Don't drop any frames (debug and I'm
|
|
||||||
// not keen on people using it!)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BOOL m_bSupplierHandlingQuality;// The response to Quality messages says
|
|
||||||
// our supplier is handling things.
|
|
||||||
// We will allow things to go extra late
|
|
||||||
// before dropping frames. We will play
|
|
||||||
// very early after he has dropped one.
|
|
||||||
|
|
||||||
// Control of scheduling, frame dropping etc.
|
|
||||||
// We need to know where the time is being spent so as to tell whether
|
|
||||||
// we should be taking action here, signalling supplier or what.
|
|
||||||
// The variables are initialised to a mode of NOT dropping frames.
|
|
||||||
// They will tell the truth after a few frames.
|
|
||||||
// We typically record a start time for an event, later we get the time
|
|
||||||
// again and subtract to get the elapsed time, and we average this over
|
|
||||||
// a few frames. The average is used to tell what mode we are in.
|
|
||||||
|
|
||||||
// Although these are reference times (64 bit) they are all DIFFERENCES
|
|
||||||
// between times which are small. An int will go up to 214 secs before
|
|
||||||
// overflow. Avoiding 64 bit multiplications and divisions seems
|
|
||||||
// worth while.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Audio-video throttling. If the user has turned up audio quality
|
|
||||||
// very high (in principle it could be any other stream, not just audio)
|
|
||||||
// then we can receive cries for help via the graph manager. In this case
|
|
||||||
// we put in a wait for some time after rendering each frame.
|
|
||||||
int m_trThrottle;
|
|
||||||
|
|
||||||
// The time taken to render (i.e. BitBlt) frames controls which component
|
|
||||||
// needs to degrade. If the blt is expensive, the renderer degrades.
|
|
||||||
// If the blt is cheap it's done anyway and the supplier degrades.
|
|
||||||
int m_trRenderAvg; // Time frames are taking to blt
|
|
||||||
int m_trRenderLast; // Time for last frame blt
|
|
||||||
int m_tRenderStart; // Just before we started drawing (mSec)
|
|
||||||
// derived from timeGetTime.
|
|
||||||
|
|
||||||
// When frames are dropped we will play the next frame as early as we can.
|
|
||||||
// If it was a false alarm and the machine is fast we slide gently back to
|
|
||||||
// normal timing. To do this, we record the offset showing just how early
|
|
||||||
// we really are. This will normally be negative meaning early or zero.
|
|
||||||
int m_trEarliness;
|
|
||||||
|
|
||||||
// Target provides slow long-term feedback to try to reduce the
|
|
||||||
// average sync offset to zero. Whenever a frame is actually rendered
|
|
||||||
// early we add a msec or two, whenever late we take off a few.
|
|
||||||
// We add or take off 1/32 of the error time.
|
|
||||||
// Eventually we should be hovering around zero. For a really bad case
|
|
||||||
// where we were (say) 300mSec off, it might take 100 odd frames to
|
|
||||||
// settle down. The rate of change of this is intended to be slower
|
|
||||||
// than any other mechanism in Quartz, thereby avoiding hunting.
|
|
||||||
int m_trTarget;
|
|
||||||
|
|
||||||
// The proportion of time spent waiting for the right moment to blt
|
|
||||||
// controls whether we bother to drop a frame or whether we reckon that
|
|
||||||
// we're doing well enough that we can stand a one-frame glitch.
|
|
||||||
int m_trWaitAvg; // Average of last few wait times
|
|
||||||
// (actually we just average how early
|
|
||||||
// we were). Negative here means LATE.
|
|
||||||
|
|
||||||
// The average inter-frame time.
|
|
||||||
// This is used to calculate the proportion of the time used by the
|
|
||||||
// three operations (supplying us, waiting, rendering)
|
|
||||||
int m_trFrameAvg; // Average inter-frame time
|
|
||||||
int m_trDuration; // duration of last frame.
|
|
||||||
|
|
||||||
#ifdef PERF
|
|
||||||
// Performance logging identifiers
|
|
||||||
int m_idTimeStamp; // MSR_id for frame time stamp
|
|
||||||
int m_idEarliness; // MSR_id for earliness fudge
|
|
||||||
int m_idTarget; // MSR_id for Target fudge
|
|
||||||
int m_idWaitReal; // MSR_id for true wait time
|
|
||||||
int m_idWait; // MSR_id for wait time recorded
|
|
||||||
int m_idFrameAccuracy; // MSR_id for time frame is late (int)
|
|
||||||
int m_idRenderAvg; // MSR_id for Render time recorded (int)
|
|
||||||
int m_idSchLateTime; // MSR_id for lateness at scheduler
|
|
||||||
int m_idQualityRate; // MSR_id for Quality rate requested
|
|
||||||
int m_idQualityTime; // MSR_id for Quality time requested
|
|
||||||
int m_idDecision; // MSR_id for decision code
|
|
||||||
int m_idDuration; // MSR_id for duration of a frame
|
|
||||||
int m_idThrottle; // MSR_id for audio-video throttling
|
|
||||||
//int m_idDebug; // MSR_id for trace style debugging
|
|
||||||
//int m_idSendQuality; // MSR_id for timing the notifications per se
|
|
||||||
#endif // PERF
|
|
||||||
REFERENCE_TIME m_trRememberStampForPerf; // original time stamp of frame
|
|
||||||
// with no earliness fudges etc.
|
|
||||||
#ifdef PERF
|
|
||||||
REFERENCE_TIME m_trRememberFrameForPerf; // time when previous frame rendered
|
|
||||||
|
|
||||||
// debug...
|
|
||||||
int m_idFrameAvg;
|
|
||||||
int m_idWaitAvg;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// PROPERTY PAGE
|
|
||||||
// This has edit fields that show the user what's happening
|
|
||||||
// These member variables hold these counts.
|
|
||||||
|
|
||||||
int m_cFramesDropped; // cumulative frames dropped IN THE RENDERER
|
|
||||||
int m_cFramesDrawn; // Frames since streaming started seen BY THE
|
|
||||||
// RENDERER (some may be dropped upstream)
|
|
||||||
|
|
||||||
// Next two support average sync offset and standard deviation of sync offset.
|
|
||||||
LONGLONG m_iTotAcc; // Sum of accuracies in mSec
|
|
||||||
LONGLONG m_iSumSqAcc; // Sum of squares of (accuracies in mSec)
|
|
||||||
|
|
||||||
// Next two allow jitter calculation. Jitter is std deviation of frame time.
|
|
||||||
REFERENCE_TIME m_trLastDraw; // Time of prev frame (for inter-frame times)
|
|
||||||
LONGLONG m_iSumSqFrameTime; // Sum of squares of (inter-frame time in mSec)
|
|
||||||
LONGLONG m_iSumFrameTime; // Sum of inter-frame times in mSec
|
|
||||||
|
|
||||||
// To get performance statistics on frame rate, jitter etc, we need
|
|
||||||
// to record the lateness and inter-frame time. What we actually need are the
|
|
||||||
// data above (sum, sum of squares and number of entries for each) but the data
|
|
||||||
// is generated just ahead of time and only later do we discover whether the
|
|
||||||
// frame was actually drawn or not. So we have to hang on to the data
|
|
||||||
int m_trLate; // hold onto frame lateness
|
|
||||||
int m_trFrame; // hold onto inter-frame time
|
|
||||||
|
|
||||||
int m_tStreamingStart; // if streaming then time streaming started
|
|
||||||
// else time of last streaming session
|
|
||||||
// used for property page statistics
|
|
||||||
#ifdef PERF
|
|
||||||
LONGLONG m_llTimeOffset; // timeGetTime()*10000+m_llTimeOffset==ref time
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
CBaseVideoRenderer(REFCLSID RenderClass, // CLSID for this renderer
|
|
||||||
TCHAR *pName, // Debug ONLY description
|
|
||||||
LPUNKNOWN pUnk, // Aggregated owner object
|
|
||||||
HRESULT *phr); // General OLE return code
|
|
||||||
|
|
||||||
~CBaseVideoRenderer();
|
|
||||||
|
|
||||||
// IQualityControl methods - Notify allows audio-video throttling
|
|
||||||
|
|
||||||
STDMETHODIMP SetSink( IQualityControl * piqc);
|
|
||||||
STDMETHODIMP Notify( IBaseFilter * pSelf, Quality q);
|
|
||||||
|
|
||||||
// These provide a full video quality management implementation
|
|
||||||
|
|
||||||
void OnRenderStart(IMediaSample *pMediaSample);
|
|
||||||
void OnRenderEnd(IMediaSample *pMediaSample);
|
|
||||||
void OnWaitStart();
|
|
||||||
void OnWaitEnd();
|
|
||||||
HRESULT OnStartStreaming();
|
|
||||||
HRESULT OnStopStreaming();
|
|
||||||
void ThrottleWait();
|
|
||||||
|
|
||||||
// Handle the statistics gathering for our quality management
|
|
||||||
|
|
||||||
void PreparePerformanceData(int trLate, int trFrame);
|
|
||||||
virtual void RecordFrameLateness(int trLate, int trFrame);
|
|
||||||
virtual void OnDirectRender(IMediaSample *pMediaSample);
|
|
||||||
virtual HRESULT ResetStreamingTimes();
|
|
||||||
BOOL ScheduleSample(IMediaSample *pMediaSample);
|
|
||||||
HRESULT ShouldDrawSampleNow(IMediaSample *pMediaSample,
|
|
||||||
REFERENCE_TIME *ptrStart,
|
|
||||||
REFERENCE_TIME *ptrEnd);
|
|
||||||
|
|
||||||
virtual HRESULT SendQuality(REFERENCE_TIME trLate, REFERENCE_TIME trRealStream);
|
|
||||||
STDMETHODIMP JoinFilterGraph(IFilterGraph * pGraph, LPCWSTR pName);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Do estimates for standard deviations for per-frame
|
|
||||||
// statistics
|
|
||||||
//
|
|
||||||
// *piResult = (llSumSq - iTot * iTot / m_cFramesDrawn - 1) /
|
|
||||||
// (m_cFramesDrawn - 2)
|
|
||||||
// or 0 if m_cFramesDrawn <= 3
|
|
||||||
//
|
|
||||||
HRESULT GetStdDev(
|
|
||||||
int nSamples,
|
|
||||||
int *piResult,
|
|
||||||
LONGLONG llSumSq,
|
|
||||||
LONGLONG iTot
|
|
||||||
);
|
|
||||||
public:
|
|
||||||
|
|
||||||
// IQualProp property page support
|
|
||||||
|
|
||||||
STDMETHODIMP get_FramesDroppedInRenderer(int *cFramesDropped);
|
|
||||||
STDMETHODIMP get_FramesDrawn(int *pcFramesDrawn);
|
|
||||||
STDMETHODIMP get_AvgFrameRate(int *piAvgFrameRate);
|
|
||||||
STDMETHODIMP get_Jitter(int *piJitter);
|
|
||||||
STDMETHODIMP get_AvgSyncOffset(int *piAvg);
|
|
||||||
STDMETHODIMP get_DevSyncOffset(int *piDev);
|
|
||||||
|
|
||||||
// Implement an IUnknown interface and expose IQualProp
|
|
||||||
|
|
||||||
DECLARE_IUNKNOWN
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,VOID **ppv);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __RENBASE__
|
|
||||||
|
|
|
@ -1,284 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: Schedule.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
|
|
||||||
// DbgLog values (all on LOG_TIMING):
|
|
||||||
//
|
|
||||||
// 2 for schedulting, firing and shunting of events
|
|
||||||
// 3 for wait delays and wake-up times of event thread
|
|
||||||
// 4 for details of whats on the list when the thread awakes
|
|
||||||
|
|
||||||
/* Construct & destructors */
|
|
||||||
|
|
||||||
CAMSchedule::CAMSchedule( HANDLE ev )
|
|
||||||
: CBaseObject(TEXT("CAMSchedule"))
|
|
||||||
, head(&z, 0), z(0, MAX_TIME)
|
|
||||||
, m_dwNextCookie(0), m_dwAdviseCount(0)
|
|
||||||
, m_pAdviseCache(0), m_dwCacheCount(0)
|
|
||||||
, m_ev( ev )
|
|
||||||
{
|
|
||||||
head.m_dwAdviseCookie = z.m_dwAdviseCookie = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CAMSchedule::~CAMSchedule()
|
|
||||||
{
|
|
||||||
m_Serialize.Lock();
|
|
||||||
|
|
||||||
// Delete cache
|
|
||||||
CAdvisePacket * p = m_pAdviseCache;
|
|
||||||
while (p)
|
|
||||||
{
|
|
||||||
CAdvisePacket *const p_next = p->m_next;
|
|
||||||
delete p;
|
|
||||||
p = p_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT( m_dwAdviseCount == 0 );
|
|
||||||
// Better to be safe than sorry
|
|
||||||
if ( m_dwAdviseCount > 0 )
|
|
||||||
{
|
|
||||||
DumpLinkedList();
|
|
||||||
while ( !head.m_next->IsZ() )
|
|
||||||
{
|
|
||||||
head.DeleteNext();
|
|
||||||
--m_dwAdviseCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If, in the debug version, we assert twice, it means, not only
|
|
||||||
// did we have left over advises, but we have also let m_dwAdviseCount
|
|
||||||
// get out of sync. with the number of advises actually on the list.
|
|
||||||
ASSERT( m_dwAdviseCount == 0 );
|
|
||||||
|
|
||||||
m_Serialize.Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Public methods */
|
|
||||||
|
|
||||||
DWORD CAMSchedule::GetAdviseCount()
|
|
||||||
{
|
|
||||||
// No need to lock, m_dwAdviseCount is 32bits & declared volatile
|
|
||||||
return m_dwAdviseCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
REFERENCE_TIME CAMSchedule::GetNextAdviseTime()
|
|
||||||
{
|
|
||||||
CAutoLock lck(&m_Serialize); // Need to stop the linked list from changing
|
|
||||||
return head.m_next->m_rtEventTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD_PTR CAMSchedule::AddAdvisePacket
|
|
||||||
( const REFERENCE_TIME & time1
|
|
||||||
, const REFERENCE_TIME & time2
|
|
||||||
, HANDLE h, BOOL periodic
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Since we use MAX_TIME as a sentry, we can't afford to
|
|
||||||
// schedule a notification at MAX_TIME
|
|
||||||
ASSERT( time1 < MAX_TIME );
|
|
||||||
DWORD_PTR Result;
|
|
||||||
CAdvisePacket * p;
|
|
||||||
|
|
||||||
m_Serialize.Lock();
|
|
||||||
|
|
||||||
if (m_pAdviseCache)
|
|
||||||
{
|
|
||||||
p = m_pAdviseCache;
|
|
||||||
m_pAdviseCache = p->m_next;
|
|
||||||
--m_dwCacheCount;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
p = new CAdvisePacket();
|
|
||||||
}
|
|
||||||
if (p)
|
|
||||||
{
|
|
||||||
p->m_rtEventTime = time1; p->m_rtPeriod = time2;
|
|
||||||
p->m_hNotify = h; p->m_bPeriodic = periodic;
|
|
||||||
Result = AddAdvisePacket( p );
|
|
||||||
}
|
|
||||||
else Result = 0;
|
|
||||||
|
|
||||||
m_Serialize.Unlock();
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT CAMSchedule::Unadvise(DWORD_PTR dwAdviseCookie)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_FALSE;
|
|
||||||
CAdvisePacket * p_prev = &head;
|
|
||||||
CAdvisePacket * p_n;
|
|
||||||
m_Serialize.Lock();
|
|
||||||
while ( p_n = p_prev->Next() ) // The Next() method returns NULL when it hits z
|
|
||||||
{
|
|
||||||
if ( p_n->m_dwAdviseCookie == dwAdviseCookie )
|
|
||||||
{
|
|
||||||
Delete( p_prev->RemoveNext() );
|
|
||||||
--m_dwAdviseCount;
|
|
||||||
hr = S_OK;
|
|
||||||
// Having found one cookie that matches, there should be no more
|
|
||||||
#ifdef DEBUG
|
|
||||||
while (p_n = p_prev->Next())
|
|
||||||
{
|
|
||||||
ASSERT(p_n->m_dwAdviseCookie != dwAdviseCookie);
|
|
||||||
p_prev = p_n;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p_prev = p_n;
|
|
||||||
};
|
|
||||||
m_Serialize.Unlock();
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
REFERENCE_TIME CAMSchedule::Advise( const REFERENCE_TIME & rtTime )
|
|
||||||
{
|
|
||||||
REFERENCE_TIME rtNextTime;
|
|
||||||
CAdvisePacket * pAdvise;
|
|
||||||
|
|
||||||
DbgLog((LOG_TIMING, 2,
|
|
||||||
TEXT("CAMSchedule::Advise( %lu ms )"), ULONG(rtTime / (UNITS / MILLISECONDS))));
|
|
||||||
|
|
||||||
CAutoLock lck(&m_Serialize);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (DbgCheckModuleLevel(LOG_TIMING, 4)) DumpLinkedList();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Note - DON'T cache the difference, it might overflow
|
|
||||||
while ( rtTime >= (rtNextTime = (pAdvise=head.m_next)->m_rtEventTime) &&
|
|
||||||
!pAdvise->IsZ() )
|
|
||||||
{
|
|
||||||
ASSERT(pAdvise->m_dwAdviseCookie); // If this is zero, its the head or the tail!!
|
|
||||||
|
|
||||||
ASSERT(pAdvise->m_hNotify != INVALID_HANDLE_VALUE);
|
|
||||||
|
|
||||||
if (pAdvise->m_bPeriodic == TRUE)
|
|
||||||
{
|
|
||||||
ReleaseSemaphore(pAdvise->m_hNotify,1,NULL);
|
|
||||||
pAdvise->m_rtEventTime += pAdvise->m_rtPeriod;
|
|
||||||
ShuntHead();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ASSERT( pAdvise->m_bPeriodic == FALSE );
|
|
||||||
EXECUTE_ASSERT(SetEvent(pAdvise->m_hNotify));
|
|
||||||
--m_dwAdviseCount;
|
|
||||||
Delete( head.RemoveNext() );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DbgLog((LOG_TIMING, 3,
|
|
||||||
TEXT("CAMSchedule::Advise() Next time stamp: %lu ms, for advise %lu."),
|
|
||||||
DWORD(rtNextTime / (UNITS / MILLISECONDS)), pAdvise->m_dwAdviseCookie ));
|
|
||||||
|
|
||||||
return rtNextTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Private methods */
|
|
||||||
|
|
||||||
DWORD_PTR CAMSchedule::AddAdvisePacket( CAdvisePacket * pPacket )
|
|
||||||
{
|
|
||||||
ASSERT(pPacket->m_rtEventTime >= 0 && pPacket->m_rtEventTime < MAX_TIME);
|
|
||||||
ASSERT(CritCheckIn(&m_Serialize));
|
|
||||||
|
|
||||||
CAdvisePacket * p_prev = &head;
|
|
||||||
CAdvisePacket * p_n;
|
|
||||||
|
|
||||||
const DWORD_PTR Result = pPacket->m_dwAdviseCookie = ++m_dwNextCookie;
|
|
||||||
// This relies on the fact that z is a sentry with a maximal m_rtEventTime
|
|
||||||
for(;;p_prev = p_n)
|
|
||||||
{
|
|
||||||
p_n = p_prev->m_next;
|
|
||||||
if ( p_n->m_rtEventTime >= pPacket->m_rtEventTime ) break;
|
|
||||||
}
|
|
||||||
p_prev->InsertAfter( pPacket );
|
|
||||||
++m_dwAdviseCount;
|
|
||||||
|
|
||||||
DbgLog((LOG_TIMING, 2, TEXT("Added advise %lu, for thread 0x%02X, scheduled at %lu"),
|
|
||||||
pPacket->m_dwAdviseCookie, GetCurrentThreadId(), (pPacket->m_rtEventTime / (UNITS / MILLISECONDS)) ));
|
|
||||||
|
|
||||||
// If packet added at the head, then clock needs to re-evaluate wait time.
|
|
||||||
if ( p_prev == &head ) SetEvent( m_ev );
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAMSchedule::Delete( CAdvisePacket * pPacket )
|
|
||||||
{
|
|
||||||
if ( m_dwCacheCount >= dwCacheMax ) delete pPacket;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_Serialize.Lock();
|
|
||||||
pPacket->m_next = m_pAdviseCache;
|
|
||||||
m_pAdviseCache = pPacket;
|
|
||||||
++m_dwCacheCount;
|
|
||||||
m_Serialize.Unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Takes the head of the list & repositions it
|
|
||||||
void CAMSchedule::ShuntHead()
|
|
||||||
{
|
|
||||||
CAdvisePacket * p_prev = &head;
|
|
||||||
CAdvisePacket * p_n;
|
|
||||||
|
|
||||||
m_Serialize.Lock();
|
|
||||||
CAdvisePacket *const pPacket = head.m_next;
|
|
||||||
|
|
||||||
// This will catch both an empty list,
|
|
||||||
// and if somehow a MAX_TIME time gets into the list
|
|
||||||
// (which would also break this method).
|
|
||||||
ASSERT( pPacket->m_rtEventTime < MAX_TIME );
|
|
||||||
|
|
||||||
// This relies on the fact that z is a sentry with a maximal m_rtEventTime
|
|
||||||
for(;;p_prev = p_n)
|
|
||||||
{
|
|
||||||
p_n = p_prev->m_next;
|
|
||||||
if ( p_n->m_rtEventTime > pPacket->m_rtEventTime ) break;
|
|
||||||
}
|
|
||||||
// If p_prev == pPacket then we're already in the right place
|
|
||||||
if (p_prev != pPacket)
|
|
||||||
{
|
|
||||||
head.m_next = pPacket->m_next;
|
|
||||||
(p_prev->m_next = pPacket)->m_next = p_n;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
|
||||||
DbgLog((LOG_TIMING, 2, TEXT("Periodic advise %lu, shunted to %lu"),
|
|
||||||
pPacket->m_dwAdviseCookie, (pPacket->m_rtEventTime / (UNITS / MILLISECONDS)) ));
|
|
||||||
#endif
|
|
||||||
m_Serialize.Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
void CAMSchedule::DumpLinkedList()
|
|
||||||
{
|
|
||||||
m_Serialize.Lock();
|
|
||||||
int i=0;
|
|
||||||
DbgLog((LOG_TIMING, 1, TEXT("CAMSchedule::DumpLinkedList() this = 0x%p"), this));
|
|
||||||
for ( CAdvisePacket * p = &head
|
|
||||||
; p
|
|
||||||
; p = p->m_next , i++
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DbgLog((LOG_TIMING, 1, TEXT("Advise List # %lu, Cookie %d, RefTime %lu"),
|
|
||||||
i,
|
|
||||||
p->m_dwAdviseCookie,
|
|
||||||
p->m_rtEventTime / (UNITS / MILLISECONDS)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
m_Serialize.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,128 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: Schedule.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __CAMSchedule__
|
|
||||||
#define __CAMSchedule__
|
|
||||||
|
|
||||||
class CAMSchedule : private CBaseObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~CAMSchedule();
|
|
||||||
// ev is the event we should fire if the advise time needs re-evaluating
|
|
||||||
CAMSchedule( HANDLE ev );
|
|
||||||
|
|
||||||
DWORD GetAdviseCount();
|
|
||||||
REFERENCE_TIME GetNextAdviseTime();
|
|
||||||
|
|
||||||
// We need a method for derived classes to add advise packets, we return the cookie
|
|
||||||
DWORD_PTR AddAdvisePacket( const REFERENCE_TIME & time1, const REFERENCE_TIME & time2, HANDLE h, BOOL periodic );
|
|
||||||
// And a way to cancel
|
|
||||||
HRESULT Unadvise(DWORD_PTR dwAdviseCookie);
|
|
||||||
|
|
||||||
// Tell us the time please, and we'll dispatch the expired events. We return the time of the next event.
|
|
||||||
// NB: The time returned will be "useless" if you start adding extra Advises. But that's the problem of
|
|
||||||
// whoever is using this helper class (typically a clock).
|
|
||||||
REFERENCE_TIME Advise( const REFERENCE_TIME & rtTime );
|
|
||||||
|
|
||||||
// Get the event handle which will be set if advise time requires re-evaluation.
|
|
||||||
HANDLE GetEvent() const { return m_ev; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
// We define the nodes that will be used in our singly linked list
|
|
||||||
// of advise packets. The list is ordered by time, with the
|
|
||||||
// elements that will expire first at the front.
|
|
||||||
class CAdvisePacket
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CAdvisePacket()
|
|
||||||
{}
|
|
||||||
|
|
||||||
CAdvisePacket * m_next;
|
|
||||||
DWORD_PTR m_dwAdviseCookie;
|
|
||||||
REFERENCE_TIME m_rtEventTime; // Time at which event should be set
|
|
||||||
REFERENCE_TIME m_rtPeriod; // Periodic time
|
|
||||||
HANDLE m_hNotify; // Handle to event or semephore
|
|
||||||
BOOL m_bPeriodic; // TRUE => Periodic event
|
|
||||||
|
|
||||||
CAdvisePacket( CAdvisePacket * next, LONGLONG time ) : m_next(next), m_rtEventTime(time)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void InsertAfter( CAdvisePacket * p )
|
|
||||||
{
|
|
||||||
p->m_next = m_next;
|
|
||||||
m_next = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IsZ() const // That is, is it the node that represents the end of the list
|
|
||||||
{ return m_next == 0; }
|
|
||||||
|
|
||||||
CAdvisePacket * RemoveNext()
|
|
||||||
{
|
|
||||||
CAdvisePacket *const next = m_next;
|
|
||||||
CAdvisePacket *const new_next = next->m_next;
|
|
||||||
m_next = new_next;
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeleteNext()
|
|
||||||
{
|
|
||||||
delete RemoveNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
CAdvisePacket * Next() const
|
|
||||||
{
|
|
||||||
CAdvisePacket * result = m_next;
|
|
||||||
if (result->IsZ()) result = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD_PTR Cookie() const
|
|
||||||
{ return m_dwAdviseCookie; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Structure is:
|
|
||||||
// head -> elmt1 -> elmt2 -> z -> null
|
|
||||||
// So an empty list is: head -> z -> null
|
|
||||||
// Having head & z as links makes insertaion,
|
|
||||||
// deletion and shunting much easier.
|
|
||||||
CAdvisePacket head, z; // z is both a tail and a sentry
|
|
||||||
|
|
||||||
volatile DWORD_PTR m_dwNextCookie; // Strictly increasing
|
|
||||||
volatile DWORD m_dwAdviseCount; // Number of elements on list
|
|
||||||
|
|
||||||
CCritSec m_Serialize;
|
|
||||||
|
|
||||||
// AddAdvisePacket: adds the packet, returns the cookie (0 if failed)
|
|
||||||
DWORD_PTR AddAdvisePacket( CAdvisePacket * pPacket );
|
|
||||||
// Event that we should set if the packed added above will be the next to fire.
|
|
||||||
const HANDLE m_ev;
|
|
||||||
|
|
||||||
// A Shunt is where we have changed the first element in the
|
|
||||||
// list and want it re-evaluating (i.e. repositioned) in
|
|
||||||
// the list.
|
|
||||||
void ShuntHead();
|
|
||||||
|
|
||||||
// Rather than delete advise packets, we cache them for future use
|
|
||||||
CAdvisePacket * m_pAdviseCache;
|
|
||||||
DWORD m_dwCacheCount;
|
|
||||||
enum { dwCacheMax = 5 }; // Don't bother caching more than five
|
|
||||||
|
|
||||||
void Delete( CAdvisePacket * pLink );// This "Delete" will cache the Link
|
|
||||||
|
|
||||||
// Attributes and methods for debugging
|
|
||||||
public:
|
|
||||||
#ifdef DEBUG
|
|
||||||
void DumpLinkedList();
|
|
||||||
#else
|
|
||||||
void DumpLinkedList() {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __CAMSchedule__
|
|
|
@ -1,83 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: SeekPT.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
#include "seekpt.h"
|
|
||||||
|
|
||||||
//==================================================================
|
|
||||||
// CreateInstance
|
|
||||||
// This goes in the factory template table to create new instances
|
|
||||||
// If there is already a mapper instance - return that, else make one
|
|
||||||
// and save it in a static variable so that forever after we can return that.
|
|
||||||
//==================================================================
|
|
||||||
|
|
||||||
CUnknown * CSeekingPassThru::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
|
|
||||||
{
|
|
||||||
return new CSeekingPassThru(NAME("Seeking PassThru"),pUnk, phr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
STDMETHODIMP CSeekingPassThru::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
|
|
||||||
{
|
|
||||||
if (riid == IID_ISeekingPassThru) {
|
|
||||||
return GetInterface((ISeekingPassThru *) this, ppv);
|
|
||||||
} else {
|
|
||||||
if (m_pPosPassThru &&
|
|
||||||
(riid == IID_IMediaSeeking ||
|
|
||||||
riid == IID_IMediaPosition)) {
|
|
||||||
return m_pPosPassThru->NonDelegatingQueryInterface(riid,ppv);
|
|
||||||
} else {
|
|
||||||
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CSeekingPassThru::CSeekingPassThru( TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr )
|
|
||||||
: CUnknown(pName, pUnk, phr),
|
|
||||||
m_pPosPassThru(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CSeekingPassThru::~CSeekingPassThru()
|
|
||||||
{
|
|
||||||
delete m_pPosPassThru;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP CSeekingPassThru::Init(BOOL bRendererSeeking, IPin *pPin)
|
|
||||||
{
|
|
||||||
HRESULT hr = NOERROR;
|
|
||||||
if (m_pPosPassThru) {
|
|
||||||
hr = E_FAIL;
|
|
||||||
} else {
|
|
||||||
m_pPosPassThru =
|
|
||||||
bRendererSeeking ?
|
|
||||||
new CRendererPosPassThru(
|
|
||||||
NAME("Render Seeking COM object"),
|
|
||||||
(IUnknown *)this,
|
|
||||||
&hr,
|
|
||||||
pPin) :
|
|
||||||
new CPosPassThru(
|
|
||||||
NAME("Render Seeking COM object"),
|
|
||||||
(IUnknown *)this,
|
|
||||||
&hr,
|
|
||||||
pPin);
|
|
||||||
if (!m_pPosPassThru) {
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
} else {
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
delete m_pPosPassThru;
|
|
||||||
m_pPosPassThru = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: SeekPT.h
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes.
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __seekpt_h__
|
|
||||||
#define __seekpt_h__
|
|
||||||
|
|
||||||
|
|
||||||
class CSeekingPassThru : public ISeekingPassThru, public CUnknown
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
|
|
||||||
CSeekingPassThru(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr);
|
|
||||||
~CSeekingPassThru();
|
|
||||||
|
|
||||||
DECLARE_IUNKNOWN;
|
|
||||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
|
|
||||||
|
|
||||||
STDMETHODIMP Init(BOOL bSupportRendering, IPin *pPin);
|
|
||||||
|
|
||||||
private:
|
|
||||||
CPosPassThru *m_pPosPassThru;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,522 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File: Source.cpp
|
|
||||||
//
|
|
||||||
// Desc: DirectShow base classes - implements CSource, which is a Quartz
|
|
||||||
// source filter 'template.'
|
|
||||||
//
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
// Locking Strategy.
|
|
||||||
//
|
|
||||||
// Hold the filter critical section (m_pFilter->pStateLock()) to serialise
|
|
||||||
// access to functions. Note that, in general, this lock may be held
|
|
||||||
// by a function when the worker thread may want to hold it. Therefore
|
|
||||||
// if you wish to access shared state from the worker thread you will
|
|
||||||
// need to add another critical section object. The execption is during
|
|
||||||
// the threads processing loop, when it is safe to get the filter critical
|
|
||||||
// section from within FillBuffer().
|
|
||||||
|
|
||||||
#include <streams.h>
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// CSource::Constructor
|
|
||||||
//
|
|
||||||
// Initialise the pin count for the filter. The user will create the pins in
|
|
||||||
// the derived class.
|
|
||||||
CSource::CSource(TCHAR *pName, LPUNKNOWN lpunk, CLSID clsid)
|
|
||||||
: CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
|
|
||||||
m_iPins(0),
|
|
||||||
m_paStreams(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CSource::CSource(TCHAR *pName, LPUNKNOWN lpunk, CLSID clsid, HRESULT *phr)
|
|
||||||
: CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
|
|
||||||
m_iPins(0),
|
|
||||||
m_paStreams(NULL)
|
|
||||||
{
|
|
||||||
UNREFERENCED_PARAMETER(phr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
CSource::CSource(CHAR *pName, LPUNKNOWN lpunk, CLSID clsid)
|
|
||||||
: CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
|
|
||||||
m_iPins(0),
|
|
||||||
m_paStreams(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CSource::CSource(CHAR *pName, LPUNKNOWN lpunk, CLSID clsid, HRESULT *phr)
|
|
||||||
: CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
|
|
||||||
m_iPins(0),
|
|
||||||
m_paStreams(NULL)
|
|
||||||
{
|
|
||||||
UNREFERENCED_PARAMETER(phr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// CSource::Destructor
|
|
||||||
//
|
|
||||||
CSource::~CSource()
|
|
||||||
{
|
|
||||||
/* Free our pins and pin array */
|
|
||||||
while (m_iPins != 0) {
|
|
||||||
// deleting the pins causes them to be removed from the array...
|
|
||||||
delete m_paStreams[m_iPins - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(m_paStreams == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Add a new pin
|
|
||||||
//
|
|
||||||
HRESULT CSource::AddPin(CSourceStream *pStream)
|
|
||||||
{
|
|
||||||
CAutoLock lock(&m_cStateLock);
|
|
||||||
|
|
||||||
/* Allocate space for this pin and the old ones */
|
|
||||||
CSourceStream **paStreams = new CSourceStream *[m_iPins + 1];
|
|
||||||
if (paStreams == NULL) {
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
if (m_paStreams != NULL) {
|
|
||||||
CopyMemory((PVOID)paStreams, (PVOID)m_paStreams,
|
|
||||||
m_iPins * sizeof(m_paStreams[0]));
|
|
||||||
paStreams[m_iPins] = pStream;
|
|
||||||
delete [] m_paStreams;
|
|
||||||
}
|
|
||||||
m_paStreams = paStreams;
|
|
||||||
m_paStreams[m_iPins] = pStream;
|
|
||||||
m_iPins++;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Remove a pin - pStream is NOT deleted
|
|
||||||
//
|
|
||||||
HRESULT CSource::RemovePin(CSourceStream *pStream)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < m_iPins; i++) {
|
|
||||||
if (m_paStreams[i] == pStream) {
|
|
||||||
if (m_iPins == 1) {
|
|
||||||
delete [] m_paStreams;
|
|
||||||
m_paStreams = NULL;
|
|
||||||
} else {
|
|
||||||
/* no need to reallocate */
|
|
||||||
while (++i < m_iPins)
|
|
||||||
m_paStreams[i - 1] = m_paStreams[i];
|
|
||||||
}
|
|
||||||
m_iPins--;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// FindPin
|
|
||||||
//
|
|
||||||
// Set *ppPin to the IPin* that has the id Id.
|
|
||||||
// or to NULL if the Id cannot be matched.
|
|
||||||
STDMETHODIMP CSource::FindPin(LPCWSTR Id, IPin **ppPin)
|
|
||||||
{
|
|
||||||
CheckPointer(ppPin,E_POINTER);
|
|
||||||
ValidateReadWritePtr(ppPin,sizeof(IPin *));
|
|
||||||
// The -1 undoes the +1 in QueryId and ensures that totally invalid
|
|
||||||
// strings (for which WstrToInt delivers 0) give a deliver a NULL pin.
|
|
||||||
int i = WstrToInt(Id) -1;
|
|
||||||
*ppPin = GetPin(i);
|
|
||||||
if (*ppPin!=NULL){
|
|
||||||
(*ppPin)->AddRef();
|
|
||||||
return NOERROR;
|
|
||||||
} else {
|
|
||||||
return VFW_E_NOT_FOUND;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// FindPinNumber
|
|
||||||
//
|
|
||||||
// return the number of the pin with this IPin* or -1 if none
|
|
||||||
int CSource::FindPinNumber(IPin *iPin) {
|
|
||||||
int i;
|
|
||||||
for (i=0; i<m_iPins; ++i) {
|
|
||||||
if ((IPin *)(m_paStreams[i])==iPin) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// GetPinCount
|
|
||||||
//
|
|
||||||
// Returns the number of pins this filter has
|
|
||||||
int CSource::GetPinCount(void) {
|
|
||||||
|
|
||||||
CAutoLock lock(&m_cStateLock);
|
|
||||||
return m_iPins;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// GetPin
|
|
||||||
//
|
|
||||||
// Return a non-addref'd pointer to pin n
|
|
||||||
// needed by CBaseFilter
|
|
||||||
CBasePin *CSource::GetPin(int n) {
|
|
||||||
|
|
||||||
CAutoLock lock(&m_cStateLock);
|
|
||||||
|
|
||||||
// n must be in the range 0..m_iPins-1
|
|
||||||
// if m_iPins>n && n>=0 it follows that m_iPins>0
|
|
||||||
// which is what used to be checked (i.e. checking that we have a pin)
|
|
||||||
if ((n >= 0) && (n < m_iPins)) {
|
|
||||||
|
|
||||||
ASSERT(m_paStreams[n]);
|
|
||||||
return m_paStreams[n];
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
// *
|
|
||||||
// * --- CSourceStream ----
|
|
||||||
// *
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set Id to point to a CoTaskMemAlloc'd
|
|
||||||
STDMETHODIMP CSourceStream::QueryId(LPWSTR *Id) {
|
|
||||||
CheckPointer(Id,E_POINTER);
|
|
||||||
ValidateReadWritePtr(Id,sizeof(LPWSTR));
|
|
||||||
|
|
||||||
// We give the pins id's which are 1,2,...
|
|
||||||
// FindPinNumber returns -1 for an invalid pin
|
|
||||||
int i = 1+ m_pFilter->FindPinNumber(this);
|
|
||||||
if (i<1) return VFW_E_NOT_FOUND;
|
|
||||||
*Id = (LPWSTR)CoTaskMemAlloc(4*sizeof(WCHAR));
|
|
||||||
if (*Id==NULL) {
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
IntToWstr(i, *Id, 4);
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// CSourceStream::Constructor
|
|
||||||
//
|
|
||||||
// increments the number of pins present on the filter
|
|
||||||
CSourceStream::CSourceStream(
|
|
||||||
TCHAR *pObjectName,
|
|
||||||
HRESULT *phr,
|
|
||||||
CSource *ps,
|
|
||||||
LPCWSTR pPinName)
|
|
||||||
: CBaseOutputPin(pObjectName, ps, ps->pStateLock(), phr, pPinName),
|
|
||||||
m_pFilter(ps) {
|
|
||||||
|
|
||||||
*phr = m_pFilter->AddPin(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
CSourceStream::CSourceStream(
|
|
||||||
char *pObjectName,
|
|
||||||
HRESULT *phr,
|
|
||||||
CSource *ps,
|
|
||||||
LPCWSTR pPinName)
|
|
||||||
: CBaseOutputPin(pObjectName, ps, ps->pStateLock(), phr, pPinName),
|
|
||||||
m_pFilter(ps) {
|
|
||||||
|
|
||||||
*phr = m_pFilter->AddPin(this);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
//
|
|
||||||
// CSourceStream::Destructor
|
|
||||||
//
|
|
||||||
// Decrements the number of pins on this filter
|
|
||||||
CSourceStream::~CSourceStream(void) {
|
|
||||||
|
|
||||||
m_pFilter->RemovePin(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// CheckMediaType
|
|
||||||
//
|
|
||||||
// Do we support this type? Provides the default support for 1 type.
|
|
||||||
HRESULT CSourceStream::CheckMediaType(const CMediaType *pMediaType) {
|
|
||||||
|
|
||||||
CAutoLock lock(m_pFilter->pStateLock());
|
|
||||||
|
|
||||||
CMediaType mt;
|
|
||||||
GetMediaType(&mt);
|
|
||||||
|
|
||||||
if (mt == *pMediaType) {
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// GetMediaType/3
|
|
||||||
//
|
|
||||||
// By default we support only one type
|
|
||||||
// iPosition indexes are 0-n
|
|
||||||
HRESULT CSourceStream::GetMediaType(int iPosition, CMediaType *pMediaType) {
|
|
||||||
|
|
||||||
CAutoLock lock(m_pFilter->pStateLock());
|
|
||||||
|
|
||||||
if (iPosition<0) {
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
if (iPosition>0) {
|
|
||||||
return VFW_S_NO_MORE_ITEMS;
|
|
||||||
}
|
|
||||||
return GetMediaType(pMediaType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Active
|
|
||||||
//
|
|
||||||
// The pin is active - start up the worker thread
|
|
||||||
HRESULT CSourceStream::Active(void) {
|
|
||||||
|
|
||||||
CAutoLock lock(m_pFilter->pStateLock());
|
|
||||||
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
if (m_pFilter->IsActive()) {
|
|
||||||
return S_FALSE; // succeeded, but did not allocate resources (they already exist...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// do nothing if not connected - its ok not to connect to
|
|
||||||
// all pins of a source filter
|
|
||||||
if (!IsConnected()) {
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = CBaseOutputPin::Active();
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(!ThreadExists());
|
|
||||||
|
|
||||||
// start the thread
|
|
||||||
if (!Create()) {
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell thread to initialize. If OnThreadCreate Fails, so does this.
|
|
||||||
hr = Init();
|
|
||||||
if (FAILED(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
return Pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Inactive
|
|
||||||
//
|
|
||||||
// Pin is inactive - shut down the worker thread
|
|
||||||
// Waits for the worker to exit before returning.
|
|
||||||
HRESULT CSourceStream::Inactive(void) {
|
|
||||||
|
|
||||||
CAutoLock lock(m_pFilter->pStateLock());
|
|
||||||
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
// do nothing if not connected - its ok not to connect to
|
|
||||||
// all pins of a source filter
|
|
||||||
if (!IsConnected()) {
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// !!! need to do this before trying to stop the thread, because
|
|
||||||
// we may be stuck waiting for our own allocator!!!
|
|
||||||
|
|
||||||
hr = CBaseOutputPin::Inactive(); // call this first to Decommit the allocator
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ThreadExists()) {
|
|
||||||
hr = Stop();
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = Exit();
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Close(); // Wait for the thread to exit, then tidy up.
|
|
||||||
}
|
|
||||||
|
|
||||||
// hr = CBaseOutputPin::Inactive(); // call this first to Decommit the allocator
|
|
||||||
//if (FAILED(hr)) {
|
|
||||||
// return hr;
|
|
||||||
//}
|
|
||||||
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// ThreadProc
|
|
||||||
//
|
|
||||||
// When this returns the thread exits
|
|
||||||
// Return codes > 0 indicate an error occured
|
|
||||||
DWORD CSourceStream::ThreadProc(void) {
|
|
||||||
|
|
||||||
HRESULT hr; // the return code from calls
|
|
||||||
Command com;
|
|
||||||
|
|
||||||
do {
|
|
||||||
com = GetRequest();
|
|
||||||
if (com != CMD_INIT) {
|
|
||||||
DbgLog((LOG_ERROR, 1, TEXT("Thread expected init command")));
|
|
||||||
Reply((DWORD) E_UNEXPECTED);
|
|
||||||
}
|
|
||||||
} while (com != CMD_INIT);
|
|
||||||
|
|
||||||
DbgLog((LOG_TRACE, 1, TEXT("CSourceStream worker thread initializing")));
|
|
||||||
|
|
||||||
hr = OnThreadCreate(); // perform set up tasks
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
DbgLog((LOG_ERROR, 1, TEXT("CSourceStream::OnThreadCreate failed. Aborting thread.")));
|
|
||||||
OnThreadDestroy();
|
|
||||||
Reply(hr); // send failed return code from OnThreadCreate
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialisation suceeded
|
|
||||||
Reply(NOERROR);
|
|
||||||
|
|
||||||
Command cmd;
|
|
||||||
do {
|
|
||||||
cmd = GetRequest();
|
|
||||||
|
|
||||||
switch (cmd) {
|
|
||||||
|
|
||||||
case CMD_EXIT:
|
|
||||||
Reply(NOERROR);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_RUN:
|
|
||||||
DbgLog((LOG_ERROR, 1, TEXT("CMD_RUN received before a CMD_PAUSE???")));
|
|
||||||
// !!! fall through???
|
|
||||||
|
|
||||||
case CMD_PAUSE:
|
|
||||||
Reply(NOERROR);
|
|
||||||
DoBufferProcessingLoop();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_STOP:
|
|
||||||
Reply(NOERROR);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
DbgLog((LOG_ERROR, 1, TEXT("Unknown command %d received!"), cmd));
|
|
||||||
Reply((DWORD) E_NOTIMPL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (cmd != CMD_EXIT);
|
|
||||||
|
|
||||||
hr = OnThreadDestroy(); // tidy up.
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
DbgLog((LOG_ERROR, 1, TEXT("CSourceStream::OnThreadDestroy failed. Exiting thread.")));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DbgLog((LOG_TRACE, 1, TEXT("CSourceStream worker thread exiting")));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// DoBufferProcessingLoop
|
|
||||||
//
|
|
||||||
// Grabs a buffer and calls the users processing function.
|
|
||||||
// Overridable, so that different delivery styles can be catered for.
|
|
||||||
HRESULT CSourceStream::DoBufferProcessingLoop(void) {
|
|
||||||
|
|
||||||
Command com;
|
|
||||||
|
|
||||||
OnThreadStartPlay();
|
|
||||||
|
|
||||||
do {
|
|
||||||
while (!CheckRequest(&com)) {
|
|
||||||
|
|
||||||
IMediaSample *pSample;
|
|
||||||
|
|
||||||
HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
Sleep(1);
|
|
||||||
continue; // go round again. Perhaps the error will go away
|
|
||||||
// or the allocator is decommited & we will be asked to
|
|
||||||
// exit soon.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Virtual function user will override.
|
|
||||||
hr = FillBuffer(pSample);
|
|
||||||
|
|
||||||
if (hr == S_OK) {
|
|
||||||
hr = Deliver(pSample);
|
|
||||||
pSample->Release();
|
|
||||||
|
|
||||||
// downstream filter returns S_FALSE if it wants us to
|
|
||||||
// stop or an error if it's reporting an error.
|
|
||||||
if(hr != S_OK)
|
|
||||||
{
|
|
||||||
DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr));
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (hr == S_FALSE) {
|
|
||||||
// derived class wants us to stop pushing data
|
|
||||||
pSample->Release();
|
|
||||||
DeliverEndOfStream();
|
|
||||||
return S_OK;
|
|
||||||
} else {
|
|
||||||
// derived class encountered an error
|
|
||||||
pSample->Release();
|
|
||||||
DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr));
|
|
||||||
DeliverEndOfStream();
|
|
||||||
m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// all paths release the sample
|
|
||||||
}
|
|
||||||
|
|
||||||
// For all commands sent to us there must be a Reply call!
|
|
||||||
|
|
||||||
if (com == CMD_RUN || com == CMD_PAUSE) {
|
|
||||||
Reply(NOERROR);
|
|
||||||
} else if (com != CMD_STOP) {
|
|
||||||
Reply((DWORD) E_UNEXPECTED);
|
|
||||||
DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!")));
|
|
||||||
}
|
|
||||||
} while (com != CMD_STOP);
|
|
||||||
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue