main.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:12k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit main;
  2. {$IFDEF VER150}
  3.   {$WARN UNSAFE_CODE OFF}
  4.   {$WARN UNSAFE_TYPE OFF}
  5.   {$WARN UNSAFE_CAST OFF}
  6. {$ENDIF}
  7. interface
  8. uses BaseClass, ActiveX, DirectShow9, Windows, DSUTil, PropEdit;
  9. const
  10.   CLSID_NullInPlace        : TGUID = '{52b63860-dc93-11ce-a099-00aa00479a58}';
  11.   IID_INullIPP             : TGUID = '{43D849C0-2FE8-11cf-BCB1-444553540000}';
  12. type
  13.   INullIPP = interface(IunKnown)
  14.   ['{0952C77F-2EFF-427B-ACAD-F295ADE6F1E7}']
  15.     function put_MediaType(mt: PAMMediaType): HRESULT; stdcall;      // the media type selected
  16.     function get_MediaType(out mt: TAMMediaType): HRESULT; stdcall;  // the media type selected
  17.     function get_IPin(out Pin: IPin): HRESULT; stdcall;                // the source pin
  18.     function get_State(out State: TFilterState): HRESULT; stdcall;    // the filter state
  19.   end;
  20. const
  21.   SudPinTypes : TRegPinTypes =
  22.     (clsMajorType: @MEDIATYPE_NULL;
  23.      clsMinorType: @MEDIASUBTYPE_NULL);
  24.   SudPins : array[0..1] of TRegFilterPins =
  25.     ((strName: 'Input'; bRendered: FALSE; bOutput: FALSE; bZero: FALSE; bMany: FALSE; oFilter: nil; strConnectsToPin: 'Output'; nMediaTypes: 1; lpMediaType: @SudPinTypes),
  26.      (strName: 'Output'; bRendered: FALSE; bOutput: TRUE; bZero: FALSE; bMany: FALSE; oFilter: nil; strConnectsToPin: 'Input'; nMediaTypes: 1; lpMediaType: @SudPinTypes));
  27. type
  28.   TNullInPlaceInputPin = class(TBCTransInPlaceInputPin)
  29.   public
  30.     constructor Create(ObjectName: string; TransInPlaceFilter: TBCTransInPlaceFilter;
  31.       out hr: HRESULT; Name: WideString);
  32.     function CheckMediaType(mt: PAMMediaType): HRESULT; override;
  33.   end;
  34.   TNullInPlaceOutputPin = class(TBCTransInPlaceOutputPin)
  35.   public
  36.     constructor Create(ObjectName: string; TransInPlaceFilter: TBCTransInPlaceFilter;
  37.       out hr: HRESULT; Name: WideString);
  38.     function CheckMediaType(mt: PAMMediaType): HRESULT; override;
  39.   end;
  40. var
  41.     // If there are multiple instances of this filter active, it's
  42.     // useful for debug messages etc. to know which one this is.
  43.   InstanceCount: integer = 0;
  44. type
  45.   TNullInPlace = class(TBCTransInPlaceFilter, INullIPP, ISpecifyPropertyPages)
  46.     FThisInstance: integer;
  47.     FPreferred: TAMMediaType; // Media type chosen from property sheet
  48.     NullIPLock: TBCCritSec;     // To serialise access.
  49.   public
  50.      function GetPin(n: integer): TBCBasePin; override;
  51.      function CheckInputType(mtIn: PAMMediaType): HRESULT; override;
  52.     function put_MediaType(mt: PAMMediaType): HRESULT; stdcall;
  53.     function get_MediaType(out mt: TAMMediaType): HRESULT; stdcall;
  54.     function get_IPin(out Pin: IPin): HRESULT; stdcall;
  55.     function get_State(out State: TFilterState): HRESULT; stdcall;          //
  56.     // --- ISpecifyPropertyPages ---
  57.     function GetPages(out pages: TCAGUID): HResult; stdcall;
  58.     constructor Create(ObjName: string; unk: IUnKnown; out hr: HRESULT);
  59.     constructor CreateFromFactory(Factory: TBCClassFactory; const Controller: IUnknown); override;
  60.     destructor Destroy; override;
  61.     // Overrides the PURE virtual Transform of CTransInPlaceFilter base class
  62.     // This is where the "real work" is done.
  63.     function Transform(Sample: IMediaSample): HRESULT; override;
  64.   end;
  65. implementation
  66. { TNullInPlaceInputPin }
  67. // CheckMediaType
  68. //
  69. // Override CTransInPlaceInputPin method.
  70. // If we have been given a preferred media type from the property sheet
  71. // then only accept a type that is exactly that.
  72. // else if there is nothing downstream, then accept anything
  73. // else if there is a downstream connection then first check to see if
  74. // the subtype (and implicitly the major type) are different from the downstream
  75. // connection and if they are different, fail them
  76. // else ask the downstream input pin if the type (i.e. all details of it)
  77. // are acceptable and take that as our answer.
  78. function TNullInPlaceInputPin.CheckMediaType(mt: PAMMediaType): HRESULT;
  79. var
  80.   pmt: PAMMediaType;
  81. begin
  82. {$IFDEF DEBUG}
  83.    DbgLog(self, 'Input type proposed');
  84. {$ENDIF}
  85.     pmt := @TNullInPlace(FTIPFilter).FPreferred;
  86.     if not TBCMediaType(pmt).IsValid then
  87.       begin
  88.         if TNullInPlace(FTIPFilter).Output.IsConnected then
  89.           begin
  90.             //  We used to check here if the subtype of the proposed type
  91.             //  matched the subtype of the type on the output pin
  92.             //  but this broke as follows:
  93.             //
  94.             //  Renderering the output pin of a CODEC we picked up
  95.             //  2 NULLIPs already in the graph:
  96.             //
  97.             //  Subtypes      Y41P       Y41P       RGB565
  98.             //  Filters  CODEC---->NULLIP---->NULLIP------>RENDERER
  99.             //
  100.             //  Each NULLIP has scheduled a reconnect at this point
  101.             //  and the reconnect on the first connection happens
  102.             //  first:
  103.             //
  104.             //  Subtypes                 Y41P       RGB565
  105.             //  Filters  CODEC     NULLIP---->NULLIP------>RENDERER
  106.             //
  107.             //  In trying to (re)connect the CODEC to the first NULLIP
  108.             //  we first propose (say) Y41P and the first NULLIP
  109.             //  checks that Y41P is the same as its output type
  110.             //  so the call gets passed to the QueryAccept of
  111.             //  the second NULLIP.  The second NULLIP rejected the
  112.             //  call because the subtype on its output pin is not
  113.             //  RGB565.  In a similar way the first NULLIP
  114.             //  rejected Y41P.
  115.             //
  116.             //  By removing this optimization (checking the
  117.             //  subtype before passing the call on) we avoided
  118.             //  the problem.
  119.             result :=  TNullInPlace(FTIPFilter).Output.GetConnected.QueryAccept(mt^);
  120.             exit;
  121.         end;
  122.          result := S_OK;
  123.          exit;
  124.       end
  125.     else
  126.         if TBCMediaType(pmt).Equal(mt) then
  127.           begin
  128.             result := S_OK;
  129.             exit;
  130.           end
  131.         else
  132.           result := VFW_E_TYPE_NOT_ACCEPTED;
  133. end;
  134. constructor TNullInPlaceInputPin.Create(ObjectName: string;
  135.   TransInPlaceFilter: TBCTransInPlaceFilter; out hr: HRESULT;
  136.   Name: WideString);
  137. begin
  138.   inherited Create(ObjectName, TransInPlaceFilter, hr, Name);
  139. end;
  140. { TNullInPlaceOutputPin }
  141. function TNullInPlaceOutputPin.CheckMediaType(mt: PAMMediaType): HRESULT;
  142. var pmt: PAMMediaType;
  143. begin
  144.   pmt := @TNullInPlace(FTIPFilter).FPreferred;
  145.   if not TBCMediaType(pmt).IsValid then
  146.     begin
  147.       result := inherited CheckMediaType(mt);
  148.       exit;
  149.     end
  150.   else
  151.     if TBCMediaType(pmt).Equal(mt) then
  152.       begin
  153.         result := S_OK;
  154.         exit;
  155.       end
  156.     else
  157.       result := VFW_E_TYPE_NOT_ACCEPTED;
  158. end;
  159. constructor TNullInPlaceOutputPin.Create(ObjectName: string;
  160.   TransInPlaceFilter: TBCTransInPlaceFilter; out hr: HRESULT;
  161.   Name: WideString);
  162. begin
  163.   inherited Create(ObjectName, TransInPlaceFilter, hr, Name);
  164. end;
  165. { TNullInPlace }
  166. function TNullInPlace.CheckInputType(mtIn: PAMMediaType): HRESULT;
  167. begin
  168.   result := S_OK;
  169. end;
  170. constructor TNullInPlace.Create(ObjName: string; unk: IInterface;
  171.   out hr: HRESULT);
  172. var pmt: PAMMediaType;
  173. begin
  174.   inherited Create(ObjName, unk, CLSID_NullInPlace, hr);
  175.   FThisInstance := InterlockedIncrement(InstanceCount);
  176.   pmt := @FPreferred;
  177.   TBCMediaType(pmt).InitMediaType;
  178.   NullIPLock := TBCCritSec.Create;
  179. {$IFDEF DEBUG}
  180.   DbgLog(self, 'TNullInPlace.Create');
  181. {$ENDIF}
  182. end;
  183. constructor TNullInPlace.CreateFromFactory(Factory: TBCClassFactory;
  184.   const Controller: IInterface);
  185. var hr: HRESULT;
  186. begin
  187.   Create(Factory.Name, Controller, hr);
  188. end;
  189. destructor TNullInPlace.Destroy;
  190. begin
  191.   NullIPLock.Free;
  192.   inherited;
  193. end;
  194. function TNullInPlace.get_IPin(out Pin: IPin): HRESULT;
  195. begin
  196.   result := S_OK;
  197.   NullIPLock.Lock;
  198.   try
  199.     if (Input = nil) then
  200.       begin
  201.         Pin := nil;
  202.         exit;
  203.       end;
  204.     if not Input.IsConnected then
  205.          Pin := nil
  206.     else Pin := Input.GetConnected;
  207.   finally
  208.     NullIPLock.UnLock;
  209.   end;
  210. end;
  211. function TNullInPlace.get_MediaType(out mt: TAMMediaType): HRESULT;
  212. begin
  213.   NullIPLock.Lock;
  214.   try
  215.     mt := FPreferred;
  216.     result := NOERROR ;
  217.   finally
  218.     NullIPLock.UnLock;
  219.   end;
  220. end;
  221. function TNullInPlace.get_State(out State: TFilterState): HRESULT;
  222. begin
  223.   NullIPLock.Lock;
  224.   try
  225.     State := self.State;
  226.     result := NOERROR ;
  227.   finally
  228.     NullIPLock.UnLock;
  229.   end;
  230. end;
  231. function TNullInPlace.GetPages(out pages: TCAGUID): HResult;
  232. begin
  233.     Pages.cElems := 1;
  234.     Pages.pElems := CoTaskMemAlloc(sizeof(TGUID));
  235.     if (Pages.pElems = nil) then
  236.       begin
  237.         result := E_OUTOFMEMORY;
  238.         exit;
  239.       end;
  240.    Pages.pElems^[0] := CLSID_NullIPPropertyPage;
  241.    result := NOERROR;
  242. end;
  243. function TNullInPlace.GetPin(n: integer): TBCBasePin;
  244. var hr: HRESULT;
  245. begin
  246.   // Create the single input pin and the single output pin
  247.   // If anything fails, fail the whole lot and clean up.
  248.   if (Input = nil) or (Output = nil) then
  249.     begin
  250.       hr := S_OK;
  251.       Input := TNullInPlaceInputPin.Create('Null input pin', self, hr, 'Input');
  252.       // a failed return code should delete the object
  253.       if FAILED(hr) or (Input = nil) then
  254.         begin
  255.           if (Input <> nil) then input.Free;
  256.           input := nil;
  257.           result := nil;
  258.           exit;
  259.         end;
  260.       Output := TNullInPlaceOutputPin.Create('Null output pin', self, hr, 'Output');
  261.       // failed return codes cause both objects to be deleted
  262.       if FAILED(hr) or (Output = nil) then
  263.         begin
  264.           if (Input  <> nil) then input.Free;
  265.           if (Output <> nil) then Output.Free;
  266.           Input  := nil;
  267.           Output := nil;
  268.           result := nil;
  269.           exit;
  270.         end;
  271.     end;
  272.   // Find which pin is required
  273.   case n of
  274.     0: result := Input;
  275.     1: result := Output;
  276.   else
  277.     result := nil;
  278.   end;
  279. end;
  280. function TNullInPlace.put_MediaType(mt: PAMMediaType): HRESULT;
  281. var
  282.   Pin: IPin;
  283.   pmt: PAMMediaType;
  284. begin
  285.   NullIPLock.Lock;
  286.   try
  287.     // if the state of the graph is running, fail the call.
  288.     if (State = State_Running) then
  289.       begin
  290.         result := E_UNEXPECTED;
  291.         exit;
  292.       end;
  293.     // check the source and sink filters like this media type
  294.     pmt := @FPreferred;
  295.     if (mt = nil) then
  296.         TBCMediaType(pmt).InitMediaType
  297.     else
  298.       begin
  299.         Pin := Input.GetConnected;
  300.         if (Pin <> nil) then
  301.         begin
  302.           if (Pin.QueryAccept(mt^) <> NOERROR) then
  303.           begin
  304.             MessageBox(0,PChar('Upstream filter cannot provide this type'),
  305.                          PChar('Format Selection'),
  306.                          MB_OK or MB_ICONEXCLAMATION);
  307.             result := VFW_E_TYPE_NOT_ACCEPTED;
  308.             exit;
  309.           end;
  310.         end;
  311.         Pin := Output.GetConnected;
  312.         if (Pin <> nil) then
  313.         begin
  314.           if (Pin.QueryAccept(mt^) <> NOERROR) then
  315.           begin
  316.             MessageBox(0, PChar('Downstream filter cannot accept this type'),
  317.                           PChar('Format Selection'),
  318.                           MB_OK or MB_ICONEXCLAMATION);
  319.             result := VFW_E_TYPE_NOT_ACCEPTED;
  320.             exit;
  321.           end;
  322.         end;
  323.         FPreferred := mt^;
  324.      end;
  325.     // force reconnect of input if the media type of connection does not match.
  326.     if (Input.IsConnected) then
  327.     begin
  328.       pmt := Input.CurrentMediaType.MediaType;
  329.       if not TBCMediaType(pmt).Equal(@FPreferred) then
  330.         Graph.Reconnect(Input);
  331.     end;
  332.     result := NOERROR ;
  333.   finally
  334.     NullIPLock.Unlock;
  335.   end;
  336. end;
  337. function TNullInPlace.Transform(Sample: IMediaSample): HRESULT;
  338. begin
  339.   result := S_OK;
  340. end;
  341. initialization
  342.   TBCClassFactory.CreateFilter(TNullInPlace, 'Null-In-Place', CLSID_NullInPlace,
  343.     CLSID_LegacyAmFilterCategory, MERIT_DO_NOT_USE, 2, @SudPins);
  344. end.