/**
   * Gets the <tt>MediaFormat</tt>s among the specified <tt>mediaFormats</tt> which have the
   * specified <tt>encoding</tt> and, optionally, <tt>clockRate</tt>.
   *
   * @param mediaFormats the <tt>MediaFormat</tt>s from which to filter out only the ones which have
   *     the specified <tt>encoding</tt> and, optionally, <tt>clockRate</tt>
   * @param encoding the well-known encoding (name) of the <tt>MediaFormat</tt>s to be retrieved
   * @param clockRate the clock rate of the <tt>MediaFormat</tt>s to be retrieved; {@link
   *     #CLOCK_RATE_NOT_SPECIFIED} if any clock rate is acceptable
   * @return a <tt>List</tt> of the <tt>MediaFormat</tt>s among <tt>mediaFormats</tt> which have the
   *     specified <tt>encoding</tt> and, optionally, <tt>clockRate</tt>
   */
  private List<MediaFormat> getMatchingMediaFormats(
      MediaFormat[] mediaFormats, String encoding, double clockRate) {
    /*
     * XXX Use String#equalsIgnoreCase(String) because some clients transmit
     * some of the codecs starting with capital letters.
     */

    /*
     * As per RFC 3551.4.5.2, because of a mistake in RFC 1890 and for
     * backward compatibility, G.722 should always be announced as 8000 even
     * though it is wideband. So, if someone is looking for G722/16000,
     * then: Forgive them, for they know not what they do!
     */
    if ("G722".equalsIgnoreCase(encoding) && (16000 == clockRate)) {
      clockRate = 8000;
      if (logger.isInfoEnabled()) logger.info("Suppressing erroneous 16000 announcement for G.722");
    }

    List<MediaFormat> supportedMediaFormats = new ArrayList<MediaFormat>();

    for (MediaFormat mediaFormat : mediaFormats) {
      if (mediaFormat.getEncoding().equalsIgnoreCase(encoding)
          && ((CLOCK_RATE_NOT_SPECIFIED == clockRate)
              || (mediaFormat.getClockRate() == clockRate))) {
        supportedMediaFormats.add(mediaFormat);
      }
    }
    return supportedMediaFormats;
  }
  /**
   * Gets the <tt>MediaFormat</tt>s supported by this <tt>MediaFormatFactory</tt> and the
   * <tt>MediaService</tt> associated with it and having the specified <tt>encoding</tt> and,
   * optionally, <tt>clockRate</tt>.
   *
   * @param encoding the well-known encoding (name) of the <tt>MediaFormat</tt>s to be retrieved
   * @param clockRate the clock rate of the <tt>MediaFormat</tt>s to be retrieved; {@link
   *     #CLOCK_RATE_NOT_SPECIFIED} if any clock rate is acceptable
   * @return a <tt>List</tt> of the <tt>MediaFormat</tt>s supported by the <tt>MediaService</tt>
   *     associated with this <tt>MediaFormatFactory</tt> and having the specified encoding and,
   *     optionally, clock rate
   */
  private List<MediaFormat> getSupportedMediaFormats(String encoding, double clockRate) {
    EncodingConfiguration encodingConfiguration =
        NeomediaServiceUtils.getMediaServiceImpl().getCurrentEncodingConfiguration();
    List<MediaFormat> supportedMediaFormats =
        getMatchingMediaFormats(
            encodingConfiguration.getAllEncodings(MediaType.AUDIO), encoding, clockRate);

    if (supportedMediaFormats.isEmpty())
      supportedMediaFormats =
          getMatchingMediaFormats(
              encodingConfiguration.getAllEncodings(MediaType.VIDEO), encoding, clockRate);
    return supportedMediaFormats;
  }
  static {
    bannedYuvCodecs = new ArrayList<String>();

    // Banned H264 encoders/decoders
    // Crashes
    bannedYuvCodecs.add("OMX.SEC.avc.enc");
    bannedYuvCodecs.add("OMX.SEC.h263.enc");
    // Don't support 3.1 profile used by Jitsi
    bannedYuvCodecs.add("OMX.Nvidia.h264.decode");
    // bannedYuvCodecs.add("OMX.SEC.avc.dec");

    // Banned VP8 encoders/decoders
    bannedYuvCodecs.add("OMX.SEC.vp8.dec");
    // This one works only for res 176x144
    bannedYuvCodecs.add("OMX.google.vpx.encoder");

    for (int codecIndex = 0, codecCount = MediaCodecList.getCodecCount();
        codecIndex < codecCount;
        codecIndex++) {
      MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(codecIndex);
      logger.info(
          "Discovered codec: "
              + codecInfo.getName()
              + "/"
              + Arrays.toString(codecInfo.getSupportedTypes()));
      CodecInfo ci = CodecInfo.getCodecInfo(codecInfo);
      if (ci != null) {
        codecs.add(ci);
        ci.setBanned(bannedYuvCodecs.contains(ci.getName()));
      }
    }
    logger.info("Selected H264 encoder: " + getCodecForType(MEDIA_CODEC_TYPE_H264, true));
    logger.info("Selected H264 decoder: " + getCodecForType(MEDIA_CODEC_TYPE_H264, false));
    logger.info("Selected H263 encoder: " + getCodecForType(MEDIA_CODEC_TYPE_H263, true));
    logger.info("Selected H263 decoder: " + getCodecForType(MEDIA_CODEC_TYPE_H263, false));
    logger.info("Selected VP8 encoder: " + getCodecForType(MEDIA_CODEC_TYPE_VP8, true));
    logger.info("Selected VP8 decoder: " + getCodecForType(MEDIA_CODEC_TYPE_VP8, false));
  }