2020-12-26 14:12:05 -08:00
|
|
|
// 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.
|
2019-05-30 19:12:05 -07:00
|
|
|
|
2025-11-07 19:55:43 -05:00
|
|
|
package org.wpilib.util;
|
2019-05-30 19:12:05 -07:00
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
import java.nio.ByteBuffer;
|
2019-05-30 19:12:05 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Class for storing raw frame data between image read call.
|
|
|
|
|
*
|
|
|
|
|
* <p>Data is reused for each frame read, rather then reallocating every frame.
|
|
|
|
|
*/
|
|
|
|
|
public class RawFrame implements AutoCloseable {
|
2023-12-26 20:05:02 -08:00
|
|
|
private long m_nativeObj;
|
|
|
|
|
private ByteBuffer m_data;
|
2019-05-30 19:12:05 -07:00
|
|
|
private int m_width;
|
|
|
|
|
private int m_height;
|
2023-12-26 20:05:02 -08:00
|
|
|
private int m_stride;
|
2024-01-06 12:50:11 -08:00
|
|
|
private PixelFormat m_pixelFormat = PixelFormat.kUnknown;
|
2025-01-07 09:33:20 -07:00
|
|
|
private long m_time;
|
|
|
|
|
private TimestampSource m_timeSource = TimestampSource.kUnknown;
|
2019-05-30 19:12:05 -07:00
|
|
|
|
2023-12-26 20:05:02 -08:00
|
|
|
/** Construct a new empty RawFrame. */
|
2019-05-30 19:12:05 -07:00
|
|
|
public RawFrame() {
|
2023-12-26 20:05:02 -08:00
|
|
|
m_nativeObj = WPIUtilJNI.allocateRawFrame();
|
2019-05-30 19:12:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* Close the RawFrame, releasing native resources. Any images currently using the data will be
|
|
|
|
|
* invalidated.
|
2019-05-30 19:12:05 -07:00
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public void close() {
|
2023-12-26 20:05:02 -08:00
|
|
|
WPIUtilJNI.freeRawFrame(m_nativeObj);
|
|
|
|
|
m_nativeObj = 0;
|
2019-05-30 19:12:05 -07:00
|
|
|
}
|
|
|
|
|
|
2021-06-10 20:46:47 -07:00
|
|
|
/**
|
|
|
|
|
* Called from JNI to set data in class.
|
|
|
|
|
*
|
2023-12-26 20:05:02 -08:00
|
|
|
* @param data A native ByteBuffer pointing to the frame data.
|
|
|
|
|
* @param width The width of the frame, in pixels
|
|
|
|
|
* @param height The height of the frame, in pixels
|
|
|
|
|
* @param stride The number of bytes in each row of image data
|
|
|
|
|
* @param pixelFormat The PixelFormat of the frame
|
2021-06-10 20:46:47 -07:00
|
|
|
*/
|
2025-01-07 09:33:20 -07:00
|
|
|
void setDataJNI(
|
|
|
|
|
ByteBuffer data, int width, int height, int stride, int pixelFormat, long time, int timeSrc) {
|
2023-12-26 20:05:02 -08:00
|
|
|
m_data = data;
|
2019-05-30 19:12:05 -07:00
|
|
|
m_width = width;
|
|
|
|
|
m_height = height;
|
2023-12-26 20:05:02 -08:00
|
|
|
m_stride = stride;
|
|
|
|
|
m_pixelFormat = PixelFormat.getFromInt(pixelFormat);
|
2025-01-07 09:33:20 -07:00
|
|
|
m_time = time;
|
|
|
|
|
m_timeSource = TimestampSource.getFromInt(timeSrc);
|
2023-12-26 20:05:02 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Called from JNI to set info in class.
|
|
|
|
|
*
|
|
|
|
|
* @param width The width of the frame, in pixels
|
|
|
|
|
* @param height The height of the frame, in pixels
|
|
|
|
|
* @param stride The number of bytes in each row of image data
|
|
|
|
|
* @param pixelFormat The PixelFormat of the frame
|
|
|
|
|
*/
|
2025-01-07 09:33:20 -07:00
|
|
|
void setInfoJNI(int width, int height, int stride, int pixelFormat, long time, int timeSrc) {
|
2023-12-26 20:05:02 -08:00
|
|
|
m_width = width;
|
|
|
|
|
m_height = height;
|
|
|
|
|
m_stride = stride;
|
|
|
|
|
m_pixelFormat = PixelFormat.getFromInt(pixelFormat);
|
2025-01-07 09:33:20 -07:00
|
|
|
m_time = time;
|
|
|
|
|
m_timeSource = TimestampSource.getFromInt(timeSrc);
|
2023-12-26 20:05:02 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set frame data.
|
|
|
|
|
*
|
|
|
|
|
* @param data A native ByteBuffer pointing to the frame data.
|
|
|
|
|
* @param width The width of the frame, in pixels
|
|
|
|
|
* @param height The height of the frame, in pixels
|
|
|
|
|
* @param stride The number of bytes in each row of image data
|
|
|
|
|
* @param pixelFormat The PixelFormat of the frame
|
|
|
|
|
*/
|
|
|
|
|
public void setData(ByteBuffer data, int width, int height, int stride, PixelFormat pixelFormat) {
|
|
|
|
|
if (!data.isDirect()) {
|
|
|
|
|
throw new UnsupportedOperationException("ByteBuffer must be direct");
|
|
|
|
|
}
|
|
|
|
|
m_data = data;
|
|
|
|
|
m_width = width;
|
|
|
|
|
m_height = height;
|
|
|
|
|
m_stride = stride;
|
|
|
|
|
m_pixelFormat = pixelFormat;
|
|
|
|
|
WPIUtilJNI.setRawFrameData(
|
|
|
|
|
m_nativeObj, data, data.limit(), width, height, stride, pixelFormat.getValue());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Call to set frame information.
|
|
|
|
|
*
|
|
|
|
|
* @param width The width of the frame, in pixels
|
|
|
|
|
* @param height The height of the frame, in pixels
|
|
|
|
|
* @param stride The number of bytes in each row of image data
|
|
|
|
|
* @param pixelFormat The PixelFormat of the frame
|
|
|
|
|
*/
|
|
|
|
|
public void setInfo(int width, int height, int stride, PixelFormat pixelFormat) {
|
|
|
|
|
m_width = width;
|
|
|
|
|
m_height = height;
|
|
|
|
|
m_stride = stride;
|
2019-05-30 19:12:05 -07:00
|
|
|
m_pixelFormat = pixelFormat;
|
2023-12-26 20:05:02 -08:00
|
|
|
WPIUtilJNI.setRawFrameInfo(
|
2024-01-06 12:50:11 -08:00
|
|
|
m_nativeObj,
|
|
|
|
|
m_data != null ? m_data.limit() : 0,
|
|
|
|
|
width,
|
|
|
|
|
height,
|
|
|
|
|
stride,
|
|
|
|
|
pixelFormat.getValue());
|
2019-05-30 19:12:05 -07:00
|
|
|
}
|
|
|
|
|
|
2025-01-07 09:33:20 -07:00
|
|
|
/**
|
|
|
|
|
* Update this frame's timestamp info.
|
|
|
|
|
*
|
|
|
|
|
* @param frameTime the time this frame was grabbed at. This uses the same time base as
|
|
|
|
|
* wpi::Now(), in us.
|
|
|
|
|
* @param frameTimeSource the time source for the timestamp this frame was grabbed at.
|
|
|
|
|
*/
|
|
|
|
|
public void setTimeInfo(long frameTime, TimestampSource frameTimeSource) {
|
|
|
|
|
m_time = frameTime;
|
|
|
|
|
m_timeSource = frameTimeSource;
|
|
|
|
|
WPIUtilJNI.setRawFrameTime(m_nativeObj, frameTime, frameTimeSource.getValue());
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-10 20:46:47 -07:00
|
|
|
/**
|
|
|
|
|
* Get the pointer to native representation of this frame.
|
|
|
|
|
*
|
|
|
|
|
* @return The pointer to native representation of this frame.
|
|
|
|
|
*/
|
2023-12-26 20:05:02 -08:00
|
|
|
public long getNativeObj() {
|
|
|
|
|
return m_nativeObj;
|
2019-05-30 19:12:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* Get a ByteBuffer pointing to the frame data. This ByteBuffer is backed by the frame directly.
|
|
|
|
|
* Its lifetime is controlled by the frame. If a new frame gets read, it will overwrite the
|
|
|
|
|
* current one.
|
2021-06-10 20:46:47 -07:00
|
|
|
*
|
|
|
|
|
* @return A ByteBuffer pointing to the frame data.
|
2019-05-30 19:12:05 -07:00
|
|
|
*/
|
2023-12-26 20:05:02 -08:00
|
|
|
public ByteBuffer getData() {
|
|
|
|
|
return m_data;
|
2019-05-30 19:12:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-12-26 20:05:02 -08:00
|
|
|
* Get a long (is a uint8_t* in native code) pointing to the frame data. This pointer is backed by
|
2020-12-29 22:45:16 -08:00
|
|
|
* the frame directly. Its lifetime is controlled by the frame. If a new frame gets read, it will
|
|
|
|
|
* overwrite the current one.
|
2021-06-10 20:46:47 -07:00
|
|
|
*
|
|
|
|
|
* @return A long pointing to the frame data.
|
2019-05-30 19:12:05 -07:00
|
|
|
*/
|
|
|
|
|
public long getDataPtr() {
|
2023-12-26 20:05:02 -08:00
|
|
|
return WPIUtilJNI.getRawFrameDataPtr(m_nativeObj);
|
2019-05-30 19:12:05 -07:00
|
|
|
}
|
|
|
|
|
|
2021-06-10 20:46:47 -07:00
|
|
|
/**
|
2023-12-26 20:05:02 -08:00
|
|
|
* Get the total size of the data stored in the frame, in bytes.
|
2021-06-10 20:46:47 -07:00
|
|
|
*
|
2023-12-26 20:05:02 -08:00
|
|
|
* @return The total size of the data stored in the frame.
|
2021-06-10 20:46:47 -07:00
|
|
|
*/
|
2023-12-26 20:05:02 -08:00
|
|
|
public int getSize() {
|
2024-01-06 12:50:11 -08:00
|
|
|
return m_data != null ? m_data.limit() : 0;
|
2019-05-30 19:12:05 -07:00
|
|
|
}
|
|
|
|
|
|
2021-06-10 20:46:47 -07:00
|
|
|
/**
|
2023-12-26 20:05:02 -08:00
|
|
|
* Get the width of the image.
|
2021-06-10 20:46:47 -07:00
|
|
|
*
|
2023-12-26 20:05:02 -08:00
|
|
|
* @return The width of the image, in pixels.
|
2021-06-10 20:46:47 -07:00
|
|
|
*/
|
2019-05-30 19:12:05 -07:00
|
|
|
public int getWidth() {
|
|
|
|
|
return m_width;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-10 20:46:47 -07:00
|
|
|
/**
|
2023-12-26 20:05:02 -08:00
|
|
|
* Get the height of the image.
|
2021-06-10 20:46:47 -07:00
|
|
|
*
|
2023-12-26 20:05:02 -08:00
|
|
|
* @return The height of the image, in pixels.
|
2021-06-10 20:46:47 -07:00
|
|
|
*/
|
2019-05-30 19:12:05 -07:00
|
|
|
public int getHeight() {
|
|
|
|
|
return m_height;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-10 20:46:47 -07:00
|
|
|
/**
|
2023-12-26 20:05:02 -08:00
|
|
|
* Get the number of bytes in each row of image data.
|
2021-06-10 20:46:47 -07:00
|
|
|
*
|
2023-12-26 20:05:02 -08:00
|
|
|
* @return The image data stride, in bytes.
|
2021-06-10 20:46:47 -07:00
|
|
|
*/
|
2023-12-26 20:05:02 -08:00
|
|
|
public int getStride() {
|
|
|
|
|
return m_stride;
|
2019-05-30 19:12:05 -07:00
|
|
|
}
|
|
|
|
|
|
2021-06-10 20:46:47 -07:00
|
|
|
/**
|
|
|
|
|
* Get the PixelFormat of the frame.
|
|
|
|
|
*
|
|
|
|
|
* @return The PixelFormat of the frame.
|
|
|
|
|
*/
|
2023-12-26 20:05:02 -08:00
|
|
|
public PixelFormat getPixelFormat() {
|
2019-05-30 19:12:05 -07:00
|
|
|
return m_pixelFormat;
|
|
|
|
|
}
|
2025-01-07 09:33:20 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the time this frame was grabbed at. This uses the same time base as wpi::Now(), in us.
|
|
|
|
|
*
|
|
|
|
|
* @return Time in 1 us increments.
|
|
|
|
|
*/
|
|
|
|
|
public long getTimestamp() {
|
|
|
|
|
return m_time;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the time source for the timestamp this frame was grabbed at.
|
|
|
|
|
*
|
|
|
|
|
* @return Time source
|
|
|
|
|
*/
|
|
|
|
|
public TimestampSource getTimestampSource() {
|
|
|
|
|
return m_timeSource;
|
|
|
|
|
}
|
2019-05-30 19:12:05 -07:00
|
|
|
}
|