Search in sources :

Example 1 with Capabilities

use of com.google.android.exoplayer2.RendererCapabilities.Capabilities in project ExoPlayer by google.

the class DownloadHelper method getRendererCapabilities.

/**
 * Extracts renderer capabilities for the renderers created by the provided renderers factory.
 *
 * @param renderersFactory A {@link RenderersFactory}.
 * @return The {@link RendererCapabilities} for each renderer created by the {@code
 *     renderersFactory}.
 */
public static RendererCapabilities[] getRendererCapabilities(RenderersFactory renderersFactory) {
    Renderer[] renderers = renderersFactory.createRenderers(Util.createHandlerForCurrentOrMainLooper(), new VideoRendererEventListener() {
    }, new AudioRendererEventListener() {
    }, (cues) -> {
    }, (metadata) -> {
    });
    RendererCapabilities[] capabilities = new RendererCapabilities[renderers.length];
    for (int i = 0; i < renderers.length; i++) {
        capabilities[i] = renderers[i].getCapabilities();
    }
    return capabilities;
}
Also used : Renderer(com.google.android.exoplayer2.Renderer) VideoRendererEventListener(com.google.android.exoplayer2.video.VideoRendererEventListener) AudioRendererEventListener(com.google.android.exoplayer2.audio.AudioRendererEventListener) RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities)

Example 2 with Capabilities

use of com.google.android.exoplayer2.RendererCapabilities.Capabilities 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 3 with Capabilities

use of com.google.android.exoplayer2.RendererCapabilities.Capabilities in project ExoPlayer by google.

the class DefaultTrackSelector method selectTracksForType.

@Nullable
private <T extends TrackInfo<T>> Pair<ExoTrackSelection.Definition, Integer> selectTracksForType(@C.TrackType int trackType, MappedTrackInfo mappedTrackInfo, @Capabilities int[][][] formatSupport, TrackInfo.Factory<T> trackInfoFactory, Comparator<List<T>> selectionComparator) {
    ArrayList<List<T>> possibleSelections = new ArrayList<>();
    int rendererCount = mappedTrackInfo.getRendererCount();
    for (int rendererIndex = 0; rendererIndex < rendererCount; rendererIndex++) {
        if (trackType == mappedTrackInfo.getRendererType(rendererIndex)) {
            TrackGroupArray groups = mappedTrackInfo.getTrackGroups(rendererIndex);
            for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) {
                TrackGroup trackGroup = groups.get(groupIndex);
                @Capabilities int[] groupSupport = formatSupport[rendererIndex][groupIndex];
                List<T> trackInfos = trackInfoFactory.create(rendererIndex, trackGroup, groupSupport);
                boolean[] usedTrackInSelection = new boolean[trackGroup.length];
                for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
                    T trackInfo = trackInfos.get(trackIndex);
                    @SelectionEligibility int eligibility = trackInfo.getSelectionEligibility();
                    if (usedTrackInSelection[trackIndex] || eligibility == SELECTION_ELIGIBILITY_NO) {
                        continue;
                    }
                    List<T> selection;
                    if (eligibility == SELECTION_ELIGIBILITY_FIXED) {
                        selection = ImmutableList.of(trackInfo);
                    } else {
                        selection = new ArrayList<>();
                        selection.add(trackInfo);
                        for (int i = trackIndex + 1; i < trackGroup.length; i++) {
                            T otherTrackInfo = trackInfos.get(i);
                            if (otherTrackInfo.getSelectionEligibility() == SELECTION_ELIGIBILITY_ADAPTIVE) {
                                if (trackInfo.isCompatibleForAdaptationWith(otherTrackInfo)) {
                                    selection.add(otherTrackInfo);
                                    usedTrackInSelection[i] = true;
                                }
                            }
                        }
                    }
                    possibleSelections.add(selection);
                }
            }
        }
    }
    if (possibleSelections.isEmpty()) {
        return null;
    }
    List<T> bestSelection = max(possibleSelections, selectionComparator);
    int[] trackIndices = new int[bestSelection.size()];
    for (int i = 0; i < bestSelection.size(); i++) {
        trackIndices[i] = bestSelection.get(i).trackIndex;
    }
    T firstTrackInfo = bestSelection.get(0);
    return Pair.create(new ExoTrackSelection.Definition(firstTrackInfo.trackGroup, trackIndices), firstTrackInfo.rendererIndex);
}
Also used : ArrayList(java.util.ArrayList) TrackGroupArray(com.google.android.exoplayer2.source.TrackGroupArray) SuppressLint(android.annotation.SuppressLint) Point(android.graphics.Point) TrackGroup(com.google.android.exoplayer2.source.TrackGroup) Capabilities(com.google.android.exoplayer2.RendererCapabilities.Capabilities) RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities) List(java.util.List) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) Nullable(androidx.annotation.Nullable)

Example 4 with Capabilities

use of com.google.android.exoplayer2.RendererCapabilities.Capabilities 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 5 with Capabilities

use of com.google.android.exoplayer2.RendererCapabilities.Capabilities in project ExoPlayer by google.

the class EventLogger method onTracksChanged.

@Override
public void onTracksChanged(EventTime eventTime, TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
    MappedTrackInfo mappedTrackInfo = trackSelector != null ? trackSelector.getCurrentMappedTrackInfo() : null;
    if (mappedTrackInfo == null) {
        logd(eventTime, "tracks", "[]");
        return;
    }
    logd("tracks [" + getEventTimeString(eventTime));
    // Log tracks associated to renderers.
    int rendererCount = mappedTrackInfo.getRendererCount();
    for (int rendererIndex = 0; rendererIndex < rendererCount; rendererIndex++) {
        TrackGroupArray rendererTrackGroups = mappedTrackInfo.getTrackGroups(rendererIndex);
        TrackSelection trackSelection = trackSelections.get(rendererIndex);
        if (rendererTrackGroups.length == 0) {
            logd("  " + mappedTrackInfo.getRendererName(rendererIndex) + " []");
        } else {
            logd("  " + mappedTrackInfo.getRendererName(rendererIndex) + " [");
            for (int groupIndex = 0; groupIndex < rendererTrackGroups.length; groupIndex++) {
                TrackGroup trackGroup = rendererTrackGroups.get(groupIndex);
                String adaptiveSupport = getAdaptiveSupportString(trackGroup.length, mappedTrackInfo.getAdaptiveSupport(rendererIndex, groupIndex, /* includeCapabilitiesExceededTracks= */
                false));
                logd("    Group:" + trackGroup.id + ", adaptive_supported=" + adaptiveSupport + " [");
                for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
                    String status = getTrackStatusString(trackSelection, trackGroup, trackIndex);
                    @Capabilities int capabilities = mappedTrackInfo.getCapabilities(rendererIndex, groupIndex, trackIndex);
                    String formatSupport = getFormatSupportString(getFormatSupport(capabilities));
                    String hardwareAccelerationSupport = getHardwareAccelerationSupport(capabilities) == HARDWARE_ACCELERATION_SUPPORTED ? ", accelerated=YES" : "";
                    String decoderSupport = getDecoderSupport(capabilities) == DECODER_SUPPORT_FALLBACK ? ", fallback=YES" : "";
                    logd("      " + status + " Track:" + trackIndex + ", " + Format.toLogString(trackGroup.getFormat(trackIndex)) + ", supported=" + formatSupport + hardwareAccelerationSupport + decoderSupport);
                }
                logd("    ]");
            }
            // Log metadata for at most one of the tracks selected for the renderer.
            if (trackSelection != null) {
                for (int selectionIndex = 0; selectionIndex < trackSelection.length(); selectionIndex++) {
                    Metadata metadata = trackSelection.getFormat(selectionIndex).metadata;
                    if (metadata != null) {
                        logd("    Metadata [");
                        printMetadata(metadata, "      ");
                        logd("    ]");
                        break;
                    }
                }
            }
            logd("  ]");
        }
    }
    // Log tracks not associated with a renderer.
    TrackGroupArray unassociatedTrackGroups = mappedTrackInfo.getUnmappedTrackGroups();
    if (unassociatedTrackGroups.length > 0) {
        logd("  Unmapped [");
        for (int groupIndex = 0; groupIndex < unassociatedTrackGroups.length; groupIndex++) {
            logd("    Group:" + groupIndex + " [");
            TrackGroup trackGroup = unassociatedTrackGroups.get(groupIndex);
            for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
                String status = getTrackStatusString(false);
                String formatSupport = getFormatSupportString(C.FORMAT_UNSUPPORTED_TYPE);
                logd("      " + status + " Track:" + trackIndex + ", " + Format.toLogString(trackGroup.getFormat(trackIndex)) + ", supported=" + formatSupport);
            }
            logd("    ]");
        }
        logd("  ]");
    }
    logd("]");
}
Also used : TrackGroup(com.google.android.exoplayer2.source.TrackGroup) RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities) Capabilities(com.google.android.exoplayer2.RendererCapabilities.Capabilities) TrackGroupArray(com.google.android.exoplayer2.source.TrackGroupArray) Metadata(com.google.android.exoplayer2.metadata.Metadata) Util.getFormatSupportString(com.google.android.exoplayer2.util.Util.getFormatSupportString) MappedTrackInfo(com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo) TrackSelection(com.google.android.exoplayer2.trackselection.TrackSelection)

Aggregations

Format (com.google.android.exoplayer2.Format)23 TrackGroupArray (com.google.android.exoplayer2.source.TrackGroupArray)23 Test (org.junit.Test)22 RendererCapabilities (com.google.android.exoplayer2.RendererCapabilities)17 Capabilities (com.google.android.exoplayer2.RendererCapabilities.Capabilities)9 Nullable (androidx.annotation.Nullable)7 SuppressLint (android.annotation.SuppressLint)6 MediaCodecInfo (com.google.android.exoplayer2.mediacodec.MediaCodecInfo)6 Point (android.graphics.Point)5 Handler (android.os.Handler)5 RendererConfiguration (com.google.android.exoplayer2.RendererConfiguration)5 Before (org.junit.Before)5 CodecCapabilities (android.media.MediaCodecInfo.CodecCapabilities)4 MediaFormat (android.media.MediaFormat)4 ImmutableList (com.google.common.collect.ImmutableList)4 HashMap (java.util.HashMap)4 Looper (android.os.Looper)3 SystemClock (android.os.SystemClock)3 ApplicationProvider (androidx.test.core.app.ApplicationProvider)3 AndroidJUnit4 (androidx.test.ext.junit.runners.AndroidJUnit4)3