PrimeSense / Sensor

PrimeSensor Modules for OpenNI
www.primesense.com
Apache License 2.0
380 stars 572 forks source link

Broken RGB Image #6

Open sma1 opened 12 years ago

sma1 commented 12 years ago

I found a problem in the XnUncompressedBayerProcessor::OnEndOfFrame() which was causing RGB broken image. This was happening on windows 7 at least.

XnImageProcessor has the general framework to reject images if not enough data was collected, but since the bayer conversion is always done in OnEndOfFrame() regardless of how much data was collected, the size of the RGB buffer will always be the expected size.

void XnImageProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) { if (!m_bCompressedOutput) { // make sure data size is right XnUInt32 nExpectedSize = CalculateExpectedSize(); if (GetWriteBuffer()->GetSize() != nExpectedSize) { xnLogWarning(XN_MASK_SENSOR_READ, "Read: Image buffer is corrupt. Size is %u (!= %u)", GetWriteBuffer()->GetSize(), nExpectedSize); FrameIsCorrupted(); } }

// call base
XnFrameStreamProcessor::OnEndOfFrame(pHeader);

}

I did something like this and now when the frames don't have the expected size the frame is thrown away

void XnUncompressedBayerProcessor::OnEndOfFrame(const XnSensorProtocolResponseHeader* pHeader) { XN_PROFILING_START_SECTION("XnUncompressedBayerProcessor::OnEndOfFrame")

xnOSEnterCriticalSection(&m_hLockCS);
try
{
    // if data was written to temp buffer, convert it now
    switch (GetStream()->GetOutputFormat())
    {
    case XN_OUTPUT_FORMAT_GRAYSCALE8:
        break;
    case XN_OUTPUT_FORMAT_RGB24:
        {
            if (m_UncompressedBayerBuffer.GetSize() != GetActualXRes() * GetActualYRes())
            {
                FrameIsCorrupted();
            }
            else
            {
                Bayer2RGB888(m_UncompressedBayerBuffer.GetData(), GetWriteBuffer()->GetUnsafeWritePointer(), GetActualXRes(), GetActualYRes(), 1, 0);
                                    GetWriteBuffer()->UnsafeUpdateSize(GetActualXRes()*GetActualYRes()*3); 
            }   
            m_UncompressedBayerBuffer.Reset();
        }
        break;
    }

    XnImageProcessor::OnEndOfFrame(pHeader);

}
catch (...)
{
}
xnOSLeaveCriticalSection(&m_hLockCS);
XN_PROFILING_END_SECTION

}

I saw some people think it happened more often under a heavy CPU load so I tried to simulate that by having the conversion take longer with a 50 ms sleep in Bayer.cpp before returning from Bayer2RGB888(). This caused the problem to happen a lot for us which was helpful in tracking the problem down. Before that sometimes it would happen several times in a row and other times we wouldn't see it for days.

This problem seems to be in both avin2's version and also in the non modded version from the OpenNI website (https://github.com/PrimeSense/Sensor/blob/unstable/Source/XnDeviceSensorV2/XnUncompressedBayerProcessor.cpp).

How do I go about submitting this code so it gets into different distributions?

gaborpapp commented 11 years ago

This fix just saved me after struggling a lot with this problem. Thank you!