Commit 8acce1b5 by christosts Committed by bachinger

DefaultExtractorsFactory: lazily load flac extension

PiperOrigin-RevId: 406332026
parent dacdf5c4
...@@ -19,6 +19,7 @@ import static com.google.android.exoplayer2.util.FileTypes.inferFileTypeFromResp ...@@ -19,6 +19,7 @@ import static com.google.android.exoplayer2.util.FileTypes.inferFileTypeFromResp
import static com.google.android.exoplayer2.util.FileTypes.inferFileTypeFromUri; import static com.google.android.exoplayer2.util.FileTypes.inferFileTypeFromUri;
import android.net.Uri; import android.net.Uri;
import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
...@@ -46,6 +47,7 @@ import java.util.ArrayList; ...@@ -46,6 +47,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
/** /**
* An {@link ExtractorsFactory} that provides an array of extractors for the following formats: * An {@link ExtractorsFactory} that provides an array of extractors for the following formats:
...@@ -99,32 +101,7 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory { ...@@ -99,32 +101,7 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
FileTypes.JPEG, FileTypes.JPEG,
}; };
@Nullable private static final FlacExtensionLoader FLAC_EXTENSION_LOADER = new FlacExtensionLoader();
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 boolean constantBitrateSeekingEnabled; private boolean constantBitrateSeekingEnabled;
private boolean constantBitrateSeekingAlwaysEnabled; private boolean constantBitrateSeekingAlwaysEnabled;
...@@ -377,13 +354,9 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory { ...@@ -377,13 +354,9 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
: 0))); : 0)));
break; break;
case FileTypes.FLAC: case FileTypes.FLAC:
if (FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR != null) { @Nullable Extractor flacExtractor = FLAC_EXTENSION_LOADER.getExtractor(flacFlags);
try { if (flacExtractor != null) {
extractors.add(FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR.newInstance(flacFlags)); extractors.add(flacExtractor);
} catch (Exception e) {
// Should never happen.
throw new IllegalStateException("Unexpected error creating FLAC extractor", e);
}
} else { } else {
extractors.add(new FlacExtractor(flacFlags)); extractors.add(new FlacExtractor(flacFlags));
} }
...@@ -430,4 +403,60 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory { ...@@ -430,4 +403,60 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
break; 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;
}
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment