كيف يمكنني التعامل مع المكالمات إلى Audiotrack من JNI دون تحطم؟

StackOverflow https://stackoverflow.com/questions/2560748

سؤال

كنت أحاول الكتابة إلى 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);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top