/**
   * Notifies this instance that a <tt>DatagramPacket</tt> packet received on the data
   * <tt>DatagramSocket</tt> of this <tt>Channel</tt> has been accepted for further processing
   * within Jitsi Videobridge.
   *
   * @param pkt the accepted <tt>RawPacket</tt>.
   */
  public void accepted(RawPacket pkt) {
    // With native simulcast we don't have a notification when a stream
    // has started/stopped. The simulcast manager implements a timeout
    // for the high quality stream and it needs to be notified when
    // the channel has accepted a datagram packet for the timeout to
    // function correctly.

    if (!hasLayers() || pkt == null) {
      return;
    }

    // Find the layer that corresponds to this packet.
    int acceptedSSRC = pkt.getSSRC();
    SimulcastLayer[] layers = getSimulcastLayers();
    SimulcastLayer acceptedLayer = null;
    for (SimulcastLayer layer : layers) {
      // We only care about the primary SSRC and not the RTX ssrc (or
      // future FEC ssrc).
      if ((int) layer.getPrimarySSRC() == acceptedSSRC) {
        acceptedLayer = layer;
        break;
      }
    }

    // If this is not an RTP packet or if we can't find an accepted
    // layer, log and return as it makes no sense to continue in this
    // situation.
    if (acceptedLayer == null) {
      return;
    }

    // There are sequences of packets with increasing timestamps but without
    // the marker bit set. Supposedly, they are probes to detect whether the
    // bandwidth may increase. We think that they should cause neither the
    // start nor the stop of any SimulcastLayer.

    // XXX There's RawPacket#getPayloadLength() but the implementation
    // includes pkt.paddingSize at the time of this writing and we do not
    // know whether that's going to stay that way.
    int pktPayloadLength = pkt.getLength() - pkt.getHeaderLength();
    int pktPaddingSize = pkt.getPaddingSize();

    if (pktPayloadLength <= pktPaddingSize) {
      if (logger.isTraceEnabled()) {
        logger.trace(
            "pkt.payloadLength= "
                + pktPayloadLength
                + " <= pkt.paddingSize= "
                + pktPaddingSize
                + "("
                + pkt.getSequenceNumber()
                + ")");
      }
      return;
    }

    // NOTE(gp) we expect the base layer to be always on, so we never touch
    // it or starve it.

    // XXX Refer to the implementation of
    // SimulcastLayer#touch(boolean, RawPacket) for an explanation of why we
    // chose to use a return value.
    boolean frameStarted = acceptedLayer.touch(pkt);
    if (frameStarted) simulcastLayerFrameStarted(acceptedLayer, pkt, layers);
  }