Receiving Media Toolkit bitmapped images - GetDataSize()/GetMediaBodySize() return 0; GetDataPointer()/GetMediaBodyPointer() return nullptr

I have read through https://developer.milestonesys.com/s/question/0D50O000049rc7RSAQ/c-media-toolkit-raw-image which seems to be running into the same issue but I don’t see what I’m doing differently from the proposed solution.

Here’s the configuration XML used to create an ImToolKit instance.

"<toolkit type='source'>"
"  <provider>mmp</provider>"
"  <config>"
"      <image_color_format_convert format='BGR24'>"
"        <video_decoder number_of_threads='4'>"
"          <toolkit type='source'>"
"            <provider>is</provider>"
"            <config>"
"              <server_uri>" + vmsRecorderUri + "</server_uri>"
"              <device_id>" + cameraId_ + "</device_id>"
"              <compressionrate>100</compressionrate>"
"              <alwaysstdjpeg>no</alwaysstdjpeg>"
"              <media_type>VIDEO</media_type>" + authorizationToken_ +
"              <maximum_queue_size>5</maximum_queue_size>"
"            </config>"
"          </toolkit>"
"        </video_decoder>"
"      </image_color_format_convert>"
"  </config>"
"</toolkit>";

I used the ComponentSample config, removed the JPEG transcoding and added image_color_format_convert, compressionrate, and alwaysstdjpeg elements (but even if I omit the last two the issue persists).

Then, my code to retrieve images - with downcasting to ImImage - looks like this:

// NmToolkit::ImData * imData_
if (liveSourceToolkit_->GetLiveData(imData_, 3000) == NmToolkit::ImLiveSourceToolkit::LIVE_DATA_RETRIEVED)
{
  // Downcast to bitmap image
  NmToolkit::ImImage * imPtr = dynamic_cast<NmToolkit::ImImage *>(imData_);
  if (imPtr != nullptr)
  {
    switch (imPtr->GetImageFormat())
    {
      case NmToolkit::ImImage::BGR24:
      {
         // Query data size/pointer/perform conversion
      }
      case NmToolkit::ImImage::RGB24:             
      {
         ...
      }

I am able to get the SDK to send me either BGR24 or RGB24 formats but I can’t get through to the actual data - GetDataPointer() and GetMediaBodyPointer() both return nullptr. However, something seems to be in there because ImImage reports the correct image size (though I’m confused why it’s reporting that there’s only one plane/channel, I expect 3)

// Output of imPtr->GetImageWidth(), imPtr->GetImageHeight()
Image dims are w=1280, h=720
 
// Output of imPtr->GetPlaneHeight(0), imPtr->GetPlaneHeight(1), imPtr->GetPlaneHeight(2), imPtr->GetPlaneWidth(0), imPtr->GetPlaneWidth(1), imPtr->GetPlaneWidth(2)
Plane data size, h0=720, h1=0, h2=0, w0=1280, w1=0, w2=0

Hi Andrey,

Sorry for the late reply first of all :).

But to get the data of the BGR24 image you need to use the ImImage pointer to get the pointer to plane 0 and calculate the image size from the hight and stride:

byte* data = imPtr->GetPlanePointer(0);

size_t len = imPtr->GetPlaneStride(0) * imPtr->GetPlaneHeight(0);

The planes are only 1(index 0) of because of the color format (similar to gray scale).

So this should give you the decoded image in the format you need.

Kind regards,

Artur

@Artur Magaljan (Milestone Systems)​ - thanks, better late, than never. I worked around in the meantime by requesting and decoding JPEGs from the server but after implementing your suggestion I have both RGB24 and BGR24 working (same thing, really, just different pixel order). Out of curiosity, is there documentation on this that I missed?

Hi Andrey,

The functions i used are in the documentation but i dont think there is a sample using them or a description in what specific case to use them. So you have not missed anything, just your specific case is not described.

Hope you can use the “new” way of doing this :).

OK, got it. Yeah, the new way is working well, thank you.