Search in sources :

Example 46 with Assertions.checkNotNull

use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.

the class HlsMediaPeriod method getStreamKeys.

// TODO: When the multivariant playlist does not de-duplicate variants by URL and allows
// Renditions with null URLs, this method must be updated to calculate stream keys that are
// compatible with those that may already be persisted for offline.
@Override
public List<StreamKey> getStreamKeys(List<ExoTrackSelection> trackSelections) {
    // See HlsMultivariantPlaylist.copy for interpretation of StreamKeys.
    HlsMultivariantPlaylist multivariantPlaylist = Assertions.checkNotNull(playlistTracker.getMultivariantPlaylist());
    boolean hasVariants = !multivariantPlaylist.variants.isEmpty();
    int audioWrapperOffset = hasVariants ? 1 : 0;
    // Subtitle sample stream wrappers are held last.
    int subtitleWrapperOffset = sampleStreamWrappers.length - multivariantPlaylist.subtitles.size();
    TrackGroupArray mainWrapperTrackGroups;
    int mainWrapperPrimaryGroupIndex;
    int[] mainWrapperVariantIndices;
    if (hasVariants) {
        HlsSampleStreamWrapper mainWrapper = sampleStreamWrappers[0];
        mainWrapperVariantIndices = manifestUrlIndicesPerWrapper[0];
        mainWrapperTrackGroups = mainWrapper.getTrackGroups();
        mainWrapperPrimaryGroupIndex = mainWrapper.getPrimaryTrackGroupIndex();
    } else {
        mainWrapperVariantIndices = new int[0];
        mainWrapperTrackGroups = TrackGroupArray.EMPTY;
        mainWrapperPrimaryGroupIndex = 0;
    }
    List<StreamKey> streamKeys = new ArrayList<>();
    boolean needsPrimaryTrackGroupSelection = false;
    boolean hasPrimaryTrackGroupSelection = false;
    for (ExoTrackSelection trackSelection : trackSelections) {
        TrackGroup trackSelectionGroup = trackSelection.getTrackGroup();
        int mainWrapperTrackGroupIndex = mainWrapperTrackGroups.indexOf(trackSelectionGroup);
        if (mainWrapperTrackGroupIndex != C.INDEX_UNSET) {
            if (mainWrapperTrackGroupIndex == mainWrapperPrimaryGroupIndex) {
                // Primary group in main wrapper.
                hasPrimaryTrackGroupSelection = true;
                for (int i = 0; i < trackSelection.length(); i++) {
                    int variantIndex = mainWrapperVariantIndices[trackSelection.getIndexInTrackGroup(i)];
                    streamKeys.add(new StreamKey(HlsMultivariantPlaylist.GROUP_INDEX_VARIANT, variantIndex));
                }
            } else {
                // Embedded group in main wrapper.
                needsPrimaryTrackGroupSelection = true;
            }
        } else {
            // Audio or subtitle group.
            for (int i = audioWrapperOffset; i < sampleStreamWrappers.length; i++) {
                TrackGroupArray wrapperTrackGroups = sampleStreamWrappers[i].getTrackGroups();
                int selectedTrackGroupIndex = wrapperTrackGroups.indexOf(trackSelectionGroup);
                if (selectedTrackGroupIndex != C.INDEX_UNSET) {
                    int groupIndexType = i < subtitleWrapperOffset ? HlsMultivariantPlaylist.GROUP_INDEX_AUDIO : HlsMultivariantPlaylist.GROUP_INDEX_SUBTITLE;
                    int[] selectedWrapperUrlIndices = manifestUrlIndicesPerWrapper[i];
                    for (int trackIndex = 0; trackIndex < trackSelection.length(); trackIndex++) {
                        int renditionIndex = selectedWrapperUrlIndices[trackSelection.getIndexInTrackGroup(trackIndex)];
                        streamKeys.add(new StreamKey(groupIndexType, renditionIndex));
                    }
                    break;
                }
            }
        }
    }
    if (needsPrimaryTrackGroupSelection && !hasPrimaryTrackGroupSelection) {
        // A track selection includes a variant-embedded track, but no variant is added yet. We use
        // the valid variant with the lowest bitrate to reduce overhead.
        int lowestBitrateIndex = mainWrapperVariantIndices[0];
        int lowestBitrate = multivariantPlaylist.variants.get(mainWrapperVariantIndices[0]).format.bitrate;
        for (int i = 1; i < mainWrapperVariantIndices.length; i++) {
            int variantBitrate = multivariantPlaylist.variants.get(mainWrapperVariantIndices[i]).format.bitrate;
            if (variantBitrate < lowestBitrate) {
                lowestBitrate = variantBitrate;
                lowestBitrateIndex = mainWrapperVariantIndices[i];
            }
        }
        streamKeys.add(new StreamKey(HlsMultivariantPlaylist.GROUP_INDEX_VARIANT, lowestBitrateIndex));
    }
    return streamKeys;
}
Also used : ExoTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection) TrackGroup(com.google.android.exoplayer2.source.TrackGroup) TrackGroupArray(com.google.android.exoplayer2.source.TrackGroupArray) ArrayList(java.util.ArrayList) HlsMultivariantPlaylist(com.google.android.exoplayer2.source.hls.playlist.HlsMultivariantPlaylist) StreamKey(com.google.android.exoplayer2.offline.StreamKey)

Example 47 with Assertions.checkNotNull

use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.

the class WebvttExtractor method processSample.

@RequiresNonNull("output")
private void processSample() throws ParserException {
    ParsableByteArray webvttData = new ParsableByteArray(sampleData);
    // Validate the first line of the header.
    WebvttParserUtil.validateWebvttHeaderLine(webvttData);
    // Defaults to use if the header doesn't contain an X-TIMESTAMP-MAP header.
    long vttTimestampUs = 0;
    long tsTimestampUs = 0;
    // Parse the remainder of the header looking for X-TIMESTAMP-MAP.
    for (String line = webvttData.readLine(); !TextUtils.isEmpty(line); line = webvttData.readLine()) {
        if (line.startsWith("X-TIMESTAMP-MAP")) {
            Matcher localTimestampMatcher = LOCAL_TIMESTAMP.matcher(line);
            if (!localTimestampMatcher.find()) {
                throw ParserException.createForMalformedContainer("X-TIMESTAMP-MAP doesn't contain local timestamp: " + line, /* cause= */
                null);
            }
            Matcher mediaTimestampMatcher = MEDIA_TIMESTAMP.matcher(line);
            if (!mediaTimestampMatcher.find()) {
                throw ParserException.createForMalformedContainer("X-TIMESTAMP-MAP doesn't contain media timestamp: " + line, /* cause= */
                null);
            }
            vttTimestampUs = WebvttParserUtil.parseTimestampUs(Assertions.checkNotNull(localTimestampMatcher.group(1)));
            tsTimestampUs = TimestampAdjuster.ptsToUs(Long.parseLong(Assertions.checkNotNull(mediaTimestampMatcher.group(1))));
        }
    }
    // Find the first cue header and parse the start time.
    Matcher cueHeaderMatcher = WebvttParserUtil.findNextCueHeader(webvttData);
    if (cueHeaderMatcher == null) {
        // No cues found. Don't output a sample, but still output a corresponding track.
        buildTrackOutput(0);
        return;
    }
    long firstCueTimeUs = WebvttParserUtil.parseTimestampUs(Assertions.checkNotNull(cueHeaderMatcher.group(1)));
    long sampleTimeUs = timestampAdjuster.adjustTsTimestamp(TimestampAdjuster.usToWrappedPts(firstCueTimeUs + tsTimestampUs - vttTimestampUs));
    long subsampleOffsetUs = sampleTimeUs - firstCueTimeUs;
    // Output the track.
    TrackOutput trackOutput = buildTrackOutput(subsampleOffsetUs);
    // Output the sample.
    sampleDataWrapper.reset(sampleData, sampleSize);
    trackOutput.sampleData(sampleDataWrapper, sampleSize);
    trackOutput.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) Matcher(java.util.regex.Matcher) TrackOutput(com.google.android.exoplayer2.extractor.TrackOutput) RequiresNonNull(org.checkerframework.checker.nullness.qual.RequiresNonNull)

Example 48 with Assertions.checkNotNull

use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.

the class DecoderVideoRenderer method onInputFormatChanged.

/**
 * Called when a new format is read from the upstream source.
 *
 * @param formatHolder A {@link FormatHolder} that holds the new {@link Format}.
 * @throws ExoPlaybackException If an error occurs (re-)initializing the decoder.
 */
@CallSuper
protected void onInputFormatChanged(FormatHolder formatHolder) throws ExoPlaybackException {
    waitingForFirstSampleInFormat = true;
    Format newFormat = Assertions.checkNotNull(formatHolder.format);
    setSourceDrmSession(formatHolder.drmSession);
    Format oldFormat = inputFormat;
    inputFormat = newFormat;
    if (decoder == null) {
        maybeInitDecoder();
        eventDispatcher.inputFormatChanged(inputFormat, /* decoderReuseEvaluation= */
        null);
        return;
    }
    DecoderReuseEvaluation evaluation;
    if (sourceDrmSession != decoderDrmSession) {
        evaluation = new DecoderReuseEvaluation(decoder.getName(), oldFormat, newFormat, REUSE_RESULT_NO, DISCARD_REASON_DRM_SESSION_CHANGED);
    } else {
        evaluation = canReuseDecoder(decoder.getName(), oldFormat, newFormat);
    }
    if (evaluation.result == REUSE_RESULT_NO) {
        if (decoderReceivedBuffers) {
            // Signal end of stream and wait for any final output buffers before re-initialization.
            decoderReinitializationState = REINITIALIZATION_STATE_SIGNAL_END_OF_STREAM;
        } else {
            // There aren't any final output buffers, so release the decoder immediately.
            releaseDecoder();
            maybeInitDecoder();
        }
    }
    eventDispatcher.inputFormatChanged(inputFormat, evaluation);
}
Also used : Format(com.google.android.exoplayer2.Format) DecoderReuseEvaluation(com.google.android.exoplayer2.decoder.DecoderReuseEvaluation) CallSuper(androidx.annotation.CallSuper)

Example 49 with Assertions.checkNotNull

use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.

the class TtmlDecoderTest method getOnlyCueTextAtTimeUs.

private static Spanned getOnlyCueTextAtTimeUs(Subtitle subtitle, long timeUs) {
    Cue cue = getOnlyCueAtTimeUs(subtitle, timeUs);
    assertThat(cue.text).isInstanceOf(Spanned.class);
    return (Spanned) Assertions.checkNotNull(cue.text);
}
Also used : Cue(com.google.android.exoplayer2.text.Cue) Spanned(android.text.Spanned)

Example 50 with Assertions.checkNotNull

use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.

the class RepeatedTranscodeTransformationTest method repeatedTranscodeNoVideo_givesConsistentLengthOutput.

@Test
public void repeatedTranscodeNoVideo_givesConsistentLengthOutput() throws Exception {
    Context context = ApplicationProvider.getApplicationContext();
    Transformer transformer = new Transformer.Builder(context).setRemoveVideo(true).setTransformationRequest(new TransformationRequest.Builder().setAudioMimeType(MimeTypes.AUDIO_AMR_NB).build()).build();
    Set<Long> differentOutputSizesBytes = new HashSet<>();
    for (int i = 0; i < TRANSCODE_COUNT; i++) {
        // Use a long video in case an error occurs a while after the start of the video.
        AndroidTestUtil.TransformationResult result = runTransformer(context, /* testId= */
        "repeatedTranscodeNoVideo_givesConsistentLengthOutput_" + i, transformer, AndroidTestUtil.REMOTE_MP4_10_SECONDS_URI_STRING, /* timeoutSeconds= */
        120);
        differentOutputSizesBytes.add(Assertions.checkNotNull(result.fileSizeBytes));
    }
    assertWithMessage("Different transcoding output sizes detected. Sizes: " + differentOutputSizesBytes).that(differentOutputSizesBytes.size()).isEqualTo(1);
}
Also used : Context(android.content.Context) AndroidTestUtil(com.google.android.exoplayer2.transformer.AndroidTestUtil) Transformer(com.google.android.exoplayer2.transformer.Transformer) AndroidTestUtil.runTransformer(com.google.android.exoplayer2.transformer.AndroidTestUtil.runTransformer) HashSet(java.util.HashSet) Test(org.junit.Test)

Aggregations

Nullable (androidx.annotation.Nullable)28 Format (com.google.android.exoplayer2.Format)10 ArrayList (java.util.ArrayList)9 MediaItem (com.google.android.exoplayer2.MediaItem)8 DataSpec (com.google.android.exoplayer2.upstream.DataSpec)5 Matcher (java.util.regex.Matcher)5 SuppressLint (android.annotation.SuppressLint)4 Context (android.content.Context)4 Uri (android.net.Uri)4 MediaSource (com.google.android.exoplayer2.source.MediaSource)4 DataSource (com.google.android.exoplayer2.upstream.DataSource)4 StatsDataSource (com.google.android.exoplayer2.upstream.StatsDataSource)4 Activity (android.app.Activity)3 Intent (android.content.Intent)3 SQLException (android.database.SQLException)3 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)3 Bundle (android.os.Bundle)3 CallbackMediaItem (androidx.media2.common.CallbackMediaItem)3 C (com.google.android.exoplayer2.C)3 ExoPlayer (com.google.android.exoplayer2.ExoPlayer)3