I am trying to convert a PNG file to a one slice video clip, so to just to make a start-up over a project.
What I had code to make it happen is :-
private boolean MediaConversion()
{
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;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.image);
Log.e("Uploaded", "Bitmap:" + bitmap.getWidth() + "X" + bitmap.getHeight());
} catch (Exception e) {
e.printStackTrace();
}
bitmap = Bitmap.createScaledBitmap(bitmap, WIDTH, HEIGHT, false);
bitmap.compress(Bitmap.CompressFormat.PNG, 100,
byteArrayOutputStream);
byte[] dat = byteArrayOutputStream.toByteArray();
info = new BufferInfo();
**// Exception occurred on this below line in Emulator, LINE No. 182//**
inputBufferIndex = codec.dequeueInputBuffer(WAITTIME);
if(dat.length<=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;
**// Exception occurred on this below line in DEVICE, LINE No. 193 //**
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){
dos = array;
}
codec.releaseOutputBuffer(outputBufferIndex, false);
inputBuffers[inputBufferIndex].clear();
outputBuffers[outputBufferIndex].clear();
}
}else{
codec.queueInputBuffer(inputBufferIndex, 0, 0, presentationTime, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
outputBufferIndex = codec.dequeueOutputBuffer(info, WAITTIME);
Log.i("CHAK", "outputBufferIndex="+outputBufferIndex);
if(outputBufferIndex >= 0){
byte[] array = new byte[info.size];
outputBuffers[outputBufferIndex].get(array);
if(array != null){
dos = array;
}
codec.releaseOutputBuffer(outputBufferIndex, false);
inputBuffers[inputBufferIndex].clear();
outputBuffers[outputBufferIndex].clear();
}
}
}
codec.stop();
codec.release();
codec = null;
return true;
}
And here is the Exception Log:-
When tried to run over Emulator Api Level 19:
12-02 23:58:58.214: E/SoftAVCEncoder(1193): internalSetParameter: StoreMetadataInBuffersParams.nPortIndex not zero!
12-02 23:58:58.214: E/OMXNodeInstance(1193): OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x80001001
12-02 23:58:58.224: E/ACodec(1193): [OMX.google.h264.encoder] storeMetaDataInBuffers (output) failed w/ err -2147483648
12-02 23:58:58.224: I/ACodec(1193): setupVideoEncoder succeeded
12-02 23:58:58.254: E/SoftAVCEncoder(1193): Failed to initialize the encoder: -8
12-02 23:58:58.254: E/ACodec(1193): [OMX.google.h264.encoder] ERROR(0x80001001)
12-02 23:58:58.254: E/MediaCodec(1193): Codec reported an error. (omx error 0x80001001, internalError -2147483648)
12-02 23:59:00.424: E/AndroidRuntime(1193): FATAL EXCEPTION: main
12-02 23:59:00.424: E/AndroidRuntime(1193): Process: com.antech.kefilm, PID: 1193
12-02 23:59:00.424: E/AndroidRuntime(1193): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.antech.kefilm/com.antech.kefilm.NewClass}: java.lang.IllegalStateException
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2176)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2226)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.ActivityThread.access$700(ActivityThread.java:135)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1397)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.os.Handler.dispatchMessage(Handler.java:102)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.os.Looper.loop(Looper.java:137)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.ActivityThread.main(ActivityThread.java:4998)
12-02 23:59:00.424: E/AndroidRuntime(1193): at java.lang.reflect.Method.invokeNative(Native Method)
12-02 23:59:00.424: E/AndroidRuntime(1193): at java.lang.reflect.Method.invoke(Method.java:515)
12-02 23:59:00.424: E/AndroidRuntime(1193): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
12-02 23:59:00.424: E/AndroidRuntime(1193): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)
12-02 23:59:00.424: E/AndroidRuntime(1193): at dalvik.system.NativeStart.main(Native Method)
12-02 23:59:00.424: E/AndroidRuntime(1193): Caused by: java.lang.IllegalStateException
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.media.MediaCodec.dequeueInputBuffer(Native Method)
12-02 23:59:00.424: E/AndroidRuntime(1193): at com.antech.kefilm.NewClass.MediaConversion(NewClass.java:182)
12-02 23:59:00.424: E/AndroidRuntime(1193): at com.antech.kefilm.NewClass.onCreate(NewClass.java:83)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.Activity.performCreate(Activity.java:5243)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2140)
12-02 23:59:00.424: E/AndroidRuntime(1193): ... 11 more
But, when run over Galaxy Tab 3 (device):
12-03 05:32:09.670: E/ACodec(3096): [OMX.MARVELL.VIDEO.HW.CODA7542ENCODER] ERROR(0x80001005)
12-03 05:32:09.670: E/MediaCodec(3096): Codec reported an error. (omx error 0x80001005, internalError -2147483648)
12-03 05:32:09.670: E/AndroidRuntime(3096): Caused by: java.lang.IllegalStateException
12-03 05:32:09.670: E/AndroidRuntime(3096): at android.media.MediaCodec.dequeueOutputBuffer(Native Method)
12-03 05:32:09.670: E/AndroidRuntime(3096): at com.antech.kefilm.NewClass.MediaConversion(NewClass.java:193)
12-03 05:32:09.670: E/AndroidRuntime(3096): at com.antech.kefilm.NewClass.onCreate(NewClass.java:83)
References, to according which I started this project:-
Thanks in advance.
First, I don't expect the emulator codecs to work at all. If they do work, I'm pleasantly surprised. This outlook helps me avoid disappointment.
Second, my guess would be that the size of the frame being passed into the encoder is wrong. You're taking an RGBA frame decoded from a Bitmap and stuffing it into a YUV 420 buffer. This doesn't work. The amount of data you're passing in should be exactly width * height * 1.5 bytes for YUV420 (where stride==width and the planes are packed together). On an Android 4.3+ device this behavior is confirmed via the CTS EncodeDecodeTest; older devices are not guaranteed to work.
Also, you're setting the format to COLOR_FormatYUV420SemiPlanar
; in general you can't assume that. You need to query the codec for the list of supported formats, determine whether the input needs to be planar or semi-planar, and then format the buffer input accordingly. The buffer-to-buffer and buffer-to-surface tests in the EncodeDecodeTest demonstrate how to do this.
Alternatively, on Android 4.3 and later, you can upload the bitmap to a texture, configure the codec for Surface input, and render the texture with GLES (which lets the hardware take care of any scaling issues if the bitmap size doesn't match your video size). This takes a lot more code though.
Having said all that, the MediaCodec
diagnostics are generally useless, so this is all guesswork.