Search in sources :

Example 11 with SeekPoints

use of androidx.media3.extractor.SeekMap.SeekPoints in project media by androidx.

the class PsExtractorSeekTest method seekToTimeUs.

/**
 * Seeks to the given seek time and keeps reading from input until we can extract at least one
 * frame from the seek position, or until end-of-input is reached.
 *
 * @return The index of the first extracted frame written to the given {@code trackOutput} after
 *     the seek is completed, or -1 if the seek is completed without any extracted frame.
 */
private int seekToTimeUs(PsExtractor psExtractor, SeekMap seekMap, long seekTimeUs, FakeTrackOutput trackOutput) throws IOException {
    int numSampleBeforeSeek = trackOutput.getSampleCount();
    SeekMap.SeekPoints seekPoints = seekMap.getSeekPoints(seekTimeUs);
    long initialSeekLoadPosition = seekPoints.first.position;
    psExtractor.seek(initialSeekLoadPosition, seekTimeUs);
    positionHolder.position = C.POSITION_UNSET;
    ExtractorInput extractorInput = getExtractorInputFromPosition(initialSeekLoadPosition);
    int extractorReadResult = Extractor.RESULT_CONTINUE;
    while (true) {
        try {
            // Keep reading until we can read at least one frame after seek
            while (extractorReadResult == Extractor.RESULT_CONTINUE && trackOutput.getSampleCount() == numSampleBeforeSeek) {
                extractorReadResult = psExtractor.read(extractorInput, positionHolder);
            }
        } finally {
            DataSourceUtil.closeQuietly(dataSource);
        }
        if (extractorReadResult == Extractor.RESULT_SEEK) {
            extractorInput = getExtractorInputFromPosition(positionHolder.position);
            extractorReadResult = Extractor.RESULT_CONTINUE;
        } else if (extractorReadResult == Extractor.RESULT_END_OF_INPUT) {
            return -1;
        } else if (trackOutput.getSampleCount() > numSampleBeforeSeek) {
            // First index after seek = num sample before seek.
            return numSampleBeforeSeek;
        }
    }
}
Also used : FakeExtractorInput(androidx.media3.test.utils.FakeExtractorInput) ExtractorInput(androidx.media3.extractor.ExtractorInput) DefaultExtractorInput(androidx.media3.extractor.DefaultExtractorInput) SeekMap(androidx.media3.extractor.SeekMap)

Example 12 with SeekPoints

use of androidx.media3.extractor.SeekMap.SeekPoints in project media by androidx.

the class TestUtil method seekToTimeUs.

/**
 * Seeks to the given seek time of the stream from the given input, and keeps reading from the
 * input until we can extract at least one sample following the seek position, or until
 * end-of-input is reached.
 *
 * @param extractor The {@link Extractor} to extract from input.
 * @param seekMap The {@link SeekMap} of the stream from the given input.
 * @param seekTimeUs The seek time, in micro-seconds.
 * @param trackOutput The {@link FakeTrackOutput} to store the extracted samples.
 * @param dataSource The {@link DataSource} that will be used to read from the input.
 * @param uri The Uri of the input.
 * @return The index of the first extracted sample written to the given {@code trackOutput} after
 *     the seek is completed, or {@link C#INDEX_UNSET} if the seek is completed without any
 *     extracted sample.
 */
public static int seekToTimeUs(Extractor extractor, SeekMap seekMap, long seekTimeUs, DataSource dataSource, FakeTrackOutput trackOutput, Uri uri) throws IOException {
    int numSampleBeforeSeek = trackOutput.getSampleCount();
    SeekMap.SeekPoints seekPoints = seekMap.getSeekPoints(seekTimeUs);
    long initialSeekLoadPosition = seekPoints.first.position;
    extractor.seek(initialSeekLoadPosition, seekTimeUs);
    PositionHolder positionHolder = new PositionHolder();
    positionHolder.position = C.POSITION_UNSET;
    ExtractorInput extractorInput = TestUtil.getExtractorInputFromPosition(dataSource, initialSeekLoadPosition, uri);
    int extractorReadResult = Extractor.RESULT_CONTINUE;
    while (true) {
        try {
            // Keep reading until we can read at least one sample after seek
            while (extractorReadResult == Extractor.RESULT_CONTINUE && trackOutput.getSampleCount() == numSampleBeforeSeek) {
                extractorReadResult = extractor.read(extractorInput, positionHolder);
            }
        } finally {
            DataSourceUtil.closeQuietly(dataSource);
        }
        if (extractorReadResult == Extractor.RESULT_SEEK) {
            extractorInput = TestUtil.getExtractorInputFromPosition(dataSource, positionHolder.position, uri);
            extractorReadResult = Extractor.RESULT_CONTINUE;
        } else if (extractorReadResult == Extractor.RESULT_END_OF_INPUT && trackOutput.getSampleCount() == numSampleBeforeSeek) {
            return C.INDEX_UNSET;
        } else if (trackOutput.getSampleCount() > numSampleBeforeSeek) {
            // First index after seek = num sample before seek.
            return numSampleBeforeSeek;
        }
    }
}
Also used : ExtractorInput(androidx.media3.extractor.ExtractorInput) DefaultExtractorInput(androidx.media3.extractor.DefaultExtractorInput) PositionHolder(androidx.media3.extractor.PositionHolder) SeekMap(androidx.media3.extractor.SeekMap)

Example 13 with SeekPoints

use of androidx.media3.extractor.SeekMap.SeekPoints in project media by androidx.

the class FlacDecoderJni method getSeekPoints.

/**
 * Maps a seek position in microseconds to the corresponding {@link SeekMap.SeekPoints} in the
 * stream.
 *
 * @param timeUs A seek position in microseconds.
 * @return The corresponding {@link SeekMap.SeekPoints} obtained from the seek table, or {@code
 *     null} if the stream doesn't have a seek table.
 */
@Nullable
public SeekMap.SeekPoints getSeekPoints(long timeUs) {
    long[] seekPoints = new long[4];
    if (!flacGetSeekPoints(nativeDecoderContext, timeUs, seekPoints)) {
        return null;
    }
    SeekPoint firstSeekPoint = new SeekPoint(seekPoints[0], seekPoints[1]);
    SeekPoint secondSeekPoint = seekPoints[2] == seekPoints[0] ? firstSeekPoint : new SeekPoint(seekPoints[2], seekPoints[3]);
    return new SeekMap.SeekPoints(firstSeekPoint, secondSeekPoint);
}
Also used : SeekPoint(androidx.media3.extractor.SeekPoint) Nullable(androidx.annotation.Nullable)

Example 14 with SeekPoints

use of androidx.media3.extractor.SeekMap.SeekPoints in project media by androidx.

the class Mp4Extractor method getSeekPoints.

@Override
public SeekPoints getSeekPoints(long timeUs) {
    if (checkNotNull(tracks).length == 0) {
        return new SeekPoints(SeekPoint.START);
    }
    long firstTimeUs;
    long firstOffset;
    long secondTimeUs = C.TIME_UNSET;
    long secondOffset = C.POSITION_UNSET;
    // If we have a video track, use it to establish one or two seek points.
    if (firstVideoTrackIndex != C.INDEX_UNSET) {
        TrackSampleTable sampleTable = tracks[firstVideoTrackIndex].sampleTable;
        int sampleIndex = getSynchronizationSampleIndex(sampleTable, timeUs);
        if (sampleIndex == C.INDEX_UNSET) {
            return new SeekPoints(SeekPoint.START);
        }
        long sampleTimeUs = sampleTable.timestampsUs[sampleIndex];
        firstTimeUs = sampleTimeUs;
        firstOffset = sampleTable.offsets[sampleIndex];
        if (sampleTimeUs < timeUs && sampleIndex < sampleTable.sampleCount - 1) {
            int secondSampleIndex = sampleTable.getIndexOfLaterOrEqualSynchronizationSample(timeUs);
            if (secondSampleIndex != C.INDEX_UNSET && secondSampleIndex != sampleIndex) {
                secondTimeUs = sampleTable.timestampsUs[secondSampleIndex];
                secondOffset = sampleTable.offsets[secondSampleIndex];
            }
        }
    } else {
        firstTimeUs = timeUs;
        firstOffset = Long.MAX_VALUE;
    }
    // Take into account other tracks.
    for (int i = 0; i < tracks.length; i++) {
        if (i != firstVideoTrackIndex) {
            TrackSampleTable sampleTable = tracks[i].sampleTable;
            firstOffset = maybeAdjustSeekOffset(sampleTable, firstTimeUs, firstOffset);
            if (secondTimeUs != C.TIME_UNSET) {
                secondOffset = maybeAdjustSeekOffset(sampleTable, secondTimeUs, secondOffset);
            }
        }
    }
    SeekPoint firstSeekPoint = new SeekPoint(firstTimeUs, firstOffset);
    if (secondTimeUs == C.TIME_UNSET) {
        return new SeekPoints(firstSeekPoint);
    } else {
        SeekPoint secondSeekPoint = new SeekPoint(secondTimeUs, secondOffset);
        return new SeekPoints(firstSeekPoint, secondSeekPoint);
    }
}
Also used : SeekPoint(androidx.media3.extractor.SeekPoint) SeekPoint(androidx.media3.extractor.SeekPoint)

Example 15 with SeekPoints

use of androidx.media3.extractor.SeekMap.SeekPoints in project media by androidx.

the class IndexSeeker method getSeekPoints.

@Override
public SeekPoints getSeekPoints(long timeUs) {
    int targetIndex = Util.binarySearchFloor(timesUs, timeUs, /* inclusive= */
    true, /* stayInBounds= */
    true);
    SeekPoint seekPoint = new SeekPoint(timesUs.get(targetIndex), positions.get(targetIndex));
    if (seekPoint.timeUs == timeUs || targetIndex == timesUs.size() - 1) {
        return new SeekPoints(seekPoint);
    } else {
        SeekPoint nextSeekPoint = new SeekPoint(timesUs.get(targetIndex + 1), positions.get(targetIndex + 1));
        return new SeekPoints(seekPoint, nextSeekPoint);
    }
}
Also used : SeekPoint(androidx.media3.extractor.SeekPoint) SeekPoint(androidx.media3.extractor.SeekPoint)

Aggregations

SeekPoint (androidx.media3.extractor.SeekPoint)10 Test (org.junit.Test)6 SeekPoints (com.google.android.exoplayer2.extractor.SeekMap.SeekPoints)5 SeekPoints (androidx.media3.extractor.SeekMap.SeekPoints)4 SeekPoint (com.google.android.exoplayer2.extractor.SeekPoint)3 DefaultExtractorInput (androidx.media3.extractor.DefaultExtractorInput)2 ExtractorInput (androidx.media3.extractor.ExtractorInput)2 SeekMap (androidx.media3.extractor.SeekMap)2 Nullable (androidx.annotation.Nullable)1 PositionHolder (androidx.media3.extractor.PositionHolder)1 FakeExtractorInput (androidx.media3.test.utils.FakeExtractorInput)1 SeekMap (com.google.android.exoplayer2.extractor.SeekMap)1