ISampleGrabber::SetCallback eigene Funktion übergeben



  • Hallo,

    ich habe wieder einmal ein DirectShow Problem, und zwar gibt es eine Möglichkeit eine Callback Routine für Samples zu definieren, jedoch konnte ich nicht herausfinden, wie man alleine mit C eine eigene Callback-Routine definieren kann mein momentaner Aufruf:

    Streamgrabber->SetCallback((ISampleGrabberCB *)grabSample, 1);
    
    HRESULT CALLBACK grabSample(double SampleTime, BYTE *pBuffer, long BufferLen) {
    	MessageBox(NULL, TEXT("safas"), TEXT("saf"), 0);
    
    	return S_OK;
    }
    

    führt zu einem Speicherzugriffsfehler(Funktionszeiger habe ich auch schon probiert, ledier mit dem gleichen Ergebniss).

    vllt hat jemand eine Idee und kann mir helfen.

    Mit freundlichen Grüßen

    Anon



  • Casten ist immer schlecht... vermutlich musst Du hier ein IDispatch-Interface übergeben... aber das wirst Du sicher in der Doku zu den Methode finden...



  • Das Problem ist, dass bei MSDN nirgendwo ein Beispiel dazu zu finden ist, wie man eine eigene Callback-Funktion definiert. Dort stehen nur die Parameter. Und eine Klasse kann ich nicht implementieren, da ich auf reines C angewiesen bin. Allgemein bin ich was DirectShow angeht noch ziemlich neu.

    Mit freundlichen Grüßen

    Anon



  • Man kann ein COM-Interface auch in C schreiben; der Aufwand ist natürlich erheblich größer als in C++ mit ATL... ich kann Dir aber nicht mal ein Beispiel zeigen... müsste ich auch zuerst mal suchen, wie das nochmals geht...


  • Mod

    Auf reines C bist Du scheinbar nicht angewiesen. Wie man an Deinem Syntax sieht verwendest Du schon C++.
    Also implementiere nur das Inteerface in C++ (ATL,...).

    Ansonsten müsstest Du eine eigene Sprungtabele für alle Interface-Einträge aufbauen (inkl. AddRef, Release, QueryInterface).

    Schau Dir mal das Beispiel für die GIT in Wine an, dass auch in C geschrieben würde:
    http://wine.sourcearchive.com/documentation/1.1.5/git_8c-source.html

    Schrecklich in meinen Augen.

    Nochmal wie Jochen es schon sagte: Mach es in C++!



  • In C++ könnte es so aussehen:

    class CSampleGrabberCB : public ISampleGrabberCB 
    {
    public:
    
    	CSampleGrabberCB();
        ~CSampleGrabberCB();
    
        STDMETHODIMP	QueryInterface(REFIID riid, void ** ppi);
    
        STDMETHODIMP	SampleCB(double SampleTime, IMediaSample * pSample);
        STDMETHODIMP	BufferCB(double SampleTime, BYTE * pBuffer, long BufferSize);
        STDMETHODIMP_	(ULONG) AddRef();
        STDMETHODIMP_	(ULONG) Release();
        .....
    
    };
    
    ..
    CSampleGrabberCB SG;
    CComPtr< ISampleGrabber > StreamGrabber;
    ..
    StreamGrabber.CoCreateInstance(CLSID_SampleGrabber);
    ..
    StreamGrabber->SetBufferSamples(false);
    StreamGrabber->SetOneShot(false);
    StreamGrabber->SetCallback(&SG, 0); // CSampleGrabberCB::SampleCB soll aufgerufen werden
    // Die Returnwerte müssen natürlich ausgewertet werden.
    

    Diese letzten Schritte erfolgen beim Erstellen des Preview-Graphen.
    Wie Jochen Kalmbach bereits geschrieben hat, ist es möglich, dies auch in C umzusetzen. Du müsstest dir einmal die MS-Headerdateien mit den jeweiligen C-Interfaces anschauen.
    Ich habe damit leider keinerlei Erfahrung.



  • Anon schrieb:

    Das Problem ist, dass bei MSDN nirgendwo ein Beispiel dazu zu finden ist, wie man eine eigene Callback-Funktion definiert.

    Weil es nur Callback-Interfaces gibt, keine einzeln stehenden Funktionen. Allerdings sind es keine dispinterfaces, was die Sache erheblich vereinfacht. ATL braucht man sich dann auch nicht unbedingt ans Bein zu binden.

    Streamgrabber->SetCallback((ISampleGrabberCB *)grabSample, 1);
    

    Und eine Klasse kann ich nicht implementieren, da ich auf reines C angewiesen bin.

    Dann kannst Du mit allen Samples nichts anfangen. In C sehen die Methoden Aufrufe nämlich ganz anders aus. Um bei Deinem Beispiel zu bleiben:

    Streamgrabber->lpVtbl->SetCallback(Streamgrabber, ...);
    


  • Vielen dank für euere Beiträge, wie es scheint wird wohl kein Weg an C++ bzw einer Klasse vorbeiführen(hatte ich versucht zu vermeiden). Ich werde also mal probieren das ganze zum laufen zu bekommen.


Anmelden zum Antworten