bilibili / ijkplayer

Android/iOS video player based on FFmpeg n3.4, with MediaCodec, VideoToolbox support.
GNU General Public License v2.0
32.43k stars 8.11k forks source link

ijkplayer播放fltp格式的AAC音频崩溃 #2591

Open thinkperson opened 7 years ago

thinkperson commented 7 years ago

我修改了ijkplayer的IO,通过向ffmpeg注册回调来喂数据,但播放fltp格式的AAC音频崩溃,我的音频的详细信息如下:

Stream #0:1(eng): Audio: aac (HE-AAC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 64 kb/s (default)

崩溃的堆栈如下:

** Crash dump: ** Build fingerprint: 'Xiaomi/virgo/virgo:4.4.4/KTU84P/V6.6.7.0.KXECNCF:user/release-keys' pid: 25303, tid: 26924, name: ff_read >>> tv.danmaku.ijk.media.example <<< signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000 Stack frame #00 pc 0002941c /data/app-lib/tv.danmaku.ijk.media.example-1/libijksdl.so (J4AC_android_media_AudioTrackgetMinBufferSize+7): Routine J4AC_android_media_AudioTrack__getMinBufferSize at /Users/peking/ijk_ori/ijkplayer/android/ijkplayer/ijkplayer-armv7a/src/main/jni/ijkmedia/ijkj4a/j4a/class/android/media/AudioTrack.c:82 Stack frame #01 pc 00011cbb /data/app-lib/tv.danmaku.ijk.media.example-1/libijksdl.so (SDL_Android_AudioTrack_new_from_spec+194): Routine SDL_Android_AudioTrack_new_from_spec at /Users/peking/ijk_ori/ijkplayer/android/ijkplayer/ijkplayer-armv7a/src/main/jni/ijkmedia/ijksdl/android/android_audiotrack.c:204 Stack frame #02 pc 00011eef /data/app-lib/tv.danmaku.ijk.media.example-1/libijksdl.so (SDL_Android_AudioTrack_new_from_sdl_spec+78): Routine SDL_Android_AudioTrack_new_from_sdl_spec at /Users/peking/ijk_ori/ijkplayer/android/ijkplayer/ijkplayer-armv7a/src/main/jni/ijkmedia/ijksdl/android/android_audiotrack.c:258 Stack frame #03 pc 00012a69 /data/app-lib/tv.danmaku.ijk.media.example-1/libijksdl.so: Routine aout_open_audio_n at /Users/peking/ijk_ori/ijkplayer/android/ijkplayer/ijkplayer-armv7a/src/main/jni/ijkmedia/ijksdl/android/ijksdl_aout_android_audiotrack.c:157 Stack frame #04 pc 00054e79 /data/app-lib/tv.danmaku.ijk.media.example-1/libijkplayer.so: Routine audio_open at /Users/peking/ijk_ori/ijkplayer/android/ijkplayer/ijkplayer-armv7a/src/main/jni/ijkmedia/ijkplayer/ff_ffplay.c:2221 Stack frame #05 pc 00055855 /data/app-lib/tv.danmaku.ijk.media.example-1/libijkplayer.so: Routine read_thread at /Users/peking/ijk_ori/ijkplayer/android/ijkplayer/ijkplayer-armv7a/src/main/jni/ijkmedia/ijkplayer/ff_ffplay.c:2685 Stack frame #06 pc 0000f89f /data/app-lib/tv.danmaku.ijk.media.example-1/libijksdl.so: Routine SDL_RunThread at /Users/peking/ijk_ori/ijkplayer/android/ijkplayer/ijkplayer-armv7a/src/main/jni/ijkmedia/ijksdl/ijksdl_thread.c:40 Stack frame #07 pc 0000d248 /system/lib/libc.so (thread_entry+72) Stack frame #08 pc 0000d3e0 /system/lib/libc.so (pthread_create+240)

崩溃的地方在: while (SDL_AoutOpenAudio(ffp->aout, &wanted_spec, &spec) < 0)

如果不通过我的回调,使用http,rtmp等协议喂数据,同样的音频数据就不会崩溃。

我猜想可能ijk对音频做了重新编码,转换成S16格式。但为什么回调方式就没有进行重采样呢?还是说我需要做什么特殊的设置或处理?

盼答复!谢谢!

==========

补充: 这是我日志打印的 AudioTrack 的参数:采样率,格式,通道数: SDL_Android_AudioTrack: CHANNEL_OUT_STEREO SDL_Android_AudioTrack: ENCODING_PCM_16BIT 1.sample rate 44100 2.sample rate 44100

我根据crash的堆栈定位到的崩溃代码是:

android_audiotrack.c: int min_buffer_size = J4AC_AudioTrack__getMinBufferSize(env, atrack->spec.sample_rate_in_hz, atrack->spec.channel_config, atrack->spec.audio_format); 打印传入的参数如下:

env=0x0, atrack->spec.sample_rate_in_hz=44100, atrack->spec.channel_config=12, atrack->spec.audio_format=2

为什么env是空的呢?

另外需要特别说明的是:在ios平台下用同样的回调方式,就没有任何崩溃的问题,音频正常。

xinzhengzhang commented 7 years ago

Seems jni problem. Add some trace in SDL_JNI_DetachThreadEnv

andyjmzheng commented 7 years ago

jni跨线程的时候。env 需要用SDL_JNI_DetachThreadEnv。

thinkperson commented 7 years ago

这是在ijkplayer/android/ijkplayer/ijkplayer-armv7a/src/main/jni/ijkmedia/ijksdl/android/ijksdl_android_jni.c里打印的输出:

In JNI_OnLoad, env == 0x416cf2e8 In SDL_JNI_SetupThreadEnv, jvm = 0x416cf288 In SDL_JNI_SetupThreadEnv, (*jvm)->AttachCurrentThread(jvm, &env, NULL) == JNI_OK, env = 0x0

貌似问题的根源就在函数SDL_JNI_SetupThreadEnv中,该函数调用AttachCurrentThread,返回JNI_OK,但获取到的JNIEnv为NULL,造成了后面函数调用链的JNIEnv一直为NULL,直至本问题中描述的crash。

为神马AttachCurrentThread返回OK,但JNIENv为NULL?