title: Decoding an RTP stream with H264 data on Android Using MediaCodec
body: <p>I am currently attempting to parse H264 data from an RTP stream and then send it to the MediaCodec to render on a SurfaceView for Android. </p>
  
  <p>However, I'm not certain how to: </p>
  
  <ul>
  <li>build the H264 slices properly from the RTP packets</li>
  <li>send the H264 slices to the media codec once they are assembled into slices</li>
  </ul>
  
  <p>I have not seen any examples of this implemented in a clear and concise way and I haven't found the MediaCodec docs to be at all helpful.  </p>
  
  <p>Anyone have any experience in this domain?</p>
  
  <pre><code>void videoCodec(ByteBuffer input, int flags) {
  
      bufferInfo.set(0, 0, 0, flags);
  
      int inputBufferId = codec.dequeueInputBuffer(10000);
  
      if (inputBufferId &gt;= 0) {
  
          //put data
          ByteBuffer inputData = inputBuffers[inputBufferId];
  
          inputData.clear();
          inputData.put(input);
  
          //queue it up
          codec.queueInputBuffer(inputBufferId, 0, input.limit(), 0, flags);
      }
  
      int outputBufferId = codec.dequeueOutputBuffer(bufferInfo, 10000);
  
      if (outputBufferId &gt;= 0) {
          // outputBuffers[outputBufferId] is ready to be processed or rendered.
          Timber.e("Rendering Data with Index of: %s", outputBufferId);
          codec.releaseOutputBuffer(outputBufferId, true);
  
      } else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
          outputBuffers = codec.getOutputBuffers();
      } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
          // Subsequent data will conform to new format.
          //format = codec.getOutputFormat();
      }
  }
  
   MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1920, 1080);
                      codec = MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
                      codec.configure(format, surfaceVideo.getHolder().getSurface(), null, 0);
                      codec.start();
  
  
                      inputBuffers = codec.getInputBuffers();
                      outputBuffers = codec.getOutputBuffers();
  
        while (streaming) {
  
            //receive RTP Packet
            h264Parser(rtpPacket.getPayload());
  
        }
  </code></pre>
  
  <p>And the the h264Parser looks something like this: </p>
  
  <pre><code>void h264Parser(byte[] payload) {
  
      int packetType = (byte) payload[0] &amp; (byte) 0x1F;
      boolean startBit = (payload[1] &amp; 0x80) != 0;
      boolean endBit = (payload[1] &amp; 0x40) != 0;
      int flags = 0;
  
      switch (packetType) {
          case 7:
              pps = new ByteArrayOutputStream();
              pps.write(prefix);
              pps.write(payload);
              break;
          case 8:
              if (pps.size() &gt; 0) {
                 pps.write(payload);
                 hasPps = true;
                 flags = MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
                 payload = pps.toByteArray();
                 //Send packet to decoder
                 videoCodec(ByteBuffer.wrap(payload), flags);
              break;
          case 28:
  
              if (hasPps) {
                  if (startBit) {
                      baos = new ByteArrayOutputStream();
                      baos.write(prefix);
                      baos.write(payload);
                  } else if (endBit) {
                          if(baos != null) {
                              baos.write(payload);
                              flags = MediaCodec.BUFFER_FLAG_KEY_FRAME;
                              payload = baos.toByteArray();
                              //Send packet to decoder
                              videoCodec(ByteBuffer.wrap(payload), flags);
                              hasPps = false;
                  } else {
                          if(baos != null ) {
                              baos.write(payload);
                          }
                  }
              }
  
              break;
          case 1:
              break;
          default:
      }
  </code></pre>