com.google.android.exoplayer2.mediacodec.MediaCodecInfo Java Examples

The following examples show how to use com.google.android.exoplayer2.mediacodec.MediaCodecInfo. 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 TelePlus-Android 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 (areAdaptationCompatible(format, streamFormat)) {
  //     maxInputSize = Math.max(maxInputSize, getCodecMaxInputSize(codecInfo, streamFormat));
  //   }
  // }
  return maxInputSize;
}
 
Example #2
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 #3
Source File: MediaCodecVideoRenderer.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Returns a maximum input buffer size for a given codec and format.
 *
 * @param codecInfo Information about the {@link MediaCodec} being configured.
 * @param format The format.
 * @return A maximum input buffer size in bytes, or {@link Format#NO_VALUE} if a maximum could not
 *     be determined.
 */
private static int getMaxInputSize(MediaCodecInfo codecInfo, Format format) {
  if (format.maxInputSize != Format.NO_VALUE) {
    // The format defines an explicit maximum input size. Add the total size of initialization
    // data buffers, as they may need to be queued in the same input buffer as the largest sample.
    int totalInitializationDataSize = 0;
    int initializationDataCount = format.initializationData.size();
    for (int i = 0; i < initializationDataCount; i++) {
      totalInitializationDataSize += format.initializationData.get(i).length;
    }
    return format.maxInputSize + totalInitializationDataSize;
  } else {
    // Calculated maximum input sizes are overestimates, so it's not necessary to add the size of
    // initialization data.
    return getCodecMaxInputSize(codecInfo, format.sampleMimeType, format.width, format.height);
  }
}
 
Example #4
Source File: MediaCodecAudioRenderer.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
@Override
protected List<MediaCodecInfo> getDecoderInfos(
    MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder)
    throws DecoderQueryException {
  if (allowPassthrough(format.channelCount, format.sampleMimeType)) {
    MediaCodecInfo passthroughDecoderInfo = mediaCodecSelector.getPassthroughDecoderInfo();
    if (passthroughDecoderInfo != null) {
      return Collections.singletonList(passthroughDecoderInfo);
    }
  }
  List<MediaCodecInfo> decoderInfos =
      mediaCodecSelector.getDecoderInfos(
          format.sampleMimeType, requiresSecureDecoder, /* requiresTunnelingDecoder= */ false);
  if (MimeTypes.AUDIO_E_AC3_JOC.equals(format.sampleMimeType)) {
    // E-AC3 decoders can decode JOC streams, but in 2-D rather than 3-D.
    List<MediaCodecInfo> decoderInfosWithEac3 = new ArrayList<>(decoderInfos);
    decoderInfosWithEac3.addAll(
        mediaCodecSelector.getDecoderInfos(
            MimeTypes.AUDIO_E_AC3, requiresSecureDecoder, /* requiresTunnelingDecoder= */ false));
    decoderInfos = decoderInfosWithEac3;
  }
  return Collections.unmodifiableList(decoderInfos);
}
 
Example #5
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 #6
Source File: MediaCodecVideoRenderer.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
@Override
protected void configureCodec(
    MediaCodecInfo codecInfo,
    MediaCodec codec,
    Format format,
    MediaCrypto crypto,
    float codecOperatingRate) {
  String codecMimeType = codecInfo.codecMimeType;
  codecMaxValues = getCodecMaxValues(codecInfo, format, getStreamFormats());
  MediaFormat mediaFormat =
      getMediaFormat(
          format,
          codecMimeType,
          codecMaxValues,
          codecOperatingRate,
          deviceNeedsNoPostProcessWorkaround,
          tunnelingAudioSessionId);
  if (surface == null) {
    Assertions.checkState(shouldUseDummySurface(codecInfo));
    if (dummySurface == null) {
      dummySurface = DummySurface.newInstanceV17(context, codecInfo.secure);
    }
    surface = dummySurface;
  }
  codec.configure(mediaFormat, surface, crypto, 0);
  if (Util.SDK_INT >= 23 && tunneling) {
    tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
  }
}
 
Example #7
Source File: MediaCodecAudioRenderer.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
@Override
protected void configureCodec(
    MediaCodecInfo codecInfo,
    MediaCodec codec,
    Format format,
    @Nullable MediaCrypto crypto,
    float codecOperatingRate) {
  codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
  codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
  codecNeedsEosBufferTimestampWorkaround = codecNeedsEosBufferTimestampWorkaround(codecInfo.name);
  passthroughEnabled = codecInfo.passthrough;
  String codecMimeType = passthroughEnabled ? MimeTypes.AUDIO_RAW : codecInfo.codecMimeType;
  MediaFormat mediaFormat =
      getMediaFormat(format, codecMimeType, codecMaxInputSize, codecOperatingRate);
  codec.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
  if (passthroughEnabled) {
    // Store the input MIME type if we're using the passthrough codec.
    passthroughMediaFormat = mediaFormat;
    passthroughMediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
  } else {
    passthroughMediaFormat = null;
  }
}
 
Example #8
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 #9
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 #10
Source File: MediaCodecAudioRenderer.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
@Override
protected void configureCodec(
    MediaCodecInfo codecInfo,
    MediaCodec codec,
    Format format,
    MediaCrypto crypto,
    float codecOperatingRate) {
  codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
  codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
  codecNeedsEosBufferTimestampWorkaround = codecNeedsEosBufferTimestampWorkaround(codecInfo.name);
  passthroughEnabled = codecInfo.passthrough;
  String codecMimeType = passthroughEnabled ? MimeTypes.AUDIO_RAW : codecInfo.codecMimeType;
  MediaFormat mediaFormat =
      getMediaFormat(format, codecMimeType, codecMaxInputSize, codecOperatingRate);
  codec.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
  if (passthroughEnabled) {
    // Store the input MIME type if we're using the passthrough codec.
    passthroughMediaFormat = mediaFormat;
    passthroughMediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
  } else {
    passthroughMediaFormat = null;
  }
}
 
Example #11
Source File: MediaCodecAudioRenderer.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
@Override
protected List<MediaCodecInfo> getDecoderInfos(
    MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder)
    throws DecoderQueryException {
  if (allowPassthrough(format.channelCount, format.sampleMimeType)) {
    MediaCodecInfo passthroughDecoderInfo = mediaCodecSelector.getPassthroughDecoderInfo();
    if (passthroughDecoderInfo != null) {
      return Collections.singletonList(passthroughDecoderInfo);
    }
  }
  List<MediaCodecInfo> decoderInfos =
      mediaCodecSelector.getDecoderInfos(
          format.sampleMimeType, requiresSecureDecoder, /* requiresTunnelingDecoder= */ false);
  if (MimeTypes.AUDIO_E_AC3_JOC.equals(format.sampleMimeType)) {
    // E-AC3 decoders can decode JOC streams, but in 2-D rather than 3-D.
    List<MediaCodecInfo> decoderInfosWithEac3 = new ArrayList<>(decoderInfos);
    decoderInfosWithEac3.addAll(
        mediaCodecSelector.getDecoderInfos(
            MimeTypes.AUDIO_E_AC3, requiresSecureDecoder, /* requiresTunnelingDecoder= */ false));
    decoderInfos = decoderInfosWithEac3;
  }
  return Collections.unmodifiableList(decoderInfos);
}
 
Example #12
Source File: MediaCodecAudioRenderer.java    From TelePlus-Android 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 (areAdaptationCompatible(format, streamFormat)) {
  //     maxInputSize = Math.max(maxInputSize, getCodecMaxInputSize(codecInfo, streamFormat));
  //   }
  // }
  return maxInputSize;
}
 
Example #13
Source File: MediaCodecAudioRenderer.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
@Override
protected void configureCodec(
    MediaCodecInfo codecInfo,
    MediaCodec codec,
    Format format,
    MediaCrypto crypto,
    float codecOperatingRate) {
  codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
  codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
  codecNeedsEosBufferTimestampWorkaround = codecNeedsEosBufferTimestampWorkaround(codecInfo.name);
  passthroughEnabled = codecInfo.passthrough;
  String codecMimeType = passthroughEnabled ? MimeTypes.AUDIO_RAW : codecInfo.codecMimeType;
  MediaFormat mediaFormat =
      getMediaFormat(format, codecMimeType, codecMaxInputSize, codecOperatingRate);
  codec.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
  if (passthroughEnabled) {
    // Store the input MIME type if we're using the passthrough codec.
    passthroughMediaFormat = mediaFormat;
    passthroughMediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
  } else {
    passthroughMediaFormat = null;
  }
}
 
Example #14
Source File: MediaCodecAudioRenderer.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
@Override
protected void configureCodec(
    MediaCodecInfo codecInfo,
    MediaCodec codec,
    Format format,
    MediaCrypto crypto,
    float codecOperatingRate) {
  codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
  codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
  passthroughEnabled = codecInfo.passthrough;
  String codecMimeType = codecInfo.mimeType == null ? MimeTypes.AUDIO_RAW : codecInfo.mimeType;
  MediaFormat mediaFormat =
      getMediaFormat(format, codecMimeType, codecMaxInputSize, codecOperatingRate);
  codec.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
  if (passthroughEnabled) {
    // Store the input MIME type if we're using the passthrough codec.
    passthroughMediaFormat = mediaFormat;
    passthroughMediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
  } else {
    passthroughMediaFormat = null;
  }
}
 
Example #15
Source File: MediaCodecAudioRenderer.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Returns a maximum input buffer size for a given format.
 *
 * @param codecInfo A {@link MediaCodecInfo} describing the decoder.
 * @param format The format.
 * @return A maximum input buffer size in bytes, or {@link Format#NO_VALUE} if a maximum could not
 *     be determined.
 */
private int getCodecMaxInputSize(MediaCodecInfo codecInfo, Format format) {
  if (Util.SDK_INT < 24 && "OMX.google.raw.decoder".equals(codecInfo.name)) {
    // OMX.google.raw.decoder didn't resize its output buffers correctly prior to N, so there's no
    // point requesting a non-default input size. Doing so may cause a native crash, where-as not
    // doing so will cause a more controlled failure when attempting to fill an input buffer. See:
    // https://github.com/google/ExoPlayer/issues/4057.
    boolean needsRawDecoderWorkaround = true;
    if (Util.SDK_INT == 23) {
      PackageManager packageManager = context.getPackageManager();
      if (packageManager != null
          && packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
        // The workaround is not required for AndroidTV devices running M.
        needsRawDecoderWorkaround = false;
      }
    }
    if (needsRawDecoderWorkaround) {
      return Format.NO_VALUE;
    }
  }
  return format.maxInputSize;
}
 
Example #16
Source File: MediaCodecVideoRenderer.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Returns a maximum input buffer size for a given codec and format.
 *
 * @param codecInfo Information about the {@link MediaCodec} being configured.
 * @param format The format.
 * @return A maximum input buffer size in bytes, or {@link Format#NO_VALUE} if a maximum could not
 *     be determined.
 */
private static int getMaxInputSize(MediaCodecInfo codecInfo, Format format) {
  if (format.maxInputSize != Format.NO_VALUE) {
    // The format defines an explicit maximum input size. Add the total size of initialization
    // data buffers, as they may need to be queued in the same input buffer as the largest sample.
    int totalInitializationDataSize = 0;
    int initializationDataCount = format.initializationData.size();
    for (int i = 0; i < initializationDataCount; i++) {
      totalInitializationDataSize += format.initializationData.get(i).length;
    }
    return format.maxInputSize + totalInitializationDataSize;
  } else {
    // Calculated maximum input sizes are overestimates, so it's not necessary to add the size of
    // initialization data.
    return getMaxInputSize(codecInfo, format.sampleMimeType, format.width, format.height);
  }
}
 
Example #17
Source File: MediaCodecVideoRenderer.java    From TelePlus-Android 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 (areAdaptationCompatible(codecInfo.adaptive, oldFormat, newFormat)
      && 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 #18
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 #19
Source File: MediaCodecAudioRenderer.java    From K-Sonic with MIT License 6 votes vote down vote up
@Override
protected int supportsFormat(MediaCodecSelector mediaCodecSelector, Format format)
    throws DecoderQueryException {
  String mimeType = format.sampleMimeType;
  if (!MimeTypes.isAudio(mimeType)) {
    return FORMAT_UNSUPPORTED_TYPE;
  }
  int tunnelingSupport = Util.SDK_INT >= 21 ? TUNNELING_SUPPORTED : TUNNELING_NOT_SUPPORTED;
  if (allowPassthrough(mimeType) && mediaCodecSelector.getPassthroughDecoderInfo() != null) {
    return ADAPTIVE_NOT_SEAMLESS | tunnelingSupport | FORMAT_HANDLED;
  }
  MediaCodecInfo decoderInfo = mediaCodecSelector.getDecoderInfo(mimeType, false);
  if (decoderInfo == null) {
    return FORMAT_UNSUPPORTED_SUBTYPE;
  }
  // Note: We assume support for unknown sampleRate and channelCount.
  boolean decoderCapable = Util.SDK_INT < 21
      || ((format.sampleRate == Format.NO_VALUE
      || decoderInfo.isAudioSampleRateSupportedV21(format.sampleRate))
      && (format.channelCount == Format.NO_VALUE
      ||  decoderInfo.isAudioChannelCountSupportedV21(format.channelCount)));
  int formatSupport = decoderCapable ? FORMAT_HANDLED : FORMAT_EXCEEDS_CAPABILITIES;
  return ADAPTIVE_NOT_SEAMLESS | tunnelingSupport | formatSupport;
}
 
Example #20
Source File: MediaCodecVideoRenderer.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Returns a maximum input buffer size for a given codec and format.
 *
 * @param codecInfo Information about the {@link MediaCodec} being configured.
 * @param format The format.
 * @return A maximum input buffer size in bytes, or {@link Format#NO_VALUE} if a maximum could not
 *     be determined.
 */
private static int getMaxInputSize(MediaCodecInfo codecInfo, Format format) {
  if (format.maxInputSize != Format.NO_VALUE) {
    // The format defines an explicit maximum input size. Add the total size of initialization
    // data buffers, as they may need to be queued in the same input buffer as the largest sample.
    int totalInitializationDataSize = 0;
    int initializationDataCount = format.initializationData.size();
    for (int i = 0; i < initializationDataCount; i++) {
      totalInitializationDataSize += format.initializationData.get(i).length;
    }
    return format.maxInputSize + totalInitializationDataSize;
  } else {
    // Calculated maximum input sizes are overestimates, so it's not necessary to add the size of
    // initialization data.
    return getCodecMaxInputSize(codecInfo, format.sampleMimeType, format.width, format.height);
  }
}
 
Example #21
Source File: MediaCodecAudioRenderer.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Returns a maximum input buffer size for a given format.
 *
 * @param codecInfo A {@link MediaCodecInfo} describing the decoder.
 * @param format The format.
 * @return A maximum input buffer size in bytes, or {@link Format#NO_VALUE} if a maximum could not
 *     be determined.
 */
private int getCodecMaxInputSize(MediaCodecInfo codecInfo, Format format) {
  if (Util.SDK_INT < 24 && "OMX.google.raw.decoder".equals(codecInfo.name)) {
    // OMX.google.raw.decoder didn't resize its output buffers correctly prior to N, so there's no
    // point requesting a non-default input size. Doing so may cause a native crash, where-as not
    // doing so will cause a more controlled failure when attempting to fill an input buffer. See:
    // https://github.com/google/ExoPlayer/issues/4057.
    boolean needsRawDecoderWorkaround = true;
    if (Util.SDK_INT == 23) {
      PackageManager packageManager = context.getPackageManager();
      if (packageManager != null
          && packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
        // The workaround is not required for AndroidTV devices running M.
        needsRawDecoderWorkaround = false;
      }
    }
    if (needsRawDecoderWorkaround) {
      return Format.NO_VALUE;
    }
  }
  return format.maxInputSize;
}
 
Example #22
Source File: MediaCodecVideoRenderer.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
/**
 * Returns a maximum input buffer size for a given {@link MediaCodec} and {@link Format}.
 *
 * @param codecInfo Information about the {@link MediaCodec} being configured.
 * @param format The format.
 * @return A maximum input buffer size in bytes, or {@link Format#NO_VALUE} if a maximum could not
 *     be determined.
 */
private static int getMaxInputSize(MediaCodecInfo codecInfo, Format format) {
  if (format.maxInputSize != Format.NO_VALUE) {
    // The format defines an explicit maximum input size. Add the total size of initialization
    // data buffers, as they may need to be queued in the same input buffer as the largest sample.
    int totalInitializationDataSize = 0;
    int initializationDataCount = format.initializationData.size();
    for (int i = 0; i < initializationDataCount; i++) {
      totalInitializationDataSize += format.initializationData.get(i).length;
    }
    return format.maxInputSize + totalInitializationDataSize;
  } else {
    // Calculated maximum input sizes are overestimates, so it's not necessary to add the size of
    // initialization data.
    return getCodecMaxInputSize(codecInfo, format.sampleMimeType, format.width, format.height);
  }
}
 
Example #23
Source File: MediaCodecVideoRenderer.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
@Override
protected void configureCodec(
    MediaCodecInfo codecInfo,
    MediaCodec codec,
    Format format,
    MediaCrypto crypto,
    float codecOperatingRate)
    throws DecoderQueryException {
  codecMaxValues = getCodecMaxValues(codecInfo, format, getStreamFormats());
  MediaFormat mediaFormat =
      getMediaFormat(
          format,
          codecMaxValues,
          codecOperatingRate,
          deviceNeedsAutoFrcWorkaround,
          tunnelingAudioSessionId);
  if (surface == null) {
    Assertions.checkState(shouldUseDummySurface(codecInfo));
    if (dummySurface == null) {
      dummySurface = DummySurface.newInstanceV17(context, codecInfo.secure);
    }
    surface = dummySurface;
  }
  codec.configure(mediaFormat, surface, crypto, 0);
  if (Util.SDK_INT >= 23 && tunneling) {
    tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
  }
}
 
Example #24
Source File: MediaCodecAudioRenderer.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
@Override
protected List<MediaCodecInfo> getDecoderInfos(
    MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder)
    throws DecoderQueryException {
  @Nullable String mimeType = format.sampleMimeType;
  if (mimeType == null) {
    return Collections.emptyList();
  }
  if (allowPassthrough(format.channelCount, mimeType)) {
    @Nullable
    MediaCodecInfo passthroughDecoderInfo = mediaCodecSelector.getPassthroughDecoderInfo();
    if (passthroughDecoderInfo != null) {
      return Collections.singletonList(passthroughDecoderInfo);
    }
  }
  List<MediaCodecInfo> decoderInfos =
      mediaCodecSelector.getDecoderInfos(
          mimeType, requiresSecureDecoder, /* requiresTunnelingDecoder= */ false);
  decoderInfos = MediaCodecUtil.getDecoderInfosSortedByFormatSupport(decoderInfos, format);
  if (MimeTypes.AUDIO_E_AC3_JOC.equals(mimeType)) {
    // E-AC3 decoders can decode JOC streams, but in 2-D rather than 3-D.
    List<MediaCodecInfo> decoderInfosWithEac3 = new ArrayList<>(decoderInfos);
    decoderInfosWithEac3.addAll(
        mediaCodecSelector.getDecoderInfos(
            MimeTypes.AUDIO_E_AC3, requiresSecureDecoder, /* requiresTunnelingDecoder= */ false));
    decoderInfos = decoderInfosWithEac3;
  }
  return Collections.unmodifiableList(decoderInfos);
}
 
Example #25
Source File: MediaCodecVideoRenderer.java    From TelePlus-Android with GNU General Public License v2.0 5 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}.
 * @throws DecoderQueryException If an error occurs querying {@code codecInfo}.
 */
protected CodecMaxValues getCodecMaxValues(
    MediaCodecInfo codecInfo, Format format, Format[] streamFormats)
    throws DecoderQueryException {
  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.
    return new CodecMaxValues(maxWidth, maxHeight, maxInputSize);
  }
  boolean haveUnknownDimensions = false;
  for (Format streamFormat : streamFormats) {
    if (areAdaptationCompatible(codecInfo.adaptive, format, streamFormat)) {
      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,
              getMaxInputSize(codecInfo, format.sampleMimeType, maxWidth, maxHeight));
      Log.w(TAG, "Codec max resolution adjusted to: " + maxWidth + "x" + maxHeight);
    }
  }
  return new CodecMaxValues(maxWidth, maxHeight, maxInputSize);
}
 
Example #26
Source File: MediaCodecVideoRenderer.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns a maximum video size to use when configuring a codec for {@code format} in a way
 * that will allow possible adaptation to other compatible formats that are expected to have the
 * same aspect ratio, but whose sizes are unknown.
 *
 * @param codecInfo Information about the {@link MediaCodec} being configured.
 * @param format The format for which the codec is being configured.
 * @return The maximum video size to use, or null if the size of {@code format} should be used.
 * @throws DecoderQueryException If an error occurs querying {@code codecInfo}.
 */
private static Point getCodecMaxSize(MediaCodecInfo codecInfo, Format format)
    throws DecoderQueryException {
  boolean isVerticalVideo = format.height > format.width;
  int formatLongEdgePx = isVerticalVideo ? format.height : format.width;
  int formatShortEdgePx = isVerticalVideo ? format.width : format.height;
  float aspectRatio = (float) formatShortEdgePx / formatLongEdgePx;
  for (int longEdgePx : STANDARD_LONG_EDGE_VIDEO_PX) {
    int shortEdgePx = (int) (longEdgePx * aspectRatio);
    if (longEdgePx <= formatLongEdgePx || shortEdgePx <= formatShortEdgePx) {
      // Don't return a size not larger than the format for which the codec is being configured.
      return null;
    } else if (Util.SDK_INT >= 21) {
      Point alignedSize = codecInfo.alignVideoSizeV21(isVerticalVideo ? shortEdgePx : longEdgePx,
          isVerticalVideo ? longEdgePx : shortEdgePx);
      float frameRate = format.frameRate;
      if (codecInfo.isVideoSizeAndRateSupportedV21(alignedSize.x, alignedSize.y, frameRate)) {
        return alignedSize;
      }
    } else {
      // Conservatively assume the codec requires 16px width and height alignment.
      longEdgePx = Util.ceilDivide(longEdgePx, 16) * 16;
      shortEdgePx = Util.ceilDivide(shortEdgePx, 16) * 16;
      if (longEdgePx * shortEdgePx <= MediaCodecUtil.maxH264DecodableFrameSize()) {
        return new Point(isVerticalVideo ? shortEdgePx : longEdgePx,
            isVerticalVideo ? longEdgePx : shortEdgePx);
      }
    }
  }
  return null;
}
 
Example #27
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 #28
Source File: MediaCodecAudioRenderer.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns a maximum input buffer size for a given format.
 *
 * @param codecInfo A {@link MediaCodecInfo} describing the decoder.
 * @param format The format.
 * @return A maximum input buffer size in bytes, or {@link Format#NO_VALUE} if a maximum could not
 *     be determined.
 */
private int getCodecMaxInputSize(MediaCodecInfo codecInfo, Format format) {
  if ("OMX.google.raw.decoder".equals(codecInfo.name)) {
    // OMX.google.raw.decoder didn't resize its output buffers correctly prior to N, except on
    // Android TV running M, so there's no point requesting a non-default input size. Doing so may
    // cause a native crash, whereas not doing so will cause a more controlled failure when
    // attempting to fill an input buffer. See: https://github.com/google/ExoPlayer/issues/4057.
    if (Util.SDK_INT < 24 && !(Util.SDK_INT == 23 && Util.isTv(context))) {
      return Format.NO_VALUE;
    }
  }
  return format.maxInputSize;
}
 
Example #29
Source File: MediaCodecVideoRenderer.java    From K-Sonic with MIT License 5 votes vote down vote up
@Override
protected int supportsFormat(MediaCodecSelector mediaCodecSelector, 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;
    }
  }
  MediaCodecInfo decoderInfo = mediaCodecSelector.getDecoderInfo(mimeType,
      requiresSecureDecryption);
  if (decoderInfo == null) {
    return FORMAT_UNSUPPORTED_SUBTYPE;
  }

  boolean decoderCapable = decoderInfo.isCodecSupported(format.codecs);
  if (decoderCapable && format.width > 0 && format.height > 0) {
    if (Util.SDK_INT >= 21) {
      decoderCapable = decoderInfo.isVideoSizeAndRateSupportedV21(format.width, format.height,
          format.frameRate);
    } else {
      decoderCapable = format.width * format.height <= MediaCodecUtil.maxH264DecodableFrameSize();
      if (!decoderCapable) {
        Log.d(TAG, "FalseCheck [legacyFrameSize, " + format.width + "x" + format.height + "] ["
            + Util.DEVICE_DEBUG_INFO + "]");
      }
    }
  }

  int adaptiveSupport = decoderInfo.adaptive ? ADAPTIVE_SEAMLESS : ADAPTIVE_NOT_SEAMLESS;
  int tunnelingSupport = decoderInfo.tunneling ? TUNNELING_SUPPORTED : TUNNELING_NOT_SUPPORTED;
  int formatSupport = decoderCapable ? FORMAT_HANDLED : FORMAT_EXCEEDS_CAPABILITIES;
  return adaptiveSupport | tunnelingSupport | formatSupport;
}
 
Example #30
Source File: MediaCodecVideoRenderer.java    From K-Sonic with MIT License 5 votes vote down vote up
@Override
protected void configureCodec(MediaCodecInfo codecInfo, MediaCodec codec, Format format,
    MediaCrypto crypto) throws DecoderQueryException {
  codecMaxValues = getCodecMaxValues(codecInfo, format, streamFormats);
  MediaFormat mediaFormat = getMediaFormat(format, codecMaxValues, deviceNeedsAutoFrcWorkaround,
      tunnelingAudioSessionId);
  codec.configure(mediaFormat, surface, crypto, 0);
  if (Util.SDK_INT >= 23 && tunneling) {
    tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
  }
}