Kodieren von H.264 von der Kamera mit Android MediaCodec

Ich versuche, diese arbeiten, die auf Android 4.1 (verwenden Sie eine aktualisierte Asus Transformer tablet). Dank Alex ' s Antwort auf meine Vorherige Frageich war bereits in der Lage zu schreiben, raw H. 264-Daten in einer Datei, aber diese Datei ist nur spielbar mit ffplay -f h264und es scheint, wie es ist verloren, alle Informationen bezüglich der framerate (extrem schnelle Wiedergabe). Auch der Farbraum nicht korrekt (atm mit der Kamera standardmäßig auf der encoder-Seite).

public class AvcEncoder {

private MediaCodec mediaCodec;
private BufferedOutputStream outputStream;

public AvcEncoder() { 
    File f = new File(Environment.getExternalStorageDirectory(), "Download/video_encoded.264");
    touch (f);
    try {
        outputStream = new BufferedOutputStream(new FileOutputStream(f));
        Log.i("AvcEncoder", "outputStream initialized");
    } catch (Exception e){ 
        e.printStackTrace();
    }

    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();
}

public void close() {
    try {
        mediaCodec.stop();
        mediaCodec.release();
        outputStream.flush();
        outputStream.close();
    } catch (Exception e){ 
        e.printStackTrace();
    }
}

//called from Camera.setPreviewCallbackWithBuffer(...) in other class
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);
            outputStream.write(outData, 0, outData.length);
            Log.i("AvcEncoder", outData.length + " bytes written");

            mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
            outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);

        }
    } catch (Throwable t) {
        t.printStackTrace();
    }

}

Änderung der encoder-Typ "video/mp4" offenbar löst das framerate-problem, aber da das Hauptziel ist, um einen streaming-Dienst, dies ist keine gute Lösung.

Ich bin mir bewusst, dass ich fallen einige von Alex' code unter Berücksichtigung der SPS-und PPS-NALU, aber ich hatte gehofft das wäre nicht nötig, da diese information wurde auch aus outData und ich angenommen, dass der encoder würde dieses format korrekt. Wenn dies nicht der Fall ist, wie soll ich ordne die verschiedenen Arten von NALU ' s in meiner Datei/stream???

So, was bin ich hier noch fehlt, um eine gültige funktionierende H. 264-stream? Und welche Einstellungen sollte ich verwenden, um eine übereinstimmung zwischen den Kamera Farbraum und die encoder-Farbraum?

Habe ich das Gefühl, dies ist mehr ein H. 264-bezogene Frage als ein Android/MediaCodec Thema. Oder bin ich immer noch nicht mit dem MediaCodec API richtig?

Vielen Dank im Voraus.

InformationsquelleAutor der Frage gleerman | 2012-11-19

Schreibe einen Kommentar