Search in sources :

Example 1 with FormatSupport

use of androidx.media3.common.C.FormatSupport in project media by androidx.

the class DefaultTrackSelector method selectOtherTrack.

// Generic track selection methods.
/**
 * Called by {@link #selectAllTracks(MappedTrackInfo, int[][][], int[], Parameters)} to create a
 * {@link ExoTrackSelection} for a renderer whose type is neither video, audio or text.
 *
 * @param trackType The type of the renderer.
 * @param groups The {@link TrackGroupArray} mapped to the renderer.
 * @param formatSupport The {@link Capabilities} for each mapped track, indexed by track group and
 *     track (in that order).
 * @param params The selector's current constraint parameters.
 * @return The {@link ExoTrackSelection} for the renderer, or null if no selection was made.
 * @throws ExoPlaybackException If an error occurs while selecting the tracks.
 */
@Nullable
protected ExoTrackSelection.Definition selectOtherTrack(int trackType, TrackGroupArray groups, @Capabilities int[][] formatSupport, Parameters params) throws ExoPlaybackException {
    @Nullable TrackGroup selectedGroup = null;
    int selectedTrackIndex = 0;
    @Nullable OtherTrackScore selectedTrackScore = null;
    for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) {
        TrackGroup trackGroup = groups.get(groupIndex);
        @Capabilities int[] trackFormatSupport = formatSupport[groupIndex];
        for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
            if (isSupported(trackFormatSupport[trackIndex], params.exceedRendererCapabilitiesIfNecessary)) {
                Format format = trackGroup.getFormat(trackIndex);
                OtherTrackScore trackScore = new OtherTrackScore(format, trackFormatSupport[trackIndex]);
                if (selectedTrackScore == null || trackScore.compareTo(selectedTrackScore) > 0) {
                    selectedGroup = trackGroup;
                    selectedTrackIndex = trackIndex;
                    selectedTrackScore = trackScore;
                }
            }
        }
    }
    return selectedGroup == null ? null : new ExoTrackSelection.Definition(selectedGroup, selectedTrackIndex);
}
Also used : Format(androidx.media3.common.Format) TrackGroup(androidx.media3.common.TrackGroup) RendererCapabilities(androidx.media3.exoplayer.RendererCapabilities) Capabilities(androidx.media3.exoplayer.RendererCapabilities.Capabilities) Nullable(androidx.annotation.Nullable) SuppressLint(android.annotation.SuppressLint) Point(android.graphics.Point) Nullable(androidx.annotation.Nullable)

Example 2 with FormatSupport

use of androidx.media3.common.C.FormatSupport 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 3 with FormatSupport

use of androidx.media3.common.C.FormatSupport in project media by androidx.

the class MappingTrackSelector method findRenderer.

/**
 * Finds the renderer to which the provided {@link TrackGroup} should be mapped.
 *
 * <p>A {@link TrackGroup} is mapped to the renderer that reports the highest of (listed in
 * decreasing order of support) {@link C#FORMAT_HANDLED}, {@link C#FORMAT_EXCEEDS_CAPABILITIES},
 * {@link C#FORMAT_UNSUPPORTED_DRM} and {@link C#FORMAT_UNSUPPORTED_SUBTYPE}.
 *
 * <p>In the case that two or more renderers report the same level of support, the assignment
 * depends on {@code preferUnassociatedRenderer}.
 *
 * <ul>
 *   <li>If {@code preferUnassociatedRenderer} is false, the renderer with the lowest index is
 *       chosen regardless of how many other track groups are already mapped to this renderer.
 *   <li>If {@code preferUnassociatedRenderer} is true, the renderer with the lowest index and no
 *       other mapped track group is chosen, or the renderer with the lowest index if all
 *       available renderers have already mapped track groups.
 * </ul>
 *
 * <p>If all renderers report {@link C#FORMAT_UNSUPPORTED_TYPE} for all of the tracks in the
 * group, then {@code renderers.length} is returned to indicate that the group was not mapped to
 * any renderer.
 *
 * @param rendererCapabilities The {@link RendererCapabilities} of the renderers.
 * @param group The track group to map to a renderer.
 * @param rendererTrackGroupCounts The number of already mapped track groups for each renderer.
 * @param preferUnassociatedRenderer Whether renderers unassociated to any track group should be
 *     preferred.
 * @return The index of the renderer to which the track group was mapped, or {@code
 *     renderers.length} if it was not mapped to any renderer.
 * @throws ExoPlaybackException If an error occurs finding a renderer.
 */
private static int findRenderer(RendererCapabilities[] rendererCapabilities, TrackGroup group, int[] rendererTrackGroupCounts, boolean preferUnassociatedRenderer) throws ExoPlaybackException {
    int bestRendererIndex = rendererCapabilities.length;
    @FormatSupport int bestFormatSupportLevel = C.FORMAT_UNSUPPORTED_TYPE;
    boolean bestRendererIsUnassociated = true;
    for (int rendererIndex = 0; rendererIndex < rendererCapabilities.length; rendererIndex++) {
        RendererCapabilities rendererCapability = rendererCapabilities[rendererIndex];
        @FormatSupport int formatSupportLevel = C.FORMAT_UNSUPPORTED_TYPE;
        for (int trackIndex = 0; trackIndex < group.length; trackIndex++) {
            @FormatSupport int trackFormatSupportLevel = RendererCapabilities.getFormatSupport(rendererCapability.supportsFormat(group.getFormat(trackIndex)));
            formatSupportLevel = max(formatSupportLevel, trackFormatSupportLevel);
        }
        boolean rendererIsUnassociated = rendererTrackGroupCounts[rendererIndex] == 0;
        if (formatSupportLevel > bestFormatSupportLevel || (formatSupportLevel == bestFormatSupportLevel && preferUnassociatedRenderer && !bestRendererIsUnassociated && rendererIsUnassociated)) {
            bestRendererIndex = rendererIndex;
            bestFormatSupportLevel = formatSupportLevel;
            bestRendererIsUnassociated = rendererIsUnassociated;
        }
    }
    return bestRendererIndex;
}
Also used : FormatSupport(androidx.media3.common.C.FormatSupport) RendererCapabilities(androidx.media3.exoplayer.RendererCapabilities)

Example 4 with FormatSupport

use of androidx.media3.common.C.FormatSupport 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 FormatSupport

use of androidx.media3.common.C.FormatSupport 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)6 SuppressLint (android.annotation.SuppressLint)4 Point (android.graphics.Point)3 Nullable (androidx.annotation.Nullable)3 TrackGroup (androidx.media3.common.TrackGroup)3 Capabilities (androidx.media3.exoplayer.RendererCapabilities.Capabilities)3 TrackGroupArray (androidx.media3.common.TrackGroupArray)2 MediaCodecInfo (androidx.media3.exoplayer.mediacodec.MediaCodecInfo)2 CodecCapabilities (android.media.MediaCodecInfo.CodecCapabilities)1 FormatSupport (androidx.media3.common.C.FormatSupport)1 DrmInitData (androidx.media3.common.DrmInitData)1 Format (androidx.media3.common.Format)1 Metadata (androidx.media3.common.Metadata)1 TrackSelection (androidx.media3.common.TrackSelection)1 Util.getFormatSupportString (androidx.media3.common.util.Util.getFormatSupportString)1 MappedTrackInfo (androidx.media3.exoplayer.trackselection.MappingTrackSelector.MappedTrackInfo)1 ImmutableList (com.google.common.collect.ImmutableList)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1