Search in sources :

Example 6 with PositionHolder

use of com.google.android.exoplayer2.extractor.PositionHolder in project ExoPlayer by google.

the class FlacExtractor method read.

@Override
public int read(final ExtractorInput input, PositionHolder seekPosition) throws IOException, InterruptedException {
    decoderJni.setData(input);
    if (!metadataParsed) {
        final FlacStreamInfo streamInfo;
        try {
            streamInfo = decoderJni.decodeMetadata();
            if (streamInfo == null) {
                throw new IOException("Metadata decoding failed");
            }
        } catch (IOException e) {
            decoderJni.reset(0);
            input.setRetryPosition(0, e);
            // never executes
            throw e;
        }
        metadataParsed = true;
        extractorOutput.seekMap(new SeekMap() {

            final boolean isSeekable = decoderJni.getSeekPosition(0) != -1;

            final long durationUs = streamInfo.durationUs();

            @Override
            public boolean isSeekable() {
                return isSeekable;
            }

            @Override
            public long getPosition(long timeUs) {
                return isSeekable ? decoderJni.getSeekPosition(timeUs) : 0;
            }

            @Override
            public long getDurationUs() {
                return durationUs;
            }
        });
        Format mediaFormat = Format.createAudioSampleFormat(null, MimeTypes.AUDIO_RAW, null, streamInfo.bitRate(), Format.NO_VALUE, streamInfo.channels, streamInfo.sampleRate, C.ENCODING_PCM_16BIT, null, null, 0, null);
        trackOutput.format(mediaFormat);
        outputBuffer = new ParsableByteArray(streamInfo.maxDecodedFrameSize());
        outputByteBuffer = ByteBuffer.wrap(outputBuffer.data);
    }
    outputBuffer.reset();
    long lastDecodePosition = decoderJni.getDecodePosition();
    int size;
    try {
        size = decoderJni.decodeSample(outputByteBuffer);
    } catch (IOException e) {
        if (lastDecodePosition >= 0) {
            decoderJni.reset(lastDecodePosition);
            input.setRetryPosition(lastDecodePosition, e);
        }
        throw e;
    }
    if (size <= 0) {
        return RESULT_END_OF_INPUT;
    }
    trackOutput.sampleData(outputBuffer, size);
    trackOutput.sampleMetadata(decoderJni.getLastSampleTimestamp(), C.BUFFER_FLAG_KEY_FRAME, size, 0, null);
    return decoderJni.isEndOfData() ? RESULT_END_OF_INPUT : RESULT_CONTINUE;
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) Format(com.google.android.exoplayer2.Format) FlacStreamInfo(com.google.android.exoplayer2.util.FlacStreamInfo) IOException(java.io.IOException) SeekMap(com.google.android.exoplayer2.extractor.SeekMap)

Example 7 with PositionHolder

use of com.google.android.exoplayer2.extractor.PositionHolder in project ExoPlayer by google.

the class TestUtil method consumeTestData.

private static void consumeTestData(Extractor extractor, FakeExtractorInput input, long timeUs, FakeExtractorOutput output, boolean retryFromStartIfLive) throws IOException, InterruptedException {
    extractor.seek(input.getPosition(), timeUs);
    PositionHolder seekPositionHolder = new PositionHolder();
    int readResult = Extractor.RESULT_CONTINUE;
    while (readResult != Extractor.RESULT_END_OF_INPUT) {
        try {
            // Extractor.read should not read seekPositionHolder.position. Set it to a value that's
            // likely to cause test failure if a read does occur.
            seekPositionHolder.position = Long.MIN_VALUE;
            readResult = extractor.read(input, seekPositionHolder);
            if (readResult == Extractor.RESULT_SEEK) {
                long seekPosition = seekPositionHolder.position;
                Assertions.checkState(0 <= seekPosition && seekPosition <= Integer.MAX_VALUE);
                input.setPosition((int) seekPosition);
            }
        } catch (SimulatedIOException e) {
            if (!retryFromStartIfLive) {
                continue;
            }
            boolean isOnDemand = input.getLength() != C.LENGTH_UNSET || (output.seekMap != null && output.seekMap.getDurationUs() != C.TIME_UNSET);
            if (isOnDemand) {
                continue;
            }
            input.setPosition(0);
            for (int i = 0; i < output.numberOfTracks; i++) {
                output.trackOutputs.valueAt(i).clear();
            }
            extractor.seek(0, 0);
        }
    }
}
Also used : SimulatedIOException(com.google.android.exoplayer2.testutil.FakeExtractorInput.SimulatedIOException) PositionHolder(com.google.android.exoplayer2.extractor.PositionHolder)

Example 8 with PositionHolder

use of com.google.android.exoplayer2.extractor.PositionHolder in project ExoPlayer by google.

the class Mp4Extractor method readSample.

/**
   * Attempts to extract the next sample in the current mdat atom for the specified track.
   * <p>
   * Returns {@link #RESULT_SEEK} if the source should be reloaded from the position in
   * {@code positionHolder}.
   * <p>
   * Returns {@link #RESULT_END_OF_INPUT} if no samples are left. Otherwise, returns
   * {@link #RESULT_CONTINUE}.
   *
   * @param input The {@link ExtractorInput} from which to read data.
   * @param positionHolder If {@link #RESULT_SEEK} is returned, this holder is updated to hold the
   *     position of the required data.
   * @return One of the {@code RESULT_*} flags in {@link Extractor}.
   * @throws IOException If an error occurs reading from the input.
   * @throws InterruptedException If the thread is interrupted.
   */
private int readSample(ExtractorInput input, PositionHolder positionHolder) throws IOException, InterruptedException {
    int trackIndex = getTrackIndexOfEarliestCurrentSample();
    if (trackIndex == C.INDEX_UNSET) {
        return RESULT_END_OF_INPUT;
    }
    Mp4Track track = tracks[trackIndex];
    TrackOutput trackOutput = track.trackOutput;
    int sampleIndex = track.sampleIndex;
    long position = track.sampleTable.offsets[sampleIndex];
    int sampleSize = track.sampleTable.sizes[sampleIndex];
    if (track.track.sampleTransformation == Track.TRANSFORMATION_CEA608_CDAT) {
        // The sample information is contained in a cdat atom. The header must be discarded for
        // committing.
        position += Atom.HEADER_SIZE;
        sampleSize -= Atom.HEADER_SIZE;
    }
    long skipAmount = position - input.getPosition() + sampleBytesWritten;
    if (skipAmount < 0 || skipAmount >= RELOAD_MINIMUM_SEEK_DISTANCE) {
        positionHolder.position = position;
        return RESULT_SEEK;
    }
    input.skipFully((int) skipAmount);
    if (track.track.nalUnitLengthFieldLength != 0) {
        // Zero the top three bytes of the array that we'll use to decode nal unit lengths, in case
        // they're only 1 or 2 bytes long.
        byte[] nalLengthData = nalLength.data;
        nalLengthData[0] = 0;
        nalLengthData[1] = 0;
        nalLengthData[2] = 0;
        int nalUnitLengthFieldLength = track.track.nalUnitLengthFieldLength;
        int nalUnitLengthFieldLengthDiff = 4 - track.track.nalUnitLengthFieldLength;
        // start codes as we encounter them.
        while (sampleBytesWritten < sampleSize) {
            if (sampleCurrentNalBytesRemaining == 0) {
                // Read the NAL length so that we know where we find the next one.
                input.readFully(nalLength.data, nalUnitLengthFieldLengthDiff, nalUnitLengthFieldLength);
                nalLength.setPosition(0);
                sampleCurrentNalBytesRemaining = nalLength.readUnsignedIntToInt();
                // Write a start code for the current NAL unit.
                nalStartCode.setPosition(0);
                trackOutput.sampleData(nalStartCode, 4);
                sampleBytesWritten += 4;
                sampleSize += nalUnitLengthFieldLengthDiff;
            } else {
                // Write the payload of the NAL unit.
                int writtenBytes = trackOutput.sampleData(input, sampleCurrentNalBytesRemaining, false);
                sampleBytesWritten += writtenBytes;
                sampleCurrentNalBytesRemaining -= writtenBytes;
            }
        }
    } else {
        while (sampleBytesWritten < sampleSize) {
            int writtenBytes = trackOutput.sampleData(input, sampleSize - sampleBytesWritten, false);
            sampleBytesWritten += writtenBytes;
            sampleCurrentNalBytesRemaining -= writtenBytes;
        }
    }
    trackOutput.sampleMetadata(track.sampleTable.timestampsUs[sampleIndex], track.sampleTable.flags[sampleIndex], sampleSize, 0, null);
    track.sampleIndex++;
    sampleBytesWritten = 0;
    sampleCurrentNalBytesRemaining = 0;
    return RESULT_CONTINUE;
}
Also used : TrackOutput(com.google.android.exoplayer2.extractor.TrackOutput)

Aggregations

PositionHolder (com.google.android.exoplayer2.extractor.PositionHolder)3 Format (com.google.android.exoplayer2.Format)2 SeekMap (com.google.android.exoplayer2.extractor.SeekMap)2 TrackOutput (com.google.android.exoplayer2.extractor.TrackOutput)2 FakeExtractorInput (com.google.android.exoplayer2.testutil.FakeExtractorInput)2 FakeExtractorOutput (com.google.android.exoplayer2.testutil.FakeExtractorOutput)2 ParsableByteArray (com.google.android.exoplayer2.util.ParsableByteArray)2 TimestampAdjuster (com.google.android.exoplayer2.util.TimestampAdjuster)2 ParserException (com.google.android.exoplayer2.ParserException)1 TrackIdGenerator (com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)1 SimulatedIOException (com.google.android.exoplayer2.testutil.FakeExtractorInput.SimulatedIOException)1 FakeTrackOutput (com.google.android.exoplayer2.testutil.FakeTrackOutput)1 FlacStreamInfo (com.google.android.exoplayer2.util.FlacStreamInfo)1 IOException (java.io.IOException)1