[wpiutil] Move RawFrame to wpiutil; add generation of RawFrame for AprilTags (#5923)

This commit is contained in:
Drew Williams
2023-11-23 13:55:10 -05:00
committed by GitHub
parent 437cc91af5
commit ca81ced409
23 changed files with 300 additions and 155 deletions

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -6,8 +6,56 @@
#include <wpi/json.h>
#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<char*>(
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<char*>(
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}};
}

View File

@@ -8,6 +8,7 @@
#include <wpi/jni_util.h>
#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"

View File

@@ -4,6 +4,7 @@
#pragma once
#include <wpi/RawFrame.h>
#include <wpi/SymbolExports.h>
#include <wpi/json_fwd.h>
@@ -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

View File

@@ -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);

View File

@@ -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.

View File

@@ -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.

View File

@@ -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<RawSinkImpl&>(*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);
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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};

View File

@@ -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<char*>(wpi::safe_realloc(frame->data, requestedSize));
} else {
frame->data = static_cast<char*>(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"

View File

@@ -10,7 +10,6 @@
#include <wpi/SmallString.h>
#include <wpi/jni_util.h>
#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<char*>(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<char*>(static_cast<intptr_t>(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<jlong>(reinterpret_cast<intptr_t>(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<CS_RawFrame*>(static_cast<intptr_t>(rawFramePtr));
WPI_RawFrame* ptr =
reinterpret_cast<WPI_RawFrame*>(static_cast<intptr_t>(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<CS_RawFrame*>(static_cast<intptr_t>(rawFramePtr));
WPI_RawFrame* ptr =
reinterpret_cast<WPI_RawFrame*>(static_cast<intptr_t>(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<intptr_t>(rawFrame);
return static_cast<jlong>(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<cs::RawFrame*>(static_cast<intptr_t>(rawFrame));
delete ptr;
}
/*
* Class: edu_wpi_first_cscore_CameraServerJNI
* Method: runMainRunLoop

View File

@@ -7,6 +7,8 @@
#include <stdint.h>
#include <wpi/RawFrame.h>
#ifdef __cplusplus
#include <cstddef>
#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);

View File

@@ -13,6 +13,7 @@
#include <string_view>
#include <vector>
#include <wpi/RawFrame.h>
#include <wpi/SmallVector.h>
#include <wpi/json_fwd.h>
@@ -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;

View File

@@ -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<void(uint64_t time)> 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);
}

View File

@@ -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;

View File

@@ -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);
}
/**

View File

@@ -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.
*

View File

@@ -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 <wpi/MemAlloc.h>
extern "C" {
void WPI_AllocateRawFrameData(WPI_RawFrame* frame, int requestedSize) {
if (frame->dataLength >= requestedSize) {
return;
}
if (frame->data) {
frame->data =
static_cast<char*>(wpi::safe_realloc(frame->data, requestedSize));
} else {
frame->data = static_cast<char*>(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"

View File

@@ -9,6 +9,7 @@
#include <fmt/format.h>
#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<intptr_t>(rawFrame);
return static_cast<jlong>(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<wpi::RawFrame*>(static_cast<intptr_t>(rawFrame));
delete ptr;
}
} // extern "C"

View File

@@ -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_