Richtiges Directx-SDK einbinden und Kamera auslesen



  • Hallo!

    Ich möchte gerne eine angeschlossene CCD-Kamera auslesen und bin mittlerweile soweit, einen IBaseFilter auf die Kamera gesetzt zu haben. Den Pin der Ausgabe bekomme ich nach Anleitung über

    CComPtr pOutPin;
    pSourceFilter->FindPin( L"1", &pOutPin );
    

    Allerdings ist diese nicht sehr ausführlich, es wird an die directX-SDK-Beispiele verwiesen. [url="http://msdn.microsoft.com/en-us/library/windows/desktop/dd407288(v=vs.85).aspx"]Dort heißt es unter anderem[/url]:

    #include <windows.h>
    #include <dshow.h>
    #include "qedit.h"
    template <class T> void SafeRelease(T **ppT){
        if (*ppT){
            (*ppT)->Release();
            *ppT = NULL;
        }
    }
    

    Allerdings gibt es da einige Fehler...
    zunächst hatte ich mir natürlich das aktuelle Windows SDK und DirectX-SDK heruntergeladen, wo die benötigten Daten irgendwie alle nicht drin waren. Nach einigen Suchen im Internet habe ich jetzt das WinSDK von 2003-Server und DirectX von 2007. Deren Include-Ordner einzustellen fand dann immerhin auch die d3d.h.
    Nur beschwert er sich momentan über die objidl.h, hauptsächlich über Zeilen wie

    __RPC__out_xcount_part(cRequest, *pcReturned) BYTE *buf,
    

    , dass er da ein ")" erwartet...
    Mit den anderen Versionen habe ich auch rumprobiert, allerdings gab es immer Fehler, irgendwo fehlt ne Klammer oder ein Typ oder die Klasse wäre schon definiert... Alles in den heruntergeladenen SDK-Dateien!

    Daher wollte ich euch mal fragen, ob das einer bei euch mal korrekt eingerichtet hat, welche SDK-Versionen und Include-Ordner ihr in welcher Reihenfolge benutzt habt und ob bei euch die SDK-Beispiele liefen.

    Ich benutze Embacadero's C++-Builder und Win7. Die Kamera wird übrigens korrekt erkannt (Hat auch 3 Tage gedauert, das einzurichten...)



  • Dediggefedde schrieb:

    zunächst hatte ich mir natürlich das aktuelle Windows SDK und DirectX-SDK heruntergeladen, wo die benötigten Daten irgendwie alle nicht drin waren.

    Für C++Builder brauchst du das:
    http://clootie.ru/cbuilder/index.html

    Dediggefedde schrieb:

    Embacadero's C++-Builder

    Leicht unpräzise. Schreib nächstesmal die Version dazu.



  • Vielen Dank audacia!

    Ja, entschuldige bitte, etwas wichtiges scheine ich immer zu vergessen... Ich benutze Embarcadero® C++Builder® XE2 Version 16.0.4429.46931.
    Ich habe die Dateien die dort für drectx9.0 angegeben waren heruntergeladen und die Schritte aus dem Beispiel dort befolgt, also...

    • C++Builder library pack und Clootie_DXxx_dlls.zip heruntergeladen und den Pfad dorthin inkludiert
    • Microsoft Platform-SDK für WinServer 2003 installiert und Include-Pfad inkludiert
    • Directx-SDK 2007 installiert und Include-Pfad inkludiert

    Danach einfach mal auf Kompilieren geklickt, um das korrekte einbinden zu überprüfen und kam dann zu folgendem Fehler:

    [BCC32 Fehler] winnt.h(588): E2211 Inline-Assembly in Inline- und Vorlagen-Funktionen nicht zulässig[...]

    markiert wird in folgendem Block die Zeile von __asm{

    __inline ULONGLONG
    NTAPI
    Int64ShllMod32 (
        ULONGLONG Value,
        DWORD ShiftCount
        )
    {
        __asm    {
            mov     ecx, ShiftCount
            mov     eax, dword ptr [Value]
            mov     edx, dword ptr [Value+4]
            shld    edx, eax, cl
            shl     eax, cl
        }
    }
    

    Binde ich hier ein aktuelles Win-SDK ein, erhalte ich Fehler wie:

    [BCC32 Fehler] winnt.h(366): E2257 , erwartet
    [BCC32 Fehler] winnt.h(367): E2238 Mehrfache Deklaration von 'WCHAR'

    für Zeilen wie

    typedef __possibly_notnullterminated WCHAR *PNZWCH;
    typedef __possibly_notnullterminated CONST WCHAR *PCNZWCH;
    

    Im Beispiel stand auch etwas von den Bedingungen
    cosf=(float)cos;sinf=(float)sin;acosf=(float)acos;asinf=(float)asin;tanf=(float)tan; atanf=(float)atan;sqrtf=(float)sqrt
    Füge ich die bei mir im Dialog ein, erhalte ich den Fehler, dass er bei sinf ein ( nach sin erwartet...

    Auch gibt es in der direktx-sdk einen Fehler, weil mehrere ) erwartet werden, unter anderem in

    virtual HRESULT STDMETHODCALLTYPE Finish_Pull( 
                /* [length_is][size_is][out] */ __RPC__out_xcount_part(cRequest, *pcReturned) BYTE *buf,
                /* [out] */ __RPC__out ULONG *pcReturned) = 0;
    

    vor *pcReturned

    Ich dachte aber eigentlich, alles so gemacht zu haben, wie im Beispiel!? Auch finde ich es seltsam, dass diese doch sehr verbreiteten Bibliotheken Fehler beinhalten würden, daher nehme ich mal an, dass ich eine Einstellung falsch habe...

    Kennt jemand von euch diese Fehler oder weiß, was ich beim Einrichten falsch gemacht habe?



  • Hallo!

    Ich habe jetzt wohl die richtigen Bibliotheken gefunden, sodass kompilieren ohne Fehler klappt.
    Eingebunden wurden aus dem DirectShow-Verzeichnis des Direktx9-SDKs (2005) aus dem Baseclasses-Ordner:
    amfilter.cpp, combase.cpp, ctlutil.cpp, mtype.cpp, renbase.cpp, wxdebug.cpp, wxlist.cpp, wxutil.cpp
    includiert wurde:
    #include <wxdebug.h>, #include <tchar.h>, #include <streams.h>, #include <Dshow.h>
    C:\Users\Julian\Desktop\Programm\cbuilder_libs
    Als bibliothekspfad wurden die cbuilder_libs from here (including strmbase.lib)
    http://realmike.org/blog/projects/directx-8-borland-libs-download-page/
    Als include-pfad habe ich hinzugefügt:
    C:\Program Files\Microsoft DirectX 9.0 SDK (February 2005)\Extras\DirectShow\Samples\C++\DirectShow\BaseClasses
    C:\Program Files\Microsoft DirectX 9.0 SDK (February 2005)\Extras\DirectShow\Include
    C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include\atl

    Nun gibt es allerdings noch das Problem mit dem tatsächlichen Auslesen.
    Das Original-Beispiel hat an einigen Punkten gewisse Dinge weggelassen, die mich vor Rätsel stellen.

    Ich habe eine Kamera angeschlossen und möchte gerne die Bilddaten als Byte-Array bzw. -Pointer o.ä. haben.
    Ich habe schon in Erfahrung gebracht, dass ich im DoRender-Bereich die IMediaSample-Objecte in Bytearrays konvertieren kann und somit den aktuellen Frame aufrufen könnte. Nur wird dieser Teil nicht aufgerufen.

    Im Breispiel wurde folgender Code angegeben:

    Now, all that remains is to instantiate this class and add it to our graph.

    {
        HRESULT hr = S_OK;
    
        // Create a bitmap renderer.
    
        m_pSnapshotter = new CBitmapRenderer( _T("Bitmap renderer"), NULL, &hr );
        if( FAILED(hr) )
        {
            Error(_T("Couldn't create bitmap renderer."));
            return hr;
        }
    
        m_pSnapshotter->SetCallback( (IBitmapCallback*) this );
    
        // Add the grabber to the graph.
    
        CComQIPtr< IBaseFilter > pGrabBase( m_pSnapshotter );
        hr = m_pGraphBuilder->AddFilter( pGrabBase, L"Snapshot" );
    
        return hr;
    }
    

    Then, after you have added the rest of the filters to the graph and rendererd the capture stream, all you need to do is have DirectShow connect the second pin of the capture filter (which is labelled "1") to the input pin of the snapshot filter:

    IBaseFilter pSourceFilter;  // the camera
        IGraphBuilder pGraphBuilder;
        ...
    
        // Now connect the snapshot pin.
    
        CComPtr pOutPin;
        pSourceFilter->FindPin( L"1", &pOutPin );
        CBasePin* pInPin = m_pSnapshotter->GetPin( 0 );
    
        hr = m_pGraphBuilder->Connect( pOutPin, pInPin );
    

    Ich habe das Versucht, bei mir umzuschreiben und es gibt keine Fehlermeldung, allerdings passiert auch nichts:

    HRESULT hr = S_OK;
    	IBaseFilter* pFilter=0;
    	hr=CreateKernelFilter(
    		CLSID_VideoInputDeviceCategory,
    			L"Videology USB-C Camera",
    			&pFilter
    	);
        CoInitialize(NULL);
    	CComQIPtr<IVideology20K1XX> pKs(pFilter);
    	if(pFilter==0)return;
    	hr=pKs->SetWhiteBalanceMode(wbAuto);
    
    	CBitmapRenderer *m_pSnapshotter = new CBitmapRenderer( _T("Bitmap renderer"), NULL, &hr );
    
    	if( FAILED(hr) )
    	{
    		ASSERT("Couldn't create bitmap renderer.");
    		return;
    	}
    	m_pSnapshotter->SetCallback( (IBitmapCallback*) this );
    	CComQIPtr< IBaseFilter > pGrabBase( m_pSnapshotter );
    
    	IGraphBuilder*  m_pGraphBuilder=0;
    	 hr = CoCreateInstance(CLSID_FilterGraph, NULL,
    	CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGraphBuilder);
    	hr = m_pGraphBuilder->AddFilter( pGrabBase, L"Snapshot" );
    
    	CComPtr<IPin> pOutPin;
    	hr= pFilter->FindPin( L"1", &pOutPin );
    
    	CBasePin* pInPin = m_pSnapshotter->GetPin( 0 );
    	m_pSnapshotter->Run(0);
    	hr = m_pGraphBuilder->Connect( pOutPin, pInPin );
    

    Dabei ist noch gut zu wissen, dass alle hr=0 sind, also alles erfolgreich abläuft, bis auf das letzte hr, welches 0x8004025F ist, also VFW_E_NOT_IN_GRAPH:Description: Cannot perform the requested function on an object that is not in the filter graph.

    Wisst ihr, wie man directshow richtig initialisiert?


Anmelden zum Antworten