Search in sources :

Example 6 with FormatHolder

use of com.google.android.exoplayer2.FormatHolder in project ExoPlayer by google.

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(com.google.android.exoplayer2.Format)

Example 7 with FormatHolder

use of com.google.android.exoplayer2.FormatHolder in project ExoPlayer by google.

the class SampleQueue method onFormatResult.

/**
 * Sets the downstream format, performs DRM resource management, and populates the {@code
 * outputFormatHolder}.
 *
 * @param newFormat The new downstream format.
 * @param outputFormatHolder The output {@link FormatHolder}.
 */
private void onFormatResult(Format newFormat, FormatHolder outputFormatHolder) {
    boolean isFirstFormat = downstreamFormat == null;
    @Nullable DrmInitData oldDrmInitData = isFirstFormat ? null : downstreamFormat.drmInitData;
    downstreamFormat = newFormat;
    @Nullable DrmInitData newDrmInitData = newFormat.drmInitData;
    outputFormatHolder.format = drmSessionManager != null ? newFormat.copyWithCryptoType(drmSessionManager.getCryptoType(newFormat)) : newFormat;
    outputFormatHolder.drmSession = currentDrmSession;
    if (drmSessionManager == null) {
        // This sample queue is not expected to handle DRM. Nothing to do.
        return;
    }
    if (!isFirstFormat && Util.areEqual(oldDrmInitData, newDrmInitData)) {
        // Nothing to do.
        return;
    }
    // Ensure we acquire the new session before releasing the previous one in case the same session
    // is being used for both DrmInitData.
    @Nullable DrmSession previousSession = currentDrmSession;
    currentDrmSession = drmSessionManager.acquireSession(drmEventDispatcher, newFormat);
    outputFormatHolder.drmSession = currentDrmSession;
    if (previousSession != null) {
        previousSession.release(drmEventDispatcher);
    }
}
Also used : DrmInitData(com.google.android.exoplayer2.drm.DrmInitData) DrmSession(com.google.android.exoplayer2.drm.DrmSession) Nullable(androidx.annotation.Nullable)

Example 8 with FormatHolder

use of com.google.android.exoplayer2.FormatHolder in project ExoPlayer by google.

the class TextRenderer method render.

@Override
public void render(long positionUs, long elapsedRealtimeUs) {
    if (isCurrentStreamFinal() && finalStreamEndPositionUs != C.TIME_UNSET && positionUs >= finalStreamEndPositionUs) {
        releaseBuffers();
        outputStreamEnded = true;
    }
    if (outputStreamEnded) {
        return;
    }
    if (nextSubtitle == null) {
        checkNotNull(decoder).setPositionUs(positionUs);
        try {
            nextSubtitle = checkNotNull(decoder).dequeueOutputBuffer();
        } catch (SubtitleDecoderException e) {
            handleDecoderError(e);
            return;
        }
    }
    if (getState() != STATE_STARTED) {
        return;
    }
    boolean textRendererNeedsUpdate = false;
    if (subtitle != null) {
        // We're iterating through the events in a subtitle. Set textRendererNeedsUpdate if we
        // advance to the next event.
        long subtitleNextEventTimeUs = getNextEventTime();
        while (subtitleNextEventTimeUs <= positionUs) {
            nextSubtitleEventIndex++;
            subtitleNextEventTimeUs = getNextEventTime();
            textRendererNeedsUpdate = true;
        }
    }
    if (nextSubtitle != null) {
        SubtitleOutputBuffer nextSubtitle = this.nextSubtitle;
        if (nextSubtitle.isEndOfStream()) {
            if (!textRendererNeedsUpdate && getNextEventTime() == Long.MAX_VALUE) {
                if (decoderReplacementState == REPLACEMENT_STATE_WAIT_END_OF_STREAM) {
                    replaceDecoder();
                } else {
                    releaseBuffers();
                    outputStreamEnded = true;
                }
            }
        } else if (nextSubtitle.timeUs <= positionUs) {
            // Advance to the next subtitle. Sync the next event index and trigger an update.
            if (subtitle != null) {
                subtitle.release();
            }
            nextSubtitleEventIndex = nextSubtitle.getNextEventTimeIndex(positionUs);
            subtitle = nextSubtitle;
            this.nextSubtitle = null;
            textRendererNeedsUpdate = true;
        }
    }
    if (textRendererNeedsUpdate) {
        // If textRendererNeedsUpdate then subtitle must be non-null.
        checkNotNull(subtitle);
        // textRendererNeedsUpdate is set and we're playing. Update the renderer.
        updateOutput(subtitle.getCues(positionUs));
    }
    if (decoderReplacementState == REPLACEMENT_STATE_WAIT_END_OF_STREAM) {
        return;
    }
    try {
        while (!inputStreamEnded) {
            @Nullable SubtitleInputBuffer nextInputBuffer = this.nextInputBuffer;
            if (nextInputBuffer == null) {
                nextInputBuffer = checkNotNull(decoder).dequeueInputBuffer();
                if (nextInputBuffer == null) {
                    return;
                }
                this.nextInputBuffer = nextInputBuffer;
            }
            if (decoderReplacementState == REPLACEMENT_STATE_SIGNAL_END_OF_STREAM) {
                nextInputBuffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
                checkNotNull(decoder).queueInputBuffer(nextInputBuffer);
                this.nextInputBuffer = null;
                decoderReplacementState = REPLACEMENT_STATE_WAIT_END_OF_STREAM;
                return;
            }
            // Try and read the next subtitle from the source.
            @ReadDataResult int result = readSource(formatHolder, nextInputBuffer, /* readFlags= */
            0);
            if (result == C.RESULT_BUFFER_READ) {
                if (nextInputBuffer.isEndOfStream()) {
                    inputStreamEnded = true;
                    waitingForKeyFrame = false;
                } else {
                    @Nullable Format format = formatHolder.format;
                    if (format == null) {
                        // We haven't received a format yet.
                        return;
                    }
                    nextInputBuffer.subsampleOffsetUs = format.subsampleOffsetUs;
                    nextInputBuffer.flip();
                    waitingForKeyFrame &= !nextInputBuffer.isKeyFrame();
                }
                if (!waitingForKeyFrame) {
                    checkNotNull(decoder).queueInputBuffer(nextInputBuffer);
                    this.nextInputBuffer = null;
                }
            } else if (result == C.RESULT_NOTHING_READ) {
                return;
            }
        }
    } catch (SubtitleDecoderException e) {
        handleDecoderError(e);
    }
}
Also used : Format(com.google.android.exoplayer2.Format) ReadDataResult(com.google.android.exoplayer2.source.SampleStream.ReadDataResult) Nullable(androidx.annotation.Nullable)

Example 9 with FormatHolder

use of com.google.android.exoplayer2.FormatHolder in project ExoPlayer by google.

the class CameraMotionRenderer method render.

@Override
public void render(long positionUs, long elapsedRealtimeUs) {
    // Keep reading available samples as long as the sample time is not too far into the future.
    while (!hasReadStreamToEnd() && lastTimestampUs < positionUs + SAMPLE_WINDOW_DURATION_US) {
        buffer.clear();
        FormatHolder formatHolder = getFormatHolder();
        @ReadDataResult int result = readSource(formatHolder, buffer, /* readFlags= */
        0);
        if (result != C.RESULT_BUFFER_READ || buffer.isEndOfStream()) {
            return;
        }
        lastTimestampUs = buffer.timeUs;
        if (listener == null || buffer.isDecodeOnly()) {
            continue;
        }
        buffer.flip();
        @Nullable float[] rotation = parseMetadata(Util.castNonNull(buffer.data));
        if (rotation == null) {
            continue;
        }
        Util.castNonNull(listener).onCameraMotion(lastTimestampUs - offsetUs, rotation);
    }
}
Also used : ReadDataResult(com.google.android.exoplayer2.source.SampleStream.ReadDataResult) FormatHolder(com.google.android.exoplayer2.FormatHolder) Nullable(androidx.annotation.Nullable)

Example 10 with FormatHolder

use of com.google.android.exoplayer2.FormatHolder in project ExoPlayer by google.

the class MergingMediaPeriodTest method selectTracks_createsSampleStreamsFromChildPeriods.

@Test
public void selectTracks_createsSampleStreamsFromChildPeriods() throws Exception {
    MergingMediaPeriod mergingMediaPeriod = prepareMergingPeriod(new MergingPeriodDefinition(/* timeOffsetUs= */
    0, /* singleSampleTimeUs= */
    0, childFormat11, childFormat12), new MergingPeriodDefinition(/* timeOffsetUs= */
    0, /* singleSampleTimeUs= */
    0, childFormat21, childFormat22));
    ExoTrackSelection selectionForChild1 = new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(1), /* track= */
    0);
    ExoTrackSelection selectionForChild2 = new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(2), /* track= */
    0);
    SampleStream[] streams = new SampleStream[4];
    mergingMediaPeriod.selectTracks(/* selections= */
    new ExoTrackSelection[] { null, selectionForChild1, selectionForChild2, null }, /* mayRetainStreamFlags= */
    new boolean[] { false, false, false, false }, streams, /* streamResetFlags= */
    new boolean[] { false, false, false, false }, /* positionUs= */
    0);
    mergingMediaPeriod.continueLoading(/* positionUs= */
    0);
    assertThat(streams[0]).isNull();
    assertThat(streams[3]).isNull();
    FormatHolder formatHolder = new FormatHolder();
    DecoderInputBuffer inputBuffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
    assertThat(streams[1].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT)).isEqualTo(C.RESULT_FORMAT_READ);
    assertThat(formatHolder.format).isEqualTo(childFormat12);
    assertThat(streams[2].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT)).isEqualTo(C.RESULT_FORMAT_READ);
    assertThat(formatHolder.format).isEqualTo(childFormat21);
}
Also used : ExoTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection) DecoderInputBuffer(com.google.android.exoplayer2.decoder.DecoderInputBuffer) FormatHolder(com.google.android.exoplayer2.FormatHolder) FixedTrackSelection(com.google.android.exoplayer2.trackselection.FixedTrackSelection) Test(org.junit.Test)

Aggregations

FormatHolder (com.google.android.exoplayer2.FormatHolder)16 Test (org.junit.Test)13 ReadDataResult (com.google.android.exoplayer2.source.SampleStream.ReadDataResult)11 Format (com.google.android.exoplayer2.Format)10 EventStream (com.google.android.exoplayer2.source.dash.manifest.EventStream)9 EventMessage (com.google.android.exoplayer2.metadata.emsg.EventMessage)8 Nullable (androidx.annotation.Nullable)7 DecoderReuseEvaluation (com.google.android.exoplayer2.decoder.DecoderReuseEvaluation)5 DecoderInputBuffer (com.google.android.exoplayer2.decoder.DecoderInputBuffer)4 DrmSession (com.google.android.exoplayer2.drm.DrmSession)4 CallSuper (androidx.annotation.CallSuper)2 DecoderException (com.google.android.exoplayer2.decoder.DecoderException)2 ExoTrackSelection (com.google.android.exoplayer2.trackselection.ExoTrackSelection)2 FixedTrackSelection (com.google.android.exoplayer2.trackselection.FixedTrackSelection)2 Before (org.junit.Before)2 CryptoException (android.media.MediaCodec.CryptoException)1 MediaCryptoException (android.media.MediaCryptoException)1 MediaFormat (android.media.MediaFormat)1 InsufficientCapacityException (com.google.android.exoplayer2.decoder.DecoderInputBuffer.InsufficientCapacityException)1 DecoderDiscardReasons (com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DecoderDiscardReasons)1