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
大佬,我试了一下发现不能在子线程解码,这是为啥呀? #2
Comments
刚刚改到子线程编解码验证了一下,确实会闪退 |
是so库的问题么? |
在子线程中,lame 库会崩溃(对应源码传送门),崩溃信息如下:
|
所以,需要重新编译lame库然后整合进去么? |
出现问题时的代码抽取如下: `// lame_main.c
}` memset 写的是声明出来的字符数组,照理应该不会引起 SEGV_MAPERR 才对。 |
目前只能够简单的推测子线程方法的内存限制比主线程严格: 将 MAX_NOGAP 的宏定义中的值,从 200 减少到 20 后,子线程不会报错,可能可以证明这点。 |
所以内存从800K降到80K就不会报错了么? |
《[bionic源码解读]Android线程栈大小》 介绍了 android 下的线程栈大小相关的内容,重要结论抽取如下 使用 《线程堆栈大小的使用介绍》 的测试代码 // WcvCodec.c
// test code
int print_stack_size() {
pthread_attr_t attr;
size_t stack_size = 0;
int ret = pthread_attr_init(&attr);
if (ret != 0) {
LOGE("pthread_attr_init FAILED");
return JNI_ERR;
}
ret = pthread_attr_getstacksize(&attr, &stack_size);
if (ret != 0) {
LOGE("pthread_attr_getstacksize FAILED");
} else {
LOGE("stack_size = %d Byte, %d k\n", stack_size, stack_size / 1024);
}
}
/*
* Class: com_reinhard_wcvcodec_WcvCodec
* Method: decode
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_reinhard_wcvcodec_WcvCodec_decode
(JNIEnv *env, jclass clazz, jstring amrPath, jstring pcmPath, jstring mp3Path) {
const char *amr = (*env)->GetStringUTFChars(env, amrPath, JNI_FALSE);
const char *pcm = (*env)->GetStringUTFChars(env, pcmPath, JNI_FALSE);
const char *mp3 = (*env)->GetStringUTFChars(env, mp3Path, JNI_FALSE);
int argc = 5;
const char *argv[] = {"./Decoder", amr, pcm, "-wechat", "-quiet"};
// test code
print_stack_size();
if (silk_decoder_main(argc, (char **) argv) == JNI_OK) {
int argc2 = 14;
const char *argv2[] = {"./lame", "-q", "5", "-b", "128", "-m", "m", "-r",
"-s", "24000", "--resample", "24000", pcm, mp3};
return lame_codec_main(argc2, (char **) argv2);
} else {
LOGE("silk_decoder_main failed!");
return JNI_ERR;
}
} 在安卓4.4(Nexus 5) 的打印如下: 06-09 14:20:48.338 24968-25529/com.reinhard.wechat.voicecodec E/WcvCodec: stack_size = 1040384 Byte, 1016 k 源码中的默认堆栈大小宏定义如下(传送门): // bionic/libc/bionic/pthread_attr.cpp
#define DEFAULT_THREAD_STACK_SIZE ((1 * 1024 * 1024) - SIGSTKSZ) 在安卓6.0(魅蓝 Note5)的打印如下: 06-09 14:49:58.692 29743-29743/com.reinhard.wechat.voicecodec E/WcvCodec: stack_size = 1040384 Byte, 1016 k 源码中的默认堆栈大小宏定义如下(传送门): // bionic/libc/bionic/pthread_internal.h
#define PTHREAD_STACK_SIZE_DEFAULT ((1 * 1024 * 1024) - SIGSTKSZ) |
虽然不同系统版本可能存在差异,但可以确定子线程栈的默认大小差不多就是 1M 左右。 回到我们的问题: 2 * 800k = 1600 k > 1024k 会出现 SIGSEGV 也就可以理解了。 |
在 魅蓝 Note 5 上进行验证: 当 MAX_NOGAP 为 89 的时候,可以正常运行,改到 90 后就无法运行了。 2 * 89 * 4k = 712k 因为线程栈还有其他地方会用到,所以无法达到 1016 k 的上限是可以理解的。 |
那有没有可能在Android端调整线程栈的默认大小 |
《线程堆栈大小的使用介绍》 介绍了 C 修改线程堆栈大小的方法,主要是通过 pthread_attr_setstacksize 实现的,如下: #include <stdio.h>
#include <stdlib.h>
#include <pthread.h>//线程操作所需头文件
int main(void)
{
size_t stack_size = 0; //堆栈大小变量
pthread_attr_t attr; //线程属性结构体变量
//初始化线程属性
int ret = pthread_attr_init(&attr);
if(ret != 0)
{
perror("pthread_attr_init");
return -1;
}
stack_size = 1024*20; //堆栈大小设置为20K
ret = pthread_attr_setstacksize(&attr, stack_size);//设置线程堆栈大小
if(ret != 0)
{
perror("pthread_attr_getstacksize");
return -1;
}
stack_size = 0;
ret = pthread_attr_getstacksize(&attr, &stack_size);//获取线程堆栈大小
//打印堆栈值
printf("stack_size = %dB, %dk\n", stack_size, stack_size/1024);
return 0;
} 个人对这方面的了解比较浅,不过还是不建议采用这种方式。 简单看了下代码,MAX_NOGAP 应该是用来控制音频分段(切片)的,语音场景语音文件应该不会特别大,这样修改应该不会导致副作用。 |
感谢大佬的讲解,学到了很多呀! |
新版本已经发布,请用新版本试试 implementation 'com.reinhard:WeChatVoiceCodec:1.0.2' |
恩,可以了。给大佬点赞 ヾ(✿゚▽゚)ノ |
好的 |
No description provided.
The text was updated successfully, but these errors were encountered: