001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.util;
006
007import java.nio.ByteBuffer;
008
009/**
010 * Class for storing raw frame data between image read call.
011 *
012 * <p>Data is reused for each frame read, rather then reallocating every frame.
013 */
014public class RawFrame implements AutoCloseable {
015  private long m_nativeObj;
016  private ByteBuffer m_data;
017  private int m_width;
018  private int m_height;
019  private int m_stride;
020  private PixelFormat m_pixelFormat = PixelFormat.kUnknown;
021  private long m_time;
022  private TimestampSource m_timeSource = TimestampSource.kUnknown;
023
024  /** Construct a new empty RawFrame. */
025  public RawFrame() {
026    m_nativeObj = WPIUtilJNI.allocateRawFrame();
027  }
028
029  /**
030   * Close the RawFrame, releasing native resources. Any images currently using the data will be
031   * invalidated.
032   */
033  @Override
034  public void close() {
035    WPIUtilJNI.freeRawFrame(m_nativeObj);
036    m_nativeObj = 0;
037  }
038
039  /**
040   * Called from JNI to set data in class.
041   *
042   * @param data A native ByteBuffer pointing to the frame data.
043   * @param width The width of the frame, in pixels
044   * @param height The height of the frame, in pixels
045   * @param stride The number of bytes in each row of image data
046   * @param pixelFormat The PixelFormat of the frame
047   */
048  void setDataJNI(
049      ByteBuffer data, int width, int height, int stride, int pixelFormat, long time, int timeSrc) {
050    m_data = data;
051    m_width = width;
052    m_height = height;
053    m_stride = stride;
054    m_pixelFormat = PixelFormat.getFromInt(pixelFormat);
055    m_time = time;
056    m_timeSource = TimestampSource.getFromInt(timeSrc);
057  }
058
059  /**
060   * Called from JNI to set info in class.
061   *
062   * @param width The width of the frame, in pixels
063   * @param height The height of the frame, in pixels
064   * @param stride The number of bytes in each row of image data
065   * @param pixelFormat The PixelFormat of the frame
066   */
067  void setInfoJNI(int width, int height, int stride, int pixelFormat, long time, int timeSrc) {
068    m_width = width;
069    m_height = height;
070    m_stride = stride;
071    m_pixelFormat = PixelFormat.getFromInt(pixelFormat);
072    m_time = time;
073    m_timeSource = TimestampSource.getFromInt(timeSrc);
074  }
075
076  /**
077   * Set frame data.
078   *
079   * @param data A native ByteBuffer pointing to the frame data.
080   * @param width The width of the frame, in pixels
081   * @param height The height of the frame, in pixels
082   * @param stride The number of bytes in each row of image data
083   * @param pixelFormat The PixelFormat of the frame
084   */
085  public void setData(ByteBuffer data, int width, int height, int stride, PixelFormat pixelFormat) {
086    if (!data.isDirect()) {
087      throw new UnsupportedOperationException("ByteBuffer must be direct");
088    }
089    m_data = data;
090    m_width = width;
091    m_height = height;
092    m_stride = stride;
093    m_pixelFormat = pixelFormat;
094    WPIUtilJNI.setRawFrameData(
095        m_nativeObj, data, data.limit(), width, height, stride, pixelFormat.getValue());
096  }
097
098  /**
099   * Call to set frame information.
100   *
101   * @param width The width of the frame, in pixels
102   * @param height The height of the frame, in pixels
103   * @param stride The number of bytes in each row of image data
104   * @param pixelFormat The PixelFormat of the frame
105   */
106  public void setInfo(int width, int height, int stride, PixelFormat pixelFormat) {
107    m_width = width;
108    m_height = height;
109    m_stride = stride;
110    m_pixelFormat = pixelFormat;
111    WPIUtilJNI.setRawFrameInfo(
112        m_nativeObj,
113        m_data != null ? m_data.limit() : 0,
114        width,
115        height,
116        stride,
117        pixelFormat.getValue());
118  }
119
120  /**
121   * Update this frame's timestamp info.
122   *
123   * @param frameTime the time this frame was grabbed at. This uses the same time base as
124   *     wpi::Now(), in us.
125   * @param frameTimeSource the time source for the timestamp this frame was grabbed at.
126   */
127  public void setTimeInfo(long frameTime, TimestampSource frameTimeSource) {
128    m_time = frameTime;
129    m_timeSource = frameTimeSource;
130    WPIUtilJNI.setRawFrameTime(m_nativeObj, frameTime, frameTimeSource.getValue());
131  }
132
133  /**
134   * Get the pointer to native representation of this frame.
135   *
136   * @return The pointer to native representation of this frame.
137   */
138  public long getNativeObj() {
139    return m_nativeObj;
140  }
141
142  /**
143   * Get a ByteBuffer pointing to the frame data. This ByteBuffer is backed by the frame directly.
144   * Its lifetime is controlled by the frame. If a new frame gets read, it will overwrite the
145   * current one.
146   *
147   * @return A ByteBuffer pointing to the frame data.
148   */
149  public ByteBuffer getData() {
150    return m_data;
151  }
152
153  /**
154   * Get a long (is a uint8_t* in native code) pointing to the frame data. This pointer is backed by
155   * the frame directly. Its lifetime is controlled by the frame. If a new frame gets read, it will
156   * overwrite the current one.
157   *
158   * @return A long pointing to the frame data.
159   */
160  public long getDataPtr() {
161    return WPIUtilJNI.getRawFrameDataPtr(m_nativeObj);
162  }
163
164  /**
165   * Get the total size of the data stored in the frame, in bytes.
166   *
167   * @return The total size of the data stored in the frame.
168   */
169  public int getSize() {
170    return m_data != null ? m_data.limit() : 0;
171  }
172
173  /**
174   * Get the width of the image.
175   *
176   * @return The width of the image, in pixels.
177   */
178  public int getWidth() {
179    return m_width;
180  }
181
182  /**
183   * Get the height of the image.
184   *
185   * @return The height of the image, in pixels.
186   */
187  public int getHeight() {
188    return m_height;
189  }
190
191  /**
192   * Get the number of bytes in each row of image data.
193   *
194   * @return The image data stride, in bytes.
195   */
196  public int getStride() {
197    return m_stride;
198  }
199
200  /**
201   * Get the PixelFormat of the frame.
202   *
203   * @return The PixelFormat of the frame.
204   */
205  public PixelFormat getPixelFormat() {
206    return m_pixelFormat;
207  }
208
209  /**
210   * Get the time this frame was grabbed at. This uses the same time base as wpi::Now(), in us.
211   *
212   * @return Time in 1 us increments.
213   */
214  public long getTimestamp() {
215    return m_time;
216  }
217
218  /**
219   * Get the time source for the timestamp this frame was grabbed at.
220   *
221   * @return Time source
222   */
223  public TimestampSource getTimestampSource() {
224    return m_timeSource;
225  }
226}