Search in sources :

Example 1 with DecoderQueryException

use of com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException in project ExoPlayer by google.

the class MediaCodecAudioRenderer method supportsFormat.

@Override
@Capabilities
protected int supportsFormat(MediaCodecSelector mediaCodecSelector, Format format) throws DecoderQueryException {
    if (!MimeTypes.isAudio(format.sampleMimeType)) {
        return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE);
    }
    @TunnelingSupport int tunnelingSupport = Util.SDK_INT >= 21 ? TUNNELING_SUPPORTED : TUNNELING_NOT_SUPPORTED;
    boolean formatHasDrm = format.cryptoType != C.CRYPTO_TYPE_NONE;
    boolean supportsFormatDrm = supportsFormatDrm(format);
    // Else we don't don't need a decoder at all.
    if (supportsFormatDrm && audioSink.supportsFormat(format) && (!formatHasDrm || MediaCodecUtil.getDecryptOnlyDecoderInfo() != null)) {
        return RendererCapabilities.create(C.FORMAT_HANDLED, ADAPTIVE_NOT_SEAMLESS, tunnelingSupport);
    }
    // the input format directly.
    if (MimeTypes.AUDIO_RAW.equals(format.sampleMimeType) && !audioSink.supportsFormat(format)) {
        return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE);
    }
    // For all other input formats, we expect the decoder to output 16-bit PCM.
    if (!audioSink.supportsFormat(Util.getPcmFormat(C.ENCODING_PCM_16BIT, format.channelCount, format.sampleRate))) {
        return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE);
    }
    List<MediaCodecInfo> decoderInfos = getDecoderInfos(mediaCodecSelector, format, /* requiresSecureDecoder= */
    false, audioSink);
    if (decoderInfos.isEmpty()) {
        return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE);
    }
    if (!supportsFormatDrm) {
        return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_DRM);
    }
    // Check whether the first decoder supports the format. This is the preferred decoder for the
    // format's MIME type, according to the MediaCodecSelector.
    MediaCodecInfo decoderInfo = decoderInfos.get(0);
    boolean isFormatSupported = decoderInfo.isFormatSupported(format);
    boolean isPreferredDecoder = true;
    if (!isFormatSupported) {
        // Check whether any of the other decoders support the format.
        for (int i = 1; i < decoderInfos.size(); i++) {
            MediaCodecInfo otherDecoderInfo = decoderInfos.get(i);
            if (otherDecoderInfo.isFormatSupported(format)) {
                decoderInfo = otherDecoderInfo;
                isFormatSupported = true;
                isPreferredDecoder = false;
                break;
            }
        }
    }
    @C.FormatSupport int formatSupport = isFormatSupported ? C.FORMAT_HANDLED : C.FORMAT_EXCEEDS_CAPABILITIES;
    @AdaptiveSupport int adaptiveSupport = isFormatSupported && decoderInfo.isSeamlessAdaptationSupported(format) ? ADAPTIVE_SEAMLESS : ADAPTIVE_NOT_SEAMLESS;
    @HardwareAccelerationSupport int hardwareAccelerationSupport = decoderInfo.hardwareAccelerated ? HARDWARE_ACCELERATION_SUPPORTED : HARDWARE_ACCELERATION_NOT_SUPPORTED;
    @DecoderSupport int decoderSupport = isPreferredDecoder ? DECODER_SUPPORT_PRIMARY : DECODER_SUPPORT_FALLBACK;
    return RendererCapabilities.create(formatSupport, adaptiveSupport, tunnelingSupport, hardwareAccelerationSupport, decoderSupport);
}
Also used : MediaCodecInfo(com.google.android.exoplayer2.mediacodec.MediaCodecInfo) SuppressLint(android.annotation.SuppressLint) RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities)

Example 2 with DecoderQueryException

use of com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException in project ExoPlayer by google.

the class MediaCodecVideoRenderer method supportsFormat.

@Override
@Capabilities
protected int supportsFormat(MediaCodecSelector mediaCodecSelector, Format format) throws DecoderQueryException {
    String mimeType = format.sampleMimeType;
    if (!MimeTypes.isVideo(mimeType)) {
        return RendererCapabilities.create(C.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(C.FORMAT_UNSUPPORTED_SUBTYPE);
    }
    if (!supportsFormatDrm(format)) {
        return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_DRM);
    }
    // Check whether the first decoder supports the format. This is the preferred decoder for the
    // format's MIME type, according to the MediaCodecSelector.
    MediaCodecInfo decoderInfo = decoderInfos.get(0);
    boolean isFormatSupported = decoderInfo.isFormatSupported(format);
    boolean isPreferredDecoder = true;
    if (!isFormatSupported) {
        // Check whether any of the other decoders support the format.
        for (int i = 1; i < decoderInfos.size(); i++) {
            MediaCodecInfo otherDecoderInfo = decoderInfos.get(i);
            if (otherDecoderInfo.isFormatSupported(format)) {
                decoderInfo = otherDecoderInfo;
                isFormatSupported = true;
                isPreferredDecoder = false;
                break;
            }
        }
    }
    @C.FormatSupport int formatSupport = isFormatSupported ? C.FORMAT_HANDLED : C.FORMAT_EXCEEDS_CAPABILITIES;
    @AdaptiveSupport int adaptiveSupport = decoderInfo.isSeamlessAdaptationSupported(format) ? ADAPTIVE_SEAMLESS : ADAPTIVE_NOT_SEAMLESS;
    @HardwareAccelerationSupport int hardwareAccelerationSupport = decoderInfo.hardwareAccelerated ? HARDWARE_ACCELERATION_SUPPORTED : HARDWARE_ACCELERATION_NOT_SUPPORTED;
    @DecoderSupport int decoderSupport = isPreferredDecoder ? DECODER_SUPPORT_PRIMARY : DECODER_SUPPORT_FALLBACK;
    @TunnelingSupport int tunnelingSupport = TUNNELING_NOT_SUPPORTED;
    if (isFormatSupported) {
        List<MediaCodecInfo> tunnelingDecoderInfos = getDecoderInfos(mediaCodecSelector, format, requiresSecureDecryption, /* requiresTunnelingDecoder= */
        true);
        if (!tunnelingDecoderInfos.isEmpty()) {
            MediaCodecInfo tunnelingDecoderInfo = MediaCodecUtil.getDecoderInfosSortedByFormatSupport(tunnelingDecoderInfos, format).get(0);
            if (tunnelingDecoderInfo.isFormatSupported(format) && tunnelingDecoderInfo.isSeamlessAdaptationSupported(format)) {
                tunnelingSupport = TUNNELING_SUPPORTED;
            }
        }
    }
    return RendererCapabilities.create(formatSupport, adaptiveSupport, tunnelingSupport, hardwareAccelerationSupport, decoderSupport);
}
Also used : DrmInitData(com.google.android.exoplayer2.drm.DrmInitData) MediaCodecInfo(com.google.android.exoplayer2.mediacodec.MediaCodecInfo) Nullable(androidx.annotation.Nullable) SuppressLint(android.annotation.SuppressLint) Point(android.graphics.Point) CodecCapabilities(android.media.MediaCodecInfo.CodecCapabilities) RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities)

Example 3 with DecoderQueryException

use of com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException in project ExoPlayer by google.

the class PlayerActivity method onPlayerError.

@Override
public void onPlayerError(ExoPlaybackException e) {
    String errorString = null;
    if (e.type == ExoPlaybackException.TYPE_RENDERER) {
        Exception cause = e.getRendererException();
        if (cause instanceof DecoderInitializationException) {
            // Special case for decoder initialization failures.
            DecoderInitializationException decoderInitializationException = (DecoderInitializationException) cause;
            if (decoderInitializationException.decoderName == null) {
                if (decoderInitializationException.getCause() instanceof DecoderQueryException) {
                    errorString = getString(R.string.error_querying_decoders);
                } else if (decoderInitializationException.secureDecoderRequired) {
                    errorString = getString(R.string.error_no_secure_decoder, decoderInitializationException.mimeType);
                } else {
                    errorString = getString(R.string.error_no_decoder, decoderInitializationException.mimeType);
                }
            } else {
                errorString = getString(R.string.error_instantiating_decoder, decoderInitializationException.decoderName);
            }
        }
    }
    if (errorString != null) {
        showToast(errorString);
    }
    needRetrySource = true;
    if (isBehindLiveWindow(e)) {
        clearResumePosition();
        initializePlayer();
    } else {
        updateResumePosition();
        updateButtonVisibilities();
        showControls();
    }
}
Also used : DecoderQueryException(com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException) DecoderInitializationException(com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException) ExoPlaybackException(com.google.android.exoplayer2.ExoPlaybackException) UnsupportedDrmException(com.google.android.exoplayer2.drm.UnsupportedDrmException) DecoderInitializationException(com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException) DecoderQueryException(com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException) BehindLiveWindowException(com.google.android.exoplayer2.source.BehindLiveWindowException)

Example 4 with DecoderQueryException

use of com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException in project ExoPlayer by google.

the class DashTest method shouldSkipAdaptiveTest.

// Internal.
private static boolean shouldSkipAdaptiveTest(String mimeType) throws DecoderQueryException {
    MediaCodecInfo decoderInfo = MediaCodecUtil.getDecoderInfo(mimeType, false);
    assertNotNull(decoderInfo);
    if (decoderInfo.adaptive) {
        return false;
    }
    assertTrue(Util.SDK_INT < 21);
    return true;
}
Also used : MediaCodecInfo(com.google.android.exoplayer2.mediacodec.MediaCodecInfo)

Example 5 with DecoderQueryException

use of com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException in project ExoPlayer by google.

the class MediaCodecRenderer method maybeInitCodec.

@SuppressWarnings("deprecation")
protected final void maybeInitCodec() throws ExoPlaybackException {
    if (!shouldInitCodec()) {
        return;
    }
    drmSession = pendingDrmSession;
    String mimeType = format.sampleMimeType;
    MediaCrypto mediaCrypto = null;
    boolean drmSessionRequiresSecureDecoder = false;
    if (drmSession != null) {
        @DrmSession.State int drmSessionState = drmSession.getState();
        if (drmSessionState == DrmSession.STATE_ERROR) {
            throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex());
        } else if (drmSessionState == DrmSession.STATE_OPENED || drmSessionState == DrmSession.STATE_OPENED_WITH_KEYS) {
            mediaCrypto = drmSession.getMediaCrypto().getWrappedMediaCrypto();
            drmSessionRequiresSecureDecoder = drmSession.requiresSecureDecoderComponent(mimeType);
        } else {
            // The drm session isn't open yet.
            return;
        }
    }
    MediaCodecInfo decoderInfo = null;
    try {
        decoderInfo = getDecoderInfo(mediaCodecSelector, format, drmSessionRequiresSecureDecoder);
        if (decoderInfo == null && drmSessionRequiresSecureDecoder) {
            // The drm session indicates that a secure decoder is required, but the device does not have
            // one. Assuming that supportsFormat indicated support for the media being played, we know
            // that it does not require a secure output path. Most CDM implementations allow playback to
            // proceed with a non-secure decoder in this case, so we try our luck.
            decoderInfo = getDecoderInfo(mediaCodecSelector, format, false);
            if (decoderInfo != null) {
                Log.w(TAG, "Drm session requires secure decoder for " + mimeType + ", but " + "no secure decoder available. Trying to proceed with " + decoderInfo.name + ".");
            }
        }
    } catch (DecoderQueryException e) {
        throwDecoderInitError(new DecoderInitializationException(format, e, drmSessionRequiresSecureDecoder, DecoderInitializationException.DECODER_QUERY_ERROR));
    }
    if (decoderInfo == null) {
        throwDecoderInitError(new DecoderInitializationException(format, null, drmSessionRequiresSecureDecoder, DecoderInitializationException.NO_SUITABLE_DECODER_ERROR));
    }
    String codecName = decoderInfo.name;
    codecIsAdaptive = decoderInfo.adaptive;
    codecNeedsDiscardToSpsWorkaround = codecNeedsDiscardToSpsWorkaround(codecName, format);
    codecNeedsFlushWorkaround = codecNeedsFlushWorkaround(codecName);
    codecNeedsAdaptationWorkaround = codecNeedsAdaptationWorkaround(codecName);
    codecNeedsEosPropagationWorkaround = codecNeedsEosPropagationWorkaround(codecName);
    codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName);
    codecNeedsEosOutputExceptionWorkaround = codecNeedsEosOutputExceptionWorkaround(codecName);
    codecNeedsMonoChannelCountWorkaround = codecNeedsMonoChannelCountWorkaround(codecName, format);
    try {
        long codecInitializingTimestamp = SystemClock.elapsedRealtime();
        TraceUtil.beginSection("createCodec:" + codecName);
        codec = MediaCodec.createByCodecName(codecName);
        TraceUtil.endSection();
        TraceUtil.beginSection("configureCodec");
        configureCodec(decoderInfo, codec, format, mediaCrypto);
        TraceUtil.endSection();
        TraceUtil.beginSection("startCodec");
        codec.start();
        TraceUtil.endSection();
        long codecInitializedTimestamp = SystemClock.elapsedRealtime();
        onCodecInitialized(codecName, codecInitializedTimestamp, codecInitializedTimestamp - codecInitializingTimestamp);
        inputBuffers = codec.getInputBuffers();
        outputBuffers = codec.getOutputBuffers();
    } catch (Exception e) {
        throwDecoderInitError(new DecoderInitializationException(format, e, drmSessionRequiresSecureDecoder, codecName));
    }
    codecHotswapDeadlineMs = getState() == STATE_STARTED ? (SystemClock.elapsedRealtime() + MAX_CODEC_HOTSWAP_TIME_MS) : C.TIME_UNSET;
    inputIndex = C.INDEX_UNSET;
    outputIndex = C.INDEX_UNSET;
    waitingForFirstSyncFrame = true;
    decoderCounters.decoderInitCount++;
}
Also used : DecoderQueryException(com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException) ExoPlaybackException(com.google.android.exoplayer2.ExoPlaybackException) CodecException(android.media.MediaCodec.CodecException) CryptoException(android.media.MediaCodec.CryptoException) DecoderQueryException(com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException) FrameworkMediaCrypto(com.google.android.exoplayer2.drm.FrameworkMediaCrypto) MediaCrypto(android.media.MediaCrypto)

Aggregations

MediaCodecInfo (com.google.android.exoplayer2.mediacodec.MediaCodecInfo)5 SuppressLint (android.annotation.SuppressLint)3 DecoderQueryException (com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException)3 Point (android.graphics.Point)2 CodecCapabilities (android.media.MediaCodecInfo.CodecCapabilities)2 Nullable (androidx.annotation.Nullable)2 ExoPlaybackException (com.google.android.exoplayer2.ExoPlaybackException)2 RendererCapabilities (com.google.android.exoplayer2.RendererCapabilities)2 CodecException (android.media.MediaCodec.CodecException)1 CryptoException (android.media.MediaCodec.CryptoException)1 MediaCrypto (android.media.MediaCrypto)1 DrmInitData (com.google.android.exoplayer2.drm.DrmInitData)1 FrameworkMediaCrypto (com.google.android.exoplayer2.drm.FrameworkMediaCrypto)1 UnsupportedDrmException (com.google.android.exoplayer2.drm.UnsupportedDrmException)1 DecoderInitializationException (com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException)1 BehindLiveWindowException (com.google.android.exoplayer2.source.BehindLiveWindowException)1