开发者

Natively buffering audio

This probably is one of my own mistakes, but I can't seem to find what is wrong. After trying to improve performance of my application, I moved audio buffering from the Java layer to the native layer. Audio handling (recording/playing) is already done natively using the OpenSL ES API.

Yet the native buffering is causing my application to crash whenever I start the application. I use a simple Queue implementation as my buffer, where the first node is the oldest data (FIFO).

struct bufferNode{
    struct bufferNode* next;
    jbyte* data;
};

struct bufferQueue{
    struct bufferNode* first;
    struct bufferNode* last;
    int size;
};

The audio data is referred to by the jbyte* in the bufferNode. Access to the Queue is done via these two methods, and is synchronized with a mutex.

void enqueueInBuffer(struct bufferQueue* queue, jbyte* data){
    SLresult result;
    if(queue != NULL){
        if(data != NULL){
            result = pthread_mutex_lock(&recMutex);
            if(result != 0){
                decodeMutexResult(result);
                logErr("EnqueueInBuffer", "Unable to acquire recording mutex");
            } else {
                struct bufferNode* node = (struct bufferNode*)malloc(sizeof(struct bufferNode));
                if(node == NULL){
                    logErr("EnqueueInBuffer", "Insufficient memory available to buffer new audio");
                } else {
                    node->data = data;
                    if(queue->first == NULL){
                        queue->first = queue->last = node;
                    } else {
                        queue->last->next = node;
                        queue->last = node;
                    }
                    queue->size = queue->size + 1;
                    node->next = NULL;
                }
            }
            result = pthread_mutex_unlock(&recMutex);
            if(result != 0){
                decodeMutexResult(result);
                logErr("EnqueueInBuffer", "Unable to release recording mutex");
            }
        } else {
            logErr("EnqueueInBuffer", "Data is NULL");
        }
    } else {
        logErr("EnqueueInBuffer", "Queue is NUL开发者_高级运维L");
    }
}

void dequeueFromBuffer(struct bufferQueue* queue, jbyte* returnData){
    SLresult result;
    result = pthread_mutex_lock(&recMutex);
    if(result != 0){
        decodeMutexResult(result);
        logErr("DequeueFromBuffer", "Unable to acquire recording mutex");
    } else {
        if(queue->first == NULL){
            returnData = NULL;
        } else {
            returnData = queue->first->data;
            struct bufferNode* tmp = queue->first;
            if(queue->first == queue->last){
                queue->first = queue->last = NULL;
            } else {
                queue->first = queue->first->next;
            }
            free(tmp);
            queue->size = queue->size - 1;
        }
    }
    result = pthread_mutex_unlock(&recMutex);
    if(result != 0){
        decodeMutexResult(result);
        logErr("DequeueFromBuffer", "Unable to release recording mutex");
    }
}
  • Where the log and decode methods are selfdeclared utility methods. Log just logs the message to the logcat, while the decode methods "decode" any error number possible from the previous method call.

Yet I keep getting an error when I try to enqueue audio data. Whenever I call the enqueueInBuffer method, I get a SIGSEGV native error, with code 1 (SEGV_MAPERR). Yet I can't seem to find what is causing the error. Both the Queue and the audio data exist when I try to make the enqueueInBuffer method call (which is done in an OpenSL ES Recorder callback, hence the synchronization).

Is there something else going on what causes the segmentation fault? Probably I am responsible for it, but I can't seem to find the error.


Apparently, this was caused by a line of code I have in my OpenSL ES Recorder callback.

The callback originally looked like this:

void recorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context){
    SLresult result;
    enqueueInBuffer(&recordingQueue, (*recorderBuffers[queueIndex]));
    result = (*bq)->Enqueue(bq, recorderBuffers[queueIndex], RECORDER_FRAMES * sizeof(jbyte));
    if(checkError(result, "RecorderCallB", "Unable to enqueue new buffer on recorder") == -1){
        return;
    }
    queueIndex = queueIndex++ % MAX_RECORDER_BUFFERS;
}

However, it seems that the last line of the callback didn't correctly create the new index. The buffers I use are in an array, which is 4 long.

Changing the last line to

queueIndex = (queueIndex + 1) % MAX_RECORDER_BUFFERS;

seems to have fixed the error.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜