Search in sources :

Example 21 with DecoderInputBuffer

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

the class FfmpegAudioDecoder method decode.

@Override
@Nullable
protected FfmpegDecoderException decode(DecoderInputBuffer inputBuffer, SimpleDecoderOutputBuffer outputBuffer, boolean reset) {
    if (reset) {
        nativeContext = ffmpegReset(nativeContext, extraData);
        if (nativeContext == 0) {
            return new FfmpegDecoderException("Error resetting (see logcat).");
        }
    }
    ByteBuffer inputData = Util.castNonNull(inputBuffer.data);
    int inputSize = inputData.limit();
    ByteBuffer outputData = outputBuffer.init(inputBuffer.timeUs, outputBufferSize);
    int result = ffmpegDecode(nativeContext, inputData, inputSize, outputData, outputBufferSize);
    if (result == AUDIO_DECODER_ERROR_OTHER) {
        return new FfmpegDecoderException("Error decoding (see logcat).");
    } else if (result == AUDIO_DECODER_ERROR_INVALID_DATA) {
        // Treat invalid data errors as non-fatal to match the behavior of MediaCodec. No output will
        // be produced for this buffer, so mark it as decode-only to ensure that the audio sink's
        // position is reset when more audio is produced.
        outputBuffer.setFlags(C.BUFFER_FLAG_DECODE_ONLY);
        return null;
    } else if (result == 0) {
        // There's no need to output empty buffers.
        outputBuffer.setFlags(C.BUFFER_FLAG_DECODE_ONLY);
        return null;
    }
    if (!hasOutputFormat) {
        channelCount = ffmpegGetChannelCount(nativeContext);
        sampleRate = ffmpegGetSampleRate(nativeContext);
        if (sampleRate == 0 && "alac".equals(codecName)) {
            Assertions.checkNotNull(extraData);
            // ALAC decoder did not set the sample rate in earlier versions of FFmpeg. See
            // https://trac.ffmpeg.org/ticket/6096.
            ParsableByteArray parsableExtraData = new ParsableByteArray(extraData);
            parsableExtraData.setPosition(extraData.length - 4);
            sampleRate = parsableExtraData.readUnsignedIntToInt();
        }
        hasOutputFormat = true;
    }
    outputData.position(0);
    outputData.limit(result);
    return null;
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) ByteBuffer(java.nio.ByteBuffer) Nullable(androidx.annotation.Nullable)

Example 22 with DecoderInputBuffer

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

the class MergingMediaPeriodTest method selectTracks_withPeriodOffsets_selectTracksWithOffset_andCreatesSampleStreamsCorrectingOffset.

@Test
public void selectTracks_withPeriodOffsets_selectTracksWithOffset_andCreatesSampleStreamsCorrectingOffset() throws Exception {
    MergingMediaPeriod mergingMediaPeriod = prepareMergingPeriod(new MergingPeriodDefinition(/* timeOffsetUs= */
    0, /* singleSampleTimeUs= */
    123_000, childFormat11, childFormat12), new MergingPeriodDefinition(/* timeOffsetUs= */
    -3000, /* singleSampleTimeUs= */
    456_000, childFormat21, childFormat22));
    ExoTrackSelection selectionForChild1 = new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(0), /* track= */
    0);
    ExoTrackSelection selectionForChild2 = new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(2), /* track= */
    0);
    SampleStream[] streams = new SampleStream[2];
    mergingMediaPeriod.selectTracks(/* selections= */
    new ExoTrackSelection[] { selectionForChild1, selectionForChild2 }, /* mayRetainStreamFlags= */
    new boolean[] { false, false }, streams, /* streamResetFlags= */
    new boolean[] { false, false }, /* positionUs= */
    0);
    mergingMediaPeriod.continueLoading(/* positionUs= */
    0);
    FormatHolder formatHolder = new FormatHolder();
    DecoderInputBuffer inputBuffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
    streams[0].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT);
    streams[1].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT);
    FakeMediaPeriodWithSelectTracksPosition childMediaPeriod1 = (FakeMediaPeriodWithSelectTracksPosition) mergingMediaPeriod.getChildPeriod(0);
    assertThat(childMediaPeriod1.selectTracksPositionUs).isEqualTo(0);
    assertThat(streams[0].readData(formatHolder, inputBuffer, /* readFlags= */
    0)).isEqualTo(C.RESULT_BUFFER_READ);
    assertThat(inputBuffer.timeUs).isEqualTo(123_000L);
    FakeMediaPeriodWithSelectTracksPosition childMediaPeriod2 = (FakeMediaPeriodWithSelectTracksPosition) mergingMediaPeriod.getChildPeriod(1);
    assertThat(childMediaPeriod2.selectTracksPositionUs).isEqualTo(3000L);
    assertThat(streams[1].readData(formatHolder, inputBuffer, /* readFlags= */
    0)).isEqualTo(C.RESULT_BUFFER_READ);
    assertThat(inputBuffer.timeUs).isEqualTo(456_000 - 3000);
}
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)

Example 23 with DecoderInputBuffer

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

the class EventSampleStreamTest method skipDataThenUpdateStreamContinueToReadFromSkippedPosition.

/**
 * Tests that {@link EventSampleStream#updateEventStream(EventStream, boolean)} will update the
 * underlying event stream, but 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 skipDataThenUpdateStreamContinueToReadFromSkippedPosition() {
    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, presentationTimeUs2 }, new EventMessage[] { eventMessage1, eventMessage2 });
    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);
    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(eventMessage3));
}
Also used : EventMessage(com.google.android.exoplayer2.metadata.emsg.EventMessage) EventStream(com.google.android.exoplayer2.source.dash.manifest.EventStream) Test(org.junit.Test)

Example 24 with DecoderInputBuffer

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

the class EventSampleStreamTest method skipDataThenReadDataReturnDataFromSkippedPosition.

/**
 * Tests that {@link EventSampleStream#skipData(long)} will skip until the given position, and the
 * next {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, int)} call will return
 * sample data from that position.
 */
@Test
public void skipDataThenReadDataReturnDataFromSkippedPosition() {
    long presentationTimeUs1 = 1000000;
    long presentationTimeUs2 = 2000000;
    EventMessage eventMessage1 = newEventMessageWithId(1);
    EventMessage eventMessage2 = newEventMessageWithId(2);
    EventStream eventStream = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, new long[] { presentationTimeUs1, presentationTimeUs2 }, new EventMessage[] { eventMessage1, eventMessage2 });
    EventSampleStream sampleStream = new EventSampleStream(eventStream, FORMAT, false);
    // first read - read format
    readData(sampleStream);
    int skipped = sampleStream.skipData(presentationTimeUs2);
    int result = readData(sampleStream);
    assertThat(skipped).isEqualTo(1);
    assertThat(result).isEqualTo(C.RESULT_BUFFER_READ);
    assertThat(inputBuffer.data.array()).isEqualTo(getEncodedMessage(eventMessage2));
}
Also used : EventMessage(com.google.android.exoplayer2.metadata.emsg.EventMessage) EventStream(com.google.android.exoplayer2.source.dash.manifest.EventStream) Test(org.junit.Test)

Example 25 with DecoderInputBuffer

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

the class TransformerBaseRenderer method feedPipelineFromInput.

/**
 * Attempts to read input data and pass the input data to the sample pipeline.
 *
 * @return Whether it may be possible to read more data immediately by calling this method again.
 * @throws TransformationException If a {@link SamplePipeline} problem occurs.
 */
@RequiresNonNull("samplePipeline")
private boolean feedPipelineFromInput() throws TransformationException {
    @Nullable DecoderInputBuffer samplePipelineInputBuffer = samplePipeline.dequeueInputBuffer();
    if (samplePipelineInputBuffer == null) {
        return false;
    }
    @ReadDataResult int result = readSource(getFormatHolder(), samplePipelineInputBuffer, /* readFlags= */
    0);
    switch(result) {
        case C.RESULT_BUFFER_READ:
            samplePipelineInputBuffer.flip();
            if (samplePipelineInputBuffer.isEndOfStream()) {
                samplePipeline.queueInputBuffer();
                return false;
            }
            mediaClock.updateTimeForTrackType(getTrackType(), samplePipelineInputBuffer.timeUs);
            samplePipelineInputBuffer.timeUs -= streamOffsetUs;
            checkStateNotNull(samplePipelineInputBuffer.data);
            maybeQueueSampleToPipeline(samplePipelineInputBuffer);
            return true;
        case C.RESULT_FORMAT_READ:
            throw new IllegalStateException("Format changes are not supported.");
        case C.RESULT_NOTHING_READ:
        default:
            return false;
    }
}
Also used : ReadDataResult(com.google.android.exoplayer2.source.SampleStream.ReadDataResult) DecoderInputBuffer(com.google.android.exoplayer2.decoder.DecoderInputBuffer) Nullable(androidx.annotation.Nullable) RequiresNonNull(org.checkerframework.checker.nullness.qual.RequiresNonNull)

Aggregations

Test (org.junit.Test)11 EventStream (com.google.android.exoplayer2.source.dash.manifest.EventStream)9 DecoderInputBuffer (com.google.android.exoplayer2.decoder.DecoderInputBuffer)8 EventMessage (com.google.android.exoplayer2.metadata.emsg.EventMessage)8 Nullable (androidx.annotation.Nullable)7 Format (com.google.android.exoplayer2.Format)7 ByteBuffer (java.nio.ByteBuffer)6 FormatHolder (com.google.android.exoplayer2.FormatHolder)5 CryptoInfo (com.google.android.exoplayer2.decoder.CryptoInfo)5 ReadDataResult (com.google.android.exoplayer2.source.SampleStream.ReadDataResult)3 Before (org.junit.Before)3 CryptoException (com.google.android.exoplayer2.decoder.CryptoException)2 DecryptionException (com.google.android.exoplayer2.drm.DecryptionException)2 ExoTrackSelection (com.google.android.exoplayer2.trackselection.ExoTrackSelection)2 FixedTrackSelection (com.google.android.exoplayer2.trackselection.FixedTrackSelection)2 ParsableByteArray (com.google.android.exoplayer2.util.ParsableByteArray)2 RequiresNonNull (org.checkerframework.checker.nullness.qual.RequiresNonNull)2 SurfaceTexture (android.graphics.SurfaceTexture)1 Handler (android.os.Handler)1 Surface (android.view.Surface)1