Search in sources :

Example 26 with FormatHolder

use of androidx.media3.exoplayer.FormatHolder in project media by androidx.

the class DecoderAudioRenderer method onInputFormatChanged.

private void onInputFormatChanged(FormatHolder formatHolder) throws ExoPlaybackException {
    Format newFormat = Assertions.checkNotNull(formatHolder.format);
    setSourceDrmSession(formatHolder.drmSession);
    Format oldFormat = inputFormat;
    inputFormat = newFormat;
    encoderDelay = newFormat.encoderDelay;
    encoderPadding = newFormat.encoderPadding;
    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();
            audioTrackNeedsConfigure = true;
        }
    }
    eventDispatcher.inputFormatChanged(inputFormat, evaluation);
}
Also used : Format(androidx.media3.common.Format) DecoderReuseEvaluation(androidx.media3.exoplayer.DecoderReuseEvaluation)

Example 27 with FormatHolder

use of androidx.media3.exoplayer.FormatHolder in project media by androidx.

the class MediaCodecRenderer method onInputFormatChanged.

/**
 * Called when a new {@link Format} is read from the upstream {@link MediaPeriod}.
 *
 * @param formatHolder A {@link FormatHolder} that holds the new {@link Format}.
 * @throws ExoPlaybackException If an error occurs re-initializing the {@link MediaCodec}.
 * @return The result of the evaluation to determine whether the existing decoder instance can be
 *     reused for the new format, or {@code null} if the renderer did not have a decoder.
 */
@CallSuper
@Nullable
protected DecoderReuseEvaluation onInputFormatChanged(FormatHolder formatHolder) throws ExoPlaybackException {
    waitingForFirstSampleInFormat = true;
    Format newFormat = checkNotNull(formatHolder.format);
    if (newFormat.sampleMimeType == null) {
        throw createRendererException(new IllegalArgumentException(), newFormat, PlaybackException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
    }
    setSourceDrmSession(formatHolder.drmSession);
    inputFormat = newFormat;
    if (bypassEnabled) {
        bypassDrainAndReinitialize = true;
        // Need to drain batch buffer first.
        return null;
    }
    if (codec == null) {
        availableCodecInfos = null;
        maybeInitCodecOrBypass();
        return null;
    }
    // We have an existing codec that we may need to reconfigure, re-initialize, or release to
    // switch to bypass. If the existing codec instance is kept then its operating rate and DRM
    // session may need to be updated.
    // Copy the current codec and codecInfo to local variables so they remain accessible if the
    // member variables are updated during the logic below.
    MediaCodecAdapter codec = this.codec;
    MediaCodecInfo codecInfo = this.codecInfo;
    Format oldFormat = codecInputFormat;
    if (drmNeedsCodecReinitialization(codecInfo, newFormat, codecDrmSession, sourceDrmSession)) {
        drainAndReinitializeCodec();
        return new DecoderReuseEvaluation(codecInfo.name, oldFormat, newFormat, REUSE_RESULT_NO, DISCARD_REASON_DRM_SESSION_CHANGED);
    }
    boolean drainAndUpdateCodecDrmSession = sourceDrmSession != codecDrmSession;
    Assertions.checkState(!drainAndUpdateCodecDrmSession || Util.SDK_INT >= 23);
    DecoderReuseEvaluation evaluation = canReuseCodec(codecInfo, oldFormat, newFormat);
    @DecoderDiscardReasons int overridingDiscardReasons = 0;
    switch(evaluation.result) {
        case REUSE_RESULT_NO:
            drainAndReinitializeCodec();
            break;
        case REUSE_RESULT_YES_WITH_FLUSH:
            if (!updateCodecOperatingRate(newFormat)) {
                overridingDiscardReasons |= DISCARD_REASON_OPERATING_RATE_CHANGED;
            } else {
                codecInputFormat = newFormat;
                if (drainAndUpdateCodecDrmSession) {
                    if (!drainAndUpdateCodecDrmSessionV23()) {
                        overridingDiscardReasons |= DISCARD_REASON_WORKAROUND;
                    }
                } else if (!drainAndFlushCodec()) {
                    overridingDiscardReasons |= DISCARD_REASON_WORKAROUND;
                }
            }
            break;
        case REUSE_RESULT_YES_WITH_RECONFIGURATION:
            if (!updateCodecOperatingRate(newFormat)) {
                overridingDiscardReasons |= DISCARD_REASON_OPERATING_RATE_CHANGED;
            } else {
                codecReconfigured = true;
                codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING;
                codecNeedsAdaptationWorkaroundBuffer = codecAdaptationWorkaroundMode == ADAPTATION_WORKAROUND_MODE_ALWAYS || (codecAdaptationWorkaroundMode == ADAPTATION_WORKAROUND_MODE_SAME_RESOLUTION && newFormat.width == oldFormat.width && newFormat.height == oldFormat.height);
                codecInputFormat = newFormat;
                if (drainAndUpdateCodecDrmSession && !drainAndUpdateCodecDrmSessionV23()) {
                    overridingDiscardReasons |= DISCARD_REASON_WORKAROUND;
                }
            }
            break;
        case REUSE_RESULT_YES_WITHOUT_RECONFIGURATION:
            if (!updateCodecOperatingRate(newFormat)) {
                overridingDiscardReasons |= DISCARD_REASON_OPERATING_RATE_CHANGED;
            } else {
                codecInputFormat = newFormat;
                if (drainAndUpdateCodecDrmSession && !drainAndUpdateCodecDrmSessionV23()) {
                    overridingDiscardReasons |= DISCARD_REASON_WORKAROUND;
                }
            }
            break;
        default:
            // Never happens.
            throw new IllegalStateException();
    }
    if (evaluation.result != REUSE_RESULT_NO && (this.codec != codec || codecDrainAction == DRAIN_ACTION_REINITIALIZE)) {
        // The reasons are indicated by overridingDiscardReasons.
        return new DecoderReuseEvaluation(codecInfo.name, oldFormat, newFormat, REUSE_RESULT_NO, overridingDiscardReasons);
    }
    return evaluation;
}
Also used : Format(androidx.media3.common.Format) MediaFormat(android.media.MediaFormat) DecoderReuseEvaluation(androidx.media3.exoplayer.DecoderReuseEvaluation) DecoderDiscardReasons(androidx.media3.exoplayer.DecoderReuseEvaluation.DecoderDiscardReasons) CallSuper(androidx.annotation.CallSuper) Nullable(androidx.annotation.Nullable)

Example 28 with FormatHolder

use of androidx.media3.exoplayer.FormatHolder in project media by androidx.

the class MediaCodecRenderer method readSourceOmittingSampleData.

/**
 * Reads from the source when sample data is not required. If a format or an end of stream buffer
 * is read, it will be handled before the call returns.
 *
 * @param readFlags Additional {@link ReadFlags}. {@link SampleStream#FLAG_OMIT_SAMPLE_DATA} is
 *     added internally, and so does not need to be passed.
 * @return Whether a format was read and processed.
 */
private boolean readSourceOmittingSampleData(@SampleStream.ReadFlags int readFlags) throws ExoPlaybackException {
    FormatHolder formatHolder = getFormatHolder();
    noDataBuffer.clear();
    @ReadDataResult int result = readSource(formatHolder, noDataBuffer, readFlags | FLAG_OMIT_SAMPLE_DATA);
    if (result == C.RESULT_FORMAT_READ) {
        onInputFormatChanged(formatHolder);
        return true;
    } else if (result == C.RESULT_BUFFER_READ && noDataBuffer.isEndOfStream()) {
        inputStreamEnded = true;
        processEndOfStream();
    }
    return false;
}
Also used : ReadDataResult(androidx.media3.exoplayer.source.SampleStream.ReadDataResult) FormatHolder(androidx.media3.exoplayer.FormatHolder)

Example 29 with FormatHolder

use of androidx.media3.exoplayer.FormatHolder in project media by androidx.

the class HlsSampleStreamWrapper method readData.

public int readData(int sampleQueueIndex, FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {
    if (isPendingReset()) {
        return C.RESULT_NOTHING_READ;
    }
    // TODO: Split into discard (in discardBuffer) and format change (here and in skipData) steps.
    if (!mediaChunks.isEmpty()) {
        int discardToMediaChunkIndex = 0;
        while (discardToMediaChunkIndex < mediaChunks.size() - 1 && finishedReadingChunk(mediaChunks.get(discardToMediaChunkIndex))) {
            discardToMediaChunkIndex++;
        }
        Util.removeRange(mediaChunks, 0, discardToMediaChunkIndex);
        HlsMediaChunk currentChunk = mediaChunks.get(0);
        Format trackFormat = currentChunk.trackFormat;
        if (!trackFormat.equals(downstreamTrackFormat)) {
            mediaSourceEventDispatcher.downstreamFormatChanged(trackType, trackFormat, currentChunk.trackSelectionReason, currentChunk.trackSelectionData, currentChunk.startTimeUs);
        }
        downstreamTrackFormat = trackFormat;
    }
    if (!mediaChunks.isEmpty() && !mediaChunks.get(0).isPublished()) {
        // Don't read into preload chunks until we can be sure they are permanently published.
        return C.RESULT_NOTHING_READ;
    }
    int result = sampleQueues[sampleQueueIndex].read(formatHolder, buffer, readFlags, loadingFinished);
    if (result == C.RESULT_FORMAT_READ) {
        Format format = Assertions.checkNotNull(formatHolder.format);
        if (sampleQueueIndex == primarySampleQueueIndex) {
            // Fill in primary sample format with information from the track format.
            int chunkUid = sampleQueues[sampleQueueIndex].peekSourceId();
            int chunkIndex = 0;
            while (chunkIndex < mediaChunks.size() && mediaChunks.get(chunkIndex).uid != chunkUid) {
                chunkIndex++;
            }
            Format trackFormat = chunkIndex < mediaChunks.size() ? mediaChunks.get(chunkIndex).trackFormat : Assertions.checkNotNull(upstreamTrackFormat);
            format = format.withManifestFormatInfo(trackFormat);
        }
        formatHolder.format = format;
    }
    return result;
}
Also used : Format(androidx.media3.common.Format)

Example 30 with FormatHolder

use of androidx.media3.exoplayer.FormatHolder in project media by androidx.

the class EventSampleStreamTest method readDataReturnFormatForFirstRead.

/**
 * Tests that {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, int)} will
 * return format for the first call.
 */
@Test
public void readDataReturnFormatForFirstRead() {
    EventStream eventStream = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, new long[0], new EventMessage[0]);
    // Make the event stream appendable so that the format is read. Otherwise, the format will be
    // skipped and the end of input will be read.
    EventSampleStream sampleStream = new EventSampleStream(eventStream, FORMAT, /* eventStreamAppendable= */
    true);
    int result = readData(sampleStream);
    assertThat(result).isEqualTo(C.RESULT_FORMAT_READ);
    assertThat(formatHolder.format).isEqualTo(FORMAT);
}
Also used : EventStream(androidx.media3.exoplayer.dash.manifest.EventStream) Test(org.junit.Test)

Aggregations

FormatHolder (androidx.media3.exoplayer.FormatHolder)16 Test (org.junit.Test)13 ReadDataResult (androidx.media3.exoplayer.source.SampleStream.ReadDataResult)11 Format (androidx.media3.common.Format)9 EventStream (androidx.media3.exoplayer.dash.manifest.EventStream)9 EventMessage (androidx.media3.extractor.metadata.emsg.EventMessage)8 Nullable (androidx.annotation.Nullable)7 DecoderReuseEvaluation (androidx.media3.exoplayer.DecoderReuseEvaluation)5 DecoderInputBuffer (androidx.media3.decoder.DecoderInputBuffer)4 DrmSession (androidx.media3.exoplayer.drm.DrmSession)4 CallSuper (androidx.annotation.CallSuper)2 DecoderException (androidx.media3.decoder.DecoderException)2 ExoTrackSelection (androidx.media3.exoplayer.trackselection.ExoTrackSelection)2 FixedTrackSelection (androidx.media3.exoplayer.trackselection.FixedTrackSelection)2 Before (org.junit.Before)2 CryptoException (android.media.MediaCodec.CryptoException)1 MediaCryptoException (android.media.MediaCryptoException)1 MediaFormat (android.media.MediaFormat)1 DrmInitData (androidx.media3.common.DrmInitData)1 Metadata (androidx.media3.common.Metadata)1