diff --git a/apriltag/src/main/java/edu/wpi/first/apriltag/AprilTag.java b/apriltag/src/main/java/edu/wpi/first/apriltag/AprilTag.java index 8e455f6dc9..ebd74db2e3 100644 --- a/apriltag/src/main/java/edu/wpi/first/apriltag/AprilTag.java +++ b/apriltag/src/main/java/edu/wpi/first/apriltag/AprilTag.java @@ -6,7 +6,9 @@ package edu.wpi.first.apriltag; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import edu.wpi.first.apriltag.jni.AprilTagJNI; import edu.wpi.first.math.geometry.Pose3d; +import edu.wpi.first.util.RawFrame; import java.util.Objects; @SuppressWarnings("MemberName") @@ -44,4 +46,28 @@ public class AprilTag { public String toString() { return "AprilTag(ID: " + ID + ", pose: " + pose + ")"; } + + /** + * Generates a RawFrame containing the apriltag with the id with family 16h5 passed in. + * + * @param id id + * @return A RawFrame containing the AprilTag image + */ + public static RawFrame generate16h5AprilTagImage(int id) { + RawFrame generatedImage = new RawFrame(); + AprilTagJNI.generate16h5AprilTagImage(id, generatedImage.getDataPtr()); + return generatedImage; + } + + /** + * Generates a RawFrame containing the apriltag with the id with family 36h11 passed in. + * + * @param id id + * @return A RawFrame containing the AprilTag image + */ + public static RawFrame generate36h11AprilTagImage(int id) { + RawFrame generatedImage = new RawFrame(); + AprilTagJNI.generate36h11AprilTagImage(id, generatedImage.getDataPtr()); + return generatedImage; + } } diff --git a/apriltag/src/main/java/edu/wpi/first/apriltag/jni/AprilTagJNI.java b/apriltag/src/main/java/edu/wpi/first/apriltag/jni/AprilTagJNI.java index f0a23fce41..d8227445ab 100644 --- a/apriltag/src/main/java/edu/wpi/first/apriltag/jni/AprilTagJNI.java +++ b/apriltag/src/main/java/edu/wpi/first/apriltag/jni/AprilTagJNI.java @@ -189,4 +189,8 @@ public class AprilTagJNI { double fy, double cx, double cy); + + public static native void generate16h5AprilTagImage(int id, long nativeAddr); + + public static native void generate36h11AprilTagImage(int id, long nativeAddr); } diff --git a/apriltag/src/main/native/cpp/AprilTag.cpp b/apriltag/src/main/native/cpp/AprilTag.cpp index 38055736e1..d5f5e8fe24 100644 --- a/apriltag/src/main/native/cpp/AprilTag.cpp +++ b/apriltag/src/main/native/cpp/AprilTag.cpp @@ -6,8 +6,56 @@ #include +#ifdef _WIN32 +#pragma warning(disable : 4200) +#elif defined(__clang__) +#pragma clang diagnostic ignored "-Wc99-extensions" +#elif defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +#include "apriltag.h" +#include "tag16h5.h" +#include "tag36h11.h" + using namespace frc; +wpi::RawFrame AprilTag::Generate36h11AprilTagImage(int id) { + apriltag_family_t* tagFamily = tag36h11_create(); + image_u8_t* image = apriltag_to_image(tagFamily, id); + wpi::RawFrame markerFrame{}; + size_t totalDataSize = image->height * image->stride * sizeof(char); + markerFrame.data = static_cast( + std::calloc(image->height * image->stride, sizeof(char))); + std::memcpy(markerFrame.data, image->buf, totalDataSize); + markerFrame.dataLength = image->width; + markerFrame.height = image->height; + markerFrame.pixelFormat = WPI_PIXFMT_GRAY; + markerFrame.width = image->stride; + markerFrame.totalData = totalDataSize; + image_u8_destroy(image); + tag36h11_destroy(tagFamily); + return markerFrame; +} + +wpi::RawFrame AprilTag::Generate16h5AprilTagImage(int id) { + apriltag_family_t* tagFamily = tag16h5_create(); + image_u8_t* image = apriltag_to_image(tagFamily, id); + wpi::RawFrame markerFrame{}; + size_t totalDataSize = image->height * image->stride * sizeof(char); + markerFrame.data = static_cast( + std::calloc(image->height * image->stride, sizeof(char))); + std::memcpy(markerFrame.data, image->buf, totalDataSize); + markerFrame.dataLength = image->width; + markerFrame.height = image->height; + markerFrame.pixelFormat = WPI_PIXFMT_GRAY; + markerFrame.width = image->stride; + markerFrame.totalData = totalDataSize; + image_u8_destroy(image); + tag16h5_destroy(tagFamily); + return markerFrame; +} + void frc::to_json(wpi::json& json, const AprilTag& apriltag) { json = wpi::json{{"ID", apriltag.ID}, {"pose", apriltag.pose}}; } diff --git a/apriltag/src/main/native/cpp/jni/AprilTagJNI.cpp b/apriltag/src/main/native/cpp/jni/AprilTagJNI.cpp index c957b2da8d..146edaf1c9 100644 --- a/apriltag/src/main/native/cpp/jni/AprilTagJNI.cpp +++ b/apriltag/src/main/native/cpp/jni/AprilTagJNI.cpp @@ -8,6 +8,7 @@ #include #include "edu_wpi_first_apriltag_jni_AprilTagJNI.h" +#include "frc/apriltag/AprilTag.h" #include "frc/apriltag/AprilTagDetector.h" #include "frc/apriltag/AprilTagPoseEstimator.h" @@ -587,4 +588,30 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePose return MakeJObject(env, estimator.Estimate(harr, carr)); } +/* + * Class: edu_wpi_first_apriltag_jni_AprilTagJNI + * Method: generate16h5AprilTagImage + * Signature: (IJ)V + */ +JNIEXPORT void JNICALL +Java_edu_wpi_first_apriltag_jni_AprilTagJNI_generate16h5AprilTagImage + (JNIEnv* env, jclass, jint id, jlong framePtr) +{ + wpi::RawFrame* javaRawFrame = (wpi::RawFrame*)framePtr; + *javaRawFrame = AprilTag::Generate16h5AprilTagImage(id); +} + +/* + * Class: edu_wpi_first_apriltag_jni_AprilTagJNI + * Method: generate36h11AprilTagImage + * Signature: (IJ)V + */ +JNIEXPORT void JNICALL +Java_edu_wpi_first_apriltag_jni_AprilTagJNI_generate36h11AprilTagImage + (JNIEnv* env, jclass, jint id, jlong framePtr) +{ + wpi::RawFrame* javaRawFrame = (wpi::RawFrame*)framePtr; + *javaRawFrame = AprilTag::Generate36h11AprilTagImage(id); +} + } // extern "C" diff --git a/apriltag/src/main/native/include/frc/apriltag/AprilTag.h b/apriltag/src/main/native/include/frc/apriltag/AprilTag.h index ba2453020f..6449c1e440 100644 --- a/apriltag/src/main/native/include/frc/apriltag/AprilTag.h +++ b/apriltag/src/main/native/include/frc/apriltag/AprilTag.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include @@ -20,6 +21,9 @@ struct WPILIB_DLLEXPORT AprilTag { * Checks equality between this AprilTag and another object. */ bool operator==(const AprilTag&) const = default; + + static wpi::RawFrame Generate36h11AprilTagImage(int id); + static wpi::RawFrame Generate16h5AprilTagImage(int id); }; WPILIB_DLLEXPORT diff --git a/cscore/src/main/java/edu/wpi/first/cscore/CameraServerJNI.java b/cscore/src/main/java/edu/wpi/first/cscore/CameraServerJNI.java index 148be68cfc..54c4d321ed 100644 --- a/cscore/src/main/java/edu/wpi/first/cscore/CameraServerJNI.java +++ b/cscore/src/main/java/edu/wpi/first/cscore/CameraServerJNI.java @@ -4,7 +4,7 @@ package edu.wpi.first.cscore; -import edu.wpi.first.cscore.raw.RawFrame; +import edu.wpi.first.util.RawFrame; import edu.wpi.first.util.RuntimeLoader; import java.io.IOException; import java.nio.ByteBuffer; @@ -387,10 +387,6 @@ public class CameraServerJNI { public static native String[] getNetworkInterfaces(); - public static native long allocateRawFrame(); - - public static native void freeRawFrame(long frame); - public static native void runMainRunLoop(); public static native int runMainRunLoopTimeout(double timeoutSeconds); diff --git a/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSink.java b/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSink.java index ae5b0ef94c..5d4bb1a5ea 100644 --- a/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSink.java +++ b/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSink.java @@ -6,6 +6,7 @@ package edu.wpi.first.cscore.raw; import edu.wpi.first.cscore.CameraServerJNI; import edu.wpi.first.cscore.ImageSink; +import edu.wpi.first.util.RawFrame; /** * A sink for user code to accept video frames as raw bytes. diff --git a/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSource.java b/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSource.java index f1be05065b..900a6705ec 100644 --- a/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSource.java +++ b/cscore/src/main/java/edu/wpi/first/cscore/raw/RawSource.java @@ -7,6 +7,7 @@ package edu.wpi.first.cscore.raw; import edu.wpi.first.cscore.CameraServerJNI; import edu.wpi.first.cscore.ImageSource; import edu.wpi.first.cscore.VideoMode; +import edu.wpi.first.util.RawFrame; /** * A source for user code to provide video frames as raw bytes. diff --git a/cscore/src/main/native/cpp/RawSinkImpl.cpp b/cscore/src/main/native/cpp/RawSinkImpl.cpp index 31c57d2cec..877de1d5ed 100644 --- a/cscore/src/main/native/cpp/RawSinkImpl.cpp +++ b/cscore/src/main/native/cpp/RawSinkImpl.cpp @@ -40,7 +40,7 @@ void RawSinkImpl::Stop() { } } -uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image) { +uint64_t RawSinkImpl::GrabFrame(WPI_RawFrame& image) { SetEnabled(true); auto source = GetSource(); @@ -60,7 +60,7 @@ uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image) { return GrabFrameImpl(image, frame); } -uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image, double timeout) { +uint64_t RawSinkImpl::GrabFrame(WPI_RawFrame& image, double timeout) { SetEnabled(true); auto source = GetSource(); @@ -80,11 +80,11 @@ uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image, double timeout) { return GrabFrameImpl(image, frame); } -uint64_t RawSinkImpl::GrabFrameImpl(CS_RawFrame& rawFrame, +uint64_t RawSinkImpl::GrabFrameImpl(WPI_RawFrame& rawFrame, Frame& incomingFrame) { Image* newImage = nullptr; - if (rawFrame.pixelFormat == CS_PixelFormat::CS_PIXFMT_UNKNOWN) { + if (rawFrame.pixelFormat == WPI_PixelFormat::WPI_PIXFMT_UNKNOWN) { // Always get incoming image directly on unknown newImage = incomingFrame.GetExistingImage(0); } else { @@ -106,7 +106,7 @@ uint64_t RawSinkImpl::GrabFrameImpl(CS_RawFrame& rawFrame, return 0; } - CS_AllocateRawFrameData(&rawFrame, newImage->size()); + WPI_AllocateRawFrameData(&rawFrame, newImage->size()); rawFrame.height = newImage->height; rawFrame.width = newImage->width; rawFrame.pixelFormat = newImage->pixelFormat; @@ -159,7 +159,7 @@ CS_Sink CreateRawSinkCallback(std::string_view name, inst.telemetry, processFrame)); } -uint64_t GrabSinkFrame(CS_Sink sink, CS_RawFrame& image, CS_Status* status) { +uint64_t GrabSinkFrame(CS_Sink sink, WPI_RawFrame& image, CS_Status* status) { auto data = Instance::GetInstance().GetSink(sink); if (!data || data->kind != CS_SINK_RAW) { *status = CS_INVALID_HANDLE; @@ -168,7 +168,7 @@ uint64_t GrabSinkFrame(CS_Sink sink, CS_RawFrame& image, CS_Status* status) { return static_cast(*data->sink).GrabFrame(image); } -uint64_t GrabSinkFrameTimeout(CS_Sink sink, CS_RawFrame& image, double timeout, +uint64_t GrabSinkFrameTimeout(CS_Sink sink, WPI_RawFrame& image, double timeout, CS_Status* status) { auto data = Instance::GetInstance().GetSink(sink); if (!data || data->kind != CS_SINK_RAW) { @@ -192,12 +192,12 @@ CS_Sink CS_CreateRawSinkCallback(const char* name, void* data, name, [=](uint64_t time) { processFrame(data, time); }, status); } -uint64_t CS_GrabRawSinkFrame(CS_Sink sink, struct CS_RawFrame* image, +uint64_t CS_GrabRawSinkFrame(CS_Sink sink, struct WPI_RawFrame* image, CS_Status* status) { return cs::GrabSinkFrame(sink, *image, status); } -uint64_t CS_GrabRawSinkFrameTimeout(CS_Sink sink, struct CS_RawFrame* image, +uint64_t CS_GrabRawSinkFrameTimeout(CS_Sink sink, struct WPI_RawFrame* image, double timeout, CS_Status* status) { return cs::GrabSinkFrameTimeout(sink, *image, timeout, status); } diff --git a/cscore/src/main/native/cpp/RawSinkImpl.h b/cscore/src/main/native/cpp/RawSinkImpl.h index 6e8032a101..ac719764ec 100644 --- a/cscore/src/main/native/cpp/RawSinkImpl.h +++ b/cscore/src/main/native/cpp/RawSinkImpl.h @@ -32,13 +32,13 @@ class RawSinkImpl : public SinkImpl { void Stop(); - uint64_t GrabFrame(CS_RawFrame& frame); - uint64_t GrabFrame(CS_RawFrame& frame, double timeout); + uint64_t GrabFrame(WPI_RawFrame& frame); + uint64_t GrabFrame(WPI_RawFrame& frame, double timeout); private: void ThreadMain(); - uint64_t GrabFrameImpl(CS_RawFrame& rawFrame, Frame& incomingFrame); + uint64_t GrabFrameImpl(WPI_RawFrame& rawFrame, Frame& incomingFrame); std::atomic_bool m_active; // set to false to terminate threads std::thread m_thread; diff --git a/cscore/src/main/native/cpp/RawSourceImpl.cpp b/cscore/src/main/native/cpp/RawSourceImpl.cpp index bad26a05cf..eab9a7b4de 100644 --- a/cscore/src/main/native/cpp/RawSourceImpl.cpp +++ b/cscore/src/main/native/cpp/RawSourceImpl.cpp @@ -21,7 +21,7 @@ RawSourceImpl::RawSourceImpl(std::string_view name, wpi::Logger& logger, RawSourceImpl::~RawSourceImpl() = default; -void RawSourceImpl::PutFrame(const CS_RawFrame& image) { +void RawSourceImpl::PutFrame(const WPI_RawFrame& image) { int type; switch (image.pixelFormat) { case VideoMode::kYUYV: @@ -57,7 +57,7 @@ CS_Source CreateRawSource(std::string_view name, const VideoMode& mode, inst.telemetry, mode)); } -void PutSourceFrame(CS_Source source, const CS_RawFrame& image, +void PutSourceFrame(CS_Source source, const WPI_RawFrame& image, CS_Status* status) { auto data = Instance::GetInstance().GetSource(source); if (!data || data->kind != CS_SOURCE_RAW) { @@ -75,7 +75,7 @@ CS_Source CS_CreateRawSource(const char* name, const CS_VideoMode* mode, status); } -void CS_PutRawSourceFrame(CS_Source source, const struct CS_RawFrame* image, +void CS_PutRawSourceFrame(CS_Source source, const struct WPI_RawFrame* image, CS_Status* status) { return cs::PutSourceFrame(source, *image, status); } diff --git a/cscore/src/main/native/cpp/RawSourceImpl.h b/cscore/src/main/native/cpp/RawSourceImpl.h index 5887ed4203..44a20b90c0 100644 --- a/cscore/src/main/native/cpp/RawSourceImpl.h +++ b/cscore/src/main/native/cpp/RawSourceImpl.h @@ -25,7 +25,7 @@ class RawSourceImpl : public ConfigurableSourceImpl { ~RawSourceImpl() override; // Raw-specific functions - void PutFrame(const CS_RawFrame& image); + void PutFrame(const WPI_RawFrame& image); private: std::atomic_bool m_connected{true}; diff --git a/cscore/src/main/native/cpp/cscore_c.cpp b/cscore/src/main/native/cpp/cscore_c.cpp index 3fbbfcda37..45583acc57 100644 --- a/cscore/src/main/native/cpp/cscore_c.cpp +++ b/cscore/src/main/native/cpp/cscore_c.cpp @@ -181,7 +181,7 @@ CS_Bool CS_SetSourceVideoMode(CS_Source source, const CS_VideoMode* mode, } CS_Bool CS_SetSourceVideoModeDiscrete(CS_Source source, - enum CS_PixelFormat pixelFormat, + enum WPI_PixelFormat pixelFormat, int width, int height, int fps, CS_Status* status) { return cs::SetSourceVideoMode( @@ -193,7 +193,7 @@ CS_Bool CS_SetSourceVideoModeDiscrete(CS_Source source, } CS_Bool CS_SetSourcePixelFormat(CS_Source source, - enum CS_PixelFormat pixelFormat, + enum WPI_PixelFormat pixelFormat, CS_Status* status) { return cs::SetSourcePixelFormat( source, @@ -541,25 +541,4 @@ void CS_FreeNetworkInterfaces(char** interfaces, int count) { std::free(interfaces); } -void CS_AllocateRawFrameData(CS_RawFrame* frame, int requestedSize) { - if (frame->dataLength >= requestedSize) { - return; - } - if (frame->data) { - frame->data = - static_cast(wpi::safe_realloc(frame->data, requestedSize)); - } else { - frame->data = static_cast(wpi::safe_malloc(requestedSize)); - } - frame->dataLength = requestedSize; -} - -void CS_FreeRawFrameData(CS_RawFrame* frame) { - if (frame->data) { - std::free(frame->data); - frame->data = nullptr; - frame->dataLength = 0; - } -} - } // extern "C" diff --git a/cscore/src/main/native/cpp/jni/CameraServerJNI.cpp b/cscore/src/main/native/cpp/jni/CameraServerJNI.cpp index f3bde4e961..0bde2e4b8f 100644 --- a/cscore/src/main/native/cpp/jni/CameraServerJNI.cpp +++ b/cscore/src/main/native/cpp/jni/CameraServerJNI.cpp @@ -10,7 +10,6 @@ #include #include -#include "cscore_cpp.h" #include "cscore_cv.h" #include "cscore_raw.h" #include "cscore_runloop.h" @@ -43,8 +42,7 @@ static JNIEnv* listenerEnv = nullptr; static const JClassInit classes[] = { {"edu/wpi/first/cscore/UsbCameraInfo", &usbCameraInfoCls}, {"edu/wpi/first/cscore/VideoMode", &videoModeCls}, - {"edu/wpi/first/cscore/VideoEvent", &videoEventCls}, - {"edu/wpi/first/cscore/raw/RawFrame", &rawFrameCls}}; + {"edu/wpi/first/cscore/VideoEvent", &videoEventCls}}; static const JExceptionInit exceptions[] = { {"edu/wpi/first/cscore/VideoException", &videoEx}, @@ -1233,7 +1231,7 @@ Java_edu_wpi_first_cscore_CameraServerJNI_putRawSourceFrameBB (JNIEnv* env, jclass, jint source, jobject byteBuffer, jint width, jint height, jint pixelFormat, jint totalData) { - CS_RawFrame rawFrame; + WPI_RawFrame rawFrame; rawFrame.data = reinterpret_cast(env->GetDirectBufferAddress(byteBuffer)); rawFrame.totalData = totalData; @@ -1255,7 +1253,7 @@ Java_edu_wpi_first_cscore_CameraServerJNI_putRawSourceFrame (JNIEnv* env, jclass, jint source, jlong ptr, jint width, jint height, jint pixelFormat, jint totalData) { - CS_RawFrame rawFrame; + WPI_RawFrame rawFrame; rawFrame.data = reinterpret_cast(static_cast(ptr)); rawFrame.totalData = totalData; rawFrame.pixelFormat = pixelFormat; @@ -1725,7 +1723,7 @@ Java_edu_wpi_first_cscore_CameraServerCvJNI_grabSinkFrameTimeout static void SetRawFrameData(JNIEnv* env, jobject rawFrameObj, jobject byteBuffer, bool didChangeDataPtr, - const CS_RawFrame& frame) { + const WPI_RawFrame& frame) { static jmethodID setMethod = env->GetMethodID(rawFrameCls, "setData", "(Ljava/nio/ByteBuffer;JIIII)V"); jlong framePtr = static_cast(reinterpret_cast(frame.data)); @@ -1750,8 +1748,8 @@ Java_edu_wpi_first_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(static_cast(rawFramePtr)); + WPI_RawFrame* ptr = + reinterpret_cast(static_cast(rawFramePtr)); auto origDataPtr = ptr->data; ptr->width = width; ptr->height = height; @@ -1776,8 +1774,8 @@ Java_edu_wpi_first_cscore_CameraServerJNI_grabRawSinkFrameTimeoutImpl jobject byteBuffer, jint width, jint height, jint pixelFormat, jdouble timeout) { - CS_RawFrame* ptr = - reinterpret_cast(static_cast(rawFramePtr)); + WPI_RawFrame* ptr = + reinterpret_cast(static_cast(rawFramePtr)); auto origDataPtr = ptr->data; ptr->width = width; ptr->height = height; @@ -2201,34 +2199,6 @@ Java_edu_wpi_first_cscore_CameraServerJNI_setLogger minLevel); } -/* - * Class: edu_wpi_first_cscore_CameraServerJNI - * Method: allocateRawFrame - * Signature: ()J - */ -JNIEXPORT jlong JNICALL -Java_edu_wpi_first_cscore_CameraServerJNI_allocateRawFrame - (JNIEnv*, jclass) -{ - cs::RawFrame* rawFrame = new cs::RawFrame{}; - intptr_t rawFrameIntPtr = reinterpret_cast(rawFrame); - return static_cast(rawFrameIntPtr); -} - -/* - * Class: edu_wpi_first_cscore_CameraServerJNI - * Method: freeRawFrame - * Signature: (J)V - */ -JNIEXPORT void JNICALL -Java_edu_wpi_first_cscore_CameraServerJNI_freeRawFrame - (JNIEnv*, jclass, jlong rawFrame) -{ - cs::RawFrame* ptr = - reinterpret_cast(static_cast(rawFrame)); - delete ptr; -} - /* * Class: edu_wpi_first_cscore_CameraServerJNI * Method: runMainRunLoop diff --git a/cscore/src/main/native/include/cscore_c.h b/cscore/src/main/native/include/cscore_c.h index c19d7bdea0..3f187f3cf4 100644 --- a/cscore/src/main/native/include/cscore_c.h +++ b/cscore/src/main/native/include/cscore_c.h @@ -7,6 +7,8 @@ #include +#include + #ifdef __cplusplus #include #else @@ -84,20 +86,6 @@ enum CS_LogLevel { CS_LOG_DEBUG4 = 6 }; -/** - * Pixel formats - */ -enum CS_PixelFormat { - CS_PIXFMT_UNKNOWN = 0, - CS_PIXFMT_MJPEG, - CS_PIXFMT_YUYV, - CS_PIXFMT_RGB565, - CS_PIXFMT_BGR, - CS_PIXFMT_GRAY, - CS_PIXFMT_Y16, - CS_PIXFMT_UYVY -}; - /** * Video mode */ @@ -302,11 +290,11 @@ void CS_GetSourceVideoMode(CS_Source source, CS_VideoMode* mode, CS_Bool CS_SetSourceVideoMode(CS_Source source, const CS_VideoMode* mode, CS_Status* status); CS_Bool CS_SetSourceVideoModeDiscrete(CS_Source source, - enum CS_PixelFormat pixelFormat, + enum WPI_PixelFormat pixelFormat, int width, int height, int fps, CS_Status* status); CS_Bool CS_SetSourcePixelFormat(CS_Source source, - enum CS_PixelFormat pixelFormat, + enum WPI_PixelFormat pixelFormat, CS_Status* status); CS_Bool CS_SetSourceResolution(CS_Source source, int width, int height, CS_Status* status); diff --git a/cscore/src/main/native/include/cscore_cpp.h b/cscore/src/main/native/include/cscore_cpp.h index 28d2d9d264..1d15039018 100644 --- a/cscore/src/main/native/include/cscore_cpp.h +++ b/cscore/src/main/native/include/cscore_cpp.h @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -60,14 +61,14 @@ struct UsbCameraInfo { */ struct VideoMode : public CS_VideoMode { enum PixelFormat { - kUnknown = CS_PIXFMT_UNKNOWN, - kMJPEG = CS_PIXFMT_MJPEG, - kYUYV = CS_PIXFMT_YUYV, - kRGB565 = CS_PIXFMT_RGB565, - kBGR = CS_PIXFMT_BGR, - kGray = CS_PIXFMT_GRAY, - kY16 = CS_PIXFMT_Y16, - kUYVY = CS_PIXFMT_UYVY + kUnknown = WPI_PIXFMT_UNKNOWN, + kMJPEG = WPI_PIXFMT_MJPEG, + kYUYV = WPI_PIXFMT_YUYV, + kRGB565 = WPI_PIXFMT_RGB565, + kBGR = WPI_PIXFMT_BGR, + kGray = WPI_PIXFMT_GRAY, + kY16 = WPI_PIXFMT_Y16, + kUYVY = WPI_PIXFMT_UYVY }; VideoMode() { pixelFormat = 0; diff --git a/cscore/src/main/native/include/cscore_raw.h b/cscore/src/main/native/include/cscore_raw.h index 21f4009ae0..6d49612218 100644 --- a/cscore/src/main/native/include/cscore_raw.h +++ b/cscore/src/main/native/include/cscore_raw.h @@ -9,36 +9,23 @@ #include "cscore_c.h" +// NOLINTBEGIN #ifdef __cplusplus #include "cscore_oo.h" #endif -/** - * Raw Frame - */ -typedef struct CS_RawFrame { // NOLINT - char* data; - int dataLength; - int pixelFormat; - int width; - int height; - int totalData; -} CS_RawFrame; - #ifdef __cplusplus extern "C" { #endif +// NOLINTEND /** * @defgroup cscore_raw_cfunc Raw Image Functions * @{ */ -void CS_AllocateRawFrameData(CS_RawFrame* frame, int requestedSize); -void CS_FreeRawFrameData(CS_RawFrame* frame); - -uint64_t CS_GrabRawSinkFrame(CS_Sink sink, struct CS_RawFrame* rawImage, +uint64_t CS_GrabRawSinkFrame(CS_Sink sink, struct WPI_RawFrame* rawImage, CS_Status* status); -uint64_t CS_GrabRawSinkFrameTimeout(CS_Sink sink, struct CS_RawFrame* rawImage, +uint64_t CS_GrabRawSinkFrameTimeout(CS_Sink sink, struct WPI_RawFrame* rawImage, double timeout, CS_Status* status); CS_Sink CS_CreateRawSink(const char* name, CS_Status* status); @@ -48,7 +35,7 @@ CS_Sink CS_CreateRawSinkCallback(const char* name, void* data, uint64_t time), CS_Status* status); -void CS_PutRawSourceFrame(CS_Source source, const struct CS_RawFrame* image, +void CS_PutRawSourceFrame(CS_Source source, const struct WPI_RawFrame* image, CS_Status* status); CS_Source CS_CreateRawSource(const char* name, const CS_VideoMode* mode, @@ -62,19 +49,6 @@ CS_Source CS_CreateRawSource(const char* name, const CS_VideoMode* mode, #ifdef __cplusplus namespace cs { -struct RawFrame : public CS_RawFrame { - RawFrame() { - data = nullptr; - dataLength = 0; - pixelFormat = CS_PIXFMT_UNKNOWN; - width = 0; - height = 0; - totalData = 0; - } - - ~RawFrame() { CS_FreeRawFrameData(this); } -}; - /** * @defgroup cscore_raw_func Raw Image Functions * @{ @@ -88,10 +62,10 @@ CS_Sink CreateRawSinkCallback(std::string_view name, std::function processFrame, CS_Status* status); -void PutSourceFrame(CS_Source source, const CS_RawFrame& image, +void PutSourceFrame(CS_Source source, const WPI_RawFrame& image, CS_Status* status); -uint64_t GrabSinkFrame(CS_Sink sink, CS_RawFrame& image, CS_Status* status); -uint64_t GrabSinkFrameTimeout(CS_Sink sink, CS_RawFrame& image, double timeout, +uint64_t GrabSinkFrame(CS_Sink sink, WPI_RawFrame& image, CS_Status* status); +uint64_t GrabSinkFrameTimeout(CS_Sink sink, WPI_RawFrame& image, double timeout, CS_Status* status); /** @@ -129,7 +103,7 @@ class RawSource : public ImageSource { * * @param image raw frame image */ - void PutFrame(RawFrame& image); + void PutFrame(wpi::RawFrame& image); }; /** @@ -177,7 +151,7 @@ class RawSink : public ImageSink { * and is in 1 us increments. */ [[nodiscard]] - uint64_t GrabFrame(RawFrame& image, double timeout = 0.225) const; + uint64_t GrabFrame(wpi::RawFrame& image, double timeout = 0.225) const; /** * Wait for the next frame and get the image. May block forever. @@ -188,7 +162,7 @@ class RawSink : public ImageSink { * and is in 1 us increments. */ [[nodiscard]] - uint64_t GrabFrameNoTimeout(RawFrame& image) const; + uint64_t GrabFrameNoTimeout(wpi::RawFrame& image) const; }; inline RawSource::RawSource(std::string_view name, const VideoMode& mode) { @@ -202,7 +176,7 @@ inline RawSource::RawSource(std::string_view name, CreateRawSource(name, VideoMode{format, width, height, fps}, &m_status); } -inline void RawSource::PutFrame(RawFrame& image) { +inline void RawSource::PutFrame(wpi::RawFrame& image) { m_status = 0; PutSourceFrame(m_handle, image, &m_status); } @@ -216,12 +190,12 @@ inline RawSink::RawSink(std::string_view name, m_handle = CreateRawSinkCallback(name, processFrame, &m_status); } -inline uint64_t RawSink::GrabFrame(RawFrame& image, double timeout) const { +inline uint64_t RawSink::GrabFrame(wpi::RawFrame& image, double timeout) const { m_status = 0; return GrabSinkFrameTimeout(m_handle, image, timeout, &m_status); } -inline uint64_t RawSink::GrabFrameNoTimeout(RawFrame& image) const { +inline uint64_t RawSink::GrabFrameNoTimeout(wpi::RawFrame& image) const { m_status = 0; return GrabSinkFrame(m_handle, image, &m_status); } diff --git a/cscore/src/main/native/include/cscore_raw_cv.h b/cscore/src/main/native/include/cscore_raw_cv.h index 11f42d6c62..7b687f8f90 100644 --- a/cscore/src/main/native/include/cscore_raw_cv.h +++ b/cscore/src/main/native/include/cscore_raw_cv.h @@ -62,7 +62,7 @@ class RawCvSource : public RawSource { void PutFrame(cv::Mat& image); private: - RawFrame rawFrame; + wpi::RawFrame rawFrame; }; /** @@ -151,7 +151,7 @@ class RawCvSink : public RawSink { uint64_t GrabFrameNoTimeoutDirect(cv::Mat& image); private: - RawFrame rawFrame; + wpi::RawFrame rawFrame; }; inline RawCvSource::RawCvSource(std::string_view name, const VideoMode& mode) @@ -168,7 +168,8 @@ inline void RawCvSource::PutFrame(cv::Mat& image) { rawFrame.width = image.cols; rawFrame.height = image.rows; rawFrame.totalData = image.total() * image.channels(); - rawFrame.pixelFormat = image.channels() == 3 ? CS_PIXFMT_BGR : CS_PIXFMT_GRAY; + rawFrame.pixelFormat = + image.channels() == 3 ? WPI_PIXFMT_BGR : WPI_PIXFMT_GRAY; PutSourceFrame(m_handle, rawFrame, &m_status); } @@ -201,7 +202,7 @@ inline uint64_t RawCvSink::GrabFrameNoTimeout(cv::Mat& image) { inline uint64_t RawCvSink::GrabFrameDirect(cv::Mat& image, double timeout) { rawFrame.height = 0; rawFrame.width = 0; - rawFrame.pixelFormat = CS_PixelFormat::CS_PIXFMT_BGR; + rawFrame.pixelFormat = WPI_PixelFormat::WPI_PIXFMT_BGR; m_status = RawSink::GrabFrame(rawFrame, timeout); if (m_status <= 0) { return m_status; @@ -213,7 +214,7 @@ inline uint64_t RawCvSink::GrabFrameDirect(cv::Mat& image, double timeout) { inline uint64_t RawCvSink::GrabFrameNoTimeoutDirect(cv::Mat& image) { rawFrame.height = 0; rawFrame.width = 0; - rawFrame.pixelFormat = CS_PixelFormat::CS_PIXFMT_BGR; + rawFrame.pixelFormat = WPI_PixelFormat::WPI_PIXFMT_BGR; m_status = RawSink::GrabFrameNoTimeout(rawFrame); if (m_status <= 0) { return m_status; diff --git a/cscore/src/main/java/edu/wpi/first/cscore/raw/RawFrame.java b/wpiutil/src/main/java/edu/wpi/first/util/RawFrame.java similarity index 95% rename from cscore/src/main/java/edu/wpi/first/cscore/raw/RawFrame.java rename to wpiutil/src/main/java/edu/wpi/first/util/RawFrame.java index 5f62481c86..19aeca072c 100644 --- a/cscore/src/main/java/edu/wpi/first/cscore/raw/RawFrame.java +++ b/wpiutil/src/main/java/edu/wpi/first/util/RawFrame.java @@ -2,9 +2,8 @@ // Open Source Software; you can modify and/or share it under the terms of // the WPILib BSD license file in the root directory of this project. -package edu.wpi.first.cscore.raw; +package edu.wpi.first.util; -import edu.wpi.first.cscore.CameraServerJNI; import java.nio.ByteBuffer; /** @@ -23,7 +22,7 @@ public class RawFrame implements AutoCloseable { /** Construct a new RawFrame. */ public RawFrame() { - m_framePtr = CameraServerJNI.allocateRawFrame(); + m_framePtr = WPIUtilJNI.allocateRawFrame(); } /** @@ -32,7 +31,7 @@ public class RawFrame implements AutoCloseable { */ @Override public void close() { - CameraServerJNI.freeRawFrame(m_framePtr); + WPIUtilJNI.freeRawFrame(m_framePtr); } /** diff --git a/wpiutil/src/main/java/edu/wpi/first/util/WPIUtilJNI.java b/wpiutil/src/main/java/edu/wpi/first/util/WPIUtilJNI.java index 9929b48228..8718324ebe 100644 --- a/wpiutil/src/main/java/edu/wpi/first/util/WPIUtilJNI.java +++ b/wpiutil/src/main/java/edu/wpi/first/util/WPIUtilJNI.java @@ -80,6 +80,10 @@ public class WPIUtilJNI { public static native boolean releaseSemaphore(int semHandle, int releaseCount); + public static native long allocateRawFrame(); + + public static native void freeRawFrame(long frame); + /** * Waits for a handle to be signaled. * diff --git a/wpiutil/src/main/native/cpp/RawFrame.cpp b/wpiutil/src/main/native/cpp/RawFrame.cpp new file mode 100644 index 0000000000..a97a2ccdfc --- /dev/null +++ b/wpiutil/src/main/native/cpp/RawFrame.cpp @@ -0,0 +1,30 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "wpi/RawFrame.h" + +#include + +extern "C" { +void WPI_AllocateRawFrameData(WPI_RawFrame* frame, int requestedSize) { + if (frame->dataLength >= requestedSize) { + return; + } + if (frame->data) { + frame->data = + static_cast(wpi::safe_realloc(frame->data, requestedSize)); + } else { + frame->data = static_cast(wpi::safe_malloc(requestedSize)); + } + frame->dataLength = requestedSize; +} + +void WPI_FreeRawFrameData(WPI_RawFrame* frame) { + if (frame->data) { + std::free(frame->data); + frame->data = nullptr; + frame->dataLength = 0; + } +} +} // extern "C" diff --git a/wpiutil/src/main/native/cpp/jni/WPIUtilJNI.cpp b/wpiutil/src/main/native/cpp/jni/WPIUtilJNI.cpp index eb55fd0124..ad0e1a4595 100644 --- a/wpiutil/src/main/native/cpp/jni/WPIUtilJNI.cpp +++ b/wpiutil/src/main/native/cpp/jni/WPIUtilJNI.cpp @@ -9,6 +9,7 @@ #include #include "edu_wpi_first_util_WPIUtilJNI.h" +#include "wpi/RawFrame.h" #include "wpi/Synchronization.h" #include "wpi/jni_util.h" #include "wpi/timestamp.h" @@ -317,4 +318,32 @@ Java_edu_wpi_first_util_WPIUtilJNI_waitForObjectsTimeout return MakeJIntArray(env, signaled); } +/* + * Class: edu_wpi_first_util_WPIUtilJNI + * Method: allocateRawFrame + * Signature: ()J + */ +JNIEXPORT jlong JNICALL +Java_edu_wpi_first_util_WPIUtilJNI_allocateRawFrame + (JNIEnv*, jclass) +{ + wpi::RawFrame* rawFrame = new wpi::RawFrame{}; + intptr_t rawFrameIntPtr = reinterpret_cast(rawFrame); + return static_cast(rawFrameIntPtr); +} + +/* + * Class: edu_wpi_first_util_WPIUtilJNI + * Method: freeRawFrame + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_edu_wpi_first_util_WPIUtilJNI_freeRawFrame + (JNIEnv*, jclass, jlong rawFrame) +{ + wpi::RawFrame* ptr = + reinterpret_cast(static_cast(rawFrame)); + delete ptr; +} + } // extern "C" diff --git a/wpiutil/src/main/native/include/wpi/RawFrame.h b/wpiutil/src/main/native/include/wpi/RawFrame.h new file mode 100644 index 0000000000..5254a64df1 --- /dev/null +++ b/wpiutil/src/main/native/include/wpi/RawFrame.h @@ -0,0 +1,63 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#ifndef WPIUTIL_WPI_RAWFRAME_H_ +#define WPIUTIL_WPI_RAWFRAME_H_ + +/** + * Raw Frame + */ +typedef struct WPI_RawFrame { // NOLINT + char* data; + int dataLength; + int pixelFormat; + int width; + int height; + int totalData; +} WPI_RawFrame; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Pixel formats + */ +enum WPI_PixelFormat { + WPI_PIXFMT_UNKNOWN = 0, + WPI_PIXFMT_MJPEG, + WPI_PIXFMT_YUYV, + WPI_PIXFMT_RGB565, + WPI_PIXFMT_BGR, + WPI_PIXFMT_GRAY, + WPI_PIXFMT_Y16, + WPI_PIXFMT_UYVY +}; + +void WPI_AllocateRawFrameData(WPI_RawFrame* frame, int requestedSize); +void WPI_FreeRawFrameData(WPI_RawFrame* frame); + +#ifdef __cplusplus +} // extern "C" +#endif + +#ifdef __cplusplus +namespace wpi { +struct RawFrame : public WPI_RawFrame { + RawFrame() { + data = nullptr; + dataLength = 0; + pixelFormat = WPI_PIXFMT_UNKNOWN; + width = 0; + height = 0; + totalData = 0; + } + + ~RawFrame() { WPI_FreeRawFrameData(this); } +}; +} // namespace wpi + +#endif + +#endif // WPIUTIL_WPI_RAWFRAME_H_