Add raw sources and sinks to cscore (#1670)

In some cases, we don't want the cv requirement to get an image, for instance interop with other versions of opencv

This enables getting a raw image, and handling conversions from the user side.
This commit is contained in:
Thad House
2019-05-30 19:12:05 -07:00
committed by Peter Johnson
parent 7de9477347
commit fb1239a2ad
37 changed files with 2218 additions and 504 deletions

View File

@@ -10,8 +10,14 @@
#include <wpi/raw_ostream.h>
#include "cscore_cpp.h"
#include "cscore_cv.h"
#include "cscore_raw.h"
#include "edu_wpi_cscore_CameraServerJNI.h"
namespace cv {
class Mat;
} // namespace cv
using namespace wpi::java;
//
@@ -23,6 +29,7 @@ static JavaVM* jvm = nullptr;
static JClass usbCameraInfoCls;
static JClass videoModeCls;
static JClass videoEventCls;
static JClass rawFrameCls;
static JException videoEx;
static JException nullPointerEx;
static JException unsupportedEx;
@@ -32,7 +39,8 @@ static JNIEnv* listenerEnv = nullptr;
static const JClassInit classes[] = {
{"edu/wpi/cscore/UsbCameraInfo", &usbCameraInfoCls},
{"edu/wpi/cscore/VideoMode", &videoModeCls},
{"edu/wpi/cscore/VideoEvent", &videoEventCls}};
{"edu/wpi/cscore/VideoEvent", &videoEventCls},
{"edu/wpi/cscore/raw/RawFrame", &rawFrameCls}};
static const JExceptionInit exceptions[] = {
{"edu/wpi/cscore/VideoException", &videoEx},
@@ -506,12 +514,12 @@ Java_edu_wpi_cscore_CameraServerJNI_createHttpCameraMulti
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Class: edu_wpi_cscore_CameraServerCvJNI
* Method: createCvSource
* Signature: (Ljava/lang/String;IIII)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_cscore_CameraServerJNI_createCvSource
Java_edu_wpi_cscore_CameraServerCvJNI_createCvSource
(JNIEnv* env, jclass, jstring name, jint pixelFormat, jint width, jint height,
jint fps)
{
@@ -530,6 +538,31 @@ Java_edu_wpi_cscore_CameraServerJNI_createCvSource
return val;
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: createRawSource
* Signature: (Ljava/lang/String;IIII)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_cscore_CameraServerJNI_createRawSource
(JNIEnv* env, jclass, jstring name, jint pixelFormat, jint width, jint height,
jint fps)
{
if (!name) {
nullPointerEx.Throw(env, "name cannot be null");
return 0;
}
CS_Status status = 0;
auto val = cs::CreateRawSource(
JStringRef{env, name}.str(),
cs::VideoMode{static_cast<cs::VideoMode::PixelFormat>(pixelFormat),
static_cast<int>(width), static_cast<int>(height),
static_cast<int>(fps)},
&status);
CheckStatus(env, status);
return val;
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: getSourceKind
@@ -1054,12 +1087,12 @@ Java_edu_wpi_cscore_CameraServerJNI_getHttpCameraUrls
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Class: edu_wpi_cscore_CameraServerCvJNI
* Method: putSourceFrame
* Signature: (IJ)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_cscore_CameraServerJNI_putSourceFrame
Java_edu_wpi_cscore_CameraServerCvJNI_putSourceFrame
(JNIEnv* env, jclass, jint source, jlong imageNativeObj)
{
cv::Mat& image = *((cv::Mat*)imageNativeObj);
@@ -1068,6 +1101,51 @@ Java_edu_wpi_cscore_CameraServerJNI_putSourceFrame
CheckStatus(env, status);
}
// int width, int height, int pixelFormat, int totalData
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: putRawSourceFrameBB
* Signature: (ILjava/lang/Object;IIII)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_cscore_CameraServerJNI_putRawSourceFrameBB
(JNIEnv* env, jclass, jint source, jobject byteBuffer, jint width,
jint height, jint pixelFormat, jint totalData)
{
CS_RawFrame rawFrame;
rawFrame.data =
reinterpret_cast<char*>(env->GetDirectBufferAddress(byteBuffer));
rawFrame.totalData = totalData;
rawFrame.pixelFormat = pixelFormat;
rawFrame.width = width;
rawFrame.height = height;
CS_Status status = 0;
cs::PutSourceFrame(source, rawFrame, &status);
CheckStatus(env, status);
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: putRawSourceFrame
* Signature: (IJIIII)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_cscore_CameraServerJNI_putRawSourceFrame
(JNIEnv* env, jclass, jint source, jlong ptr, jint width, jint height,
jint pixelFormat, jint totalData)
{
CS_RawFrame rawFrame;
rawFrame.data = reinterpret_cast<char*>(static_cast<intptr_t>(ptr));
rawFrame.totalData = totalData;
rawFrame.pixelFormat = pixelFormat;
rawFrame.width = width;
rawFrame.height = height;
CS_Status status = 0;
cs::PutSourceFrame(source, rawFrame, &status);
CheckStatus(env, status);
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: notifySourceError
@@ -1192,12 +1270,12 @@ Java_edu_wpi_cscore_CameraServerJNI_createMjpegServer
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Class: edu_wpi_cscore_CameraServerCvJNI
* Method: createCvSink
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_cscore_CameraServerJNI_createCvSink
Java_edu_wpi_cscore_CameraServerCvJNI_createCvSink
(JNIEnv* env, jclass, jstring name)
{
if (!name) {
@@ -1210,6 +1288,25 @@ Java_edu_wpi_cscore_CameraServerJNI_createCvSink
return val;
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: createRawSink
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_cscore_CameraServerJNI_createRawSink
(JNIEnv* env, jclass, jstring name)
{
if (!name) {
nullPointerEx.Throw(env, "name cannot be null");
return 0;
}
CS_Status status = 0;
auto val = cs::CreateRawSink(JStringRef{env, name}.str(), &status);
CheckStatus(env, status);
return val;
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: getSinkKind
@@ -1449,12 +1546,12 @@ Java_edu_wpi_cscore_CameraServerJNI_setSinkDescription
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Class: edu_wpi_cscore_CameraServerCvJNI
* Method: grabSinkFrame
* Signature: (IJ)J
*/
JNIEXPORT jlong JNICALL
Java_edu_wpi_cscore_CameraServerJNI_grabSinkFrame
Java_edu_wpi_cscore_CameraServerCvJNI_grabSinkFrame
(JNIEnv* env, jclass, jint sink, jlong imageNativeObj)
{
cv::Mat& image = *((cv::Mat*)imageNativeObj);
@@ -1465,12 +1562,12 @@ Java_edu_wpi_cscore_CameraServerJNI_grabSinkFrame
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Class: edu_wpi_cscore_CameraServerCvJNI
* Method: grabSinkFrameTimeout
* Signature: (IJD)J
*/
JNIEXPORT jlong JNICALL
Java_edu_wpi_cscore_CameraServerJNI_grabSinkFrameTimeout
Java_edu_wpi_cscore_CameraServerCvJNI_grabSinkFrameTimeout
(JNIEnv* env, jclass, jint sink, jlong imageNativeObj, jdouble timeout)
{
cv::Mat& image = *((cv::Mat*)imageNativeObj);
@@ -1480,6 +1577,75 @@ Java_edu_wpi_cscore_CameraServerJNI_grabSinkFrameTimeout
return rv;
}
static void SetRawFrameData(JNIEnv* env, jobject rawFrameObj,
jobject byteBuffer, bool didChangeDataPtr,
const CS_RawFrame& frame) {
static jmethodID setMethod =
env->GetMethodID(rawFrameCls, "setData", "(Ljava/nio/ByteBuffer;JIIII)V");
jlong framePtr = static_cast<jlong>(reinterpret_cast<intptr_t>(frame.data));
if (didChangeDataPtr) {
byteBuffer = env->NewDirectByteBuffer(frame.data, frame.dataLength);
}
env->CallVoidMethod(
rawFrameObj, setMethod, byteBuffer, framePtr,
static_cast<jint>(frame.totalData), static_cast<jint>(frame.width),
static_cast<jint>(frame.height), static_cast<jint>(frame.pixelFormat));
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: grabRawSinkFrameImpl
* Signature: (ILjava/lang/Object;JLjava/lang/Object;III)J
*/
JNIEXPORT jlong JNICALL
Java_edu_wpi_cscore_CameraServerJNI_grabRawSinkFrameImpl
(JNIEnv* env, jclass, jint sink, jobject rawFrameObj, jlong rawFramePtr,
jobject byteBuffer, jint width, jint height, jint pixelFormat)
{
CS_RawFrame* ptr =
reinterpret_cast<CS_RawFrame*>(static_cast<intptr_t>(rawFramePtr));
auto origDataPtr = ptr->data;
ptr->width = width;
ptr->height = height;
ptr->pixelFormat = pixelFormat;
CS_Status status = 0;
auto rv = cs::GrabSinkFrame(static_cast<CS_Sink>(sink), *ptr, &status);
if (!CheckStatus(env, status)) {
return 0;
}
SetRawFrameData(env, rawFrameObj, byteBuffer, origDataPtr != ptr->data, *ptr);
return rv;
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: grabRawSinkFrameTimeoutImpl
* Signature: (ILjava/lang/Object;JLjava/lang/Object;IIID)J
*/
JNIEXPORT jlong JNICALL
Java_edu_wpi_cscore_CameraServerJNI_grabRawSinkFrameTimeoutImpl
(JNIEnv* env, jclass, jint sink, jobject rawFrameObj, jlong rawFramePtr,
jobject byteBuffer, jint width, jint height, jint pixelFormat,
jdouble timeout)
{
CS_RawFrame* ptr =
reinterpret_cast<CS_RawFrame*>(static_cast<intptr_t>(rawFramePtr));
auto origDataPtr = ptr->data;
ptr->width = width;
ptr->height = height;
ptr->pixelFormat = pixelFormat;
CS_Status status = 0;
auto rv = cs::GrabSinkFrameTimeout(static_cast<CS_Sink>(sink), *ptr, timeout,
&status);
if (!CheckStatus(env, status)) {
return 0;
}
SetRawFrameData(env, rawFrameObj, byteBuffer, origDataPtr != ptr->data, *ptr);
return rv;
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: getSinkError
@@ -1781,4 +1947,32 @@ Java_edu_wpi_cscore_CameraServerJNI_setLogger
minLevel);
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: allocateRawFrame
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_edu_wpi_cscore_CameraServerJNI_allocateRawFrame
(JNIEnv*, jclass)
{
cs::RawFrame* rawFrame = new cs::RawFrame{};
intptr_t rawFrameIntPtr = reinterpret_cast<intptr_t>(rawFrame);
return static_cast<jlong>(rawFrameIntPtr);
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: freeRawFrame
* Signature: (J)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_cscore_CameraServerJNI_freeRawFrame
(JNIEnv*, jclass, jlong rawFrame)
{
cs::RawFrame* ptr =
reinterpret_cast<cs::RawFrame*>(static_cast<intptr_t>(rawFrame));
delete ptr;
}
} // extern "C"