public static boolean isTranscodeRequired(TranscodeProfile profile, AudioStream stream) {
    // Check audio codec
    if (getAudioChannelCount(stream.getConfiguration()) > 2) {
      if (profile.getMchCodecs() == null
          || !isSupported(profile.getMchCodecs(), stream.getCodec())) {
        return true;
      }
    } else {
      if (!isSupported(profile.getCodecs(), stream.getCodec())) {
        return true;
      }
    }

    // Check audio sample rate
    if (stream.getSampleRate() > profile.getMaxSampleRate()) {
      return true;
    }

    // If direct play is not enabled check stream parameters
    if (!profile.isDirectPlayEnabled()) {
      // Check bitrate for audio elements
      if (profile.getMediaElement().getType() == MediaElementType.AUDIO) {
        int bitrate =
            (getAudioChannelCount(stream.getConfiguration())
                * AUDIO_QUALITY_MAX_BITRATE[profile.getQuality()]);

        if (bitrate > 0 && profile.getMediaElement().getBitrate() > bitrate) {
          return true;
        }
      }
    }

    return false;
  }
  public static boolean processAudio(TranscodeProfile profile) {
    // Check variables
    if (profile.getMediaElement() == null
        || profile.getCodecs() == null
        || profile.getQuality() == null) {
      return false;
    }

    // If there are no audio streams to process we are done
    if (profile.getMediaElement().getAudioStreams() == null) {
      return true;
    }

    // Set audio track if necessary
    if (profile.getAudioTrack() == null) {
      if (profile.getMediaElement().getAudioStreams().size() > 0) {
        profile.setAudioTrack(0);
      } else {
        return true;
      }
    }

    // Check a format is specified for video transcode
    if (profile.getMediaElement().getType() == MediaElementType.VIDEO
        && profile.getFormat() == null) {
      return false;
    }

    // Process each audio stream
    List<AudioTranscode> transcodes = new ArrayList<>();

    for (AudioStream stream : profile.getMediaElement().getAudioStreams()) {
      String codec = null;
      Integer quality = null;
      Integer sampleRate = null;
      boolean downmix = false;

      // Check if transcoding is required
      boolean transcodeRequired = isTranscodeRequired(profile, stream);

      // Check the format supports this codec for video or that we can stream this codec for audio
      if (!transcodeRequired) {
        if (profile.getFormat() != null) {
          transcodeRequired =
              !isSupported(getCodecsForFormat(profile.getFormat()), stream.getCodec());
        } else {
          transcodeRequired = !isSupported(TRANSCODE_AUDIO_CODECS, stream.getCodec());
        }
      }

      if (!transcodeRequired) {
        // Work around transcoder bug where flac files have the wrong duration if the stream is
        // copied
        codec = "copy";

        // Get format if required
        if (profile.getFormat() == null) {
          profile.setFormat(getFormatForAudioCodec(stream.getCodec()));
        }
      } else {
        // Test if lossless codecs should be prioritised
        if (profile.getMediaElement().getType() == MediaElementType.AUDIO
            && (profile.getQuality() == AudioQuality.LOSSLESS || profile.isDirectPlayEnabled())
            && isSupported(LOSSLESS_CODECS, stream.getCodec())) {
          profile.setCodecs(sortStringList(profile.getCodecs(), LOSSLESS_CODECS));

          if (profile.mchCodecs != null) {
            profile.setMchCodecs(sortStringList(profile.getMchCodecs(), LOSSLESS_CODECS));
          }
        }

        // Check for multichannel codecs if this is a multichannel stream
        if (getAudioChannelCount(stream.getConfiguration()) > 2) {
          // Try to get a suitable multichannel codec
          if (profile.getMchCodecs() != null) {
            for (String test : profile.getMchCodecs()) {
              if (isSupported(TRANSCODE_AUDIO_CODECS, test)) {
                if (profile.getFormat() != null) {
                  if (isSupported(getCodecsForFormat(profile.getFormat()), test)) {
                    codec = test;
                    break;
                  }
                } else {
                  codec = test;
                  break;
                }
              }
            }
          }

          // If a codec couldn't be found we need to downmix to stereo
          if (codec == null) {
            downmix = true;
          }
        }

        // If we still don't have a codec just try anything...
        if (codec == null) {
          for (String test : profile.getCodecs()) {
            if (isSupported(TRANSCODE_AUDIO_CODECS, test)) {
              if (profile.getFormat() != null) {
                if (isSupported(getCodecsForFormat(profile.getFormat()), test)) {
                  codec = test;
                  break;
                }
              } else {
                codec = test;
                break;
              }
            }
          }
        }

        // Check audio parameters for codec
        if (codec != null) {

          // Sample rate
          if ((stream.getSampleRate() > profile.getMaxSampleRate())
              || (stream.getSampleRate() > getMaxSampleRateForCodec(codec))) {
            sampleRate =
                (profile.getMaxSampleRate() > getMaxSampleRateForCodec(codec))
                    ? getMaxSampleRateForCodec(codec)
                    : profile.getMaxSampleRate();
          }

          // Quality
          if (profile.getMediaElement().getType() == MediaElementType.AUDIO) {
            quality = getAudioQualityForCodec(codec, profile.getQuality());
          } else if (profile.getMediaElement().getType() == MediaElementType.VIDEO) {
            quality =
                getAudioQualityForCodec(codec, VIDEO_QUALITY_AUDIO_QUALITY[profile.getQuality()]);
          }

          // Get format if required
          if (profile.getFormat() == null) {
            profile.setFormat(getFormatForAudioCodec(codec));
          }

          // Update codec
          codec = getEncoderForAudioCodec(codec);
        }
      }

      // Add transcode properties to array
      transcodes.add(new AudioTranscode(codec, quality, sampleRate, downmix));
    }

    // Update profile with audio transcode properties
    profile.setAudioTranscodes(transcodes.toArray(new AudioTranscode[transcodes.size()]));

    return true;
  }