Codierung von H.264 von der Kamera mit Android MediaCodec

Ich versuche, dies auf Android 4.1 (unter Verwendung eines aktualisierten Asus Transformer-Tablets) zum Laufen zu bringen. Dank anAlex 'Antwort auf meine vorherige FrageIch konnte bereits einige H.264-Rohdaten in eine Datei schreiben, aber diese Datei kann nur mit abgespielt werdenffplay -f h264, und es scheint, als ob alle Informationen bezüglich der Framerate verloren gegangen sind (extrem schnelle Wiedergabe). Auch der Farbraum sieht falsch aus (atm verwendet die Standardeinstellung der Kamera auf der Encoderseite).

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

}

Das Ändern des Encodertyps auf "video / mp4" löst anscheinend das Framerate-Problem, aber da das Hauptziel darin besteht, einen Streaming-Dienst bereitzustellen, ist dies keine gute Lösung.

Ich bin mir bewusst, dass ich in Anbetracht der SPS- und PPS-NALUs einen Teil von Alex 'Code gelöscht habe, aber ich hatte gehofft, dass dies nicht notwendig sein würde, da diese Informationen auch von kommenoutData und ich nahm an, der Encoder würde dies korrekt formatieren. Wenn dies nicht der Fall ist, wie sollte ich die verschiedenen Arten von NALUs in meiner Datei / meinem Stream anordnen?

Was fehlt mir hier, um einen gültigen, funktionierenden H.264-Stream zu erstellen? Und welche Einstellungen sollte ich verwenden, um eine Übereinstimmung zwischen dem Farbraum der Kamera und dem Farbraum des Encoders herzustellen?

Ich habe das Gefühl, dies ist eher eine H.264-bezogene Frage als ein Android / MediaCodec-Thema. Oder verwende ich die MediaCodec-API immer noch nicht richtig?

Danke im Voraus.

Antworten auf die Frage(5)

Ihre Antwort auf die Frage