001/*----------------------------------------------------------------------------*/
002/* Copyright (c) FIRST 2016. All Rights Reserved.                             */
003/* Open Source Software - may be modified and shared by FRC teams. The code   */
004/* must be accompanied by the FIRST BSD license file in the root directory of */
005/* the project.                                                               */
006/*----------------------------------------------------------------------------*/
007
008package edu.wpi.cscore;
009
010/// A source for video that provides a sequence of frames.  Each frame may
011/// consist of multiple images (e.g. from a stereo or depth camera); these
012/// are called channels.
013public class VideoSink {
014  public enum Kind {
015    kUnknown(0), kMjpeg(2), kCv(4);
016    private int value;
017
018    private Kind(int value) {
019      this.value = value;
020    }
021
022    public int getValue() {
023      return value;
024    }
025  }
026
027  public static Kind getKindFromInt(int kind) {
028    switch (kind) {
029      case 2: return Kind.kMjpeg;
030      case 4: return Kind.kCv;
031      default: return Kind.kUnknown;
032    }
033  }
034
035  protected VideoSink(int handle) {
036    m_handle = handle;
037  }
038
039  public synchronized void free() {
040    if (m_handle != 0) {
041      CameraServerJNI.releaseSink(m_handle);
042    }
043    m_handle = 0;
044  }
045
046  public boolean isValid() {
047    return m_handle != 0;
048  }
049
050  public int getHandle() {
051    return m_handle;
052  }
053
054  public boolean equals(Object other) {
055    if (this == other) return true;
056    if (other == null) return false;
057    if (getClass() != other.getClass()) return false;
058    VideoSink sink = (VideoSink) other;
059    return m_handle == sink.m_handle;
060  }
061
062  public int hashCode() {
063    return m_handle;
064  }
065
066  /// Get the kind of the sink.
067  public Kind getKind() {
068    return getKindFromInt(CameraServerJNI.getSinkKind(m_handle));
069  }
070
071  /// Get the name of the sink.  The name is an arbitrary identifier
072  /// provided when the sink is created, and should be unique.
073  public String getName() {
074    return CameraServerJNI.getSinkName(m_handle);
075  }
076
077  /// Get the sink description.  This is sink-kind specific.
078  public String getDescription() {
079    return CameraServerJNI.getSinkDescription(m_handle);
080  }
081
082  /// Configure which source should provide frames to this sink.  Each sink
083  /// can accept frames from only a single source, but a single source can
084  /// provide frames to multiple clients.
085  /// @param source Source
086  public void setSource(VideoSource source) {
087    if (source == null) {
088      CameraServerJNI.setSinkSource(m_handle, 0);
089    } else {
090      CameraServerJNI.setSinkSource(m_handle, source.m_handle);
091    }
092  }
093
094  /// Get the connected source.
095  /// @return Connected source; nullptr if no source connected.
096  public VideoSource getSource() {
097    // While VideoSource.free() will call releaseSource(), getSinkSource()
098    // increments the internal reference count so this is okay to do.
099    return new VideoSource(CameraServerJNI.getSinkSource(m_handle));
100  }
101
102  /// Get a property of the associated source.
103  /// @param name Property name
104  /// @return Property (kind Property::kNone if no property with
105  ///         the given name exists or no source connected)
106  public VideoProperty getSourceProperty(String name) {
107    return new VideoProperty(
108        CameraServerJNI.getSinkSourceProperty(m_handle, name));
109  }
110
111  /// Enumerate all existing sinks.
112  /// @return Vector of sinks.
113  public static VideoSink[] enumerateSinks() {
114    int[] handles = CameraServerJNI.enumerateSinks();
115    VideoSink[] rv = new VideoSink[handles.length];
116    for (int i=0; i<handles.length; i++) {
117      rv[i] = new VideoSink(handles[i]);
118    }
119    return rv;
120  }
121
122  protected int m_handle;
123}