FFmpeg-Android
FFmpeg-Android copied to clipboard
use jniLibs to work with targetSdkVersion=29
Fixing https://github.com/bravobit/FFmpeg-Android/issues/126
Just curious why this hasn't been merged in. Seems straightforward and needed.
@darrinps there are some good reasons why this was not merged. One, as you noticed, is that this still lacks 64 bit, which makes this solution unsatisfactory for majority of the people who need to target Android Q. Second, people may consider renaming the executable to lib…so to be a dirty trick. Third, this removes a lot of code people had wrote, debugged, and invested into. Not a very nice feeling for a maintainer.
I'm strongly looking forward speedy marge and release, and next one as completely fix.
I would like to target Q as well but cannot until ffmpeg is working with it. Is this code in a fork with a release that can be included?
@pcm2a what is your incentive to target Q? Remember, you can use Q APIs in a project that targets earlier SDK. At any rate, if you don't set min supported SDK to Q, you have to check the availability of these APIs before using them.
@alexcohn just planning ahead. When R is released in 2020 all apps will be forced to target Q I plan on being ready in advance vs rushing to the finish line.
@pcm2a if you think this PR is important, feel free to vote for it.
Waiting for this merge
Besides this fix, for this library to work when targeting Q, we need an option to pass a FileDescriptor
instead of having to pass the file path.
For example, instead of:
String[] command = {"-i", mStringFilePath, "-crf", "18", "-c:v", "libx264", "-c:a", "copy", pathToAppDirectory};
FFmpeg.getInstance(this).execute(command, new ExecuteBinaryResponseHandler()...
We could be given an option to pass a FileDescriptor
, like this:
FileDescriptor fd = getContentResolver().openFileDescriptor(Uri, "r").getFileDescriptor();
//Note that there is no input path provided below
String[] command = {"-crf", "18", "-c:v", "libx264", "-c:a", "copy", pathToAppDirectory};
FFmpeg.getInstance(this).execute(command, fd, new ExecuteBinaryResponseHandler()...
//and when the developer doesn't want to use the FileDescriptor
FFmpeg.getInstance(this).execute(command, null, new ExecuteBinaryResponseHandler()
@HBiSoft Passing FileDescriptor still won't let you work around the scoped storage. You need significant changes on the ffmpeg binary as well, to handle this: pass these file descriptors via Unix sockets.
If you switch to an ffmpeg in-process library solution, e.g. https://github.com/tanersener/mobile-ffmpeg, you can transparently pass your FileDescriptor with the /proc/self/fd/%d trick or pipe:
protocol or use it through a custom AVIOContext.
@alexcohn The owner of FFmpegMediaMetadataRetriever did something similar, have a look here:
https://github.com/wseemann/FFmpegMediaMetadataRetriever/blob/b42986fb4044c54131379407598d8ac0ff1a3326/gradle/fmmr-library/library/src/main/jni/metadata/ffmpeg_mediametadataretriever.c#L304
You can also have a look at my post on the mobile-ffmpeg library which is related to this - https://github.com/tanersener/mobile-ffmpeg/issues/334#issuecomment-581254355
I believe the owner of this library can easily implement this as well.
@HBiSoft they have their struct State that can handle such URI, that's not how FFmpeg-Android is built.
@alexcohn I was able to get it working on mobile-ffmpeg using the pipe protocol.
What suggestions do you have if we want to achieve the same using this library?
@HBiSoft on the one hand, ffmpeg supports the pipe protocol out-of-the-box, and I believe that the Android port did not damage this functionality. On the other hand, the pipe protocol is not seekable, which may be a significant limitation for some ffmpeg file formats and some applications. I won't propose it as a panacea.
@alexcohn
I tested it with this library and it didn't work. Even if it does, it's not the solution.
This library will either have to be rebuild in a way that excepts Uri
's and can handle them properly or I can't see it working after developers are forced to target API level 29 (which will probably be within the next few months).
@HBiSoft
I tested it with this library and it didn't work.
I am confused. Did you test pipes or the /proc/self/fd
trick?
@alexcohn I tested with pipe ->
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 "";
}
}
The pipe:
protocol has its own limitations, but in my limited experiments, the /proc/…/fd/…
trick worked as expected. Only note that you cannot use /proc/self/fd
here, you must put the actual Process.myPid()
instead.
@HBiSoft please see https://github.com/alexcohn/FFmpeg-Android/commit/686c4b50653e39c5acb181b0d09cec03e873af5d – for me it resolves the problem with Android Q. I only care about input, but I have no doubt you can follow the same approach to use an output directory out of the app sandbox.
@alexcohn Thank you for your reply.
I have tested the above and I get /proc/4759/fd/70: Permission denied
when selecting from the SD Card.
I see you mentioned this:
Work around the API 29 new [restrictions on use of external storage]
I have tested the above and I get
/proc/4759/fd/70: Permission denied
when selecting from the SD Card.
Yes, it seems to only work for Downloads.
Thanks to @Le-Dinh-Nam #126 comment, I could clean up a bit more. It seems that later platform versions extract all files from lib folder, not filtering by the lib….so pattern, as earlier.
UPDATE no, it does not, see Google Issue. I was forced to revert this change.
Looks good! @Brianvdb Please merge this.
Any update about this?
waiting for this to be merged..
Thanks @alexcohn for merging these changes. When will you release new version of library with this merge?
Any update about this?
Any update about this? When can I expect a new version?
Any update about this?
any update ??