Noop cleanup of binary seeking / duration reading.

This is a precursor for fixing the ref'd issue. These classes are
well tested, so the tests passing should give you reasonable
confidence I didn't break anything :).

Issue: #5097

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=221435824
This commit is contained in:
olly 2018-11-14 06:44:38 -08:00 committed by Oliver Woodman
parent 0311e153f3
commit 177f3883e9
5 changed files with 87 additions and 102 deletions

View File

@ -42,31 +42,16 @@ public abstract class BinarySearchSeeker {
protected interface TimestampSeeker { protected interface TimestampSeeker {
/** /**
* Searches for a given timestamp from the input. * Searches a limited window of the provided input for a target timestamp. The size of the
* window is implementation specific, but should be small enough such that it's reasonable for
* multiple such reads to occur during a seek operation.
* *
* <p>Given a target timestamp and an input stream, this seeker will try to read up to a range * @param input The {@link ExtractorInput} from which data should be peeked.
* of {@code searchRangeBytes} bytes from that input, look for all available timestamps from all * @param targetTimestamp The target timestamp.
* frames in that range, compare those with the target timestamp, and return one of the {@link * @param outputFrameHolder If {@link TimestampSearchResult#TYPE_TARGET_TIMESTAMP_FOUND} is
* TimestampSearchResult}.
*
* @param input The {@link ExtractorInput} from which data should be read.
* @param targetTimestamp The target timestamp that we are looking for.
* @param outputFrameHolder If {@link TimestampSearchResult#RESULT_TARGET_TIMESTAMP_FOUND} is
* returned, this holder may be updated to hold the extracted frame that contains the target * returned, this holder may be updated to hold the extracted frame that contains the target
* frame/sample associated with the target timestamp. * frame/sample associated with the target timestamp.
* @return A {@link TimestampSearchResult}, that includes a {@link TimestampSearchResult#result} * @return A {@link TimestampSearchResult} that describes the result of the search.
* value, and other necessary info:
* <ul>
* <li>{@link TimestampSearchResult#RESULT_NO_TIMESTAMP} is returned if there is no
* timestamp in the reading range.
* <li>{@link TimestampSearchResult#RESULT_POSITION_UNDERESTIMATED} is returned if all
* timestamps in the range are smaller than the target timestamp.
* <li>{@link TimestampSearchResult#RESULT_POSITION_OVERESTIMATED} is returned if all
* timestamps in the range are larger than the target timestamp.
* <li>{@link TimestampSearchResult#RESULT_TARGET_TIMESTAMP_FOUND} is returned if this
* seeker can find a timestamp that it deems close enough to the given target.
* </ul>
*
* @throws IOException If an error occurred reading from the input. * @throws IOException If an error occurred reading from the input.
* @throws InterruptedException If the thread was interrupted. * @throws InterruptedException If the thread was interrupted.
*/ */
@ -231,22 +216,22 @@ public abstract class BinarySearchSeeker {
timestampSeeker.searchForTimestamp( timestampSeeker.searchForTimestamp(
input, seekOperationParams.getTargetTimePosition(), outputFrameHolder); input, seekOperationParams.getTargetTimePosition(), outputFrameHolder);
switch (timestampSearchResult.result) { switch (timestampSearchResult.type) {
case TimestampSearchResult.RESULT_POSITION_OVERESTIMATED: case TimestampSearchResult.TYPE_POSITION_OVERESTIMATED:
seekOperationParams.updateSeekCeiling( seekOperationParams.updateSeekCeiling(
timestampSearchResult.timestampToUpdate, timestampSearchResult.bytePositionToUpdate); timestampSearchResult.timestampToUpdate, timestampSearchResult.bytePositionToUpdate);
break; break;
case TimestampSearchResult.RESULT_POSITION_UNDERESTIMATED: case TimestampSearchResult.TYPE_POSITION_UNDERESTIMATED:
seekOperationParams.updateSeekFloor( seekOperationParams.updateSeekFloor(
timestampSearchResult.timestampToUpdate, timestampSearchResult.bytePositionToUpdate); timestampSearchResult.timestampToUpdate, timestampSearchResult.bytePositionToUpdate);
break; break;
case TimestampSearchResult.RESULT_TARGET_TIMESTAMP_FOUND: case TimestampSearchResult.TYPE_TARGET_TIMESTAMP_FOUND:
markSeekOperationFinished( markSeekOperationFinished(
/* foundTargetFrame= */ true, timestampSearchResult.bytePositionToUpdate); /* foundTargetFrame= */ true, timestampSearchResult.bytePositionToUpdate);
skipInputUntilPosition(input, timestampSearchResult.bytePositionToUpdate); skipInputUntilPosition(input, timestampSearchResult.bytePositionToUpdate);
return seekToPosition( return seekToPosition(
input, timestampSearchResult.bytePositionToUpdate, seekPositionHolder); input, timestampSearchResult.bytePositionToUpdate, seekPositionHolder);
case TimestampSearchResult.RESULT_NO_TIMESTAMP: case TimestampSearchResult.TYPE_NO_TIMESTAMP:
// We can't find any timestamp in the search range from the search position. // We can't find any timestamp in the search range from the search position.
// Give up, and just continue reading from the last search position in this case. // Give up, and just continue reading from the last search position in this case.
markSeekOperationFinished(/* foundTargetFrame= */ false, searchPosition); markSeekOperationFinished(/* foundTargetFrame= */ false, searchPosition);
@ -433,45 +418,49 @@ public abstract class BinarySearchSeeker {
*/ */
public static final class TimestampSearchResult { public static final class TimestampSearchResult {
public static final int RESULT_TARGET_TIMESTAMP_FOUND = 0; /** The search found a timestamp that it deems close enough to the given target. */
public static final int RESULT_POSITION_OVERESTIMATED = -1; public static final int TYPE_TARGET_TIMESTAMP_FOUND = 0;
public static final int RESULT_POSITION_UNDERESTIMATED = -2; /** The search found only timestamps larger than the target timestamp. */
public static final int RESULT_NO_TIMESTAMP = -3; public static final int TYPE_POSITION_OVERESTIMATED = -1;
/** The search found only timestamps smaller than the target timestamp. */
public static final int TYPE_POSITION_UNDERESTIMATED = -2;
/** The search didn't find any timestamps. */
public static final int TYPE_NO_TIMESTAMP = -3;
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({ @IntDef({
RESULT_TARGET_TIMESTAMP_FOUND, TYPE_TARGET_TIMESTAMP_FOUND,
RESULT_POSITION_OVERESTIMATED, TYPE_POSITION_OVERESTIMATED,
RESULT_POSITION_UNDERESTIMATED, TYPE_POSITION_UNDERESTIMATED,
RESULT_NO_TIMESTAMP TYPE_NO_TIMESTAMP
}) })
@interface SearchResult {} @interface Type {}
public static final TimestampSearchResult NO_TIMESTAMP_IN_RANGE_RESULT = public static final TimestampSearchResult NO_TIMESTAMP_IN_RANGE_RESULT =
new TimestampSearchResult(RESULT_NO_TIMESTAMP, C.TIME_UNSET, C.POSITION_UNSET); new TimestampSearchResult(TYPE_NO_TIMESTAMP, C.TIME_UNSET, C.POSITION_UNSET);
/** @see TimestampSeeker */ /** The type of the result. */
private final @SearchResult int result; @Type private final int type;
/** /**
* When {@code result} is {@link #RESULT_POSITION_OVERESTIMATED}, the {@link * When {@link #type} is {@link #TYPE_POSITION_OVERESTIMATED}, the {@link
* SeekOperationParams#ceilingTimePosition} should be updated with this value. When {@code * SeekOperationParams#ceilingTimePosition} should be updated with this value. When {@link
* result} is {@link #RESULT_POSITION_UNDERESTIMATED}, the {@link * #type} is {@link #TYPE_POSITION_UNDERESTIMATED}, the {@link
* SeekOperationParams#floorTimePosition} should be updated with this value. * SeekOperationParams#floorTimePosition} should be updated with this value.
*/ */
private final long timestampToUpdate; private final long timestampToUpdate;
/** /**
* When {@code result} is {@link #RESULT_POSITION_OVERESTIMATED}, the {@link * When {@link #type} is {@link #TYPE_POSITION_OVERESTIMATED}, the {@link
* SeekOperationParams#ceilingBytePosition} should be updated with this value. When {@code * SeekOperationParams#ceilingBytePosition} should be updated with this value. When {@link
* result} is {@link #RESULT_POSITION_UNDERESTIMATED}, the {@link * #type} is {@link #TYPE_POSITION_UNDERESTIMATED}, the {@link
* SeekOperationParams#floorBytePosition} should be updated with this value. * SeekOperationParams#floorBytePosition} should be updated with this value.
*/ */
private final long bytePositionToUpdate; private final long bytePositionToUpdate;
private TimestampSearchResult( private TimestampSearchResult(
@SearchResult int result, long timestampToUpdate, long bytePositionToUpdate) { @Type int type, long timestampToUpdate, long bytePositionToUpdate) {
this.result = result; this.type = type;
this.timestampToUpdate = timestampToUpdate; this.timestampToUpdate = timestampToUpdate;
this.bytePositionToUpdate = bytePositionToUpdate; this.bytePositionToUpdate = bytePositionToUpdate;
} }
@ -484,7 +473,7 @@ public abstract class BinarySearchSeeker {
public static TimestampSearchResult overestimatedResult( public static TimestampSearchResult overestimatedResult(
long newCeilingTimestamp, long newCeilingBytePosition) { long newCeilingTimestamp, long newCeilingBytePosition) {
return new TimestampSearchResult( return new TimestampSearchResult(
RESULT_POSITION_OVERESTIMATED, newCeilingTimestamp, newCeilingBytePosition); TYPE_POSITION_OVERESTIMATED, newCeilingTimestamp, newCeilingBytePosition);
} }
/** /**
@ -495,11 +484,11 @@ public abstract class BinarySearchSeeker {
public static TimestampSearchResult underestimatedResult( public static TimestampSearchResult underestimatedResult(
long newFloorTimestamp, long newCeilingBytePosition) { long newFloorTimestamp, long newCeilingBytePosition) {
return new TimestampSearchResult( return new TimestampSearchResult(
RESULT_POSITION_UNDERESTIMATED, newFloorTimestamp, newCeilingBytePosition); TYPE_POSITION_UNDERESTIMATED, newFloorTimestamp, newCeilingBytePosition);
} }
/** /**
* Returns a result to signal that the target timestamp has been found at the {@code * Returns a result to signal that the target timestamp has been found at {@code
* resultBytePosition}, and the seek operation can stop. * resultBytePosition}, and the seek operation can stop.
* *
* <p>Note that when this value is returned from {@link * <p>Note that when this value is returned from {@link
@ -508,7 +497,7 @@ public abstract class BinarySearchSeeker {
*/ */
public static TimestampSearchResult targetFoundResult(long resultBytePosition) { public static TimestampSearchResult targetFoundResult(long resultBytePosition) {
return new TimestampSearchResult( return new TimestampSearchResult(
RESULT_TARGET_TIMESTAMP_FOUND, C.TIME_UNSET, resultBytePosition); TYPE_TARGET_TIMESTAMP_FOUND, C.TIME_UNSET, resultBytePosition);
} }
} }

View File

@ -53,10 +53,9 @@ import java.io.IOException;
/** /**
* A seeker that looks for a given SCR timestamp at a given position in a PS stream. * A seeker that looks for a given SCR timestamp at a given position in a PS stream.
* *
* <p>Given a SCR timestamp, and a position within a PS stream, this seeker will try to read a * <p>Given a SCR timestamp, and a position within a PS stream, this seeker will peek up to {@link
* range of up to {@link #TIMESTAMP_SEARCH_BYTES} bytes from that stream position, look for all * #TIMESTAMP_SEARCH_BYTES} bytes from that stream position, look for all packs in that range, and
* packs in that range, and then compare the SCR timestamps (if available) of these packets vs the * then compare the SCR timestamps (if available) of these packets to the target timestamp.
* target timestamp.
*/ */
private static final class PsScrSeeker implements TimestampSeeker { private static final class PsScrSeeker implements TimestampSeeker {
@ -73,10 +72,10 @@ import java.io.IOException;
ExtractorInput input, long targetTimestamp, OutputFrameHolder outputFrameHolder) ExtractorInput input, long targetTimestamp, OutputFrameHolder outputFrameHolder)
throws IOException, InterruptedException { throws IOException, InterruptedException {
long inputPosition = input.getPosition(); long inputPosition = input.getPosition();
int bytesToRead = int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength() - inputPosition);
(int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength() - input.getPosition());
packetBuffer.reset(bytesToRead); input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);
input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToRead); packetBuffer.reset(bytesToSearch);
return searchForScrValueInBuffer(packetBuffer, targetTimestamp, inputPosition); return searchForScrValueInBuffer(packetBuffer, targetTimestamp, inputPosition);
} }

View File

@ -38,7 +38,7 @@ import java.io.IOException;
*/ */
/* package */ final class PsDurationReader { /* package */ final class PsDurationReader {
private static final int DURATION_READ_BYTES = 20000; private static final int TIMESTAMP_SEARCH_BYTES = 20000;
private final TimestampAdjuster scrTimestampAdjuster; private final TimestampAdjuster scrTimestampAdjuster;
private final ParsableByteArray packetBuffer; private final ParsableByteArray packetBuffer;
@ -56,7 +56,7 @@ import java.io.IOException;
firstScrValue = C.TIME_UNSET; firstScrValue = C.TIME_UNSET;
lastScrValue = C.TIME_UNSET; lastScrValue = C.TIME_UNSET;
durationUs = C.TIME_UNSET; durationUs = C.TIME_UNSET;
packetBuffer = new ParsableByteArray(DURATION_READ_BYTES); packetBuffer = new ParsableByteArray(TIMESTAMP_SEARCH_BYTES);
} }
/** Returns true if a PS duration has been read. */ /** Returns true if a PS duration has been read. */
@ -136,16 +136,16 @@ import java.io.IOException;
private int readFirstScrValue(ExtractorInput input, PositionHolder seekPositionHolder) private int readFirstScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
throws IOException, InterruptedException { throws IOException, InterruptedException {
if (input.getPosition() != 0) { int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength());
seekPositionHolder.position = 0; int searchStartPosition = 0;
if (input.getPosition() != searchStartPosition) {
seekPositionHolder.position = searchStartPosition;
return Extractor.RESULT_SEEK; return Extractor.RESULT_SEEK;
} }
int bytesToRead = (int) Math.min(DURATION_READ_BYTES, input.getLength());
input.resetPeekPosition(); input.resetPeekPosition();
input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToRead); input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);
packetBuffer.setPosition(0); packetBuffer.reset(bytesToSearch);
packetBuffer.setLimit(bytesToRead);
firstScrValue = readFirstScrValueFromBuffer(packetBuffer); firstScrValue = readFirstScrValueFromBuffer(packetBuffer);
isFirstScrValueRead = true; isFirstScrValueRead = true;
@ -172,17 +172,17 @@ import java.io.IOException;
private int readLastScrValue(ExtractorInput input, PositionHolder seekPositionHolder) private int readLastScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
throws IOException, InterruptedException { throws IOException, InterruptedException {
int bytesToRead = (int) Math.min(DURATION_READ_BYTES, input.getLength()); long inputLength = input.getLength();
long bufferStartStreamPosition = input.getLength() - bytesToRead; int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, inputLength);
if (input.getPosition() != bufferStartStreamPosition) { long searchStartPosition = inputLength - bytesToSearch;
seekPositionHolder.position = bufferStartStreamPosition; if (input.getPosition() != searchStartPosition) {
seekPositionHolder.position = searchStartPosition;
return Extractor.RESULT_SEEK; return Extractor.RESULT_SEEK;
} }
input.resetPeekPosition(); input.resetPeekPosition();
input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToRead); input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);
packetBuffer.setPosition(0); packetBuffer.reset(bytesToSearch);
packetBuffer.setLimit(bytesToRead);
lastScrValue = readLastScrValueFromBuffer(packetBuffer); lastScrValue = readLastScrValueFromBuffer(packetBuffer);
isLastScrValueRead = true; isLastScrValueRead = true;

View File

@ -33,10 +33,8 @@ import java.io.IOException;
/* package */ final class TsBinarySearchSeeker extends BinarySearchSeeker { /* package */ final class TsBinarySearchSeeker extends BinarySearchSeeker {
private static final long SEEK_TOLERANCE_US = 100_000; private static final long SEEK_TOLERANCE_US = 100_000;
private static final int MINIMUM_SEARCH_RANGE_BYTES = TsExtractor.TS_PACKET_SIZE * 5; private static final int MINIMUM_SEARCH_RANGE_BYTES = 5 * TsExtractor.TS_PACKET_SIZE;
private static final int TIMESTAMP_SEARCH_PACKETS = 200; private static final int TIMESTAMP_SEARCH_BYTES = 200 * TsExtractor.TS_PACKET_SIZE;
private static final int TIMESTAMP_SEARCH_BYTES =
TsExtractor.TS_PACKET_SIZE * TIMESTAMP_SEARCH_PACKETS;
public TsBinarySearchSeeker( public TsBinarySearchSeeker(
TimestampAdjuster pcrTimestampAdjuster, long streamDurationUs, long inputLength, int pcrPid) { TimestampAdjuster pcrTimestampAdjuster, long streamDurationUs, long inputLength, int pcrPid) {
@ -56,10 +54,10 @@ import java.io.IOException;
* A {@link TimestampSeeker} implementation that looks for a given PCR timestamp at a given * A {@link TimestampSeeker} implementation that looks for a given PCR timestamp at a given
* position in a TS stream. * position in a TS stream.
* *
* <p>Given a PCR timestamp, and a position within a TS stream, this seeker will try to read up to * <p>Given a PCR timestamp, and a position within a TS stream, this seeker will peek up to {@link
* {@link #TIMESTAMP_SEARCH_PACKETS} TS packets from that stream position, look for all packet * #TIMESTAMP_SEARCH_BYTES} from that stream position, look for all packets with PID equal to
* with PID equals to PCR_PID, and then compare the PCR timestamps (if available) of these packets * PCR_PID, and then compare the PCR timestamps (if available) of these packets to the target
* vs the target timestamp. * timestamp.
*/ */
private static final class TsPcrSeeker implements TimestampSeeker { private static final class TsPcrSeeker implements TimestampSeeker {
@ -78,10 +76,10 @@ import java.io.IOException;
ExtractorInput input, long targetTimestamp, OutputFrameHolder outputFrameHolder) ExtractorInput input, long targetTimestamp, OutputFrameHolder outputFrameHolder)
throws IOException, InterruptedException { throws IOException, InterruptedException {
long inputPosition = input.getPosition(); long inputPosition = input.getPosition();
int bytesToRead = int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength() - inputPosition);
(int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength() - input.getPosition());
packetBuffer.reset(bytesToRead); input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);
input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToRead); packetBuffer.reset(bytesToSearch);
return searchForPcrValueInBuffer(packetBuffer, targetTimestamp, inputPosition); return searchForPcrValueInBuffer(packetBuffer, targetTimestamp, inputPosition);
} }

View File

@ -35,8 +35,7 @@ import java.io.IOException;
*/ */
/* package */ final class TsDurationReader { /* package */ final class TsDurationReader {
private static final int DURATION_READ_PACKETS = 200; private static final int TIMESTAMP_SEARCH_BYTES = 200 * TsExtractor.TS_PACKET_SIZE;
private static final int DURATION_READ_BYTES = TsExtractor.TS_PACKET_SIZE * DURATION_READ_PACKETS;
private final TimestampAdjuster pcrTimestampAdjuster; private final TimestampAdjuster pcrTimestampAdjuster;
private final ParsableByteArray packetBuffer; private final ParsableByteArray packetBuffer;
@ -54,7 +53,7 @@ import java.io.IOException;
firstPcrValue = C.TIME_UNSET; firstPcrValue = C.TIME_UNSET;
lastPcrValue = C.TIME_UNSET; lastPcrValue = C.TIME_UNSET;
durationUs = C.TIME_UNSET; durationUs = C.TIME_UNSET;
packetBuffer = new ParsableByteArray(DURATION_READ_BYTES); packetBuffer = new ParsableByteArray(TIMESTAMP_SEARCH_BYTES);
} }
/** Returns true if a TS duration has been read. */ /** Returns true if a TS duration has been read. */
@ -124,16 +123,16 @@ import java.io.IOException;
private int readFirstPcrValue(ExtractorInput input, PositionHolder seekPositionHolder, int pcrPid) private int readFirstPcrValue(ExtractorInput input, PositionHolder seekPositionHolder, int pcrPid)
throws IOException, InterruptedException { throws IOException, InterruptedException {
if (input.getPosition() != 0) { int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength());
seekPositionHolder.position = 0; int searchStartPosition = 0;
if (input.getPosition() != searchStartPosition) {
seekPositionHolder.position = searchStartPosition;
return Extractor.RESULT_SEEK; return Extractor.RESULT_SEEK;
} }
int bytesToRead = (int) Math.min(DURATION_READ_BYTES, input.getLength());
input.resetPeekPosition(); input.resetPeekPosition();
input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToRead); input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);
packetBuffer.setPosition(0); packetBuffer.reset(bytesToSearch);
packetBuffer.setLimit(bytesToRead);
firstPcrValue = readFirstPcrValueFromBuffer(packetBuffer, pcrPid); firstPcrValue = readFirstPcrValueFromBuffer(packetBuffer, pcrPid);
isFirstPcrValueRead = true; isFirstPcrValueRead = true;
@ -159,17 +158,17 @@ import java.io.IOException;
private int readLastPcrValue(ExtractorInput input, PositionHolder seekPositionHolder, int pcrPid) private int readLastPcrValue(ExtractorInput input, PositionHolder seekPositionHolder, int pcrPid)
throws IOException, InterruptedException { throws IOException, InterruptedException {
int bytesToRead = (int) Math.min(DURATION_READ_BYTES, input.getLength()); long inputLength = input.getLength();
long bufferStartStreamPosition = input.getLength() - bytesToRead; int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, inputLength);
if (input.getPosition() != bufferStartStreamPosition) { long searchStartPosition = inputLength - bytesToSearch;
seekPositionHolder.position = bufferStartStreamPosition; if (input.getPosition() != searchStartPosition) {
seekPositionHolder.position = searchStartPosition;
return Extractor.RESULT_SEEK; return Extractor.RESULT_SEEK;
} }
input.resetPeekPosition(); input.resetPeekPosition();
input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToRead); input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);
packetBuffer.setPosition(0); packetBuffer.reset(bytesToSearch);
packetBuffer.setLimit(bytesToRead);
lastPcrValue = readLastPcrValueFromBuffer(packetBuffer, pcrPid); lastPcrValue = readLastPcrValueFromBuffer(packetBuffer, pcrPid);
isLastPcrValueRead = true; isLastPcrValueRead = true;