Guest User

Unit_VideoPlayerTest

a guest
Apr 23rd, 2017
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 15.45 KB | None | 0 0
  1. unit Unit_VideoPlayerTest;
  2.  
  3. interface
  4. uses Winapi.Windows, Winapi.Messages, Winapi.DirectShow9, Winapi.ActiveX,
  5. System.SysUtils, Vcl.Graphics;
  6.  
  7.  
  8. type
  9.   PThunk = ^TThunk;
  10.   TThunk = packed record
  11.     POPEDX: Byte;
  12.     MOVEAX: Byte;
  13.     SelfPtr: Pointer;
  14.     PUSHEAX: Byte;
  15.     PUSHEDX: Byte;
  16.     JMP: Byte;
  17.     JmpOffset: Integer;
  18.   end;
  19. //type
  20.   TCallbackThunk = class(TObject)
  21.   private
  22.     FCallAddress: Pointer;
  23.     FProcPtr: Pointer;
  24.     FSavedFlag: LongWord;
  25.     FSelfPtr: Pointer;
  26.     function GetCallAddress: Pointer;
  27.   public
  28.     constructor Create(pSelf, pProc: Pointer);
  29.     destructor Destroy; override;
  30.     procedure Clear;
  31.     property CallAddress: Pointer read GetCallAddress;
  32.   end;
  33.  
  34.  
  35. type
  36.   TVideoPlayer = class(TObject, ISampleGrabberCB)
  37.     private
  38.       nLeft : Integer;
  39.       nTop : Integer;
  40.       nWidth : Integer;
  41.       nHeight : Integer;
  42.  
  43.       hMainWindow : HWND;
  44.       hVideoOutputWindow : HWND;
  45.       hRootWindow : HWND;
  46.       hVideoOutputContainerWindow : HWND;
  47.  
  48.       fBrushRootWindow : HBRUSH;
  49.  
  50.  
  51.       VideoWidth, VideoHeight : Integer;
  52.       fThunkRoot : TCallbackThunk;
  53.       fOldRootProc : LongInt;
  54.       fCallbackActive : Boolean;
  55.       fFileName :  string;
  56.       procedure SetPositionLeft(const x : Integer);
  57.       procedure SetPositionWidth(const w : Integer);
  58.       procedure SetPositionHeight(const h : Integer);
  59.       procedure SetPositionTop(const y : Integer);
  60.     public
  61.       pGraphBuilder : IGraphBuilder;
  62.       pCaptureGraphBuilder : ICaptureGraphBuilder2;
  63.       pFilterGraph : IFilterGraph;
  64.       pVideoWindow : IVideoWindow;
  65.       pMediaControl : IMediaControl;
  66.       pMediaPosition : IMediaPosition;
  67.       pMediaEvent : IMediaEventEx;
  68.       pBasicVideo : IBasicVideo;
  69.  
  70.       fAudioDecoder : IBaseFilter;
  71.       pBasicAudio : IBasicAudio;
  72.  
  73.       fSource : IBaseFilter;
  74.       pSource : IFileSourceFilter;
  75.       fSplitter : IBaseFilter;
  76.       pSampleGrabberVideo : ISampleGrabber;
  77.       fSampleGrabberVideo : IBaseFilter;
  78.       fVideoDecoder : IBaseFilter;
  79.       fAudioRenderer : IBaseFilter;
  80.       fVideoRenderer : IBaseFilter;
  81.       constructor Create(x,y : Integer; aOwner, aMainForm : HWND);
  82.       destructor Destroy; override;
  83.       function PlayerRootProc(wnd:HWND; Msg : uint; Wpar:Wparam; Lpar:LPARAM):Lresult; stdcall;
  84.  
  85.       function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  86.       function _AddRef: Integer; stdcall;
  87.       function _Release: Integer; stdcall;
  88.       function SampleCB(SampleTime: Double; pSample: IMediaSample): HResult; stdcall;
  89.       function BufferCB(SampleTime: Double; pBuffer: PByte; BufferLen: longint): HResult; stdcall;
  90.  
  91.       procedure Clear;
  92.       function BuildGraph(fn : string) : HRESULT;
  93.       function Play : HRESULT;
  94.       procedure Redraw;
  95.       procedure SetPlayerPositionSize(const x,y,w,h : Integer);
  96.       property Left: Integer read nLeft write SetPositionLeft;
  97.       property Top: Integer read nTop write SetPositionTop;
  98.       property Width: Integer read nWidth write SetPositionWidth;
  99.       property Height: Integer read nHeight write SetPositionHeight;
  100.       property Screen: HWND read hVideoOutputWindow;
  101.       property Handle: HWND read hRootWindow;
  102.       property FileName : string read fFileName write fFileName;
  103.       property UseCallback : Boolean read fCallbackActive write fCallbackActive;
  104.   end;
  105.  
  106. const
  107.   CLSID_FfdshowVideoDecoder : TGUID = '{04FE9017-F873-410E-871E-AB91661A4EF7}';
  108.   CLSID_ffdshowAudioDecoder : TGUID = '{0F40E1E5-4F79-4988-B1A9-CC98794E6B55}';
  109.   CLSID_DivX_DecoderFilter : TGUID = '{78766964-0000-0010-8000-00AA00389B71}';
  110.   CLSID_DivX_H264_Decoder : TGUID = '{6F513D27-97C3-453C-87FE-B24AE50B1601}';
  111.   CLSID_DivX_AAC_Decoder : TGUID = '{2CCC9657-58A9-41AC-AA39-451202B98FAF}';
  112.   CLSID_XviD_VideoDecoder : TGUID = '{64697678-0000-0010-8000-00AA00389B71}';
  113.   CLSID_MPC_VideoDecoder : TGUID = '{008BAC12-FBAF-497B-9670-BC6F6FBAE2C4}';
  114.   CLSID_haaliMediaSplitter : TGUID = '{55DA30FC-F16B-49FC-BAA5-AE59FC65F82D}';
  115.   CLSID_HaaliVideoRenderer : TGUID = '{760A8F35-97E7-479D-AAF5-DA9EFF95D751}';
  116.   CLSID_AC3ParserFilter : TGUID = '{280A3020-86CF-11D1-ABE6-00A0C905F375}';
  117.   CLSID_AC3Filter : TGUID = '{A753A1EC-973E-4718-AF8E-A3F554D45C44}';
  118.   CLSID_ElecardMPEGDemultiplexer : TGUID = '{136DCBF5-3874-4B70-AE3E-15997D6334F7}';
  119.   CLSID_MPEG2_Splitter : TGUID = '{3AE86B20-7BE8-11D1-ABE6-00A0C905F375}';
  120.   CLSID_MicrosoftDTVDVDVideoDecoder : TGUID = '{212690FB-83E5-4526-8FD7-74478B7939CD}';
  121.   CLSID_LAV_VideoDecoder : TGUID = '{EE30215D-164F-4A92-A4EB-9D4C13390F9F}';
  122.   CLSID_LAV_AudioDecoder : TGUID = '{E8E73B6B-4CB3-44A4-BE99-4F7BCB96E491}';
  123.   //CLSID_VideoMixingRenderer9 : TGUID = '{51B4ABF3-748F-4E3B-A276-C828330E926A}';
  124.   CLSID_VideoMixingRenderer7 : TGUID = '{B87BEB7B-8D29-423F-AE4D-6582C10175AC}';
  125.   CLSID_ColorSpaceConverter : TGUID = '{1643E180-90F5-11CE-97D5-00AA0055595A}';
  126.   CLSID_HaaliMediaSplitterAR : TGUID = '{564FD788-86C9-4444-971E-CC4A243DA150}';
  127.   CLSID_LAV_Splitter : TGUID = '{171252A0-8820-4AFE-9DF8-5C92B2D66B04}';
  128.   CLSID_FileSourceAsync : TGUID = '{E436EBB5-524F-11CE-9F53-0020AF0BA770}';
  129.   CLSID_WM_ASF_Reader : TGUID = '{187463A0-5BB7-11D3-ACBE-0080C75E246E}';
  130.   CLSID_WMVideoDecoderDMO : TGUID = '{94297043-BD82-4DFD-B0DE-8177739C6D20}';
  131.   //CLSID_MicrosoftMPEG2_Demultplexer : TGUID = '{AFB6C280-2C41-11D3-8A60-0000F81E0E4A}';
  132.   CLSID_BandisoftMPEG1VideoDecoder : tguid = '{89C4B786-A490-4A3E-AA70-E6A8C61D3689}';
  133.   CLSID_BandisoftMPEG1AudioDecoder : tguid = '{E2E7539A-CECF-4A6A-B187-939943ECEF05}';
  134.   CLSID_MPC_MP4_Splitter : TGUID = '{61F47056-E400-43D3-AF1E-AB7DFFD4C4AD}';
  135.  
  136.   MEDIASUBTYPE_AVC1 : tguid = '{31435641-0000-0010-8000-00AA00389B71}';
  137.  
  138.  
  139.  
  140.   WM_DS_MESSAGE = WM_USER + 4;
  141.  
  142. implementation
  143.  
  144. constructor TCallbackThunk.Create(pSelf, pProc: Pointer);
  145. begin
  146.   FCallAddress := nil;
  147.   FSelfPtr := pSelf;
  148.   FProcPtr := pProc;
  149. end;
  150.  
  151. destructor TCallbackThunk.Destroy;
  152. begin
  153.   Clear;
  154.   inherited Destroy;
  155. end;
  156.  
  157. procedure TCallbackThunk.Clear;
  158. var
  159.   SaveFlag: DWORD;
  160. begin
  161.   if @FCallAddress <> nil then begin
  162.     VirtualProtect(PThunk(@FCallAddress), SizeOf(TThunk),
  163.       FSavedFlag, @SaveFlag);
  164.     VirtualFree(FCallAddress, 0, MEM_RELEASE);
  165.     FCallAddress := nil;
  166.     FSavedFlag := 0;
  167.   end;
  168. end;
  169.  
  170. function TCallbackThunk.GetCallAddress: Pointer;
  171. begin
  172.   if FCallAddress = nil then begin
  173.     FCallAddress := VirtualAlloc(nil, SizeOf(TThunk), MEM_COMMIT, PAGE_READWRITE);
  174.     with PThunk(FCallAddress)^ do begin
  175.       POPEDX := $5A;
  176.       MOVEAX := $B8;
  177.       SelfPtr := FSelfPtr;
  178.       PUSHEAX := $50;
  179.       PUSHEDX := $52;
  180.       JMP := $E9;
  181.       JmpOffset := Integer(FProcPtr) - Integer(@JMP) - 5;
  182.     end;
  183.     if not VirtualProtect(FCallAddress, SizeOf(TThunk), PAGE_EXECUTE_READ,
  184.        @FSavedFlag) then begin
  185.       FCallAddress := nil;
  186. //      raise Exception.Create('Cannot get call address');
  187.       MessageBox(0,'','',0);
  188.     end;
  189.   end;
  190.   Result := FCallAddress;
  191. end;
  192.  
  193.  
  194.  
  195. function TVideoPlayer.PlayerRootProc(wnd:HWND; Msg : uint; Wpar:Wparam; Lpar:LPARAM):Lresult; stdcall;
  196. var
  197.   n : Integer;
  198.   l1,l2 : LONG_PTR;
  199. Begin
  200.   case msg of
  201.  
  202.     WM_DS_MESSAGE:
  203.     begin
  204.       while pMediaEvent.GetEvent(n, L1, l2, 1) = S_OK do
  205.       begin
  206.         if n = EC_COMPLETE then
  207.         begin
  208.           pMediaPosition.put_CurrentPosition(0);
  209.         end;
  210.         pMediaEvent.FreeEventParams(n, l1, l2);
  211.       end;
  212.     end;
  213.  
  214.   else Result := callWindowProc(Pointer(fOldRootProc),wnd,msg,wpar,lpar);
  215.   end;
  216. End;
  217.  
  218. function TVideoPlayer.SampleCB(SampleTime: Double; pSample: IMediaSample): HRESULT;
  219. begin
  220.   Result := S_OK;
  221. end;
  222.  
  223.  
  224. function TVideoPlayer.BufferCB(SampleTime: Double; pBuffer: PByte; BufferLen: Integer) : HRESULT;
  225. var
  226.   mt : TAMMediaType;
  227.   bmpInfo : TBitmapInfo;
  228.   vih : TVideoInfoHeader;
  229.   bmp : TBitmap;
  230.   HBMP : HBITMAP;
  231.   tmp : array of Byte;
  232.   buffer : Pointer;
  233.   dc : HDC;
  234.   r : TRect;
  235. begin
  236.     pSampleGrabberVideo.GetConnectedMediaType(mt);
  237.     vih := tvideoinfoheader(mt.pbFormat^);
  238.     ZeroMemory(@bmpinfo,SizeOf(tbitmapinfo));
  239.     CopyMemory(@bmpinfo.bmiheader,@vih.bmiheader,SizeOf(tbitmapinfoheader));
  240.     Buffer := nil;
  241.     hbmp := CreateDIBSection(0,BMPInfo,DIB_PAL_COLORS, BUFFER,0,0);
  242.     if (HBMP = 0) or (HBMP = ERROR_INVALID_PARAMETER) then
  243.     begin
  244. //      ShowMessage('error');
  245.       Exit;
  246.     end;
  247.     bmp := TBitmap.Create;
  248.     bmp.Handle := HBMP;
  249.     VideoWidth := bmp.Width;
  250.     videoHeight := bmp.Height;
  251.     SetLength(tmp,BufferLen);
  252.     CopyMemory(buffer,pBuffer,mt.lSampleSize);
  253.  
  254.     bmp.Canvas.Pen.Width := 4;
  255.     bmp.Canvas.Pen.Color := RGB(255,0,0);
  256.     bmp.Canvas.LineTo(bmp.Width,bmp.Height);
  257.     bmp.Canvas.MoveTo(0,bmp.Height);
  258.     bmp.Canvas.LineTo(bmp.Width,0);
  259.  
  260.  
  261.     GetClientRect(Screen,r);
  262.     dc := GetDC(Screen);
  263.     SetStretchBltMode(dc,COLORONCOLOR);
  264.     StretchBlt(dc,0,0,r.Right,r.Bottom, bmp.Canvas.Handle,0,0, bmp.Width,bmp.Height,SRCCOPY);
  265.     ReleaseDC(Screen,dc);
  266.  
  267.  
  268.     MoFreeMediaType(@mt);
  269.     buffer := nil;
  270.     bmp.Free;
  271.   Result := S_OK;
  272. end;
  273.  
  274. function TVideoPlayer.QueryInterface(const IID: TGUID; out Obj) : Integer;
  275. begin
  276.   Result := 0;
  277. end;
  278.  
  279. function TVideoPlayer._AddRef : Integer;
  280. begin
  281.   Result := 0;
  282. end;
  283.  
  284. function TVideoPlayer._Release;
  285. begin
  286.   Result := 0;
  287. end;
  288.  
  289. constructor TVideoPlayer.Create(x: Integer; y: Integer; aOwner: HWND; aMainForm: HWND);
  290. begin
  291.   inherited Create;
  292.   nLeft := x;
  293.   nTop := y;
  294.   nWidth := 300;
  295.   nHeight := 300;
  296.   hRootWindow := CreateWindow('static','',
  297.                                 WS_CHILD or WS_VISIBLE or WS_CLIPSIBLINGS or
  298.                                 WS_CLIPCHILDREN or SS_NOTIFY or SS_BITMAP,
  299.                                 x,y,300,300,
  300.                                 aOwner,0,HInstance,nil);
  301.   hVideoOutputContainerWindow := CreateWindow('static','',
  302.                                 WS_CHILD or WS_VISIBLE or SS_NOTIFY or
  303.                                 SS_BITMAP or WS_CLIPCHILDREN,
  304.                                 0,0,200,200,
  305.                                 hRootWindow,0,HInstance,nil);
  306.   hVideoOutputWindow := CreateWindow('static','',
  307.                                 WS_CHILD or WS_VISIBLE or SS_NOTIFY or SS_BITMAP,
  308.                                 0,0,200,200,
  309.                                 hVideoOutputContainerWindow,0,HInstance,nil);
  310.   fThunkRoot := TCallbackThunk.Create(Self,@TVideoPlayer.PlayerRootProc);
  311.   fOldRootProc := SetWindowLong(hRootWindow,GWL_WNDPROC,LongInt(fThunkRoot.CallAddress));
  312.  
  313.   fBrushRootWindow := CreateSolidBrush(RGB(0,255,0));
  314. end;
  315.  
  316. destructor TVideoPlayer.Destroy;
  317. begin
  318.   Clear;
  319.   DestroyWindow(hVideoOutputWindow);
  320.   DestroyWindow(hVideoOutputContainerWindow);
  321.   DestroyWindow(hRootWindow);
  322.  
  323.   DeleteObject(fBrushRootWindow);
  324.  
  325.   fThunkRoot.Free;
  326.  
  327.   inherited;
  328. end;
  329.  
  330. procedure TVideoPlayer.Clear;
  331. begin
  332.   if Assigned(pMediaControl) then
  333.   pMediaControl.Stop;
  334.  
  335.   fVideoRenderer := nil;
  336.   fVideoDecoder := nil;
  337.   pVideoWindow := nil;
  338. //  pVideoGrabber.SetCallback(nil,0);
  339.   pSampleGrabberVideo := nil;
  340.   fSampleGrabberVideo := nil;
  341.   fAudioDecoder := nil;
  342.   fSplitter := nil;
  343.   pSource := nil;
  344.   fSource := nil;
  345.   pMediaControl := nil;
  346.   pMediaPosition := nil;
  347.   pGraphBuilder := nil;
  348.   pCaptureGraphBuilder := nil;
  349. end;
  350.  
  351. function TVideoPlayer.BuildGraph(fn: string) : HRESULT;
  352. var
  353.   mtv : AM_MEDIA_TYPE;
  354.   r : TRect;
  355. begin
  356.   Result := CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER ,
  357.                            IID_IGraphBuilder, pGraphBuilder);
  358.   Result := CoCreateInstance(CLSID_CaptureGraphBuilder2, NIL,
  359.                           CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
  360.                          pCaptureGraphBuilder);
  361.   pCaptureGraphBuilder.SetFiltergraph(pGraphBuilder);
  362.  
  363.   Result := pGraphBuilder.AddSourceFilter(StringToOleStr(fn),'source', fSource);
  364.  
  365.  
  366.  
  367.   Result := coCreateInstance(CLSID_FfdshowVideoDecoder, nil,
  368.                                CLSCTX_INPROC_SERVER,
  369.                                IID_IBaseFilter, FVIDEODECODER);
  370.   pGraphBuilder.AddFilter(fVideoDecoder, 'ffdshow video');
  371.  
  372.  
  373.   Result := coCreateInstance(CLSID_SampleGrabber, nil,
  374.                                CLSCTX_INPROC_SERVER,
  375.                                IID_ISampleGrabber, pSampleGrabberVideo);
  376.  
  377.   ZeroMemory(@mtv, SizeOf(mtv));
  378.   mtv.majortype := MEDIATYPE_Video;
  379.   mtv.subtype := MEDIASUBTYPE_RGB32;
  380.   mtv.formattype := FORMAT_VideoInfo;
  381.   pSampleGrabberVideo.SetMediaType(mtv);
  382.   pSampleGrabberVideo.SetOneShot(False);
  383.   pSampleGrabberVideo.SetBufferSamples(True);
  384.  
  385.   if UseCallback then
  386.   pSampleGrabberVideo.setCallback(Self,1);
  387.  
  388.   pSampleGrabberVideo.QueryInterface(IID_IBaseFilter, fSAMPLEGRABBERVIDEO);
  389.   pGraphBuilder.AddFilter(fSampleGrabberVideo, 'video grabber');
  390.  
  391.  
  392.   if UseCallback then
  393.   begin
  394.     Result := coCreateInstance(CLSID_NullRenderer, nil,
  395.                                CLSCTX_INPROC_SERVER,
  396.                                IID_IBaseFilter, fVideoRenderer);
  397.     pGraphBuilder.AddFilter(fVideoRenderer, 'null video renderer');
  398.  
  399.   end else
  400.   begin
  401.     Result := coCreateInstance(CLSID_VideoRendererDefault, nil,
  402.                                CLSCTX_INPROC_SERVER,
  403.                                IID_IBaseFilter, fVideoRenderer);
  404.     pGraphBuilder.AddFilter(fVideoRenderer, 'video renderer');
  405.  
  406.   end;
  407.  
  408.   Result := pCaptureGraphBuilder.RenderStream(nil,@mediatype_video,
  409.                              fSource, fVideoDecoder,fSampleGrabberVideo);
  410.   Result := pCaptureGraphBuilder.RenderStream(nil,@mediatype_video,
  411.                              fSampleGrabberVideo, nil, fVideoRenderer);
  412.  
  413.   if Result = S_OK then
  414.   begin
  415.     pGraphBuilder.QueryInterface(IID_IVideoWindow, pvideowindow);
  416.     pVideoWindow.put_Owner(Screen);
  417.     pVideoWindow.put_WindowStyle(WS_CHILD or WS_CLIPSIBLINGS);
  418.     GetClientRect(Screen,r);
  419.     pVideoWindow.SetWindowPosition(0,0, r.Right,r.Bottom);
  420.     pGraphBuilder.QueryInterface(IID_IMediaPosition,pmediaposition);
  421.     pMediaPosition.put_CurrentPosition(35);
  422.     pGraphBuilder.QueryInterface(IID_IMediaControl,pMediaControl);
  423.     pMediaControl.Run;
  424.   end else
  425.   Clear;
  426.  
  427. end;
  428.  
  429. function TVideoPlayer.Play : HRESULT;
  430. begin
  431.   Result := S_OK;
  432.   if Assigned(pMediaControl) then
  433.   begin
  434.     Result := pMediaControl.Run;
  435.   end else
  436.   begin
  437.     if (FileName<>'') and (FileExists(FileName)) then
  438.     begin
  439.       Clear;
  440.       if BuildGraph(FileName) = S_OK then
  441.       Result := pMediaControl.Run;
  442.     end;
  443.   end;
  444. end;
  445.  
  446. procedure TVideoPlayer.Redraw;
  447. var
  448.   r : TRect;
  449.   dc : HDC;
  450. begin
  451.   GetClientRect(hRootWindow,r);
  452.   dc := GetDC(hRootWindow);
  453.   FillRect(dc,r,fBrushRootWindow);
  454.   ReleaseDC(hRootWindow,dc);
  455. end;
  456.  
  457. procedure TVideoPlayer.SetPlayerPositionSize(const x,y,w,h : Integer);
  458. begin
  459.   nLeft := x;
  460.   nTop := y;
  461.   nWidth := w;
  462.   nHeight := h;
  463.   SetWindowPos(hRootWindow,0,x,y,w,h, SWP_NOZORDER or SWP_NOACTIVATE);
  464.   Redraw;
  465. end;
  466.  
  467. procedure TVideoPlayer.SetPositionLeft(const x : Integer);
  468. begin
  469.   if nLeft <> x then
  470.   begin
  471.     nLeft := x;
  472.     SetPlayerPositionSize(x,nTop,nWidth,nHeight);
  473.   end;
  474. end;
  475.  
  476. procedure TVideoPlayer.SetPositionTop(const y : Integer);
  477. begin
  478.   if nTop <> y then
  479.   begin
  480.     nTop := y;
  481.     SetPlayerPositionSize(nLeft,nTop,nWidth,nHeight);
  482.   end;
  483. end;
  484.  
  485. procedure TVideoPlayer.SetPositionWidth(const w : Integer);
  486. begin
  487.   if nWidth <> w then
  488.   begin
  489.     nWidth := w;
  490.     SetPlayerPositionSize(nLeft,nTop,W,nHeight);
  491.   end;
  492. end;
  493.  
  494. procedure TVideoPlayer.SetPositionHeight(const h : Integer);
  495. begin
  496.   if nHeight <> h then
  497.   begin
  498.     nHeight := h;
  499.     SetPlayerPositionSize(nLeft,nTop,nWidth,H);
  500.   end;
  501. end;
  502.  
  503. end.
Add Comment
Please, Sign In to add comment