mirror of
https://github.com/samsonjs/media.git
synced 2026-03-26 09:35:47 +00:00
commit
5abb413f4e
3 changed files with 51 additions and 30 deletions
|
|
@ -673,7 +673,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
|||
@Override
|
||||
protected boolean isReady() {
|
||||
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 {
|
|||
|
||||
private static final int NO_RESET_PENDING = -1;
|
||||
|
||||
private static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 1;
|
||||
|
||||
private final int eventSourceId;
|
||||
private final LoadControl loadControl;
|
||||
private final ChunkSource chunkSource;
|
||||
|
|
@ -150,6 +152,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
|
|||
private final boolean frameAccurateSeeking;
|
||||
private final Handler eventHandler;
|
||||
private final EventListener eventListener;
|
||||
private final int minLoadableRetryCount;
|
||||
|
||||
private int state;
|
||||
private long downstreamPositionUs;
|
||||
|
|
@ -175,6 +178,13 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
|
|||
public ChunkSampleSource(ChunkSource chunkSource, LoadControl loadControl,
|
||||
int bufferSizeContribution, boolean frameAccurateSeeking, Handler eventHandler,
|
||||
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.loadControl = loadControl;
|
||||
this.bufferSizeContribution = bufferSizeContribution;
|
||||
|
|
@ -182,6 +192,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
|
|||
this.eventHandler = eventHandler;
|
||||
this.eventListener = eventListener;
|
||||
this.eventSourceId = eventSourceId;
|
||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||
currentLoadableHolder = new ChunkOperationHolder();
|
||||
mediaChunks = new LinkedList<MediaChunk>();
|
||||
readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks);
|
||||
|
|
@ -287,9 +298,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
|
|||
|
||||
downstreamPositionUs = positionUs;
|
||||
if (isPendingReset()) {
|
||||
if (currentLoadableException != null) {
|
||||
throw currentLoadableException;
|
||||
}
|
||||
maybeThrowLoadableException();
|
||||
IOException chunkSourceException = chunkSource.getError();
|
||||
if (chunkSourceException != null) {
|
||||
throw chunkSourceException;
|
||||
|
|
@ -342,9 +351,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
|
|||
onSampleRead(mediaChunk, sampleHolder);
|
||||
return SAMPLE_READ;
|
||||
} else {
|
||||
if (currentLoadableException != null) {
|
||||
throw currentLoadableException;
|
||||
}
|
||||
maybeThrowLoadableException();
|
||||
return NOTHING_READ;
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
Iterator<MediaChunk> mediaChunkIterator = mediaChunks.iterator();
|
||||
while (mediaChunkIterator.hasNext()) {
|
||||
|
|
|
|||
|
|
@ -53,8 +53,13 @@ public class WebvttParser implements SubtitleParser {
|
|||
|
||||
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 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 = Pattern.compile("MPEGTS:\\d+");
|
||||
|
||||
|
|
@ -90,30 +95,33 @@ public class WebvttParser implements SubtitleParser {
|
|||
throw new ParserException("Expected WEBVTT. Got " + line);
|
||||
}
|
||||
|
||||
// after "WEBVTT" there should be either an empty line or an "X-TIMESTAMP-MAP" line and then
|
||||
// and empty line
|
||||
line = webvttData.readLine();
|
||||
if (!line.isEmpty()) {
|
||||
if (!line.startsWith("X-TIMESTAMP-MAP")) {
|
||||
throw new ParserException("Expected an empty line or X-TIMESTAMP-MAP. Got " + line);
|
||||
}
|
||||
|
||||
// parse the media timestamp
|
||||
Matcher matcher = MEDIA_TIMESTAMP.matcher(line);
|
||||
if (!matcher.find()) {
|
||||
throw new ParserException("X-TIMESTAMP-MAP doesn't contain media timestmap: " + 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)
|
||||
// parse the remainder of the header
|
||||
while (true) {
|
||||
line = webvttData.readLine();
|
||||
}
|
||||
if (!line.isEmpty()) {
|
||||
throw new ParserException("Expected an empty line after WEBVTT or X-TIMESTAMP-MAP. Got "
|
||||
+ line);
|
||||
if (line == null) {
|
||||
// we reached EOF before finishing the header
|
||||
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;
|
||||
}
|
||||
|
||||
Matcher matcher = WEBVTT_METADATA_HEADER.matcher(line);
|
||||
if (!matcher.find()) {
|
||||
throw new ParserException("Expected webvtt metadata header; got: " + line);
|
||||
}
|
||||
|
||||
if (line.startsWith("X-TIMESTAMP-MAP")) {
|
||||
// parse the media timestamp
|
||||
Matcher timestampMatcher = MEDIA_TIMESTAMP.matcher(line);
|
||||
if (!timestampMatcher.find()) {
|
||||
throw new ParserException("X-TIMESTAMP-MAP doesn't contain media timestamp: " + line);
|
||||
} else {
|
||||
mediaTimestampUs = (Long.parseLong(timestampMatcher.group().substring(7)) * 1000)
|
||||
/ SAMPLING_RATE - mediaTimestampOffsetUs;
|
||||
}
|
||||
mediaTimestampUs = getAdjustedStartTime(mediaTimestampUs);
|
||||
}
|
||||
}
|
||||
|
||||
// process the cues and text
|
||||
|
|
|
|||
Loading…
Reference in a new issue