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

Delphi控件源码

开发平台:

Delphi

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