Search in sources :

Example 6 with DecoderException

use of com.google.android.exoplayer2.decoder.DecoderException in project ExoPlayer by google.

the class DecoderVideoRendererTest method setUp.

@Before
public void setUp() {
    surface = new Surface(new SurfaceTexture(/* texName= */
    0));
    renderer = new DecoderVideoRenderer(/* allowedJoiningTimeMs= */
    0, new Handler(), eventListener, /* maxDroppedFramesToNotify= */
    -1) {

        private final Phaser inputBuffersInCodecPhaser = new Phaser();

        @C.VideoOutputMode
        private int outputMode;

        @Override
        public String getName() {
            return "TestVideoRenderer";
        }

        @Override
        @Capabilities
        public int supportsFormat(Format format) {
            return RendererCapabilities.create(C.FORMAT_HANDLED);
        }

        @Override
        protected void setDecoderOutputMode(@C.VideoOutputMode int outputMode) {
            this.outputMode = outputMode;
        }

        @Override
        protected void renderOutputBufferToSurface(VideoDecoderOutputBuffer outputBuffer, Surface surface) {
        // Do nothing.
        }

        @Override
        protected void onQueueInputBuffer(DecoderInputBuffer buffer) {
            // Decoding is done on a background thread we have no control about from the test.
            // Ensure the background calls are predictably serialized by waiting for them to finish:
            // 1. Register queued input buffers here.
            // 2. Deregister the input buffer when it's cleared. If an input buffer is cleared it
            // will have been fully handled by the decoder.
            // 3. Send a message on the test thread to wait for all currently pending input buffers
            // to be cleared.
            // 4. The tests need to call ShadowLooper.idleMainThread() to execute the wait message
            // sent in step (3).
            int currentPhase = inputBuffersInCodecPhaser.register();
            new Handler().post(() -> inputBuffersInCodecPhaser.awaitAdvance(currentPhase));
            super.onQueueInputBuffer(buffer);
        }

        @Override
        protected SimpleDecoder<DecoderInputBuffer, ? extends VideoDecoderOutputBuffer, ? extends DecoderException> createDecoder(Format format, @Nullable CryptoConfig cryptoConfig) {
            return new SimpleDecoder<DecoderInputBuffer, VideoDecoderOutputBuffer, DecoderException>(new DecoderInputBuffer[10], new VideoDecoderOutputBuffer[10]) {

                @Override
                protected DecoderInputBuffer createInputBuffer() {
                    return new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT) {

                        @Override
                        public void clear() {
                            super.clear();
                            inputBuffersInCodecPhaser.arriveAndDeregister();
                        }
                    };
                }

                @Override
                protected VideoDecoderOutputBuffer createOutputBuffer() {
                    return new VideoDecoderOutputBuffer(this::releaseOutputBuffer);
                }

                @Override
                protected DecoderException createUnexpectedDecodeException(Throwable error) {
                    return new DecoderException("error", error);
                }

                @Nullable
                @Override
                protected DecoderException decode(DecoderInputBuffer inputBuffer, VideoDecoderOutputBuffer outputBuffer, boolean reset) {
                    outputBuffer.init(inputBuffer.timeUs, outputMode, /* supplementalData= */
                    null);
                    return null;
                }

                @Override
                public String getName() {
                    return "TestDecoder";
                }
            };
        }
    };
    renderer.setOutput(surface);
}
Also used : SimpleDecoder(com.google.android.exoplayer2.decoder.SimpleDecoder) Handler(android.os.Handler) Surface(android.view.Surface) VideoDecoderOutputBuffer(com.google.android.exoplayer2.decoder.VideoDecoderOutputBuffer) DecoderException(com.google.android.exoplayer2.decoder.DecoderException) SurfaceTexture(android.graphics.SurfaceTexture) Format(com.google.android.exoplayer2.Format) DecoderInputBuffer(com.google.android.exoplayer2.decoder.DecoderInputBuffer) RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities) Phaser(java.util.concurrent.Phaser) CryptoConfig(com.google.android.exoplayer2.decoder.CryptoConfig) Nullable(androidx.annotation.Nullable) Before(org.junit.Before)

Example 7 with DecoderException

use of com.google.android.exoplayer2.decoder.DecoderException in project ExoPlayer by google.

the class DecoderAudioRenderer method drainOutputBuffer.

private boolean drainOutputBuffer() throws ExoPlaybackException, DecoderException, AudioSink.ConfigurationException, AudioSink.InitializationException, AudioSink.WriteException {
    if (outputBuffer == null) {
        outputBuffer = decoder.dequeueOutputBuffer();
        if (outputBuffer == null) {
            return false;
        }
        if (outputBuffer.skippedOutputBufferCount > 0) {
            decoderCounters.skippedOutputBufferCount += outputBuffer.skippedOutputBufferCount;
            audioSink.handleDiscontinuity();
        }
    }
    if (outputBuffer.isEndOfStream()) {
        if (decoderReinitializationState == REINITIALIZATION_STATE_WAIT_END_OF_STREAM) {
            // We're waiting to re-initialize the decoder, and have now processed all final buffers.
            releaseDecoder();
            maybeInitDecoder();
            // The audio track may need to be recreated once the new output format is known.
            audioTrackNeedsConfigure = true;
        } else {
            outputBuffer.release();
            outputBuffer = null;
            try {
                processEndOfStream();
            } catch (AudioSink.WriteException e) {
                throw createRendererException(e, e.format, e.isRecoverable, PlaybackException.ERROR_CODE_AUDIO_TRACK_WRITE_FAILED);
            }
        }
        return false;
    }
    if (audioTrackNeedsConfigure) {
        Format outputFormat = getOutputFormat(decoder).buildUpon().setEncoderDelay(encoderDelay).setEncoderPadding(encoderPadding).build();
        audioSink.configure(outputFormat, /* specifiedBufferSize= */
        0, /* outputChannels= */
        null);
        audioTrackNeedsConfigure = false;
    }
    if (audioSink.handleBuffer(outputBuffer.data, outputBuffer.timeUs, /* encodedAccessUnitCount= */
    1)) {
        decoderCounters.renderedOutputBufferCount++;
        outputBuffer.release();
        outputBuffer = null;
        return true;
    }
    return false;
}
Also used : Format(com.google.android.exoplayer2.Format)

Example 8 with DecoderException

use of com.google.android.exoplayer2.decoder.DecoderException in project ExoPlayer by google.

the class DecoderVideoRenderer method feedInputBuffer.

private boolean feedInputBuffer() throws DecoderException, ExoPlaybackException {
    if (decoder == null || decoderReinitializationState == REINITIALIZATION_STATE_WAIT_END_OF_STREAM || inputStreamEnded) {
        // We need to reinitialize the decoder or the input stream has ended.
        return false;
    }
    if (inputBuffer == null) {
        inputBuffer = decoder.dequeueInputBuffer();
        if (inputBuffer == null) {
            return false;
        }
    }
    if (decoderReinitializationState == REINITIALIZATION_STATE_SIGNAL_END_OF_STREAM) {
        inputBuffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
        decoder.queueInputBuffer(inputBuffer);
        inputBuffer = null;
        decoderReinitializationState = REINITIALIZATION_STATE_WAIT_END_OF_STREAM;
        return false;
    }
    FormatHolder formatHolder = getFormatHolder();
    switch(readSource(formatHolder, inputBuffer, /* readFlags= */
    0)) {
        case C.RESULT_NOTHING_READ:
            return false;
        case C.RESULT_FORMAT_READ:
            onInputFormatChanged(formatHolder);
            return true;
        case C.RESULT_BUFFER_READ:
            if (inputBuffer.isEndOfStream()) {
                inputStreamEnded = true;
                decoder.queueInputBuffer(inputBuffer);
                inputBuffer = null;
                return false;
            }
            if (waitingForFirstSampleInFormat) {
                formatQueue.add(inputBuffer.timeUs, inputFormat);
                waitingForFirstSampleInFormat = false;
            }
            inputBuffer.flip();
            inputBuffer.format = inputFormat;
            onQueueInputBuffer(inputBuffer);
            decoder.queueInputBuffer(inputBuffer);
            buffersInCodecCount++;
            decoderReceivedBuffers = true;
            decoderCounters.queuedInputBufferCount++;
            inputBuffer = null;
            return true;
        default:
            throw new IllegalStateException();
    }
}
Also used : FormatHolder(com.google.android.exoplayer2.FormatHolder)

Example 9 with DecoderException

use of com.google.android.exoplayer2.decoder.DecoderException in project ExoPlayer by google.

the class DecoderVideoRenderer method render.

// BaseRenderer implementation.
@Override
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
    if (outputStreamEnded) {
        return;
    }
    if (inputFormat == null) {
        // We don't have a format yet, so try and read one.
        FormatHolder formatHolder = getFormatHolder();
        flagsOnlyBuffer.clear();
        @ReadDataResult int result = readSource(formatHolder, flagsOnlyBuffer, FLAG_REQUIRE_FORMAT);
        if (result == C.RESULT_FORMAT_READ) {
            onInputFormatChanged(formatHolder);
        } else if (result == C.RESULT_BUFFER_READ) {
            // End of stream read having not read a format.
            Assertions.checkState(flagsOnlyBuffer.isEndOfStream());
            inputStreamEnded = true;
            outputStreamEnded = true;
            return;
        } else {
            // We still don't have a format and can't make progress without one.
            return;
        }
    }
    // If we don't have a decoder yet, we need to instantiate one.
    maybeInitDecoder();
    if (decoder != null) {
        try {
            // Rendering loop.
            TraceUtil.beginSection("drainAndFeed");
            while (drainOutputBuffer(positionUs, elapsedRealtimeUs)) {
            }
            while (feedInputBuffer()) {
            }
            TraceUtil.endSection();
        } catch (DecoderException e) {
            Log.e(TAG, "Video codec error", e);
            eventDispatcher.videoCodecError(e);
            throw createRendererException(e, inputFormat, PlaybackException.ERROR_CODE_DECODING_FAILED);
        }
        decoderCounters.ensureUpdated();
    }
}
Also used : DecoderException(com.google.android.exoplayer2.decoder.DecoderException) ReadDataResult(com.google.android.exoplayer2.source.SampleStream.ReadDataResult) FormatHolder(com.google.android.exoplayer2.FormatHolder)

Aggregations

DecoderException (com.google.android.exoplayer2.decoder.DecoderException)5 FormatHolder (com.google.android.exoplayer2.FormatHolder)4 Format (com.google.android.exoplayer2.Format)3 CryptoConfig (com.google.android.exoplayer2.decoder.CryptoConfig)3 DrmSessionException (com.google.android.exoplayer2.drm.DrmSession.DrmSessionException)2 ReadDataResult (com.google.android.exoplayer2.source.SampleStream.ReadDataResult)2 SurfaceTexture (android.graphics.SurfaceTexture)1 Handler (android.os.Handler)1 Surface (android.view.Surface)1 Nullable (androidx.annotation.Nullable)1 RendererCapabilities (com.google.android.exoplayer2.RendererCapabilities)1 DecoderInputBuffer (com.google.android.exoplayer2.decoder.DecoderInputBuffer)1 SimpleDecoder (com.google.android.exoplayer2.decoder.SimpleDecoder)1 VideoDecoderOutputBuffer (com.google.android.exoplayer2.decoder.VideoDecoderOutputBuffer)1 Phaser (java.util.concurrent.Phaser)1 Before (org.junit.Before)1