Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have set a series of classes to decode H264 streaming video from a server and render it on a SurfaceView. Now this code is working perfectly on every device I've tried including the emulator, but suddenly I bought myself a S7 and in this device it does not work properly anymore.

The weird thing is that some times it will work perfectly, then some other times it will throw this error:

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.

Sometimes it will crash on the dequeueInputBuffers call:

java.lang.IllegalStateException
                                                                                at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
                                                                                at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:2379)

And then again, some other times it will throw this very different error:

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

These errors by themselves are not very verbose and thus I cannot figure out where the problem might be.

Again my code works perfectly on most devices but it's failing on this one. How is this possible? Any ideas?

This is my decoding code:

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()
                    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;
                I would suggest extend your question with some code of decoding the video. 1. I would guess dequeueOutputBuffer being called in wrong state of media codec. 2. SurfaceView does not valid surface when you try to configure media codec.
– Volodymyr Lykhonis
                Jun 15, 2016 at 22:51

It is hard to say what can go wrong. One thing is though

mDecoder.releaseOutputBuffer(outputBufferIndex, updateRender);
if(!updateRender) {
    return outputBuffer[outputBufferIndex].array();

I would not recommend returning array from output buffer. According to documentation it states

Once an output buffer is released to the codec, it MUST NOT be used

If you truly need to have encoded sample, I would better create a copy of output buffer, call release, and then return the copy.

If byte array that's returned used to be processed somehow else, I would recommend extracting this method of decoder into the loop and process the byte buffer (output buffer), and then call release output buffer. For more reference I would look into MediaCodec Synchronous Processing using Buffers

Thanks @VladimirLichonos. I actually removed that bit and got the same result. What I did find out though is that if I up the timeout it seems to work better, whilst if I put a lower value it will fail almost all the time. – MichelReap Jun 16, 2016 at 16:59 Both errors show something is off with surface, one says surface been released other one I think occur when releaseOutputBuffer called with updateRender=true, which is also related to the surface. – Volodymyr Lykhonis Jun 16, 2016 at 17:03 Actually I just tried setting updateRender=false and obviously I don't see anything on the screen, but I am still getting the same exception. Sometimes it happens on the dequeueOutputBuffers, sometimes on the dequeueInputBuffers call. – MichelReap Jun 17, 2016 at 10:03

On Samsung Galaxy S8, I would get ERROR(0x90000012) asynchronously after calling MediaCodec.configure(), before feeding any stream input.

One sure way of getting ERROR(0x90000012) is to use streams in AVCC format (like Apple Quicktime movies).

In fact, it seems across many Android devices, we have more success using H264 in Annex-B format.

Annex-b also means not needing to pass out of band extra data using MediaCodec.BUFFER_FLAG_CODEC_CONFIG or sps/pps configured via MediaFormat (csd-0, csd-1 keys).

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.