Android MediaCodec缓冲区下溢EXE

Android MediaCodec缓冲区下溢EXE,android,android-mediacodec,Android,Android Mediacodec,我有一个h264流,想在Android 4.1.2中使用MediaCodec进行解码 流可以使用ffmpeg进行解码,但是速度很慢,所以我想使用MediaCodec。手机是三星GalaxyS3 单击一个按钮,将启动一个新的活动 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); test = new SurfaceView(getApplicationCont

我有一个h264流,想在Android 4.1.2中使用MediaCodec进行解码

流可以使用ffmpeg进行解码,但是速度很慢,所以我想使用MediaCodec。手机是三星GalaxyS3

单击一个按钮,将启动一个新的活动

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    test = new SurfaceView(getApplicationContext());
    test.getHolder().addCallback(this);
    setContentView(test);
}
在回调中

public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    // TODO Auto-generated method stub
    //codedBuffer = new byte[1536000];
    if(wt == null){
        wt = new RenderThread(arg0.getSurface());
        wt.start();
    }

}
RenderRead在哪里

public void run() {
formatIn = MediaFormat.createVideoFormat("video/avc", 480, 800);
coder = MediaCodec.createDecoderByType("video/avc");
if(formatIn != null)
    coder.configure(formatIn, mSurface, null, 0);
coder.start();
ByteBuffer[] inputBuffers = coder.getInputBuffers();
ByteBuffer[] outputBuffers = coder.getOutputBuffers();
mBufferInfo = new BufferInfo();
while(!Thread.interrupted()){

    while(waitForStream){
        Thread.yield();
}
if(!EOS ){

int inBufIndex = coder.dequeueInputBuffer(10000);
if(inBufIndex != -1){
ByteBuffer buffer = inputBuffers[inBufIndex]; 
buffer.put(receivebuffer,0,size);
coder.queueInputBuffer(inBufIndex, 0, size, 0,0);
}
int outBufIndex = coder.dequeueOutputBuffer(mBufferInfo, 10000);
switch (outBufIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED");
outputBuffers = coder.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
Log.d("DecodeActivity", "New format " );
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
    Log.d("DecodeActivity", "dequeueOutputBuffer timed out!");
    break;
default:
//  ByteBuffer buffer = outputBuffers[outBufIndex];
//  buffer.get(decodedBuffer);
    coder.releaseOutputBuffer(outBufIndex, true);
}
}
decodedBuffer
是一个字节[1536000]

更新的错误日志为 由于这是一个
get()
调用,我假设您在这里失败了:

ByteBuffer buffer = outputBuffers[outBufIndex];
buffer.get(decodedBuffer);
如果您查看使用原始YUV数据的CTS,您将看到一个额外的位:

ByteBuffer outputFrame = decoderOutputBuffers[decoderStatus];
outputFrame.position(info.offset);
outputFrame.limit(info.offset + info.size);
MediaCodec
代码不读取或更新
ByteBuffer
状态,因此必须显式执行。这也适用于输入端

EncodeDecodeTest的缓冲区到缓冲区和缓冲区到表面部分将与API 16一起工作,并且对检查非常有用。表面对表面试验要求API 18

您会发现,测试并没有将缓冲区内容提取到固定大小的数组中,因为帧的解码大小是静态不可知的。您需要知道输出的颜色格式,不同设备的颜色格式会有所不同。您还会发现,
checkFrame()
在某些设备上完全放弃,因为它不理解帧格式


如果您可以解码到曲面,那么您的代码可以像
checkSurfaceFrame()
那样工作,您不需要关心缓冲区格式,因为OpenGL ES可以完成所有工作。另请参见。

因为我不想使用
buffer.get()
调用,我只是对其进行注释,它正在工作,但出现了一个新问题,现在我得到了
BufferOverFlow
异常!我将更新问题中的日志,因为在我遇到
BufferOverFlow
问题之前,我看到了解码的帧(可能是第一个解码的帧)。。在打电话之前先打个电话把它解决了谢谢你,法登。如果没有这个“额外位”,应用程序在成功解码36次后,就会获得java.nio.BufferUnderflowException。这是100%可复制的。它是用来解码音频的。
ByteBuffer outputFrame = decoderOutputBuffers[decoderStatus];
outputFrame.position(info.offset);
outputFrame.limit(info.offset + info.size);