Fehler bei IGraphBuilder von DLL



  • Hallo Leute,

    ich entwickle gerade eine BDA-Software um digitales Fernsehen auf den PC zu empfangen. Ich habe dazu den kompletten DirectShow-Graphen und alle dazugehörigen BDA-Komponenten in eine DLL gepackt. Dazu habe ich einige Funktionen aus der DLL exportiert, so dass ich den die TV-Karte steuern kann, z.B. einstellen der Sender usw. oder das Erstellen des Graphen.

    Ich habe die DLL über eine Exe-Datei getestet und ich empfange Bild und Ton. Also funktioniert alles bestens über die DLL. Mein Problem ist nun, wie kann ich eine Referenz auf den Zeiger von IGraphBuilder aus der DLL bekommen, um den Graphen über die Exe zu steuern.

    Eine Funktion in der DLL habe ich dafür, aber der Zeiger von den ich zurückkriege ist irgendwie falsch.

    die Funktion sieht so aus in der DLL:

    //-----structur auf das DirectShow-Interface
    struct DSInterface
    {
    	bool GraphReady;
    	DWORD ROTFlag;
    	IGraphBuilder *Graph;
    	IMediaControl *MControl;
    	IBaseFilter *VideoFilter;
    	IBaseFilter *AudioFilter;
    	IBaseFilter *VideoRenderer;
    	IBaseFilter *AudioRenderer;
    	//IBasicAudio	*BasicAudio;
    	//IBasicVideo *BasicVideo;
    	//-----BDA Filters/Functions
    	IMpeg2Demultiplexer *MPEG2Dem;
    	IBaseFilter *NetworkProvider;
    	IMpeg2Data *MPEG2Data;
    	IBaseFilter *BDA_Receiver;
    	IBaseFilter *BDA_Tuner;
    	IBaseFilter *BDA_TIF;
    	IDVBTuneRequest *TuneReq;
    	IDVBSTuningSpace *TuneSpace;
    	IDVBSLocator *Locator;
    	ITuner *Tuner;
    	IBDA_SignalStatistics	*Signal;
    };
    //-----Diese Funktion in der DLL erstellt den DirectshowGraphen anhand der Parameter und übergibt dann einen Zeiger auf
    //DSI damit ich von der Exe daraufzugreifen kann
    
    __declspec(dllexport) int CreateDSGraphComponents(DSInterface *DSI,bool AddtoROT,CLSID Video_Decoder,CLSID Audio_Decoder,int VideoRendererType,int AudioRendererType)
    {
       CoInitialize(NULL);
       //---Interface IGraphBuilder erstellen
       if (FAILED(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER ,IID_IGraphBuilder, (void **)&DSI->Graph))) return -1;
       ....
       ....
       ....
       DSI->GraphReady=true; //----Graph ist fertig und funktioniert
    }
    

    Das Problem ist, dass ich den Zeiger DSInterface zurückkriege, aber nicht vollständig. D.h. wenn ich dann über die Exe versuche auf "DSInterface" ->Graph zuzugreifen kommen zugriffs verletzungen, aber wenn ich versuche auf "DSInterface" ->GraphReady zuzugreifen, dann kommt das richtige raus, also true.

    Es ist aber nicht nur bei ->Graph so auch bei den anderen COM-Sachen, z.b. ->VideoRenderer. In der DLL funktionieren alle!

    Weiss jemand woran das liegt?? Ich habe auch mit dem Parameter CLSCTX_INPROC_SERVER rumgespielt, aber kein Erfolg.



  • Ich habe mittlerweile das Problem auf eine andere Weise gelöst. Ich habe statt z.B. IBaseFilter* den Typ DWORD als Zeiger verwendet und dann wieder auf IBaseFilter* zurückgecastet.
    Ich weiss nicht warum das nicht direkt mit IBaseFilter* klappt, vielleicht ist es nicht 'C'-konform und C-Dlls funktionieren nur mit den Standard-Typen...

    😕 😕 😕



  • Hawkxxx schrieb:

    Ich habe mittlerweile das Problem auf eine andere Weise gelöst. Ich habe statt z.B. IBaseFilter* den Typ DWORD als Zeiger verwendet und dann wieder auf IBaseFilter* zurückgecastet.

    Zeige mal bitte deine beiden Code-Varianten zwecks Vergleichsmöglichkeit.



  • Alte Variante:

    struct DSInterface // Diese struct funktioniert in der Exe nicht aus der Dll heraus
    {
    	bool GraphReady;
    	DWORD ROTFlag;
    	IGraphBuilder *Graph;
    	IMediaControl *MControl;
    	IBaseFilter *VideoFilter;
    	IBaseFilter *AudioFilter;
    	IBaseFilter *VideoRenderer;
    	IBaseFilter *AudioRenderer;
    	//IBasicAudio	*BasicAudio;
    	//IBasicVideo *BasicVideo;
    	//-----BDA Filters/Functions
    	ITuner *Tuner;
    	IMpeg2Demultiplexer *MPEG2Dem;
    	IBaseFilter *NetworkProvider;
    	IMpeg2Data *MPEG2Data;
    	IBaseFilter *BDA_Receiver;
    	IBaseFilter *BDA_Tuner;
    	IBaseFilter *BDA_TIF;
    	IBDA_SignalStatistics	*Signal;
    	IDVBTuneRequest *TuneReq;
    	//--DVB-S
    	IDVBSTuningSpace *TuneSpace;
    	IDVBSLocator *Locator;
    	//--DVB-T
    	IDVBTuningSpace2 *TuneSpace2;
    	IDVBTLocator *LocatorT;
    	//--DVB-S
    	IDVBCLocator *LocatorC;
    };
    
    __declspec(dllexport) void GetDSInterface(DSInterface *DSI)
    	{
    		DSI->Graph->QueryInterface //.... bla bla bla (beim Zugriff in der Exe gibt es ein Access Violation)
    		DSP->MControl..... // bla bla bla (beim Zugriff in der Exe gibt es ein Access Violation)
                    DSI->GraphReady=true; // (Zugriff in der Exe läuft ohne Probleme)
    	}
    

    Neue Variante:

    struct DSPointers // Diese struct funktioniert prima in der Exe aus der Dll heraus
    {
    	DWORD GraphBuilder;
    	DWORD MediaControl;
    	DWORD VideoFilter;
    	DWORD AudioFilter;
    	DWORD VideoRenderer;
    	DWORD AudioRenderer;
    	DWORD MPEG2Demultiplexer;
    	DWORD NetworkProvider;
    	DWORD BDA_Tuner;
    	DWORD BDA_Receiver;
    	DWORD BDA_TIF;
    };
    
    DSPointers *DSP = new DSPointers; // ist irgendwo im Program deklariert
    
    __declspec(dllexport) DSPointers* GetDSInterface()
    	{
    		DSP->GraphBuilder=(DWORD)DSCoreInterface->Graph;
    		DSP->MediaControl=(DWORD)DSCoreInterface->MControl;
    		DSP->VideoFilter=(DWORD)DSCoreInterface->VideoFilter;
    		DSP->AudioFilter=(DWORD)DSCoreInterface->AudioFilter;
    		DSP->VideoRenderer=(DWORD)DSCoreInterface->VideoRenderer;
    		DSP->AudioRenderer=(DWORD)DSCoreInterface->AudioRenderer;
    		DSP->MPEG2Demultiplexer=(DWORD)DSCoreInterface->MPEG2Dem;
    		DSP->NetworkProvider=(DWORD)DSCoreInterface->NetworkProvider;
    		DSP->BDA_Tuner=(DWORD)DSCoreInterface->BDA_Tuner;
    		DSP->BDA_Receiver=(DWORD)DSCoreInterface->BDA_Receiver;
    		DSP->BDA_TIF=(DWORD)DSCoreInterface->BDA_TIF;
    		return DSP;
    	}
    

    In der Exe kann ich dann auf z.B. das IGraphBuilder Interface zugreifen, indem ich das folgendermaßen anstelle:

    DSInterface *dsinterface = new DSInterface;
      DSPointers *dsp=GetDSInterface(); //---Funktion aus der DLL mit dem Zeigern
      dsinterface->Graph=(IGraphBuilder*)dsp->GraphBuider; //---Hier wird aus einem DWORD ein IGraphBuilder! So läuft alles bestens!
    

    Bei der neuen Variante ist alles bestens! Dabei spielt in der ersten Variante keine Rolle, ob die struct als Parameter der Funktion oder als Rückgabewert der Funktion zurückgegeben wird.
    In der zweiten Variante funktionieren beide Rüchgabeformen ohne Probleme.

    Hoffe du kannst es irgendwie nachvollziehen... 😃


Anmelden zum Antworten