Skip to content

Instantly share code, notes, and snippets.

@dzeikei
Forked from wobbals/AvcEncoder.java
Created November 13, 2013 10:48
Show Gist options
  • Select an option

  • Save dzeikei/7447088 to your computer and use it in GitHub Desktop.

Select an option

Save dzeikei/7447088 to your computer and use it in GitHub Desktop.

Revisions

  1. @wobbals wobbals created this gist Oct 31, 2012.
    87 changes: 87 additions & 0 deletions AvcEncoder.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,87 @@
    package com.opentok.media.avc;

    import java.io.IOException;
    import java.nio.ByteBuffer;

    import android.media.MediaCodec;
    import android.media.MediaCodecInfo;
    import android.media.MediaFormat;

    public class AvcEncoder {

    private EncodedFrameListener frameListener;
    private MediaCodec mediaCodec;

    private byte[] sps;
    private byte[] pps;
    private ParameterSetsListener parameterSetsListener;

    public AvcEncoder() {
    mediaCodec = MediaCodec.createEncoderByType("video/avc");
    MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 320, 240);
    mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000);
    mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
    mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
    mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
    mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    mediaCodec.start();
    }

    @Override
    public void close() throws IOException {
    mediaCodec.stop();
    mediaCodec.release();
    }

    @Override
    public void offerEncoder(byte[] input) {
    try {
    ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
    ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
    int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
    if (inputBufferIndex >= 0) {
    ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
    inputBuffer.clear();
    inputBuffer.put(input);
    mediaCodec.queueInputBuffer(inputBufferIndex, 0, input.length, 0, 0);
    }

    MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
    int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
    while (outputBufferIndex >= 0) {
    ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
    byte[] outData = new byte[bufferInfo.size];
    outputBuffer.get(outData);
    if (sps != null && pps != null) {
    ByteBuffer frameBuffer = ByteBuffer.wrap(outData);
    frameBuffer.putInt(bufferInfo.size - 4);
    frameListener.frameReceived(outData, 0, outData.length);
    } else {
    ByteBuffer spsPpsBuffer = ByteBuffer.wrap(outData);
    if (spsPpsBuffer.getInt() == 0x00000001) {
    System.out.println("parsing sps/pps");
    } else {
    System.out.println("something is amiss?");
    }
    int ppsIndex = 0;
    while(!(spsPpsBuffer.get() == 0x00 && spsPpsBuffer.get() == 0x00 && spsPpsBuffer.get() == 0x00 && spsPpsBuffer.get() == 0x01)) {

    }
    ppsIndex = spsPpsBuffer.position();
    sps = new byte[ppsIndex - 8];
    System.arraycopy(outData, 4, sps, 0, sps.length);
    pps = new byte[outData.length - ppsIndex];
    System.arraycopy(outData, ppsIndex, pps, 0, pps.length);
    if (null != parameterSetsListener) {
    parameterSetsListener.avcParametersSetsEstablished(sps, pps);
    }
    }
    mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
    outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
    }
    } catch (Throwable t) {
    t.printStackTrace();
    }

    }
    }