/** * Processes an end of stream signal. * * @throws ExoPlaybackException If an error occurs processing the signal. */ private void processEndOfStream() throws ExoPlaybackException { if (codecReinitializationState == REINITIALIZATION_STATE_WAIT_END_OF_STREAM) { // We're waiting to re-initialize the codec, and have now processed all final buffers. releaseCodec(); maybeInitCodec(); } else { outputStreamEnded = true; onOutputStreamEnded(); } }
private void flushCodec() throws ExoPlaybackException { codecHotswapTimeMs = -1; inputIndex = -1; outputIndex = -1; waitingForFirstSyncFrame = true; waitingForKeys = false; decodeOnlyPresentationTimestamps.clear(); if (Util.SDK_INT < 18 || (codecNeedsEosFlushWorkaround && codecReceivedEos)) { // Workaround framework bugs. See [Internal: b/8347958, b/8578467, b/8543366, b/23361053]. releaseCodec(); maybeInitCodec(); } else if (codecReinitializationState != REINITIALIZATION_STATE_NONE) { // We're already waiting to release and re-initialize the codec. Since we're now flushing, // there's no need to wait any longer. releaseCodec(); maybeInitCodec(); } else { // We can flush and re-use the existing decoder. codec.flush(); codecHasQueuedBuffers = false; } if (codecReconfigured && format != null) { // Any reconfiguration data that we send shortly before the flush may be discarded. We // avoid this issue by sending reconfiguration data following every flush. codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING; } }
/** * Invoked when a new format is read from the upstream {@link SampleSource}. * * @param formatHolder Holds the new format. * @throws ExoPlaybackException If an error occurs reinitializing the {@link MediaCodec}. */ protected void onInputFormatChanged(MediaFormatHolder formatHolder) throws ExoPlaybackException { MediaFormat oldFormat = format; format = formatHolder.format; drmInitData = formatHolder.drmInitData; if (codec != null && canReconfigureCodec(codec, codecIsAdaptive, oldFormat, format)) { codecReconfigured = true; codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING; } else { if (codecHasQueuedBuffers) { // Signal end of stream and wait for any final output buffers before re-initialization. codecReinitializationState = REINITIALIZATION_STATE_SIGNAL_END_OF_STREAM; } else { // There aren't any final output buffers, so perform re-initialization immediately. releaseCodec(); maybeInitCodec(); } } }
@Override protected void doSomeWork(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException { sourceState = continueBufferingSource(positionUs) ? (sourceState == SOURCE_STATE_NOT_READY ? SOURCE_STATE_READY : sourceState) : SOURCE_STATE_NOT_READY; checkForDiscontinuity(positionUs); if (format == null) { readFormat(positionUs); } if (codec == null && shouldInitCodec()) { maybeInitCodec(); } if (codec != null) { TraceUtil.beginSection("drainAndFeed"); while (drainOutputBuffer(positionUs, elapsedRealtimeUs)) {} if (feedInputBuffer(positionUs, true)) { while (feedInputBuffer(positionUs, false)) {} } TraceUtil.endSection(); } codecCounters.ensureUpdated(); }