Commit 5abb413f by ojw28

Merge pull request #127 from google/dev

dev -> dev-l
parents e6c7e296 1653e816
...@@ -673,7 +673,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { ...@@ -673,7 +673,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
@Override @Override
protected boolean isReady() { protected boolean isReady() {
return format != null && !waitingForKeys return format != null && !waitingForKeys
&& sourceState != SOURCE_STATE_NOT_READY || outputIndex >= 0 || isWithinHotswapPeriod(); && (sourceState != SOURCE_STATE_NOT_READY || outputIndex >= 0 || isWithinHotswapPeriod());
} }
/** /**
......
...@@ -140,6 +140,8 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback { ...@@ -140,6 +140,8 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
private static final int NO_RESET_PENDING = -1; private static final int NO_RESET_PENDING = -1;
private static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 1;
private final int eventSourceId; private final int eventSourceId;
private final LoadControl loadControl; private final LoadControl loadControl;
private final ChunkSource chunkSource; private final ChunkSource chunkSource;
...@@ -150,6 +152,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback { ...@@ -150,6 +152,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
private final boolean frameAccurateSeeking; private final boolean frameAccurateSeeking;
private final Handler eventHandler; private final Handler eventHandler;
private final EventListener eventListener; private final EventListener eventListener;
private final int minLoadableRetryCount;
private int state; private int state;
private long downstreamPositionUs; private long downstreamPositionUs;
...@@ -175,6 +178,13 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback { ...@@ -175,6 +178,13 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
public ChunkSampleSource(ChunkSource chunkSource, LoadControl loadControl, public ChunkSampleSource(ChunkSource chunkSource, LoadControl loadControl,
int bufferSizeContribution, boolean frameAccurateSeeking, Handler eventHandler, int bufferSizeContribution, boolean frameAccurateSeeking, Handler eventHandler,
EventListener eventListener, int eventSourceId) { EventListener eventListener, int eventSourceId) {
this(chunkSource, loadControl, bufferSizeContribution, frameAccurateSeeking, eventHandler,
eventListener, eventSourceId, DEFAULT_MIN_LOADABLE_RETRY_COUNT);
}
public ChunkSampleSource(ChunkSource chunkSource, LoadControl loadControl,
int bufferSizeContribution, boolean frameAccurateSeeking, Handler eventHandler,
EventListener eventListener, int eventSourceId, int minLoadableRetryCount) {
this.chunkSource = chunkSource; this.chunkSource = chunkSource;
this.loadControl = loadControl; this.loadControl = loadControl;
this.bufferSizeContribution = bufferSizeContribution; this.bufferSizeContribution = bufferSizeContribution;
...@@ -182,6 +192,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback { ...@@ -182,6 +192,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
this.eventHandler = eventHandler; this.eventHandler = eventHandler;
this.eventListener = eventListener; this.eventListener = eventListener;
this.eventSourceId = eventSourceId; this.eventSourceId = eventSourceId;
this.minLoadableRetryCount = minLoadableRetryCount;
currentLoadableHolder = new ChunkOperationHolder(); currentLoadableHolder = new ChunkOperationHolder();
mediaChunks = new LinkedList<MediaChunk>(); mediaChunks = new LinkedList<MediaChunk>();
readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks); readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks);
...@@ -287,9 +298,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback { ...@@ -287,9 +298,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
downstreamPositionUs = positionUs; downstreamPositionUs = positionUs;
if (isPendingReset()) { if (isPendingReset()) {
if (currentLoadableException != null) { maybeThrowLoadableException();
throw currentLoadableException;
}
IOException chunkSourceException = chunkSource.getError(); IOException chunkSourceException = chunkSource.getError();
if (chunkSourceException != null) { if (chunkSourceException != null) {
throw chunkSourceException; throw chunkSourceException;
...@@ -342,9 +351,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback { ...@@ -342,9 +351,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
onSampleRead(mediaChunk, sampleHolder); onSampleRead(mediaChunk, sampleHolder);
return SAMPLE_READ; return SAMPLE_READ;
} else { } else {
if (currentLoadableException != null) { maybeThrowLoadableException();
throw currentLoadableException;
}
return NOTHING_READ; return NOTHING_READ;
} }
} }
...@@ -369,6 +376,12 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback { ...@@ -369,6 +376,12 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
} }
} }
private void maybeThrowLoadableException() throws IOException {
if (currentLoadableException != null && currentLoadableExceptionCount > minLoadableRetryCount) {
throw currentLoadableException;
}
}
private MediaChunk getMediaChunk(long positionUs) { private MediaChunk getMediaChunk(long positionUs) {
Iterator<MediaChunk> mediaChunkIterator = mediaChunks.iterator(); Iterator<MediaChunk> mediaChunkIterator = mediaChunks.iterator();
while (mediaChunkIterator.hasNext()) { while (mediaChunkIterator.hasNext()) {
......
...@@ -53,8 +53,13 @@ public class WebvttParser implements SubtitleParser { ...@@ -53,8 +53,13 @@ public class WebvttParser implements SubtitleParser {
private static final long SAMPLING_RATE = 90; private static final long SAMPLING_RATE = 90;
private static final String WEBVTT_METADATA_HEADER_STRING = "\\S*[:=]\\S*";
private static final Pattern WEBVTT_METADATA_HEADER =
Pattern.compile(WEBVTT_METADATA_HEADER_STRING);
private static final String WEBVTT_TIMESTAMP_STRING = "(\\d+:)?[0-5]\\d:[0-5]\\d\\.\\d{3}"; private static final String WEBVTT_TIMESTAMP_STRING = "(\\d+:)?[0-5]\\d:[0-5]\\d\\.\\d{3}";
private static final Pattern WEBVTT_TIMESTAMP = Pattern.compile(WEBVTT_TIMESTAMP_STRING); private static final Pattern WEBVTT_TIMESTAMP = Pattern.compile(WEBVTT_TIMESTAMP_STRING);
private static final Pattern MEDIA_TIMESTAMP_OFFSET = Pattern.compile(OFFSET + "\\d+"); private static final Pattern MEDIA_TIMESTAMP_OFFSET = Pattern.compile(OFFSET + "\\d+");
private static final Pattern MEDIA_TIMESTAMP = Pattern.compile("MPEGTS:\\d+"); private static final Pattern MEDIA_TIMESTAMP = Pattern.compile("MPEGTS:\\d+");
...@@ -90,30 +95,33 @@ public class WebvttParser implements SubtitleParser { ...@@ -90,30 +95,33 @@ public class WebvttParser implements SubtitleParser {
throw new ParserException("Expected WEBVTT. Got " + line); throw new ParserException("Expected WEBVTT. Got " + line);
} }
// after "WEBVTT" there should be either an empty line or an "X-TIMESTAMP-MAP" line and then // parse the remainder of the header
// and empty line while (true) {
line = webvttData.readLine(); line = webvttData.readLine();
if (!line.isEmpty()) { if (line == null) {
if (!line.startsWith("X-TIMESTAMP-MAP")) { // we reached EOF before finishing the header
throw new ParserException("Expected an empty line or X-TIMESTAMP-MAP. Got " + line); throw new ParserException("Expected an empty line after webvtt header");
} else if (line.isEmpty()) {
// we've read the newline that separates the header from the body
break;
} }
// parse the media timestamp Matcher matcher = WEBVTT_METADATA_HEADER.matcher(line);
Matcher matcher = MEDIA_TIMESTAMP.matcher(line);
if (!matcher.find()) { if (!matcher.find()) {
throw new ParserException("X-TIMESTAMP-MAP doesn't contain media timestmap: " + line); throw new ParserException("Expected webvtt metadata header; got: " + line);
} else {
mediaTimestampUs = (Long.parseLong(matcher.group().substring(7)) * 1000) / SAMPLING_RATE
- mediaTimestampOffsetUs;
} }
mediaTimestampUs = getAdjustedStartTime(mediaTimestampUs);
// read in the next line (which should be an empty line) if (line.startsWith("X-TIMESTAMP-MAP")) {
line = webvttData.readLine(); // parse the media timestamp
} Matcher timestampMatcher = MEDIA_TIMESTAMP.matcher(line);
if (!line.isEmpty()) { if (!timestampMatcher.find()) {
throw new ParserException("Expected an empty line after WEBVTT or X-TIMESTAMP-MAP. Got " throw new ParserException("X-TIMESTAMP-MAP doesn't contain media timestamp: " + line);
+ line); } else {
mediaTimestampUs = (Long.parseLong(timestampMatcher.group().substring(7)) * 1000)
/ SAMPLING_RATE - mediaTimestampOffsetUs;
}
mediaTimestampUs = getAdjustedStartTime(mediaTimestampUs);
}
} }
// process the cues and text // process the cues and text
......
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