0

I want to write my own DirectShow filter to pull out packets of information for my own purposes. To do this, I used the guide to creating filters.

I did steps 1 to 5, and am stuck at step 6: failed to implement CreateInstance(). Can't instantiate the class because the MSDN example doesn't pass parameters, but code in Pascal requires (ObjectName: string; unk: IUnKnown; const clsid: TGUID). I used regsvr32, unfortunately I don’t know how to connect my DLL and I can’t think of it. The DSFMgr program also does not see my filter.

I read how filters are connected, tried to implement various searches, it's useless. Tried to connect manually via CLSID. Everything is useless. I know the answer is somewhere on the surface, but I don't see it. I can't figure out how DirectShow should see my library if it didn't exist in the first place. It's not logical. I've been trying to implement this for a very long time, but it doesn't work, I'm stuck.

Please don't recommend FFmpeg and the like. I don't want to use third party libraries. In DirectX, as far as I know it's built-in.

Step 6 example:

CUnknown * WINAPI CRleFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
{
    CRleFilter *pFilter = new CRleFilter();
    if (pFilter== NULL) 
    {
        *pHr = E_OUTOFMEMORY;
    }
    return pFilter;
}

I Implemented/converted it like this, but it doesn't work. Errors:

no variables sent

function TCRleFilter.CreateInstance(pUnk: PPUnknown; pHr: HRESULT): PUnknown;
var
  pFilter: TCRleFilter;
begin
  pFilter:= TCRleFilter.Create();
  if pFilter = nil then pHr:= E_OUTOFMEMORY;
  Result:= pFilter;
end;

I think at least a logical explanation should suffice.

The whole class:

unit Unit1;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
  Windows, ActiveX, Classes, ComObj, DirectShow9, BaseClass, Dialogs;

type
  TCRleFilter = class(TBCTransformFilter)
  public
    function CheckInputType(mtIn: PAMMediaType): HRESULT;
    function GetMediaType (IPosition: Integer; pMediaType: PAMMediaType): HRESULT;
    function CheckTransform(mtln: PAMMediaType; mt0ut: PAMMediaType): HRESULT;
    function DecideBufferSize(pAlloc: IMemAllocator; pProp: PAllocatorProperties): HRESULT;
    function Transform(pSource, pDest: IMediaSample): HRESULT;
    function CreateInstance(pUnk: PPUnknown; pHr: HRESULT): PUnknown;
  end;

const
  CLSID_CRleFilter: TGUID = '{FBA9B97F-505B-49C7-A6C2-D1EFC34B2C0D}';


implementation

uses ComServ;

{ TCRleFilter }

function TCRleFilter.CheckInputType(mtIn: PAMMediaType): HRESULT;
begin
  Result := S_OK;
  ShowMessage('CheckInputType: âåðíóë "S_OK"');
end;

function TCRleFilter.CheckTransform(mtln, mt0ut: PAMMediaType): HRESULT;
begin
  Result := S_OK;
  ShowMessage('CheckTransform: âåðíóë "S_OK"');
end;

function TCRleFilter.CreateInstance(pUnk: PPUnknown;
  pHr: HRESULT): PUnknown;
var
  pFilter: TCRleFilter;
begin
  try
    pFilter:= TCRleFilter.Create('');
    Result := pFilter;
  except
    pHr:= E_OUTOFMEMORY;
    Result:= nil;
  end;
end;

function TCRleFilter.DecideBufferSize(pAlloc: IMemAllocator; pProp: PAllocatorProperties): HRESULT;
begin
  Result := S_OK;
  ShowMessage('DecideBufferSize: âåðíóë "S_OK"');
end;

function TCRleFilter.GetMediaType(IPosition: Integer; pMediaType: PAMMediaType): HRESULT;
begin
  Result := S_OK;
  ShowMessage('GetMediaType: âåðíóë "S_OK"');
end;

function TCRleFilter.Transform(pSource, pDest: IMediaSample): HRESULT;
begin
  Result := S_OK;
  ShowMessage('Transform: âåðíóë "S_OK"');
end;

initialization
  {.Create(ComServer, TCRleFilter, Class_CRleFilter, 'CRleFilter', 'CRle_Filter', ciMultiInstance, tmApartment); }

  TBCClassFactory.CreateFilter(TCRleFilter,'CRle_Filter', CLSID_CRleFilter, CLSID_LegacyAmFilterCategory, MERIT_DO_NOT_USE, 0, nil );
end.
AmigoJack
  • 5,234
  • 1
  • 15
  • 31
Legat
  • 21
  • 5
  • Setting `pHr` makes no sense - it won't change anything outside the function. That's what you get for ignoring `*` almost always instead of recognizing it as pointers. Maybe you should read Q&A's that explain what `TYPE *name` and `*name = value` actually means and what its Pascal equivalents would be. – AmigoJack Sep 18 '22 at 15:55
  • Perhaps I don't know something about pointers, but the "If" check has nothing to do with it, you can remove it. For fun added a pointer to "pFilter: TCRleFilter;" but it didn't change anything. Error in the absence of transmitted data. C++ uses "new", it is not in Delphi, there is no substitute for it on the Internet. And that's not my main problem. – Legat Sep 18 '22 at 19:39

1 Answers1

0

Your class inherites from TBCTransformFilter and the needed parameters are defined as:

constructor TBCTransformFilter.Create(ObjectName: string; unk: IUnKnown; const clsid: TGUID);

Untested, but it should be much more correct than your attempt:

function TCRleFilter.CreateInstance
( pUnk: IUnknown  // LPUNKNOWN
; var pHr: HRESULT  // Pointer to variable = VAR
): PUnknown;  // Pointer
var
  oFilter: TCRleFilter;  // Object, not pointer
begin
  try  // Failing constructors throw exceptions
    oFilter:= TCRleFilter.Create( 'my RLE encoder', pUnk, CLSID_CRleFilter );
    result:= oFilter;  // In doubt cast via "PUnknown(oFilter)"
  except  // Constructor failed, oFilter is undefined
    pHr:= E_OUTOFMEMORY;
    result:= nil;
  end;
end;

The var parameter ensures that assigned values inside the function also live on outside the function - otherwise you'd only have a local variable. Which is also the point (haha) of pointers in C++ parameters.

AmigoJack
  • 5,234
  • 1
  • 15
  • 31
  • Unfortunately, your changes do not make sense. The key error is on this line: 'pFilter:= TCRleFilter.Create();'. On MSDN, a copy of the class is created and no parameters are sent. Perhaps there is a small error here that I am missing and cannot solve. in Delphi an error pops up: [Error] Unit1.pas(52): Not enough actual parameters. How to create a copy of a class? – Legat Sep 26 '22 at 16:35
  • As if I know which line of your code is line 52. On top you haven't posted the rest of your `TCRleFilter` class declaration. – AmigoJack Sep 26 '22 at 17:32
  • I'm sorry. I took the error from the context of my project. And I'm still not used to the fact that lines are not numbered in this forum. line number 52: `pFilter:= TCRleFilter.Create();`. In your code, this is number 9. This line is related to the error: Not enough actual parameters. In C++: `CRleFilter *pFilter = new CRleFilter();`. In Delphi? – Legat Sep 26 '22 at 19:58
  • See how much code was missing to understand your problem? Better check if `BaseClass.pas` linked by me is identical to the one you use. Edited my post. – AmigoJack Sep 26 '22 at 20:46
  • I created the question only twice in all time. I don't have much experience in creating the right question yet. Thanks for understanding. I was right, I missed a small detail. Weird, why didn't I come up with this? Thank you. Theoretically, the filter is completely ready. I will try again to use it in DirectShow. Perhaps now I can apply it. – Legat Sep 28 '22 at 19:46
  • Then add your own answer pointing out **which** detail **where**, because this website is not meant to you only, but to everyone. – AmigoJack Sep 29 '22 at 07:04