Usando MediaCodec para guardar series de imágenes como video

Estoy tratando de usarMediaCodec para guardar una serie de Imágenes, guardadas como Matrices de bytes en un archivo, en un archivo de video. He probado estas imágenes en unaSurfaceView (Jugándolos en series) y puedo verlos bien. He visto muchos ejemplos usandoMediaCodec, y esto es lo que entiendo (corríjame si me equivoco):

Obtenga InputBuffers del objeto MediaCodec -> llénelo con los datos de imagen de su marco -> ponga en cola el búfer de entrada -> obtenga el búfer de salida codificado -> escríbalo en un archivo -> aumente el tiempo de presentación y repita

Sin embargo, he probado esto mucho y termino con uno de dos casos:

Todos los proyectos de muestra que intenté imitar causaron la muerte del servidor de medios al llamarqueueInputBuffer por segunda vez.Intenté llamarcodec.flush() al final (después de guardar el búfer de salida en el archivo, aunque ninguno de los ejemplos que vi hizo esto) y el servidor de medios no murió, sin embargo, no puedo abrir el archivo de video de salida con ningún reproductor de medios, por lo que algo está mal .

Aquí está mi código:

MediaCodec codec = MediaCodec.createEncoderByType(MIMETYPE);
        MediaFormat mediaFormat = null;
        if(CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)){
            mediaFormat = MediaFormat.createVideoFormat(MIMETYPE, 1280 , 720);
        } else {
            mediaFormat = MediaFormat.createVideoFormat(MIMETYPE, 720, 480);
        }


        mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 700000);
        mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 10);
        mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
        mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
        codec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);

        codec.start();

        ByteBuffer[] inputBuffers = codec.getInputBuffers();
        ByteBuffer[] outputBuffers = codec.getOutputBuffers();
        boolean sawInputEOS = false;
        int inputBufferIndex=-1,outputBufferIndex=-1;
        BufferInfo info=null;

                    //loop to read YUV byte array from file

            inputBufferIndex = codec.dequeueInputBuffer(WAITTIME);
            if(bytesread<=0)sawInputEOS=true;

            if(inputBufferIndex >= 0){
                if(!sawInputEOS){
                    int samplesiz=dat.length;
                    inputBuffers[inputBufferIndex].put(dat);
                    codec.queueInputBuffer(inputBufferIndex, 0, samplesiz, presentationTime, 0);
                    presentationTime += 100;

                    info = new BufferInfo();
                    outputBufferIndex = codec.dequeueOutputBuffer(info, WAITTIME);
                    Log.i("BATA", "outputBufferIndex="+outputBufferIndex);
                    if(outputBufferIndex >= 0){
                        byte[] array = new byte[info.size];
                        outputBuffers[outputBufferIndex].get(array);

                        if(array != null){
                            try {
                                dos.write(array);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }

                        codec.releaseOutputBuffer(outputBufferIndex, false);
                        inputBuffers[inputBufferIndex].clear();
                        outputBuffers[outputBufferIndex].clear();

                        if(sawInputEOS) break;
                    }
                }else{
                    codec.queueInputBuffer(inputBufferIndex, 0, 0, presentationTime, MediaCodec.BUFFER_FLAG_END_OF_STREAM);

                    info = new BufferInfo();
                    outputBufferIndex = codec.dequeueOutputBuffer(info, WAITTIME);

                    if(outputBufferIndex >= 0){
                        byte[] array = new byte[info.size];
                        outputBuffers[outputBufferIndex].get(array);

                        if(array != null){
                            try {
                                dos.write(array);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }

                        codec.releaseOutputBuffer(outputBufferIndex, false);
                        inputBuffers[inputBufferIndex].clear();
                        outputBuffers[outputBufferIndex].clear();
                        break;
                    }
                }


            }
        }

        codec.flush();

        try {
            fstream2.close();
            dos.flush();
            dos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        codec.stop();
        codec.release();
        codec = null;

        return true;

    }

Mi pregunta es, ¿cómo puedo obtener un video de trabajo de una secuencia de imágenes usando MediaCodec? ¿Qué estoy haciendo mal?

Otra pregunta (si no soy demasiado codicioso), me gustaría agregar una pista de audio a este video, ¿se puede hacer con MediaCodec también, o debo usar FFmpeg?

Nota: Se acerca deMediaMux en Android 4.3, sin embargo, no es una opción para mí, ya que mi aplicación debe funcionar en Android 4.1+.

Actualizar Gracias a la respuesta fadden, pude alcanzar el EOS sin que el servidor de medios muriera (el código anterior es posterior a la modificación). Sin embargo, el archivo que estoy obteniendo está produciendo galimatías. Aquí hay una instantánea del video que recibo (solo funciona como archivo .h264).

El formato de mi imagen de entrada es la imagen YUV (NV21 de la vista previa de la cámara). No puedo conseguir que sea un formato jugable. Probé todos los formatos COLOR_FormatYUV420 y la misma salida de galimatías. Y todavía no puedo encontrar (usando MediaCodec) para agregar audio.

Respuestas a la pregunta(1)

Su respuesta a la pregunta