title: Using MediaCodec to save series of images as Video
body: <p>I am trying to use <code>MediaCodec</code> to save a series of Images, saved as Byte Arrays in a file, to a video file. I have tested these images on a <code>SurfaceView</code> (playing them in series) and I can see them fine. I have looked at many examples using <code>MediaCodec</code>, and here is what I understand (please correct me if I am wrong):</p>
  
  <blockquote>
    <p>Get InputBuffers from MediaCodec object -> fill it with your frame's
    image data -> queue the input buffer -> get coded output buffer ->
    write it to a file -> increase presentation time and repeat</p>
  </blockquote>
  
  <p>However, I have tested this a lot and I end up with one of two cases:</p>
  
  <ul>
  <li>All sample projects I tried to imitate have caused Media server to die when calling <code>queueInputBuffer</code> for the second time.</li>
  <li>I tried calling <code>codec.flush()</code> at the end (after saving output buffer to file, although none of the examples I saw did this) and the media server did not die, however, I am not able to open the output video file with any media player, so something is wrong.</li>
  </ul>
  
  <p>Here is my code:</p>
  
  <pre><code>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&lt;=0)sawInputEOS=true;
  
              if(inputBufferIndex &gt;= 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 &gt;= 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 &gt;= 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;
  
      }
  </code></pre>
  
  <p>My question is, how can I get a working video from a stream of images using MediaCodec. What am I doing wrong?</p>
  
  <p>Another question (if I am not too greedy), I would like to add an Audio track to this video, can it be done with MediaCodec as well, or must I use FFmpeg?</p>
  
  <p><strong>Note</strong>: I know about <code>MediaMux</code> in Android 4.3, however, it is not an option for me as my App must work on Android 4.1+.</p>
  
  <p><strong>Update</strong>
  Thanks to fadden answer, I was able to reach EOS without Media server dying (Above code is after modification). However, the file I am getting is producing gibberish. Here is a snapshot of the video I get (only works as .h264 file).</p>
  
  <p><img src="https://i.stack.imgur.com/yRquJ.png" alt="Video Output"></p>
  
  <p>My Input image format is YUV image (NV21 from camera preview). I can't get it to be any playable format. I tried all COLOR_FormatYUV420 formats and same gibberish output. And I still can't find away (using MediaCodec) to add audio.</p>