Fehler in stop()



  • Hallo ich habe (für meine Begriffe) einen sehr schwerliegenden Fehler in meinem Programm. zuerst dachte ich, es sei ein reines WinAPI Problem, was es abernach langem durchsteppen nicht ist.
    Darum habe ich auch zuerst in das WinAPI Forum geschrieben. Wer es sich einmal anschauen will:
    http://www.c-plusplus.net/forum/viewtopic-var-p-is-1098907.html#1098907

    Programmbeschreibung:
    in Prinzip sind es zwei(eine DLL und eine WinAPI Applikation) und nicht ein einziges Prgramm. Das Programm soll einen videostream einer Webcam einlesen und dann in einem Fenster, das in WinAPI geschrieben ist anzeigen. Alle Filter und sonst noch das, was die Webcam benutzt ist in einer DLL geschrieben die nur den Videostream an das WinAPI Programm übergibt.
    Der Code für die Webcam folgt nach der Fehlerbeschreibung, der Code von dem Winain() ist in dem oben angegebenen Link zu finden. Ich denke, dass ich die Stop() benötige um meine Filter bei der Beendigung des Programmes zu stoppen und zu löschen.

    Fehlerbeschreibung:
    Mein Programm hängt sich in der stop() auf. Wenn ich das Fenster schließe, dann schließt sich zwar das fenster, das Programm jedoch läuft im Hintergrund weiter. Ich schätze dass das stoppen irgendeines Filters oder ein überlaufender Speicher das Problem ist, ich kann den Fehler nur nicht finden. Der Fehler tritt nicht jedesmal auf, was aber sicher ist, ist dass mit der der Zeit die das Programm läuft, auch die Wahrscheinlichkeit eines Auftreten des Fehlers wächst.

    Interessant ist, dass der Fehler nur in 90% aller Fälle auftritt und dass wenn ich die Priorität des Prozesses im Taskmanager erhöhe der Fehler gar nicht mehr auftritt.

    Fragen:
    Wie kann ich dieses Problem lösen?
    Gibt es vielleicht eine andere Möglichkeit die Filter zu stoppen?

    Hier einmal der Code. Ich habe ein Kommentar an der Fehlerstelle hingeschrieben.

    #include "stdafx.h"
    
    HRESULT CGetVideo::CheckMediaType(const CMediaType *media)
    	{    
            VIDEOINFO* vi; 
    
    		if(!IsEqualGUID( *media->Subtype(), MEDIASUBTYPE_RGB24) || !(vi=(VIDEOINFO *)media->Format()) )
    			return E_FAIL;
    
            bmih=vi->bmiHeader;
    		SetWindowPos(hwnd,0,0,0,20 +(w=vi->bmiHeader.biWidth),60  +(h=vi->bmiHeader.biHeight),SWP_NOZORDER|SWP_NOMOVE);
    
    		return  S_OK;
    	};
    
    HRESULT CGetVideo::DoRenderSample(IMediaSample *sample)
    {		
    
    	escape= true;
    	static BYTE* data;
    	static bool firsttime= true;
    
    	if (firsttime)
    	{
    		sample->GetPointer( &data );
    		firsttime=false;
    	}
    
    	if (!turnedoff)
    	{
    		turnedoff= true;
    
    		if (pBuffer != NULL)	delete pBuffer;
    		BufferSize= sample->GetSize();
    		pBuffer= (BYTE*) malloc(BufferSize);
    		memcpy(pBuffer, data, BufferSize);
    
    		//pBuffer = filter.bildFiltern(/*bmih,*/ pBuffer);
    		//pBuffer = check.scanHuelse(pBuffer);
    
    		turnedoff=false;
    	}
    
    	BITMAPINFO bmi={0};
    	bmi.bmiHeader=bmih; 
    	RECT r; 
    	GetClientRect( hwnd, &r );
    
    	HDC hdc= GetDC(hwnd);
    
    	int ret= StretchDIBits(hdc ,0,16,r.right,r.bottom-16,0,0,w,h,pBuffer,&bmi,DIB_RGB_COLORS,SRCCOPY); 
    	ReleaseDC(hwnd, hdc);
    
    	escape= false;
    	return ret; 
    };
    
    CGetVideo::CGetVideo(HWND hw): CBaseVideoRenderer(__uuidof(CLSID_Sampler), NAME("Frame Sampler"), 0, &hr)
    {
    
    	turnedoff= false;
    	pBuffer= NULL;
    	escape= false;
    
    	hwnd= hw;
    	graph= 0; 
    	w= 0;
    	h= 0;
    	hr = CoInitialize(0);
    	MSG msg = {0}; 
    
    	BITMAPINFOHEADER bmih={0}; 
    
    	memset( &bfh, 0, sizeof( bfh ));
    	bfh.bfType = 'MB';
    	bfh.bfSize = sizeof( bfh ) + BufferSize + sizeof( BITMAPINFOHEADER );
    
    	hr = CoCreateInstance( CLSID_FilterGraph, 0, CLSCTX_INPROC,IID_IGraphBuilder, (void **)&graph );
    
    	ctrl = 0; hr = graph->QueryInterface( IID_IMediaControl, (void **)&ctrl );
    
    	rnd  = 0; hr = FindPin(L"In", &rnd);
    			  hr = graph->AddFilter((IBaseFilter*)this, L"Sampler");
    
        devs = 0; hr = CoCreateInstance (CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &devs);
        cams = 0; hr = devs?devs->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &cams, 0):0;  
        mon  = 0; hr = cams?cams->Next (1, &mon, 0):0;
        cam  = 0; hr = mon?mon->BindToObject(0,0,IID_IBaseFilter, (void**)&cam):0;
        pins = 0; hr = cam?cam->EnumPins(&pins):0; 
        cap  = 0; hr = pins?pins->Next(1,&cap, 0):0;
                  hr = graph->AddFilter(cam, L"Capture Source"); 
    
    	vid  = 0; hr = graph->AddSourceFilter (L"c:\\Windows\\clock.avi",  L"File Source", &vid);
    	avi  = 0; hr = vid?vid->FindPin(L"Output", &avi):0;
    
        hr = graph->Connect(cap?cap:avi,rnd);
        hr = graph->Render( cap?cap:avi );
        hr = ctrl->Run();
    
    };
    
    CGetVideo::~CGetVideo()
    {
    
    	HRESULT result;
    
    	result= this->Stop(); //Hier tritt mein Fehler auf, das Programm bleibt hier hängen.
    	result= graph->RemoveFilter(this);
    	result= rnd->Release();
    	result= rnd->Release();
    	result= rnd->Release();
    
    }
    
    BYTE* CGetVideo::C_GetBitmap()
    {
    	turnedoff=true;
    
    	pBuffCopy= (BYTE*) malloc(BufferSize);
    	pBuffCopy= (BYTE*) memcpy(pBuffCopy, pBuffer, BufferSize);
    
    	turnedoff= false;
    
    	return pBuffCopy;
    };
    
    int CGetVideo::C_GetPicSize()
    {
    	return BufferSize;
    };
    
    BITMAPINFOHEADER CGetVideo::C_GetPicInfo()
    {
    	return bmih;
    };
    
    BITMAPFILEHEADER CGetVideo::C_GetPicFilInfo()
    {
    	return bfh;
    };
    

    Vielen Dank euch allen!!!!!



  • Ich hoffe du empfindest nach meinem erfolglosen Hilfeversuch im WinAPI Forum diesen Post nicht als lästig, aber:

    gramboler schrieb:

    //  ...
    
    HRESULT CGetVideo::DoRenderSample(IMediaSample *sample)
    {       
    //  ...
    
        if (!turnedoff)
        {
            turnedoff = true;
           
            if( pBuffer != NULL )
                delete pBuffer;                   // delete und
                                                  //
            BufferSize= sample->GetSize();        //
            pBuffer= (BYTE*) malloc(BufferSize);  // malloc( );
            memcpy(pBuffer, data, BufferSize);    // vertragen sich in der Regel nicht!
      
    //  ...
    
        }
       
    //  ...
    
    };
    
    CGetVideo::CGetVideo(HWND hw): CBaseVideoRenderer(__uuidof(CLSID_Sampler), NAME("Frame Sampler"), 0, &hr)
    {
    
        turnedoff= false;
        pBuffer= NULL;  // pBuffer "einfach so" auf 0 setzen?
        escape= false;
    
        hwnd= hw;
        graph= 0;
        w= 0;
        h= 0;
        hr = CoInitialize(0);  // MSDN: New applications should call CoInitializeEx instead of CoInitialize.
                               //       Typically, the COM library is initialized on a thread only once.
                               //       However, the first thread in the application that calls CoInitialize(0)
                               //       or CoInitializeEx(COINIT_APARTMENTTHREADED) must be the last thread to
                               //       call CoUninitialize(). 
        MSG msg = {0};
       
    
        BITMAPINFOHEADER bmih={0};
    
        memset( &bfh, 0, sizeof( bfh ));
    
    //  bfh.bfType = 'MB';      eher:
        bfh.bfType = 'BM';   // Little Endian!!!
        bfh.bfType = 0x4d42; // <- sicher.
    
    // ...
    
    };
    
    CGetVideo::~CGetVideo()
    {
        HRESULT result;
    
        result= this->Stop(); //Hier tritt mein Fehler auf, das Programm bleibt hier hängen.
        result= graph->RemoveFilter(this);
        result= rnd->Release(); // 3 * Release() wirkt irgendwie willkürlich
        result= rnd->Release(); // mir fehlt leider die Möglichkeit es - ob der
        result= rnd->Release(); // fehlenden Sources - die MÖglichkeit es nachzuprüfen
    }
    
    BYTE* CGetVideo::C_GetBitmap()
    {
        turnedoff = true;
    
        pBuffCopy= (BYTE*) malloc(BufferSize);                     // ich würd' mich für new entscheiden
        pBuffCopy= (BYTE*) memcpy(pBuffCopy, pBuffer, BufferSize); // wo wird pBuffCopy eigentlich wieder freigegeben?
                                                                   // auf jeden Fall hoffe ich mit free( )!?
        turnedoff= false;
    
        return pBuffCopy;
    };
    

    Greetz, Swordfish

    PS: Ansonsten würd' mich wirklich interessieren, wo der Fehler genau liegt. Bei interesse kannst mir das Projekt mailen: reiter.e AT gmx.net
    Sag' aber bescheid.



  • @Swordfish
    nein,..........ich bin immer dankbar wenn mir jemand versucht zu helfen.
    Ich weiss nicht ich dir das ganze Projet schicken kann, weil es ziemlich umfangreich (insgesamt 17 Dateien + eine INI Datei) ist und vielleicht auch mein Prof etwas dagenen hätte. Du hast geschrieben, dass du bisher noch nicht viel mit directX gemacht hast. Vielleicht solltest du dir erst einmal die Basis meines Programmes anschauen.

    http://www.codeproject.com/useritems/VideoImageGrabber.asp

    Um dieses Programm zum laufen zu bringen musst du zusaätzlich zu dem Platform SDK das directX SDK (summer2004) herunterladen um die strmbasd.h Datei zu bekommen. Danach wie auf der Seite beschrieben musst du auch noch die Libs einfügen.

    Ich muss einmal schauen ob ich dir vielleicht einen kopelierbaren Teil schicken kann.

    --------------------------------------------------------------------------------

    buffcopy benötige ich in einem anderen Programteil wo ich verschiedene Filter über das einzelne Bild laufen lassen.

    zu free()
    nein ich habe alles mit delete gemacht. Ich habe nicht gewusst dass sich malloc und delete sich nicht vertragen.
    Bisher hat bei mir aber immer wunderbar funktioniert. Ich habe noch eine etwas andere Variante des Programmes das schon seit einem Mant ohne Fehler durchläuft.



  • gramboler schrieb:

    Ich weiss nicht ich dir das ganze Projet schicken kann, weil es ziemlich umfangreich (insgesamt 17 Dateien + eine INI Datei) ist [...]

    Einfach zippen 😉

    gramboler schrieb:

    Du hast geschrieben, dass du bisher noch nicht viel mit directX gemacht hast. Vielleicht solltest du dir erst einmal die Basis meines Programmes anschauen.

    Naja, bis auf eine Starfield-Simpulation noch nichts, aber ich bin ein Mensch der "Learning by Doing"-Kategorie. Deine Link sieht wirklich nett aus.

    gramboler schrieb:

    Um dieses Programm zum laufen zu bringen musst du zusaätzlich zu dem Platform SDK das directX SDK (summer2004) herunterladen um die strmbasd.h Datei zu bekommen.

    Hm ich hoff' 'ne Visual Studio .net Enterprise Architect mit DirectX 9 SDK Oktober '04 reicht 😃

    gramboler schrieb:

    Ich muss einmal schauen ob ich dir vielleicht einen kopelierbaren Teil schicken kann.

    wie Du willst.

    gramboler schrieb:

    zu free()
    nein ich habe alles mit delete gemacht. Ich habe nicht gewusst dass sich malloc und delete sich nicht vertragen.

    Naja, das ist eher eine "Volksweisheit". Ich hab' damit auch noch keine Probleme gehabt, weil ich sie nie gemischt habe. Da müsste man mal die Gurus fragen...

    gramboler schrieb:

    Bisher hat bei mir aber immer wunderbar funktioniert. Ich habe noch eine etwas andere Variante des Programmes das schon seit einem Mant ohne Fehler durchläuft.

    Wie groß ist denn der Unterschied zu dieser "Variante"?

    Greetz, Swordfish



  • [edit] falscher Thread [/edit]

    Greetz, Swordfish



  • Hm ich hoff' 'ne Visual Studio .net Enterprise Architect mit DirectX 9 SDK Oktober '04 reicht

    ich selbst arbeite mit VS2003 .net 😉 habe mir das Platform und das DirectX SDK heruntergeladen und es hat funktioniert.

    Du musst in deinem Programm auf die Pfade der zusätzlichen Libs und Header in deinem Projekt verweisen.

    Zur strmbasd.h: im DirectX SDK gibt es Beispiel namens BaseCLasses
    C:\Programme\Microsoft DirectX 9.0 SDK (Summer 2004)\Samples\C++\DirectShow\BaseClasses

    dieses Beispiel musst du debuggen um die strmbasd.h zu bekommen 😉 Achtung, du darfst nicht die Release Version nehmen!!

    Die LIBs suchst du dir a besten über die Windows Suchfunktion.

    du kannst mir es ja mal mitteilen wenn du das zum laufen gebracht hast. Dann kann ich dir etwas von mir schicken.

    Wie groß ist denn der Unterschied zu dieser "Variante"?

    Zu den Varianten: Die Klassen für das Video aptureing sind eigengtlich die gleichen. Die Programme unterscheiden sich im Wesentlichen nur darin, was ich miit dem Viedeostream mache.

    Variante 1 Farberkennung: Eine bestimmte Fläche des Bildes wird erfasst, Pixel von RGB in HSV umgewandelt und dann wird die Farbe geprüft.
    Variante 2 Figurenerkennung: Ich lasse verschieden Filter, zur Kantenerkennung darüberlaufen und versuche einen Kreis im Bild zu erkennen, Mittelpunkt ausrechen und den Innenradius messen. Das ganze wird dann noch im Bild angezeigt.

    Beide Projekte sind ungefähr gleich groß.



  • Hallo, leider besteht mein Problem noch immer 😞

    vielleicht fällt jemanden noch etwas ein 🙂


Anmelden zum Antworten