Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Unity Android中读取ShortBuffer时发生IllegalStateException_Android_Unity3d_Bytebuffer_M4a_Flac - Fatal编程技术网

在Unity Android中读取ShortBuffer时发生IllegalStateException

在Unity Android中读取ShortBuffer时发生IllegalStateException,android,unity3d,bytebuffer,m4a,flac,Android,Unity3d,Bytebuffer,M4a,Flac,我正在Unity做一个游戏,我需要媒体缓冲区中的原始音频数据。下面的代码被用作Unity中的jar插件。它在安卓4.x上运行没有问题。但当我尝试在Android 5.0.1或5.1上运行它时,我会遇到以下异常,但仅当我尝试打开aac或m4a文件时。有什么建议吗 这是我读取音频缓冲区的函数: public short[] ReadNextSamples() { if (sawOutputEOS) { return new short[0];

我正在Unity做一个游戏,我需要媒体缓冲区中的原始音频数据。下面的代码被用作Unity中的jar插件。它在安卓4.x上运行没有问题。但当我尝试在Android 5.0.1或5.1上运行它时,我会遇到以下异常,但仅当我尝试打开aac或m4a文件时。有什么建议吗

这是我读取音频缓冲区的函数:

   public short[] ReadNextSamples() {
        if (sawOutputEOS) {
            return new short[0];
        }
        int res;
        while (true)
        {
            res = codec.dequeueOutputBuffer(info, kTimeOutUs);

        if (res >= 0)
        {
            if (info.size > 0)
            {
                break;
            }
            else
            {
                codec.releaseOutputBuffer(res, false);

                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM)!= 0)
                {
                    sawOutputEOS = true;
                    return new short[0];
                }
            }
        }
    }
    int outputBufIndex = res;
    ByteBuffer buf = codecOutputBuffers[outputBufIndex];
    int sampleSize = info.size / 2;
    short[] sampleValues = new short[sampleSize];
    ShortBuffer shBuf = buf.asShortBuffer();

    try {
        shBuf.get(sampleValues, 0, sampleSize);
    } catch (Exception e) {
        //the exception is being thrown here
        e.printStackTrace();
    }

    codec.releaseOutputBuffer(outputBufIndex, false);
    if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
        sawOutputEOS = true;
    }
    return sampleValues;
}
例外情况:

06-04 16:18:01.188: W/System.err(20884): java.lang.IllegalStateException: buffer is inaccessible
06-04 16:18:01.188: W/System.err(20884): at java.nio.DirectByteBuffer.checkIsAccessible(DirectByteBuffer.java:551)
06-04 16:18:01.188: W/System.err(20884): at java.nio.DirectByteBuffer.get(DirectByteBuffer.java:155)
06-04 16:18:01.188: W/System.err(20884): at java.nio.ByteBufferAsShortBuffer.get(ByteBufferAsShortBuffer.java:103)
06-04 16:18:01.190: W/System.err(20884): at com.pocketgames.musiverse.MediaDecoder.ReadNextSamples(MediaDecoder.java:112)
06-04 16:18:01.190: W/System.err(20884): at com.unity3d.player.ReflectionHelper.nativeProxyInvoke(Native Method)
06-04 16:18:01.190: W/System.err(20884): at com.unity3d.player.ReflectionHelper.a(Unknown Source)
06-04 16:18:01.190: W/System.err(20884): at com.unity3d.player.ReflectionHelper$1.invoke(Unknown Source)
06-04 16:18:01.190: W/System.err(20884): at java.lang.reflect.Proxy.invoke(Proxy.java:397)
06-04 16:18:01.190: W/System.err(20884): at $Proxy0.run(Unknown Source)
06-04 16:18:01.191: W/System.err(20884): at java.lang.Thread.run(Thread.java:818)

我在Android L中遇到了类似的问题,可以通过使用新的MediaCodec API获取缓冲区来解决

而不是

ByteBuffer buf = codecOutputBuffers[outputBufIndex];
你可以使用

ByteBuffer buf = codec.getOutputBuffer(outputBufIndex);

在我的例子中,这解决了访问输入缓冲区时的问题。

基本上,您应该使用API级别相关的代码。我想你可能已经弄明白了。但是为了记录,您应该使用

ByteBuffer buf = codecOutputBuffers[outputBufIndex];
对于API级别<21

对于API级别>=21

代码如下所示:

final int version = Build.VERSION.SDK_INT;
ByteBuffer buf;
if (version >= 21) {
    buf = codec.getOutputBuffer(outputBufIndex);
} else {
    buf = codecOutputBuffers[outputBufIndex];
}
如果查看
MediaCodec
类的源代码,则
getOutputBuffer
的代码为:

@Nullable
public ByteBuffer getOutputBuffer(int index) {
    ByteBuffer newBuffer = getBuffer(false /* input */, index);
    synchronized(mBufferLock) {
        invalidateByteBuffer(mCachedOutputBuffers, index);
        mDequeuedOutputBuffers.put(index, newBuffer);
    }
    return newBuffer;
}
因此,您得到的错误与获取锁有关,对于API级别>=21的
MediaCodec
的实现可能需要锁
mBufferLock
,因此您得到与不可访问性相关的错误。我希望这有帮助

@Nullable
public ByteBuffer getOutputBuffer(int index) {
    ByteBuffer newBuffer = getBuffer(false /* input */, index);
    synchronized(mBufferLock) {
        invalidateByteBuffer(mCachedOutputBuffers, index);
        mDequeuedOutputBuffers.put(index, newBuffer);
    }
    return newBuffer;
}