Search in sources :

Example 1 with NullableType

use of org.checkerframework.checker.nullness.compatqual.NullableType in project ExoPlayer by google.

the class CastPlayer method updateTracksAndSelectionsAndNotifyIfChanged.

/**
 * Updates the internal tracks and selection and returns whether they have changed.
 */
private boolean updateTracksAndSelectionsAndNotifyIfChanged() {
    if (remoteMediaClient == null) {
        // There is no session. We leave the state of the player as it is now.
        return false;
    }
    MediaStatus mediaStatus = getMediaStatus();
    MediaInfo mediaInfo = mediaStatus != null ? mediaStatus.getMediaInfo() : null;
    List<MediaTrack> castMediaTracks = mediaInfo != null ? mediaInfo.getMediaTracks() : null;
    if (castMediaTracks == null || castMediaTracks.isEmpty()) {
        boolean hasChanged = !currentTrackGroups.isEmpty();
        currentTrackGroups = TrackGroupArray.EMPTY;
        currentTrackSelection = EMPTY_TRACK_SELECTION_ARRAY;
        currentTracksInfo = TracksInfo.EMPTY;
        return hasChanged;
    }
    long[] activeTrackIds = mediaStatus.getActiveTrackIds();
    if (activeTrackIds == null) {
        activeTrackIds = EMPTY_TRACK_ID_ARRAY;
    }
    TrackGroup[] trackGroups = new TrackGroup[castMediaTracks.size()];
    @NullableType TrackSelection[] trackSelections = new TrackSelection[RENDERER_COUNT];
    TracksInfo.TrackGroupInfo[] trackGroupInfos = new TracksInfo.TrackGroupInfo[castMediaTracks.size()];
    for (int i = 0; i < castMediaTracks.size(); i++) {
        MediaTrack mediaTrack = castMediaTracks.get(i);
        trackGroups[i] = new TrackGroup(/* id= */
        Integer.toString(i), CastUtils.mediaTrackToFormat(mediaTrack));
        long id = mediaTrack.getId();
        @C.TrackType int trackType = MimeTypes.getTrackType(mediaTrack.getContentType());
        int rendererIndex = getRendererIndexForTrackType(trackType);
        boolean supported = rendererIndex != C.INDEX_UNSET;
        boolean selected = isTrackActive(id, activeTrackIds) && supported && trackSelections[rendererIndex] == null;
        if (selected) {
            trackSelections[rendererIndex] = new CastTrackSelection(trackGroups[i]);
        }
        @C.FormatSupport int[] trackSupport = new int[] { supported ? C.FORMAT_HANDLED : C.FORMAT_UNSUPPORTED_TYPE };
        final boolean[] trackSelected = new boolean[] { selected };
        trackGroupInfos[i] = new TracksInfo.TrackGroupInfo(trackGroups[i], trackSupport, trackType, trackSelected);
    }
    TrackGroupArray newTrackGroups = new TrackGroupArray(trackGroups);
    TrackSelectionArray newTrackSelections = new TrackSelectionArray(trackSelections);
    TracksInfo newTracksInfo = new TracksInfo(ImmutableList.copyOf(trackGroupInfos));
    if (!newTrackGroups.equals(currentTrackGroups) || !newTrackSelections.equals(currentTrackSelection) || !newTracksInfo.equals(currentTracksInfo)) {
        currentTrackSelection = newTrackSelections;
        currentTrackGroups = newTrackGroups;
        currentTracksInfo = newTracksInfo;
        return true;
    }
    return false;
}
Also used : TrackGroupArray(com.google.android.exoplayer2.source.TrackGroupArray) NullableType(org.checkerframework.checker.nullness.compatqual.NullableType) TracksInfo(com.google.android.exoplayer2.TracksInfo) TrackSelectionArray(com.google.android.exoplayer2.trackselection.TrackSelectionArray) MediaTrack(com.google.android.gms.cast.MediaTrack) MediaInfo(com.google.android.gms.cast.MediaInfo) TrackGroup(com.google.android.exoplayer2.source.TrackGroup) TrackSelection(com.google.android.exoplayer2.trackselection.TrackSelection) MediaStatus(com.google.android.gms.cast.MediaStatus)

Example 2 with NullableType

use of org.checkerframework.checker.nullness.compatqual.NullableType in project ExoPlayer by google.

the class TrackSelectionUtil method createTrackSelectionsForDefinitions.

/**
 * Creates track selections for an array of track selection definitions, with at most one
 * multi-track adaptive selection.
 *
 * @param definitions The list of track selection {@link Definition definitions}. May include null
 *     values.
 * @param adaptiveTrackSelectionFactory A factory for the multi-track adaptive track selection.
 * @return The array of created track selection. For null entries in {@code definitions} returns
 *     null values.
 */
@NullableType
public static ExoTrackSelection[] createTrackSelectionsForDefinitions(@NullableType Definition[] definitions, AdaptiveTrackSelectionFactory adaptiveTrackSelectionFactory) {
    ExoTrackSelection[] selections = new ExoTrackSelection[definitions.length];
    boolean createdAdaptiveTrackSelection = false;
    for (int i = 0; i < definitions.length; i++) {
        Definition definition = definitions[i];
        if (definition == null) {
            continue;
        }
        if (definition.tracks.length > 1 && !createdAdaptiveTrackSelection) {
            createdAdaptiveTrackSelection = true;
            selections[i] = adaptiveTrackSelectionFactory.createAdaptiveTrackSelection(definition);
        } else {
            selections[i] = new FixedTrackSelection(definition.group, definition.tracks[0], /* type= */
            definition.type);
        }
    }
    return selections;
}
Also used : Definition(com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition) NullableType(org.checkerframework.checker.nullness.compatqual.NullableType)

Example 3 with NullableType

use of org.checkerframework.checker.nullness.compatqual.NullableType in project ExoPlayer by google.

the class DashDownloader method getSegmentIndex.

@Nullable
private DashSegmentIndex getSegmentIndex(DataSource dataSource, int trackType, Representation representation, boolean removing) throws IOException, InterruptedException {
    DashSegmentIndex index = representation.getIndex();
    if (index != null) {
        return index;
    }
    RunnableFutureTask<@NullableType ChunkIndex, IOException> runnable = new RunnableFutureTask<@NullableType ChunkIndex, IOException>() {

        @Override
        @NullableType
        protected ChunkIndex doWork() throws IOException {
            return DashUtil.loadChunkIndex(dataSource, trackType, representation);
        }
    };
    @Nullable ChunkIndex seekMap = execute(runnable, removing);
    return seekMap == null ? null : new DashWrappingSegmentIndex(seekMap, representation.presentationTimeOffsetUs);
}
Also used : DashWrappingSegmentIndex(com.google.android.exoplayer2.source.dash.DashWrappingSegmentIndex) RunnableFutureTask(com.google.android.exoplayer2.util.RunnableFutureTask) IOException(java.io.IOException) NullableType(org.checkerframework.checker.nullness.compatqual.NullableType) DashSegmentIndex(com.google.android.exoplayer2.source.dash.DashSegmentIndex) ChunkIndex(com.google.android.exoplayer2.extractor.ChunkIndex) Nullable(androidx.annotation.Nullable) Nullable(androidx.annotation.Nullable)

Example 4 with NullableType

use of org.checkerframework.checker.nullness.compatqual.NullableType in project ExoPlayer by google.

the class HlsMediaPeriod method selectTracks.

@Override
public long selectTracks(@NullableType ExoTrackSelection[] selections, boolean[] mayRetainStreamFlags, @NullableType SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
    // Map each selection and stream onto a child period index.
    int[] streamChildIndices = new int[selections.length];
    int[] selectionChildIndices = new int[selections.length];
    for (int i = 0; i < selections.length; i++) {
        streamChildIndices[i] = streams[i] == null ? C.INDEX_UNSET : streamWrapperIndices.get(streams[i]);
        selectionChildIndices[i] = C.INDEX_UNSET;
        if (selections[i] != null) {
            TrackGroup trackGroup = selections[i].getTrackGroup();
            for (int j = 0; j < sampleStreamWrappers.length; j++) {
                if (sampleStreamWrappers[j].getTrackGroups().indexOf(trackGroup) != C.INDEX_UNSET) {
                    selectionChildIndices[i] = j;
                    break;
                }
            }
        }
    }
    boolean forceReset = false;
    streamWrapperIndices.clear();
    // Select tracks for each child, copying the resulting streams back into a new streams array.
    SampleStream[] newStreams = new SampleStream[selections.length];
    @NullableType SampleStream[] childStreams = new SampleStream[selections.length];
    @NullableType ExoTrackSelection[] childSelections = new ExoTrackSelection[selections.length];
    int newEnabledSampleStreamWrapperCount = 0;
    HlsSampleStreamWrapper[] newEnabledSampleStreamWrappers = new HlsSampleStreamWrapper[sampleStreamWrappers.length];
    for (int i = 0; i < sampleStreamWrappers.length; i++) {
        for (int j = 0; j < selections.length; j++) {
            childStreams[j] = streamChildIndices[j] == i ? streams[j] : null;
            childSelections[j] = selectionChildIndices[j] == i ? selections[j] : null;
        }
        HlsSampleStreamWrapper sampleStreamWrapper = sampleStreamWrappers[i];
        boolean wasReset = sampleStreamWrapper.selectTracks(childSelections, mayRetainStreamFlags, childStreams, streamResetFlags, positionUs, forceReset);
        boolean wrapperEnabled = false;
        for (int j = 0; j < selections.length; j++) {
            SampleStream childStream = childStreams[j];
            if (selectionChildIndices[j] == i) {
                // Assert that the child provided a stream for the selection.
                Assertions.checkNotNull(childStream);
                newStreams[j] = childStream;
                wrapperEnabled = true;
                streamWrapperIndices.put(childStream, i);
            } else if (streamChildIndices[j] == i) {
                // Assert that the child cleared any previous stream.
                Assertions.checkState(childStream == null);
            }
        }
        if (wrapperEnabled) {
            newEnabledSampleStreamWrappers[newEnabledSampleStreamWrapperCount] = sampleStreamWrapper;
            if (newEnabledSampleStreamWrapperCount++ == 0) {
                // The first enabled wrapper is always allowed to initialize timestamp adjusters. Note
                // that the first wrapper will correspond to a variant, or else an audio rendition, or
                // else a text rendition, in that order.
                sampleStreamWrapper.setIsTimestampMaster(true);
                if (wasReset || enabledSampleStreamWrappers.length == 0 || sampleStreamWrapper != enabledSampleStreamWrappers[0]) {
                    // The wrapper responsible for initializing the timestamp adjusters was reset or
                    // changed. We need to reset the timestamp adjuster provider and all other wrappers.
                    timestampAdjusterProvider.reset();
                    forceReset = true;
                }
            } else {
                // Additional wrappers are also allowed to initialize timestamp adjusters if they contain
                // audio or video, since they are expected to contain dense samples. Text wrappers are not
                // permitted except in the case above in which no variant or audio rendition wrappers are
                // enabled.
                sampleStreamWrapper.setIsTimestampMaster(i < audioVideoSampleStreamWrapperCount);
            }
        }
    }
    // Copy the new streams back into the streams array.
    System.arraycopy(newStreams, 0, streams, 0, newStreams.length);
    // Update the local state.
    enabledSampleStreamWrappers = Util.nullSafeArrayCopy(newEnabledSampleStreamWrappers, newEnabledSampleStreamWrapperCount);
    compositeSequenceableLoader = compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(enabledSampleStreamWrappers);
    return positionUs;
}
Also used : ExoTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection) TrackGroup(com.google.android.exoplayer2.source.TrackGroup) NullableType(org.checkerframework.checker.nullness.compatqual.NullableType) SampleStream(com.google.android.exoplayer2.source.SampleStream)

Example 5 with NullableType

use of org.checkerframework.checker.nullness.compatqual.NullableType in project ExoPlayer by google.

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(com.google.android.exoplayer2.source.TrackGroupArray) NullableType(org.checkerframework.checker.nullness.compatqual.NullableType) TracksInfo(com.google.android.exoplayer2.TracksInfo) TrackGroup(com.google.android.exoplayer2.source.TrackGroup) RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities) Capabilities(com.google.android.exoplayer2.RendererCapabilities.Capabilities) AdaptiveSupport(com.google.android.exoplayer2.RendererCapabilities.AdaptiveSupport)

Aggregations

NullableType (org.checkerframework.checker.nullness.compatqual.NullableType)7 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)3 TracksInfo (com.google.android.exoplayer2.TracksInfo)2 TrackGroupArray (com.google.android.exoplayer2.source.TrackGroupArray)2 ExoTrackSelection (com.google.android.exoplayer2.trackselection.ExoTrackSelection)2 SuppressLint (android.annotation.SuppressLint)1 Point (android.graphics.Point)1 Pair (android.util.Pair)1 Nullable (androidx.annotation.Nullable)1 RendererCapabilities (com.google.android.exoplayer2.RendererCapabilities)1 AdaptiveSupport (com.google.android.exoplayer2.RendererCapabilities.AdaptiveSupport)1 Capabilities (com.google.android.exoplayer2.RendererCapabilities.Capabilities)1 RendererConfiguration (com.google.android.exoplayer2.RendererConfiguration)1 ChunkIndex (com.google.android.exoplayer2.extractor.ChunkIndex)1 SampleStream (com.google.android.exoplayer2.source.SampleStream)1 DashSegmentIndex (com.google.android.exoplayer2.source.dash.DashSegmentIndex)1 DashWrappingSegmentIndex (com.google.android.exoplayer2.source.dash.DashWrappingSegmentIndex)1 Definition (com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition)1 TrackSelection (com.google.android.exoplayer2.trackselection.TrackSelection)1 TrackSelectionArray (com.google.android.exoplayer2.trackselection.TrackSelectionArray)1