كيف يمكنني التعامل مع المكالمات إلى Audiotrack من JNI دون تحطم؟
-
23-09-2019 - |
سؤال
كنت أحاول الكتابة إلى Audiotrack من رد اتصال JNI ، وأحصل على إشارة 7 (Sigbus) ، خطأ Addr 00000000.
لقد نظرت إلى مثال Wolf3D Odroid ويبدو أنهم يستخدمون Android.os.handler لنشر عملية تشغيل قابلة للتشغيل من شأنها إجراء تحديث في سياق الخيط الصحيح. لقد حاولت أيضًا إرفاق CurrentTrThread ، لكنني فشلت في هذه الحالة أيضًا.
إنه يعمل لتشغيل الصوت عند الركض من المُنشئ حتى لو قمت بلفه في خيط ثم نشره على المعالج. عندما أفعل "نفسه" عبر رد اتصال من Jni يفشل. أفترض أنني أتعامل مع بعض القواعد ، لكنني لم أتمكن من معرفة ما هي عليه. حتى الآن ، لم أجد الإجابة هنا على ذلك.
لذلك أتساءل عما إذا كان أي شخص يعرف كيف ينبغي القيام بذلك.
تحرير: تم الرد عليها أدناه.
الرمز التالي هو توضيح المشكلة.
جافا:
package com.example.jniaudiotrack;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
public class JniAudioTrackActivity extends Activity {
AudioTrack mAudioTrack;
byte[] mArr;
public static final Handler mHandler = new Handler();
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mArr = new byte[2048];
for (int i = 0; i < 2048; i++) {
mArr[i] = (byte) (Math.sin(i) * 128);
}
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
11025,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_8BIT,
2048,
AudioTrack.MODE_STREAM);
mAudioTrack.play();
new Thread(new Runnable() {
public void run() {
mHandler.post(new Runnable() {
public void run() {
mAudioTrack.write(mArr, 0, 2048);
Log.i(TAG, "*** Handler from constructor ***");
}
});
}
}).start();
new Thread(new Runnable() {
public void run() {
audioFunc();
}
}).start();
}
public native void audioFunc();
@SuppressWarnings("unused")
private void audioCB() {
mHandler.post(new Runnable() {
public void run() {
mAudioTrack.write(mArr, 0, 2048);
Log.i(TAG, "*** audioCB called ***");
}
});
}
private static final String TAG = "JniAudioTrackActivity";
static {
System.loadLibrary("jni_audiotrack");
}
}
CPP:
#include <jni.h>
extern "C" {
JNIEXPORT void Java_com_example_jniaudiotrack_JniAudioTrackActivity_audioFunc(JNIEnv* env, jobject obj);
}
JNIEXPORT void Java_com_example_jniaudiotrack_JniAudioTrackActivity_audioFunc(JNIEnv* env, jobject obj)
{
JNIEnv* jniEnv;
JavaVM* vm;
env->GetJavaVM(&vm);
vm->AttachCurrentThread(&jniEnv, 0);
jclass cls = env->GetObjectClass(obj);
jmethodID audioCBID = env->GetMethodID(cls, "audioCB", "()V");
if (!audioCBID) {
return;
}
env->CallVoidMethod(cls, audioCBID);
}
مقتطف تتبع:
I/DEBUG ( 1653): pid: 9811, tid: 9811 >>> com.example.jniaudiotrack <<<
I/DEBUG ( 1653): signal 7 (SIGBUS), fault addr 00000000
I/DEBUG ( 1653): r0 00000800 r1 00000026 r2 00000001 r3 00000000
I/DEBUG ( 1653): r4 42385726 r5 41049e54 r6 bee25570 r7 ad00e540
I/DEBUG ( 1653): r8 000040f8 r9 41048200 10 41049e44 fp 00000000
I/DEBUG ( 1653): ip 000000f8 sp bee25530 lr ad02dbb5 pc ad012358 cpsr 20000010
I/DEBUG ( 1653): #00 pc 00012358 /system/lib/libdvm.so
المحلول
يبدو أن هناك مشكلة في الذاكرة. جعل Maudiotrack و Marr ثابت حل. كنت أرسل الكائن الخطأ إلى رد الاتصال. انظر تعليق فادين. لقد قمت بإزالة المكالمة إلى AttachCurrentThread لأنه لم تحدث أي فرق في هذه الحالة.
جافا:
package com.example.jniaudiotrack;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
public class JniAudioTrackActivity extends Activity {
public AudioTrack mAudioTrack;
public byte[] mArr;
public static Handler mHandler = new Handler();
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mArr = new byte[2048];
for (int i = 0; i < 2048; i++) {
mArr[i] = (byte) (Math.sin(i) * 128);
}
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
11025,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_8BIT,
2048,
AudioTrack.MODE_STREAM);
mAudioTrack.play();
new Thread(new Runnable() {
public void run() {
audioFunc();
}
}).start();
}
public native void audioFunc();
@SuppressWarnings("unused")
private void audioCB() {
mHandler.post(new Runnable() {
public void run() {
mAudioTrack.write(mArr, 0, 2048);
Log.i(TAG, "*** audioCB called ***");
}
});
}
private static final String TAG = "JniAudioTrackActivity";
static {
System.loadLibrary("jni_audiotrack");
}
}
CPP:
#include <jni.h>
extern "C" {
JNIEXPORT void Java_com_example_jniaudiotrack_JniAudioTrackActivity_audioFunc(JNIEnv* env, jobject obj);
}
JNIEXPORT void Java_com_example_jniaudiotrack_JniAudioTrackActivity_audioFunc(JNIEnv* env, jobject obj)
{
jclass cls = env->GetObjectClass(obj);
jmethodID audioCBID = env->GetMethodID(cls, "audioCB", "()V");
if (!audioCBID) {
return;
}
env->CallVoidMethod(obj, audioCBID);
}