我该如何处理电话从JNI来AudioTrack没有崩溃? [英] How do I handle calls to AudioTrack from jni without crashing?

查看:201
本文介绍了我该如何处理电话从JNI来AudioTrack没有崩溃?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图写从JNI回调的AudioTrack,我也得到一个信号7(SIGBUS),故障地址00000000。

我已经看过了Wolf3D例子 odroid 并他们似乎使用android.os.Handler发布一个Runnable,会做一个更新,在正确的线程上下文。我也曾尝试AttachCurrentThread,但我不能在这种情况下也。

它可以播放声音从构造上运行时,即使我把它包在一个线程,然后将其发布到处理程序。当我从JNI做到了相同的通过回调失败。我以为我braeaking一些规则,但我一直没能找出它们是什么。到目前为止,我还没有找到答案在这里左右。

所以我不知道是否有人知道应如何做。

编辑:下面回答

下面code是为了说明这个问题。

Java的:

 包com.example.jniaudiotrack;

进口android.app.Activity;
进口android.media.AudioFormat;
进口android.media.AudioManager;
进口android.media.AudioTrack;
进口android.os.Bundle;
进口android.os.Handler;
进口android.util.Log;

公共类JniAudioTrackActivity延伸活动{
    AudioTrack mAudioTrack;
    byte []的马​​尔;
    公共静态最后的处理程序mHandler =新的处理程序();

    / **第一次创建活动时调用。 * /
    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.main);

        马尔=新的字节[2048];
        的for(int i = 0; I< 2048;我++){
            马尔[I] =(字节)(Math.sin(一)* 128);
        }

        mAudioTrack =新AudioTrack(AudioManager.STREAM_MUSIC,
                11025,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_8BIT,
                2048,
                AudioTrack.MODE_STREAM);
        mAudioTrack.play();

        新主题(新的Runnable(){
            公共无效的run(){
                mHandler.post(新的Runnable(){
                    公共无效的run(){
                        mAudioTrack.write(马尔,0,2048);
                        Log.i(TAG,***从构造处理程序***);
                    }
                });
            }
        })。开始();

        新主题(新的Runnable(){
            公共无效的run(){
                audioFunc();
            }
        })。开始();
    }

    公共本地无效audioFunc();

    @燮pressWarnings(未使用)
    私人无效audioCB(){
        mHandler.post(新的Runnable(){
            公共无效的run(){
                mAudioTrack.write(马尔,0,2048);
                Log.i(TAG,*** audioCB叫***);
            }
        });
    }

    私有静态最后字符串变量=JniAudioTrackActivity;

    静态{
        的System.loadLibrary(jni_audiotrack);
    }
}
 

CPP:

 的#include< jni.h>

为externC{
    JNIEXPORT无效Java_com_example_jniaudiotrack_JniAudioTrackActivity_audioFunc(JNIEnv的* ENV,jobject OBJ);
}

JNIEXPORT无效Java_com_example_jniaudiotrack_JniAudioTrackActivity_audioFunc(JNIEnv的* ENV,jobject OBJ)
{
    JNIEnv的* JNIEnv的;
    JavaVM的*虚拟机;
    ENV-> GetJavaVM(安培; VM);
    VM-> AttachCurrentThread(安培; JNIEnv的,0);

    JCLASS CLS = ENV-> GetObjectClass(OBJ);
    jmethodID audioCBID = ENV->的GetMethodID(CLS,audioCB,()V);

    如果(!audioCBID){
        返回;
    }

    ENV-> CallVoidMethod(CLS,audioCBID);
}
 

跟踪片断:

  I / DEBUG(1653):PID:9811,TID:9811>>> com.example.jniaudiotrack<<<
I / DEBUG(1653):信号7(SIGBUS),故障地址00000000
I / DEBUG(1653):R0 00000800 R1 R2 00000026 00000001 00000000 R3
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件00012358 /system/lib/libdvm.so
 

解决方案

<打击>似乎一直是内存问题。制作mAudioTrack和马尔静态的解决了这个问题。我是送错了对象回调。看到法登发表评论。我已删除调用AttachCurrentThread,因为它并没有使在这种情况下,任何差异。

Java的:

 包com.example.jniaudiotrack;

进口android.app.Activity;
进口android.media.AudioFormat;
进口android.media.AudioManager;
进口android.media.AudioTrack;
进口android.os.Bundle;
进口android.os.Handler;
进口android.util.Log;

公共类JniAudioTrackActivity延伸活动{
    公共AudioTrack mAudioTrack;
    公共字节[]马尔;
    公共静态处理程序mHandler =新的处理程序();

    / **第一次创建活动时调用。 * /
    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.main);

        马尔=新的字节[2048];
        的for(int i = 0; I&LT; 2048;我++){
            马尔[I] =(字节)(Math.sin(一)* 128);
        }

        mAudioTrack =新AudioTrack(AudioManager.STREAM_MUSIC,
                    11025,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_8BIT,
                    2048,
                    AudioTrack.MODE_STREAM);
        mAudioTrack.play();

        新主题(新的Runnable(){
            公共无效的run(){
                audioFunc();
            }
        })。开始();
    }

    公共本地无效audioFunc();

    @燮pressWarnings(未使用)
    私人无效audioCB(){
        mHandler.post(新的Runnable(){
            公共无效的run(){
                mAudioTrack.write(马尔,0,2048);
                Log.i(TAG,*** audioCB叫***);
            }
        });
    }

    私有静态最后字符串变量=JniAudioTrackActivity;

    静态{
        的System.loadLibrary(jni_audiotrack);
    }
}
 

.cpp的:

 的#include&LT; jni.h&GT;

为externC{
    JNIEXPORT无效Java_com_example_jniaudiotrack_JniAudioTrackActivity_audioFunc(JNIEnv的* ENV,jobject OBJ);
}

JNIEXPORT无效Java_com_example_jniaudiotrack_JniAudioTrackActivity_audioFunc(JNIEnv的* ENV,jobject OBJ)
{
    JCLASS CLS = ENV-&GT; GetObjectClass(OBJ);
    jmethodID audioCBID = ENV-&GT;的GetMethodID(CLS,audioCB,()V);

    如果(!audioCBID){
        返回;
    }

    ENV-&GT; CallVoidMethod(OBJ,audioCBID);
}
 

I was trying to write to an AudioTrack from a jni callback, and I get a signal 7 (SIGBUS), fault addr 00000000.

I have looked at the Wolf3D example for odroid and they seem to use a android.os.Handler to post a Runnable that will do an update in the correct thread context. I have also tried AttachCurrentThread, but I fail in this case also.

It works to play the sound when running from the constructor even if I wrap it in a thread and then post it to the handler. When I do the "same" via a callback from jni it fails. I assume I am braeaking some rules, but I haven't been able to figure out what they are. So far, I haven't found the answer here on SO.

So I wonder if anyone knows how this should be done.

EDIT: Answered below.

The following code is to illustrate the problem.

Java:

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);
}

Trace snippet:

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

解决方案

There seems to have been a memory problem. Making mAudioTrack and mArr static solved it. I was sending the wrong object to the callback. See comment by fadden. I have removed the call to AttachCurrentThread since it did not make any difference in this case.

Java:

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);
}

这篇关于我该如何处理电话从JNI来AudioTrack没有崩溃?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆