RTSP over HTTP streaming of H.264 video in Android
Android Jeally Bean and later (API Level 16 and above) support MediaCodec thatn can handle H.264 encoded video. There are some samples using this feature.
To use MediaCodec display H.264 encode video streamed using RTSP over HTTP:
- Demux the stream to packets each of which corresponds to a frame.
- Once the first frame is completed, MediaFormat mf = MediaFormat.createVideoFormat("video/avc", uiFrameWidth, uiFrameHeight); where uiFrameWidth and uiFrameHeight are from SPS.
- Configure MediaFormat mf with SPS and PPS with the header (i.e. startcode: 0x00, 0x00, 0x00, 0x01) - mf.setByteBuffer("csd-0", bbSPS); mf.setByteBuffer("csd-1", bbPPS); This is critical. SPS and PPS must be provided to MediaFormat mf. Sending them as NAL units to the decoder will not work, but will not hurt either.
- Create MediaCode: _mcDecoder = MediaCodec.createDecoderByType("video/avc");
- Configure it: _mcDecoder.configure(mf, _surface, null, 0); where _surface can be retrieved from the SurfaceHolder of a SurfaceView.
- Start decoding: _mcDecoder.start();
- Add NAL units to the decoder as soon as they arrive.
- Keeping checking the output buffer (_mcDecoder.dequeueOutputBuffer(bi, TIMEOUT_USEC). If the returned output buffer index is none of the following: MediaCodec.INFO_TRY_AGAIN_LATER, MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED, or MediaCodec.INFO_OUTPUT_FORMAT_CHANGED, < 0, rend the decoded frame (_mcDecoder.releaseOutputBuffer(iOutputBufferIndex, true);). This is necessary, not optinal as the Android document states.
This blog has a good explanation of codec specific data.
MediaCodec is not as robust as many wish, and exceptions generated by it are terse often with little useful information. For example, the setup of MediaCode can go smoothly without any problem, and even dequeueInputBuffer wors fine, but dequeueOutputBuffer may generate a "java.lang.IllegalStateException" exception.
Emulators usually cannot handle H.264 video. There have been exceptions.