ich schreibe gerade ein Programm, dass Bilder von der Kinectkamera anzeigen soll. Da ich mit Oop noch nicht viel gemacht habe, tue ich mich ziemlich schwer damit. (Habe zuerst alles in eine Datei geschrieben und das funktioniert auch, nun will ich das ganze kapseln in Klassen)
Bisher sieht mein Programm wie folgt aus: Ich habe eine Hauptklasse mit main, eine Klasse, die mit SDL das Bild anzeigen soll und eine Klasse, die die Bilder von der Kinect holen und dann mit der SDL-Klasse anzeigen soll.
Nun habe ich schon einiges ausprobiert. Zuerst habe ich den Thread in der Kinect Klasse gestartet, dann habe ich das ganze in meiner Hauptklasse in der main versucht. Das Ergebnis ist das selbe. Der Thread (hab's mit WinThreads und SDL_Threads probiert) startet und zeigt auch ein paar Bilder an (beim debuggen in Einzelschritten in VC++ 2010 Express wurden mir ein paar Einzelbilder angezeigt) und dann hängt sich irgendwo was auf und mein Programm kommt zu keinem der gesetzten Breakpoints mehr...?
In der Ausgabe beim Debugging kommt:
Der Thread 'Win32-Thread' (0xedc) hat mit Code 0 (0x0) geendet.
Und dann ist das Bild eingefroren, das Fenster ist also noch offen, aber im Debugger ist "F5 Weiter" ausgegraut. Es geht also nix mehr. Irgendwie scheint sich das Programm selbst zu beenden, aber der Thread, bzw. das SDL-Fenster bleibt noch offen. Ich weiß jetzt gar nicht mehr weiter und weiß auch gar nicht wo ich nach dem Fehler suchen soll. Es wird wohl ein typischer Anfängerfehler sein...?
Ich hoffe irgendjemand sieht wo das Problem liegt.
Vielen Dank schon einmal.
Hier mal der Code:
meine Hauptklasse EarTracker.h
Code: Alles auswählen
#pragma once
#include "ProcessSDL.h"
#include "ShowKinect.h"
#include <SDL_thread.h>
class ProcessSDL;
class EarTracker
{
public:
SDL_Thread *rgbThread;
bool sdlQuit;
public:
EarTracker(void);
virtual ~EarTracker(void);
int threadFunctionRGB(void* pthis);
};
Code: Alles auswählen
#include "EarTracker.h"
EarTracker::EarTracker(void)
{
}
EarTracker::~EarTracker(void)
{
}
int threadFunctionRGB(void* pthis)
{
return ((ShowKinect*)pthis)->Nui_GotColorAlert();
}
int main(int argc, char* argv[]){
ProcessSDL *myProcessSDL = new ProcessSDL; //SDL Objekt
ShowKinect *myShowKinect = new ShowKinect; //Kinect Objekt
SDL_Thread *rgbThread = NULL;
int xPos = 0;
int yPos = 0;
//Close SDL Window or kill Thread: Wait for quit
bool sdlQuit = false;
if (myProcessSDL->initSDL() == false) return 1; //init SDL
HRESULT hr = myShowKinect->Nui_Init(myProcessSDL); // zero and init Kinect
if ( FAILED( hr ) )
{
MessageBox( NULL, "Could not init Kinect.", NULL, NULL );
return hr;
}
rgbThread = SDL_CreateThread(threadFunctionRGB,myShowKinect);
while(!sdlQuit && !myShowKinect->quitThread) { //Fenster schließen
//Do everything here
while(SDL_PollEvent(&myProcessSDL->event)) {
if (myProcessSDL->event.type == SDL_QUIT) {
sdlQuit=true;
myShowKinect->quitThread = true;
}
}
}
myProcessSDL->quitSDL();
delete myProcessSDL;
delete myShowKinect;
SDL_KillThread( rgbThread );
return 0;
}
Code: Alles auswählen
#pragma once
#include <SDL.h>
//extern SDL_Surface *m_pScreen;
class ProcessSDL
{
public:
SDL_Surface *m_pScreen;
SDL_Event event;
public:
ProcessSDL(void);
virtual ~ProcessSDL(void);
bool initSDL();
void quitSDL();
SDL_Surface *GetScreen() {return m_pScreen;}
bool ShowImageOnScreen(void* buffer, int imageWidth, int imageHeight, int imageDepth, int xPos, int yPos, int myPitch);
};
Code: Alles auswählen
#include "ProcessSDL.h"
ProcessSDL::ProcessSDL(void)
{
SDL_Surface *m_pScreen;
m_pScreen = NULL;
}
ProcessSDL::~ProcessSDL(void)
{
}
bool ProcessSDL::initSDL() {
//Initialize all SDL subsystems
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ) { return false; }
//
atexit(SDL_Quit);
// init screen
SDL_putenv("SDL_VIDEO_CENTERED=center");
SDL_WM_SetCaption("Ear Tracker", NULL);
m_pScreen = SDL_SetVideoMode( 1280,720, 32, SDL_SWSURFACE); //2 * 640 = 1280 2 Bilder (640 + 480) nebeneinander, 480+240 = 720 1,5 Bilder (640*480 und 320*240) übereinander
if ( m_pScreen == NULL )
{
return false;
}
//If everything initialized fine
return true;
}
void ProcessSDL::quitSDL() {
//Free the surfaces
SDL_FreeSurface( m_pScreen );
//Quit SDL
SDL_Quit();
}
bool ProcessSDL::ShowImageOnScreen(void* buffer, int imageWidth, int imageHeight, int imageDepth, int xPos, int yPos, int myPitch)
{
//SDL_Surface *m_pScreen;
SDL_Surface *Image;
Image = (SDL_Surface*)malloc(sizeof(SDL_Surface));
Image = SDL_CreateRGBSurfaceFrom(buffer,imageWidth,imageHeight,imageDepth,myPitch, 0,0,0,0);
//Put Picture on Screen
SDL_Rect sRect; //Quellbereich
SDL_Rect dRect; //Zielbereich
// Setzen des Quellbereichs
sRect.x = 0;
sRect.y = 0;
sRect.w = Image->w; // das gesamte Bildbreite
sRect.h = Image->h; // das gesamte Bildhöhe
// Setzen des Zielbereichs
dRect.x = xPos;
dRect.y = yPos;
dRect.w = Image->w;
dRect.h = Image->h;
if( SDL_MUSTLOCK( m_pScreen ) ) { SDL_LockSurface( m_pScreen ); }
//Rectausschnitt des Quellbildes Image auf Rectausschnitt des Screen kopieren
SDL_BlitSurface(Image, &sRect, m_pScreen, &dRect );
//Update Screen
SDL_UpdateRects(m_pScreen,1,&dRect);
if( SDL_MUSTLOCK( m_pScreen ) ) { SDL_UnlockSurface( m_pScreen ); }
//Pause
SDL_Delay( 1 );
SDL_FreeSurface(Image);
return 0;
}
Code: Alles auswählen
#pragma once
#include <Windows.h>
#include <NuiApi.h>
#include <stdio.h>
#include "ProcessSDL.h"
class ProcessSDL;
class ShowKinect
{
public:
// thread handling
HANDLE m_hThNuiProcess;
HANDLE m_hEvNuiProcessStop;
HANDLE m_hNextDepthFrameEvent;
HANDLE m_hNextColorFrameEvent;
HANDLE m_hNextSkeletonEvent;
HANDLE m_pDepthStreamHandle;
HANDLE m_pVideoStreamHandle;
HANDLE hColorStreamHandle;
HANDLE hDepthStreamHandle;
HANDLE hSkeletonStreamHandle;
INuiSensor *m_pNuiSensor;
BSTR m_instanceId;
HRESULT hr;
byte *rgbBuffer;
int rgbPitch;
bool canGetRGBFrame;
bool gotRGBFrame;
ProcessSDL *p_myProcessSDL;
public:
int rgbImageWidth;
int rgbImageHeight;
int rgbImageDepth;
bool quitThread;
public:
ShowKinect(void);
virtual ~ShowKinect(void);
void zeroKinect();
HRESULT Nui_Init( ProcessSDL *myProcessSDL );
void StartThread();
void Nui_UnInit( );
void Nui_GotDepthAlert( );
int Nui_GotColorAlert( );
void Nui_GotSkeletonAlert( );
static DWORD WINAPI Nui_ProcessThread(LPVOID pParam);
DWORD WINAPI Nui_ProcessThread();
byte *GetRGBFrame() {return rgbBuffer;}
int GetRGBPitch() {return rgbPitch;}
bool GetCanGetRGBFrame() {return canGetRGBFrame;}
void SetCanGetRGBFrame(bool b) {canGetRGBFrame = b;}
bool GetGotRGBFrame() {return gotRGBFrame;}
void SetGotRGBFrame(bool b) {gotRGBFrame = b;}
//friend class EarTracker;
};
Code: Alles auswählen
#include "ShowKinect.h"
ShowKinect::ShowKinect(void):rgbImageWidth(640),rgbImageHeight(480),rgbImageDepth(32),canGetRGBFrame(false),gotRGBFrame(true),rgbPitch(0),rgbBuffer(NULL)
{
ShowKinect::zeroKinect();
}
ShowKinect::~ShowKinect(void)
{
}
void ShowKinect::zeroKinect()
{
if (m_pNuiSensor)
{
m_pNuiSensor = NULL;
}
m_hNextDepthFrameEvent = NULL;
m_hNextColorFrameEvent = NULL;
m_hNextSkeletonEvent = NULL;
m_pDepthStreamHandle = NULL;
m_pVideoStreamHandle = NULL;
m_hThNuiProcess = NULL;
m_hEvNuiProcessStop = NULL;
m_instanceId = NULL;
hr = NULL;
p_myProcessSDL = NULL;
quitThread = false;
}
HRESULT ShowKinect::Nui_Init( ProcessSDL* myProcessSDL)
{
p_myProcessSDL = myProcessSDL;
HRESULT hr;
if ( !m_pNuiSensor )
{
HRESULT hr = NuiCreateSensorByIndex(0, &m_pNuiSensor);
if ( FAILED(hr) )
{
return hr;
}
SysFreeString(m_instanceId);
m_instanceId = m_pNuiSensor->NuiDeviceConnectionId();
}
m_hNextDepthFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_hNextColorFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_hNextSkeletonEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX | NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR;
hr = m_pNuiSensor->NuiInitialize( nuiFlags );
if ( E_NUI_SKELETAL_ENGINE_BUSY == hr )
{
nuiFlags = NUI_INITIALIZE_FLAG_USES_DEPTH | NUI_INITIALIZE_FLAG_USES_COLOR;
hr = m_pNuiSensor->NuiInitialize( nuiFlags) ;
}
if ( FAILED( hr ) )
{
if ( E_NUI_DEVICE_IN_USE == hr )
{
MessageBox(NULL,"This Kinect sensor is already in use.", NULL,NULL );
}
else
{
MessageBox( NULL, "Failed to initialize Kinect.", NULL, NULL );
}
return hr;
}
if ( HasSkeletalEngine( m_pNuiSensor ) )
{
hr = m_pNuiSensor->NuiSkeletonTrackingEnable( m_hNextSkeletonEvent, 0 );
if( FAILED( hr ) )
{
MessageBox( NULL, "Could not enable skeleton tracking.", NULL, NULL );
return hr;
}
}
hr = m_pNuiSensor->NuiImageStreamOpen(
NUI_IMAGE_TYPE_COLOR,
NUI_IMAGE_RESOLUTION_640x480,
0,
2,
m_hNextColorFrameEvent,
&m_pVideoStreamHandle );
if ( FAILED( hr ) )
{
MessageBox( NULL, "Could not open image stream video.", NULL, NULL );
return hr;
}
hr = m_pNuiSensor->NuiImageStreamOpen(
HasSkeletalEngine(m_pNuiSensor) ? NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX : NUI_IMAGE_TYPE_DEPTH,
NUI_IMAGE_RESOLUTION_320x240,
0,
2,
m_hNextDepthFrameEvent,
&m_pDepthStreamHandle );
if ( FAILED( hr ) )
{
MessageBox( NULL, "Could not open image stream depth.", NULL, NULL );
return hr;
}
// Start the Nui processing thread
//m_hEvNuiProcessStop = CreateEvent( NULL, FALSE, FALSE, NULL );
//m_hThNuiProcess = CreateThread( NULL, 0, Nui_ProcessThread, this, 0, NULL );
return hr;
}
/*void ShowKinect::StartThread()
{
// Start the Nui processing thread
m_hEvNuiProcessStop = CreateEvent( NULL, FALSE, FALSE, NULL );
m_hThNuiProcess = CreateThread( NULL, 0, Nui_ProcessThread, this, 0, NULL );
}*/
void ShowKinect::Nui_UnInit( )
{
// Stop the Nui processing thread
if ( NULL != m_hEvNuiProcessStop )
{
// Signal the thread
SetEvent(m_hEvNuiProcessStop);
// Wait for thread to stop
if ( NULL != m_hThNuiProcess )
{
WaitForSingleObject( m_hThNuiProcess, INFINITE );
CloseHandle( m_hThNuiProcess );
}
CloseHandle( m_hEvNuiProcessStop );
}
if ( m_pNuiSensor )
{
m_pNuiSensor->NuiShutdown( );
}
if ( m_hNextSkeletonEvent && ( m_hNextSkeletonEvent != INVALID_HANDLE_VALUE ) )
{
CloseHandle( m_hNextSkeletonEvent );
m_hNextSkeletonEvent = NULL;
}
if ( m_hNextDepthFrameEvent && ( m_hNextDepthFrameEvent != INVALID_HANDLE_VALUE ) )
{
CloseHandle( m_hNextDepthFrameEvent );
m_hNextDepthFrameEvent = NULL;
}
if ( m_hNextColorFrameEvent && ( m_hNextColorFrameEvent != INVALID_HANDLE_VALUE ) )
{
CloseHandle( m_hNextColorFrameEvent );
m_hNextColorFrameEvent = NULL;
}
if ( m_pNuiSensor )
{
m_pNuiSensor->Release();
m_pNuiSensor = NULL;
}
}
/*
DWORD WINAPI ShowKinect::Nui_GotVideoAlert(LPVOID pParam)
{
ShowKinect *pthis = (ShowKinect *) pParam;
return pthis->Nui_GotVideoAlert();
}*/
DWORD WINAPI ShowKinect::Nui_ProcessThread(LPVOID pParam)
{
ShowKinect *pthis = (ShowKinect *) pParam;
return pthis->Nui_ProcessThread();
}
DWORD WINAPI ShowKinect::Nui_ProcessThread()
{
const int numEvents = 4;
HANDLE hEvents[numEvents] = { m_hEvNuiProcessStop, m_hNextDepthFrameEvent, m_hNextColorFrameEvent, m_hNextSkeletonEvent };
int nEventIdx;
// Main thread loop
bool continueProcessing = true;
while ( continueProcessing )
{
// Wait for any of the events to be signalled
nEventIdx = WaitForMultipleObjects( numEvents, hEvents, FALSE, 100 );
// Process signal events
switch ( nEventIdx )
{
case WAIT_TIMEOUT:
continue;
// If the stop event, stop looping and exit
case WAIT_OBJECT_0:
continueProcessing = false;
continue;
case WAIT_OBJECT_0 + 1:
Nui_GotDepthAlert();
break;
case WAIT_OBJECT_0 + 2:
Nui_GotColorAlert();
break;
case WAIT_OBJECT_0 + 3:
Nui_GotSkeletonAlert( );
break;
}
}
return 0;
}
int ShowKinect::Nui_GotColorAlert( )
{
while (!quitThread)
{
NUI_IMAGE_FRAME imageFrame;
HRESULT hr = m_pNuiSensor->NuiImageStreamGetNextFrame( m_pVideoStreamHandle, 0, &imageFrame );
if ( FAILED( hr ) )
{
return 1;
}
INuiFrameTexture * pTexture = imageFrame.pFrameTexture;
NUI_LOCKED_RECT LockedRect;
pTexture->LockRect( 0, &LockedRect, NULL, 0 );
if ( LockedRect.Pitch != 0 )
{
//Show Frame in SDL
p_myProcessSDL->ShowImageOnScreen(static_cast<BYTE *>(LockedRect.pBits), rgbImageWidth, rgbImageHeight, rgbImageDepth, 0, 0, LockedRect.Pitch);//Pos 0,0 => obere linke Ecke
}
else
{
OutputDebugString( "Buffer length of received texture is bogus\r\n" );
}
pTexture->UnlockRect( 0 );
m_pNuiSensor->NuiImageStreamReleaseFrame( m_pVideoStreamHandle, &imageFrame );
}
return 0;
}
void ShowKinect::Nui_GotDepthAlert( )
{
//TODO Grab Depth
}
void ShowKinect::Nui_GotSkeletonAlert()
{
//TODO Grab Skeleton bzw. Headposition
}