The actual fix here is to not call discardExtractors in HlsSampleSource whilst the loading thread that's pushing data into it is still running. It's required to wait for that thread to have exited before doing this. Issue: #159
This commit is contained in:
parent
8c07847b00
commit
81e2c9f0d3
@ -138,9 +138,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
|
||||
if (loader.isLoading()) {
|
||||
loader.cancelLoading();
|
||||
} else {
|
||||
discardExtractors();
|
||||
clearCurrentLoadable();
|
||||
previousTsLoadable = null;
|
||||
clearState();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -186,7 +184,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
|
||||
TsExtractor extractor = extractors.getFirst();
|
||||
while (extractors.size() > 1 && !extractor.hasSamples()) {
|
||||
// We're finished reading from the extractor for all tracks, and so can discard it.
|
||||
extractors.removeFirst().clear();
|
||||
extractors.removeFirst().release();
|
||||
extractor = extractors.getFirst();
|
||||
}
|
||||
|
||||
@ -294,11 +292,10 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
|
||||
|
||||
@Override
|
||||
public void onLoadCanceled(Loadable loadable) {
|
||||
clearCurrentLoadable();
|
||||
if (enabledTrackCount > 0) {
|
||||
restartFrom(pendingResetPositionUs);
|
||||
} else {
|
||||
previousTsLoadable = null;
|
||||
clearState();
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,17 +309,24 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
|
||||
|
||||
private void restartFrom(long positionUs) {
|
||||
pendingResetPositionUs = positionUs;
|
||||
previousTsLoadable = null;
|
||||
loadingFinished = false;
|
||||
discardExtractors();
|
||||
if (loader.isLoading()) {
|
||||
loader.cancelLoading();
|
||||
} else {
|
||||
clearCurrentLoadable();
|
||||
clearState();
|
||||
maybeStartLoading();
|
||||
}
|
||||
}
|
||||
|
||||
private void clearState() {
|
||||
for (int i = 0; i < extractors.size(); i++) {
|
||||
extractors.get(i).release();
|
||||
}
|
||||
extractors.clear();
|
||||
clearCurrentLoadable();
|
||||
previousTsLoadable = null;
|
||||
}
|
||||
|
||||
private void clearCurrentLoadable() {
|
||||
currentLoadable = null;
|
||||
currentLoadableException = null;
|
||||
@ -370,13 +374,6 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
|
||||
loader.startLoading(currentLoadable, this);
|
||||
}
|
||||
|
||||
private void discardExtractors() {
|
||||
for (int i = 0; i < extractors.size(); i++) {
|
||||
extractors.get(i).clear();
|
||||
}
|
||||
extractors.clear();
|
||||
}
|
||||
|
||||
private boolean isTsChunk(HlsChunk chunk) {
|
||||
return chunk instanceof TsChunk;
|
||||
}
|
||||
|
@ -58,12 +58,16 @@ public final class TsExtractor {
|
||||
private final SamplePool samplePool;
|
||||
/* package */ final long firstSampleTimestamp;
|
||||
|
||||
private boolean prepared;
|
||||
// Accessed only by the consuming thread.
|
||||
private boolean spliceConfigured;
|
||||
|
||||
// Accessed only by the loading thread.
|
||||
/* package */ boolean pendingFirstSampleTimestampAdjustment;
|
||||
/* package */ long sampleTimestampOffsetUs;
|
||||
/* package */ long largestParsedTimestampUs;
|
||||
|
||||
// Accessed by both the loading and consuming threads.
|
||||
private volatile boolean prepared;
|
||||
/* package */ volatile long largestParsedTimestampUs;
|
||||
|
||||
public TsExtractor(long firstSampleTimestamp, SamplePool samplePool) {
|
||||
this.firstSampleTimestamp = firstSampleTimestamp;
|
||||
@ -111,11 +115,13 @@ public final class TsExtractor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes any pending or incomplete samples, returning them to the sample pool.
|
||||
* Releases the extractor, recycling any pending or incomplete samples to the sample pool.
|
||||
* <p>
|
||||
* This method should not be called whilst {@link #read(DataSource)} is also being invoked.
|
||||
*/
|
||||
public void clear() {
|
||||
public void release() {
|
||||
for (int i = 0; i < sampleQueues.size(); i++) {
|
||||
sampleQueues.valueAt(i).clear();
|
||||
sampleQueues.valueAt(i).release();
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,16 +510,19 @@ public final class TsExtractor {
|
||||
private final SamplePool samplePool;
|
||||
private final ConcurrentLinkedQueue<Sample> internalQueue;
|
||||
|
||||
private MediaFormat mediaFormat;
|
||||
private long spliceOutTimeUs;
|
||||
private long lastParsedTimestampUs;
|
||||
// Accessed only by the consuming thread.
|
||||
private boolean readFirstFrame;
|
||||
private long lastReadTimeUs;
|
||||
private long spliceOutTimeUs;
|
||||
|
||||
// Accessed by both the loading and consuming threads.
|
||||
private volatile MediaFormat mediaFormat;
|
||||
|
||||
protected SampleQueue(SamplePool samplePool) {
|
||||
this.samplePool = samplePool;
|
||||
internalQueue = new ConcurrentLinkedQueue<Sample>();
|
||||
spliceOutTimeUs = Long.MIN_VALUE;
|
||||
lastParsedTimestampUs = Long.MIN_VALUE;
|
||||
lastReadTimeUs = Long.MIN_VALUE;
|
||||
}
|
||||
|
||||
public boolean hasMediaFormat() {
|
||||
@ -541,6 +550,7 @@ public final class TsExtractor {
|
||||
if (head != null) {
|
||||
internalQueue.remove();
|
||||
readFirstFrame = true;
|
||||
lastReadTimeUs = head.timeUs;
|
||||
}
|
||||
return head;
|
||||
}
|
||||
@ -575,7 +585,7 @@ public final class TsExtractor {
|
||||
/**
|
||||
* Clears the queue.
|
||||
*/
|
||||
public void clear() {
|
||||
public void release() {
|
||||
Sample toRecycle = internalQueue.poll();
|
||||
while (toRecycle != null) {
|
||||
recycle(toRecycle);
|
||||
@ -608,7 +618,7 @@ public final class TsExtractor {
|
||||
if (nextSample != null) {
|
||||
firstPossibleSpliceTime = nextSample.timeUs;
|
||||
} else {
|
||||
firstPossibleSpliceTime = lastParsedTimestampUs + 1;
|
||||
firstPossibleSpliceTime = lastReadTimeUs + 1;
|
||||
}
|
||||
ConcurrentLinkedQueue<Sample> nextInternalQueue = nextQueue.internalQueue;
|
||||
Sample nextQueueSample = nextInternalQueue.peek();
|
||||
@ -656,7 +666,6 @@ public final class TsExtractor {
|
||||
|
||||
protected void addSample(Sample sample) {
|
||||
adjustTimestamp(sample);
|
||||
lastParsedTimestampUs = sample.timeUs;
|
||||
largestParsedTimestampUs = Math.max(largestParsedTimestampUs, sample.timeUs);
|
||||
internalQueue.add(sample);
|
||||
}
|
||||
@ -712,8 +721,8 @@ public final class TsExtractor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
public void release() {
|
||||
super.release();
|
||||
if (currentSample != null) {
|
||||
recycle(currentSample);
|
||||
currentSample = null;
|
||||
@ -1057,8 +1066,8 @@ public final class TsExtractor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
public void release() {
|
||||
super.release();
|
||||
adtsBuffer.reset();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user