bravobit / FFmpeg-Android

FFMpeg/FFprobe compiled for Android
https://bravobit.nl/
MIT License
734 stars 172 forks source link

use jniLibs to work with targetSdkVersion=29 #130

Open alexcohn opened 4 years ago

alexcohn commented 4 years ago

Fixing https://github.com/bravobit/FFmpeg-Android/issues/126

darrinps commented 4 years ago

Just curious why this hasn't been merged in. Seems straightforward and needed.

alexcohn commented 4 years ago

@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.

HiroyukiTamura commented 4 years ago

I'm strongly looking forward speedy marge and release, and next one as completely fix.

pcm2a commented 4 years ago

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?

alexcohn commented 4 years ago

@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.

pcm2a commented 4 years ago

@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.

alexcohn commented 4 years ago

@pcm2a if you think this PR is important, feel free to vote for it.

kartik1225 commented 4 years ago

Waiting for this merge

HBiSoft commented 4 years ago

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()
alexcohn commented 4 years ago

@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.

HBiSoft commented 4 years ago

@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.

alexcohn commented 4 years ago

@HBiSoft they have their struct State that can handle such URI, that's not how FFmpeg-Android is built.

HBiSoft commented 4 years ago

@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?

alexcohn commented 4 years ago

@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.

HBiSoft commented 4 years ago

@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).

alexcohn commented 4 years ago

@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?

HBiSoft commented 4 years ago

@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 "";
    }
}
alexcohn commented 4 years ago

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.

alexcohn commented 4 years ago

@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.

HBiSoft commented 4 years ago

@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]

alexcohn commented 4 years ago

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.

alexcohn commented 4 years ago

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.

Aditya94A commented 4 years ago

Looks good! @Brianvdb Please merge this.

maxirosson commented 4 years ago

Any update about this?

magicseal commented 4 years ago

waiting for this to be merged..

mshahidjanjua commented 4 years ago

Thanks @alexcohn for merging these changes. When will you release new version of library with this merge?

serkanucar commented 4 years ago

Any update about this?

SoluLabLive commented 4 years ago

Any update about this? When can I expect a new version?

maxirosson commented 4 years ago

Any update about this?

Ahmed-Basalib10 commented 3 years ago

any update ??

GauravCreed commented 3 years ago

Hi @alexcohn

Any update...? Then please help me.. Thanks(_)

alexcohn commented 3 years ago

@GauravCreed help you what?

GauravCreed commented 3 years ago

Hi @alexcohn

getting ffmpeg error code 13 in android 10 permission denied in android 10 device. so i am using https://github.com/tanersener/mobile-ffmpeg then problem is apk size increase.

Aditya94A commented 3 years ago

Looks like this isn't going to be merged, is it safe to use the fork directly? @alexcohn Any gotchas? Does this fully work with Android Q/R in the way we expect bravobit/FFmpeg-Android to work?

HBiSoft commented 3 years ago

@AdityaAnand1 I would recommend using (https://github.com/tanersener/mobile-ffmpeg). You get more control over what arch you want to build and you can pass it a Uri.

pratik-tech4 commented 3 years ago

Hi, @alexcohn

I am using this library,

https://github.com/tanersener/mobile-ffmpeg implementation 'com.arthenica:mobile-ffmpeg-full:4.2.2.LTS'

this is working on android 10 too , But the problem is i added this library my apk size is increased too much, almost 50mb increased.

Could you please help me with this?

alexcohn commented 3 years ago

@pratik-tech4 you definitely don't need the 'full' flavor of mobile-ffmpeg: it includes extra libraries that are not part of bravobit. You can make the right choice, or even build a bespoke mixture yourself, only including the external libs that you really need (and maybe revisit your commands to avoid non-necessary external libs, too). Also, if you don't use AAB and don't use split APK, the APK now includes all ABIs. For production, you only care about arm64 and armv7-a as separate binaries.

GauravCreed commented 3 years ago

HI @alexcohn

How about when I am using both audio and video both, i want to add text and image both in video,

implementation 'com.arthenica:mobile-ffmpeg-audio:4.4' implementation 'com.arthenica:mobile-ffmpeg-video:4.4'

it will gives some error like duplicate classes.

Capture

pratik-tech4 commented 3 years ago

Hi @alexcohn

as @GauravCreed said same way i tried but same error.

If i add audio and video version both it gives me same error as @GauravCreed faced. Thats why i am using full version.

I am using it to cut audio then merge it and adding audio to video. So if possible which version i should use to work these functionality.

alexcohn commented 3 years ago

@GauravCreed, @pratik-tech4: no, you cannot and should not add two ffmpeg-mobile packages.

I would suggest to start with min, and find out what is missing for you. Only if you find that you desperately need more, consider another package. Note that the audio package does contain basic video capabilities, while the video package still provides the essential audio functions.

HBiSoft commented 3 years ago

@GauravCreed, @pratik-tech4 You can build it with custom options like this:

Use the .aar in your project and do a few tests. If there are missing libraries (in my case zlib) build the project again and add the missing lib.


By doing this, you have full control over which libs you want based on what you need.

pratik-tech4 commented 3 years ago

hi, @HBiSoft , @alexcohn

Thank you for your response,

for now i used
implementation 'com.arthenica:mobile-ffmpeg-full:4.4.LTS' in this my apk size is around 74MB.

so, I added ndk filters like below

ndk { abiFilters "armeabi-v7a","arm64-v8a" }

by this two filters apk size is around 48MB.

So now i have one doubt is that

if i make sign apk with these two filters "armeabi-v7a","arm64-v8a", is it approve in play store? as in play store apk must have 64-bit support.

So by these two filter it will approve or no? And it will run in older devices? like which are 32 bit.

Thanks in advance!

HBiSoft commented 3 years ago

@pratik-tech4 Yes it will be approved. armeabi-v7a is 32bit and arm64-v8a is 64bit.

I would rather suggest using splits (as shown below) instead of using abiFilter. By splitting the apk`s you will only install the necessary apk. Using abiFilter, you will include all the archs, which increases your apk size unnecessarily.

android.splits {
    abi {
        enable true
        reset()
        include 'armeabi-v7a', 'arm64-v8a'
        universalApk false
    }
}
pratik-tech4 commented 3 years ago

@pratik-tech4 Yes it will be approved. armeabi-v7a is 32bit and arm64-v8a is 64bit.

I would rather suggest using splits (as shown below) instead of using abiFilter. By splitting the apk`s you will only install the necessary apk. Using abiFilter, you will include all the archs, which increases your apk size unnecessarily.

android.splits {
    abi {
        enable true
        reset()
        include 'armeabi-v7a', 'arm64-v8a'
        universalApk false
    }
}

@HBiSoft Thanks

by doing this changes both apk is build separately app_armeabi-v7a.apk, app_arm64-v8a.apk. So which one need to upload in play store?

AxitaKathiriya commented 3 years ago

When will you release new version of library with this merge? Please release this as soon as possible. I am waiting for this..

Shabinder commented 2 years ago

@alexcohn Hey thanks for this PR and it works fine when building and using debug apk,

but as soon as I use a release apk after signing, it doesn't save ffmpeg & ffprobe in /data/app/xxxx/libs folder.

I have tried various methods like enabling/disabling android:extractNativeLibs="true" in App manifest but no luck

However migrating libs to jniLibs folder as lib..ffmpeg.so worked , no idea why.... if anybody does, I am curious

alexcohn commented 2 years ago

@Shabinder that's true. Android system APK installer extracts only libraries that follow the strict libxxxx.so naming convention, but makes exception for debug APKs (so that you can embed your debug scripts, like wrap.sh).

When I published this PR, I was not aware of this weird behavior.

Shabinder commented 2 years ago

When I published this PR, I was not aware of this weird behavior.

Yeah the most weird about it is that there is no flag to keep such resources when building release apk. Anyway thanks for your contributions they helped a lot 👍

alexcohn commented 2 years ago

At any rate, I strongly recommend you to switch from a poorly supported executable-based solution to a library-based one, e.g. https://github.com/tanersener/ffmpeg-kit.

Shabinder commented 2 years ago

At any rate, I strongly recommend you to switch from a poorly supported executable-based solution to a library-based one, e.g. https://github.com/tanersener/ffmpeg-kit.

I did went to initially configure ffmpeg-kit, but I needed very much control over ffmpeg-build configuration and wanted to keep the lib size to as low as possible, hence I decided to build my own ffmpeg libs and include them in-app, and as a result Adding FFmpeg just increased just around 2.9 mb in my apk (All 4 arch arm64, x86, arm7, x86_64 ) , I was surprised too. if you want to explore, project is here: https://github.com/Shabinder/SpotiFlyer

Adding FFmpeg-kit as a submodule was not a solution while configuring it custom as It was giving some error that said that produced aar wont be included in parent app(I don't remember the proper wording but there was a limitation) and I didn't wanted to go to the route of maintaining my fork and using mavenCentral as the source