................

program VmrAlloc;
uses
   Windows,
   Messages,
   untVideo in 'untVideo.pas';
const
   AppName = 'VmrAlloctor';
var
   g_video: YVideo = NIL;
   g_hwnd: HWND   = 0;
{$R *.RES}
procedure PaintWindow(hWnd: HWND);
var
   ps: PAINTSTRUCT;
   dc: HDC;
begin
   dc := BeginPaint(hWnd, ps);
   //   if( g_mediaControl == NULL ) // we know that there is nothing loaded
     {
         bNeedPaint = true;
     }
   //   else
     {
         // If we have a movie loaded, we only need to repaint
         // when the graph is stopped
         OAFilterState state;
         if( SUCCEEDED( g_mediaControl->GetState(0, & state ) ) )
         {
             bNeedPaint = ( state == State_Stopped );
         }
   // }
   // if ( bNeedPaint )
     {
         RECT rc2;
         GetClientRect(hWnd, &rc2);
         FillRect(hdc, &rc2, (HBRUSH)(COLOR_WINDOW+1));
     }
     EndPaint( hWnd, ps );
end;
function WindowProc(hWnd, uMsg, wParam, lParam: Integer): Integer; stdcall;
begin
   result := 0;
   case uMsg of
     WM_DESTROY:
     begin
       PostQuitMessage(0);
       Exit;
     end;
     WM_KEYUP:
     begin
       case wParam of
         VK_ESCAPE: DestroyWindow(hWnd);
       end;
       Exit;
     end;
     WM_PAINT:
     begin
       PaintWindow(hWnd);
       Exit;
     end;
   end;
   Result := DefWindowProc(hWnd, uMsg, wParam, lParam);
end;
function RegWindowClass(): Bool;
var
   WinClass: TWndClassEx;
begin
   FillChar(WinClass, sizeof(WinClass), 0);
   WinClass.cbSize := sizeof(WinClass);
   WinClass.style := CS_CLASSDC;
   WinClass.lpfnWndProc := @WindowProc;
   WinClass.hInstance := hInstance;
   WinClass.lpszClassName := AppName;
   WinClass.hCursor := LoadCursor(0, IDC_ARROW);
   Result := RegisterClassEx(WinClass) <> 0;
end;

begin
   //注册窗口类
   if not RegWindowClass then
   begin
   MessageBox(0, 'Call RegisterClass() Failed.', AppName, MB_IConERROR);
     Exit;
   end;
   //创建窗口
   g_hwnd := CreateWindowEx(0, AppName, AppName, WS_OVERLAPPED,
       0, 0, 700, 500, 0, 0, hInstance, nil);
   if g_hwnd = 0 then
   begin
     MessageBox(0, 'Call CreateWindowEx() Failed.', AppName, MB_IConERROR);
     UnregisterClass(AppName, hInstance);
     Exit;
   end;
   //创建g_game
   g_video := YVideo.Create;
   //初始化g_game
   if g_video.Initialise(g_hwnd, NiL)then
   begin
     ShowWindow( g_hwnd, SW_SHOWDEFAULT );
     UpdateWindow( g_hwnd );
     g_video.LoadVideoFromFile('Windows Movie Maker 样本文件.wmv');
     g_video.Play();
     g_video.GameLoop();
   end else
   begin
     MessageBox(0, 'g_video.Initialise() Failed.', AppName, MB_IConERROR);
   end;
   //销毁g_game
   g_video.Free;
   UnregisterClass(AppName, hInstance);
end.

 


unit untVideo;
interface
uses
   Windows, Messages, sysUtils, Classes, Direct3D9, D3DX9, DirectMusic, DirectShow9,
   ActiveX, MultiMon, untConst;
const
   PANEL_D3DFVF_CUSTOMVERTEX = D3DFVF_XYZ or D3DFVF_DIFFUSE or D3DFVF_TEX1;
type
   PANEL_CUSTOMVERTEX = record
     x, y, z: float;
     color: DWORD;
     u, v: float;
   end;
   PPANEL_CUSTOMVERTEX = ^PANEL_CUSTOMVERTEX;
   YVideoPanel = class
   public
     constructor Create();
     destructor Destroy; override;
     function Init(d3ddev: IDirect3DDevice9):HRESULT;
     function DrawScene(d3ddev: IDirect3DDevice9; texture: IDirect3DTexture9):HRESULT;
     procedure UpdateVertices(fTU, fTV: FLOAT);
   private
     m_pVertexBuffer: IDIRECT3DVERTEXBUFFER9;
     m_vertices: Array [00..3] of PANEL_CUSTOMVERTEX;
   end;

   //有3个成员变量需要外部传入:m_window, m_d3dDev, m_vmrSurfAllocNotify
   YAllocator = class(TInterfacedObject, IVMRSurfaceAllocator9, IVMRImagePresenter9)
   public
     constructor Create(hwnd: HWND; d3d: IDirect3D9; d3ddd3dDev: IDIRECT3DDEVICE9; var hr: HRESULT);
     destructor Destroy();override;
     function CreateDevice():HRESULT;
     function InitializeDevice(dwUserID: DWORD; lpAllocInfo: PVMR9AllocationInfo; var lpNumBuffers: DWORD): HResult; stdcall;
     function TerminateDevice(dwID: DWORD): HResult; stdcall;
     function GetSurface(dwUserID: DWORD; SurfaceIndex: DWORD; SurfaceFlags: DWORD; out lplpSurface: IDirect3DSurface9): HResult; stdcall;
     function AdviseNotify(lpIVMRSurfAllocNotify: IVMRSurfaceAllocatorNotify9): HResult; stdcall;
   function StartPresenting(dwUserID: DWORD):HResult; stdcall;
   function StopPresenting(dwUserID: DWORD):HResult; stdcall;
   function PresentImage(dwUserID: DWORD; lpPresInfo: PVMR9PresentationInfo):HResult; stdcall;
   { function QueryInterface(const riid: TGUID; out ppvObject):HRESULT; stdcall;
     function _AddRef():S32; stdcall;
     function _Release():S32; stdcall;   }
   protected
     procedure _DeleteSurfaces();
   private
     m_window: HWND;
     m_d3d: IDirect3D9;
     m_d3dDev: IDIRECT3DDEVICE9;
     m_refCount: S32;
     m_vmrSurfAllocNotify: IVMRSurfaceAllocatorNotify9;
     m_privateTexture: IDirect3DTexture9;
m_d3dSurfaces: Array of IDirect3DSurface9;
     m_renderTarget: IDirect3DSurface9;
     m_scene: YVideoPanel;
   end;
   YVideo = class
   public
     constructor Create();
     destructor Destroy();override;
     function Initialise(hwnd: HWND; d3dDev: IDIRECT3DDEVICE9):BOOL;
     procedure LoadVideoFromFile(sFileName: string);
     procedure Play();
     procedure Stop();
     procedure GameLoop();
   private
     m_GraphBuilder: IGraphBuilder; //FILTER管理器
     m_BaseFilter: IBaseFilter;     //用于创建VMR9
     m_MediaControl: IMediaControl; //媒体控制
     m_vmrAllocator: YAllocator;
   end;
implementation
var
   CS_VIDEOTEXTRUE_LOCK: TRTLCriticalSection; //临界区,保证线程安全
{ YVideoPanel }
constructor YVideoPanel.Create();
begin
m_pVertexBuffer := NULL;
end;
destructor YVideoPanel.Destroy;
begin
SafeRelease(m_pVertexBuffer);
end;
function YVideoPanel.Init(d3ddev: IDirect3DDevice9):HRESULT;
var
   backBuffer: IDirect3DSurface9;
   backBufferDesc: D3DSURFACE_DESC;
   matProj, matView: TD3DXMATRIX;
   fAspect: FLOAT;
   from, at, up: TD3DXVECTOR3;
begin
   if( d3ddev = NULL ) then
   begin
     result := E_POINTER;
     Exit;
   end;
   d3ddev.SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
   d3ddev.SetRenderState(D3DRS_LIGHTING, U32(FALSE));
   d3ddev.SetRenderState(D3DRS_ALPHABLENDENABLE, U32(TRUE));
   d3ddev.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
   d3ddev.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
   d3ddev.SetRenderState(D3DRS_ALPHATESTENABLE, U32(TRUE));
   d3ddev.SetRenderState(D3DRS_ALPHAREF, $10);
   d3ddev.SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
   d3ddev.SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
   d3ddev.SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
   d3ddev.SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
   d3ddev.SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
   d3ddev.SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
   m_pVertexBuffer := NULL;
   d3ddev.CreateVertexBuffer(4 * sizeof(PANEL_CUSTOMVERTEX),D3DUSAGE_WRITEONLY,PANEL_D3DFVF_CUSTOMVERTEX,D3DPOOL_MANAGED,m_pvertexBuffer, NULL );
   d3ddev.GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, backBuffer);
   backBuffer.GetDesc( backBufferDesc);
   // Set the projection matrix
   //fAspect := backBufferDesc.Width / backBufferDesc.Height;
   fAspect:=1.0;
   D3DXMatrixPerspectiveFovLH( matProj, D3DX_PI/4, fAspect, 1.0, 500.0 );
   d3ddev.SetTransform( D3DTS_PROJECTION, matProj );
   from := D3DXVECTOR3( 0.0, 0.0, -9.0 );
   at := D3DXVECTOR3( 0.0, 0.0, 0.0 );
   up := D3DXVECTOR3( 0.0, 1.0, 0.0 );
   D3DXMatrixLookAtLH(matView, from, at, up);
   d3ddev.SetTransform( D3DTS_VIEW, matView );
   //m_time = GetTickCount();
   result := S_OK;
   UpdateVertices(1.0,1.0);
end;
function YVideoPanel.DrawScene(d3ddev: IDirect3DDevice9; texture: IDirect3DTexture9):HRESULT;
begin
   if( d3ddev = NULL) or( texture = NULL )then
   begin
     result := E_POINTER;
     Exit;
   end;
   if( m_pvertexBuffer = NULL )then
   begin
     result := D3DERR_INVALIDCALL;
     Exit;
   end;
                 {
   // get the difference in time
   dwCurrentTime := GetTickCount();
   double difference = m_time - dwCurrentTime ;
   // figure out the rotation of the plane
   float x = (float) ( -cos(difference / 2000.0 ) ) ;
   float y = (float) ( cos(difference / 2000.0 ) ) ;
   float z = (float) ( sin(difference / 2000.0 ) ) ;
   // update the two rotating vertices with the new position
   m_vertices[0].position = CUSTOMVERTEX::Position(x,   y, z);   // top left
   m_vertices[3].position = CUSTOMVERTEX::Position(-x, -y, -z); // bottom right
   // Adjust the color so the blue is always on the bottom.
   // As the corner approaches the bottom, get rid of all the other
   // colors besides blue
   DWORD mask0 = (DWORD) (255 * ( ( y + 1.0   )/ 2.0 ));
   DWORD mask3 = (DWORD) (255 * ( ( -y + 1.0   )/ 2.0 ));
   m_vertices[0].color = 0xff0000ff | ( mask0 << 16 ) | ( mask0 << 8 );
   m_vertices[3].color = 0xff0000ff | ( mask3 << 16 ) | ( mask3 << 8 );
   // write the new vertex information into the buffer
   void* pData;
   FAIL_RET( m_vertexBuffer->Lock(0,sizeof(pData), &pData,0) );
   memcpy(pData,m_vertices,sizeof(m_vertices));                            
   FAIL_RET( m_vertexBuffer->Unlock() );
                         }
   // clear the scene so we don't have any articats left
   d3ddev.Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0, 0 );
   d3ddev.BeginScene();
   d3ddev.SetTexture( 0, texture);
   d3ddev.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
   d3ddev.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
   d3ddev.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
   d3ddev.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
   d3ddev.SetStreamSource(0, m_pvertexBuffer, 0, sizeof(PANEL_CUSTOMVERTEX) ); //set next source ( NEW )
   d3ddev.SetFVF( PANEL_D3DFVF_CUSTOMVERTEX );
   d3ddev.DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2);   //draw quad
   d3ddev.SetTexture( 0, NULL);
   d3ddev.EndScene();
   result := S_OK;
end;
procedure YVideoPanel.UpdateVertices(fTU, fTV: FLOAT);
const
   W = 3.2;
   H = 2.4;
var
pVertices: PPANEL_CUSTOMVERTEX;//   = NULL;
begin
   if m_pVertexBuffer = NULL then
     Exit;
   pVertices := NULL;
m_pVertexBuffer.Lock(0, 4 * sizeof(PANEL_CUSTOMVERTEX), Pointer(pVertices), 0);
//Set all the vertices to selected colour
m_Vertices[0].color := $ffffffff;
m_Vertices[1].color := $ffffffff;
m_Vertices[2].color := $ffffffff;
m_Vertices[3].color := $ffffffff;
//Set the positions of the vertices
   m_Vertices[0].x := -W; m_Vertices[0].y := -H; m_Vertices[0].z := 0.0;
   m_Vertices[1].x := -W; m_Vertices[1].y := +H; m_Vertices[1].z := 0.0;
   m_Vertices[2].x := +W; m_Vertices[2].y := -H; m_Vertices[2].z := 0.0;
   m_Vertices[3].x := +W; m_Vertices[3].y := +H; m_Vertices[3].z := 0.0;
//Set the texture coordinates of the vertices
   m_Vertices[0].u := 0.0; m_Vertices[0].v := fTV;
   m_Vertices[1].u := 0.0; m_Vertices[1].v := 0.0;
   m_Vertices[2].u := fTU; m_Vertices[2].v := fTV;
   m_Vertices[3].u := fTU; m_Vertices[3].v := 0.0;
   Move(m_vertices[0], pVertices^, sizeof(m_vertices[0])*4);
m_pVertexBuffer.Unlock();
end;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值