Мое приложение в Unity и использует Google Tango SDK. Я получаю буфер изображений YUV, доставленный в OnTangoImageAvailableEventHandler
оттуда мне нужно получить отдельные буферы Y, U и V и передать их плагину C ++. Вот что я делаю:
public class LibraryWrapper {
[DllImport ("library")]
public static extern void incomingI420Frame(uint width, uint height,
uint strideY, uint strideU, uint strideV,
IntPtr yPlane, IntPtr uPlane, IntPtr vPlane);
}
public void OnTangoImageAvailableEventHandler(Tango.TangoEnums.TangoCameraId cameraId, Tango.TangoUnityImageData imageBuffer)
{
uint offset = imageData.stride; // offset, because first scanline is a metadata, according to Tango documentation
uint yPlaneSize = imageData.width * imageData.height;
uint vPlaneSize = imageData.width / 2 * imageData.height / 2;
uint uPlaneSize = vPlaneSize;
GCHandle pinnedBuffer = GCHandle.Alloc (imageData.data, GCHandleType.Pinned);
IntPtr yPlane = new IntPtr (pinnedBuffer.AddrOfPinnedObject ().ToInt64 () + offset);
offset += yPlaneSize;
IntPtr vPlane = new IntPtr (pinnedBuffer.AddrOfPinnedObject ().ToInt64 () + offset);
offset += vPlaneSize;
IntPtr uPlane = new IntPtr (pinnedBuffer.AddrOfPinnedObject ().ToInt64 () + offset);
Debug.Log ("processing frame... " + imageData.width + "x" + imageData.height + " total size " + imageData.data.Length);
Debug.Log ("stride " + imageData.stride + ". yplane " + String.Format("{0:X}", yPlane) + " (" + yPlaneSize + " bytes)");
Debug.Log ("uplane " + String.Format("{0:X}", uPlane) + " (" + uPlaneSize + " bytes)");
Debug.Log ("vplane " + String.Format("{0:X}", vPlane) + " (" + vPlaneSize + " bytes)");
LibraryWrapper.incomingI420Frame (imageData.width, imageData.height,
yPlaneSize, uPlaneSize, vPlaneSize, yPlane, uPlane, vPlane);
pinnedBuffer.Free ();
}
Функция библиотеки C ++:
void incomingI420Frame(
const unsigned int width,
const unsigned int height,
const unsigned int strideY,
const unsigned int strideU,
const unsigned int strideV,
const unsigned char* yBuffer,
const unsigned char* uBuffer,
const unsigned char* vBuffer);
Приложение падает на memcpy
данных:
08-09 14:42:42.789 9384 9401 F libc : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 9401 (UnityMain)
backtrace:
08-09 14:42:42.907 542 542 F DEBUG : #00 pc 00016978 /system/lib/libc.so (__memcpy_base+104)
Очевидно, я запутался с указателем, однако я не вижу, как — я использую GCHandle
закрепить буфер, чтобы он не двигался, верно? Более того, вызов C ++ происходит в том же потоке, поэтому я сомневаюсь, что у GC когда-нибудь будет возможность прикоснуться к буферу. Таким образом, я подозреваю, что ошибка может заключаться в вычислении указателей для данных Y, U или V.
Задача ещё не решена.
Других решений пока нет …