android.media.MediaCrypto#com.google.android.exoplayer2.mediacodec.MediaCodecInfo源码实例Demo

下面列出了android.media.MediaCrypto#com.google.android.exoplayer2.mediacodec.MediaCodecInfo 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。


@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;
  }
}
 

@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);
  }
}
 

/**
 * 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;
}
 

/**
 * 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);
  }
}
 

/**
 * 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;
}
 

/**
 * 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;
}
 

/**
 * 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);
  }
}
 

/**
 * 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);
  }
}
 

@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;
  }
}
 

/**
 * 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;
}
 

/**
 * 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;
}
 

@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;
}
 
源代码13 项目: Telegram   文件: MediaCodecAudioRenderer.java

@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;
  }
}
 
源代码14 项目: K-Sonic   文件: MediaCodecAudioRenderer.java

@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;
}
 

@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);
}
 

@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;
  }
}
 

@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;
  }
}
 

/**
 * 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;
}
 

@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;
}
 

/**
 * 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);
  }
}
 
源代码21 项目: Telegram   文件: MediaCodecAudioRenderer.java

@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);
}
 
源代码22 项目: Telegram   文件: MediaCodecAudioRenderer.java

@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;
  }
}
 
源代码23 项目: Telegram   文件: MediaCodecVideoRenderer.java

/**
 * 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.
 */
private static Point getCodecMaxSize(MediaCodecInfo codecInfo, Format format) {
  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 {
      try {
        // 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);
        }
      } catch (DecoderQueryException e) {
        // We tried our best. Give up!
        return null;
      }
    }
  }
  return null;
}
 
源代码24 项目: MediaSDK   文件: MediaCodecAudioRenderer.java

@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);
}
 
源代码25 项目: MediaSDK   文件: MediaCodecAudioRenderer.java

/**
 * Returns a maximum input buffer size for a given {@link Format}.
 *
 * @param codecInfo A {@link MediaCodecInfo} describing the decoder.
 * @param format The {@link 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;
}
 
源代码26 项目: MediaSDK   文件: MediaCodecVideoRenderer.java

private static List<MediaCodecInfo> getDecoderInfos(
    MediaCodecSelector mediaCodecSelector,
    Format format,
    boolean requiresSecureDecoder,
    boolean requiresTunnelingDecoder)
    throws DecoderQueryException {
  @Nullable String mimeType = format.sampleMimeType;
  if (mimeType == null) {
    return Collections.emptyList();
  }
  List<MediaCodecInfo> decoderInfos =
      mediaCodecSelector.getDecoderInfos(
          mimeType, requiresSecureDecoder, requiresTunnelingDecoder);
  decoderInfos = MediaCodecUtil.getDecoderInfosSortedByFormatSupport(decoderInfos, format);
  if (MimeTypes.VIDEO_DOLBY_VISION.equals(mimeType)) {
    // Fall back to H.264/AVC or H.265/HEVC for the relevant DV profiles.
    @Nullable
    Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
    if (codecProfileAndLevel != null) {
      int profile = codecProfileAndLevel.first;
      if (profile == CodecProfileLevel.DolbyVisionProfileDvheDtr
          || profile == CodecProfileLevel.DolbyVisionProfileDvheSt) {
        decoderInfos.addAll(
            mediaCodecSelector.getDecoderInfos(
                MimeTypes.VIDEO_H265, requiresSecureDecoder, requiresTunnelingDecoder));
      } else if (profile == CodecProfileLevel.DolbyVisionProfileDvavSe) {
        decoderInfos.addAll(
            mediaCodecSelector.getDecoderInfos(
                MimeTypes.VIDEO_H264, requiresSecureDecoder, requiresTunnelingDecoder));
      }
    }
  }
  return Collections.unmodifiableList(decoderInfos);
}
 
源代码27 项目: MediaSDK   文件: MediaCodecVideoRenderer.java

@Override
protected void configureCodec(
    MediaCodecInfo codecInfo,
    MediaCodec codec,
    Format format,
    @Nullable 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);
  }
}
 
源代码28 项目: MediaSDK   文件: MediaCodecVideoRenderer.java

@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;
}
 
源代码29 项目: MediaSDK   文件: MediaCodecVideoRenderer.java

/**
 * 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 {@link 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.
 */
private static Point getCodecMaxSize(MediaCodecInfo codecInfo, Format format) {
  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 {
      try {
        // 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);
        }
      } catch (DecoderQueryException e) {
        // We tried our best. Give up!
        return null;
      }
    }
  }
  return null;
}
 

@Override
protected List<MediaCodecInfo> getDecoderInfos(
    MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder)
    throws DecoderQueryException {
  if (allowPassthrough(format.sampleMimeType)) {
    MediaCodecInfo passthroughDecoderInfo = mediaCodecSelector.getPassthroughDecoderInfo();
    if (passthroughDecoderInfo != null) {
      return Collections.singletonList(passthroughDecoderInfo);
    }
  }
  return super.getDecoderInfos(mediaCodecSelector, format, requiresSecureDecoder);
}