Closed PaulWoitaschek closed 4 years ago
Can you please give some more info like what is the issue you're facing right now and why that feature needs to be implemented in the library rather than the application?
I need to parse metadata of a lot of media files from the users phone storage.
On Android 10 you don't have access to the users sd card using the file api: https://developer.android.com/about/versions/10/privacy/changes#scoped-storage
Instead you need to use the SAF framework: https://developer.android.com/guide/topics/providers/document-provider
You fire an intent: https://developer.android.com/reference/android/content/Intent.html#ACTION_OPEN_DOCUMENT
And get an uri in onActivityResult. This uri is no file uri but a content provider uri. Therefore you can't use it with mobile-ffmpeg at all (unless you make a deep temporary copy of the file, which is no option here as I can't duplicate gigabytes of media.)
You can use the content provider to obtain a file descriptor:
contentResolver.openFileDescriptor(uri, "r")
. and work with that.
But this need integration with mobile-ffmpeg.
Thanks for explaining the issue in detail.
MobileFFmpeg
for Android is made of two modules; one native module (written in C/C++) and one Java module. There is a JNI layer between these two and Java module sends API requests to native module through this JNI layer.
Argument parsing and opening input/output files are all implemented in native module. Supported protocols are also defined there. As far as I know, SAF is not available in NDK. That means that I can't use SAF inside the native module. So, I don't think that SAF can be integrated with MobileFFmpeg
. Do you have any recommendations?
@wseemann
Can you help out here?
@tanersener I'm not that familiar with NDK and I do not want to highjack this issue, I just thought I would give my 2 cents.
As @PaulWoitaschek mentioned, on Android we can not access the file (or its path) directly, unless the file is located in our application's directory. Instead, we have to make use of the ContentResolver
to open a FileDescriptor
. As shown below:
FileDescriptor fd = getContentResolver().openFileDescriptor(Uri, "r").getFileDescriptor();
In the project that was provided as an example above, the owner of that library checks to see if the Uri that was passed is a content://
Uri. If it was then he uses a FileDescriptor
instead of passing the path of the file, please have a look here:
So you can create 2 native methods, one for handling file paths(as you have it currently): https://github.com/tanersener/mobile-ffmpeg/blob/917c22e20947e89d4c1cf4ce4290909360f8973b/android/app/src/main/java/com/arthenica/mobileffmpeg/Config.java#L642
and one for passing the FileDescriptor
, something like this:
native static int nativeFFmpegExecute((final String[] arguments, final FileDescriptor fd) {
On the C/C++ side you can then handle this depending on which one of the above was called. Of course, there will also have to be another method added in FFmpeg.java:
Like this:
public static int execute(final String[] arguments, final FileDescriptor fd) {
Developers using your library could then have the option to pass a FileDescriptor
, something like this:
FileDescriptor fd = getContentResolver().openFileDescriptor(Uri, "r").getFileDescriptor();
//Note that, instead of passing the path at the end, FileDiscriptor is passed instead.
FFmpeg.execute("some_commands_by_developer"+outputPath, fd);
Edit:
This is how he handles it from C:
int set_data_source_fd(State **ps, int fd, int64_t offset, int64_t length) {
char path[256] = "";
State *state = *ps;
ANativeWindow *native_window = NULL;
if (state && state->native_window) {
native_window = state->native_window;
}
init(&state);
state->native_window = native_window;
int myfd = dup(fd);
char str[20];
sprintf(str, "pipe:%d", myfd);
strcat(path, str);
state->fd = myfd;
state->offset = offset;
*ps = state;
return set_data_source_l(ps, path);
}
There is no need to change the C++ side at all. A neat trick lets you work with a file path instead of the FileDescriptor. It's based on the specs of the Linux /proc/self/fd
files.
As service to the community, the integer descriptor may be extracted on the Java side of the library (if it sniffs the content://
prefix), but may be easily done by the app developer who uses the library.
Hi, another reason that must support FileDescriptor is defined here https://github.com/tanersener/mobile-ffmpeg/issues/185
Above trick, I am testing with the other project with same purpose, but this behaviour can be changed by Google in the future.
I know you expect the library to handle URIs internally but I think using the following method is the most elegant solution for SAF.
File descriptors received from SAF can be used using the pipe protocol. Both input and output files can be defined with pipe protocol. But some file formats require the output to be seekable, so pipe protocol will fail with them. Be careful about them.
String safUriToFFmpegPath(final Uri uri) {
try {
ParcelFileDescriptor parcelFileDescriptor = getContentResolver().openFileDescriptor(uri, "r");
return String.format(Locale.getDefault(), "pipe:%d", parcelFileDescriptor.getFd());
} catch (FileNotFoundException e) {
return "";
}
}
All this is unnecessary, I pondered upon this myself and hated this elegant library for it. I did it using a utility function like:
val filePath = RealPathUtil.getRealPath(
context,
currentUri
)
so, contentUri to filePath is what you need. It is just as fast.
@RowlandOti
The RealPathUtil
you are referring to is probably querying the _data
column to get the path of the file. I have released a library myself that converts a Uri
to a "real" path. The problem is that the _data
column can no longer be accessed when you are targeting 29.
You are right, this will only work for API < 29. This was the only caveat. @HBiSoft
@tanersener I've tested the pipe protocol and it is working.
But some file formats require the output to be seekable
Can you please explain what is meant with the above?
@HBiSoft
Muxers of some file formats like mp4 and mov requires the output to be seekable to write file metadata/header information correctly. Unfortunately pipe protocol does not support seeking. Therefore you may receive muxer does not support non seekable output
error if you try to use pipe protocol in an output file.
There are some options that can be used to overcome this limitation, like -movflags frag_keyframe
or -movflags empty_moov
. But using these options has consequences. For example, you may not have a seekable video file at the end. So, you need to be careful about the options you use. FFmpeg's mov, mp4, ismv guide includes the list of options and explains what they are used for. It may help you to understand the those consequences better.
Update: Unfortunately input files are affected from this limitation too. You can't use mp4 and mov files with pipe protocol as input unless they are created using -movflags +faststart
. There is not way to overcome this limitation.
@tanersener Thank you for your informative reply. As I understand it, this will only be an issue if I use the pipe protocol with the output and not when I use it with the input? If this is the case, I will then be able to set the output path to my application directory and all will be good.
There is no need to change the C++ side at all. A neat trick lets you work with a file path instead of the FileDescriptor. It's based on the specs of the Linux
/proc/self/fd
files.As service to the community, the integer descriptor may be extracted on the Java side of the library (if it sniffs the
content://
prefix), but may be easily done by the app developer who uses the library.
About this solution?, why does not any one interest this one?
@HBiSoft I missed some details about input files. Updated my previous post with the following information. It looks like safUriToFFmpegPath
can be used as a temporary workaround but a protocol like saf:
or fd:
has to be implemented.
Unfortunately input files are affected from this limitation too. You can't use mp4 and mov files with pipe protocol as input unless they are created using -movflags +faststart. There is not way to overcome this limitation.
@kingvhit That solution is a trick that works for some devices and doesn't work on some others. I tested it and it didn't work for me. I receive Permission denied
errors when I try. You can try and see if it works for you.
@tanersener : Hi, I have tested on Xiaomi Mi 8 Pro (Adroid 9), and Google Pixel XL 3 (android 10) and all of them working well.
I have concern when you told that it's is not really work for all devices :'(. Could you please tell me which device are you testing on before.
Just I want to re-check it on my app.
@tanersener I agree with:
a protocol like saf: or fd: has to be implemented.
I think the best is to use fd:
because we can open a FileDescriptor
with any(almost) Uri. Then we, using the library, can pass the FileDescriptor
instead of the path. This will work on all API's and no "hacks" are involved. I know my first comment means more work, but I believe it is the best/correct way - https://developer.android.com/training/data-storage/shared/media#native
@kingvhit
My old Galaxy A5 (2016) (Android 7.0) receives /proc/self/fd/66: Permission denied
.
Also Pixel 2 Simulator with API 24 also receives permission denied error for me.
@tanersener I am afraid this only means that there is no universal way of handling this. I didn't expect Permission denied on Android 7, but anyways you only need this workaround for API 29 and higher. BTW, my Android 7.0 device handles this perfectly. I only bothered to handle input in my simple exercise, but it works even cross-process: see https://github.com/alexcohn/FFmpeg-Android/commit/686c4b50653e39c5acb181b0d09cec03e873af5d
@alexcohn Tried to test your pull request to see whether I'm missing something but I still receive /proc/11193/fd/52: Permission denied
on my device. Attached the logs here if you want to take a look.
Which file did you choose? For me, uri content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Fqq.mov
points to /sdcard/Download/qq.mov
(a.k.a. /storage/emulated/0/Download/qq.mov
).
I tested with a file on my SD Card, the content uri is content://com.android.externalstorage.documents/document/6330-6333%3ATest.mp4
. It is pointing to /storage/6330-6333/Test.mp4
and I also get permissions denied -
/proc/23074/fd/70: Permission denied
I tested the above by calling:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SELECT_VIDEO_REQUEST && resultCode == RESULT_OK) {
ParcelFileDescriptor parcelFileDescriptor = null;
try {
parcelFileDescriptor = getContentResolver().openFileDescriptor(data.getData(), "r");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int fd = parcelFileDescriptor.getFd();
int pid = Process.myPid();
String mediaFile = "/proc/" + pid + "/fd/" + fd;
int rc = FFmpeg.execute("-i "+mediaFile+" -crf 18 -c:v libx264 -c:a copy "+outputPath");
if (rc == RETURN_CODE_SUCCESS) {
Log.i(Config.TAG, "Command execution completed successfully.");
} else if (rc == RETURN_CODE_CANCEL) {
Log.i(Config.TAG, "Command execution cancelled by user.");
} else {
Log.i(Config.TAG, String.format("Command execution failed with rc=%d and the output below.", rc));
Config.printLastCommandOutput(Log.INFO);
}
}
}
By default, by experimentation, I noticed that drives mounted to /storage/XXXX-XXX
will by default have write permissions denied.
I don't think we should face similar problems with /sdcard/Download/ aka /storage/emulated/0/Download/ as both have read/write access.
@alexcohn
If I select /storage/emulated/0/Download/video1.mp4
file, it gets content://com.android.externalstorage.documents/document/primary%3ADownload%2Fvideo1.mp4
uri. I don't know why it has a different format then yours or from @HBiSoft's file.
opened content://com.android.externalstorage.documents/document/primary%3ADownload%2Fvideo1.mp4 as /proc/14517/fd/52
/proc/14517/fd/52: Permission denied
@tanersener
The reason why it is different is - If you select a file from the downloads provider directly, it will return the Uri as content://com.android.providers.downloads.documents/document/3656
or like in @alexcohn's case content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Fqq.mov
and if you select a file by going to your internal storage then Downloads, it will return content://com.android.externalstorage.documents/document/primary%3ADownload%2FNameOfVideo.mp4
.
See the deffirence between com.android.providers.downloads
and com.android.externalstorage.documents/document/primary
.
@alexcohn
If the Uri
returned is a raw file then it works. For example, if I select a file from the downloads provider and I get a Uri like
content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Fqq.mov
then it works, but if I select the same file, by selecting it from Internal Storage/Download and the returned Uri is
content://com.android.externalstorage.documents/document/primary%3ADownload%2F`Fqq.mov
then I get the permissions denied.
@HBiSoft Thanks for explaining that. Unfortunately, selecting a file from one of the providers doesn't improve the case for me. Selected a file from Videos provider which was actually under the /storage/emulated/0/Pictures/
path and got the url content://com.android.providers.media.documents/document/video%3A727
, which still receives permission denied errors.
@tanersener I see. I also tested with different providers/paths and it was very inconsistent, some worked and some didn't. The same when using the pipe protocol, a lot of videos failed, especially videos that were recorded with an iPhone. What other options do we have? How is it that it works with the FFmpegMediaMetadataRetriever library as mentioned here?
I don't know any other options we can try right now.
I think FFmpegMediaMetadataRetriever
is using an offset to skip the data and just reads the metadata/header. But I'm not sure, I think @alexcohn may have a better idea.
Unfortunately, I don't know how this can be overcome. Regarding the FFmpegMediaMetadataRetriever, they use ffmpeg as library, so they are not limited with filenames-based API. Having an open descriptor, you can access the file the way you want (e.g. funopen()
).
People think that the problem loading media files (and some other types) from /sdcard
is a bug: https://issuetracker.google.com/issues/147619577. More stars there may have a positive effect! I gave mine.
can this help(I am a novice, hope this works)
https://www.youtube.com/watch?v=oIn0MZQJpp0&feature=youtu.be&t=961
https://stackoverflow.com/questions/43815688/passing-a-native-fd-int-to-ffmpeg-from-openable-uri
https://proandroiddev.com/a-story-about-ffmpeg-in-android-part-ii-integration-55fb217251f0
https://github.com/Javernaut/WhatTheCodec
is android.system.os.lseek
useful in anyway
@kingvhit My old Galaxy A5 (2016) (Android 7.0) receives
/proc/self/fd/66: Permission denied
. Also Pixel 2 Simulator with API 24 also receives permission denied error for me.
according to this video , there were recent changes in android , to support android.system.os.lseek
so may be /proc/self/fd/66
was not supported earlier
https://www.youtube.com/watch?v=oIn0MZQJpp0&feature=youtu.be&t=961
as per this , it looks like to be the expected behavior
https://developer.android.com/training/data-storage/shared/media#native
so we can use
Uri contentUri = ContentUris.withAppendedId(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
cursor.getLong(Integer.parseInt(BaseColumns._ID)));
String fileOpenMode = "r";
ParcelFileDescriptor parcelFd =
resolver.openFileDescriptor(contentUri, fileOpenMode);
if (parcelFd != null) {
int fd = parcelFd.detachFd();
// Pass the integer value "fd" into your native code. Remember to call
// close(2) on the file descriptor when you're done using it.
}
to manage it in a better way we may check the android version using
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
// use /proc/self/fd/66
}
else {
// use file path
}
I dont know if this is the perfect solution, but till we find a better sollution we can use this, as I said earlier I am a Novice, to FFmpecg and android can some one help with the way to get '/proc/self/fd/66' I think we can get it from a native code (I dont know NDK) can some body share a .so
file to pass it to the FFmpeg code
thanks
You don't need to check SDK_INT. The detached file descriptor will work for earlier Android versions, just as well. The caveat is that on Q, you cannot use /proc/self/fd/66
if it points to a file on sdcard (/sdcard/Downloads are still OK, but, as far as I understand, through a different Provider).
@alexcohn I agree. It is clear that the only way is to pass an open file descriptor. Is there any reason this will not work?
Edit: This seems like exactly what we want (I see you commented on it):
I have asked for help here 6963
I dont know if they would help, but if somebody can really clarify on this accessing files in native C/C++ code with Google Scoped Storage API
thing, it would be really helpful, otherwise many apps which are in production may stop working
You don't need to check SDK_INT. The detached file descriptor will work for earlier Android versions, just as well. The caveat is that on Q, you cannot use
/proc/self/fd/66
if it points to a file on sdcard (/sdcard/Downloads are still OK, but, as far as I understand, through a different Provider).
just a thought, how are you getting the fd
int,
I guess, one should use
String fileOpenMode = "r";
ParcelFileDescriptor parcelFd =
resolver.openFileDescriptor(contentUri, fileOpenMode);
where String fileOpenMode = "r";
is the important part
You don't need to check SDK_INT. The detached file descriptor will work for earlier Android versions, just as well. The caveat is that on Q, you cannot use
/proc/self/fd/66
if it points to a file on sdcard (/sdcard/Downloads are still OK, but, as far as I understand, through a different Provider).just a thought, how are you getting the
fd
int,I guess, one should use
String fileOpenMode = "r"; ParcelFileDescriptor parcelFd = resolver.openFileDescriptor(contentUri, fileOpenMode);
where
String fileOpenMode = "r";
is the important part
you can easily get the fd
number by method
String fileOpenMode = "r";
ParcelFileDescriptor parcelFd =
resolver.openFileDescriptor(contentUri, fileOpenMode);
parcelFd.getFdId();
I don't know why, but could you please write down all your expected result of your issue
@kingvhit My old Galaxy A5 (2016) (Android 7.0) receives
/proc/self/fd/66: Permission denied
. Also Pixel 2 Simulator with API 24 also receives permission denied error for me.
unfortunately my Android Q emulator has crashed, and not starting at all, while I was testing, so it will take time , the problem is not about getting fd
but may be the permission required to read
the file, which we can access using String fileOpenMode = "r";
@kingvhit My old Galaxy A5 (2016) (Android 7.0) receives
/proc/self/fd/66: Permission denied
. Also Pixel 2 Simulator with API 24 also receives permission denied error for me.unfortunately my Android Q emulator has crashed, and not starting at all, while I was testing, so it will take time , the problem is not about getting
fd
but may be the permission required toread
the file, which we can access usingString fileOpenMode = "r";
Let me know, which is expected result you want to do.
E.g:
I have to make my app working with all of above case, with some tip trick in this issue. If you understand what is my question, let me more detail of you case.
case 1 I want to input a file from A (uri, file) and then process -> export the file results to B destination (uri, file)
Firstly, as you target SDK to 29, when you pick a file from the Other Apps (Google Driver, File Manager...) you just get a uri
with content://
prefix.
My solution is:
First, check a uri is internal storage or Document Provider by other app (Google Driver, One Driver, ...) or is a external storage (sd-card)
NOTE: We only have permission to access internal storage by absolute path, like /storage/emulated/0/DCIM...
and we don't have any permission (read/write) to access to the other absolute path of the other Document Provider or private internal storage of other app like /storage/emulated/0/data/data/com.googledrive.com/**
except owner of that apps.
Bellow is a tip trick of above issue:
proc
absolute path -> Then, check this path is readable or not.
If Yes -> (maybe this path is internal storage) -> normally reading.
If no -> (maybe this path is in private storage of the other application) -> copy this file into cached dir of your app (use contentResolver) -> normally reading by cached dir by your app, mark this case.Bellow is a way to copy file from all of URI into cached dir without permission
val contentResolver = getApplication<Application>().contentResolver
val inputStream = contentResolver.openInputStream(uri)
val outputStream = FileOutputStream(getApplication<Application>().cacheDir)
Read file by absolute file path above to continue working aboslute path (input file) on your app.
In case this path is in internal storage -> You can easily to write file into it with abosolute path. In case this path is in Document Provider (E.g: /data/data/com.google.driver...) or external storage (SD-card): You need using abosolute path of your app (like cached dir) to export the result file, then copy it into target uri you want. This is a method that you can do.
// Folder to extract a file. val treeDocFile = DocumentFile.fromTreeUri(getApplication(), data) // Create a output file with no data (just create a file) val docFile = treeDocFile.createFile("text/csv", fileName) // Copy data of output file from cached dir into target uri val contentResolver = getApplication<Application>().contentResolver // Input file from cached dir val exportedCsv = File(context.cacheDir.absolutePath,fileName) val inputStream = FileInputStream(exportedCsv) // Output file into target uri val outputStream = contentResolver.openOutputStream(docFile.uri, "w")
// write file into target uri inputStream.copyTo(out)
@kingvhit I do not believe this is a feasible solution.
Let's say the file size if 2GB>, it will take very long to copy/write a new file.
By doing it as you say, you will have to write the file to your applications directory to get a file scheme Uri
and get the path from that Uri
(the user will have to wait for the file to be copied/written), then run the FFmpeg
command (the user will have to wait again).
If the file is from (Google Driver, One Drive, ...) then there is no other way then to copy the file to your application's directory and get the path from that. But I do not believe that this should be the option with SD Card.
Also, with what you said:
First, check a uri is internal storage or Document Provider by other app (Google Driver, One Driver, ...) or is a external storage (sd-card)
AFAIK, there is no way to check if a Uri
points to a file on the SD Card. Look here
I feel this should be handled by the library and I think we should stop looking at "workarounds/tricks" and focus on doing it right.
As I mentioned in my previous comment, this answer got it working.
In this question (above), he mentioned the following (he is talking about /proc/self/fd/" + fd
):
Passing this to native C/C++ code works, but only if the file is in phone main storage. If the user tries to open a file that is on external SD card inserted into the phone slot, it does not work - there is no read permission for the file opened this way. I can only grab the file descriptor int number and use fdopen(fd). But this will require modifying the source code of 3rd party libraries (open source or licensed), and a big headache, whenever the original source of these libraries is updated.
And with the solution he provided, there is no need to change the native library itself.
After wasting another good day of my life on the Android "Scoped Storage" B.S., I found a solution that works, without modifying the source of 3rd party native libraries, provided that one has the source of these libraries and can build them.
@HBiSoft : I agree with you about this is a tip/tricks to handle this issue. May I discuss in wrong topic, because my app does not have any solution to modify native code, but FFmpeg mobile here can do it.
This is a last confirm that I was tested on my app.
If the file is from (Google Driver, One Drive, ...) then there is no other way then to copy the file to your application's directory and get the path from that. But I do not believe that this should be the option with SD Card.
=> We don't need to care about this folder is a member of Document Provider or SD-card, but we can check writable permission with its file. All of them is the same. If write permission is no, use content resolver to open uri as input stream from this file from them, then write to application dir.
I agree with you, it's not best solution to handle the large file but this case is only appear when user picking file or input file, output file which are not internal storage where our app have full permission to read/write dirrectly (just only need READ/WRITE permission). If the input file, output file still internal storage, we can still using fd
path based proc
(/proc/self/fd/66).
I tested with a file on my SD Card, the content uri is
content://com.android.externalstorage.documents/document/6330-6333%3ATest.mp4
. It is pointing to/storage/6330-6333/Test.mp4
and I also get permissions denied -/proc/23074/fd/70: Permission denied
I tested the above by calling:
protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == SELECT_VIDEO_REQUEST && resultCode == RESULT_OK) { ParcelFileDescriptor parcelFileDescriptor = null; try { parcelFileDescriptor = getContentResolver().openFileDescriptor(data.getData(), "r"); } catch (FileNotFoundException e) { e.printStackTrace(); } int fd = parcelFileDescriptor.getFd(); int pid = Process.myPid(); String mediaFile = "/proc/" + pid + "/fd/" + fd; int rc = FFmpeg.execute("-i "+mediaFile+" -crf 18 -c:v libx264 -c:a copy "+outputPath"); if (rc == RETURN_CODE_SUCCESS) { Log.i(Config.TAG, "Command execution completed successfully."); } else if (rc == RETURN_CODE_CANCEL) { Log.i(Config.TAG, "Command execution cancelled by user."); } else { Log.i(Config.TAG, String.format("Command execution failed with rc=%d and the output below.", rc)); Config.printLastCommandOutput(Log.INFO); } } }
how do you create file in outputPath
can you please elaborate
@pawaom
outputPath
is my applications directory.
File directoryToStore = getBaseContext().getExternalFilesDir("tempDirectory");
if(directoryToStore != null) {
if (!directoryToStore.exists()) {
if (directoryToStore.mkdir()) ; //directory is created;
}
}
// Output path passed to FFmpeg
String outputPath = directoryToStore+"/testFile.mp4";
The path will be:
/storage/emulated/0/Android/data/com.package.name/files/tempDirectory/testFile.mp4
any update guys , has anyone tested on multiple devices using the Firebase Test lab,
https://www.youtube.com/watch?v=o0aUuKztO4A
I tested with a file on my SD Card, the content uri is
content://com.android.externalstorage.documents/document/6330-6333%3ATest.mp4
. It is pointing to/storage/6330-6333/Test.mp4
and I also get permissions denied -/proc/23074/fd/70: Permission denied
have you used takePersistableUriPermission
if (resultCode == RESULT_OK) {
getContentResolver().takePersistableUriPermission(data.getData(),
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
@pawaom
has anyone tested on multiple devices using the Firebase Test lab
What do you want to test? There is nothing to test at the moment.
have you used takePersistableUriPermission
Yes, I did.
@tanersener
Can you have a look at this(and the answer)? It looks like we can add that to the build and perhaps create a native method, similar to nativeFFmpegExecute
and return the path, or just use that file.
@HBiSoft Solution posted in the answer has to be tested. I don't know what will that idiocy_fopen_fd
function return for files on the cloud?
so what is this all about
1) file path access to (read) media will be allowed 2) media modification API (To edit delete)
https://youtu.be/UnJ3amzJM94?t=1451
so what are we supposed to do , its really confusing now
I need to use this library on android using an uri from SAF. Therefore it would be great if you implemented an api for using a file descriptor.
An example for how to implement this so the uir can be passed to the NDK can be found here: https://github.com/wseemann/FFmpegMediaMetadataRetriever/blob/b42986fb4044c54131379407598d8ac0ff1a3326/gradle/fmmr-library/core/src/main/java/wseemann/media/FFmpegMediaMetadataRetriever.java#L214