I want to create mp4 video
from YUV images
sequence. I test this code on my Nexus 5, Android 4.4
Problem is i have no output data from encoder
.
Encoder give me data just 2 times
And then encoder.dequeueOutputBuffer(info, TIMEOUT_USEC) alway return -1
— INFO_TRY_AGAIN_LATER
CODE
String type="video/avc";
MediaCodecInfo codecInfo = selectCodec(type);
int colorFormat = selectColorFormat(codecInfo, type); // This return 21
MediaFormat format = MediaFormat.createVideoFormat(type,
videowidth, videoheight); //"video/avc" 1280 720
// Set some properties
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
format.setInteger(MediaFormat.KEY_BIT_RATE, 17000000);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
format.setInteger(MediaFormat.KEY_WIDTH,videowidth);
format.setInteger(MediaFormat.KEY_HEIGHT,videoheight);
encoder = MediaCodec.createByCodecName(codecInfo.getName());
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
encoder.start(); //ок
ByteBuffer[] encoderInputBuffers = encoder.getInputBuffers();
ByteBuffer[] encoderOutputBuffers = encoder.getOutputBuffers();
BufferInfo info = new BufferInfo();
int k = 0; // just counter
int inputBufIndex;
int encoderStatus=0;
int col=20; // i want to encode 20 frames
info = new BufferInfo();
while (k < col) {
k++;
try {
Thread.sleep(33); //some pause
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//input to buffer always works fine
inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC);
if (inputBufIndex >= 0) {
if (k == col) { //EOS
encoder.queueInputBuffer(inputBufIndex, 0, 0, ptsUsec,
MediaCodec.BUFFER_FLAG_END_OF_STREAM);
Log.v(TAG, "sent input EOS (with zero-length frame)");
} else {
ByteBuffer inputBuf = encoderInputBuffers[inputBufIndex];
inputBuf.clear();
byte[] frameData = new byte[videowidth * videoheight * 3 / 2]; //1 plane w*h Y + 2 planes w*h/2 Cb Cr
Arrays.fill(frameData, (byte) 0); // zero for example
inputBuf.put(frameData);
encoder.queueInputBuffer(inputBufIndex, 0,
frameData.length, ptsUsec, 0);
Log.v(TAG, "submitted frame " + k + " to enc");
}
} else {
// either all in use, or we timed out during initial setup
Log.v(TAG, "input buffer not available");
}
// output Buffer have problems
info = new BufferInfo();
encoderStatus = encoder.dequeueOutputBuffer(info, TIMEOUT_USEC);
// 1-st time encoderStatus =-2 INFO_OUTPUT_FORMAT_CHANGED
// 2-nd time encoderStatus =0
// 3 to 20 times encoderStatus =-1
if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
// no output available yet
Log.v(TAG, "no output from encoder available");
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
encoderOutputBuffers = encoder.getOutputBuffers();
Log.v(TAG, "encoder output buffers changed");
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
Log.v(TAG, "encoder output format changed: " +encoder.getOutputFormat() );
} else if (encoderStatus < 0) {
Log.v(TAG, "unexpected result from encoder.dequeueOutputBuffer: " + encoderStatus);
} else { // encoderStatus >= 0
ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
if (encodedData == null) {
Log.v(TAG, "encoderOutputBuffer " + encoderStatus + " was null");
}
else
{
Log.v(TAG, "encoderOutputBuffer " + info.size+" | "+encoderStatus+" | "+info );
}
encoder.releaseOutputBuffer(encoderStatus, false);
}
}
Log.d(TAG, "-finish-");
LOG:
08-13 17:23:32.927: V/CAR_DVR(20874): encoder output format: {frame-rate=30, bitrate=17000000, height=720, mime=video/avc, color-format=21, i-frame-interval=10, width=1280} 08-13 17:23:35.347: V/CAR_DVR(20874): submitted frame 1 to enc 08-13 17:23:37.637: V/CAR_DVR(20874): encoder output format changed: {csd-1=java.nio.ByteArrayBuffer[position=0,limit=8,capacity=8], height=720, mime=video/avc, csd-0=java.nio.ByteArrayBuffer[position=0,limit=18,capacity=18], what=1869968451, width=1280} 08-13 17:23:38.537: V/CAR_DVR(20874): submitted frame 2 to enc 08-13 17:23:39.177: V/CAR_DVR(20874): encoderOutputBuffer 26 | 0 | android.media.MediaCodec$BufferInfo@4264dfb0 08-13 17:23:40.007: V/CAR_DVR(20874): submitted frame 3 to enc 08-13 17:23:55.207: V/CAR_DVR(20874): encoderOutputBuffer 3625 | 1 | android.media.MediaCodec$BufferInfo@42654b60 08-13 17:23:57.067: V/CAR_DVR(20874): submitted frame 4 to enc 08-13 17:24:03.187: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:10.167: V/CAR_DVR(20874): submitted frame 5 to enc 08-13 17:24:14.477: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:14.787: V/CAR_DVR(20874): submitted frame 6 to enc 08-13 17:24:14.787: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:15.047: V/CAR_DVR(20874): submitted frame 7 to enc 08-13 17:24:15.047: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:15.317: V/CAR_DVR(20874): submitted frame 8 to enc 08-13 17:24:15.317: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:15.577: V/CAR_DVR(20874): submitted frame 9 to enc 08-13 17:24:15.587: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:15.847: V/CAR_DVR(20874): submitted frame 10 to enc 08-13 17:24:15.847: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:16.107: V/CAR_DVR(20874): submitted frame 11 to enc 08-13 17:24:16.107: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:16.377: V/CAR_DVR(20874): submitted frame 12 to enc 08-13 17:24:16.377: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:16.637: V/CAR_DVR(20874): submitted frame 13 to enc 08-13 17:24:16.637: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:16.897: V/CAR_DVR(20874): submitted frame 14 to enc 08-13 17:24:16.897: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:17.157: V/CAR_DVR(20874): submitted frame 15 to enc 08-13 17:24:17.157: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:17.427: V/CAR_DVR(20874): submitted frame 16 to enc 08-13 17:24:17.427: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:17.697: V/CAR_DVR(20874): submitted frame 17 to enc 08-13 17:24:17.697: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:17.987: V/CAR_DVR(20874): submitted frame 18 to enc 08-13 17:24:17.987: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:18.257: V/CAR_DVR(20874): submitted frame 19 to enc 08-13 17:24:18.257: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:18.297: V/CAR_DVR(20874): sent input EOS (with zero-length frame) 08-13 17:24:18.297: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:18.297: D/CAR_DVR(20874): -finish-
Problem is, that i not compute ptsUsec. I just add ptsUsec=ptsUsec+33; and now all works fine.
ptsUsec - presentation time - is the time of current frame.
When ptsUsec not changed, codec thinking that it is already encoded frame does nothing