mirror of
https://github.com/samsonjs/media.git
synced 2026-04-18 13:25:47 +00:00
Call onPrepared/onSourceInfoRefreshed on the playback thread.
HlsSampleStreamWrapper and ExtractorMediaPeriod would call onPrepared/onSourceInfoRefreshed from their loading threads. That was problematic for ConcatenatingMediaSource and MergingMediaSource, which assume that their callbacks are called on the same thread (iterating through timelines from all sources and updating pendingTimelineSources respectively). This change makes them post calls to the callbacks on the playback thread. Generally, implementing a composite MediaSource is easier if MediaPeriod.Callback's methods are all called on the same (playback) thread, so this change makes that part of its contract. Also post onContinueLoadingRequested from ExtractingLoadable because MergingMediaPeriod.onContinueLoadingRequested reads trackGroups written on the playback thread. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=134407280
This commit is contained in:
parent
eaf8218855
commit
85b61adb32
5 changed files with 53 additions and 20 deletions
|
|
@ -66,6 +66,9 @@ import java.util.Arrays;
|
|||
private final Loader loader;
|
||||
private final ExtractorHolder extractorHolder;
|
||||
private final ConditionVariable loadCondition;
|
||||
private final Runnable maybeFinishPrepareRunnable;
|
||||
private final Runnable onContinueLoadingRequestedRunnable;
|
||||
private final Handler handler;
|
||||
|
||||
private SeekMap seekMap;
|
||||
private boolean tracksBuilt;
|
||||
|
|
@ -85,6 +88,7 @@ import java.util.Arrays;
|
|||
|
||||
private int extractedSamplesCountAtStartOfLoad;
|
||||
private boolean loadingFinished;
|
||||
private boolean released;
|
||||
|
||||
/**
|
||||
* @param uri The {@link Uri} of the media stream.
|
||||
|
|
@ -100,7 +104,7 @@ import java.util.Arrays;
|
|||
public ExtractorMediaPeriod(Uri uri, DataSource dataSource, Extractor[] extractors,
|
||||
int minLoadableRetryCount, Handler eventHandler,
|
||||
ExtractorMediaSource.EventListener eventListener, MediaSource.Listener sourceListener,
|
||||
Callback callback, Allocator allocator) {
|
||||
final Callback callback, Allocator allocator) {
|
||||
this.uri = uri;
|
||||
this.dataSource = dataSource;
|
||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||
|
|
@ -112,6 +116,21 @@ import java.util.Arrays;
|
|||
loader = new Loader("Loader:ExtractorMediaPeriod");
|
||||
extractorHolder = new ExtractorHolder(extractors, this);
|
||||
loadCondition = new ConditionVariable();
|
||||
maybeFinishPrepareRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
maybeFinishPrepare();
|
||||
}
|
||||
};
|
||||
onContinueLoadingRequestedRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!released) {
|
||||
callback.onContinueLoadingRequested(ExtractorMediaPeriod.this);
|
||||
}
|
||||
}
|
||||
};
|
||||
handler = new Handler();
|
||||
|
||||
pendingResetPositionUs = C.TIME_UNSET;
|
||||
sampleQueues = new DefaultTrackOutput[0];
|
||||
|
|
@ -126,11 +145,13 @@ import java.util.Arrays;
|
|||
@Override
|
||||
public void run() {
|
||||
extractorHolder.release();
|
||||
for (DefaultTrackOutput sampleQueue : sampleQueues) {
|
||||
sampleQueue.disable();
|
||||
}
|
||||
}
|
||||
});
|
||||
for (DefaultTrackOutput sampleQueue : sampleQueues) {
|
||||
sampleQueue.disable();
|
||||
}
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
released = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -330,7 +351,7 @@ import java.util.Arrays;
|
|||
return madeProgress ? Loader.RETRY_RESET_ERROR_COUNT : Loader.RETRY;
|
||||
}
|
||||
|
||||
// ExtractorOutput implementation.
|
||||
// ExtractorOutput implementation. Called by the loading thread.
|
||||
|
||||
@Override
|
||||
public TrackOutput track(int id) {
|
||||
|
|
@ -344,26 +365,26 @@ import java.util.Arrays;
|
|||
@Override
|
||||
public void endTracks() {
|
||||
tracksBuilt = true;
|
||||
maybeFinishPrepare();
|
||||
handler.post(maybeFinishPrepareRunnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seekMap(SeekMap seekMap) {
|
||||
this.seekMap = seekMap;
|
||||
maybeFinishPrepare();
|
||||
handler.post(maybeFinishPrepareRunnable);
|
||||
}
|
||||
|
||||
// UpstreamFormatChangedListener implementation
|
||||
// UpstreamFormatChangedListener implementation. Called by the loading thread.
|
||||
|
||||
@Override
|
||||
public void onUpstreamFormatChanged(Format format) {
|
||||
maybeFinishPrepare();
|
||||
handler.post(maybeFinishPrepareRunnable);
|
||||
}
|
||||
|
||||
// Internal methods.
|
||||
|
||||
private void maybeFinishPrepare() {
|
||||
if (prepared || seekMap == null || !tracksBuilt) {
|
||||
if (released || prepared || seekMap == null || !tracksBuilt) {
|
||||
return;
|
||||
}
|
||||
for (DefaultTrackOutput sampleQueue : sampleQueues) {
|
||||
|
|
@ -576,7 +597,7 @@ import java.util.Arrays;
|
|||
if (input.getPosition() > position + CONTINUE_LOADING_CHECK_INTERVAL_BYTES) {
|
||||
position = input.getPosition();
|
||||
loadCondition.close();
|
||||
callback.onContinueLoadingRequested(ExtractorMediaPeriod.this);
|
||||
handler.post(onContinueLoadingRequestedRunnable);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public interface MediaPeriod extends SequenceableLoader {
|
|||
/**
|
||||
* Called when preparation completes.
|
||||
* <p>
|
||||
* May be called from any thread. After invoking this method, the {@link MediaPeriod} can expect
|
||||
* Called on the playback thread. After invoking this method, the {@link MediaPeriod} can expect
|
||||
* for {@link #selectTracks(TrackSelection[], boolean[], SampleStream[], boolean[], long)} to be
|
||||
* called with the initial track selection.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public interface SequenceableLoader {
|
|||
|
||||
/**
|
||||
* Called by the loader to indicate that it wishes for its {@link #continueLoading(long)} method
|
||||
* to be called when it can continue to load data.
|
||||
* to be called when it can continue to load data. Called on the playback thread.
|
||||
*/
|
||||
void onContinueLoadingRequested(T source);
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ import java.util.List;
|
|||
private final Handler continueLoadingHandler;
|
||||
private final Loader manifestFetcher;
|
||||
private final long preparePositionUs;
|
||||
private final Runnable continueLoadingRunnable;
|
||||
|
||||
private int pendingPrepareCount;
|
||||
private HlsPlaylist playlist;
|
||||
|
|
@ -72,7 +73,6 @@ import java.util.List;
|
|||
private HlsSampleStreamWrapper[] sampleStreamWrappers;
|
||||
private HlsSampleStreamWrapper[] enabledSampleStreamWrappers;
|
||||
private CompositeSequenceableLoader sequenceableLoader;
|
||||
private Runnable continueLoadingRunnable;
|
||||
|
||||
public HlsMediaPeriod(Uri manifestUri, DataSource.Factory dataSourceFactory,
|
||||
int minLoadableRetryCount, EventDispatcher eventDispatcher,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.source.hls;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
import android.util.SparseArray;
|
||||
import com.google.android.exoplayer2.C;
|
||||
|
|
@ -81,13 +82,15 @@ import java.util.LinkedList;
|
|||
private final HlsChunkSource.HlsChunkHolder nextChunkHolder;
|
||||
private final SparseArray<DefaultTrackOutput> sampleQueues;
|
||||
private final LinkedList<HlsMediaChunk> mediaChunks;
|
||||
private final Runnable maybeFinishPrepareRunnable;
|
||||
private final Handler handler;
|
||||
|
||||
private volatile boolean sampleQueuesBuilt;
|
||||
|
||||
private boolean sampleQueuesBuilt;
|
||||
private boolean prepared;
|
||||
private int enabledTrackCount;
|
||||
private Format downstreamTrackFormat;
|
||||
private int upstreamChunkUid;
|
||||
private boolean released;
|
||||
|
||||
// Tracks are complicated in HLS. See documentation of buildTracks for details.
|
||||
// Indexed by track (as exposed by this source).
|
||||
|
|
@ -130,6 +133,13 @@ import java.util.LinkedList;
|
|||
nextChunkHolder = new HlsChunkSource.HlsChunkHolder();
|
||||
sampleQueues = new SparseArray<>();
|
||||
mediaChunks = new LinkedList<>();
|
||||
maybeFinishPrepareRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
maybeFinishPrepare();
|
||||
}
|
||||
};
|
||||
handler = new Handler();
|
||||
lastSeekPositionUs = positionUs;
|
||||
pendingResetPositionUs = positionUs;
|
||||
}
|
||||
|
|
@ -255,6 +265,8 @@ import java.util.LinkedList;
|
|||
sampleQueues.valueAt(i).disable();
|
||||
}
|
||||
loader.release();
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
released = true;
|
||||
}
|
||||
|
||||
public long getLargestQueuedTimestampUs() {
|
||||
|
|
@ -464,7 +476,7 @@ import java.util.LinkedList;
|
|||
@Override
|
||||
public void endTracks() {
|
||||
sampleQueuesBuilt = true;
|
||||
maybeFinishPrepare();
|
||||
handler.post(maybeFinishPrepareRunnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -472,17 +484,17 @@ import java.util.LinkedList;
|
|||
// Do nothing.
|
||||
}
|
||||
|
||||
// UpstreamFormatChangedListener implementation.
|
||||
// UpstreamFormatChangedListener implementation. Called by the loading thread.
|
||||
|
||||
@Override
|
||||
public void onUpstreamFormatChanged(Format format) {
|
||||
maybeFinishPrepare();
|
||||
handler.post(maybeFinishPrepareRunnable);
|
||||
}
|
||||
|
||||
// Internal methods.
|
||||
|
||||
private void maybeFinishPrepare() {
|
||||
if (prepared || !sampleQueuesBuilt) {
|
||||
if (released || prepared || !sampleQueuesBuilt) {
|
||||
return;
|
||||
}
|
||||
int sampleQueueCount = sampleQueues.size();
|
||||
|
|
|
|||
Loading…
Reference in a new issue