mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Reuse thread in MetadataRetriever
MetadataRetriever is often used in a loop to retrieve data about many items in a directory for example. In such cases, it's wasteful to start a new 'playback' thread for each retrieval, in particular since this thread is doing almost nothing (just triggering loads and handling events). This change re-uses an existing thread if one exists already. PiperOrigin-RevId: 650633343
This commit is contained in:
parent
00d1e70a34
commit
5777e30979
1 changed files with 31 additions and 7 deletions
|
|
@ -17,11 +17,14 @@
|
||||||
package androidx.media3.exoplayer;
|
package androidx.media3.exoplayer;
|
||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.MediaItem;
|
import androidx.media3.common.MediaItem;
|
||||||
|
|
@ -94,8 +97,6 @@ public final class MetadataRetriever {
|
||||||
|
|
||||||
private static ListenableFuture<TrackGroupArray> retrieveMetadata(
|
private static ListenableFuture<TrackGroupArray> retrieveMetadata(
|
||||||
MediaSource.Factory mediaSourceFactory, MediaItem mediaItem, Clock clock) {
|
MediaSource.Factory mediaSourceFactory, MediaItem mediaItem, Clock clock) {
|
||||||
// Recreate thread and handler every time this method is called so that it can be used
|
|
||||||
// concurrently.
|
|
||||||
return new MetadataRetrieverInternal(mediaSourceFactory, clock).retrieveMetadata(mediaItem);
|
return new MetadataRetrieverInternal(mediaSourceFactory, clock).retrieveMetadata(mediaItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,17 +107,17 @@ public final class MetadataRetriever {
|
||||||
private static final int MESSAGE_CONTINUE_LOADING = 3;
|
private static final int MESSAGE_CONTINUE_LOADING = 3;
|
||||||
private static final int MESSAGE_RELEASE = 4;
|
private static final int MESSAGE_RELEASE = 4;
|
||||||
|
|
||||||
|
private static final SharedWorkerThread SHARED_WORKER_THREAD = new SharedWorkerThread();
|
||||||
|
|
||||||
private final MediaSource.Factory mediaSourceFactory;
|
private final MediaSource.Factory mediaSourceFactory;
|
||||||
private final HandlerThread mediaSourceThread;
|
|
||||||
private final HandlerWrapper mediaSourceHandler;
|
private final HandlerWrapper mediaSourceHandler;
|
||||||
private final SettableFuture<TrackGroupArray> trackGroupsFuture;
|
private final SettableFuture<TrackGroupArray> trackGroupsFuture;
|
||||||
|
|
||||||
public MetadataRetrieverInternal(MediaSource.Factory mediaSourceFactory, Clock clock) {
|
public MetadataRetrieverInternal(MediaSource.Factory mediaSourceFactory, Clock clock) {
|
||||||
this.mediaSourceFactory = mediaSourceFactory;
|
this.mediaSourceFactory = mediaSourceFactory;
|
||||||
mediaSourceThread = new HandlerThread("ExoPlayer:MetadataRetriever");
|
Looper workerThreadLooper = SHARED_WORKER_THREAD.addWorker();
|
||||||
mediaSourceThread.start();
|
|
||||||
mediaSourceHandler =
|
mediaSourceHandler =
|
||||||
clock.createHandler(mediaSourceThread.getLooper(), new MediaSourceHandlerCallback());
|
clock.createHandler(workerThreadLooper, new MediaSourceHandlerCallback());
|
||||||
trackGroupsFuture = SettableFuture.create();
|
trackGroupsFuture = SettableFuture.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,7 +173,7 @@ public final class MetadataRetriever {
|
||||||
}
|
}
|
||||||
checkNotNull(mediaSource).releaseSource(mediaSourceCaller);
|
checkNotNull(mediaSource).releaseSource(mediaSourceCaller);
|
||||||
mediaSourceHandler.removeCallbacksAndMessages(/* token= */ null);
|
mediaSourceHandler.removeCallbacksAndMessages(/* token= */ null);
|
||||||
mediaSourceThread.quit();
|
SHARED_WORKER_THREAD.removeWorker();
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -225,4 +226,27 @@ public final class MetadataRetriever {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class SharedWorkerThread {
|
||||||
|
|
||||||
|
@Nullable private HandlerThread mediaSourceThread;
|
||||||
|
private int referenceCount;
|
||||||
|
|
||||||
|
public synchronized Looper addWorker() {
|
||||||
|
if (mediaSourceThread == null) {
|
||||||
|
checkState(referenceCount == 0);
|
||||||
|
mediaSourceThread = new HandlerThread("ExoPlayer:MetadataRetriever");
|
||||||
|
mediaSourceThread.start();
|
||||||
|
}
|
||||||
|
referenceCount++;
|
||||||
|
return mediaSourceThread.getLooper();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void removeWorker() {
|
||||||
|
if (--referenceCount == 0) {
|
||||||
|
checkNotNull(mediaSourceThread).quit();
|
||||||
|
mediaSourceThread = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue