/** {@inheritDoc} */
        @Override
        public RawPacket transform(RawPacket pkt) {
          if (pkt == null) {
            return pkt;
          }

          RTCPCompoundPacket inPacket;
          try {
            inPacket =
                (RTCPCompoundPacket)
                    parser.parse(pkt.getBuffer(), pkt.getOffset(), pkt.getLength());
          } catch (BadFormatException e) {
            logger.warn("Failed to terminate an RTCP packet. " + "Dropping packet.");
            return null;
          }

          // Update our RTCP stats map (timestamps). This operation is
          // read-only.
          remoteClockEstimator.apply(inPacket);

          cnameRegistry.update(inPacket);

          // Remove SRs and RRs from the RTCP packet.
          pkt = feedbackGateway.gateway(inPacket);

          return pkt;
        }
  /**
   * Makes <tt>RTCPSDES</tt> packets for all the RTP streams that we're sending.
   *
   * @return a <tt>List</tt> of <tt>RTCPSDES</tt> packets for all the RTP streams that we're
   *     sending.
   */
  private RTCPSDESPacket makeSDESPacket() {
    Collection<RTCPSDES> sdesChunks = new ArrayList<RTCPSDES>();

    // Create an SDES for our own SSRC.
    RTCPSDES ownSDES = new RTCPSDES();

    SSRCInfo ourinfo = getStream().getStreamRTPManager().getSSRCCache().ourssrc;
    ownSDES.ssrc = (int) getLocalSSRC();
    Collection<RTCPSDESItem> ownItems = new ArrayList<RTCPSDESItem>();
    ownItems.add(new RTCPSDESItem(RTCPSDESItem.CNAME, ourinfo.sourceInfo.getCNAME()));

    // Throttle the source description bandwidth. See RFC3550#6.3.9
    // Allocation of Source Description Bandwidth.

    if (sdesCounter % 3 == 0) {
      if (ourinfo.name != null && ourinfo.name.getDescription() != null)
        ownItems.add(new RTCPSDESItem(RTCPSDESItem.NAME, ourinfo.name.getDescription()));
      if (ourinfo.email != null && ourinfo.email.getDescription() != null)
        ownItems.add(new RTCPSDESItem(RTCPSDESItem.EMAIL, ourinfo.email.getDescription()));
      if (ourinfo.phone != null && ourinfo.phone.getDescription() != null)
        ownItems.add(new RTCPSDESItem(RTCPSDESItem.PHONE, ourinfo.phone.getDescription()));
      if (ourinfo.loc != null && ourinfo.loc.getDescription() != null)
        ownItems.add(new RTCPSDESItem(RTCPSDESItem.LOC, ourinfo.loc.getDescription()));
      if (ourinfo.tool != null && ourinfo.tool.getDescription() != null)
        ownItems.add(new RTCPSDESItem(RTCPSDESItem.TOOL, ourinfo.tool.getDescription()));
      if (ourinfo.note != null && ourinfo.note.getDescription() != null)
        ownItems.add(new RTCPSDESItem(RTCPSDESItem.NOTE, ourinfo.note.getDescription()));
    }

    sdesCounter++;

    ownSDES.items = ownItems.toArray(new RTCPSDESItem[ownItems.size()]);

    sdesChunks.add(ownSDES);

    for (Map.Entry<Integer, byte[]> entry : cnameRegistry.entrySet()) {
      RTCPSDES sdes = new RTCPSDES();
      sdes.ssrc = entry.getKey();
      sdes.items = new RTCPSDESItem[] {new RTCPSDESItem(RTCPSDESItem.CNAME, entry.getValue())};
    }

    RTCPSDES[] sps = sdesChunks.toArray(new RTCPSDES[sdesChunks.size()]);
    RTCPSDESPacket sp = new RTCPSDESPacket(sps);

    return sp;
  }