Search in sources :

Example 1 with EnsuresNonNull

use of org.checkerframework.checker.nullness.qual.EnsuresNonNull in project ExoPlayer by google.

the class HlsSampleStreamWrapper method mapSampleQueuesToMatchTrackGroups.

@RequiresNonNull("trackGroups")
@EnsuresNonNull("trackGroupToSampleQueueIndex")
private void mapSampleQueuesToMatchTrackGroups() {
    int trackGroupCount = trackGroups.length;
    trackGroupToSampleQueueIndex = new int[trackGroupCount];
    Arrays.fill(trackGroupToSampleQueueIndex, C.INDEX_UNSET);
    for (int i = 0; i < trackGroupCount; i++) {
        for (int queueIndex = 0; queueIndex < sampleQueues.length; queueIndex++) {
            SampleQueue sampleQueue = sampleQueues[queueIndex];
            Format upstreamFormat = Assertions.checkStateNotNull(sampleQueue.getUpstreamFormat());
            if (formatsMatch(upstreamFormat, trackGroups.get(i).getFormat(0))) {
                trackGroupToSampleQueueIndex[i] = queueIndex;
                break;
            }
        }
    }
    for (HlsSampleStream sampleStream : hlsSampleStreams) {
        sampleStream.bindSampleQueue();
    }
}
Also used : SampleQueue(com.google.android.exoplayer2.source.SampleQueue) Format(com.google.android.exoplayer2.Format) EnsuresNonNull(org.checkerframework.checker.nullness.qual.EnsuresNonNull) RequiresNonNull(org.checkerframework.checker.nullness.qual.RequiresNonNull)

Example 2 with EnsuresNonNull

use of org.checkerframework.checker.nullness.qual.EnsuresNonNull in project ExoPlayer by google.

the class FlacExtractor method decodeStreamMetadata.

// Requires initialized.
@RequiresNonNull({ "decoderJni", "extractorOutput", "trackOutput" })
// Ensures stream metadata decoded.
@EnsuresNonNull({ "streamMetadata", "outputFrameHolder" })
@SuppressWarnings("nullness:contracts.postcondition")
private void decodeStreamMetadata(ExtractorInput input) throws IOException {
    if (streamMetadataDecoded) {
        return;
    }
    FlacDecoderJni flacDecoderJni = decoderJni;
    FlacStreamMetadata streamMetadata;
    try {
        streamMetadata = flacDecoderJni.decodeStreamMetadata();
    } catch (IOException e) {
        flacDecoderJni.reset(/* newPosition= */
        0);
        input.setRetryPosition(/* position= */
        0, e);
        throw e;
    }
    streamMetadataDecoded = true;
    if (this.streamMetadata == null) {
        this.streamMetadata = streamMetadata;
        outputBuffer.reset(streamMetadata.getMaxDecodedFrameSize());
        outputFrameHolder = new OutputFrameHolder(ByteBuffer.wrap(outputBuffer.getData()));
        binarySearchSeeker = outputSeekMap(flacDecoderJni, streamMetadata, input.getLength(), extractorOutput, outputFrameHolder);
        @Nullable Metadata metadata = streamMetadata.getMetadataCopyWithAppendedEntriesFrom(id3Metadata);
        outputFormat(streamMetadata, metadata, trackOutput);
    }
}
Also used : FlacStreamMetadata(com.google.android.exoplayer2.extractor.FlacStreamMetadata) Metadata(com.google.android.exoplayer2.metadata.Metadata) IOException(java.io.IOException) FlacStreamMetadata(com.google.android.exoplayer2.extractor.FlacStreamMetadata) Nullable(androidx.annotation.Nullable) OutputFrameHolder(com.google.android.exoplayer2.ext.flac.FlacBinarySearchSeeker.OutputFrameHolder) EnsuresNonNull(org.checkerframework.checker.nullness.qual.EnsuresNonNull) RequiresNonNull(org.checkerframework.checker.nullness.qual.RequiresNonNull)

Example 3 with EnsuresNonNull

use of org.checkerframework.checker.nullness.qual.EnsuresNonNull in project ExoPlayer by google.

the class DecoderInputBuffer method ensureSpaceForWrite.

/**
 * Ensures that {@link #data} is large enough to accommodate a write of a given length at its
 * current position.
 *
 * <p>If the capacity of {@link #data} is sufficient this method does nothing. If the capacity is
 * insufficient then an attempt is made to replace {@link #data} with a new {@link ByteBuffer}
 * whose capacity is sufficient. Data up to the current position is copied to the new buffer.
 *
 * @param length The length of the write that must be accommodated, in bytes.
 * @throws InsufficientCapacityException If there is insufficient capacity to accommodate the
 *     write and {@link #bufferReplacementMode} is {@link #BUFFER_REPLACEMENT_MODE_DISABLED}.
 */
@EnsuresNonNull("data")
public void ensureSpaceForWrite(int length) {
    length += paddingSize;
    @Nullable ByteBuffer currentData = data;
    if (currentData == null) {
        data = createReplacementByteBuffer(length);
        return;
    }
    // Check whether the current buffer is sufficient.
    int capacity = currentData.capacity();
    int position = currentData.position();
    int requiredCapacity = position + length;
    if (capacity >= requiredCapacity) {
        data = currentData;
        return;
    }
    // Instantiate a new buffer if possible.
    ByteBuffer newData = createReplacementByteBuffer(requiredCapacity);
    newData.order(currentData.order());
    // Copy data up to the current position from the old buffer to the new one.
    if (position > 0) {
        currentData.flip();
        newData.put(currentData);
    }
    // Set the new buffer.
    data = newData;
}
Also used : ByteBuffer(java.nio.ByteBuffer) Nullable(androidx.annotation.Nullable) EnsuresNonNull(org.checkerframework.checker.nullness.qual.EnsuresNonNull)

Example 4 with EnsuresNonNull

use of org.checkerframework.checker.nullness.qual.EnsuresNonNull in project ExoPlayer by google.

the class DefaultDrmSessionManager method initPlaybackLooper.

@EnsuresNonNull({ "this.playbackLooper", "this.playbackHandler" })
private synchronized void initPlaybackLooper(Looper playbackLooper) {
    if (this.playbackLooper == null) {
        this.playbackLooper = playbackLooper;
        this.playbackHandler = new Handler(playbackLooper);
    } else {
        checkState(this.playbackLooper == playbackLooper);
        checkNotNull(playbackHandler);
    }
}
Also used : Handler(android.os.Handler) EnsuresNonNull(org.checkerframework.checker.nullness.qual.EnsuresNonNull)

Example 5 with EnsuresNonNull

use of org.checkerframework.checker.nullness.qual.EnsuresNonNull in project ExoPlayer by google.

the class HlsSampleStreamWrapper method buildTracksFromSampleStreams.

/**
 * Builds tracks that are exposed by this {@link HlsSampleStreamWrapper} instance, as well as
 * internal data-structures required for operation.
 *
 * <p>Tracks in HLS are complicated. A HLS multivariant playlist contains a number of "variants".
 * Each variant stream typically contains muxed video, audio and (possibly) additional audio,
 * metadata and caption tracks. We wish to allow the user to select between an adaptive track that
 * spans all variants, as well as each individual variant. If multiple audio tracks are present
 * within each variant then we wish to allow the user to select between those also.
 *
 * <p>To do this, tracks are constructed as follows. The {@link HlsChunkSource} exposes (N+1)
 * tracks, where N is the number of variants defined in the HLS multivariant playlist. These
 * consist of one adaptive track defined to span all variants and a track for each individual
 * variant. The adaptive track is initially selected. The extractor is then prepared to discover
 * the tracks inside of each variant stream. The two sets of tracks are then combined by this
 * method to create a third set, which is the set exposed by this {@link HlsSampleStreamWrapper}:
 *
 * <ul>
 *   <li>The extractor tracks are inspected to infer a "primary" track type. If a video track is
 *       present then it is always the primary type. If not, audio is the primary type if present.
 *       Else text is the primary type if present. Else there is no primary type.
 *   <li>If there is exactly one extractor track of the primary type, it's expanded into (N+1)
 *       exposed tracks, all of which correspond to the primary extractor track and each of which
 *       corresponds to a different chunk source track. Selecting one of these tracks has the
 *       effect of switching the selected track on the chunk source.
 *   <li>All other extractor tracks are exposed directly. Selecting one of these tracks has the
 *       effect of selecting an extractor track, leaving the selected track on the chunk source
 *       unchanged.
 * </ul>
 */
@EnsuresNonNull({ "trackGroups", "optionalTrackGroups", "trackGroupToSampleQueueIndex" })
private void buildTracksFromSampleStreams() {
    // Iterate through the extractor tracks to discover the "primary" track type, and the index
    // of the single track of this type.
    int primaryExtractorTrackType = C.TRACK_TYPE_NONE;
    int primaryExtractorTrackIndex = C.INDEX_UNSET;
    int extractorTrackCount = sampleQueues.length;
    for (int i = 0; i < extractorTrackCount; i++) {
        @Nullable String sampleMimeType = Assertions.checkStateNotNull(sampleQueues[i].getUpstreamFormat()).sampleMimeType;
        int trackType;
        if (MimeTypes.isVideo(sampleMimeType)) {
            trackType = C.TRACK_TYPE_VIDEO;
        } else if (MimeTypes.isAudio(sampleMimeType)) {
            trackType = C.TRACK_TYPE_AUDIO;
        } else if (MimeTypes.isText(sampleMimeType)) {
            trackType = C.TRACK_TYPE_TEXT;
        } else {
            trackType = C.TRACK_TYPE_NONE;
        }
        if (getTrackTypeScore(trackType) > getTrackTypeScore(primaryExtractorTrackType)) {
            primaryExtractorTrackType = trackType;
            primaryExtractorTrackIndex = i;
        } else if (trackType == primaryExtractorTrackType && primaryExtractorTrackIndex != C.INDEX_UNSET) {
            // We have multiple tracks of the primary type. We only want an index if there only exists a
            // single track of the primary type, so unset the index again.
            primaryExtractorTrackIndex = C.INDEX_UNSET;
        }
    }
    TrackGroup chunkSourceTrackGroup = chunkSource.getTrackGroup();
    int chunkSourceTrackCount = chunkSourceTrackGroup.length;
    // Instantiate the necessary internal data-structures.
    primaryTrackGroupIndex = C.INDEX_UNSET;
    trackGroupToSampleQueueIndex = new int[extractorTrackCount];
    for (int i = 0; i < extractorTrackCount; i++) {
        trackGroupToSampleQueueIndex[i] = i;
    }
    // Construct the set of exposed track groups.
    TrackGroup[] trackGroups = new TrackGroup[extractorTrackCount];
    for (int i = 0; i < extractorTrackCount; i++) {
        Format sampleFormat = Assertions.checkStateNotNull(sampleQueues[i].getUpstreamFormat());
        if (i == primaryExtractorTrackIndex) {
            Format[] formats = new Format[chunkSourceTrackCount];
            for (int j = 0; j < chunkSourceTrackCount; j++) {
                Format playlistFormat = chunkSourceTrackGroup.getFormat(j);
                if (primaryExtractorTrackType == C.TRACK_TYPE_AUDIO && muxedAudioFormat != null) {
                    playlistFormat = playlistFormat.withManifestFormatInfo(muxedAudioFormat);
                }
                // If there's only a single variant (chunkSourceTrackCount == 1) then we can safely
                // retain all fields from sampleFormat. Else we need to use deriveFormat to retain only
                // the fields that will be the same for all variants.
                formats[j] = chunkSourceTrackCount == 1 ? sampleFormat.withManifestFormatInfo(playlistFormat) : deriveFormat(playlistFormat, sampleFormat, /* propagateBitrates= */
                true);
            }
            trackGroups[i] = new TrackGroup(uid, formats);
            primaryTrackGroupIndex = i;
        } else {
            @Nullable Format playlistFormat = primaryExtractorTrackType == C.TRACK_TYPE_VIDEO && MimeTypes.isAudio(sampleFormat.sampleMimeType) ? muxedAudioFormat : null;
            String muxedTrackGroupId = uid + ":muxed:" + (i < primaryExtractorTrackIndex ? i : i - 1);
            trackGroups[i] = new TrackGroup(muxedTrackGroupId, deriveFormat(playlistFormat, sampleFormat, /* propagateBitrates= */
            false));
        }
    }
    this.trackGroups = createTrackGroupArrayWithDrmInfo(trackGroups);
    Assertions.checkState(optionalTrackGroups == null);
    optionalTrackGroups = Collections.emptySet();
}
Also used : Format(com.google.android.exoplayer2.Format) TrackGroup(com.google.android.exoplayer2.source.TrackGroup) Nullable(androidx.annotation.Nullable) EnsuresNonNull(org.checkerframework.checker.nullness.qual.EnsuresNonNull)

Aggregations

EnsuresNonNull (org.checkerframework.checker.nullness.qual.EnsuresNonNull)6 Nullable (androidx.annotation.Nullable)3 RequiresNonNull (org.checkerframework.checker.nullness.qual.RequiresNonNull)3 Format (com.google.android.exoplayer2.Format)2 Handler (android.os.Handler)1 OutputFrameHolder (com.google.android.exoplayer2.ext.flac.FlacBinarySearchSeeker.OutputFrameHolder)1 DefaultExtractorInput (com.google.android.exoplayer2.extractor.DefaultExtractorInput)1 FlacStreamMetadata (com.google.android.exoplayer2.extractor.FlacStreamMetadata)1 Metadata (com.google.android.exoplayer2.metadata.Metadata)1 SampleQueue (com.google.android.exoplayer2.source.SampleQueue)1 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)1 IOException (java.io.IOException)1 InterruptedIOException (java.io.InterruptedIOException)1 ByteBuffer (java.nio.ByteBuffer)1