Android MediaCodec缓冲区下溢EXE
我有一个h264流,想在Android 4.1.2中使用MediaCodec进行解码 流可以使用ffmpeg进行解码,但是速度很慢,所以我想使用MediaCodec。手机是三星GalaxyS3 单击一个按钮,将启动一个新的活动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
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);