Search in sources :

Example 31 with DecoderInputBuffer

use of androidx.media3.decoder.DecoderInputBuffer in project media by androidx.

the class EventSampleStreamTest method skipDataThenUpdateStreamContinueToReadDoNotSkippedMoreThanAvailable.

/**
 * Tests that {@link EventSampleStream#skipData(long)} will only skip to the point right after it
 * last event. A following {@link EventSampleStream#updateEventStream(EventStream, boolean)} will
 * update the underlying event stream and keep the timestamp the stream has skipped to, so the
 * next {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, int)} call will return
 * sample data from the skipped position.
 */
@Test
public void skipDataThenUpdateStreamContinueToReadDoNotSkippedMoreThanAvailable() {
    long presentationTimeUs1 = 1000000;
    long presentationTimeUs2 = 2000000;
    long presentationTimeUs3 = 3000000;
    EventMessage eventMessage1 = newEventMessageWithId(1);
    EventMessage eventMessage2 = newEventMessageWithId(2);
    EventMessage eventMessage3 = newEventMessageWithId(3);
    EventStream eventStream1 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, new long[] { presentationTimeUs1 }, new EventMessage[] { eventMessage1 });
    EventStream eventStream2 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, new long[] { presentationTimeUs1, presentationTimeUs2, presentationTimeUs3 }, new EventMessage[] { eventMessage1, eventMessage2, eventMessage3 });
    EventSampleStream sampleStream = new EventSampleStream(eventStream1, FORMAT, true);
    // first read - read format
    readData(sampleStream);
    // even though the skip call is to 2000001, since eventStream1 only contains sample until
    // 1000000, it will only skip to 1000001.
    sampleStream.skipData(presentationTimeUs2 + 1);
    sampleStream.updateEventStream(eventStream2, true);
    int result = readData(sampleStream);
    assertThat(result).isEqualTo(C.RESULT_BUFFER_READ);
    assertThat(inputBuffer.data.array()).isEqualTo(getEncodedMessage(eventMessage2));
}
Also used : EventMessage(androidx.media3.extractor.metadata.emsg.EventMessage) EventStream(androidx.media3.exoplayer.dash.manifest.EventStream) Test(org.junit.Test)

Example 32 with DecoderInputBuffer

use of androidx.media3.decoder.DecoderInputBuffer in project media by androidx.

the class SampleDataQueue method readEncryptionData.

/**
 * Reads encryption data for the sample described by {@code extrasHolder}.
 *
 * <p>The encryption data is written into {@link DecoderInputBuffer#cryptoInfo}, and {@link
 * SampleExtrasHolder#size} is adjusted to subtract the number of bytes that were read. The same
 * value is added to {@link SampleExtrasHolder#offset}.
 *
 * @param allocationNode The first {@link AllocationNode} containing data yet to be read.
 * @param buffer The buffer into which the encryption data should be written.
 * @param extrasHolder The extras holder whose offset should be read and subsequently adjusted.
 * @param scratch A scratch {@link ParsableByteArray}.
 * @return The first {@link AllocationNode} that contains unread bytes after this method returns.
 */
private static AllocationNode readEncryptionData(AllocationNode allocationNode, DecoderInputBuffer buffer, SampleExtrasHolder extrasHolder, ParsableByteArray scratch) {
    long offset = extrasHolder.offset;
    // Read the signal byte.
    scratch.reset(1);
    allocationNode = readData(allocationNode, offset, scratch.getData(), 1);
    offset++;
    byte signalByte = scratch.getData()[0];
    boolean subsampleEncryption = (signalByte & 0x80) != 0;
    int ivSize = signalByte & 0x7F;
    // Read the initialization vector.
    CryptoInfo cryptoInfo = buffer.cryptoInfo;
    if (cryptoInfo.iv == null) {
        cryptoInfo.iv = new byte[16];
    } else {
        // Zero out cryptoInfo.iv so that if ivSize < 16, the remaining bytes are correctly set to 0.
        Arrays.fill(cryptoInfo.iv, (byte) 0);
    }
    allocationNode = readData(allocationNode, offset, cryptoInfo.iv, ivSize);
    offset += ivSize;
    // Read the subsample count, if present.
    int subsampleCount;
    if (subsampleEncryption) {
        scratch.reset(2);
        allocationNode = readData(allocationNode, offset, scratch.getData(), 2);
        offset += 2;
        subsampleCount = scratch.readUnsignedShort();
    } else {
        subsampleCount = 1;
    }
    // Write the clear and encrypted subsample sizes.
    @Nullable int[] clearDataSizes = cryptoInfo.numBytesOfClearData;
    if (clearDataSizes == null || clearDataSizes.length < subsampleCount) {
        clearDataSizes = new int[subsampleCount];
    }
    @Nullable int[] encryptedDataSizes = cryptoInfo.numBytesOfEncryptedData;
    if (encryptedDataSizes == null || encryptedDataSizes.length < subsampleCount) {
        encryptedDataSizes = new int[subsampleCount];
    }
    if (subsampleEncryption) {
        int subsampleDataLength = 6 * subsampleCount;
        scratch.reset(subsampleDataLength);
        allocationNode = readData(allocationNode, offset, scratch.getData(), subsampleDataLength);
        offset += subsampleDataLength;
        scratch.setPosition(0);
        for (int i = 0; i < subsampleCount; i++) {
            clearDataSizes[i] = scratch.readUnsignedShort();
            encryptedDataSizes[i] = scratch.readUnsignedIntToInt();
        }
    } else {
        clearDataSizes[0] = 0;
        encryptedDataSizes[0] = extrasHolder.size - (int) (offset - extrasHolder.offset);
    }
    // Populate the cryptoInfo.
    CryptoData cryptoData = Util.castNonNull(extrasHolder.cryptoData);
    cryptoInfo.set(subsampleCount, clearDataSizes, encryptedDataSizes, cryptoData.encryptionKey, cryptoInfo.iv, cryptoData.cryptoMode, cryptoData.encryptedBlocks, cryptoData.clearBlocks);
    // Adjust the offset and size to take into account the bytes read.
    int bytesRead = (int) (offset - extrasHolder.offset);
    extrasHolder.offset += bytesRead;
    extrasHolder.size -= bytesRead;
    return allocationNode;
}
Also used : CryptoData(androidx.media3.extractor.TrackOutput.CryptoData) CryptoInfo(androidx.media3.decoder.CryptoInfo) Nullable(androidx.annotation.Nullable)

Example 33 with DecoderInputBuffer

use of androidx.media3.decoder.DecoderInputBuffer in project media by androidx.

the class SampleQueue method peekSampleMetadata.

// See comments in setUpstreamFormat
@SuppressWarnings("ReferenceEquality")
private synchronized int peekSampleMetadata(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired, boolean loadingFinished, SampleExtrasHolder extrasHolder) {
    buffer.waitingForKeys = false;
    if (!hasNextSample()) {
        if (loadingFinished || isLastSampleQueued) {
            buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
            return C.RESULT_BUFFER_READ;
        } else if (upstreamFormat != null && (formatRequired || upstreamFormat != downstreamFormat)) {
            onFormatResult(Assertions.checkNotNull(upstreamFormat), formatHolder);
            return C.RESULT_FORMAT_READ;
        } else {
            return C.RESULT_NOTHING_READ;
        }
    }
    Format format = sharedSampleMetadata.get(getReadIndex()).format;
    if (formatRequired || format != downstreamFormat) {
        onFormatResult(format, formatHolder);
        return C.RESULT_FORMAT_READ;
    }
    int relativeReadIndex = getRelativeIndex(readPosition);
    if (!mayReadSample(relativeReadIndex)) {
        buffer.waitingForKeys = true;
        return C.RESULT_NOTHING_READ;
    }
    buffer.setFlags(flags[relativeReadIndex]);
    buffer.timeUs = timesUs[relativeReadIndex];
    if (buffer.timeUs < startTimeUs) {
        buffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
    }
    extrasHolder.size = sizes[relativeReadIndex];
    extrasHolder.offset = offsets[relativeReadIndex];
    extrasHolder.cryptoData = cryptoDatas[relativeReadIndex];
    return C.RESULT_BUFFER_READ;
}
Also used : Format(androidx.media3.common.Format)

Aggregations

Test (org.junit.Test)13 Nullable (androidx.annotation.Nullable)10 EventStream (androidx.media3.exoplayer.dash.manifest.EventStream)9 DecoderInputBuffer (androidx.media3.decoder.DecoderInputBuffer)8 EventMessage (androidx.media3.extractor.metadata.emsg.EventMessage)8 DecoderInputBuffer (com.google.android.exoplayer2.decoder.DecoderInputBuffer)8 Format (androidx.media3.common.Format)6 Before (org.junit.Before)6 FormatHolder (androidx.media3.exoplayer.FormatHolder)5 RequiresNonNull (org.checkerframework.checker.nullness.qual.RequiresNonNull)4 CryptoInfo (androidx.media3.decoder.CryptoInfo)3 ReadDataResult (androidx.media3.exoplayer.source.SampleStream.ReadDataResult)3 FormatHolder (com.google.android.exoplayer2.FormatHolder)3 ByteBuffer (java.nio.ByteBuffer)3 SurfaceTexture (android.graphics.SurfaceTexture)2 Handler (android.os.Handler)2 Surface (android.view.Surface)2 CryptoException (androidx.media3.decoder.CryptoException)2 ExoTrackSelection (androidx.media3.exoplayer.trackselection.ExoTrackSelection)2 FixedTrackSelection (androidx.media3.exoplayer.trackselection.FixedTrackSelection)2