PostADay-Round2#4 – Cinder Kinect OpenNI – Playing and seeking a .oni file

I’ve been using the Kinect for the past two weeks. It’s an amazing device, very fun to code for.
To be honest, the Kinect really provides a webcam image, and a depth map… That’s really all it adds to the mix. While that’s a lot – people (by that i mean gadget blogs, non-coder blogs) seem to think that you can just plug this thing and you will get instant Minority Report.

That’s not how it works, in fact the REAL magic of the kinect is the OpenNI drivers provided by Primesense. Primesense are the people who created the technology which microsoft has licensed. Their OpenNI drivers provide the amazing skeleton tracking / user tracking / hand tracking / gesture tracking stuff that people associate with the Kinect.

When trying to create something using the Kinect it can be somewhat annoying having to get up, calibrate it with the proper use, and then start moving around to test a variable you changed. For that reason, the OpenNI library provides a way to record, and also create files which it calls “.oni”

The easiest way to create your own .oni file, is to record one with the NIViewer sample project. However just as useful if that’s too annoying, is the skeleton.oni file provided by primesense.

These files can actually then be played by the the library, and you can even seek within them to skip around to the interesting parts you want to test.

Here’s how to play back a .oni file, it’s actually very simple. This file makes some assumptions but i’ll explain those later.

void CinderRibbons::setupWithOniFile( std::string filepath ) {
  nRetVal = skeleton->mContext.OpenFileRecording( filepath.c_str() );
		// File opened
		CHECK_RC(nRetVal, "Open File Recording", true);
		// Get recording 'player'
		nRetVal = skeleton->mContext.FindExistingNode(XN_NODE_TYPE_PLAYER, skeleton->mPlayer);
		CHECK_RC(nRetVal, "Find player generator", true);
void CinderRibbons::seekToFrame( XnUInt32 seekPosition )
	CinderOpenNISkeleton *skeleton = CINDERSKELETON;
	XnStatus nRetVal = XN_STATUS_OK;
    // Make sure we're ready
	if(!openNIThread || !skeleton->mDepthGenerator)
	const XnChar*	nodeName		= skeleton->mDepthGenerator.GetName();
	XnUInt32		currentFrame	= 0;
	XnUInt32		totalFames		= 0;
	nRetVal = skeleton->mPlayer.TellFrame(nodeName, currentFrame);
	CHECK_RC(nRetVal, "Getting CURRENT frame", false);
	nRetVal = skeleton->mPlayer.GetNumFrames(nodeName, totalFames);
	CHECK_RC(nRetVal, "Getting TOTAL frames", false);
	// Stop the thread before trying to seek
    // We'll be offset currentFrame and passing this value to the seek funciton which takes a relative position
    XnUInt32        seekAbsolutePos = -currentFrame + seekPosition;
    // Seek
	nRetVal = skeleton->mPlayer.SeekToFrame(nodeName, seekAbsolutePosition, XN_PLAYER_SEEK_CUR);
	CHECK_RC(nRetVal, "Seeking to frame", false);
	// Update the data now that we're at the new position
	skeleton->mDepthGenerator.GetMetaData( skeleton->mDepthMD );
	skeleton->mUserGenerator.GetUserPixels(0, skeleton->mSceneMD);
	// Restart the thread...
	// Thread count stays the same - but there is a race condition on a nanoscale
	// Had some problems, will have to look into later - for now we're creating a new thread.
	openNIThread = new OpenNIThreadRunner();
	// Output debug
	app::console() << "Seeked to frame" << currentFrame+seekPosition << std::endl;

2 thoughts on “PostADay-Round2#4 – Cinder Kinect OpenNI – Playing and seeking a .oni file”

  1. Yes,I’m trying something doing like this but in openni library and in samples there is an example project NiViewer.And i’m trying to take inputs from SkeletonRec.oni.But i could not.If you could help me i will be very happy.Thanks a lot.

Leave a Reply

Your email address will not be published. Required fields are marked *