I am trying to use MediaCodec to save a series of Images, saved as Byte Arrays in a file, to a video file. I have tested these images on a SurfaceView (playing them in series) and I can see them fine. I have looked at many examples using MediaCodec, and here is what I understand (please correct me if I am wrong):
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
However, I have tested this a lot and I end up with one of two cases:
- All sample projects I tried to imitate have caused Media server to die when calling
queueInputBufferfor the second time. - I tried calling
codec.flush()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.
Here is my 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<=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; } My question is, how can I get a working video from a stream of images using MediaCodec. What am I doing wrong?
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?
Note: I know about MediaMux in Android 4.3, however, it is not an option for me as my App must work on Android 4.1+.
Update 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).

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.
IllegalStateExceptionat eitherMediaCodec.CONFIGURE_FLAG_ENCODEor atcodec.getOutputBuffers(). I don't find any valid reason for it to happen when even you have the same code with success of running at-least.