Search in sources :

Example 1 with AdaptiveSupport

use of androidx.media3.exoplayer.RendererCapabilities.AdaptiveSupport in project media by androidx.

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(androidx.media3.exoplayer.mediacodec.MediaCodecInfo) SuppressLint(android.annotation.SuppressLint) RendererCapabilities(androidx.media3.exoplayer.RendererCapabilities)

Example 2 with AdaptiveSupport

use of androidx.media3.exoplayer.RendererCapabilities.AdaptiveSupport in project media by androidx.

the class DefaultTrackSelector method selectTracks.

// MappingTrackSelector implementation.
@Override
protected final Pair<@NullableType RendererConfiguration[], @NullableType ExoTrackSelection[]> selectTracks(MappedTrackInfo mappedTrackInfo, @Capabilities int[][][] rendererFormatSupports, @AdaptiveSupport int[] rendererMixedMimeTypeAdaptationSupports, MediaPeriodId mediaPeriodId, Timeline timeline) throws ExoPlaybackException {
    Parameters params = parametersReference.get();
    int rendererCount = mappedTrackInfo.getRendererCount();
    ExoTrackSelection.@NullableType Definition[] definitions = selectAllTracks(mappedTrackInfo, rendererFormatSupports, rendererMixedMimeTypeAdaptationSupports, params);
    // Apply per track type overrides.
    SparseArray<Pair<TrackSelectionOverride, Integer>> applicableOverridesByTrackType = getApplicableOverrides(mappedTrackInfo, params);
    for (int i = 0; i < applicableOverridesByTrackType.size(); i++) {
        Pair<TrackSelectionOverride, Integer> overrideAndRendererIndex = applicableOverridesByTrackType.valueAt(i);
        applyTrackTypeOverride(mappedTrackInfo, definitions, /* trackType= */
        applicableOverridesByTrackType.keyAt(i), /* override= */
        overrideAndRendererIndex.first, /* overrideRendererIndex= */
        overrideAndRendererIndex.second);
    }
    // Apply legacy per renderer overrides.
    for (int i = 0; i < rendererCount; i++) {
        if (hasLegacyRendererOverride(mappedTrackInfo, params, /* rendererIndex= */
        i)) {
            definitions[i] = getLegacyRendererOverride(mappedTrackInfo, params, /* rendererIndex= */
            i);
        }
    }
    // Disable renderers if needed.
    for (int i = 0; i < rendererCount; i++) {
        if (isRendererDisabled(mappedTrackInfo, params, /* rendererIndex= */
        i)) {
            definitions[i] = null;
        }
    }
    @NullableType ExoTrackSelection[] rendererTrackSelections = trackSelectionFactory.createTrackSelections(definitions, getBandwidthMeter(), mediaPeriodId, timeline);
    // Initialize the renderer configurations to the default configuration for all renderers with
    // selections, and null otherwise.
    @NullableType RendererConfiguration[] rendererConfigurations = new RendererConfiguration[rendererCount];
    for (int i = 0; i < rendererCount; i++) {
        @C.TrackType int rendererType = mappedTrackInfo.getRendererType(i);
        boolean forceRendererDisabled = params.getRendererDisabled(i) || params.disabledTrackTypes.contains(rendererType);
        boolean rendererEnabled = !forceRendererDisabled && (mappedTrackInfo.getRendererType(i) == C.TRACK_TYPE_NONE || rendererTrackSelections[i] != null);
        rendererConfigurations[i] = rendererEnabled ? RendererConfiguration.DEFAULT : null;
    }
    // Configure audio and video renderers to use tunneling if appropriate.
    if (params.tunnelingEnabled) {
        maybeConfigureRenderersForTunneling(mappedTrackInfo, rendererFormatSupports, rendererConfigurations, rendererTrackSelections);
    }
    return Pair.create(rendererConfigurations, rendererTrackSelections);
}
Also used : TrackSelectionParameters(androidx.media3.common.TrackSelectionParameters) TrackSelectionOverride(androidx.media3.common.TrackSelectionOverrides.TrackSelectionOverride) NullableType(org.checkerframework.checker.nullness.compatqual.NullableType) SuppressLint(android.annotation.SuppressLint) Point(android.graphics.Point) RendererConfiguration(androidx.media3.exoplayer.RendererConfiguration) Pair(android.util.Pair) TrackSelectionOverride(androidx.media3.common.TrackSelectionOverrides.TrackSelectionOverride)

Example 3 with AdaptiveSupport

use of androidx.media3.exoplayer.RendererCapabilities.AdaptiveSupport in project media by androidx.

the class MappingTrackSelector method selectTracks.

@Override
public final TrackSelectorResult selectTracks(RendererCapabilities[] rendererCapabilities, TrackGroupArray trackGroups, MediaPeriodId periodId, Timeline timeline) throws ExoPlaybackException {
    // Structures into which data will be written during the selection. The extra item at the end
    // of each array is to store data associated with track groups that cannot be associated with
    // any renderer.
    int[] rendererTrackGroupCounts = new int[rendererCapabilities.length + 1];
    TrackGroup[][] rendererTrackGroups = new TrackGroup[rendererCapabilities.length + 1][];
    @Capabilities int[][][] rendererFormatSupports = new int[rendererCapabilities.length + 1][][];
    for (int i = 0; i < rendererTrackGroups.length; i++) {
        rendererTrackGroups[i] = new TrackGroup[trackGroups.length];
        rendererFormatSupports[i] = new int[trackGroups.length][];
    }
    // Determine the extent to which each renderer supports mixed mimeType adaptation.
    @AdaptiveSupport int[] rendererMixedMimeTypeAdaptationSupports = getMixedMimeTypeAdaptationSupports(rendererCapabilities);
    // renderer provides for each track in the group.
    for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) {
        TrackGroup group = trackGroups.get(groupIndex);
        // Associate the group to a preferred renderer.
        boolean preferUnassociatedRenderer = MimeTypes.getTrackType(group.getFormat(0).sampleMimeType) == C.TRACK_TYPE_METADATA;
        int rendererIndex = findRenderer(rendererCapabilities, group, rendererTrackGroupCounts, preferUnassociatedRenderer);
        // Evaluate the support that the renderer provides for each track in the group.
        @Capabilities int[] rendererFormatSupport = rendererIndex == rendererCapabilities.length ? new int[group.length] : getFormatSupport(rendererCapabilities[rendererIndex], group);
        // Stash the results.
        int rendererTrackGroupCount = rendererTrackGroupCounts[rendererIndex];
        rendererTrackGroups[rendererIndex][rendererTrackGroupCount] = group;
        rendererFormatSupports[rendererIndex][rendererTrackGroupCount] = rendererFormatSupport;
        rendererTrackGroupCounts[rendererIndex]++;
    }
    // Create a track group array for each renderer, and trim each rendererFormatSupports entry.
    TrackGroupArray[] rendererTrackGroupArrays = new TrackGroupArray[rendererCapabilities.length];
    String[] rendererNames = new String[rendererCapabilities.length];
    int[] rendererTrackTypes = new int[rendererCapabilities.length];
    for (int i = 0; i < rendererCapabilities.length; i++) {
        int rendererTrackGroupCount = rendererTrackGroupCounts[i];
        rendererTrackGroupArrays[i] = new TrackGroupArray(Util.nullSafeArrayCopy(rendererTrackGroups[i], rendererTrackGroupCount));
        rendererFormatSupports[i] = Util.nullSafeArrayCopy(rendererFormatSupports[i], rendererTrackGroupCount);
        rendererNames[i] = rendererCapabilities[i].getName();
        rendererTrackTypes[i] = rendererCapabilities[i].getTrackType();
    }
    // Create a track group array for track groups not mapped to a renderer.
    int unmappedTrackGroupCount = rendererTrackGroupCounts[rendererCapabilities.length];
    TrackGroupArray unmappedTrackGroupArray = new TrackGroupArray(Util.nullSafeArrayCopy(rendererTrackGroups[rendererCapabilities.length], unmappedTrackGroupCount));
    // Package up the track information and selections.
    MappedTrackInfo mappedTrackInfo = new MappedTrackInfo(rendererNames, rendererTrackTypes, rendererTrackGroupArrays, rendererMixedMimeTypeAdaptationSupports, rendererFormatSupports, unmappedTrackGroupArray);
    Pair<@NullableType RendererConfiguration[], @NullableType ExoTrackSelection[]> result = selectTracks(mappedTrackInfo, rendererFormatSupports, rendererMixedMimeTypeAdaptationSupports, periodId, timeline);
    TracksInfo tracksInfo = buildTracksInfo(result.second, mappedTrackInfo);
    return new TrackSelectorResult(result.first, result.second, tracksInfo, mappedTrackInfo);
}
Also used : TrackGroupArray(androidx.media3.common.TrackGroupArray) NullableType(org.checkerframework.checker.nullness.compatqual.NullableType) TracksInfo(androidx.media3.common.TracksInfo) TrackGroup(androidx.media3.common.TrackGroup) RendererCapabilities(androidx.media3.exoplayer.RendererCapabilities) Capabilities(androidx.media3.exoplayer.RendererCapabilities.Capabilities) AdaptiveSupport(androidx.media3.exoplayer.RendererCapabilities.AdaptiveSupport)

Example 4 with AdaptiveSupport

use of androidx.media3.exoplayer.RendererCapabilities.AdaptiveSupport in project media by androidx.

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(androidx.media3.common.TrackGroup) RendererCapabilities(androidx.media3.exoplayer.RendererCapabilities) Capabilities(androidx.media3.exoplayer.RendererCapabilities.Capabilities) TrackGroupArray(androidx.media3.common.TrackGroupArray) Metadata(androidx.media3.common.Metadata) Util.getFormatSupportString(androidx.media3.common.util.Util.getFormatSupportString) MappedTrackInfo(androidx.media3.exoplayer.trackselection.MappingTrackSelector.MappedTrackInfo) TrackSelection(androidx.media3.common.TrackSelection)

Example 5 with AdaptiveSupport

use of androidx.media3.exoplayer.RendererCapabilities.AdaptiveSupport in project media by androidx.

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(androidx.media3.common.DrmInitData) MediaCodecInfo(androidx.media3.exoplayer.mediacodec.MediaCodecInfo) Nullable(androidx.annotation.Nullable) SuppressLint(android.annotation.SuppressLint) Point(android.graphics.Point) CodecCapabilities(android.media.MediaCodecInfo.CodecCapabilities) RendererCapabilities(androidx.media3.exoplayer.RendererCapabilities)

Aggregations

RendererCapabilities (androidx.media3.exoplayer.RendererCapabilities)4 SuppressLint (android.annotation.SuppressLint)3 TrackGroupArray (androidx.media3.common.TrackGroupArray)3 Point (android.graphics.Point)2 TrackGroup (androidx.media3.common.TrackGroup)2 Capabilities (androidx.media3.exoplayer.RendererCapabilities.Capabilities)2 MediaCodecInfo (androidx.media3.exoplayer.mediacodec.MediaCodecInfo)2 NullableType (org.checkerframework.checker.nullness.compatqual.NullableType)2 CodecCapabilities (android.media.MediaCodecInfo.CodecCapabilities)1 Pair (android.util.Pair)1 Nullable (androidx.annotation.Nullable)1 DrmInitData (androidx.media3.common.DrmInitData)1 Metadata (androidx.media3.common.Metadata)1 TrackSelection (androidx.media3.common.TrackSelection)1 TrackSelectionOverride (androidx.media3.common.TrackSelectionOverrides.TrackSelectionOverride)1 TrackSelectionParameters (androidx.media3.common.TrackSelectionParameters)1 TracksInfo (androidx.media3.common.TracksInfo)1 Util.getFormatSupportString (androidx.media3.common.util.Util.getFormatSupportString)1 AdaptiveSupport (androidx.media3.exoplayer.RendererCapabilities.AdaptiveSupport)1 RendererConfiguration (androidx.media3.exoplayer.RendererConfiguration)1