Java Code Examples for com.google.android.exoplayer2.mediacodec.MediaCodecInfo#isSeamlessAdaptationSupported()

The following examples show how to use com.google.android.exoplayer2.mediacodec.MediaCodecInfo#isSeamlessAdaptationSupported() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: MediaCodecAudioRenderer.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
@Override
protected @KeepCodecResult int canKeepCodec(
    MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
  // TODO: We currently rely on recreating the codec when encoder delay or padding is non-zero.
  // Re-creating the codec is necessary to guarantee that onOutputFormatChanged is called, which
  // is where encoder delay and padding are propagated to the sink. We should find a better way to
  // propagate these values, and then allow the codec to be re-used in cases where this would
  // otherwise be possible.
  if (getCodecMaxInputSize(codecInfo, newFormat) > codecMaxInputSize
      || oldFormat.encoderDelay != 0
      || oldFormat.encoderPadding != 0
      || newFormat.encoderDelay != 0
      || newFormat.encoderPadding != 0) {
    return KEEP_CODEC_RESULT_NO;
  } else if (codecInfo.isSeamlessAdaptationSupported(
      oldFormat, newFormat, /* isNewFormatComplete= */ true)) {
    return KEEP_CODEC_RESULT_YES_WITHOUT_RECONFIGURATION;
  } else if (canKeepCodecWithFlush(oldFormat, newFormat)) {
    return KEEP_CODEC_RESULT_YES_WITH_FLUSH;
  } else {
    return KEEP_CODEC_RESULT_NO;
  }
}
 
Example 2
Source File: MediaCodecAudioRenderer.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
/**
 * Returns a maximum input size suitable for configuring a codec for {@code format} in a way that
 * will allow possible adaptation to other compatible formats in {@code streamFormats}.
 *
 * @param codecInfo A {@link MediaCodecInfo} describing the decoder.
 * @param format The {@link Format} for which the codec is being configured.
 * @param streamFormats The possible stream formats.
 * @return A suitable maximum input size.
 */
protected int getCodecMaxInputSize(
    MediaCodecInfo codecInfo, Format format, Format[] streamFormats) {
  int maxInputSize = getCodecMaxInputSize(codecInfo, format);
  if (streamFormats.length == 1) {
    // The single entry in streamFormats must correspond to the format for which the codec is
    // being configured.
    return maxInputSize;
  }
  for (Format streamFormat : streamFormats) {
    if (codecInfo.isSeamlessAdaptationSupported(
        format, streamFormat, /* isNewFormatComplete= */ false)) {
      maxInputSize = Math.max(maxInputSize, getCodecMaxInputSize(codecInfo, streamFormat));
    }
  }
  return maxInputSize;
}
 
Example 3
Source File: MediaCodecAudioRenderer.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
@Override
protected @KeepCodecResult int canKeepCodec(
    MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
  // TODO: We currently rely on recreating the codec when encoder delay or padding is non-zero.
  // Re-creating the codec is necessary to guarantee that onOutputFormatChanged is called, which
  // is where encoder delay and padding are propagated to the sink. We should find a better way to
  // propagate these values, and then allow the codec to be re-used in cases where this would
  // otherwise be possible.
  if (getCodecMaxInputSize(codecInfo, newFormat) > codecMaxInputSize
      || oldFormat.encoderDelay != 0
      || oldFormat.encoderPadding != 0
      || newFormat.encoderDelay != 0
      || newFormat.encoderPadding != 0) {
    return KEEP_CODEC_RESULT_NO;
  } else if (codecInfo.isSeamlessAdaptationSupported(
      oldFormat, newFormat, /* isNewFormatComplete= */ true)) {
    return KEEP_CODEC_RESULT_YES_WITHOUT_RECONFIGURATION;
  } else if (areCodecConfigurationCompatible(oldFormat, newFormat)) {
    return KEEP_CODEC_RESULT_YES_WITH_FLUSH;
  } else {
    return KEEP_CODEC_RESULT_NO;
  }
}
 
Example 4
Source File: MediaCodecAudioRenderer.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Returns a maximum input size suitable for configuring a codec for {@code format} in a way that
 * will allow possible adaptation to other compatible formats in {@code streamFormats}.
 *
 * @param codecInfo A {@link MediaCodecInfo} describing the decoder.
 * @param format The format for which the codec is being configured.
 * @param streamFormats The possible stream formats.
 * @return A suitable maximum input size.
 */
protected int getCodecMaxInputSize(
    MediaCodecInfo codecInfo, Format format, Format[] streamFormats) {
  int maxInputSize = getCodecMaxInputSize(codecInfo, format);
  if (streamFormats.length == 1) {
    // The single entry in streamFormats must correspond to the format for which the codec is
    // being configured.
    return maxInputSize;
  }
  for (Format streamFormat : streamFormats) {
    if (codecInfo.isSeamlessAdaptationSupported(
        format, streamFormat, /* isNewFormatComplete= */ false)) {
      maxInputSize = Math.max(maxInputSize, getCodecMaxInputSize(codecInfo, streamFormat));
    }
  }
  return maxInputSize;
}
 
Example 5
Source File: MediaCodecVideoRenderer.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
@Override
protected @KeepCodecResult int canKeepCodec(
    MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
  if (codecInfo.isSeamlessAdaptationSupported(
          oldFormat, newFormat, /* isNewFormatComplete= */ true)
      && newFormat.width <= codecMaxValues.width
      && newFormat.height <= codecMaxValues.height
      && getMaxInputSize(codecInfo, newFormat) <= codecMaxValues.inputSize) {
    return oldFormat.initializationDataEquals(newFormat)
        ? KEEP_CODEC_RESULT_YES_WITHOUT_RECONFIGURATION
        : KEEP_CODEC_RESULT_YES_WITH_RECONFIGURATION;
  }
  return KEEP_CODEC_RESULT_NO;
}
 
Example 6
Source File: MediaCodecAudioRenderer.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
@Override
protected @KeepCodecResult int canKeepCodec(
    MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
  // TODO: We currently rely on recreating the codec when encoder delay or padding is non-zero.
  // Re-creating the codec is necessary to guarantee that onOutputFormatChanged is called, which
  // is where encoder delay and padding are propagated to the sink. We should find a better way to
  // propagate these values, and then allow the codec to be re-used in cases where this would
  // otherwise be possible.
  if (getCodecMaxInputSize(codecInfo, newFormat) > codecMaxInputSize
      || oldFormat.encoderDelay != 0
      || oldFormat.encoderPadding != 0
      || newFormat.encoderDelay != 0
      || newFormat.encoderPadding != 0) {
    return KEEP_CODEC_RESULT_NO;
  } else if (codecInfo.isSeamlessAdaptationSupported(
      oldFormat, newFormat, /* isNewFormatComplete= */ true)) {
    return KEEP_CODEC_RESULT_YES_WITHOUT_RECONFIGURATION;
  } else if (areCodecConfigurationCompatible(oldFormat, newFormat)) {
    return KEEP_CODEC_RESULT_YES_WITH_FLUSH;
  } else {
    return KEEP_CODEC_RESULT_NO;
  }
}
 
Example 7
Source File: MediaCodecAudioRenderer.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Returns a maximum input size suitable for configuring a codec for {@code format} in a way that
 * will allow possible adaptation to other compatible formats in {@code streamFormats}.
 *
 * @param codecInfo A {@link MediaCodecInfo} describing the decoder.
 * @param format The format for which the codec is being configured.
 * @param streamFormats The possible stream formats.
 * @return A suitable maximum input size.
 */
protected int getCodecMaxInputSize(
    MediaCodecInfo codecInfo, Format format, Format[] streamFormats) {
  int maxInputSize = getCodecMaxInputSize(codecInfo, format);
  if (streamFormats.length == 1) {
    // The single entry in streamFormats must correspond to the format for which the codec is
    // being configured.
    return maxInputSize;
  }
  for (Format streamFormat : streamFormats) {
    if (codecInfo.isSeamlessAdaptationSupported(
        format, streamFormat, /* isNewFormatComplete= */ false)) {
      maxInputSize = Math.max(maxInputSize, getCodecMaxInputSize(codecInfo, streamFormat));
    }
  }
  return maxInputSize;
}
 
Example 8
Source File: MediaCodecVideoRenderer.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
@Override
protected @KeepCodecResult int canKeepCodec(
    MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
  if (codecInfo.isSeamlessAdaptationSupported(
          oldFormat, newFormat, /* isNewFormatComplete= */ true)
      && newFormat.width <= codecMaxValues.width
      && newFormat.height <= codecMaxValues.height
      && getMaxInputSize(codecInfo, newFormat) <= codecMaxValues.inputSize) {
    return oldFormat.initializationDataEquals(newFormat)
        ? KEEP_CODEC_RESULT_YES_WITHOUT_RECONFIGURATION
        : KEEP_CODEC_RESULT_YES_WITH_RECONFIGURATION;
  }
  return KEEP_CODEC_RESULT_NO;
}
 
Example 9
Source File: MediaCodecVideoRenderer.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
@Override
protected @KeepCodecResult int canKeepCodec(
    MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
  if (codecInfo.isSeamlessAdaptationSupported(
          oldFormat, newFormat, /* isNewFormatComplete= */ true)
      && newFormat.width <= codecMaxValues.width
      && newFormat.height <= codecMaxValues.height
      && getMaxInputSize(codecInfo, newFormat) <= codecMaxValues.inputSize) {
    return oldFormat.initializationDataEquals(newFormat)
        ? KEEP_CODEC_RESULT_YES_WITHOUT_RECONFIGURATION
        : KEEP_CODEC_RESULT_YES_WITH_RECONFIGURATION;
  }
  return KEEP_CODEC_RESULT_NO;
}
 
Example 10
Source File: MediaCodecAudioRenderer.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
@Override
@Capabilities
protected int supportsFormat(
    MediaCodecSelector mediaCodecSelector,
    @Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
    Format format)
    throws DecoderQueryException {
  String mimeType = format.sampleMimeType;
  if (!MimeTypes.isAudio(mimeType)) {
    return RendererCapabilities.create(FORMAT_UNSUPPORTED_TYPE);
  }
  @TunnelingSupport
  int tunnelingSupport = Util.SDK_INT >= 21 ? TUNNELING_SUPPORTED : TUNNELING_NOT_SUPPORTED;
  boolean supportsFormatDrm =
      format.drmInitData == null
          || FrameworkMediaCrypto.class.equals(format.exoMediaCryptoType)
          || (format.exoMediaCryptoType == null
              && supportsFormatDrm(drmSessionManager, format.drmInitData));
  if (supportsFormatDrm
      && allowPassthrough(format.channelCount, mimeType)
      && mediaCodecSelector.getPassthroughDecoderInfo() != null) {
    return RendererCapabilities.create(FORMAT_HANDLED, ADAPTIVE_NOT_SEAMLESS, tunnelingSupport);
  }
  if ((MimeTypes.AUDIO_RAW.equals(mimeType)
          && !audioSink.supportsOutput(format.channelCount, format.pcmEncoding))
      || !audioSink.supportsOutput(format.channelCount, C.ENCODING_PCM_16BIT)) {
    // Assume the decoder outputs 16-bit PCM, unless the input is raw.
    return RendererCapabilities.create(FORMAT_UNSUPPORTED_SUBTYPE);
  }
  List<MediaCodecInfo> decoderInfos =
      getDecoderInfos(mediaCodecSelector, format, /* requiresSecureDecoder= */ false);
  if (decoderInfos.isEmpty()) {
    return RendererCapabilities.create(FORMAT_UNSUPPORTED_SUBTYPE);
  }
  if (!supportsFormatDrm) {
    return RendererCapabilities.create(FORMAT_UNSUPPORTED_DRM);
  }
  // Check capabilities for the first decoder in the list, which takes priority.
  MediaCodecInfo decoderInfo = decoderInfos.get(0);
  boolean isFormatSupported = decoderInfo.isFormatSupported(format);
  @AdaptiveSupport
  int adaptiveSupport =
      isFormatSupported && decoderInfo.isSeamlessAdaptationSupported(format)
          ? ADAPTIVE_SEAMLESS
          : ADAPTIVE_NOT_SEAMLESS;
  @FormatSupport
  int formatSupport = isFormatSupported ? FORMAT_HANDLED : FORMAT_EXCEEDS_CAPABILITIES;
  return RendererCapabilities.create(formatSupport, adaptiveSupport, tunnelingSupport);
}
 
Example 11
Source File: MediaCodecVideoRenderer.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
@Override
@Capabilities
protected int supportsFormat(
    MediaCodecSelector mediaCodecSelector,
    @Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
    Format format)
    throws DecoderQueryException {
  String mimeType = format.sampleMimeType;
  if (!MimeTypes.isVideo(mimeType)) {
    return RendererCapabilities.create(FORMAT_UNSUPPORTED_TYPE);
  }
  @Nullable DrmInitData drmInitData = format.drmInitData;
  // Assume encrypted content requires secure decoders.
  boolean requiresSecureDecryption = drmInitData != null;
  List<MediaCodecInfo> decoderInfos =
      getDecoderInfos(
          mediaCodecSelector,
          format,
          requiresSecureDecryption,
          /* requiresTunnelingDecoder= */ false);
  if (requiresSecureDecryption && decoderInfos.isEmpty()) {
    // No secure decoders are available. Fall back to non-secure decoders.
    decoderInfos =
        getDecoderInfos(
            mediaCodecSelector,
            format,
            /* requiresSecureDecoder= */ false,
            /* requiresTunnelingDecoder= */ false);
  }
  if (decoderInfos.isEmpty()) {
    return RendererCapabilities.create(FORMAT_UNSUPPORTED_SUBTYPE);
  }
  boolean supportsFormatDrm =
      drmInitData == null
          || FrameworkMediaCrypto.class.equals(format.exoMediaCryptoType)
          || (format.exoMediaCryptoType == null
              && supportsFormatDrm(drmSessionManager, drmInitData));
  if (!supportsFormatDrm) {
    return RendererCapabilities.create(FORMAT_UNSUPPORTED_DRM);
  }
  // Check capabilities for the first decoder in the list, which takes priority.
  MediaCodecInfo decoderInfo = decoderInfos.get(0);
  boolean isFormatSupported = decoderInfo.isFormatSupported(format);
  @AdaptiveSupport
  int adaptiveSupport =
      decoderInfo.isSeamlessAdaptationSupported(format)
          ? ADAPTIVE_SEAMLESS
          : ADAPTIVE_NOT_SEAMLESS;
  @TunnelingSupport int tunnelingSupport = TUNNELING_NOT_SUPPORTED;
  if (isFormatSupported) {
    List<MediaCodecInfo> tunnelingDecoderInfos =
        getDecoderInfos(
            mediaCodecSelector,
            format,
            requiresSecureDecryption,
            /* requiresTunnelingDecoder= */ true);
    if (!tunnelingDecoderInfos.isEmpty()) {
      MediaCodecInfo tunnelingDecoderInfo = tunnelingDecoderInfos.get(0);
      if (tunnelingDecoderInfo.isFormatSupported(format)
          && tunnelingDecoderInfo.isSeamlessAdaptationSupported(format)) {
        tunnelingSupport = TUNNELING_SUPPORTED;
      }
    }
  }
  @FormatSupport
  int formatSupport = isFormatSupported ? FORMAT_HANDLED : FORMAT_EXCEEDS_CAPABILITIES;
  return RendererCapabilities.create(formatSupport, adaptiveSupport, tunnelingSupport);
}
 
Example 12
Source File: MediaCodecVideoRenderer.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
/**
 * Returns {@link CodecMaxValues} suitable for configuring a codec for {@code format} in a way
 * that will allow possible adaptation to other compatible formats in {@code streamFormats}.
 *
 * @param codecInfo Information about the {@link MediaCodec} being configured.
 * @param format The {@link Format} for which the codec is being configured.
 * @param streamFormats The possible stream formats.
 * @return Suitable {@link CodecMaxValues}.
 */
protected CodecMaxValues getCodecMaxValues(
    MediaCodecInfo codecInfo, Format format, Format[] streamFormats) {
  int maxWidth = format.width;
  int maxHeight = format.height;
  int maxInputSize = getMaxInputSize(codecInfo, format);
  if (streamFormats.length == 1) {
    // The single entry in streamFormats must correspond to the format for which the codec is
    // being configured.
    if (maxInputSize != Format.NO_VALUE) {
      int codecMaxInputSize =
          getCodecMaxInputSize(codecInfo, format.sampleMimeType, format.width, format.height);
      if (codecMaxInputSize != Format.NO_VALUE) {
        // Scale up the initial video decoder maximum input size so playlist item transitions with
        // small increases in maximum sample size don't require reinitialization. This only makes
        // a difference if the exact maximum sample sizes are known from the container.
        int scaledMaxInputSize =
            (int) (maxInputSize * INITIAL_FORMAT_MAX_INPUT_SIZE_SCALE_FACTOR);
        // Avoid exceeding the maximum expected for the codec.
        maxInputSize = Math.min(scaledMaxInputSize, codecMaxInputSize);
      }
    }
    return new CodecMaxValues(maxWidth, maxHeight, maxInputSize);
  }
  boolean haveUnknownDimensions = false;
  for (Format streamFormat : streamFormats) {
    if (codecInfo.isSeamlessAdaptationSupported(
        format, streamFormat, /* isNewFormatComplete= */ false)) {
      haveUnknownDimensions |=
          (streamFormat.width == Format.NO_VALUE || streamFormat.height == Format.NO_VALUE);
      maxWidth = Math.max(maxWidth, streamFormat.width);
      maxHeight = Math.max(maxHeight, streamFormat.height);
      maxInputSize = Math.max(maxInputSize, getMaxInputSize(codecInfo, streamFormat));
    }
  }
  if (haveUnknownDimensions) {
    Log.w(TAG, "Resolutions unknown. Codec max resolution: " + maxWidth + "x" + maxHeight);
    Point codecMaxSize = getCodecMaxSize(codecInfo, format);
    if (codecMaxSize != null) {
      maxWidth = Math.max(maxWidth, codecMaxSize.x);
      maxHeight = Math.max(maxHeight, codecMaxSize.y);
      maxInputSize =
          Math.max(
              maxInputSize,
              getCodecMaxInputSize(codecInfo, format.sampleMimeType, maxWidth, maxHeight));
      Log.w(TAG, "Codec max resolution adjusted to: " + maxWidth + "x" + maxHeight);
    }
  }
  return new CodecMaxValues(maxWidth, maxHeight, maxInputSize);
}
 
Example 13
Source File: MediaCodecVideoRenderer.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
@Override
protected int supportsFormat(MediaCodecSelector mediaCodecSelector,
    DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, Format format)
    throws DecoderQueryException {
  String mimeType = format.sampleMimeType;
  if (!MimeTypes.isVideo(mimeType)) {
    return FORMAT_UNSUPPORTED_TYPE;
  }
  boolean requiresSecureDecryption = false;
  DrmInitData drmInitData = format.drmInitData;
  if (drmInitData != null) {
    for (int i = 0; i < drmInitData.schemeDataCount; i++) {
      requiresSecureDecryption |= drmInitData.get(i).requiresSecureDecryption;
    }
  }
  List<MediaCodecInfo> decoderInfos =
      getDecoderInfos(mediaCodecSelector, format, requiresSecureDecryption);
  if (decoderInfos.isEmpty()) {
    return requiresSecureDecryption
            && !mediaCodecSelector
                .getDecoderInfos(
                    format.sampleMimeType,
                    /* requiresSecureDecoder= */ false,
                    /* requiresTunnelingDecoder= */ false)
                .isEmpty()
        ? FORMAT_UNSUPPORTED_DRM
        : FORMAT_UNSUPPORTED_SUBTYPE;
  }
  if (!supportsFormatDrm(drmSessionManager, drmInitData)) {
    return FORMAT_UNSUPPORTED_DRM;
  }
  // Check capabilities for the first decoder in the list, which takes priority.
  MediaCodecInfo decoderInfo = decoderInfos.get(0);
  boolean isFormatSupported = decoderInfo.isFormatSupported(format);
  int adaptiveSupport =
      decoderInfo.isSeamlessAdaptationSupported(format)
          ? ADAPTIVE_SEAMLESS
          : ADAPTIVE_NOT_SEAMLESS;
  int tunnelingSupport = TUNNELING_NOT_SUPPORTED;
  if (isFormatSupported) {
    List<MediaCodecInfo> tunnelingDecoderInfos =
        mediaCodecSelector.getDecoderInfos(
            format.sampleMimeType,
            requiresSecureDecryption,
            /* requiresTunnelingDecoder= */ true);
    if (!tunnelingDecoderInfos.isEmpty()) {
      MediaCodecInfo tunnelingDecoderInfo = tunnelingDecoderInfos.get(0);
      if (tunnelingDecoderInfo.isFormatSupported(format)
          && tunnelingDecoderInfo.isSeamlessAdaptationSupported(format)) {
        tunnelingSupport = TUNNELING_SUPPORTED;
      }
    }
  }
  int formatSupport = isFormatSupported ? FORMAT_HANDLED : FORMAT_EXCEEDS_CAPABILITIES;
  return adaptiveSupport | tunnelingSupport | formatSupport;
}
 
Example 14
Source File: MediaCodecVideoRenderer.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Returns {@link CodecMaxValues} suitable for configuring a codec for {@code format} in a way
 * that will allow possible adaptation to other compatible formats in {@code streamFormats}.
 *
 * @param codecInfo Information about the {@link MediaCodec} being configured.
 * @param format The format for which the codec is being configured.
 * @param streamFormats The possible stream formats.
 * @return Suitable {@link CodecMaxValues}.
 */
protected CodecMaxValues getCodecMaxValues(
    MediaCodecInfo codecInfo, Format format, Format[] streamFormats) {
  int maxWidth = format.width;
  int maxHeight = format.height;
  int maxInputSize = getMaxInputSize(codecInfo, format);
  if (streamFormats.length == 1) {
    // The single entry in streamFormats must correspond to the format for which the codec is
    // being configured.
    if (maxInputSize != Format.NO_VALUE) {
      int codecMaxInputSize =
          getCodecMaxInputSize(codecInfo, format.sampleMimeType, format.width, format.height);
      if (codecMaxInputSize != Format.NO_VALUE) {
        // Scale up the initial video decoder maximum input size so playlist item transitions with
        // small increases in maximum sample size don't require reinitialization. This only makes
        // a difference if the exact maximum sample sizes are known from the container.
        int scaledMaxInputSize =
            (int) (maxInputSize * INITIAL_FORMAT_MAX_INPUT_SIZE_SCALE_FACTOR);
        // Avoid exceeding the maximum expected for the codec.
        maxInputSize = Math.min(scaledMaxInputSize, codecMaxInputSize);
      }
    }
    return new CodecMaxValues(maxWidth, maxHeight, maxInputSize);
  }
  boolean haveUnknownDimensions = false;
  for (Format streamFormat : streamFormats) {
    if (codecInfo.isSeamlessAdaptationSupported(
        format, streamFormat, /* isNewFormatComplete= */ false)) {
      haveUnknownDimensions |=
          (streamFormat.width == Format.NO_VALUE || streamFormat.height == Format.NO_VALUE);
      maxWidth = Math.max(maxWidth, streamFormat.width);
      maxHeight = Math.max(maxHeight, streamFormat.height);
      maxInputSize = Math.max(maxInputSize, getMaxInputSize(codecInfo, streamFormat));
    }
  }
  if (haveUnknownDimensions) {
    Log.w(TAG, "Resolutions unknown. Codec max resolution: " + maxWidth + "x" + maxHeight);
    Point codecMaxSize = getCodecMaxSize(codecInfo, format);
    if (codecMaxSize != null) {
      maxWidth = Math.max(maxWidth, codecMaxSize.x);
      maxHeight = Math.max(maxHeight, codecMaxSize.y);
      maxInputSize =
          Math.max(
              maxInputSize,
              getCodecMaxInputSize(codecInfo, format.sampleMimeType, maxWidth, maxHeight));
      Log.w(TAG, "Codec max resolution adjusted to: " + maxWidth + "x" + maxHeight);
    }
  }
  return new CodecMaxValues(maxWidth, maxHeight, maxInputSize);
}
 
Example 15
Source File: MediaCodecVideoRenderer.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
@Override
protected int supportsFormat(MediaCodecSelector mediaCodecSelector,
    DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, Format format)
    throws DecoderQueryException {
  String mimeType = format.sampleMimeType;
  if (!MimeTypes.isVideo(mimeType)) {
    return FORMAT_UNSUPPORTED_TYPE;
  }
  boolean requiresSecureDecryption = false;
  DrmInitData drmInitData = format.drmInitData;
  if (drmInitData != null) {
    for (int i = 0; i < drmInitData.schemeDataCount; i++) {
      requiresSecureDecryption |= drmInitData.get(i).requiresSecureDecryption;
    }
  }
  List<MediaCodecInfo> decoderInfos =
      getDecoderInfos(mediaCodecSelector, format, requiresSecureDecryption);
  if (decoderInfos.isEmpty()) {
    return requiresSecureDecryption
            && !mediaCodecSelector
                .getDecoderInfos(
                    format.sampleMimeType,
                    /* requiresSecureDecoder= */ false,
                    /* requiresTunnelingDecoder= */ false)
                .isEmpty()
        ? FORMAT_UNSUPPORTED_DRM
        : FORMAT_UNSUPPORTED_SUBTYPE;
  }
  if (!supportsFormatDrm(drmSessionManager, drmInitData)) {
    return FORMAT_UNSUPPORTED_DRM;
  }
  // Check capabilities for the first decoder in the list, which takes priority.
  MediaCodecInfo decoderInfo = decoderInfos.get(0);
  boolean isFormatSupported = decoderInfo.isFormatSupported(format);
  int adaptiveSupport =
      decoderInfo.isSeamlessAdaptationSupported(format)
          ? ADAPTIVE_SEAMLESS
          : ADAPTIVE_NOT_SEAMLESS;
  int tunnelingSupport = TUNNELING_NOT_SUPPORTED;
  if (isFormatSupported) {
    List<MediaCodecInfo> tunnelingDecoderInfos =
        mediaCodecSelector.getDecoderInfos(
            format.sampleMimeType,
            requiresSecureDecryption,
            /* requiresTunnelingDecoder= */ true);
    if (!tunnelingDecoderInfos.isEmpty()) {
      MediaCodecInfo tunnelingDecoderInfo = tunnelingDecoderInfos.get(0);
      if (tunnelingDecoderInfo.isFormatSupported(format)
          && tunnelingDecoderInfo.isSeamlessAdaptationSupported(format)) {
        tunnelingSupport = TUNNELING_SUPPORTED;
      }
    }
  }
  int formatSupport = isFormatSupported ? FORMAT_HANDLED : FORMAT_EXCEEDS_CAPABILITIES;
  return adaptiveSupport | tunnelingSupport | formatSupport;
}
 
Example 16
Source File: MediaCodecVideoRenderer.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Returns {@link CodecMaxValues} suitable for configuring a codec for {@code format} in a way
 * that will allow possible adaptation to other compatible formats in {@code streamFormats}.
 *
 * @param codecInfo Information about the {@link MediaCodec} being configured.
 * @param format The format for which the codec is being configured.
 * @param streamFormats The possible stream formats.
 * @return Suitable {@link CodecMaxValues}.
 */
protected CodecMaxValues getCodecMaxValues(
    MediaCodecInfo codecInfo, Format format, Format[] streamFormats) {
  int maxWidth = format.width;
  int maxHeight = format.height;
  int maxInputSize = getMaxInputSize(codecInfo, format);
  if (streamFormats.length == 1) {
    // The single entry in streamFormats must correspond to the format for which the codec is
    // being configured.
    if (maxInputSize != Format.NO_VALUE) {
      int codecMaxInputSize =
          getCodecMaxInputSize(codecInfo, format.sampleMimeType, format.width, format.height);
      if (codecMaxInputSize != Format.NO_VALUE) {
        // Scale up the initial video decoder maximum input size so playlist item transitions with
        // small increases in maximum sample size don't require reinitialization. This only makes
        // a difference if the exact maximum sample sizes are known from the container.
        int scaledMaxInputSize =
            (int) (maxInputSize * INITIAL_FORMAT_MAX_INPUT_SIZE_SCALE_FACTOR);
        // Avoid exceeding the maximum expected for the codec.
        maxInputSize = Math.min(scaledMaxInputSize, codecMaxInputSize);
      }
    }
    return new CodecMaxValues(maxWidth, maxHeight, maxInputSize);
  }
  boolean haveUnknownDimensions = false;
  for (Format streamFormat : streamFormats) {
    if (codecInfo.isSeamlessAdaptationSupported(
        format, streamFormat, /* isNewFormatComplete= */ false)) {
      haveUnknownDimensions |=
          (streamFormat.width == Format.NO_VALUE || streamFormat.height == Format.NO_VALUE);
      maxWidth = Math.max(maxWidth, streamFormat.width);
      maxHeight = Math.max(maxHeight, streamFormat.height);
      maxInputSize = Math.max(maxInputSize, getMaxInputSize(codecInfo, streamFormat));
    }
  }
  if (haveUnknownDimensions) {
    Log.w(TAG, "Resolutions unknown. Codec max resolution: " + maxWidth + "x" + maxHeight);
    Point codecMaxSize = getCodecMaxSize(codecInfo, format);
    if (codecMaxSize != null) {
      maxWidth = Math.max(maxWidth, codecMaxSize.x);
      maxHeight = Math.max(maxHeight, codecMaxSize.y);
      maxInputSize =
          Math.max(
              maxInputSize,
              getCodecMaxInputSize(codecInfo, format.sampleMimeType, maxWidth, maxHeight));
      Log.w(TAG, "Codec max resolution adjusted to: " + maxWidth + "x" + maxHeight);
    }
  }
  return new CodecMaxValues(maxWidth, maxHeight, maxInputSize);
}