public final FrameInfo dequeueDecodedFrame() throws IOException {
        if(mOutputEos) return null;

        int res = mCodec.dequeueOutputBuffer(mBufferInfo, TIMEOUT_US);
        mOutputEos = res >= 0 && (mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;

        if(mOutputEos && mRepresentationChanging) {
            /* Here, the output is not really at its end, it's just the end of the
             * current representation segment, and the codec needs to be reconfigured to
             * the following representation format to carry on.
             */

            reinitCodec();

            mOutputEos = false;
            mRepresentationChanging = false;
            mRepresentationChanged = true;
        }
        else if (res >= 0) {
            // Frame decoded. Fill frame info object and return to caller...

            // Adjust buffer: http://bigflake.com/mediacodec/#q11
            // This is done on audio buffers only, video decoder does not return actual buffers
            ByteBuffer data = mCodecOutputBuffers[res];
            if (data != null && mBufferInfo.size != 0) {
                data.position(mBufferInfo.offset);
                data.limit(mBufferInfo.offset + mBufferInfo.size);
                //Log.d(TAG, "raw data bytes: " + mBufferInfo.size);
            }

            FrameInfo fi = mEmptyFrameInfos.get(0);
            fi.buffer = res;
            fi.data = data;
            fi.presentationTimeUs = mBufferInfo.presentationTimeUs;
            fi.endOfStream = mOutputEos;

            if(mRepresentationChanged) {
                mRepresentationChanged = false;
                fi.representationChanged = true;
            }
            if(fi.endOfStream) {
                Log.d(TAG, "EOS output");
            } else {
                mDecodingPTS = fi.presentationTimeUs;
            }

            //Log.d(TAG, "decoded PTS " + fi.presentationTimeUs);

            return fi;
        } else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
            mCodecOutputBuffers = mCodec.getOutputBuffers();
            Log.d(TAG, "output buffers have changed.");
        } else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
            // NOTE: this is the format of the raw output, not the format as specified by the container
            MediaFormat format = mCodec.getOutputFormat();
            Log.d(TAG, "output format has changed to " + format);
            onOutputFormatChanged(format);
        } else if (res == MediaCodec.INFO_TRY_AGAIN_LATER) {
            //Log.d(TAG, "dequeueOutputBuffer timed out");
        }

        //Log.d(TAG, "EOS NULL");
        return null; // EOS already reached, no frame left to return
    }
Consumes a decoded frame from the decoder output and returns information about it.

@return a FrameInfo if a frame was available; NULL if the decoder needs more input
samples/decoding time or if the output EOS has been reached
MediaPlayer/src/main/java/net/protyposis/android/mediaplayer/MediaCodecDecoder.java