Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native crash in FFmpegFrameRecorder.recordSamples() when using RTMPS connection #399

Open
scorpeeon opened this issue Apr 27, 2016 · 42 comments

Comments

@scorpeeon
Copy link

I'm using this lib to decode sound from microphone to aac and stream it through RTMP(S) to a server. For this I'm using FFmpegFrameRecorder.recordSamples() function and it is working fine when I'm connecting through a normal RTMP connection. But when I'm using RTMPS, it also works fine for the initial 2-3 seconds (and I can playback this little part on the server) but after that the native part just crashes with a not very verbose message:

E/audit: type=1701 msg=audit(1461335772.791:1017): auid=4294967295 uid=10325 gid=10325 ses=4294967295 subj=u:r:untrusted_app:s0:c512,c768 pid=23492 comm="pool-4-thread-1" reason="memory violation" sig=11

When debugging I found that this happens a few seconds after initiating the connection precisely when returning from the recordSamples() function. (initially I thought that the last line was crashing but I modified it and it still crashed when it returned from this function).

Since the crash message is not very verbose and the said function is over a 100 lines with quite a few native calls, I don't really know how to debug this issue. Any ideas?

@scorpeeon
Copy link
Author

I tried it with those, and the same thing happens.
I also rebuilt javacpp-presets and javacv from source (and even changed the last line in the said javacv function as I thought it caused the crash but it wasn't the case apparently) and the same thing is happening..

One strange thing I noticed is that while this function normally runs around 24 times before crashing (producing the 2-3 second sound on the server), if I put a breakpoint to the function's beginning and make the program wait at least a few seconds there, it actually crashes the first time it would return from it. So it's like it's something external/asynchronous that's causing this - but I don't know what can it be as I don't call ffmpeg related functions elsewhere... Might be something about the network connection? (it would make sense as it works fine just by changing rtmps to rtmp) I really don't know...

@saudet
Copy link
Member

saudet commented Apr 28, 2016

Does the same thing happen in another OS?

@scorpeeon
Copy link
Author

That's a good question, I didn't test that yet. It's used in an Android app currently.
I might try to make a basic Java project to test that.

@scorpeeon
Copy link
Author

It looks like it's working through the normal desktop java console app on windows (x86_64), I managed to stream a 10 second audio without problems.
So the error is something Android specific it seems? Really strange...

@saudet
Copy link
Member

saudet commented Apr 28, 2016

I think the Windows binaries were built with GnuTLS instead of OpenSSL though.

@scorpeeon
Copy link
Author

scorpeeon commented Apr 28, 2016

That's interesting, I might try to build a version that uses GnuTLS..

Meanwhile an interesting observation: I made the aforementioned minimalist app work on Android (to exclude all other sources of errors) and this time, there's no error, in runs through, but a 10 second sample takes around 3 minutes to process. I did some logging, and the first ~3 second go normally, then it gets blocked in recordSamples() for around a whole minute (!) (around 56 seconds to be precise) then it continues as if nothing happened when after a further ~3 seconds, the same 1 minute long blocking happens, etc.
The actual error was probably cased by other codes in the project (which used the lib through RxJava) which assumed it would run in around real-time and no minute-long blocking happen meanwhile. In the end the result is on the server in a 10 second sample, the only problem is that it can't really be used in any real-time applications this way because of the long blockings...

So apparently it looks like it

  1. start off/continue fine
  2. get stuck after ~ 3-4 seconds
  3. when reaching a minute (3-4 seconds normal processing + 56 seconds blocking) -> repeat from 1

It must be something network/protocol related... Like the connection or something gets reset every minute or something - which makes it continue that gets otherwise blocked after a few seconds.

@scorpeeon
Copy link
Author

I see the script in javacpp-presets that builds ffmpeg (cppbuild.sh) is only made to build with OpenSSL and for Windows it uses Zeranoe's builds which has GnuTLS already integrated so that's of little help.

Any tip about how to build it with GnuTLS? I'm really noob in this, and I'm unsure about how to get started. What I'm unsure about is if I somehow manage to separately compile GnuTLS for Android (using RTMPDump or similar) - or even better FFMPEG with GnuTLS for Android - can I just put it in this lib (in the place of the corresponding .so file that currently has openssl - I'm not even sure which one is it) and make it work with minimal additional work? Or it's not so simple and I'm better off building "from scratch" and modifying this script to compile gnutls insted of openssl (if I figure out howto do that)?

@saudet
Copy link
Member

saudet commented May 2, 2016

Sure, if you get a build with GnuTLS, the rest is easy. The hard part is getting the build working...

@scorpeeon
Copy link
Author

scorpeeon commented May 2, 2016

Yeah, thanks, I'll try to do that - though I assume it really won't be easy and I'm not even sure where to start...
BTW it looks like the precompiled binaries for Android are for armv5, is this intentional? As I understand, pretty much all devices today are armv7 compatible and armv5 is lacking pretty basic things like floating point unit support which can cause a huge performance difference...

@scorpeeon
Copy link
Author

scorpeeon commented May 5, 2016

Some very interesting new findings:
It looks like the issue is not present in javacv release 0.11 (it's present on 1.0 and onwards).
On 0.11, rtmps streaming is working fine on android.

(I compiled javacpp-presets + javacv with newer ffmpeg (3.0.2) and openssl (1.0.2h) and it was still broken that's why I starting digging into older versions and since I got various compile errors I got tired with I just tried the archived releases - I'm really unsure where the problem might be)

@saudet saudet added the bug label May 5, 2016
@saudet
Copy link
Member

saudet commented May 5, 2016

Nothing special happened at the release of version 1.0. If you figure out how to fix that, please let me know! Thanks

@scorpeeon
Copy link
Author

I checked and between 0.11 and 1.0 at the first glance I see:
-8 commits in javacpp-presets
-4 commits in javacv
that has changes related to ffmpeg/openssl. (Well, it could be in javacpp too..) And the issue is probably only in one repo of the 2 (or 3), so it shouldn't take too long to test out which commit is to blame..
Well, javacv compiles fairly quickly, but javacpp-presets can take pretty long (took more than on hour on my machine from which ffmpeg took like 15 minutes).

I'll try to check with the changes reverted in javacv but if it's in the other 2 repos, I'm not sure I can check them because of the compile times.

@saudet
Copy link
Member

saudet commented May 6, 2016

Great, thanks for testing that! BTW, it's possible to limit the presets to build only ffmpeg with a command like mvn clean install -pl .,ffmpeg.

@scorpeeon
Copy link
Author

Yeah, I tried that once already, thanks, so I guess building only ffmpeg from the libs should be ok as long as I don't need anything else from javacv. Do I see it correctly that since javacv depends on javacpp-presets and javacpp-presets depends on javacpp: if i change something in javacpp, I would have to recompile the other 2 repos as well, right?
I checked out commits at around javacv release 1.0, first it died at the beginning as it was attempting to use older version of gcc that the current NDK has, but changing that it seems to work.
I'll try to do some basic testing but can't promise anything as I sadly don't have a lot of time for this..
It seems to be a weird compatibility issue. It would be interesting to see if it happens on other platforms that use openssl too..

@saudet
Copy link
Member

saudet commented May 6, 2016

If something doesn't work, yes trying to rebuild everything is the first thing to try, but it's not always required just to test things out.

It's possible to make a Windows build with OpenSSL as well you know. Check inside the cppbuild.sh file for details.

Of course I can't expect you to spend a lot of time on this, but do let me know if you figure out a fix! Thanks

@saudet
Copy link
Member

saudet commented Dec 9, 2016

JavaCV 1.3 has just been released and depends on newer versions of FFmpeg and OpenSSL. Could you give it a try and see if it works now? Thanks for your time on this!

@scorpeeon
Copy link
Author

Hello!

Thanks for the update. I grabbed version 1.3 and tried quickly but it looks like I still get the same exceptions as before. A handful of these exceptions (when continuously trying to write audio), then at the end a memory violation and crash:

12-09 10:53:57.061 12264-12964/com.google.android.alarm W/System.err: org.bytedeco.javacv.FrameRecorder$Exception: av_write_frame() error -5 while writing audio packet.
12-09 10:53:57.061 12264-12964/com.google.android.alarm W/System.err: at org.bytedeco.javacv.FFmpegFrameRecorder.writePacket(FFmpegFrameRecorder.java:1044)
12-09 10:53:57.061 12264-12964/com.google.android.alarm W/System.err: at org.bytedeco.javacv.FFmpegFrameRecorder.record(FFmpegFrameRecorder.java:1026)
12-09 10:53:57.061 12264-12964/com.google.android.alarm W/System.err: at org.bytedeco.javacv.FFmpegFrameRecorder.recordSamples(FFmpegFrameRecorder.java:994)
12-09 10:53:57.061 12264-12964/com.google.android.alarm W/System.err: at org.bytedeco.javacv.FFmpegFrameRecorder.recordSamples(FFmpegFrameRecorder.java:867)

@saudet
Copy link
Member

saudet commented Dec 9, 2016

Thanks for testing! The Windows build also uses OpenSSL these days. Does it do the same thing?

@scorpeeon
Copy link
Author

I tried it on Windows but I get this exception when trying to instantiate FFmpegFrameRecorder:

Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class org.bytedeco.javacpp.avutil
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.bytedeco.javacpp.Loader.load(Loader.java:585)
at org.bytedeco.javacpp.Loader.load(Loader.java:530)
at org.bytedeco.javacpp.avcodec$AVPacket.(avcodec.java:1694)
at org.bytedeco.javacv.FFmpegFrameRecorder.(FFmpegFrameRecorder.java:149)

(the same thing works when I use libs from an older JavaCV, maybe it was 1.1 when it worked)

@saudet
Copy link
Member

saudet commented Dec 9, 2016 via email

@scorpeeon
Copy link
Author

@saudet
Copy link
Member

saudet commented Dec 9, 2016 via email

@pascalbaljet
Copy link

@scorpeeon Did you find a solution?

@scorpeeon
Copy link
Author

@pascalbaljet I didn't yet, unfortunately I didn't have time for it to investigate since then... Still using the old version (0.11) I found to be working.

@pascalbaljet
Copy link

@scorpeeon Thanks for letting me know!

@pascalbaljet
Copy link

pascalbaljet commented May 11, 2017

The solution is building FFMpeg with the librtmp library and then everything works as expected. Here are some useful instructions: https://github.com/OnlyInAmerica/FFmpeg-Android

Succesfully tested with FFMpeg 3.2.4 and rtmpdump 2.4

@saudet
Copy link
Member

saudet commented May 11, 2017

@pascalbaljet Great! Could you send a pull request for that?

@pascalbaljet
Copy link

Yes sure! It needs some cleanup and it is only tested on the Android platform.

@atiqmumtaz507
Copy link

@pascalbaljet Can you please send me working Solution on
[email protected]

I tried also and FFmpegRecorder sends only some packets and then wait so long and then sends again some packets. With RTMP works fine but i have only problem with RTMPS.

Here is my Gradle config

compile 'com.android.support:appcompat-v7:22.0.0'
compile group: 'org.bytedeco', name: 'javacv', version: '1.3.3'
compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '1.3.3'
compile group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: '3.0.0-1.1', classifier: 'android-arm'

Thanks

@saudet
Copy link
Member

saudet commented Aug 16, 2017 via email

@atiqmumtaz507
Copy link

@saudet
i tried following in Gradle (Visual Studio). But Gradle failed to resolve it.
compile group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg-platform', version: '3.3.2-1.3.4', classifier: 'android-arm'

Can you please tell me how can i upgrade it in Gradle ?

@atiqmumtaz507
Copy link

@pascalbaljet
Copy link

@webdeutschland I'll submit a pull request next week

@atiqmumtaz507
Copy link

@pascalbaljet @saudet when will you guys submit the pull ? I am really waiting to test it with new FFmpeg.

Thanks :-)

@pascalbaljet
Copy link

pascalbaljet commented Aug 22, 2017

@saudet @webdeutschland I've commit my changes to a fork: pascalbaljet/javacpp-presets@4952499

I did this instead of pull request because I had to revert OpenSSL back to the 1.0.2 LTS branch, the 1.1.0 branch seems incompatible with librtmp. Another flaw in my commit is this hardcoded path: https://github.com/pascalbaljet/javacpp-presets/blob/4952499f9c03d1b6537b0562ca26ab8571b7d57b/ffmpeg/ffmpeg-librtmp.patch#L10

With these changes I've just successfully compiled FFmpeg for android-arm (javacpp and javacpp-presets v1.3.3 on MacOS 10.12.6). I hope someone finds a solution for the OpenSSL incompatibility and could do some more cleanup of the build script.

@atiqmumtaz507
Copy link

atiqmumtaz507 commented Aug 23, 2017

@pascalbaljet what if you upload your SO (binary files like libavcodec.so etc) Files and we replace these files in JNI Folder. In this way no one needs to compile again and again.

I hope for Android it will work :-) you may upload file in a Google Drive and share link with us.

@pascalbaljet
Copy link

It's a common issue, there is a page about it:
https://github.com/bytedeco/javacpp-presets/wiki/The-UnsatisfiedLinkError-X-File-(a-real-experience)

You'll also find issues opened in this repository and in the javacpp-presets repository concerning the error. For my build I added this line of code:

ReLinker.loadLibrary(context, "rtmp");

@atiqmumtaz507
Copy link

atiqmumtaz507 commented Aug 24, 2017

@saudet @pascalbaljet can you provide me your .so files
(I am using Windows+Visual studio for android development)
Email at : atiqmumtaz2006 (at) gmail.com

@atiqmumtaz507
Copy link

@pascalbaljet thank you. :-) 👍

It was my mistake. I was not loading all libs at the start. NOw i did it and i can run use RTMPS Feature.

@atiqmumtaz507
Copy link

atiqmumtaz507 commented Aug 30, 2017

My compile works only on armeabi-v7a. The problem is other devices does not load rtmp library, although i used ReLinker to load the libraries.

My idea is can you provide me your .so files and i will try to run my app with your .so files.
@pascalbaljet please help me !

@saudet
Copy link
Member

saudet commented Jan 18, 2018

@pascalbaljet @webdeutschland
Could you finish with bytedeco/javacpp-presets#463 so we can merge it?
Thanks all for testing this out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants