Commit 66335ab6 by apodob Committed by Oliver Woodman

Redesign states of the SubtitleExtractor.

Simplifies the SubtitleExtractor implementation. Makes the extractor
more aligned with the Extractor interface documentation by removing
STATE_DECODING in which extractor was doing nothing in term of input
and output while returning RESULT_CONTINUE at the same time.

PiperOrigin-RevId: 395267468
parent 9949424d
...@@ -47,33 +47,20 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -47,33 +47,20 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** Generic extractor for extracting subtitles from various subtitle formats. */ /** Generic extractor for extracting subtitles from various subtitle formats. */
public class SubtitleExtractor implements Extractor { public class SubtitleExtractor implements Extractor {
@IntDef(
value = {
STATE_CREATED,
STATE_INITIALIZED,
STATE_READING,
STATE_DECODING,
STATE_WRITING,
STATE_FINISHED,
STATE_RELEASED
})
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({STATE_CREATED, STATE_INITIALIZED, STATE_EXTRACTING, STATE_FINISHED, STATE_RELEASED})
private @interface State {} private @interface State {}
/** The extractor has been created. */ /** The extractor has been created. */
private static final int STATE_CREATED = 0; private static final int STATE_CREATED = 0;
/** The extractor has been initialized. */ /** The extractor has been initialized. */
private static final int STATE_INITIALIZED = 1; private static final int STATE_INITIALIZED = 1;
/** The extractor is reading data from the input. */ /** The extractor is reading from input and writing to output. */
private static final int STATE_READING = 2; private static final int STATE_EXTRACTING = 2;
/** The extractor is queueing data for decoding. */ /** The extractor has finished. */
private static final int STATE_DECODING = 3; private static final int STATE_FINISHED = 3;
/** The extractor is writing data to the output. */ /** The extractor has been released. */
private static final int STATE_WRITING = 4; private static final int STATE_RELEASED = 4;
/** The extractor has finished writing. */
private static final int STATE_FINISHED = 5;
/** The extractor has bean released */
private static final int STATE_RELEASED = 6;
private static final int DEFAULT_BUFFER_SIZE = 1024; private static final int DEFAULT_BUFFER_SIZE = 1024;
...@@ -126,29 +113,26 @@ public class SubtitleExtractor implements Extractor { ...@@ -126,29 +113,26 @@ public class SubtitleExtractor implements Extractor {
@Override @Override
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException { public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
switch (state) { checkState(state != STATE_CREATED && state != STATE_RELEASED);
case STATE_INITIALIZED: if (state == STATE_INITIALIZED) {
prepareMemory(input); subtitleData.reset(
state = readFromInput(input) ? STATE_DECODING : STATE_READING; input.getLength() != C.LENGTH_UNSET
return Extractor.RESULT_CONTINUE; ? Ints.checkedCast(input.getLength())
case STATE_READING: : DEFAULT_BUFFER_SIZE);
state = readFromInput(input) ? STATE_DECODING : STATE_READING; bytesRead = 0;
return Extractor.RESULT_CONTINUE; state = STATE_EXTRACTING;
case STATE_DECODING: }
queueDataToDecoder(); if (state == STATE_EXTRACTING) {
state = STATE_WRITING; boolean inputFinished = readFromInput(input);
return RESULT_CONTINUE; if (inputFinished) {
case STATE_WRITING: decodeAndWriteToOutput();
writeToOutput();
state = STATE_FINISHED; state = STATE_FINISHED;
return Extractor.RESULT_END_OF_INPUT; }
case STATE_FINISHED:
return Extractor.RESULT_END_OF_INPUT;
case STATE_CREATED:
case STATE_RELEASED:
default:
throw new IllegalStateException();
} }
if (state == STATE_FINISHED) {
return RESULT_END_OF_INPUT;
}
return RESULT_CONTINUE;
} }
@Override @Override
...@@ -166,13 +150,6 @@ public class SubtitleExtractor implements Extractor { ...@@ -166,13 +150,6 @@ public class SubtitleExtractor implements Extractor {
state = STATE_RELEASED; state = STATE_RELEASED;
} }
private void prepareMemory(ExtractorInput input) {
subtitleData.reset(
input.getLength() != C.LENGTH_UNSET
? Ints.checkedCast(input.getLength())
: DEFAULT_BUFFER_SIZE);
}
/** Returns whether reading has been finished. */ /** Returns whether reading has been finished. */
private boolean readFromInput(ExtractorInput input) throws IOException { private boolean readFromInput(ExtractorInput input) throws IOException {
if (subtitleData.capacity() == bytesRead) { if (subtitleData.capacity() == bytesRead) {
...@@ -186,7 +163,9 @@ public class SubtitleExtractor implements Extractor { ...@@ -186,7 +163,9 @@ public class SubtitleExtractor implements Extractor {
return readResult == C.RESULT_END_OF_INPUT; return readResult == C.RESULT_END_OF_INPUT;
} }
private void queueDataToDecoder() throws IOException { /** Decodes subtitle data and writes samples to the output. */
private void decodeAndWriteToOutput() throws IOException {
checkStateNotNull(this.trackOutput);
try { try {
@Nullable SubtitleInputBuffer inputBuffer = subtitleDecoder.dequeueInputBuffer(); @Nullable SubtitleInputBuffer inputBuffer = subtitleDecoder.dequeueInputBuffer();
while (inputBuffer == null) { while (inputBuffer == null) {
...@@ -196,23 +175,11 @@ public class SubtitleExtractor implements Extractor { ...@@ -196,23 +175,11 @@ public class SubtitleExtractor implements Extractor {
inputBuffer.ensureSpaceForWrite(bytesRead); inputBuffer.ensureSpaceForWrite(bytesRead);
inputBuffer.data.put(subtitleData.getData(), /* offset= */ 0, bytesRead); inputBuffer.data.put(subtitleData.getData(), /* offset= */ 0, bytesRead);
subtitleDecoder.queueInputBuffer(inputBuffer); subtitleDecoder.queueInputBuffer(inputBuffer);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new InterruptedIOException();
} catch (SubtitleDecoderException e) {
throw ParserException.createForMalformedContainer("SubtitleDecoder failed.", e);
}
}
private void writeToOutput() throws IOException {
checkStateNotNull(this.trackOutput);
try {
@Nullable SubtitleOutputBuffer outputBuffer = subtitleDecoder.dequeueOutputBuffer(); @Nullable SubtitleOutputBuffer outputBuffer = subtitleDecoder.dequeueOutputBuffer();
while (outputBuffer == null) { while (outputBuffer == null) {
Thread.sleep(5); Thread.sleep(5);
outputBuffer = subtitleDecoder.dequeueOutputBuffer(); outputBuffer = subtitleDecoder.dequeueOutputBuffer();
} }
for (int i = 0; i < outputBuffer.getEventTimeCount(); i++) { for (int i = 0; i < outputBuffer.getEventTimeCount(); i++) {
List<Cue> cues = outputBuffer.getCues(outputBuffer.getEventTime(i)); List<Cue> cues = outputBuffer.getCues(outputBuffer.getEventTime(i));
byte[] cuesSample = cueEncoder.encode(cues); byte[] cuesSample = cueEncoder.encode(cues);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment