Fix retries if failure occurrs when reading seek map.

The following sequence was problematic:

1. See start of a cluster having not output a seek map. Decide
   to seek for the cues. Enter CUES_STATE_BUILDING state.
2. Error occurs before seek map is output.
3. ExtractorSampleSource isn't prepared yet, so restarts from the
   start of the stream.
4. See start of the same cluster having not output a seek map.
   This time cuesState is CUES_STATE_BUILDING, so we just carry
   on. We then fill the buffer with sample data, despite the
   source not being prepared, at which point we get stuck.

It's unclear to me why cuesState needed three states, so I've rm'd
the BUILDING state. Step (4) above will now do the same thing as
in step (1). If the failure repeats, we'll eventually fail, which
is WAI.
This commit is contained in:
Oliver Woodman 2015-09-01 14:03:45 +01:00
parent b3ba7e16c1
commit 009d4d0c2c

View file

@ -59,10 +59,6 @@ public final class WebmExtractor implements Extractor {
private static final int BLOCK_STATE_HEADER = 1;
private static final int BLOCK_STATE_DATA = 2;
private static final int CUES_STATE_NOT_BUILT = 0;
private static final int CUES_STATE_BUILDING = 1;
private static final int CUES_STATE_BUILT = 2;
private static final String DOC_TYPE_WEBM = "webm";
private static final String DOC_TYPE_MATROSKA = "matroska";
private static final String CODEC_ID_VP8 = "V_VP8";
@ -164,6 +160,7 @@ public final class WebmExtractor implements Extractor {
// Whether drm init data has been sent to the output.
private boolean sentDrmInitData;
private boolean sentSeekMap;
// Master seek entry related elements.
private int seekEntryId;
@ -173,7 +170,6 @@ public final class WebmExtractor implements Extractor {
private boolean seekForCues;
private long cuesContentPosition = UNKNOWN;
private long seekPositionAfterBuildingCues = UNKNOWN;
private int cuesState = CUES_STATE_NOT_BUILT;
private long clusterTimecodeUs = UNKNOWN;
private LongArray cueTimesUs;
private LongArray cueClusterPositions;
@ -335,7 +331,7 @@ public final class WebmExtractor implements Extractor {
seenClusterPositionForCurrentCuePoint = false;
return;
case ID_CLUSTER:
if (cuesState == CUES_STATE_NOT_BUILT) {
if (!sentSeekMap) {
// We need to build cues before parsing the cluster.
if (cuesContentPosition != UNKNOWN) {
// We know where the Cues element is located. Seek to request it.
@ -344,7 +340,7 @@ public final class WebmExtractor implements Extractor {
// We don't know where the Cues element is located. It's most likely omitted. Allow
// playback, but disable seeking.
extractorOutput.seekMap(SeekMap.UNSEEKABLE);
cuesState = CUES_STATE_BUILT;
sentSeekMap = true;
}
}
return;
@ -385,9 +381,9 @@ public final class WebmExtractor implements Extractor {
}
return;
case ID_CUES:
if (cuesState != CUES_STATE_BUILT) {
if (!sentSeekMap) {
extractorOutput.seekMap(buildSeekMap());
cuesState = CUES_STATE_BUILT;
sentSeekMap = true;
} else {
// We have already built the cues. Ignore.
}
@ -920,13 +916,12 @@ public final class WebmExtractor implements Extractor {
if (seekForCues) {
seekPositionAfterBuildingCues = currentPosition;
seekPosition.position = cuesContentPosition;
cuesState = CUES_STATE_BUILDING;
seekForCues = false;
return true;
}
// After parsing Cues, Seek back to original position if available. We will not do this unless
// After parsing Cues, seek back to original position if available. We will not do this unless
// we seeked to get to the Cues in the first place.
if (cuesState == CUES_STATE_BUILT && seekPositionAfterBuildingCues != UNKNOWN) {
if (sentSeekMap && seekPositionAfterBuildingCues != UNKNOWN) {
seekPosition.position = seekPositionAfterBuildingCues;
seekPositionAfterBuildingCues = UNKNOWN;
return true;