Search in sources :

Example 6 with DataSpec

use of com.google.android.exoplayer2.upstream.DataSpec in project ExoPlayer by google.

the class DefaultExtractorInputTest method buildLargeDataSource.

private static FakeDataSource buildLargeDataSource() throws Exception {
    FakeDataSource.Builder builder = new FakeDataSource.Builder();
    builder.appendReadData(new byte[LARGE_TEST_DATA_LENGTH]);
    FakeDataSource testDataSource = builder.build();
    testDataSource.open(new DataSpec(Uri.parse(TEST_URI)));
    return testDataSource;
}
Also used : FakeDataSource(com.google.android.exoplayer2.testutil.FakeDataSource) DataSpec(com.google.android.exoplayer2.upstream.DataSpec)

Example 7 with DataSpec

use of com.google.android.exoplayer2.upstream.DataSpec in project ExoPlayer by google.

the class DefaultExtractorInputTest method buildDataSource.

private static FakeDataSource buildDataSource() throws Exception {
    FakeDataSource.Builder builder = new FakeDataSource.Builder();
    builder.appendReadData(Arrays.copyOfRange(TEST_DATA, 0, 3));
    builder.appendReadData(Arrays.copyOfRange(TEST_DATA, 3, 6));
    builder.appendReadData(Arrays.copyOfRange(TEST_DATA, 6, 9));
    FakeDataSource testDataSource = builder.build();
    testDataSource.open(new DataSpec(Uri.parse(TEST_URI)));
    return testDataSource;
}
Also used : FakeDataSource(com.google.android.exoplayer2.testutil.FakeDataSource) DataSpec(com.google.android.exoplayer2.upstream.DataSpec)

Example 8 with DataSpec

use of com.google.android.exoplayer2.upstream.DataSpec in project ExoPlayer by google.

the class DefaultExtractorInputTest method testSkipFullyLarge.

public void testSkipFullyLarge() throws Exception {
    // Tests skipping an amount of data that's larger than any internal scratch space.
    int largeSkipSize = 1024 * 1024;
    FakeDataSource.Builder builder = new FakeDataSource.Builder();
    builder.appendReadData(new byte[largeSkipSize]);
    FakeDataSource testDataSource = builder.build();
    testDataSource.open(new DataSpec(Uri.parse(TEST_URI)));
    DefaultExtractorInput input = new DefaultExtractorInput(testDataSource, 0, C.LENGTH_UNSET);
    input.skipFully(largeSkipSize);
    assertEquals(largeSkipSize, input.getPosition());
    // Check that we fail with EOFException we skip again.
    try {
        input.skipFully(1);
        fail();
    } catch (EOFException e) {
    // Expected.
    }
}
Also used : FakeDataSource(com.google.android.exoplayer2.testutil.FakeDataSource) EOFException(java.io.EOFException) DataSpec(com.google.android.exoplayer2.upstream.DataSpec)

Example 9 with DataSpec

use of com.google.android.exoplayer2.upstream.DataSpec in project ExoPlayer by google.

the class Aes128DataSource method open.

@Override
public long open(DataSpec dataSpec) throws IOException {
    Cipher cipher;
    try {
        cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        throw new RuntimeException(e);
    }
    Key cipherKey = new SecretKeySpec(encryptionKey, "AES");
    AlgorithmParameterSpec cipherIV = new IvParameterSpec(encryptionIv);
    try {
        cipher.init(Cipher.DECRYPT_MODE, cipherKey, cipherIV);
    } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
        throw new RuntimeException(e);
    }
    cipherInputStream = new CipherInputStream(new DataSourceInputStream(upstream, dataSpec), cipher);
    return C.LENGTH_UNSET;
}
Also used : InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) CipherInputStream(javax.crypto.CipherInputStream) NoSuchPaddingException(javax.crypto.NoSuchPaddingException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) InvalidKeyException(java.security.InvalidKeyException) SecretKeySpec(javax.crypto.spec.SecretKeySpec) IvParameterSpec(javax.crypto.spec.IvParameterSpec) Cipher(javax.crypto.Cipher) AlgorithmParameterSpec(java.security.spec.AlgorithmParameterSpec) Key(java.security.Key) DataSourceInputStream(com.google.android.exoplayer2.upstream.DataSourceInputStream)

Example 10 with DataSpec

use of com.google.android.exoplayer2.upstream.DataSpec in project ExoPlayer by google.

the class HlsChunkSource method getNextChunk.

/**
   * Returns the next chunk to load.
   * <p>
   * If a chunk is available then {@link HlsChunkHolder#chunk} is set. If the end of the stream has
   * been reached then {@link HlsChunkHolder#endOfStream} is set. If a chunk is not available but
   * the end of the stream has not been reached, {@link HlsChunkHolder#playlist} is set to
   * contain the {@link HlsUrl} that refers to the playlist that needs refreshing.
   *
   * @param previous The most recently loaded media chunk.
   * @param playbackPositionUs The current playback position. If {@code previous} is null then this
   *     parameter is the position from which playback is expected to start (or restart) and hence
   *     should be interpreted as a seek position.
   * @param out A holder to populate.
   */
public void getNextChunk(HlsMediaChunk previous, long playbackPositionUs, HlsChunkHolder out) {
    int oldVariantIndex = previous == null ? C.INDEX_UNSET : trackGroup.indexOf(previous.trackFormat);
    // Use start time of the previous chunk rather than its end time because switching format will
    // require downloading overlapping segments.
    long bufferedDurationUs = previous == null ? 0 : Math.max(0, previous.startTimeUs - playbackPositionUs);
    // Select the variant.
    trackSelection.updateSelectedTrack(bufferedDurationUs);
    int selectedVariantIndex = trackSelection.getSelectedIndexInTrackGroup();
    boolean switchingVariant = oldVariantIndex != selectedVariantIndex;
    HlsUrl selectedUrl = variants[selectedVariantIndex];
    if (!playlistTracker.isSnapshotValid(selectedUrl)) {
        out.playlist = selectedUrl;
        // Retry when playlist is refreshed.
        return;
    }
    HlsMediaPlaylist mediaPlaylist = playlistTracker.getPlaylistSnapshot(selectedUrl);
    // Select the chunk.
    int chunkMediaSequence;
    if (previous == null || switchingVariant) {
        long targetPositionUs = previous == null ? playbackPositionUs : previous.startTimeUs;
        if (!mediaPlaylist.hasEndTag && targetPositionUs > mediaPlaylist.getEndTimeUs()) {
            // If the playlist is too old to contain the chunk, we need to refresh it.
            chunkMediaSequence = mediaPlaylist.mediaSequence + mediaPlaylist.segments.size();
        } else {
            chunkMediaSequence = Util.binarySearchFloor(mediaPlaylist.segments, targetPositionUs - mediaPlaylist.startTimeUs, true, !playlistTracker.isLive() || previous == null) + mediaPlaylist.mediaSequence;
            if (chunkMediaSequence < mediaPlaylist.mediaSequence && previous != null) {
                // We try getting the next chunk without adapting in case that's the reason for falling
                // behind the live window.
                selectedVariantIndex = oldVariantIndex;
                selectedUrl = variants[selectedVariantIndex];
                mediaPlaylist = playlistTracker.getPlaylistSnapshot(selectedUrl);
                chunkMediaSequence = previous.getNextChunkIndex();
            }
        }
    } else {
        chunkMediaSequence = previous.getNextChunkIndex();
    }
    if (chunkMediaSequence < mediaPlaylist.mediaSequence) {
        fatalError = new BehindLiveWindowException();
        return;
    }
    int chunkIndex = chunkMediaSequence - mediaPlaylist.mediaSequence;
    if (chunkIndex >= mediaPlaylist.segments.size()) {
        if (mediaPlaylist.hasEndTag) {
            out.endOfStream = true;
        } else /* Live */
        {
            out.playlist = selectedUrl;
        }
        return;
    }
    // Handle encryption.
    HlsMediaPlaylist.Segment segment = mediaPlaylist.segments.get(chunkIndex);
    // Check if encryption is specified.
    if (segment.isEncrypted) {
        Uri keyUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, segment.encryptionKeyUri);
        if (!keyUri.equals(encryptionKeyUri)) {
            // Encryption is specified and the key has changed.
            out.chunk = newEncryptionKeyChunk(keyUri, segment.encryptionIV, selectedVariantIndex, trackSelection.getSelectionReason(), trackSelection.getSelectionData());
            return;
        }
        if (!Util.areEqual(segment.encryptionIV, encryptionIvString)) {
            setEncryptionData(keyUri, segment.encryptionIV, encryptionKey);
        }
    } else {
        clearEncryptionData();
    }
    DataSpec initDataSpec = null;
    Segment initSegment = mediaPlaylist.initializationSegment;
    if (initSegment != null) {
        Uri initSegmentUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, initSegment.url);
        initDataSpec = new DataSpec(initSegmentUri, initSegment.byterangeOffset, initSegment.byterangeLength, null);
    }
    // Compute start time of the next chunk.
    long startTimeUs = mediaPlaylist.startTimeUs + segment.relativeStartTimeUs;
    int discontinuitySequence = mediaPlaylist.discontinuitySequence + segment.relativeDiscontinuitySequence;
    TimestampAdjuster timestampAdjuster = timestampAdjusterProvider.getAdjuster(discontinuitySequence);
    // Configure the data source and spec for the chunk.
    Uri chunkUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, segment.url);
    DataSpec dataSpec = new DataSpec(chunkUri, segment.byterangeOffset, segment.byterangeLength, null);
    out.chunk = new HlsMediaChunk(mediaDataSource, dataSpec, initDataSpec, selectedUrl, muxedCaptionFormats, trackSelection.getSelectionReason(), trackSelection.getSelectionData(), startTimeUs, startTimeUs + segment.durationUs, chunkMediaSequence, discontinuitySequence, isTimestampMaster, timestampAdjuster, previous, encryptionKey, encryptionIv);
}
Also used : Segment(com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment) HlsUrl(com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.HlsUrl) BehindLiveWindowException(com.google.android.exoplayer2.source.BehindLiveWindowException) DataSpec(com.google.android.exoplayer2.upstream.DataSpec) HlsMediaPlaylist(com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist) TimestampAdjuster(com.google.android.exoplayer2.util.TimestampAdjuster) Uri(android.net.Uri) Segment(com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment)

Aggregations

DataSpec (com.google.android.exoplayer2.upstream.DataSpec)24 DefaultExtractorInput (com.google.android.exoplayer2.extractor.DefaultExtractorInput)5 ExtractorInput (com.google.android.exoplayer2.extractor.ExtractorInput)5 Test (org.junit.Test)5 FakeDataSource (com.google.android.exoplayer2.testutil.FakeDataSource)4 IOException (java.io.IOException)4 DataSourceException (com.google.android.exoplayer2.upstream.DataSourceException)3 DataSourceInputStream (com.google.android.exoplayer2.upstream.DataSourceInputStream)3 Uri (android.net.Uri)2 Extractor (com.google.android.exoplayer2.extractor.Extractor)2 ContainerMediaChunk (com.google.android.exoplayer2.source.chunk.ContainerMediaChunk)2 InitializationChunk (com.google.android.exoplayer2.source.chunk.InitializationChunk)2 RangedUri (com.google.android.exoplayer2.source.dash.manifest.RangedUri)2 InterruptedIOException (java.io.InterruptedIOException)2 TrackOutput (com.google.android.exoplayer2.extractor.TrackOutput)1 BehindLiveWindowException (com.google.android.exoplayer2.source.BehindLiveWindowException)1 SingleSampleMediaChunk (com.google.android.exoplayer2.source.chunk.SingleSampleMediaChunk)1 DashManifestParser (com.google.android.exoplayer2.source.dash.manifest.DashManifestParser)1 Representation (com.google.android.exoplayer2.source.dash.manifest.Representation)1 HlsUrl (com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.HlsUrl)1