OpenSL ES RegisterCallback вызывает сбой

Я должен использовать OpenSL для своего проекта (пробовал Soundpool, но это совсем не хорошо). Однако после многократного воспроизведения звука (около 35 раз подряд) приложение закрывается (думаю, может быть, из-за переполнения).

Я попытался освободить буфер/память, чтобы решить проблему (и, ради бога, я не знаю, как это сделать, используя этот OpenSL). Поэтому я решил попробовать освободить, когда файл закончил играть. OpenSL ES предоставляет нам функцию RegisterCallback, которая может помочь. Возникла новая проблема, в моем случае (с использованием файла URI) RegisterCallback снова вызвала сбой моего приложения. Он застрял.

Вот мой код. Пожалуйста помоги. Он разбился сразу после //register callback for uri.

static short fdBuffer[SAWTOOTH_FRAMES];

// create URI audio player
    jboolean Java_jp_mobigame_ayakashi_CardGameActivity_createUriAudioPlayer(JNIEnv* env, jclass clazz,
            jstring uri)
    {
        __android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "\n createUri \n");
        SLresult result;

        // convert Java string to UTF-8
        const jbyte *utf8 = (*env)->GetStringUTFChars(env, uri, NULL);
        assert(NULL != utf8);

        // configure audio source
        // (requires the INTERNET permission depending on the uri parameter)
        SLDataLocator_URI loc_uri = {SL_DATALOCATOR_URI, (SLchar *) utf8};
        SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
        SLDataSource audioSrc = {&loc_uri, &format_mime};

        // configure audio sink
        SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
        SLDataSink audioSnk = {&loc_outmix, NULL};

        // create audio player
        const SLInterfaceID ids[3] = {SL_IID_SEEK, SL_IID_MUTESOLO /*SL_IID_BUFFERQUEUE*/, SL_IID_VOLUME};
        const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
        result = (*engineEngine)->CreateAudioPlayer(engineEngine, &uriPlayerObject, &audioSrc,
                &audioSnk, 3, ids, req);
        // note that an invalid URI is not detected here, but during prepare/prefetch on Android,
        // or possibly during Realize on other platforms
        assert(SL_RESULT_SUCCESS == result);

        // release the Java string and UTF-8
        (*env)->ReleaseStringUTFChars(env, uri, utf8);

        // realize the player
        result = (*uriPlayerObject)->Realize(uriPlayerObject, SL_BOOLEAN_FALSE);
        // this will always succeed on Android, but we check result for portability to other platforms
        if (SL_RESULT_SUCCESS != result) {
            (*uriPlayerObject)->Destroy(uriPlayerObject);
            uriPlayerObject = NULL;
            return JNI_FALSE;
        }

        // get the play interface
        result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PLAY, &uriPlayerPlay);
        assert(SL_RESULT_SUCCESS == result);

        // get the seek interface
        result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_SEEK, &uriPlayerSeek);
        assert(SL_RESULT_SUCCESS == result);


        __android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "\n createUri 1\n");
        //get the buffer queue interface
        result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &uriPlayerBufferQueue);
        assert(SL_RESULT_SUCCESS == result);
        __android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "\n createUri 2\n");


        //register callback for uri
        result = (*uriPlayerBufferQueue)->RegisterCallback(uriPlayerBufferQueue, bqUriPlayerCallback, NULL);
        assert(SL_RESULT_SUCCESS == result);
        __android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "\n createUri 4\n");

        //Enqueue
        __android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "\n createUri 3\n");
        result = (*uriPlayerBufferQueue)->Enqueue(uriPlayerBufferQueue, fdBuffer, sizeof(fdBuffer));


        // get the mute/solo interface
        result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_MUTESOLO, &uriPlayerMuteSolo);
        assert(SL_RESULT_SUCCESS == result);

        // get the volume interface
        result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_VOLUME, &uriPlayerVolume);
        assert(SL_RESULT_SUCCESS == result);

        return JNI_TRUE;

    }

person Egar    schedule 11.09.2012    source источник


Ответы (1)


Похоже, вы пытаетесь получить интерфейс буферной очереди, хотя указываете источник uri. Вы также, кажется, запрашиваете данные. Если вы просто пытаетесь воспроизвести звук из uri, вам не нужно этого делать. Если вы пытаетесь выводить в буфер вместо динамиков, то это может быть допустимо. Я ни в коем случае не эксперт по OpenSL, поэтому для этого может быть причина. Однако, если для этого нет причины, попробуйте вместо этого зарегистрировать обратный вызов в объекте игрока.

(*uriPlayerPlay)->RegisterCallback(uriPlayerPlay, bqUriPlayerCallback, NULL);

В качестве примечания вы, вероятно, захотите установить маску события обратного вызова. Есть несколько вариантов, но я считаю, что тот, который вы ищете, это:

(*uriPlayerPlay)->SetCallbackEventsMask(uriPlayerPlay, SL_PLAYEVENT_HEADATEND)

Обратите внимание, что с этим могут возникнуть проблемы. См. https://groups.google.com/forum/?fromgroups=#!topic/android-ndk/7YaqlKlDMO4.

Если это не поможет, может быть полезно увидеть ваше определение функции обратного вызова. Я считаю, что это должно выглядеть примерно так:

static void bqUriPlayerCallback (SLPlayItf caller, void *pContext, SLuint32 playevent)
person tboling1    schedule 18.03.2013