Retrieving a list of supported video modes for depth stream

From the previous recipe we learned that we can use different video modes for the sensor's output, different resolutions, fps, and pixel formats. We also wrote a table of known supported resolutions and pixel formats. But in case you want to be sure about the list of supported types or if you have a new device and want to know the possible resolutions and pixel formats of one of its sensors, you can easily ask device driver. OpenNI gives us this possibility to retrieve a list of supported video modes for each sensor from the driver itself. In this recipe, we will try to show you how to retrieve a list of supported video modes for the Depth sensor and we will let the user select what video mode to use for our sensor.

Getting ready

Create a project in Visual Studio 2010 and prepare it for working with OpenNI using the Creating a project in Visual Studio 2010 recipe in this chapter.

How to do it...

Have a look at the following steps:

  1. Open your project and then the project's main source code file. Locate this line:
    int _tmain(int argc, _TCHAR* argv[])
    {
  2. Write the following code snippet above the preceding line of code:
    char ReadLastCharOfLine()
    {
      int newChar = 0;
      int lastChar;
      fflush(stdout);
    
      do 
      {
        lastChar = newChar;
        newChar = getchar();
      }
      while ((newChar != '
    ') && (newChar != EOF));
      return (char)lastChar;
     }
    
    bool HandleStatus(Status status)
    {
      if (status == STATUS_OK)
        return true;
      printf("ERROR: #%d, %s", status,
        OpenNI::getExtendedError());
      ReadLastCharOfLine();
      return false;
    }
  3. Locate this line again:
    int _tmain(int argc, _TCHAR* argv[])
    {
  4. Write the following code snippet below the preceding line of code:
      Status status = STATUS_OK;
      printf("Scanning machine for devices and loading "
          "modules/drivers ...
    ");
      status = OpenNI::initialize();
      if (!HandleStatus(status)) return 1;
      printf("Completed.
    ");
    
      printf("Press ENTER to continue.
    ");
      ReadLastCharOfLine();
    
      printf("Opening any device ...
    ");
      Device device;
      status = device.open(ANY_DEVICE);
      if (!HandleStatus(status)) return 1;
      printf("%s Opened, Completed.
    ",
        device.getDeviceInfo().getName());
    
      printf("Press ENTER to continue.
    ");
      ReadLastCharOfLine();
    
      printf("Checking if depth stream is supported ...
    ");
      if (false && !device.hasSensor(SENSOR_DEPTH))
      {
        printf("Depth stream not supported by this device. "
            "Press ENTER to exit.
    ");
        ReadLastCharOfLine();
        return 1;
      }
    
      printf("Asking device to create a depth stream ...
    ");
      VideoStream sensor;
      status = sensor.create(device,SENSOR_DEPTH);
      if (!HandleStatus(status)) return 1;
      printf("Completed.
    ");
    
      printf("Retrieving list of possible video modes for this "
            "stream ...
    ");
      const Array<VideoMode> *supportedVideoModes =
        &(sensor.getSensorInfo().getSupportedVideoModes());
      int numOfVideoModes = supportedVideoModes->getSize();
      if (numOfVideoModes == 0)
      {
        printf("No supported video mode available, press ENTER "
              "to exit.
    ");
        ReadLastCharOfLine();
        return 1;
      }
      
      for (int i = 0; i < numOfVideoModes; i++)
      {
        VideoMode vm = (*supportedVideoModes)[i];
        printf("%c. %dx%d at %dfps with %d format 
    ",
            'a' + i,
            vm.getResolutionX(),
            vm.getResolutionY(),
            vm.getFps(),
            vm.getPixelFormat());
      }
      printf("Completed.
    ");
    
      int selected = 0;
      do
      {
        printf("Select your desired video mode and then press "
              "ENTER to continue.
    ");
        selected = ReadLastCharOfLine() - 'a';
      } while (selected < 0 || selected >= numOfVideoModes);
    
      VideoMode vm = (*supportedVideoModes)[selected];
      printf("%dx%d at %dfps with %d format selected. "
            "Requesting video mode ... 
    ",
          vm.getResolutionX(),
          vm.getResolutionY(),
          vm.getFps(),
          vm.getPixelFormat());
      status = sensor.setVideoMode(vm);
      if (!HandleStatus(status)) return 1;
    
      printf("Accepted. Starting stream ...
    ");
      status = sensor.start();
      if (!HandleStatus(status)) return 1;
      printf("Completed.
    ");
    
      printf("Press ENTER to exit.
    ");
      ReadLastCharOfLine();
      sensor.destroy();
      device.close();
      OpenNI::shutdown();
      return 0;

How it works...

We defined our ReadLastCharOfLine() and HandleStatus() methods just like we did previously; read the previous recipes about that.

In the first line of the fourth step, we used the openni::OpenNI::initialize() method to initialize OpenNI and load modules and drivers. Again you can read previous recipes for more information.

Then we used the openni::Device::hasSensor() method to become sure if accessing the depth stream is possible and if so, then we use a variable of type openni::VideoStream to have access to the sensor's stream. These lines are just like the ones in the previous recipe, which talk about how to access a depth stream. Read it for a line-by-line description of code.

Our main code actually started when we defined a variable of type Array<VideoMode>* named supportedVideoModes. We talked a lot about the openni::Array template class in previous recipes, so I don't want to speak too much about it here.

For getting the list of supported video modes we need to call the openni::SensorInfo::getSupportedVideoModes() method that is located in the openni::SensorInfo class, but actually we don't have the openni::SensorInfo object associated with our openni::VideoStream that we created previously. So we need to use one of the openni::VideoStream methods named openni::VideoStream::getSensorInfo() that return the associated openni::SensorInfo object for our selected sensor and then using the return value of openni::SensorInfo::getSupportedVideoModes(), we can put our hand on the list of supported video modes of our desired sensor:

  const Array<VideoMode> *supportedVideoModes =
    &(sensor.getSensorInfo().getSupportedVideoModes());

Then to make sure that there is at least one supported video mode, we use openni::Array::getSize() to get the size of the returned array, and store it in a variable of type int named numOfVideoModes. If numOfVideoModes was equal to 0, there will be no supported video mode and we will show an error to the user and ask to press the Enter key. Then it returns 1 so as to terminate the program execution; but if it wasn't 0, then we can loop through this array and show its members to the user and ask him/her to select the desired video mode.

  int numOfVideoModes = supportedVideoModes->getSize();
  if (numOfVideoModes == 0)
  {
    printf("No supported video mode available, press ENTER ""to exit.
");
    ReadLastCharOfLine();
    return 1;
  }
  for (int i = 0; i < numOfVideoModes; i++)
  {
    ...
  }

In this loop we used a variable of type openni::VideoMode to temporarily store one of array's members , so as to show it to the user. Then using its method to return its properties and using printf(), we displayed different properties of this video mode to the user.

    VideoMode vm = (*supportedVideoModes)[i];
    printf("%c. %dx%d at %dfps with %d format 
",
       'a' + i,
        vm.getResolutionX(),
        vm.getResolutionY(),
        vm.getFps(),
        vm.getPixelFormat());

You may question why we used 'a' + i here. Actually the reason behind doing this is related to the ASCII code of characters. We know that the ASCII code for 'a' is 97 and other characters in the table follow this number ('b' is 98 and so on); so using this code (and keeping in mind that the value of i increases during the loop) we can print a character for each item in the list. So we can use these characters later to recognize the user's selection.

Going more deeply into the code you can see the usage of different methods of the openni::VideoMode class. Their names are self-describing and we don't see any reason to describe them one by one.

You can guess now that our next move is to ask the user to input one of these characters to show which video mode he/she selected.

  int selected = 0;
  do
  {
    printf("Select your desired video mode and then press "
          "ENTER to continue.
");
    selected = ReadLastCharOfLine() - 'a';
  } while (selected < 0 || selected >= numOfVideoModes);

As you can see we put our question and calling of ReadLastCharOfLine() method in a do while loop; we did that because we want to make sure that the user selects a character in the range of our options; and if he/she puts an incorrect input, we can ask him/her to do it again.

Here we have the same point as the last part of the code; we used 'a' character again but this time for reading the user input. As we know, the ReadLastCharOfLine() method will return the last character typed before the user presses the Enter key. This character can be converted to int. On the other hand, we don't need a character but we need to know the index of the selected video mode in the array. This is achieved using a simple subtraction of returned values of the ReadLastCharOfLine() method and the 'a' character. We can extract the index of the selected video mode by this method. You may ask how, so read the last 20 lines and think about the ASCII table and the order of characters again.

Anyway, using this number, which is an index of the selected video mode in our array, we can show the user his/her chosen item and then ask the sensor to use this video mode.

  VideoMode vm = (*supportedVideoModes)[selected];
  printf("%dx%d at %dfps with %d format selected. "
        "Requesting video mode ... 
",
      vm.getResolutionX(),
      vm.getResolutionY(),
      vm.getFps(),
      vm.getPixelFormat());
  status = sensor.setVideoMode(vm);
  if (!HandleStatus(status)) return 1;

Then we will ask the sensor to start generating data and after that we need to read the data, but reading the data is not part of this topic so we end it without really using the sensor's data.

  printf("Accepted. Starting stream ...
");
  status = sensor.start();
  if (!HandleStatus(status)) return 1;
  printf("Completed.
");

  printf("Press ENTER to exit.
");
  ReadLastCharOfLine();
  sensor.destroy();
  device.close();
  OpenNI::shutdown();
  return 0;
How it works...

See also

  • The Reading and showing a frame from the depth sensor recipe in Chapter 3, Using Low-level Data
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.97.53