Usando o MediaCodec para salvar séries de imagens como vídeo

Estou tentando usarMediaCodec para salvar uma série de imagens, salvas como matrizes de bytes em um arquivo, em um arquivo de vídeo. Eu testei essas imagens em umSurfaceView (tocando-os em série) e eu posso vê-los bem. Eu olhei muitos exemplos usandoMediaCodece aqui está o que eu entendo (por favor corrija-me se eu estiver errado):

Obter InputBuffers do objeto MediaCodec -> preenchê-lo com dados de imagem do seu quadro -> enfileirar o buffer de entrada -> obter buffer de saída codificado -> gravá-lo em um arquivo -> aumentar o tempo de apresentação e repita

No entanto, eu testei muito isso e acabo com um dos dois casos:

Todos os projetos de amostra que tentei imitar fizeram com que o servidor de mídia morresse ao chamarqueueInputBuffer pela segunda vez.Eu tentei ligarcodec.flush() no final (depois de salvar o buffer de saída para arquivo, embora nenhum dos exemplos que vi fez isso) e o servidor de mídia não morreu, no entanto, eu não sou capaz de abrir o arquivo de vídeo de saída com qualquer media player, então algo está errado .

Aqui está o meu 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;

    }

A minha pergunta é: como posso obter um vídeo em funcionamento a partir de um fluxo de imagens usando o MediaCodec. O que estou fazendo de errado?

Outra questão (se eu não sou muito ganancioso), gostaria de adicionar uma faixa de áudio para este vídeo, pode ser feito com o MediaCodec, ou devo usar o FFmpeg?

Nota: Eu sei sobreMediaMux no Android 4.3, no entanto, não é uma opção para mim, pois meu aplicativo deve funcionar no Android 4.1 ou superior.

Atualizar Graças à resposta do fadden, consegui alcançar o EOS sem o servidor Media morrer (o código acima é após a modificação). No entanto, o arquivo que estou recebendo está produzindo rabiscos. Aqui está um instantâneo do vídeo que recebo (funciona apenas como arquivo .h264).

Meu formato de imagem de entrada é imagem YUV (NV21 da visualização da câmera). Eu não posso conseguir que seja qualquer formato jogável. Eu tentei todos os formatos COLOR_FormatYUV420 e a mesma saída sem sentido. E eu ainda não consigo encontrar (usando o MediaCodec) para adicionar áudio.

questionAnswers(1)

yourAnswerToTheQuestion