我设置了一系列类来解码来自服务器的H264流视频,并将其呈现在SurfaceView上。现在,这段代码在我尝试过的每个设备上都能完美地工作,包括模拟器,但是突然我给自己买了一个S7,在这个设备上它不能正常工作了。
奇怪的是,有时它会完美地工作,而另一些时候则会抛出这个错误:
06-15 16:41:40.249 13300-24605/cm.myapp E/ACodec: [OMX.Exynos.avc.dec] ERROR(0x90000012)
06-15 16:41:40.249 13300-24605/cm.myapp E/ACodec: signalError(omxError 0x90000012, internalError -2147483648)
06-15 16:41:40.249 13300-24604/cm.myapp E/MediaCodec: Codec reported err 0x90000012, actionCode 0, while in state 6
06-15 16:41:40.249 13300-24578/cm.myapp W/MediaStreamerThread: Failed to draw media.有时它会在dequeueInputBuffers调用中崩溃:
java.lang.IllegalStateException
at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:2379)然后,在其他一些时候,它会抛出这个非常不同的错误:
06-15 16:34:57.239 13300-16625/cm.myapp W/System.err: java.lang.IllegalArgumentException: The surface has been released
06-15 16:34:57.239 13300-16625/cm.myapp W/System.err: at android.media.MediaCodec.native_configure(Native Method)
06-15 16:34:57.239 13300-16625/cm.myapp W/System.err: at android.media.MediaCodec.configure(MediaCodec.java:1778)
java.lang.RuntimeException: Could not create h264 decoder这些错误本身并不是很详细,因此我不知道问题出在哪里。
再说一次,我的代码在大多数设备上都运行得很好,但在这台设备上却失败了。这怎麽可能?有什么想法吗?
这是我的解码代码:
public class H264Decoder
{
static private final long TIMEOUT_US = 10000L;
private MediaCodec mDecoder;
private Surface mSurface;
private static final List<byte[]> EMPTY_ENCODE_RESULT = new ArrayList<>();
public void init()
{
try
{
mDecoder = MediaCodec.createDecoderByType( "video/avc" );
MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 640, 480);
mDecoder.configure(mediaFormat, mSurface, null, 0);
mDecoder.start();
}
catch(NoClassDefFoundError ex) {
ex.printStackTrace();
throw new RuntimeException("Could not create h264 decoder", ex);
}
}
public List<byte[]> offer(byte[] data)
{
List<byte[]> returnValue = new ArrayList<>();
returnValue.add(decode(data, true));
return returnValue;
}
public void release()
{
assert mSurface != null;
assert mDecoder != null;
mDecoder.stop();
mDecoder.release();
mDecoder = null;
}
public H264Decoder(Surface surface)
{
mSurface = surface;
}
public byte[] decode(byte[] data, boolean updateRender)
{
if (mSurface == null)
{
return null;
}
// INPUT -----------------------------------------------------------------------------------
int inputBufferIndex = mDecoder.dequeueInputBuffer(TIMEOUT_US);
if (inputBufferIndex >= 0)
{
// Get an input buffer from the codec, fill it with data, give it back
ByteBuffer inputBuffer = mDecoder.getInputBuffers()[inputBufferIndex];
inputBuffer.put(data);
mDecoder.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0 );
}
// OUTPUT ----------------------------------------------------------------------------------
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
int outputBufferIndex = mDecoder.dequeueOutputBuffer(info, TIMEOUT_US);
if ( outputBufferIndex >= 0 )
{
final ByteBuffer[] outputBuffer = mDecoder.getOutputBuffers();
mDecoder.releaseOutputBuffer(outputBufferIndex, updateRender);
}
else if ( outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED )
{
//outputBuffers = codec.getOutputBuffers();
}
else if ( outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED )
{
MediaFormat format = mDecoder.getOutputFormat();
}
return null;
}
}发布于 2016-06-17 00:19:59
很难说会出什么问题。但有一件事是
mDecoder.releaseOutputBuffer(outputBufferIndex, updateRender);
if(!updateRender) {
return outputBuffer[outputBufferIndex].array();
}我不建议从输出缓冲区返回数组。According to documentation它声明
一旦输出缓冲区释放到编解码器,就不能使用它
如果您确实需要编码的样本,我最好创建一个输出缓冲区的副本,调用release,然后返回副本。
如果返回的字节数组被以某种方式处理,我建议将解码器的这个方法提取到循环中并处理字节缓冲区(输出缓冲区),然后调用释放输出缓冲区。为了获得更多参考,我将查看MediaCodec Synchronous Processing using Buffers
发布于 2017-01-12 17:41:24
对于三星S7,您必须确保插入解码器的第一个H264帧是I帧。
发布于 2019-08-17 16:31:09
在三星Galaxy S8上,我会在调用MediaCodec.configure()之后异步获取ERROR(0x90000012),然后再提供任何流输入。
获得ERROR(0x90000012)的一个可靠方法是使用AVCC格式的流(就像Apple Quicktime电影)。
事实上,似乎在许多安卓设备上,我们使用附件B格式的H264取得了更大的成功。
附件-b还意味着不需要使用MediaCodec.BUFFER_FLAG_CODEC_CONFIG或通过MediaFormat (csd-0、csd-1密钥)配置的sps/pps传递带外额外数据。
https://stackoverflow.com/questions/37839215
复制相似问题