14

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.

Community
  • 1
  • 1
Harpreet
  • 2,990
  • 3
  • 38
  • 52
  • what does NewClass contains at line number 182 and 83 ? – TheLittleNaruto Dec 03 '13 at 10:12
  • @TheLittleNaruto : Please check code again, I have added comment in code where that line no. is. – Harpreet Dec 03 '13 at 11:12
  • put try n catch for both lines of code and see once if problem persist – TheLittleNaruto Dec 03 '13 at 11:34
  • @TheLittleNaruto: I know we can use the try/catch to remove exception, but its an initialization, which is required to move further if we'll just error handle it then it'll give `NullPointException` on its usage further. – Harpreet Dec 03 '13 at 11:50
  • inputBufferIndex, it'll only give NPE, if it does not contain any value. Also IllegalState Exception only occurs, For example, this would be the exception to throw if the caller attempted to use some object before it had been properly initialized. – TheLittleNaruto Dec 03 '13 at 12:01
  • 1
    also check this link, http://stackoverflow.com/questions/17233835/illegalstateexception-when-mediacodec-configure-android – TheLittleNaruto Dec 03 '13 at 12:23
  • That was the exact issue before (shown in that link), I overcome that one and now it moved to these places. – Harpreet Dec 03 '13 at 12:28

1 Answers1

8

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.

fadden
  • 51,356
  • 5
  • 116
  • 166