DefaultExtractorsFactory: lazily load flac extension

PiperOrigin-RevId: 406332026
This commit is contained in:
christosts 2021-10-29 12:34:43 +01:00 committed by bachinger
parent dacdf5c42d
commit 8acce1b5c2

View file

@ -19,6 +19,7 @@ import static com.google.android.exoplayer2.util.FileTypes.inferFileTypeFromResp
import static com.google.android.exoplayer2.util.FileTypes.inferFileTypeFromUri;
import android.net.Uri;
import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
@ -46,6 +47,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* An {@link ExtractorsFactory} that provides an array of extractors for the following formats:
@ -99,32 +101,7 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
FileTypes.JPEG,
};
@Nullable
private static final Constructor<? extends Extractor> FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR;
static {
@Nullable Constructor<? extends Extractor> flacExtensionExtractorConstructor = null;
try {
@SuppressWarnings("nullness:argument")
boolean isFlacNativeLibraryAvailable =
Boolean.TRUE.equals(
Class.forName("com.google.android.exoplayer2.ext.flac.FlacLibrary")
.getMethod("isAvailable")
.invoke(/* obj= */ null));
if (isFlacNativeLibraryAvailable) {
flacExtensionExtractorConstructor =
Class.forName("com.google.android.exoplayer2.ext.flac.FlacExtractor")
.asSubclass(Extractor.class)
.getConstructor(int.class);
}
} catch (ClassNotFoundException e) {
// Expected if the app was built without the FLAC extension.
} catch (Exception e) {
// The FLAC extension is present, but instantiation failed.
throw new RuntimeException("Error instantiating FLAC extension", e);
}
FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR = flacExtensionExtractorConstructor;
}
private static final FlacExtensionLoader FLAC_EXTENSION_LOADER = new FlacExtensionLoader();
private boolean constantBitrateSeekingEnabled;
private boolean constantBitrateSeekingAlwaysEnabled;
@ -377,13 +354,9 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
: 0)));
break;
case FileTypes.FLAC:
if (FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR != null) {
try {
extractors.add(FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR.newInstance(flacFlags));
} catch (Exception e) {
// Should never happen.
throw new IllegalStateException("Unexpected error creating FLAC extractor", e);
}
@Nullable Extractor flacExtractor = FLAC_EXTENSION_LOADER.getExtractor(flacFlags);
if (flacExtractor != null) {
extractors.add(flacExtractor);
} else {
extractors.add(new FlacExtractor(flacFlags));
}
@ -430,4 +403,60 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
break;
}
}
private static final class FlacExtensionLoader {
private final AtomicBoolean extensionLoaded;
@GuardedBy("extensionLoaded")
@Nullable
private Constructor<? extends Extractor> extractorConstructor;
public FlacExtensionLoader() {
extensionLoaded = new AtomicBoolean(false);
}
@Nullable
public Extractor getExtractor(int flags) {
@Nullable
Constructor<? extends Extractor> extractorConstructor = maybeLoadExtractorConstructor();
if (extractorConstructor == null) {
return null;
}
try {
return extractorConstructor.newInstance(flags);
} catch (Exception e) {
throw new IllegalStateException("Unexpected error creating FLAC extractor", e);
}
}
@Nullable
private Constructor<? extends Extractor> maybeLoadExtractorConstructor() {
synchronized (extensionLoaded) {
if (extensionLoaded.get()) {
return extractorConstructor;
}
try {
@SuppressWarnings("nullness:argument")
boolean isFlacNativeLibraryAvailable =
Boolean.TRUE.equals(
Class.forName("com.google.android.exoplayer2.ext.flac.FlacLibrary")
.getMethod("isAvailable")
.invoke(/* obj= */ null));
if (isFlacNativeLibraryAvailable) {
extractorConstructor =
Class.forName("com.google.android.exoplayer2.ext.flac.FlacExtractor")
.asSubclass(Extractor.class)
.getConstructor(int.class);
}
} catch (ClassNotFoundException e) {
// Expected if the app was built without the FLAC extension.
} catch (Exception e) {
// The FLAC extension is present, but instantiation failed.
throw new RuntimeException("Error instantiating FLAC extension", e);
}
extensionLoaded.set(true);
return extractorConstructor;
}
}
}
}