/**
   * Checks whether RTP packets from {@code sourceChannel} should be forwarded to {@link #channel}.
   *
   * @param sourceChannel the channel.
   * @return {@code true} iff RTP packets from {@code sourceChannel} should be forwarded to {@link
   *     #channel}.
   */
  public boolean isForwarded(Channel sourceChannel) {
    if (lastN < 0 && currentLastN < 0) {
      // If Last-N is disabled, we forward everything.
      return true;
    }

    if (sourceChannel == null) {
      logger.warn("Invalid sourceChannel: null.");
      return false;
    }

    Endpoint channelEndpoint = sourceChannel.getEndpoint();
    if (channelEndpoint == null) {
      logger.warn("sourceChannel has no endpoint.");
      return false;
    }

    if (forwardedEndpoints == INITIAL_EMPTY_LIST) {
      // LastN is enabled, but we haven't yet initialized the list of
      // endpoints in the conference.
      initializeConferenceEndpoints();
    }

    // This may look like a place to optimize, because we query an unordered
    // list (in O(n)) and it executes on each video packet if lastN is
    // enabled. However, the size of  forwardedEndpoints is restricted to
    // lastN and so small enough that it is not worth optimizing.
    return forwardedEndpoints.contains(channelEndpoint.getID());
  }
 /** @return the ID of the endpoint of our channel. */
 private String getEndpointId() {
   if (endpointId == null) {
     Endpoint endpoint = channel.getEndpoint();
     if (endpoint != null) {
       endpointId = endpoint.getID();
     }
   }
   return endpointId;
 }
  /**
   * Extracts a list of endpoint IDs from a list of {@link Endpoint}s.
   *
   * @param endpoints the list of {@link Endpoint}s.
   * @return the list of IDs of endpoints in {@code endpoints}.
   */
  private List<String> getIDs(List<Endpoint> endpoints) {
    if (endpoints != null && !endpoints.isEmpty()) {
      List<String> endpointIds = new LinkedList<>();
      for (Endpoint endpoint : endpoints) {
        endpointIds.add(endpoint.getID());
      }
      return endpointIds;
    }

    return null;
  }
  /**
   * Notifies this instance that the ordered list of endpoints in the conference has changed.
   *
   * @param endpoints the new ordered list of endpoints in the conference.
   * @return the list of endpoints which were added to the list of forwarded endpoints as a result
   *     of the call, or {@code null} if none were added.
   */
  public List<Endpoint> speechActivityEndpointsChanged(List<Endpoint> endpoints) {
    List<String> newEndpointIdList = getIDs(endpoints);
    List<String> enteringEndpointIds = speechActivityEndpointIdsChanged(newEndpointIdList);

    if (logger.isDebugEnabled()) {
      logger.debug(
          "New list of conference endpoints: "
              + newEndpointIdList.toString()
              + "; entering endpoints: "
              + (enteringEndpointIds == null ? "none" : enteringEndpointIds.toString()));
    }

    List<Endpoint> ret = new LinkedList<>();
    if (enteringEndpointIds != null) {
      for (Endpoint endpoint : endpoints) {
        if (enteringEndpointIds.contains(endpoint.getID())) {
          ret.add(endpoint);
        }
      }
    }

    return ret;
  }