web-dev-qa-db-ja.com

MediaCodec.dequeInputBuffer / dequeOutputBufferでのIllegalStateException

PNGファイルを1スライスのビデオクリップに変換しようとしているので、プロジェクトを起動するだけです。

それを実現するためのコードがあったのは:-

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;
    }

そしてここに例外ログがあります:-

エミュレーターApiレベル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

ただし、Galaxy Tab 3(デバイス)で実行した場合:

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)

私がこのプロジェクトを始めた参考文献:-

前もって感謝します。

13
Harpreet

まず、エミュレータコーデックがまったく機能しないと思います。彼らがうまくいくなら、私はうれしい驚きです。このOutlookは、失望を避けるのに役立ちます。

第二に、私の推測では、エンコーダーに渡されるフレームのサイズが間違っていると思います。ビットマップからデコードされたRGBAフレームを取得し、それをYUV420バッファーに詰め込んでいます。これは機能しません。渡すデータの量は、YUV420の場合は幅*高さ* 1.5バイトである必要があります(stride == widthとプレーンが一緒にパックされている場合)。 Android 4.3+デバイスでは、この動作は CTS EncodeDecodeTest を介して確認されます;古いデバイスは動作が保証されていません。

また、フォーマットをCOLOR_FormatYUV420SemiPlanarに設定しています。一般的に、あなたはそれを仮定することはできません。サポートされている形式のリストについてコーデックにクエリを実行し、入力を平面にする必要があるか半平面にする必要があるかを判断し、それに応じてバッファ入力をフォーマットする必要があります。 EncodeDecodeTestのbuffer-to-bufferおよびbuffer-to-surfaceテストは、これを行う方法を示しています。

または、Android 4.3以降では、ビットマップをテクスチャにアップロードし、Surface入力用にコーデックを構成し、GLESを使用してテクスチャをレンダリングできます(これにより、ハードウェアでスケーリングの問題を処理できます)ビットマップサイズがビデオサイズと一致しない場合)。ただし、これにはさらに多くのコードが必要です。

そうは言っても、MediaCodec診断は一般的に役に立たないので、これはすべて当て推量です。

7
fadden