Skip to content

Commit

Permalink
implement reusable saf urls, fixes #911
Browse files Browse the repository at this point in the history
  • Loading branch information
tanersener committed Apr 14, 2024
1 parent b4130e7 commit c6e08c0
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -46,6 +48,7 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

Expand Down Expand Up @@ -128,6 +131,7 @@ public ParcelFileDescriptor getParcelFileDescriptor() {
private static final SparseArray<SAFProtocolUrl> safIdMap;
private static final SparseArray<SAFProtocolUrl> safFileDescriptorMap;
private static LogRedirectionStrategy globalLogRedirectionStrategy;
private static final AtomicBoolean safUrlsReusable;

static {

Expand Down Expand Up @@ -172,6 +176,7 @@ protected boolean removeEldestEntry(Map.Entry<Long, Session> eldest) {
safIdMap = new SparseArray<>();
safFileDescriptorMap = new SparseArray<>();
globalLogRedirectionStrategy = LogRedirectionStrategy.PRINT_LOGS_WHEN_NO_CALLBACKS_DEFINED;
safUrlsReusable = new AtomicBoolean(false);

android.util.Log.i(FFmpegKitConfig.TAG, String.format("Loaded ffmpeg-kit-%s-%s-%s-%s.", NativeLoader.loadPackageName(), NativeLoader.loadAbi(), NativeLoader.loadVersion(), NativeLoader.loadBuildDate()));
}
Expand Down Expand Up @@ -487,7 +492,8 @@ public static void setFontDirectoryList(final Context context, final List<String
/**
* <p>Creates a new named pipe to use in <code>FFmpeg</code> operations.
*
* <p>Please note that creator is responsible of closing created pipes.
* <p>Please note that creator is responsible of closing created pipes via the
* {@link #closeFFmpegPipe} method.
*
* @param context application context
* @return the full path of the named pipe
Expand Down Expand Up @@ -1029,6 +1035,7 @@ private static int safOpen(final int safId) {
safUrl.setParcelFileDescriptor(parcelFileDescriptor);
final int fd = parcelFileDescriptor.getFd();
safFileDescriptorMap.put(fd, safUrl);
android.util.Log.d(TAG, String.format("Generated fd %d for SAF id %d.", fd, safId));
return fd;
} else {
android.util.Log.e(TAG, String.format("SAF id %d not found.", safId));
Expand All @@ -1050,11 +1057,15 @@ private static int safClose(final int fileDescriptor) {
try {
final SAFProtocolUrl safProtocolUrl = safFileDescriptorMap.get(fileDescriptor);
if (safProtocolUrl != null) {
final int safId = safProtocolUrl.getSafId();
ParcelFileDescriptor parcelFileDescriptor = safProtocolUrl.getParcelFileDescriptor();
if (parcelFileDescriptor != null) {
safFileDescriptorMap.delete(fileDescriptor);
safIdMap.delete(safProtocolUrl.getSafId());
parcelFileDescriptor.close();
if (!safUrlsReusable.get()) {
safIdMap.delete(safId);
}
android.util.Log.d(TAG, String.format("Closed fd %d for SAF id %d.", fileDescriptor, safId));
return 1;
} else {
android.util.Log.e(TAG, String.format("ParcelFileDescriptor for SAF fd %d not found.", fileDescriptor));
Expand All @@ -1069,6 +1080,31 @@ private static int safClose(final int fileDescriptor) {
return 0;
}

/**
* Unregisters saf protocol urls and cleans up the resources associated with them.
*
* @param safUrl saf protocol url e.g. saf:1.mp4
*/
public static void unregisterSafProtocolUrl(final String safUrl) {
if (safUrl != null) {
try {
URI uri = new URI(safUrl);
String path = uri.getSchemeSpecificPart();
int index = path.indexOf(".");
if (index > -1) {
String safIdString = path.substring(0, index);
int safId = Integer.parseInt(safIdString);
safIdMap.delete(safId);
android.util.Log.d(TAG, String.format("Unregistered safUrl %s successfully.", safUrl));
} else {
android.util.Log.w(FFmpegKitConfig.TAG, String.format("Cannot unregister safUrl %s. Failed to drop extension!", safUrl));
}
} catch (URISyntaxException | NumberFormatException e) {
android.util.Log.w(FFmpegKitConfig.TAG, String.format("Cannot unregister safUrl %s. Failed to extract saf id!", safUrl));
}
}
}

/**
* Returns the session history size.
*
Expand Down Expand Up @@ -1295,6 +1331,31 @@ public static void setLogRedirectionStrategy(final LogRedirectionStrategy logRed
FFmpegKitConfig.globalLogRedirectionStrategy = logRedirectionStrategy;
}

/**
* Returns if SAF protocol urls are reusable or not.
*
* @return true if SAF protocol urls are reusable, false otherwise
*/
public static boolean getSafUrlsReusable() {
return safUrlsReusable.get();
}

/**
* Defines whether the generated SAF protocol urls will be reusable or not.
*
* <p>Note that SAF protocol urls are not reusable by default and are automatically
* unregistered when the file associated with them is closed.
*
* <p>If they are set to be reused using this method, automatic unregistration will be
* disabled. Therefore, it will be the developer's responsibility to unregister them via the
* {@link #unregisterSafProtocolUrl} method.
*
* @param safUrlsReusable set to true to enable the reuse of SAF protocol urls
*/
public static void setSafUrlsReusable(final boolean safUrlsReusable) {
FFmpegKitConfig.safUrlsReusable.compareAndSet(!safUrlsReusable, safUrlsReusable);
}

/**
* Converts session state to string.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ public void setSessionHistorySize() {
}
}

@Test
public void unregisterSafProtocolUrl() {
FFmpegKitConfig.unregisterSafProtocolUrl("saf:1.mp4");
}

private String listToPackageName(final List<String> externalLibraryList) {
boolean speex = externalLibraryList.contains("speex");
boolean fribidi = externalLibraryList.contains("fribidi");
Expand Down

0 comments on commit c6e08c0

Please sign in to comment.